Skip to content

Commit d2d9c40

Browse files
committed
Don't support quoted strings for SQLite
1 parent c92f2fa commit d2d9c40

File tree

4 files changed

+43
-11
lines changed

4 files changed

+43
-11
lines changed

src/dialect/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,10 @@ pub trait Dialect: Debug + Any {
527527
false
528528
}
529529

530+
fn supports_dollar_quoted_string(&self) -> bool {
531+
true
532+
}
533+
530534
/// Does the dialect support with clause in create index statement?
531535
/// e.g. `CREATE INDEX idx ON t WITH (key = value, key2)`
532536
fn supports_create_index_with_clause(&self) -> bool {

src/dialect/sqlite.rs

+4
Original file line numberDiff line numberDiff line change
@@ -81,4 +81,8 @@ impl Dialect for SQLiteDialect {
8181
fn supports_asc_desc_in_column_definition(&self) -> bool {
8282
true
8383
}
84+
85+
fn supports_dollar_quoted_string(&self) -> bool {
86+
false
87+
}
8488
}

src/tokenizer.rs

+34-11
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ use sqlparser_derive::{Visit, VisitMut};
4343
use crate::ast::DollarQuotedString;
4444
use crate::dialect::Dialect;
4545
use crate::dialect::{
46-
BigQueryDialect, DuckDbDialect, GenericDialect, MySqlDialect, PostgreSqlDialect, SQLiteDialect,
46+
BigQueryDialect, DuckDbDialect, GenericDialect, MySqlDialect, PostgreSqlDialect,
4747
SnowflakeDialect,
4848
};
4949
use crate::keywords::{Keyword, ALL_KEYWORDS, ALL_KEYWORDS_INDEX};
@@ -1278,15 +1278,11 @@ impl<'a> Tokenizer<'a> {
12781278

12791279
chars.next();
12801280

1281-
if let Some('$') = chars.peek() {
1281+
// Check if the second character is a dollar sign
1282+
let next_is_dollar = matches!(chars.peek(), Some('$'));
1283+
if next_is_dollar && self.dialect.supports_dollar_quoted_string() {
12821284
chars.next();
12831285

1284-
// Treat `$$` as a placeholder for SQLite
1285-
// See https://www.sqlite.org/lang_expr.html#varparam
1286-
if self.dialect.is::<SQLiteDialect>() {
1287-
return Ok(Token::Placeholder("$$".to_string()));
1288-
}
1289-
12901286
let mut is_terminated = false;
12911287
let mut prev: Option<char> = None;
12921288

@@ -1318,10 +1314,13 @@ impl<'a> Tokenizer<'a> {
13181314
};
13191315
} else {
13201316
value.push_str(&peeking_take_while(chars, |ch| {
1321-
ch.is_alphanumeric() || ch == '_'
1317+
ch.is_alphanumeric()
1318+
|| ch == '_'
1319+
|| matches!(ch, '$' if !self.dialect.supports_dollar_quoted_string())
13221320
}));
13231321

1324-
if let Some('$') = chars.peek() {
1322+
let next_is_dollar = matches!(chars.peek(), Some('$'));
1323+
if next_is_dollar && self.dialect.supports_dollar_quoted_string() {
13251324
chars.next();
13261325

13271326
'searching_for_end: loop {
@@ -1891,7 +1890,7 @@ fn take_char_from_hex_digits(
18911890
mod tests {
18921891
use super::*;
18931892
use crate::dialect::{
1894-
BigQueryDialect, ClickHouseDialect, HiveDialect, MsSqlDialect, MySqlDialect,
1893+
BigQueryDialect, ClickHouseDialect, HiveDialect, MsSqlDialect, MySqlDialect, SQLiteDialect,
18951894
};
18961895
use core::fmt::Debug;
18971896

@@ -2327,6 +2326,30 @@ mod tests {
23272326
);
23282327
}
23292328

2329+
#[test]
2330+
fn tokenize_dollar_placeholder_sqlite() {
2331+
let sql = String::from("SELECT $$, $$ABC$$, $ABC$, $ABC");
2332+
let dialect = SQLiteDialect {};
2333+
let tokens = Tokenizer::new(&dialect, &sql).tokenize().unwrap();
2334+
assert_eq!(
2335+
tokens,
2336+
vec![
2337+
Token::make_keyword("SELECT"),
2338+
Token::Whitespace(Whitespace::Space),
2339+
Token::Placeholder("$$".into()),
2340+
Token::Comma,
2341+
Token::Whitespace(Whitespace::Space),
2342+
Token::Placeholder("$$ABC$$".into()),
2343+
Token::Comma,
2344+
Token::Whitespace(Whitespace::Space),
2345+
Token::Placeholder("$ABC$".into()),
2346+
Token::Comma,
2347+
Token::Whitespace(Whitespace::Space),
2348+
Token::Placeholder("$ABC".into()),
2349+
]
2350+
);
2351+
}
2352+
23302353
#[test]
23312354
fn tokenize_dollar_quoted_string_untagged() {
23322355
let sql =

tests/sqlparser_sqlite.rs

+1
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,7 @@ fn test_dollar_identifier_as_placeholder() {
569569
_ => unreachable!(),
570570
}
571571

572+
// $$ is a valid placeholder in SQLite
572573
match sqlite().verified_expr("id = $$") {
573574
Expr::BinaryOp { op, left, right } => {
574575
assert_eq!(op, BinaryOperator::Eq);

0 commit comments

Comments
 (0)