@@ -405,6 +405,37 @@ def _initcap_sql(self: DuckDB.Generator, expression: exp.Initcap) -> str:
405405 return _build_capitalization_sql (self , this_sql , escaped_delimiters_sql )
406406
407407
408+ def _greatest_sql (self : DuckDB .Generator , expression : exp .Greatest ) -> str :
409+ """
410+ Handle GREATEST function with dialect-aware NULL behavior.
411+
412+ - If null_if_any_null=True (BigQuery-style): return NULL if any argument is NULL
413+ - If null_if_any_null=False (DuckDB/PostgreSQL-style): ignore NULLs, return greatest non-NULL value
414+ """
415+ all_args = [expression .this ] + expression .expressions
416+ greatest_expr = self .func ("GREATEST" , * all_args )
417+
418+ # Check if this GREATEST should return NULL if any arg is NULL (BigQuery behavior)
419+ if getattr (expression , 'null_if_any_null' , False ):
420+ # BigQuery behavior: NULL if any argument is NULL
421+ null_checks = []
422+ for arg in all_args :
423+ null_checks .append (exp .Is (this = arg , expression = exp .Null ()))
424+
425+ is_any_null_expr : exp .Expression = null_checks [0 ]
426+ for null_check in null_checks [1 :]:
427+ is_any_null_expr = exp .Or (this = is_any_null_expr , expression = null_check )
428+
429+ # Create CASE expression
430+ case_expr = exp .Case (
431+ ifs = [exp .If (this = is_any_null_expr , true = exp .Null ())], default = greatest_expr
432+ )
433+ return self .sql (case_expr )
434+ else :
435+ # DuckDB/PostgreSQL behavior: use native GREATEST (ignores NULLs)
436+ return self .sql (greatest_expr )
437+
438+
408439class DuckDB (Dialect ):
409440 NULL_ORDERING = "nulls_are_last"
410441 SUPPORTS_USER_DEFINED_TYPES = True
@@ -866,6 +897,7 @@ class Generator(generator.Generator):
866897 exp .EuclideanDistance : rename_func ("LIST_DISTANCE" ),
867898 exp .GenerateDateArray : _generate_datetime_array_sql ,
868899 exp .GenerateTimestampArray : _generate_datetime_array_sql ,
900+ exp .Greatest : _greatest_sql ,
869901 exp .GroupConcat : lambda self , e : groupconcat_sql (self , e , within_group = False ),
870902 exp .Explode : rename_func ("UNNEST" ),
871903 exp .IntDiv : lambda self , e : self .binary (e , "//" ),
0 commit comments