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
This commit is contained in:
Ning Sun 2022-10-21 03:27:15 +08:00 committed by GitHub
parent 2c266a437c
commit 914810d366
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 69 additions and 4 deletions

View file

@ -3661,7 +3661,11 @@ impl<'a> Parser<'a> {
_ => {
self.prev_token();
let type_name = self.parse_object_name()?;
Ok(DataType::Custom(type_name))
if let Some(modifiers) = self.parse_optional_type_modifiers()? {
Ok(DataType::Custom(type_name, modifiers))
} else {
Ok(DataType::Custom(type_name, vec![]))
}
}
},
unexpected => self.expected("a data type name", unexpected),
@ -3907,6 +3911,31 @@ impl<'a> Parser<'a> {
}
}
pub fn parse_optional_type_modifiers(&mut self) -> Result<Option<Vec<String>>, ParserError> {
if self.consume_token(&Token::LParen) {
let mut modifiers = Vec::new();
loop {
match self.next_token() {
Token::Word(w) => modifiers.push(w.to_string()),
Token::Number(n, _) => modifiers.push(n),
Token::SingleQuotedString(s) => modifiers.push(s),
Token::Comma => {
continue;
}
Token::RParen => {
break;
}
unexpected => self.expected("type modifiers", unexpected)?,
}
}
Ok(Some(modifiers))
} else {
Ok(None)
}
}
pub fn parse_delete(&mut self) -> Result<Statement, ParserError> {
self.expect_keyword(Keyword::FROM)?;
let table_name = self.parse_table_factor()?;
@ -5540,7 +5569,7 @@ mod tests {
#[cfg(test)]
mod test_parse_data_type {
use crate::ast::{
CharLengthUnits, CharacterLength, DataType, ExactNumberInfo, TimezoneInfo,
CharLengthUnits, CharacterLength, DataType, ExactNumberInfo, ObjectName, TimezoneInfo,
};
use crate::dialect::{AnsiDialect, GenericDialect};
use crate::test_utils::TestedDialects;
@ -5717,6 +5746,36 @@ mod tests {
test_parse_data_type!(dialect, "CLOB(20)", DataType::Clob(Some(20)));
}
#[test]
fn test_parse_custom_types() {
let dialect = TestedDialects {
dialects: vec![Box::new(GenericDialect {}), Box::new(AnsiDialect {})],
};
test_parse_data_type!(
dialect,
"GEOMETRY",
DataType::Custom(ObjectName(vec!["GEOMETRY".into()]), vec![])
);
test_parse_data_type!(
dialect,
"GEOMETRY(POINT)",
DataType::Custom(
ObjectName(vec!["GEOMETRY".into()]),
vec!["POINT".to_string()]
)
);
test_parse_data_type!(
dialect,
"GEOMETRY(POINT, 4326)",
DataType::Custom(
ObjectName(vec!["GEOMETRY".into()]),
vec!["POINT".to_string(), "4326".to_string()]
)
);
}
#[test]
fn test_ansii_exact_numeric_types() {
// Exact numeric types: <https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#exact-numeric-type>