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::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
488pub 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 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
633pub 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
679pub 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}