sqlparser/ast/visitor.rs
1// Licensed under the Apache License, Version 2.0 (the "License");
2// you may not use this file except in compliance with the License.
3// You may obtain a copy of the License at
4//
5// http://www.apache.org/licenses/LICENSE-2.0
6//
7// Unless required by applicable law or agreed to in writing, software
8// distributed under the License is distributed on an "AS IS" BASIS,
9// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10// See the License for the specific language governing permissions and
11// limitations under the License.
12
13//! Recursive visitors for ast Nodes. See [`Visitor`] for more details.
14
15use crate::ast::{Expr, ObjectName, Statement};
16use core::ops::ControlFlow;
17
18/// A type that can be visited by a [`Visitor`]. See [`Visitor`] for
19/// recursively visiting parsed SQL statements.
20///
21/// # Note
22///
23/// This trait should be automatically derived for sqlparser AST nodes
24/// using the [Visit](sqlparser_derive::Visit) proc macro.
25///
26/// ```text
27/// #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
28/// ```
29pub trait Visit {
30 fn visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break>;
31}
32
33/// A type that can be visited by a [`VisitorMut`]. See [`VisitorMut`] for
34/// recursively visiting parsed SQL statements.
35///
36/// # Note
37///
38/// This trait should be automatically derived for sqlparser AST nodes
39/// using the [VisitMut](sqlparser_derive::VisitMut) proc macro.
40///
41/// ```text
42/// #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
43/// ```
44pub trait VisitMut {
45 fn visit<V: VisitorMut>(&mut self, visitor: &mut V) -> ControlFlow<V::Break>;
46}
47
48impl<T: Visit> Visit for Option<T> {
49 fn visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> {
50 if let Some(s) = self {
51 s.visit(visitor)?;
52 }
53 ControlFlow::Continue(())
54 }
55}
56
57impl<T: Visit> Visit for Vec<T> {
58 fn visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> {
59 for v in self {
60 v.visit(visitor)?;
61 }
62 ControlFlow::Continue(())
63 }
64}
65
66impl<T: Visit> Visit for Box<T> {
67 fn visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> {
68 T::visit(self, visitor)
69 }
70}
71
72impl<T: VisitMut> VisitMut for Option<T> {
73 fn visit<V: VisitorMut>(&mut self, visitor: &mut V) -> ControlFlow<V::Break> {
74 if let Some(s) = self {
75 s.visit(visitor)?;
76 }
77 ControlFlow::Continue(())
78 }
79}
80
81impl<T: VisitMut> VisitMut for Vec<T> {
82 fn visit<V: VisitorMut>(&mut self, visitor: &mut V) -> ControlFlow<V::Break> {
83 for v in self {
84 v.visit(visitor)?;
85 }
86 ControlFlow::Continue(())
87 }
88}
89
90impl<T: VisitMut> VisitMut for Box<T> {
91 fn visit<V: VisitorMut>(&mut self, visitor: &mut V) -> ControlFlow<V::Break> {
92 T::visit(self, visitor)
93 }
94}
95
96macro_rules! visit_noop {
97 ($($t:ty),+) => {
98 $(impl Visit for $t {
99 fn visit<V: Visitor>(&self, _visitor: &mut V) -> ControlFlow<V::Break> {
100 ControlFlow::Continue(())
101 }
102 })+
103 $(impl VisitMut for $t {
104 fn visit<V: VisitorMut>(&mut self, _visitor: &mut V) -> ControlFlow<V::Break> {
105 ControlFlow::Continue(())
106 }
107 })+
108 };
109}
110
111visit_noop!(u8, u16, u32, u64, i8, i16, i32, i64, char, bool, String);
112
113#[cfg(feature = "bigdecimal")]
114visit_noop!(bigdecimal::BigDecimal);
115
116/// A visitor that can be used to walk an AST tree.
117///
118/// `previst_` methods are invoked before visiting all children of the
119/// node and `postvisit_` methods are invoked after visiting all
120/// children of the node.
121///
122/// # See also
123///
124/// These methods provide a more concise way of visiting nodes of a certain type:
125/// * [visit_relations]
126/// * [visit_expressions]
127/// * [visit_statements]
128///
129/// # Example
130/// ```
131/// # use sqlparser::parser::Parser;
132/// # use sqlparser::dialect::GenericDialect;
133/// # use sqlparser::ast::{Visit, Visitor, ObjectName, Expr};
134/// # use core::ops::ControlFlow;
135/// // A structure that records statements and relations
136/// #[derive(Default)]
137/// struct V {
138/// visited: Vec<String>,
139/// }
140///
141/// // Visit relations and exprs before children are visited (depth first walk)
142/// // Note you can also visit statements and visit exprs after children have been visitoed
143/// impl Visitor for V {
144/// type Break = ();
145///
146/// fn pre_visit_relation(&mut self, relation: &ObjectName) -> ControlFlow<Self::Break> {
147/// self.visited.push(format!("PRE: RELATION: {}", relation));
148/// ControlFlow::Continue(())
149/// }
150///
151/// fn pre_visit_expr(&mut self, expr: &Expr) -> ControlFlow<Self::Break> {
152/// self.visited.push(format!("PRE: EXPR: {}", expr));
153/// ControlFlow::Continue(())
154/// }
155/// }
156///
157/// let sql = "SELECT a FROM foo where x IN (SELECT y FROM bar)";
158/// let statements = Parser::parse_sql(&GenericDialect{}, sql)
159/// .unwrap();
160///
161/// // Drive the visitor through the AST
162/// let mut visitor = V::default();
163/// statements.visit(&mut visitor);
164///
165/// // The visitor has visited statements and expressions in pre-traversal order
166/// let expected : Vec<_> = [
167/// "PRE: EXPR: a",
168/// "PRE: RELATION: foo",
169/// "PRE: EXPR: x IN (SELECT y FROM bar)",
170/// "PRE: EXPR: x",
171/// "PRE: EXPR: y",
172/// "PRE: RELATION: bar",
173/// ]
174/// .into_iter().map(|s| s.to_string()).collect();
175///
176/// assert_eq!(visitor.visited, expected);
177/// ```
178pub trait Visitor {
179 /// Type returned when the recursion returns early.
180 type Break;
181
182 /// Invoked for any relations (e.g. tables) that appear in the AST before visiting children
183 fn pre_visit_relation(&mut self, _relation: &ObjectName) -> ControlFlow<Self::Break> {
184 ControlFlow::Continue(())
185 }
186
187 /// Invoked for any relations (e.g. tables) that appear in the AST after visiting children
188 fn post_visit_relation(&mut self, _relation: &ObjectName) -> ControlFlow<Self::Break> {
189 ControlFlow::Continue(())
190 }
191
192 /// Invoked for any expressions that appear in the AST before visiting children
193 fn pre_visit_expr(&mut self, _expr: &Expr) -> ControlFlow<Self::Break> {
194 ControlFlow::Continue(())
195 }
196
197 /// Invoked for any expressions that appear in the AST
198 fn post_visit_expr(&mut self, _expr: &Expr) -> ControlFlow<Self::Break> {
199 ControlFlow::Continue(())
200 }
201
202 /// Invoked for any statements that appear in the AST before visiting children
203 fn pre_visit_statement(&mut self, _statement: &Statement) -> ControlFlow<Self::Break> {
204 ControlFlow::Continue(())
205 }
206
207 /// Invoked for any statements that appear in the AST after visiting children
208 fn post_visit_statement(&mut self, _statement: &Statement) -> ControlFlow<Self::Break> {
209 ControlFlow::Continue(())
210 }
211}
212
213/// A visitor that can be used to mutate an AST tree.
214///
215/// `previst_` methods are invoked before visiting all children of the
216/// node and `postvisit_` methods are invoked after visiting all
217/// children of the node.
218///
219/// # See also
220///
221/// These methods provide a more concise way of visiting nodes of a certain type:
222/// * [visit_relations_mut]
223/// * [visit_expressions_mut]
224/// * [visit_statements_mut]
225///
226/// # Example
227/// ```
228/// # use sqlparser::parser::Parser;
229/// # use sqlparser::dialect::GenericDialect;
230/// # use sqlparser::ast::{VisitMut, VisitorMut, ObjectName, Expr, Ident};
231/// # use core::ops::ControlFlow;
232///
233/// // A visitor that replaces "to_replace" with "replaced" in all expressions
234/// struct Replacer;
235///
236/// // Visit each expression after its children have been visited
237/// impl VisitorMut for Replacer {
238/// type Break = ();
239///
240/// fn post_visit_expr(&mut self, expr: &mut Expr) -> ControlFlow<Self::Break> {
241/// if let Expr::Identifier(Ident{ value, ..}) = expr {
242/// *value = value.replace("to_replace", "replaced")
243/// }
244/// ControlFlow::Continue(())
245/// }
246/// }
247///
248/// let sql = "SELECT to_replace FROM foo where to_replace IN (SELECT to_replace FROM bar)";
249/// let mut statements = Parser::parse_sql(&GenericDialect{}, sql).unwrap();
250///
251/// // Drive the visitor through the AST
252/// statements.visit(&mut Replacer);
253///
254/// assert_eq!(statements[0].to_string(), "SELECT replaced FROM foo WHERE replaced IN (SELECT replaced FROM bar)");
255/// ```
256pub trait VisitorMut {
257 /// Type returned when the recursion returns early.
258 type Break;
259
260 /// Invoked for any relations (e.g. tables) that appear in the AST before visiting children
261 fn pre_visit_relation(&mut self, _relation: &mut ObjectName) -> ControlFlow<Self::Break> {
262 ControlFlow::Continue(())
263 }
264
265 /// Invoked for any relations (e.g. tables) that appear in the AST after visiting children
266 fn post_visit_relation(&mut self, _relation: &mut ObjectName) -> ControlFlow<Self::Break> {
267 ControlFlow::Continue(())
268 }
269
270 /// Invoked for any expressions that appear in the AST before visiting children
271 fn pre_visit_expr(&mut self, _expr: &mut Expr) -> ControlFlow<Self::Break> {
272 ControlFlow::Continue(())
273 }
274
275 /// Invoked for any expressions that appear in the AST
276 fn post_visit_expr(&mut self, _expr: &mut Expr) -> ControlFlow<Self::Break> {
277 ControlFlow::Continue(())
278 }
279
280 /// Invoked for any statements that appear in the AST before visiting children
281 fn pre_visit_statement(&mut self, _statement: &mut Statement) -> ControlFlow<Self::Break> {
282 ControlFlow::Continue(())
283 }
284
285 /// Invoked for any statements that appear in the AST after visiting children
286 fn post_visit_statement(&mut self, _statement: &mut Statement) -> ControlFlow<Self::Break> {
287 ControlFlow::Continue(())
288 }
289}
290
291struct RelationVisitor<F>(F);
292
293impl<E, F: FnMut(&ObjectName) -> ControlFlow<E>> Visitor for RelationVisitor<F> {
294 type Break = E;
295
296 fn pre_visit_relation(&mut self, relation: &ObjectName) -> ControlFlow<Self::Break> {
297 self.0(relation)
298 }
299}
300
301impl<E, F: FnMut(&mut ObjectName) -> ControlFlow<E>> VisitorMut for RelationVisitor<F> {
302 type Break = E;
303
304 fn post_visit_relation(&mut self, relation: &mut ObjectName) -> ControlFlow<Self::Break> {
305 self.0(relation)
306 }
307}
308
309/// Invokes the provided closure on all relations (e.g. table names) present in `v`
310///
311/// # Example
312/// ```
313/// # use sqlparser::parser::Parser;
314/// # use sqlparser::dialect::GenericDialect;
315/// # use sqlparser::ast::{visit_relations};
316/// # use core::ops::ControlFlow;
317/// let sql = "SELECT a FROM foo where x IN (SELECT y FROM bar)";
318/// let statements = Parser::parse_sql(&GenericDialect{}, sql)
319/// .unwrap();
320///
321/// // visit statements, capturing relations (table names)
322/// let mut visited = vec![];
323/// visit_relations(&statements, |relation| {
324/// visited.push(format!("RELATION: {}", relation));
325/// ControlFlow::<()>::Continue(())
326/// });
327///
328/// let expected : Vec<_> = [
329/// "RELATION: foo",
330/// "RELATION: bar",
331/// ]
332/// .into_iter().map(|s| s.to_string()).collect();
333///
334/// assert_eq!(visited, expected);
335/// ```
336pub fn visit_relations<V, E, F>(v: &V, f: F) -> ControlFlow<E>
337where
338 V: Visit,
339 F: FnMut(&ObjectName) -> ControlFlow<E>,
340{
341 let mut visitor = RelationVisitor(f);
342 v.visit(&mut visitor)?;
343 ControlFlow::Continue(())
344}
345
346/// Invokes the provided closure with a mutable reference to all relations (e.g. table names)
347/// present in `v`.
348///
349/// When the closure mutates its argument, the new mutated relation will not be visited again.
350///
351/// # Example
352/// ```
353/// # use sqlparser::parser::Parser;
354/// # use sqlparser::dialect::GenericDialect;
355/// # use sqlparser::ast::{ObjectName, visit_relations_mut};
356/// # use core::ops::ControlFlow;
357/// let sql = "SELECT a FROM foo";
358/// let mut statements = Parser::parse_sql(&GenericDialect{}, sql)
359/// .unwrap();
360///
361/// // visit statements, renaming table foo to bar
362/// visit_relations_mut(&mut statements, |table| {
363/// table.0[0].value = table.0[0].value.replace("foo", "bar");
364/// ControlFlow::<()>::Continue(())
365/// });
366///
367/// assert_eq!(statements[0].to_string(), "SELECT a FROM bar");
368/// ```
369pub fn visit_relations_mut<V, E, F>(v: &mut V, f: F) -> ControlFlow<E>
370where
371 V: VisitMut,
372 F: FnMut(&mut ObjectName) -> ControlFlow<E>,
373{
374 let mut visitor = RelationVisitor(f);
375 v.visit(&mut visitor)?;
376 ControlFlow::Continue(())
377}
378
379struct ExprVisitor<F>(F);
380
381impl<E, F: FnMut(&Expr) -> ControlFlow<E>> Visitor for ExprVisitor<F> {
382 type Break = E;
383
384 fn pre_visit_expr(&mut self, expr: &Expr) -> ControlFlow<Self::Break> {
385 self.0(expr)
386 }
387}
388
389impl<E, F: FnMut(&mut Expr) -> ControlFlow<E>> VisitorMut for ExprVisitor<F> {
390 type Break = E;
391
392 fn post_visit_expr(&mut self, expr: &mut Expr) -> ControlFlow<Self::Break> {
393 self.0(expr)
394 }
395}
396
397/// Invokes the provided closure on all expressions (e.g. `1 + 2`) present in `v`
398///
399/// # Example
400/// ```
401/// # use sqlparser::parser::Parser;
402/// # use sqlparser::dialect::GenericDialect;
403/// # use sqlparser::ast::{visit_expressions};
404/// # use core::ops::ControlFlow;
405/// let sql = "SELECT a FROM foo where x IN (SELECT y FROM bar)";
406/// let statements = Parser::parse_sql(&GenericDialect{}, sql)
407/// .unwrap();
408///
409/// // visit all expressions
410/// let mut visited = vec![];
411/// visit_expressions(&statements, |expr| {
412/// visited.push(format!("EXPR: {}", expr));
413/// ControlFlow::<()>::Continue(())
414/// });
415///
416/// let expected : Vec<_> = [
417/// "EXPR: a",
418/// "EXPR: x IN (SELECT y FROM bar)",
419/// "EXPR: x",
420/// "EXPR: y",
421/// ]
422/// .into_iter().map(|s| s.to_string()).collect();
423///
424/// assert_eq!(visited, expected);
425/// ```
426pub fn visit_expressions<V, E, F>(v: &V, f: F) -> ControlFlow<E>
427where
428 V: Visit,
429 F: FnMut(&Expr) -> ControlFlow<E>,
430{
431 let mut visitor = ExprVisitor(f);
432 v.visit(&mut visitor)?;
433 ControlFlow::Continue(())
434}
435
436/// Invokes the provided closure iteratively with a mutable reference to all expressions
437/// present in `v`.
438///
439/// This performs a depth-first search, so if the closure mutates the expression
440///
441/// # Example
442///
443/// ## Remove all select limits in sub-queries
444/// ```
445/// # use sqlparser::parser::Parser;
446/// # use sqlparser::dialect::GenericDialect;
447/// # use sqlparser::ast::{Expr, visit_expressions_mut, visit_statements_mut};
448/// # use core::ops::ControlFlow;
449/// let sql = "SELECT (SELECT y FROM z LIMIT 9) FROM t LIMIT 3";
450/// let mut statements = Parser::parse_sql(&GenericDialect{}, sql).unwrap();
451///
452/// // Remove all select limits in sub-queries
453/// visit_expressions_mut(&mut statements, |expr| {
454/// if let Expr::Subquery(q) = expr {
455/// q.limit = None
456/// }
457/// ControlFlow::<()>::Continue(())
458/// });
459///
460/// assert_eq!(statements[0].to_string(), "SELECT (SELECT y FROM z) FROM t LIMIT 3");
461/// ```
462///
463/// ## Wrap column name in function call
464///
465/// This demonstrates how to effectively replace an expression with another more complicated one
466/// that references the original. This example avoids unnecessary allocations by using the
467/// [`std::mem`](std::mem) family of functions.
468///
469/// ```
470/// # use sqlparser::parser::Parser;
471/// # use sqlparser::dialect::GenericDialect;
472/// # use sqlparser::ast::{Expr, Function, FunctionArg, FunctionArgExpr, Ident, ObjectName, Value, visit_expressions_mut, visit_statements_mut};
473/// # use core::ops::ControlFlow;
474/// let sql = "SELECT x, y FROM t";
475/// let mut statements = Parser::parse_sql(&GenericDialect{}, sql).unwrap();
476///
477/// visit_expressions_mut(&mut statements, |expr| {
478/// if matches!(expr, Expr::Identifier(col_name) if col_name.value == "x") {
479/// let old_expr = std::mem::replace(expr, Expr::Value(Value::Null));
480/// *expr = Expr::Function(Function {
481/// name: ObjectName(vec![Ident::new("f")]),
482/// args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(old_expr))],
483/// over: None, distinct: false, special: false,
484/// });
485/// }
486/// ControlFlow::<()>::Continue(())
487/// });
488///
489/// assert_eq!(statements[0].to_string(), "SELECT f(x), y FROM t");
490/// ```
491pub fn visit_expressions_mut<V, E, F>(v: &mut V, f: F) -> ControlFlow<E>
492where
493 V: VisitMut,
494 F: FnMut(&mut Expr) -> ControlFlow<E>,
495{
496 v.visit(&mut ExprVisitor(f))?;
497 ControlFlow::Continue(())
498}
499
500struct StatementVisitor<F>(F);
501
502impl<E, F: FnMut(&Statement) -> ControlFlow<E>> Visitor for StatementVisitor<F> {
503 type Break = E;
504
505 fn pre_visit_statement(&mut self, statement: &Statement) -> ControlFlow<Self::Break> {
506 self.0(statement)
507 }
508}
509
510impl<E, F: FnMut(&mut Statement) -> ControlFlow<E>> VisitorMut for StatementVisitor<F> {
511 type Break = E;
512
513 fn post_visit_statement(&mut self, statement: &mut Statement) -> ControlFlow<Self::Break> {
514 self.0(statement)
515 }
516}
517
518/// Invokes the provided closure iteratively with a mutable reference to all statements
519/// present in `v` (e.g. `SELECT`, `CREATE TABLE`, etc).
520///
521/// # Example
522/// ```
523/// # use sqlparser::parser::Parser;
524/// # use sqlparser::dialect::GenericDialect;
525/// # use sqlparser::ast::{visit_statements};
526/// # use core::ops::ControlFlow;
527/// let sql = "SELECT a FROM foo where x IN (SELECT y FROM bar); CREATE TABLE baz(q int)";
528/// let statements = Parser::parse_sql(&GenericDialect{}, sql)
529/// .unwrap();
530///
531/// // visit all statements
532/// let mut visited = vec![];
533/// visit_statements(&statements, |stmt| {
534/// visited.push(format!("STATEMENT: {}", stmt));
535/// ControlFlow::<()>::Continue(())
536/// });
537///
538/// let expected : Vec<_> = [
539/// "STATEMENT: SELECT a FROM foo WHERE x IN (SELECT y FROM bar)",
540/// "STATEMENT: CREATE TABLE baz (q INT)"
541/// ]
542/// .into_iter().map(|s| s.to_string()).collect();
543///
544/// assert_eq!(visited, expected);
545/// ```
546pub fn visit_statements<V, E, F>(v: &V, f: F) -> ControlFlow<E>
547where
548 V: Visit,
549 F: FnMut(&Statement) -> ControlFlow<E>,
550{
551 let mut visitor = StatementVisitor(f);
552 v.visit(&mut visitor)?;
553 ControlFlow::Continue(())
554}
555
556/// Invokes the provided closure on all statements (e.g. `SELECT`, `CREATE TABLE`, etc) present in `v`
557///
558/// # Example
559/// ```
560/// # use sqlparser::parser::Parser;
561/// # use sqlparser::dialect::GenericDialect;
562/// # use sqlparser::ast::{Statement, visit_statements_mut};
563/// # use core::ops::ControlFlow;
564/// let sql = "SELECT x FROM foo LIMIT 9+$limit; SELECT * FROM t LIMIT f()";
565/// let mut statements = Parser::parse_sql(&GenericDialect{}, sql).unwrap();
566///
567/// // Remove all select limits in outer statements (not in sub-queries)
568/// visit_statements_mut(&mut statements, |stmt| {
569/// if let Statement::Query(q) = stmt {
570/// q.limit = None
571/// }
572/// ControlFlow::<()>::Continue(())
573/// });
574///
575/// assert_eq!(statements[0].to_string(), "SELECT x FROM foo");
576/// assert_eq!(statements[1].to_string(), "SELECT * FROM t");
577/// ```
578pub fn visit_statements_mut<V, E, F>(v: &mut V, f: F) -> ControlFlow<E>
579where
580 V: VisitMut,
581 F: FnMut(&mut Statement) -> ControlFlow<E>,
582{
583 v.visit(&mut StatementVisitor(f))?;
584 ControlFlow::Continue(())
585}
586
587#[cfg(test)]
588mod tests {
589 use super::*;
590 use crate::dialect::GenericDialect;
591 use crate::parser::Parser;
592 use crate::tokenizer::Tokenizer;
593
594 #[derive(Default)]
595 struct TestVisitor {
596 visited: Vec<String>,
597 }
598
599 impl Visitor for TestVisitor {
600 type Break = ();
601
602 fn pre_visit_relation(&mut self, relation: &ObjectName) -> ControlFlow<Self::Break> {
603 self.visited.push(format!("PRE: RELATION: {relation}"));
604 ControlFlow::Continue(())
605 }
606
607 fn post_visit_relation(&mut self, relation: &ObjectName) -> ControlFlow<Self::Break> {
608 self.visited.push(format!("POST: RELATION: {relation}"));
609 ControlFlow::Continue(())
610 }
611
612 fn pre_visit_expr(&mut self, expr: &Expr) -> ControlFlow<Self::Break> {
613 self.visited.push(format!("PRE: EXPR: {expr}"));
614 ControlFlow::Continue(())
615 }
616
617 fn post_visit_expr(&mut self, expr: &Expr) -> ControlFlow<Self::Break> {
618 self.visited.push(format!("POST: EXPR: {expr}"));
619 ControlFlow::Continue(())
620 }
621
622 fn pre_visit_statement(&mut self, statement: &Statement) -> ControlFlow<Self::Break> {
623 self.visited.push(format!("PRE: STATEMENT: {statement}"));
624 ControlFlow::Continue(())
625 }
626
627 fn post_visit_statement(&mut self, statement: &Statement) -> ControlFlow<Self::Break> {
628 self.visited.push(format!("POST: STATEMENT: {statement}"));
629 ControlFlow::Continue(())
630 }
631 }
632
633 fn do_visit(sql: &str) -> Vec<String> {
634 let dialect = GenericDialect {};
635 let mut tokenizer = Tokenizer::new(&dialect, sql);
636 let tokens = tokenizer.tokenize().unwrap();
637 let s = Parser::new(&dialect)
638 .with_tokens(tokens)
639 .parse_statement()
640 .unwrap();
641
642 let mut visitor = TestVisitor::default();
643 s.visit(&mut visitor);
644 visitor.visited
645 }
646
647 #[test]
648 fn test_sql() {
649 let tests = vec![
650 (
651 "SELECT * from table_name",
652 vec![
653 "PRE: STATEMENT: SELECT * FROM table_name",
654 "PRE: RELATION: table_name",
655 "POST: RELATION: table_name",
656 "POST: STATEMENT: SELECT * FROM table_name",
657 ],
658 ),
659 (
660 "SELECT * from t1 join t2 on t1.id = t2.t1_id",
661 vec![
662 "PRE: STATEMENT: SELECT * FROM t1 JOIN t2 ON t1.id = t2.t1_id",
663 "PRE: RELATION: t1",
664 "POST: RELATION: t1",
665 "PRE: RELATION: t2",
666 "POST: RELATION: t2",
667 "PRE: EXPR: t1.id = t2.t1_id",
668 "PRE: EXPR: t1.id",
669 "POST: EXPR: t1.id",
670 "PRE: EXPR: t2.t1_id",
671 "POST: EXPR: t2.t1_id",
672 "POST: EXPR: t1.id = t2.t1_id",
673 "POST: STATEMENT: SELECT * FROM t1 JOIN t2 ON t1.id = t2.t1_id",
674 ],
675 ),
676 (
677 "SELECT * from t1 where EXISTS(SELECT column from t2)",
678 vec![
679 "PRE: STATEMENT: SELECT * FROM t1 WHERE EXISTS (SELECT column FROM t2)",
680 "PRE: RELATION: t1",
681 "POST: RELATION: t1",
682 "PRE: EXPR: EXISTS (SELECT column FROM t2)",
683 "PRE: EXPR: column",
684 "POST: EXPR: column",
685 "PRE: RELATION: t2",
686 "POST: RELATION: t2",
687 "POST: EXPR: EXISTS (SELECT column FROM t2)",
688 "POST: STATEMENT: SELECT * FROM t1 WHERE EXISTS (SELECT column FROM t2)",
689 ],
690 ),
691 (
692 "SELECT * from t1 where EXISTS(SELECT column from t2)",
693 vec![
694 "PRE: STATEMENT: SELECT * FROM t1 WHERE EXISTS (SELECT column FROM t2)",
695 "PRE: RELATION: t1",
696 "POST: RELATION: t1",
697 "PRE: EXPR: EXISTS (SELECT column FROM t2)",
698 "PRE: EXPR: column",
699 "POST: EXPR: column",
700 "PRE: RELATION: t2",
701 "POST: RELATION: t2",
702 "POST: EXPR: EXISTS (SELECT column FROM t2)",
703 "POST: STATEMENT: SELECT * FROM t1 WHERE EXISTS (SELECT column FROM t2)",
704 ],
705 ),
706 (
707 "SELECT * from t1 where EXISTS(SELECT column from t2) UNION SELECT * from t3",
708 vec![
709 "PRE: STATEMENT: SELECT * FROM t1 WHERE EXISTS (SELECT column FROM t2) UNION SELECT * FROM t3",
710 "PRE: RELATION: t1",
711 "POST: RELATION: t1",
712 "PRE: EXPR: EXISTS (SELECT column FROM t2)",
713 "PRE: EXPR: column",
714 "POST: EXPR: column",
715 "PRE: RELATION: t2",
716 "POST: RELATION: t2",
717 "POST: EXPR: EXISTS (SELECT column FROM t2)",
718 "PRE: RELATION: t3",
719 "POST: RELATION: t3",
720 "POST: STATEMENT: SELECT * FROM t1 WHERE EXISTS (SELECT column FROM t2) UNION SELECT * FROM t3",
721 ],
722 ),
723 ];
724 for (sql, expected) in tests {
725 let actual = do_visit(sql);
726 let actual: Vec<_> = actual.iter().map(|x| x.as_str()).collect();
727 assert_eq!(actual, expected)
728 }
729 }
730}