Skip to content

Commit e0a208c

Browse files
committed
Add support for CREATE TYPE (AS) statements
1 parent 4607add commit e0a208c

File tree

4 files changed

+94
-1
lines changed

4 files changed

+94
-1
lines changed

src/ast/ddl.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -715,3 +715,23 @@ impl fmt::Display for ReferentialAction {
715715
})
716716
}
717717
}
718+
719+
/// SQL composite type attribute definition
720+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
721+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
722+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
723+
pub struct CreateTypeAttrDef {
724+
pub name: Ident,
725+
pub data_type: DataType,
726+
pub collation: Option<ObjectName>,
727+
}
728+
729+
impl fmt::Display for CreateTypeAttrDef {
730+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
731+
write!(f, "{} {}", self.name, self.data_type)?;
732+
if let Some(collation) = &self.collation {
733+
write!(f, " COLLATE {collation}")?;
734+
}
735+
Ok(())
736+
}
737+
}

src/ast/mod.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ pub use self::data_type::{
3030
};
3131
pub use self::ddl::{
3232
AlterColumnOperation, AlterIndexOperation, AlterTableOperation, ColumnDef, ColumnOption,
33-
ColumnOptionDef, GeneratedAs, IndexType, KeyOrIndexDisplay, ReferentialAction, TableConstraint,
33+
ColumnOptionDef, CreateTypeAttrDef, GeneratedAs, IndexType, KeyOrIndexDisplay,
34+
ReferentialAction, TableConstraint,
3435
};
3536
pub use self::operator::{BinaryOperator, UnaryOperator};
3637
pub use self::query::{
@@ -1711,6 +1712,11 @@ pub enum Statement {
17111712
sequence_options: Vec<SequenceOptions>,
17121713
owned_by: Option<ObjectName>,
17131714
},
1715+
/// CREATE TYPE <name>
1716+
CreateType {
1717+
name: ObjectName,
1718+
attributes: Vec<CreateTypeAttrDef>,
1719+
},
17141720
}
17151721

17161722
impl fmt::Display for Statement {
@@ -2921,6 +2927,13 @@ impl fmt::Display for Statement {
29212927
}
29222928
Ok(())
29232929
}
2930+
Statement::CreateType { name, attributes } => {
2931+
write!(
2932+
f,
2933+
"CREATE TYPE {name} AS ({})",
2934+
display_comma_separated(attributes)
2935+
)
2936+
}
29242937
}
29252938
}
29262939
}

src/parser.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2365,6 +2365,8 @@ impl<'a> Parser<'a> {
23652365
self.parse_create_role()
23662366
} else if self.parse_keyword(Keyword::SEQUENCE) {
23672367
self.parse_create_sequence(temporary)
2368+
} else if self.parse_keyword(Keyword::TYPE) {
2369+
self.parse_create_type()
23682370
} else {
23692371
self.expected("an object type after CREATE", self.peek_token())
23702372
}
@@ -7053,6 +7055,40 @@ impl<'a> Parser<'a> {
70537055
window_frame,
70547056
})
70557057
}
7058+
7059+
pub fn parse_create_type(&mut self) -> Result<Statement, ParserError> {
7060+
let name = self.parse_object_name()?;
7061+
self.expect_keyword(Keyword::AS)?;
7062+
7063+
let mut attributes = vec![];
7064+
if !self.consume_token(&Token::LParen) || self.consume_token(&Token::RParen) {
7065+
return Ok(Statement::CreateType { name, attributes });
7066+
}
7067+
7068+
loop {
7069+
let attr_name = self.parse_identifier()?;
7070+
let attr_data_type = self.parse_data_type()?;
7071+
let attr_collation = if self.parse_keyword(Keyword::COLLATE) {
7072+
Some(self.parse_object_name()?)
7073+
} else {
7074+
None
7075+
};
7076+
attributes.push(CreateTypeAttrDef {
7077+
name: attr_name,
7078+
data_type: attr_data_type,
7079+
collation: attr_collation,
7080+
});
7081+
let comma = self.consume_token(&Token::Comma);
7082+
if self.consume_token(&Token::RParen) {
7083+
// allow a trailing comma
7084+
break;
7085+
} else if !comma {
7086+
return self.expected("',' or ')' after attribute definition", self.peek_token());
7087+
}
7088+
}
7089+
7090+
Ok(Statement::CreateType { name, attributes })
7091+
}
70567092
}
70577093

70587094
impl Word {

tests/sqlparser_postgres.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2972,3 +2972,27 @@ fn parse_truncate() {
29722972
truncate
29732973
);
29742974
}
2975+
2976+
#[test]
2977+
fn parse_create_type() {
2978+
let create_type = pg_and_generic()
2979+
.verified_stmt("CREATE TYPE db.type_name AS (foo INT, bar TEXT COLLATE \"de_DE\")");
2980+
assert_eq!(
2981+
Statement::CreateType {
2982+
name: ObjectName(vec![Ident::new("db"), Ident::new("type_name")]),
2983+
attributes: vec![
2984+
CreateTypeAttrDef {
2985+
name: Ident::new("foo"),
2986+
data_type: DataType::Int(None),
2987+
collation: None,
2988+
},
2989+
CreateTypeAttrDef {
2990+
name: Ident::new("bar"),
2991+
data_type: DataType::Text,
2992+
collation: Some(ObjectName(vec![Ident::with_quote('\"', "de_DE")])),
2993+
}
2994+
]
2995+
},
2996+
create_type
2997+
);
2998+
}

0 commit comments

Comments
 (0)