Skip to content

Commit 0606024

Browse files
authored
Support for MSSQL CONVERT styles (apache#1219)
1 parent 6fcf8c9 commit 0606024

File tree

3 files changed

+47
-0
lines changed

3 files changed

+47
-0
lines changed

src/ast/mod.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,10 @@ pub enum Expr {
567567
charset: Option<ObjectName>,
568568
/// whether the target comes before the expr (MSSQL syntax)
569569
target_before_value: bool,
570+
/// How to translate the expression.
571+
///
572+
/// [MSSQL]: https://learn.microsoft.com/en-us/sql/t-sql/functions/cast-and-convert-transact-sql?view=sql-server-ver16#style
573+
styles: Vec<Expr>,
570574
},
571575
/// `CAST` an expression to a different data type e.g. `CAST(foo AS VARCHAR(123))`
572576
Cast {
@@ -979,6 +983,7 @@ impl fmt::Display for Expr {
979983
target_before_value,
980984
data_type,
981985
charset,
986+
styles,
982987
} => {
983988
write!(f, "CONVERT(")?;
984989
if let Some(data_type) = data_type {
@@ -994,6 +999,9 @@ impl fmt::Display for Expr {
994999
} else {
9951000
write!(f, "{expr}") // This should never happen
9961001
}?;
1002+
if !styles.is_empty() {
1003+
write!(f, ", {}", display_comma_separated(styles))?;
1004+
}
9971005
write!(f, ")")
9981006
}
9991007
Expr::Cast {

src/parser/mod.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1462,12 +1462,18 @@ impl<'a> Parser<'a> {
14621462
let data_type = self.parse_data_type()?;
14631463
self.expect_token(&Token::Comma)?;
14641464
let expr = self.parse_expr()?;
1465+
let styles = if self.consume_token(&Token::Comma) {
1466+
self.parse_comma_separated(Parser::parse_expr)?
1467+
} else {
1468+
Default::default()
1469+
};
14651470
self.expect_token(&Token::RParen)?;
14661471
Ok(Expr::Convert {
14671472
expr: Box::new(expr),
14681473
data_type: Some(data_type),
14691474
charset: None,
14701475
target_before_value: true,
1476+
styles,
14711477
})
14721478
}
14731479

@@ -1489,6 +1495,7 @@ impl<'a> Parser<'a> {
14891495
data_type: None,
14901496
charset: Some(charset),
14911497
target_before_value: false,
1498+
styles: vec![],
14921499
});
14931500
}
14941501
self.expect_token(&Token::Comma)?;
@@ -1504,6 +1511,7 @@ impl<'a> Parser<'a> {
15041511
data_type: Some(data_type),
15051512
charset,
15061513
target_before_value: false,
1514+
styles: vec![],
15071515
})
15081516
}
15091517

tests/sqlparser_mssql.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use test_utils::*;
2020

2121
use sqlparser::ast::*;
2222
use sqlparser::dialect::{GenericDialect, MsSqlDialect};
23+
use sqlparser::parser::ParserError;
2324

2425
#[test]
2526
fn parse_mssql_identifiers() {
@@ -437,9 +438,39 @@ fn parse_cast_varchar_max() {
437438

438439
#[test]
439440
fn parse_convert() {
441+
let sql = "CONVERT(INT, 1, 2, 3, NULL)";
442+
let Expr::Convert {
443+
expr,
444+
data_type,
445+
charset,
446+
target_before_value,
447+
styles,
448+
} = ms().verified_expr(sql)
449+
else {
450+
unreachable!()
451+
};
452+
assert_eq!(Expr::Value(number("1")), *expr);
453+
assert_eq!(Some(DataType::Int(None)), data_type);
454+
assert!(charset.is_none());
455+
assert!(target_before_value);
456+
assert_eq!(
457+
vec![
458+
Expr::Value(number("2")),
459+
Expr::Value(number("3")),
460+
Expr::Value(Value::Null),
461+
],
462+
styles
463+
);
464+
440465
ms().verified_expr("CONVERT(VARCHAR(MAX), 'foo')");
441466
ms().verified_expr("CONVERT(VARCHAR(10), 'foo')");
442467
ms().verified_expr("CONVERT(DECIMAL(10,5), 12.55)");
468+
469+
let error_sql = "SELECT CONVERT(INT, 'foo',) FROM T";
470+
assert_eq!(
471+
ParserError::ParserError("Expected an expression:, found: )".to_owned()),
472+
ms().parse_sql_statements(error_sql).unwrap_err()
473+
);
443474
}
444475

445476
#[test]

0 commit comments

Comments
 (0)