Skip to main content

qusql_parse/
visit.rs

1use crate::{
2    DoBody, Expression, Is, JoinSpecification, JsonTableColumn, JsonTableOnErrorEmpty,
3    OnConflictAction, Select, Statement, TableReference, WindowFrameBound, WindowSpec,
4};
5
6/// Visitor pattern for traversing the AST.
7///
8/// Each `visit_*` method recursively walks the node's children by default via
9/// the corresponding public `walk_*` free function. Override individual methods
10/// to observe or transform specific node kinds, then call the `walk_*` function
11/// to continue the descent.
12///
13/// # Return type
14///
15/// Every method returns `Result<Self::T, Self::E>`. `T: Default` allows walk
16/// functions to return a value even when visiting many children and discarding
17/// each intermediate result - they simply return `Ok(T::default())` after
18/// processing all children. For pure side-effects set `T = ()`. For
19/// early-termination, encode the "found" value in `E` and short-circuit with
20/// `Err(...)`.
21pub trait Visitor<'a>: Sized {
22    /// The success value produced when visiting a node.
23    type T: Default;
24    /// The error / early-exit value.
25    type E;
26
27    /// Visit a [`Statement`] node. Recurses into all child statements and expressions by default.
28    fn visit_statement(&mut self, stmt: &Statement<'a>) -> Result<Self::T, Self::E> {
29        walk_statement(self, stmt)
30    }
31
32    /// Visit an [`Expression`] node. Recurses into all child expressions by default.
33    fn visit_expression(&mut self, expr: &Expression<'a>) -> Result<Self::T, Self::E> {
34        walk_expression(self, expr)
35    }
36
37    /// Visit a [`Select`] node. Recurses into all select expressions, table references,
38    /// and clause expressions (WHERE, GROUP BY, HAVING, ORDER BY, LIMIT, etc.) by default.
39    fn visit_select(&mut self, select: &Select<'a>) -> Result<Self::T, Self::E> {
40        walk_select(self, select)
41    }
42
43    /// Visit a [`TableReference`] node. Recurses into subqueries, JOIN children,
44    /// and any expressions (JSON path, function arguments, ON clause) by default.
45    fn visit_table_reference(&mut self, tr: &TableReference<'a>) -> Result<Self::T, Self::E> {
46        walk_table_reference(self, tr)
47    }
48}
49
50// -- private helpers ----------------------------------------------------------
51
52/// Recurse into the partition-by, order-by, and frame bound expressions of a window specification.
53fn walk_window_spec<'a, V: Visitor<'a>>(v: &mut V, spec: &WindowSpec<'a>) -> Result<V::T, V::E> {
54    if let Some((_, exprs)) = &spec.partition_by {
55        for expr in exprs {
56            v.visit_expression(expr)?;
57        }
58    }
59    if let Some((_, items)) = &spec.order_by {
60        for (expr, _) in items {
61            v.visit_expression(expr)?;
62        }
63    }
64    if let Some(frame) = &spec.frame {
65        walk_window_frame_bound(v, &frame.start)?;
66        if let Some((_, end)) = &frame.between {
67            walk_window_frame_bound(v, end)?;
68        }
69    }
70    Ok(V::T::default())
71}
72
73/// Recurse into the expression of a window frame bound, if any.
74/// `UNBOUNDED PRECEDING/FOLLOWING` and `CURRENT ROW` have no child expressions.
75fn walk_window_frame_bound<'a, V: Visitor<'a>>(
76    v: &mut V,
77    bound: &WindowFrameBound<'a>,
78) -> Result<V::T, V::E> {
79    match bound {
80        WindowFrameBound::Preceding(expr, _) | WindowFrameBound::Following(expr, _) => {
81            v.visit_expression(expr)
82        }
83        WindowFrameBound::UnboundedPreceding(_)
84        | WindowFrameBound::CurrentRow(_)
85        | WindowFrameBound::UnboundedFollowing(_) => Ok(V::T::default()),
86    }
87}
88
89/// Recurse into the path and ON EMPTY/ERROR expressions within a `JSON_TABLE` column definition.
90/// For `Nested` columns this recurses into the nested column list as well.
91fn walk_json_table_column<'a, V: Visitor<'a>>(
92    v: &mut V,
93    col: &JsonTableColumn<'a>,
94) -> Result<V::T, V::E> {
95    match col {
96        JsonTableColumn::Column {
97            path,
98            on_empty,
99            on_error,
100            ..
101        } => {
102            v.visit_expression(path)?;
103            if let Some((JsonTableOnErrorEmpty::Default(expr), _)) = on_empty {
104                v.visit_expression(expr)?;
105            }
106            if let Some((JsonTableOnErrorEmpty::Default(expr), _)) = on_error {
107                v.visit_expression(expr)?;
108            }
109            Ok(V::T::default())
110        }
111        JsonTableColumn::Ordinality { .. } => Ok(V::T::default()),
112        JsonTableColumn::Nested { path, columns, .. } => {
113            v.visit_expression(path)?;
114            for col in columns {
115                walk_json_table_column(v, col)?;
116            }
117            Ok(V::T::default())
118        }
119    }
120}
121
122// -- public walk functions ----------------------------------------------------
123
124/// Default recursion for [`Statement`] nodes.
125pub fn walk_statement<'a, V: Visitor<'a>>(v: &mut V, stmt: &Statement<'a>) -> Result<V::T, V::E> {
126    match stmt {
127        // -- DML ------------------------------------------------------------------
128        Statement::Select(s) => v.visit_select(s),
129
130        Statement::CompoundQuery(q) => {
131            v.visit_statement(&q.left)?;
132            for branch in &q.with {
133                v.visit_statement(&branch.statement)?;
134            }
135            if let Some((_, items)) = &q.order_by {
136                for (expr, _) in items {
137                    v.visit_expression(expr)?;
138                }
139            }
140            if let Some((_, offset, count)) = &q.limit {
141                if let Some(o) = offset {
142                    v.visit_expression(o)?;
143                }
144                v.visit_expression(count)?;
145            }
146            Ok(V::T::default())
147        }
148
149        Statement::WithQuery(q) => {
150            for block in &q.with_blocks {
151                v.visit_statement(&block.statement)?;
152            }
153            v.visit_statement(&q.statement)
154        }
155
156        Statement::InsertReplace(i) => {
157            if let Some((_, rows)) = &i.values {
158                for row in rows {
159                    for expr in row {
160                        v.visit_expression(expr)?;
161                    }
162                }
163            }
164            if let Some(sel) = &i.select {
165                v.visit_statement(sel)?;
166            }
167            if let Some(set) = &i.set {
168                for p in &set.pairs {
169                    v.visit_expression(&p.value)?;
170                }
171            }
172            if let Some(odk) = &i.on_duplicate_key_update {
173                for p in &odk.pairs {
174                    v.visit_expression(&p.value)?;
175                }
176            }
177            if let Some(oc) = &i.on_conflict
178                && let OnConflictAction::DoUpdateSet { sets, where_, .. } = &oc.action
179            {
180                for (_, expr) in sets {
181                    v.visit_expression(expr)?;
182                }
183                if let Some((_, expr)) = where_ {
184                    v.visit_expression(expr)?;
185                }
186            }
187            if let Some((_, exprs)) = &i.returning {
188                for se in exprs {
189                    v.visit_expression(&se.expr)?;
190                }
191            }
192            Ok(V::T::default())
193        }
194
195        Statement::Update(u) => {
196            for tr in &u.tables {
197                v.visit_table_reference(tr)?;
198            }
199            for (_, expr) in &u.set {
200                v.visit_expression(expr)?;
201            }
202            if let Some((expr, _)) = &u.where_ {
203                v.visit_expression(expr)?;
204            }
205            if let Some((_, refs)) = &u.from {
206                for tr in refs {
207                    v.visit_table_reference(tr)?;
208                }
209            }
210            if let Some((_, exprs)) = &u.returning {
211                for se in exprs {
212                    v.visit_expression(&se.expr)?;
213                }
214            }
215            Ok(V::T::default())
216        }
217
218        Statement::Delete(d) => {
219            for tr in &d.using {
220                v.visit_table_reference(tr)?;
221            }
222            if let Some((expr, _)) = &d.where_ {
223                v.visit_expression(expr)?;
224            }
225            if let Some((_, items)) = &d.order_by {
226                for (expr, _) in items {
227                    v.visit_expression(expr)?;
228                }
229            }
230            if let Some((_, offset, count)) = &d.limit {
231                if let Some(o) = offset {
232                    v.visit_expression(o)?;
233                }
234                v.visit_expression(count)?;
235            }
236            if let Some((_, exprs)) = &d.returning {
237                for se in exprs {
238                    v.visit_expression(&se.expr)?;
239                }
240            }
241            Ok(V::T::default())
242        }
243
244        Statement::Values(vals) => {
245            for row in &vals.rows {
246                for expr in row {
247                    v.visit_expression(expr)?;
248                }
249            }
250            if let Some((_, items)) = &vals.order_by {
251                for (expr, _) in items {
252                    v.visit_expression(expr)?;
253                }
254            }
255            if let Some((_, expr)) = &vals.limit {
256                v.visit_expression(expr)?;
257            }
258            if let Some((_, expr)) = &vals.offset {
259                v.visit_expression(expr)?;
260            }
261            if let Some(fetch) = &vals.fetch
262                && let Some(expr) = &fetch.count
263            {
264                v.visit_expression(expr)?;
265            }
266            Ok(V::T::default())
267        }
268
269        Statement::Set(s) => {
270            for (_, exprs) in &s.values {
271                for expr in exprs {
272                    v.visit_expression(expr)?;
273                }
274            }
275            Ok(V::T::default())
276        }
277
278        Statement::Call(c) => {
279            for expr in &c.args {
280                v.visit_expression(expr)?;
281            }
282            Ok(V::T::default())
283        }
284
285        // -- Expression-bearing statements ------------------------------------------
286        Statement::Return(r) => v.visit_expression(&r.expr),
287        Statement::Perform(p) => v.visit_expression(&p.expr),
288
289        Statement::Raise(r) => {
290            for expr in &r.args {
291                v.visit_expression(expr)?;
292            }
293            for (_, _, expr) in &r.using {
294                v.visit_expression(expr)?;
295            }
296            Ok(V::T::default())
297        }
298
299        Statement::Assign(a) => {
300            v.visit_expression(&a.target)?;
301            v.visit_select(&a.value)
302        }
303
304        Statement::PlpgsqlExecute(e) => {
305            v.visit_expression(&e.command)?;
306            for expr in &e.using {
307                v.visit_expression(expr)?;
308            }
309            Ok(V::T::default())
310        }
311
312        // -- Control-flow / compound statements ---------------------------------------
313        Statement::Block(b) => {
314            for stmt in &b.statements {
315                v.visit_statement(stmt)?;
316            }
317            for handler in &b.exception_handlers {
318                for stmt in &handler.statements {
319                    v.visit_statement(stmt)?;
320                }
321            }
322            Ok(V::T::default())
323        }
324
325        Statement::If(i) => {
326            for cond in &i.conditions {
327                v.visit_select(&cond.search_condition)?;
328                for stmt in &cond.then {
329                    v.visit_statement(stmt)?;
330                }
331            }
332            if let Some((_, stmts)) = &i.else_ {
333                for stmt in stmts {
334                    v.visit_statement(stmt)?;
335                }
336            }
337            Ok(V::T::default())
338        }
339
340        Statement::While(w) => {
341            v.visit_expression(&w.condition)?;
342            for stmt in &w.body {
343                v.visit_statement(stmt)?;
344            }
345            Ok(V::T::default())
346        }
347
348        Statement::Loop(l) => {
349            for stmt in &l.body {
350                v.visit_statement(stmt)?;
351            }
352            Ok(V::T::default())
353        }
354
355        Statement::Repeat(r) => {
356            for stmt in &r.body {
357                v.visit_statement(stmt)?;
358            }
359            v.visit_expression(&r.condition)
360        }
361
362        Statement::Case(c) => {
363            if let Some(expr) = &c.value {
364                v.visit_expression(expr)?;
365            }
366            for when in &c.whens {
367                v.visit_expression(&when.when)?;
368                for stmt in &when.then {
369                    v.visit_statement(stmt)?;
370                }
371            }
372            if let Some((_, stmts)) = &c.else_ {
373                for stmt in stmts {
374                    v.visit_statement(stmt)?;
375                }
376            }
377            Ok(V::T::default())
378        }
379
380        // -- Statement wrappers -------------------------------------------------------
381        Statement::Explain(e) => v.visit_statement(&e.statement),
382        Statement::DeclareCursor(d) => v.visit_statement(&d.query),
383        Statement::DeclareCursorMariaDb(d) => v.visit_select(&d.query),
384        Statement::DeclareHandler(d) => v.visit_statement(&d.statement),
385        Statement::Prepare(p) => v.visit_statement(&p.statement),
386
387        Statement::DeclareVariable(d) => {
388            if let Some((_, sel)) = &d.default {
389                v.visit_select(sel)?;
390            }
391            Ok(V::T::default())
392        }
393
394        Statement::Do(d) => {
395            if let DoBody::Statements(stmts) = &d.body {
396                for stmt in stmts {
397                    v.visit_statement(stmt)?;
398                }
399            }
400            Ok(V::T::default())
401        }
402
403        // -- Leaf statements (DDL, TCL, SHOW, ...) -------------------------------------
404        // These have no child expressions or statements to recurse into.
405        Statement::AlterSchema(_)
406        | Statement::AlterTable(_)
407        | Statement::AlterRole(_)
408        | Statement::AlterSequence(_)
409        | Statement::AlterType(_)
410        | Statement::AlterOperator(_)
411        | Statement::AlterOperatorClass(_)
412        | Statement::AlterOperatorFamily(_)
413        | Statement::CreateIndex(_)
414        | Statement::CreateTable(_)
415        | Statement::CreateView(_)
416        | Statement::CreateTrigger(_)
417        | Statement::CreateFunction(_)
418        | Statement::CreateProcedure(_)
419        | Statement::CreateDatabase(_)
420        | Statement::CreateSchema(_)
421        | Statement::CreateSequence(_)
422        | Statement::CreateServer(_)
423        | Statement::CreateRole(_)
424        | Statement::CreateOperator(_)
425        | Statement::CreateTypeEnum(_)
426        | Statement::CreateOperatorClass(_)
427        | Statement::CreateOperatorFamily(_)
428        | Statement::CreateExtension(_)
429        | Statement::CreateDomain(_)
430        | Statement::CreateConstraintTrigger(_)
431        | Statement::CreateTablePartitionOf(_)
432        | Statement::DropIndex(_)
433        | Statement::DropTable(_)
434        | Statement::DropFunction(_)
435        | Statement::DropProcedure(_)
436        | Statement::DropSequence(_)
437        | Statement::DropEvent(_)
438        | Statement::DropDatabase(_)
439        | Statement::DropSchema(_)
440        | Statement::DropServer(_)
441        | Statement::DropTrigger(_)
442        | Statement::DropView(_)
443        | Statement::DropExtension(_)
444        | Statement::DropOperator(_)
445        | Statement::DropOperatorFamily(_)
446        | Statement::DropOperatorClass(_)
447        | Statement::DropDomain(_)
448        | Statement::DropType(_)
449        | Statement::RenameTable(_)
450        | Statement::TruncateTable(_)
451        | Statement::RefreshMaterializedView(_)
452        | Statement::CommentOn(_)
453        | Statement::Signal(_)
454        | Statement::Kill(_)
455        | Statement::ShowTables(_)
456        | Statement::ShowDatabases(_)
457        | Statement::ShowProcessList(_)
458        | Statement::ShowVariables(_)
459        | Statement::ShowStatus(_)
460        | Statement::ShowColumns(_)
461        | Statement::ShowCreateTable(_)
462        | Statement::ShowCreateDatabase(_)
463        | Statement::ShowCreateView(_)
464        | Statement::ShowCharacterSet(_)
465        | Statement::ShowCollation(_)
466        | Statement::ShowEngines(_)
467        | Statement::Flush(_)
468        | Statement::Unlock(_)
469        | Statement::Lock(_)
470        | Statement::Begin(_)
471        | Statement::End(_)
472        | Statement::Commit(_)
473        | Statement::StartTransaction(_)
474        | Statement::CopyFrom(_)
475        | Statement::CopyTo(_)
476        | Statement::Stdin(_)
477        | Statement::OpenCursor(_)
478        | Statement::CloseCursor(_)
479        | Statement::FetchCursor(_)
480        | Statement::Leave(_)
481        | Statement::Iterate(_)
482        | Statement::Grant(_)
483        | Statement::ExecuteFunction(_)
484        | Statement::Analyze(_)
485        | Statement::Invalid(_) => Ok(V::T::default()),
486    }
487}
488
489/// Default recursion for [`Expression`] nodes.
490pub fn walk_expression<'a, V: Visitor<'a>>(v: &mut V, expr: &Expression<'a>) -> Result<V::T, V::E> {
491    match expr {
492        Expression::Binary(e) => {
493            v.visit_expression(&e.lhs)?;
494            v.visit_expression(&e.rhs)
495        }
496        Expression::Unary(e) => v.visit_expression(&e.operand),
497        Expression::Subquery(e) => v.visit_statement(&e.expression),
498        Expression::Exists(e) => v.visit_statement(&e.subquery),
499        Expression::Extract(e) => v.visit_expression(&e.date),
500        Expression::Trim(e) => {
501            if let Some(what) = &e.what {
502                v.visit_expression(what)?;
503            }
504            v.visit_expression(&e.value)
505        }
506        Expression::In(e) => {
507            v.visit_expression(&e.lhs)?;
508            for rhs_expr in &e.rhs {
509                v.visit_expression(rhs_expr)?;
510            }
511            Ok(V::T::default())
512        }
513        Expression::Between(e) => {
514            v.visit_expression(&e.lhs)?;
515            v.visit_expression(&e.low)?;
516            v.visit_expression(&e.high)
517        }
518        Expression::Like(e) => {
519            v.visit_expression(&e.lhs)?;
520            v.visit_expression(&e.rhs)?;
521            if let Some(escape) = &e.escape {
522                v.visit_expression(escape)?;
523            }
524            Ok(V::T::default())
525        }
526        Expression::MemberOf(e) => {
527            v.visit_expression(&e.lhs)?;
528            v.visit_expression(&e.rhs)
529        }
530        Expression::Is(e) => {
531            v.visit_expression(&e.lhs)?;
532            match &e.is {
533                Is::DistinctFrom(rhs) | Is::NotDistinctFrom(rhs) => v.visit_expression(rhs),
534                _ => Ok(V::T::default()),
535            }
536        }
537        Expression::Case(e) => {
538            if let Some(val) = &e.value {
539                v.visit_expression(val)?;
540            }
541            for when in &e.whens {
542                v.visit_expression(&when.when)?;
543                v.visit_expression(&when.then)?;
544            }
545            if let Some((_, else_expr)) = &e.else_ {
546                v.visit_expression(else_expr)?;
547            }
548            Ok(V::T::default())
549        }
550        Expression::Cast(e) => v.visit_expression(&e.expr),
551        Expression::Convert(e) => v.visit_expression(&e.expr),
552        Expression::TypeCast(e) => v.visit_expression(&e.expr),
553        Expression::Function(e) => {
554            for arg in &e.args {
555                v.visit_expression(arg)?;
556            }
557            Ok(V::T::default())
558        }
559        Expression::WindowFunction(e) => {
560            for arg in &e.args {
561                v.visit_expression(arg)?;
562            }
563            walk_window_spec(v, &e.over.window_spec)
564        }
565        Expression::AggregateFunction(e) => {
566            for arg in &e.args {
567                v.visit_expression(arg)?;
568            }
569            if let Some((_, items)) = &e.within_group {
570                for (expr, _) in items {
571                    v.visit_expression(expr)?;
572                }
573            }
574            if let Some((_, expr)) = &e.filter {
575                v.visit_expression(expr)?;
576            }
577            if let Some(over) = &e.over {
578                walk_window_spec(v, &over.window_spec)?;
579            }
580            Ok(V::T::default())
581        }
582        Expression::Char(e) => {
583            for arg in &e.args {
584                v.visit_expression(arg)?;
585            }
586            Ok(V::T::default())
587        }
588        Expression::GroupConcat(e) => v.visit_expression(&e.expr),
589        Expression::TimestampAdd(e) => {
590            v.visit_expression(&e.interval)?;
591            v.visit_expression(&e.datetime)
592        }
593        Expression::TimestampDiff(e) => {
594            v.visit_expression(&e.e1)?;
595            v.visit_expression(&e.e2)
596        }
597        Expression::MatchAgainst(e) => {
598            for col in &e.columns {
599                v.visit_expression(col)?;
600            }
601            v.visit_expression(&e.expr)
602        }
603        Expression::Array(e) => {
604            for elem in &e.elements {
605                v.visit_expression(elem)?;
606            }
607            Ok(V::T::default())
608        }
609        Expression::ArraySubscript(e) => {
610            v.visit_expression(&e.expr)?;
611            v.visit_expression(&e.lower)?;
612            if let Some(upper) = &e.upper {
613                v.visit_expression(upper)?;
614            }
615            Ok(V::T::default())
616        }
617        Expression::Quantifier(e) => v.visit_expression(&e.operand),
618        Expression::FieldAccess(e) => v.visit_expression(&e.expr),
619        Expression::Row(e) => {
620            for elem in &e.elements {
621                v.visit_expression(elem)?;
622            }
623            Ok(V::T::default())
624        }
625        // Leaf expressions - no children to recurse into.
626        Expression::Null(_)
627        | Expression::Default(_)
628        | Expression::Bool(_)
629        | Expression::String(_)
630        | Expression::Integer(_)
631        | Expression::Float(_)
632        | Expression::ListHack(_)
633        | Expression::Arg(_)
634        | Expression::Identifier(_)
635        | Expression::Variable(_)
636        | Expression::UserVariable(_)
637        | Expression::Interval(_)
638        | Expression::Invalid(_) => Ok(V::T::default()),
639    }
640}
641
642/// Default recursion for [`Select`] nodes.
643pub fn walk_select<'a, V: Visitor<'a>>(v: &mut V, select: &Select<'a>) -> Result<V::T, V::E> {
644    for se in &select.select_exprs {
645        v.visit_expression(&se.expr)?;
646    }
647    if let Some(refs) = &select.table_references {
648        for tr in refs {
649            v.visit_table_reference(tr)?;
650        }
651    }
652    if let Some((expr, _)) = &select.where_ {
653        v.visit_expression(expr)?;
654    }
655    if let Some((_, exprs)) = &select.group_by {
656        for expr in exprs {
657            v.visit_expression(expr)?;
658        }
659    }
660    if let Some((expr, _)) = &select.having {
661        v.visit_expression(expr)?;
662    }
663    if let Some((_, items)) = &select.order_by {
664        for (expr, _) in items {
665            v.visit_expression(expr)?;
666        }
667    }
668    if let Some((_, offset, count)) = &select.limit {
669        if let Some(o) = offset {
670            v.visit_expression(o)?;
671        }
672        v.visit_expression(count)?;
673    }
674    if let Some((_, exprs)) = &select.distinct_on {
675        for expr in exprs {
676            v.visit_expression(expr)?;
677        }
678    }
679    if let Some((_, expr)) = &select.offset {
680        v.visit_expression(expr)?;
681    }
682    if let Some((_, expr)) = &select.fetch {
683        v.visit_expression(expr)?;
684    }
685    Ok(V::T::default())
686}
687
688/// Default recursion for [`TableReference`] nodes.
689pub fn walk_table_reference<'a, V: Visitor<'a>>(
690    v: &mut V,
691    tr: &TableReference<'a>,
692) -> Result<V::T, V::E> {
693    match tr {
694        TableReference::Table { .. } => Ok(V::T::default()),
695        TableReference::Query { query, .. } => v.visit_statement(query),
696        TableReference::JsonTable {
697            json_expr,
698            path,
699            columns,
700            ..
701        } => {
702            v.visit_expression(json_expr)?;
703            v.visit_expression(path)?;
704            for col in columns {
705                walk_json_table_column(v, col)?;
706            }
707            Ok(V::T::default())
708        }
709        TableReference::Function { args, .. } => {
710            for arg in args {
711                v.visit_expression(arg)?;
712            }
713            Ok(V::T::default())
714        }
715        TableReference::Join {
716            left,
717            right,
718            specification,
719            ..
720        } => {
721            v.visit_table_reference(left)?;
722            v.visit_table_reference(right)?;
723            if let Some(JoinSpecification::On(expr, _)) = specification {
724                v.visit_expression(expr)?;
725            }
726            Ok(V::T::default())
727        }
728    }
729}