Skip to content

Commit 6da9653

Browse files
authored
fix(optimizer): support bigquery type inference for unnest + array + struct (#7525)
* fix(optimizer): support bigquery type inference for unnest + array + struct * refactor loop
1 parent d289db3 commit 6da9653

2 files changed

Lines changed: 22 additions & 11 deletions

File tree

sqlglot-integration-tests

sqlglot/typing/bigquery.py

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -93,22 +93,33 @@ def _annotate_array(self: TypeAnnotator, expression: exp.Array) -> exp.Array:
9393
#
9494
# SELECT t, TYPEOF(t) FROM (SELECT 'foo') AS t -- foo, STRUCT<STRING>
9595
# SELECT ARRAY(SELECT 'foo'), TYPEOF(ARRAY(SELECT 'foo')) -- foo, ARRAY<STRING>
96-
# ARRAY(SELECT ... UNION ALL SELECT ...) -- ARRAY<type from coerced projections>
96+
# ARRAY(SELECT ... UNION ALL SELECT ...) -- ARRAY<type from coerced projections>
97+
# ARRAY(SELECT AS STRUCT 1 AS a, 'b' AS b) -- ARRAY<STRUCT<INT64, STRING>>
9798
if len(array_args) == 1:
9899
unnested = array_args[0].unnest()
99100
projection_type: exp.DataType | exp.DType | None = None
100101

101102
# Handle ARRAY(SELECT ...) - single SELECT query
102103
if isinstance(unnested, exp.Select):
103-
if (
104-
(query_type := unnested.meta.get("query_type")) is not None
105-
and query_type.is_type(exp.DType.STRUCT)
106-
and len(query_type.expressions) == 1
107-
and isinstance(col_def := query_type.expressions[0], exp.ColumnDef)
108-
and (col_type := col_def.kind) is not None
109-
and not col_type.is_type(exp.DType.UNKNOWN)
110-
):
111-
projection_type = col_type
104+
query_type = unnested.meta.get("query_type")
105+
106+
if query_type and query_type.is_type(exp.DType.STRUCT):
107+
query_exprs = query_type.expressions
108+
109+
col_defs = [
110+
e
111+
for e in query_exprs
112+
if isinstance(e, exp.ColumnDef)
113+
and not (e.kind and e.kind.is_type(exp.DType.UNKNOWN))
114+
]
115+
116+
if len(col_defs) == len(query_exprs):
117+
if unnested.args.get("kind") == "STRUCT":
118+
# ARRAY(SELECT AS STRUCT ...) -> ARRAY<STRUCT<col1, col2, ...>>
119+
projection_type = query_type
120+
elif len(col_defs) == 1 and (col_type := col_defs[0].kind):
121+
# ARRAY(SELECT col FROM ...) -> ARRAY<col_type>
122+
projection_type = col_type
112123

113124
# Handle ARRAY(SELECT ... UNION ALL SELECT ...) - set operations
114125
elif isinstance(unnested, exp.SetOperation):

0 commit comments

Comments
 (0)