Skip to content

Commit

Permalink
fix: allow unnesting to bring struct fields into scope
Browse files Browse the repository at this point in the history
  • Loading branch information
tobymao committed Apr 12, 2024
1 parent 2224881 commit 5b2feb7
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 2 deletions.
16 changes: 14 additions & 2 deletions sqlglot/optimizer/qualify_columns.py
Expand Up @@ -7,6 +7,7 @@
from sqlglot.dialects.dialect import Dialect, DialectType
from sqlglot.errors import OptimizeError
from sqlglot.helper import seq_get, SingleValuedMapping
from sqlglot.optimizer.annotate_types import annotate_types
from sqlglot.optimizer.scope import Scope, build_scope, traverse_scope, walk_in_scope
from sqlglot.optimizer.simplify import simplify_parens
from sqlglot.schema import Schema, ensure_schema
Expand Down Expand Up @@ -652,8 +653,19 @@ def get_source_columns(self, name: str, only_visible: bool = False) -> t.Sequenc

if isinstance(source, exp.Table):
columns = self.schema.column_names(source, only_visible)
elif isinstance(source, Scope) and isinstance(source.expression, exp.Values):
columns = source.expression.alias_column_names
elif isinstance(source, Scope) and isinstance(source.expression, (exp.Values, exp.Unnest)):
columns = source.expression.named_selects

# in bigquery, unnest structs are automatically scoped as tables, so you can
# directly select a struct field in a query.
# this handles the case where the unnest is statically defined.
if self.schema.dialect == "bigquery":
expression = source.expression
annotate_types(expression)

if expression.is_type(exp.DataType.Type.STRUCT):
for k in expression.type.expressions: # type: ignore
columns.append(k.name)
else:
columns = source.expression.named_selects

Expand Down
5 changes: 5 additions & 0 deletions tests/fixtures/optimizer/qualify_columns.sql
Expand Up @@ -492,6 +492,11 @@ SELECT x AS x, offset AS offset FROM UNNEST([1, 2]) AS x WITH OFFSET AS offset;
select * from unnest ([1, 2]) as x with offset as y;
SELECT x AS x, y AS y FROM UNNEST([1, 2]) AS x WITH OFFSET AS y;

# dialect: bigquery
# execute: false
select x, a, x.a from unnest([STRUCT(1 AS a)]) as x;
SELECT x AS x, a AS a, x.a AS a FROM UNNEST([STRUCT(1 AS a)]) AS x;

# dialect: presto
SELECT x.a, i.b FROM x CROSS JOIN UNNEST(SPLIT(CAST(b AS VARCHAR), ',')) AS i(b);
SELECT x.a AS a, i.b AS b FROM x AS x CROSS JOIN UNNEST(SPLIT(CAST(x.b AS VARCHAR), ',')) AS i(b);
Expand Down

0 comments on commit 5b2feb7

Please sign in to comment.