summaryrefslogtreecommitdiffstats
path: root/sqlglot/optimizer/scope.py
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2023-01-04 07:24:08 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2023-01-04 07:24:08 +0000
commit7a2201963d5b03bd1828d350ccaecb4eda30d30c (patch)
tree19effbe90b8d78fdcb5f7d4bd0dd46b177ffdaab /sqlglot/optimizer/scope.py
parentReleasing debian version 10.2.9-1. (diff)
downloadsqlglot-7a2201963d5b03bd1828d350ccaecb4eda30d30c.tar.xz
sqlglot-7a2201963d5b03bd1828d350ccaecb4eda30d30c.zip
Merging upstream version 10.4.2.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'sqlglot/optimizer/scope.py')
-rw-r--r--sqlglot/optimizer/scope.py30
1 files changed, 24 insertions, 6 deletions
diff --git a/sqlglot/optimizer/scope.py b/sqlglot/optimizer/scope.py
index 18848f3..6125e4e 100644
--- a/sqlglot/optimizer/scope.py
+++ b/sqlglot/optimizer/scope.py
@@ -511,9 +511,20 @@ def _traverse_union(scope):
def _traverse_derived_tables(derived_tables, scope, scope_type):
sources = {}
+ is_cte = scope_type == ScopeType.CTE
for derived_table in derived_tables:
- top = None
+ recursive_scope = None
+
+ # if the scope is a recursive cte, it must be in the form of
+ # base_case UNION recursive. thus the recursive scope is the first
+ # section of the union.
+ if is_cte and scope.expression.args["with"].recursive:
+ union = derived_table.this
+
+ if isinstance(union, exp.Union):
+ recursive_scope = scope.branch(union.this, scope_type=ScopeType.CTE)
+
for child_scope in _traverse_scope(
scope.branch(
derived_table if isinstance(derived_table, exp.UDTF) else derived_table.this,
@@ -523,16 +534,23 @@ def _traverse_derived_tables(derived_tables, scope, scope_type):
)
):
yield child_scope
- top = child_scope
+
# Tables without aliases will be set as ""
# This shouldn't be a problem once qualify_columns runs, as it adds aliases on everything.
# Until then, this means that only a single, unaliased derived table is allowed (rather,
# the latest one wins.
- sources[derived_table.alias] = child_scope
- if scope_type == ScopeType.CTE:
- scope.cte_scopes.append(top)
+ alias = derived_table.alias
+ sources[alias] = child_scope
+
+ if recursive_scope:
+ child_scope.add_source(alias, recursive_scope)
+
+ # append the final child_scope yielded
+ if is_cte:
+ scope.cte_scopes.append(child_scope)
else:
- scope.derived_table_scopes.append(top)
+ scope.derived_table_scopes.append(child_scope)
+
scope.sources.update(sources)