diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2023-07-24 08:03:48 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2023-07-24 08:03:48 +0000 |
commit | 36db14f4c6c28209371d563d76697df0172e337f (patch) | |
tree | 527347be54a38fc9b14fe1fa04c27a4bbae44016 /sqlglot/optimizer/scope.py | |
parent | Releasing debian version 17.4.1-1. (diff) | |
download | sqlglot-36db14f4c6c28209371d563d76697df0172e337f.tar.xz sqlglot-36db14f4c6c28209371d563d76697df0172e337f.zip |
Merging upstream version 17.7.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'sqlglot/optimizer/scope.py')
-rw-r--r-- | sqlglot/optimizer/scope.py | 32 |
1 files changed, 21 insertions, 11 deletions
diff --git a/sqlglot/optimizer/scope.py b/sqlglot/optimizer/scope.py index b2b4230..a7dab35 100644 --- a/sqlglot/optimizer/scope.py +++ b/sqlglot/optimizer/scope.py @@ -124,8 +124,8 @@ class Scope: self._ctes.append(node) elif ( isinstance(node, exp.Subquery) - and isinstance(parent, (exp.From, exp.Join)) - and _is_subquery_scope(node) + and isinstance(parent, (exp.From, exp.Join, exp.Subquery)) + and _is_derived_table(node) ): self._derived_tables.append(node) elif isinstance(node, exp.Subqueryable): @@ -610,13 +610,13 @@ def _traverse_ctes(scope): scope.sources.update(sources) -def _is_subquery_scope(expression: exp.Subquery) -> bool: +def _is_derived_table(expression: exp.Subquery) -> bool: """ - We represent (tbl1 JOIN tbl2) as a Subquery, but it's not really a new scope. - If an alias is present, it shadows all names under the Subquery, so that's an - exception to this rule. + We represent (tbl1 JOIN tbl2) as a Subquery, but it's not really a "derived table", + as it doesn't introduce a new scope. If an alias is present, it shadows all names + under the Subquery, so that's one exception to this rule. """ - return bool(not isinstance(expression.unnest(), exp.Table) or expression.alias) + return bool(expression.alias or isinstance(expression.this, exp.Subqueryable)) def _traverse_tables(scope): @@ -654,7 +654,10 @@ def _traverse_tables(scope): else: sources[source_name] = expression - expressions.extend(join.this for join in expression.args.get("joins") or []) + # Make sure to not include the joins twice + if expression is not scope.expression: + expressions.extend(join.this for join in expression.args.get("joins") or []) + continue if not isinstance(expression, exp.DerivedTable): @@ -664,10 +667,11 @@ def _traverse_tables(scope): lateral_sources = sources scope_type = ScopeType.UDTF scopes = scope.udtf_scopes - elif _is_subquery_scope(expression): + elif _is_derived_table(expression): lateral_sources = None scope_type = ScopeType.DERIVED_TABLE scopes = scope.derived_table_scopes + expressions.extend(join.this for join in expression.args.get("joins") or []) else: # Makes sure we check for possible sources in nested table constructs expressions.append(expression.this) @@ -735,10 +739,16 @@ def walk_in_scope(expression, bfs=True): isinstance(node, exp.CTE) or ( isinstance(node, exp.Subquery) - and isinstance(parent, (exp.From, exp.Join)) - and _is_subquery_scope(node) + and isinstance(parent, (exp.From, exp.Join, exp.Subquery)) + and _is_derived_table(node) ) or isinstance(node, exp.UDTF) or isinstance(node, exp.Subqueryable) ): prune = True + + if isinstance(node, (exp.Subquery, exp.UDTF)): + # The following args are not actually in the inner scope, so we should visit them + for key in ("joins", "laterals", "pivots"): + for arg in node.args.get(key) or []: + yield from walk_in_scope(arg, bfs=bfs) |