Skip to main content

rudb_bind/
binder.rs

1//! From an `Ast` to a `Plan`.
2//!
3//! The binder walks the written query once, in the order the operators end up in rather than the
4//! order the clauses are written in, which is `FROM`, `WHERE`, `GROUP BY`, `HAVING`, `SELECT`,
5//! `DISTINCT`, `ORDER BY`, `LIMIT`. That order is not a stylistic choice: it is the reason `WHERE`
6//! cannot see an output alias and `HAVING` cannot see a column that was not grouped, and doing it
7//! in any other order means special casing both of those instead of getting them for free.
8//!
9//! Two things leave here settled that nothing downstream reconsiders. Every column is a table index
10//! and a position rather than a name, so the optimizer never has to ask which `id` a name meant.
11//! And every expression has a type, with the casts that make the types line up already written into
12//! the plan as [`Expr::Cast`] nodes, so an executor never has to decide what a comparison between
13//! an `INTEGER` and a `BIGINT` does.
14
15use 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
25/// Binds a parsed statement against a catalog.
26///
27/// # Errors
28///
29/// If the script does not hold exactly one statement, if a name does not resolve, if a type does
30/// not work out, or if the query uses something M0 does not bind yet.
31pub 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
45/// Parses and binds one query, which is the whole front end in one call.
46///
47/// # Errors
48///
49/// Anything the parser or the binder reports.
50pub fn bind_sql(query: &str, catalog: &Catalog) -> Result<Plan> {
51    let ast = parse_ast(query)?;
52    bind(&ast, catalog)
53}
54
55/// What an aggregating select block has decided so far.
56#[derive(Debug)]
57pub(crate) struct Aggregation {
58    /// The table index the aggregate's output binds against.
59    pub(crate) index: u32,
60    /// The group expressions, over the input, which are the first output columns.
61    pub(crate) groups: Vec<ExprRef>,
62    /// The aggregate calls found so far, which follow the groups in the output.
63    pub(crate) aggregates: Vec<ExprRef>,
64}
65
66/// The state one binding run carries.
67#[derive(Debug)]
68pub(crate) struct Binder<'a> {
69    catalog: &'a Catalog,
70    plan: Plan,
71    next_index: u32,
72    /// Set while a select block aggregates, which changes what a bare column means.
73    pub(crate) aggregation: Option<Aggregation>,
74    /// Set while an aggregate's own arguments are being bound, so nesting is caught.
75    pub(crate) in_aggregate: bool,
76    /// Where we are, for an error message that says which clause the writer should look at.
77    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    /// A table index nothing else has.
105    fn fresh_index(&mut self) -> u32 {
106        let index = self.next_index;
107        self.next_index += 1;
108        index
109    }
110
111    /// A reference to one column of an operator's output.
112    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    // ---------------------------------------------------------------- queries
118
119    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        // Both sides have to hand back one set of types, so each column meets the other side's.
155        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        // UNION alone removes duplicates and UNION ALL keeps them, which is the one place the
174        // unwritten quantifier and ALL disagree.
175        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        // Above a set operation there is nothing but the output columns, so an ORDER BY term is
193        // either a position, an output name, or an expression over the output, and never needs a
194        // column projected for it that the query did not ask for.
195        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    /// Projects one side of a set operation so that its columns have the agreed types.
205    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    // ----------------------------------------------------------------- select
223
224    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        // The projection's index has to exist before the sort keys are built, because a key is a
272        // reference to a projected column even when the expression it sorts on is not selected.
273        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        // An expression sorted on but not selected was carried this far to make the sort possible,
331        // and now it goes, because the query did not ask for it.
332        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    /// Binds the target list, expanding every star into the columns it stands for.
354    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    /// The name an unaliased target gets.
386    ///
387    /// A bare column keeps the spelling the table was created with rather than the spelling the
388    /// query used, so `SELECT USERID FROM hits` has a column called `UserID`. Identifiers match
389    /// without regard to case and the catalog is the one that holds the case.
390    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    /// The expressions a `GROUP BY` clause names, with positions and output aliases followed.
401    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            // GROUP BY ALL means every target that is not itself an aggregate, which is the set
409            // that would otherwise have to be written out again by hand.
410            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    /// The target a `GROUP BY` or `ORDER BY` term names, when it names one by position or alias.
424    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    // -------------------------------------------------------------- modifiers
464
465    /// Sort keys for a select, projecting anything sorted on that is not already selected.
466    #[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    /// Sort keys over an output that has nothing behind it to project, which is a set operation.
508    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    /// Which output column a term names, by position or by name.
550    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    /// The expressions a `DISTINCT ON` names, which have to be columns of the output.
583    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    /// The row count a `LIMIT` or an `OFFSET` names, which has to be a constant.
620    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    // ------------------------------------------------------------------- from
655
656    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            // No FROM clause is one row of no columns, which is what SELECT 1 sits on. Not an
660            // empty table: an empty table would make SELECT 1 return nothing.
661            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        // NATURAL is USING over whatever both sides happen to call the same thing, which is why it
758        // is resolved here and never reaches the plan as its own idea.
759        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        // A joined-on column appears once, so the right side's copy goes. Dropping from the back
804        // keeps the positions of the ones still to drop correct.
805        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    // -------------------------------------------------------------- aggregates
848
849    /// Binds an aggregate call, records it, and hands back a reference to where its result lands.
850    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        // Two identical aggregates are one column of the aggregate's output. `SELECT sum(x),
900        // sum(x) / count(*)` computes one sum, not two.
901        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    /// Rewrites a bound expression into one the aggregate's output can answer.
917    ///
918    /// A subexpression that is one of the group expressions becomes a reference to that group. A
919    /// column that is neither grouped nor inside an aggregate is the error every SQL user has seen,
920    /// and it is reported here because this is the first point where it is knowable.
921    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    /// Whether two bound expressions are the same expression, by shape rather than by reference.
993    pub(crate) fn same_expr(&self, left: ExprRef, right: ExprRef) -> bool {
994        same_expr(&self.plan, left, right)
995    }
996}
997
998/// A sort key with SQL's defaults filled in.
999///
1000/// Unstated is ascending, and unstated nulls go where the direction puts them, which is last for
1001/// ascending and first for descending. That is DuckDB's rule and it is the one that makes
1002/// `ORDER BY x DESC` the exact reverse of `ORDER BY x`.
1003fn 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
1013/// Structural equality over two expressions of one plan.
1014fn 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}