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 (_, 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 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 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::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 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
485pub 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 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
630pub 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
676pub 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}