@@ -408,6 +408,26 @@ impl fmt::Display for MapAccessKey {
408408 }
409409}
410410
411+ /// The syntax used for in a cast expression.
412+ #[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
413+ #[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
414+ #[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
415+ pub enum CastKind {
416+ /// The standard SQL cast syntax, e.g. `CAST(<expr> as <datatype>)`
417+ Cast ,
418+ /// A cast that returns `NULL` on failure, e.g. `TRY_CAST(<expr> as <datatype>)`.
419+ ///
420+ /// See <https://docs.snowflake.com/en/sql-reference/functions/try_cast>.
421+ /// See <https://learn.microsoft.com/en-us/sql/t-sql/functions/try-cast-transact-sql>.
422+ TryCast ,
423+ /// A cast that returns `NULL` on failure, bigQuery-specific , e.g. `SAFE_CAST(<expr> as <datatype>)`.
424+ ///
425+ /// See <https://cloud.google.com/bigquery/docs/reference/standard-sql/functions-and-operators#safe_casting>.
426+ SafeCast ,
427+ /// `<expr> :: <datatype>`
428+ DoubleColon ,
429+ }
430+
411431/// An SQL expression of any type.
412432///
413433/// The parser does not distinguish between expressions of different types
@@ -546,25 +566,7 @@ pub enum Expr {
546566 } ,
547567 /// `CAST` an expression to a different data type e.g. `CAST(foo AS VARCHAR(123))`
548568 Cast {
549- expr : Box < Expr > ,
550- data_type : DataType ,
551- // Optional CAST(string_expression AS type FORMAT format_string_expression) as used by BigQuery
552- // https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements#formatting_syntax
553- format : Option < CastFormat > ,
554- } ,
555- /// `TRY_CAST` an expression to a different data type e.g. `TRY_CAST(foo AS VARCHAR(123))`
556- // this differs from CAST in the choice of how to implement invalid conversions
557- TryCast {
558- expr : Box < Expr > ,
559- data_type : DataType ,
560- // Optional CAST(string_expression AS type FORMAT format_string_expression) as used by BigQuery
561- // https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements#formatting_syntax
562- format : Option < CastFormat > ,
563- } ,
564- /// `SAFE_CAST` an expression to a different data type e.g. `SAFE_CAST(foo AS FLOAT64)`
565- // only available for BigQuery: https://cloud.google.com/bigquery/docs/reference/standard-sql/functions-and-operators#safe_casting
566- // this works the same as `TRY_CAST`
567- SafeCast {
569+ kind : CastKind ,
568570 expr : Box < Expr > ,
569571 data_type : DataType ,
570572 // Optional CAST(string_expression AS type FORMAT format_string_expression) as used by BigQuery
@@ -989,38 +991,36 @@ impl fmt::Display for Expr {
989991 write ! ( f, ")" )
990992 }
991993 Expr :: Cast {
994+ kind,
992995 expr,
993996 data_type,
994997 format,
995- } => {
996- if let Some ( format) = format {
997- write ! ( f, "CAST({expr} AS {data_type} FORMAT {format})" )
998- } else {
999- write ! ( f, "CAST({expr} AS {data_type})" )
998+ } => match kind {
999+ CastKind :: Cast => {
1000+ if let Some ( format) = format {
1001+ write ! ( f, "CAST({expr} AS {data_type} FORMAT {format})" )
1002+ } else {
1003+ write ! ( f, "CAST({expr} AS {data_type})" )
1004+ }
10001005 }
1001- }
1002- Expr :: TryCast {
1003- expr,
1004- data_type,
1005- format,
1006- } => {
1007- if let Some ( format) = format {
1008- write ! ( f, "TRY_CAST({expr} AS {data_type} FORMAT {format})" )
1009- } else {
1010- write ! ( f, "TRY_CAST({expr} AS {data_type})" )
1006+ CastKind :: TryCast => {
1007+ if let Some ( format) = format {
1008+ write ! ( f, "TRY_CAST({expr} AS {data_type} FORMAT {format})" )
1009+ } else {
1010+ write ! ( f, "TRY_CAST({expr} AS {data_type})" )
1011+ }
10111012 }
1012- }
1013- Expr :: SafeCast {
1014- expr,
1015- data_type,
1016- format,
1017- } => {
1018- if let Some ( format) = format {
1019- write ! ( f, "SAFE_CAST({expr} AS {data_type} FORMAT {format})" )
1020- } else {
1021- write ! ( f, "SAFE_CAST({expr} AS {data_type})" )
1013+ CastKind :: SafeCast => {
1014+ if let Some ( format) = format {
1015+ write ! ( f, "SAFE_CAST({expr} AS {data_type} FORMAT {format})" )
1016+ } else {
1017+ write ! ( f, "SAFE_CAST({expr} AS {data_type})" )
1018+ }
10221019 }
1023- }
1020+ CastKind :: DoubleColon => {
1021+ write ! ( f, "{expr}::{data_type}" )
1022+ }
1023+ } ,
10241024 Expr :: Extract { field, expr } => write ! ( f, "EXTRACT({field} FROM {expr})" ) ,
10251025 Expr :: Ceil { expr, field } => {
10261026 if field == & DateTimeField :: NoDateTime {
0 commit comments