mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-09-26 15:39:12 +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>,
|
charset: Option<ObjectName>,
|
||||||
/// whether the target comes before the expr (MSSQL syntax)
|
/// whether the target comes before the expr (MSSQL syntax)
|
||||||
target_before_value: bool,
|
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` an expression to a different data type e.g. `CAST(foo AS VARCHAR(123))`
|
||||||
Cast {
|
Cast {
|
||||||
|
@ -979,6 +983,7 @@ impl fmt::Display for Expr {
|
||||||
target_before_value,
|
target_before_value,
|
||||||
data_type,
|
data_type,
|
||||||
charset,
|
charset,
|
||||||
|
styles,
|
||||||
} => {
|
} => {
|
||||||
write!(f, "CONVERT(")?;
|
write!(f, "CONVERT(")?;
|
||||||
if let Some(data_type) = data_type {
|
if let Some(data_type) = data_type {
|
||||||
|
@ -994,6 +999,9 @@ impl fmt::Display for Expr {
|
||||||
} else {
|
} else {
|
||||||
write!(f, "{expr}") // This should never happen
|
write!(f, "{expr}") // This should never happen
|
||||||
}?;
|
}?;
|
||||||
|
if !styles.is_empty() {
|
||||||
|
write!(f, ", {}", display_comma_separated(styles))?;
|
||||||
|
}
|
||||||
write!(f, ")")
|
write!(f, ")")
|
||||||
}
|
}
|
||||||
Expr::Cast {
|
Expr::Cast {
|
||||||
|
|
|
@ -1462,12 +1462,18 @@ impl<'a> Parser<'a> {
|
||||||
let data_type = self.parse_data_type()?;
|
let data_type = self.parse_data_type()?;
|
||||||
self.expect_token(&Token::Comma)?;
|
self.expect_token(&Token::Comma)?;
|
||||||
let expr = self.parse_expr()?;
|
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)?;
|
self.expect_token(&Token::RParen)?;
|
||||||
Ok(Expr::Convert {
|
Ok(Expr::Convert {
|
||||||
expr: Box::new(expr),
|
expr: Box::new(expr),
|
||||||
data_type: Some(data_type),
|
data_type: Some(data_type),
|
||||||
charset: None,
|
charset: None,
|
||||||
target_before_value: true,
|
target_before_value: true,
|
||||||
|
styles,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1489,6 +1495,7 @@ impl<'a> Parser<'a> {
|
||||||
data_type: None,
|
data_type: None,
|
||||||
charset: Some(charset),
|
charset: Some(charset),
|
||||||
target_before_value: false,
|
target_before_value: false,
|
||||||
|
styles: vec![],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
self.expect_token(&Token::Comma)?;
|
self.expect_token(&Token::Comma)?;
|
||||||
|
@ -1504,6 +1511,7 @@ impl<'a> Parser<'a> {
|
||||||
data_type: Some(data_type),
|
data_type: Some(data_type),
|
||||||
charset,
|
charset,
|
||||||
target_before_value: false,
|
target_before_value: false,
|
||||||
|
styles: vec![],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ use test_utils::*;
|
||||||
|
|
||||||
use sqlparser::ast::*;
|
use sqlparser::ast::*;
|
||||||
use sqlparser::dialect::{GenericDialect, MsSqlDialect};
|
use sqlparser::dialect::{GenericDialect, MsSqlDialect};
|
||||||
|
use sqlparser::parser::ParserError;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_mssql_identifiers() {
|
fn parse_mssql_identifiers() {
|
||||||
|
@ -437,9 +438,39 @@ fn parse_cast_varchar_max() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_convert() {
|
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(MAX), 'foo')");
|
||||||
ms().verified_expr("CONVERT(VARCHAR(10), 'foo')");
|
ms().verified_expr("CONVERT(VARCHAR(10), 'foo')");
|
||||||
ms().verified_expr("CONVERT(DECIMAL(10,5), 12.55)");
|
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]
|
#[test]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue