mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-03 13:58:15 +00:00
Fix escaping of trailing quote in quoted identifiers (#505)
* Generalize EscapeSingleQuoteString to arbitrary quote character * Fix escaping of trailing quote in quoted identifiers * Add new tests instead of modifying existing tests
This commit is contained in:
parent
cc2559c097
commit
d19c6c323c
4 changed files with 56 additions and 18 deletions
|
@ -23,7 +23,7 @@ use alloc::{
|
|||
string::{String, ToString},
|
||||
vec::Vec,
|
||||
};
|
||||
use core::fmt::{self, Write};
|
||||
use core::fmt;
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
@ -128,16 +128,8 @@ impl fmt::Display for Ident {
|
|||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self.quote_style {
|
||||
Some(q) if q == '"' || q == '\'' || q == '`' => {
|
||||
f.write_char(q)?;
|
||||
let mut first = true;
|
||||
for s in self.value.split_inclusive(q) {
|
||||
if !first {
|
||||
f.write_char(q)?;
|
||||
}
|
||||
first = false;
|
||||
f.write_str(s)?;
|
||||
}
|
||||
f.write_char(q)
|
||||
let escaped = value::escape_quoted_string(&self.value, q);
|
||||
write!(f, "{}{}{}", q, escaped, q)
|
||||
}
|
||||
Some(q) if q == '[' => write!(f, "[{}]", self.value),
|
||||
None => f.write_str(&self.value),
|
||||
|
|
|
@ -178,13 +178,16 @@ impl fmt::Display for DateTimeField {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct EscapeSingleQuoteString<'a>(&'a str);
|
||||
pub struct EscapeQuotedString<'a> {
|
||||
string: &'a str,
|
||||
quote: char,
|
||||
}
|
||||
|
||||
impl<'a> fmt::Display for EscapeSingleQuoteString<'a> {
|
||||
impl<'a> fmt::Display for EscapeQuotedString<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
for c in self.0.chars() {
|
||||
if c == '\'' {
|
||||
write!(f, "\'\'")?;
|
||||
for c in self.string.chars() {
|
||||
if c == self.quote {
|
||||
write!(f, "{q}{q}", q = self.quote)?;
|
||||
} else {
|
||||
write!(f, "{}", c)?;
|
||||
}
|
||||
|
@ -193,8 +196,12 @@ impl<'a> fmt::Display for EscapeSingleQuoteString<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn escape_single_quote_string(s: &str) -> EscapeSingleQuoteString<'_> {
|
||||
EscapeSingleQuoteString(s)
|
||||
pub fn escape_quoted_string(string: &str, quote: char) -> EscapeQuotedString<'_> {
|
||||
EscapeQuotedString { string, quote }
|
||||
}
|
||||
|
||||
pub fn escape_single_quote_string(s: &str) -> EscapeQuotedString<'_> {
|
||||
escape_quoted_string(s, '\'')
|
||||
}
|
||||
|
||||
pub struct EscapeEscapedStringLiteral<'a>(&'a str);
|
||||
|
|
|
@ -325,6 +325,40 @@ fn parse_quote_identifiers_2() {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_quote_identifiers_3() {
|
||||
let sql = "SELECT ```quoted identifier```";
|
||||
assert_eq!(
|
||||
mysql().verified_stmt(sql),
|
||||
Statement::Query(Box::new(Query {
|
||||
with: None,
|
||||
body: SetExpr::Select(Box::new(Select {
|
||||
distinct: false,
|
||||
top: None,
|
||||
projection: vec![SelectItem::UnnamedExpr(Expr::Identifier(Ident {
|
||||
value: "`quoted identifier`".into(),
|
||||
quote_style: Some('`'),
|
||||
}))],
|
||||
into: None,
|
||||
from: vec![],
|
||||
lateral_views: vec![],
|
||||
selection: None,
|
||||
group_by: vec![],
|
||||
cluster_by: vec![],
|
||||
distribute_by: vec![],
|
||||
sort_by: vec![],
|
||||
having: None,
|
||||
qualify: None
|
||||
})),
|
||||
order_by: vec![],
|
||||
limit: None,
|
||||
offset: None,
|
||||
fetch: None,
|
||||
lock: None,
|
||||
}))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_unterminated_escape() {
|
||||
let sql = r#"SELECT 'I\'m not fine\'"#;
|
||||
|
|
|
@ -1441,6 +1441,11 @@ fn parse_quoted_identifier() {
|
|||
pg_and_generic().verified_stmt(r#"SELECT "quoted "" ident""#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_quoted_identifier_2() {
|
||||
pg_and_generic().verified_stmt(r#"SELECT """quoted ident""""#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_local_and_global() {
|
||||
pg_and_generic().verified_stmt("CREATE LOCAL TEMPORARY TABLE table (COL INT)");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue