Make TypedString preserve quote style (#1679)

This commit is contained in:
Paul Grau 2025-01-31 08:04:41 +02:00 committed by GitHub
parent aeaafbe6e4
commit 447142c6d0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 132 additions and 55 deletions

View file

@ -39,43 +39,45 @@ fn parse_literal_string() {
r#"'''triple-single'unescaped''', "#,
r#""double\"escaped", "#,
r#""""triple-double\"escaped""", "#,
r#""""triple-double"unescaped""""#,
r#""""triple-double"unescaped""", "#,
r#""""triple-double'unescaped""", "#,
r#"'''triple-single"unescaped'''"#,
);
let dialect = TestedDialects::new_with_options(
vec![Box::new(BigQueryDialect {})],
ParserOptions::new().with_unescape(false),
);
let select = dialect.verified_only_select(sql);
assert_eq!(10, select.projection.len());
assert_eq!(12, select.projection.len());
assert_eq!(
&Expr::Value(Value::SingleQuotedString("single".to_string())),
&Expr::Value(Value::SingleQuotedString("single".into())),
expr_from_projection(&select.projection[0])
);
assert_eq!(
&Expr::Value(Value::DoubleQuotedString("double".to_string())),
&Expr::Value(Value::DoubleQuotedString("double".into())),
expr_from_projection(&select.projection[1])
);
assert_eq!(
&Expr::Value(Value::TripleSingleQuotedString("triple-single".to_string())),
&Expr::Value(Value::TripleSingleQuotedString("triple-single".into())),
expr_from_projection(&select.projection[2])
);
assert_eq!(
&Expr::Value(Value::TripleDoubleQuotedString("triple-double".to_string())),
&Expr::Value(Value::TripleDoubleQuotedString("triple-double".into())),
expr_from_projection(&select.projection[3])
);
assert_eq!(
&Expr::Value(Value::SingleQuotedString(r#"single\'escaped"#.to_string())),
&Expr::Value(Value::SingleQuotedString(r#"single\'escaped"#.into())),
expr_from_projection(&select.projection[4])
);
assert_eq!(
&Expr::Value(Value::TripleSingleQuotedString(
r#"triple-single\'escaped"#.to_string()
r#"triple-single\'escaped"#.into()
)),
expr_from_projection(&select.projection[5])
);
assert_eq!(
&Expr::Value(Value::TripleSingleQuotedString(
r#"triple-single'unescaped"#.to_string()
r#"triple-single'unescaped"#.into()
)),
expr_from_projection(&select.projection[6])
);
@ -95,6 +97,18 @@ fn parse_literal_string() {
)),
expr_from_projection(&select.projection[9])
);
assert_eq!(
&Expr::Value(Value::TripleDoubleQuotedString(
r#"triple-double'unescaped"#.to_string()
)),
expr_from_projection(&select.projection[10])
);
assert_eq!(
&Expr::Value(Value::TripleSingleQuotedString(
r#"triple-single"unescaped"#.to_string()
)),
expr_from_projection(&select.projection[11])
);
}
#[test]
@ -588,7 +602,7 @@ fn parse_tuple_struct_literal() {
&Expr::Tuple(vec![
Expr::Value(number("1")),
Expr::Value(number("1.0")),
Expr::Value(Value::SingleQuotedString("123".to_string())),
Expr::Value(Value::SingleQuotedString("123".into())),
Expr::Value(Value::Boolean(true))
]),
expr_from_projection(&select.projection[1])
@ -616,7 +630,7 @@ fn parse_typeless_struct_syntax() {
assert_eq!(
&Expr::Struct {
values: vec![Expr::Value(Value::SingleQuotedString("abc".to_string())),],
values: vec![Expr::Value(Value::SingleQuotedString("abc".into())),],
fields: Default::default()
},
expr_from_projection(&select.projection[1])
@ -639,7 +653,7 @@ fn parse_typeless_struct_syntax() {
name: Ident::from("a")
},
Expr::Named {
expr: Expr::Value(Value::SingleQuotedString("abc".to_string())).into(),
expr: Expr::Value(Value::SingleQuotedString("abc".into())).into(),
name: Ident::from("b")
},
],
@ -804,9 +818,7 @@ fn parse_typed_struct_syntax_bigquery() {
assert_eq!(4, select.projection.len());
assert_eq!(
&Expr::Struct {
values: vec![Expr::Value(Value::DoubleQuotedString(
"2011-05-05".to_string()
)),],
values: vec![Expr::Value(Value::DoubleQuotedString("2011-05-05".into())),],
fields: vec![StructField {
field_name: None,
field_type: DataType::Date
@ -818,7 +830,7 @@ fn parse_typed_struct_syntax_bigquery() {
&Expr::Struct {
values: vec![Expr::TypedString {
data_type: DataType::Datetime(None),
value: "1999-01-01 01:23:34.45".to_string()
value: Value::SingleQuotedString("1999-01-01 01:23:34.45".into())
},],
fields: vec![StructField {
field_name: None,
@ -854,7 +866,7 @@ fn parse_typed_struct_syntax_bigquery() {
assert_eq!(
&Expr::Struct {
values: vec![Expr::Interval(Interval {
value: Box::new(Expr::Value(Value::SingleQuotedString("2".to_string()))),
value: Box::new(Expr::Value(Value::SingleQuotedString("2".into()))),
leading_field: Some(DateTimeField::Hour),
leading_precision: None,
last_field: None,
@ -871,7 +883,9 @@ fn parse_typed_struct_syntax_bigquery() {
&Expr::Struct {
values: vec![Expr::TypedString {
data_type: DataType::JSON,
value: r#"{"class" : {"students" : [{"name" : "Jane"}]}}"#.to_string()
value: Value::SingleQuotedString(
r#"{"class" : {"students" : [{"name" : "Jane"}]}}"#.into()
)
},],
fields: vec![StructField {
field_name: None,
@ -886,7 +900,7 @@ fn parse_typed_struct_syntax_bigquery() {
assert_eq!(3, select.projection.len());
assert_eq!(
&Expr::Struct {
values: vec![Expr::Value(Value::DoubleQuotedString("foo".to_string())),],
values: vec![Expr::Value(Value::DoubleQuotedString("foo".into())),],
fields: vec![StructField {
field_name: None,
field_type: DataType::String(Some(42))
@ -898,7 +912,7 @@ fn parse_typed_struct_syntax_bigquery() {
&Expr::Struct {
values: vec![Expr::TypedString {
data_type: DataType::Timestamp(None, TimezoneInfo::None),
value: "2008-12-25 15:30:00 America/Los_Angeles".to_string()
value: Value::SingleQuotedString("2008-12-25 15:30:00 America/Los_Angeles".into())
},],
fields: vec![StructField {
field_name: None,
@ -912,7 +926,7 @@ fn parse_typed_struct_syntax_bigquery() {
&Expr::Struct {
values: vec![Expr::TypedString {
data_type: DataType::Time(None, TimezoneInfo::None),
value: "15:30:00".to_string()
value: Value::SingleQuotedString("15:30:00".into())
},],
fields: vec![StructField {
field_name: None,
@ -929,7 +943,7 @@ fn parse_typed_struct_syntax_bigquery() {
&Expr::Struct {
values: vec![Expr::TypedString {
data_type: DataType::Numeric(ExactNumberInfo::None),
value: "1".to_string()
value: Value::SingleQuotedString("1".into())
},],
fields: vec![StructField {
field_name: None,
@ -942,7 +956,7 @@ fn parse_typed_struct_syntax_bigquery() {
&Expr::Struct {
values: vec![Expr::TypedString {
data_type: DataType::BigNumeric(ExactNumberInfo::None),
value: "1".to_string()
value: Value::SingleQuotedString("1".into())
},],
fields: vec![StructField {
field_name: None,
@ -1119,9 +1133,7 @@ fn parse_typed_struct_syntax_bigquery_and_generic() {
assert_eq!(4, select.projection.len());
assert_eq!(
&Expr::Struct {
values: vec![Expr::Value(Value::SingleQuotedString(
"2011-05-05".to_string()
)),],
values: vec![Expr::Value(Value::SingleQuotedString("2011-05-05".into())),],
fields: vec![StructField {
field_name: None,
field_type: DataType::Date
@ -1133,7 +1145,7 @@ fn parse_typed_struct_syntax_bigquery_and_generic() {
&Expr::Struct {
values: vec![Expr::TypedString {
data_type: DataType::Datetime(None),
value: "1999-01-01 01:23:34.45".to_string()
value: Value::SingleQuotedString("1999-01-01 01:23:34.45".into())
},],
fields: vec![StructField {
field_name: None,
@ -1169,7 +1181,7 @@ fn parse_typed_struct_syntax_bigquery_and_generic() {
assert_eq!(
&Expr::Struct {
values: vec![Expr::Interval(Interval {
value: Box::new(Expr::Value(Value::SingleQuotedString("1".to_string()))),
value: Box::new(Expr::Value(Value::SingleQuotedString("1".into()))),
leading_field: Some(DateTimeField::Month),
leading_precision: None,
last_field: None,
@ -1186,7 +1198,9 @@ fn parse_typed_struct_syntax_bigquery_and_generic() {
&Expr::Struct {
values: vec![Expr::TypedString {
data_type: DataType::JSON,
value: r#"{"class" : {"students" : [{"name" : "Jane"}]}}"#.to_string()
value: Value::SingleQuotedString(
r#"{"class" : {"students" : [{"name" : "Jane"}]}}"#.into()
)
},],
fields: vec![StructField {
field_name: None,
@ -1201,7 +1215,7 @@ fn parse_typed_struct_syntax_bigquery_and_generic() {
assert_eq!(3, select.projection.len());
assert_eq!(
&Expr::Struct {
values: vec![Expr::Value(Value::SingleQuotedString("foo".to_string())),],
values: vec![Expr::Value(Value::SingleQuotedString("foo".into())),],
fields: vec![StructField {
field_name: None,
field_type: DataType::String(Some(42))
@ -1213,7 +1227,7 @@ fn parse_typed_struct_syntax_bigquery_and_generic() {
&Expr::Struct {
values: vec![Expr::TypedString {
data_type: DataType::Timestamp(None, TimezoneInfo::None),
value: "2008-12-25 15:30:00 America/Los_Angeles".to_string()
value: Value::SingleQuotedString("2008-12-25 15:30:00 America/Los_Angeles".into())
},],
fields: vec![StructField {
field_name: None,
@ -1227,7 +1241,7 @@ fn parse_typed_struct_syntax_bigquery_and_generic() {
&Expr::Struct {
values: vec![Expr::TypedString {
data_type: DataType::Time(None, TimezoneInfo::None),
value: "15:30:00".to_string()
value: Value::SingleQuotedString("15:30:00".into())
},],
fields: vec![StructField {
field_name: None,
@ -1244,7 +1258,7 @@ fn parse_typed_struct_syntax_bigquery_and_generic() {
&Expr::Struct {
values: vec![Expr::TypedString {
data_type: DataType::Numeric(ExactNumberInfo::None),
value: "1".to_string()
value: Value::SingleQuotedString("1".into())
},],
fields: vec![StructField {
field_name: None,
@ -1257,7 +1271,7 @@ fn parse_typed_struct_syntax_bigquery_and_generic() {
&Expr::Struct {
values: vec![Expr::TypedString {
data_type: DataType::BigNumeric(ExactNumberInfo::None),
value: "1".to_string()
value: Value::SingleQuotedString("1".into())
},],
fields: vec![StructField {
field_name: None,
@ -1285,7 +1299,7 @@ fn parse_typed_struct_with_field_name_bigquery() {
);
assert_eq!(
&Expr::Struct {
values: vec![Expr::Value(Value::DoubleQuotedString("foo".to_string())),],
values: vec![Expr::Value(Value::DoubleQuotedString("foo".into())),],
fields: vec![StructField {
field_name: Some(Ident::from("y")),
field_type: DataType::String(None)
@ -1332,7 +1346,7 @@ fn parse_typed_struct_with_field_name_bigquery_and_generic() {
);
assert_eq!(
&Expr::Struct {
values: vec![Expr::Value(Value::SingleQuotedString("foo".to_string())),],
values: vec![Expr::Value(Value::SingleQuotedString("foo".into())),],
fields: vec![StructField {
field_name: Some(Ident::from("y")),
field_type: DataType::String(None)
@ -2234,6 +2248,20 @@ fn test_select_as_value() {
assert_eq!(Some(ValueTableMode::AsValue), select.value_table_mode);
}
#[test]
fn test_triple_quote_typed_strings() {
bigquery().verified_expr(r#"JSON '''{"foo":"bar's"}'''"#);
let expr = bigquery().verified_expr(r#"JSON """{"foo":"bar's"}""""#);
assert_eq!(
Expr::TypedString {
data_type: DataType::JSON,
value: Value::TripleDoubleQuotedString(r#"{"foo":"bar's"}"#.into())
},
expr
);
}
#[test]
fn test_array_agg() {
bigquery_and_generic().verified_expr("ARRAY_AGG(state)");