fix(mysql): handle export terminators and escaped quotes
This commit is contained in:
2 files changed
+60
-7
No files matched your search
@@ -382,11 +382,11 @@ impl SqlStatementSplitter {
|
||||
}
|
||||
|
||||
match ch {
|
||||
'\'' if !self.in_double_quote && !self.in_backtick && self.previous != Some('\\') => {
|
||||
'\'' if !self.in_double_quote && !self.in_backtick && !has_odd_trailing_backslashes(&self.buffer) => {
|
||||
self.in_single_quote = !self.in_single_quote;
|
||||
self.buffer.push(ch);
|
||||
}
|
||||
'"' if !self.in_single_quote && !self.in_backtick && self.previous != Some('\\') => {
|
||||
'"' if !self.in_single_quote && !self.in_backtick && !has_odd_trailing_backslashes(&self.buffer) => {
|
||||
self.in_double_quote = !self.in_double_quote;
|
||||
self.buffer.push(ch);
|
||||
}
|
||||
@@ -522,6 +522,10 @@ impl SqlStatementSplitter {
|
||||
}
|
||||
}
|
||||
|
||||
fn has_odd_trailing_backslashes(sql: &str) -> bool {
|
||||
sql.as_bytes().iter().rev().take_while(|byte| **byte == b'\\').count() % 2 == 1
|
||||
}
|
||||
|
||||
pub fn split_sql_statements(sql: &str) -> Vec<String> {
|
||||
split_sql_statements_with_options(sql, SqlParsingOptions::default())
|
||||
}
|
||||
@@ -2457,6 +2461,39 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn closes_mysql_string_after_even_trailing_backslashes() {
|
||||
let sql = r#"CREATE TABLE paths (value varchar(100) COMMENT 'Windows path\\'); DROP TABLE paths;"#;
|
||||
|
||||
assert_eq!(
|
||||
split_sql_statements_for_database(sql, DatabaseType::Mysql),
|
||||
vec![r#"CREATE TABLE paths (value varchar(100) COMMENT 'Windows path\\')"#, "DROP TABLE paths"]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keeps_mysql_string_open_after_odd_trailing_backslashes() {
|
||||
let sql = r#"INSERT INTO notes VALUES ('it\'s; still one value'); SELECT 1;"#;
|
||||
|
||||
assert_eq!(
|
||||
split_sql_statements_for_database(sql, DatabaseType::Mysql),
|
||||
vec![r#"INSERT INTO notes VALUES ('it\'s; still one value')"#, "SELECT 1"]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn closes_mysql_string_after_even_trailing_backslashes_across_chunks() {
|
||||
let mut splitter =
|
||||
SqlStatementSplitter::with_options(SqlParsingOptions::for_database_type(DatabaseType::Mysql));
|
||||
|
||||
assert!(splitter.push_chunk("CREATE TABLE paths (value varchar(100) COMMENT 'Windows path\\").is_empty());
|
||||
assert_eq!(
|
||||
splitter.push_chunk("\\'); DROP TABLE paths;"),
|
||||
vec![r#"CREATE TABLE paths (value varchar(100) COMMENT 'Windows path\\')"#, "DROP TABLE paths"]
|
||||
);
|
||||
assert!(splitter.finish().is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn emits_trailing_statement_without_semicolon() {
|
||||
assert_eq!(
|
||||
|
||||
Reference in new issue
Block a user