Skip to content

Commit 914810d

Browse files
authored
Modifier support for Custom Datatype (#680)
* feat: add support for custom types with argument * refactor: add support for number and string as type arguments * fix: ignore CustomWithArgs when parsing TypedString * refactor: merge CustomWithArgs into Custom * refactor: rename arguments to modifiers
1 parent 2c266a4 commit 914810d

File tree

2 files changed

+69
-4
lines changed

2 files changed

+69
-4
lines changed

src/ast/data_type.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ pub enum DataType {
129129
/// Bytea
130130
Bytea,
131131
/// Custom type such as enums
132-
Custom(ObjectName),
132+
Custom(ObjectName, Vec<String>),
133133
/// Arrays
134134
Array(Box<DataType>),
135135
/// Enums
@@ -217,7 +217,13 @@ impl fmt::Display for DataType {
217217
DataType::String => write!(f, "STRING"),
218218
DataType::Bytea => write!(f, "BYTEA"),
219219
DataType::Array(ty) => write!(f, "{}[]", ty),
220-
DataType::Custom(ty) => write!(f, "{}", ty),
220+
DataType::Custom(ty, modifiers) => {
221+
if modifiers.is_empty() {
222+
write!(f, "{}", ty)
223+
} else {
224+
write!(f, "{}({})", ty, modifiers.join(", "))
225+
}
226+
}
221227
DataType::Enum(vals) => {
222228
write!(f, "ENUM(")?;
223229
for (i, v) in vals.iter().enumerate() {

src/parser.rs

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3661,7 +3661,11 @@ impl<'a> Parser<'a> {
36613661
_ => {
36623662
self.prev_token();
36633663
let type_name = self.parse_object_name()?;
3664-
Ok(DataType::Custom(type_name))
3664+
if let Some(modifiers) = self.parse_optional_type_modifiers()? {
3665+
Ok(DataType::Custom(type_name, modifiers))
3666+
} else {
3667+
Ok(DataType::Custom(type_name, vec![]))
3668+
}
36653669
}
36663670
},
36673671
unexpected => self.expected("a data type name", unexpected),
@@ -3907,6 +3911,31 @@ impl<'a> Parser<'a> {
39073911
}
39083912
}
39093913

3914+
pub fn parse_optional_type_modifiers(&mut self) -> Result<Option<Vec<String>>, ParserError> {
3915+
if self.consume_token(&Token::LParen) {
3916+
let mut modifiers = Vec::new();
3917+
loop {
3918+
match self.next_token() {
3919+
Token::Word(w) => modifiers.push(w.to_string()),
3920+
Token::Number(n, _) => modifiers.push(n),
3921+
Token::SingleQuotedString(s) => modifiers.push(s),
3922+
3923+
Token::Comma => {
3924+
continue;
3925+
}
3926+
Token::RParen => {
3927+
break;
3928+
}
3929+
unexpected => self.expected("type modifiers", unexpected)?,
3930+
}
3931+
}
3932+
3933+
Ok(Some(modifiers))
3934+
} else {
3935+
Ok(None)
3936+
}
3937+
}
3938+
39103939
pub fn parse_delete(&mut self) -> Result<Statement, ParserError> {
39113940
self.expect_keyword(Keyword::FROM)?;
39123941
let table_name = self.parse_table_factor()?;
@@ -5540,7 +5569,7 @@ mod tests {
55405569
#[cfg(test)]
55415570
mod test_parse_data_type {
55425571
use crate::ast::{
5543-
CharLengthUnits, CharacterLength, DataType, ExactNumberInfo, TimezoneInfo,
5572+
CharLengthUnits, CharacterLength, DataType, ExactNumberInfo, ObjectName, TimezoneInfo,
55445573
};
55455574
use crate::dialect::{AnsiDialect, GenericDialect};
55465575
use crate::test_utils::TestedDialects;
@@ -5717,6 +5746,36 @@ mod tests {
57175746
test_parse_data_type!(dialect, "CLOB(20)", DataType::Clob(Some(20)));
57185747
}
57195748

5749+
#[test]
5750+
fn test_parse_custom_types() {
5751+
let dialect = TestedDialects {
5752+
dialects: vec![Box::new(GenericDialect {}), Box::new(AnsiDialect {})],
5753+
};
5754+
test_parse_data_type!(
5755+
dialect,
5756+
"GEOMETRY",
5757+
DataType::Custom(ObjectName(vec!["GEOMETRY".into()]), vec![])
5758+
);
5759+
5760+
test_parse_data_type!(
5761+
dialect,
5762+
"GEOMETRY(POINT)",
5763+
DataType::Custom(
5764+
ObjectName(vec!["GEOMETRY".into()]),
5765+
vec!["POINT".to_string()]
5766+
)
5767+
);
5768+
5769+
test_parse_data_type!(
5770+
dialect,
5771+
"GEOMETRY(POINT, 4326)",
5772+
DataType::Custom(
5773+
ObjectName(vec!["GEOMETRY".into()]),
5774+
vec!["POINT".to_string(), "4326".to_string()]
5775+
)
5776+
);
5777+
}
5778+
57205779
#[test]
57215780
fn test_ansii_exact_numeric_types() {
57225781
// Exact numeric types: <https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#exact-numeric-type>

0 commit comments

Comments
 (0)