1use crate::{
2 DoBody, Expression, Is, JoinSpecification, JsonTableColumn, JsonTableOnErrorEmpty,
3 OnConflictAction, Select, Statement, TableReference, WindowFrameBound, WindowSpec,
4};
5
6pub trait Visitor<'a>: Sized {
22 type T: Default;
24 type E;
26
27 fn visit_statement(&mut self, stmt: &Statement<'a>) -> Result<Self::T, Self::E> {
29 walk_statement(self, stmt)
30 }
31
32 fn visit_expression(&mut self, expr: &Expression<'a>) -> Result<Self::T, Self::E> {
34 walk_expression(self, expr)
35 }
36
37 fn visit_select(&mut self, select: &Select<'a>) -> Result<Self::T, Self::E> {
40 walk_select(self, select)
41 }
42
43 fn visit_table_reference(&mut self, tr: &TableReference<'a>) -> Result<Self::T, Self::E> {
46 walk_table_reference(self, tr)
47 }
48}
49
50fn 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
73fn 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
89fn 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
122pub fn walk_statement<'a, V: Visitor<'a>>(v: &mut V, stmt: &Statement<'a>) -> Result<V::T, V::E> {
126 match stmt {
127 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 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 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::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 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
489pub 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 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
642pub 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
688pub 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}