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 (_, expr) in &s.values {
271                v.visit_expression(expr)?;
272            }
273            Ok(V::T::default())
274        }
275
276        Statement::Call(c) => {
277            for expr in &c.args {
278                v.visit_expression(expr)?;
279            }
280            Ok(V::T::default())
281        }
282
283        // -- Expression-bearing statements ------------------------------------------
284        Statement::Return(r) => v.visit_expression(&r.expr),
285        Statement::Perform(p) => v.visit_expression(&p.expr),
286
287        Statement::Raise(r) => {
288            for expr in &r.args {
289                v.visit_expression(expr)?;
290            }
291            for (_, _, expr) in &r.using {
292                v.visit_expression(expr)?;
293            }
294            Ok(V::T::default())
295        }
296
297        Statement::Assign(a) => {
298            v.visit_expression(&a.target)?;
299            v.visit_select(&a.value)
300        }
301
302        Statement::PlpgsqlExecute(e) => {
303            v.visit_expression(&e.command)?;
304            for expr in &e.using {
305                v.visit_expression(expr)?;
306            }
307            Ok(V::T::default())
308        }
309
310        // -- Control-flow / compound statements ---------------------------------------
311        Statement::Block(b) => {
312            for stmt in &b.statements {
313                v.visit_statement(stmt)?;
314            }
315            for handler in &b.exception_handlers {
316                for stmt in &handler.statements {
317                    v.visit_statement(stmt)?;
318                }
319            }
320            Ok(V::T::default())
321        }
322
323        Statement::If(i) => {
324            for cond in &i.conditions {
325                v.visit_select(&cond.search_condition)?;
326                for stmt in &cond.then {
327                    v.visit_statement(stmt)?;
328                }
329            }
330            if let Some((_, stmts)) = &i.else_ {
331                for stmt in stmts {
332                    v.visit_statement(stmt)?;
333                }
334            }
335            Ok(V::T::default())
336        }
337
338        Statement::While(w) => {
339            v.visit_expression(&w.condition)?;
340            for stmt in &w.body {
341                v.visit_statement(stmt)?;
342            }
343            Ok(V::T::default())
344        }
345
346        Statement::Loop(l) => {
347            for stmt in &l.body {
348                v.visit_statement(stmt)?;
349            }
350            Ok(V::T::default())
351        }
352
353        Statement::Repeat(r) => {
354            for stmt in &r.body {
355                v.visit_statement(stmt)?;
356            }
357            v.visit_expression(&r.condition)
358        }
359
360        Statement::Case(c) => {
361            if let Some(expr) = &c.value {
362                v.visit_expression(expr)?;
363            }
364            for when in &c.whens {
365                v.visit_expression(&when.when)?;
366                for stmt in &when.then {
367                    v.visit_statement(stmt)?;
368                }
369            }
370            if let Some((_, stmts)) = &c.else_ {
371                for stmt in stmts {
372                    v.visit_statement(stmt)?;
373                }
374            }
375            Ok(V::T::default())
376        }
377
378        // -- Statement wrappers -------------------------------------------------------
379        Statement::Explain(e) => v.visit_statement(&e.statement),
380        Statement::DeclareCursor(d) => v.visit_statement(&d.query),
381        Statement::DeclareCursorMariaDb(d) => v.visit_select(&d.query),
382        Statement::DeclareHandler(d) => v.visit_statement(&d.statement),
383        Statement::Prepare(p) => v.visit_statement(&p.statement),
384
385        Statement::DeclareVariable(d) => {
386            if let Some((_, sel)) = &d.default {
387                v.visit_select(sel)?;
388            }
389            Ok(V::T::default())
390        }
391
392        Statement::Do(d) => {
393            if let DoBody::Statements(stmts) = &d.body {
394                for stmt in stmts {
395                    v.visit_statement(stmt)?;
396                }
397            }
398            Ok(V::T::default())
399        }
400
401        // -- Leaf statements (DDL, TCL, SHOW, ...) -------------------------------------
402        // These have no child expressions or statements to recurse into.
403        Statement::AlterSchema(_)
404        | Statement::AlterTable(_)
405        | Statement::AlterRole(_)
406        | Statement::AlterType(_)
407        | Statement::AlterOperator(_)
408        | Statement::AlterOperatorClass(_)
409        | Statement::AlterOperatorFamily(_)
410        | Statement::CreateIndex(_)
411        | Statement::CreateTable(_)
412        | Statement::CreateView(_)
413        | Statement::CreateTrigger(_)
414        | Statement::CreateFunction(_)
415        | Statement::CreateProcedure(_)
416        | Statement::CreateDatabase(_)
417        | Statement::CreateSchema(_)
418        | Statement::CreateSequence(_)
419        | Statement::CreateServer(_)
420        | Statement::CreateRole(_)
421        | Statement::CreateOperator(_)
422        | Statement::CreateTypeEnum(_)
423        | Statement::CreateOperatorClass(_)
424        | Statement::CreateOperatorFamily(_)
425        | Statement::CreateExtension(_)
426        | Statement::CreateDomain(_)
427        | Statement::CreateConstraintTrigger(_)
428        | Statement::CreateTablePartitionOf(_)
429        | Statement::DropIndex(_)
430        | Statement::DropTable(_)
431        | Statement::DropFunction(_)
432        | Statement::DropProcedure(_)
433        | Statement::DropSequence(_)
434        | Statement::DropEvent(_)
435        | Statement::DropDatabase(_)
436        | Statement::DropServer(_)
437        | Statement::DropTrigger(_)
438        | Statement::DropView(_)
439        | Statement::DropExtension(_)
440        | Statement::DropOperator(_)
441        | Statement::DropOperatorFamily(_)
442        | Statement::DropOperatorClass(_)
443        | Statement::DropDomain(_)
444        | Statement::DropType(_)
445        | Statement::RenameTable(_)
446        | Statement::TruncateTable(_)
447        | Statement::RefreshMaterializedView(_)
448        | Statement::CommentOn(_)
449        | Statement::Signal(_)
450        | Statement::Kill(_)
451        | Statement::ShowTables(_)
452        | Statement::ShowDatabases(_)
453        | Statement::ShowProcessList(_)
454        | Statement::ShowVariables(_)
455        | Statement::ShowStatus(_)
456        | Statement::ShowColumns(_)
457        | Statement::ShowCreateTable(_)
458        | Statement::ShowCreateDatabase(_)
459        | Statement::ShowCreateView(_)
460        | Statement::ShowCharacterSet(_)
461        | Statement::ShowCollation(_)
462        | Statement::ShowEngines(_)
463        | Statement::Flush(_)
464        | Statement::Unlock(_)
465        | Statement::Lock(_)
466        | Statement::Begin(_)
467        | Statement::End(_)
468        | Statement::Commit(_)
469        | Statement::StartTransaction(_)
470        | Statement::CopyFrom(_)
471        | Statement::CopyTo(_)
472        | Statement::Stdin(_)
473        | Statement::OpenCursor(_)
474        | Statement::CloseCursor(_)
475        | Statement::FetchCursor(_)
476        | Statement::Leave(_)
477        | Statement::Iterate(_)
478        | Statement::Grant(_)
479        | Statement::ExecuteFunction(_)
480        | Statement::Analyze(_)
481        | Statement::Invalid(_) => Ok(V::T::default()),
482    }
483}
484
485/// Default recursion for [`Expression`] nodes.
486pub fn walk_expression<'a, V: Visitor<'a>>(v: &mut V, expr: &Expression<'a>) -> Result<V::T, V::E> {
487    match expr {
488        Expression::Binary(e) => {
489            v.visit_expression(&e.lhs)?;
490            v.visit_expression(&e.rhs)
491        }
492        Expression::Unary(e) => v.visit_expression(&e.operand),
493        Expression::Subquery(e) => v.visit_statement(&e.expression),
494        Expression::Exists(e) => v.visit_statement(&e.subquery),
495        Expression::Extract(e) => v.visit_expression(&e.date),
496        Expression::Trim(e) => {
497            if let Some(what) = &e.what {
498                v.visit_expression(what)?;
499            }
500            v.visit_expression(&e.value)
501        }
502        Expression::In(e) => {
503            v.visit_expression(&e.lhs)?;
504            for rhs_expr in &e.rhs {
505                v.visit_expression(rhs_expr)?;
506            }
507            Ok(V::T::default())
508        }
509        Expression::Between(e) => {
510            v.visit_expression(&e.lhs)?;
511            v.visit_expression(&e.low)?;
512            v.visit_expression(&e.high)
513        }
514        Expression::MemberOf(e) => {
515            v.visit_expression(&e.lhs)?;
516            v.visit_expression(&e.rhs)
517        }
518        Expression::Is(e) => {
519            v.visit_expression(&e.lhs)?;
520            match &e.is {
521                Is::DistinctFrom(rhs) | Is::NotDistinctFrom(rhs) => v.visit_expression(rhs),
522                _ => Ok(V::T::default()),
523            }
524        }
525        Expression::Case(e) => {
526            if let Some(val) = &e.value {
527                v.visit_expression(val)?;
528            }
529            for when in &e.whens {
530                v.visit_expression(&when.when)?;
531                v.visit_expression(&when.then)?;
532            }
533            if let Some((_, else_expr)) = &e.else_ {
534                v.visit_expression(else_expr)?;
535            }
536            Ok(V::T::default())
537        }
538        Expression::Cast(e) => v.visit_expression(&e.expr),
539        Expression::Convert(e) => v.visit_expression(&e.expr),
540        Expression::TypeCast(e) => v.visit_expression(&e.expr),
541        Expression::Function(e) => {
542            for arg in &e.args {
543                v.visit_expression(arg)?;
544            }
545            Ok(V::T::default())
546        }
547        Expression::WindowFunction(e) => {
548            for arg in &e.args {
549                v.visit_expression(arg)?;
550            }
551            walk_window_spec(v, &e.over.window_spec)
552        }
553        Expression::AggregateFunction(e) => {
554            for arg in &e.args {
555                v.visit_expression(arg)?;
556            }
557            if let Some((_, items)) = &e.within_group {
558                for (expr, _) in items {
559                    v.visit_expression(expr)?;
560                }
561            }
562            if let Some((_, expr)) = &e.filter {
563                v.visit_expression(expr)?;
564            }
565            if let Some(over) = &e.over {
566                walk_window_spec(v, &over.window_spec)?;
567            }
568            Ok(V::T::default())
569        }
570        Expression::Char(e) => {
571            for arg in &e.args {
572                v.visit_expression(arg)?;
573            }
574            Ok(V::T::default())
575        }
576        Expression::GroupConcat(e) => v.visit_expression(&e.expr),
577        Expression::TimestampAdd(e) => {
578            v.visit_expression(&e.interval)?;
579            v.visit_expression(&e.datetime)
580        }
581        Expression::TimestampDiff(e) => {
582            v.visit_expression(&e.e1)?;
583            v.visit_expression(&e.e2)
584        }
585        Expression::MatchAgainst(e) => {
586            for col in &e.columns {
587                v.visit_expression(col)?;
588            }
589            v.visit_expression(&e.expr)
590        }
591        Expression::Array(e) => {
592            for elem in &e.elements {
593                v.visit_expression(elem)?;
594            }
595            Ok(V::T::default())
596        }
597        Expression::ArraySubscript(e) => {
598            v.visit_expression(&e.expr)?;
599            v.visit_expression(&e.lower)?;
600            if let Some(upper) = &e.upper {
601                v.visit_expression(upper)?;
602            }
603            Ok(V::T::default())
604        }
605        Expression::Quantifier(e) => v.visit_expression(&e.operand),
606        Expression::FieldAccess(e) => v.visit_expression(&e.expr),
607        Expression::Row(e) => {
608            for elem in &e.elements {
609                v.visit_expression(elem)?;
610            }
611            Ok(V::T::default())
612        }
613        // Leaf expressions - no children to recurse into.
614        Expression::Null(_)
615        | Expression::Default(_)
616        | Expression::Bool(_)
617        | Expression::String(_)
618        | Expression::Integer(_)
619        | Expression::Float(_)
620        | Expression::ListHack(_)
621        | Expression::Arg(_)
622        | Expression::Identifier(_)
623        | Expression::Variable(_)
624        | Expression::UserVariable(_)
625        | Expression::Interval(_)
626        | Expression::Invalid(_) => Ok(V::T::default()),
627    }
628}
629
630/// Default recursion for [`Select`] nodes.
631pub fn walk_select<'a, V: Visitor<'a>>(v: &mut V, select: &Select<'a>) -> Result<V::T, V::E> {
632    for se in &select.select_exprs {
633        v.visit_expression(&se.expr)?;
634    }
635    if let Some(refs) = &select.table_references {
636        for tr in refs {
637            v.visit_table_reference(tr)?;
638        }
639    }
640    if let Some((expr, _)) = &select.where_ {
641        v.visit_expression(expr)?;
642    }
643    if let Some((_, exprs)) = &select.group_by {
644        for expr in exprs {
645            v.visit_expression(expr)?;
646        }
647    }
648    if let Some((expr, _)) = &select.having {
649        v.visit_expression(expr)?;
650    }
651    if let Some((_, items)) = &select.order_by {
652        for (expr, _) in items {
653            v.visit_expression(expr)?;
654        }
655    }
656    if let Some((_, offset, count)) = &select.limit {
657        if let Some(o) = offset {
658            v.visit_expression(o)?;
659        }
660        v.visit_expression(count)?;
661    }
662    if let Some((_, exprs)) = &select.distinct_on {
663        for expr in exprs {
664            v.visit_expression(expr)?;
665        }
666    }
667    if let Some((_, expr)) = &select.offset {
668        v.visit_expression(expr)?;
669    }
670    if let Some((_, expr)) = &select.fetch {
671        v.visit_expression(expr)?;
672    }
673    Ok(V::T::default())
674}
675
676/// Default recursion for [`TableReference`] nodes.
677pub fn walk_table_reference<'a, V: Visitor<'a>>(
678    v: &mut V,
679    tr: &TableReference<'a>,
680) -> Result<V::T, V::E> {
681    match tr {
682        TableReference::Table { .. } => Ok(V::T::default()),
683        TableReference::Query { query, .. } => v.visit_statement(query),
684        TableReference::JsonTable {
685            json_expr,
686            path,
687            columns,
688            ..
689        } => {
690            v.visit_expression(json_expr)?;
691            v.visit_expression(path)?;
692            for col in columns {
693                walk_json_table_column(v, col)?;
694            }
695            Ok(V::T::default())
696        }
697        TableReference::Function { args, .. } => {
698            for arg in args {
699                v.visit_expression(arg)?;
700            }
701            Ok(V::T::default())
702        }
703        TableReference::Join {
704            left,
705            right,
706            specification,
707            ..
708        } => {
709            v.visit_table_reference(left)?;
710            v.visit_table_reference(right)?;
711            if let Some(JoinSpecification::On(expr, _)) = specification {
712                v.visit_expression(expr)?;
713            }
714            Ok(V::T::default())
715        }
716    }
717}