Skip to content

Commit e9cfb7c

Browse files
support transpilation of GREATEST from BigQuery to DuckDB
1 parent e4d1a4f commit e9cfb7c

File tree

1 file changed

+32
-0
lines changed

1 file changed

+32
-0
lines changed

sqlglot/dialects/duckdb.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,37 @@ def _anyvalue_sql(self: DuckDB.Generator, expression: exp.AnyValue) -> str:
290290
return self.function_fallback_sql(expression)
291291

292292

293+
def _greatest_sql(self: DuckDB.Generator, expression: exp.Greatest) -> str:
294+
"""
295+
Handle GREATEST function to match BigQuery's NULL and NaN behavior.
296+
In BigQuery:
297+
- if any argument is NULL, the result is NULL
298+
In DuckDB:
299+
- NULLs are ignored, returns greatest non-NULL value.
300+
301+
If any argument is NaN (and other arugments are not NULL), DuckDB returns NaN, which matches BigQuery's behavior
302+
"""
303+
all_args = [expression.this] + expression.expressions
304+
305+
greatest_expr = self.func("GREATEST", *all_args)
306+
307+
# Check for NULL: arg1 IS NULL OR arg2 IS NULL OR ...
308+
null_checks = []
309+
for arg in all_args:
310+
null_checks.append(exp.Is(this=arg, expression=exp.Null()))
311+
312+
is_any_null_expr: exp.Expression = null_checks[0]
313+
for null_check in null_checks[1:]:
314+
is_any_null_expr = exp.Or(this=is_any_null_expr, expression=null_check)
315+
316+
# Create CASE expression - only need NULL check, DuckDB handles NaN natively
317+
case_expr = exp.Case(
318+
ifs=[exp.If(this=is_any_null_expr, true=exp.Null())], default=greatest_expr
319+
)
320+
321+
return self.sql(case_expr)
322+
323+
293324
class DuckDB(Dialect):
294325
NULL_ORDERING = "nulls_are_last"
295326
SUPPORTS_USER_DEFINED_TYPES = True
@@ -751,6 +782,7 @@ class Generator(generator.Generator):
751782
exp.EuclideanDistance: rename_func("LIST_DISTANCE"),
752783
exp.GenerateDateArray: _generate_datetime_array_sql,
753784
exp.GenerateTimestampArray: _generate_datetime_array_sql,
785+
exp.Greatest: _greatest_sql,
754786
exp.GroupConcat: lambda self, e: groupconcat_sql(self, e, within_group=False),
755787
exp.Explode: rename_func("UNNEST"),
756788
exp.IntDiv: lambda self, e: self.binary(e, "//"),

0 commit comments

Comments
 (0)