add support for MAX as a character length (#1038)

This commit is contained in:
Ophir LOJKINE 2023-11-10 21:57:56 +01:00 committed by GitHub
parent 4cdaa40abe
commit ff8312bfd8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 63 additions and 39 deletions

View file

@ -518,18 +518,29 @@ impl fmt::Display for ExactNumberInfo {
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub struct CharacterLength { pub enum CharacterLength {
/// Default (if VARYING) or maximum (if not VARYING) length IntegerLength {
pub length: u64, /// Default (if VARYING) or maximum (if not VARYING) length
/// Optional unit. If not informed, the ANSI handles it as CHARACTERS implicitly length: u64,
pub unit: Option<CharLengthUnits>, /// Optional unit. If not informed, the ANSI handles it as CHARACTERS implicitly
unit: Option<CharLengthUnits>,
},
/// VARCHAR(MAX) or NVARCHAR(MAX), used in T-SQL (Miscrosoft SQL Server)
Max,
} }
impl fmt::Display for CharacterLength { impl fmt::Display for CharacterLength {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.length)?; match self {
if let Some(unit) = &self.unit { CharacterLength::IntegerLength { length, unit } => {
write!(f, " {unit}")?; write!(f, "{}", length)?;
if let Some(unit) = unit {
write!(f, " {unit}")?;
}
}
CharacterLength::Max => {
write!(f, "MAX")?;
}
} }
Ok(()) Ok(())
} }

View file

