Skip to content

Commit f89df29

Browse files
committed
Guard quote delimited string by explicit dialect setting
1 parent e7438c1 commit f89df29

File tree

5 files changed

+38
-10
lines changed

5 files changed

+38
-10
lines changed

src/dialect/generic.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,4 +195,8 @@ impl Dialect for GenericDialect {
195195
fn supports_interval_options(&self) -> bool {
196196
true
197197
}
198+
199+
fn supports_quote_delimited_string(&self) -> bool {
200+
true
201+
}
198202
}

src/dialect/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1209,6 +1209,13 @@ pub trait Dialect: Debug + Any {
12091209
fn supports_semantic_view_table_factor(&self) -> bool {
12101210
false
12111211
}
1212+
1213+
/// Support quote delimited string literals, e.g. `Q'{...}'`
1214+
///
1215+
/// [Oracle](https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/Literals.html#GUID-1824CBAA-6E16-4921-B2A6-112FB02248DA)
1216+
fn supports_quote_delimited_string(&self) -> bool {
1217+
false
1218+
}
12121219
}
12131220

12141221
/// This represents the operators for which precedence must be defined

src/dialect/oracle.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,4 +95,8 @@ impl Dialect for OracleDialect {
9595
fn supports_group_by_expr(&self) -> bool {
9696
true
9797
}
98+
99+
fn supports_quote_delimited_string(&self) -> bool {
100+
true
101+
}
98102
}

src/tokenizer.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,11 @@ use serde::{Deserialize, Serialize};
4040
#[cfg(feature = "visitor")]
4141
use sqlparser_derive::{Visit, VisitMut};
4242

43+
use crate::dialect::Dialect;
4344
use crate::dialect::{
4445
BigQueryDialect, DuckDbDialect, GenericDialect, MySqlDialect, PostgreSqlDialect,
4546
SnowflakeDialect,
4647
};
47-
use crate::dialect::{Dialect, OracleDialect};
4848
use crate::keywords::{Keyword, ALL_KEYWORDS, ALL_KEYWORDS_INDEX};
4949
use crate::{
5050
ast::{DollarQuotedString, QuoteDelimitedString},
@@ -1043,7 +1043,8 @@ impl<'a> Tokenizer<'a> {
10431043
self.tokenize_single_quoted_string(chars, '\'', backslash_escape)?;
10441044
Ok(Some(Token::NationalStringLiteral(s)))
10451045
}
1046-
Some(&q @ 'q') | Some(&q @ 'Q') if dialect_of!(self is OracleDialect | GenericDialect) =>
1046+
Some(&q @ 'q') | Some(&q @ 'Q')
1047+
if self.dialect.supports_quote_delimited_string() =>
10471048
{
10481049
chars.next(); // consume and check the next char
10491050
if let Some('\'') = chars.peek() {
@@ -1061,7 +1062,7 @@ impl<'a> Tokenizer<'a> {
10611062
}
10621063
}
10631064
}
1064-
q @ 'Q' | q @ 'q' if dialect_of!(self is OracleDialect | GenericDialect) => {
1065+
q @ 'Q' | q @ 'q' if self.dialect.supports_quote_delimited_string() => {
10651066
chars.next(); // consume and check the next char
10661067
if let Some('\'') = chars.peek() {
10671068
self.tokenize_quote_delimited_string(chars, &[q])

tests/sqlparser_oracle.rs

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@
2121
use pretty_assertions::assert_eq;
2222

2323
use sqlparser::{
24-
ast::{BinaryOperator, Expr, Ident, QuoteDelimitedString, Value, ValueWithSpan}, dialect::OracleDialect, parser::ParserError, tokenizer::Span
24+
ast::{BinaryOperator, Expr, Ident, QuoteDelimitedString, Value, ValueWithSpan},
25+
dialect::OracleDialect,
26+
parser::ParserError,
27+
tokenizer::Span,
2528
};
2629
use test_utils::{expr_from_projection, number, TestedDialects};
2730

@@ -188,19 +191,28 @@ fn parse_invalid_quote_delimited_strings() {
188191
for q in [' ', '\t', '\r', '\n'] {
189192
assert_eq!(
190193
oracle().parse_sql_statements(&format!("SELECT Q'{q}abc{q}' FROM dual")),
191-
Err(ParserError::TokenizerError("Invalid space, tab, newline, or EOF after 'Q'' at Line: 1, Column: 10".into())),
192-
"with quote char {q:?}");
194+
Err(ParserError::TokenizerError(
195+
"Invalid space, tab, newline, or EOF after 'Q'' at Line: 1, Column: 10".into()
196+
)),
197+
"with quote char {q:?}"
198+
);
193199
}
194200
// ~ invalid eof after quote
195201
assert_eq!(
196202
oracle().parse_sql_statements("SELECT Q'"),
197-
Err(ParserError::TokenizerError("Invalid space, tab, newline, or EOF after 'Q'' at Line: 1, Column: 10".into())),
198-
"with EOF quote char");
203+
Err(ParserError::TokenizerError(
204+
"Invalid space, tab, newline, or EOF after 'Q'' at Line: 1, Column: 10".into()
205+
)),
206+
"with EOF quote char"
207+
);
199208
// ~ unterminated string
200209
assert_eq!(
201210
oracle().parse_sql_statements("SELECT Q'|asdfa...."),
202-
Err(ParserError::TokenizerError("Unterminated string literal at Line: 1, Column: 9".into())),
203-
"with EOF quote char");
211+
Err(ParserError::TokenizerError(
212+
"Unterminated string literal at Line: 1, Column: 9".into()
213+
)),
214+
"with EOF quote char"
215+
);
204216
}
205217

206218
#[test]

0 commit comments

Comments
 (0)