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            for (condition, result) in &c.whens {
546                children.push(("when", condition));
547                children.push(("then", result));
548            }
549            if let Some(ref else_) = c.else_ {
550                children.push(("else", else_));
551            }
552        }
553        Expression::WindowFunction(wf) => {
554            children.push(("this", &wf.this));
555        }
556        Expression::Union(u) => {
557            children.push(("left", &u.left));
558            children.push(("right", &u.right));
559            if let Some(with) = &u.with {
560                for cte in &with.ctes {
561                    children.push(("with_cte", &cte.this));
562                }
563                if let Some(search) = &with.search {
564                    children.push(("with_search", search));
565                }
566            }
567            if let Some(order_by) = &u.order_by {
568                for ordered in &order_by.expressions {
569                    children.push(("order_by", &ordered.this));
570                }
571            }
572            if let Some(limit) = &u.limit {
573                children.push(("limit", limit));
574            }
575            if let Some(offset) = &u.offset {
576                children.push(("offset", offset));
577            }
578            if let Some(distribute_by) = &u.distribute_by {
579                for e in &distribute_by.expressions {
580                    children.push(("distribute_by", e));
581                }
582            }
583            if let Some(sort_by) = &u.sort_by {
584                for ordered in &sort_by.expressions {
585                    children.push(("sort_by", &ordered.this));
586                }
587            }
588            if let Some(cluster_by) = &u.cluster_by {
589                for ordered in &cluster_by.expressions {
590                    children.push(("cluster_by", &ordered.this));
591                }
592            }
593            for e in &u.on_columns {
594                children.push(("on_column", e));
595            }
596        }
597        Expression::Intersect(i) => {
598            children.push(("left", &i.left));
599            children.push(("right", &i.right));
600            if let Some(with) = &i.with {
601                for cte in &with.ctes {
602                    children.push(("with_cte", &cte.this));
603                }
604                if let Some(search) = &with.search {
605                    children.push(("with_search", search));
606                }
607            }
608            if let Some(order_by) = &i.order_by {
609                for ordered in &order_by.expressions {
610                    children.push(("order_by", &ordered.this));
611                }
612            }
613            if let Some(limit) = &i.limit {
614                children.push(("limit", limit));
615            }
616            if let Some(offset) = &i.offset {
617                children.push(("offset", offset));
618            }
619            if let Some(distribute_by) = &i.distribute_by {
620                for e in &distribute_by.expressions {
621                    children.push(("distribute_by", e));
622                }
623            }
624            if let Some(sort_by) = &i.sort_by {
625                for ordered in &sort_by.expressions {
626                    children.push(("sort_by", &ordered.this));
627                }
628            }
629            if let Some(cluster_by) = &i.cluster_by {
630                for ordered in &cluster_by.expressions {
631                    children.push(("cluster_by", &ordered.this));
632                }
633            }
634            for e in &i.on_columns {
635                children.push(("on_column", e));
636            }
637        }
638        Expression::Except(e) => {
639            children.push(("left", &e.left));
640            children.push(("right", &e.right));
641            if let Some(with) = &e.with {
642                for cte in &with.ctes {
643                    children.push(("with_cte", &cte.this));
644                }
645                if let Some(search) = &with.search {
646                    children.push(("with_search", search));
647                }
648            }
649            if let Some(order_by) = &e.order_by {
650                for ordered in &order_by.expressions {
651                    children.push(("order_by", &ordered.this));
652                }
653            }
654            if let Some(limit) = &e.limit {
655                children.push(("limit", limit));
656            }
657            if let Some(offset) = &e.offset {
658                children.push(("offset", offset));
659            }
660            if let Some(distribute_by) = &e.distribute_by {
661                for expr in &distribute_by.expressions {
662                    children.push(("distribute_by", expr));
663                }
664            }
665            if let Some(sort_by) = &e.sort_by {
666                for ordered in &sort_by.expressions {
667                    children.push(("sort_by", &ordered.this));
668                }
669            }
670            if let Some(cluster_by) = &e.cluster_by {
671                for ordered in &cluster_by.expressions {
672                    children.push(("cluster_by", &ordered.this));
673                }
674            }
675            for expr in &e.on_columns {
676                children.push(("on_column", expr));
677            }
678        }
679        Expression::Merge(merge) => {
680            children.push(("this", &merge.this));
681            children.push(("using", &merge.using));
682            if let Some(on) = &merge.on {
683                children.push(("on", on));
684            }
685            if let Some(using_cond) = &merge.using_cond {
686                children.push(("using_cond", using_cond));
687            }
688            if let Some(whens) = &merge.whens {
689                children.push(("whens", whens));
690            }
691            if let Some(with_) = &merge.with_ {
692                children.push(("with_", with_));
693            }
694            if let Some(returning) = &merge.returning {
695                children.push(("returning", returning));
696            }
697        }
698        Expression::Any(q) | Expression::All(q) => {
699            children.push(("this", &q.this));
700            children.push(("subquery", &q.subquery));
701        }
702        Expression::Ordered(o) => {
703            children.push(("this", &o.this));
704        }
705        Expression::Interval(i) => {
706            if let Some(ref this) = i.this {
707                children.push(("this", this));
708            }
709        }
710        Expression::Describe(d) => {
711            children.push(("target", &d.target));
712        }
713        Expression::CreateTask(ct) => {
714            children.push(("body", &ct.body));
715        }
716        Expression::Prepare(prepare) => {
717            children.push(("statement", &prepare.statement));
718        }
719        Expression::Execute(exec) => {
720            children.push(("this", &exec.this));
721            for argument in &exec.arguments {
722                children.push(("argument", argument));
723            }
724            for parameter in &exec.parameters {
725                children.push(("parameter", &parameter.value));
726            }
727        }
728        Expression::Analyze(a) => {
729            if let Some(this) = &a.this {
730                children.push(("this", this));
731            }
732            if let Some(expr) = &a.expression {
733                children.push(("expression", expr));
734            }
735        }
736        _ => {}
737    }
738
739    children
740}
741
742/// Iterate over list-child fields of an expression
743///
744/// Returns an iterator of (field_name, &[Expression]) pairs.
745fn iter_children_lists(expr: &Expression) -> Vec<(&'static str, &[Expression])> {
746    let mut lists = Vec::new();
747
748    match expr {
749        Expression::Select(s) => lists.push(("expressions", s.expressions.as_slice())),
750        Expression::Function(f) => {
751            lists.push(("args", f.args.as_slice()));
752        }
753        Expression::AggregateFunction(f) => {
754            lists.push(("args", f.args.as_slice()));
755        }
756        Expression::From(f) => {
757            lists.push(("expressions", f.expressions.as_slice()));
758        }
759        Expression::GroupBy(g) => {
760            lists.push(("expressions", g.expressions.as_slice()));
761        }
762        // OrderBy.expressions is Vec<Ordered>, not Vec<Expression>
763        // We handle Ordered items via iter_children
764        Expression::In(i) => {
765            lists.push(("expressions", i.expressions.as_slice()));
766        }
767        Expression::Array(a) => {
768            lists.push(("expressions", a.expressions.as_slice()));
769        }
770        Expression::Tuple(t) => {
771            lists.push(("expressions", t.expressions.as_slice()));
772        }
773        Expression::TryCatch(try_catch) => {
774            lists.push(("try_body", try_catch.try_body.as_slice()));
775            if let Some(catch_body) = &try_catch.catch_body {
776                lists.push(("catch_body", catch_body.as_slice()));
777            }
778        }
779        // Values.expressions is Vec<Tuple>, handle specially
780        Expression::Coalesce(c) => {
781            lists.push(("expressions", c.expressions.as_slice()));
782        }
783        Expression::Greatest(g) | Expression::Least(g) => {
784            lists.push(("expressions", g.expressions.as_slice()));
785        }
786        _ => {}
787    }
788
789    lists
790}
791
792/// Pre-order depth-first iterator over an expression tree.
793///
794/// Visits each node before its children, using a stack-based approach. This means
795/// the root is yielded first, followed by the entire left subtree (recursively),
796/// then the right subtree. For a binary expression `a + b`, the iteration order
797/// is: `Add`, `a`, `b`.
798///
799/// Created via [`ExpressionWalk::dfs`] or [`DfsIter::new`].
800pub struct DfsIter<'a> {
801    stack: Vec<&'a Expression>,
802}
803
804impl<'a> DfsIter<'a> {
805    /// Create a new DFS iterator starting from the given expression
806    pub fn new(root: &'a Expression) -> Self {
807        Self { stack: vec![root] }
808    }
809}
810
811impl<'a> Iterator for DfsIter<'a> {
812    type Item = &'a Expression;
813
814    fn next(&mut self) -> Option<Self::Item> {
815        let expr = self.stack.pop()?;
816
817        // Add children in reverse order so they come out in forward order
818        let children: Vec<_> = iter_children(expr).into_iter().map(|(_, e)| e).collect();
819        for child in children.into_iter().rev() {
820            self.stack.push(child);
821        }
822
823        let lists: Vec<_> = iter_children_lists(expr)
824            .into_iter()
825            .flat_map(|(_, es)| es.iter())
826            .collect();
827        for child in lists.into_iter().rev() {
828            self.stack.push(child);
829        }
830
831        Some(expr)
832    }
833}
834
835/// Level-order breadth-first iterator over an expression tree.
836///
837/// Visits all nodes at depth N before any node at depth N+1, using a queue-based
838/// approach. For a tree `(a + b) = c`, the iteration order is: `Eq` (depth 0),
839/// `Add`, `c` (depth 1), `a`, `b` (depth 2).
840///
841/// Created via [`ExpressionWalk::bfs`] or [`BfsIter::new`].
842pub struct BfsIter<'a> {
843    queue: VecDeque<&'a Expression>,
844}
845
846impl<'a> BfsIter<'a> {
847    /// Create a new BFS iterator starting from the given expression
848    pub fn new(root: &'a Expression) -> Self {
849        let mut queue = VecDeque::new();
850        queue.push_back(root);
851        Self { queue }
852    }
853}
854
855impl<'a> Iterator for BfsIter<'a> {
856    type Item = &'a Expression;
857
858    fn next(&mut self) -> Option<Self::Item> {
859        let expr = self.queue.pop_front()?;
860
861        // Add children to queue
862        for (_, child) in iter_children(expr) {
863            self.queue.push_back(child);
864        }
865
866        for (_, children) in iter_children_lists(expr) {
867            for child in children {
868                self.queue.push_back(child);
869            }
870        }
871
872        Some(expr)
873    }
874}
875
876/// Extension trait that adds traversal and search methods to [`Expression`].
877///
878/// This trait is implemented for `Expression` and provides a fluent API for
879/// iterating, searching, measuring, and transforming expression trees without
880/// needing to import the iterator types directly.
881pub trait ExpressionWalk {
882    /// Returns a depth-first (pre-order) iterator over this expression and all descendants.
883    ///
884    /// The root node is yielded first, then its children are visited recursively
885    /// from left to right.
886    fn dfs(&self) -> DfsIter<'_>;
887
888    /// Returns a breadth-first (level-order) iterator over this expression and all descendants.
889    ///
890    /// All nodes at depth N are yielded before any node at depth N+1.
891    fn bfs(&self) -> BfsIter<'_>;
892
893    /// Finds the first expression matching `predicate` in depth-first order.
894    ///
895    /// Returns `None` if no descendant (including this node) matches.
896    fn find<F>(&self, predicate: F) -> Option<&Expression>
897    where
898        F: Fn(&Expression) -> bool;
899
900    /// Collects all expressions matching `predicate` in depth-first order.
901    ///
902    /// Returns an empty vector if no descendants match.
903    fn find_all<F>(&self, predicate: F) -> Vec<&Expression>
904    where
905        F: Fn(&Expression) -> bool;
906
907    /// Returns `true` if this node or any descendant matches `predicate`.
908    fn contains<F>(&self, predicate: F) -> bool
909    where
910        F: Fn(&Expression) -> bool;
911
912    /// Counts how many nodes (including this one) match `predicate`.
913    fn count<F>(&self, predicate: F) -> usize
914    where
915        F: Fn(&Expression) -> bool;
916
917    /// Returns direct child expressions of this node.
918    ///
919    /// Collects all single-child fields and list-child fields into a flat vector
920    /// of references. Leaf nodes return an empty vector.
921    fn children(&self) -> Vec<&Expression>;
922
923    /// Returns the maximum depth of the expression tree rooted at this node.
924    ///
925    /// A leaf node has depth 0, a node whose deepest child is a leaf has depth 1, etc.
926    fn tree_depth(&self) -> usize;
927
928    /// Transforms this expression tree bottom-up using the given function (owned variant).
929    ///
930    /// Children are transformed first, then `fun` is called on the resulting node.
931    /// Return `Ok(None)` from `fun` to replace a node with `NULL`.
932    /// Return `Ok(Some(expr))` to substitute the node with `expr`.
933    #[cfg(any(
934        feature = "transpile",
935        feature = "ast-tools",
936        feature = "generate",
937        feature = "semantic"
938    ))]
939    fn transform_owned<F>(self, fun: F) -> crate::Result<Expression>
940    where
941        F: Fn(Expression) -> crate::Result<Option<Expression>>,
942        Self: Sized;
943}
944
945impl ExpressionWalk for Expression {
946    fn dfs(&self) -> DfsIter<'_> {
947        DfsIter::new(self)
948    }
949
950    fn bfs(&self) -> BfsIter<'_> {
951        BfsIter::new(self)
952    }
953
954    fn find<F>(&self, predicate: F) -> Option<&Expression>
955    where
956        F: Fn(&Expression) -> bool,
957    {
958        self.dfs().find(|e| predicate(e))
959    }
960
961    fn find_all<F>(&self, predicate: F) -> Vec<&Expression>
962    where
963        F: Fn(&Expression) -> bool,
964    {
965        self.dfs().filter(|e| predicate(e)).collect()
966    }
967
968    fn contains<F>(&self, predicate: F) -> bool
969    where
970        F: Fn(&Expression) -> bool,
971    {
972        self.dfs().any(|e| predicate(e))
973    }
974
975    fn count<F>(&self, predicate: F) -> usize
976    where
977        F: Fn(&Expression) -> bool,
978    {
979        self.dfs().filter(|e| predicate(e)).count()
980    }
981
982    fn children(&self) -> Vec<&Expression> {
983        let mut result: Vec<&Expression> = Vec::new();
984        for (_, child) in iter_children(self) {
985            result.push(child);
986        }
987        for (_, children_list) in iter_children_lists(self) {
988            for child in children_list {
989                result.push(child);
990            }
991        }
992        result
993    }
994
995    fn tree_depth(&self) -> usize {
996        let mut max_depth = 0;
997
998        for (_, child) in iter_children(self) {
999            let child_depth = child.tree_depth();
1000            if child_depth + 1 > max_depth {
1001                max_depth = child_depth + 1;
1002            }
1003        }
1004
1005        for (_, children) in iter_children_lists(self) {
1006            for child in children {
1007                let child_depth = child.tree_depth();
1008                if child_depth + 1 > max_depth {
1009                    max_depth = child_depth + 1;
1010                }
1011            }
1012        }
1013
1014        max_depth
1015    }
1016
1017    #[cfg(any(
1018        feature = "transpile",
1019        feature = "ast-tools",
1020        feature = "generate",
1021        feature = "semantic"
1022    ))]
1023    fn transform_owned<F>(self, fun: F) -> crate::Result<Expression>
1024    where
1025        F: Fn(Expression) -> crate::Result<Option<Expression>>,
1026    {
1027        transform(self, &fun)
1028    }
1029}
1030
1031/// Transforms an expression tree bottom-up, with optional node removal.
1032///
1033/// Recursively transforms all children first, then applies `fun` to the resulting node.
1034/// If `fun` returns `Ok(None)`, the node is replaced with an `Expression::Null`.
1035/// If `fun` returns `Ok(Some(expr))`, the node is replaced with `expr`.
1036///
1037/// This is the primary transformation entry point when callers need the ability to
1038/// "delete" nodes by returning `None`.
1039///
1040/// # Example
1041///
1042/// ```rust,ignore
1043/// use polyglot_sql::traversal::transform;
1044///
1045/// // Remove all Paren wrapper nodes from a tree
1046/// let result = transform(expr, &|e| match e {
1047///     Expression::Paren(p) => Ok(Some(p.this)),
1048///     other => Ok(Some(other)),
1049/// })?;
1050/// ```
1051#[cfg(any(
1052    feature = "transpile",
1053    feature = "ast-tools",
1054    feature = "generate",
1055    feature = "semantic"
1056))]
1057pub fn transform<F>(expr: Expression, fun: &F) -> crate::Result<Expression>
1058where
1059    F: Fn(Expression) -> crate::Result<Option<Expression>>,
1060{
1061    crate::dialects::transform_recursive(expr, &|e| match fun(e)? {
1062        Some(transformed) => Ok(transformed),
1063        None => Ok(Expression::Null(crate::expressions::Null)),
1064    })
1065}
1066
1067/// Transforms an expression tree bottom-up without node removal.
1068///
1069/// Like [`transform`], but `fun` returns an `Expression` directly rather than
1070/// `Option<Expression>`, so nodes cannot be deleted. This is a convenience wrapper
1071/// for the common case where every node is mapped to exactly one output node.
1072///
1073/// # Example
1074///
1075/// ```rust,ignore
1076/// use polyglot_sql::traversal::transform_map;
1077///
1078/// // Uppercase all column names in a tree
1079/// let result = transform_map(expr, &|e| match e {
1080///     Expression::Column(mut c) => {
1081///         c.name.name = c.name.name.to_uppercase();
1082///         Ok(Expression::Column(c))
1083///     }
1084///     other => Ok(other),
1085/// })?;
1086/// ```
1087#[cfg(any(
1088    feature = "transpile",
1089    feature = "ast-tools",
1090    feature = "generate",
1091    feature = "semantic"
1092))]
1093pub fn transform_map<F>(expr: Expression, fun: &F) -> crate::Result<Expression>
1094where
1095    F: Fn(Expression) -> crate::Result<Expression>,
1096{
1097    crate::dialects::transform_recursive(expr, fun)
1098}
1099
1100// ---------------------------------------------------------------------------
1101// Common expression predicates
1102// ---------------------------------------------------------------------------
1103// These free functions are intended for use with the search methods on
1104// `ExpressionWalk` (e.g., `expr.find(is_column)`, `expr.contains(is_aggregate)`).
1105
1106/// Returns `true` if `expr` is a column reference ([`Expression::Column`]).
1107pub fn is_column(expr: &Expression) -> bool {
1108    matches!(expr, Expression::Column(_))
1109}
1110
1111/// Returns `true` if `expr` is a literal value (number, string, boolean, or NULL).
1112pub fn is_literal(expr: &Expression) -> bool {
1113    matches!(
1114        expr,
1115        Expression::Literal(_) | Expression::Boolean(_) | Expression::Null(_)
1116    )
1117}
1118
1119/// Returns `true` if `expr` is a function call (regular or aggregate).
1120pub fn is_function(expr: &Expression) -> bool {
1121    matches!(
1122        expr,
1123        Expression::Function(_) | Expression::AggregateFunction(_)
1124    )
1125}
1126
1127/// Returns `true` if `expr` is a subquery ([`Expression::Subquery`]).
1128pub fn is_subquery(expr: &Expression) -> bool {
1129    matches!(expr, Expression::Subquery(_))
1130}
1131
1132/// Returns `true` if `expr` is a SELECT statement ([`Expression::Select`]).
1133pub fn is_select(expr: &Expression) -> bool {
1134    matches!(expr, Expression::Select(_))
1135}
1136
1137/// Returns `true` if `expr` is an aggregate function.
1138pub fn is_aggregate(expr: &Expression) -> bool {
1139    matches!(
1140        expr,
1141        Expression::AggregateFunction(_)
1142            | Expression::Count(_)
1143            | Expression::Sum(_)
1144            | Expression::Avg(_)
1145            | Expression::Min(_)
1146            | Expression::Max(_)
1147            | Expression::GroupConcat(_)
1148            | Expression::StringAgg(_)
1149            | Expression::ListAgg(_)
1150            | Expression::CountIf(_)
1151            | Expression::SumIf(_)
1152    )
1153}
1154
1155/// Returns `true` if `expr` is a window function ([`Expression::WindowFunction`]).
1156pub fn is_window_function(expr: &Expression) -> bool {
1157    matches!(expr, Expression::WindowFunction(_))
1158}
1159
1160/// Collects all column references ([`Expression::Column`]) from the expression tree.
1161///
1162/// Performs a depth-first search and returns references to every column node found.
1163pub fn get_columns(expr: &Expression) -> Vec<&Expression> {
1164    expr.find_all(is_column)
1165}
1166
1167/// Collects all table references ([`Expression::Table`]) from the expression tree.
1168///
1169/// Performs a depth-first search and returns references to every table node found.
1170///
1171/// Note: DML target tables (`Insert.table`, `Update.table`, `Delete.table`) are
1172/// stored as `TableRef` struct fields, not as `Expression::Table` nodes, so they
1173/// are not reachable via tree traversal. Use [`get_all_tables`] to include those.
1174pub fn get_tables(expr: &Expression) -> Vec<&Expression> {
1175    expr.find_all(|e| matches!(e, Expression::Table(_)))
1176}
1177
1178/// Collects **all** referenced tables from the expression tree, including DML
1179/// target tables that are stored as `TableRef` struct fields and are therefore
1180/// not reachable through normal tree traversal.
1181///
1182/// Returns owned `Expression::Table` values. This is the comprehensive version
1183/// of [`get_tables`] — use it when you need to discover every table referenced
1184/// in a statement, including inside CTE bodies containing INSERT/UPDATE/DELETE.
1185pub fn get_all_tables(expr: &Expression) -> Vec<Expression> {
1186    use std::collections::HashSet;
1187
1188    let mut seen = HashSet::new();
1189    let mut result = Vec::new();
1190
1191    // First: collect all Expression::Table nodes found via DFS.
1192    for node in expr.dfs() {
1193        if let Expression::Table(t) = node {
1194            let qname = table_ref_qualified_name(t);
1195            if seen.insert(qname) {
1196                result.push(node.clone());
1197            }
1198        }
1199
1200        // Also extract DML target TableRef fields not reachable via iter_children.
1201        let refs: Vec<&TableRef> = match node {
1202            Expression::Insert(ins) => vec![&ins.table],
1203            Expression::Update(upd) => {
1204                let mut v = vec![&upd.table];
1205                v.extend(upd.extra_tables.iter());
1206                v
1207            }
1208            Expression::Delete(del) => {
1209                let mut v = vec![&del.table];
1210                v.extend(del.using.iter());
1211                v
1212            }
1213            _ => continue,
1214        };
1215        for tref in refs {
1216            if tref.name.name.is_empty() {
1217                continue;
1218            }
1219            let qname = table_ref_qualified_name(tref);
1220            if seen.insert(qname) {
1221                result.push(Expression::Table(Box::new(tref.clone())));
1222            }
1223        }
1224    }
1225
1226    result
1227}
1228
1229/// Build a qualified name string from a TableRef for deduplication purposes.
1230fn table_ref_qualified_name(t: &TableRef) -> String {
1231    let mut name = String::new();
1232    if let Some(ref cat) = t.catalog {
1233        name.push_str(&cat.name);
1234        name.push('.');
1235    }
1236    if let Some(ref schema) = t.schema {
1237        name.push_str(&schema.name);
1238        name.push('.');
1239    }
1240    name.push_str(&t.name.name);
1241    name
1242}
1243
1244/// Extracts the underlying [`Expression::Table`] from a MERGE field that may
1245/// be a bare `Table`, an `Alias` wrapping a `Table`, or an `Identifier`.
1246/// Returns `None` if the expression doesn't contain a recognisable table.
1247fn unwrap_merge_table(expr: &Expression) -> Option<&Expression> {
1248    match expr {
1249        Expression::Table(_) => Some(expr),
1250        Expression::Alias(alias) => match &alias.this {
1251            Expression::Table(_) => Some(&alias.this),
1252            _ => None,
1253        },
1254        _ => None,
1255    }
1256}
1257
1258/// Returns the target table of a MERGE statement (the `Merge.this` field),
1259/// unwrapping any alias wrapper to yield the underlying [`Expression::Table`].
1260///
1261/// Returns `None` if `expr` is not a `Merge` or the target isn't a recognisable table.
1262pub fn get_merge_target(expr: &Expression) -> Option<&Expression> {
1263    match expr {
1264        Expression::Merge(m) => unwrap_merge_table(&m.this),
1265        _ => None,
1266    }
1267}
1268
1269/// Returns the source table of a MERGE statement (the `Merge.using` field),
1270/// unwrapping any alias wrapper to yield the underlying [`Expression::Table`].
1271///
1272/// Returns `None` if `expr` is not a `Merge`, the source isn't a recognisable
1273/// table (e.g. it's a subquery), or the source is otherwise unresolvable.
1274pub fn get_merge_source(expr: &Expression) -> Option<&Expression> {
1275    match expr {
1276        Expression::Merge(m) => unwrap_merge_table(&m.using),
1277        _ => None,
1278    }
1279}
1280
1281/// Returns `true` if the expression tree contains any aggregate function calls.
1282pub fn contains_aggregate(expr: &Expression) -> bool {
1283    expr.contains(is_aggregate)
1284}
1285
1286/// Returns `true` if the expression tree contains any window function calls.
1287pub fn contains_window_function(expr: &Expression) -> bool {
1288    expr.contains(is_window_function)
1289}
1290
1291/// Returns `true` if the expression tree contains any subquery nodes.
1292pub fn contains_subquery(expr: &Expression) -> bool {
1293    expr.contains(is_subquery)
1294}
1295
1296// ---------------------------------------------------------------------------
1297// Extended type predicates
1298// ---------------------------------------------------------------------------
1299
1300/// Macro for generating simple type-predicate functions.
1301macro_rules! is_type {
1302    ($name:ident, $($variant:pat),+ $(,)?) => {
1303        /// Returns `true` if `expr` matches the expected AST variant(s).
1304        pub fn $name(expr: &Expression) -> bool {
1305            matches!(expr, $($variant)|+)
1306        }
1307    };
1308}
1309
1310// Query
1311is_type!(is_insert, Expression::Insert(_));
1312is_type!(is_update, Expression::Update(_));
1313is_type!(is_delete, Expression::Delete(_));
1314is_type!(is_merge, Expression::Merge(_));
1315is_type!(is_union, Expression::Union(_));
1316is_type!(is_intersect, Expression::Intersect(_));
1317is_type!(is_except, Expression::Except(_));
1318
1319// Identifiers & literals
1320is_type!(is_boolean, Expression::Boolean(_));
1321is_type!(is_null_literal, Expression::Null(_));
1322is_type!(is_star, Expression::Star(_));
1323is_type!(is_identifier, Expression::Identifier(_));
1324is_type!(is_table, Expression::Table(_));
1325
1326// Comparison
1327is_type!(is_eq, Expression::Eq(_));
1328is_type!(is_neq, Expression::Neq(_));
1329is_type!(is_lt, Expression::Lt(_));
1330is_type!(is_lte, Expression::Lte(_));
1331is_type!(is_gt, Expression::Gt(_));
1332is_type!(is_gte, Expression::Gte(_));
1333is_type!(is_like, Expression::Like(_));
1334is_type!(is_ilike, Expression::ILike(_));
1335
1336// Arithmetic
1337is_type!(is_add, Expression::Add(_));
1338is_type!(is_sub, Expression::Sub(_));
1339is_type!(is_mul, Expression::Mul(_));
1340is_type!(is_div, Expression::Div(_));
1341is_type!(is_mod, Expression::Mod(_));
1342is_type!(is_concat, Expression::Concat(_));
1343
1344// Logical
1345is_type!(is_and, Expression::And(_));
1346is_type!(is_or, Expression::Or(_));
1347is_type!(is_not, Expression::Not(_));
1348
1349// Predicates
1350is_type!(is_in, Expression::In(_));
1351is_type!(is_between, Expression::Between(_));
1352is_type!(is_is_null, Expression::IsNull(_));
1353is_type!(is_exists, Expression::Exists(_));
1354
1355// Functions
1356is_type!(is_count, Expression::Count(_));
1357is_type!(is_sum, Expression::Sum(_));
1358is_type!(is_avg, Expression::Avg(_));
1359is_type!(is_min_func, Expression::Min(_));
1360is_type!(is_max_func, Expression::Max(_));
1361is_type!(is_coalesce, Expression::Coalesce(_));
1362is_type!(is_null_if, Expression::NullIf(_));
1363is_type!(is_cast, Expression::Cast(_));
1364is_type!(is_try_cast, Expression::TryCast(_));
1365is_type!(is_safe_cast, Expression::SafeCast(_));
1366is_type!(is_case, Expression::Case(_));
1367
1368// Clauses
1369is_type!(is_from, Expression::From(_));
1370is_type!(is_join, Expression::Join(_));
1371is_type!(is_where, Expression::Where(_));
1372is_type!(is_group_by, Expression::GroupBy(_));
1373is_type!(is_having, Expression::Having(_));
1374is_type!(is_order_by, Expression::OrderBy(_));
1375is_type!(is_limit, Expression::Limit(_));
1376is_type!(is_offset, Expression::Offset(_));
1377is_type!(is_with, Expression::With(_));
1378is_type!(is_cte, Expression::Cte(_));
1379is_type!(is_alias, Expression::Alias(_));
1380is_type!(is_paren, Expression::Paren(_));
1381is_type!(is_ordered, Expression::Ordered(_));
1382
1383// DDL
1384is_type!(is_create_table, Expression::CreateTable(_));
1385is_type!(is_drop_table, Expression::DropTable(_));
1386is_type!(is_alter_table, Expression::AlterTable(_));
1387is_type!(is_create_index, Expression::CreateIndex(_));
1388is_type!(is_drop_index, Expression::DropIndex(_));
1389is_type!(is_create_view, Expression::CreateView(_));
1390is_type!(is_drop_view, Expression::DropView(_));
1391
1392// ---------------------------------------------------------------------------
1393// Composite predicates
1394// ---------------------------------------------------------------------------
1395
1396/// Returns `true` if `expr` is a query statement (SELECT, INSERT, UPDATE, DELETE, or MERGE).
1397pub fn is_query(expr: &Expression) -> bool {
1398    matches!(
1399        expr,
1400        Expression::Select(_)
1401            | Expression::Insert(_)
1402            | Expression::Update(_)
1403            | Expression::Delete(_)
1404            | Expression::Merge(_)
1405    )
1406}
1407
1408/// Returns `true` if `expr` is a set operation (UNION, INTERSECT, or EXCEPT).
1409pub fn is_set_operation(expr: &Expression) -> bool {
1410    matches!(
1411        expr,
1412        Expression::Union(_) | Expression::Intersect(_) | Expression::Except(_)
1413    )
1414}
1415
1416/// Returns `true` if `expr` is a comparison operator.
1417pub fn is_comparison(expr: &Expression) -> bool {
1418    matches!(
1419        expr,
1420        Expression::Eq(_)
1421            | Expression::Neq(_)
1422            | Expression::Lt(_)
1423            | Expression::Lte(_)
1424            | Expression::Gt(_)
1425            | Expression::Gte(_)
1426            | Expression::Like(_)
1427            | Expression::ILike(_)
1428    )
1429}
1430
1431/// Returns `true` if `expr` is an arithmetic operator.
1432pub fn is_arithmetic(expr: &Expression) -> bool {
1433    matches!(
1434        expr,
1435        Expression::Add(_)
1436            | Expression::Sub(_)
1437            | Expression::Mul(_)
1438            | Expression::Div(_)
1439            | Expression::Mod(_)
1440    )
1441}
1442
1443/// Returns `true` if `expr` is a logical operator (AND, OR, NOT).
1444pub fn is_logical(expr: &Expression) -> bool {
1445    matches!(
1446        expr,
1447        Expression::And(_) | Expression::Or(_) | Expression::Not(_)
1448    )
1449}
1450
1451/// Returns `true` if `expr` is a DDL statement.
1452pub fn is_ddl(expr: &Expression) -> bool {
1453    matches!(
1454        expr,
1455        Expression::CreateTable(_)
1456            | Expression::DropTable(_)
1457            | Expression::Undrop(_)
1458            | Expression::AlterTable(_)
1459            | Expression::CreateIndex(_)
1460            | Expression::DropIndex(_)
1461            | Expression::CreateView(_)
1462            | Expression::DropView(_)
1463            | Expression::AlterView(_)
1464            | Expression::CreateSchema(_)
1465            | Expression::DropSchema(_)
1466            | Expression::CreateDatabase(_)
1467            | Expression::DropDatabase(_)
1468            | Expression::CreateFunction(_)
1469            | Expression::DropFunction(_)
1470            | Expression::CreateProcedure(_)
1471            | Expression::DropProcedure(_)
1472            | Expression::CreateSequence(_)
1473            | Expression::CreateSynonym(_)
1474            | Expression::DropSequence(_)
1475            | Expression::AlterSequence(_)
1476            | Expression::CreateTrigger(_)
1477            | Expression::DropTrigger(_)
1478            | Expression::CreateType(_)
1479            | Expression::DropType(_)
1480    )
1481}
1482
1483/// Find the parent of `target` within the tree rooted at `root`.
1484///
1485/// Uses pointer identity ([`std::ptr::eq`]) — `target` must be a reference
1486/// obtained from the same tree (e.g., via [`ExpressionWalk::find`] or DFS iteration).
1487///
1488/// Returns `None` if `target` is the root itself or is not found in the tree.
1489pub fn find_parent<'a>(root: &'a Expression, target: &Expression) -> Option<&'a Expression> {
1490    fn search<'a>(node: &'a Expression, target: *const Expression) -> Option<&'a Expression> {
1491        for (_, child) in iter_children(node) {
1492            if std::ptr::eq(child, target) {
1493                return Some(node);
1494            }
1495            if let Some(found) = search(child, target) {
1496                return Some(found);
1497            }
1498        }
1499        for (_, children_list) in iter_children_lists(node) {
1500            for child in children_list {
1501                if std::ptr::eq(child, target) {
1502                    return Some(node);
1503                }
1504                if let Some(found) = search(child, target) {
1505                    return Some(found);
1506                }
1507            }
1508        }
1509        None
1510    }
1511
1512    search(root, target as *const Expression)
1513}
1514
1515/// Find the first ancestor of `target` matching `predicate`, walking from
1516/// parent toward root.
1517///
1518/// Uses pointer identity for target lookup. Returns `None` if no ancestor
1519/// matches or `target` is not found in the tree.
1520pub fn find_ancestor<'a, F>(
1521    root: &'a Expression,
1522    target: &Expression,
1523    predicate: F,
1524) -> Option<&'a Expression>
1525where
1526    F: Fn(&Expression) -> bool,
1527{
1528    // Build path from root to target
1529    fn build_path<'a>(
1530        node: &'a Expression,
1531        target: *const Expression,
1532        path: &mut Vec<&'a Expression>,
1533    ) -> bool {
1534        if std::ptr::eq(node, target) {
1535            return true;
1536        }
1537        path.push(node);
1538        for (_, child) in iter_children(node) {
1539            if build_path(child, target, path) {
1540                return true;
1541            }
1542        }
1543        for (_, children_list) in iter_children_lists(node) {
1544            for child in children_list {
1545                if build_path(child, target, path) {
1546                    return true;
1547                }
1548            }
1549        }
1550        path.pop();
1551        false
1552    }
1553
1554    let mut path = Vec::new();
1555    if !build_path(root, target as *const Expression, &mut path) {
1556        return None;
1557    }
1558
1559    // Walk path in reverse (parent first, then grandparent, etc.)
1560    for ancestor in path.iter().rev() {
1561        if predicate(ancestor) {
1562            return Some(ancestor);
1563        }
1564    }
1565    None
1566}
1567
1568#[cfg(test)]
1569mod tests {
1570    use super::*;
1571    use crate::expressions::{BinaryOp, Column, Identifier, Literal};
1572
1573    fn make_column(name: &str) -> Expression {
1574        Expression::boxed_column(Column {
1575            name: Identifier {
1576                name: name.to_string(),
1577                quoted: false,
1578                trailing_comments: vec![],
1579                span: None,
1580            },
1581            table: None,
1582            join_mark: false,
1583            trailing_comments: vec![],
1584            span: None,
1585            inferred_type: None,
1586        })
1587    }
1588
1589    fn make_literal(value: i64) -> Expression {
1590        Expression::Literal(Box::new(Literal::Number(value.to_string())))
1591    }
1592
1593    #[test]
1594    fn test_dfs_simple() {
1595        let left = make_column("a");
1596        let right = make_literal(1);
1597        let expr = Expression::Eq(Box::new(BinaryOp {
1598            left,
1599            right,
1600            left_comments: vec![],
1601            operator_comments: vec![],
1602            trailing_comments: vec![],
1603            inferred_type: None,
1604        }));
1605
1606        let nodes: Vec<_> = expr.dfs().collect();
1607        assert_eq!(nodes.len(), 3); // Eq, Column, Literal
1608        assert!(matches!(nodes[0], Expression::Eq(_)));
1609        assert!(matches!(nodes[1], Expression::Column(_)));
1610        assert!(matches!(nodes[2], Expression::Literal(_)));
1611    }
1612
1613    #[test]
1614    fn test_find() {
1615        let left = make_column("a");
1616        let right = make_literal(1);
1617        let expr = Expression::Eq(Box::new(BinaryOp {
1618            left,
1619            right,
1620            left_comments: vec![],
1621            operator_comments: vec![],
1622            trailing_comments: vec![],
1623            inferred_type: None,
1624        }));
1625
1626        let column = expr.find(is_column);
1627        assert!(column.is_some());
1628        assert!(matches!(column.unwrap(), Expression::Column(_)));
1629
1630        let literal = expr.find(is_literal);
1631        assert!(literal.is_some());
1632        assert!(matches!(literal.unwrap(), Expression::Literal(_)));
1633    }
1634
1635    #[test]
1636    fn test_find_all() {
1637        let col1 = make_column("a");
1638        let col2 = make_column("b");
1639        let expr = Expression::And(Box::new(BinaryOp {
1640            left: col1,
1641            right: col2,
1642            left_comments: vec![],
1643            operator_comments: vec![],
1644            trailing_comments: vec![],
1645            inferred_type: None,
1646        }));
1647
1648        let columns = expr.find_all(is_column);
1649        assert_eq!(columns.len(), 2);
1650    }
1651
1652    #[test]
1653    fn test_contains() {
1654        let col = make_column("a");
1655        let lit = make_literal(1);
1656        let expr = Expression::Eq(Box::new(BinaryOp {
1657            left: col,
1658            right: lit,
1659            left_comments: vec![],
1660            operator_comments: vec![],
1661            trailing_comments: vec![],
1662            inferred_type: None,
1663        }));
1664
1665        assert!(expr.contains(is_column));
1666        assert!(expr.contains(is_literal));
1667        assert!(!expr.contains(is_subquery));
1668    }
1669
1670    #[test]
1671    fn test_count() {
1672        let col1 = make_column("a");
1673        let col2 = make_column("b");
1674        let lit = make_literal(1);
1675
1676        let inner = Expression::Add(Box::new(BinaryOp {
1677            left: col2,
1678            right: lit,
1679            left_comments: vec![],
1680            operator_comments: vec![],
1681            trailing_comments: vec![],
1682            inferred_type: None,
1683        }));
1684
1685        let expr = Expression::Eq(Box::new(BinaryOp {
1686            left: col1,
1687            right: inner,
1688            left_comments: vec![],
1689            operator_comments: vec![],
1690            trailing_comments: vec![],
1691            inferred_type: None,
1692        }));
1693
1694        assert_eq!(expr.count(is_column), 2);
1695        assert_eq!(expr.count(is_literal), 1);
1696    }
1697
1698    #[test]
1699    fn test_tree_depth() {
1700        // Single node
1701        let lit = make_literal(1);
1702        assert_eq!(lit.tree_depth(), 0);
1703
1704        // One level
1705        let col = make_column("a");
1706        let expr = Expression::Eq(Box::new(BinaryOp {
1707            left: col,
1708            right: lit.clone(),
1709            left_comments: vec![],
1710            operator_comments: vec![],
1711            trailing_comments: vec![],
1712            inferred_type: None,
1713        }));
1714        assert_eq!(expr.tree_depth(), 1);
1715
1716        // Two levels
1717        let inner = Expression::Add(Box::new(BinaryOp {
1718            left: make_column("b"),
1719            right: lit,
1720            left_comments: vec![],
1721            operator_comments: vec![],
1722            trailing_comments: vec![],
1723            inferred_type: None,
1724        }));
1725        let outer = Expression::Eq(Box::new(BinaryOp {
1726            left: make_column("a"),
1727            right: inner,
1728            left_comments: vec![],
1729            operator_comments: vec![],
1730            trailing_comments: vec![],
1731            inferred_type: None,
1732        }));
1733        assert_eq!(outer.tree_depth(), 2);
1734    }
1735
1736    #[test]
1737    fn test_tree_context() {
1738        let col = make_column("a");
1739        let lit = make_literal(1);
1740        let expr = Expression::Eq(Box::new(BinaryOp {
1741            left: col,
1742            right: lit,
1743            left_comments: vec![],
1744            operator_comments: vec![],
1745            trailing_comments: vec![],
1746            inferred_type: None,
1747        }));
1748
1749        let ctx = TreeContext::build(&expr);
1750
1751        // Root has no parent
1752        let root_info = ctx.get(0).unwrap();
1753        assert!(root_info.parent_id.is_none());
1754
1755        // Children have root as parent
1756        let left_info = ctx.get(1).unwrap();
1757        assert_eq!(left_info.parent_id, Some(0));
1758        assert_eq!(left_info.arg_key, "left");
1759
1760        let right_info = ctx.get(2).unwrap();
1761        assert_eq!(right_info.parent_id, Some(0));
1762        assert_eq!(right_info.arg_key, "right");
1763    }
1764
1765    // -- Step 8: transform / transform_map tests --
1766
1767    #[test]
1768    fn test_transform_rename_columns() {
1769        let ast = crate::parser::Parser::parse_sql("SELECT a, b FROM t").unwrap();
1770        let expr = ast[0].clone();
1771        let result = super::transform_map(expr, &|e| {
1772            if let Expression::Column(ref c) = e {
1773                if c.name.name == "a" {
1774                    return Ok(Expression::boxed_column(Column {
1775                        name: Identifier::new("alpha"),
1776                        table: c.table.clone(),
1777                        join_mark: false,
1778                        trailing_comments: vec![],
1779                        span: None,
1780                        inferred_type: None,
1781                    }));
1782                }
1783            }
1784            Ok(e)
1785        })
1786        .unwrap();
1787        let sql = crate::generator::Generator::sql(&result).unwrap();
1788        assert!(sql.contains("alpha"), "Expected 'alpha' in: {}", sql);
1789        assert!(sql.contains("b"), "Expected 'b' in: {}", sql);
1790    }
1791
1792    #[test]
1793    fn test_transform_noop() {
1794        let ast = crate::parser::Parser::parse_sql("SELECT 1 + 2").unwrap();
1795        let expr = ast[0].clone();
1796        let result = super::transform_map(expr.clone(), &|e| Ok(e)).unwrap();
1797        let sql1 = crate::generator::Generator::sql(&expr).unwrap();
1798        let sql2 = crate::generator::Generator::sql(&result).unwrap();
1799        assert_eq!(sql1, sql2);
1800    }
1801
1802    #[test]
1803    fn test_transform_nested() {
1804        let ast = crate::parser::Parser::parse_sql("SELECT a + b FROM t").unwrap();
1805        let expr = ast[0].clone();
1806        let result = super::transform_map(expr, &|e| {
1807            if let Expression::Column(ref c) = e {
1808                return Ok(Expression::Literal(Box::new(Literal::Number(
1809                    if c.name.name == "a" { "1" } else { "2" }.to_string(),
1810                ))));
1811            }
1812            Ok(e)
1813        })
1814        .unwrap();
1815        let sql = crate::generator::Generator::sql(&result).unwrap();
1816        assert_eq!(sql, "SELECT 1 + 2 FROM t");
1817    }
1818
1819    #[test]
1820    fn test_transform_error() {
1821        let ast = crate::parser::Parser::parse_sql("SELECT a FROM t").unwrap();
1822        let expr = ast[0].clone();
1823        let result = super::transform_map(expr, &|e| {
1824            if let Expression::Column(ref c) = e {
1825                if c.name.name == "a" {
1826                    return Err(crate::error::Error::parse("test error", 0, 0, 0, 0));
1827                }
1828            }
1829            Ok(e)
1830        });
1831        assert!(result.is_err());
1832    }
1833
1834    #[test]
1835    fn test_transform_owned_trait() {
1836        let ast = crate::parser::Parser::parse_sql("SELECT x FROM t").unwrap();
1837        let expr = ast[0].clone();
1838        let result = expr.transform_owned(|e| Ok(Some(e))).unwrap();
1839        let sql = crate::generator::Generator::sql(&result).unwrap();
1840        assert_eq!(sql, "SELECT x FROM t");
1841    }
1842
1843    // -- children() tests --
1844
1845    #[test]
1846    fn test_children_leaf() {
1847        let lit = make_literal(1);
1848        assert_eq!(lit.children().len(), 0);
1849    }
1850
1851    #[test]
1852    fn test_children_binary_op() {
1853        let left = make_column("a");
1854        let right = make_literal(1);
1855        let expr = Expression::Eq(Box::new(BinaryOp {
1856            left,
1857            right,
1858            left_comments: vec![],
1859            operator_comments: vec![],
1860            trailing_comments: vec![],
1861            inferred_type: None,
1862        }));
1863        let children = expr.children();
1864        assert_eq!(children.len(), 2);
1865        assert!(matches!(children[0], Expression::Column(_)));
1866        assert!(matches!(children[1], Expression::Literal(_)));
1867    }
1868
1869    #[test]
1870    fn test_children_select() {
1871        let ast = crate::parser::Parser::parse_sql("SELECT a, b FROM t").unwrap();
1872        let expr = &ast[0];
1873        let children = expr.children();
1874        // Should include select list items (a, b)
1875        assert!(children.len() >= 2);
1876    }
1877
1878    #[test]
1879    fn test_children_select_includes_from_and_join_sources() {
1880        let ast = crate::parser::Parser::parse_sql(
1881            "SELECT u.id FROM users u JOIN orders o ON u.id = o.user_id",
1882        )
1883        .unwrap();
1884        let expr = &ast[0];
1885        let children = expr.children();
1886
1887        let table_names: Vec<&str> = children
1888            .iter()
1889            .filter_map(|e| match e {
1890                Expression::Table(t) => Some(t.name.name.as_str()),
1891                _ => None,
1892            })
1893            .collect();
1894
1895        assert!(table_names.contains(&"users"));
1896        assert!(table_names.contains(&"orders"));
1897    }
1898
1899    #[test]
1900    fn test_get_tables_includes_insert_query_sources() {
1901        let ast = crate::parser::Parser::parse_sql(
1902            "INSERT INTO dst (id) SELECT s.id FROM src s JOIN dim d ON s.id = d.id",
1903        )
1904        .unwrap();
1905        let expr = &ast[0];
1906        let tables = get_tables(expr);
1907        let names: Vec<&str> = tables
1908            .iter()
1909            .filter_map(|e| match e {
1910                Expression::Table(t) => Some(t.name.name.as_str()),
1911                _ => None,
1912            })
1913            .collect();
1914
1915        assert!(names.contains(&"src"));
1916        assert!(names.contains(&"dim"));
1917    }
1918
1919    // -- find_parent() tests --
1920
1921    #[test]
1922    fn test_find_parent_binary() {
1923        let left = make_column("a");
1924        let right = make_literal(1);
1925        let expr = Expression::Eq(Box::new(BinaryOp {
1926            left,
1927            right,
1928            left_comments: vec![],
1929            operator_comments: vec![],
1930            trailing_comments: vec![],
1931            inferred_type: None,
1932        }));
1933
1934        // Find the column child and get its parent
1935        let col = expr.find(is_column).unwrap();
1936        let parent = super::find_parent(&expr, col);
1937        assert!(parent.is_some());
1938        assert!(matches!(parent.unwrap(), Expression::Eq(_)));
1939    }
1940
1941    #[test]
1942    fn test_find_parent_root_has_none() {
1943        let lit = make_literal(1);
1944        let parent = super::find_parent(&lit, &lit);
1945        assert!(parent.is_none());
1946    }
1947
1948    // -- find_ancestor() tests --
1949
1950    #[test]
1951    fn test_find_ancestor_select() {
1952        let ast = crate::parser::Parser::parse_sql("SELECT a FROM t WHERE a > 1").unwrap();
1953        let expr = &ast[0];
1954
1955        // Find a column inside the WHERE clause
1956        let where_col = expr.dfs().find(|e| {
1957            if let Expression::Column(c) = e {
1958                c.name.name == "a"
1959            } else {
1960                false
1961            }
1962        });
1963        assert!(where_col.is_some());
1964
1965        // Find Select ancestor of that column
1966        let ancestor = super::find_ancestor(expr, where_col.unwrap(), is_select);
1967        assert!(ancestor.is_some());
1968        assert!(matches!(ancestor.unwrap(), Expression::Select(_)));
1969    }
1970
1971    #[test]
1972    fn test_find_ancestor_no_match() {
1973        let left = make_column("a");
1974        let right = make_literal(1);
1975        let expr = Expression::Eq(Box::new(BinaryOp {
1976            left,
1977            right,
1978            left_comments: vec![],
1979            operator_comments: vec![],
1980            trailing_comments: vec![],
1981            inferred_type: None,
1982        }));
1983
1984        let col = expr.find(is_column).unwrap();
1985        let ancestor = super::find_ancestor(&expr, col, is_select);
1986        assert!(ancestor.is_none());
1987    }
1988
1989    #[test]
1990    fn test_ancestors() {
1991        let col = make_column("a");
1992        let lit = make_literal(1);
1993        let inner = Expression::Add(Box::new(BinaryOp {
1994            left: col,
1995            right: lit,
1996            left_comments: vec![],
1997            operator_comments: vec![],
1998            trailing_comments: vec![],
1999            inferred_type: None,
2000        }));
2001        let outer = Expression::Eq(Box::new(BinaryOp {
2002            left: make_column("b"),
2003            right: inner,
2004            left_comments: vec![],
2005            operator_comments: vec![],
2006            trailing_comments: vec![],
2007            inferred_type: None,
2008        }));
2009
2010        let ctx = TreeContext::build(&outer);
2011
2012        // The inner Add's left child (column "a") should have ancestors
2013        // Node 0: Eq
2014        // Node 1: Column "b" (left of Eq)
2015        // Node 2: Add (right of Eq)
2016        // Node 3: Column "a" (left of Add)
2017        // Node 4: Literal (right of Add)
2018
2019        let ancestors = ctx.ancestors_of(3);
2020        assert_eq!(ancestors, vec![2, 0]); // Add, then Eq
2021    }
2022
2023    #[test]
2024    fn test_get_merge_target_and_source() {
2025        let dialect = crate::Dialect::get(crate::dialects::DialectType::Generic);
2026
2027        // MERGE with aliased target and source tables
2028        let sql = "MERGE INTO orders o USING customers c ON o.customer_id = c.id WHEN MATCHED THEN UPDATE SET amount = amount + 100";
2029        let exprs = dialect.parse(sql).unwrap();
2030        let expr = &exprs[0];
2031
2032        assert!(is_merge(expr));
2033        assert!(is_query(expr));
2034
2035        let target = get_merge_target(expr).expect("should find target table");
2036        assert!(matches!(target, Expression::Table(_)));
2037        if let Expression::Table(t) = target {
2038            assert_eq!(t.name.name, "orders");
2039        }
2040
2041        let source = get_merge_source(expr).expect("should find source table");
2042        assert!(matches!(source, Expression::Table(_)));
2043        if let Expression::Table(t) = source {
2044            assert_eq!(t.name.name, "customers");
2045        }
2046    }
2047
2048    #[test]
2049    fn test_get_merge_source_subquery_returns_none() {
2050        let dialect = crate::Dialect::get(crate::dialects::DialectType::Generic);
2051
2052        // MERGE with subquery source — get_merge_source should return None
2053        let sql = "MERGE INTO orders o USING (SELECT * FROM customers) c ON o.customer_id = c.id WHEN MATCHED THEN DELETE";
2054        let exprs = dialect.parse(sql).unwrap();
2055        let expr = &exprs[0];
2056
2057        assert!(get_merge_target(expr).is_some());
2058        assert!(get_merge_source(expr).is_none());
2059    }
2060
2061    #[test]
2062    fn test_get_merge_on_non_merge_returns_none() {
2063        let dialect = crate::Dialect::get(crate::dialects::DialectType::Generic);
2064        let exprs = dialect.parse("SELECT 1").unwrap();
2065        assert!(get_merge_target(&exprs[0]).is_none());
2066        assert!(get_merge_source(&exprs[0]).is_none());
2067    }
2068
2069    #[test]
2070    fn test_get_tables_finds_tables_inside_in_subquery() {
2071        let dialect = crate::Dialect::get(crate::dialects::DialectType::Generic);
2072        let sql = "SELECT id, name FROM customers WHERE id IN (SELECT customer_id FROM orders WHERE amount > 1000)";
2073        let exprs = dialect.parse(sql).unwrap();
2074        let tables = get_tables(&exprs[0]);
2075        let names: Vec<&str> = tables
2076            .iter()
2077            .filter_map(|e| {
2078                if let Expression::Table(t) = e {
2079                    Some(t.name.name.as_str())
2080                } else {
2081                    None
2082                }
2083            })
2084            .collect();
2085        assert!(names.contains(&"customers"), "should find outer table");
2086        assert!(names.contains(&"orders"), "should find subquery table");
2087    }
2088
2089    #[test]
2090    fn test_get_tables_finds_tables_inside_exists_subquery() {
2091        let dialect = crate::Dialect::get(crate::dialects::DialectType::Generic);
2092        let sql = "SELECT * FROM customers c WHERE EXISTS (SELECT 1 FROM orders o WHERE o.customer_id = c.id)";
2093        let exprs = dialect.parse(sql).unwrap();
2094        let tables = get_tables(&exprs[0]);
2095        let names: Vec<&str> = tables
2096            .iter()
2097            .filter_map(|e| {
2098                if let Expression::Table(t) = e {
2099                    Some(t.name.name.as_str())
2100                } else {
2101                    None
2102                }
2103            })
2104            .collect();
2105        assert!(names.contains(&"customers"), "should find outer table");
2106        assert!(
2107            names.contains(&"orders"),
2108            "should find EXISTS subquery table"
2109        );
2110    }
2111
2112    #[test]
2113    fn test_get_tables_finds_tables_in_correlated_subquery() {
2114        let dialect = crate::Dialect::get(crate::dialects::DialectType::TSQL);
2115        let sql = "SELECT id, name FROM customers WHERE id IN (SELECT customer_id FROM orders WHERE amount > 1000)";
2116        let exprs = dialect.parse(sql).unwrap();
2117        let tables = get_tables(&exprs[0]);
2118        let names: Vec<&str> = tables
2119            .iter()
2120            .filter_map(|e| {
2121                if let Expression::Table(t) = e {
2122                    Some(t.name.name.as_str())
2123                } else {
2124                    None
2125                }
2126            })
2127            .collect();
2128        assert!(
2129            names.contains(&"customers"),
2130            "TSQL: should find outer table"
2131        );
2132        assert!(
2133            names.contains(&"orders"),
2134            "TSQL: should find subquery table"
2135        );
2136    }
2137}