Skip to content

Commit a8432b5

Browse files
authored
Add PostgreSQL specfic "CREATE TYPE t AS ENUM (...)" support. (apache#1460)
1 parent 45c5d69 commit a8432b5

File tree

3 files changed

+68
-1
lines changed

3 files changed

+68
-1
lines changed

src/ast/ddl.rs

+5
Original file line numberDiff line numberDiff line change
@@ -1706,6 +1706,8 @@ pub enum UserDefinedTypeRepresentation {
17061706
Composite {
17071707
attributes: Vec<UserDefinedTypeCompositeAttributeDef>,
17081708
},
1709+
/// Note: this is PostgreSQL-specific. See <https://www.postgresql.org/docs/current/sql-createtype.html>
1710+
Enum { labels: Vec<Ident> },
17091711
}
17101712

17111713
impl fmt::Display for UserDefinedTypeRepresentation {
@@ -1714,6 +1716,9 @@ impl fmt::Display for UserDefinedTypeRepresentation {
17141716
UserDefinedTypeRepresentation::Composite { attributes } => {
17151717
write!(f, "({})", display_comma_separated(attributes))
17161718
}
1719+
UserDefinedTypeRepresentation::Enum { labels } => {
1720+
write!(f, "ENUM ({})", display_comma_separated(labels))
1721+
}
17171722
}
17181723
}
17191724
}

src/dialect/postgresql.rs

+34-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
// limitations under the License.
2929
use log::debug;
3030

31-
use crate::ast::{CommentObject, Statement};
31+
use crate::ast::{CommentObject, ObjectName, Statement, UserDefinedTypeRepresentation};
3232
use crate::dialect::{Dialect, Precedence};
3333
use crate::keywords::Keyword;
3434
use crate::parser::{Parser, ParserError};
@@ -138,6 +138,9 @@ impl Dialect for PostgreSqlDialect {
138138
fn parse_statement(&self, parser: &mut Parser) -> Option<Result<Statement, ParserError>> {
139139
if parser.parse_keyword(Keyword::COMMENT) {
140140
Some(parse_comment(parser))
141+
} else if parser.parse_keyword(Keyword::CREATE) {
142+
parser.prev_token(); // unconsume the CREATE in case we don't end up parsing anything
143+
parse_create(parser)
141144
} else {
142145
None
143146
}
@@ -225,3 +228,33 @@ pub fn parse_comment(parser: &mut Parser) -> Result<Statement, ParserError> {
225228
if_exists,
226229
})
227230
}
231+
232+
pub fn parse_create(parser: &mut Parser) -> Option<Result<Statement, ParserError>> {
233+
let name = parser.maybe_parse(|parser| -> Result<ObjectName, ParserError> {
234+
parser.expect_keyword(Keyword::CREATE)?;
235+
parser.expect_keyword(Keyword::TYPE)?;
236+
let name = parser.parse_object_name(false)?;
237+
parser.expect_keyword(Keyword::AS)?;
238+
parser.expect_keyword(Keyword::ENUM)?;
239+
Ok(name)
240+
});
241+
name.map(|name| parse_create_type_as_enum(parser, name))
242+
}
243+
244+
// https://www.postgresql.org/docs/current/sql-createtype.html
245+
pub fn parse_create_type_as_enum(
246+
parser: &mut Parser,
247+
name: ObjectName,
248+
) -> Result<Statement, ParserError> {
249+
if !parser.consume_token(&Token::LParen) {
250+
return parser.expected("'(' after CREATE TYPE AS ENUM", parser.peek_token());
251+
}
252+
253+
let labels = parser.parse_comma_separated0(|p| p.parse_identifier(false), Token::RParen)?;
254+
parser.expect_token(&Token::RParen)?;
255+
256+
Ok(Statement::CreateType {
257+
name,
258+
representation: UserDefinedTypeRepresentation::Enum { labels },
259+
})
260+
}

tests/sqlparser_postgres.rs

+29
Original file line numberDiff line numberDiff line change
@@ -5128,3 +5128,32 @@ fn arrow_cast_precedence() {
51285128
}
51295129
)
51305130
}
5131+
5132+
#[test]
5133+
fn parse_create_type_as_enum() {
5134+
let statement = pg().one_statement_parses_to(
5135+
r#"CREATE TYPE public.my_type AS ENUM (
5136+
'label1',
5137+
'label2',
5138+
'label3',
5139+
'label4'
5140+
);"#,
5141+
"CREATE TYPE public.my_type AS ENUM ('label1', 'label2', 'label3', 'label4')",
5142+
);
5143+
match statement {
5144+
Statement::CreateType {
5145+
name,
5146+
representation: UserDefinedTypeRepresentation::Enum { labels },
5147+
} => {
5148+
assert_eq!("public.my_type", name.to_string());
5149+
assert_eq!(
5150+
vec!["label1", "label2", "label3", "label4"]
5151+
.into_iter()
5152+
.map(|l| Ident::with_quote('\'', l))
5153+
.collect::<Vec<Ident>>(),
5154+
labels
5155+
);
5156+
}
5157+
_ => unreachable!(),
5158+
}
5159+
}

0 commit comments

Comments
 (0)