1use rudb_catalog::{Catalog, same_name};
16use rudb_common::{Error, Field, LogicalType, Result, Value};
17use rudb_functions::resolve;
18use rudb_parse::ast::{self, Ast, Distinct, LiteralKind, Nulls, Order, Quantifier, SetOp};
19use rudb_parse::{NONE, parse_ast};
20use rudb_plan::{ColumnBinding, Expr, ExprRef, JoinKind, Node, NodeRef, Plan, SetOpKind, SortKey};
21
22use crate::expr::{describe, has_aggregate};
23use crate::scope::{Scope, Visible};
24
25pub fn bind(ast: &Ast, catalog: &Catalog) -> Result<Plan> {
32 let query = match ast.statements.as_slice() {
33 [ast::Statement::Query(query)] => *query,
34 [] => return Err(Error::binder("no statement to bind")),
35 _ => return Err(Error::not_implemented("a script of more than one statement")),
36 };
37 let mut binder = Binder::new(catalog);
38 let (root, _) = binder.bind_query(ast, query)?;
39 let mut plan = binder.into_plan();
40 plan.set_root(root);
41 plan.validate()?;
42 Ok(plan)
43}
44
45pub fn bind_sql(query: &str, catalog: &Catalog) -> Result<Plan> {
51 let ast = parse_ast(query)?;
52 bind(&ast, catalog)
53}
54
55#[derive(Debug)]
57pub(crate) struct Aggregation {
58 pub(crate) index: u32,
60 pub(crate) groups: Vec<ExprRef>,
62 pub(crate) aggregates: Vec<ExprRef>,
64}
65
66#[derive(Debug)]
68pub(crate) struct Binder<'a> {
69 catalog: &'a Catalog,
70 plan: Plan,
71 next_index: u32,
72 pub(crate) aggregation: Option<Aggregation>,
74 pub(crate) in_aggregate: bool,
76 pub(crate) clause: &'static str,
78}
79
80impl<'a> Binder<'a> {
81 pub(crate) fn new(catalog: &'a Catalog) -> Self {
82 Self {
83 catalog,
84 plan: Plan::new(),
85 next_index: 0,
86 aggregation: None,
87 in_aggregate: false,
88 clause: "SELECT clause",
89 }
90 }
91
92 pub(crate) fn plan(&self) -> &Plan {
93 &self.plan
94 }
95
96 pub(crate) fn plan_mut(&mut self) -> &mut Plan {
97 &mut self.plan
98 }
99
100 pub(crate) fn into_plan(self) -> Plan {
101 self.plan
102 }
103
104 fn fresh_index(&mut self) -> u32 {
106 let index = self.next_index;
107 self.next_index += 1;
108 index
109 }
110
111 fn column(&mut self, index: u32, position: usize, ty: LogicalType) -> ExprRef {
113 let binding = ColumnBinding::new(index, position as u32);
114 self.plan.add_expr(Expr::Column(binding), ty)
115 }
116
117 pub(crate) fn bind_query(
120 &mut self,
121 ast: &Ast,
122 query: ast::QueryRef,
123 ) -> Result<(NodeRef, Scope)> {
124 let written = ast.query(query);
125 match written.body {
126 ast::QueryBody::Select(select) => self.bind_select(ast, select, &written),
127 ast::QueryBody::SetOp { op, quantifier, by_name, left, right } => {
128 if by_name {
129 return Err(Error::not_implemented("UNION BY NAME"));
130 }
131 self.bind_set_op(ast, &written, op, quantifier, left, right)
132 }
133 }
134 }
135
136 fn bind_set_op(
137 &mut self,
138 ast: &Ast,
139 query: &ast::Query,
140 op: SetOp,
141 quantifier: Quantifier,
142 left: ast::QueryRef,
143 right: ast::QueryRef,
144 ) -> Result<(NodeRef, Scope)> {
145 let (left_node, left_scope) = self.bind_query(ast, left)?;
146 let (right_node, right_scope) = self.bind_query(ast, right)?;
147 if left_scope.len() != right_scope.len() {
148 return Err(Error::binder(format!(
149 "Set operations can only apply to expressions with the same number of result columns, but left side has {} and right side has {}",
150 left_scope.len(),
151 right_scope.len()
152 )));
153 }
154 let mut types = Vec::with_capacity(left_scope.len());
156 for (left, right) in left_scope.columns.iter().zip(&right_scope.columns) {
157 let common = left.ty.promote(&right.ty).ok_or_else(|| {
158 Error::binder(format!(
159 "Cannot combine a column of type {} with a column of type {} in a set operation",
160 left.ty, right.ty
161 ))
162 })?;
163 types.push(common);
164 }
165 let left_node = self.conform(left_node, &left_scope, &types);
166 let right_node = self.conform(right_node, &right_scope, &types);
167 let index = self.fresh_index();
168 let kind = match op {
169 SetOp::Union => SetOpKind::Union,
170 SetOp::Except => SetOpKind::Except,
171 SetOp::Intersect => SetOpKind::Intersect,
172 };
173 let all = quantifier == Quantifier::All;
176 let mut node = self.plan.add_node(Node::SetOp {
177 left: left_node,
178 right: right_node,
179 kind,
180 all,
181 index,
182 });
183 let mut scope = Scope::empty();
184 for (at, (column, ty)) in left_scope.columns.iter().zip(&types).enumerate() {
185 scope.push(Visible {
186 table: String::new(),
187 name: column.name.clone(),
188 binding: ColumnBinding::new(index, at as u32),
189 ty: ty.clone(),
190 });
191 }
192 let keys = self.sort_keys(ast, query, &scope, &[])?;
196 if !keys.is_empty() {
197 let keys = self.plan.add_sort_keys(&keys);
198 node = self.plan.add_node(Node::Sort { input: node, keys });
199 }
200 node = self.apply_limit(ast, query, node)?;
201 Ok((node, scope))
202 }
203
204 fn conform(&mut self, node: NodeRef, scope: &Scope, types: &[LogicalType]) -> NodeRef {
206 if scope.columns.iter().zip(types).all(|(column, ty)| &column.ty == ty) {
207 return node;
208 }
209 let index = self.fresh_index();
210 let mut exprs = Vec::with_capacity(types.len());
211 let mut names = Vec::with_capacity(types.len());
212 for (column, ty) in scope.columns.iter().zip(types) {
213 let expr = self.plan.add_expr(Expr::Column(column.binding), column.ty.clone());
214 exprs.push(self.cast_to(expr, ty));
215 names.push(self.plan.intern(&column.name));
216 }
217 let exprs = self.plan.add_expr_list(&exprs);
218 let names = self.plan.add_name_list(&names);
219 self.plan.add_node(Node::Project { input: node, index, exprs, names })
220 }
221
222 fn bind_select(
225 &mut self,
226 ast: &Ast,
227 select: ast::SelectRef,
228 query: &ast::Query,
229 ) -> Result<(NodeRef, Scope)> {
230 let written = ast.select(select);
231 let (mut node, input) = self.bind_from(ast, written.from)?;
232
233 if written.filter != NONE {
234 self.clause = "WHERE clause";
235 let predicate = self.bind_expr(ast, written.filter, &input)?;
236 let predicate = self.as_boolean(predicate, "WHERE")?;
237 node = self.plan.add_node(Node::Filter { input: node, predicate });
238 }
239
240 let targets = ast.target_list(written.targets).to_vec();
241 if targets.is_empty() {
242 return Err(Error::binder("a SELECT needs at least one expression to select"));
243 }
244
245 let group_items = self.group_items(ast, &written, &targets)?;
246 let aggregating = !group_items.is_empty()
247 || written.having != NONE
248 || targets.iter().any(|target| has_aggregate(ast, target.expr));
249 if aggregating {
250 self.clause = "GROUP BY clause";
251 let mut groups = Vec::with_capacity(group_items.len());
252 for item in &group_items {
253 groups.push(self.bind_expr(ast, *item, &input)?);
254 }
255 let index = self.fresh_index();
256 self.aggregation = Some(Aggregation { index, groups, aggregates: Vec::new() });
257 }
258
259 self.clause = "SELECT clause";
260 let (mut exprs, mut names) = self.bind_targets(ast, &targets, &input)?;
261 let visible = exprs.len();
262
263 let mut having = None;
264 if written.having != NONE {
265 self.clause = "HAVING clause";
266 let predicate = self.bind_expr(ast, written.having, &input)?;
267 let predicate = self.over_aggregate(predicate, &input)?;
268 having = Some(self.as_boolean(predicate, "HAVING")?);
269 }
270
271 let project = self.fresh_index();
274 let mut output = Scope::empty();
275 for (at, (expr, name)) in exprs.iter().zip(&names).enumerate() {
276 output.push(Visible {
277 table: String::new(),
278 name: name.clone(),
279 binding: ColumnBinding::new(project, at as u32),
280 ty: self.plan.expr_type(*expr).clone(),
281 });
282 }
283
284 self.clause = "ORDER BY clause";
285 let mut extra = Vec::new();
286 let keys = self.select_sort_keys(
287 ast, query, &input, &output, project, &mut exprs, &mut names, &mut extra,
288 )?;
289 if !extra.is_empty() && written.distinct != Distinct::No {
290 return Err(Error::binder(
291 "For SELECT DISTINCT, ORDER BY expressions must appear in the select list",
292 ));
293 }
294 let on = self.distinct_on(ast, written.distinct, &output)?;
295
296 if let Some(aggregation) = self.aggregation.take() {
297 let index = aggregation.index;
298 let groups = self.plan.add_expr_list(&aggregation.groups);
299 let aggregates = self.plan.add_expr_list(&aggregation.aggregates);
300 node = self.plan.add_node(Node::Aggregate { input: node, index, groups, aggregates });
301 }
302 if let Some(predicate) = having {
303 node = self.plan.add_node(Node::Filter { input: node, predicate });
304 }
305
306 let interned: Vec<u32> = names.iter().map(|name| self.plan.intern(name)).collect();
307 let exprs_slice = self.plan.add_expr_list(&exprs);
308 let names_slice = self.plan.add_name_list(&interned);
309 node = self.plan.add_node(Node::Project {
310 input: node,
311 index: project,
312 exprs: exprs_slice,
313 names: names_slice,
314 });
315
316 if written.distinct != Distinct::No {
317 let on = self.plan.add_expr_list(&on);
318 node = self.plan.add_node(Node::Distinct { input: node, on });
319 }
320 if !keys.is_empty() {
321 let keys = self.plan.add_sort_keys(&keys);
322 node = self.plan.add_node(Node::Sort { input: node, keys });
323 }
324 node = self.apply_limit(ast, query, node)?;
325
326 if extra.is_empty() {
327 output.columns.truncate(visible);
328 return Ok((node, output));
329 }
330 let index = self.fresh_index();
333 let mut kept = Vec::with_capacity(visible);
334 let mut kept_names = Vec::with_capacity(visible);
335 let mut scope = Scope::empty();
336 for (at, name) in names.iter().enumerate().take(visible) {
337 let ty = output.columns[at].ty.clone();
338 kept.push(self.column(project, at, ty.clone()));
339 kept_names.push(self.plan.intern(name));
340 scope.push(Visible {
341 table: String::new(),
342 name: name.clone(),
343 binding: ColumnBinding::new(index, at as u32),
344 ty,
345 });
346 }
347 let exprs = self.plan.add_expr_list(&kept);
348 let names = self.plan.add_name_list(&kept_names);
349 node = self.plan.add_node(Node::Project { input: node, index, exprs, names });
350 Ok((node, scope))
351 }
352
353 fn bind_targets(
355 &mut self,
356 ast: &Ast,
357 targets: &[ast::Target],
358 input: &Scope,
359 ) -> Result<(Vec<ExprRef>, Vec<String>)> {
360 let mut exprs = Vec::with_capacity(targets.len());
361 let mut names = Vec::with_capacity(targets.len());
362 for target in targets {
363 if let ast::Expr::Star { qualifier } = ast.expr(target.expr) {
364 let table = ast.name(qualifier).last().map(str::to_string);
365 let expanded: Vec<Visible> =
366 input.star(table.as_deref())?.into_iter().cloned().collect();
367 for column in expanded {
368 let expr = self.plan.add_expr(Expr::Column(column.binding), column.ty);
369 exprs.push(self.over_aggregate(expr, input)?);
370 names.push(column.name);
371 }
372 continue;
373 }
374 let expr = self.bind_expr(ast, target.expr, input)?;
375 exprs.push(self.over_aggregate(expr, input)?);
376 names.push(if target.alias == NONE {
377 self.output_name(ast, target.expr, input)
378 } else {
379 ast.string(target.alias).to_string()
380 });
381 }
382 Ok((exprs, names))
383 }
384
385 fn output_name(&self, ast: &Ast, target: ast::ExprRef, input: &Scope) -> String {
391 if let ast::Expr::Column { name } = ast.expr(target) {
392 let parts: Vec<&str> = ast.name(name).collect();
393 if let Ok(found) = input.resolve(&parts) {
394 return found.name.clone();
395 }
396 }
397 describe(ast, target)
398 }
399
400 fn group_items(
402 &self,
403 ast: &Ast,
404 select: &ast::Select,
405 targets: &[ast::Target],
406 ) -> Result<Vec<ast::ExprRef>> {
407 if select.group_by_all {
408 return Ok(targets
411 .iter()
412 .filter(|target| !has_aggregate(ast, target.expr))
413 .map(|target| target.expr)
414 .collect());
415 }
416 let mut items = Vec::new();
417 for &item in ast.expr_list(select.group_by) {
418 items.push(self.output_reference(ast, item, targets, "GROUP BY")?.unwrap_or(item));
419 }
420 Ok(items)
421 }
422
423 fn output_reference(
425 &self,
426 ast: &Ast,
427 item: ast::ExprRef,
428 targets: &[ast::Target],
429 clause: &str,
430 ) -> Result<Option<ast::ExprRef>> {
431 match ast.expr(item) {
432 ast::Expr::Literal { kind: LiteralKind::Number, text } => {
433 let written = ast.string(text);
434 let position: usize = written.parse().map_err(|_| {
435 Error::binder(format!("{clause} term {written} is not a column"))
436 })?;
437 if position == 0 || position > targets.len() {
438 return Err(Error::binder(format!(
439 "{clause} term out of range - should be between 1 and {}",
440 targets.len()
441 )));
442 }
443 Ok(Some(targets[position - 1].expr))
444 }
445 ast::Expr::Column { name } => {
446 let parts: Vec<&str> = ast.name(name).collect();
447 let [written] = parts.as_slice() else { return Ok(None) };
448 let mut found = None;
449 for target in targets {
450 if target.alias != NONE && same_name(ast.string(target.alias), written) {
451 if found.is_some() {
452 return Ok(None);
453 }
454 found = Some(target.expr);
455 }
456 }
457 Ok(found)
458 }
459 _ => Ok(None),
460 }
461 }
462
463 #[allow(clippy::too_many_arguments)]
467 fn select_sort_keys(
468 &mut self,
469 ast: &Ast,
470 query: &ast::Query,
471 input: &Scope,
472 output: &Scope,
473 project: u32,
474 exprs: &mut Vec<ExprRef>,
475 names: &mut Vec<String>,
476 extra: &mut Vec<usize>,
477 ) -> Result<Vec<SortKey>> {
478 if query.order_by_all {
479 return Ok(self.every_column(output));
480 }
481 let items = ast.order_list(query.order_by).to_vec();
482 let mut keys = Vec::with_capacity(items.len());
483 for item in items {
484 let position = match self.output_position(ast, item.expr, output)? {
485 Some(position) => position,
486 None => {
487 let bound = self.bind_expr(ast, item.expr, input)?;
488 let bound = self.over_aggregate(bound, input)?;
489 match exprs.iter().position(|&held| self.same_expr(held, bound)) {
490 Some(position) => position,
491 None => {
492 exprs.push(bound);
493 names.push(describe(ast, item.expr));
494 extra.push(exprs.len() - 1);
495 exprs.len() - 1
496 }
497 }
498 }
499 };
500 let ty = self.plan.expr_type(exprs[position]).clone();
501 let expr = self.column(project, position, ty);
502 keys.push(sort_key(expr, item));
503 }
504 Ok(keys)
505 }
506
507 fn sort_keys(
509 &mut self,
510 ast: &Ast,
511 query: &ast::Query,
512 output: &Scope,
513 targets: &[ast::Target],
514 ) -> Result<Vec<SortKey>> {
515 if query.order_by_all {
516 return Ok(self.every_column(output));
517 }
518 let items = ast.order_list(query.order_by).to_vec();
519 let mut keys = Vec::with_capacity(items.len());
520 for item in items {
521 let expr = match self.output_position(ast, item.expr, output)? {
522 Some(position) => {
523 let column = &output.columns[position];
524 let (binding, ty) = (column.binding, column.ty.clone());
525 self.plan.add_expr(Expr::Column(binding), ty)
526 }
527 None => {
528 let _ = targets;
529 self.bind_expr(ast, item.expr, output)?
530 }
531 };
532 keys.push(sort_key(expr, item));
533 }
534 Ok(keys)
535 }
536
537 fn every_column(&mut self, output: &Scope) -> Vec<SortKey> {
538 let columns: Vec<(ColumnBinding, LogicalType)> =
539 output.columns.iter().map(|column| (column.binding, column.ty.clone())).collect();
540 columns
541 .into_iter()
542 .map(|(binding, ty)| {
543 let expr = self.plan.add_expr(Expr::Column(binding), ty);
544 SortKey { expr, descending: false, nulls_first: false }
545 })
546 .collect()
547 }
548
549 fn output_position(
551 &self,
552 ast: &Ast,
553 item: ast::ExprRef,
554 output: &Scope,
555 ) -> Result<Option<usize>> {
556 match ast.expr(item) {
557 ast::Expr::Literal { kind: LiteralKind::Number, text } => {
558 let written = ast.string(text);
559 if written.contains(['.', 'e', 'E']) {
560 return Ok(None);
561 }
562 let position: usize = written.parse().map_err(|_| {
563 Error::binder(format!("ORDER BY term {written} is not a column"))
564 })?;
565 if position == 0 || position > output.len() {
566 return Err(Error::binder(format!(
567 "ORDER BY term out of range - should be between 1 and {}",
568 output.len()
569 )));
570 }
571 Ok(Some(position - 1))
572 }
573 ast::Expr::Column { name } => {
574 let parts: Vec<&str> = ast.name(name).collect();
575 let [written] = parts.as_slice() else { return Ok(None) };
576 Ok(output.position_of(None, written))
577 }
578 _ => Ok(None),
579 }
580 }
581
582 fn distinct_on(
584 &mut self,
585 ast: &Ast,
586 distinct: Distinct,
587 output: &Scope,
588 ) -> Result<Vec<ExprRef>> {
589 let Distinct::On(items) = distinct else {
590 return Ok(Vec::new());
591 };
592 let items = ast.expr_list(items).to_vec();
593 let mut on = Vec::with_capacity(items.len());
594 for item in items {
595 let Some(position) = self.output_position(ast, item, output)? else {
596 return Err(Error::not_implemented(
597 "DISTINCT ON an expression that is not in the select list",
598 ));
599 };
600 let column = &output.columns[position];
601 let (binding, ty) = (column.binding, column.ty.clone());
602 on.push(self.plan.add_expr(Expr::Column(binding), ty));
603 }
604 Ok(on)
605 }
606
607 fn apply_limit(&mut self, ast: &Ast, query: &ast::Query, input: NodeRef) -> Result<NodeRef> {
608 if query.limit_percent {
609 return Err(Error::not_implemented("LIMIT with a percentage"));
610 }
611 let count = self.constant_count(ast, query.limit, "LIMIT")?;
612 let offset = self.constant_count(ast, query.offset, "OFFSET")?.unwrap_or(0);
613 if count.is_none() && offset == 0 {
614 return Ok(input);
615 }
616 Ok(self.plan.add_node(Node::Limit { input, count, offset }))
617 }
618
619 fn constant_count(
621 &mut self,
622 ast: &Ast,
623 written: ast::ExprRef,
624 clause: &str,
625 ) -> Result<Option<u64>> {
626 if written == NONE {
627 return Ok(None);
628 }
629 self.clause = "LIMIT clause";
630 let scope = Scope::empty();
631 let bound = self.bind_expr(ast, written, &scope)?;
632 let Expr::Constant(value) = *self.plan.expr(bound) else {
633 return Err(Error::not_implemented(format!("a {clause} that is not a constant")));
634 };
635 let count = match self.plan.value(value) {
636 Value::Null => return Ok(None),
637 Value::TinyInt(count) => i128::from(*count),
638 Value::SmallInt(count) => i128::from(*count),
639 Value::Integer(count) => i128::from(*count),
640 Value::BigInt(count) => i128::from(*count),
641 Value::HugeInt(count) => *count,
642 other => {
643 return Err(Error::binder(format!(
644 "{clause} takes a whole number of rows, not a value of type {}",
645 other.logical_type()
646 )));
647 }
648 };
649 u64::try_from(count)
650 .map(Some)
651 .map_err(|_| Error::binder(format!("{clause} must not be negative")))
652 }
653
654 fn bind_from(&mut self, ast: &Ast, from: ast::Slice) -> Result<(NodeRef, Scope)> {
657 let sources = ast.source_list(from).to_vec();
658 let Some((first, rest)) = sources.split_first() else {
659 return Ok((self.plan.add_node(Node::Dummy), Scope::empty()));
662 };
663 let (mut node, mut scope) = self.bind_source(ast, *first)?;
664 for source in rest {
665 let (right, right_scope) = self.bind_source(ast, *source)?;
666 node = self.plan.add_node(Node::CrossProduct { left: node, right });
667 scope = scope.concat(right_scope);
668 }
669 Ok((node, scope))
670 }
671
672 fn bind_source(&mut self, ast: &Ast, source: ast::SourceRef) -> Result<(NodeRef, Scope)> {
673 match ast.source(source) {
674 ast::Source::Table { name, alias, columns } => {
675 self.bind_table(ast, name, alias, columns)
676 }
677 ast::Source::Subquery { query, alias, columns } => {
678 let (node, mut scope) = self.bind_query(ast, query)?;
679 let label = if alias == NONE {
680 "unnamed_subquery".to_string()
681 } else {
682 ast.string(alias).to_string()
683 };
684 scope.relabel(&label);
685 if !columns.is_empty() {
686 let names: Vec<&str> = ast.name(columns).collect();
687 scope.rename(&names, &label)?;
688 }
689 Ok((node, scope))
690 }
691 ast::Source::Join { left, right, kind, natural, on, using } => {
692 self.bind_join(ast, left, right, kind, natural, on, using)
693 }
694 }
695 }
696
697 fn bind_table(
698 &mut self,
699 ast: &Ast,
700 name: ast::Slice,
701 alias: ast::StrRef,
702 columns: ast::Slice,
703 ) -> Result<(NodeRef, Scope)> {
704 let parts: Vec<&str> = ast.name(name).collect();
705 let catalog = self.catalog;
706 let resolved = catalog.resolve(&parts)?;
707 let table = catalog.table(&resolved)?;
708 let fields: Vec<Field> = table.columns().to_vec();
709 let label =
710 if alias == NONE { resolved.table.clone() } else { ast.string(alias).to_string() };
711 let index = self.fresh_index();
712 let mut scope = Scope::empty();
713 for (at, field) in fields.iter().enumerate() {
714 scope.push(Visible {
715 table: label.clone(),
716 name: field.name.clone(),
717 binding: ColumnBinding::new(index, at as u32),
718 ty: field.ty.clone(),
719 });
720 }
721 if !columns.is_empty() {
722 let names: Vec<&str> = ast.name(columns).collect();
723 scope.rename(&names, &label)?;
724 }
725 let catalog_name = self.plan.intern(&resolved.catalog);
726 let schema = self.plan.intern(&resolved.schema);
727 let table_name = self.plan.intern(&resolved.table);
728 let alias = self.plan.intern(&label);
729 let columns = self.plan.add_fields(&fields);
730 let node = self.plan.add_node(Node::Get {
731 catalog: catalog_name,
732 schema,
733 table: table_name,
734 alias,
735 index,
736 columns,
737 });
738 Ok((node, scope))
739 }
740
741 #[allow(clippy::too_many_arguments)]
742 fn bind_join(
743 &mut self,
744 ast: &Ast,
745 left: ast::SourceRef,
746 right: ast::SourceRef,
747 kind: ast::JoinKind,
748 natural: bool,
749 on: ast::ExprRef,
750 using: ast::Slice,
751 ) -> Result<(NodeRef, Scope)> {
752 let (left_node, left_scope) = self.bind_source(ast, left)?;
753 let (right_node, right_scope) = self.bind_source(ast, right)?;
754 let split = left_scope.len();
755 let mut scope = left_scope.concat(right_scope);
756
757 let merged: Vec<String> = if natural {
760 let mut names = Vec::new();
761 for (at, column) in scope.columns.iter().enumerate().take(split) {
762 if scope.columns[split..].iter().any(|right| same_name(&right.name, &column.name))
763 && !names.iter().any(|held: &String| same_name(held, &column.name))
764 {
765 let _ = at;
766 names.push(column.name.clone());
767 }
768 }
769 names
770 } else {
771 ast.name(using).map(str::to_string).collect()
772 };
773
774 let mut conditions = Vec::new();
775 let mut dropped = Vec::new();
776 for name in &merged {
777 let left_at = scope.columns[..split]
778 .iter()
779 .position(|column| same_name(&column.name, name))
780 .ok_or_else(|| {
781 Error::binder(format!(
782 "column \"{name}\" specified in USING clause does not exist in left table"
783 ))
784 })?;
785 let right_at = scope.columns[split..]
786 .iter()
787 .position(|column| same_name(&column.name, name))
788 .map(|at| at + split)
789 .ok_or_else(|| {
790 Error::binder(format!(
791 "column \"{name}\" specified in USING clause does not exist in right table"
792 ))
793 })?;
794 let left_column = &scope.columns[left_at];
795 let (left_binding, left_type) = (left_column.binding, left_column.ty.clone());
796 let right_column = &scope.columns[right_at];
797 let (right_binding, right_type) = (right_column.binding, right_column.ty.clone());
798 let left_expr = self.plan.add_expr(Expr::Column(left_binding), left_type);
799 let right_expr = self.plan.add_expr(Expr::Column(right_binding), right_type);
800 conditions.push(self.compare(rudb_plan::CompareOp::Equal, left_expr, right_expr)?);
801 dropped.push(right_at);
802 }
803 dropped.sort_unstable();
806 for at in dropped.into_iter().rev() {
807 scope.remove(at);
808 }
809
810 if on != NONE {
811 if !merged.is_empty() {
812 return Err(Error::binder("a join cannot have both ON and USING"));
813 }
814 self.clause = "JOIN condition";
815 let predicate = self.bind_expr(ast, on, &scope)?;
816 conditions.push(self.as_boolean(predicate, "JOIN")?);
817 }
818
819 if kind == ast::JoinKind::Cross {
820 if !conditions.is_empty() {
821 return Err(Error::binder("a CROSS JOIN cannot have a condition"));
822 }
823 let node =
824 self.plan.add_node(Node::CrossProduct { left: left_node, right: right_node });
825 return Ok((node, scope));
826 }
827 if conditions.is_empty() && kind == ast::JoinKind::Inner {
828 let node =
829 self.plan.add_node(Node::CrossProduct { left: left_node, right: right_node });
830 return Ok((node, scope));
831 }
832 let kind = match kind {
833 ast::JoinKind::Inner | ast::JoinKind::Cross => JoinKind::Inner,
834 ast::JoinKind::Left => JoinKind::Left,
835 ast::JoinKind::Right => JoinKind::Right,
836 ast::JoinKind::Full => JoinKind::Full,
837 ast::JoinKind::Semi => JoinKind::Semi,
838 ast::JoinKind::Anti => JoinKind::Anti,
839 ast::JoinKind::Positional => JoinKind::Positional,
840 };
841 let conditions = self.plan.add_expr_list(&conditions);
842 let node =
843 self.plan.add_node(Node::Join { left: left_node, right: right_node, kind, conditions });
844 Ok((node, scope))
845 }
846
847 pub(crate) fn bind_aggregate(
851 &mut self,
852 ast: &Ast,
853 name: &str,
854 args: &[ast::ExprRef],
855 distinct: bool,
856 scope: &Scope,
857 ) -> Result<ExprRef> {
858 if self.in_aggregate {
859 return Err(Error::binder(format!(
860 "aggregate function calls cannot be nested, and {name}() is inside one"
861 )));
862 }
863 if self.aggregation.is_none() {
864 return Err(Error::binder(format!(
865 "aggregate function calls cannot be used in the {}",
866 self.clause
867 )));
868 }
869 self.in_aggregate = true;
870 let mut bound = Vec::with_capacity(args.len());
871 let mut failure = None;
872 for &arg in args {
873 match self.bind_expr(ast, arg, scope) {
874 Ok(expr) => bound.push(expr),
875 Err(error) => {
876 failure = Some(error);
877 break;
878 }
879 }
880 }
881 self.in_aggregate = false;
882 if let Some(error) = failure {
883 return Err(error);
884 }
885
886 let types: Vec<LogicalType> =
887 bound.iter().map(|&arg| self.plan.expr_type(arg).clone()).collect();
888 let resolved = resolve(name, &types)?;
889 let mut cast = Vec::with_capacity(bound.len());
890 for (arg, wanted) in bound.iter().zip(&resolved.arguments) {
891 cast.push(self.cast_to(*arg, wanted));
892 }
893 let args = self.plan.add_expr_list(&cast);
894 let name = self.plan.intern(resolved.name);
895 let ty = resolved.returns;
896 let call =
897 self.plan.add_expr(Expr::Aggregate { name, args, distinct, filter: None }, ty.clone());
898
899 let existing = self.aggregation.as_ref().map(|held| held.aggregates.clone());
902 let existing = existing.unwrap_or_default();
903 let at = match existing.iter().position(|&held| self.same_expr(held, call)) {
904 Some(at) => at,
905 None => {
906 let aggregation = self.aggregation.as_mut().expect("checked above");
907 aggregation.aggregates.push(call);
908 aggregation.aggregates.len() - 1
909 }
910 };
911 let aggregation = self.aggregation.as_ref().expect("checked above");
912 let (index, groups) = (aggregation.index, aggregation.groups.len());
913 Ok(self.column(index, groups + at, ty))
914 }
915
916 pub(crate) fn over_aggregate(&mut self, expr: ExprRef, scope: &Scope) -> Result<ExprRef> {
922 let Some(aggregation) = self.aggregation.as_ref() else {
923 return Ok(expr);
924 };
925 let index = aggregation.index;
926 let groups = aggregation.groups.clone();
927 for (at, group) in groups.iter().enumerate() {
928 if self.same_expr(expr, *group) {
929 let ty = self.plan.expr_type(*group).clone();
930 return Ok(self.column(index, at, ty));
931 }
932 }
933 let ty = self.plan.expr_type(expr).clone();
934 match self.plan.expr(expr).clone() {
935 Expr::Column(binding) if binding.table == index => Ok(expr),
936 Expr::Column(binding) => {
937 let name =
938 scope.columns.iter().find(|column| column.binding == binding).map_or_else(
939 || "a column".to_string(),
940 |column| format!("\"{}\"", column.name),
941 );
942 Err(Error::binder(format!(
943 "column {name} must appear in the GROUP BY clause or must be part of an aggregate function"
944 )))
945 }
946 Expr::Constant(_) | Expr::Aggregate { .. } => Ok(expr),
947 Expr::Cast { input, try_cast } => {
948 let input = self.over_aggregate(input, scope)?;
949 Ok(self.plan.add_expr(Expr::Cast { input, try_cast }, ty))
950 }
951 Expr::Compare { op, left, right } => {
952 let left = self.over_aggregate(left, scope)?;
953 let right = self.over_aggregate(right, scope)?;
954 Ok(self.plan.add_expr(Expr::Compare { op, left, right }, ty))
955 }
956 Expr::Conjunction { op, children } => {
957 let written = self.plan.expr_list(children).to_vec();
958 let mut rewritten = Vec::with_capacity(written.len());
959 for child in written {
960 rewritten.push(self.over_aggregate(child, scope)?);
961 }
962 let children = self.plan.add_expr_list(&rewritten);
963 Ok(self.plan.add_expr(Expr::Conjunction { op, children }, ty))
964 }
965 Expr::Function { name, args } => {
966 let written = self.plan.expr_list(args).to_vec();
967 let mut rewritten = Vec::with_capacity(written.len());
968 for arg in written {
969 rewritten.push(self.over_aggregate(arg, scope)?);
970 }
971 let args = self.plan.add_expr_list(&rewritten);
972 Ok(self.plan.add_expr(Expr::Function { name, args }, ty))
973 }
974 Expr::Case { arms, otherwise } => {
975 let written = self.plan.arm_list(arms).to_vec();
976 let mut rewritten = Vec::with_capacity(written.len());
977 for arm in written {
978 let when = self.over_aggregate(arm.when, scope)?;
979 let then = self.over_aggregate(arm.then, scope)?;
980 rewritten.push(rudb_plan::Arm { when, then });
981 }
982 let otherwise = match otherwise {
983 Some(expr) => Some(self.over_aggregate(expr, scope)?),
984 None => None,
985 };
986 let arms = self.plan.add_arms(&rewritten);
987 Ok(self.plan.add_expr(Expr::Case { arms, otherwise }, ty))
988 }
989 }
990 }
991
992 pub(crate) fn same_expr(&self, left: ExprRef, right: ExprRef) -> bool {
994 same_expr(&self.plan, left, right)
995 }
996}
997
998fn sort_key(expr: ExprRef, item: ast::OrderItem) -> SortKey {
1004 let descending = item.order == Order::Descending;
1005 let nulls_first = match item.nulls {
1006 Nulls::First => true,
1007 Nulls::Last => false,
1008 Nulls::Unstated => descending,
1009 };
1010 SortKey { expr, descending, nulls_first }
1011}
1012
1013fn same_expr(plan: &Plan, left: ExprRef, right: ExprRef) -> bool {
1015 if left == right {
1016 return true;
1017 }
1018 if plan.expr_type(left) != plan.expr_type(right) {
1019 return false;
1020 }
1021 let lists = |left, right| {
1022 let left: &[ExprRef] = plan.expr_list(left);
1023 let right: &[ExprRef] = plan.expr_list(right);
1024 left.len() == right.len()
1025 && left.iter().zip(right).all(|(&left, &right)| same_expr(plan, left, right))
1026 };
1027 match (plan.expr(left), plan.expr(right)) {
1028 (Expr::Column(left), Expr::Column(right)) => left == right,
1029 (Expr::Constant(left), Expr::Constant(right)) => plan.value(*left) == plan.value(*right),
1030 (
1031 Expr::Cast { input: left, try_cast: left_try },
1032 Expr::Cast { input: right, try_cast: right_try },
1033 ) => left_try == right_try && same_expr(plan, *left, *right),
1034 (
1035 Expr::Compare { op: left_op, left: left_a, right: left_b },
1036 Expr::Compare { op: right_op, left: right_a, right: right_b },
1037 ) => {
1038 left_op == right_op
1039 && same_expr(plan, *left_a, *right_a)
1040 && same_expr(plan, *left_b, *right_b)
1041 }
1042 (
1043 Expr::Conjunction { op: left_op, children: left_children },
1044 Expr::Conjunction { op: right_op, children: right_children },
1045 ) => left_op == right_op && lists(*left_children, *right_children),
1046 (
1047 Expr::Function { name: left_name, args: left_args },
1048 Expr::Function { name: right_name, args: right_args },
1049 ) => plan.string(*left_name) == plan.string(*right_name) && lists(*left_args, *right_args),
1050 (
1051 Expr::Aggregate {
1052 name: left_name,
1053 args: left_args,
1054 distinct: left_distinct,
1055 filter: left_filter,
1056 },
1057 Expr::Aggregate {
1058 name: right_name,
1059 args: right_args,
1060 distinct: right_distinct,
1061 filter: right_filter,
1062 },
1063 ) => {
1064 plan.string(*left_name) == plan.string(*right_name)
1065 && left_distinct == right_distinct
1066 && match (left_filter, right_filter) {
1067 (None, None) => true,
1068 (Some(left), Some(right)) => same_expr(plan, *left, *right),
1069 _ => false,
1070 }
1071 && lists(*left_args, *right_args)
1072 }
1073 (
1074 Expr::Case { arms: left_arms, otherwise: left_otherwise },
1075 Expr::Case { arms: right_arms, otherwise: right_otherwise },
1076 ) => {
1077 let left_arms = plan.arm_list(*left_arms);
1078 let right_arms = plan.arm_list(*right_arms);
1079 left_arms.len() == right_arms.len()
1080 && left_arms.iter().zip(right_arms).all(|(left, right)| {
1081 same_expr(plan, left.when, right.when) && same_expr(plan, left.then, right.then)
1082 })
1083 && match (left_otherwise, right_otherwise) {
1084 (None, None) => true,
1085 (Some(left), Some(right)) => same_expr(plan, *left, *right),
1086 _ => false,
1087 }
1088 }
1089 _ => false,
1090 }
1091}