1use crate::expressions::Expression;
9use crate::traversal::ExpressionWalk;
10use serde::{Deserialize, Serialize};
11use std::collections::{HashMap, HashSet, VecDeque};
12#[cfg(feature = "bindings")]
13use ts_rs::TS;
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
17#[cfg_attr(feature = "bindings", derive(TS))]
18#[cfg_attr(feature = "bindings", ts(export))]
19pub enum ScopeType {
20 Root,
22 Subquery,
24 DerivedTable,
26 Cte,
28 SetOperation,
30 Udtf,
32}
33
34#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
36#[serde(rename_all = "snake_case")]
37pub enum SourceKind {
38 Root,
40 Table,
42 DerivedTable,
44 Cte,
46 Virtual,
48 Unknown,
50}
51
52impl Default for SourceKind {
53 fn default() -> Self {
54 Self::Unknown
55 }
56}
57
58pub(crate) fn scope_query(expression: &Expression) -> &Expression {
60 match expression {
61 Expression::Cte(cte) => scope_query(&cte.this),
62 Expression::Subquery(subquery) => scope_query(&subquery.this),
63 Expression::Paren(paren) => scope_query(&paren.this),
64 Expression::Alias(alias) => scope_query(&alias.this),
65 Expression::Prepare(prepare) => scope_query(&prepare.statement),
66 Expression::CreateTable(create) if create.as_select.is_some() => {
67 scope_query(create.as_select.as_ref().unwrap())
68 }
69 _ => expression,
70 }
71}
72
73pub(crate) fn selected_reference_scope(scope: &Scope) -> Scope {
76 let query = scope_query(&scope.expression);
77 let aliases: HashSet<_> = walk_in_scope(query, false)
78 .filter_map(|node| match node {
79 Expression::Table(table) => Some(
80 table
81 .alias
82 .as_ref()
83 .unwrap_or(&table.name)
84 .name
85 .to_lowercase(),
86 ),
87 _ => None,
88 })
89 .collect();
90 let mut selected = Scope::new(query.clone());
91 selected.cte_sources = scope.cte_sources.clone();
92 selected.sources = scope
93 .sources
94 .iter()
95 .filter(|(name, source)| {
96 source.kind != SourceKind::Cte || aliases.contains(&name.to_lowercase())
97 })
98 .map(|(name, source)| (name.clone(), source.clone()))
99 .collect();
100 selected
101}
102
103#[derive(Debug, Clone)]
105pub struct SourceInfo {
106 pub expression: Expression,
108 pub is_scope: bool,
110 pub kind: SourceKind,
112 pub alias: Option<String>,
114 pub lineage_name: Option<String>,
116}
117
118impl SourceInfo {
119 pub fn new(expression: Expression, is_scope: bool, kind: SourceKind) -> Self {
120 Self {
121 expression,
122 is_scope,
123 kind,
124 alias: None,
125 lineage_name: None,
126 }
127 }
128
129 pub fn with_alias(mut self, alias: impl Into<String>) -> Self {
130 self.alias = Some(alias.into());
131 self
132 }
133
134 pub fn with_lineage_name(mut self, lineage_name: impl Into<String>) -> Self {
135 self.lineage_name = Some(lineage_name.into());
136 self
137 }
138}
139
140#[derive(Debug, Clone, PartialEq, Eq, Hash)]
142pub struct ColumnRef {
143 pub table: Option<String>,
145 pub name: String,
147}
148
149#[derive(Debug, Clone)]
154pub struct Scope {
155 pub expression: Expression,
157
158 pub scope_type: ScopeType,
160
161 pub sources: HashMap<String, SourceInfo>,
163
164 pub lateral_sources: HashMap<String, SourceInfo>,
166
167 pub cte_sources: HashMap<String, SourceInfo>,
169
170 pub outer_columns: Vec<String>,
173
174 pub can_be_correlated: bool,
177
178 pub subquery_scopes: Vec<Scope>,
180
181 pub derived_table_scopes: Vec<Scope>,
183
184 pub cte_scopes: Vec<Scope>,
186
187 pub udtf_scopes: Vec<Scope>,
189
190 pub table_scopes: Vec<Scope>,
192
193 pub union_scopes: Vec<Scope>,
195
196 columns_cache: Option<Vec<ColumnRef>>,
198
199 external_columns_cache: Option<Vec<ColumnRef>>,
201}
202
203impl Scope {
204 pub fn new(expression: Expression) -> Self {
206 Self {
207 expression,
208 scope_type: ScopeType::Root,
209 sources: HashMap::new(),
210 lateral_sources: HashMap::new(),
211 cte_sources: HashMap::new(),
212 outer_columns: Vec::new(),
213 can_be_correlated: false,
214 subquery_scopes: Vec::new(),
215 derived_table_scopes: Vec::new(),
216 cte_scopes: Vec::new(),
217 udtf_scopes: Vec::new(),
218 table_scopes: Vec::new(),
219 union_scopes: Vec::new(),
220 columns_cache: None,
221 external_columns_cache: None,
222 }
223 }
224
225 pub fn branch(&self, expression: Expression, scope_type: ScopeType) -> Self {
227 self.branch_with_options(expression, scope_type, None, None, None)
228 }
229
230 pub fn branch_with_options(
232 &self,
233 expression: Expression,
234 scope_type: ScopeType,
235 sources: Option<HashMap<String, SourceInfo>>,
236 lateral_sources: Option<HashMap<String, SourceInfo>>,
237 outer_columns: Option<Vec<String>>,
238 ) -> Self {
239 let can_be_correlated = self.can_be_correlated
240 || scope_type == ScopeType::Subquery
241 || scope_type == ScopeType::Udtf;
242
243 Self {
244 expression,
245 scope_type,
246 sources: sources.unwrap_or_default(),
247 lateral_sources: lateral_sources.unwrap_or_default(),
248 cte_sources: self.cte_sources.clone(),
249 outer_columns: outer_columns.unwrap_or_default(),
250 can_be_correlated,
251 subquery_scopes: Vec::new(),
252 derived_table_scopes: Vec::new(),
253 cte_scopes: Vec::new(),
254 udtf_scopes: Vec::new(),
255 table_scopes: Vec::new(),
256 union_scopes: Vec::new(),
257 columns_cache: None,
258 external_columns_cache: None,
259 }
260 }
261
262 pub fn clear_cache(&mut self) {
264 self.columns_cache = None;
265 self.external_columns_cache = None;
266 }
267
268 pub fn add_source(&mut self, name: String, expression: Expression, is_scope: bool) {
270 let kind = if is_scope {
271 SourceKind::DerivedTable
272 } else {
273 SourceKind::Table
274 };
275 self.add_source_info(name, SourceInfo::new(expression, is_scope, kind));
276 }
277
278 pub fn add_source_info(&mut self, name: String, info: SourceInfo) {
280 self.sources.insert(name, info);
281 self.clear_cache();
282 }
283
284 pub fn add_virtual_source(&mut self, alias: String, expression: Expression) {
286 let lineage_name = self.next_virtual_source_name();
287 let info = SourceInfo::new(expression, false, SourceKind::Virtual)
288 .with_alias(alias.clone())
289 .with_lineage_name(lineage_name);
290 self.add_source_info(alias, info);
291 }
292
293 fn next_virtual_source_name(&self) -> String {
294 let count = self
295 .sources
296 .values()
297 .filter(|source| source.kind == SourceKind::Virtual)
298 .count();
299 format!("_{}", count)
300 }
301
302 pub fn add_lateral_source(&mut self, name: String, expression: Expression, is_scope: bool) {
304 let kind = if is_scope {
305 SourceKind::DerivedTable
306 } else {
307 SourceKind::Table
308 };
309 let info = SourceInfo::new(expression.clone(), is_scope, kind);
310 self.sources.insert(name.clone(), info.clone());
311 self.lateral_sources.insert(name, info);
312 self.clear_cache();
313 }
314
315 pub fn add_cte_source(&mut self, name: String, expression: Expression) {
317 let info = SourceInfo::new(expression, true, SourceKind::Cte);
318 self.cte_sources.insert(name.clone(), info.clone());
319 self.sources.insert(name, info);
320 self.clear_cache();
321 }
322
323 pub fn rename_source(&mut self, old_name: &str, new_name: String) {
325 if let Some(source) = self.sources.remove(old_name) {
326 self.sources.insert(new_name, source);
327 }
328 self.clear_cache();
329 }
330
331 pub fn remove_source(&mut self, name: &str) {
333 self.sources.remove(name);
334 self.clear_cache();
335 }
336
337 pub fn columns(&mut self) -> &[ColumnRef] {
339 if self.columns_cache.is_none() {
340 let mut columns = Vec::new();
341 collect_columns(&self.expression, &mut columns);
342 self.columns_cache = Some(columns);
343 }
344 self.columns_cache.as_ref().unwrap()
345 }
346
347 pub fn output_columns(&self) -> Vec<String> {
352 crate::ast_transforms::get_output_column_names(&self.expression)
353 }
354
355 pub fn source_names(&self) -> HashSet<String> {
357 let mut names: HashSet<String> = self.sources.keys().cloned().collect();
358 names.extend(self.cte_sources.keys().cloned());
359 names
360 }
361
362 pub fn external_columns(&mut self) -> Vec<ColumnRef> {
364 if self.external_columns_cache.is_some() {
365 return self.external_columns_cache.clone().unwrap();
366 }
367
368 let source_names = self.source_names();
369 let columns = self.columns().to_vec();
370
371 let external: Vec<ColumnRef> = columns
372 .into_iter()
373 .filter(|col| {
374 match &col.table {
376 Some(table) => !source_names.contains(table),
377 None => false, }
379 })
380 .collect();
381
382 self.external_columns_cache = Some(external.clone());
383 external
384 }
385
386 pub fn local_columns(&mut self) -> Vec<ColumnRef> {
388 let external_set: HashSet<_> = self.external_columns().into_iter().collect();
389 let columns = self.columns().to_vec();
390
391 columns
392 .into_iter()
393 .filter(|col| !external_set.contains(col))
394 .collect()
395 }
396
397 pub fn unqualified_columns(&mut self) -> Vec<ColumnRef> {
399 self.columns()
400 .iter()
401 .filter(|c| c.table.is_none())
402 .cloned()
403 .collect()
404 }
405
406 pub fn source_columns(&mut self, source_name: &str) -> Vec<ColumnRef> {
408 self.columns()
409 .iter()
410 .filter(|col| col.table.as_deref() == Some(source_name))
411 .cloned()
412 .collect()
413 }
414
415 pub fn is_correlated_subquery(&mut self) -> bool {
421 self.can_be_correlated && !self.external_columns().is_empty()
422 }
423
424 pub fn is_subquery(&self) -> bool {
426 self.scope_type == ScopeType::Subquery
427 }
428
429 pub fn is_derived_table(&self) -> bool {
431 self.scope_type == ScopeType::DerivedTable
432 }
433
434 pub fn is_cte(&self) -> bool {
436 self.scope_type == ScopeType::Cte
437 }
438
439 pub fn is_root(&self) -> bool {
441 self.scope_type == ScopeType::Root
442 }
443
444 pub fn is_udtf(&self) -> bool {
446 self.scope_type == ScopeType::Udtf
447 }
448
449 pub fn is_union(&self) -> bool {
451 self.scope_type == ScopeType::SetOperation
452 }
453
454 pub fn traverse(&self) -> Vec<&Scope> {
456 let mut result = Vec::new();
457 self.traverse_impl(&mut result);
458 result
459 }
460
461 fn traverse_impl<'a>(&'a self, result: &mut Vec<&'a Scope>) {
462 for scope in &self.cte_scopes {
464 scope.traverse_impl(result);
465 }
466 for scope in &self.union_scopes {
467 scope.traverse_impl(result);
468 }
469 for scope in &self.table_scopes {
470 scope.traverse_impl(result);
471 }
472 for scope in &self.subquery_scopes {
473 scope.traverse_impl(result);
474 }
475 result.push(self);
477 }
478
479 pub fn ref_count(&self) -> HashMap<usize, usize> {
481 let mut counts: HashMap<usize, usize> = HashMap::new();
482
483 for scope in self.traverse() {
484 for (_, source_info) in scope.sources.iter() {
485 if source_info.is_scope {
486 let id = &source_info.expression as *const _ as usize;
487 *counts.entry(id).or_insert(0) += 1;
488 }
489 }
490 }
491
492 counts
493 }
494}
495
496fn collect_columns(expr: &Expression, columns: &mut Vec<ColumnRef>) {
498 match expr {
499 Expression::Column(col) => {
500 columns.push(ColumnRef {
501 table: col.table.as_ref().map(|t| t.name.clone()),
502 name: col.name.name.clone(),
503 });
504 }
505 Expression::Select(select) => {
506 for e in &select.expressions {
508 collect_columns(e, columns);
509 }
510 for join in &select.joins {
512 if let Some(on) = &join.on {
513 collect_columns(on, columns);
514 }
515 if let Some(match_condition) = &join.match_condition {
516 collect_columns(match_condition, columns);
517 }
518 }
519 if let Some(where_clause) = &select.where_clause {
521 collect_columns(&where_clause.this, columns);
522 }
523 if let Some(having) = &select.having {
525 collect_columns(&having.this, columns);
526 }
527 if let Some(order_by) = &select.order_by {
529 for ord in &order_by.expressions {
530 collect_columns(&ord.this, columns);
531 }
532 }
533 if let Some(group_by) = &select.group_by {
535 for e in &group_by.expressions {
536 collect_columns(e, columns);
537 }
538 }
539 }
542 Expression::And(bin)
544 | Expression::Or(bin)
545 | Expression::Add(bin)
546 | Expression::Sub(bin)
547 | Expression::Mul(bin)
548 | Expression::Div(bin)
549 | Expression::Mod(bin)
550 | Expression::Eq(bin)
551 | Expression::Neq(bin)
552 | Expression::Lt(bin)
553 | Expression::Lte(bin)
554 | Expression::Gt(bin)
555 | Expression::Gte(bin)
556 | Expression::BitwiseAnd(bin)
557 | Expression::BitwiseOr(bin)
558 | Expression::BitwiseXor(bin)
559 | Expression::Concat(bin) => {
560 collect_columns(&bin.left, columns);
561 collect_columns(&bin.right, columns);
562 }
563 Expression::Like(like) | Expression::ILike(like) => {
565 collect_columns(&like.left, columns);
566 collect_columns(&like.right, columns);
567 if let Some(escape) = &like.escape {
568 collect_columns(escape, columns);
569 }
570 }
571 Expression::Not(un) | Expression::Neg(un) | Expression::BitwiseNot(un) => {
573 collect_columns(&un.this, columns);
574 }
575 Expression::Function(func) => {
576 for arg in &func.args {
577 collect_columns(arg, columns);
578 }
579 }
580 Expression::AggregateFunction(agg) => {
581 for arg in &agg.args {
582 collect_columns(arg, columns);
583 }
584 }
585 Expression::WindowFunction(wf) => {
586 collect_columns(&wf.this, columns);
587 for e in &wf.over.partition_by {
588 collect_columns(e, columns);
589 }
590 for e in &wf.over.order_by {
591 collect_columns(&e.this, columns);
592 }
593 }
594 Expression::Alias(alias) => {
595 collect_columns(&alias.this, columns);
596 }
597 Expression::Case(case) => {
598 if let Some(operand) = &case.operand {
599 collect_columns(operand, columns);
600 }
601 for (when_expr, then_expr) in &case.whens {
602 collect_columns(when_expr, columns);
603 collect_columns(then_expr, columns);
604 }
605 if let Some(else_clause) = &case.else_ {
606 collect_columns(else_clause, columns);
607 }
608 }
609 Expression::Paren(paren) => {
610 collect_columns(&paren.this, columns);
611 }
612 Expression::Ordered(ord) => {
613 collect_columns(&ord.this, columns);
614 }
615 Expression::In(in_expr) => {
616 collect_columns(&in_expr.this, columns);
617 for e in &in_expr.expressions {
618 collect_columns(e, columns);
619 }
620 }
622 Expression::Between(between) => {
623 collect_columns(&between.this, columns);
624 collect_columns(&between.low, columns);
625 collect_columns(&between.high, columns);
626 }
627 Expression::IsNull(is_null) => {
628 collect_columns(&is_null.this, columns);
629 }
630 Expression::Cast(cast) => {
631 collect_columns(&cast.this, columns);
632 }
633 Expression::Extract(extract) => {
634 collect_columns(&extract.this, columns);
635 }
636 Expression::Exists(_) | Expression::Subquery(_) => {
637 }
639 Expression::Prepare(prepare) => {
640 collect_columns(&prepare.statement, columns);
641 }
642 _ => {
643 }
645 }
646}
647
648pub fn build_scope(expression: &Expression) -> Scope {
653 let mut root = Scope::new(expression.clone());
654 build_scope_impl(expression, &mut root);
655 root
656}
657
658fn build_scope_impl(expression: &Expression, current_scope: &mut Scope) {
659 match expression {
660 Expression::Prepare(prepare) => {
661 build_scope_impl(&prepare.statement, current_scope);
662 }
663 Expression::Select(select) => {
664 if let Some(with) = &select.with {
666 process_ctes(with, current_scope);
667 }
668
669 if let Some(from) = &select.from {
671 for table in &from.expressions {
672 add_table_to_scope(table, current_scope);
673 }
674 }
675
676 for join in &select.joins {
678 add_table_to_scope(&join.this, current_scope);
679 }
680
681 for lateral_view in &select.lateral_views {
683 add_lateral_view_to_scope(lateral_view, current_scope);
684 }
685
686 collect_subqueries(expression, current_scope);
688 }
689 Expression::Union(union) => {
690 if let Some(with) = &union.with {
691 process_ctes(with, current_scope);
692 }
693
694 let mut left_scope = current_scope.branch(union.left.clone(), ScopeType::SetOperation);
695 build_scope_impl(&union.left, &mut left_scope);
696
697 let mut right_scope =
698 current_scope.branch(union.right.clone(), ScopeType::SetOperation);
699 build_scope_impl(&union.right, &mut right_scope);
700
701 current_scope.union_scopes.push(left_scope);
702 current_scope.union_scopes.push(right_scope);
703 }
704 Expression::Intersect(intersect) => {
705 if let Some(with) = &intersect.with {
706 process_ctes(with, current_scope);
707 }
708
709 let mut left_scope =
710 current_scope.branch(intersect.left.clone(), ScopeType::SetOperation);
711 build_scope_impl(&intersect.left, &mut left_scope);
712
713 let mut right_scope =
714 current_scope.branch(intersect.right.clone(), ScopeType::SetOperation);
715 build_scope_impl(&intersect.right, &mut right_scope);
716
717 current_scope.union_scopes.push(left_scope);
718 current_scope.union_scopes.push(right_scope);
719 }
720 Expression::Except(except) => {
721 if let Some(with) = &except.with {
722 process_ctes(with, current_scope);
723 }
724
725 let mut left_scope = current_scope.branch(except.left.clone(), ScopeType::SetOperation);
726 build_scope_impl(&except.left, &mut left_scope);
727
728 let mut right_scope =
729 current_scope.branch(except.right.clone(), ScopeType::SetOperation);
730 build_scope_impl(&except.right, &mut right_scope);
731
732 current_scope.union_scopes.push(left_scope);
733 current_scope.union_scopes.push(right_scope);
734 }
735 Expression::CreateTable(create) => {
736 if let Some(with) = &create.with_cte {
739 process_ctes(with, current_scope);
740 }
741 if let Some(as_select) = &create.as_select {
743 build_scope_impl(as_select, current_scope);
744 }
745 }
746 Expression::Subquery(subquery) => {
747 build_scope_impl(&subquery.this, current_scope);
748 }
749 Expression::Paren(paren) => {
750 build_scope_impl(&paren.this, current_scope);
751 }
752 _ => {}
753 }
754}
755
756fn process_ctes(with: &crate::expressions::With, current_scope: &mut Scope) {
757 for cte in &with.ctes {
758 let cte_name = cte.alias.name.clone();
759 let cte_expr = Expression::Cte(Box::new(cte.clone()));
760 let mut cte_scope = current_scope.branch(cte_expr.clone(), ScopeType::Cte);
761
762 if with.recursive && cte_body_self_references(cte) {
763 cte_scope.add_cte_source(cte_name.clone(), cte_expr.clone());
764 }
765
766 build_scope_impl(&cte.this, &mut cte_scope);
767 current_scope.add_cte_source(cte_name, cte_expr);
768 current_scope.cte_scopes.push(cte_scope);
769 }
770}
771
772fn cte_body_self_references(cte: &crate::expressions::Cte) -> bool {
773 let cte_name = cte.alias.name.as_str();
774 !cte.this
775 .find_all(|expr| match expr {
776 Expression::Table(table) if table.schema.is_none() && table.catalog.is_none() => {
777 table.name.name.eq_ignore_ascii_case(cte_name)
778 }
779 _ => false,
780 })
781 .is_empty()
782}
783
784fn add_table_to_scope(expr: &Expression, scope: &mut Scope) {
785 match expr {
786 Expression::Table(table) => {
787 let name = table
788 .alias
789 .as_ref()
790 .map(|a| a.name.clone())
791 .unwrap_or_else(|| table.name.name.clone());
792 let cte_source = if table.schema.is_none() && table.catalog.is_none() {
793 scope.cte_sources.get(&table.name.name).or_else(|| {
794 scope
795 .cte_sources
796 .iter()
797 .find(|(cte_name, _)| cte_name.eq_ignore_ascii_case(&table.name.name))
798 .map(|(_, source)| source)
799 })
800 } else {
801 None
802 };
803
804 if let Some(source) = cte_source {
805 scope.add_source_info(name, source.clone());
806 } else {
807 let mut source = SourceInfo::new(expr.clone(), false, SourceKind::Table);
808 if let Some(alias) = &table.alias {
809 source = source.with_alias(alias.name.clone());
810 }
811 scope.add_source_info(name, source);
812 }
813 }
814 Expression::Subquery(subquery) => {
815 let name = subquery
816 .alias
817 .as_ref()
818 .map(|a| a.name.clone())
819 .unwrap_or_default();
820
821 let mut derived_scope = scope.branch(subquery.this.clone(), ScopeType::DerivedTable);
822 build_scope_impl(&subquery.this, &mut derived_scope);
823
824 scope.add_source(name.clone(), expr.clone(), true);
825 scope.derived_table_scopes.push(derived_scope);
826 }
827 Expression::Unnest(unnest) => {
828 if let Some(alias) = &unnest.alias {
829 scope.add_virtual_source(alias.name.clone(), expr.clone());
830 }
831 }
832 Expression::Alias(alias) if matches!(&alias.this, Expression::Unnest(_)) => {
833 scope.add_virtual_source(alias.alias.name.clone(), expr.clone());
834 }
835 Expression::Alias(alias) if is_query_like_relation(&alias.this) => {
836 let outer_columns = alias
837 .column_aliases
838 .iter()
839 .map(|column| column.name.clone())
840 .collect::<Vec<_>>();
841 let mut derived_scope = scope.branch_with_options(
842 alias.this.clone(),
843 ScopeType::DerivedTable,
844 None,
845 None,
846 Some(outer_columns),
847 );
848 build_scope_impl(&alias.this, &mut derived_scope);
849
850 scope.add_source(alias.alias.name.clone(), expr.clone(), true);
851 scope.derived_table_scopes.push(derived_scope);
852 }
853 Expression::Lateral(lateral) => {
854 if let Some(alias) = &lateral.alias {
855 scope.add_virtual_source(alias.clone(), expr.clone());
856 }
857 }
858 Expression::LateralView(lateral_view) => {
859 add_lateral_view_to_scope(lateral_view, scope);
860 }
861 Expression::Pivot(pivot) => {
862 let name =
863 pivot_source_name(&pivot.this, pivot.alias.as_ref().map(|a| a.name.as_str()));
864 scope.add_source_info(
865 name,
866 SourceInfo::new(expr.clone(), false, SourceKind::DerivedTable),
867 );
868 add_pivot_inner_scope(&pivot.this, scope);
869 }
870 Expression::Unpivot(unpivot) => {
871 let name = pivot_source_name(
872 &unpivot.this,
873 unpivot.alias.as_ref().map(|a| a.name.as_str()),
874 );
875 scope.add_source_info(
876 name,
877 SourceInfo::new(expr.clone(), false, SourceKind::DerivedTable),
878 );
879 add_pivot_inner_scope(&unpivot.this, scope);
880 }
881 Expression::Paren(paren) => {
882 add_table_to_scope(&paren.this, scope);
883 }
884 _ => {}
885 }
886}
887
888fn is_query_like_relation(expr: &Expression) -> bool {
889 match expr {
890 Expression::Select(_)
891 | Expression::Subquery(_)
892 | Expression::Union(_)
893 | Expression::Intersect(_)
894 | Expression::Except(_) => true,
895 Expression::Paren(paren) => is_query_like_relation(&paren.this),
896 _ => false,
897 }
898}
899
900fn pivot_source_name(source: &Expression, explicit_alias: Option<&str>) -> String {
901 if let Some(alias) = explicit_alias {
902 return alias.to_string();
903 }
904
905 match source {
906 Expression::Table(table) => table
907 .alias
908 .as_ref()
909 .map(|alias| alias.name.clone())
910 .unwrap_or_else(|| table.name.name.clone()),
911 Expression::Subquery(subquery) => subquery
912 .alias
913 .as_ref()
914 .map(|alias| alias.name.clone())
915 .unwrap_or_else(|| "_0".to_string()),
916 Expression::Paren(paren) => pivot_source_name(&paren.this, explicit_alias),
917 _ => "_0".to_string(),
918 }
919}
920
921fn add_pivot_inner_scope(source: &Expression, scope: &mut Scope) {
922 match source {
923 Expression::Subquery(subquery) => {
924 let mut derived_scope = scope.branch(subquery.this.clone(), ScopeType::DerivedTable);
925 build_scope_impl(&subquery.this, &mut derived_scope);
926 scope.derived_table_scopes.push(derived_scope);
927 }
928 Expression::Paren(paren) => add_pivot_inner_scope(&paren.this, scope),
929 _ => {}
930 }
931}
932
933fn add_lateral_view_to_scope(lateral_view: &crate::expressions::LateralView, scope: &mut Scope) {
934 let alias = lateral_view
935 .table_alias
936 .as_ref()
937 .or_else(|| lateral_view.column_aliases.first())
938 .map(|alias| alias.name.clone());
939
940 if let Some(alias) = alias {
941 scope.add_virtual_source(
942 alias,
943 Expression::LateralView(Box::new(lateral_view.clone())),
944 );
945 }
946}
947
948fn collect_subqueries(expr: &Expression, parent_scope: &mut Scope) {
949 if matches!(expr, Expression::Select(_)) {
950 use crate::ast_children::ChildPathSegment::{Field, Index};
951
952 crate::ast_children::for_each_child(expr, |path, child| {
956 if !matches!(
957 path,
958 [Field("from" | "with" | "lateral_views"), ..]
959 | [Field("joins"), Index(_), Field("this"), ..]
960 ) {
961 collect_subqueries_in_expr(child, parent_scope);
962 }
963 });
964 }
965}
966
967fn collect_subqueries_in_expr(expr: &Expression, parent_scope: &mut Scope) {
968 let mut seen = HashSet::new();
969 for node in walk_in_scope(expr, false) {
970 let query = match node {
971 Expression::Subquery(subquery) if subquery.alias.is_none() => Some(&subquery.this),
972 Expression::Exists(exists) => Some(&exists.this),
973 Expression::In(in_expr) => in_expr.query.as_ref(),
974 Expression::Any(quantified) | Expression::All(quantified) => Some(&quantified.subquery),
975 _ => None,
976 };
977
978 let Some(query) = query else {
979 continue;
980 };
981
982 let key = query as *const Expression as usize;
983 if !seen.insert(key) {
984 continue;
985 }
986
987 let mut sub_scope = parent_scope.branch(query.clone(), ScopeType::Subquery);
988 build_scope_impl(query, &mut sub_scope);
989 parent_scope.subquery_scopes.push(sub_scope);
990 }
991}
992
993pub fn walk_in_scope<'a>(
1005 expression: &'a Expression,
1006 bfs: bool,
1007) -> impl Iterator<Item = &'a Expression> {
1008 WalkInScopeIter::new(expression, bfs)
1009}
1010
1011struct WalkInScopeIter<'a> {
1013 queue: VecDeque<&'a Expression>,
1014 bfs: bool,
1015}
1016
1017impl<'a> WalkInScopeIter<'a> {
1018 fn new(expression: &'a Expression, bfs: bool) -> Self {
1019 let mut queue = VecDeque::new();
1020 queue.push_back(expression);
1021 Self { queue, bfs }
1022 }
1023
1024 fn should_stop_at(&self, expr: &Expression, is_root: bool) -> bool {
1025 if is_root {
1026 return false;
1027 }
1028
1029 if matches!(expr, Expression::Cte(_)) {
1031 return true;
1032 }
1033
1034 if let Expression::Subquery(subquery) = expr {
1036 if subquery.alias.is_some() {
1037 return true;
1038 }
1039 }
1040
1041 if matches!(
1043 expr,
1044 Expression::Select(_)
1045 | Expression::Union(_)
1046 | Expression::Intersect(_)
1047 | Expression::Except(_)
1048 ) {
1049 return true;
1050 }
1051
1052 false
1053 }
1054
1055 fn get_children(&self, expr: &'a Expression) -> Vec<&'a Expression> {
1056 let mut children = Vec::new();
1057
1058 match expr {
1059 Expression::Prepare(prepare) => {
1060 children.push(&prepare.statement);
1061 }
1062 Expression::Select(select) => {
1063 for e in &select.expressions {
1065 children.push(e);
1066 }
1067 if let Some(from) = &select.from {
1069 for table in &from.expressions {
1070 if !self.should_stop_at(table, false) {
1071 children.push(table);
1072 }
1073 }
1074 }
1075 for join in &select.joins {
1077 if !self.should_stop_at(&join.this, false) {
1078 children.push(&join.this);
1079 }
1080 if let Some(on) = &join.on {
1081 children.push(on);
1082 }
1083 if let Some(condition) = &join.match_condition {
1084 children.push(condition);
1085 }
1086 }
1087 if let Some(where_clause) = &select.where_clause {
1089 children.push(&where_clause.this);
1090 }
1091 if let Some(group_by) = &select.group_by {
1093 for e in &group_by.expressions {
1094 children.push(e);
1095 }
1096 }
1097 if let Some(having) = &select.having {
1099 children.push(&having.this);
1100 }
1101 if let Some(qualify) = &select.qualify {
1102 children.push(&qualify.this);
1103 }
1104 if let Some(order_by) = &select.order_by {
1106 for ord in &order_by.expressions {
1107 children.push(&ord.this);
1108 }
1109 }
1110 if let Some(limit) = &select.limit {
1112 children.push(&limit.this);
1113 }
1114 if let Some(offset) = &select.offset {
1116 children.push(&offset.this);
1117 }
1118 }
1119 Expression::And(bin)
1120 | Expression::Or(bin)
1121 | Expression::Add(bin)
1122 | Expression::Sub(bin)
1123 | Expression::Mul(bin)
1124 | Expression::Div(bin)
1125 | Expression::Mod(bin)
1126 | Expression::Eq(bin)
1127 | Expression::Neq(bin)
1128 | Expression::Lt(bin)
1129 | Expression::Lte(bin)
1130 | Expression::Gt(bin)
1131 | Expression::Gte(bin)
1132 | Expression::BitwiseAnd(bin)
1133 | Expression::BitwiseOr(bin)
1134 | Expression::BitwiseXor(bin)
1135 | Expression::Concat(bin) => {
1136 children.push(&bin.left);
1137 children.push(&bin.right);
1138 }
1139 Expression::Like(like) | Expression::ILike(like) => {
1140 children.push(&like.left);
1141 children.push(&like.right);
1142 if let Some(escape) = &like.escape {
1143 children.push(escape);
1144 }
1145 }
1146 Expression::Not(un) | Expression::Neg(un) | Expression::BitwiseNot(un) => {
1147 children.push(&un.this);
1148 }
1149 Expression::Function(func) => {
1150 for arg in &func.args {
1151 children.push(arg);
1152 }
1153 }
1154 Expression::AggregateFunction(agg) => {
1155 for arg in &agg.args {
1156 children.push(arg);
1157 }
1158 }
1159 Expression::WindowFunction(wf) => {
1160 children.push(&wf.this);
1161 for e in &wf.over.partition_by {
1162 children.push(e);
1163 }
1164 for e in &wf.over.order_by {
1165 children.push(&e.this);
1166 }
1167 }
1168 Expression::Alias(alias) => {
1169 children.push(&alias.this);
1170 }
1171 Expression::Case(case) => {
1172 if let Some(operand) = &case.operand {
1173 children.push(operand);
1174 }
1175 for (when_expr, then_expr) in &case.whens {
1176 children.push(when_expr);
1177 children.push(then_expr);
1178 }
1179 if let Some(else_clause) = &case.else_ {
1180 children.push(else_clause);
1181 }
1182 }
1183 Expression::Paren(paren) => {
1184 children.push(&paren.this);
1185 }
1186 Expression::Ordered(ord) => {
1187 children.push(&ord.this);
1188 }
1189 Expression::In(in_expr) => {
1190 children.push(&in_expr.this);
1191 for e in &in_expr.expressions {
1192 children.push(e);
1193 }
1194 }
1196 Expression::Between(between) => {
1197 children.push(&between.this);
1198 children.push(&between.low);
1199 children.push(&between.high);
1200 }
1201 Expression::IsNull(is_null) => {
1202 children.push(&is_null.this);
1203 }
1204 Expression::Cast(cast) => {
1205 children.push(&cast.this);
1206 }
1207 Expression::Extract(extract) => {
1208 children.push(&extract.this);
1209 }
1210 Expression::Coalesce(coalesce) => {
1211 for e in &coalesce.expressions {
1212 children.push(e);
1213 }
1214 }
1215 Expression::NullIf(nullif) => {
1216 children.push(&nullif.this);
1217 children.push(&nullif.expression);
1218 }
1219 Expression::Table(_table) => {
1220 }
1223 Expression::TryCatch(try_catch) => {
1224 for stmt in &try_catch.try_body {
1225 children.push(stmt);
1226 }
1227 if let Some(catch_body) = &try_catch.catch_body {
1228 for stmt in catch_body {
1229 children.push(stmt);
1230 }
1231 }
1232 }
1233 Expression::Column(_) | Expression::Literal(_) | Expression::Identifier(_) => {
1234 }
1236 Expression::Subquery(_) | Expression::Exists(_) => {}
1238 _ => {
1239 children.extend(expr.children());
1243 }
1244 }
1245
1246 children
1247 }
1248}
1249
1250impl<'a> Iterator for WalkInScopeIter<'a> {
1251 type Item = &'a Expression;
1252
1253 fn next(&mut self) -> Option<Self::Item> {
1254 let expr = if self.bfs {
1255 self.queue.pop_front()?
1256 } else {
1257 self.queue.pop_back()?
1258 };
1259
1260 let children = self.get_children(expr);
1262
1263 if self.bfs {
1264 for child in children {
1265 if !self.should_stop_at(child, false) {
1266 self.queue.push_back(child);
1267 }
1268 }
1269 } else {
1270 for child in children.into_iter().rev() {
1271 if !self.should_stop_at(child, false) {
1272 self.queue.push_back(child);
1273 }
1274 }
1275 }
1276
1277 Some(expr)
1278 }
1279}
1280
1281pub fn find_in_scope<'a, F>(
1293 expression: &'a Expression,
1294 predicate: F,
1295 bfs: bool,
1296) -> Option<&'a Expression>
1297where
1298 F: Fn(&Expression) -> bool,
1299{
1300 walk_in_scope(expression, bfs).find(|e| predicate(e))
1301}
1302
1303pub fn find_all_in_scope<'a, F>(
1315 expression: &'a Expression,
1316 predicate: F,
1317 bfs: bool,
1318) -> Vec<&'a Expression>
1319where
1320 F: Fn(&Expression) -> bool,
1321{
1322 walk_in_scope(expression, bfs)
1323 .filter(|e| predicate(e))
1324 .collect()
1325}
1326
1327pub fn traverse_scope(expression: &Expression) -> Vec<Scope> {
1337 match expression {
1338 Expression::Select(_)
1339 | Expression::Union(_)
1340 | Expression::Intersect(_)
1341 | Expression::Except(_)
1342 | Expression::Prepare(_)
1343 | Expression::CreateTable(_) => {
1344 let root = build_scope(expression);
1345 root.traverse().into_iter().cloned().collect()
1346 }
1347 _ => Vec::new(),
1348 }
1349}
1350
1351#[cfg(test)]
1352mod tests {
1353 use super::*;
1354 use crate::parser::Parser;
1355
1356 fn parse_and_build_scope(sql: &str) -> Scope {
1357 let ast = Parser::parse_sql(sql).expect("Failed to parse SQL");
1358 build_scope(&ast[0])
1359 }
1360
1361 #[test]
1362 fn test_simple_select_scope() {
1363 let mut scope = parse_and_build_scope("SELECT a, b FROM t");
1364
1365 assert!(scope.is_root());
1366 assert!(!scope.can_be_correlated);
1367 assert!(scope.sources.contains_key("t"));
1368
1369 let columns = scope.columns();
1370 assert_eq!(columns.len(), 2);
1371 }
1372
1373 #[test]
1374 fn test_derived_table_scope() {
1375 let mut scope = parse_and_build_scope("SELECT x.a FROM (SELECT a FROM t) AS x");
1376
1377 assert!(scope.sources.contains_key("x"));
1378 assert_eq!(scope.derived_table_scopes.len(), 1);
1379
1380 let derived = &mut scope.derived_table_scopes[0];
1381 assert!(derived.is_derived_table());
1382 assert!(derived.sources.contains_key("t"));
1383 }
1384
1385 #[test]
1386 fn test_subquery_collection_respects_relation_boundaries() {
1387 let scope = parse_and_build_scope(
1388 "SELECT t.a FROM t JOIN (SELECT a FROM s) ON t.a = 1 \
1389 WHERE EXISTS (SELECT 1 FROM u) ORDER BY (SELECT MAX(a) FROM v)",
1390 );
1391 assert_eq!(scope.derived_table_scopes.len(), 1);
1392 assert_eq!(scope.subquery_scopes.len(), 2);
1393 let scope = parse_and_build_scope(
1394 "SELECT t.a FROM t JOIN s ON EXISTS (SELECT 1 FROM u WHERE u.a = t.a)",
1395 );
1396 assert_eq!(scope.subquery_scopes.len(), 1);
1397 assert!(scope.subquery_scopes[0].sources.contains_key("u"));
1398 }
1399
1400 #[test]
1401 fn test_non_correlated_subquery() {
1402 let mut scope = parse_and_build_scope("SELECT * FROM t WHERE EXISTS (SELECT b FROM s)");
1403
1404 assert_eq!(scope.subquery_scopes.len(), 1);
1405
1406 let subquery = &mut scope.subquery_scopes[0];
1407 assert!(subquery.is_subquery());
1408 assert!(subquery.can_be_correlated);
1409
1410 assert!(subquery.sources.contains_key("s"));
1412 assert!(!subquery.is_correlated_subquery());
1413 }
1414
1415 #[test]
1416 fn test_correlated_subquery() {
1417 let mut scope =
1418 parse_and_build_scope("SELECT * FROM t WHERE EXISTS (SELECT b FROM s WHERE s.x = t.y)");
1419
1420 assert_eq!(scope.subquery_scopes.len(), 1);
1421
1422 let subquery = &mut scope.subquery_scopes[0];
1423 assert!(subquery.is_subquery());
1424 assert!(subquery.can_be_correlated);
1425
1426 let external = subquery.external_columns();
1428 assert!(!external.is_empty());
1429 assert!(external.iter().any(|c| c.table.as_deref() == Some("t")));
1430 assert!(subquery.is_correlated_subquery());
1431 }
1432
1433 #[test]
1434 fn test_cte_scope() {
1435 let scope = parse_and_build_scope("WITH cte AS (SELECT a FROM t) SELECT * FROM cte");
1436
1437 assert_eq!(scope.cte_scopes.len(), 1);
1438 assert!(scope.cte_sources.contains_key("cte"));
1439
1440 let cte = &scope.cte_scopes[0];
1441 assert!(cte.is_cte());
1442 }
1443
1444 #[test]
1445 fn test_multiple_sources() {
1446 let scope = parse_and_build_scope("SELECT t.a, s.b FROM t JOIN s ON t.id = s.id");
1447
1448 assert!(scope.sources.contains_key("t"));
1449 assert!(scope.sources.contains_key("s"));
1450 assert_eq!(scope.sources.len(), 2);
1451 }
1452
1453 #[test]
1454 fn test_aliased_table() {
1455 let scope = parse_and_build_scope("SELECT x.a FROM t AS x");
1456
1457 assert!(scope.sources.contains_key("x"));
1459 assert!(!scope.sources.contains_key("t"));
1460 }
1461
1462 #[test]
1463 fn test_local_columns() {
1464 let mut scope = parse_and_build_scope("SELECT t.a, t.b, s.c FROM t JOIN s ON t.id = s.id");
1465
1466 let local = scope.local_columns();
1467 assert_eq!(local.len(), 5);
1470 assert!(local.iter().all(|c| c.table.is_some()));
1471 }
1472
1473 #[test]
1474 fn test_columns_include_join_on_clause_references() {
1475 let mut scope = parse_and_build_scope(
1476 "SELECT o.total FROM orders o JOIN customers c ON c.id = o.customer_id",
1477 );
1478
1479 let cols: Vec<String> = scope
1480 .columns()
1481 .iter()
1482 .map(|c| match &c.table {
1483 Some(t) => format!("{}.{}", t, c.name),
1484 None => c.name.clone(),
1485 })
1486 .collect();
1487
1488 assert!(cols.contains(&"o.total".to_string()));
1489 assert!(cols.contains(&"c.id".to_string()));
1490 assert!(cols.contains(&"o.customer_id".to_string()));
1491 }
1492
1493 #[test]
1494 fn test_unqualified_columns() {
1495 let mut scope = parse_and_build_scope("SELECT a, b, t.c FROM t");
1496
1497 let unqualified = scope.unqualified_columns();
1498 assert_eq!(unqualified.len(), 2);
1500 assert!(unqualified.iter().all(|c| c.table.is_none()));
1501 }
1502
1503 #[test]
1504 fn test_source_columns() {
1505 let mut scope = parse_and_build_scope("SELECT t.a, t.b, s.c FROM t JOIN s ON t.id = s.id");
1506
1507 let t_cols = scope.source_columns("t");
1508 assert!(t_cols.len() >= 2);
1510 assert!(t_cols.iter().all(|c| c.table.as_deref() == Some("t")));
1511
1512 let s_cols = scope.source_columns("s");
1513 assert!(s_cols.len() >= 1);
1515 assert!(s_cols.iter().all(|c| c.table.as_deref() == Some("s")));
1516 }
1517
1518 #[test]
1519 fn test_rename_source() {
1520 let mut scope = parse_and_build_scope("SELECT a FROM t");
1521
1522 assert!(scope.sources.contains_key("t"));
1523 scope.rename_source("t", "new_name".to_string());
1524 assert!(!scope.sources.contains_key("t"));
1525 assert!(scope.sources.contains_key("new_name"));
1526 }
1527
1528 #[test]
1529 fn test_remove_source() {
1530 let mut scope = parse_and_build_scope("SELECT a FROM t");
1531
1532 assert!(scope.sources.contains_key("t"));
1533 scope.remove_source("t");
1534 assert!(!scope.sources.contains_key("t"));
1535 }
1536
1537 #[test]
1538 fn test_walk_in_scope() {
1539 let ast = Parser::parse_sql("SELECT a, b FROM t WHERE a > 1").expect("Failed to parse");
1540 let expr = &ast[0];
1541
1542 let walked: Vec<_> = walk_in_scope(expr, true).collect();
1544 assert!(!walked.is_empty());
1545
1546 assert!(walked.iter().any(|e| matches!(e, Expression::Select(_))));
1548 assert!(walked.iter().any(|e| matches!(e, Expression::Column(_))));
1550 }
1551
1552 #[test]
1553 fn test_find_in_scope() {
1554 let ast = Parser::parse_sql("SELECT a, b FROM t WHERE a > 1").expect("Failed to parse");
1555 let expr = &ast[0];
1556
1557 let found = find_in_scope(expr, |e| matches!(e, Expression::Column(_)), true);
1559 assert!(found.is_some());
1560 assert!(matches!(found.unwrap(), Expression::Column(_)));
1561 }
1562
1563 #[test]
1564 fn test_find_all_in_scope() {
1565 let ast = Parser::parse_sql("SELECT a, b, c FROM t").expect("Failed to parse");
1566 let expr = &ast[0];
1567
1568 let found = find_all_in_scope(expr, |e| matches!(e, Expression::Column(_)), true);
1570 assert_eq!(found.len(), 3);
1571 }
1572
1573 #[test]
1574 fn test_traverse_scope() {
1575 let ast =
1576 Parser::parse_sql("SELECT a FROM (SELECT b FROM t) AS x").expect("Failed to parse");
1577 let expr = &ast[0];
1578
1579 let scopes = traverse_scope(expr);
1580 assert!(!scopes.is_empty());
1583 assert!(scopes.iter().any(|s| s.is_root()));
1585 }
1586
1587 #[test]
1588 fn test_branch_with_options() {
1589 let ast = Parser::parse_sql("SELECT a FROM t").expect("Failed to parse");
1590 let scope = build_scope(&ast[0]);
1591
1592 let child = scope.branch_with_options(
1593 ast[0].clone(),
1594 ScopeType::Subquery, None,
1596 None,
1597 Some(vec!["col1".to_string(), "col2".to_string()]),
1598 );
1599
1600 assert_eq!(child.outer_columns, vec!["col1", "col2"]);
1601 assert!(child.can_be_correlated); }
1603
1604 #[test]
1605 fn test_is_udtf() {
1606 let ast = Parser::parse_sql("SELECT a FROM t").expect("Failed to parse");
1607 let scope = Scope::new(ast[0].clone());
1608 assert!(!scope.is_udtf());
1609
1610 let root = build_scope(&ast[0]);
1611 let udtf_scope = root.branch(ast[0].clone(), ScopeType::Udtf);
1612 assert!(udtf_scope.is_udtf());
1613 }
1614
1615 #[test]
1616 fn test_is_union() {
1617 let scope = parse_and_build_scope("SELECT a FROM t UNION SELECT b FROM s");
1618
1619 assert!(scope.is_root());
1620 assert_eq!(scope.union_scopes.len(), 2);
1621 assert!(scope.union_scopes[0].is_union());
1623 assert!(scope.union_scopes[1].is_union());
1624 }
1625
1626 #[test]
1627 fn test_union_output_columns() {
1628 let scope = parse_and_build_scope(
1629 "SELECT id, name FROM customers UNION ALL SELECT id, name FROM employees",
1630 );
1631 assert_eq!(scope.output_columns(), vec!["id", "name"]);
1632 }
1633
1634 #[test]
1635 fn test_clear_cache() {
1636 let mut scope = parse_and_build_scope("SELECT t.a FROM t");
1637
1638 let _ = scope.columns();
1640 assert!(scope.columns_cache.is_some());
1641
1642 scope.clear_cache();
1644 assert!(scope.columns_cache.is_none());
1645 assert!(scope.external_columns_cache.is_none());
1646 }
1647
1648 #[test]
1649 fn test_scope_traverse() {
1650 let scope = parse_and_build_scope(
1651 "WITH cte AS (SELECT a FROM t) SELECT * FROM cte WHERE EXISTS (SELECT b FROM s)",
1652 );
1653
1654 let traversed = scope.traverse();
1655 assert!(traversed.len() >= 3);
1657 }
1658
1659 #[test]
1660 fn test_create_table_as_select_scope() {
1661 let scope = parse_and_build_scope("CREATE TABLE out_table AS SELECT 1 AS id FROM src");
1663 assert!(
1664 scope.sources.contains_key("src"),
1665 "CTAS scope should contain the FROM table"
1666 );
1667 assert!(
1668 !scope.sources.contains_key("out_table"),
1669 "CTAS target table should not be treated as a source"
1670 );
1671
1672 let scope = parse_and_build_scope(
1674 "CREATE TABLE out_table AS SELECT a.id FROM foo AS a JOIN bar AS b ON a.id = b.id",
1675 );
1676 assert!(scope.sources.contains_key("a"));
1677 assert!(scope.sources.contains_key("b"));
1678 assert!(
1679 !scope.sources.contains_key("out_table"),
1680 "CTAS target table should not be treated as a source"
1681 );
1682
1683 let scope = parse_and_build_scope(
1685 "CREATE TABLE out_table AS WITH cte AS (SELECT 1 AS id FROM src) SELECT * FROM cte",
1686 );
1687 assert!(
1688 scope.sources.contains_key("cte"),
1689 "CTAS with CTE should resolve CTE as source"
1690 );
1691 assert!(
1692 !scope.sources.contains_key("out_table"),
1693 "CTAS target table should not be treated as a source"
1694 );
1695 assert_eq!(scope.cte_scopes.len(), 1);
1696 }
1697
1698 #[test]
1699 fn test_create_table_as_select_traverse() {
1700 let ast = Parser::parse_sql("CREATE TABLE t AS SELECT a FROM src").unwrap();
1701 let scopes = traverse_scope(&ast[0]);
1702 assert!(
1703 !scopes.is_empty(),
1704 "traverse_scope should return scopes for CTAS"
1705 );
1706 }
1707}