Skip to main content

polyglot_sql/
traversal.rs

1//! Tree traversal utilities for SQL expression ASTs.
2//!
3//! This module provides read-only traversal, search, and transformation utilities
4//! for the [`Expression`] tree produced by the parser. Because Rust's ownership
5//! model does not allow parent pointers inside the AST, parent information is
6//! tracked externally via [`TreeContext`] (built on demand).
7//!
8//! # Traversal
9//!
10//! Two iterator types are provided:
11//! - [`DfsIter`] -- depth-first (pre-order) traversal using a stack. Visits a node
12//!   before its children. Good for top-down analysis and early termination.
13//! - [`BfsIter`] -- breadth-first (level-order) traversal using a queue. Visits all
14//!   nodes at depth N before any node at depth N+1. Good for level-aware analysis.
15//!
16//! Both are available through the [`ExpressionWalk`] trait methods [`dfs`](ExpressionWalk::dfs)
17//! and [`bfs`](ExpressionWalk::bfs).
18//!
19//! # Searching
20//!
21//! The [`ExpressionWalk`] trait also provides convenience methods for finding expressions:
22//! [`find`](ExpressionWalk::find), [`find_all`](ExpressionWalk::find_all),
23//! [`contains`](ExpressionWalk::contains), and [`count`](ExpressionWalk::count).
24//! Common predicates are available as free functions: [`is_column`], [`is_literal`],
25//! [`is_function`], [`is_aggregate`], [`is_window_function`], [`is_subquery`], and
26//! [`is_select`].
27//!
28//! # Transformation
29//!
30//! The [`transform`] and [`transform_map`] functions perform bottom-up (post-order)
31//! tree rewrites, delegating to [`transform_recursive`](crate::dialects::transform_recursive).
32//! The [`ExpressionWalk::transform_owned`] method provides the same capability as
33//! an owned method on `Expression`.
34//!
35//! Based on traversal patterns from `sqlglot/expressions.py`.
36
37#![cfg_attr(
38    not(any(feature = "ast-tools", feature = "generate", feature = "semantic")),
39    allow(dead_code)
40)]
41
42use crate::expressions::{Expression, TableRef};
43use std::collections::{HashMap, VecDeque};
44
45/// Unique identifier for expression nodes during traversal
46pub type NodeId = usize;
47
48/// Information about a node's parent relationship
49#[derive(Debug, Clone)]
50pub struct ParentInfo {
51    /// The NodeId of the parent (None for root)
52    pub parent_id: Option<NodeId>,
53    /// Which argument/field in the parent this node occupies
54    pub arg_key: String,
55    /// Index if the node is part of a list (e.g., expressions in SELECT)
56    pub index: Option<usize>,
57}
58
59/// External parent-tracking context for an expression tree.
60///
61/// Since Rust's ownership model does not allow intrusive parent pointers in the AST,
62/// `TreeContext` provides an on-demand side-table that maps each node (identified by
63/// a [`NodeId`]) to its [`ParentInfo`] (parent node, field name, and list index).
64///
65/// Build a context from any expression root with [`TreeContext::build`], then query
66/// parent relationships with [`get`](TreeContext::get), ancestry chains with
67/// [`ancestors_of`](TreeContext::ancestors_of), or tree depth with
68/// [`depth_of`](TreeContext::depth_of).
69///
70/// This is useful when analysis requires upward navigation (e.g., determining whether
71/// a column reference appears inside a WHERE clause or a JOIN condition).
72#[derive(Debug, Default)]
73pub struct TreeContext {
74    /// Map from NodeId to parent information
75    nodes: HashMap<NodeId, ParentInfo>,
76    /// Counter for generating NodeIds
77    next_id: NodeId,
78    /// Stack for tracking current path during traversal
79    path: Vec<(NodeId, String, Option<usize>)>,
80}
81
82impl TreeContext {
83    /// Create a new empty tree context
84    pub fn new() -> Self {
85        Self::default()
86    }
87
88    /// Build context from an expression tree
89    pub fn build(root: &Expression) -> Self {
90        let mut ctx = Self::new();
91        ctx.visit_expr(root);
92        ctx
93    }
94
95    /// Visit an expression and record parent information
96    fn visit_expr(&mut self, expr: &Expression) -> NodeId {
97        let id = self.next_id;
98        self.next_id += 1;
99
100        // Record parent info based on current path
101        let parent_info = if let Some((parent_id, arg_key, index)) = self.path.last() {
102            ParentInfo {
103                parent_id: Some(*parent_id),
104                arg_key: arg_key.clone(),
105                index: *index,
106            }
107        } else {
108            ParentInfo {
109                parent_id: None,
110                arg_key: String::new(),
111                index: None,
112            }
113        };
114        self.nodes.insert(id, parent_info);
115
116        // Visit children
117        for (key, child) in iter_children(expr) {
118            self.path.push((id, key.to_string(), None));
119            self.visit_expr(child);
120            self.path.pop();
121        }
122
123        // Visit children in lists
124        for (key, children) in iter_children_lists(expr) {
125            for (idx, child) in children.iter().enumerate() {
126                self.path.push((id, key.to_string(), Some(idx)));
127                self.visit_expr(child);
128                self.path.pop();
129            }
130        }
131
132        id
133    }
134
135    /// Get parent info for a node
136    pub fn get(&self, id: NodeId) -> Option<&ParentInfo> {
137        self.nodes.get(&id)
138    }
139
140    /// Get the depth of a node (0 for root)
141    pub fn depth_of(&self, id: NodeId) -> usize {
142        let mut depth = 0;
143        let mut current = id;
144        while let Some(info) = self.nodes.get(&current) {
145            if let Some(parent_id) = info.parent_id {
146                depth += 1;
147                current = parent_id;
148            } else {
149                break;
150            }
151        }
152        depth
153    }
154
155    /// Get ancestors of a node (parent, grandparent, etc.)
156    pub fn ancestors_of(&self, id: NodeId) -> Vec<NodeId> {
157        let mut ancestors = Vec::new();
158        let mut current = id;
159        while let Some(info) = self.nodes.get(&current) {
160            if let Some(parent_id) = info.parent_id {
161                ancestors.push(parent_id);
162                current = parent_id;
163            } else {
164                break;
165            }
166        }
167        ancestors
168    }
169}
170
171/// Iterate over single-child fields of an expression
172///
173/// Returns an iterator of (field_name, &Expression) pairs.
174fn iter_children(expr: &Expression) -> Vec<(&'static str, &Expression)> {
175    let mut children = Vec::new();
176
177    match expr {
178        Expression::Select(s) => {
179            if let Some(from) = &s.from {
180                for source in &from.expressions {
181                    children.push(("from", source));
182                }
183            }
184            for join in &s.joins {
185                children.push(("join_this", &join.this));
186                if let Some(on) = &join.on {
187                    children.push(("join_on", on));
188                }
189                if let Some(match_condition) = &join.match_condition {
190                    children.push(("join_match_condition", match_condition));
191                }
192                for pivot in &join.pivots {
193                    children.push(("join_pivot", pivot));
194                }
195            }
196            for lateral_view in &s.lateral_views {
197                children.push(("lateral_view", &lateral_view.this));
198            }
199            if let Some(prewhere) = &s.prewhere {
200                children.push(("prewhere", prewhere));
201            }
202            if let Some(where_clause) = &s.where_clause {
203                children.push(("where", &where_clause.this));
204            }
205            if let Some(group_by) = &s.group_by {
206                for e in &group_by.expressions {
207                    children.push(("group_by", e));
208                }
209            }
210            if let Some(having) = &s.having {
211                children.push(("having", &having.this));
212            }
213            if let Some(qualify) = &s.qualify {
214                children.push(("qualify", &qualify.this));
215            }
216            if let Some(order_by) = &s.order_by {
217                for ordered in &order_by.expressions {
218                    children.push(("order_by", &ordered.this));
219                }
220            }
221            if let Some(distribute_by) = &s.distribute_by {
222                for e in &distribute_by.expressions {
223                    children.push(("distribute_by", e));
224                }
225            }
226            if let Some(cluster_by) = &s.cluster_by {
227                for ordered in &cluster_by.expressions {
228                    children.push(("cluster_by", &ordered.this));
229                }
230            }
231            if let Some(sort_by) = &s.sort_by {
232                for ordered in &sort_by.expressions {
233                    children.push(("sort_by", &ordered.this));
234                }
235            }
236            if let Some(limit) = &s.limit {
237                children.push(("limit", &limit.this));
238            }
239            if let Some(offset) = &s.offset {
240                children.push(("offset", &offset.this));
241            }
242            if let Some(limit_by) = &s.limit_by {
243                for e in limit_by {
244                    children.push(("limit_by", e));
245                }
246            }
247            if let Some(fetch) = &s.fetch {
248                if let Some(count) = &fetch.count {
249                    children.push(("fetch", count));
250                }
251            }
252            if let Some(top) = &s.top {
253                children.push(("top", &top.this));
254            }
255            if let Some(with) = &s.with {
256                for cte in &with.ctes {
257                    children.push(("with_cte", &cte.this));
258                }
259                if let Some(search) = &with.search {
260                    children.push(("with_search", search));
261                }
262            }
263            if let Some(sample) = &s.sample {
264                children.push(("sample_size", &sample.size));
265                if let Some(seed) = &sample.seed {
266                    children.push(("sample_seed", seed));
267                }
268                if let Some(offset) = &sample.offset {
269                    children.push(("sample_offset", offset));
270                }
271                if let Some(bucket_numerator) = &sample.bucket_numerator {
272                    children.push(("sample_bucket_numerator", bucket_numerator));
273                }
274                if let Some(bucket_denominator) = &sample.bucket_denominator {
275                    children.push(("sample_bucket_denominator", bucket_denominator));
276                }
277                if let Some(bucket_field) = &sample.bucket_field {
278                    children.push(("sample_bucket_field", bucket_field));
279                }
280            }
281            if let Some(connect) = &s.connect {
282                if let Some(start) = &connect.start {
283                    children.push(("connect_start", start));
284                }
285                children.push(("connect", &connect.connect));
286            }
287            if let Some(into) = &s.into {
288                children.push(("into", &into.this));
289            }
290            for lock in &s.locks {
291                for e in &lock.expressions {
292                    children.push(("lock_expression", e));
293                }
294                if let Some(wait) = &lock.wait {
295                    children.push(("lock_wait", wait));
296                }
297                if let Some(key) = &lock.key {
298                    children.push(("lock_key", key));
299                }
300                if let Some(update) = &lock.update {
301                    children.push(("lock_update", update));
302                }
303            }
304            for e in &s.for_xml {
305                children.push(("for_xml", e));
306            }
307        }
308        Expression::With(with) => {
309            for cte in &with.ctes {
310                children.push(("cte", &cte.this));
311            }
312            if let Some(search) = &with.search {
313                children.push(("search", search));
314            }
315        }
316        Expression::Cte(cte) => {
317            children.push(("this", &cte.this));
318        }
319        Expression::Insert(insert) => {
320            if let Some(query) = &insert.query {
321                children.push(("query", query));
322            }
323            if let Some(with) = &insert.with {
324                for cte in &with.ctes {
325                    children.push(("with_cte", &cte.this));
326                }
327                if let Some(search) = &with.search {
328                    children.push(("with_search", search));
329                }
330            }
331            if let Some(on_conflict) = &insert.on_conflict {
332                children.push(("on_conflict", on_conflict));
333            }
334            if let Some(replace_where) = &insert.replace_where {
335                children.push(("replace_where", replace_where));
336            }
337            if let Some(source) = &insert.source {
338                children.push(("source", source));
339            }
340            if let Some(function_target) = &insert.function_target {
341                children.push(("function_target", function_target));
342            }
343            if let Some(partition_by) = &insert.partition_by {
344                children.push(("partition_by", partition_by));
345            }
346            if let Some(output) = &insert.output {
347                for column in &output.columns {
348                    children.push(("output_column", column));
349                }
350                if let Some(into_table) = &output.into_table {
351                    children.push(("output_into_table", into_table));
352                }
353            }
354            for row in &insert.values {
355                for value in row {
356                    children.push(("value", value));
357                }
358            }
359            for (_, value) in &insert.partition {
360                if let Some(value) = value {
361                    children.push(("partition_value", value));
362                }
363            }
364            for returning in &insert.returning {
365                children.push(("returning", returning));
366            }
367            for setting in &insert.settings {
368                children.push(("setting", setting));
369            }
370        }
371        Expression::Update(update) => {
372            if let Some(from_clause) = &update.from_clause {
373                for source in &from_clause.expressions {
374                    children.push(("from", source));
375                }
376            }
377            for join in &update.table_joins {
378                children.push(("table_join_this", &join.this));
379                if let Some(on) = &join.on {
380                    children.push(("table_join_on", on));
381                }
382            }
383            for join in &update.from_joins {
384                children.push(("from_join_this", &join.this));
385                if let Some(on) = &join.on {
386                    children.push(("from_join_on", on));
387                }
388            }
389            for (_, value) in &update.set {
390                children.push(("set_value", value));
391            }
392            if let Some(where_clause) = &update.where_clause {
393                children.push(("where", &where_clause.this));
394            }
395            if let Some(output) = &update.output {
396                for column in &output.columns {
397                    children.push(("output_column", column));
398                }
399                if let Some(into_table) = &output.into_table {
400                    children.push(("output_into_table", into_table));
401                }
402            }
403            if let Some(with) = &update.with {
404                for cte in &with.ctes {
405                    children.push(("with_cte", &cte.this));
406                }
407                if let Some(search) = &with.search {
408                    children.push(("with_search", search));
409                }
410            }
411            if let Some(limit) = &update.limit {
412                children.push(("limit", limit));
413            }
414            if let Some(order_by) = &update.order_by {
415                for ordered in &order_by.expressions {
416                    children.push(("order_by", &ordered.this));
417                }
418            }
419            for returning in &update.returning {
420                children.push(("returning", returning));
421            }
422        }
423        Expression::Delete(delete) => {
424            if let Some(with) = &delete.with {
425                for cte in &with.ctes {
426                    children.push(("with_cte", &cte.this));
427                }
428                if let Some(search) = &with.search {
429                    children.push(("with_search", search));
430                }
431            }
432            if let Some(where_clause) = &delete.where_clause {
433                children.push(("where", &where_clause.this));
434            }
435            if let Some(output) = &delete.output {
436                for column in &output.columns {
437                    children.push(("output_column", column));
438                }
439                if let Some(into_table) = &output.into_table {
440                    children.push(("output_into_table", into_table));
441                }
442            }
443            if let Some(limit) = &delete.limit {
444                children.push(("limit", limit));
445            }
446            if let Some(order_by) = &delete.order_by {
447                for ordered in &order_by.expressions {
448                    children.push(("order_by", &ordered.this));
449                }
450            }
451            for returning in &delete.returning {
452                children.push(("returning", returning));
453            }
454            for join in &delete.joins {
455                children.push(("join_this", &join.this));
456                if let Some(on) = &join.on {
457                    children.push(("join_on", on));
458                }
459            }
460        }
461        Expression::Join(join) => {
462            children.push(("this", &join.this));
463            if let Some(on) = &join.on {
464                children.push(("on", on));
465            }
466            if let Some(match_condition) = &join.match_condition {
467                children.push(("match_condition", match_condition));
468            }
469            for pivot in &join.pivots {
470                children.push(("pivot", pivot));
471            }
472        }
473        Expression::Alias(a) => {
474            children.push(("this", &a.this));
475        }
476        Expression::Cast(c) => {
477            children.push(("this", &c.this));
478        }
479        Expression::Not(u) | Expression::Neg(u) | Expression::BitwiseNot(u) => {
480            children.push(("this", &u.this));
481        }
482        Expression::Paren(p) => {
483            children.push(("this", &p.this));
484        }
485        Expression::IsNull(i) => {
486            children.push(("this", &i.this));
487        }
488        Expression::Exists(e) => {
489            children.push(("this", &e.this));
490        }
491        Expression::Subquery(s) => {
492            children.push(("this", &s.this));
493        }
494        Expression::Where(w) => {
495            children.push(("this", &w.this));
496        }
497        Expression::Having(h) => {
498            children.push(("this", &h.this));
499        }
500        Expression::Qualify(q) => {
501            children.push(("this", &q.this));
502        }
503        Expression::And(op)
504        | Expression::Or(op)
505        | Expression::Add(op)
506        | Expression::Sub(op)
507        | Expression::Mul(op)
508        | Expression::Div(op)
509        | Expression::Mod(op)
510        | Expression::Eq(op)
511        | Expression::Neq(op)
512        | Expression::Lt(op)
513        | Expression::Lte(op)
514        | Expression::Gt(op)
515        | Expression::Gte(op)
516        | Expression::BitwiseAnd(op)
517        | Expression::BitwiseOr(op)
518        | Expression::BitwiseXor(op)
519        | Expression::Concat(op) => {
520            children.push(("left", &op.left));
521            children.push(("right", &op.right));
522        }
523        Expression::Like(op) | Expression::ILike(op) => {
524            children.push(("left", &op.left));
525            children.push(("right", &op.right));
526        }
527        Expression::Between(b) => {
528            children.push(("this", &b.this));
529            children.push(("low", &b.low));
530            children.push(("high", &b.high));
531        }
532        Expression::In(i) => {
533            children.push(("this", &i.this));
534            if let Some(ref query) = i.query {
535                children.push(("query", query));
536            }
537            if let Some(ref unnest) = i.unnest {
538                children.push(("unnest", unnest));
539            }
540        }
541        Expression::Case(c) => {
542            if let Some(ref operand) = &c.operand {
543                children.push(("operand", operand));
544            }
545        }
546        Expression::WindowFunction(wf) => {
547            children.push(("this", &wf.this));
548        }
549        Expression::Union(u) => {
550            children.push(("left", &u.left));
551            children.push(("right", &u.right));
552            if let Some(with) = &u.with {
553                for cte in &with.ctes {
554                    children.push(("with_cte", &cte.this));
555                }
556                if let Some(search) = &with.search {
557                    children.push(("with_search", search));
558                }
559            }
560            if let Some(order_by) = &u.order_by {
561                for ordered in &order_by.expressions {
562                    children.push(("order_by", &ordered.this));
563                }
564            }
565            if let Some(limit) = &u.limit {
566                children.push(("limit", limit));
567            }
568            if let Some(offset) = &u.offset {
569                children.push(("offset", offset));
570            }
571            if let Some(distribute_by) = &u.distribute_by {
572                for e in &distribute_by.expressions {
573                    children.push(("distribute_by", e));
574                }
575            }
576            if let Some(sort_by) = &u.sort_by {
577                for ordered in &sort_by.expressions {
578                    children.push(("sort_by", &ordered.this));
579                }
580            }
581            if let Some(cluster_by) = &u.cluster_by {
582                for ordered in &cluster_by.expressions {
583                    children.push(("cluster_by", &ordered.this));
584                }
585            }
586            for e in &u.on_columns {
587                children.push(("on_column", e));
588            }
589        }
590        Expression::Intersect(i) => {
591            children.push(("left", &i.left));
592            children.push(("right", &i.right));
593            if let Some(with) = &i.with {
594                for cte in &with.ctes {
595                    children.push(("with_cte", &cte.this));
596                }
597                if let Some(search) = &with.search {
598                    children.push(("with_search", search));
599                }
600            }
601            if let Some(order_by) = &i.order_by {
602                for ordered in &order_by.expressions {
603                    children.push(("order_by", &ordered.this));
604                }
605            }
606            if let Some(limit) = &i.limit {
607                children.push(("limit", limit));
608            }
609            if let Some(offset) = &i.offset {
610                children.push(("offset", offset));
611            }
612            if let Some(distribute_by) = &i.distribute_by {
613                for e in &distribute_by.expressions {
614                    children.push(("distribute_by", e));
615                }
616            }
617            if let Some(sort_by) = &i.sort_by {
618                for ordered in &sort_by.expressions {
619                    children.push(("sort_by", &ordered.this));
620                }
621            }
622            if let Some(cluster_by) = &i.cluster_by {
623                for ordered in &cluster_by.expressions {
624                    children.push(("cluster_by", &ordered.this));
625                }
626            }
627            for e in &i.on_columns {
628                children.push(("on_column", e));
629            }
630        }
631        Expression::Except(e) => {
632            children.push(("left", &e.left));
633            children.push(("right", &e.right));
634            if let Some(with) = &e.with {
635                for cte in &with.ctes {
636                    children.push(("with_cte", &cte.this));
637                }
638                if let Some(search) = &with.search {
639                    children.push(("with_search", search));
640                }
641            }
642            if let Some(order_by) = &e.order_by {
643                for ordered in &order_by.expressions {
644                    children.push(("order_by", &ordered.this));
645                }
646            }
647            if let Some(limit) = &e.limit {
648                children.push(("limit", limit));
649            }
650            if let Some(offset) = &e.offset {
651                children.push(("offset", offset));
652            }
653            if let Some(distribute_by) = &e.distribute_by {
654                for expr in &distribute_by.expressions {
655                    children.push(("distribute_by", expr));
656                }
657            }
658            if let Some(sort_by) = &e.sort_by {
659                for ordered in &sort_by.expressions {
660                    children.push(("sort_by", &ordered.this));
661                }
662            }
663            if let Some(cluster_by) = &e.cluster_by {
664                for ordered in &cluster_by.expressions {
665                    children.push(("cluster_by", &ordered.this));
666                }
667            }
668            for expr in &e.on_columns {
669                children.push(("on_column", expr));
670            }
671        }
672        Expression::Merge(merge) => {
673            children.push(("this", &merge.this));
674            children.push(("using", &merge.using));
675            if let Some(on) = &merge.on {
676                children.push(("on", on));
677            }
678            if let Some(using_cond) = &merge.using_cond {
679                children.push(("using_cond", using_cond));
680            }
681            if let Some(whens) = &merge.whens {
682                children.push(("whens", whens));
683            }
684            if let Some(with_) = &merge.with_ {
685                children.push(("with_", with_));
686            }
687            if let Some(returning) = &merge.returning {
688                children.push(("returning", returning));
689            }
690        }
691        Expression::Any(q) | Expression::All(q) => {
692            children.push(("this", &q.this));
693            children.push(("subquery", &q.subquery));
694        }
695        Expression::Ordered(o) => {
696            children.push(("this", &o.this));
697        }
698        Expression::Interval(i) => {
699            if let Some(ref this) = i.this {
700                children.push(("this", this));
701            }
702        }
703        Expression::Describe(d) => {
704            children.push(("target", &d.target));
705        }
706        Expression::CreateTask(ct) => {
707            children.push(("body", &ct.body));
708        }
709        Expression::Prepare(prepare) => {
710            children.push(("statement", &prepare.statement));
711        }
712        Expression::Execute(exec) => {
713            children.push(("this", &exec.this));
714            for argument in &exec.arguments {
715                children.push(("argument", argument));
716            }
717            for parameter in &exec.parameters {
718                children.push(("parameter", &parameter.value));
719            }
720        }
721        Expression::Analyze(a) => {
722            if let Some(this) = &a.this {
723                children.push(("this", this));
724            }
725            if let Some(expr) = &a.expression {
726                children.push(("expression", expr));
727            }
728        }
729        _ => {}
730    }
731
732    children
733}
734
735/// Iterate over list-child fields of an expression
736///
737/// Returns an iterator of (field_name, &[Expression]) pairs.
738fn iter_children_lists(expr: &Expression) -> Vec<(&'static str, &[Expression])> {
739    let mut lists = Vec::new();
740
741    match expr {
742        Expression::Select(s) => lists.push(("expressions", s.expressions.as_slice())),
743        Expression::Function(f) => {
744            lists.push(("args", f.args.as_slice()));
745        }
746        Expression::AggregateFunction(f) => {
747            lists.push(("args", f.args.as_slice()));
748        }
749        Expression::From(f) => {
750            lists.push(("expressions", f.expressions.as_slice()));
751        }
752        Expression::GroupBy(g) => {
753            lists.push(("expressions", g.expressions.as_slice()));
754        }
755        // OrderBy.expressions is Vec<Ordered>, not Vec<Expression>
756        // We handle Ordered items via iter_children
757        Expression::In(i) => {
758            lists.push(("expressions", i.expressions.as_slice()));
759        }
760        Expression::Array(a) => {
761            lists.push(("expressions", a.expressions.as_slice()));
762        }
763        Expression::Tuple(t) => {
764            lists.push(("expressions", t.expressions.as_slice()));
765        }
766        Expression::TryCatch(try_catch) => {
767            lists.push(("try_body", try_catch.try_body.as_slice()));
768            if let Some(catch_body) = &try_catch.catch_body {
769                lists.push(("catch_body", catch_body.as_slice()));
770            }
771        }
772        // Values.expressions is Vec<Tuple>, handle specially
773        Expression::Coalesce(c) => {
774            lists.push(("expressions", c.expressions.as_slice()));
775        }
776        Expression::Greatest(g) | Expression::Least(g) => {
777            lists.push(("expressions", g.expressions.as_slice()));
778        }
779        _ => {}
780    }
781
782    lists
783}
784
785/// Pre-order depth-first iterator over an expression tree.
786///
787/// Visits each node before its children, using a stack-based approach. This means
788/// the root is yielded first, followed by the entire left subtree (recursively),
789/// then the right subtree. For a binary expression `a + b`, the iteration order
790/// is: `Add`, `a`, `b`.
791///
792/// Created via [`ExpressionWalk::dfs`] or [`DfsIter::new`].
793pub struct DfsIter<'a> {
794    stack: Vec<&'a Expression>,
795}
796
797impl<'a> DfsIter<'a> {
798    /// Create a new DFS iterator starting from the given expression
799    pub fn new(root: &'a Expression) -> Self {
800        Self { stack: vec![root] }
801    }
802}
803
804impl<'a> Iterator for DfsIter<'a> {
805    type Item = &'a Expression;
806
807    fn next(&mut self) -> Option<Self::Item> {
808        let expr = self.stack.pop()?;
809
810        // Add children in reverse order so they come out in forward order
811        let children: Vec<_> = iter_children(expr).into_iter().map(|(_, e)| e).collect();
812        for child in children.into_iter().rev() {
813            self.stack.push(child);
814        }
815
816        let lists: Vec<_> = iter_children_lists(expr)
817            .into_iter()
818            .flat_map(|(_, es)| es.iter())
819            .collect();
820        for child in lists.into_iter().rev() {
821            self.stack.push(child);
822        }
823
824        Some(expr)
825    }
826}
827
828/// Level-order breadth-first iterator over an expression tree.
829///
830/// Visits all nodes at depth N before any node at depth N+1, using a queue-based
831/// approach. For a tree `(a + b) = c`, the iteration order is: `Eq` (depth 0),
832/// `Add`, `c` (depth 1), `a`, `b` (depth 2).
833///
834/// Created via [`ExpressionWalk::bfs`] or [`BfsIter::new`].
835pub struct BfsIter<'a> {
836    queue: VecDeque<&'a Expression>,
837}
838
839impl<'a> BfsIter<'a> {
840    /// Create a new BFS iterator starting from the given expression
841    pub fn new(root: &'a Expression) -> Self {
842        let mut queue = VecDeque::new();
843        queue.push_back(root);
844        Self { queue }
845    }
846}
847
848impl<'a> Iterator for BfsIter<'a> {
849    type Item = &'a Expression;
850
851    fn next(&mut self) -> Option<Self::Item> {
852        let expr = self.queue.pop_front()?;
853
854        // Add children to queue
855        for (_, child) in iter_children(expr) {
856            self.queue.push_back(child);
857        }
858
859        for (_, children) in iter_children_lists(expr) {
860            for child in children {
861                self.queue.push_back(child);
862            }
863        }
864
865        Some(expr)
866    }
867}
868
869/// Extension trait that adds traversal and search methods to [`Expression`].
870///
871/// This trait is implemented for `Expression` and provides a fluent API for
872/// iterating, searching, measuring, and transforming expression trees without
873/// needing to import the iterator types directly.
874pub trait ExpressionWalk {
875    /// Returns a depth-first (pre-order) iterator over this expression and all descendants.
876    ///
877    /// The root node is yielded first, then its children are visited recursively
878    /// from left to right.
879    fn dfs(&self) -> DfsIter<'_>;
880
881    /// Returns a breadth-first (level-order) iterator over this expression and all descendants.
882    ///
883    /// All nodes at depth N are yielded before any node at depth N+1.
884    fn bfs(&self) -> BfsIter<'_>;
885
886    /// Finds the first expression matching `predicate` in depth-first order.
887    ///
888    /// Returns `None` if no descendant (including this node) matches.
889    fn find<F>(&self, predicate: F) -> Option<&Expression>
890    where
891        F: Fn(&Expression) -> bool;
892
893    /// Collects all expressions matching `predicate` in depth-first order.
894    ///
895    /// Returns an empty vector if no descendants match.
896    fn find_all<F>(&self, predicate: F) -> Vec<&Expression>
897    where
898        F: Fn(&Expression) -> bool;
899
900    /// Returns `true` if this node or any descendant matches `predicate`.
901    fn contains<F>(&self, predicate: F) -> bool
902    where
903        F: Fn(&Expression) -> bool;
904
905    /// Counts how many nodes (including this one) match `predicate`.
906    fn count<F>(&self, predicate: F) -> usize
907    where
908        F: Fn(&Expression) -> bool;
909
910    /// Returns direct child expressions of this node.
911    ///
912    /// Collects all single-child fields and list-child fields into a flat vector
913    /// of references. Leaf nodes return an empty vector.
914    fn children(&self) -> Vec<&Expression>;
915
916    /// Returns the maximum depth of the expression tree rooted at this node.
917    ///
918    /// A leaf node has depth 0, a node whose deepest child is a leaf has depth 1, etc.
919    fn tree_depth(&self) -> usize;
920
921    /// Transforms this expression tree bottom-up using the given function (owned variant).
922    ///
923    /// Children are transformed first, then `fun` is called on the resulting node.
924    /// Return `Ok(None)` from `fun` to replace a node with `NULL`.
925    /// Return `Ok(Some(expr))` to substitute the node with `expr`.
926    #[cfg(any(
927        feature = "transpile",
928        feature = "ast-tools",
929        feature = "generate",
930        feature = "semantic"
931    ))]
932    fn transform_owned<F>(self, fun: F) -> crate::Result<Expression>
933    where
934        F: Fn(Expression) -> crate::Result<Option<Expression>>,
935        Self: Sized;
936}
937
938impl ExpressionWalk for Expression {
939    fn dfs(&self) -> DfsIter<'_> {
940        DfsIter::new(self)
941    }
942
943    fn bfs(&self) -> BfsIter<'_> {
944        BfsIter::new(self)
945    }
946
947    fn find<F>(&self, predicate: F) -> Option<&Expression>
948    where
949        F: Fn(&Expression) -> bool,
950    {
951        self.dfs().find(|e| predicate(e))
952    }
953
954    fn find_all<F>(&self, predicate: F) -> Vec<&Expression>
955    where
956        F: Fn(&Expression) -> bool,
957    {
958        self.dfs().filter(|e| predicate(e)).collect()
959    }
960
961    fn contains<F>(&self, predicate: F) -> bool
962    where
963        F: Fn(&Expression) -> bool,
964    {
965        self.dfs().any(|e| predicate(e))
966    }
967
968    fn count<F>(&self, predicate: F) -> usize
969    where
970        F: Fn(&Expression) -> bool,
971    {
972        self.dfs().filter(|e| predicate(e)).count()
973    }
974
975    fn children(&self) -> Vec<&Expression> {
976        let mut result: Vec<&Expression> = Vec::new();
977        for (_, child) in iter_children(self) {
978            result.push(child);
979        }
980        for (_, children_list) in iter_children_lists(self) {
981            for child in children_list {
982                result.push(child);
983            }
984        }
985        result
986    }
987
988    fn tree_depth(&self) -> usize {
989        let mut max_depth = 0;
990
991        for (_, child) in iter_children(self) {
992            let child_depth = child.tree_depth();
993            if child_depth + 1 > max_depth {
994                max_depth = child_depth + 1;
995            }
996        }
997
998        for (_, children) in iter_children_lists(self) {
999            for child in children {
1000                let child_depth = child.tree_depth();
1001                if child_depth + 1 > max_depth {
1002                    max_depth = child_depth + 1;
1003                }
1004            }
1005        }
1006
1007        max_depth
1008    }
1009
1010    #[cfg(any(
1011        feature = "transpile",
1012        feature = "ast-tools",
1013        feature = "generate",
1014        feature = "semantic"
1015    ))]
1016    fn transform_owned<F>(self, fun: F) -> crate::Result<Expression>
1017    where
1018        F: Fn(Expression) -> crate::Result<Option<Expression>>,
1019    {
1020        transform(self, &fun)
1021    }
1022}
1023
1024/// Transforms an expression tree bottom-up, with optional node removal.
1025///
1026/// Recursively transforms all children first, then applies `fun` to the resulting node.
1027/// If `fun` returns `Ok(None)`, the node is replaced with an `Expression::Null`.
1028/// If `fun` returns `Ok(Some(expr))`, the node is replaced with `expr`.
1029///
1030/// This is the primary transformation entry point when callers need the ability to
1031/// "delete" nodes by returning `None`.
1032///
1033/// # Example
1034///
1035/// ```rust,ignore
1036/// use polyglot_sql::traversal::transform;
1037///
1038/// // Remove all Paren wrapper nodes from a tree
1039/// let result = transform(expr, &|e| match e {
1040///     Expression::Paren(p) => Ok(Some(p.this)),
1041///     other => Ok(Some(other)),
1042/// })?;
1043/// ```
1044#[cfg(any(
1045    feature = "transpile",
1046    feature = "ast-tools",
1047    feature = "generate",
1048    feature = "semantic"
1049))]
1050pub fn transform<F>(expr: Expression, fun: &F) -> crate::Result<Expression>
1051where
1052    F: Fn(Expression) -> crate::Result<Option<Expression>>,
1053{
1054    crate::dialects::transform_recursive(expr, &|e| match fun(e)? {
1055        Some(transformed) => Ok(transformed),
1056        None => Ok(Expression::Null(crate::expressions::Null)),
1057    })
1058}
1059
1060/// Transforms an expression tree bottom-up without node removal.
1061///
1062/// Like [`transform`], but `fun` returns an `Expression` directly rather than
1063/// `Option<Expression>`, so nodes cannot be deleted. This is a convenience wrapper
1064/// for the common case where every node is mapped to exactly one output node.
1065///
1066/// # Example
1067///
1068/// ```rust,ignore
1069/// use polyglot_sql::traversal::transform_map;
1070///
1071/// // Uppercase all column names in a tree
1072/// let result = transform_map(expr, &|e| match e {
1073///     Expression::Column(mut c) => {
1074///         c.name.name = c.name.name.to_uppercase();
1075///         Ok(Expression::Column(c))
1076///     }
1077///     other => Ok(other),
1078/// })?;
1079/// ```
1080#[cfg(any(
1081    feature = "transpile",
1082    feature = "ast-tools",
1083    feature = "generate",
1084    feature = "semantic"
1085))]
1086pub fn transform_map<F>(expr: Expression, fun: &F) -> crate::Result<Expression>
1087where
1088    F: Fn(Expression) -> crate::Result<Expression>,
1089{
1090    crate::dialects::transform_recursive(expr, fun)
1091}
1092
1093// ---------------------------------------------------------------------------
1094// Common expression predicates
1095// ---------------------------------------------------------------------------
1096// These free functions are intended for use with the search methods on
1097// `ExpressionWalk` (e.g., `expr.find(is_column)`, `expr.contains(is_aggregate)`).
1098
1099/// Returns `true` if `expr` is a column reference ([`Expression::Column`]).
1100pub fn is_column(expr: &Expression) -> bool {
1101    matches!(expr, Expression::Column(_))
1102}
1103
1104/// Returns `true` if `expr` is a literal value (number, string, boolean, or NULL).
1105pub fn is_literal(expr: &Expression) -> bool {
1106    matches!(
1107        expr,
1108        Expression::Literal(_) | Expression::Boolean(_) | Expression::Null(_)
1109    )
1110}
1111
1112/// Returns `true` if `expr` is a function call (regular or aggregate).
1113pub fn is_function(expr: &Expression) -> bool {
1114    matches!(
1115        expr,
1116        Expression::Function(_) | Expression::AggregateFunction(_)
1117    )
1118}
1119
1120/// Returns `true` if `expr` is a subquery ([`Expression::Subquery`]).
1121pub fn is_subquery(expr: &Expression) -> bool {
1122    matches!(expr, Expression::Subquery(_))
1123}
1124
1125/// Returns `true` if `expr` is a SELECT statement ([`Expression::Select`]).
1126pub fn is_select(expr: &Expression) -> bool {
1127    matches!(expr, Expression::Select(_))
1128}
1129
1130/// Returns `true` if `expr` is an aggregate function.
1131pub fn is_aggregate(expr: &Expression) -> bool {
1132    matches!(
1133        expr,
1134        Expression::AggregateFunction(_)
1135            | Expression::Count(_)
1136            | Expression::Sum(_)
1137            | Expression::Avg(_)
1138            | Expression::Min(_)
1139            | Expression::Max(_)
1140            | Expression::GroupConcat(_)
1141            | Expression::StringAgg(_)
1142            | Expression::ListAgg(_)
1143            | Expression::CountIf(_)
1144            | Expression::SumIf(_)
1145    )
1146}
1147
1148/// Returns `true` if `expr` is a window function ([`Expression::WindowFunction`]).
1149pub fn is_window_function(expr: &Expression) -> bool {
1150    matches!(expr, Expression::WindowFunction(_))
1151}
1152
1153/// Collects all column references ([`Expression::Column`]) from the expression tree.
1154///
1155/// Performs a depth-first search and returns references to every column node found.
1156pub fn get_columns(expr: &Expression) -> Vec<&Expression> {
1157    expr.find_all(is_column)
1158}
1159
1160/// Collects all table references ([`Expression::Table`]) from the expression tree.
1161///
1162/// Performs a depth-first search and returns references to every table node found.
1163///
1164/// Note: DML target tables (`Insert.table`, `Update.table`, `Delete.table`) are
1165/// stored as `TableRef` struct fields, not as `Expression::Table` nodes, so they
1166/// are not reachable via tree traversal. Use [`get_all_tables`] to include those.
1167pub fn get_tables(expr: &Expression) -> Vec<&Expression> {
1168    expr.find_all(|e| matches!(e, Expression::Table(_)))
1169}
1170
1171/// Collects **all** referenced tables from the expression tree, including DML
1172/// target tables that are stored as `TableRef` struct fields and are therefore
1173/// not reachable through normal tree traversal.
1174///
1175/// Returns owned `Expression::Table` values. This is the comprehensive version
1176/// of [`get_tables`] — use it when you need to discover every table referenced
1177/// in a statement, including inside CTE bodies containing INSERT/UPDATE/DELETE.
1178pub fn get_all_tables(expr: &Expression) -> Vec<Expression> {
1179    use std::collections::HashSet;
1180
1181    let mut seen = HashSet::new();
1182    let mut result = Vec::new();
1183
1184    // First: collect all Expression::Table nodes found via DFS.
1185    for node in expr.dfs() {
1186        if let Expression::Table(t) = node {
1187            let qname = table_ref_qualified_name(t);
1188            if seen.insert(qname) {
1189                result.push(node.clone());
1190            }
1191        }
1192
1193        // Also extract DML target TableRef fields not reachable via iter_children.
1194        let refs: Vec<&TableRef> = match node {
1195            Expression::Insert(ins) => vec![&ins.table],
1196            Expression::Update(upd) => {
1197                let mut v = vec![&upd.table];
1198                v.extend(upd.extra_tables.iter());
1199                v
1200            }
1201            Expression::Delete(del) => {
1202                let mut v = vec![&del.table];
1203                v.extend(del.using.iter());
1204                v
1205            }
1206            _ => continue,
1207        };
1208        for tref in refs {
1209            if tref.name.name.is_empty() {
1210                continue;
1211            }
1212            let qname = table_ref_qualified_name(tref);
1213            if seen.insert(qname) {
1214                result.push(Expression::Table(Box::new(tref.clone())));
1215            }
1216        }
1217    }
1218
1219    result
1220}
1221
1222/// Build a qualified name string from a TableRef for deduplication purposes.
1223fn table_ref_qualified_name(t: &TableRef) -> String {
1224    let mut name = String::new();
1225    if let Some(ref cat) = t.catalog {
1226        name.push_str(&cat.name);
1227        name.push('.');
1228    }
1229    if let Some(ref schema) = t.schema {
1230        name.push_str(&schema.name);
1231        name.push('.');
1232    }
1233    name.push_str(&t.name.name);
1234    name
1235}
1236
1237/// Extracts the underlying [`Expression::Table`] from a MERGE field that may
1238/// be a bare `Table`, an `Alias` wrapping a `Table`, or an `Identifier`.
1239/// Returns `None` if the expression doesn't contain a recognisable table.
1240fn unwrap_merge_table(expr: &Expression) -> Option<&Expression> {
1241    match expr {
1242        Expression::Table(_) => Some(expr),
1243        Expression::Alias(alias) => match &alias.this {
1244            Expression::Table(_) => Some(&alias.this),
1245            _ => None,
1246        },
1247        _ => None,
1248    }
1249}
1250
1251/// Returns the target table of a MERGE statement (the `Merge.this` field),
1252/// unwrapping any alias wrapper to yield the underlying [`Expression::Table`].
1253///
1254/// Returns `None` if `expr` is not a `Merge` or the target isn't a recognisable table.
1255pub fn get_merge_target(expr: &Expression) -> Option<&Expression> {
1256    match expr {
1257        Expression::Merge(m) => unwrap_merge_table(&m.this),
1258        _ => None,
1259    }
1260}
1261
1262/// Returns the source table of a MERGE statement (the `Merge.using` field),
1263/// unwrapping any alias wrapper to yield the underlying [`Expression::Table`].
1264///
1265/// Returns `None` if `expr` is not a `Merge`, the source isn't a recognisable
1266/// table (e.g. it's a subquery), or the source is otherwise unresolvable.
1267pub fn get_merge_source(expr: &Expression) -> Option<&Expression> {
1268    match expr {
1269        Expression::Merge(m) => unwrap_merge_table(&m.using),
1270        _ => None,
1271    }
1272}
1273
1274/// Returns `true` if the expression tree contains any aggregate function calls.
1275pub fn contains_aggregate(expr: &Expression) -> bool {
1276    expr.contains(is_aggregate)
1277}
1278
1279/// Returns `true` if the expression tree contains any window function calls.
1280pub fn contains_window_function(expr: &Expression) -> bool {
1281    expr.contains(is_window_function)
1282}
1283
1284/// Returns `true` if the expression tree contains any subquery nodes.
1285pub fn contains_subquery(expr: &Expression) -> bool {
1286    expr.contains(is_subquery)
1287}
1288
1289// ---------------------------------------------------------------------------
1290// Extended type predicates
1291// ---------------------------------------------------------------------------
1292
1293/// Macro for generating simple type-predicate functions.
1294macro_rules! is_type {
1295    ($name:ident, $($variant:pat),+ $(,)?) => {
1296        /// Returns `true` if `expr` matches the expected AST variant(s).
1297        pub fn $name(expr: &Expression) -> bool {
1298            matches!(expr, $($variant)|+)
1299        }
1300    };
1301}
1302
1303// Query
1304is_type!(is_insert, Expression::Insert(_));
1305is_type!(is_update, Expression::Update(_));
1306is_type!(is_delete, Expression::Delete(_));
1307is_type!(is_merge, Expression::Merge(_));
1308is_type!(is_union, Expression::Union(_));
1309is_type!(is_intersect, Expression::Intersect(_));
1310is_type!(is_except, Expression::Except(_));
1311
1312// Identifiers & literals
1313is_type!(is_boolean, Expression::Boolean(_));
1314is_type!(is_null_literal, Expression::Null(_));
1315is_type!(is_star, Expression::Star(_));
1316is_type!(is_identifier, Expression::Identifier(_));
1317is_type!(is_table, Expression::Table(_));
1318
1319// Comparison
1320is_type!(is_eq, Expression::Eq(_));
1321is_type!(is_neq, Expression::Neq(_));
1322is_type!(is_lt, Expression::Lt(_));
1323is_type!(is_lte, Expression::Lte(_));
1324is_type!(is_gt, Expression::Gt(_));
1325is_type!(is_gte, Expression::Gte(_));
1326is_type!(is_like, Expression::Like(_));
1327is_type!(is_ilike, Expression::ILike(_));
1328
1329// Arithmetic
1330is_type!(is_add, Expression::Add(_));
1331is_type!(is_sub, Expression::Sub(_));
1332is_type!(is_mul, Expression::Mul(_));
1333is_type!(is_div, Expression::Div(_));
1334is_type!(is_mod, Expression::Mod(_));
1335is_type!(is_concat, Expression::Concat(_));
1336
1337// Logical
1338is_type!(is_and, Expression::And(_));
1339is_type!(is_or, Expression::Or(_));
1340is_type!(is_not, Expression::Not(_));
1341
1342// Predicates
1343is_type!(is_in, Expression::In(_));
1344is_type!(is_between, Expression::Between(_));
1345is_type!(is_is_null, Expression::IsNull(_));
1346is_type!(is_exists, Expression::Exists(_));
1347
1348// Functions
1349is_type!(is_count, Expression::Count(_));
1350is_type!(is_sum, Expression::Sum(_));
1351is_type!(is_avg, Expression::Avg(_));
1352is_type!(is_min_func, Expression::Min(_));
1353is_type!(is_max_func, Expression::Max(_));
1354is_type!(is_coalesce, Expression::Coalesce(_));
1355is_type!(is_null_if, Expression::NullIf(_));
1356is_type!(is_cast, Expression::Cast(_));
1357is_type!(is_try_cast, Expression::TryCast(_));
1358is_type!(is_safe_cast, Expression::SafeCast(_));
1359is_type!(is_case, Expression::Case(_));
1360
1361// Clauses
1362is_type!(is_from, Expression::From(_));
1363is_type!(is_join, Expression::Join(_));
1364is_type!(is_where, Expression::Where(_));
1365is_type!(is_group_by, Expression::GroupBy(_));
1366is_type!(is_having, Expression::Having(_));
1367is_type!(is_order_by, Expression::OrderBy(_));
1368is_type!(is_limit, Expression::Limit(_));
1369is_type!(is_offset, Expression::Offset(_));
1370is_type!(is_with, Expression::With(_));
1371is_type!(is_cte, Expression::Cte(_));
1372is_type!(is_alias, Expression::Alias(_));
1373is_type!(is_paren, Expression::Paren(_));
1374is_type!(is_ordered, Expression::Ordered(_));
1375
1376// DDL
1377is_type!(is_create_table, Expression::CreateTable(_));
1378is_type!(is_drop_table, Expression::DropTable(_));
1379is_type!(is_alter_table, Expression::AlterTable(_));
1380is_type!(is_create_index, Expression::CreateIndex(_));
1381is_type!(is_drop_index, Expression::DropIndex(_));
1382is_type!(is_create_view, Expression::CreateView(_));
1383is_type!(is_drop_view, Expression::DropView(_));
1384
1385// ---------------------------------------------------------------------------
1386// Composite predicates
1387// ---------------------------------------------------------------------------
1388
1389/// Returns `true` if `expr` is a query statement (SELECT, INSERT, UPDATE, DELETE, or MERGE).
1390pub fn is_query(expr: &Expression) -> bool {
1391    matches!(
1392        expr,
1393        Expression::Select(_)
1394            | Expression::Insert(_)
1395            | Expression::Update(_)
1396            | Expression::Delete(_)
1397            | Expression::Merge(_)
1398    )
1399}
1400
1401/// Returns `true` if `expr` is a set operation (UNION, INTERSECT, or EXCEPT).
1402pub fn is_set_operation(expr: &Expression) -> bool {
1403    matches!(
1404        expr,
1405        Expression::Union(_) | Expression::Intersect(_) | Expression::Except(_)
1406    )
1407}
1408
1409/// Returns `true` if `expr` is a comparison operator.
1410pub fn is_comparison(expr: &Expression) -> bool {
1411    matches!(
1412        expr,
1413        Expression::Eq(_)
1414            | Expression::Neq(_)
1415            | Expression::Lt(_)
1416            | Expression::Lte(_)
1417            | Expression::Gt(_)
1418            | Expression::Gte(_)
1419            | Expression::Like(_)
1420            | Expression::ILike(_)
1421    )
1422}
1423
1424/// Returns `true` if `expr` is an arithmetic operator.
1425pub fn is_arithmetic(expr: &Expression) -> bool {
1426    matches!(
1427        expr,
1428        Expression::Add(_)
1429            | Expression::Sub(_)
1430            | Expression::Mul(_)
1431            | Expression::Div(_)
1432            | Expression::Mod(_)
1433    )
1434}
1435
1436/// Returns `true` if `expr` is a logical operator (AND, OR, NOT).
1437pub fn is_logical(expr: &Expression) -> bool {
1438    matches!(
1439        expr,
1440        Expression::And(_) | Expression::Or(_) | Expression::Not(_)
1441    )
1442}
1443
1444/// Returns `true` if `expr` is a DDL statement.
1445pub fn is_ddl(expr: &Expression) -> bool {
1446    matches!(
1447        expr,
1448        Expression::CreateTable(_)
1449            | Expression::DropTable(_)
1450            | Expression::Undrop(_)
1451            | Expression::AlterTable(_)
1452            | Expression::CreateIndex(_)
1453            | Expression::DropIndex(_)
1454            | Expression::CreateView(_)
1455            | Expression::DropView(_)
1456            | Expression::AlterView(_)
1457            | Expression::CreateSchema(_)
1458            | Expression::DropSchema(_)
1459            | Expression::CreateDatabase(_)
1460            | Expression::DropDatabase(_)
1461            | Expression::CreateFunction(_)
1462            | Expression::DropFunction(_)
1463            | Expression::CreateProcedure(_)
1464            | Expression::DropProcedure(_)
1465            | Expression::CreateSequence(_)
1466            | Expression::CreateSynonym(_)
1467            | Expression::DropSequence(_)
1468            | Expression::AlterSequence(_)
1469            | Expression::CreateTrigger(_)
1470            | Expression::DropTrigger(_)
1471            | Expression::CreateType(_)
1472            | Expression::DropType(_)
1473    )
1474}
1475
1476/// Find the parent of `target` within the tree rooted at `root`.
1477///
1478/// Uses pointer identity ([`std::ptr::eq`]) — `target` must be a reference
1479/// obtained from the same tree (e.g., via [`ExpressionWalk::find`] or DFS iteration).
1480///
1481/// Returns `None` if `target` is the root itself or is not found in the tree.
1482pub fn find_parent<'a>(root: &'a Expression, target: &Expression) -> Option<&'a Expression> {
1483    fn search<'a>(node: &'a Expression, target: *const Expression) -> Option<&'a Expression> {
1484        for (_, child) in iter_children(node) {
1485            if std::ptr::eq(child, target) {
1486                return Some(node);
1487            }
1488            if let Some(found) = search(child, target) {
1489                return Some(found);
1490            }
1491        }
1492        for (_, children_list) in iter_children_lists(node) {
1493            for child in children_list {
1494                if std::ptr::eq(child, target) {
1495                    return Some(node);
1496                }
1497                if let Some(found) = search(child, target) {
1498                    return Some(found);
1499                }
1500            }
1501        }
1502        None
1503    }
1504
1505    search(root, target as *const Expression)
1506}
1507
1508/// Find the first ancestor of `target` matching `predicate`, walking from
1509/// parent toward root.
1510///
1511/// Uses pointer identity for target lookup. Returns `None` if no ancestor
1512/// matches or `target` is not found in the tree.
1513pub fn find_ancestor<'a, F>(
1514    root: &'a Expression,
1515    target: &Expression,
1516    predicate: F,
1517) -> Option<&'a Expression>
1518where
1519    F: Fn(&Expression) -> bool,
1520{
1521    // Build path from root to target
1522    fn build_path<'a>(
1523        node: &'a Expression,
1524        target: *const Expression,
1525        path: &mut Vec<&'a Expression>,
1526    ) -> bool {
1527        if std::ptr::eq(node, target) {
1528            return true;
1529        }
1530        path.push(node);
1531        for (_, child) in iter_children(node) {
1532            if build_path(child, target, path) {
1533                return true;
1534            }
1535        }
1536        for (_, children_list) in iter_children_lists(node) {
1537            for child in children_list {
1538                if build_path(child, target, path) {
1539                    return true;
1540                }
1541            }
1542        }
1543        path.pop();
1544        false
1545    }
1546
1547    let mut path = Vec::new();
1548    if !build_path(root, target as *const Expression, &mut path) {
1549        return None;
1550    }
1551
1552    // Walk path in reverse (parent first, then grandparent, etc.)
1553    for ancestor in path.iter().rev() {
1554        if predicate(ancestor) {
1555            return Some(ancestor);
1556        }
1557    }
1558    None
1559}
1560
1561#[cfg(test)]
1562mod tests {
1563    use super::*;
1564    use crate::expressions::{BinaryOp, Column, Identifier, Literal};
1565
1566    fn make_column(name: &str) -> Expression {
1567        Expression::boxed_column(Column {
1568            name: Identifier {
1569                name: name.to_string(),
1570                quoted: false,
1571                trailing_comments: vec![],
1572                span: None,
1573            },
1574            table: None,
1575            join_mark: false,
1576            trailing_comments: vec![],
1577            span: None,
1578            inferred_type: None,
1579        })
1580    }
1581
1582    fn make_literal(value: i64) -> Expression {
1583        Expression::Literal(Box::new(Literal::Number(value.to_string())))
1584    }
1585
1586    #[test]
1587    fn test_dfs_simple() {
1588        let left = make_column("a");
1589        let right = make_literal(1);
1590        let expr = Expression::Eq(Box::new(BinaryOp {
1591            left,
1592            right,
1593            left_comments: vec![],
1594            operator_comments: vec![],
1595            trailing_comments: vec![],
1596            inferred_type: None,
1597        }));
1598
1599        let nodes: Vec<_> = expr.dfs().collect();
1600        assert_eq!(nodes.len(), 3); // Eq, Column, Literal
1601        assert!(matches!(nodes[0], Expression::Eq(_)));
1602        assert!(matches!(nodes[1], Expression::Column(_)));
1603        assert!(matches!(nodes[2], Expression::Literal(_)));
1604    }
1605
1606    #[test]
1607    fn test_find() {
1608        let left = make_column("a");
1609        let right = make_literal(1);
1610        let expr = Expression::Eq(Box::new(BinaryOp {
1611            left,
1612            right,
1613            left_comments: vec![],
1614            operator_comments: vec![],
1615            trailing_comments: vec![],
1616            inferred_type: None,
1617        }));
1618
1619        let column = expr.find(is_column);
1620        assert!(column.is_some());
1621        assert!(matches!(column.unwrap(), Expression::Column(_)));
1622
1623        let literal = expr.find(is_literal);
1624        assert!(literal.is_some());
1625        assert!(matches!(literal.unwrap(), Expression::Literal(_)));
1626    }
1627
1628    #[test]
1629    fn test_find_all() {
1630        let col1 = make_column("a");
1631        let col2 = make_column("b");
1632        let expr = Expression::And(Box::new(BinaryOp {
1633            left: col1,
1634            right: col2,
1635            left_comments: vec![],
1636            operator_comments: vec![],
1637            trailing_comments: vec![],
1638            inferred_type: None,
1639        }));
1640
1641        let columns = expr.find_all(is_column);
1642        assert_eq!(columns.len(), 2);
1643    }
1644
1645    #[test]
1646    fn test_contains() {
1647        let col = make_column("a");
1648        let lit = make_literal(1);
1649        let expr = Expression::Eq(Box::new(BinaryOp {
1650            left: col,
1651            right: lit,
1652            left_comments: vec![],
1653            operator_comments: vec![],
1654            trailing_comments: vec![],
1655            inferred_type: None,
1656        }));
1657
1658        assert!(expr.contains(is_column));
1659        assert!(expr.contains(is_literal));
1660        assert!(!expr.contains(is_subquery));
1661    }
1662
1663    #[test]
1664    fn test_count() {
1665        let col1 = make_column("a");
1666        let col2 = make_column("b");
1667        let lit = make_literal(1);
1668
1669        let inner = Expression::Add(Box::new(BinaryOp {
1670            left: col2,
1671            right: lit,
1672            left_comments: vec![],
1673            operator_comments: vec![],
1674            trailing_comments: vec![],
1675            inferred_type: None,
1676        }));
1677
1678        let expr = Expression::Eq(Box::new(BinaryOp {
1679            left: col1,
1680            right: inner,
1681            left_comments: vec![],
1682            operator_comments: vec![],
1683            trailing_comments: vec![],
1684            inferred_type: None,
1685        }));
1686
1687        assert_eq!(expr.count(is_column), 2);
1688        assert_eq!(expr.count(is_literal), 1);
1689    }
1690
1691    #[test]
1692    fn test_tree_depth() {
1693        // Single node
1694        let lit = make_literal(1);
1695        assert_eq!(lit.tree_depth(), 0);
1696
1697        // One level
1698        let col = make_column("a");
1699        let expr = Expression::Eq(Box::new(BinaryOp {
1700            left: col,
1701            right: lit.clone(),
1702            left_comments: vec![],
1703            operator_comments: vec![],
1704            trailing_comments: vec![],
1705            inferred_type: None,
1706        }));
1707        assert_eq!(expr.tree_depth(), 1);
1708
1709        // Two levels
1710        let inner = Expression::Add(Box::new(BinaryOp {
1711            left: make_column("b"),
1712            right: lit,
1713            left_comments: vec![],
1714            operator_comments: vec![],
1715            trailing_comments: vec![],
1716            inferred_type: None,
1717        }));
1718        let outer = Expression::Eq(Box::new(BinaryOp {
1719            left: make_column("a"),
1720            right: inner,
1721            left_comments: vec![],
1722            operator_comments: vec![],
1723            trailing_comments: vec![],
1724            inferred_type: None,
1725        }));
1726        assert_eq!(outer.tree_depth(), 2);
1727    }
1728
1729    #[test]
1730    fn test_tree_context() {
1731        let col = make_column("a");
1732        let lit = make_literal(1);
1733        let expr = Expression::Eq(Box::new(BinaryOp {
1734            left: col,
1735            right: lit,
1736            left_comments: vec![],
1737            operator_comments: vec![],
1738            trailing_comments: vec![],
1739            inferred_type: None,
1740        }));
1741
1742        let ctx = TreeContext::build(&expr);
1743
1744        // Root has no parent
1745        let root_info = ctx.get(0).unwrap();
1746        assert!(root_info.parent_id.is_none());
1747
1748        // Children have root as parent
1749        let left_info = ctx.get(1).unwrap();
1750        assert_eq!(left_info.parent_id, Some(0));
1751        assert_eq!(left_info.arg_key, "left");
1752
1753        let right_info = ctx.get(2).unwrap();
1754        assert_eq!(right_info.parent_id, Some(0));
1755        assert_eq!(right_info.arg_key, "right");
1756    }
1757
1758    // -- Step 8: transform / transform_map tests --
1759
1760    #[test]
1761    fn test_transform_rename_columns() {
1762        let ast = crate::parser::Parser::parse_sql("SELECT a, b FROM t").unwrap();
1763        let expr = ast[0].clone();
1764        let result = super::transform_map(expr, &|e| {
1765            if let Expression::Column(ref c) = e {
1766                if c.name.name == "a" {
1767                    return Ok(Expression::boxed_column(Column {
1768                        name: Identifier::new("alpha"),
1769                        table: c.table.clone(),
1770                        join_mark: false,
1771                        trailing_comments: vec![],
1772                        span: None,
1773                        inferred_type: None,
1774                    }));
1775                }
1776            }
1777            Ok(e)
1778        })
1779        .unwrap();
1780        let sql = crate::generator::Generator::sql(&result).unwrap();
1781        assert!(sql.contains("alpha"), "Expected 'alpha' in: {}", sql);
1782        assert!(sql.contains("b"), "Expected 'b' in: {}", sql);
1783    }
1784
1785    #[test]
1786    fn test_transform_noop() {
1787        let ast = crate::parser::Parser::parse_sql("SELECT 1 + 2").unwrap();
1788        let expr = ast[0].clone();
1789        let result = super::transform_map(expr.clone(), &|e| Ok(e)).unwrap();
1790        let sql1 = crate::generator::Generator::sql(&expr).unwrap();
1791        let sql2 = crate::generator::Generator::sql(&result).unwrap();
1792        assert_eq!(sql1, sql2);
1793    }
1794
1795    #[test]
1796    fn test_transform_nested() {
1797        let ast = crate::parser::Parser::parse_sql("SELECT a + b FROM t").unwrap();
1798        let expr = ast[0].clone();
1799        let result = super::transform_map(expr, &|e| {
1800            if let Expression::Column(ref c) = e {
1801                return Ok(Expression::Literal(Box::new(Literal::Number(
1802                    if c.name.name == "a" { "1" } else { "2" }.to_string(),
1803                ))));
1804            }
1805            Ok(e)
1806        })
1807        .unwrap();
1808        let sql = crate::generator::Generator::sql(&result).unwrap();
1809        assert_eq!(sql, "SELECT 1 + 2 FROM t");
1810    }
1811
1812    #[test]
1813    fn test_transform_error() {
1814        let ast = crate::parser::Parser::parse_sql("SELECT a FROM t").unwrap();
1815        let expr = ast[0].clone();
1816        let result = super::transform_map(expr, &|e| {
1817            if let Expression::Column(ref c) = e {
1818                if c.name.name == "a" {
1819                    return Err(crate::error::Error::parse("test error", 0, 0, 0, 0));
1820                }
1821            }
1822            Ok(e)
1823        });
1824        assert!(result.is_err());
1825    }
1826
1827    #[test]
1828    fn test_transform_owned_trait() {
1829        let ast = crate::parser::Parser::parse_sql("SELECT x FROM t").unwrap();
1830        let expr = ast[0].clone();
1831        let result = expr.transform_owned(|e| Ok(Some(e))).unwrap();
1832        let sql = crate::generator::Generator::sql(&result).unwrap();
1833        assert_eq!(sql, "SELECT x FROM t");
1834    }
1835
1836    // -- children() tests --
1837
1838    #[test]
1839    fn test_children_leaf() {
1840        let lit = make_literal(1);
1841        assert_eq!(lit.children().len(), 0);
1842    }
1843
1844    #[test]
1845    fn test_children_binary_op() {
1846        let left = make_column("a");
1847        let right = make_literal(1);
1848        let expr = Expression::Eq(Box::new(BinaryOp {
1849            left,
1850            right,
1851            left_comments: vec![],
1852            operator_comments: vec![],
1853            trailing_comments: vec![],
1854            inferred_type: None,
1855        }));
1856        let children = expr.children();
1857        assert_eq!(children.len(), 2);
1858        assert!(matches!(children[0], Expression::Column(_)));
1859        assert!(matches!(children[1], Expression::Literal(_)));
1860    }
1861
1862    #[test]
1863    fn test_children_select() {
1864        let ast = crate::parser::Parser::parse_sql("SELECT a, b FROM t").unwrap();
1865        let expr = &ast[0];
1866        let children = expr.children();
1867        // Should include select list items (a, b)
1868        assert!(children.len() >= 2);
1869    }
1870
1871    #[test]
1872    fn test_children_select_includes_from_and_join_sources() {
1873        let ast = crate::parser::Parser::parse_sql(
1874            "SELECT u.id FROM users u JOIN orders o ON u.id = o.user_id",
1875        )
1876        .unwrap();
1877        let expr = &ast[0];
1878        let children = expr.children();
1879
1880        let table_names: Vec<&str> = children
1881            .iter()
1882            .filter_map(|e| match e {
1883                Expression::Table(t) => Some(t.name.name.as_str()),
1884                _ => None,
1885            })
1886            .collect();
1887
1888        assert!(table_names.contains(&"users"));
1889        assert!(table_names.contains(&"orders"));
1890    }
1891
1892    #[test]
1893    fn test_get_tables_includes_insert_query_sources() {
1894        let ast = crate::parser::Parser::parse_sql(
1895            "INSERT INTO dst (id) SELECT s.id FROM src s JOIN dim d ON s.id = d.id",
1896        )
1897        .unwrap();
1898        let expr = &ast[0];
1899        let tables = get_tables(expr);
1900        let names: Vec<&str> = tables
1901            .iter()
1902            .filter_map(|e| match e {
1903                Expression::Table(t) => Some(t.name.name.as_str()),
1904                _ => None,
1905            })
1906            .collect();
1907
1908        assert!(names.contains(&"src"));
1909        assert!(names.contains(&"dim"));
1910    }
1911
1912    // -- find_parent() tests --
1913
1914    #[test]
1915    fn test_find_parent_binary() {
1916        let left = make_column("a");
1917        let right = make_literal(1);
1918        let expr = Expression::Eq(Box::new(BinaryOp {
1919            left,
1920            right,
1921            left_comments: vec![],
1922            operator_comments: vec![],
1923            trailing_comments: vec![],
1924            inferred_type: None,
1925        }));
1926
1927        // Find the column child and get its parent
1928        let col = expr.find(is_column).unwrap();
1929        let parent = super::find_parent(&expr, col);
1930        assert!(parent.is_some());
1931        assert!(matches!(parent.unwrap(), Expression::Eq(_)));
1932    }
1933
1934    #[test]
1935    fn test_find_parent_root_has_none() {
1936        let lit = make_literal(1);
1937        let parent = super::find_parent(&lit, &lit);
1938        assert!(parent.is_none());
1939    }
1940
1941    // -- find_ancestor() tests --
1942
1943    #[test]
1944    fn test_find_ancestor_select() {
1945        let ast = crate::parser::Parser::parse_sql("SELECT a FROM t WHERE a > 1").unwrap();
1946        let expr = &ast[0];
1947
1948        // Find a column inside the WHERE clause
1949        let where_col = expr.dfs().find(|e| {
1950            if let Expression::Column(c) = e {
1951                c.name.name == "a"
1952            } else {
1953                false
1954            }
1955        });
1956        assert!(where_col.is_some());
1957
1958        // Find Select ancestor of that column
1959        let ancestor = super::find_ancestor(expr, where_col.unwrap(), is_select);
1960        assert!(ancestor.is_some());
1961        assert!(matches!(ancestor.unwrap(), Expression::Select(_)));
1962    }
1963
1964    #[test]
1965    fn test_find_ancestor_no_match() {
1966        let left = make_column("a");
1967        let right = make_literal(1);
1968        let expr = Expression::Eq(Box::new(BinaryOp {
1969            left,
1970            right,
1971            left_comments: vec![],
1972            operator_comments: vec![],
1973            trailing_comments: vec![],
1974            inferred_type: None,
1975        }));
1976
1977        let col = expr.find(is_column).unwrap();
1978        let ancestor = super::find_ancestor(&expr, col, is_select);
1979        assert!(ancestor.is_none());
1980    }
1981
1982    #[test]
1983    fn test_ancestors() {
1984        let col = make_column("a");
1985        let lit = make_literal(1);
1986        let inner = Expression::Add(Box::new(BinaryOp {
1987            left: col,
1988            right: lit,
1989            left_comments: vec![],
1990            operator_comments: vec![],
1991            trailing_comments: vec![],
1992            inferred_type: None,
1993        }));
1994        let outer = Expression::Eq(Box::new(BinaryOp {
1995            left: make_column("b"),
1996            right: inner,
1997            left_comments: vec![],
1998            operator_comments: vec![],
1999            trailing_comments: vec![],
2000            inferred_type: None,
2001        }));
2002
2003        let ctx = TreeContext::build(&outer);
2004
2005        // The inner Add's left child (column "a") should have ancestors
2006        // Node 0: Eq
2007        // Node 1: Column "b" (left of Eq)
2008        // Node 2: Add (right of Eq)
2009        // Node 3: Column "a" (left of Add)
2010        // Node 4: Literal (right of Add)
2011
2012        let ancestors = ctx.ancestors_of(3);
2013        assert_eq!(ancestors, vec![2, 0]); // Add, then Eq
2014    }
2015
2016    #[test]
2017    fn test_get_merge_target_and_source() {
2018        let dialect = crate::Dialect::get(crate::dialects::DialectType::Generic);
2019
2020        // MERGE with aliased target and source tables
2021        let sql = "MERGE INTO orders o USING customers c ON o.customer_id = c.id WHEN MATCHED THEN UPDATE SET amount = amount + 100";
2022        let exprs = dialect.parse(sql).unwrap();
2023        let expr = &exprs[0];
2024
2025        assert!(is_merge(expr));
2026        assert!(is_query(expr));
2027
2028        let target = get_merge_target(expr).expect("should find target table");
2029        assert!(matches!(target, Expression::Table(_)));
2030        if let Expression::Table(t) = target {
2031            assert_eq!(t.name.name, "orders");
2032        }
2033
2034        let source = get_merge_source(expr).expect("should find source table");
2035        assert!(matches!(source, Expression::Table(_)));
2036        if let Expression::Table(t) = source {
2037            assert_eq!(t.name.name, "customers");
2038        }
2039    }
2040
2041    #[test]
2042    fn test_get_merge_source_subquery_returns_none() {
2043        let dialect = crate::Dialect::get(crate::dialects::DialectType::Generic);
2044
2045        // MERGE with subquery source — get_merge_source should return None
2046        let sql = "MERGE INTO orders o USING (SELECT * FROM customers) c ON o.customer_id = c.id WHEN MATCHED THEN DELETE";
2047        let exprs = dialect.parse(sql).unwrap();
2048        let expr = &exprs[0];
2049
2050        assert!(get_merge_target(expr).is_some());
2051        assert!(get_merge_source(expr).is_none());
2052    }
2053
2054    #[test]
2055    fn test_get_merge_on_non_merge_returns_none() {
2056        let dialect = crate::Dialect::get(crate::dialects::DialectType::Generic);
2057        let exprs = dialect.parse("SELECT 1").unwrap();
2058        assert!(get_merge_target(&exprs[0]).is_none());
2059        assert!(get_merge_source(&exprs[0]).is_none());
2060    }
2061
2062    #[test]
2063    fn test_get_tables_finds_tables_inside_in_subquery() {
2064        let dialect = crate::Dialect::get(crate::dialects::DialectType::Generic);
2065        let sql = "SELECT id, name FROM customers WHERE id IN (SELECT customer_id FROM orders WHERE amount > 1000)";
2066        let exprs = dialect.parse(sql).unwrap();
2067        let tables = get_tables(&exprs[0]);
2068        let names: Vec<&str> = tables
2069            .iter()
2070            .filter_map(|e| {
2071                if let Expression::Table(t) = e {
2072                    Some(t.name.name.as_str())
2073                } else {
2074                    None
2075                }
2076            })
2077            .collect();
2078        assert!(names.contains(&"customers"), "should find outer table");
2079        assert!(names.contains(&"orders"), "should find subquery table");
2080    }
2081
2082    #[test]
2083    fn test_get_tables_finds_tables_inside_exists_subquery() {
2084        let dialect = crate::Dialect::get(crate::dialects::DialectType::Generic);
2085        let sql = "SELECT * FROM customers c WHERE EXISTS (SELECT 1 FROM orders o WHERE o.customer_id = c.id)";
2086        let exprs = dialect.parse(sql).unwrap();
2087        let tables = get_tables(&exprs[0]);
2088        let names: Vec<&str> = tables
2089            .iter()
2090            .filter_map(|e| {
2091                if let Expression::Table(t) = e {
2092                    Some(t.name.name.as_str())
2093                } else {
2094                    None
2095                }
2096            })
2097            .collect();
2098        assert!(names.contains(&"customers"), "should find outer table");
2099        assert!(
2100            names.contains(&"orders"),
2101            "should find EXISTS subquery table"
2102        );
2103    }
2104
2105    #[test]
2106    fn test_get_tables_finds_tables_in_correlated_subquery() {
2107        let dialect = crate::Dialect::get(crate::dialects::DialectType::TSQL);
2108        let sql = "SELECT id, name FROM customers WHERE id IN (SELECT customer_id FROM orders WHERE amount > 1000)";
2109        let exprs = dialect.parse(sql).unwrap();
2110        let tables = get_tables(&exprs[0]);
2111        let names: Vec<&str> = tables
2112            .iter()
2113            .filter_map(|e| {
2114                if let Expression::Table(t) = e {
2115                    Some(t.name.name.as_str())
2116                } else {
2117                    None
2118                }
2119            })
2120            .collect();
2121        assert!(
2122            names.contains(&"customers"),
2123            "TSQL: should find outer table"
2124        );
2125        assert!(
2126            names.contains(&"orders"),
2127            "TSQL: should find subquery table"
2128        );
2129    }
2130}