Skip to content

Commit ba66a66

Browse files
committed
snowflake: string literal parse esc quotes
1 parent d7fa30c commit ba66a66

1 file changed

Lines changed: 20 additions & 12 deletions

File tree

src/tokenizer.rs

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ pub enum Token {
3939
/// A character that could not be tokenized
4040
Char(char),
4141
/// Single quoted string: i.e: 'string'
42+
/// This should retains the escaped character sequences so that
43+
/// .to_string() of the value will give the value that was in the input
4244
SingleQuotedString(String),
4345
/// "National" string literal: i.e: N'string'
4446
NationalStringLiteral(String),
@@ -550,22 +552,28 @@ impl<'a> Tokenizer<'a> {
550552
) -> Result<String, TokenizerError> {
551553
let mut s = String::new();
552554
chars.next(); // consume the opening quote
553-
while let Some(&ch) = chars.peek() {
555+
while let Some(ch) = chars.next() {
556+
let next_char_is_quote = chars.peek().map(|c| *c == '\'').unwrap_or(false);
554557
match ch {
555-
'\'' => {
556-
chars.next(); // consume
557-
let escaped_quote = chars.peek().map(|c| *c == '\'').unwrap_or(false);
558-
if escaped_quote {
559-
s.push('\'');
560-
chars.next();
561-
} else {
562-
return Ok(s);
558+
// allow backslash to escape the next character, whatever it is
559+
'\\' => {
560+
s.push('\\');
561+
if let Some(next_ch) = chars.next() {
562+
s.push(next_ch);
563563
}
564564
}
565-
_ => {
566-
chars.next(); // consume
567-
s.push(ch);
565+
// bq allows escaping only with backslash; other warehouses
566+
// allow escaping the quote character by repeating it
567+
_ if !dialect_of!(self is BigQueryDialect)
568+
&& ch == '\''
569+
&& next_char_is_quote =>
570+
{
571+
s.push('\'');
572+
s.push('\'');
573+
chars.next(); // consume '
568574
}
575+
'\'' => return Ok(s),
576+
_ => s.push(ch),
569577
}
570578
}
571579
self.tokenizer_error("Unterminated string literal")

0 commit comments

Comments
 (0)