This is an automated email from the ASF dual-hosted git repository. LucaCappelletti94 pushed a commit to branch byte-string-display-escaping in repository https://gitbox.apache.org/repos/asf/datafusion-sqlparser-rs.git
commit f2e1d68108e7bf6e49f46d5fcb59697da27467a5 Author: LucaCappelletti94 <[email protected]> AuthorDate: Mon Sep 21 22:47:39 2026 +0200 Generic: Fix quote escaping when displaying byte and raw string literals --- src/ast/value.rs | 53 +++++++++++++++++++++++++++++++++++++++++---- tests/sqlparser_bigquery.rs | 27 +++++++++++++++++++++++ tests/sqlparser_mysql.rs | 6 +++++ tests/sqlparser_postgres.rs | 6 +++++ 4 files changed, 88 insertions(+), 4 deletions(-) diff --git a/src/ast/value.rs b/src/ast/value.rs index a906c4b3..967e6477 100644 --- a/src/ast/value.rs +++ b/src/ast/value.rs @@ -278,12 +278,20 @@ impl fmt::Display for Value { Value::NationalQuoteDelimitedStringLiteral(v) => write!(f, "N{v}"), Value::HexStringLiteral(v) => write!(f, "X'{v}'"), Value::Boolean(v) => write!(f, "{v}"), - Value::SingleQuotedByteStringLiteral(v) => write!(f, "B'{v}'"), - Value::DoubleQuotedByteStringLiteral(v) => write!(f, "B\"{v}\""), + Value::SingleQuotedByteStringLiteral(v) => { + write!(f, "B'{}'", escape_single_quote_string(v)) + } + Value::DoubleQuotedByteStringLiteral(v) => { + write!(f, "B\"{}\"", escape_double_quote_string(v)) + } Value::TripleSingleQuotedByteStringLiteral(v) => write!(f, "B'''{v}'''"), Value::TripleDoubleQuotedByteStringLiteral(v) => write!(f, r#"B"""{v}""""#), - Value::SingleQuotedRawStringLiteral(v) => write!(f, "R'{v}'"), - Value::DoubleQuotedRawStringLiteral(v) => write!(f, "R\"{v}\""), + Value::SingleQuotedRawStringLiteral(v) => { + write!(f, "R'{}'", escape_single_quote_string(v)) + } + Value::DoubleQuotedRawStringLiteral(v) => { + write!(f, "R\"{}\"", escape_double_quote_string(v)) + } Value::TripleSingleQuotedRawStringLiteral(v) => write!(f, "R'''{v}'''"), Value::TripleDoubleQuotedRawStringLiteral(v) => write!(f, r#"R"""{v}""""#), Value::Null => write!(f, "NULL"), @@ -717,3 +725,40 @@ fn test_escape_quoted_string_with_multibyte_quote_char() { "a🦀🦀b🦀🦀c" ); } + +#[cfg(test)] +#[test] +fn test_byte_and_raw_string_literal_display_escaping() { + assert_eq!( + Value::SingleQuotedByteStringLiteral("'".to_string()).to_string(), + "B''''" + ); + assert_eq!( + Value::SingleQuotedByteStringLiteral("it's".to_string()).to_string(), + "B'it''s'" + ); + assert_eq!( + Value::DoubleQuotedByteStringLiteral("\"".to_string()).to_string(), + "B\"\"\"\"" + ); + assert_eq!( + Value::DoubleQuotedByteStringLiteral("it\"s".to_string()).to_string(), + "B\"it\"\"s\"" + ); + assert_eq!( + Value::SingleQuotedRawStringLiteral("'".to_string()).to_string(), + "R''''" + ); + assert_eq!( + Value::SingleQuotedRawStringLiteral("it's".to_string()).to_string(), + "R'it''s'" + ); + assert_eq!( + Value::DoubleQuotedRawStringLiteral("\"".to_string()).to_string(), + "R\"\"\"\"" + ); + assert_eq!( + Value::DoubleQuotedRawStringLiteral("it\"s".to_string()).to_string(), + "R\"it\"\"s\"" + ); +} diff --git a/tests/sqlparser_bigquery.rs b/tests/sqlparser_bigquery.rs index 97f71cfe..d6ae192e 100644 --- a/tests/sqlparser_bigquery.rs +++ b/tests/sqlparser_bigquery.rs @@ -2957,3 +2957,30 @@ fn parse_from_first_select() { bigquery().verified_stmt("FROM t SELECT a, b"); bigquery().verified_stmt("FROM t |> WHERE a > 1 |> SELECT a"); } + +#[test] +fn test_byte_and_raw_string_quote_escaping() { + let generic = TestedDialects::new(vec![Box::new(GenericDialect {})]); + generic.verified_stmt("SELECT B''''"); + generic.verified_stmt("SELECT B'it''s'"); + generic.verified_stmt("SELECT B\"\"\"\""); + generic.verified_stmt(r#"SELECT B"it""s""#); + generic.verified_stmt("SELECT R'it''s'"); + generic.verified_stmt(r#"SELECT R"it""s""#); + generic.verified_stmt("SELECT COUNSELECT AS name, B''''"); + + bigquery_and_generic().verified_stmt("SELECT B'it''s'"); + bigquery_and_generic().verified_stmt(r#"SELECT B"it""s""#); + bigquery_and_generic().verified_stmt("SELECT R'it''s'"); + bigquery_and_generic().verified_stmt(r#"SELECT R"it""s""#); + + let err = generic + .parse_sql_statements("SELECT B'unterminated") + .unwrap_err(); + assert_eq!( + ParserError::TokenizerError( + "Unterminated string literal at Line: 1, Column: 9".to_string(), + ), + err + ); +} diff --git a/tests/sqlparser_mysql.rs b/tests/sqlparser_mysql.rs index 97f21374..ffa2e47a 100644 --- a/tests/sqlparser_mysql.rs +++ b/tests/sqlparser_mysql.rs @@ -5052,3 +5052,9 @@ fn parse_is_distinct_from_json_arrow_precedence() { mysql_and_generic().verified_expr("a IS NOT DISTINCT FROM b ->> 'k'") ); } + +#[test] +fn parse_bitstring_literal_escaping() { + mysql_and_generic().verified_stmt("SELECT B''''"); + mysql_and_generic().verified_stmt("SELECT B'it''s'"); +} diff --git a/tests/sqlparser_postgres.rs b/tests/sqlparser_postgres.rs index ab2d4b8e..e097ca63 100644 --- a/tests/sqlparser_postgres.rs +++ b/tests/sqlparser_postgres.rs @@ -9984,3 +9984,9 @@ fn parse_unary_minus_before_pg_prefix_operators() { pg().verified_stmt("SELECT - @ 2"); pg().one_statement_parses_to("SELECT - #x", "SELECT - # x"); } + +#[test] +fn parse_bitstring_literal_escaping() { + pg_and_generic().verified_stmt("SELECT B''''"); + pg_and_generic().verified_stmt("SELECT B'it''s'"); +} --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
