1use std::collections::{BTreeMap, BTreeSet};
10
11use crate::ast::{
12 Expr, FrameBound, FromClause, OrderBy, Projection, RuleEvent, SelectStmt, Statement,
13 UpdateStmt, CTE,
14};
15use crate::plpgsql::{bind_statement, ResolvedVariable, VariableResolver};
16use crate::SQLError;
17
18mod insert;
19use insert::bind_insert;
20mod namespace;
21mod references;
22mod returning;
23mod row_expansion;
24mod scope;
25pub use references::{
26 first_rule_row_reference_in_expr, first_rule_row_reference_in_select,
27 first_rule_row_reference_in_statement, rule_action_has_set_operation,
28 rule_condition_plan_references_whole_row, rule_condition_plan_row_columns,
29 rule_expr_references_row, rule_expr_references_whole_row, rule_expr_row_columns,
30 rule_new_row_columns, rule_statement_references_row, rule_statement_references_whole_row,
31 rule_statement_row_columns,
32};
33pub use returning::expand_rule_action_returning_stars;
34pub use row_expansion::expand_rule_action_row_stars;
35use scope::{
36 apply_positional_aliases, collect_visible_scope, cte_output_columns, RuleBindingScope,
37};
38
39pub fn action_target_qualifier_referenced(
40 catalog: &dyn RuleSourceCatalog,
41 action: &Statement,
42 qualifier: &str,
43) -> bool {
44 namespace::action_target_qualifier_referenced(catalog, action, qualifier)
45}
46
47mod context;
48use context::RuleBindingContext;
49pub use context::{rule_action_target_columns, rule_action_target_row_type, RuleSourceCatalog};
50
51pub fn bind_rule_action(
54 catalog: &dyn RuleSourceCatalog,
55 action: &Statement,
56 action_columns: &BTreeSet<String>,
57 resolver: &mut dyn VariableResolver,
58) -> Result<Statement, SQLError> {
59 let context = RuleBindingContext::with_catalog(catalog, true);
60 let (returning, action_event) = match action {
61 Statement::Insert(statement) => (&statement.returning, RuleEvent::Insert),
62 Statement::Update(statement) => (&statement.returning, RuleEvent::Update),
63 Statement::Delete(statement) => (&statement.returning, RuleEvent::Delete),
64 _ => {
65 return bind_rule_statement_body(
66 action,
67 resolver,
68 &RuleBindingScope::default(),
69 &context,
70 )
71 }
72 };
73 let mut body = action.clone();
74 let aliases = match &mut body {
75 Statement::Insert(statement) => {
76 statement.returning.clear();
77 statement.returning_aliases.clone()
78 }
79 Statement::Update(statement) => {
80 statement.returning.clear();
81 statement.returning_aliases.clone()
82 }
83 Statement::Delete(statement) => {
84 statement.returning.clear();
85 statement.returning_aliases.clone()
86 }
87 _ => unreachable!("DML rule action changed statement kind"),
88 };
89 let mut bound = {
90 let mut body_resolver = RuleActionBodyResolver {
91 action_columns,
92 action_event,
93 event_resolver: resolver,
94 };
95 bind_rule_statement_body(
96 &body,
97 &mut body_resolver,
98 &RuleBindingScope::default(),
99 &context,
100 )?
101 };
102 if returning.is_empty() {
103 return Ok(bound);
104 }
105 let returning = returning::bind_rule_action_returning(
106 returning,
107 action_columns,
108 &aliases,
109 action_event,
110 resolver,
111 &context,
112 )?;
113 match &mut bound {
114 Statement::Insert(statement) => statement.returning = returning,
115 Statement::Update(statement) => statement.returning = returning,
116 Statement::Delete(statement) => statement.returning = returning,
117 _ => unreachable!("bound DML rule action changed statement kind"),
118 }
119 Ok(bound)
120}
121
122struct RuleActionBodyResolver<'a, 'resolver> {
123 action_columns: &'a BTreeSet<String>,
124 action_event: RuleEvent,
125 event_resolver: &'resolver mut dyn VariableResolver,
126}
127
128impl RuleActionBodyResolver<'_, '_> {
129 fn is_action_column(&self, name: &str) -> bool {
130 matches!(self.action_event, RuleEvent::Update | RuleEvent::Delete)
131 && self
132 .action_columns
133 .iter()
134 .any(|column| column.eq_ignore_ascii_case(name))
135 }
136}
137
138impl VariableResolver for RuleActionBodyResolver<'_, '_> {
139 fn resolve_name(&mut self, name: &str) -> Result<Option<ResolvedVariable>, SQLError> {
140 if self.is_action_column(name) {
141 Ok(None)
142 } else {
143 self.event_resolver.resolve_name(name)
144 }
145 }
146
147 fn resolve_qualified(
148 &mut self,
149 qualifier: &str,
150 column: &str,
151 ) -> Result<Option<ResolvedVariable>, SQLError> {
152 self.event_resolver.resolve_qualified(qualifier, column)
153 }
154
155 fn resolve_param(&mut self, index: usize) -> Result<Option<ResolvedVariable>, SQLError> {
156 self.event_resolver.resolve_param(index)
157 }
158
159 fn rewrite_name(&mut self, name: &str) -> Result<Option<Expr>, SQLError> {
160 if self.is_action_column(name) {
161 Ok(None)
162 } else {
163 self.event_resolver.rewrite_name(name)
164 }
165 }
166
167 fn rewrite_qualified(
168 &mut self,
169 qualifier: &str,
170 column: &str,
171 ) -> Result<Option<Expr>, SQLError> {
172 self.event_resolver.rewrite_qualified(qualifier, column)
173 }
174
175 fn rewrite_qualified_star(&mut self, qualifier: &str) -> Result<Option<Vec<Expr>>, SQLError> {
176 self.event_resolver.rewrite_qualified_star(qualifier)
177 }
178
179 fn rewrite_qualified_whole_row(&mut self, qualifier: &str) -> Result<Option<Expr>, SQLError> {
180 self.event_resolver.rewrite_qualified_whole_row(qualifier)
181 }
182
183 fn rewrite_param(&mut self, index: usize) -> Result<Option<Expr>, SQLError> {
184 self.event_resolver.rewrite_param(index)
185 }
186
187 fn rewrite_internal(
188 &mut self,
189 column: crate::ast::InternalColumnRef,
190 ) -> Result<Option<Expr>, SQLError> {
191 self.event_resolver.rewrite_internal(column)
192 }
193}
194
195pub fn bind_rule_expr_scoped(
197 expr: &Expr,
198 resolver: &mut dyn VariableResolver,
199 shadowed: &BTreeSet<String>,
200) -> Result<Expr, SQLError> {
201 bind_rule_expr_with_scope(
202 expr,
203 resolver,
204 &RuleBindingScope::from_qualifiers(shadowed),
205 &RuleBindingContext::default(),
206 )
207}
208
209fn bind_rule_expr_with_scope(
210 expr: &Expr,
211 resolver: &mut dyn VariableResolver,
212 scope: &RuleBindingScope,
213 context: &RuleBindingContext<'_>,
214) -> Result<Expr, SQLError> {
215 Ok(match expr {
216 Expr::Column(name) => {
217 if scope.qualifier_is_shadowed(name) || scope.column_is_shadowed(name) {
218 expr.clone()
219 } else {
220 resolver.rewrite_name(name)?.unwrap_or_else(|| expr.clone())
221 }
222 }
223 Expr::QualifiedColumn { qualifier, column } => {
224 if scope.qualifier_is_shadowed(qualifier) {
225 expr.clone()
226 } else {
227 resolver
228 .rewrite_qualified(qualifier, column)?
229 .unwrap_or_else(|| expr.clone())
230 }
231 }
232 Expr::Param(index) => resolver
233 .rewrite_param(*index)?
234 .unwrap_or_else(|| expr.clone()),
235 Expr::InternalColumn(column) => resolver
236 .rewrite_internal(*column)?
237 .unwrap_or_else(|| expr.clone()),
238 Expr::QualifiedStar(qualifier) => {
239 if scope.qualifier_is_shadowed(qualifier) {
240 expr.clone()
241 } else {
242 resolver
243 .rewrite_qualified_whole_row(qualifier)?
244 .unwrap_or_else(|| expr.clone())
245 }
246 }
247 Expr::Default | Expr::Literal(_) | Expr::TypedLiteral { .. } | Expr::Star => expr.clone(),
248 Expr::Func { .. } => bind_rule_function_expression(expr, resolver, scope, context)?,
249 Expr::Array(items) => Expr::Array(bind_exprs(items, resolver, scope, context)?),
250 Expr::Row(items) => Expr::Row(bind_expanding_exprs(items, resolver, scope, context)?),
251 Expr::Binary { op, lhs, rhs } => Expr::Binary {
252 op: *op,
253 lhs: Box::new(bind_rule_expr_with_scope(lhs, resolver, scope, context)?),
254 rhs: Box::new(bind_rule_expr_with_scope(rhs, resolver, scope, context)?),
255 },
256 Expr::UnaryMinus(inner) => Expr::UnaryMinus(Box::new(bind_rule_expr_with_scope(
257 inner, resolver, scope, context,
258 )?)),
259 Expr::Not(inner) => Expr::Not(Box::new(bind_rule_expr_with_scope(
260 inner, resolver, scope, context,
261 )?)),
262 Expr::And(items) => Expr::And(bind_exprs(items, resolver, scope, context)?),
263 Expr::Or(items) => Expr::Or(bind_exprs(items, resolver, scope, context)?),
264 Expr::IsNull { expr, negated } => Expr::IsNull {
265 expr: Box::new(bind_rule_expr_with_scope(expr, resolver, scope, context)?),
266 negated: *negated,
267 },
268 Expr::Between { expr, low, high } => Expr::Between {
269 expr: Box::new(bind_rule_expr_with_scope(expr, resolver, scope, context)?),
270 low: Box::new(bind_rule_expr_with_scope(low, resolver, scope, context)?),
271 high: Box::new(bind_rule_expr_with_scope(high, resolver, scope, context)?),
272 },
273 Expr::InList {
274 expr,
275 list,
276 negated,
277 } => Expr::InList {
278 expr: Box::new(bind_rule_expr_with_scope(expr, resolver, scope, context)?),
279 list: bind_exprs(list, resolver, scope, context)?,
280 negated: *negated,
281 },
282 Expr::WindowCall { .. } => bind_rule_window_expression(expr, resolver, scope, context)?,
283 Expr::Case { .. } => bind_rule_case_expression(expr, resolver, scope, context)?,
284 Expr::Cast { expr, ty } => Expr::Cast {
285 expr: Box::new(bind_rule_expr_with_scope(expr, resolver, scope, context)?),
286 ty: ty.clone(),
287 },
288 Expr::ScalarSubquery(body) => Expr::ScalarSubquery(Box::new(bind_select_with_scope(
289 body, resolver, scope, context,
290 )?)),
291 Expr::Exists { body, negated } => Expr::Exists {
292 body: Box::new(bind_select_with_scope(body, resolver, scope, context)?),
293 negated: *negated,
294 },
295 Expr::InSubquery {
296 expr,
297 body,
298 negated,
299 } => Expr::InSubquery {
300 expr: Box::new(bind_rule_expr_with_scope(expr, resolver, scope, context)?),
301 body: Box::new(bind_select_with_scope(body, resolver, scope, context)?),
302 negated: *negated,
303 },
304 })
305}
306
307fn bind_rule_function_expression(
308 expr: &Expr,
309 resolver: &mut dyn VariableResolver,
310 scope: &RuleBindingScope,
311 context: &RuleBindingContext<'_>,
312) -> Result<Expr, SQLError> {
313 let Expr::Func {
314 name,
315 binding,
316 args,
317 distinct,
318 order_by,
319 filter,
320 } = expr
321 else {
322 unreachable!("function binder received a non-function expression")
323 };
324 Ok(Expr::Func {
325 name: name.clone(),
326 binding: binding.clone(),
327 args: bind_exprs(args, resolver, scope, context)?,
328 distinct: *distinct,
329 order_by: bind_orders(order_by, resolver, scope, context)?,
330 filter: filter
331 .as_deref()
332 .map(|expr| bind_rule_expr_with_scope(expr, resolver, scope, context).map(Box::new))
333 .transpose()?,
334 })
335}
336
337fn bind_rule_window_expression(
338 expr: &Expr,
339 resolver: &mut dyn VariableResolver,
340 scope: &RuleBindingScope,
341 context: &RuleBindingContext<'_>,
342) -> Result<Expr, SQLError> {
343 let Expr::WindowCall { name, args, spec } = expr else {
344 unreachable!("window binder received a non-window expression")
345 };
346 Ok(Expr::WindowCall {
347 name: name.clone(),
348 args: bind_exprs(args, resolver, scope, context)?,
349 spec: crate::ast::WindowSpec {
350 reference: spec.reference.clone(),
351 partition_by: bind_exprs(&spec.partition_by, resolver, scope, context)?,
352 order_by: bind_orders(&spec.order_by, resolver, scope, context)?,
353 frame: spec
354 .frame
355 .as_ref()
356 .map(|frame| -> Result<crate::ast::WindowFrame, SQLError> {
357 Ok(crate::ast::WindowFrame {
358 mode: frame.mode,
359 start: bind_frame_bound(&frame.start, resolver, scope, context)?,
360 end: bind_frame_bound(&frame.end, resolver, scope, context)?,
361 })
362 })
363 .transpose()?,
364 },
365 })
366}
367
368fn bind_rule_case_expression(
369 expr: &Expr,
370 resolver: &mut dyn VariableResolver,
371 scope: &RuleBindingScope,
372 context: &RuleBindingContext<'_>,
373) -> Result<Expr, SQLError> {
374 let Expr::Case {
375 base,
376 when,
377 else_branch,
378 } = expr
379 else {
380 unreachable!("CASE binder received a non-CASE expression")
381 };
382 Ok(Expr::Case {
383 base: base
384 .as_deref()
385 .map(|expr| bind_rule_expr_with_scope(expr, resolver, scope, context).map(Box::new))
386 .transpose()?,
387 when: when
388 .iter()
389 .map(|(condition, result)| {
390 Ok((
391 bind_rule_expr_with_scope(condition, resolver, scope, context)?,
392 bind_rule_expr_with_scope(result, resolver, scope, context)?,
393 ))
394 })
395 .collect::<Result<Vec<_>, SQLError>>()?,
396 else_branch: else_branch
397 .as_deref()
398 .map(|expr| bind_rule_expr_with_scope(expr, resolver, scope, context).map(Box::new))
399 .transpose()?,
400 })
401}
402
403fn bind_rule_select_scoped(
404 catalog: &dyn RuleSourceCatalog,
405 select: &SelectStmt,
406 resolver: &mut dyn VariableResolver,
407) -> Result<SelectStmt, SQLError> {
408 bind_select_with_scope(
409 select,
410 resolver,
411 &RuleBindingScope::default(),
412 &RuleBindingContext::with_catalog(catalog, false),
413 )
414}
415
416fn bind_rule_statement_body(
417 statement: &Statement,
418 resolver: &mut dyn VariableResolver,
419 inherited: &RuleBindingScope,
420 context: &RuleBindingContext<'_>,
421) -> Result<Statement, SQLError> {
422 Ok(match statement {
423 Statement::Select(select) => Statement::Select(Box::new(bind_select_with_scope(
424 select, resolver, inherited, context,
425 )?)),
426 Statement::Insert(insert) => {
427 Statement::Insert(bind_insert(insert, resolver, inherited, context)?)
428 }
429 Statement::Update(update) => {
430 Statement::Update(bind_update(update, resolver, inherited, context)?)
431 }
432 Statement::Delete(delete) => {
433 let mut output = delete.clone();
434 output.with = bind_ctes(&delete.with, resolver, inherited, context)?;
435 let context = context.with_ctes(&delete.with)?;
436 let mut target_scope = inherited.clone();
437 target_scope.insert_qualifier(&delete.target_qualifier);
438 output.using = delete
439 .using
440 .as_ref()
441 .map(|source| bind_from(source, resolver, &target_scope, &context))
442 .transpose()?;
443 let mut expression_scope = target_scope;
444 if let Some(source) = &delete.using {
445 collect_visible_scope(source, &context, &mut expression_scope)?;
446 }
447 output.r#where = bind_optional_expr(
448 delete.r#where.as_ref(),
449 resolver,
450 &expression_scope,
451 &context,
452 )?;
453 output.returning.clear();
454 Statement::Delete(output)
455 }
456 _ => return bind_statement(statement, resolver),
457 })
458}
459
460fn bind_assignment_target(
461 target: &crate::ast::AssignmentTarget,
462 resolver: &mut dyn VariableResolver,
463 scope: &RuleBindingScope,
464 context: &RuleBindingContext<'_>,
465) -> Result<crate::ast::AssignmentTarget, SQLError> {
466 let mut target = target.clone();
467 for expression in target.expressions_mut() {
468 *expression = bind_rule_expr_with_scope(expression, resolver, scope, context)?;
469 }
470 Ok(target)
471}
472
473fn bind_update(
474 update: &UpdateStmt,
475 resolver: &mut dyn VariableResolver,
476 inherited: &RuleBindingScope,
477 context: &RuleBindingContext<'_>,
478) -> Result<UpdateStmt, SQLError> {
479 let mut output = update.clone();
480 output.with = bind_ctes(&update.with, resolver, inherited, context)?;
481 let context = context.with_ctes(&update.with)?;
482 let mut target_scope = inherited.clone();
483 target_scope.insert_qualifier(&update.target_qualifier);
484 output.from = update
485 .from
486 .as_ref()
487 .map(|source| bind_from(source, resolver, &target_scope, &context))
488 .transpose()?;
489 let mut expression_scope = target_scope;
490 if let Some(source) = &update.from {
491 collect_visible_scope(source, &context, &mut expression_scope)?;
492 }
493 output.assignments = update
494 .assignments
495 .iter()
496 .map(|(column, expr)| {
497 Ok((
498 bind_assignment_target(column, resolver, &expression_scope, &context)?,
499 bind_rule_expr_with_scope(expr, resolver, &expression_scope, &context)?,
500 ))
501 })
502 .collect::<Result<Vec<_>, SQLError>>()?;
503 output.r#where = bind_optional_expr(
504 update.r#where.as_ref(),
505 resolver,
506 &expression_scope,
507 &context,
508 )?;
509 output.returning.clear();
510 Ok(output)
511}
512
513fn bind_select_with_scope(
514 select: &SelectStmt,
515 resolver: &mut dyn VariableResolver,
516 inherited: &RuleBindingScope,
517 context: &RuleBindingContext<'_>,
518) -> Result<SelectStmt, SQLError> {
519 let local_context = context.with_ctes(&select.with)?;
520 let mut scope = inherited.clone();
521 if let Some(source) = &select.from {
522 collect_visible_scope(source, &local_context, &mut scope)?;
523 }
524 Ok(SelectStmt {
525 projections: bind_projections(&select.projections, resolver, &scope, &local_context)?,
526 values: select
527 .values
528 .iter()
529 .map(|row| bind_expanding_exprs(row, resolver, &scope, &local_context))
530 .collect::<Result<Vec<_>, SQLError>>()?,
531 from: select
532 .from
533 .as_ref()
534 .map(|source| bind_from(source, resolver, inherited, &local_context))
535 .transpose()?,
536 r#where: bind_optional_expr(select.r#where.as_ref(), resolver, &scope, &local_context)?,
537 group_by: bind_exprs(&select.group_by, resolver, &scope, &local_context)?,
538 grouping_sets: select
539 .grouping_sets
540 .iter()
541 .map(|set| bind_exprs(set, resolver, &scope, &local_context))
542 .collect::<Result<Vec<_>, SQLError>>()?,
543 group_distinct: select.group_distinct,
544 having: bind_optional_expr(select.having.as_ref(), resolver, &scope, &local_context)?,
545 order_by: bind_orders(&select.order_by, resolver, &scope, &local_context)?,
546 limit: bind_optional_expr(select.limit.as_ref(), resolver, &scope, &local_context)?,
547 with_ties: select.with_ties,
548 offset: bind_optional_expr(select.offset.as_ref(), resolver, &scope, &local_context)?,
549 with: bind_ctes(&select.with, resolver, inherited, context)?,
550 set_op: select
551 .set_op
552 .as_ref()
553 .map(|operation| -> Result<Box<crate::ast::SetOp>, SQLError> {
554 Ok(Box::new(crate::ast::SetOp {
555 kind: operation.kind,
556 all: operation.all,
557 left: operation
558 .left
559 .as_deref()
560 .map(|left| {
561 bind_select_with_scope(left, resolver, inherited, &local_context)
562 .map(Box::new)
563 })
564 .transpose()?,
565 right: bind_select_with_scope(
566 &operation.right,
567 resolver,
568 inherited,
569 &local_context,
570 )?,
571 combined_order_by: bind_orders(
572 &operation.combined_order_by,
573 resolver,
574 inherited,
575 &local_context,
576 )?,
577 combined_limit: bind_optional_expr(
578 operation.combined_limit.as_ref(),
579 resolver,
580 inherited,
581 &local_context,
582 )?,
583 combined_with_ties: operation.combined_with_ties,
584 combined_offset: bind_optional_expr(
585 operation.combined_offset.as_ref(),
586 resolver,
587 inherited,
588 &local_context,
589 )?,
590 }))
591 })
592 .transpose()?,
593 distinct: select.distinct,
594 distinct_on: bind_exprs(&select.distinct_on, resolver, &scope, &local_context)?,
595 locking: select.locking.clone(),
596 })
597}
598
599fn bind_from(
600 from: &FromClause,
601 resolver: &mut dyn VariableResolver,
602 inherited: &RuleBindingScope,
603 context: &RuleBindingContext<'_>,
604) -> Result<FromClause, SQLError> {
605 Ok(match from {
606 FromClause::Table { .. } => from.clone(),
607 FromClause::Join { .. } => bind_join_from(from, resolver, inherited, context)?,
608 FromClause::Values {
609 rows,
610 alias,
611 column_aliases,
612 internal_relation,
613 internal_column_types,
614 } => FromClause::Values {
615 rows: rows
616 .iter()
617 .map(|row| bind_exprs(row, resolver, inherited, context))
618 .collect::<Result<Vec<_>, SQLError>>()?,
619 alias: alias.clone(),
620 column_aliases: column_aliases.clone(),
621 internal_relation: *internal_relation,
622 internal_column_types: internal_column_types.clone(),
623 },
624 FromClause::Function {
625 name,
626 binding,
627 output_name,
628 relations,
629 args,
630 alias,
631 column_aliases,
632 ordinality,
633 column_types,
634 } => FromClause::Function {
635 name: name.clone(),
636 binding: binding.clone(),
637 output_name: output_name.clone(),
638 relations: relations.clone(),
639 args: bind_exprs(args, resolver, inherited, context)?,
640 alias: alias.clone(),
641 column_aliases: column_aliases.clone(),
642 ordinality: *ordinality,
643 column_types: column_types.clone(),
644 },
645 FromClause::FunctionGroup {
646 functions,
647 alias,
648 column_aliases,
649 ordinality,
650 } => FromClause::FunctionGroup {
651 functions: functions
652 .iter()
653 .map(|function| {
654 Ok(crate::ast::TableFunction {
655 name: function.name.clone(),
656 binding: function.binding.clone(),
657 output_name: function.output_name.clone(),
658 relations: function.relations.clone(),
659 args: bind_exprs(&function.args, resolver, inherited, context)?,
660 column_aliases: function.column_aliases.clone(),
661 column_types: function.column_types.clone(),
662 })
663 })
664 .collect::<Result<Vec<_>, SQLError>>()?,
665 alias: alias.clone(),
666 column_aliases: column_aliases.clone(),
667 ordinality: *ordinality,
668 },
669 FromClause::Subquery {
670 body,
671 alias,
672 column_aliases,
673 } => FromClause::Subquery {
674 body: Box::new(bind_select_with_scope(body, resolver, inherited, context)?),
675 alias: alias.clone(),
676 column_aliases: column_aliases.clone(),
677 },
678 })
679}
680
681fn bind_join_from(
682 from: &FromClause,
683 resolver: &mut dyn VariableResolver,
684 inherited: &RuleBindingScope,
685 context: &RuleBindingContext<'_>,
686) -> Result<FromClause, SQLError> {
687 let FromClause::Join {
688 left,
689 right,
690 kind,
691 on,
692 using,
693 natural,
694 alias,
695 column_aliases,
696 lateral,
697 } = from
698 else {
699 unreachable!("join binder received a non-join source")
700 };
701 let bound_left = bind_from(left, resolver, inherited, context)?;
702 let mut right_scope = inherited.clone();
703 if *lateral {
704 collect_visible_scope(left, context, &mut right_scope)?;
705 }
706 let bound_right = bind_from(right, resolver, &right_scope, context)?;
707 let mut on_scope = inherited.clone();
708 collect_visible_scope(left, context, &mut on_scope)?;
709 collect_visible_scope(right, context, &mut on_scope)?;
710 Ok(FromClause::Join {
711 left: Box::new(bound_left),
712 right: Box::new(bound_right),
713 kind: *kind,
714 on: bind_optional_expr(on.as_ref(), resolver, &on_scope, context)?,
715 using: using.clone(),
716 natural: *natural,
717 alias: alias.clone(),
718 column_aliases: column_aliases.clone(),
719 lateral: *lateral,
720 })
721}
722
723fn bind_ctes(
724 ctes: &[CTE],
725 resolver: &mut dyn VariableResolver,
726 inherited: &RuleBindingScope,
727 context: &RuleBindingContext<'_>,
728) -> Result<Vec<CTE>, SQLError> {
729 let mut visible = context.clone();
730 let mut bound = Vec::with_capacity(ctes.len());
731 for cte in ctes {
732 if cte.recursive {
733 visible
734 .ctes
735 .entry(cte.name.to_ascii_lowercase())
736 .or_default();
737 let mut columns = cte_output_columns(&cte.body, &visible)?;
738 apply_positional_aliases(&mut columns, &cte.columns);
739 visible.ctes.insert(cte.name.to_ascii_lowercase(), columns);
740 }
741 bound.push(CTE {
742 name: cte.name.clone(),
743 columns: cte.columns.clone(),
744 recursive: cte.recursive,
745 materialization: cte.materialization,
746 search: cte.search.clone(),
747 cycle: cte
748 .cycle
749 .as_ref()
750 .map(|cycle| -> Result<crate::ast::CteCycleClause, SQLError> {
751 Ok(crate::ast::CteCycleClause {
752 columns: cycle.columns.clone(),
753 mark_column: cycle.mark_column.clone(),
754 mark_value: bind_rule_expr_with_scope(
755 &cycle.mark_value,
756 resolver,
757 inherited,
758 &visible,
759 )?,
760 mark_default: bind_rule_expr_with_scope(
761 &cycle.mark_default,
762 resolver,
763 inherited,
764 &visible,
765 )?,
766 path_column: cycle.path_column.clone(),
767 })
768 })
769 .transpose()?,
770 body: match &cte.body {
771 crate::ast::CteBody::Query(query) => crate::ast::CteBody::Query(Box::new(
772 bind_select_with_scope(query, resolver, inherited, &visible)?,
773 )),
774 body => body.clone(),
776 },
777 });
778 let mut columns = cte_output_columns(&cte.body, &visible)?;
779 apply_positional_aliases(&mut columns, &cte.columns);
780 if let Some(search) = &cte.search {
781 columns.push(search.sequence_column.clone());
782 }
783 if let Some(cycle) = &cte.cycle {
784 columns.push(cycle.mark_column.clone());
785 columns.push(cycle.path_column.clone());
786 }
787 visible.ctes.insert(cte.name.to_ascii_lowercase(), columns);
788 }
789 Ok(bound)
790}
791
792fn bind_frame_bound(
793 bound: &FrameBound,
794 resolver: &mut dyn VariableResolver,
795 scope: &RuleBindingScope,
796 context: &RuleBindingContext<'_>,
797) -> Result<FrameBound, SQLError> {
798 Ok(match bound {
799 FrameBound::Preceding(expr) => FrameBound::Preceding(Box::new(bind_rule_expr_with_scope(
800 expr, resolver, scope, context,
801 )?)),
802 FrameBound::Following(expr) => FrameBound::Following(Box::new(bind_rule_expr_with_scope(
803 expr, resolver, scope, context,
804 )?)),
805 _ => bound.clone(),
806 })
807}
808
809fn bind_projections(
810 projections: &[Projection],
811 resolver: &mut dyn VariableResolver,
812 scope: &RuleBindingScope,
813 context: &RuleBindingContext<'_>,
814) -> Result<Vec<Projection>, SQLError> {
815 let mut bound = Vec::with_capacity(projections.len());
816 for projection in projections {
817 if let Some(expressions) = expand_qualified_star(&projection.expr, resolver, scope)? {
818 bound.extend(expressions.into_iter().map(|expr| Projection {
819 expr,
820 alias: projection.alias.clone(),
821 }));
822 } else {
823 bound.push(Projection {
824 expr: bind_rule_expr_with_scope(&projection.expr, resolver, scope, context)?,
825 alias: projection.alias.clone(),
826 });
827 }
828 }
829 Ok(bound)
830}
831
832fn bind_expanding_exprs(
833 expressions: &[Expr],
834 resolver: &mut dyn VariableResolver,
835 scope: &RuleBindingScope,
836 context: &RuleBindingContext<'_>,
837) -> Result<Vec<Expr>, SQLError> {
838 let mut bound = Vec::with_capacity(expressions.len());
839 for expression in expressions {
840 if let Some(expressions) = expand_qualified_star(expression, resolver, scope)? {
841 bound.extend(expressions);
842 } else {
843 bound.push(bind_rule_expr_with_scope(
844 expression, resolver, scope, context,
845 )?);
846 }
847 }
848 Ok(bound)
849}
850
851fn expand_qualified_star(
852 expression: &Expr,
853 resolver: &mut dyn VariableResolver,
854 scope: &RuleBindingScope,
855) -> Result<Option<Vec<Expr>>, SQLError> {
856 let Expr::QualifiedStar(qualifier) = expression else {
857 return Ok(None);
858 };
859 if scope.qualifier_is_shadowed(qualifier) {
860 return Ok(None);
861 }
862 resolver.rewrite_qualified_star(qualifier)
863}
864
865fn bind_exprs(
866 expressions: &[Expr],
867 resolver: &mut dyn VariableResolver,
868 scope: &RuleBindingScope,
869 context: &RuleBindingContext<'_>,
870) -> Result<Vec<Expr>, SQLError> {
871 expressions
872 .iter()
873 .map(|expr| bind_rule_expr_with_scope(expr, resolver, scope, context))
874 .collect()
875}
876
877fn bind_optional_expr(
878 expression: Option<&Expr>,
879 resolver: &mut dyn VariableResolver,
880 scope: &RuleBindingScope,
881 context: &RuleBindingContext<'_>,
882) -> Result<Option<Expr>, SQLError> {
883 expression
884 .map(|expr| bind_rule_expr_with_scope(expr, resolver, scope, context))
885 .transpose()
886}
887
888fn bind_orders(
889 orders: &[OrderBy],
890 resolver: &mut dyn VariableResolver,
891 scope: &RuleBindingScope,
892 context: &RuleBindingContext<'_>,
893) -> Result<Vec<OrderBy>, SQLError> {
894 orders
895 .iter()
896 .map(|order| {
897 Ok(OrderBy {
898 expr: bind_rule_expr_with_scope(&order.expr, resolver, scope, context)?,
899 descending: order.descending,
900 nulls: order.nulls,
901 })
902 })
903 .collect()
904}
905
906pub fn invalid_rule_action_reference(qualifier: &str) -> SQLError {
907 SQLError::Routine {
908 sqlstate: "42P01".into(),
909 message: format!(
910 "invalid reference to FROM-clause entry for table \"{qualifier}\"\nDETAIL: There is an entry for table \"{qualifier}\", but it cannot be referenced from this part of the query."
911 ),
912 }
913}