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::AlterType(_)
409        | Statement::AlterOperator(_)
410        | Statement::AlterOperatorClass(_)
411        | Statement::AlterOperatorFamily(_)
412        | Statement::CreateIndex(_)
413        | Statement::CreateTable(_)
414        | Statement::CreateView(_)
415        | Statement::CreateTrigger(_)
416        | Statement::CreateFunction(_)
417        | Statement::CreateProcedure(_)
418        | Statement::CreateDatabase(_)
419        | Statement::CreateSchema(_)
420        | Statement::CreateSequence(_)
421        | Statement::CreateServer(_)
422        | Statement::CreateRole(_)
423        | Statement::CreateOperator(_)
424        | Statement::CreateTypeEnum(_)
425        | Statement::CreateOperatorClass(_)
426        | Statement::CreateOperatorFamily(_)
427        | Statement::CreateExtension(_)
428        | Statement::CreateDomain(_)
429        | Statement::CreateConstraintTrigger(_)
430        | Statement::CreateTablePartitionOf(_)
431        | Statement::DropIndex(_)
432        | Statement::DropTable(_)
433        | Statement::DropFunction(_)
434        | Statement::DropProcedure(_)
435        | Statement::DropSequence(_)
436        | Statement::DropEvent(_)
437        | Statement::DropDatabase(_)
438        | Statement::DropSchema(_)
439        | Statement::DropServer(_)
440        | Statement::DropTrigger(_)
441        | Statement::DropView(_)
442        | Statement::DropExtension(_)
443        | Statement::DropOperator(_)
444        | Statement::DropOperatorFamily(_)
445        | Statement::DropOperatorClass(_)
446        | Statement::DropDomain(_)
447        | Statement::DropType(_)
448        | Statement::RenameTable(_)
449        | Statement::TruncateTable(_)
450        | Statement::RefreshMaterializedView(_)
451        | Statement::CommentOn(_)
452        | Statement::Signal(_)
453        | Statement::Kill(_)
454        | Statement::ShowTables(_)
455        | Statement::ShowDatabases(_)
456        | Statement::ShowProcessList(_)
457        | Statement::ShowVariables(_)
458        | Statement::ShowStatus(_)
459        | Statement::ShowColumns(_)
460        | Statement::ShowCreateTable(_)
461        | Statement::ShowCreateDatabase(_)
462        | Statement::ShowCreateView(_)
463        | Statement::ShowCharacterSet(_)
464        | Statement::ShowCollation(_)
465        | Statement::ShowEngines(_)
466        | Statement::Flush(_)
467        | Statement::Unlock(_)
468        | Statement::Lock(_)
469        | Statement::Begin(_)
470        | Statement::End(_)
471        | Statement::Commit(_)
472        | Statement::StartTransaction(_)
473        | Statement::CopyFrom(_)
474        | Statement::CopyTo(_)
475        | Statement::Stdin(_)
476        | Statement::OpenCursor(_)
477        | Statement::CloseCursor(_)
478        | Statement::FetchCursor(_)
479        | Statement::Leave(_)
480        | Statement::Iterate(_)
481        | Statement::Grant(_)
482        | Statement::ExecuteFunction(_)
483        | Statement::Analyze(_)
484        | Statement::Invalid(_) => Ok(V::T::default()),
485    }
486}
487
488/// Default recursion for [`Expression`] nodes.
489pub fn walk_expression<'a, V: Visitor<'a>>(v: &mut V, expr: &Expression<'a>) -> Result<V::T, V::E> {
490    match expr {
491        Expression::Binary(e) => {
492            v.visit_expression(&e.lhs)?;
493            v.visit_expression(&e.rhs)
494        }
495        Expression::Unary(e) => v.visit_expression(&e.operand),
496        Expression::Subquery(e) => v.visit_statement(&e.expression),
497        Expression::Exists(e) => v.visit_statement(&e.subquery),
498        Expression::Extract(e) => v.visit_expression(&e.date),
499        Expression::Trim(e) => {
500            if let Some(what) = &e.what {
501                v.visit_expression(what)?;
502            }
503            v.visit_expression(&e.value)
504        }
505        Expression::In(e) => {
506            v.visit_expression(&e.lhs)?;
507            for rhs_expr in &e.rhs {
508                v.visit_expression(rhs_expr)?;
509            }
510            Ok(V::T::default())
511        }
512        Expression::Between(e) => {
513            v.visit_expression(&e.lhs)?;
514            v.visit_expression(&e.low)?;
515            v.visit_expression(&e.high)
516        }
517        Expression::MemberOf(e) => {
518            v.visit_expression(&e.lhs)?;
519            v.visit_expression(&e.rhs)
520        }
521        Expression::Is(e) => {
522            v.visit_expression(&e.lhs)?;
523            match &e.is {
524                Is::DistinctFrom(rhs) | Is::NotDistinctFrom(rhs) => v.visit_expression(rhs),
525                _ => Ok(V::T::default()),
526            }
527        }
528        Expression::Case(e) => {
529            if let Some(val) = &e.value {
530                v.visit_expression(val)?;
531            }
532            for when in &e.whens {
533                v.visit_expression(&when.when)?;
534                v.visit_expression(&when.then)?;
535            }
536            if let Some((_, else_expr)) = &e.else_ {
537                v.visit_expression(else_expr)?;
538            }
539            Ok(V::T::default())
540        }
541        Expression::Cast(e) => v.visit_expression(&e.expr),
542        Expression::Convert(e) => v.visit_expression(&e.expr),
543        Expression::TypeCast(e) => v.visit_expression(&e.expr),
544        Expression::Function(e) => {
545            for arg in &e.args {
546                v.visit_expression(arg)?;
547            }
548            Ok(V::T::default())
549        }
550        Expression::WindowFunction(e) => {
551            for arg in &e.args {
552                v.visit_expression(arg)?;
553            }
554            walk_window_spec(v, &e.over.window_spec)
555        }
556        Expression::AggregateFunction(e) => {
557            for arg in &e.args {
558                v.visit_expression(arg)?;
559            }
560            if let Some((_, items)) = &e.within_group {
561                for (expr, _) in items {
562                    v.visit_expression(expr)?;
563                }
564            }
565            if let Some((_, expr)) = &e.filter {
566                v.visit_expression(expr)?;
567            }
568            if let Some(over) = &e.over {
569                walk_window_spec(v, &over.window_spec)?;
570            }
571            Ok(V::T::default())
572        }
573        Expression::Char(e) => {
574            for arg in &e.args {
575                v.visit_expression(arg)?;
576            }
577            Ok(V::T::default())
578        }
579        Expression::GroupConcat(e) => v.visit_expression(&e.expr),
580        Expression::TimestampAdd(e) => {
581            v.visit_expression(&e.interval)?;
582            v.visit_expression(&e.datetime)
583        }
584        Expression::TimestampDiff(e) => {
585            v.visit_expression(&e.e1)?;
586            v.visit_expression(&e.e2)
587        }
588        Expression::MatchAgainst(e) => {
589            for col in &e.columns {
590                v.visit_expression(col)?;
591            }
592            v.visit_expression(&e.expr)
593        }
594        Expression::Array(e) => {
595            for elem in &e.elements {
596                v.visit_expression(elem)?;
597            }
598            Ok(V::T::default())
599        }
600        Expression::ArraySubscript(e) => {
601            v.visit_expression(&e.expr)?;
602            v.visit_expression(&e.lower)?;
603            if let Some(upper) = &e.upper {
604                v.visit_expression(upper)?;
605            }
606            Ok(V::T::default())
607        }
608        Expression::Quantifier(e) => v.visit_expression(&e.operand),
609        Expression::FieldAccess(e) => v.visit_expression(&e.expr),
610        Expression::Row(e) => {
611            for elem in &e.elements {
612                v.visit_expression(elem)?;
613            }
614            Ok(V::T::default())
615        }
616        // Leaf expressions - no children to recurse into.
617        Expression::Null(_)
618        | Expression::Default(_)
619        | Expression::Bool(_)
620        | Expression::String(_)
621        | Expression::Integer(_)
622        | Expression::Float(_)
623        | Expression::ListHack(_)
624        | Expression::Arg(_)
625        | Expression::Identifier(_)
626        | Expression::Variable(_)
627        | Expression::UserVariable(_)
628        | Expression::Interval(_)
629        | Expression::Invalid(_) => Ok(V::T::default()),
630    }
631}
632
633/// Default recursion for [`Select`] nodes.
634pub fn walk_select<'a, V: Visitor<'a>>(v: &mut V, select: &Select<'a>) -> Result<V::T, V::E> {
635    for se in &select.select_exprs {
636        v.visit_expression(&se.expr)?;
637    }
638    if let Some(refs) = &select.table_references {
639        for tr in refs {
640            v.visit_table_reference(tr)?;
641        }
642    }
643    if let Some((expr, _)) = &select.where_ {
644        v.visit_expression(expr)?;
645    }
646    if let Some((_, exprs)) = &select.group_by {
647        for expr in exprs {
648            v.visit_expression(expr)?;
649        }
650    }
651    if let Some((expr, _)) = &select.having {
652        v.visit_expression(expr)?;
653    }
654    if let Some((_, items)) = &select.order_by {
655        for (expr, _) in items {
656            v.visit_expression(expr)?;
657        }
658    }
659    if let Some((_, offset, count)) = &select.limit {
660        if let Some(o) = offset {
661            v.visit_expression(o)?;
662        }
663        v.visit_expression(count)?;
664    }
665    if let Some((_, exprs)) = &select.distinct_on {
666        for expr in exprs {
667            v.visit_expression(expr)?;
668        }
669    }
670    if let Some((_, expr)) = &select.offset {
671        v.visit_expression(expr)?;
672    }
673    if let Some((_, expr)) = &select.fetch {
674        v.visit_expression(expr)?;
675    }
676    Ok(V::T::default())
677}
678
679/// Default recursion for [`TableReference`] nodes.
680pub fn walk_table_reference<'a, V: Visitor<'a>>(
681    v: &mut V,
682    tr: &TableReference<'a>,
683) -> Result<V::T, V::E> {
684    match tr {
685        TableReference::Table { .. } => Ok(V::T::default()),
686        TableReference::Query { query, .. } => v.visit_statement(query),
687        TableReference::JsonTable {
688            json_expr,
689            path,
690            columns,
691            ..
692        } => {
693            v.visit_expression(json_expr)?;
694            v.visit_expression(path)?;
695            for col in columns {
696                walk_json_table_column(v, col)?;
697            }
698            Ok(V::T::default())
699        }
700        TableReference::Function { args, .. } => {
701            for arg in args {
702                v.visit_expression(arg)?;
703            }
704            Ok(V::T::default())
705        }
706        TableReference::Join {
707            left,
708            right,
709            specification,
710            ..
711        } => {
712            v.visit_table_reference(left)?;
713            v.visit_table_reference(right)?;
714            if let Some(JoinSpecification::On(expr, _)) = specification {
715                v.visit_expression(expr)?;
716            }
717            Ok(V::T::default())
718        }
719    }
720}