1use rudb_catalog::{Catalog, Entry, QualifiedName, same_name};
16use rudb_common::{Error, Field, LogicalType, Result, Value};
17use rudb_functions::{
18 Columns, TableFunction, csv_fields, files, is_file, is_pattern, parquet_fields, resolve,
19 resolve_table,
20};
21use rudb_parse::ast::{self, Ast, Distinct, LiteralKind, Nulls, Order, Quantifier, SetOp};
22use rudb_parse::{NONE, parse_ast};
23use rudb_plan::{ColumnBinding, Expr, ExprRef, JoinKind, Node, NodeRef, Plan, SetOpKind, SortKey};
24
25use crate::expr::{describe, has_aggregate};
26use crate::parameters::Parameters;
27use crate::scope::{Scope, Visible};
28
29pub fn bind(ast: &Ast, catalog: &Catalog) -> Result<Plan> {
36 bind_with(ast, catalog, &Parameters::new())
37}
38
39pub fn bind_with(ast: &Ast, catalog: &Catalog, parameters: &Parameters) -> Result<Plan> {
45 let query = match ast.statements.as_slice() {
46 [ast::Statement::Query(query)] => *query,
47 [] => return Err(Error::binder("no statement to bind")),
48 _ => return Err(Error::not_implemented("a script of more than one statement")),
49 };
50 let mut binder = Binder::with(catalog, parameters);
51 let (root, _) = binder.bind_query(ast, query)?;
52 let mut plan = binder.into_plan();
53 plan.set_root(root);
54 plan.validate()?;
55 Ok(plan)
56}
57
58pub fn bind_sql(query: &str, catalog: &Catalog) -> Result<Plan> {
64 let ast = parse_ast(query)?;
65 bind(&ast, catalog)
66}
67
68#[derive(Debug)]
70pub(crate) struct Aggregation {
71 pub(crate) index: u32,
73 pub(crate) groups: Vec<ExprRef>,
75 pub(crate) aggregates: Vec<ExprRef>,
77}
78
79#[derive(Debug)]
81pub(crate) struct Binder<'a> {
82 catalog: &'a Catalog,
83 pub(crate) parameters: &'a Parameters,
85 plan: Plan,
86 next_index: u32,
87 pub(crate) aggregation: Option<Aggregation>,
89 pub(crate) in_aggregate: bool,
91 pub(crate) clause: &'static str,
93 expanding: Vec<String>,
95}
96
97impl<'a> Binder<'a> {
98 pub(crate) fn with(catalog: &'a Catalog, parameters: &'a Parameters) -> Self {
99 Self {
100 catalog,
101 parameters,
102 plan: Plan::new(),
103 next_index: 0,
104 aggregation: None,
105 in_aggregate: false,
106 clause: "SELECT clause",
107 expanding: Vec::new(),
108 }
109 }
110
111 pub(crate) fn plan(&self) -> &Plan {
112 &self.plan
113 }
114
115 pub(crate) fn plan_mut(&mut self) -> &mut Plan {
116 &mut self.plan
117 }
118
119 pub(crate) fn into_plan(self) -> Plan {
120 self.plan
121 }
122
123 pub(crate) fn fresh_index(&mut self) -> u32 {
125 let index = self.next_index;
126 self.next_index += 1;
127 index
128 }
129
130 fn column(&mut self, index: u32, position: usize, ty: LogicalType) -> ExprRef {
132 let binding = ColumnBinding::new(index, position as u32);
133 self.plan.add_expr(Expr::Column(binding), ty)
134 }
135
136 pub(crate) fn bind_query(
139 &mut self,
140 ast: &Ast,
141 query: ast::QueryRef,
142 ) -> Result<(NodeRef, Scope)> {
143 let written = ast.query(query);
144 match written.body {
145 ast::QueryBody::Select(select) => self.bind_select(ast, select, &written),
146 ast::QueryBody::SetOp { op, quantifier, by_name, left, right } => {
147 if by_name {
148 return Err(Error::not_implemented("UNION BY NAME"));
149 }
150 self.bind_set_op(ast, &written, op, quantifier, left, right)
151 }
152 ast::QueryBody::Values(rows) => self.bind_values(ast, &written, rows),
153 }
154 }
155
156 fn bind_values(
163 &mut self,
164 ast: &Ast,
165 query: &ast::Query,
166 rows: ast::Slice,
167 ) -> Result<(NodeRef, Scope)> {
168 let written = ast.rows(rows).to_vec();
169 let Some(first) = written.first() else {
170 return Err(Error::binder("VALUES needs at least one row"));
171 };
172 let width = first.len as usize;
173 for (at, row) in written.iter().enumerate() {
174 if row.len as usize != width {
175 return Err(Error::binder(format!(
176 "VALUES lists must all be the same length, expected {width} columns but row {} has {}",
177 at + 1,
178 row.len
179 )));
180 }
181 }
182 let empty = Scope::empty();
184 let previous = std::mem::replace(&mut self.clause, "VALUES clause");
185 let mut bound: Vec<Vec<ExprRef>> = Vec::with_capacity(written.len());
186 for row in &written {
187 let mut items = Vec::with_capacity(width);
188 for &expr in ast.expr_list(*row) {
189 items.push(self.bind_expr(ast, expr, &empty)?);
190 }
191 bound.push(items);
192 }
193 self.clause = previous;
194 let mut types = Vec::with_capacity(width);
195 for at in 0..width {
196 let mut ty = self.plan.expr_type(bound[0][at]).clone();
197 for row in &bound[1..] {
198 let other = self.plan.expr_type(row[at]).clone();
199 ty = ty.promote(&other).ok_or_else(|| {
200 Error::binder(format!(
201 "Cannot combine a value of type {ty} with a value of type {other} in column {} of a VALUES",
202 at + 1
203 ))
204 })?;
205 }
206 types.push(ty);
207 }
208 let mut slices = Vec::with_capacity(bound.len());
209 for row in &bound {
210 let items: Vec<ExprRef> =
211 row.iter().zip(&types).map(|(&expr, ty)| self.cast_to(expr, ty)).collect();
212 slices.push(self.plan.add_expr_list(&items));
213 }
214 let rows = self.plan.add_rows(&slices);
215 let fields: Vec<Field> = types
216 .iter()
217 .enumerate()
218 .map(|(at, ty)| Field::new(format!("col{at}"), ty.clone()))
219 .collect();
220 let columns = self.plan.add_fields(&fields);
221 let index = self.fresh_index();
222 let mut node = self.plan.add_node(Node::Values { index, columns, rows });
223 let mut scope = Scope::empty();
224 for (at, field) in fields.iter().enumerate() {
225 scope.push(Visible {
226 table: String::new(),
227 name: field.name.clone(),
228 binding: ColumnBinding::new(index, at as u32),
229 ty: field.ty.clone(),
230 });
231 }
232 let keys = self.sort_keys(ast, query, &scope, &[])?;
233 if !keys.is_empty() {
234 let keys = self.plan.add_sort_keys(&keys);
235 node = self.plan.add_node(Node::Sort { input: node, keys });
236 }
237 node = self.apply_limit(ast, query, node)?;
238 Ok((node, scope))
239 }
240
241 fn bind_set_op(
242 &mut self,
243 ast: &Ast,
244 query: &ast::Query,
245 op: SetOp,
246 quantifier: Quantifier,
247 left: ast::QueryRef,
248 right: ast::QueryRef,
249 ) -> Result<(NodeRef, Scope)> {
250 let (left_node, left_scope) = self.bind_query(ast, left)?;
251 let (right_node, right_scope) = self.bind_query(ast, right)?;
252 if left_scope.len() != right_scope.len() {
253 return Err(Error::binder(format!(
254 "Set operations can only apply to expressions with the same number of result columns, but left side has {} and right side has {}",
255 left_scope.len(),
256 right_scope.len()
257 )));
258 }
259 let mut types = Vec::with_capacity(left_scope.len());
261 for (left, right) in left_scope.columns.iter().zip(&right_scope.columns) {
262 let common = left.ty.promote(&right.ty).ok_or_else(|| {
263 Error::binder(format!(
264 "Cannot combine a column of type {} with a column of type {} in a set operation",
265 left.ty, right.ty
266 ))
267 })?;
268 types.push(common);
269 }
270 let left_node = self.conform(left_node, &left_scope, &types);
271 let right_node = self.conform(right_node, &right_scope, &types);
272 let index = self.fresh_index();
273 let kind = match op {
274 SetOp::Union => SetOpKind::Union,
275 SetOp::Except => SetOpKind::Except,
276 SetOp::Intersect => SetOpKind::Intersect,
277 };
278 let all = quantifier == Quantifier::All;
281 let mut node = self.plan.add_node(Node::SetOp {
282 left: left_node,
283 right: right_node,
284 kind,
285 all,
286 index,
287 });
288 let mut scope = Scope::empty();
289 for (at, (column, ty)) in left_scope.columns.iter().zip(&types).enumerate() {
290 scope.push(Visible {
291 table: String::new(),
292 name: column.name.clone(),
293 binding: ColumnBinding::new(index, at as u32),
294 ty: ty.clone(),
295 });
296 }
297 let keys = self.sort_keys(ast, query, &scope, &[])?;
301 if !keys.is_empty() {
302 let keys = self.plan.add_sort_keys(&keys);
303 node = self.plan.add_node(Node::Sort { input: node, keys });
304 }
305 node = self.apply_limit(ast, query, node)?;
306 Ok((node, scope))
307 }
308
309 fn conform(&mut self, node: NodeRef, scope: &Scope, types: &[LogicalType]) -> NodeRef {
311 if scope.columns.iter().zip(types).all(|(column, ty)| &column.ty == ty) {
312 return node;
313 }
314 let index = self.fresh_index();
315 let mut exprs = Vec::with_capacity(types.len());
316 let mut names = Vec::with_capacity(types.len());
317 for (column, ty) in scope.columns.iter().zip(types) {
318 let expr = self.plan.add_expr(Expr::Column(column.binding), column.ty.clone());
319 exprs.push(self.cast_to(expr, ty));
320 names.push(self.plan.intern(&column.name));
321 }
322 let exprs = self.plan.add_expr_list(&exprs);
323 let names = self.plan.add_name_list(&names);
324 self.plan.add_node(Node::Project { input: node, index, exprs, names })
325 }
326
327 fn bind_select(
330 &mut self,
331 ast: &Ast,
332 select: ast::SelectRef,
333 query: &ast::Query,
334 ) -> Result<(NodeRef, Scope)> {
335 let written = ast.select(select);
336 let (mut node, input) = self.bind_from(ast, written.from)?;
337
338 if written.filter != NONE {
339 self.clause = "WHERE clause";
340 let predicate = self.bind_expr(ast, written.filter, &input)?;
341 let predicate = self.as_boolean(predicate, "WHERE")?;
342 node = self.plan.add_node(Node::Filter { input: node, predicate });
343 }
344
345 let targets = ast.target_list(written.targets).to_vec();
346 if targets.is_empty() {
347 return Err(Error::binder("a SELECT needs at least one expression to select"));
348 }
349
350 let group_items = self.group_items(ast, &written, &targets)?;
351 let aggregating = !group_items.is_empty()
352 || written.having != NONE
353 || targets.iter().any(|target| has_aggregate(ast, target.expr));
354 if aggregating {
355 self.clause = "GROUP BY clause";
356 let mut groups = Vec::with_capacity(group_items.len());
357 for item in &group_items {
358 groups.push(self.bind_expr(ast, *item, &input)?);
359 }
360 let index = self.fresh_index();
361 self.aggregation = Some(Aggregation { index, groups, aggregates: Vec::new() });
362 }
363
364 self.clause = "SELECT clause";
365 let (mut exprs, mut names) = self.bind_targets(ast, &targets, &input)?;
366 let visible = exprs.len();
367
368 let mut having = None;
369 if written.having != NONE {
370 self.clause = "HAVING clause";
371 let predicate = self.bind_expr(ast, written.having, &input)?;
372 let predicate = self.over_aggregate(predicate, &input)?;
373 having = Some(self.as_boolean(predicate, "HAVING")?);
374 }
375
376 let project = self.fresh_index();
379 let mut output = Scope::empty();
380 for (at, (expr, name)) in exprs.iter().zip(&names).enumerate() {
381 output.push(Visible {
382 table: String::new(),
383 name: name.clone(),
384 binding: ColumnBinding::new(project, at as u32),
385 ty: self.plan.expr_type(*expr).clone(),
386 });
387 }
388
389 self.clause = "ORDER BY clause";
390 let mut extra = Vec::new();
391 let keys = self.select_sort_keys(
392 ast, query, &input, &output, project, &mut exprs, &mut names, &mut extra,
393 )?;
394 if !extra.is_empty() && written.distinct != Distinct::No {
395 return Err(Error::binder(
396 "For SELECT DISTINCT, ORDER BY expressions must appear in the select list",
397 ));
398 }
399 let on = self.distinct_on(ast, written.distinct, &output)?;
400
401 if let Some(aggregation) = self.aggregation.take() {
402 let index = aggregation.index;
403 let groups = self.plan.add_expr_list(&aggregation.groups);
404 let aggregates = self.plan.add_expr_list(&aggregation.aggregates);
405 node = self.plan.add_node(Node::Aggregate { input: node, index, groups, aggregates });
406 }
407 if let Some(predicate) = having {
408 node = self.plan.add_node(Node::Filter { input: node, predicate });
409 }
410
411 let interned: Vec<u32> = names.iter().map(|name| self.plan.intern(name)).collect();
412 let exprs_slice = self.plan.add_expr_list(&exprs);
413 let names_slice = self.plan.add_name_list(&interned);
414 node = self.plan.add_node(Node::Project {
415 input: node,
416 index: project,
417 exprs: exprs_slice,
418 names: names_slice,
419 });
420
421 if written.distinct != Distinct::No {
422 let on = self.plan.add_expr_list(&on);
423 node = self.plan.add_node(Node::Distinct { input: node, on });
424 }
425 if !keys.is_empty() {
426 let keys = self.plan.add_sort_keys(&keys);
427 node = self.plan.add_node(Node::Sort { input: node, keys });
428 }
429 node = self.apply_limit(ast, query, node)?;
430
431 if extra.is_empty() {
432 output.columns.truncate(visible);
433 return Ok((node, output));
434 }
435 let index = self.fresh_index();
438 let mut kept = Vec::with_capacity(visible);
439 let mut kept_names = Vec::with_capacity(visible);
440 let mut scope = Scope::empty();
441 for (at, name) in names.iter().enumerate().take(visible) {
442 let ty = output.columns[at].ty.clone();
443 kept.push(self.column(project, at, ty.clone()));
444 kept_names.push(self.plan.intern(name));
445 scope.push(Visible {
446 table: String::new(),
447 name: name.clone(),
448 binding: ColumnBinding::new(index, at as u32),
449 ty,
450 });
451 }
452 let exprs = self.plan.add_expr_list(&kept);
453 let names = self.plan.add_name_list(&kept_names);
454 node = self.plan.add_node(Node::Project { input: node, index, exprs, names });
455 Ok((node, scope))
456 }
457
458 fn bind_targets(
460 &mut self,
461 ast: &Ast,
462 targets: &[ast::Target],
463 input: &Scope,
464 ) -> Result<(Vec<ExprRef>, Vec<String>)> {
465 let mut exprs = Vec::with_capacity(targets.len());
466 let mut names = Vec::with_capacity(targets.len());
467 for target in targets {
468 if let ast::Expr::Star { qualifier, replacements } = ast.expr(target.expr) {
469 let table = ast.name(qualifier).last().map(str::to_string);
470 let expanded: Vec<Visible> =
471 input.star(table.as_deref())?.into_iter().cloned().collect();
472 let replacements = ast.target_list(replacements).to_vec();
473 let mut used = vec![false; replacements.len()];
474 for column in expanded {
475 let found = replacements.iter().zip(&mut used).find(|(replacement, _)| {
476 same_name(ast.string(replacement.alias), &column.name)
477 });
478 let (expr, name) = match found {
483 Some((replacement, used)) => {
484 *used = true;
485 let expr = self.bind_expr(ast, replacement.expr, input)?;
486 (expr, ast.string(replacement.alias).to_string())
487 }
488 None => (
489 self.plan.add_expr(Expr::Column(column.binding), column.ty),
490 column.name,
491 ),
492 };
493 exprs.push(self.over_aggregate(expr, input)?);
494 names.push(name);
495 }
496 if let Some((replacement, _)) =
500 replacements.iter().zip(&used).find(|(_, used)| !**used)
501 {
502 return Err(missing_replacement(ast.string(replacement.alias), input));
503 }
504 continue;
505 }
506 let expr = self.bind_expr(ast, target.expr, input)?;
507 exprs.push(self.over_aggregate(expr, input)?);
508 names.push(if target.alias == NONE {
509 self.output_name(ast, target.expr, input)
510 } else {
511 ast.string(target.alias).to_string()
512 });
513 }
514 Ok((exprs, names))
515 }
516
517 fn output_name(&self, ast: &Ast, target: ast::ExprRef, input: &Scope) -> String {
523 if let ast::Expr::Column { name } = ast.expr(target) {
524 let parts: Vec<&str> = ast.name(name).collect();
525 if let Ok(found) = input.resolve(&parts) {
526 return found.name.clone();
527 }
528 }
529 describe(ast, target)
530 }
531
532 fn group_items(
534 &self,
535 ast: &Ast,
536 select: &ast::Select,
537 targets: &[ast::Target],
538 ) -> Result<Vec<ast::ExprRef>> {
539 if select.group_by_all {
540 return Ok(targets
543 .iter()
544 .filter(|target| !has_aggregate(ast, target.expr))
545 .map(|target| target.expr)
546 .collect());
547 }
548 let mut items = Vec::new();
549 for &item in ast.expr_list(select.group_by) {
550 items.push(self.output_reference(ast, item, targets, "GROUP BY")?.unwrap_or(item));
551 }
552 Ok(items)
553 }
554
555 fn output_reference(
557 &self,
558 ast: &Ast,
559 item: ast::ExprRef,
560 targets: &[ast::Target],
561 clause: &str,
562 ) -> Result<Option<ast::ExprRef>> {
563 match ast.expr(item) {
564 ast::Expr::Literal { kind: LiteralKind::Number, text } => {
565 let written = ast.string(text);
566 let position: usize = written.parse().map_err(|_| {
567 Error::binder(format!("{clause} term {written} is not a column"))
568 })?;
569 if position == 0 || position > targets.len() {
570 return Err(Error::binder(format!(
571 "{clause} term out of range - should be between 1 and {}",
572 targets.len()
573 )));
574 }
575 Ok(Some(targets[position - 1].expr))
576 }
577 ast::Expr::Column { name } => {
578 let parts: Vec<&str> = ast.name(name).collect();
579 let [written] = parts.as_slice() else { return Ok(None) };
580 let mut found = None;
581 for target in targets {
582 if target.alias != NONE && same_name(ast.string(target.alias), written) {
583 if found.is_some() {
584 return Ok(None);
585 }
586 found = Some(target.expr);
587 }
588 }
589 Ok(found)
590 }
591 _ => Ok(None),
592 }
593 }
594
595 #[allow(clippy::too_many_arguments)]
599 fn select_sort_keys(
600 &mut self,
601 ast: &Ast,
602 query: &ast::Query,
603 input: &Scope,
604 output: &Scope,
605 project: u32,
606 exprs: &mut Vec<ExprRef>,
607 names: &mut Vec<String>,
608 extra: &mut Vec<usize>,
609 ) -> Result<Vec<SortKey>> {
610 if query.order_by_all {
611 return Ok(self.every_column(output));
612 }
613 let items = ast.order_list(query.order_by).to_vec();
614 let mut keys = Vec::with_capacity(items.len());
615 for item in items {
616 let position = match self.output_position(ast, item.expr, output)? {
617 Some(position) => position,
618 None => {
619 let bound = self.bind_expr(ast, item.expr, input)?;
620 let bound = self.over_aggregate(bound, input)?;
621 match exprs.iter().position(|&held| self.same_expr(held, bound)) {
622 Some(position) => position,
623 None => {
624 exprs.push(bound);
625 names.push(describe(ast, item.expr));
626 extra.push(exprs.len() - 1);
627 exprs.len() - 1
628 }
629 }
630 }
631 };
632 let ty = self.plan.expr_type(exprs[position]).clone();
633 let expr = self.column(project, position, ty);
634 keys.push(sort_key(expr, item));
635 }
636 Ok(keys)
637 }
638
639 fn sort_keys(
641 &mut self,
642 ast: &Ast,
643 query: &ast::Query,
644 output: &Scope,
645 targets: &[ast::Target],
646 ) -> Result<Vec<SortKey>> {
647 if query.order_by_all {
648 return Ok(self.every_column(output));
649 }
650 let items = ast.order_list(query.order_by).to_vec();
651 let mut keys = Vec::with_capacity(items.len());
652 for item in items {
653 let expr = match self.output_position(ast, item.expr, output)? {
654 Some(position) => {
655 let column = &output.columns[position];
656 let (binding, ty) = (column.binding, column.ty.clone());
657 self.plan.add_expr(Expr::Column(binding), ty)
658 }
659 None => {
660 let _ = targets;
661 self.bind_expr(ast, item.expr, output)?
662 }
663 };
664 keys.push(sort_key(expr, item));
665 }
666 Ok(keys)
667 }
668
669 fn every_column(&mut self, output: &Scope) -> Vec<SortKey> {
670 let columns: Vec<(ColumnBinding, LogicalType)> =
671 output.columns.iter().map(|column| (column.binding, column.ty.clone())).collect();
672 columns
673 .into_iter()
674 .map(|(binding, ty)| {
675 let expr = self.plan.add_expr(Expr::Column(binding), ty);
676 SortKey { expr, descending: false, nulls_first: false }
677 })
678 .collect()
679 }
680
681 fn output_position(
683 &self,
684 ast: &Ast,
685 item: ast::ExprRef,
686 output: &Scope,
687 ) -> Result<Option<usize>> {
688 match ast.expr(item) {
689 ast::Expr::Literal { kind: LiteralKind::Number, text } => {
690 let written = ast.string(text);
691 if written.contains(['.', 'e', 'E']) {
692 return Ok(None);
693 }
694 let position: usize = written.parse().map_err(|_| {
695 Error::binder(format!("ORDER BY term {written} is not a column"))
696 })?;
697 if position == 0 || position > output.len() {
698 return Err(Error::binder(format!(
699 "ORDER BY term out of range - should be between 1 and {}",
700 output.len()
701 )));
702 }
703 Ok(Some(position - 1))
704 }
705 ast::Expr::Column { name } => {
706 let parts: Vec<&str> = ast.name(name).collect();
707 let [written] = parts.as_slice() else { return Ok(None) };
708 Ok(output.position_of(None, written))
709 }
710 _ => Ok(None),
711 }
712 }
713
714 fn distinct_on(
716 &mut self,
717 ast: &Ast,
718 distinct: Distinct,
719 output: &Scope,
720 ) -> Result<Vec<ExprRef>> {
721 let Distinct::On(items) = distinct else {
722 return Ok(Vec::new());
723 };
724 let items = ast.expr_list(items).to_vec();
725 let mut on = Vec::with_capacity(items.len());
726 for item in items {
727 let Some(position) = self.output_position(ast, item, output)? else {
728 return Err(Error::not_implemented(
729 "DISTINCT ON an expression that is not in the select list",
730 ));
731 };
732 let column = &output.columns[position];
733 let (binding, ty) = (column.binding, column.ty.clone());
734 on.push(self.plan.add_expr(Expr::Column(binding), ty));
735 }
736 Ok(on)
737 }
738
739 fn apply_limit(&mut self, ast: &Ast, query: &ast::Query, input: NodeRef) -> Result<NodeRef> {
740 if query.limit_percent {
741 return Err(Error::not_implemented("LIMIT with a percentage"));
742 }
743 let count = self.constant_count(ast, query.limit, "LIMIT")?;
744 let offset = self.constant_count(ast, query.offset, "OFFSET")?.unwrap_or(0);
745 if count.is_none() && offset == 0 {
746 return Ok(input);
747 }
748 Ok(self.plan.add_node(Node::Limit { input, count, offset }))
749 }
750
751 fn constant_count(
753 &mut self,
754 ast: &Ast,
755 written: ast::ExprRef,
756 clause: &str,
757 ) -> Result<Option<u64>> {
758 if written == NONE {
759 return Ok(None);
760 }
761 self.clause = "LIMIT clause";
762 let scope = Scope::empty();
763 let bound = self.bind_expr(ast, written, &scope)?;
764 let Expr::Constant(value) = *self.plan.expr(bound) else {
765 return Err(Error::not_implemented(format!("a {clause} that is not a constant")));
766 };
767 let count = match self.plan.value(value) {
768 Value::Null => return Ok(None),
769 Value::TinyInt(count) => i128::from(*count),
770 Value::SmallInt(count) => i128::from(*count),
771 Value::Integer(count) => i128::from(*count),
772 Value::BigInt(count) => i128::from(*count),
773 Value::HugeInt(count) => *count,
774 other => {
775 return Err(Error::binder(format!(
776 "{clause} takes a whole number of rows, not a value of type {}",
777 other.logical_type()
778 )));
779 }
780 };
781 u64::try_from(count)
782 .map(Some)
783 .map_err(|_| Error::binder(format!("{clause} must not be negative")))
784 }
785
786 fn bind_from(&mut self, ast: &Ast, from: ast::Slice) -> Result<(NodeRef, Scope)> {
789 let sources = ast.source_list(from).to_vec();
790 let Some((first, rest)) = sources.split_first() else {
791 return Ok((self.plan.add_node(Node::Dummy), Scope::empty()));
794 };
795 let (mut node, mut scope) = self.bind_source(ast, *first)?;
796 for source in rest {
797 let (right, right_scope) = self.bind_source(ast, *source)?;
798 node = self.plan.add_node(Node::CrossProduct { left: node, right });
799 scope = scope.concat(right_scope);
800 }
801 Ok((node, scope))
802 }
803
804 fn bind_source(&mut self, ast: &Ast, source: ast::SourceRef) -> Result<(NodeRef, Scope)> {
805 match ast.source(source) {
806 ast::Source::Table { name, alias, columns } => {
807 self.bind_table(ast, name, alias, columns)
808 }
809 ast::Source::Function { name, args, alias, columns } => {
810 self.bind_table_function(ast, name, args, alias, columns)
811 }
812 ast::Source::Subquery { query, alias, columns } => {
813 let (node, mut scope) = self.bind_query(ast, query)?;
814 let label = if alias == NONE {
815 "unnamed_subquery".to_string()
816 } else {
817 ast.string(alias).to_string()
818 };
819 scope.relabel(&label);
820 if !columns.is_empty() {
821 let names: Vec<&str> = ast.name(columns).collect();
822 scope.rename(&names, &label)?;
823 }
824 Ok((node, scope))
825 }
826 ast::Source::Values { rows, alias, columns } => {
827 let bare = ast::Query::bare(ast::QueryBody::Values(rows));
828 let (node, mut scope) = self.bind_values(ast, &bare, rows)?;
829 let label =
830 if alias == NONE { String::new() } else { ast.string(alias).to_string() };
831 scope.relabel(&label);
832 if !columns.is_empty() {
833 let names: Vec<&str> = ast.name(columns).collect();
834 scope.rename(&names, &label)?;
835 }
836 Ok((node, scope))
837 }
838 ast::Source::Join { left, right, kind, natural, on, using } => {
839 self.bind_join(ast, left, right, kind, natural, on, using)
840 }
841 }
842 }
843
844 fn bind_table(
845 &mut self,
846 ast: &Ast,
847 name: ast::Slice,
848 alias: ast::StrRef,
849 columns: ast::Slice,
850 ) -> Result<(NodeRef, Scope)> {
851 let parts: Vec<&str> = ast.name(name).collect();
852 let catalog = self.catalog;
853 let resolved = match catalog.resolve(&parts) {
856 Ok(resolved) => resolved,
857 Err(missing) => {
858 return self.bind_replacement_scan(ast, &parts, alias, columns, missing);
859 }
860 };
861 if catalog.entry(&resolved)? == Entry::View {
862 return self.bind_view(ast, &resolved, alias, columns);
863 }
864 let table = catalog.table(&resolved)?;
865 let fields: Vec<Field> = table.columns().to_vec();
866 let label =
867 if alias == NONE { resolved.table.clone() } else { ast.string(alias).to_string() };
868 let index = self.fresh_index();
869 let mut scope = Scope::empty();
870 for (at, field) in fields.iter().enumerate() {
871 scope.push(Visible {
872 table: label.clone(),
873 name: field.name.clone(),
874 binding: ColumnBinding::new(index, at as u32),
875 ty: field.ty.clone(),
876 });
877 }
878 if !columns.is_empty() {
879 let names: Vec<&str> = ast.name(columns).collect();
880 scope.rename(&names, &label)?;
881 }
882 let catalog_name = self.plan.intern(&resolved.catalog);
883 let schema = self.plan.intern(&resolved.schema);
884 let table_name = self.plan.intern(&resolved.table);
885 let alias = self.plan.intern(&label);
886 let columns = self.plan.add_fields(&fields);
887 let node = self.plan.add_node(Node::Get {
888 catalog: catalog_name,
889 schema,
890 table: table_name,
891 alias,
892 index,
893 columns,
894 });
895 Ok((node, scope))
896 }
897
898 fn bind_view(
910 &mut self,
911 ast: &Ast,
912 name: &QualifiedName,
913 alias: ast::StrRef,
914 columns: ast::Slice,
915 ) -> Result<(NodeRef, Scope)> {
916 let view = self.catalog.view(name)?;
917 let full = name.to_string();
918 if self.expanding.contains(&full) {
919 return Err(Error::binder(format!(
923 "infinite recursion detected: attempting to recursively bind view \"\"{}\"\"",
924 name.table
925 )));
926 }
927 let body = parse_ast(view.sql())?;
928 let query = match body.statements.as_slice() {
929 [ast::Statement::Query(query)] => *query,
930 _ => return Err(Error::binder(format!("view \"{}\" is not a query", name.table))),
933 };
934 self.expanding.push(full);
935 let bound = self.bind_query(&body, query);
936 self.expanding.pop();
937 let (node, mut scope) = bound?;
938
939 let aliases: Vec<&str> = view.aliases().iter().map(String::as_str).collect();
940 if !aliases.is_empty() {
941 scope.rename(&aliases, "unnamed_subquery")?;
942 }
943 let label = if alias == NONE { name.table.clone() } else { ast.string(alias).to_string() };
944 scope.relabel(&label);
945 if !columns.is_empty() {
946 let names: Vec<&str> = ast.name(columns).collect();
947 scope.rename(&names, &label)?;
948 }
949 Ok((node, scope))
950 }
951
952 fn bind_table_function(
960 &mut self,
961 ast: &Ast,
962 name: ast::Slice,
963 args: ast::Slice,
964 alias: ast::StrRef,
965 columns: ast::Slice,
966 ) -> Result<(NodeRef, Scope)> {
967 let parts: Vec<&str> = ast.name(name).collect();
968 let function_name = *parts.last().unwrap_or(&"");
972 if let Some(schema) = parts.iter().rev().nth(1) {
973 if !schema.eq_ignore_ascii_case("main") && !schema.eq_ignore_ascii_case("system") {
974 return Err(Error::catalog(format!(
975 "Table Function with name {} does not exist!",
976 parts.join(".")
977 )));
978 }
979 }
980 let Some(called) = TableFunction::lookup(function_name) else {
984 return Err(Error::catalog(format!(
985 "Table Function with name {function_name} does not exist!"
986 )));
987 };
988 let written = ast.target_list(args).to_vec();
989 let empty = Scope::empty();
990 let previous = std::mem::replace(&mut self.clause, "table function arguments");
991 let mut bound = Vec::new();
992 let mut options = Options::default();
993 for argument in written {
994 let expr = self.bind_expr(ast, argument.expr, &empty)?;
995 if argument.alias == NONE {
996 bound.push(expr);
997 } else {
998 self.named_argument(called, ast.string(argument.alias), expr, &mut options)?;
999 }
1000 }
1001 self.clause = previous;
1002
1003 let given: Vec<LogicalType> =
1006 bound.iter().map(|&expr| self.plan.expr_type(expr).clone()).collect();
1007 let resolved = resolve_table(function_name, &given)?;
1008 let mut cast: Vec<ExprRef> = bound
1009 .iter()
1010 .zip(&resolved.arguments)
1011 .map(|(&expr, ty)| self.cast_to(expr, ty))
1012 .collect();
1013
1014 let fields = match resolved.columns {
1015 Columns::Fixed(fields) => fields,
1016 columns => {
1017 let paths = self.file_paths(cast[0], resolved.function.name())?;
1022 let first = paths.first().map_or("", String::as_str);
1023 let mut fields = match columns {
1024 Columns::Csv => csv_fields(&paths)?,
1027 _ => parquet_fields(first)?,
1028 };
1029 if options.binary_as_string {
1030 for field in &mut fields {
1035 if field.ty == LogicalType::Blob {
1036 field.ty = LogicalType::Varchar;
1037 }
1038 }
1039 }
1040 cast = paths.iter().map(|path| self.path_constant(path)).collect();
1041 fields
1042 }
1043 };
1044 let label = if alias == NONE {
1045 resolved.function.name().to_string()
1046 } else {
1047 ast.string(alias).to_string()
1048 };
1049 let names: Vec<&str> = ast.name(columns).collect();
1050 self.table_function_source(resolved.function, &cast, fields, &label, &names)
1051 }
1052
1053 fn named_argument(
1067 &mut self,
1068 function: TableFunction,
1069 name: &str,
1070 expr: ExprRef,
1071 options: &mut Options,
1072 ) -> Result<()> {
1073 let known = function
1074 .parameters()
1075 .iter()
1076 .find(|(parameter, _)| parameter.eq_ignore_ascii_case(name));
1077 let Some((parameter, wanted)) = known else {
1078 let candidates: Vec<String> = function
1079 .parameters()
1080 .iter()
1081 .map(|(parameter, ty)| format!("{parameter} {ty}"))
1082 .collect();
1083 return Err(Error::binder(format!(
1084 "Invalid named parameter \"{name}\" for function {} Candidates: {}",
1085 function.name(),
1086 candidates.join(", ")
1087 )));
1088 };
1089 let Expr::Constant(reference) = *self.plan.expr(expr) else {
1090 return Err(Error::not_implemented(format!(
1091 "the named parameter {parameter} with a value that is not a constant"
1092 )));
1093 };
1094 let value = self.plan.value(reference).clone();
1095 if value == Value::Null {
1096 return Err(Error::binder(format!("Cannot use NULL as argument to \"{parameter}\"")));
1097 }
1098 let given = self.plan.expr_type(expr).clone();
1099 match (*parameter, value) {
1100 ("binary_as_string", Value::Boolean(on)) => options.binary_as_string = on,
1101 _ => {
1102 return Err(Error::not_implemented(format!(
1103 "the named parameter {parameter} given a {given} where a {wanted} was wanted"
1104 )));
1105 }
1106 }
1107 Ok(())
1108 }
1109
1110 fn bind_replacement_scan(
1121 &mut self,
1122 ast: &Ast,
1123 parts: &[&str],
1124 alias: ast::StrRef,
1125 columns: ast::Slice,
1126 missing: Error,
1127 ) -> Result<(NodeRef, Scope)> {
1128 let [path] = parts else { return Err(missing) };
1129 let path = *path;
1130 let extension = path.rsplit_once('.').map(|(_, after)| after).unwrap_or_default();
1131 let Some(function) = Self::reader_for(extension) else {
1132 if is_file(path) {
1133 return Err(Error::binder(format!(
1138 "No extension found that is capable of reading the file \"{path}\"\n* If this \
1139 file is a supported file format you can explicitly use the reader functions, \
1140 such as read_csv, read_json or read_parquet"
1141 )));
1142 }
1143 return Err(missing);
1144 };
1145 let paths = files(path)?;
1150 let first = paths.first().map_or("", String::as_str);
1151 let fields = match function {
1152 TableFunction::ReadParquet => parquet_fields(first)?,
1153 _ => csv_fields(&paths)?,
1154 };
1155 let label = if alias == NONE {
1161 if is_pattern(path) {
1162 path.to_string()
1163 } else {
1164 let file = path.rsplit_once('/').map_or(path, |(_, file)| file);
1165 file.rsplit_once('.').map_or(file, |(stem, _)| stem).to_string()
1166 }
1167 } else {
1168 ast.string(alias).to_string()
1169 };
1170 let arguments: Vec<ExprRef> = paths.iter().map(|path| self.path_constant(path)).collect();
1171 let names: Vec<&str> = ast.name(columns).collect();
1172 self.table_function_source(function, &arguments, fields, &label, &names)
1173 }
1174
1175 fn path_constant(&mut self, path: &str) -> ExprRef {
1177 let value = self.plan.add_value(Value::Varchar(path.to_string()));
1178 self.plan.add_expr(Expr::Constant(value), LogicalType::Varchar)
1179 }
1180
1181 fn reader_for(extension: &str) -> Option<TableFunction> {
1188 if extension.eq_ignore_ascii_case("parquet") {
1189 return Some(TableFunction::ReadParquet);
1190 }
1191 if extension.eq_ignore_ascii_case("csv") || extension.eq_ignore_ascii_case("tsv") {
1192 return Some(TableFunction::ReadCsv);
1193 }
1194 None
1195 }
1196
1197 fn table_function_source(
1202 &mut self,
1203 function: TableFunction,
1204 args: &[ExprRef],
1205 fields: Vec<Field>,
1206 label: &str,
1207 names: &[&str],
1208 ) -> Result<(NodeRef, Scope)> {
1209 let index = self.fresh_index();
1210 let mut scope = Scope::empty();
1211 for (at, field) in fields.iter().enumerate() {
1212 scope.push(Visible {
1213 table: label.to_string(),
1214 name: field.name.clone(),
1215 binding: ColumnBinding::new(index, at as u32),
1216 ty: field.ty.clone(),
1217 });
1218 }
1219 if !names.is_empty() {
1220 scope.rename(names, label)?;
1221 }
1222 let function = self.plan.intern(function.name());
1223 let args = self.plan.add_expr_list(args);
1224 let columns = self.plan.add_fields(&fields);
1225 let node = self.plan.add_node(Node::TableFunction { index, function, args, columns });
1226 Ok((node, scope))
1227 }
1228
1229 fn file_paths(&self, expr: ExprRef, name: &str) -> Result<Vec<String>> {
1236 let mut paths = Vec::new();
1237 for pattern in self.file_patterns(expr, name)? {
1238 paths.extend(files(&pattern)?);
1239 }
1240 Ok(paths)
1241 }
1242
1243 fn file_patterns(&self, expr: ExprRef, name: &str) -> Result<Vec<String>> {
1255 let Expr::Constant(reference) = *self.plan.expr(expr) else {
1256 return Err(Error::not_implemented(
1257 "a table function file name that is not a constant",
1258 ));
1259 };
1260 match self.plan.value(reference) {
1261 Value::Varchar(path) => Ok(vec![path.clone()]),
1262 Value::Null => Err(Error::parser(format!("{name} cannot take NULL list as parameter"))),
1264 Value::List { values, .. } => values
1265 .iter()
1266 .map(|value| match value {
1267 Value::Varchar(path) => Ok(path.clone()),
1268 _ => Err(Error::parser(format!(
1269 "{name} reader cannot take NULL input as parameter"
1270 ))),
1271 })
1272 .collect(),
1273 other => {
1274 Err(Error::internal(format!("a file name bound as VARCHAR arrived as {other}")))
1275 }
1276 }
1277 }
1278
1279 #[allow(clippy::too_many_arguments)]
1280 fn bind_join(
1281 &mut self,
1282 ast: &Ast,
1283 left: ast::SourceRef,
1284 right: ast::SourceRef,
1285 kind: ast::JoinKind,
1286 natural: bool,
1287 on: ast::ExprRef,
1288 using: ast::Slice,
1289 ) -> Result<(NodeRef, Scope)> {
1290 let (left_node, left_scope) = self.bind_source(ast, left)?;
1291 let (right_node, right_scope) = self.bind_source(ast, right)?;
1292 let split = left_scope.len();
1293 let mut scope = left_scope.concat(right_scope);
1294
1295 let merged: Vec<String> = if natural {
1298 let mut names = Vec::new();
1299 for (at, column) in scope.columns.iter().enumerate().take(split) {
1300 if scope.columns[split..].iter().any(|right| same_name(&right.name, &column.name))
1301 && !names.iter().any(|held: &String| same_name(held, &column.name))
1302 {
1303 let _ = at;
1304 names.push(column.name.clone());
1305 }
1306 }
1307 names
1308 } else {
1309 ast.name(using).map(str::to_string).collect()
1310 };
1311
1312 let mut conditions = Vec::new();
1313 let mut dropped = Vec::new();
1314 for name in &merged {
1315 let left_at = scope.columns[..split]
1316 .iter()
1317 .position(|column| same_name(&column.name, name))
1318 .ok_or_else(|| {
1319 Error::binder(format!(
1320 "column \"{name}\" specified in USING clause does not exist in left table"
1321 ))
1322 })?;
1323 let right_at = scope.columns[split..]
1324 .iter()
1325 .position(|column| same_name(&column.name, name))
1326 .map(|at| at + split)
1327 .ok_or_else(|| {
1328 Error::binder(format!(
1329 "column \"{name}\" specified in USING clause does not exist in right table"
1330 ))
1331 })?;
1332 let left_column = &scope.columns[left_at];
1333 let (left_binding, left_type) = (left_column.binding, left_column.ty.clone());
1334 let right_column = &scope.columns[right_at];
1335 let (right_binding, right_type) = (right_column.binding, right_column.ty.clone());
1336 let left_expr = self.plan.add_expr(Expr::Column(left_binding), left_type);
1337 let right_expr = self.plan.add_expr(Expr::Column(right_binding), right_type);
1338 conditions.push(self.compare(rudb_plan::CompareOp::Equal, left_expr, right_expr)?);
1339 dropped.push(right_at);
1340 }
1341 dropped.sort_unstable();
1344 for at in dropped.into_iter().rev() {
1345 scope.remove(at);
1346 }
1347
1348 if on != NONE {
1349 if !merged.is_empty() {
1350 return Err(Error::binder("a join cannot have both ON and USING"));
1351 }
1352 self.clause = "JOIN condition";
1353 let predicate = self.bind_expr(ast, on, &scope)?;
1354 conditions.push(self.as_boolean(predicate, "JOIN")?);
1355 }
1356
1357 if kind == ast::JoinKind::Cross {
1358 if !conditions.is_empty() {
1359 return Err(Error::binder("a CROSS JOIN cannot have a condition"));
1360 }
1361 let node =
1362 self.plan.add_node(Node::CrossProduct { left: left_node, right: right_node });
1363 return Ok((node, scope));
1364 }
1365 if conditions.is_empty() && kind == ast::JoinKind::Inner {
1366 let node =
1367 self.plan.add_node(Node::CrossProduct { left: left_node, right: right_node });
1368 return Ok((node, scope));
1369 }
1370 let kind = match kind {
1371 ast::JoinKind::Inner | ast::JoinKind::Cross => JoinKind::Inner,
1372 ast::JoinKind::Left => JoinKind::Left,
1373 ast::JoinKind::Right => JoinKind::Right,
1374 ast::JoinKind::Full => JoinKind::Full,
1375 ast::JoinKind::Semi => JoinKind::Semi,
1376 ast::JoinKind::Anti => JoinKind::Anti,
1377 ast::JoinKind::Positional => JoinKind::Positional,
1378 };
1379 let conditions = self.plan.add_expr_list(&conditions);
1380 let node =
1381 self.plan.add_node(Node::Join { left: left_node, right: right_node, kind, conditions });
1382 Ok((node, scope))
1383 }
1384
1385 pub(crate) fn bind_aggregate(
1389 &mut self,
1390 ast: &Ast,
1391 name: &str,
1392 args: &[ast::ExprRef],
1393 distinct: bool,
1394 scope: &Scope,
1395 ) -> Result<ExprRef> {
1396 if self.in_aggregate {
1397 return Err(Error::binder(format!(
1398 "aggregate function calls cannot be nested, and {name}() is inside one"
1399 )));
1400 }
1401 if self.aggregation.is_none() {
1402 return Err(Error::binder(format!(
1403 "aggregate function calls cannot be used in the {}",
1404 self.clause
1405 )));
1406 }
1407 self.in_aggregate = true;
1408 let mut bound = Vec::with_capacity(args.len());
1409 let mut failure = None;
1410 for &arg in args {
1411 match self.bind_expr(ast, arg, scope) {
1412 Ok(expr) => bound.push(expr),
1413 Err(error) => {
1414 failure = Some(error);
1415 break;
1416 }
1417 }
1418 }
1419 self.in_aggregate = false;
1420 if let Some(error) = failure {
1421 return Err(error);
1422 }
1423
1424 let types: Vec<LogicalType> =
1425 bound.iter().map(|&arg| self.plan.expr_type(arg).clone()).collect();
1426 let resolved = resolve(name, &types)?;
1427 let mut cast = Vec::with_capacity(bound.len());
1428 for (arg, wanted) in bound.iter().zip(&resolved.arguments) {
1429 cast.push(self.cast_to(*arg, wanted));
1430 }
1431 let args = self.plan.add_expr_list(&cast);
1432 let name = self.plan.intern(resolved.name);
1433 let ty = resolved.returns;
1434 let call =
1435 self.plan.add_expr(Expr::Aggregate { name, args, distinct, filter: None }, ty.clone());
1436
1437 let existing = self.aggregation.as_ref().map(|held| held.aggregates.clone());
1440 let existing = existing.unwrap_or_default();
1441 let at = match existing.iter().position(|&held| self.same_expr(held, call)) {
1442 Some(at) => at,
1443 None => {
1444 let aggregation = self.aggregation.as_mut().expect("checked above");
1445 aggregation.aggregates.push(call);
1446 aggregation.aggregates.len() - 1
1447 }
1448 };
1449 let aggregation = self.aggregation.as_ref().expect("checked above");
1450 let (index, groups) = (aggregation.index, aggregation.groups.len());
1451 Ok(self.column(index, groups + at, ty))
1452 }
1453
1454 pub(crate) fn over_aggregate(&mut self, expr: ExprRef, scope: &Scope) -> Result<ExprRef> {
1460 let Some(aggregation) = self.aggregation.as_ref() else {
1461 return Ok(expr);
1462 };
1463 let index = aggregation.index;
1464 let groups = aggregation.groups.clone();
1465 for (at, group) in groups.iter().enumerate() {
1466 if self.same_expr(expr, *group) {
1467 let ty = self.plan.expr_type(*group).clone();
1468 return Ok(self.column(index, at, ty));
1469 }
1470 }
1471 let ty = self.plan.expr_type(expr).clone();
1472 match self.plan.expr(expr).clone() {
1473 Expr::Column(binding) if binding.table == index => Ok(expr),
1474 Expr::Column(binding) => {
1475 let name =
1476 scope.columns.iter().find(|column| column.binding == binding).map_or_else(
1477 || "a column".to_string(),
1478 |column| format!("\"{}\"", column.name),
1479 );
1480 Err(Error::binder(format!(
1481 "column {name} must appear in the GROUP BY clause or must be part of an aggregate function"
1482 )))
1483 }
1484 Expr::Constant(_) | Expr::Aggregate { .. } => Ok(expr),
1485 Expr::Cast { input, try_cast } => {
1486 let input = self.over_aggregate(input, scope)?;
1487 Ok(self.plan.add_expr(Expr::Cast { input, try_cast }, ty))
1488 }
1489 Expr::Compare { op, left, right } => {
1490 let left = self.over_aggregate(left, scope)?;
1491 let right = self.over_aggregate(right, scope)?;
1492 Ok(self.plan.add_expr(Expr::Compare { op, left, right }, ty))
1493 }
1494 Expr::Conjunction { op, children } => {
1495 let written = self.plan.expr_list(children).to_vec();
1496 let mut rewritten = Vec::with_capacity(written.len());
1497 for child in written {
1498 rewritten.push(self.over_aggregate(child, scope)?);
1499 }
1500 let children = self.plan.add_expr_list(&rewritten);
1501 Ok(self.plan.add_expr(Expr::Conjunction { op, children }, ty))
1502 }
1503 Expr::Function { name, args } => {
1504 let written = self.plan.expr_list(args).to_vec();
1505 let mut rewritten = Vec::with_capacity(written.len());
1506 for arg in written {
1507 rewritten.push(self.over_aggregate(arg, scope)?);
1508 }
1509 let args = self.plan.add_expr_list(&rewritten);
1510 Ok(self.plan.add_expr(Expr::Function { name, args }, ty))
1511 }
1512 Expr::Case { arms, otherwise } => {
1513 let written = self.plan.arm_list(arms).to_vec();
1514 let mut rewritten = Vec::with_capacity(written.len());
1515 for arm in written {
1516 let when = self.over_aggregate(arm.when, scope)?;
1517 let then = self.over_aggregate(arm.then, scope)?;
1518 rewritten.push(rudb_plan::Arm { when, then });
1519 }
1520 let otherwise = match otherwise {
1521 Some(expr) => Some(self.over_aggregate(expr, scope)?),
1522 None => None,
1523 };
1524 let arms = self.plan.add_arms(&rewritten);
1525 Ok(self.plan.add_expr(Expr::Case { arms, otherwise }, ty))
1526 }
1527 }
1528 }
1529
1530 pub(crate) fn same_expr(&self, left: ExprRef, right: ExprRef) -> bool {
1532 same_expr(&self.plan, left, right)
1533 }
1534}
1535
1536#[derive(Debug, Default)]
1542struct Options {
1543 binary_as_string: bool,
1546}
1547
1548fn missing_replacement(name: &str, input: &Scope) -> Error {
1553 Error::binder(format!(
1554 "Column \"{name}\" in REPLACE list not found in FROM clause{}",
1555 input.candidates()
1556 ))
1557}
1558
1559fn sort_key(expr: ExprRef, item: ast::OrderItem) -> SortKey {
1565 let descending = item.order == Order::Descending;
1566 let nulls_first = match item.nulls {
1567 Nulls::First => true,
1568 Nulls::Last => false,
1569 Nulls::Unstated => descending,
1570 };
1571 SortKey { expr, descending, nulls_first }
1572}
1573
1574fn same_expr(plan: &Plan, left: ExprRef, right: ExprRef) -> bool {
1576 if left == right {
1577 return true;
1578 }
1579 if plan.expr_type(left) != plan.expr_type(right) {
1580 return false;
1581 }
1582 let lists = |left, right| {
1583 let left: &[ExprRef] = plan.expr_list(left);
1584 let right: &[ExprRef] = plan.expr_list(right);
1585 left.len() == right.len()
1586 && left.iter().zip(right).all(|(&left, &right)| same_expr(plan, left, right))
1587 };
1588 match (plan.expr(left), plan.expr(right)) {
1589 (Expr::Column(left), Expr::Column(right)) => left == right,
1590 (Expr::Constant(left), Expr::Constant(right)) => plan.value(*left) == plan.value(*right),
1591 (
1592 Expr::Cast { input: left, try_cast: left_try },
1593 Expr::Cast { input: right, try_cast: right_try },
1594 ) => left_try == right_try && same_expr(plan, *left, *right),
1595 (
1596 Expr::Compare { op: left_op, left: left_a, right: left_b },
1597 Expr::Compare { op: right_op, left: right_a, right: right_b },
1598 ) => {
1599 left_op == right_op
1600 && same_expr(plan, *left_a, *right_a)
1601 && same_expr(plan, *left_b, *right_b)
1602 }
1603 (
1604 Expr::Conjunction { op: left_op, children: left_children },
1605 Expr::Conjunction { op: right_op, children: right_children },
1606 ) => left_op == right_op && lists(*left_children, *right_children),
1607 (
1608 Expr::Function { name: left_name, args: left_args },
1609 Expr::Function { name: right_name, args: right_args },
1610 ) => plan.string(*left_name) == plan.string(*right_name) && lists(*left_args, *right_args),
1611 (
1612 Expr::Aggregate {
1613 name: left_name,
1614 args: left_args,
1615 distinct: left_distinct,
1616 filter: left_filter,
1617 },
1618 Expr::Aggregate {
1619 name: right_name,
1620 args: right_args,
1621 distinct: right_distinct,
1622 filter: right_filter,
1623 },
1624 ) => {
1625 plan.string(*left_name) == plan.string(*right_name)
1626 && left_distinct == right_distinct
1627 && match (left_filter, right_filter) {
1628 (None, None) => true,
1629 (Some(left), Some(right)) => same_expr(plan, *left, *right),
1630 _ => false,
1631 }
1632 && lists(*left_args, *right_args)
1633 }
1634 (
1635 Expr::Case { arms: left_arms, otherwise: left_otherwise },
1636 Expr::Case { arms: right_arms, otherwise: right_otherwise },
1637 ) => {
1638 let left_arms = plan.arm_list(*left_arms);
1639 let right_arms = plan.arm_list(*right_arms);
1640 left_arms.len() == right_arms.len()
1641 && left_arms.iter().zip(right_arms).all(|(left, right)| {
1642 same_expr(plan, left.when, right.when) && same_expr(plan, left.then, right.then)
1643 })
1644 && match (left_otherwise, right_otherwise) {
1645 (None, None) => true,
1646 (Some(left), Some(right)) => same_expr(plan, *left, *right),
1647 _ => false,
1648 }
1649 }
1650 _ => false,
1651 }
1652}