Support for MSSQL CONVERT styles (#1219)

This commit is contained in:
Ifeanyi Ubah 2024-04-30 16:22:13 +02:00 committed by GitHub
parent 6fcf8c9abe
commit 0606024353
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 47 additions and 0 deletions

View file

@ -567,6 +567,10 @@ pub enum Expr {
charset: Option<ObjectName>,
/// whether the target comes before the expr (MSSQL syntax)
target_before_value: bool,
/// How to translate the expression.
///
/// [MSSQL]: https://learn.microsoft.com/en-us/sql/t-sql/functions/cast-and-convert-transact-sql?view=sql-server-ver16#style
styles: Vec<Expr>,
},
/// `CAST` an expression to a different data type e.g. `CAST(foo AS VARCHAR(123))`
Cast {
@ -979,6 +983,7 @@ impl fmt::Display for Expr {
target_before_value,
data_type,
charset,
styles,
} => {
write!(f, "CONVERT(")?;
if let Some(data_type) = data_type {
@ -994,6 +999,9 @@ impl fmt::Display for Expr {
} else {
write!(f, "{expr}") // This should never happen
}?;
if !styles.is_empty() {
write!(f, ", {}", display_comma_separated(styles))?;
}
write!(f, ")")
}
Expr::Cast {

View file

@ -1462,12 +1462,18 @@ impl<'a> Parser<'a> {
let data_type = self.parse_data_type()?;
self.expect_token(&Token::Comma)?;
let expr = self.parse_expr()?;
let styles = if self.consume_token(&Token::Comma) {
self.parse_comma_separated(Parser::parse_expr)?
} else {
Default::default()
};
self.expect_token(&Token::RParen)?;
Ok(Expr::Convert {
expr: Box::new(expr),
data_type: Some(data_type),
charset: None,
target_before_value: true,
styles,
})
}
@ -1489,6 +1495,7 @@ impl<'a> Parser<'a> {
data_type: None,
charset: Some(charset),
target_before_value: false,
styles: vec![],
});
}
self.expect_token(&Token::Comma)?;
@ -1504,6 +1511,7 @@ impl<'a> Parser<'a> {
data_type: Some(data_type),
charset,
target_before_value: false,
styles: vec![],
})
}

View file

@ -20,6 +20,7 @@ use test_utils::*;
use sqlparser::ast::*;
use sqlparser::dialect::{GenericDialect, MsSqlDialect};
use sqlparser::parser::ParserError;
#[test]
fn parse_mssql_identifiers() {
@ -437,9 +438,39 @@ fn parse_cast_varchar_max() {
#[test]
fn parse_convert() {
let sql = "CONVERT(INT, 1, 2, 3, NULL)";
let Expr::Convert {
expr,
data_type,
charset,
target_before_value,
styles,
} = ms().verified_expr(sql)
else {
unreachable!()
};
assert_eq!(Expr::Value(number("1")), *expr);
assert_eq!(Some(DataType::Int(None)), data_type);
assert!(charset.is_none());
assert!(target_before_value);
assert_eq!(
vec![
Expr::Value(number("2")),
Expr::Value(number("3")),
Expr::Value(Value::Null),
],
styles
);
ms().verified_expr("CONVERT(VARCHAR(MAX), 'foo')");
ms().verified_expr("CONVERT(VARCHAR(10), 'foo')");
ms().verified_expr("CONVERT(DECIMAL(10,5), 12.55)");
let error_sql = "SELECT CONVERT(INT, 'foo',) FROM T";
assert_eq!(
ParserError::ParserError("Expected an expression:, found: )".to_owned()),
ms().parse_sql_statements(error_sql).unwrap_err()
);
}
#[test]