Skip to content

Commit 1fab7b2

Browse files
Merge pull request #8 from AikidoSec/national-strings
National strings: check if dialect supports backslash escape
2 parents 3fb8f4b + e13ac19 commit 1fab7b2

File tree

2 files changed

+44
-2
lines changed

2 files changed

+44
-2
lines changed

src/test_utils.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ use core::fmt::Debug;
3333

3434
use crate::dialect::*;
3535
use crate::parser::{Parser, ParserError};
36-
use crate::tokenizer::Tokenizer;
36+
use crate::tokenizer::{Token, Tokenizer};
3737
use crate::{ast::*, parser::ParserOptions};
3838

3939
#[cfg(test)]
@@ -215,6 +215,18 @@ impl TestedDialects {
215215
pub fn verified_expr(&self, sql: &str) -> Expr {
216216
self.expr_parses_to(sql, sql)
217217
}
218+
219+
/// Check that the tokenizer returns the expected tokens for the given SQL.
220+
pub fn tokenizes_to(&self, sql: &str, expected: Vec<Token>) {
221+
self.dialects.iter().for_each(|dialect| {
222+
let mut tokenizer = Tokenizer::new(&**dialect, sql);
223+
if let Some(options) = &self.options {
224+
tokenizer = tokenizer.with_unescape(options.unescape);
225+
}
226+
let tokens = tokenizer.tokenize().unwrap();
227+
assert_eq!(expected, tokens);
228+
});
229+
}
218230
}
219231

220232
/// Returns all available dialects.

src/tokenizer.rs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -776,7 +776,10 @@ impl<'a> Tokenizer<'a> {
776776
match chars.peek() {
777777
Some('\'') => {
778778
// N'...' - a <national character string literal>
779-
let s = self.tokenize_single_quoted_string(chars, '\'', true)?;
779+
let backslash_escape =
780+
self.dialect.supports_string_literal_backslash_escape();
781+
let s =
782+
self.tokenize_single_quoted_string(chars, '\'', backslash_escape)?;
780783
Ok(Some(Token::NationalStringLiteral(s)))
781784
}
782785
_ => {
@@ -1890,6 +1893,7 @@ mod tests {
18901893
use crate::dialect::{
18911894
BigQueryDialect, ClickHouseDialect, HiveDialect, MsSqlDialect, MySqlDialect, SQLiteDialect,
18921895
};
1896+
use crate::test_utils::all_dialects_where;
18931897
use core::fmt::Debug;
18941898

18951899
#[test]
@@ -3214,4 +3218,30 @@ mod tests {
32143218
let expected = vec![Token::SingleQuotedString("''".to_string())];
32153219
compare(expected, tokens);
32163220
}
3221+
3222+
#[test]
3223+
fn test_national_strings_backslash_escape_not_supported() {
3224+
all_dialects_where(|dialect| !dialect.supports_string_literal_backslash_escape())
3225+
.tokenizes_to(
3226+
"select n'''''\\'",
3227+
vec![
3228+
Token::make_keyword("select"),
3229+
Token::Whitespace(Whitespace::Space),
3230+
Token::NationalStringLiteral("''\\".to_string()),
3231+
],
3232+
);
3233+
}
3234+
3235+
#[test]
3236+
fn test_national_strings_backslash_escape_supported() {
3237+
all_dialects_where(|dialect| dialect.supports_string_literal_backslash_escape())
3238+
.tokenizes_to(
3239+
"select n'''''\\''",
3240+
vec![
3241+
Token::make_keyword("select"),
3242+
Token::Whitespace(Whitespace::Space),
3243+
Token::NationalStringLiteral("'''".to_string()),
3244+
],
3245+
);
3246+
}
32173247
}

0 commit comments

Comments
 (0)