From 45fc758c8b0f25a18d127009b69087a6cebff175 Mon Sep 17 00:00:00 2001 From: git-hulk Date: Tue, 27 Aug 2024 18:50:55 +0800 Subject: [PATCH] Fix identifier starts with `$` should be regarded as a placeholder in SQLite Currently, `$var` would be parsed as an identifier instead of a placeholder in SQLite dialect, which is unexpected from the SQLite's documentation: https://www.sqlite.org/lang_expr.html#varparam. This relates to the issue comment: https://github.com/sqlparser-rs/sqlparser-rs/issues/291#issuecomment-2309797948 --- src/dialect/sqlite.rs | 1 - tests/sqlparser_sqlite.rs | 17 +++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/dialect/sqlite.rs b/src/dialect/sqlite.rs index daad6a159..cc08d7961 100644 --- a/src/dialect/sqlite.rs +++ b/src/dialect/sqlite.rs @@ -41,7 +41,6 @@ impl Dialect for SQLiteDialect { ch.is_ascii_lowercase() || ch.is_ascii_uppercase() || ch == '_' - || ch == '$' || ('\u{007f}'..='\u{ffff}').contains(&ch) } diff --git a/tests/sqlparser_sqlite.rs b/tests/sqlparser_sqlite.rs index 629ab5fc2..ce11b015a 100644 --- a/tests/sqlparser_sqlite.rs +++ b/tests/sqlparser_sqlite.rs @@ -20,6 +20,7 @@ mod test_utils; use test_utils::*; use sqlparser::ast::SelectItem::UnnamedExpr; +use sqlparser::ast::Value::Placeholder; use sqlparser::ast::*; use sqlparser::dialect::{GenericDialect, SQLiteDialect}; use sqlparser::parser::{ParserError, ParserOptions}; @@ -470,6 +471,22 @@ fn parse_start_transaction_with_modifier() { ); } +#[test] +fn test_dollar_identifier_as_placeholder() { + // This relates to the discussion in issue #291. The `$id` should be treated as a placeholder, + // not as an identifier in SQLite dialect. + // + // Reference: https://www.sqlite.org/lang_expr.html#varparam + match sqlite().verified_expr("id = $id") { + Expr::BinaryOp { op, left, right } => { + assert_eq!(op, BinaryOperator::Eq); + assert_eq!(left, Box::new(Expr::Identifier(Ident::new("id")))); + assert_eq!(right, Box::new(Expr::Value(Placeholder("$id".to_string())))); + } + _ => unreachable!(), + } +} + fn sqlite() -> TestedDialects { TestedDialects { dialects: vec![Box::new(SQLiteDialect {})],