diff --git a/sqlglot/optimizer/qualify_tables.py b/sqlglot/optimizer/qualify_tables.py index c223f55eec..3e9935149a 100644 --- a/sqlglot/optimizer/qualify_tables.py +++ b/sqlglot/optimizer/qualify_tables.py @@ -75,6 +75,11 @@ def _qualify(table: exp.Table) -> None: _qualify(node) for scope in traverse_scope(expression): + for query in scope.subqueries: + subquery = query.parent + if isinstance(subquery, exp.Subquery): + subquery.unwrap().replace(subquery) + for derived_table in scope.derived_tables: unnested = derived_table.unnest() if isinstance(unnested, exp.Table): diff --git a/sqlglot/optimizer/scope.py b/sqlglot/optimizer/scope.py index 96d3a60a1c..e3754db289 100644 --- a/sqlglot/optimizer/scope.py +++ b/sqlglot/optimizer/scope.py @@ -156,7 +156,7 @@ def _collect(self): self._ctes.append(node) elif _is_derived_table(node) and _is_from_or_join(node): self._derived_tables.append(node) - elif isinstance(node, exp.UNWRAPPED_QUERIES): + elif isinstance(node, exp.UNWRAPPED_QUERIES) and not _is_from_or_join(node): self._subqueries.append(node) elif isinstance(node, exp.TableColumn): self._table_columns.append(node) @@ -821,7 +821,7 @@ def _traverse_udtfs(scope): sources = {} for expression in expressions: - if _is_derived_table(expression): + if isinstance(expression, exp.Subquery): top = None for child_scope in _traverse_scope( scope.branch( @@ -870,10 +870,7 @@ def walk_in_scope(expression, bfs=True, prune=None): if ( isinstance(node, exp.CTE) - or ( - isinstance(node.parent, (exp.From, exp.Join, exp.Subquery)) - and _is_derived_table(node) - ) + or (isinstance(node.parent, (exp.From, exp.Join)) and _is_derived_table(node)) or (isinstance(node.parent, exp.UDTF) and isinstance(node, exp.Query)) or isinstance(node, exp.UNWRAPPED_QUERIES) ): diff --git a/tests/fixtures/optimizer/qualify_columns.sql b/tests/fixtures/optimizer/qualify_columns.sql index 5b3b19bf4c..6676812a77 100644 --- a/tests/fixtures/optimizer/qualify_columns.sql +++ b/tests/fixtures/optimizer/qualify_columns.sql @@ -337,7 +337,7 @@ SELECT _q_0.a AS a FROM (SELECT x.a AS a FROM x AS x UNION SELECT x.a AS a FROM # title: nested subqueries in union ((select a from x where a < 1)) UNION ((select a from x where a > 2)); -((SELECT x.a AS a FROM x AS x WHERE x.a < 1)) UNION ((SELECT x.a AS a FROM x AS x WHERE x.a > 2)); +(SELECT x.a AS a FROM x AS x WHERE x.a < 1) UNION (SELECT x.a AS a FROM x AS x WHERE x.a > 2); # dialect: bigquery @@ -443,6 +443,10 @@ SELECT _q_1.a AS a FROM (SELECT x.a AS a FROM x AS x) AS _q_1 WHERE _q_1.a IN (S SELECT * FROM table_a as A WHERE A.col1 IN (SELECT MAX(B.col2) FROM table_b as B UNION ALL SELECT MAX(C.col2) FROM table_b as C); SELECT * FROM table_a AS `A` WHERE `A`.col1 IN (SELECT MAX(`B`.col2) AS _col_0 FROM table_b AS `B` UNION ALL SELECT MAX(`C`.col2) AS _col_0 FROM table_b AS `C`); +# Title: Unnest deep subquery +select * from x where b in ((((select b from y)))); +SELECT x.a AS a, x.b AS b FROM x AS x WHERE x.b IN (SELECT y.b AS b FROM y AS y); + -------------------------------------- -- Correlated subqueries --------------------------------------