Skip to content

Commit 39a111d

Browse files
committed
Add PostgreSQL specfic "CREATE TYPE t AS ENUM (...)" support.
See: https://www.postgresql.org/docs/current/sql-createtype.html
1 parent 1e0460a commit 39a111d

File tree

3 files changed

+62
-1
lines changed

3 files changed

+62
-1
lines changed

src/ast/ddl.rs

+5
Original file line numberDiff line numberDiff line change
@@ -1479,6 +1479,8 @@ pub enum UserDefinedTypeRepresentation {
14791479
Composite {
14801480
attributes: Vec<UserDefinedTypeCompositeAttributeDef>,
14811481
},
1482+
/// Note: this is PostgreSQL-specific. See <https://www.postgresql.org/docs/current/sql-createtype.html>
1483+
Enum { labels: Vec<Ident> },
14821484
}
14831485

14841486
impl fmt::Display for UserDefinedTypeRepresentation {
@@ -1487,6 +1489,9 @@ impl fmt::Display for UserDefinedTypeRepresentation {
14871489
UserDefinedTypeRepresentation::Composite { attributes } => {
14881490
write!(f, "({})", display_comma_separated(attributes))
14891491
}
1492+
UserDefinedTypeRepresentation::Enum { labels } => {
1493+
write!(f, "ENUM ({})", display_comma_separated(labels))
1494+
}
14901495
}
14911496
}
14921497
}

src/dialect/postgresql.rs

+31-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
}
@@ -221,3 +224,30 @@ pub fn parse_comment(parser: &mut Parser) -> Result<Statement, ParserError> {
221224
if_exists,
222225
})
223226
}
227+
228+
pub fn parse_create(parser: &mut Parser) -> Option<Result<Statement, ParserError>> {
229+
let name = parser.maybe_parse(|parser| -> Result<ObjectName, ParserError> {
230+
parser.expect_keyword(Keyword::CREATE)?;
231+
parser.expect_keyword(Keyword::TYPE)?;
232+
let name = parser.parse_object_name(false)?;
233+
parser.expect_keyword(Keyword::AS)?;
234+
parser.expect_keyword(Keyword::ENUM)?;
235+
Ok(name)
236+
});
237+
name.map(|name| parse_create_type_as_enum(parser, name))
238+
}
239+
240+
// https://www.postgresql.org/docs/current/sql-createtype.html
241+
pub fn parse_create_type_as_enum(
242+
parser: &mut Parser,
243+
name: ObjectName,
244+
) -> Result<Statement, ParserError> {
245+
if !parser.consume_token(&Token::LParen) {
246+
return parser.expected("'(' after CREATE TYPE AS ENUM", parser.peek_token());
247+
}
248+
249+
let labels = parser.parse_comma_separated0(|p| p.parse_identifier(false), Token::RParen)?;
250+
parser.expect_token(&Token::RParen)?;
251+
252+
Ok(Statement::CreateType { name, representation: UserDefinedTypeRepresentation::Enum { labels } })
253+
}

tests/sqlparser_postgres.rs

+26
Original file line numberDiff line numberDiff line change
@@ -5113,3 +5113,29 @@ fn arrow_cast_precedence() {
51135113
}
51145114
)
51155115
}
5116+
5117+
#[test]
5118+
fn parse_create_type_as_enum() {
5119+
let statement = pg().one_statement_parses_to(
5120+
r#"CREATE TYPE public.my_type AS ENUM (
5121+
'label1',
5122+
'label2',
5123+
'label3',
5124+
'label4'
5125+
);"#,
5126+
"CREATE TYPE public.my_type AS ENUM ('label1', 'label2', 'label3', 'label4')",
5127+
);
5128+
match statement {
5129+
Statement::CreateType { name, representation: UserDefinedTypeRepresentation::Enum { labels } } => {
5130+
assert_eq!("public.my_type", name.to_string());
5131+
assert_eq!(
5132+
vec!["label1", "label2", "label3", "label4"]
5133+
.into_iter()
5134+
.map(|l| Ident::with_quote('\'', l))
5135+
.collect::<Vec<Ident>>(),
5136+
labels
5137+
);
5138+
}
5139+
_ => unreachable!(),
5140+
}
5141+
}

0 commit comments

Comments
 (0)