diff --git a/datafusion/sql/src/unparser/dialect.rs b/datafusion/sql/src/unparser/dialect.rs index 9e0683bdd7b2..0f4f086127d8 100644 --- a/datafusion/sql/src/unparser/dialect.rs +++ b/datafusion/sql/src/unparser/dialect.rs @@ -645,6 +645,55 @@ impl Dialect for BigQueryDialect { fn unnest_as_table_factor(&self) -> bool { true } + + fn supports_column_alias_in_table_alias(&self) -> bool { + false + } + + fn float64_ast_dtype(&self) -> ast::DataType { + ast::DataType::Float64 + } + + fn utf8_cast_dtype(&self) -> ast::DataType { + ast::DataType::String(None) + } + + fn large_utf8_cast_dtype(&self) -> ast::DataType { + ast::DataType::String(None) + } + + fn int64_cast_dtype(&self) -> ast::DataType { + ast::DataType::Int64 + } + + fn timestamp_cast_dtype( + &self, + _time_unit: &TimeUnit, + _tz: &Option>, + ) -> ast::DataType { + ast::DataType::Timestamp(None, TimezoneInfo::None) + } + + fn date_field_extract_style(&self) -> DateFieldExtractStyle { + DateFieldExtractStyle::Extract + } + + fn interval_style(&self) -> IntervalStyle { + IntervalStyle::SQLStandard + } + + fn scalar_function_to_sql_overrides( + &self, + unparser: &Unparser, + func_name: &str, + args: &[Expr], + ) -> Result> { + if func_name == "date_part" { + return date_part_to_sql(unparser, self.date_field_extract_style(), args); + } + + Ok(None) + } } impl BigQueryDialect { diff --git a/datafusion/sql/src/unparser/expr.rs b/datafusion/sql/src/unparser/expr.rs index 3601febe744c..d199600147e7 100644 --- a/datafusion/sql/src/unparser/expr.rs +++ b/datafusion/sql/src/unparser/expr.rs @@ -3468,4 +3468,58 @@ mod tests { } Ok(()) } + + #[test] + fn test_bigquery_dialect_overrides() -> Result<()> { + let bigquery_dialect: Arc = Arc::new(BigQueryDialect::new()); + let unparser = Unparser::new(bigquery_dialect.as_ref()); + + // date_field_extract_style: EXTRACT instead of date_part + let expr = Expr::ScalarFunction(ScalarFunction { + func: Arc::new(ScalarUDF::new_from_impl( + datafusion_functions::datetime::date_part::DatePartFunc::new(), + )), + args: vec![lit("YEAR"), col("date_col")], + }); + let actual = format!("{}", unparser.expr_to_sql(&expr)?); + assert_eq!(actual, "EXTRACT(YEAR FROM `date_col`)"); + + // interval_style: SQL standard instead of PostgresVerbose + let expr = interval_year_month_lit("3 months"); + let actual = format!("{}", unparser.expr_to_sql(&expr)?); + assert_eq!(actual, "INTERVAL '3' MONTH"); + + // float64_ast_dtype: FLOAT64 instead of DOUBLE + let expr = cast(col("a"), DataType::Float64); + let actual = format!("{}", unparser.expr_to_sql(&expr)?); + assert_eq!(actual, "CAST(`a` AS FLOAT64)"); + + // supports_column_alias_in_table_alias: false + assert!(!bigquery_dialect.supports_column_alias_in_table_alias()); + + // utf8_cast_dtype: STRING instead of VARCHAR + let expr = cast(col("a"), DataType::Utf8); + let actual = format!("{}", unparser.expr_to_sql(&expr)?); + assert_eq!(actual, "CAST(`a` AS STRING)"); + + // large_utf8_cast_dtype: STRING instead of TEXT + let expr = cast(col("a"), DataType::LargeUtf8); + let actual = format!("{}", unparser.expr_to_sql(&expr)?); + assert_eq!(actual, "CAST(`a` AS STRING)"); + + // int64_cast_dtype: INT64 instead of BIGINT + let expr = cast(col("a"), DataType::Int64); + let actual = format!("{}", unparser.expr_to_sql(&expr)?); + assert_eq!(actual, "CAST(`a` AS INT64)"); + + // timestamp_cast_dtype: TIMESTAMP (no WITH TIME ZONE) + let expr = cast( + col("a"), + DataType::Timestamp(TimeUnit::Microsecond, Some("+00:00".into())), + ); + let actual = format!("{}", unparser.expr_to_sql(&expr)?); + assert_eq!(actual, "CAST(`a` AS TIMESTAMP)"); + + Ok(()) + } }