mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-04 14:28:22 +00:00
Support for MSSQL CONVERT
styles (#1219)
This commit is contained in:
parent
6fcf8c9abe
commit
0606024353
3 changed files with 47 additions and 0 deletions
|
@ -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 {
|
||||
|
|
|
@ -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![],
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -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]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue