@@ -322,6 +322,16 @@ impl fmt::Display for JsonOperator {
322
322
}
323
323
}
324
324
325
+ /// Options for `CAST` / `TRY_CAST`
326
+ /// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements#formatting_syntax>
327
+ #[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
328
+ #[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
329
+ #[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
330
+ pub enum CastFormat {
331
+ Value ( Value ) ,
332
+ ValueAtTimeZone ( Value , Value ) ,
333
+ }
334
+
325
335
/// An SQL expression of any type.
326
336
///
327
337
/// The parser does not distinguish between expressions of different types
@@ -437,19 +447,28 @@ pub enum Expr {
437
447
Cast {
438
448
expr : Box < Expr > ,
439
449
data_type : DataType ,
450
+ // Optional CAST(string_expression AS type FORMAT format_string_expression) as used by BigQuery
451
+ // https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements#formatting_syntax
452
+ format : Option < CastFormat > ,
440
453
} ,
441
454
/// TRY_CAST an expression to a different data type e.g. `TRY_CAST(foo AS VARCHAR(123))`
442
455
// this differs from CAST in the choice of how to implement invalid conversions
443
456
TryCast {
444
457
expr : Box < Expr > ,
445
458
data_type : DataType ,
459
+ // Optional CAST(string_expression AS type FORMAT format_string_expression) as used by BigQuery
460
+ // https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements#formatting_syntax
461
+ format : Option < CastFormat > ,
446
462
} ,
447
463
/// SAFE_CAST an expression to a different data type e.g. `SAFE_CAST(foo AS FLOAT64)`
448
464
// only available for BigQuery: https://cloud.google.com/bigquery/docs/reference/standard-sql/functions-and-operators#safe_casting
449
465
// this works the same as `TRY_CAST`
450
466
SafeCast {
451
467
expr : Box < Expr > ,
452
468
data_type : DataType ,
469
+ // Optional CAST(string_expression AS type FORMAT format_string_expression) as used by BigQuery
470
+ // https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements#formatting_syntax
471
+ format : Option < CastFormat > ,
453
472
} ,
454
473
/// AT a timestamp to a different timezone e.g. `FROM_UNIXTIME(0) AT TIME ZONE 'UTC-06:00'`
455
474
AtTimeZone {
@@ -597,6 +616,15 @@ pub enum Expr {
597
616
} ,
598
617
}
599
618
619
+ impl fmt:: Display for CastFormat {
620
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
621
+ match self {
622
+ CastFormat :: Value ( v) => write ! ( f, "{v}" ) ,
623
+ CastFormat :: ValueAtTimeZone ( v, tz) => write ! ( f, "{v} AT TIME ZONE {tz}" ) ,
624
+ }
625
+ }
626
+ }
627
+
600
628
impl fmt:: Display for Expr {
601
629
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
602
630
match self {
@@ -753,9 +781,39 @@ impl fmt::Display for Expr {
753
781
write ! ( f, "{op}{expr}" )
754
782
}
755
783
}
756
- Expr :: Cast { expr, data_type } => write ! ( f, "CAST({expr} AS {data_type})" ) ,
757
- Expr :: TryCast { expr, data_type } => write ! ( f, "TRY_CAST({expr} AS {data_type})" ) ,
758
- Expr :: SafeCast { expr, data_type } => write ! ( f, "SAFE_CAST({expr} AS {data_type})" ) ,
784
+ Expr :: Cast {
785
+ expr,
786
+ data_type,
787
+ format,
788
+ } => {
789
+ if let Some ( format) = format {
790
+ write ! ( f, "CAST({expr} AS {data_type} FORMAT {format})" )
791
+ } else {
792
+ write ! ( f, "CAST({expr} AS {data_type})" )
793
+ }
794
+ }
795
+ Expr :: TryCast {
796
+ expr,
797
+ data_type,
798
+ format,
799
+ } => {
800
+ if let Some ( format) = format {
801
+ write ! ( f, "TRY_CAST({expr} AS {data_type} FORMAT {format})" )
802
+ } else {
803
+ write ! ( f, "TRY_CAST({expr} AS {data_type})" )
804
+ }
805
+ }
806
+ Expr :: SafeCast {
807
+ expr,
808
+ data_type,
809
+ format,
810
+ } => {
811
+ if let Some ( format) = format {
812
+ write ! ( f, "SAFE_CAST({expr} AS {data_type} FORMAT {format})" )
813
+ } else {
814
+ write ! ( f, "SAFE_CAST({expr} AS {data_type})" )
815
+ }
816
+ }
759
817
Expr :: Extract { field, expr } => write ! ( f, "EXTRACT({field} FROM {expr})" ) ,
760
818
Expr :: Ceil { expr, field } => {
761
819
if field == & DateTimeField :: NoDateTime {
0 commit comments