10
10
// See the License for the specific language governing permissions and
11
11
// limitations under the License.
12
12
13
+ //! Recursive visitors for ast Nodes. See [`Visitor`] for more details.
14
+
13
15
use crate :: ast:: { Expr , ObjectName , Statement } ;
14
16
use core:: ops:: ControlFlow ;
15
17
16
- /// A type that can be visited by a `visitor`
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))]
28
+ /// ```
17
29
pub trait Visit {
18
30
fn visit < V : Visitor > ( & self , visitor : & mut V ) -> ControlFlow < V :: Break > ;
19
31
}
@@ -57,8 +69,70 @@ visit_noop!(u8, u16, u32, u64, i8, i16, i32, i64, char, bool, String);
57
69
#[ cfg( feature = "bigdecimal" ) ]
58
70
visit_noop ! ( bigdecimal:: BigDecimal ) ;
59
71
60
- /// A visitor that can be used to walk an AST tree
72
+ /// A visitor that can be used to walk an AST tree.
73
+ ///
74
+ /// `previst_` methods are invoked before visiting all children of the
75
+ /// node and `postvisit_` methods are invoked after visiting all
76
+ /// children of the node.
77
+ ///
78
+ /// # See also
79
+ ///
80
+ /// These methods provide a more concise way of visiting nodes of a certain type:
81
+ /// * [visit_relations]
82
+ /// * [visit_expressions]
83
+ /// * [visit_statements]
84
+ ///
85
+ /// # Example
86
+ /// ```
87
+ /// # use sqlparser::parser::Parser;
88
+ /// # use sqlparser::dialect::GenericDialect;
89
+ /// # use sqlparser::ast::{Visit, Visitor, ObjectName, Expr};
90
+ /// # use core::ops::ControlFlow;
91
+ /// // A structure that records statements and relations
92
+ /// #[derive(Default)]
93
+ /// struct V {
94
+ /// visited: Vec<String>,
95
+ /// }
96
+ ///
97
+ /// // Visit relations and exprs before children are visited (depth first walk)
98
+ /// // Note you can also visit statements and visit exprs after children have been visitoed
99
+ /// impl Visitor for V {
100
+ /// type Break = ();
101
+ ///
102
+ /// fn pre_visit_relation(&mut self, relation: &ObjectName) -> ControlFlow<Self::Break> {
103
+ /// self.visited.push(format!("PRE: RELATION: {}", relation));
104
+ /// ControlFlow::Continue(())
105
+ /// }
106
+ ///
107
+ /// fn pre_visit_expr(&mut self, expr: &Expr) -> ControlFlow<Self::Break> {
108
+ /// self.visited.push(format!("PRE: EXPR: {}", expr));
109
+ /// ControlFlow::Continue(())
110
+ /// }
111
+ /// }
112
+ ///
113
+ /// let sql = "SELECT a FROM foo where x IN (SELECT y FROM bar)";
114
+ /// let statements = Parser::parse_sql(&GenericDialect{}, sql)
115
+ /// .unwrap();
116
+ ///
117
+ /// // Drive the visitor through the AST
118
+ /// let mut visitor = V::default();
119
+ /// statements.visit(&mut visitor);
120
+ ///
121
+ /// // The visitor has visited statements and expressions in pre-traversal order
122
+ /// let expected : Vec<_> = [
123
+ /// "PRE: EXPR: a",
124
+ /// "PRE: RELATION: foo",
125
+ /// "PRE: EXPR: x IN (SELECT y FROM bar)",
126
+ /// "PRE: EXPR: x",
127
+ /// "PRE: EXPR: y",
128
+ /// "PRE: RELATION: bar",
129
+ /// ]
130
+ /// .into_iter().map(|s| s.to_string()).collect();
131
+ ///
132
+ /// assert_eq!(visitor.visited, expected);
133
+ /// ```
61
134
pub trait Visitor {
135
+ /// Type returned when the recursion returns early.
62
136
type Break ;
63
137
64
138
/// Invoked for any relations (e.g. tables) that appear in the AST before visiting children
@@ -102,7 +176,33 @@ impl<E, F: FnMut(&ObjectName) -> ControlFlow<E>> Visitor for RelationVisitor<F>
102
176
}
103
177
}
104
178
105
- /// Invokes the provided closure on all relations present in v
179
+ /// Invokes the provided closure on all relations (e.g. table names) present in `v`
180
+ ///
181
+ /// # Example
182
+ /// ```
183
+ /// # use sqlparser::parser::Parser;
184
+ /// # use sqlparser::dialect::GenericDialect;
185
+ /// # use sqlparser::ast::{visit_relations};
186
+ /// # use core::ops::ControlFlow;
187
+ /// let sql = "SELECT a FROM foo where x IN (SELECT y FROM bar)";
188
+ /// let statements = Parser::parse_sql(&GenericDialect{}, sql)
189
+ /// .unwrap();
190
+ ///
191
+ /// // visit statements, capturing relations (table names)
192
+ /// let mut visited = vec![];
193
+ /// visit_relations(&statements, |relation| {
194
+ /// visited.push(format!("RELATION: {}", relation));
195
+ /// ControlFlow::<()>::Continue(())
196
+ /// });
197
+ ///
198
+ /// let expected : Vec<_> = [
199
+ /// "RELATION: foo",
200
+ /// "RELATION: bar",
201
+ /// ]
202
+ /// .into_iter().map(|s| s.to_string()).collect();
203
+ ///
204
+ /// assert_eq!(visited, expected);
205
+ /// ```
106
206
pub fn visit_relations < V , E , F > ( v : & V , f : F ) -> ControlFlow < E >
107
207
where
108
208
V : Visit ,
@@ -123,7 +223,35 @@ impl<E, F: FnMut(&Expr) -> ControlFlow<E>> Visitor for ExprVisitor<F> {
123
223
}
124
224
}
125
225
126
- /// Invokes the provided closure on all expressions present in v
226
+ /// Invokes the provided closure on all expressions (e.g. `1 + 2`) present in `v`
227
+ ///
228
+ /// # Example
229
+ /// ```
230
+ /// # use sqlparser::parser::Parser;
231
+ /// # use sqlparser::dialect::GenericDialect;
232
+ /// # use sqlparser::ast::{visit_expressions};
233
+ /// # use core::ops::ControlFlow;
234
+ /// let sql = "SELECT a FROM foo where x IN (SELECT y FROM bar)";
235
+ /// let statements = Parser::parse_sql(&GenericDialect{}, sql)
236
+ /// .unwrap();
237
+ ///
238
+ /// // visit all expressions
239
+ /// let mut visited = vec![];
240
+ /// visit_expressions(&statements, |expr| {
241
+ /// visited.push(format!("EXPR: {}", expr));
242
+ /// ControlFlow::<()>::Continue(())
243
+ /// });
244
+ ///
245
+ /// let expected : Vec<_> = [
246
+ /// "EXPR: a",
247
+ /// "EXPR: x IN (SELECT y FROM bar)",
248
+ /// "EXPR: x",
249
+ /// "EXPR: y",
250
+ /// ]
251
+ /// .into_iter().map(|s| s.to_string()).collect();
252
+ ///
253
+ /// assert_eq!(visited, expected);
254
+ /// ```
127
255
pub fn visit_expressions < V , E , F > ( v : & V , f : F ) -> ControlFlow < E >
128
256
where
129
257
V : Visit ,
@@ -144,7 +272,33 @@ impl<E, F: FnMut(&Statement) -> ControlFlow<E>> Visitor for StatementVisitor<F>
144
272
}
145
273
}
146
274
147
- /// Invokes the provided closure on all statements present in v
275
+ /// Invokes the provided closure on all statements (e.g. `SELECT`, `CREATE TABLE`, etc) present in `v`
276
+ ///
277
+ /// # Example
278
+ /// ```
279
+ /// # use sqlparser::parser::Parser;
280
+ /// # use sqlparser::dialect::GenericDialect;
281
+ /// # use sqlparser::ast::{visit_statements};
282
+ /// # use core::ops::ControlFlow;
283
+ /// let sql = "SELECT a FROM foo where x IN (SELECT y FROM bar); CREATE TABLE baz(q int)";
284
+ /// let statements = Parser::parse_sql(&GenericDialect{}, sql)
285
+ /// .unwrap();
286
+ ///
287
+ /// // visit all statements
288
+ /// let mut visited = vec![];
289
+ /// visit_statements(&statements, |stmt| {
290
+ /// visited.push(format!("STATEMENT: {}", stmt));
291
+ /// ControlFlow::<()>::Continue(())
292
+ /// });
293
+ ///
294
+ /// let expected : Vec<_> = [
295
+ /// "STATEMENT: SELECT a FROM foo WHERE x IN (SELECT y FROM bar)",
296
+ /// "STATEMENT: CREATE TABLE baz (q INT)"
297
+ /// ]
298
+ /// .into_iter().map(|s| s.to_string()).collect();
299
+ ///
300
+ /// assert_eq!(visited, expected);
301
+ /// ```
148
302
pub fn visit_statements < V , E , F > ( v : & V , f : F ) -> ControlFlow < E >
149
303
where
150
304
V : Visit ,
0 commit comments