Add span for Expr::TypedString (#1919)

This commit is contained in:
feral-dot-io 2025-07-03 16:24:51 +00:00 committed by GitHub
parent be2d2f14e7
commit 9020385c02
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 155 additions and 47 deletions

View file

@ -996,7 +996,7 @@ pub enum Expr {
data_type: DataType, data_type: DataType,
/// The value of the constant. /// The value of the constant.
/// Hint: you can unwrap the string value using `value.into_string()`. /// Hint: you can unwrap the string value using `value.into_string()`.
value: Value, value: ValueWithSpan,
}, },
/// Scalar function call e.g. `LEFT(foo, 5)` /// Scalar function call e.g. `LEFT(foo, 5)`
Function(Function), Function(Function),

View file

@ -1415,7 +1415,6 @@ impl Spanned for AssignmentTarget {
/// f.e. `IS NULL <expr>` reports as `<expr>::span`. /// f.e. `IS NULL <expr>` reports as `<expr>::span`.
/// ///
/// Missing spans: /// Missing spans:
/// - [Expr::TypedString] # missing span for data_type
/// - [Expr::MatchAgainst] # MySQL specific /// - [Expr::MatchAgainst] # MySQL specific
/// - [Expr::RLike] # MySQL specific /// - [Expr::RLike] # MySQL specific
/// - [Expr::Struct] # BigQuery specific /// - [Expr::Struct] # BigQuery specific

View file

@ -1521,7 +1521,7 @@ impl<'a> Parser<'a> {
DataType::Custom(..) => parser_err!("dummy", loc), DataType::Custom(..) => parser_err!("dummy", loc),
data_type => Ok(Expr::TypedString { data_type => Ok(Expr::TypedString {
data_type, data_type,
value: parser.parse_value()?.value, value: parser.parse_value()?,
}), }),
} }
})?; })?;
@ -1708,10 +1708,9 @@ impl<'a> Parser<'a> {
} }
fn parse_geometric_type(&mut self, kind: GeometricTypeKind) -> Result<Expr, ParserError> { fn parse_geometric_type(&mut self, kind: GeometricTypeKind) -> Result<Expr, ParserError> {
let value: Value = self.parse_value()?.value;
Ok(Expr::TypedString { Ok(Expr::TypedString {
data_type: DataType::GeometricType(kind), data_type: DataType::GeometricType(kind),
value, value: self.parse_value()?,
}) })
} }

View file

