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