1use crate::{
10 ast::{Expr, FrameBound, FromClause, SelectStmt, Statement},
11 SQLError,
12};
13use std::collections::BTreeSet;
14use uqa_core::RelationIdentity;
15mod expressions;
16mod merge;
17mod routines;
18mod sources;
19mod types;
20pub use expressions::*;
21pub use merge::visit_stored_statement_merges;
22pub use routines::*;
23pub use sources::*;
24pub use types::*;
25
26pub type MergeCallback<'a> = &'a mut dyn FnMut(&mut crate::ast::MergeStmt) -> Result<(), SQLError>;
27
28pub type ExpressionCallback<'a> = &'a mut dyn FnMut(&mut Expr) -> Result<(), SQLError>;
29pub type SourceCallback<'a> = &'a mut dyn FnMut(&mut FromClause) -> Result<(), SQLError>;
30
31pub struct StoredAstVisitor<'a, R, F> {
32 pub source: Option<SourceCallback<'a>>,
33 pub merge: Option<MergeCallback<'a>>,
34 pub expression: Option<ExpressionCallback<'a>>,
35 pub ty: Option<&'a mut dyn FnMut(&mut String)>,
36 pub relation: &'a mut R,
37 pub routine: &'a mut F,
38}
39
40impl<R, F> StoredAstVisitor<'_, R, F>
41where
42 R: FnMut(&mut String) -> Result<(), SQLError>,
43 F: FnMut(&mut String, Option<&mut Option<crate::ast::FunctionBinding>>) -> Result<(), SQLError>,
44{
45 pub fn bind_statement(&mut self, statement: &mut Statement) -> Result<(), SQLError> {
46 let ctes = BTreeSet::new();
47 match statement {
48 Statement::Select(query) => self.bind_select(query, &ctes),
49 Statement::Insert(insert) => self.bind_insert(insert, &ctes),
50 Statement::Update(update) => self.bind_update(update, &ctes),
51 Statement::Delete(delete) => self.bind_delete(delete, &ctes),
52 Statement::Notify { .. } => Ok(()),
53 Statement::Values { rows } => {
54 for expression in rows.iter_mut().flatten() {
55 self.bind_expr(expression, &ctes)?;
56 }
57 Ok(())
58 }
59 Statement::Merge(merge) => self.bind_merge(merge, &ctes),
60 _ => Err(SQLError::Internal(
61 "catalog-owned statement has an unsupported dependency shape".into(),
62 )),
63 }
64 }
65
66 fn bind_insert(
67 &mut self,
68 insert: &mut crate::ast::InsertStmt,
69 inherited: &BTreeSet<String>,
70 ) -> Result<(), SQLError> {
71 (self.relation)(&mut insert.table)?;
72 let visible = self.bind_ctes(&mut insert.with, inherited)?;
73 if let Some(source) = insert.select_source.as_deref_mut() {
74 self.bind_select(source, &visible)?;
75 }
76 for expression in insert.rows.iter_mut().flatten() {
77 self.bind_expr(expression, &visible)?;
78 }
79 if let Some(conflict) = &mut insert.on_conflict {
80 for expression in &mut conflict.expressions {
81 self.bind_expr(expression, &visible)?;
82 }
83 if let Some(predicate) = conflict.predicate.as_deref_mut() {
84 self.bind_expr(predicate, &visible)?;
85 }
86 if let crate::ast::OnConflictAction::Update {
87 assignments,
88 r#where,
89 } = &mut conflict.action
90 {
91 for (_, expression) in assignments {
92 self.bind_expr(expression, &visible)?;
93 }
94 if let Some(expression) = r#where {
95 self.bind_expr(expression, &visible)?;
96 }
97 }
98 }
99 for projection in &mut insert.returning {
100 self.bind_expr(&mut projection.expr, &visible)?;
101 }
102 Ok(())
103 }
104
105 fn bind_update(
106 &mut self,
107 update: &mut crate::ast::UpdateStmt,
108 inherited: &BTreeSet<String>,
109 ) -> Result<(), SQLError> {
110 (self.relation)(&mut update.table)?;
111 let visible = self.bind_ctes(&mut update.with, inherited)?;
112 if let Some(source) = &mut update.from {
113 self.bind_from(source, &visible)?;
114 }
115 for (_, expression) in &mut update.assignments {
116 self.bind_expr(expression, &visible)?;
117 }
118 if let Some(expression) = &mut update.r#where {
119 self.bind_expr(expression, &visible)?;
120 }
121 for projection in &mut update.returning {
122 self.bind_expr(&mut projection.expr, &visible)?;
123 }
124 Ok(())
125 }
126
127 fn bind_delete(
128 &mut self,
129 delete: &mut crate::ast::DeleteStmt,
130 inherited: &BTreeSet<String>,
131 ) -> Result<(), SQLError> {
132 (self.relation)(&mut delete.table)?;
133 let visible = self.bind_ctes(&mut delete.with, inherited)?;
134 if let Some(source) = &mut delete.using {
135 self.bind_from(source, &visible)?;
136 }
137 if let Some(expression) = &mut delete.r#where {
138 self.bind_expr(expression, &visible)?;
139 }
140 for projection in &mut delete.returning {
141 self.bind_expr(&mut projection.expr, &visible)?;
142 }
143 Ok(())
144 }
145
146 fn bind_ctes(
147 &mut self,
148 ctes: &mut [crate::ast::CTE],
149 inherited: &BTreeSet<String>,
150 ) -> Result<BTreeSet<String>, SQLError> {
151 let mut visible = inherited.clone();
152 let recursive = ctes.iter().any(|cte| cte.recursive).then(|| {
153 ctes.iter()
154 .map(|cte| cte.name.clone())
155 .collect::<BTreeSet<_>>()
156 });
157 for cte in ctes {
158 let body_scope = recursive.as_ref().map_or_else(
159 || visible.clone(),
160 |recursive| inherited.union(recursive).cloned().collect(),
161 );
162 match &mut cte.body {
163 crate::ast::CteBody::Query(query) => self.bind_select(query, &body_scope)?,
164 crate::ast::CteBody::Insert(plan) => self.bind_insert(plan, &body_scope)?,
165 crate::ast::CteBody::Update(plan) => self.bind_update(plan, &body_scope)?,
166 crate::ast::CteBody::Delete(plan) => self.bind_delete(plan, &body_scope)?,
167 crate::ast::CteBody::Merge(plan) => self.bind_merge(plan, &body_scope)?,
168 }
169 if let Some(cycle) = &mut cte.cycle {
170 self.bind_expr(&mut cycle.mark_value, &body_scope)?;
171 self.bind_expr(&mut cycle.mark_default, &body_scope)?;
172 }
173 visible.insert(cte.name.clone());
174 }
175 Ok(visible)
176 }
177
178 fn bind_select(
179 &mut self,
180 select: &mut SelectStmt,
181 inherited: &BTreeSet<String>,
182 ) -> Result<(), SQLError> {
183 let visible = self.bind_ctes(&mut select.with, inherited)?;
184 if let Some(source) = &mut select.from {
185 self.bind_from(source, &visible)?;
186 }
187 for projection in &mut select.projections {
188 self.bind_expr(&mut projection.expr, &visible)?;
189 }
190 for expression in select.values.iter_mut().flatten() {
191 self.bind_expr(expression, &visible)?;
192 }
193 if let Some(expression) = &mut select.r#where {
194 self.bind_expr(expression, &visible)?;
195 }
196 for expression in &mut select.group_by {
197 self.bind_expr(expression, &visible)?;
198 }
199 for expression in select.grouping_sets.iter_mut().flatten() {
200 self.bind_expr(expression, &visible)?;
201 }
202 if let Some(expression) = &mut select.having {
203 self.bind_expr(expression, &visible)?;
204 }
205 for order in &mut select.order_by {
206 self.bind_expr(&mut order.expr, &visible)?;
207 }
208 if let Some(expression) = &mut select.limit {
209 self.bind_expr(expression, &visible)?;
210 }
211 if let Some(expression) = &mut select.offset {
212 self.bind_expr(expression, &visible)?;
213 }
214 for expression in &mut select.distinct_on {
215 self.bind_expr(expression, &visible)?;
216 }
217 if let Some(set) = &mut select.set_op {
218 if let Some(left) = &mut set.left {
219 self.bind_select(left, &visible)?;
220 }
221 self.bind_select(&mut set.right, &visible)?;
222 for order in &mut set.combined_order_by {
223 self.bind_expr(&mut order.expr, &visible)?;
224 }
225 if let Some(expression) = &mut set.combined_limit {
226 self.bind_expr(expression, &visible)?;
227 }
228 if let Some(expression) = &mut set.combined_offset {
229 self.bind_expr(expression, &visible)?;
230 }
231 }
232 Ok(())
233 }
234
235 fn bind_from(
236 &mut self,
237 source: &mut FromClause,
238 visible_ctes: &BTreeSet<String>,
239 ) -> Result<(), SQLError> {
240 if let FromClause::Table { name, .. } = source {
241 let is_cte =
242 RelationIdentity::parse_reference(name)
243 .ok()
244 .is_some_and(|(schema, relation)| {
245 schema.is_none() && visible_ctes.contains(&relation)
246 });
247 if is_cte {
248 return Ok(());
249 }
250 }
251 if let Some(visit) = self.source.as_mut() {
252 visit(source)?;
253 }
254 match source {
255 FromClause::Table { name, .. } => {
256 (self.relation)(name)?;
257 }
258 FromClause::Join {
259 left, right, on, ..
260 } => {
261 self.bind_from(left, visible_ctes)?;
262 self.bind_from(right, visible_ctes)?;
263 if let Some(expression) = on {
264 self.bind_expr(expression, visible_ctes)?;
265 }
266 }
267 FromClause::Values { rows, .. } => {
268 for expression in rows.iter_mut().flatten() {
269 self.bind_expr(expression, visible_ctes)?;
270 }
271 }
272 FromClause::Function {
273 name,
274 binding,
275 relations,
276 args,
277 ..
278 } => {
279 (self.routine)(name, Some(binding))?;
280 if let Some(relations) = relations {
281 (self.relation)(&mut relations.left)?;
282 (self.relation)(&mut relations.right)?;
283 }
284 for expression in args {
285 self.bind_expr(expression, visible_ctes)?;
286 }
287 }
288 FromClause::FunctionGroup { functions, .. } => {
289 for function in functions {
290 (self.routine)(&mut function.name, Some(&mut function.binding))?;
291 if let Some(relations) = &mut function.relations {
292 (self.relation)(&mut relations.left)?;
293 (self.relation)(&mut relations.right)?;
294 }
295 for expression in &mut function.args {
296 self.bind_expr(expression, visible_ctes)?;
297 }
298 }
299 }
300 FromClause::Subquery { body, .. } => self.bind_select(body, visible_ctes)?,
301 }
302 Ok(())
303 }
304
305 fn bind_expression_type(&mut self, expression: &mut Expr) -> Result<(), SQLError> {
306 if let Some(visit) = self.expression.as_mut() {
307 visit(expression)?;
308 }
309 if let (Some(visit), Expr::Cast { ty, .. } | Expr::TypedLiteral { ty, .. }) =
310 (self.ty.as_mut(), expression)
311 {
312 visit(ty);
313 }
314 Ok(())
315 }
316
317 pub fn bind_expr(
318 &mut self,
319 expression: &mut Expr,
320 visible_ctes: &BTreeSet<String>,
321 ) -> Result<(), SQLError> {
322 self.bind_expression_type(expression)?;
323 match expression {
324 Expr::Func {
325 name,
326 binding,
327 args,
328 order_by,
329 filter,
330 ..
331 } => {
332 for argument in args {
333 self.bind_expr(argument, visible_ctes)?;
334 }
335 for order in order_by {
336 self.bind_expr(&mut order.expr, visible_ctes)?;
337 }
338 if let Some(filter) = filter {
339 self.bind_expr(filter, visible_ctes)?;
340 }
341 (self.routine)(name, Some(binding))?;
342 }
343 Expr::Array(items) | Expr::Row(items) | Expr::And(items) | Expr::Or(items) => {
344 for item in items {
345 self.bind_expr(item, visible_ctes)?;
346 }
347 }
348 Expr::Binary { lhs, rhs, .. } => {
349 self.bind_expr(lhs, visible_ctes)?;
350 self.bind_expr(rhs, visible_ctes)?;
351 }
352 Expr::UnaryMinus(inner)
353 | Expr::Not(inner)
354 | Expr::IsNull { expr: inner, .. }
355 | Expr::Cast { expr: inner, .. } => self.bind_expr(inner, visible_ctes)?,
356 Expr::Between { expr, low, high } => {
357 self.bind_expr(expr, visible_ctes)?;
358 self.bind_expr(low, visible_ctes)?;
359 self.bind_expr(high, visible_ctes)?;
360 }
361 Expr::InList { expr, list, .. } => {
362 self.bind_expr(expr, visible_ctes)?;
363 for item in list {
364 self.bind_expr(item, visible_ctes)?;
365 }
366 }
367 Expr::WindowCall { name, args, spec } => {
368 for argument in args {
369 self.bind_expr(argument, visible_ctes)?;
370 }
371 for partition in &mut spec.partition_by {
372 self.bind_expr(partition, visible_ctes)?;
373 }
374 for order in &mut spec.order_by {
375 self.bind_expr(&mut order.expr, visible_ctes)?;
376 }
377 if let Some(frame) = &mut spec.frame {
378 for bound in [&mut frame.start, &mut frame.end] {
379 if let FrameBound::Preceding(inner) | FrameBound::Following(inner) = bound {
380 self.bind_expr(inner, visible_ctes)?;
381 }
382 }
383 }
384 (self.routine)(name, None)?;
385 }
386 Expr::Case {
387 base,
388 when,
389 else_branch,
390 } => {
391 if let Some(base) = base {
392 self.bind_expr(base, visible_ctes)?;
393 }
394 for (condition, result) in when {
395 self.bind_expr(condition, visible_ctes)?;
396 self.bind_expr(result, visible_ctes)?;
397 }
398 if let Some(branch) = else_branch {
399 self.bind_expr(branch, visible_ctes)?;
400 }
401 }
402 Expr::ScalarSubquery(body) | Expr::Exists { body, .. } => {
403 self.bind_select(body, visible_ctes)?;
404 }
405 Expr::InSubquery { expr, body, .. } => {
406 self.bind_expr(expr, visible_ctes)?;
407 self.bind_select(body, visible_ctes)?;
408 }
409 Expr::Star
410 | Expr::QualifiedStar(_)
411 | Expr::Default
412 | Expr::Column(_)
413 | Expr::QualifiedColumn { .. }
414 | Expr::InternalColumn(_)
415 | Expr::Literal(_)
416 | Expr::TypedLiteral { .. }
417 | Expr::Param(_) => {}
418 }
419 Ok(())
420 }
421}