@ -906,7 +906,10 @@ fn parse_typed_struct_syntax_bigquery() {
&Expr::Struct { &Expr::Struct {
values: vec![Expr::TypedString { values: vec![Expr::TypedString {
data_type: DataType::Datetime(None), data_type: DataType::Datetime(None),
value: Value::SingleQuotedString("1999-01-01 01:23:34.45".into()) value: ValueWithSpan {
value: Value::SingleQuotedString("1999-01-01 01:23:34.45".into()),
span: Span::empty(),
},
}], }],
fields: vec![StructField { fields: vec![StructField {
field_name: None, field_name: None,
@ -965,9 +968,12 @@ fn parse_typed_struct_syntax_bigquery() {
&Expr::Struct { &Expr::Struct {
values: vec![Expr::TypedString { values: vec![Expr::TypedString {
data_type: DataType::JSON, data_type: DataType::JSON,
value: Value::SingleQuotedString( value: ValueWithSpan {
r#"{"class" : {"students" : [{"name" : "Jane"}]}}"#.into() value: Value::SingleQuotedString(
) r#"{"class" : {"students" : [{"name" : "Jane"}]}}"#.into()
),
span: Span::empty(),
}
}], }],
fields: vec![StructField { fields: vec![StructField {
field_name: None, field_name: None,
@ -998,7 +1004,12 @@ fn parse_typed_struct_syntax_bigquery() {
&Expr::Struct { &Expr::Struct {
values: vec![Expr::TypedString { values: vec![Expr::TypedString {
data_type: DataType::Timestamp(None, TimezoneInfo::None), data_type: DataType::Timestamp(None, TimezoneInfo::None),
value: Value::SingleQuotedString("2008-12-25 15:30:00 America/Los_Angeles".into()) value: ValueWithSpan {
value: Value::SingleQuotedString(
"2008-12-25 15:30:00 America/Los_Angeles".into()
),
span: Span::empty(),
},
}], }],
fields: vec![StructField { fields: vec![StructField {
field_name: None, field_name: None,
@ -1013,7 +1024,10 @@ fn parse_typed_struct_syntax_bigquery() {
&Expr::Struct { &Expr::Struct {
values: vec![Expr::TypedString { values: vec![Expr::TypedString {
data_type: DataType::Time(None, TimezoneInfo::None), data_type: DataType::Time(None, TimezoneInfo::None),
value: Value::SingleQuotedString("15:30:00".into()) value: ValueWithSpan {
value: Value::SingleQuotedString("15:30:00".into()),
span: Span::empty(),
}
}], }],
fields: vec![StructField { fields: vec![StructField {
field_name: None, field_name: None,
@ -1031,7 +1045,10 @@ fn parse_typed_struct_syntax_bigquery() {
&Expr::Struct { &Expr::Struct {
values: vec![Expr::TypedString { values: vec![Expr::TypedString {
data_type: DataType::Numeric(ExactNumberInfo::None), data_type: DataType::Numeric(ExactNumberInfo::None),
value: Value::SingleQuotedString("1".into()) value: ValueWithSpan {
value: Value::SingleQuotedString("1".into()),
span: Span::empty(),
}
}], }],
fields: vec![StructField { fields: vec![StructField {
field_name: None, field_name: None,
@ -1045,7 +1062,10 @@ fn parse_typed_struct_syntax_bigquery() {
&Expr::Struct { &Expr::Struct {
values: vec![Expr::TypedString { values: vec![Expr::TypedString {
data_type: DataType::BigNumeric(ExactNumberInfo::None), data_type: DataType::BigNumeric(ExactNumberInfo::None),
value: Value::SingleQuotedString("1".into()) value: ValueWithSpan {
value: Value::SingleQuotedString("1".into()),
span: Span::empty(),
}
}], }],
fields: vec![StructField { fields: vec![StructField {
field_name: None, field_name: None,
@ -1219,7 +1239,10 @@ fn parse_typed_struct_syntax_bigquery_and_generic() {
&Expr::Struct { &Expr::Struct {
values: vec![Expr::TypedString { values: vec![Expr::TypedString {
data_type: DataType::Datetime(None), data_type: DataType::Datetime(None),
value: Value::SingleQuotedString("1999-01-01 01:23:34.45".into()) value: ValueWithSpan {
value: Value::SingleQuotedString("1999-01-01 01:23:34.45".into()),
span: Span::empty(),
}
}], }],
fields: vec![StructField { fields: vec![StructField {
field_name: None, field_name: None,
@ -1278,9 +1301,12 @@ fn parse_typed_struct_syntax_bigquery_and_generic() {
&Expr::Struct { &Expr::Struct {
values: vec![Expr::TypedString { values: vec![Expr::TypedString {
data_type: DataType::JSON, data_type: DataType::JSON,
value: Value::SingleQuotedString( value: ValueWithSpan {
r#"{"class" : {"students" : [{"name" : "Jane"}]}}"#.into() value: Value::SingleQuotedString(
) r#"{"class" : {"students" : [{"name" : "Jane"}]}}"#.into()
),
span: Span::empty(),
}
}], }],
fields: vec![StructField { fields: vec![StructField {
field_name: None, field_name: None,
@ -1311,7 +1337,12 @@ fn parse_typed_struct_syntax_bigquery_and_generic() {
&Expr::Struct { &Expr::Struct {
values: vec![Expr::TypedString { values: vec![Expr::TypedString {
data_type: DataType::Timestamp(None, TimezoneInfo::None), data_type: DataType::Timestamp(None, TimezoneInfo::None),
value: Value::SingleQuotedString("2008-12-25 15:30:00 America/Los_Angeles".into()) value: ValueWithSpan {
value: Value::SingleQuotedString(
"2008-12-25 15:30:00 America/Los_Angeles".into()
),
span: Span::empty(),
}
}], }],
fields: vec![StructField { fields: vec![StructField {
field_name: None, field_name: None,
@ -1326,7 +1357,10 @@ fn parse_typed_struct_syntax_bigquery_and_generic() {
&Expr::Struct { &Expr::Struct {
values: vec![Expr::TypedString { values: vec![Expr::TypedString {
data_type: DataType::Time(None, TimezoneInfo::None), data_type: DataType::Time(None, TimezoneInfo::None),
value: Value::SingleQuotedString("15:30:00".into()) value: ValueWithSpan {
value: Value::SingleQuotedString("15:30:00".into()),
span: Span::empty(),
}
}], }],
fields: vec![StructField { fields: vec![StructField {
field_name: None, field_name: None,
@ -1344,7 +1378,10 @@ fn parse_typed_struct_syntax_bigquery_and_generic() {
&Expr::Struct { &Expr::Struct {
values: vec![Expr::TypedString { values: vec![Expr::TypedString {
data_type: DataType::Numeric(ExactNumberInfo::None), data_type: DataType::Numeric(ExactNumberInfo::None),
value: Value::SingleQuotedString("1".into()) value: ValueWithSpan {
value: Value::SingleQuotedString("1".into()),
span: Span::empty(),
}
}], }],
fields: vec![StructField { fields: vec![StructField {
field_name: None, field_name: None,
@ -1358,7 +1395,10 @@ fn parse_typed_struct_syntax_bigquery_and_generic() {
&Expr::Struct { &Expr::Struct {
values: vec![Expr::TypedString { values: vec![Expr::TypedString {
data_type: DataType::BigNumeric(ExactNumberInfo::None), data_type: DataType::BigNumeric(ExactNumberInfo::None),
value: Value::SingleQuotedString("1".into()) value: ValueWithSpan {
value: Value::SingleQuotedString("1".into()),
span: Span::empty(),
}
}], }],
fields: vec![StructField { fields: vec![StructField {
field_name: None, field_name: None,
@ -2393,7 +2433,10 @@ fn test_triple_quote_typed_strings() {
assert_eq!( assert_eq!(
Expr::TypedString { Expr::TypedString {
data_type: DataType::JSON, data_type: DataType::JSON,
value: Value::TripleDoubleQuotedString(r#"{"foo":"bar's"}"#.into()) value: ValueWithSpan {
value: Value::TripleDoubleQuotedString(r#"{"foo":"bar's"}"#.into()),
span: Span::empty(),
}
}, },
expr expr
); );

View file

@ -5851,7 +5851,10 @@ fn parse_literal_date() {
assert_eq!( assert_eq!(
&Expr::TypedString { &Expr::TypedString {
data_type: DataType::Date, data_type: DataType::Date,
value: Value::SingleQuotedString("1999-01-01".into()), value: ValueWithSpan {
value: Value::SingleQuotedString("1999-01-01".into()),
span: Span::empty(),
}
}, },
expr_from_projection(only(&select.projection)), expr_from_projection(only(&select.projection)),
); );
@ -5864,7 +5867,10 @@ fn parse_literal_time() {
assert_eq!( assert_eq!(
&Expr::TypedString { &Expr::TypedString {
data_type: DataType::Time(None, TimezoneInfo::None), data_type: DataType::Time(None, TimezoneInfo::None),
value: Value::SingleQuotedString("01:23:34".into()), value: ValueWithSpan {
value: Value::SingleQuotedString("01:23:34".into()),
span: Span::empty(),
},
}, },
expr_from_projection(only(&select.projection)), expr_from_projection(only(&select.projection)),
); );
@ -5877,7 +5883,10 @@ fn parse_literal_datetime() {
assert_eq!( assert_eq!(
&Expr::TypedString { &Expr::TypedString {
data_type: DataType::Datetime(None), data_type: DataType::Datetime(None),
value: Value::SingleQuotedString("1999-01-01 01:23:34.45".into()), value: ValueWithSpan {
value: Value::SingleQuotedString("1999-01-01 01:23:34.45".into()),
span: Span::empty(),
},
}, },
expr_from_projection(only(&select.projection)), expr_from_projection(only(&select.projection)),
); );
@ -5890,7 +5899,10 @@ fn parse_literal_timestamp_without_time_zone() {
assert_eq!( assert_eq!(
&Expr::TypedString { &Expr::TypedString {
data_type: DataType::Timestamp(None, TimezoneInfo::None), data_type: DataType::Timestamp(None, TimezoneInfo::None),
value: Value::SingleQuotedString("1999-01-01 01:23:34".into()), value: ValueWithSpan {
value: Value::SingleQuotedString("1999-01-01 01:23:34".into()),
span: Span::empty(),
},
}, },
expr_from_projection(only(&select.projection)), expr_from_projection(only(&select.projection)),
); );
@ -5905,7 +5917,10 @@ fn parse_literal_timestamp_with_time_zone() {
assert_eq!( assert_eq!(
&Expr::TypedString { &Expr::TypedString {
data_type: DataType::Timestamp(None, TimezoneInfo::Tz), data_type: DataType::Timestamp(None, TimezoneInfo::Tz),
value: Value::SingleQuotedString("1999-01-01 01:23:34Z".into()), value: ValueWithSpan {
value: Value::SingleQuotedString("1999-01-01 01:23:34Z".into()),
span: Span::empty(),
},
}, },
expr_from_projection(only(&select.projection)), expr_from_projection(only(&select.projection)),
); );
@ -6477,8 +6492,9 @@ fn parse_json_keyword() {
assert_eq!( assert_eq!(
&Expr::TypedString { &Expr::TypedString {
data_type: DataType::JSON, data_type: DataType::JSON,
value: Value::SingleQuotedString( value: ValueWithSpan {
r#"{ value: Value::SingleQuotedString(
r#"{
"id": 10, "id": 10,
"type": "fruit", "type": "fruit",
"name": "apple", "name": "apple",
@ -6498,8 +6514,10 @@ fn parse_json_keyword() {
] ]
} }
}"# }"#
.to_string() .to_string()
) ),
span: Span::empty(),
}
}, },
expr_from_projection(only(&select.projection)), expr_from_projection(only(&select.projection)),
); );
@ -6511,7 +6529,10 @@ fn parse_typed_strings() {
assert_eq!( assert_eq!(
Expr::TypedString { Expr::TypedString {
data_type: DataType::JSON, data_type: DataType::JSON,
value: Value::SingleQuotedString(r#"{"foo":"bar"}"#.into()) value: ValueWithSpan {
value: Value::SingleQuotedString(r#"{"foo":"bar"}"#.into()),
span: Span::empty(),
}
}, },
expr expr
); );
@ -6529,7 +6550,10 @@ fn parse_bignumeric_keyword() {
assert_eq!( assert_eq!(
&Expr::TypedString { &Expr::TypedString {
data_type: DataType::BigNumeric(ExactNumberInfo::None), data_type: DataType::BigNumeric(ExactNumberInfo::None),
value: Value::SingleQuotedString(r#"0"#.into()) value: ValueWithSpan {
value: Value::SingleQuotedString(r#"0"#.into()),
span: Span::empty(),
}
}, },
expr_from_projection(only(&select.projection)), expr_from_projection(only(&select.projection)),
); );
@ -6540,7 +6564,10 @@ fn parse_bignumeric_keyword() {
assert_eq!( assert_eq!(
&Expr::TypedString { &Expr::TypedString {
data_type: DataType::BigNumeric(ExactNumberInfo::None), data_type: DataType::BigNumeric(ExactNumberInfo::None),
value: Value::SingleQuotedString(r#"123456"#.into()) value: ValueWithSpan {
value: Value::SingleQuotedString(r#"123456"#.into()),
span: Span::empty(),
}
}, },
expr_from_projection(only(&select.projection)), expr_from_projection(only(&select.projection)),
); );
@ -6551,7 +6578,10 @@ fn parse_bignumeric_keyword() {
assert_eq!( assert_eq!(
&Expr::TypedString { &Expr::TypedString {
data_type: DataType::BigNumeric(ExactNumberInfo::None), data_type: DataType::BigNumeric(ExactNumberInfo::None),
value: Value::SingleQuotedString(r#"-3.14"#.into()) value: ValueWithSpan {
value: Value::SingleQuotedString(r#"-3.14"#.into()),
span: Span::empty(),
}
}, },
expr_from_projection(only(&select.projection)), expr_from_projection(only(&select.projection)),
); );
@ -6562,7 +6592,10 @@ fn parse_bignumeric_keyword() {
assert_eq!( assert_eq!(
&Expr::TypedString { &Expr::TypedString {
data_type: DataType::BigNumeric(ExactNumberInfo::None), data_type: DataType::BigNumeric(ExactNumberInfo::None),
value: Value::SingleQuotedString(r#"-0.54321"#.into()) value: ValueWithSpan {
value: Value::SingleQuotedString(r#"-0.54321"#.into()),
span: Span::empty(),
}
}, },
expr_from_projection(only(&select.projection)), expr_from_projection(only(&select.projection)),
); );
@ -6573,7 +6606,10 @@ fn parse_bignumeric_keyword() {
assert_eq!( assert_eq!(
&Expr::TypedString { &Expr::TypedString {
data_type: DataType::BigNumeric(ExactNumberInfo::None), data_type: DataType::BigNumeric(ExactNumberInfo::None),
value: Value::SingleQuotedString(r#"1.23456e05"#.into()) value: ValueWithSpan {
value: Value::SingleQuotedString(r#"1.23456e05"#.into()),
span: Span::empty(),
}
}, },
expr_from_projection(only(&select.projection)), expr_from_projection(only(&select.projection)),
); );
@ -6584,7 +6620,10 @@ fn parse_bignumeric_keyword() {
assert_eq!( assert_eq!(
&Expr::TypedString { &Expr::TypedString {
data_type: DataType::BigNumeric(ExactNumberInfo::None), data_type: DataType::BigNumeric(ExactNumberInfo::None),
value: Value::SingleQuotedString(r#"-9.876e-3"#.into()) value: ValueWithSpan {
value: Value::SingleQuotedString(r#"-9.876e-3"#.into()),
span: Span::empty(),
}
}, },
expr_from_projection(only(&select.projection)), expr_from_projection(only(&select.projection)),
); );
@ -14833,7 +14872,10 @@ fn test_geometry_type() {
all_dialects_where(|d| d.supports_geometric_types()).verified_expr(sql), all_dialects_where(|d| d.supports_geometric_types()).verified_expr(sql),
Expr::TypedString { Expr::TypedString {
data_type: DataType::GeometricType(GeometricTypeKind::Point), data_type: DataType::GeometricType(GeometricTypeKind::Point),
value: Value::SingleQuotedString("1,2".to_string()), value: ValueWithSpan {
value: Value::SingleQuotedString("1,2".to_string()),
span: Span::empty(),
},
} }
); );
@ -14842,7 +14884,10 @@ fn test_geometry_type() {
all_dialects_where(|d| d.supports_geometric_types()).verified_expr(sql), all_dialects_where(|d| d.supports_geometric_types()).verified_expr(sql),
Expr::TypedString { Expr::TypedString {
data_type: DataType::GeometricType(GeometricTypeKind::Line), data_type: DataType::GeometricType(GeometricTypeKind::Line),
value: Value::SingleQuotedString("1,2,3,4".to_string()), value: ValueWithSpan {
value: Value::SingleQuotedString("1,2,3,4".to_string()),
span: Span::empty(),
},
} }
); );
@ -14851,7 +14896,10 @@ fn test_geometry_type() {
all_dialects_where(|d| d.supports_geometric_types()).verified_expr(sql), all_dialects_where(|d| d.supports_geometric_types()).verified_expr(sql),
Expr::TypedString { Expr::TypedString {
data_type: DataType::GeometricType(GeometricTypeKind::GeometricPath), data_type: DataType::GeometricType(GeometricTypeKind::GeometricPath),
value: Value::SingleQuotedString("1,2,3,4".to_string()), value: ValueWithSpan {
value: Value::SingleQuotedString("1,2,3,4".to_string()),
span: Span::empty(),
},
} }
); );
let sql = "box '1,2,3,4'"; let sql = "box '1,2,3,4'";
@ -14859,7 +14907,10 @@ fn test_geometry_type() {
all_dialects_where(|d| d.supports_geometric_types()).verified_expr(sql), all_dialects_where(|d| d.supports_geometric_types()).verified_expr(sql),
Expr::TypedString { Expr::TypedString {
data_type: DataType::GeometricType(GeometricTypeKind::GeometricBox), data_type: DataType::GeometricType(GeometricTypeKind::GeometricBox),
value: Value::SingleQuotedString("1,2,3,4".to_string()), value: ValueWithSpan {
value: Value::SingleQuotedString("1,2,3,4".to_string()),
span: Span::empty(),
},
} }
); );
@ -14868,7 +14919,10 @@ fn test_geometry_type() {
all_dialects_where(|d| d.supports_geometric_types()).verified_expr(sql), all_dialects_where(|d| d.supports_geometric_types()).verified_expr(sql),
Expr::TypedString { Expr::TypedString {
data_type: DataType::GeometricType(GeometricTypeKind::Circle), data_type: DataType::GeometricType(GeometricTypeKind::Circle),
value: Value::SingleQuotedString("1,2,3".to_string()), value: ValueWithSpan {
value: Value::SingleQuotedString("1,2,3".to_string()),
span: Span::empty(),
},
} }
); );
@ -14877,7 +14931,10 @@ fn test_geometry_type() {
all_dialects_where(|d| d.supports_geometric_types()).verified_expr(sql), all_dialects_where(|d| d.supports_geometric_types()).verified_expr(sql),
Expr::TypedString { Expr::TypedString {
data_type: DataType::GeometricType(GeometricTypeKind::Polygon), data_type: DataType::GeometricType(GeometricTypeKind::Polygon),
value: Value::SingleQuotedString("1,2,3,4".to_string()), value: ValueWithSpan {
value: Value::SingleQuotedString("1,2,3,4".to_string()),
span: Span::empty(),
},
} }
); );
let sql = "lseg '1,2,3,4'"; let sql = "lseg '1,2,3,4'";
@ -14885,7 +14942,10 @@ fn test_geometry_type() {
all_dialects_where(|d| d.supports_geometric_types()).verified_expr(sql), all_dialects_where(|d| d.supports_geometric_types()).verified_expr(sql),
Expr::TypedString { Expr::TypedString {
data_type: DataType::GeometricType(GeometricTypeKind::LineSegment), data_type: DataType::GeometricType(GeometricTypeKind::LineSegment),
value: Value::SingleQuotedString("1,2,3,4".to_string()), value: ValueWithSpan {
value: Value::SingleQuotedString("1,2,3,4".to_string()),
span: Span::empty(),
},
} }
); );
} }

View file

@ -19,6 +19,7 @@ use sqlparser::ast::helpers::attached_token::AttachedToken;
use sqlparser::ast::*; use sqlparser::ast::*;
use sqlparser::dialect::{DatabricksDialect, GenericDialect}; use sqlparser::dialect::{DatabricksDialect, GenericDialect};
use sqlparser::parser::ParserError; use sqlparser::parser::ParserError;
use sqlparser::tokenizer::Span;
use test_utils::*; use test_utils::*;
#[macro_use] #[macro_use]
@ -328,7 +329,10 @@ fn data_type_timestamp_ntz() {
databricks().verified_expr("TIMESTAMP_NTZ '2025-03-29T18:52:00'"), databricks().verified_expr("TIMESTAMP_NTZ '2025-03-29T18:52:00'"),
Expr::TypedString { Expr::TypedString {
data_type: DataType::TimestampNtz, data_type: DataType::TimestampNtz,
value: Value::SingleQuotedString("2025-03-29T18:52:00".to_owned()) value: ValueWithSpan {
value: Value::SingleQuotedString("2025-03-29T18:52:00".to_owned()),
span: Span::empty(),
}
} }
); );

View file

@ -5257,7 +5257,10 @@ fn parse_at_time_zone() {
left: Box::new(Expr::AtTimeZone { left: Box::new(Expr::AtTimeZone {
timestamp: Box::new(Expr::TypedString { timestamp: Box::new(Expr::TypedString {
data_type: DataType::Timestamp(None, TimezoneInfo::None), data_type: DataType::Timestamp(None, TimezoneInfo::None),
value: Value::SingleQuotedString("2001-09-28 01:00".to_string()), value: ValueWithSpan {
value: Value::SingleQuotedString("2001-09-28 01:00".to_string()),
span: Span::empty(),
},
}), }),
time_zone: Box::new(Expr::Cast { time_zone: Box::new(Expr::Cast {
kind: CastKind::DoubleColon, kind: CastKind::DoubleColon,