diff --git a/src/ast/data_type.rs b/src/ast/data_type.rs index baa23acf2..58c1305ac 100644 --- a/src/ast/data_type.rs +++ b/src/ast/data_type.rs @@ -39,7 +39,15 @@ pub enum DataType { Nvarchar(Option), /// Uuid type Uuid, - /// Large character object with optional length e.g. CLOB, CLOB(1000), [standard], [Oracle] + /// Large character object with optional length e.g. CHARACTER LARGE OBJECT, CHARACTER LARGE OBJECT(1000), [standard] + /// + /// [standard]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#character-large-object-type + CharacterLargeObject(Option), + /// Large character object with optional length e.g. CHAR LARGE OBJECT, CHAR LARGE OBJECT(1000), [standard] + /// + /// [standard]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#character-large-object-type + CharLargeObject(Option), + /// Large character object with optional length e.g. CLOB, CLOB(1000), [standard] /// /// [standard]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#character-large-object-type /// [Oracle]: https://docs.oracle.com/javadb/10.10.1.2/ref/rrefclob.html @@ -145,6 +153,12 @@ impl fmt::Display for DataType { format_type_with_optional_length(f, "NVARCHAR", size, false) } DataType::Uuid => write!(f, "UUID"), + DataType::CharacterLargeObject(size) => { + format_type_with_optional_length(f, "CHARACTER LARGE OBJECT", size, false) + } + DataType::CharLargeObject(size) => { + format_type_with_optional_length(f, "CHAR LARGE OBJECT", size, false) + } DataType::Clob(size) => format_type_with_optional_length(f, "CLOB", size, false), DataType::Binary(size) => format_type_with_optional_length(f, "BINARY", size, false), DataType::Varbinary(size) => { diff --git a/src/parser.rs b/src/parser.rs index 0c0bd9c5a..5338c2ac0 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -3433,6 +3433,10 @@ impl<'a> Parser<'a> { Ok(DataType::CharacterVarying( self.parse_optional_character_length()?, )) + } else if self.parse_keywords(&[Keyword::LARGE, Keyword::OBJECT]) { + Ok(DataType::CharacterLargeObject( + self.parse_optional_precision()?, + )) } else { Ok(DataType::Character(self.parse_optional_character_length()?)) } @@ -3442,6 +3446,8 @@ impl<'a> Parser<'a> { Ok(DataType::CharVarying( self.parse_optional_character_length()?, )) + } else if self.parse_keywords(&[Keyword::LARGE, Keyword::OBJECT]) { + Ok(DataType::CharLargeObject(self.parse_optional_precision()?)) } else { Ok(DataType::Char(self.parse_optional_character_length()?)) } @@ -5511,6 +5517,39 @@ mod tests { ); } + #[test] + fn test_ansii_character_large_object_types() { + // Character large object types: + let dialect = TestedDialects { + dialects: vec![Box::new(GenericDialect {}), Box::new(AnsiDialect {})], + }; + + test_parse_data_type!( + dialect, + "CHARACTER LARGE OBJECT", + DataType::CharacterLargeObject(None) + ); + test_parse_data_type!( + dialect, + "CHARACTER LARGE OBJECT(20)", + DataType::CharacterLargeObject(Some(20)) + ); + + test_parse_data_type!( + dialect, + "CHAR LARGE OBJECT", + DataType::CharLargeObject(None) + ); + test_parse_data_type!( + dialect, + "CHAR LARGE OBJECT(20)", + DataType::CharLargeObject(Some(20)) + ); + + test_parse_data_type!(dialect, "CLOB", DataType::Clob(None)); + test_parse_data_type!(dialect, "CLOB(20)", DataType::Clob(Some(20))); + } + #[test] fn test_ansii_exact_numeric_types() { // Exact numeric types: