Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions datafusion/sql/src/unparser/dialect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -657,6 +657,55 @@ impl Dialect for BigQueryDialect {
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<Arc<str>>,
) -> 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<Option<ast::Expr>> {
if func_name == "date_part" {
return date_part_to_sql(unparser, self.date_field_extract_style(), args);
}

Ok(None)
}

fn timestamp_with_tz_to_string(&self, dt: DateTime<Tz>, unit: TimeUnit) -> String {
// https://docs.cloud.google.com/bigquery/docs/reference/standard-sql/data-types#timestamp_type
let format = match unit {
Expand Down
54 changes: 54 additions & 0 deletions datafusion/sql/src/unparser/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3469,4 +3469,58 @@ mod tests {
}
Ok(())
}

#[test]
fn test_bigquery_dialect_overrides() -> Result<()> {
let bigquery_dialect: Arc<dyn Dialect> = 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(())
}
}
Loading