From b00ac3d9af68d65ad50131957241efe18734d269 Mon Sep 17 00:00:00 2001 From: Shuowei Li Date: Tue, 16 Jun 2026 19:23:30 +0000 Subject: [PATCH 1/2] fix: avoid invalid CAST(NULL AS NULL) in SQLGlot compiler --- .../bigframes/core/compile/sqlglot/sql/base.py | 2 ++ .../tests/unit/core/compile/sqlglot/sql/test_base.py | 12 ++++++++++++ 2 files changed, 14 insertions(+) diff --git a/packages/bigframes/bigframes/core/compile/sqlglot/sql/base.py b/packages/bigframes/bigframes/core/compile/sqlglot/sql/base.py index 8b5eb748f575..a2218e948205 100644 --- a/packages/bigframes/bigframes/core/compile/sqlglot/sql/base.py +++ b/packages/bigframes/bigframes/core/compile/sqlglot/sql/base.py @@ -69,6 +69,8 @@ def literal(value: typing.Any, dtype: dtypes.Dtype | None = None) -> sge.Express return sge.Null() if value is None: + if sqlglot_type.upper() == "NULL": + return sge.Null() return cast(sge.Null(), sqlglot_type) if dtypes.is_struct_like(dtype): items = [ diff --git a/packages/bigframes/tests/unit/core/compile/sqlglot/sql/test_base.py b/packages/bigframes/tests/unit/core/compile/sqlglot/sql/test_base.py index 5ba77d925d0f..617f3636d403 100644 --- a/packages/bigframes/tests/unit/core/compile/sqlglot/sql/test_base.py +++ b/packages/bigframes/tests/unit/core/compile/sqlglot/sql/test_base.py @@ -159,3 +159,15 @@ def test_literal_explicit_dtype(value, dtype, expected): def test_literal_for_list(value: list, expected: str): got = sql.to_sql(sql.literal(value)) assert got == expected + + +def test_literal_null_type(): + import unittest.mock as mock + + mock_dtype = mock.Mock() + with mock.patch( + "bigframes.core.compile.sqlglot.sql.base.sgt.from_bigframes_dtype", + return_value="NULL", + ): + got = sql.to_sql(sql.literal(None, dtype=mock_dtype)) + assert got == "NULL" From a42324124698c78465528b1643c8fc863c403687 Mon Sep 17 00:00:00 2001 From: Shuowei Li Date: Tue, 16 Jun 2026 16:34:11 -0700 Subject: [PATCH 2/2] Update packages/bigframes/bigframes/core/compile/sqlglot/sql/base.py Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- packages/bigframes/bigframes/core/compile/sqlglot/sql/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/bigframes/bigframes/core/compile/sqlglot/sql/base.py b/packages/bigframes/bigframes/core/compile/sqlglot/sql/base.py index a2218e948205..f77dcbee4d93 100644 --- a/packages/bigframes/bigframes/core/compile/sqlglot/sql/base.py +++ b/packages/bigframes/bigframes/core/compile/sqlglot/sql/base.py @@ -69,7 +69,7 @@ def literal(value: typing.Any, dtype: dtypes.Dtype | None = None) -> sge.Express return sge.Null() if value is None: - if sqlglot_type.upper() == "NULL": + if str(sqlglot_type).upper() == "NULL": return sge.Null() return cast(sge.Null(), sqlglot_type) if dtypes.is_struct_like(dtype):