@@ -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