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::CompositeRow { items, binding } => Expr::CompositeRow {
252 items: bind_expanding_exprs(items, resolver, scope, context)?,
253 binding: binding.clone(),
254 },
255 Expr::Binary { op, lhs, rhs } => Expr::Binary {
256 op: *op,
257 lhs: Box::new(bind_rule_expr_with_scope(lhs, resolver, scope, context)?),
258 rhs: Box::new(bind_rule_expr_with_scope(rhs, resolver, scope, context)?),
259 },
260 Expr::UnaryMinus(inner) => Expr::UnaryMinus(Box::new(bind_rule_expr_with_scope(
261 inner, resolver, scope, context,
262 )?)),
263 Expr::Not(inner) => Expr::Not(Box::new(bind_rule_expr_with_scope(
264 inner, resolver, scope, context,
265 )?)),
266 Expr::And(items) => Expr::And(bind_exprs(items, resolver, scope, context)?),
267 Expr::Or(items) => Expr::Or(bind_exprs(items, resolver, scope, context)?),
268 Expr::IsNull { expr, negated } => Expr::IsNull {
269 expr: Box::new(bind_rule_expr_with_scope(expr, resolver, scope, context)?),
270 negated: *negated,
271 },
272 Expr::Between { expr, low, high } => Expr::Between {
273 expr: Box::new(bind_rule_expr_with_scope(expr, resolver, scope, context)?),
274 low: Box::new(bind_rule_expr_with_scope(low, resolver, scope, context)?),
275 high: Box::new(bind_rule_expr_with_scope(high, resolver, scope, context)?),
276 },
277 Expr::InList {
278 expr,
279 list,
280 negated,
281 } => Expr::InList {
282 expr: Box::new(bind_rule_expr_with_scope(expr, resolver, scope, context)?),
283 list: bind_exprs(list, resolver, scope, context)?,
284 negated: *negated,
285 },
286 Expr::WindowCall { .. } => bind_rule_window_expression(expr, resolver, scope, context)?,
287 Expr::Case { .. } => bind_rule_case_expression(expr, resolver, scope, context)?,
288 Expr::Cast { expr, ty, implicit } => Expr::Cast {
289 implicit: *implicit,
290 expr: Box::new(bind_rule_expr_with_scope(expr, resolver, scope, context)?),
291 ty: ty.clone(),
292 },
293 Expr::ScalarSubquery(body) => Expr::ScalarSubquery(Box::new(bind_select_with_scope(
294 body, resolver, scope, context,
295 )?)),
296 Expr::Exists { body, negated } => Expr::Exists {
297 body: Box::new(bind_select_with_scope(body, resolver, scope, context)?),
298 negated: *negated,
299 },
300 Expr::InSubquery {
301 expr,
302 body,
303 negated,
304 } => Expr::InSubquery {
305 expr: Box::new(bind_rule_expr_with_scope(expr, resolver, scope, context)?),
306 body: Box::new(bind_select_with_scope(body, resolver, scope, context)?),
307 negated: *negated,
308 },
309 })
310}
311
312fn bind_rule_function_expression(
313 expr: &Expr,
314 resolver: &mut dyn VariableResolver,
315 scope: &RuleBindingScope,
316 context: &RuleBindingContext<'_>,
317) -> Result<Expr, SQLError> {
318 if let Some((qualifier, column)) = namespace::event_field_reference(expr, scope) {
319 return Ok(resolver
320 .rewrite_qualified(qualifier, column)?
321 .unwrap_or_else(|| Expr::qualified_column(qualifier, column)));
322 }
323 let Expr::Func {
324 order_syntax,
325 name,
326 binding,
327 args,
328 distinct,
329 order_by,
330 filter,
331 } = expr
332 else {
333 unreachable!("function binder received a non-function expression")
334 };
335 Ok(Expr::Func {
336 order_syntax: *order_syntax,
337 name: name.clone(),
338 binding: binding.clone(),
339 args: bind_exprs(args, resolver, scope, context)?,
340 distinct: *distinct,
341 order_by: bind_orders(order_by, resolver, scope, context)?,
342 filter: filter
343 .as_deref()
344 .map(|expr| bind_rule_expr_with_scope(expr, resolver, scope, context).map(Box::new))
345 .transpose()?,
346 })
347}
348
349fn bind_window_spec(
350 spec: &crate::ast::WindowSpec,
351 resolver: &mut dyn VariableResolver,
352 scope: &RuleBindingScope,
353 context: &RuleBindingContext<'_>,
354) -> Result<crate::ast::WindowSpec, SQLError> {
355 Ok(crate::ast::WindowSpec {
356 definition: spec.definition,
357 raw_definition: None,
358 reference: spec.reference.clone(),
359 partition_by: bind_exprs(&spec.partition_by, resolver, scope, context)?,
360 order_by: bind_orders(&spec.order_by, resolver, scope, context)?,
361 frame: spec
362 .frame
363 .as_ref()
364 .map(|frame| -> Result<crate::ast::WindowFrame, SQLError> {
365 Ok(crate::ast::WindowFrame {
366 mode: frame.mode,
367 start: bind_frame_bound(&frame.start, resolver, scope, context)?,
368 end: bind_frame_bound(&frame.end, resolver, scope, context)?,
369 between: frame.between,
370 exclusion: frame.exclusion,
371 })
372 })
373 .transpose()?,
374 })
375}
376
377fn bind_rule_window_expression(
378 expr: &Expr,
379 resolver: &mut dyn VariableResolver,
380 scope: &RuleBindingScope,
381 context: &RuleBindingContext<'_>,
382) -> Result<Expr, SQLError> {
383 let Expr::WindowCall {
384 name,
385 args,
386 spec,
387 filter,
388 modifiers,
389 } = expr
390 else {
391 unreachable!("window binder received a non-window expression")
392 };
393 Ok(Expr::WindowCall {
394 modifiers: *modifiers,
395 name: name.clone(),
396 args: bind_exprs(args, resolver, scope, context)?,
397 filter: filter
398 .as_deref()
399 .map(|filter| bind_rule_expr_with_scope(filter, resolver, scope, context).map(Box::new))
400 .transpose()?,
401 spec: Box::new(bind_window_spec(spec, resolver, scope, context)?),
402 })
403}
404
405fn bind_rule_case_expression(
406 expr: &Expr,
407 resolver: &mut dyn VariableResolver,
408 scope: &RuleBindingScope,
409 context: &RuleBindingContext<'_>,
410) -> Result<Expr, SQLError> {
411 let Expr::Case {
412 base,
413 when,
414 else_branch,
415 } = expr
416 else {
417 unreachable!("CASE binder received a non-CASE expression")
418 };
419 Ok(Expr::Case {
420 base: base
421 .as_deref()
422 .map(|expr| bind_rule_expr_with_scope(expr, resolver, scope, context).map(Box::new))
423 .transpose()?,
424 when: when
425 .iter()
426 .map(|(condition, result)| {
427 Ok((
428 bind_rule_expr_with_scope(condition, resolver, scope, context)?,
429 bind_rule_expr_with_scope(result, resolver, scope, context)?,
430 ))
431 })
432 .collect::<Result<Vec<_>, SQLError>>()?,
433 else_branch: else_branch
434 .as_deref()
435 .map(|expr| bind_rule_expr_with_scope(expr, resolver, scope, context).map(Box::new))
436 .transpose()?,
437 })
438}
439
440fn bind_rule_select_scoped(
441 catalog: &dyn RuleSourceCatalog,
442 select: &SelectStmt,
443 resolver: &mut dyn VariableResolver,
444) -> Result<SelectStmt, SQLError> {
445 bind_select_with_scope(
446 select,
447 resolver,
448 &RuleBindingScope::default(),
449 &RuleBindingContext::with_catalog(catalog, false),
450 )
451}
452
453fn bind_rule_statement_body(
454 statement: &Statement,
455 resolver: &mut dyn VariableResolver,
456 inherited: &RuleBindingScope,
457 context: &RuleBindingContext<'_>,
458) -> Result<Statement, SQLError> {
459 Ok(match statement {
460 Statement::Select(select) => Statement::Select(Box::new(bind_select_with_scope(
461 select, resolver, inherited, context,
462 )?)),
463 Statement::Insert(insert) => {
464 Statement::Insert(bind_insert(insert, resolver, inherited, context)?)
465 }
466 Statement::Update(update) => {
467 Statement::Update(bind_update(update, resolver, inherited, context)?)
468 }
469 Statement::Delete(delete) => {
470 let mut output = delete.clone();
471 output.with = bind_ctes(&delete.with, resolver, inherited, context)?;
472 let context = context.with_ctes(&delete.with)?;
473 let mut target_scope = inherited.clone();
474 target_scope.insert_qualifier(&delete.target_qualifier);
475 output.using = delete
476 .using
477 .as_ref()
478 .map(|source| bind_from(source, resolver, &target_scope, &context))
479 .transpose()?;
480 let mut expression_scope = target_scope;
481 if let Some(source) = &delete.using {
482 collect_visible_scope(source, &context, &mut expression_scope)?;
483 }
484 output.r#where = bind_optional_expr(
485 delete.r#where.as_ref(),
486 resolver,
487 &expression_scope,
488 &context,
489 )?;
490 output.returning.clear();
491 Statement::Delete(output)
492 }
493 _ => return bind_statement(statement, resolver),
494 })
495}
496
497fn bind_assignment_targets(
498 targets: &crate::ast::AssignmentTargets,
499 resolver: &mut dyn VariableResolver,
500 scope: &RuleBindingScope,
501 context: &RuleBindingContext<'_>,
502) -> Result<crate::ast::AssignmentTargets, SQLError> {
503 let mut targets = targets.clone();
504 for expression in targets.expressions_mut() {
505 *expression = bind_rule_expr_with_scope(expression, resolver, scope, context)?;
506 }
507 Ok(targets)
508}
509
510fn bind_assignment_target(
511 target: &crate::ast::AssignmentTarget,
512 resolver: &mut dyn VariableResolver,
513 scope: &RuleBindingScope,
514 context: &RuleBindingContext<'_>,
515) -> Result<crate::ast::AssignmentTarget, SQLError> {
516 let mut target = target.clone();
517 for expression in target.expressions_mut() {
518 *expression = bind_rule_expr_with_scope(expression, resolver, scope, context)?;
519 }
520 Ok(target)
521}
522
523fn bind_update(
524 update: &UpdateStmt,
525 resolver: &mut dyn VariableResolver,
526 inherited: &RuleBindingScope,
527 context: &RuleBindingContext<'_>,
528) -> Result<UpdateStmt, SQLError> {
529 let mut output = update.clone();
530 output.with = bind_ctes(&update.with, resolver, inherited, context)?;
531 let context = context.with_ctes(&update.with)?;
532 let mut target_scope = inherited.clone();
533 target_scope.insert_qualifier(&update.target_qualifier);
534 output.from = update
535 .from
536 .as_ref()
537 .map(|source| bind_from(source, resolver, &target_scope, &context))
538 .transpose()?;
539 let mut expression_scope = target_scope;
540 if let Some(source) = &update.from {
541 collect_visible_scope(source, &context, &mut expression_scope)?;
542 }
543 output.assignments = update
544 .assignments
545 .iter()
546 .map(|(column, expr)| {
547 Ok((
548 bind_assignment_targets(column, resolver, &expression_scope, &context)?,
549 bind_rule_expr_with_scope(expr, resolver, &expression_scope, &context)?,
550 ))
551 })
552 .collect::<Result<Vec<_>, SQLError>>()?;
553 output.r#where = bind_optional_expr(
554 update.r#where.as_ref(),
555 resolver,
556 &expression_scope,
557 &context,
558 )?;
559 output.returning.clear();
560 Ok(output)
561}
562
563fn bind_select_with_scope(
564 select: &SelectStmt,
565 resolver: &mut dyn VariableResolver,
566 inherited: &RuleBindingScope,
567 context: &RuleBindingContext<'_>,
568) -> Result<SelectStmt, SQLError> {
569 let local_context = context.with_ctes(&select.with)?;
570 let mut scope = inherited.clone();
571 if let Some(source) = &select.from {
572 collect_visible_scope(source, &local_context, &mut scope)?;
573 }
574 Ok(SelectStmt {
575 windows: select
576 .windows
577 .iter()
578 .map(|window| {
579 Ok(crate::ast::WindowDefinition {
580 name: window.name.clone(),
581 inherited: window.inherited,
582 spec: bind_window_spec(&window.spec, resolver, &scope, &local_context)?,
583 })
584 })
585 .collect::<Result<Vec<_>, SQLError>>()?,
586 projections: bind_projections(&select.projections, resolver, &scope, &local_context)?,
587 values: select
588 .values
589 .iter()
590 .map(|row| bind_expanding_exprs(row, resolver, &scope, &local_context))
591 .collect::<Result<Vec<_>, SQLError>>()?,
592 from: select
593 .from
594 .as_ref()
595 .map(|source| bind_from(source, resolver, inherited, &local_context))
596 .transpose()?,
597 r#where: bind_optional_expr(select.r#where.as_ref(), resolver, &scope, &local_context)?,
598 group_by: bind_exprs(&select.group_by, resolver, &scope, &local_context)?,
599 grouping_sets: select
600 .grouping_sets
601 .iter()
602 .map(|set| bind_exprs(set, resolver, &scope, &local_context))
603 .collect::<Result<Vec<_>, SQLError>>()?,
604 group_distinct: select.group_distinct,
605 having: bind_optional_expr(select.having.as_ref(), resolver, &scope, &local_context)?,
606 order_by: bind_orders(&select.order_by, resolver, &scope, &local_context)?,
607 limit: bind_optional_expr(select.limit.as_ref(), resolver, &scope, &local_context)?,
608 with_ties: select.with_ties,
609 offset: bind_optional_expr(select.offset.as_ref(), resolver, &scope, &local_context)?,
610 with: bind_ctes(&select.with, resolver, inherited, context)?,
611 set_op: select
612 .set_op
613 .as_ref()
614 .map(|operation| -> Result<Box<crate::ast::SetOp>, SQLError> {
615 Ok(Box::new(crate::ast::SetOp {
616 kind: operation.kind,
617 all: operation.all,
618 left: operation
619 .left
620 .as_deref()
621 .map(|left| {
622 bind_select_with_scope(left, resolver, inherited, &local_context)
623 .map(Box::new)
624 })
625 .transpose()?,
626 right: bind_select_with_scope(
627 &operation.right,
628 resolver,
629 inherited,
630 &local_context,
631 )?,
632 combined_order_by: bind_orders(
633 &operation.combined_order_by,
634 resolver,
635 inherited,
636 &local_context,
637 )?,
638 combined_limit: bind_optional_expr(
639 operation.combined_limit.as_ref(),
640 resolver,
641 inherited,
642 &local_context,
643 )?,
644 combined_with_ties: operation.combined_with_ties,
645 combined_offset: bind_optional_expr(
646 operation.combined_offset.as_ref(),
647 resolver,
648 inherited,
649 &local_context,
650 )?,
651 }))
652 })
653 .transpose()?,
654 distinct: select.distinct,
655 distinct_on: bind_exprs(&select.distinct_on, resolver, &scope, &local_context)?,
656 locking: select.locking.clone(),
657 })
658}
659
660fn bind_from(
661 from: &FromClause,
662 resolver: &mut dyn VariableResolver,
663 inherited: &RuleBindingScope,
664 context: &RuleBindingContext<'_>,
665) -> Result<FromClause, SQLError> {
666 Ok(match from {
667 FromClause::Table { .. } => from.clone(),
668 FromClause::Join { .. } => bind_join_from(from, resolver, inherited, context)?,
669 FromClause::Values {
670 rows,
671 alias,
672 column_aliases,
673 internal_relation,
674 internal_column_types,
675 internal_column_collations,
676 } => FromClause::Values {
677 rows: rows
678 .iter()
679 .map(|row| bind_exprs(row, resolver, inherited, context))
680 .collect::<Result<Vec<_>, SQLError>>()?,
681 alias: alias.clone(),
682 column_aliases: column_aliases.clone(),
683 internal_relation: *internal_relation,
684 internal_column_types: internal_column_types.clone(),
685 internal_column_collations: internal_column_collations.clone(),
686 },
687 FromClause::Function {
688 name,
689 binding,
690 output_name,
691 relations,
692 args,
693 alias,
694 column_aliases,
695 ordinality,
696 column_types,
697 } => FromClause::Function {
698 name: name.clone(),
699 binding: binding.clone(),
700 output_name: output_name.clone(),
701 relations: relations.clone(),
702 args: bind_exprs(args, resolver, inherited, context)?,
703 alias: alias.clone(),
704 column_aliases: column_aliases.clone(),
705 ordinality: *ordinality,
706 column_types: column_types.clone(),
707 },
708 FromClause::FunctionGroup {
709 functions,
710 alias,
711 column_aliases,
712 ordinality,
713 } => FromClause::FunctionGroup {
714 functions: functions
715 .iter()
716 .map(|function| {
717 Ok(crate::ast::TableFunction {
718 name: function.name.clone(),
719 binding: function.binding.clone(),
720 output_name: function.output_name.clone(),
721 relations: function.relations.clone(),
722 args: bind_exprs(&function.args, resolver, inherited, context)?,
723 column_aliases: function.column_aliases.clone(),
724 column_types: function.column_types.clone(),
725 })
726 })
727 .collect::<Result<Vec<_>, SQLError>>()?,
728 alias: alias.clone(),
729 column_aliases: column_aliases.clone(),
730 ordinality: *ordinality,
731 },
732 FromClause::Subquery {
733 body,
734 alias,
735 column_aliases,
736 } => FromClause::Subquery {
737 body: Box::new(bind_select_with_scope(body, resolver, inherited, context)?),
738 alias: alias.clone(),
739 column_aliases: column_aliases.clone(),
740 },
741 })
742}
743
744fn bind_join_from(
745 from: &FromClause,
746 resolver: &mut dyn VariableResolver,
747 inherited: &RuleBindingScope,
748 context: &RuleBindingContext<'_>,
749) -> Result<FromClause, SQLError> {
750 let FromClause::Join {
751 left,
752 right,
753 kind,
754 on,
755 using,
756 natural,
757 alias,
758 column_aliases,
759 lateral,
760 } = from
761 else {
762 unreachable!("join binder received a non-join source")
763 };
764 let bound_left = bind_from(left, resolver, inherited, context)?;
765 let mut right_scope = inherited.clone();
766 if *lateral {
767 collect_visible_scope(left, context, &mut right_scope)?;
768 }
769 let bound_right = bind_from(right, resolver, &right_scope, context)?;
770 let mut on_scope = inherited.clone();
771 collect_visible_scope(left, context, &mut on_scope)?;
772 collect_visible_scope(right, context, &mut on_scope)?;
773 Ok(FromClause::Join {
774 left: Box::new(bound_left),
775 right: Box::new(bound_right),
776 kind: *kind,
777 on: bind_optional_expr(on.as_ref(), resolver, &on_scope, context)?,
778 using: using.clone(),
779 natural: *natural,
780 alias: alias.clone(),
781 column_aliases: column_aliases.clone(),
782 lateral: *lateral,
783 })
784}
785
786fn bind_ctes(
787 ctes: &[CTE],
788 resolver: &mut dyn VariableResolver,
789 inherited: &RuleBindingScope,
790 context: &RuleBindingContext<'_>,
791) -> Result<Vec<CTE>, SQLError> {
792 let mut visible = context.clone();
793 let mut bound = Vec::with_capacity(ctes.len());
794 for cte in ctes {
795 if cte.recursive {
796 visible
797 .ctes
798 .entry(cte.name.to_ascii_lowercase())
799 .or_default();
800 let mut columns = cte_output_columns(&cte.body, &visible)?;
801 apply_positional_aliases(&mut columns, &cte.columns);
802 visible.ctes.insert(cte.name.to_ascii_lowercase(), columns);
803 }
804 bound.push(CTE {
805 name: cte.name.clone(),
806 columns: cte.columns.clone(),
807 recursive: cte.recursive,
808 materialization: cte.materialization,
809 search: cte.search.clone(),
810 cycle: cte
811 .cycle
812 .as_ref()
813 .map(|cycle| -> Result<crate::ast::CteCycleClause, SQLError> {
814 Ok(crate::ast::CteCycleClause {
815 columns: cycle.columns.clone(),
816 mark_column: cycle.mark_column.clone(),
817 mark_value: bind_rule_expr_with_scope(
818 &cycle.mark_value,
819 resolver,
820 inherited,
821 &visible,
822 )?,
823 mark_default: bind_rule_expr_with_scope(
824 &cycle.mark_default,
825 resolver,
826 inherited,
827 &visible,
828 )?,
829 path_column: cycle.path_column.clone(),
830 })
831 })
832 .transpose()?,
833 body: match &cte.body {
834 crate::ast::CteBody::Query(query) => crate::ast::CteBody::Query(Box::new(
835 bind_select_with_scope(query, resolver, inherited, &visible)?,
836 )),
837 body => body.clone(),
839 },
840 });
841 let mut columns = cte_output_columns(&cte.body, &visible)?;
842 apply_positional_aliases(&mut columns, &cte.columns);
843 if let Some(search) = &cte.search {
844 columns.push(search.sequence_column.clone());
845 }
846 if let Some(cycle) = &cte.cycle {
847 columns.push(cycle.mark_column.clone());
848 columns.push(cycle.path_column.clone());
849 }
850 visible.ctes.insert(cte.name.to_ascii_lowercase(), columns);
851 }
852 Ok(bound)
853}
854
855fn bind_frame_bound(
856 bound: &FrameBound,
857 resolver: &mut dyn VariableResolver,
858 scope: &RuleBindingScope,
859 context: &RuleBindingContext<'_>,
860) -> Result<FrameBound, SQLError> {
861 Ok(match bound {
862 FrameBound::Preceding(expr) => FrameBound::Preceding(Box::new(bind_rule_expr_with_scope(
863 expr, resolver, scope, context,
864 )?)),
865 FrameBound::Following(expr) => FrameBound::Following(Box::new(bind_rule_expr_with_scope(
866 expr, resolver, scope, context,
867 )?)),
868 _ => bound.clone(),
869 })
870}
871
872fn bind_projections(
873 projections: &[Projection],
874 resolver: &mut dyn VariableResolver,
875 scope: &RuleBindingScope,
876 context: &RuleBindingContext<'_>,
877) -> Result<Vec<Projection>, SQLError> {
878 let mut bound = Vec::with_capacity(projections.len());
879 for projection in projections {
880 if let Some(expressions) = expand_qualified_star(&projection.expr, resolver, scope)? {
881 bound.extend(expressions.into_iter().map(|expr| Projection {
882 expr,
883 alias: projection.alias.clone(),
884 }));
885 } else {
886 bound.push(Projection {
887 expr: bind_rule_expr_with_scope(&projection.expr, resolver, scope, context)?,
888 alias: projection.alias.clone(),
889 });
890 }
891 }
892 Ok(bound)
893}
894
895fn bind_expanding_exprs(
896 expressions: &[Expr],
897 resolver: &mut dyn VariableResolver,
898 scope: &RuleBindingScope,
899 context: &RuleBindingContext<'_>,
900) -> Result<Vec<Expr>, SQLError> {
901 let mut bound = Vec::with_capacity(expressions.len());
902 for expression in expressions {
903 if let Some(expressions) = expand_qualified_star(expression, resolver, scope)? {
904 bound.extend(expressions);
905 } else {
906 bound.push(bind_rule_expr_with_scope(
907 expression, resolver, scope, context,
908 )?);
909 }
910 }
911 Ok(bound)
912}
913
914fn expand_qualified_star(
915 expression: &Expr,
916 resolver: &mut dyn VariableResolver,
917 scope: &RuleBindingScope,
918) -> Result<Option<Vec<Expr>>, SQLError> {
919 let Expr::QualifiedStar(qualifier) = expression else {
920 return Ok(None);
921 };
922 if scope.qualifier_is_shadowed(qualifier) {
923 return Ok(None);
924 }
925 resolver.rewrite_qualified_star(qualifier)
926}
927
928fn bind_exprs(
929 expressions: &[Expr],
930 resolver: &mut dyn VariableResolver,
931 scope: &RuleBindingScope,
932 context: &RuleBindingContext<'_>,
933) -> Result<Vec<Expr>, SQLError> {
934 expressions
935 .iter()
936 .map(|expr| bind_rule_expr_with_scope(expr, resolver, scope, context))
937 .collect()
938}
939
940fn bind_optional_expr(
941 expression: Option<&Expr>,
942 resolver: &mut dyn VariableResolver,
943 scope: &RuleBindingScope,
944 context: &RuleBindingContext<'_>,
945) -> Result<Option<Expr>, SQLError> {
946 expression
947 .map(|expr| bind_rule_expr_with_scope(expr, resolver, scope, context))
948 .transpose()
949}
950
951fn bind_orders(
952 orders: &[OrderBy],
953 resolver: &mut dyn VariableResolver,
954 scope: &RuleBindingScope,
955 context: &RuleBindingContext<'_>,
956) -> Result<Vec<OrderBy>, SQLError> {
957 orders
958 .iter()
959 .map(|order| {
960 Ok(OrderBy {
961 expr: bind_rule_expr_with_scope(&order.expr, resolver, scope, context)?,
962 descending: order.descending,
963 nulls: order.nulls,
964 })
965 })
966 .collect()
967}
968
969pub fn invalid_rule_relation_reference(qualifier: &str) -> SQLError {
970 SQLError::Diagnostic {
971 sqlstate: "42P01".into(),
972 message: format!("invalid reference to FROM-clause entry for table \"{qualifier}\""),
973 detail: Some(format!(
974 "There is an entry for table \"{qualifier}\", but it cannot be referenced from this part of the query."
975 )),
976 hint: None,
977 }
978}