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, Entry, QualifiedName, same_name};
16use rudb_common::{Error, Field, LogicalType, Result, Session, Value};
17use rudb_functions::{
18    Columns, FILE_ROW_NUMBER, Given, TableFunction, csv_fields, csv_given, files, is_file,
19    is_pattern, parquet_fields, resolve, resolve_table,
20};
21use rudb_parse::ast::{self, Ast, Distinct, LiteralKind, Nulls, Order, Quantifier, SetOp};
22use rudb_parse::{NONE, identifier_parts, 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
29/// Binds a parsed statement against a catalog.
30///
31/// # Errors
32///
33/// If the script does not hold exactly one statement, if a name does not resolve, if a type does
34/// not work out, or if the query uses something M0 does not bind yet.
35pub fn bind(ast: &Ast, catalog: &Catalog) -> Result<Plan> {
36    bind_with(ast, catalog, &Parameters::new(), &Session::new())
37}
38
39/// Binds a parsed query against a catalog, with values for its parameters and its settings.
40///
41/// The session is what `current_setting()` reads, and a caller with no database behind it passes an
42/// empty one, which makes every setting name unrecognized rather than making up an answer.
43///
44/// # Errors
45///
46/// Everything [`bind`] reports, plus an error for a parameter that was given no value.
47pub fn bind_with(
48    ast: &Ast,
49    catalog: &Catalog,
50    parameters: &Parameters,
51    session: &Session,
52) -> Result<Plan> {
53    let query = match ast.statements.as_slice() {
54        [ast::Statement::Query(query)] => *query,
55        [] => return Err(Error::binder("no statement to bind")),
56        // One statement that is not a query is its own answer. Reporting it as a script of several
57        // reads as a count being wrong, and the count is right.
58        [_] => return Err(Error::not_implemented("a statement that is not a query")),
59        _ => return Err(Error::not_implemented("a script of more than one statement")),
60    };
61    let mut binder = Binder::with(catalog, parameters, session);
62    let (root, _) = binder.bind_query(ast, query)?;
63    let mut plan = binder.into_plan();
64    plan.set_root(root);
65    plan.validate()?;
66    Ok(plan)
67}
68
69/// Parses and binds one query, which is the whole front end in one call.
70///
71/// # Errors
72///
73/// Anything the parser or the binder reports.
74pub fn bind_sql(query: &str, catalog: &Catalog) -> Result<Plan> {
75    bind_sql_with(query, catalog, &Session::new())
76}
77
78/// Parses and binds one query, with the settings a call to `current_setting()` reads.
79///
80/// # Errors
81///
82/// Anything the parser or the binder reports.
83pub fn bind_sql_with(query: &str, catalog: &Catalog, session: &Session) -> Result<Plan> {
84    let ast = parse_ast(query)?;
85    bind_with(&ast, catalog, &Parameters::new(), session)
86}
87
88/// What an aggregating select block has decided so far.
89#[derive(Debug)]
90pub(crate) struct Aggregation {
91    /// The table index the aggregate's output binds against.
92    pub(crate) index: u32,
93    /// The group expressions, over the input, which are the first output columns.
94    pub(crate) groups: Vec<ExprRef>,
95    /// The aggregate calls found so far, which follow the groups in the output.
96    pub(crate) aggregates: Vec<ExprRef>,
97}
98
99/// The state one binding run carries.
100#[derive(Debug)]
101pub(crate) struct Binder<'a> {
102    catalog: &'a Catalog,
103    /// What the parameters were given, empty for a statement that is not prepared.
104    pub(crate) parameters: &'a Parameters,
105    /// What the settings are now, which is what `current_setting()` folds to.
106    pub(crate) session: &'a Session,
107    plan: Plan,
108    next_index: u32,
109    /// Set while a select block aggregates, which changes what a bare column means.
110    pub(crate) aggregation: Option<Aggregation>,
111    /// Set while an aggregate's own arguments are being bound, so nesting is caught.
112    pub(crate) in_aggregate: bool,
113    /// Where we are, for an error message that says which clause the writer should look at.
114    pub(crate) clause: &'static str,
115    /// The views whose bodies are open on the stack, which is what catches a cycle.
116    expanding: Vec<String>,
117    /// When this statement started, read once and kept, which is what `now()` folds to.
118    started: Option<i64>,
119}
120
121impl<'a> Binder<'a> {
122    pub(crate) fn with(
123        catalog: &'a Catalog,
124        parameters: &'a Parameters,
125        session: &'a Session,
126    ) -> Self {
127        Self {
128            catalog,
129            parameters,
130            session,
131            plan: Plan::new(),
132            next_index: 0,
133            aggregation: None,
134            in_aggregate: false,
135            clause: "SELECT clause",
136            expanding: Vec::new(),
137            started: None,
138        }
139    }
140
141    pub(crate) fn catalog(&self) -> &Catalog {
142        self.catalog
143    }
144
145    /// When this statement started, in microseconds since the epoch.
146    ///
147    /// Read from the clock the first time something asks and kept after that, so a query that
148    /// writes `now()` twice gets one answer for both. That is what the pin does and what it reports
149    /// in the `stability` column of `duckdb_functions()`, where every one of these is
150    /// `CONSISTENT_WITHIN_QUERY`. A query that never asks never reads the clock.
151    pub(crate) fn instant(&mut self) -> i64 {
152        *self.started.get_or_insert_with(crate::context::micros_now)
153    }
154
155    pub(crate) fn plan(&self) -> &Plan {
156        &self.plan
157    }
158
159    pub(crate) fn plan_mut(&mut self) -> &mut Plan {
160        &mut self.plan
161    }
162
163    pub(crate) fn into_plan(self) -> Plan {
164        self.plan
165    }
166
167    /// A table index nothing else has.
168    pub(crate) fn fresh_index(&mut self) -> u32 {
169        let index = self.next_index;
170        self.next_index += 1;
171        index
172    }
173
174    /// A reference to one column of an operator's output.
175    fn column(&mut self, index: u32, position: usize, ty: LogicalType) -> ExprRef {
176        let binding = ColumnBinding::new(index, position as u32);
177        self.plan.add_expr(Expr::Column(binding), ty)
178    }
179
180    // ---------------------------------------------------------------- queries
181
182    pub(crate) fn bind_query(
183        &mut self,
184        ast: &Ast,
185        query: ast::QueryRef,
186    ) -> Result<(NodeRef, Scope)> {
187        let written = ast.query(query);
188        match written.body {
189            ast::QueryBody::Select(select) => self.bind_select(ast, select, &written),
190            ast::QueryBody::SetOp { op, quantifier, by_name, left, right } => {
191                if by_name {
192                    return Err(Error::not_implemented("UNION BY NAME"));
193                }
194                self.bind_set_op(ast, &written, op, quantifier, left, right)
195            }
196            ast::QueryBody::Values(rows) => self.bind_values(ast, &written, rows),
197            ast::QueryBody::Describe(inner) => self.bind_describe(ast, &written, inner),
198        }
199    }
200
201    /// `DESCRIBE <query>`, which is six VARCHAR columns saying what the query returns.
202    ///
203    /// The query is bound and never run, because binding is the whole of the answer: the names and
204    /// the types of a query's columns are settled by the time the binder is done with it, so the
205    /// rows of a describe are a constant from there on. That is why this comes out as a `VALUES`
206    /// whose rows were computed here rather than as an operator of its own, and it is what makes
207    /// `SELECT column_name FROM (DESCRIBE ...) WHERE ...` an ordinary query over an ordinary
208    /// relation with no special case above it.
209    ///
210    /// The six columns, their order and their types are the reference binary's. `key`, `default`
211    /// and `extra` are null for everything this engine can declare, since `PRIMARY KEY`, `UNIQUE`
212    /// and `DEFAULT` are all refused by `CREATE TABLE` today and there is nothing for the first two
213    /// to hold, and `extra` is empty upstream as well on every table it was asked about. They are
214    /// here rather than left out because the width of a result is part of the result, and a program
215    /// that reads the fifth column has to find one.
216    fn bind_describe(
217        &mut self,
218        ast: &Ast,
219        query: &ast::Query,
220        inner: ast::QueryRef,
221    ) -> Result<(NodeRef, Scope)> {
222        let (_, described) = self.bind_query(ast, inner)?;
223        let fields: Vec<Field> = ["column_name", "column_type", "null", "key", "default", "extra"]
224            .iter()
225            .map(|name| Field::new(*name, LogicalType::Varchar))
226            .collect();
227        let mut slices = Vec::with_capacity(described.columns.len());
228        for column in described.columns.clone() {
229            // `NO` and `YES` and not a boolean, because the column is VARCHAR upstream and a
230            // client that prints the result has to get the same four or three characters.
231            let written = [
232                column.name.clone(),
233                column.ty.to_string(),
234                if column.not_null { "NO" } else { "YES" }.to_owned(),
235            ];
236            let mut items: Vec<ExprRef> = written
237                .into_iter()
238                .map(|text| self.plan.add_constant(Value::Varchar(text)))
239                .collect();
240            for _ in 0..3 {
241                let empty = self.plan.add_constant(Value::Null);
242                items.push(self.cast_to(empty, &LogicalType::Varchar));
243            }
244            slices.push(self.plan.add_expr_list(&items));
245        }
246        let rows = self.plan.add_rows(&slices);
247        let columns = self.plan.add_fields(&fields);
248        let index = self.fresh_index();
249        let mut node = self.plan.add_node(Node::Values { index, columns, rows });
250        let mut scope = Scope::empty();
251        for (at, field) in fields.iter().enumerate() {
252            scope.push(Visible {
253                table: String::new(),
254                name: field.name.clone(),
255                binding: ColumnBinding::new(index, at as u32),
256                ty: field.ty.clone(),
257                not_null: false,
258            });
259        }
260        let keys = self.sort_keys(ast, query, &scope, &[])?;
261        if !keys.is_empty() {
262            let keys = self.plan.add_sort_keys(&keys);
263            node = self.plan.add_node(Node::Sort { input: node, keys });
264        }
265        node = self.apply_limit(ast, query, node)?;
266        Ok((node, scope))
267    }
268
269    /// Whether a projected expression is a column passed straight through from below.
270    ///
271    /// Only `DESCRIBE` asks, and only to decide whether the `null` column says `NO`. Anything that
272    /// is computed is nullable however strict its inputs were, which is both the safe reading and
273    /// the one the reference binary gives.
274    fn passes_through(&self, expr: ExprRef, input: &Scope) -> bool {
275        let Expr::Column(binding) = *self.plan.expr(expr) else { return false };
276        input.columns.iter().any(|column| column.binding == binding && column.not_null)
277    }
278
279    /// `VALUES (1, 'a'), (2, 'b')`, as a query in its own right.
280    ///
281    /// The column names are `col0`, `col1` and so on, which is what DuckDB calls them, and the
282    /// column types are what every row in that position promotes to. Promotion is the same rule a
283    /// set operation uses, and for the same reason: a column has one type and the rows have to
284    /// agree on it before anything downstream can read the column.
285    fn bind_values(
286        &mut self,
287        ast: &Ast,
288        query: &ast::Query,
289        rows: ast::Slice,
290    ) -> Result<(NodeRef, Scope)> {
291        let written = ast.rows(rows).to_vec();
292        let Some(first) = written.first() else {
293            return Err(Error::binder("VALUES needs at least one row"));
294        };
295        let width = first.len as usize;
296        for (at, row) in written.iter().enumerate() {
297            if row.len as usize != width {
298                return Err(Error::binder(format!(
299                    "VALUES lists must all be the same length, expected {width} columns but row {} has {}",
300                    at + 1,
301                    row.len
302                )));
303            }
304        }
305        // A row of a `VALUES` cannot see a column, because there is nothing under it to see.
306        let empty = Scope::empty();
307        let previous = std::mem::replace(&mut self.clause, "VALUES clause");
308        let mut bound: Vec<Vec<ExprRef>> = Vec::with_capacity(written.len());
309        for row in &written {
310            let mut items = Vec::with_capacity(width);
311            for &expr in ast.expr_list(*row) {
312                items.push(self.bind_expr(ast, expr, &empty)?);
313            }
314            bound.push(items);
315        }
316        self.clause = previous;
317        let mut types = Vec::with_capacity(width);
318        for at in 0..width {
319            let mut ty = self.plan.expr_type(bound[0][at]).clone();
320            for row in &bound[1..] {
321                let other = self.plan.expr_type(row[at]).clone();
322                ty = ty.promote(&other).ok_or_else(|| {
323                    Error::binder(format!(
324                        "Cannot combine a value of type {ty} with a value of type {other} in column {} of a VALUES",
325                        at + 1
326                    ))
327                })?;
328            }
329            types.push(ty);
330        }
331        let mut slices = Vec::with_capacity(bound.len());
332        for row in &bound {
333            let items: Vec<ExprRef> =
334                row.iter().zip(&types).map(|(&expr, ty)| self.cast_to(expr, ty)).collect();
335            slices.push(self.plan.add_expr_list(&items));
336        }
337        let rows = self.plan.add_rows(&slices);
338        let fields: Vec<Field> = types
339            .iter()
340            .enumerate()
341            .map(|(at, ty)| Field::new(format!("col{at}"), ty.clone()))
342            .collect();
343        let columns = self.plan.add_fields(&fields);
344        let index = self.fresh_index();
345        let mut node = self.plan.add_node(Node::Values { index, columns, rows });
346        let mut scope = Scope::empty();
347        for (at, field) in fields.iter().enumerate() {
348            scope.push(Visible {
349                table: String::new(),
350                name: field.name.clone(),
351                binding: ColumnBinding::new(index, at as u32),
352                ty: field.ty.clone(),
353                not_null: false,
354            });
355        }
356        let keys = self.sort_keys(ast, query, &scope, &[])?;
357        if !keys.is_empty() {
358            let keys = self.plan.add_sort_keys(&keys);
359            node = self.plan.add_node(Node::Sort { input: node, keys });
360        }
361        node = self.apply_limit(ast, query, node)?;
362        Ok((node, scope))
363    }
364
365    fn bind_set_op(
366        &mut self,
367        ast: &Ast,
368        query: &ast::Query,
369        op: SetOp,
370        quantifier: Quantifier,
371        left: ast::QueryRef,
372        right: ast::QueryRef,
373    ) -> Result<(NodeRef, Scope)> {
374        let (left_node, left_scope) = self.bind_query(ast, left)?;
375        let (right_node, right_scope) = self.bind_query(ast, right)?;
376        if left_scope.len() != right_scope.len() {
377            return Err(Error::binder(format!(
378                "Set operations can only apply to expressions with the same number of result columns, but left side has {} and right side has {}",
379                left_scope.len(),
380                right_scope.len()
381            )));
382        }
383        // Both sides have to hand back one set of types, so each column meets the other side's.
384        let mut types = Vec::with_capacity(left_scope.len());
385        for (left, right) in left_scope.columns.iter().zip(&right_scope.columns) {
386            let common = left.ty.promote(&right.ty).ok_or_else(|| {
387                Error::binder(format!(
388                    "Cannot combine a column of type {} with a column of type {} in a set operation",
389                    left.ty, right.ty
390                ))
391            })?;
392            types.push(common);
393        }
394        let left_node = self.conform(left_node, &left_scope, &types);
395        let right_node = self.conform(right_node, &right_scope, &types);
396        let index = self.fresh_index();
397        let kind = match op {
398            SetOp::Union => SetOpKind::Union,
399            SetOp::Except => SetOpKind::Except,
400            SetOp::Intersect => SetOpKind::Intersect,
401        };
402        // UNION alone removes duplicates and UNION ALL keeps them, which is the one place the
403        // unwritten quantifier and ALL disagree.
404        let all = quantifier == Quantifier::All;
405        let mut node = self.plan.add_node(Node::SetOp {
406            left: left_node,
407            right: right_node,
408            kind,
409            all,
410            index,
411        });
412        let mut scope = Scope::empty();
413        for (at, (column, ty)) in left_scope.columns.iter().zip(&types).enumerate() {
414            scope.push(Visible {
415                table: String::new(),
416                name: column.name.clone(),
417                binding: ColumnBinding::new(index, at as u32),
418                ty: ty.clone(),
419                // A column of a set operation is nullable whatever the two sides were, because a
420                // column that refuses nulls on one side and takes them on the other takes them.
421                not_null: false,
422            });
423        }
424        // Above a set operation there is nothing but the output columns, so an ORDER BY term is
425        // either a position, an output name, or an expression over the output, and never needs a
426        // column projected for it that the query did not ask for.
427        let keys = self.sort_keys(ast, query, &scope, &[])?;
428        if !keys.is_empty() {
429            let keys = self.plan.add_sort_keys(&keys);
430            node = self.plan.add_node(Node::Sort { input: node, keys });
431        }
432        node = self.apply_limit(ast, query, node)?;
433        Ok((node, scope))
434    }
435
436    /// Projects one side of a set operation so that its columns have the agreed types.
437    fn conform(&mut self, node: NodeRef, scope: &Scope, types: &[LogicalType]) -> NodeRef {
438        if scope.columns.iter().zip(types).all(|(column, ty)| &column.ty == ty) {
439            return node;
440        }
441        let index = self.fresh_index();
442        let mut exprs = Vec::with_capacity(types.len());
443        let mut names = Vec::with_capacity(types.len());
444        for (column, ty) in scope.columns.iter().zip(types) {
445            let expr = self.plan.add_expr(Expr::Column(column.binding), column.ty.clone());
446            exprs.push(self.cast_to(expr, ty));
447            names.push(self.plan.intern(&column.name));
448        }
449        let exprs = self.plan.add_expr_list(&exprs);
450        let names = self.plan.add_name_list(&names);
451        self.plan.add_node(Node::Project { input: node, index, exprs, names })
452    }
453
454    // ----------------------------------------------------------------- select
455
456    fn bind_select(
457        &mut self,
458        ast: &Ast,
459        select: ast::SelectRef,
460        query: &ast::Query,
461    ) -> Result<(NodeRef, Scope)> {
462        let written = ast.select(select);
463        let (mut node, input) = self.bind_from(ast, written.from)?;
464
465        if written.filter != NONE {
466            self.clause = "WHERE clause";
467            let predicate = self.bind_expr(ast, written.filter, &input)?;
468            let predicate = self.as_boolean(predicate, "WHERE")?;
469            node = self.plan.add_node(Node::Filter { input: node, predicate });
470        }
471
472        let targets = ast.target_list(written.targets).to_vec();
473        if targets.is_empty() {
474            return Err(Error::binder("a SELECT needs at least one expression to select"));
475        }
476
477        let group_items = self.group_items(ast, &written, &targets)?;
478        let aggregating = !group_items.is_empty()
479            || written.having != NONE
480            || targets.iter().any(|target| has_aggregate(ast, target.expr));
481        if aggregating {
482            self.clause = "GROUP BY clause";
483            let mut groups = Vec::with_capacity(group_items.len());
484            for item in &group_items {
485                groups.push(self.bind_expr(ast, *item, &input)?);
486            }
487            let index = self.fresh_index();
488            self.aggregation = Some(Aggregation { index, groups, aggregates: Vec::new() });
489        }
490
491        self.clause = "SELECT clause";
492        let (mut exprs, mut names) = self.bind_targets(ast, &targets, &input)?;
493        let visible = exprs.len();
494
495        let mut having = None;
496        if written.having != NONE {
497            self.clause = "HAVING clause";
498            let predicate = self.bind_expr(ast, written.having, &input)?;
499            let predicate = self.over_aggregate(predicate, &input)?;
500            having = Some(self.as_boolean(predicate, "HAVING")?);
501        }
502
503        // The projection's index has to exist before the sort keys are built, because a key is a
504        // reference to a projected column even when the expression it sorts on is not selected.
505        let project = self.fresh_index();
506        let mut output = Scope::empty();
507        for (at, (expr, name)) in exprs.iter().zip(&names).enumerate() {
508            output.push(Visible {
509                table: String::new(),
510                name: name.clone(),
511                binding: ColumnBinding::new(project, at as u32),
512                ty: self.plan.expr_type(*expr).clone(),
513                not_null: self.passes_through(*expr, &input),
514            });
515        }
516
517        self.clause = "ORDER BY clause";
518        let mut extra = Vec::new();
519        let keys = self.select_sort_keys(
520            ast, query, &input, &output, project, &mut exprs, &mut names, &mut extra,
521        )?;
522        if !extra.is_empty() && written.distinct != Distinct::No {
523            return Err(Error::binder(
524                "For SELECT DISTINCT, ORDER BY expressions must appear in the select list",
525            ));
526        }
527        let on = self.distinct_on(ast, written.distinct, &output)?;
528
529        if let Some(aggregation) = self.aggregation.take() {
530            let index = aggregation.index;
531            let groups = self.plan.add_expr_list(&aggregation.groups);
532            let aggregates = self.plan.add_expr_list(&aggregation.aggregates);
533            node = self.plan.add_node(Node::Aggregate { input: node, index, groups, aggregates });
534        }
535        if let Some(predicate) = having {
536            node = self.plan.add_node(Node::Filter { input: node, predicate });
537        }
538
539        let interned: Vec<u32> = names.iter().map(|name| self.plan.intern(name)).collect();
540        let exprs_slice = self.plan.add_expr_list(&exprs);
541        let names_slice = self.plan.add_name_list(&interned);
542        node = self.plan.add_node(Node::Project {
543            input: node,
544            index: project,
545            exprs: exprs_slice,
546            names: names_slice,
547        });
548
549        if written.distinct != Distinct::No {
550            let on = self.plan.add_expr_list(&on);
551            node = self.plan.add_node(Node::Distinct { input: node, on });
552        }
553        if !keys.is_empty() {
554            let keys = self.plan.add_sort_keys(&keys);
555            node = self.plan.add_node(Node::Sort { input: node, keys });
556        }
557        node = self.apply_limit(ast, query, node)?;
558
559        if extra.is_empty() {
560            output.columns.truncate(visible);
561            return Ok((node, output));
562        }
563        // An expression sorted on but not selected was carried this far to make the sort possible,
564        // and now it goes, because the query did not ask for it.
565        let index = self.fresh_index();
566        let mut kept = Vec::with_capacity(visible);
567        let mut kept_names = Vec::with_capacity(visible);
568        let mut scope = Scope::empty();
569        for (at, name) in names.iter().enumerate().take(visible) {
570            let ty = output.columns[at].ty.clone();
571            kept.push(self.column(project, at, ty.clone()));
572            kept_names.push(self.plan.intern(name));
573            scope.push(Visible {
574                table: String::new(),
575                name: name.clone(),
576                binding: ColumnBinding::new(index, at as u32),
577                ty,
578                not_null: output.columns[at].not_null,
579            });
580        }
581        let exprs = self.plan.add_expr_list(&kept);
582        let names = self.plan.add_name_list(&kept_names);
583        node = self.plan.add_node(Node::Project { input: node, index, exprs, names });
584        Ok((node, scope))
585    }
586
587    /// Binds the target list, expanding every star into the columns it stands for.
588    fn bind_targets(
589        &mut self,
590        ast: &Ast,
591        targets: &[ast::Target],
592        input: &Scope,
593    ) -> Result<(Vec<ExprRef>, Vec<String>)> {
594        let mut exprs = Vec::with_capacity(targets.len());
595        let mut names = Vec::with_capacity(targets.len());
596        for target in targets {
597            if let ast::Expr::Star { qualifier, replacements } = ast.expr(target.expr) {
598                let table = ast.name(qualifier).last().map(str::to_string);
599                let expanded: Vec<Visible> =
600                    input.star(table.as_deref())?.into_iter().cloned().collect();
601                let replacements = ast.target_list(replacements).to_vec();
602                let mut used = vec![false; replacements.len()];
603                for column in expanded {
604                    let found = replacements.iter().zip(&mut used).find(|(replacement, _)| {
605                        same_name(ast.string(replacement.alias), &column.name)
606                    });
607                    // The replacement takes the column's place and its position, and it is named the
608                    // way the replace list spells it rather than the way the table does. That only
609                    // shows when the two differ in case, and `AS EventDate` over a column called
610                    // `eventdate` is exactly the case that shows it.
611                    let (expr, name) = match found {
612                        Some((replacement, used)) => {
613                            *used = true;
614                            let expr = self.bind_expr(ast, replacement.expr, input)?;
615                            (expr, ast.string(replacement.alias).to_string())
616                        }
617                        None => (
618                            self.plan.add_expr(Expr::Column(column.binding), column.ty),
619                            column.name,
620                        ),
621                    };
622                    exprs.push(self.over_aggregate(expr, input)?);
623                    names.push(name);
624                }
625                // A replace list that named something the star did not stand for is a mistake and
626                // not a no op, and it is caught here because this is the first point at which the
627                // set of names the star stands for is known.
628                if let Some((replacement, _)) =
629                    replacements.iter().zip(&used).find(|(_, used)| !**used)
630                {
631                    return Err(missing_replacement(ast.string(replacement.alias), input));
632                }
633                continue;
634            }
635            let expr = self.bind_expr(ast, target.expr, input)?;
636            exprs.push(self.over_aggregate(expr, input)?);
637            names.push(if target.alias == NONE {
638                self.output_name(ast, target.expr, input)
639            } else {
640                ast.string(target.alias).to_string()
641            });
642        }
643        Ok((exprs, names))
644    }
645
646    /// The name an unaliased target gets.
647    ///
648    /// A bare column keeps the spelling the table was created with rather than the spelling the
649    /// query used, so `SELECT USERID FROM hits` has a column called `UserID`. Identifiers match
650    /// without regard to case and the catalog is the one that holds the case.
651    fn output_name(&self, ast: &Ast, target: ast::ExprRef, input: &Scope) -> String {
652        if let ast::Expr::Column { name } = ast.expr(target) {
653            let parts: Vec<&str> = ast.name(name).collect();
654            if let Ok(found) = input.resolve(&parts) {
655                return found.name.clone();
656            }
657        }
658        describe(ast, target)
659    }
660
661    /// The expressions a `GROUP BY` clause names, with positions and output aliases followed.
662    fn group_items(
663        &self,
664        ast: &Ast,
665        select: &ast::Select,
666        targets: &[ast::Target],
667    ) -> Result<Vec<ast::ExprRef>> {
668        if select.group_by_all {
669            // GROUP BY ALL means every target that is not itself an aggregate, which is the set
670            // that would otherwise have to be written out again by hand.
671            return Ok(targets
672                .iter()
673                .filter(|target| !has_aggregate(ast, target.expr))
674                .map(|target| target.expr)
675                .collect());
676        }
677        let mut items = Vec::new();
678        for &item in ast.expr_list(select.group_by) {
679            items.push(self.output_reference(ast, item, targets, "GROUP BY")?.unwrap_or(item));
680        }
681        Ok(items)
682    }
683
684    /// The target a `GROUP BY` or `ORDER BY` term names, when it names one by position or alias.
685    fn output_reference(
686        &self,
687        ast: &Ast,
688        item: ast::ExprRef,
689        targets: &[ast::Target],
690        clause: &str,
691    ) -> Result<Option<ast::ExprRef>> {
692        match ast.expr(item) {
693            ast::Expr::Literal { kind: LiteralKind::Number, text } => {
694                let written = ast.string(text);
695                let position: usize = written.parse().map_err(|_| {
696                    Error::binder(format!("{clause} term {written} is not a column"))
697                })?;
698                if position == 0 || position > targets.len() {
699                    return Err(Error::binder(format!(
700                        "{clause} term out of range - should be between 1 and {}",
701                        targets.len()
702                    )));
703                }
704                Ok(Some(targets[position - 1].expr))
705            }
706            ast::Expr::Column { name } => {
707                let parts: Vec<&str> = ast.name(name).collect();
708                let [written] = parts.as_slice() else { return Ok(None) };
709                let mut found = None;
710                for target in targets {
711                    if target.alias != NONE && same_name(ast.string(target.alias), written) {
712                        if found.is_some() {
713                            return Ok(None);
714                        }
715                        found = Some(target.expr);
716                    }
717                }
718                Ok(found)
719            }
720            _ => Ok(None),
721        }
722    }
723
724    // -------------------------------------------------------------- modifiers
725
726    /// Sort keys for a select, projecting anything sorted on that is not already selected.
727    #[allow(clippy::too_many_arguments)]
728    fn select_sort_keys(
729        &mut self,
730        ast: &Ast,
731        query: &ast::Query,
732        input: &Scope,
733        output: &Scope,
734        project: u32,
735        exprs: &mut Vec<ExprRef>,
736        names: &mut Vec<String>,
737        extra: &mut Vec<usize>,
738    ) -> Result<Vec<SortKey>> {
739        if query.order_by_all {
740            return Ok(self.every_column(output));
741        }
742        let items = ast.order_list(query.order_by).to_vec();
743        let mut keys = Vec::with_capacity(items.len());
744        for item in items {
745            let position = match self.output_position(ast, item.expr, output)? {
746                Some(position) => position,
747                None => {
748                    let bound = self.bind_expr(ast, item.expr, input)?;
749                    let bound = self.over_aggregate(bound, input)?;
750                    match exprs.iter().position(|&held| self.same_expr(held, bound)) {
751                        Some(position) => position,
752                        None => {
753                            exprs.push(bound);
754                            names.push(describe(ast, item.expr));
755                            extra.push(exprs.len() - 1);
756                            exprs.len() - 1
757                        }
758                    }
759                }
760            };
761            let ty = self.plan.expr_type(exprs[position]).clone();
762            let expr = self.column(project, position, ty);
763            keys.push(sort_key(expr, item));
764        }
765        Ok(keys)
766    }
767
768    /// Sort keys over an output that has nothing behind it to project, which is a set operation.
769    fn sort_keys(
770        &mut self,
771        ast: &Ast,
772        query: &ast::Query,
773        output: &Scope,
774        targets: &[ast::Target],
775    ) -> Result<Vec<SortKey>> {
776        if query.order_by_all {
777            return Ok(self.every_column(output));
778        }
779        let items = ast.order_list(query.order_by).to_vec();
780        let mut keys = Vec::with_capacity(items.len());
781        for item in items {
782            let expr = match self.output_position(ast, item.expr, output)? {
783                Some(position) => {
784                    let column = &output.columns[position];
785                    let (binding, ty) = (column.binding, column.ty.clone());
786                    self.plan.add_expr(Expr::Column(binding), ty)
787                }
788                None => {
789                    let _ = targets;
790                    self.bind_expr(ast, item.expr, output)?
791                }
792            };
793            keys.push(sort_key(expr, item));
794        }
795        Ok(keys)
796    }
797
798    fn every_column(&mut self, output: &Scope) -> Vec<SortKey> {
799        let columns: Vec<(ColumnBinding, LogicalType)> =
800            output.columns.iter().map(|column| (column.binding, column.ty.clone())).collect();
801        columns
802            .into_iter()
803            .map(|(binding, ty)| {
804                let expr = self.plan.add_expr(Expr::Column(binding), ty);
805                SortKey { expr, descending: false, nulls_first: false }
806            })
807            .collect()
808    }
809
810    /// Which output column a term names, by position or by name.
811    fn output_position(
812        &self,
813        ast: &Ast,
814        item: ast::ExprRef,
815        output: &Scope,
816    ) -> Result<Option<usize>> {
817        match ast.expr(item) {
818            ast::Expr::Literal { kind: LiteralKind::Number, text } => {
819                let written = ast.string(text);
820                if written.contains(['.', 'e', 'E']) {
821                    return Ok(None);
822                }
823                let position: usize = written.parse().map_err(|_| {
824                    Error::binder(format!("ORDER BY term {written} is not a column"))
825                })?;
826                if position == 0 || position > output.len() {
827                    return Err(Error::binder(format!(
828                        "ORDER BY term out of range - should be between 1 and {}",
829                        output.len()
830                    )));
831                }
832                Ok(Some(position - 1))
833            }
834            ast::Expr::Column { name } => {
835                let parts: Vec<&str> = ast.name(name).collect();
836                let [written] = parts.as_slice() else { return Ok(None) };
837                Ok(output.position_of(None, written))
838            }
839            _ => Ok(None),
840        }
841    }
842
843    /// The expressions a `DISTINCT ON` names, which have to be columns of the output.
844    fn distinct_on(
845        &mut self,
846        ast: &Ast,
847        distinct: Distinct,
848        output: &Scope,
849    ) -> Result<Vec<ExprRef>> {
850        let Distinct::On(items) = distinct else {
851            return Ok(Vec::new());
852        };
853        let items = ast.expr_list(items).to_vec();
854        let mut on = Vec::with_capacity(items.len());
855        for item in items {
856            let Some(position) = self.output_position(ast, item, output)? else {
857                return Err(Error::not_implemented(
858                    "DISTINCT ON an expression that is not in the select list",
859                ));
860            };
861            let column = &output.columns[position];
862            let (binding, ty) = (column.binding, column.ty.clone());
863            on.push(self.plan.add_expr(Expr::Column(binding), ty));
864        }
865        Ok(on)
866    }
867
868    fn apply_limit(&mut self, ast: &Ast, query: &ast::Query, input: NodeRef) -> Result<NodeRef> {
869        if query.limit_percent {
870            return Err(Error::not_implemented("LIMIT with a percentage"));
871        }
872        let count = self.constant_count(ast, query.limit, "LIMIT")?;
873        let offset = self.constant_count(ast, query.offset, "OFFSET")?.unwrap_or(0);
874        if count.is_none() && offset == 0 {
875            return Ok(input);
876        }
877        Ok(self.plan.add_node(Node::Limit { input, count, offset }))
878    }
879
880    /// The row count a `LIMIT` or an `OFFSET` names, which has to be a constant.
881    fn constant_count(
882        &mut self,
883        ast: &Ast,
884        written: ast::ExprRef,
885        clause: &str,
886    ) -> Result<Option<u64>> {
887        if written == NONE {
888            return Ok(None);
889        }
890        self.clause = "LIMIT clause";
891        let scope = Scope::empty();
892        let bound = self.bind_expr(ast, written, &scope)?;
893        let Expr::Constant(value) = *self.plan.expr(bound) else {
894            return Err(Error::not_implemented(format!("a {clause} that is not a constant")));
895        };
896        let count = match self.plan.value(value) {
897            Value::Null => return Ok(None),
898            Value::TinyInt(count) => i128::from(*count),
899            Value::SmallInt(count) => i128::from(*count),
900            Value::Integer(count) => i128::from(*count),
901            Value::BigInt(count) => i128::from(*count),
902            Value::HugeInt(count) => *count,
903            other => {
904                return Err(Error::binder(format!(
905                    "{clause} takes a whole number of rows, not a value of type {}",
906                    other.logical_type()
907                )));
908            }
909        };
910        u64::try_from(count)
911            .map(Some)
912            .map_err(|_| Error::binder(format!("{clause} must not be negative")))
913    }
914
915    // ------------------------------------------------------------------- from
916
917    fn bind_from(&mut self, ast: &Ast, from: ast::Slice) -> Result<(NodeRef, Scope)> {
918        let sources = ast.source_list(from).to_vec();
919        let Some((first, rest)) = sources.split_first() else {
920            // No FROM clause is one row of no columns, which is what SELECT 1 sits on. Not an
921            // empty table: an empty table would make SELECT 1 return nothing.
922            return Ok((self.plan.add_node(Node::Dummy), Scope::empty()));
923        };
924        let (mut node, mut scope) = self.bind_source(ast, *first)?;
925        for source in rest {
926            let (right, right_scope) = self.bind_source(ast, *source)?;
927            node = self.plan.add_node(Node::CrossProduct { left: node, right });
928            scope = scope.concat(right_scope);
929        }
930        Ok((node, scope))
931    }
932
933    fn bind_source(&mut self, ast: &Ast, source: ast::SourceRef) -> Result<(NodeRef, Scope)> {
934        match ast.source(source) {
935            ast::Source::Table { name, alias, columns } => {
936                self.bind_table(ast, name, alias, columns)
937            }
938            ast::Source::Function { name, args, alias, columns } => {
939                self.bind_table_function(ast, name, args, alias, columns)
940            }
941            ast::Source::Subquery { query, alias, columns } => {
942                let (node, mut scope) = self.bind_query(ast, query)?;
943                let label = if alias == NONE {
944                    "unnamed_subquery".to_string()
945                } else {
946                    ast.string(alias).to_string()
947                };
948                scope.relabel(&label);
949                if !columns.is_empty() {
950                    let names: Vec<&str> = ast.name(columns).collect();
951                    scope.rename(&names, &label)?;
952                }
953                Ok((node, scope))
954            }
955            ast::Source::Values { rows, alias, columns } => {
956                let bare = ast::Query::bare(ast::QueryBody::Values(rows));
957                let (node, mut scope) = self.bind_values(ast, &bare, rows)?;
958                let label =
959                    if alias == NONE { String::new() } else { ast.string(alias).to_string() };
960                scope.relabel(&label);
961                if !columns.is_empty() {
962                    let names: Vec<&str> = ast.name(columns).collect();
963                    scope.rename(&names, &label)?;
964                }
965                Ok((node, scope))
966            }
967            ast::Source::Join { left, right, kind, natural, on, using } => {
968                self.bind_join(ast, left, right, kind, natural, on, using)
969            }
970        }
971    }
972
973    fn bind_table(
974        &mut self,
975        ast: &Ast,
976        name: ast::Slice,
977        alias: ast::StrRef,
978        columns: ast::Slice,
979    ) -> Result<(NodeRef, Scope)> {
980        let parts: Vec<&str> = ast.name(name).collect();
981        let catalog = self.catalog;
982        // The catalog is asked first and the file is the fallback, which is the order DuckDB uses:
983        // a table really called `mixed.parquet` wins over a file of that name sitting next to it.
984        let resolved = match catalog.resolve(&parts) {
985            Ok(resolved) => resolved,
986            Err(missing) => {
987                return self.bind_replacement_scan(ast, &parts, alias, columns, missing);
988            }
989        };
990        if catalog.entry(&resolved)? == Entry::View {
991            return self.bind_view(ast, &resolved, alias, columns);
992        }
993        let table = catalog.table(&resolved)?;
994        let fields: Vec<Field> = table.columns().to_vec();
995        let label =
996            if alias == NONE { resolved.table.clone() } else { ast.string(alias).to_string() };
997        let index = self.fresh_index();
998        let mut scope = Scope::empty();
999        for (at, field) in fields.iter().enumerate() {
1000            scope.push(Visible {
1001                table: label.clone(),
1002                name: field.name.clone(),
1003                binding: ColumnBinding::new(index, at as u32),
1004                ty: field.ty.clone(),
1005                not_null: field.not_null,
1006            });
1007        }
1008        if !columns.is_empty() {
1009            let names: Vec<&str> = ast.name(columns).collect();
1010            scope.rename(&names, &label)?;
1011        }
1012        let catalog_name = self.plan.intern(&resolved.catalog);
1013        let schema = self.plan.intern(&resolved.schema);
1014        let table_name = self.plan.intern(&resolved.table);
1015        let alias = self.plan.intern(&label);
1016        let columns = self.plan.add_fields(&fields);
1017        let node = self.plan.add_node(Node::Get {
1018            catalog: catalog_name,
1019            schema,
1020            table: table_name,
1021            alias,
1022            index,
1023            columns,
1024        });
1025        Ok((node, scope))
1026    }
1027
1028    /// A view where a table goes, which is the body bound again right here.
1029    ///
1030    /// Inline and not behind a node. The view is gone by the time the plan exists, so everything
1031    /// downstream sees the query somebody would have written by hand, and the column pruning that
1032    /// makes `SELECT COUNT(*) FROM 'hits.parquet'` read no columns at all keeps working through
1033    /// `FROM hits`. A `Node::View` would be a barrier with nothing on the other side of it.
1034    ///
1035    /// The scope this builds is a subquery's, right down to the name in the error message. duckdb
1036    /// v1.5.1 reports a view whose column list has gone stale as `table "unnamed_subquery" has 1
1037    /// columns available but 2 columns specified`, which is the sentence its subquery alias rule
1038    /// produces, so a view there is a subquery with the view's name written over it afterwards.
1039    fn bind_view(
1040        &mut self,
1041        ast: &Ast,
1042        name: &QualifiedName,
1043        alias: ast::StrRef,
1044        columns: ast::Slice,
1045    ) -> Result<(NodeRef, Scope)> {
1046        let view = self.catalog.view(name)?;
1047        let full = name.to_string();
1048        if self.expanding.contains(&full) {
1049            // Two quotes each side, which is what the binary prints. It quotes the name on the way
1050            // in and then formats the quoted name into a quoted slot, so a view called `a` comes
1051            // back as `""a""`. That is upstream's wart and copying it is the whole job here.
1052            return Err(Error::binder(format!(
1053                "infinite recursion detected: attempting to recursively bind view \"\"{}\"\"",
1054                name.table
1055            )));
1056        }
1057        let body = parse_ast(view.sql())?;
1058        let query = match body.statements.as_slice() {
1059            [ast::Statement::Query(query)] => *query,
1060            // Only a query can have got past the binder at creation, so this is a view the catalog
1061            // was handed some other way rather than anything a statement can produce.
1062            _ => return Err(Error::binder(format!("view \"{}\" is not a query", name.table))),
1063        };
1064        self.expanding.push(full);
1065        let bound = self.bind_query(&body, query);
1066        self.expanding.pop();
1067        let (node, mut scope) = bound?;
1068
1069        let aliases: Vec<&str> = view.aliases().iter().map(String::as_str).collect();
1070        if !aliases.is_empty() {
1071            scope.rename(&aliases, "unnamed_subquery")?;
1072        }
1073        // What the catalog tables report as this view's columns, written down here because this is
1074        // the moment they are known. Upstream refreshes the same cache at the same point, which was
1075        // measured: both `duckdb_columns()` and `duckdb_views().column_count` keep reporting the old
1076        // list after an `ALTER TABLE` underneath until something reads the view, and then both move.
1077        // It is written before the label and before the `AS t(a, b)` list below, because those two
1078        // rename the view for one query and not for everyone.
1079        view.remember(scope.fields());
1080        let label = if alias == NONE { name.table.clone() } else { ast.string(alias).to_string() };
1081        scope.relabel(&label);
1082        if !columns.is_empty() {
1083            let names: Vec<&str> = ast.name(columns).collect();
1084            scope.rename(&names, &label)?;
1085        }
1086        Ok((node, scope))
1087    }
1088
1089    /// A function call where a table goes, such as `range(10)`.
1090    ///
1091    /// The arguments are bound against an empty scope. A table function that can see the row on its
1092    /// left is `LATERAL`, and this is not it, so a column name in here is not resolved against
1093    /// whatever happens to be to the left in the `FROM` list. Letting it would mean `FROM t,
1094    /// range(t.n)` quietly binding to something whose meaning depends on the order the sources were
1095    /// written in.
1096    fn bind_table_function(
1097        &mut self,
1098        ast: &Ast,
1099        name: ast::Slice,
1100        args: ast::Slice,
1101        alias: ast::StrRef,
1102        columns: ast::Slice,
1103    ) -> Result<(NodeRef, Scope)> {
1104        let parts: Vec<&str> = ast.name(name).collect();
1105        // A qualified call names a schema, and the two schemas that exist are the ones every
1106        // built-in lives in. Anything else is a name that has to fail rather than fall through to
1107        // the unqualified lookup and be found somewhere it was not asked for.
1108        let function_name = *parts.last().unwrap_or(&"");
1109        if let Some(schema) = parts.iter().rev().nth(1) {
1110            if !schema.eq_ignore_ascii_case("main") && !schema.eq_ignore_ascii_case("system") {
1111                return Err(Error::catalog(format!(
1112                    "Table Function with name {} does not exist!",
1113                    parts.join(".")
1114                )));
1115            }
1116        }
1117        // The name is looked up before the arguments are bound so that a call of something that is
1118        // not a table function says that, rather than reporting whatever is wrong with the
1119        // arguments of a function that was never going to exist.
1120        let Some(called) = TableFunction::lookup(function_name) else {
1121            return Err(Error::catalog(format!(
1122                "Table Function with name {function_name} does not exist!"
1123            )));
1124        };
1125        let written = ast.target_list(args).to_vec();
1126        let empty = Scope::empty();
1127        let previous = std::mem::replace(&mut self.clause, "table function arguments");
1128        let mut bound = Vec::new();
1129        let mut written_options = Vec::new();
1130        for argument in written {
1131            let expr = self.bind_expr(ast, argument.expr, &empty)?;
1132            if argument.alias == NONE {
1133                bound.push(expr);
1134            } else {
1135                let name = ast.string(argument.alias).to_string();
1136                let (parameter, value) = self.named_argument(called, &name, expr)?;
1137                written_options.push((parameter, value, expr));
1138            }
1139        }
1140        self.clause = previous;
1141        let options = Options::of(&written_options)?;
1142
1143        // The types are what resolve the call, not the count, because `read_parquet(3)` is a
1144        // different answer from `read_parquet('3')` and only the types tell them apart.
1145        let given: Vec<LogicalType> =
1146            bound.iter().map(|&expr| self.plan.expr_type(expr).clone()).collect();
1147        let resolved = resolve_table(function_name, &given)?;
1148        let mut cast: Vec<ExprRef> = bound
1149            .iter()
1150            .zip(&resolved.arguments)
1151            .map(|(&expr, ty)| self.cast_to(expr, ty))
1152            .collect();
1153
1154        if resolved.function.takes_a_name() {
1155            let Columns::Fixed(fields) = resolved.columns else {
1156                return Err(Error::internal("a pragma that resolved to a file"));
1157            };
1158            let [argument] = cast[..] else {
1159                return Err(Error::internal("a pragma that resolved to more than one name"));
1160            };
1161            return self.bind_pragma(ast, resolved.function, &fields, argument, alias, columns);
1162        }
1163        let fields = match resolved.columns {
1164            Columns::Fixed(fields) => fields,
1165            columns => {
1166                // The one argument is a pattern, and what replaces it is one constant per file it
1167                // matched. The executor is handed names rather than a pattern, so it never walks a
1168                // directory and the answer cannot change between binding a prepared statement and
1169                // running it, which is the same reason the schema is settled here.
1170                let paths = self.file_paths(cast[0], resolved.function.name())?;
1171                let first = paths.first().map_or("", String::as_str);
1172                let mut fields = match columns {
1173                    // Parquet takes the first file's footer as the answer and CSV sniffs all of
1174                    // them, which is not a choice made here. See `csv_fields`.
1175                    Columns::Csv => csv_fields(&paths, options.given)?,
1176                    _ => parquet_fields(first)?,
1177                };
1178                if options.all_varchar {
1179                    // The sniffer still ran, because the names come out of the same pass over the
1180                    // front of the file and only the types are being overruled. The executor reads
1181                    // the text as VARCHAR because this is the schema it is told to read into, which
1182                    // is the same road a file in a glob takes when the set is wider than the file.
1183                    for field in &mut fields {
1184                        field.ty = LogicalType::Varchar;
1185                    }
1186                }
1187                if options.binary_as_string {
1188                    // A byte array column with no annotation on it is a BLOB, and this is the caller
1189                    // saying that the file's writer meant text. The reader already holds both in the
1190                    // same string column and already validates the bytes, so the whole of the option
1191                    // is what the column is called from here on.
1192                    for field in &mut fields {
1193                        if field.ty == LogicalType::Blob {
1194                            field.ty = LogicalType::Varchar;
1195                        }
1196                    }
1197                }
1198                if options.file_row_number {
1199                    // Not a column of the file, so it goes on the end where a projection cannot be
1200                    // confused about which one it is, and the executor counts it as the rows come
1201                    // out. A file that already has a column of that name is the one case where the
1202                    // option cannot be honoured, and saying so is better than handing back two
1203                    // columns with the same name and letting a reference to it pick one.
1204                    if fields.iter().any(|field| field.name == FILE_ROW_NUMBER) {
1205                        return Err(Error::binder(format!(
1206                            "Duplicate column name \"{FILE_ROW_NUMBER}\": the file already has a \
1207                             column of that name, so file_row_number cannot add one"
1208                        )));
1209                    }
1210                    fields.push(Field::required(FILE_ROW_NUMBER.to_string(), LogicalType::BigInt));
1211                }
1212                cast = paths.iter().map(|path| self.path_constant(path)).collect();
1213                fields
1214            }
1215        };
1216        let label = if alias == NONE {
1217            resolved.function.name().to_string()
1218        } else {
1219            ast.string(alias).to_string()
1220        };
1221        let names: Vec<&str> = ast.name(columns).collect();
1222        self.table_function_source(
1223            resolved.function,
1224            &cast,
1225            &written_options,
1226            fields,
1227            &label,
1228            &names,
1229        )
1230    }
1231
1232    /// `pragma_table_info('t')` or `pragma_show('t')`, answered while it is bound.
1233    ///
1234    /// The same trick `DESCRIBE` uses and for the same reason: the columns of a table are settled by
1235    /// the time the name has resolved, so the rows are a constant from there on and this comes out
1236    /// as a `VALUES` rather than as an operator that reads a catalog while the query runs. It also
1237    /// means `SELECT name FROM pragma_table_info('t') WHERE notnull` is an ordinary query over an
1238    /// ordinary relation, which is the whole reason these exist as functions rather than only as
1239    /// statements.
1240    ///
1241    /// The name arrives as a string rather than as something the parser read, so it is split here
1242    /// under the identifier rule and then resolved like any other name. A name that is not there
1243    /// comes back as the catalog's own complaint, which is what the pin answers with too.
1244    fn bind_pragma(
1245        &mut self,
1246        ast: &Ast,
1247        function: TableFunction,
1248        fields: &[Field],
1249        argument: ExprRef,
1250        alias: ast::StrRef,
1251        columns: ast::Slice,
1252    ) -> Result<(NodeRef, Scope)> {
1253        let written = self.pragma_name(argument, function)?;
1254        let parts = identifier_parts(&written);
1255        let spelled: Vec<&str> = parts.iter().map(String::as_str).collect();
1256        let name = self.catalog.resolve(&spelled)?;
1257        let described = self.described(ast, &name)?;
1258        let mut rows = Vec::with_capacity(described.len());
1259        for (at, field) in described.iter().enumerate() {
1260            let items = if matches!(function, TableFunction::PragmaShow) {
1261                self.describing(field)
1262            } else {
1263                self.table_info(at, field)
1264            };
1265            rows.push(self.plan.add_expr_list(&items));
1266        }
1267        let rows = self.plan.add_rows(&rows);
1268        let held = self.plan.add_fields(fields);
1269        let index = self.fresh_index();
1270        let node = self.plan.add_node(Node::Values { index, columns: held, rows });
1271        let label =
1272            if alias == NONE { function.name().to_string() } else { ast.string(alias).to_string() };
1273        let mut scope = Scope::empty();
1274        for (at, field) in fields.iter().enumerate() {
1275            scope.push(Visible {
1276                table: label.clone(),
1277                name: field.name.clone(),
1278                binding: ColumnBinding::new(index, at as u32),
1279                ty: field.ty.clone(),
1280                not_null: false,
1281            });
1282        }
1283        if !columns.is_empty() {
1284            let names: Vec<&str> = ast.name(columns).collect();
1285            scope.rename(&names, &label)?;
1286        }
1287        Ok((node, scope))
1288    }
1289
1290    /// The name a pragma was called with, which has to be a constant.
1291    ///
1292    /// A null is a name spelled `NULL` rather than an error about nulls, because the pin turns
1293    /// whatever it was handed into text before it goes looking and then says a table of that name
1294    /// does not exist. Writing `pragma_table_info(NULL)` is a mistake either way and this is the
1295    /// sentence the mistake already has.
1296    ///
1297    /// `pragma_table_info('t' || 'x')` is the pin's `tx` and is turned away here, which is the same
1298    /// missing constant folding [`Binder::named_argument`] writes about and closes the same day.
1299    fn pragma_name(&self, argument: ExprRef, function: TableFunction) -> Result<String> {
1300        let Expr::Constant(reference) = *self.plan.expr(argument) else {
1301            return Err(Error::not_implemented(format!(
1302                "{}() given a name that is not a constant",
1303                function.name()
1304            )));
1305        };
1306        match self.plan.value(reference) {
1307            Value::Varchar(name) => Ok(name.clone()),
1308            Value::Null => Ok("NULL".to_string()),
1309            other => {
1310                Err(Error::internal(format!("a pragma name bound as VARCHAR arrived as {other}")))
1311            }
1312        }
1313    }
1314
1315    /// The columns of whatever a pragma was pointed at.
1316    ///
1317    /// A view is bound here, which is how it comes to have columns at all. Reading a view is what
1318    /// binds it and describing one counts as reading it, so a view the engine ships with reports a
1319    /// column count from this point on, the same as it would after a select. The node that binding
1320    /// produces is thrown away, because the answer is the scope and not the query.
1321    ///
1322    /// Every column of a view is nullable whatever the column underneath was declared as, which is
1323    /// the pin's answer through `pragma_table_info()`, `pragma_show()` and `duckdb_columns()` alike.
1324    /// [`Scope::fields`] drops the flag on its own, so there is nothing to clear here.
1325    fn described(&mut self, ast: &Ast, name: &QualifiedName) -> Result<Vec<Field>> {
1326        if self.catalog.entry(name)? == Entry::Table {
1327            return Ok(self.catalog.table(name)?.columns().to_vec());
1328        }
1329        let (_, scope) = self.bind_view(ast, name, NONE, ast::Slice::default())?;
1330        Ok(scope.fields())
1331    }
1332
1333    /// One row of `pragma_show()`, which is one row of `DESCRIBE` written by the other caller.
1334    fn describing(&mut self, field: &Field) -> Vec<ExprRef> {
1335        let written = [
1336            field.name.clone(),
1337            field.ty.to_string(),
1338            if field.not_null { "NO" } else { "YES" }.to_owned(),
1339        ];
1340        let mut items: Vec<ExprRef> =
1341            written.into_iter().map(|text| self.plan.add_constant(Value::Varchar(text))).collect();
1342        for _ in 0..3 {
1343            let empty = self.plan.add_constant(Value::Null);
1344            items.push(self.cast_to(empty, &LogicalType::Varchar));
1345        }
1346        items
1347    }
1348
1349    /// One row of `pragma_table_info()`, which is SQLite's six columns about the same column.
1350    ///
1351    /// `cid` counts from zero, which is SQLite's numbering and not the one based `ordinal_position`
1352    /// the standard views report. `dflt_value` and `pk` are the two nothings rudb has to report
1353    /// until `CREATE TABLE` takes a `DEFAULT` or a key.
1354    fn table_info(&mut self, at: usize, field: &Field) -> Vec<ExprRef> {
1355        let cid = self.plan.add_constant(Value::Integer(i32::try_from(at).unwrap_or(i32::MAX)));
1356        let name = self.plan.add_constant(Value::Varchar(field.name.clone()));
1357        let ty = self.plan.add_constant(Value::Varchar(field.ty.to_string()));
1358        let not_null = self.plan.add_constant(Value::Boolean(field.not_null));
1359        let default = self.plan.add_constant(Value::Null);
1360        let default = self.cast_to(default, &LogicalType::Varchar);
1361        let key = self.plan.add_constant(Value::Boolean(false));
1362        vec![cid, name, ty, not_null, default, key]
1363    }
1364
1365    /// One named parameter of a table function call, folded into what the call was given.
1366    ///
1367    /// The value has to be a constant of the type the parameter wants. It has to be constant
1368    /// because an option can decide what the columns are and the columns are settled here, and it
1369    /// has to be already of the type because there is no constant folding in front of the binder
1370    /// yet. DuckDB folds first, so `binary_as_string=1` and `binary_as_string='yes'` are both true
1371    /// there and both are turned away here, which is a gap that closes on its own the day the
1372    /// optimizer runs before the plan is finished. `binary_as_string=True` is what the ClickBench
1373    /// entry writes and is what has to work.
1374    ///
1375    /// A name that is not a parameter of this function is the binary's sentence followed by what it
1376    /// could have been. The binary puts the candidates on their own indented lines and this puts
1377    /// them on the same line, because an error is one line here.
1378    fn named_argument(
1379        &mut self,
1380        function: TableFunction,
1381        name: &str,
1382        expr: ExprRef,
1383    ) -> Result<(&'static str, Value)> {
1384        let known = function
1385            .parameters()
1386            .iter()
1387            .find(|(parameter, _)| parameter.eq_ignore_ascii_case(name));
1388        let Some((parameter, wanted)) = known else {
1389            let candidates: Vec<String> = function
1390                .parameters()
1391                .iter()
1392                .map(|(parameter, ty)| format!("    {parameter} {ty}"))
1393                .collect();
1394            return Err(Error::binder(format!(
1395                "Invalid named parameter \"{name}\" for function {}\nCandidates:\n{}\n",
1396                function.name(),
1397                candidates.join("\n")
1398            )));
1399        };
1400        let Expr::Constant(reference) = *self.plan.expr(expr) else {
1401            return Err(Error::not_implemented(format!(
1402                "the named parameter {parameter} with a value that is not a constant"
1403            )));
1404        };
1405        let value = self.plan.value(reference).clone();
1406        if value == Value::Null {
1407            return Err(Error::binder(null_parameter(function, parameter)));
1408        }
1409        let given = self.plan.expr_type(expr).clone();
1410        if given != *wanted {
1411            return Err(Error::not_implemented(format!(
1412                "the named parameter {parameter} given a {given} where a {wanted} was wanted"
1413            )));
1414        }
1415        Ok((parameter, value))
1416    }
1417
1418    /// A file where a table name goes, which is what DuckDB calls a replacement scan.
1419    ///
1420    /// `SELECT * FROM 'hits.parquet'` is how most DuckDB queries in the wild are written, ClickBench
1421    /// among them, so this is not sugar over `read_parquet` so much as the spelling people use. The
1422    /// catalog has already been asked and has already said no, and `missing` is what it said, so a
1423    /// name that is not a file comes back with the catalog's own answer rather than with a complaint
1424    /// about files.
1425    ///
1426    /// Only a single unqualified name is a candidate. A qualified one names a schema and a schema
1427    /// that does not exist is not a path.
1428    fn bind_replacement_scan(
1429        &mut self,
1430        ast: &Ast,
1431        parts: &[&str],
1432        alias: ast::StrRef,
1433        columns: ast::Slice,
1434        missing: Error,
1435    ) -> Result<(NodeRef, Scope)> {
1436        let [path] = parts else { return Err(missing) };
1437        let path = *path;
1438        let extension = path.rsplit_once('.').map(|(_, after)| after).unwrap_or_default();
1439        let Some(function) = Self::reader_for(extension) else {
1440            if is_file(path) {
1441                // A file that is really there and that nothing here can read is a different mistake
1442                // from a name that is not a file, and DuckDB says so with both lines, the second of
1443                // which is the way out. A file with no dot in it lands here too, which is why the
1444                // test is on the extension having a reader rather than on there being an extension.
1445                return Err(Error::binder(format!(
1446                    "No extension found that is capable of reading the file \"{path}\"\n* If this \
1447                     file is a supported file format you can explicitly use the reader functions, \
1448                     such as read_csv, read_json or read_parquet"
1449                )));
1450            }
1451            return Err(missing);
1452        };
1453        // The pattern is expanded before it is known to match anything, so a name that ends in .csv
1454        // and is not there gives the reader's own message rather than the catalog's. That is
1455        // DuckDB's order and it is the helpful one: somebody who wrote a file name wants to hear
1456        // about the file.
1457        let paths = files(path)?;
1458        let first = paths.first().map_or("", String::as_str);
1459        let fields = match function {
1460            TableFunction::ReadParquet => parquet_fields(first)?,
1461            _ => csv_fields(&paths, Given::default())?,
1462        };
1463        // The name the columns answer to is the file's stem, so `SELECT mixed.a FROM
1464        // 'data/mixed.parquet'` works. That is DuckDB's choice and it is the useful one, since the
1465        // alternative is a table name with a dot and a slash in it that nothing can write. A pattern
1466        // keeps the whole of what was written instead, which is DuckDB's choice too and was
1467        // measured: there is no stem to take when the name stands for a directory full of files.
1468        let label = if alias == NONE {
1469            if is_pattern(path) {
1470                path.to_string()
1471            } else {
1472                let file = path.rsplit_once('/').map_or(path, |(_, file)| file);
1473                file.rsplit_once('.').map_or(file, |(stem, _)| stem).to_string()
1474            }
1475        } else {
1476            ast.string(alias).to_string()
1477        };
1478        let arguments: Vec<ExprRef> = paths.iter().map(|path| self.path_constant(path)).collect();
1479        let names: Vec<&str> = ast.name(columns).collect();
1480        self.table_function_source(function, &arguments, &[], fields, &label, &names)
1481    }
1482
1483    /// One file name, as a constant expression in the plan.
1484    fn path_constant(&mut self, path: &str) -> ExprRef {
1485        let value = self.plan.add_value(Value::Varchar(path.to_string()));
1486        self.plan.add_expr(Expr::Constant(value), LogicalType::Varchar)
1487    }
1488
1489    /// The table function a file with this extension is read by, and `None` for one nothing reads.
1490    ///
1491    /// Both spellings of a tab separated file go to the CSV reader, which is not a shortcut: the
1492    /// extension picks the reader and the reader sniffs the punctuation, so a `.tsv` file that holds
1493    /// commas is read as commas. That was measured rather than assumed. The comparison ignores case
1494    /// because `UP.CSV` reads in duckdb v1.4.1.
1495    fn reader_for(extension: &str) -> Option<TableFunction> {
1496        if extension.eq_ignore_ascii_case("parquet") {
1497            return Some(TableFunction::ReadParquet);
1498        }
1499        if extension.eq_ignore_ascii_case("csv") || extension.eq_ignore_ascii_case("tsv") {
1500            return Some(TableFunction::ReadCsv);
1501        }
1502        None
1503    }
1504
1505    /// The node and the scope of a table function call whose arguments and columns are settled.
1506    ///
1507    /// The half a written out call shares with a replacement scan, which is everything after the
1508    /// question of what the file is called has been answered one way or the other.
1509    fn table_function_source(
1510        &mut self,
1511        function: TableFunction,
1512        args: &[ExprRef],
1513        written: &[(&'static str, Value, ExprRef)],
1514        fields: Vec<Field>,
1515        label: &str,
1516        names: &[&str],
1517    ) -> Result<(NodeRef, Scope)> {
1518        let index = self.fresh_index();
1519        let mut scope = Scope::empty();
1520        for (at, field) in fields.iter().enumerate() {
1521            scope.push(Visible {
1522                table: label.to_string(),
1523                name: field.name.clone(),
1524                binding: ColumnBinding::new(index, at as u32),
1525                ty: field.ty.clone(),
1526                // A reader takes what the file has, and no file format this reads says a column
1527                // cannot be null. The reference binary answers YES for every column of a Parquet.
1528                not_null: false,
1529            });
1530        }
1531        if !names.is_empty() {
1532            scope.rename(names, label)?;
1533        }
1534        let function = self.plan.intern(function.name());
1535        let args = self.plan.add_expr_list(args);
1536        let named: Vec<u32> =
1537            written.iter().map(|(parameter, _, _)| self.plan.intern(parameter)).collect();
1538        let settings: Vec<ExprRef> = written.iter().map(|(_, _, expr)| *expr).collect();
1539        let options = self.plan.add_name_list(&named);
1540        let settings = self.plan.add_expr_list(&settings);
1541        let columns = self.plan.add_fields(&fields);
1542        let node = self.plan.add_node(Node::TableFunction {
1543            index,
1544            function,
1545            args,
1546            options,
1547            settings,
1548            columns,
1549        });
1550        Ok((node, scope))
1551    }
1552
1553    /// Every file a table function's file argument names, in the order they were written.
1554    ///
1555    /// Each pattern has to find at least one file of its own, which is DuckDB's rule and is why
1556    /// this expands one at a time rather than gathering everything and looking at the total. A
1557    /// list keeps its written order and its duplicates, so a file named twice is read twice, which
1558    /// was measured: the sort and the dedup belong to one pattern rather than to the list.
1559    fn file_paths(&self, expr: ExprRef, name: &str) -> Result<Vec<String>> {
1560        let mut paths = Vec::new();
1561        for pattern in self.file_patterns(expr, name)? {
1562            paths.extend(files(&pattern)?);
1563        }
1564        Ok(paths)
1565    }
1566
1567    /// The patterns a table function argument names, which have to be constants.
1568    ///
1569    /// A table function that reads a file is resolved by opening the file, and that happens here
1570    /// rather than when the query runs, because the rest of the statement cannot bind until the
1571    /// column names are known. So the path has to be something this binder can work out without
1572    /// running anything, and a literal is that. DuckDB folds a constant expression first, so
1573    /// `read_parquet('a' || '.parquet')` works there, and folding is M1 work that this will pick up
1574    /// for free once the optimizer runs before the plan is finished rather than after.
1575    ///
1576    /// One string is one pattern and a list is one pattern an item, which is DuckDB's pair of
1577    /// overloads. A null is a different sentence in each of them, both of them measured.
1578    fn file_patterns(&self, expr: ExprRef, name: &str) -> Result<Vec<String>> {
1579        let Expr::Constant(reference) = *self.plan.expr(expr) else {
1580            return Err(Error::not_implemented(
1581                "a table function file name that is not a constant",
1582            ));
1583        };
1584        match self.plan.value(reference) {
1585            Value::Varchar(path) => Ok(vec![path.clone()]),
1586            // DuckDB's own wording, which says list because its other overload takes one.
1587            Value::Null => Err(Error::parser(format!("{name} cannot take NULL list as parameter"))),
1588            Value::List { values, .. } => values
1589                .iter()
1590                .map(|value| match value {
1591                    Value::Varchar(path) => Ok(path.clone()),
1592                    _ => Err(Error::parser(format!(
1593                        "{name} reader cannot take NULL input as parameter"
1594                    ))),
1595                })
1596                .collect(),
1597            other => {
1598                Err(Error::internal(format!("a file name bound as VARCHAR arrived as {other}")))
1599            }
1600        }
1601    }
1602
1603    #[allow(clippy::too_many_arguments)]
1604    fn bind_join(
1605        &mut self,
1606        ast: &Ast,
1607        left: ast::SourceRef,
1608        right: ast::SourceRef,
1609        kind: ast::JoinKind,
1610        natural: bool,
1611        on: ast::ExprRef,
1612        using: ast::Slice,
1613    ) -> Result<(NodeRef, Scope)> {
1614        let (left_node, left_scope) = self.bind_source(ast, left)?;
1615        let (right_node, right_scope) = self.bind_source(ast, right)?;
1616        let split = left_scope.len();
1617        let mut scope = left_scope.concat(right_scope);
1618
1619        // NATURAL is USING over whatever both sides happen to call the same thing, which is why it
1620        // is resolved here and never reaches the plan as its own idea.
1621        let merged: Vec<String> = if natural {
1622            let mut names = Vec::new();
1623            for (at, column) in scope.columns.iter().enumerate().take(split) {
1624                if scope.columns[split..].iter().any(|right| same_name(&right.name, &column.name))
1625                    && !names.iter().any(|held: &String| same_name(held, &column.name))
1626                {
1627                    let _ = at;
1628                    names.push(column.name.clone());
1629                }
1630            }
1631            names
1632        } else {
1633            // A name written twice is one column, not two. `USING (id, id)` is legal and means what
1634            // `USING (id)` means, and the reference binary agrees. Taking it twice would build the
1635            // same equality twice and, worse, drop the right side's copy twice, which takes a
1636            // column out of the answer that nobody named and runs off the end of the scope when the
1637            // copy was the last column in it.
1638            let mut names: Vec<String> = Vec::new();
1639            for name in ast.name(using) {
1640                if !names.iter().any(|held| same_name(held, name)) {
1641                    names.push(name.to_string());
1642                }
1643            }
1644            names
1645        };
1646
1647        let mut conditions = Vec::new();
1648        let mut dropped = Vec::new();
1649        for name in &merged {
1650            let left_at = scope.columns[..split]
1651                .iter()
1652                .position(|column| same_name(&column.name, name))
1653                .ok_or_else(|| {
1654                    Error::binder(format!(
1655                        "column \"{name}\" specified in USING clause does not exist in left table"
1656                    ))
1657                })?;
1658            let right_at = scope.columns[split..]
1659                .iter()
1660                .position(|column| same_name(&column.name, name))
1661                .map(|at| at + split)
1662                .ok_or_else(|| {
1663                    Error::binder(format!(
1664                        "column \"{name}\" specified in USING clause does not exist in right table"
1665                    ))
1666                })?;
1667            let left_column = &scope.columns[left_at];
1668            let (left_binding, left_type) = (left_column.binding, left_column.ty.clone());
1669            let right_column = &scope.columns[right_at];
1670            let (right_binding, right_type) = (right_column.binding, right_column.ty.clone());
1671            let left_expr = self.plan.add_expr(Expr::Column(left_binding), left_type);
1672            let right_expr = self.plan.add_expr(Expr::Column(right_binding), right_type);
1673            conditions.push(self.compare(rudb_plan::CompareOp::Equal, left_expr, right_expr)?);
1674            dropped.push(right_at);
1675        }
1676        // A joined-on column appears once, so the right side's copy goes. Dropping from the back
1677        // keeps the positions of the ones still to drop correct.
1678        dropped.sort_unstable();
1679        for at in dropped.into_iter().rev() {
1680            scope.remove(at);
1681        }
1682
1683        if on != NONE {
1684            if !merged.is_empty() {
1685                return Err(Error::binder("a join cannot have both ON and USING"));
1686            }
1687            self.clause = "JOIN condition";
1688            let predicate = self.bind_expr(ast, on, &scope)?;
1689            conditions.push(self.as_boolean(predicate, "JOIN")?);
1690        }
1691
1692        if kind == ast::JoinKind::Cross {
1693            if !conditions.is_empty() {
1694                return Err(Error::binder("a CROSS JOIN cannot have a condition"));
1695            }
1696            let node =
1697                self.plan.add_node(Node::CrossProduct { left: left_node, right: right_node });
1698            return Ok((node, scope));
1699        }
1700        if conditions.is_empty() && kind == ast::JoinKind::Inner {
1701            let node =
1702                self.plan.add_node(Node::CrossProduct { left: left_node, right: right_node });
1703            return Ok((node, scope));
1704        }
1705        let kind = match kind {
1706            ast::JoinKind::Inner | ast::JoinKind::Cross => JoinKind::Inner,
1707            ast::JoinKind::Left => JoinKind::Left,
1708            ast::JoinKind::Right => JoinKind::Right,
1709            ast::JoinKind::Full => JoinKind::Full,
1710            ast::JoinKind::Semi => JoinKind::Semi,
1711            ast::JoinKind::Anti => JoinKind::Anti,
1712            ast::JoinKind::Positional => JoinKind::Positional,
1713        };
1714        let conditions = self.plan.add_expr_list(&conditions);
1715        let node =
1716            self.plan.add_node(Node::Join { left: left_node, right: right_node, kind, conditions });
1717        Ok((node, scope))
1718    }
1719
1720    // -------------------------------------------------------------- aggregates
1721
1722    /// Binds an aggregate call, records it, and hands back a reference to where its result lands.
1723    pub(crate) fn bind_aggregate(
1724        &mut self,
1725        ast: &Ast,
1726        name: &str,
1727        args: &[ast::ExprRef],
1728        distinct: bool,
1729        scope: &Scope,
1730    ) -> Result<ExprRef> {
1731        if self.in_aggregate {
1732            return Err(Error::binder(format!(
1733                "aggregate function calls cannot be nested, and {name}() is inside one"
1734            )));
1735        }
1736        if self.aggregation.is_none() {
1737            return Err(Error::binder(format!(
1738                "aggregate function calls cannot be used in the {}",
1739                self.clause
1740            )));
1741        }
1742        self.in_aggregate = true;
1743        let mut bound = Vec::with_capacity(args.len());
1744        let mut failure = None;
1745        for &arg in args {
1746            match self.bind_expr(ast, arg, scope) {
1747                Ok(expr) => bound.push(expr),
1748                Err(error) => {
1749                    failure = Some(error);
1750                    break;
1751                }
1752            }
1753        }
1754        self.in_aggregate = false;
1755        if let Some(error) = failure {
1756            return Err(error);
1757        }
1758
1759        let types: Vec<LogicalType> =
1760            bound.iter().map(|&arg| self.plan.expr_type(arg).clone()).collect();
1761        let resolved = resolve(name, &types)?;
1762        let mut cast = Vec::with_capacity(bound.len());
1763        for (arg, wanted) in bound.iter().zip(&resolved.arguments) {
1764            cast.push(self.cast_to(*arg, wanted));
1765        }
1766        let args = self.plan.add_expr_list(&cast);
1767        let name = self.plan.intern(resolved.name);
1768        let ty = resolved.returns;
1769        let call =
1770            self.plan.add_expr(Expr::Aggregate { name, args, distinct, filter: None }, ty.clone());
1771
1772        // Two identical aggregates are one column of the aggregate's output. `SELECT sum(x),
1773        // sum(x) / count(*)` computes one sum, not two.
1774        let existing = self.aggregation.as_ref().map(|held| held.aggregates.clone());
1775        let existing = existing.unwrap_or_default();
1776        let at = match existing.iter().position(|&held| self.same_expr(held, call)) {
1777            Some(at) => at,
1778            None => {
1779                let aggregation = self.aggregation.as_mut().expect("checked above");
1780                aggregation.aggregates.push(call);
1781                aggregation.aggregates.len() - 1
1782            }
1783        };
1784        let aggregation = self.aggregation.as_ref().expect("checked above");
1785        let (index, groups) = (aggregation.index, aggregation.groups.len());
1786        Ok(self.column(index, groups + at, ty))
1787    }
1788
1789    /// Rewrites a bound expression into one the aggregate's output can answer.
1790    ///
1791    /// A subexpression that is one of the group expressions becomes a reference to that group. A
1792    /// column that is neither grouped nor inside an aggregate is the error every SQL user has seen,
1793    /// and it is reported here because this is the first point where it is knowable.
1794    pub(crate) fn over_aggregate(&mut self, expr: ExprRef, scope: &Scope) -> Result<ExprRef> {
1795        let Some(aggregation) = self.aggregation.as_ref() else {
1796            return Ok(expr);
1797        };
1798        let index = aggregation.index;
1799        let groups = aggregation.groups.clone();
1800        for (at, group) in groups.iter().enumerate() {
1801            if self.same_expr(expr, *group) {
1802                let ty = self.plan.expr_type(*group).clone();
1803                return Ok(self.column(index, at, ty));
1804            }
1805        }
1806        let ty = self.plan.expr_type(expr).clone();
1807        match self.plan.expr(expr).clone() {
1808            Expr::Column(binding) if binding.table == index => Ok(expr),
1809            Expr::Column(binding) => {
1810                let name =
1811                    scope.columns.iter().find(|column| column.binding == binding).map_or_else(
1812                        || "a column".to_string(),
1813                        |column| format!("\"{}\"", column.name),
1814                    );
1815                Err(Error::binder(format!(
1816                    "column {name} must appear in the GROUP BY clause or must be part of an aggregate function"
1817                )))
1818            }
1819            Expr::Constant(_) | Expr::Aggregate { .. } => Ok(expr),
1820            Expr::Cast { input, try_cast } => {
1821                let input = self.over_aggregate(input, scope)?;
1822                Ok(self.plan.add_expr(Expr::Cast { input, try_cast }, ty))
1823            }
1824            Expr::Compare { op, left, right } => {
1825                let left = self.over_aggregate(left, scope)?;
1826                let right = self.over_aggregate(right, scope)?;
1827                Ok(self.plan.add_expr(Expr::Compare { op, left, right }, ty))
1828            }
1829            Expr::Conjunction { op, children } => {
1830                let written = self.plan.expr_list(children).to_vec();
1831                let mut rewritten = Vec::with_capacity(written.len());
1832                for child in written {
1833                    rewritten.push(self.over_aggregate(child, scope)?);
1834                }
1835                let children = self.plan.add_expr_list(&rewritten);
1836                Ok(self.plan.add_expr(Expr::Conjunction { op, children }, ty))
1837            }
1838            Expr::Function { name, args } => {
1839                let written = self.plan.expr_list(args).to_vec();
1840                let mut rewritten = Vec::with_capacity(written.len());
1841                for arg in written {
1842                    rewritten.push(self.over_aggregate(arg, scope)?);
1843                }
1844                let args = self.plan.add_expr_list(&rewritten);
1845                Ok(self.plan.add_expr(Expr::Function { name, args }, ty))
1846            }
1847            Expr::Case { arms, otherwise } => {
1848                let written = self.plan.arm_list(arms).to_vec();
1849                let mut rewritten = Vec::with_capacity(written.len());
1850                for arm in written {
1851                    let when = self.over_aggregate(arm.when, scope)?;
1852                    let then = self.over_aggregate(arm.then, scope)?;
1853                    rewritten.push(rudb_plan::Arm { when, then });
1854                }
1855                let otherwise = match otherwise {
1856                    Some(expr) => Some(self.over_aggregate(expr, scope)?),
1857                    None => None,
1858                };
1859                let arms = self.plan.add_arms(&rewritten);
1860                Ok(self.plan.add_expr(Expr::Case { arms, otherwise }, ty))
1861            }
1862        }
1863    }
1864
1865    /// Whether two bound expressions are the same expression, by shape rather than by reference.
1866    pub(crate) fn same_expr(&self, left: ExprRef, right: ExprRef) -> bool {
1867        same_expr(&self.plan, left, right)
1868    }
1869}
1870
1871/// The named parameters a table function call was written with.
1872///
1873/// A struct rather than the fields loose, because the seventeen DuckDB has on `read_parquet` and the
1874/// thirty on `read_csv` are all going to want somewhere to go, and because a call with none of them
1875/// written should read as the default of this rather than as a bare false somewhere.
1876///
1877/// The CSV half goes on to the reader and is opened with, here and again in the executor. The
1878/// Parquet half is answered here and nothing downstream sees it, which is what `binary_as_string`
1879/// turning a BLOB column into a VARCHAR one is.
1880#[derive(Debug, Default)]
1881struct Options {
1882    /// `binary_as_string`, which says an unannotated byte array column in a Parquet file holds
1883    /// text. The ClickBench file has twenty eight of those and every query reads them as strings.
1884    binary_as_string: bool,
1885    /// `all_varchar`, which reads every column of a CSV file as text rather than sniffing a type.
1886    all_varchar: bool,
1887    /// `file_row_number`, which adds a column holding each row's ordinal inside its own file.
1888    ///
1889    /// The one Parquet option here that the executor has to act on rather than the binder, since
1890    /// the column is not in the file and has to be counted as the rows come out of it.
1891    file_row_number: bool,
1892    /// `delim`, `sep`, `quote`, `escape` and `header`, which are what the sniffer would decide.
1893    given: Given,
1894}
1895
1896impl Options {
1897    /// What these named parameters add up to.
1898    ///
1899    /// Each one was already checked against the function's list, so a name in here is a name that
1900    /// function takes and the value is already the type it wants. What is left is reading them, and
1901    /// the last one written wins, which is DuckDB's answer to `delim='|', delim=','` and was
1902    /// measured rather than assumed.
1903    fn of(written: &[(&'static str, Value, ExprRef)]) -> Result<Self> {
1904        let mut options = Self::default();
1905        for (parameter, value, _) in written {
1906            match (*parameter, value) {
1907                ("binary_as_string", Value::Boolean(on)) => options.binary_as_string = *on,
1908                ("all_varchar", Value::Boolean(on)) => options.all_varchar = *on,
1909                ("file_row_number", Value::Boolean(on)) => options.file_row_number = *on,
1910                _ => {}
1911            }
1912        }
1913        let named: Vec<(&str, Value)> =
1914            written.iter().map(|(parameter, value, _)| (*parameter, value.clone())).collect();
1915        options.given = csv_given(&named)?;
1916        Ok(options)
1917    }
1918}
1919
1920/// DuckDB's complaint about a named parameter that was given a null, which is a different sentence
1921/// for almost every parameter.
1922///
1923/// Three of them were measured on `v2.0.0-dev84237` and no two agree: `binary_as_string` is the
1924/// first, `all_varchar` is the second and `header` is the third. They read like three people each
1925/// writing the message in front of them, which is what they are, and a harness that compares error
1926/// text compares all of it. Anything not measured gets the first one, which is the most general of
1927/// the three.
1928fn null_parameter(function: TableFunction, parameter: &str) -> String {
1929    match parameter {
1930        "header" => format!("\"{parameter}\" expects a non-null boolean value (e.g. TRUE or 1)"),
1931        "all_varchar" => format!("{} \"{parameter}\" cannot be NULL", function.name()),
1932        _ => format!("Cannot use NULL as argument to \"{parameter}\""),
1933    }
1934}
1935
1936/// The complaint about a `REPLACE` entry that named a column the star did not stand for.
1937///
1938/// It reads like the complaint about any other name that is not there, down to the list of names
1939/// that are, because from the writer's side it is the same mistake.
1940fn missing_replacement(name: &str, input: &Scope) -> Error {
1941    Error::binder(format!(
1942        "Column \"{name}\" in REPLACE list not found in FROM clause{}",
1943        input.candidates()
1944    ))
1945}
1946
1947/// A sort key with SQL's defaults filled in.
1948///
1949/// Unstated is ascending, and unstated nulls go where the direction puts them, which is last for
1950/// ascending and first for descending. That is DuckDB's rule and it is the one that makes
1951/// `ORDER BY x DESC` the exact reverse of `ORDER BY x`.
1952fn sort_key(expr: ExprRef, item: ast::OrderItem) -> SortKey {
1953    let descending = item.order == Order::Descending;
1954    let nulls_first = match item.nulls {
1955        Nulls::First => true,
1956        Nulls::Last => false,
1957        Nulls::Unstated => descending,
1958    };
1959    SortKey { expr, descending, nulls_first }
1960}
1961
1962/// Structural equality over two expressions of one plan.
1963fn same_expr(plan: &Plan, left: ExprRef, right: ExprRef) -> bool {
1964    if left == right {
1965        return true;
1966    }
1967    if plan.expr_type(left) != plan.expr_type(right) {
1968        return false;
1969    }
1970    let lists = |left, right| {
1971        let left: &[ExprRef] = plan.expr_list(left);
1972        let right: &[ExprRef] = plan.expr_list(right);
1973        left.len() == right.len()
1974            && left.iter().zip(right).all(|(&left, &right)| same_expr(plan, left, right))
1975    };
1976    match (plan.expr(left), plan.expr(right)) {
1977        (Expr::Column(left), Expr::Column(right)) => left == right,
1978        (Expr::Constant(left), Expr::Constant(right)) => plan.value(*left) == plan.value(*right),
1979        (
1980            Expr::Cast { input: left, try_cast: left_try },
1981            Expr::Cast { input: right, try_cast: right_try },
1982        ) => left_try == right_try && same_expr(plan, *left, *right),
1983        (
1984            Expr::Compare { op: left_op, left: left_a, right: left_b },
1985            Expr::Compare { op: right_op, left: right_a, right: right_b },
1986        ) => {
1987            left_op == right_op
1988                && same_expr(plan, *left_a, *right_a)
1989                && same_expr(plan, *left_b, *right_b)
1990        }
1991        (
1992            Expr::Conjunction { op: left_op, children: left_children },
1993            Expr::Conjunction { op: right_op, children: right_children },
1994        ) => left_op == right_op && lists(*left_children, *right_children),
1995        (
1996            Expr::Function { name: left_name, args: left_args },
1997            Expr::Function { name: right_name, args: right_args },
1998        ) => plan.string(*left_name) == plan.string(*right_name) && lists(*left_args, *right_args),
1999        (
2000            Expr::Aggregate {
2001                name: left_name,
2002                args: left_args,
2003                distinct: left_distinct,
2004                filter: left_filter,
2005            },
2006            Expr::Aggregate {
2007                name: right_name,
2008                args: right_args,
2009                distinct: right_distinct,
2010                filter: right_filter,
2011            },
2012        ) => {
2013            plan.string(*left_name) == plan.string(*right_name)
2014                && left_distinct == right_distinct
2015                && match (left_filter, right_filter) {
2016                    (None, None) => true,
2017                    (Some(left), Some(right)) => same_expr(plan, *left, *right),
2018                    _ => false,
2019                }
2020                && lists(*left_args, *right_args)
2021        }
2022        (
2023            Expr::Case { arms: left_arms, otherwise: left_otherwise },
2024            Expr::Case { arms: right_arms, otherwise: right_otherwise },
2025        ) => {
2026            let left_arms = plan.arm_list(*left_arms);
2027            let right_arms = plan.arm_list(*right_arms);
2028            left_arms.len() == right_arms.len()
2029                && left_arms.iter().zip(right_arms).all(|(left, right)| {
2030                    same_expr(plan, left.when, right.when) && same_expr(plan, left.then, right.then)
2031                })
2032                && match (left_otherwise, right_otherwise) {
2033                    (None, None) => true,
2034                    (Some(left), Some(right)) => same_expr(plan, *left, *right),
2035                    _ => false,
2036                }
2037        }
2038        _ => false,
2039    }
2040}