Skip to content

Commit d8f92e8

Browse files
committed
dollar prefix support for money constants in mssql
1 parent 6f8e7b8 commit d8f92e8

File tree

4 files changed

+37
-0
lines changed

4 files changed

+37
-0
lines changed

src/dialect/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1047,6 +1047,12 @@ pub trait Dialect: Debug + Any {
10471047
false
10481048
}
10491049

1050+
/// Returns true if this dialect supports `$` as a prefix for money literals
1051+
/// e.g. `SELECT $123.45` (T-SQL)
1052+
fn supports_dollar_as_money_prefix(&self) -> bool {
1053+
false
1054+
}
1055+
10501056
/// Does the dialect support with clause in create index statement?
10511057
/// e.g. `CREATE INDEX idx ON t WITH (key = value, key2)`
10521058
fn supports_create_index_with_clause(&self) -> bool {

src/dialect/mssql.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,12 @@ impl Dialect for MsSqlDialect {
6565
true
6666
}
6767

68+
/// SQL Server supports `$` as a prefix for money literals
69+
/// <https://learn.microsoft.com/en-us/sql/t-sql/data-types/constants-transact-sql?view=sql-server-ver17#money-constants>
70+
fn supports_dollar_as_money_prefix(&self) -> bool {
71+
true
72+
}
73+
6874
fn supports_connect_by(&self) -> bool {
6975
true
7076
}

src/tokenizer.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1966,6 +1966,19 @@ impl<'a> Tokenizer<'a> {
19661966
|| matches!(ch, '$' if self.dialect.supports_dollar_placeholder())
19671967
}));
19681968

1969+
// If the dialect supports a dollar sign as a money prefix (e.g., T-SQL),
1970+
// and the value so far is all digits, check for a decimal part, e.g. `$123.45`
1971+
if matches!(chars.peek(), Some('.'))
1972+
&& self.dialect.supports_dollar_as_money_prefix()
1973+
&& !value.is_empty()
1974+
&& value.chars().all(|c| c.is_ascii_digit())
1975+
{
1976+
value.push('.');
1977+
chars.next();
1978+
value.push_str(&peeking_take_while(chars, |ch| ch.is_ascii_digit()));
1979+
return Ok(Token::Placeholder(format!("${value}")));
1980+
}
1981+
19691982
// If the dialect does not support dollar-quoted strings, don't look for the end delimiter.
19701983
if matches!(chars.peek(), Some('$')) && !self.dialect.supports_dollar_placeholder() {
19711984
chars.next();

tests/sqlparser_mssql.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2860,3 +2860,15 @@ fn parse_mssql_update_with_output_into() {
28602860
"UPDATE employees SET salary = salary * 1.1 OUTPUT INSERTED.id, DELETED.salary, INSERTED.salary INTO @changes WHERE department = 'Engineering'",
28612861
);
28622862
}
2863+
2864+
#[test]
2865+
fn parse_mssql_money_constants() {
2866+
ms().verified_only_select("SELECT CEILING($123.45)");
2867+
2868+
ms().verified_only_select("SELECT $123.45");
2869+
ms().verified_only_select("SELECT $0.99");
2870+
ms().verified_only_select("SELECT $0.0");
2871+
2872+
ms().verified_only_select("SELECT $123");
2873+
ms().verified_only_select("SELECT $0");
2874+
}

0 commit comments

Comments
 (0)