fix: mysql backslash escaping (#373)

* fix: mysql backslash escaping

* fixes
This commit is contained in:
Alex Vasilev 2021-12-23 16:50:33 +03:00 committed by GitHub
parent 60ad78dafc
commit ea0eb1be61
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 67 additions and 6 deletions

View file

@ -31,8 +31,8 @@ use core::str::Chars;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use crate::dialect::Dialect;
use crate::dialect::SnowflakeDialect;
use crate::dialect::{Dialect, MySqlDialect};
use crate::keywords::{Keyword, ALL_KEYWORDS, ALL_KEYWORDS_INDEX};
/// SQL Token enumeration
@ -411,6 +411,7 @@ impl<'a> Tokenizer<'a> {
// string
'\'' => {
let s = self.tokenize_single_quoted_string(chars)?;
Ok(Some(Token::SingleQuotedString(s)))
}
// delimited (quoted) identifier
@ -636,18 +637,31 @@ impl<'a> Tokenizer<'a> {
) -> Result<String, TokenizerError> {
let mut s = String::new();
chars.next(); // consume the opening quote
// slash escaping is specific to MySQL dialect
let mut is_escaped = false;
while let Some(&ch) = chars.peek() {
match ch {
'\'' => {
chars.next(); // consume
let escaped_quote = chars.peek().map(|c| *c == '\'').unwrap_or(false);
if escaped_quote {
s.push('\'');
if is_escaped {
s.push(ch);
is_escaped = false;
} else if chars.peek().map(|c| *c == '\'').unwrap_or(false) {
s.push(ch);
chars.next();
} else {
return Ok(s);
}
}
'\\' => {
if dialect_of!(self is MySqlDialect) {
is_escaped = !is_escaped;
} else {
s.push(ch);
}
chars.next();
}
_ => {
chars.next(); // consume
s.push(ch);