@ -5617,6 +5617,9 @@ impl<'a> Parser<'a> {
} }
pub fn parse_character_length(&mut self) -> Result<CharacterLength, ParserError> { pub fn parse_character_length(&mut self) -> Result<CharacterLength, ParserError> {
if self.parse_keyword(Keyword::MAX) {
return Ok(CharacterLength::Max);
}
let length = self.parse_literal_uint()?; let length = self.parse_literal_uint()?;
let unit = if self.parse_keyword(Keyword::CHARACTERS) { let unit = if self.parse_keyword(Keyword::CHARACTERS) {
Some(CharLengthUnits::Characters) Some(CharLengthUnits::Characters)
@ -5625,8 +5628,7 @@ impl<'a> Parser<'a> {
} else { } else {
None None
}; };
Ok(CharacterLength::IntegerLength { length, unit })
Ok(CharacterLength { length, unit })
} }
pub fn parse_optional_precision_scale( pub fn parse_optional_precision_scale(
@ -8111,7 +8113,7 @@ mod tests {
test_parse_data_type!( test_parse_data_type!(
dialect, dialect,
"CHARACTER(20)", "CHARACTER(20)",
DataType::Character(Some(CharacterLength { DataType::Character(Some(CharacterLength::IntegerLength {
length: 20, length: 20,
unit: None unit: None
})) }))
@ -8120,7 +8122,7 @@ mod tests {
test_parse_data_type!( test_parse_data_type!(
dialect, dialect,
"CHARACTER(20 CHARACTERS)", "CHARACTER(20 CHARACTERS)",
DataType::Character(Some(CharacterLength { DataType::Character(Some(CharacterLength::IntegerLength {
length: 20, length: 20,
unit: Some(CharLengthUnits::Characters) unit: Some(CharLengthUnits::Characters)
})) }))
@ -8129,7 +8131,7 @@ mod tests {
test_parse_data_type!( test_parse_data_type!(
dialect, dialect,
"CHARACTER(20 OCTETS)", "CHARACTER(20 OCTETS)",
DataType::Character(Some(CharacterLength { DataType::Character(Some(CharacterLength::IntegerLength {
length: 20, length: 20,
unit: Some(CharLengthUnits::Octets) unit: Some(CharLengthUnits::Octets)
})) }))
@ -8140,7 +8142,7 @@ mod tests {
test_parse_data_type!( test_parse_data_type!(
dialect, dialect,
"CHAR(20)", "CHAR(20)",
DataType::Char(Some(CharacterLength { DataType::Char(Some(CharacterLength::IntegerLength {
length: 20, length: 20,
unit: None unit: None
})) }))
@ -8149,7 +8151,7 @@ mod tests {
test_parse_data_type!( test_parse_data_type!(
dialect, dialect,
"CHAR(20 CHARACTERS)", "CHAR(20 CHARACTERS)",
DataType::Char(Some(CharacterLength { DataType::Char(Some(CharacterLength::IntegerLength {
length: 20, length: 20,
unit: Some(CharLengthUnits::Characters) unit: Some(CharLengthUnits::Characters)
})) }))
@ -8158,7 +8160,7 @@ mod tests {
test_parse_data_type!( test_parse_data_type!(
dialect, dialect,
"CHAR(20 OCTETS)", "CHAR(20 OCTETS)",
DataType::Char(Some(CharacterLength { DataType::Char(Some(CharacterLength::IntegerLength {
length: 20, length: 20,
unit: Some(CharLengthUnits::Octets) unit: Some(CharLengthUnits::Octets)
})) }))
@ -8167,7 +8169,7 @@ mod tests {
test_parse_data_type!( test_parse_data_type!(
dialect, dialect,
"CHARACTER VARYING(20)", "CHARACTER VARYING(20)",
DataType::CharacterVarying(Some(CharacterLength { DataType::CharacterVarying(Some(CharacterLength::IntegerLength {
length: 20, length: 20,
unit: None unit: None
})) }))
@ -8176,7 +8178,7 @@ mod tests {
test_parse_data_type!( test_parse_data_type!(
dialect, dialect,
"CHARACTER VARYING(20 CHARACTERS)", "CHARACTER VARYING(20 CHARACTERS)",
DataType::CharacterVarying(Some(CharacterLength { DataType::CharacterVarying(Some(CharacterLength::IntegerLength {
length: 20, length: 20,
unit: Some(CharLengthUnits::Characters) unit: Some(CharLengthUnits::Characters)
})) }))
@ -8185,7 +8187,7 @@ mod tests {
test_parse_data_type!( test_parse_data_type!(
dialect, dialect,
"CHARACTER VARYING(20 OCTETS)", "CHARACTER VARYING(20 OCTETS)",
DataType::CharacterVarying(Some(CharacterLength { DataType::CharacterVarying(Some(CharacterLength::IntegerLength {
length: 20, length: 20,
unit: Some(CharLengthUnits::Octets) unit: Some(CharLengthUnits::Octets)
})) }))
@ -8194,7 +8196,7 @@ mod tests {
test_parse_data_type!( test_parse_data_type!(
dialect, dialect,
"CHAR VARYING(20)", "CHAR VARYING(20)",
DataType::CharVarying(Some(CharacterLength { DataType::CharVarying(Some(CharacterLength::IntegerLength {
length: 20, length: 20,
unit: None unit: None
})) }))
@ -8203,7 +8205,7 @@ mod tests {
test_parse_data_type!( test_parse_data_type!(
dialect, dialect,
"CHAR VARYING(20 CHARACTERS)", "CHAR VARYING(20 CHARACTERS)",
DataType::CharVarying(Some(CharacterLength { DataType::CharVarying(Some(CharacterLength::IntegerLength {
length: 20, length: 20,
unit: Some(CharLengthUnits::Characters) unit: Some(CharLengthUnits::Characters)
})) }))
@ -8212,7 +8214,7 @@ mod tests {
test_parse_data_type!( test_parse_data_type!(
dialect, dialect,
"CHAR VARYING(20 OCTETS)", "CHAR VARYING(20 OCTETS)",
DataType::CharVarying(Some(CharacterLength { DataType::CharVarying(Some(CharacterLength::IntegerLength {
length: 20, length: 20,
unit: Some(CharLengthUnits::Octets) unit: Some(CharLengthUnits::Octets)
})) }))
@ -8221,7 +8223,7 @@ mod tests {
test_parse_data_type!( test_parse_data_type!(
dialect, dialect,
"VARCHAR(20)", "VARCHAR(20)",
DataType::Varchar(Some(CharacterLength { DataType::Varchar(Some(CharacterLength::IntegerLength {
length: 20, length: 20,
unit: None unit: None
})) }))

View file

@ -2381,7 +2381,7 @@ fn parse_create_table() {
vec![ vec![
ColumnDef { ColumnDef {
name: "name".into(), name: "name".into(),
data_type: DataType::Varchar(Some(CharacterLength { data_type: DataType::Varchar(Some(CharacterLength::IntegerLength {
length: 100, length: 100,
unit: None, unit: None,
})), })),
@ -2929,7 +2929,7 @@ fn parse_create_external_table() {
vec![ vec![
ColumnDef { ColumnDef {
name: "name".into(), name: "name".into(),
data_type: DataType::Varchar(Some(CharacterLength { data_type: DataType::Varchar(Some(CharacterLength::IntegerLength {
length: 100, length: 100,
unit: None, unit: None,
})), })),
@ -3000,7 +3000,7 @@ fn parse_create_or_replace_external_table() {
columns, columns,
vec![ColumnDef { vec![ColumnDef {
name: "name".into(), name: "name".into(),
data_type: DataType::Varchar(Some(CharacterLength { data_type: DataType::Varchar(Some(CharacterLength::IntegerLength {
length: 100, length: 100,
unit: None, unit: None,
})), })),

View file

@ -127,7 +127,7 @@ fn parse_create_procedure() {
value: "@bar".into(), value: "@bar".into(),
quote_style: None quote_style: None
}, },
data_type: DataType::Varchar(Some(CharacterLength { data_type: DataType::Varchar(Some(CharacterLength::IntegerLength {
length: 256, length: 256,
unit: None unit: None
})) }))
@ -431,6 +431,11 @@ fn parse_like() {
chk(true); chk(true);
} }
#[test]
fn parse_cast_varchar_max() {
ms_and_generic().verified_expr("CAST('foo' AS VARCHAR(MAX))");
}
#[test] #[test]
fn parse_similar_to() { fn parse_similar_to() {
fn chk(negated: bool) { fn chk(negated: bool) {

View file

@ -349,10 +349,12 @@ fn parse_create_table_with_defaults() {
}, },
ColumnDef { ColumnDef {
name: "first_name".into(), name: "first_name".into(),
data_type: DataType::CharacterVarying(Some(CharacterLength { data_type: DataType::CharacterVarying(Some(
length: 45, CharacterLength::IntegerLength {
unit: None length: 45,
})), unit: None
}
)),
collation: None, collation: None,
options: vec![ColumnOptionDef { options: vec![ColumnOptionDef {
name: None, name: None,
@ -361,10 +363,12 @@ fn parse_create_table_with_defaults() {
}, },
ColumnDef { ColumnDef {
name: "last_name".into(), name: "last_name".into(),
data_type: DataType::CharacterVarying(Some(CharacterLength { data_type: DataType::CharacterVarying(Some(
length: 45, CharacterLength::IntegerLength {
unit: None length: 45,
})), unit: None
}
)),
collation: Some(ObjectName(vec![Ident::with_quote('"', "es_ES")])), collation: Some(ObjectName(vec![Ident::with_quote('"', "es_ES")])),
options: vec![ColumnOptionDef { options: vec![ColumnOptionDef {
name: None, name: None,
@ -373,10 +377,12 @@ fn parse_create_table_with_defaults() {
}, },
ColumnDef { ColumnDef {
name: "email".into(), name: "email".into(),
data_type: DataType::CharacterVarying(Some(CharacterLength { data_type: DataType::CharacterVarying(Some(
length: 50, CharacterLength::IntegerLength {
unit: None length: 50,
})), unit: None
}
)),
collation: None, collation: None,
options: vec![], options: vec![],
}, },