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::{
17    Error, Field, LogicalType, Result, Semantics, Session, ShowBehavior, Span, Value,
18};
19use rudb_functions::{
20    Columns, FILE_ROW_NUMBER, FunctionKind, Given, Resolved, TableFunction, csv_fields, csv_given,
21    files, is_file, is_pattern, kind_of, parquet_fields, resolve, resolve_pragma, resolve_table,
22};
23use rudb_parse::ast::{self, Ast, Distinct, LiteralKind, Nulls, Order, Quantifier, SetOp};
24use rudb_parse::{NONE, identifier_parts, parse_ast_with_case};
25use rudb_plan::{
26    BuildSide, ColumnBinding, Expr, ExprRef, JoinKind, Node, NodeRef, Plan, SetOpKind, SortKey,
27    WindowBound, WindowExclude, WindowFrame, WindowUnit,
28};
29
30use crate::expr::{describe, has_aggregate};
31use crate::parameters::Parameters;
32use crate::scope::{Scope, Visible};
33
34/// Binds a parsed statement against a catalog.
35///
36/// # Errors
37///
38/// If the script does not hold exactly one statement, if a name does not resolve, if a type does
39/// not work out, or if the query uses something M0 does not bind yet.
40pub fn bind(ast: &Ast, catalog: &Catalog) -> Result<Plan> {
41    bind_with(ast, catalog, &Parameters::new(), &Session::new())
42}
43
44/// Binds a parsed query against a catalog, with values for its parameters and its settings.
45///
46/// The session is what `current_setting()` reads, and a caller with no database behind it passes an
47/// empty one, which makes every setting name unrecognized rather than making up an answer.
48///
49/// # Errors
50///
51/// Everything [`bind`] reports, plus an error for a parameter that was given no value.
52pub fn bind_with(
53    ast: &Ast,
54    catalog: &Catalog,
55    parameters: &Parameters,
56    session: &Session,
57) -> Result<Plan> {
58    let query = match ast.statements.as_slice() {
59        [ast::Statement::Query(query)] => *query,
60        [] => return Err(Error::binder("no statement to bind")),
61        // One statement that is not a query is its own answer. Reporting it as a script of several
62        // reads as a count being wrong, and the count is right.
63        [_] => return Err(Error::not_implemented("a statement that is not a query")),
64        _ => return Err(Error::not_implemented("a script of more than one statement")),
65    };
66    let mut binder = Binder::with(catalog, parameters, session);
67    let (root, _) = binder.bind_query(ast, query)?;
68    let mut plan = binder.into_plan();
69    plan.set_root(root);
70    plan.validate()?;
71    Ok(plan)
72}
73
74/// Parses and binds one query, which is the whole front end in one call.
75///
76/// # Errors
77///
78/// Anything the parser or the binder reports.
79pub fn bind_sql(query: &str, catalog: &Catalog) -> Result<Plan> {
80    bind_sql_with(query, catalog, &Session::new())
81}
82
83/// Parses and binds one query, with the settings a call to `current_setting()` reads.
84///
85/// # Errors
86///
87/// Anything the parser or the binder reports.
88pub fn bind_sql_with(query: &str, catalog: &Catalog, session: &Session) -> Result<Plan> {
89    let ast = parse_ast_with_case(query, session.semantics().identifier_case())?;
90    bind_with(&ast, catalog, &Parameters::new(), session)
91}
92
93/// What an aggregating select block has decided so far.
94#[derive(Debug)]
95pub(crate) struct Aggregation {
96    /// The table index the aggregate's output binds against.
97    pub(crate) index: u32,
98    /// The group expressions, over the input, which are the first output columns.
99    pub(crate) groups: Vec<ExprRef>,
100    /// The aggregate calls found so far, which follow the groups in the output.
101    pub(crate) aggregates: Vec<ExprRef>,
102}
103
104/// One run of window calls that agree on where the rows come from and in what order.
105///
106/// The run is the unit the plan has an operator for, so two calls that write the same partition,
107/// the same order and the same frame are one operator and one sort, and a third that writes a
108/// different order is a second operator stacked on the first. Nothing here merges runs that only
109/// look compatible, because a window is evaluated over the rows the operator below it produced and
110/// deciding two runs are the same is the optimizer's job rather than the binder's.
111#[derive(Debug)]
112pub(crate) struct WindowRun {
113    /// The table index the run's result columns bind against.
114    index: u32,
115    /// What divides the input into independent partitions.
116    partition: Vec<ExprRef>,
117    /// The order within a partition.
118    order: Vec<SortKey>,
119    /// The frame every call in the run shares.
120    frame: WindowFrame,
121    /// The calls, in the order their columns are appended.
122    calls: Vec<ExprRef>,
123}
124
125/// One window call as it was written, before any of it has been bound.
126///
127/// These six travel together from the parser all the way to the run they end up filed under, and
128/// carrying them as one thing keeps the call that binds them readable.
129pub(crate) struct WindowCall<'a> {
130    /// The function name, as written and not yet resolved.
131    pub(crate) name: &'a str,
132    /// The arguments, which may include a star that only `count` is allowed to be given.
133    pub(crate) args: &'a [ast::ExprRef],
134    /// Whether `DISTINCT` was written inside the parens.
135    pub(crate) distinct: bool,
136    /// The `FILTER (WHERE ...)` predicate, which is written before the `OVER`, or `NONE`.
137    pub(crate) filter: ast::ExprRef,
138    /// Whether `IGNORE NULLS` was written inside the parens, which is where DuckDB puts it.
139    pub(crate) ignore_nulls: bool,
140    /// The `OVER`, which the parser has already resolved against any `WINDOW` clause.
141    pub(crate) spec: ast::WindowRef,
142}
143
144/// Everything inside one window call once it is bound, which is what decides its run.
145struct WindowParts {
146    /// The arguments, before the casts the resolved signature asks for.
147    args: Vec<ExprRef>,
148    /// What divides the input into independent partitions.
149    partition: Vec<ExprRef>,
150    /// The order within a partition.
151    order: Vec<SortKey>,
152    /// The frame, with both ends and the exclusion.
153    frame: WindowFrame,
154}
155
156/// A materialised `WITH` definition that has been bound and can be read by name.
157#[derive(Debug)]
158struct Materialized {
159    /// Which written definition this is, as an index into `Ast::ctes`.
160    written: u32,
161    /// The number the plan uses to pair a read with what it reads.
162    cte: u32,
163    /// The name it was written with, which is the table name a read is reachable through.
164    name: String,
165    /// What it produces, in order, under the declared names when a column list was written.
166    fields: Vec<Field>,
167}
168
169#[derive(Debug)]
170pub(crate) struct PendingSubquery {
171    pub(crate) node: NodeRef,
172    pub(crate) kind: JoinKind,
173    pub(crate) conditions: Vec<ExprRef>,
174    pub(crate) dependent: bool,
175    /// The table index this query's join adds to the rows it is joined into.
176    ///
177    /// Kept so that a `HAVING` which reads one of these can say which columns came from a query
178    /// joined above the grouping rather than from the table underneath it. Those columns are not
179    /// the table's and the grouping rule has nothing to say about them.
180    pub(crate) index: u32,
181}
182
183/// The state one binding run carries.
184#[derive(Debug)]
185pub(crate) struct Binder<'a> {
186    catalog: &'a Catalog,
187    /// What the parameters were given, empty for a statement that is not prepared.
188    pub(crate) parameters: &'a Parameters,
189    /// What the settings are now, which is what `current_setting()` folds to.
190    pub(crate) session: &'a Session,
191    /// Meaning-changing choices copied once and resolved into the plan above execution.
192    pub(crate) semantics: Semantics,
193    plan: Plan,
194    next_index: u32,
195    /// Source range inherited by plan objects built for the current AST expression or query.
196    pub(crate) current_span: Span,
197    /// Set while a select block aggregates, which changes what a bare column means.
198    pub(crate) aggregation: Option<Aggregation>,
199    /// Set while an aggregate's own arguments are being bound, so nesting is caught.
200    pub(crate) in_aggregate: bool,
201    /// Set while an aggregate's `FILTER` is being bound, which is refused its own aggregate.
202    pub(crate) in_filter: bool,
203    /// The window runs this select block has collected, in the order they were first written.
204    pub(crate) windows: Vec<WindowRun>,
205    /// Set while a window call's own arguments and keys are being bound, so nesting is caught.
206    pub(crate) in_window: bool,
207    /// Uncorrelated scalar queries waiting to be joined into the select block that uses them.
208    pub(crate) scalar_subqueries: Vec<PendingSubquery>,
209    /// Table indices of the queries this block will join in above its grouping, not below it.
210    ///
211    /// Only ever set while a `HAVING` is being rewritten over the aggregate. A column from one of
212    /// these is not a column of the grouped table, so the rule about grouping every column does not
213    /// reach it, and the join that produces it goes on top of the `Aggregate` rather than under it.
214    pub(crate) joined_above: Vec<u32>,
215    pub(crate) outer_scopes: Vec<Scope>,
216    /// Which of the outer scopes are a FROM entry's left neighbours rather than an enclosing query.
217    ///
218    /// The two are resolved the same way and refused differently. An aggregate may read a column of
219    /// the query it is written in and may not read one a LATERAL brought in from the left, so the
220    /// check needs to know which scope the name came out of. Each entry is a position in
221    /// `outer_scopes`.
222    pub(crate) lateral_scopes: Vec<usize>,
223    pub(crate) correlations: Vec<Vec<ColumnBinding>>,
224    /// Where we are, for an error message that says which clause the writer should look at.
225    pub(crate) clause: &'static str,
226    /// The views whose bodies are open on the stack, which is what catches a cycle.
227    expanding: Vec<String>,
228    /// The materialised `WITH` definitions whose bodies are being bound, innermost last.
229    ///
230    /// A stack rather than a map from what was written, because a plain `WITH` is put into every
231    /// place it is named, so a materialised one written inside a plain one is bound once per use
232    /// and each of those is a materialisation of its own with a number of its own.
233    materialized: Vec<Materialized>,
234    /// How many materialisations have been numbered, which is where the next number comes from.
235    next_cte: u32,
236    /// When this statement started, read once and kept, which is what `now()` folds to.
237    started: Option<i64>,
238}
239
240impl<'a> Binder<'a> {
241    pub(crate) fn with(
242        catalog: &'a Catalog,
243        parameters: &'a Parameters,
244        session: &'a Session,
245    ) -> Self {
246        Self {
247            catalog,
248            parameters,
249            session,
250            semantics: session.semantics(),
251            plan: Plan::new(),
252            next_index: 0,
253            current_span: Span::new(0, 0),
254            aggregation: None,
255            in_aggregate: false,
256            in_filter: false,
257            windows: Vec::new(),
258            in_window: false,
259            scalar_subqueries: Vec::new(),
260            joined_above: Vec::new(),
261            outer_scopes: Vec::new(),
262            lateral_scopes: Vec::new(),
263            correlations: Vec::new(),
264            clause: "SELECT clause",
265            expanding: Vec::new(),
266            materialized: Vec::new(),
267            next_cte: 0,
268            started: None,
269        }
270    }
271
272    pub(crate) fn catalog(&self) -> &Catalog {
273        self.catalog
274    }
275
276    /// When this statement started, in microseconds since the epoch.
277    ///
278    /// Read from the clock the first time something asks and kept after that, so a query that
279    /// writes `now()` twice gets one answer for both. That is what the pin does and what it reports
280    /// in the `stability` column of `duckdb_functions()`, where every one of these is
281    /// `CONSISTENT_WITHIN_QUERY`. A query that never asks never reads the clock.
282    pub(crate) fn instant(&mut self) -> i64 {
283        *self.started.get_or_insert_with(crate::context::micros_now)
284    }
285
286    pub(crate) fn plan(&self) -> &Plan {
287        &self.plan
288    }
289
290    pub(crate) fn plan_mut(&mut self) -> &mut Plan {
291        &mut self.plan
292    }
293
294    pub(crate) fn add_expr(&mut self, expr: Expr, ty: LogicalType) -> ExprRef {
295        self.plan.add_expr_at(expr, ty, self.current_span)
296    }
297
298    pub(crate) fn add_constant(&mut self, value: Value) -> ExprRef {
299        let ty = value.logical_type();
300        let reference = self.plan.add_value(value);
301        self.plan.add_expr_at(Expr::Constant(reference), ty, self.current_span)
302    }
303
304    pub(crate) fn add_node(&mut self, node: Node) -> NodeRef {
305        self.plan.add_node_at(node, self.current_span)
306    }
307
308    pub(crate) fn into_plan(self) -> Plan {
309        self.plan
310    }
311
312    /// A table index nothing else has.
313    pub(crate) fn fresh_index(&mut self) -> u32 {
314        let index = self.next_index;
315        self.next_index += 1;
316        index
317    }
318
319    /// A reference to one column of an operator's output.
320    fn column(&mut self, index: u32, position: usize, ty: LogicalType) -> ExprRef {
321        let binding = ColumnBinding::new(index, position as u32);
322        self.plan.add_expr(Expr::Column(binding), ty)
323    }
324
325    /// Joins scalar query results into the row stream that contains their expressions.
326    fn attach_scalar_subqueries(&mut self, mut input: NodeRef) -> NodeRef {
327        let subqueries = std::mem::take(&mut self.scalar_subqueries);
328        for pending in subqueries {
329            let PendingSubquery { node: mut right, kind, conditions, dependent, index: _ } =
330                pending;
331            if kind == JoinKind::Single && !self.semantics.scalar_subquery_error_on_multiple_rows()
332            {
333                right = self.add_node(Node::Limit { input: right, count: Some(1), offset: 0 });
334            }
335            let conditions = self.plan.add_expr_list(&conditions);
336            input = if dependent {
337                self.add_node(Node::DependentJoin { left: input, right, kind, conditions })
338            } else {
339                self.add_node(Node::Join {
340                    left: input,
341                    right,
342                    kind,
343                    conditions,
344                    build: BuildSide::default(),
345                })
346            };
347        }
348        input
349    }
350
351    // ---------------------------------------------------------------- queries
352
353    pub(crate) fn bind_query(
354        &mut self,
355        ast: &Ast,
356        query: ast::QueryRef,
357    ) -> Result<(NodeRef, Scope)> {
358        let span = ast.query_span(query);
359        let outer = std::mem::replace(&mut self.current_span, span);
360        let result =
361            self.bind_query_inner(ast, query).map_err(|error| error.with_fallback_span(span));
362        self.current_span = outer;
363        result
364    }
365
366    fn bind_query_inner(&mut self, ast: &Ast, query: ast::QueryRef) -> Result<(NodeRef, Scope)> {
367        let written = ast.query(query);
368        if written.ctes.is_empty() {
369            return self.bind_body(ast, &written);
370        }
371        // The names a query introduces are gone again once it is bound, and they go whether the
372        // binding worked or not, which is why the stack is cut back here rather than at the end of
373        // the call that pushed onto it.
374        let depth = self.materialized.len();
375        let result = self.bind_materialized(ast, &written);
376        self.materialized.truncate(depth);
377        result
378    }
379
380    /// A query with materialised `WITH` definitions in front of it.
381    ///
382    /// The definitions are bound first and in the order they were written, so that a later one can
383    /// read an earlier one, and then the body. The wrapping runs backwards so that the first
384    /// definition ends up outermost, which is the order they have to be filled in.
385    fn bind_materialized(&mut self, ast: &Ast, written: &ast::Query) -> Result<(NodeRef, Scope)> {
386        let depth = self.materialized.len();
387        let held = ast.cte_list(written.ctes).to_vec();
388        let mut definitions = Vec::with_capacity(held.len());
389        for &index in &held {
390            definitions.push(self.bind_definition(ast, index)?);
391        }
392        let (mut node, scope) = self.bind_body(ast, written)?;
393        for (at, definition) in definitions.into_iter().enumerate().rev() {
394            let entry = &self.materialized[depth + at];
395            let cte = entry.cte;
396            let name = entry.name.clone();
397            let fields = entry.fields.clone();
398            let name = self.plan.intern(&name);
399            let columns = self.plan.add_fields(&fields);
400            node =
401                self.add_node(Node::MaterializedCte { definition, body: node, name, cte, columns });
402        }
403        Ok((node, scope))
404    }
405
406    /// Binds one materialised `WITH` definition and makes its name readable from there on.
407    ///
408    /// The definition is projected onto exactly the columns a read of it sees, under the names the
409    /// column list declared when there was one. That projection is not decoration: what is held is
410    /// what a read gets back, so the held rows have to be the rows of the definition's own select
411    /// list and nothing it happened to carry along underneath.
412    ///
413    /// A column list with more names in it than the definition has columns is not an error here,
414    /// which is the pinned build's rule and is written out on [`Scope::rename_prefix`].
415    fn bind_definition(&mut self, ast: &Ast, index: u32) -> Result<NodeRef> {
416        let held = ast.cte(index);
417        let name = ast.string(held.name).to_string();
418        let (node, mut scope) = self.bind_query(ast, held.query)?;
419        if !held.columns.is_empty() {
420            let names: Vec<&str> = ast.name(held.columns).collect();
421            scope.rename_prefix(&names);
422        }
423        let table = self.fresh_index();
424        let mut exprs = Vec::with_capacity(scope.len());
425        let mut names = Vec::with_capacity(scope.len());
426        for column in &scope.columns {
427            exprs.push(self.plan.add_expr(Expr::Column(column.binding), column.ty.clone()));
428            names.push(self.plan.intern(&column.name));
429        }
430        let exprs = self.plan.add_expr_list(&exprs);
431        let names = self.plan.add_name_list(&names);
432        let node = self.add_node(Node::Project { input: node, index: table, exprs, names });
433        let cte = self.next_cte;
434        self.next_cte += 1;
435        self.materialized.push(Materialized { written: index, cte, name, fields: scope.fields() });
436        Ok(node)
437    }
438
439    fn bind_body(&mut self, ast: &Ast, written: &ast::Query) -> Result<(NodeRef, Scope)> {
440        match written.body {
441            ast::QueryBody::Select(select) => self.bind_select(ast, select, written),
442            ast::QueryBody::SetOp { op, quantifier, by_name, left, right } => {
443                if by_name {
444                    return Err(Error::not_implemented("UNION BY NAME"));
445                }
446                self.bind_set_op(ast, written, op, quantifier, left, right)
447            }
448            ast::QueryBody::Values(rows) => self.bind_values(ast, written, rows),
449            ast::QueryBody::Describe(inner) => self.bind_describe(ast, written, inner),
450            ast::QueryBody::Show { name, relation } => self.bind_show(ast, written, name, relation),
451        }
452    }
453
454    /// `SHOW name`, resolved while binding so execution receives an ordinary constant plan.
455    fn bind_show(
456        &mut self,
457        ast: &Ast,
458        query: &ast::Query,
459        name: ast::Slice,
460        relation: ast::QueryRef,
461    ) -> Result<(NodeRef, Scope)> {
462        let text = ast.name_text(name);
463        let parts: Vec<&str> = ast.name(name).collect();
464        let table_exists = self.catalog.resolve(&parts).is_ok();
465        let as_table = match self.semantics.show_behavior() {
466            ShowBehavior::Auto => table_exists,
467            ShowBehavior::Setting => false,
468            ShowBehavior::Table => true,
469        };
470        if as_table {
471            return self.bind_describe(ast, query, relation);
472        }
473        let Some((_, value)) =
474            self.session.iter().find(|(name, _)| name.eq_ignore_ascii_case(&text))
475        else {
476            return Err(Error::catalog(format!("Setting with name \"{text}\" does not exist")));
477        };
478        let field = Field::new(text, LogicalType::Varchar);
479        let expr = self.plan.add_constant(Value::Varchar(value.to_string()));
480        let row = self.plan.add_expr_list(&[expr]);
481        let rows = self.plan.add_rows(&[row]);
482        let columns = self.plan.add_fields(std::slice::from_ref(&field));
483        let index = self.fresh_index();
484        let node = self.add_node(Node::Values { index, columns, rows });
485        let mut scope = Scope::empty();
486        scope.push(Visible {
487            table: String::new(),
488            name: field.name,
489            binding: ColumnBinding::new(index, 0),
490            ty: LogicalType::Varchar,
491            not_null: false,
492        });
493        Ok((node, scope))
494    }
495
496    /// `DESCRIBE <query>`, which is six VARCHAR columns saying what the query returns.
497    ///
498    /// The query is bound and never run, because binding is the whole of the answer: the names and
499    /// the types of a query's columns are settled by the time the binder is done with it, so the
500    /// rows of a describe are a constant from there on. That is why this comes out as a `VALUES`
501    /// whose rows were computed here rather than as an operator of its own, and it is what makes
502    /// `SELECT column_name FROM (DESCRIBE ...) WHERE ...` an ordinary query over an ordinary
503    /// relation with no special case above it.
504    ///
505    /// The six columns, their order and their types are the reference binary's. `key`, `default`
506    /// and `extra` are null for everything this engine can declare, since `PRIMARY KEY`, `UNIQUE`
507    /// and `DEFAULT` are all refused by `CREATE TABLE` today and there is nothing for the first two
508    /// to hold, and `extra` is empty upstream as well on every table it was asked about. They are
509    /// here rather than left out because the width of a result is part of the result, and a program
510    /// that reads the fifth column has to find one.
511    fn bind_describe(
512        &mut self,
513        ast: &Ast,
514        query: &ast::Query,
515        inner: ast::QueryRef,
516    ) -> Result<(NodeRef, Scope)> {
517        let (_, described) = self.bind_query(ast, inner)?;
518        let fields: Vec<Field> = ["column_name", "column_type", "null", "key", "default", "extra"]
519            .iter()
520            .map(|name| Field::new(*name, LogicalType::Varchar))
521            .collect();
522        let mut slices = Vec::with_capacity(described.columns.len());
523        for column in described.columns.clone() {
524            // `NO` and `YES` and not a boolean, because the column is VARCHAR upstream and a
525            // client that prints the result has to get the same four or three characters.
526            let written = [
527                column.name.clone(),
528                column.ty.to_string(),
529                if column.not_null { "NO" } else { "YES" }.to_owned(),
530            ];
531            let mut items: Vec<ExprRef> = written
532                .into_iter()
533                .map(|text| self.plan.add_constant(Value::Varchar(text)))
534                .collect();
535            for _ in 0..3 {
536                let empty = self.plan.add_constant(Value::Null);
537                items.push(self.cast_to(empty, &LogicalType::Varchar));
538            }
539            slices.push(self.plan.add_expr_list(&items));
540        }
541        let rows = self.plan.add_rows(&slices);
542        let columns = self.plan.add_fields(&fields);
543        let index = self.fresh_index();
544        let mut node = self.add_node(Node::Values { index, columns, rows });
545        let mut scope = Scope::empty();
546        for (at, field) in fields.iter().enumerate() {
547            scope.push(Visible {
548                table: String::new(),
549                name: field.name.clone(),
550                binding: ColumnBinding::new(index, at as u32),
551                ty: field.ty.clone(),
552                not_null: false,
553            });
554        }
555        let keys = self.sort_keys(ast, query, &scope, &[])?;
556        if !keys.is_empty() {
557            let keys = self.plan.add_sort_keys(&keys);
558            node = self.add_node(Node::Sort { input: node, keys });
559        }
560        node = self.apply_limit(ast, query, node)?;
561        Ok((node, scope))
562    }
563
564    /// Whether a projected expression is a column passed straight through from below.
565    ///
566    /// Only `DESCRIBE` asks, and only to decide whether the `null` column says `NO`. Anything that
567    /// is computed is nullable however strict its inputs were, which is both the safe reading and
568    /// the one the reference binary gives.
569    fn passes_through(&self, expr: ExprRef, input: &Scope) -> bool {
570        let Expr::Column(binding) = *self.plan.expr(expr) else { return false };
571        input.columns.iter().any(|column| column.binding == binding && column.not_null)
572    }
573
574    /// `VALUES (1, 'a'), (2, 'b')`, as a query in its own right.
575    ///
576    /// The column names are `col0`, `col1` and so on, which is what DuckDB calls them, and the
577    /// column types are what every row in that position promotes to. Promotion is the same rule a
578    /// set operation uses, and for the same reason: a column has one type and the rows have to
579    /// agree on it before anything downstream can read the column.
580    fn bind_values(
581        &mut self,
582        ast: &Ast,
583        query: &ast::Query,
584        rows: ast::Slice,
585    ) -> Result<(NodeRef, Scope)> {
586        let written = ast.rows(rows).to_vec();
587        let Some(first) = written.first() else {
588            return Err(Error::binder("VALUES needs at least one row"));
589        };
590        let width = first.len as usize;
591        for (at, row) in written.iter().enumerate() {
592            if row.len as usize != width {
593                return Err(Error::binder(format!(
594                    "VALUES lists must all be the same length, expected {width} columns but row {} has {}",
595                    at + 1,
596                    row.len
597                )));
598            }
599        }
600        // A row of a `VALUES` cannot see a column, because there is nothing under it to see.
601        let empty = Scope::empty();
602        let previous = std::mem::replace(&mut self.clause, "VALUES clause");
603        let mut bound: Vec<Vec<ExprRef>> = Vec::with_capacity(written.len());
604        for row in &written {
605            let mut items = Vec::with_capacity(width);
606            for &expr in ast.expr_list(*row) {
607                items.push(self.bind_expr(ast, expr, &empty)?);
608            }
609            bound.push(items);
610        }
611        self.clause = previous;
612        let mut types = Vec::with_capacity(width);
613        for at in 0..width {
614            let mut ty = self.plan.expr_type(bound[0][at]).clone();
615            for row in &bound[1..] {
616                let other = self.plan.expr_type(row[at]).clone();
617                ty = ty.promote(&other).ok_or_else(|| {
618                    Error::binder(format!(
619                        "Cannot combine a value of type {ty} with a value of type {other} in column {} of a VALUES",
620                        at + 1
621                    ))
622                })?;
623            }
624            types.push(ty);
625        }
626        let mut slices = Vec::with_capacity(bound.len());
627        for row in &bound {
628            let items: Vec<ExprRef> = row
629                .iter()
630                .zip(&types)
631                .map(|(&expr, ty)| self.checked_cast_to(expr, ty, false))
632                .collect::<Result<_>>()?;
633            slices.push(self.plan.add_expr_list(&items));
634        }
635        let rows = self.plan.add_rows(&slices);
636        let fields: Vec<Field> = types
637            .iter()
638            .enumerate()
639            .map(|(at, ty)| Field::new(format!("col{at}"), ty.clone()))
640            .collect();
641        let columns = self.plan.add_fields(&fields);
642        let index = self.fresh_index();
643        let mut node = self.add_node(Node::Values { index, columns, rows });
644        let mut scope = Scope::empty();
645        for (at, field) in fields.iter().enumerate() {
646            scope.push(Visible {
647                table: String::new(),
648                name: field.name.clone(),
649                binding: ColumnBinding::new(index, at as u32),
650                ty: field.ty.clone(),
651                not_null: false,
652            });
653        }
654        let keys = self.sort_keys(ast, query, &scope, &[])?;
655        if !keys.is_empty() {
656            let keys = self.plan.add_sort_keys(&keys);
657            node = self.add_node(Node::Sort { input: node, keys });
658        }
659        node = self.apply_limit(ast, query, node)?;
660        Ok((node, scope))
661    }
662
663    fn bind_set_op(
664        &mut self,
665        ast: &Ast,
666        query: &ast::Query,
667        op: SetOp,
668        quantifier: Quantifier,
669        left: ast::QueryRef,
670        right: ast::QueryRef,
671    ) -> Result<(NodeRef, Scope)> {
672        let (left_node, left_scope) = self.bind_query(ast, left)?;
673        let (right_node, right_scope) = self.bind_query(ast, right)?;
674        if left_scope.len() != right_scope.len() {
675            return Err(Error::binder(format!(
676                "Set operations can only apply to expressions with the same number of result columns, but left side has {} and right side has {}",
677                left_scope.len(),
678                right_scope.len()
679            )));
680        }
681        // Both sides have to hand back one set of types, so each column meets the other side's.
682        let mut types = Vec::with_capacity(left_scope.len());
683        for (left, right) in left_scope.columns.iter().zip(&right_scope.columns) {
684            let common = left.ty.promote(&right.ty).ok_or_else(|| {
685                Error::binder(format!(
686                    "Cannot combine a column of type {} with a column of type {} in a set operation",
687                    left.ty, right.ty
688                ))
689            })?;
690            types.push(common);
691        }
692        let left_node = self.conform(left_node, &left_scope, &types)?;
693        let right_node = self.conform(right_node, &right_scope, &types)?;
694        let index = self.fresh_index();
695        let kind = match op {
696            SetOp::Union => SetOpKind::Union,
697            SetOp::Except => SetOpKind::Except,
698            SetOp::Intersect => SetOpKind::Intersect,
699        };
700        // UNION alone removes duplicates and UNION ALL keeps them, which is the one place the
701        // unwritten quantifier and ALL disagree.
702        let all = quantifier == Quantifier::All;
703        let mut node =
704            self.add_node(Node::SetOp { left: left_node, right: right_node, kind, all, index });
705        let mut scope = Scope::empty();
706        for (at, (column, ty)) in left_scope.columns.iter().zip(&types).enumerate() {
707            scope.push(Visible {
708                table: String::new(),
709                name: column.name.clone(),
710                binding: ColumnBinding::new(index, at as u32),
711                ty: ty.clone(),
712                // A column of a set operation is nullable whatever the two sides were, because a
713                // column that refuses nulls on one side and takes them on the other takes them.
714                not_null: false,
715            });
716        }
717        // Above a set operation there is nothing but the output columns, so an ORDER BY term is
718        // either a position, an output name, or an expression over the output, and never needs a
719        // column projected for it that the query did not ask for.
720        let keys = self.sort_keys(ast, query, &scope, &[])?;
721        if !keys.is_empty() {
722            let keys = self.plan.add_sort_keys(&keys);
723            node = self.add_node(Node::Sort { input: node, keys });
724        }
725        node = self.apply_limit(ast, query, node)?;
726        Ok((node, scope))
727    }
728
729    /// Projects one side of a set operation so that its columns have the agreed types.
730    fn conform(&mut self, node: NodeRef, scope: &Scope, types: &[LogicalType]) -> Result<NodeRef> {
731        if scope.columns.iter().zip(types).all(|(column, ty)| &column.ty == ty) {
732            return Ok(node);
733        }
734        let index = self.fresh_index();
735        let mut exprs = Vec::with_capacity(types.len());
736        let mut names = Vec::with_capacity(types.len());
737        for (column, ty) in scope.columns.iter().zip(types) {
738            let expr = self.plan.add_expr(Expr::Column(column.binding), column.ty.clone());
739            exprs.push(self.checked_cast_to(expr, ty, false)?);
740            names.push(self.plan.intern(&column.name));
741        }
742        let exprs = self.plan.add_expr_list(&exprs);
743        let names = self.plan.add_name_list(&names);
744        Ok(self.add_node(Node::Project { input: node, index, exprs, names }))
745    }
746
747    // ----------------------------------------------------------------- select
748
749    fn bind_select(
750        &mut self,
751        ast: &Ast,
752        select: ast::SelectRef,
753        query: &ast::Query,
754    ) -> Result<(NodeRef, Scope)> {
755        let written = ast.select(select);
756        // A window belongs to the block that wrote it, and a block can be bound inside another one
757        // without a subquery in between, so the outer block's runs are put aside for the duration
758        // rather than left where a nested block would append to them.
759        let outer_windows = std::mem::take(&mut self.windows);
760        let (mut node, input) = self.bind_from(ast, written.from)?;
761        node = self.attach_scalar_subqueries(node);
762
763        if written.filter != NONE {
764            self.clause = "WHERE clause";
765            let predicate = self.bind_expr(ast, written.filter, &input)?;
766            let predicate = self.as_boolean(predicate, "WHERE")?;
767            node = self.attach_scalar_subqueries(node);
768            node = self.add_node(Node::Filter { input: node, predicate });
769        }
770
771        let targets = ast.target_list(written.targets).to_vec();
772        if targets.is_empty() {
773            return Err(Error::binder("a SELECT needs at least one expression to select"));
774        }
775
776        let group_items = self.group_items(ast, &written, &targets)?;
777        let aggregating = !group_items.is_empty()
778            || written.having != NONE
779            || targets.iter().any(|target| has_aggregate(ast, target.expr));
780        if aggregating {
781            self.clause = "GROUP BY clause";
782            let mut groups = Vec::with_capacity(group_items.len());
783            for item in &group_items {
784                groups.push(self.bind_expr(ast, *item, &input)?);
785            }
786            let index = self.fresh_index();
787            self.aggregation = Some(Aggregation { index, groups, aggregates: Vec::new() });
788        }
789
790        self.clause = "SELECT clause";
791        let (mut exprs, mut names) = self.bind_targets(ast, &targets, &input)?;
792        let visible = exprs.len();
793
794        let mut having = None;
795        // The queries a `HAVING` wrote, which are joined in above the grouping rather than below
796        // it. TPC-H q11 is the case: `HAVING sum(ps_supplycost * ps_availqty) > (SELECT sum(...))`
797        // compares one group's total against a total over the whole table, and the second total is
798        // one row that has nothing to do with the groups. Joined underneath the grouping it would
799        // be a column of every input row and the grouping rule would ask for it in the GROUP BY,
800        // which is the complaint this used to make.
801        let mut above = Vec::new();
802        if written.having != NONE {
803            self.clause = "HAVING clause";
804            let before = self.scalar_subqueries.len();
805            let predicate = self.bind_expr(ast, written.having, &input)?;
806            // A correlated one still goes underneath, because what it correlates to is a column of
807            // the rows going into the grouping and there is nothing above the grouping to read.
808            for pending in self.scalar_subqueries.split_off(before) {
809                if pending.dependent {
810                    self.scalar_subqueries.push(pending);
811                } else {
812                    above.push(pending);
813                }
814            }
815            self.joined_above = above.iter().map(|pending| pending.index).collect();
816            let predicate = self.over_aggregate(predicate, &input)?;
817            // A mark join carries its comparison rather than the predicate carrying it, and that
818            // comparison is written over the outer rows, so it needs the same rewrite.
819            let mut rewritten = Vec::with_capacity(above.len());
820            for mut pending in above {
821                let conditions = std::mem::take(&mut pending.conditions);
822                let mut over = Vec::with_capacity(conditions.len());
823                for condition in conditions {
824                    over.push(self.over_aggregate(condition, &input)?);
825                }
826                pending.conditions = over;
827                rewritten.push(pending);
828            }
829            above = rewritten;
830            self.joined_above.clear();
831            having = Some(self.as_boolean(predicate, "HAVING")?);
832        }
833
834        // The projection's index has to exist before the sort keys are built, because a key is a
835        // reference to a projected column even when the expression it sorts on is not selected.
836        let project = self.fresh_index();
837        let mut output = Scope::empty();
838        for (at, (expr, name)) in exprs.iter().zip(&names).enumerate() {
839            output.push(Visible {
840                table: String::new(),
841                name: name.clone(),
842                binding: ColumnBinding::new(project, at as u32),
843                ty: self.plan.expr_type(*expr).clone(),
844                not_null: self.passes_through(*expr, &input),
845            });
846        }
847
848        self.clause = "ORDER BY clause";
849        let mut extra = Vec::new();
850        let keys = self.select_sort_keys(
851            ast, query, &input, &output, project, &mut exprs, &mut names, &mut extra,
852        )?;
853        if !extra.is_empty() && written.distinct != Distinct::No {
854            return Err(Error::binder(
855                "For SELECT DISTINCT, ORDER BY expressions must appear in the select list",
856            ));
857        }
858        let on = self.distinct_on(ast, written.distinct, &output)?;
859
860        node = self.attach_scalar_subqueries(node);
861
862        if let Some(aggregation) = self.aggregation.take() {
863            let index = aggregation.index;
864            let groups = self.plan.add_expr_list(&aggregation.groups);
865            let aggregates = self.plan.add_expr_list(&aggregation.aggregates);
866            node = self.add_node(Node::Aggregate { input: node, index, groups, aggregates });
867        }
868        if !above.is_empty() {
869            debug_assert!(self.scalar_subqueries.is_empty(), "a query is waiting to be joined");
870            self.scalar_subqueries = above;
871            node = self.attach_scalar_subqueries(node);
872        }
873        if let Some(predicate) = having {
874            node = self.add_node(Node::Filter { input: node, predicate });
875        }
876
877        // After the grouping and after `HAVING`, which is where the reference binary puts it:
878        // `SELECT j, sum(count(i)) OVER () FROM t GROUP BY j HAVING count(i) > 1` totals only the
879        // groups that survived the filter.
880        for run in std::mem::replace(&mut self.windows, outer_windows) {
881            let partition = self.plan.add_expr_list(&run.partition);
882            let order = self.plan.add_sort_keys(&run.order);
883            let expressions = self.plan.add_expr_list(&run.calls);
884            node = self.add_node(Node::Window {
885                input: node,
886                index: run.index,
887                partition,
888                order,
889                frame: run.frame,
890                expressions,
891            });
892        }
893
894        let interned: Vec<u32> = names.iter().map(|name| self.plan.intern(name)).collect();
895        let exprs_slice = self.plan.add_expr_list(&exprs);
896        let names_slice = self.plan.add_name_list(&interned);
897        node = self.add_node(Node::Project {
898            input: node,
899            index: project,
900            exprs: exprs_slice,
901            names: names_slice,
902        });
903
904        if written.distinct != Distinct::No {
905            let on = self.plan.add_expr_list(&on);
906            node = self.add_node(Node::Distinct { input: node, on });
907        }
908        if !keys.is_empty() {
909            let keys = self.plan.add_sort_keys(&keys);
910            node = self.add_node(Node::Sort { input: node, keys });
911        }
912        node = self.apply_limit(ast, query, node)?;
913
914        if extra.is_empty() {
915            output.columns.truncate(visible);
916            return Ok((node, output));
917        }
918        // An expression sorted on but not selected was carried this far to make the sort possible,
919        // and now it goes, because the query did not ask for it.
920        let index = self.fresh_index();
921        let mut kept = Vec::with_capacity(visible);
922        let mut kept_names = Vec::with_capacity(visible);
923        let mut scope = Scope::empty();
924        for (at, name) in names.iter().enumerate().take(visible) {
925            let ty = output.columns[at].ty.clone();
926            kept.push(self.column(project, at, ty.clone()));
927            kept_names.push(self.plan.intern(name));
928            scope.push(Visible {
929                table: String::new(),
930                name: name.clone(),
931                binding: ColumnBinding::new(index, at as u32),
932                ty,
933                not_null: output.columns[at].not_null,
934            });
935        }
936        let exprs = self.plan.add_expr_list(&kept);
937        let names = self.plan.add_name_list(&kept_names);
938        node = self.add_node(Node::Project { input: node, index, exprs, names });
939        Ok((node, scope))
940    }
941
942    /// Binds the target list, expanding every star into the columns it stands for.
943    fn bind_targets(
944        &mut self,
945        ast: &Ast,
946        targets: &[ast::Target],
947        input: &Scope,
948    ) -> Result<(Vec<ExprRef>, Vec<String>)> {
949        let mut exprs = Vec::with_capacity(targets.len());
950        let mut names = Vec::with_capacity(targets.len());
951        for target in targets {
952            if let ast::Expr::Star { qualifier, replacements } = ast.expr(target.expr) {
953                let table = ast.name(qualifier).last().map(str::to_string);
954                let expanded: Vec<Visible> =
955                    input.star(table.as_deref())?.into_iter().cloned().collect();
956                let replacements = ast.target_list(replacements).to_vec();
957                let mut used = vec![false; replacements.len()];
958                for column in expanded {
959                    let found = replacements.iter().zip(&mut used).find(|(replacement, _)| {
960                        same_name(ast.string(replacement.alias), &column.name)
961                    });
962                    // The replacement takes the column's place and its position, and it is named the
963                    // way the replace list spells it rather than the way the table does. That only
964                    // shows when the two differ in case, and `AS EventDate` over a column called
965                    // `eventdate` is exactly the case that shows it.
966                    let (expr, name) = match found {
967                        Some((replacement, used)) => {
968                            *used = true;
969                            let expr = self.bind_expr(ast, replacement.expr, input)?;
970                            (expr, ast.string(replacement.alias).to_string())
971                        }
972                        None => (
973                            self.plan.add_expr(Expr::Column(column.binding), column.ty),
974                            column.name,
975                        ),
976                    };
977                    exprs.push(self.over_aggregate(expr, input)?);
978                    names.push(name);
979                }
980                // A replace list that named something the star did not stand for is a mistake and
981                // not a no op, and it is caught here because this is the first point at which the
982                // set of names the star stands for is known.
983                if let Some((replacement, _)) =
984                    replacements.iter().zip(&used).find(|(_, used)| !**used)
985                {
986                    return Err(missing_replacement(ast.string(replacement.alias), input));
987                }
988                continue;
989            }
990            let expr = self.bind_expr(ast, target.expr, input)?;
991            exprs.push(self.over_aggregate(expr, input)?);
992            names.push(if target.alias == NONE {
993                self.output_name(ast, target.expr, input)
994            } else {
995                ast.string(target.alias).to_string()
996            });
997        }
998        Ok((exprs, names))
999    }
1000
1001    /// The name an unaliased target gets.
1002    ///
1003    /// A bare column keeps the spelling the table was created with rather than the spelling the
1004    /// query used, so `SELECT USERID FROM hits` has a column called `UserID`. Identifiers match
1005    /// without regard to case and the catalog is the one that holds the case.
1006    fn output_name(&self, ast: &Ast, target: ast::ExprRef, input: &Scope) -> String {
1007        if let ast::Expr::Column { name } = ast.expr(target) {
1008            let parts: Vec<&str> = ast.name(name).collect();
1009            if let Ok(found) = input.resolve(&parts) {
1010                return found.name.clone();
1011            }
1012        }
1013        describe(ast, target, self.semantics)
1014    }
1015
1016    /// The expressions a `GROUP BY` clause names, with positions and output aliases followed.
1017    fn group_items(
1018        &self,
1019        ast: &Ast,
1020        select: &ast::Select,
1021        targets: &[ast::Target],
1022    ) -> Result<Vec<ast::ExprRef>> {
1023        if select.group_by_all {
1024            // GROUP BY ALL means every target that is not itself an aggregate, which is the set
1025            // that would otherwise have to be written out again by hand.
1026            return Ok(targets
1027                .iter()
1028                .filter(|target| !has_aggregate(ast, target.expr))
1029                .map(|target| target.expr)
1030                .collect());
1031        }
1032        let mut items = Vec::new();
1033        for &item in ast.expr_list(select.group_by) {
1034            items.push(self.output_reference(ast, item, targets, "GROUP BY")?.unwrap_or(item));
1035        }
1036        Ok(items)
1037    }
1038
1039    /// The target a `GROUP BY` or `ORDER BY` term names, when it names one by position or alias.
1040    fn output_reference(
1041        &self,
1042        ast: &Ast,
1043        item: ast::ExprRef,
1044        targets: &[ast::Target],
1045        clause: &str,
1046    ) -> Result<Option<ast::ExprRef>> {
1047        match ast.expr(item) {
1048            ast::Expr::Literal { kind: LiteralKind::Number, text } => {
1049                let written = ast.string(text);
1050                let position: usize = written.parse().map_err(|_| {
1051                    Error::binder(format!("{clause} term {written} is not a column"))
1052                })?;
1053                if position == 0 || position > targets.len() {
1054                    return Err(Error::binder(format!(
1055                        "{clause} term out of range - should be between 1 and {}",
1056                        targets.len()
1057                    )));
1058                }
1059                Ok(Some(targets[position - 1].expr))
1060            }
1061            ast::Expr::Column { name } => {
1062                let parts: Vec<&str> = ast.name(name).collect();
1063                let [written] = parts.as_slice() else { return Ok(None) };
1064                let mut found = None;
1065                for target in targets {
1066                    if target.alias != NONE && same_name(ast.string(target.alias), written) {
1067                        if found.is_some() {
1068                            return Ok(None);
1069                        }
1070                        found = Some(target.expr);
1071                    }
1072                }
1073                Ok(found)
1074            }
1075            _ => Ok(None),
1076        }
1077    }
1078
1079    // -------------------------------------------------------------- modifiers
1080
1081    /// Sort keys for a select, projecting anything sorted on that is not already selected.
1082    #[allow(clippy::too_many_arguments)]
1083    fn select_sort_keys(
1084        &mut self,
1085        ast: &Ast,
1086        query: &ast::Query,
1087        input: &Scope,
1088        output: &Scope,
1089        project: u32,
1090        exprs: &mut Vec<ExprRef>,
1091        names: &mut Vec<String>,
1092        extra: &mut Vec<usize>,
1093    ) -> Result<Vec<SortKey>> {
1094        if query.order_by_all {
1095            return Ok(self.every_column(output));
1096        }
1097        let items = ast.order_list(query.order_by).to_vec();
1098        let mut keys = Vec::with_capacity(items.len());
1099        for item in items {
1100            self.check_order_literal(ast, item.expr)?;
1101            let position = match self.output_position(ast, item.expr, output)? {
1102                Some(position) => position,
1103                None => {
1104                    let bound = self.bind_expr(ast, item.expr, input)?;
1105                    let bound = self.over_aggregate(bound, input)?;
1106                    match exprs.iter().position(|&held| self.same_expr(held, bound)) {
1107                        Some(position) => position,
1108                        None => {
1109                            exprs.push(bound);
1110                            names.push(describe(ast, item.expr, self.semantics));
1111                            extra.push(exprs.len() - 1);
1112                            exprs.len() - 1
1113                        }
1114                    }
1115                }
1116            };
1117            let ty = self.plan.expr_type(exprs[position]).clone();
1118            let expr = self.column(project, position, ty);
1119            keys.push(self.sort_key(expr, item));
1120        }
1121        Ok(keys)
1122    }
1123
1124    /// Sort keys over an output that has nothing behind it to project, which is a set operation.
1125    fn sort_keys(
1126        &mut self,
1127        ast: &Ast,
1128        query: &ast::Query,
1129        output: &Scope,
1130        targets: &[ast::Target],
1131    ) -> Result<Vec<SortKey>> {
1132        if query.order_by_all {
1133            return Ok(self.every_column(output));
1134        }
1135        let items = ast.order_list(query.order_by).to_vec();
1136        let mut keys = Vec::with_capacity(items.len());
1137        for item in items {
1138            self.check_order_literal(ast, item.expr)?;
1139            let expr = match self.output_position(ast, item.expr, output)? {
1140                Some(position) => {
1141                    let column = &output.columns[position];
1142                    let (binding, ty) = (column.binding, column.ty.clone());
1143                    self.plan.add_expr(Expr::Column(binding), ty)
1144                }
1145                None => {
1146                    let _ = targets;
1147                    self.bind_expr(ast, item.expr, output)?
1148                }
1149            };
1150            keys.push(self.sort_key(expr, item));
1151        }
1152        Ok(keys)
1153    }
1154
1155    fn every_column(&mut self, output: &Scope) -> Vec<SortKey> {
1156        let columns: Vec<(ColumnBinding, LogicalType)> =
1157            output.columns.iter().map(|column| (column.binding, column.ty.clone())).collect();
1158        columns
1159            .into_iter()
1160            .map(|(binding, ty)| {
1161                let expr = self.plan.add_expr(Expr::Column(binding), ty);
1162                let descending = self.semantics.default_descending();
1163                SortKey { expr, descending, nulls_first: self.semantics.nulls_first(descending) }
1164            })
1165            .collect()
1166    }
1167
1168    /// A sort key with the session defaults filled in.
1169    fn sort_key(&self, expr: ExprRef, item: ast::OrderItem) -> SortKey {
1170        let descending = match item.order {
1171            Order::Unstated => self.semantics.default_descending(),
1172            Order::Ascending => false,
1173            Order::Descending => true,
1174        };
1175        let nulls_first = match item.nulls {
1176            Nulls::First => true,
1177            Nulls::Last => false,
1178            Nulls::Unstated => self.semantics.nulls_first(descending),
1179        };
1180        SortKey { expr, descending, nulls_first }
1181    }
1182
1183    /// Which output column a term names, by position or by name.
1184    fn output_position(
1185        &self,
1186        ast: &Ast,
1187        item: ast::ExprRef,
1188        output: &Scope,
1189    ) -> Result<Option<usize>> {
1190        match ast.expr(item) {
1191            ast::Expr::Literal { kind: LiteralKind::Number, text } => {
1192                let written = ast.string(text);
1193                if written.contains(['.', 'e', 'E']) {
1194                    return Ok(None);
1195                }
1196                let position: usize = written.parse().map_err(|_| {
1197                    Error::binder(format!("ORDER BY term {written} is not a column"))
1198                })?;
1199                if position == 0 || position > output.len() {
1200                    return Err(Error::binder(format!(
1201                        "ORDER BY term out of range - should be between 1 and {}",
1202                        output.len()
1203                    )));
1204                }
1205                Ok(Some(position - 1))
1206            }
1207            ast::Expr::Column { name } => {
1208                let parts: Vec<&str> = ast.name(name).collect();
1209                let [written] = parts.as_slice() else { return Ok(None) };
1210                Ok(output.position_of(None, written))
1211            }
1212            _ => Ok(None),
1213        }
1214    }
1215
1216    /// Refuses a literal sort key unless the session explicitly accepts its no-op behavior.
1217    fn check_order_literal(&self, ast: &Ast, item: ast::ExprRef) -> Result<()> {
1218        if !self.semantics.order_by_non_integer_literal()
1219            && matches!(
1220                ast.expr(item),
1221                ast::Expr::Literal { kind, text }
1222                    if kind != LiteralKind::Number
1223                        || ast.string(text).contains(['.', 'e', 'E'])
1224            )
1225        {
1226            return Err(Error::binder(
1227                "ORDER BY non-integer literal has no effect.\n* SET order_by_non_integer_literal=true to allow this behavior.",
1228            ));
1229        }
1230        Ok(())
1231    }
1232
1233    /// The expressions a `DISTINCT ON` names, which have to be columns of the output.
1234    fn distinct_on(
1235        &mut self,
1236        ast: &Ast,
1237        distinct: Distinct,
1238        output: &Scope,
1239    ) -> Result<Vec<ExprRef>> {
1240        let Distinct::On(items) = distinct else {
1241            return Ok(Vec::new());
1242        };
1243        let items = ast.expr_list(items).to_vec();
1244        let mut on = Vec::with_capacity(items.len());
1245        for item in items {
1246            let Some(position) = self.output_position(ast, item, output)? else {
1247                return Err(Error::not_implemented(
1248                    "DISTINCT ON an expression that is not in the select list",
1249                ));
1250            };
1251            let column = &output.columns[position];
1252            let (binding, ty) = (column.binding, column.ty.clone());
1253            on.push(self.plan.add_expr(Expr::Column(binding), ty));
1254        }
1255        Ok(on)
1256    }
1257
1258    fn apply_limit(&mut self, ast: &Ast, query: &ast::Query, input: NodeRef) -> Result<NodeRef> {
1259        if query.limit_percent {
1260            return Err(Error::not_implemented("LIMIT with a percentage"));
1261        }
1262        let count = self.constant_count(ast, query.limit, "LIMIT")?;
1263        let offset = self.constant_count(ast, query.offset, "OFFSET")?.unwrap_or(0);
1264        if count.is_none() && offset == 0 {
1265            return Ok(input);
1266        }
1267        Ok(self.add_node(Node::Limit { input, count, offset }))
1268    }
1269
1270    /// The row count a `LIMIT` or an `OFFSET` names, which has to be a constant.
1271    fn constant_count(
1272        &mut self,
1273        ast: &Ast,
1274        written: ast::ExprRef,
1275        clause: &str,
1276    ) -> Result<Option<u64>> {
1277        if written == NONE {
1278            return Ok(None);
1279        }
1280        self.clause = "LIMIT clause";
1281        let scope = Scope::empty();
1282        let bound = self.bind_expr(ast, written, &scope)?;
1283        let Expr::Constant(value) = *self.plan.expr(bound) else {
1284            return Err(Error::not_implemented(format!("a {clause} that is not a constant")));
1285        };
1286        let count = match self.plan.value(value) {
1287            Value::Null => return Ok(None),
1288            Value::TinyInt(count) => i128::from(*count),
1289            Value::SmallInt(count) => i128::from(*count),
1290            Value::Integer(count) => i128::from(*count),
1291            Value::BigInt(count) => i128::from(*count),
1292            Value::HugeInt(count) => *count,
1293            other => {
1294                return Err(Error::binder(format!(
1295                    "{clause} takes a whole number of rows, not a value of type {}",
1296                    other.logical_type()
1297                )));
1298            }
1299        };
1300        u64::try_from(count)
1301            .map(Some)
1302            .map_err(|_| Error::binder(format!("{clause} must not be negative")))
1303    }
1304
1305    // ------------------------------------------------------------------- from
1306
1307    fn bind_from(&mut self, ast: &Ast, from: ast::Slice) -> Result<(NodeRef, Scope)> {
1308        let sources = ast.source_list(from).to_vec();
1309        let Some((first, rest)) = sources.split_first() else {
1310            // No FROM clause is one row of no columns, which is what SELECT 1 sits on. Not an
1311            // empty table: an empty table would make SELECT 1 return nothing.
1312            return Ok((self.add_node(Node::Dummy), Scope::empty()));
1313        };
1314        let (mut node, mut scope) = self.bind_source(ast, *first)?;
1315        for source in rest {
1316            let (right, right_scope, correlations) = self.bind_lateral(ast, *source, &scope)?;
1317            node = if correlations.is_empty() {
1318                self.add_node(Node::CrossProduct { left: node, right })
1319            } else {
1320                let conditions = self.plan.add_expr_list(&[]);
1321                self.add_node(Node::DependentJoin {
1322                    left: node,
1323                    right,
1324                    kind: JoinKind::Inner,
1325                    conditions,
1326                })
1327            };
1328            scope = scope.concat(right_scope);
1329        }
1330        Ok((node, scope))
1331    }
1332
1333    /// Binds one FROM entry with everything written to its left already visible.
1334    ///
1335    /// That is what LATERAL means, and it is what a comma separated FROM does here whether the word
1336    /// was written or not, because the pinned build resolves `FROM o, (SELECT o.k + 1)` without it.
1337    /// The keyword therefore changes nothing and is accepted rather than acted on.
1338    ///
1339    /// The columns of the left that the entry read come back with it, and an entry that read none
1340    /// is an ordinary product. The rest are somebody else's: a name that resolved past the left
1341    /// neighbours belongs to an enclosing query, so it is handed up to whichever frame is waiting
1342    /// for it rather than counted here, or the subquery this FROM sits in would lose track of its
1343    /// own correlation.
1344    fn bind_lateral(
1345        &mut self,
1346        ast: &Ast,
1347        source: ast::SourceRef,
1348        left: &Scope,
1349    ) -> Result<(NodeRef, Scope, Vec<ColumnBinding>)> {
1350        self.lateral_scopes.push(self.outer_scopes.len());
1351        self.outer_scopes.push(left.clone());
1352        self.correlations.push(Vec::new());
1353        let bound = self.bind_source(ast, source);
1354        let read = self.correlations.pop().expect("correlation frame");
1355        self.outer_scopes.pop();
1356        self.lateral_scopes.pop();
1357        let (node, scope) = bound?;
1358
1359        let mut here = Vec::new();
1360        for binding in read {
1361            if left.columns.iter().any(|column| column.binding == binding) {
1362                here.push(binding);
1363            } else if let Some(enclosing) = self.correlations.last_mut() {
1364                if !enclosing.contains(&binding) {
1365                    enclosing.push(binding);
1366                }
1367            }
1368        }
1369        // A table function is allowed to read the left the same as anything else here. There is
1370        // nothing underneath one for the domain to be pushed into, since its arguments are what
1371        // produce its rows, so the unnesting pass turns it into a `LateralFunction` and the call is
1372        // made once per domain value. That is `domain.rs`.
1373        //
1374        // Nothing has to be turned down here for the functions that would not survive it. The only
1375        // table functions taking an argument that is not a name are the series family, which is the
1376        // family that operator answers, and a name that is not a constant is refused where the
1377        // columns are settled, because settling them means opening the file or reading the catalog.
1378        Ok((node, scope, here))
1379    }
1380
1381    fn bind_source(&mut self, ast: &Ast, source: ast::SourceRef) -> Result<(NodeRef, Scope)> {
1382        match ast.source(source) {
1383            ast::Source::Table { name, alias, columns } => {
1384                self.bind_table(ast, name, alias, columns)
1385            }
1386            ast::Source::Function { name, args, alias, columns, pragma } => {
1387                self.bind_table_function(ast, name, args, alias, columns, pragma)
1388            }
1389            ast::Source::Subquery { query, alias, columns } => {
1390                let (node, mut scope) = self.bind_query(ast, query)?;
1391                let label = if alias == NONE {
1392                    "unnamed_subquery".to_string()
1393                } else {
1394                    ast.string(alias).to_string()
1395                };
1396                scope.relabel(&label);
1397                if !columns.is_empty() {
1398                    let names: Vec<&str> = ast.name(columns).collect();
1399                    scope.rename(&names, &label)?;
1400                }
1401                Ok((node, scope))
1402            }
1403            ast::Source::Values { rows, alias, columns } => {
1404                let bare = ast::Query::bare(ast::QueryBody::Values(rows));
1405                let (node, mut scope) = self.bind_values(ast, &bare, rows)?;
1406                let label =
1407                    if alias == NONE { String::new() } else { ast.string(alias).to_string() };
1408                scope.relabel(&label);
1409                if !columns.is_empty() {
1410                    let names: Vec<&str> = ast.name(columns).collect();
1411                    scope.rename(&names, &label)?;
1412                }
1413                Ok((node, scope))
1414            }
1415            ast::Source::Cte { cte, alias, columns } => {
1416                self.bind_cte_scan(ast, cte, alias, columns)
1417            }
1418            ast::Source::Join { left, right, kind, natural, on, using } => {
1419                self.bind_join(ast, left, right, kind, natural, on, using)
1420            }
1421        }
1422    }
1423
1424    /// A read of a materialised `WITH`, which is a leaf the same way a table scan is.
1425    ///
1426    /// Which definition it reads was settled by the parser, so there is no name to look up here and
1427    /// no shadowing left to think about. What is looked up is the materialisation that definition
1428    /// turned into, and the search runs backwards because the same definition is bound again for
1429    /// each use of a plain `WITH` it sits inside, and a read means the innermost of those.
1430    fn bind_cte_scan(
1431        &mut self,
1432        ast: &Ast,
1433        written: u32,
1434        alias: ast::StrRef,
1435        columns: ast::Slice,
1436    ) -> Result<(NodeRef, Scope)> {
1437        let Some(held) = self.materialized.iter().rev().find(|held| held.written == written) else {
1438            let name = ast.string(ast.cte(written).name);
1439            return Err(Error::binder(format!("Table with name {name} does not exist!")));
1440        };
1441        let cte = held.cte;
1442        let fields = held.fields.clone();
1443        let text = held.name.clone();
1444        let label = if alias == NONE { text.clone() } else { ast.string(alias).to_string() };
1445        let name = self.plan.intern(&text);
1446        let index = self.fresh_index();
1447        let mut scope = Scope::empty();
1448        for (at, field) in fields.iter().enumerate() {
1449            scope.push(Visible {
1450                table: label.clone(),
1451                name: field.name.clone(),
1452                binding: ColumnBinding::new(index, at as u32),
1453                ty: field.ty.clone(),
1454                not_null: field.not_null,
1455            });
1456        }
1457        if !columns.is_empty() {
1458            let names: Vec<&str> = ast.name(columns).collect();
1459            scope.rename(&names, &label)?;
1460        }
1461        let columns = self.plan.add_fields(&fields);
1462        let node = self.add_node(Node::CteScan { index, cte, name, columns });
1463        Ok((node, scope))
1464    }
1465
1466    fn bind_table(
1467        &mut self,
1468        ast: &Ast,
1469        name: ast::Slice,
1470        alias: ast::StrRef,
1471        columns: ast::Slice,
1472    ) -> Result<(NodeRef, Scope)> {
1473        let parts: Vec<&str> = ast.name(name).collect();
1474        let catalog = self.catalog;
1475        // The catalog is asked first and the file is the fallback, which is the order DuckDB uses:
1476        // a table really called `mixed.parquet` wins over a file of that name sitting next to it.
1477        let resolved = match catalog.resolve(&parts) {
1478            Ok(resolved) => resolved,
1479            Err(missing) => {
1480                return self.bind_replacement_scan(ast, &parts, alias, columns, missing);
1481            }
1482        };
1483        if catalog.entry(&resolved)? == Entry::View {
1484            return self.bind_view(ast, &resolved, alias, columns);
1485        }
1486        let table = catalog.table(&resolved)?;
1487        let fields: Vec<Field> = table.columns().to_vec();
1488        let label =
1489            if alias == NONE { resolved.table.clone() } else { ast.string(alias).to_string() };
1490        let index = self.fresh_index();
1491        let mut scope = Scope::empty();
1492        for (at, field) in fields.iter().enumerate() {
1493            scope.push(Visible {
1494                table: label.clone(),
1495                name: field.name.clone(),
1496                binding: ColumnBinding::new(index, at as u32),
1497                ty: field.ty.clone(),
1498                not_null: field.not_null,
1499            });
1500        }
1501        if !columns.is_empty() {
1502            let names: Vec<&str> = ast.name(columns).collect();
1503            scope.rename(&names, &label)?;
1504        }
1505        let catalog_name = self.plan.intern(&resolved.catalog);
1506        let schema = self.plan.intern(&resolved.schema);
1507        let table_name = self.plan.intern(&resolved.table);
1508        let alias = self.plan.intern(&label);
1509        let columns = self.plan.add_fields(&fields);
1510        let node = self.add_node(Node::Get {
1511            catalog: catalog_name,
1512            schema,
1513            table: table_name,
1514            alias,
1515            index,
1516            columns,
1517        });
1518        Ok((node, scope))
1519    }
1520
1521    /// A view where a table goes, which is the body bound again right here.
1522    ///
1523    /// Inline and not behind a node. The view is gone by the time the plan exists, so everything
1524    /// downstream sees the query somebody would have written by hand, and the column pruning that
1525    /// makes `SELECT COUNT(*) FROM 'hits.parquet'` read no columns at all keeps working through
1526    /// `FROM hits`. A `Node::View` would be a barrier with nothing on the other side of it.
1527    ///
1528    /// The scope this builds is a subquery's, right down to the name in the error message. duckdb
1529    /// v1.5.1 reports a view whose column list has gone stale as `table "unnamed_subquery" has 1
1530    /// columns available but 2 columns specified`, which is the sentence its subquery alias rule
1531    /// produces, so a view there is a subquery with the view's name written over it afterwards.
1532    fn bind_view(
1533        &mut self,
1534        ast: &Ast,
1535        name: &QualifiedName,
1536        alias: ast::StrRef,
1537        columns: ast::Slice,
1538    ) -> Result<(NodeRef, Scope)> {
1539        let view = self.catalog.view(name)?;
1540        let full = name.to_string();
1541        if self.expanding.contains(&full) {
1542            // Two quotes each side, which is what the binary prints. It quotes the name on the way
1543            // in and then formats the quoted name into a quoted slot, so a view called `a` comes
1544            // back as `""a""`. That is upstream's wart and copying it is the whole job here.
1545            return Err(Error::binder(format!(
1546                "infinite recursion detected: attempting to recursively bind view \"\"{}\"\"",
1547                name.table
1548            )));
1549        }
1550        let body = parse_ast_with_case(view.sql(), self.semantics.identifier_case())?;
1551        let query = match body.statements.as_slice() {
1552            [ast::Statement::Query(query)] => *query,
1553            // Only a query can have got past the binder at creation, so this is a view the catalog
1554            // was handed some other way rather than anything a statement can produce.
1555            _ => return Err(Error::binder(format!("view \"{}\" is not a query", name.table))),
1556        };
1557        self.expanding.push(full);
1558        let bound = self.bind_query(&body, query);
1559        self.expanding.pop();
1560        let (node, mut scope) = bound?;
1561
1562        let aliases: Vec<&str> = view.aliases().iter().map(String::as_str).collect();
1563        if !aliases.is_empty() {
1564            scope.rename(&aliases, "unnamed_subquery")?;
1565        }
1566        // What the catalog tables report as this view's columns, written down here because this is
1567        // the moment they are known. Upstream refreshes the same cache at the same point, which was
1568        // measured: both `duckdb_columns()` and `duckdb_views().column_count` keep reporting the old
1569        // list after an `ALTER TABLE` underneath until something reads the view, and then both move.
1570        // It is written before the label and before the `AS t(a, b)` list below, because those two
1571        // rename the view for one query and not for everyone.
1572        view.remember(scope.fields());
1573        let label = if alias == NONE { name.table.clone() } else { ast.string(alias).to_string() };
1574        scope.relabel(&label);
1575        if !columns.is_empty() {
1576            let names: Vec<&str> = ast.name(columns).collect();
1577            scope.rename(&names, &label)?;
1578        }
1579        Ok((node, scope))
1580    }
1581
1582    /// A function call where a table goes, such as `range(10)`.
1583    ///
1584    /// The arguments are bound against an empty scope. A table function that can see the row on its
1585    /// left is `LATERAL`, and this is not it, so a column name in here is not resolved against
1586    /// whatever happens to be to the left in the `FROM` list. Letting it would mean `FROM t,
1587    /// range(t.n)` quietly binding to something whose meaning depends on the order the sources were
1588    /// written in.
1589    fn bind_table_function(
1590        &mut self,
1591        ast: &Ast,
1592        name: ast::Slice,
1593        args: ast::Slice,
1594        alias: ast::StrRef,
1595        columns: ast::Slice,
1596        pragma: bool,
1597    ) -> Result<(NodeRef, Scope)> {
1598        let parts: Vec<&str> = ast.name(name).collect();
1599        // A qualified call names a schema, and the two schemas that exist are the ones every
1600        // built-in lives in. Anything else is a name that has to fail rather than fall through to
1601        // the unqualified lookup and be found somewhere it was not asked for.
1602        let function_name = *parts.last().unwrap_or(&"");
1603        if let Some(schema) = parts.iter().rev().nth(1) {
1604            if !schema.eq_ignore_ascii_case("main") && !schema.eq_ignore_ascii_case("system") {
1605                return Err(Error::catalog(format!(
1606                    "Table Function with name {} does not exist!",
1607                    parts.join(".")
1608                )));
1609            }
1610        }
1611        // The name is looked up before the arguments are bound so that a call of something that is
1612        // not a table function says that, rather than reporting whatever is wrong with the
1613        // arguments of a function that was never going to exist.
1614        let Some(called) = TableFunction::lookup(function_name) else {
1615            if pragma {
1616                // `PRAGMA database_list` is a view upstream and not a function, and the pragma
1617                // namespace holds both, so a name that is not a function gets one more look in the
1618                // catalog before it is turned down. It has to be the no argument form: a view
1619                // takes none, and `pragma_database_list()` with parentheses is a missing function
1620                // on the pin too.
1621                if args.is_empty() && self.catalog.resolve(&parts).is_ok() {
1622                    return self.bind_table(ast, name, alias, columns);
1623                }
1624                let spelled = function_name.strip_prefix("pragma_").unwrap_or(function_name);
1625                return Err(Error::catalog(format!(
1626                    "Pragma Function with name {spelled} does not exist!"
1627                )));
1628            }
1629            return Err(Error::catalog(format!(
1630                "Table Function with name {function_name} does not exist!"
1631            )));
1632        };
1633        let written = ast.target_list(args).to_vec();
1634        let empty = Scope::empty();
1635        let previous = std::mem::replace(&mut self.clause, "table function arguments");
1636        let mut bound = Vec::new();
1637        let mut written_options = Vec::new();
1638        for argument in written {
1639            let expr = self.bind_expr(ast, argument.expr, &empty)?;
1640            if argument.alias == NONE {
1641                bound.push(expr);
1642            } else {
1643                let name = ast.string(argument.alias).to_string();
1644                let (parameter, value) = self.named_argument(called, &name, expr)?;
1645                written_options.push((parameter, value, expr));
1646            }
1647        }
1648        self.clause = previous;
1649        let options = Options::of(&written_options)?;
1650
1651        // The types are what resolve the call, not the count, because `read_parquet(3)` is a
1652        // different answer from `read_parquet('3')` and only the types tell them apart.
1653        let given: Vec<LogicalType> =
1654            bound.iter().map(|&expr| self.plan.expr_type(expr).clone()).collect();
1655        let resolved = if pragma {
1656            resolve_pragma(function_name, &given)?
1657        } else {
1658            resolve_table(function_name, &given)?
1659        };
1660        let mut cast: Vec<ExprRef> = bound
1661            .iter()
1662            .zip(&resolved.arguments)
1663            .map(|(&expr, ty)| self.checked_cast_to(expr, ty, false))
1664            .collect::<Result<_>>()?;
1665
1666        if resolved.function.takes_a_name() {
1667            let Columns::Fixed(fields) = resolved.columns else {
1668                return Err(Error::internal("a pragma that resolved to a file"));
1669            };
1670            let [argument] = cast[..] else {
1671                return Err(Error::internal("a pragma that resolved to more than one name"));
1672            };
1673            return self.bind_pragma(ast, resolved.function, &fields, argument, alias, columns);
1674        }
1675        let fields = match resolved.columns {
1676            Columns::Fixed(fields) => fields,
1677            columns => {
1678                // The one argument is a pattern, and what replaces it is one constant per file it
1679                // matched. The executor is handed names rather than a pattern, so it never walks a
1680                // directory and the answer cannot change between binding a prepared statement and
1681                // running it, which is the same reason the schema is settled here.
1682                let paths = self.file_paths(cast[0], resolved.function.name())?;
1683                let first = paths.first().map_or("", String::as_str);
1684                let mut fields = match columns {
1685                    // Parquet takes the first file's footer as the answer and CSV sniffs all of
1686                    // them, which is not a choice made here. See `csv_fields`.
1687                    Columns::Csv => csv_fields(&paths, options.given)?,
1688                    _ => parquet_fields(first)?,
1689                };
1690                if options.all_varchar {
1691                    // The sniffer still ran, because the names come out of the same pass over the
1692                    // front of the file and only the types are being overruled. The executor reads
1693                    // the text as VARCHAR because this is the schema it is told to read into, which
1694                    // is the same road a file in a glob takes when the set is wider than the file.
1695                    for field in &mut fields {
1696                        field.ty = LogicalType::Varchar;
1697                    }
1698                }
1699                if options.binary_as_string {
1700                    // A byte array column with no annotation on it is a BLOB, and this is the caller
1701                    // saying that the file's writer meant text. The reader already holds both in the
1702                    // same string column and already validates the bytes, so the whole of the option
1703                    // is what the column is called from here on.
1704                    for field in &mut fields {
1705                        if field.ty == LogicalType::Blob {
1706                            field.ty = LogicalType::Varchar;
1707                        }
1708                    }
1709                }
1710                if options.file_row_number {
1711                    // Not a column of the file, so it goes on the end where a projection cannot be
1712                    // confused about which one it is, and the executor counts it as the rows come
1713                    // out. A file that already has a column of that name is the one case where the
1714                    // option cannot be honoured, and saying so is better than handing back two
1715                    // columns with the same name and letting a reference to it pick one.
1716                    if fields.iter().any(|field| field.name == FILE_ROW_NUMBER) {
1717                        return Err(Error::binder(format!(
1718                            "Duplicate column name \"{FILE_ROW_NUMBER}\": the file already has a \
1719                             column of that name, so file_row_number cannot add one"
1720                        )));
1721                    }
1722                    fields.push(Field::required(FILE_ROW_NUMBER.to_string(), LogicalType::BigInt));
1723                }
1724                cast = paths.iter().map(|path| self.path_constant(path)).collect();
1725                fields
1726            }
1727        };
1728        let label = if alias == NONE {
1729            resolved.function.name().to_string()
1730        } else {
1731            ast.string(alias).to_string()
1732        };
1733        let names: Vec<&str> = ast.name(columns).collect();
1734        self.table_function_source(
1735            resolved.function,
1736            &cast,
1737            &written_options,
1738            fields,
1739            &label,
1740            &names,
1741        )
1742    }
1743
1744    /// `pragma_table_info('t')` or `pragma_show('t')`, answered while it is bound.
1745    ///
1746    /// The same trick `DESCRIBE` uses and for the same reason: the columns of a table are settled by
1747    /// the time the name has resolved, so the rows are a constant from there on and this comes out
1748    /// as a `VALUES` rather than as an operator that reads a catalog while the query runs. It also
1749    /// means `SELECT name FROM pragma_table_info('t') WHERE notnull` is an ordinary query over an
1750    /// ordinary relation, which is the whole reason these exist as functions rather than only as
1751    /// statements.
1752    ///
1753    /// The name arrives as a string rather than as something the parser read, so it is split here
1754    /// under the identifier rule and then resolved like any other name. A name that is not there
1755    /// comes back as the catalog's own complaint, which is what the pin answers with too.
1756    fn bind_pragma(
1757        &mut self,
1758        ast: &Ast,
1759        function: TableFunction,
1760        fields: &[Field],
1761        argument: ExprRef,
1762        alias: ast::StrRef,
1763        columns: ast::Slice,
1764    ) -> Result<(NodeRef, Scope)> {
1765        let written = self.pragma_name(argument, function)?;
1766        let parts = identifier_parts(&written);
1767        let spelled: Vec<&str> = parts.iter().map(String::as_str).collect();
1768        let name = self.catalog.resolve(&spelled)?;
1769        let described = self.described(ast, &name)?;
1770        let mut rows = Vec::with_capacity(described.len());
1771        for (at, field) in described.iter().enumerate() {
1772            let items = if matches!(function, TableFunction::PragmaShow) {
1773                self.describing(field)
1774            } else {
1775                self.table_info(at, field)
1776            };
1777            rows.push(self.plan.add_expr_list(&items));
1778        }
1779        let rows = self.plan.add_rows(&rows);
1780        let held = self.plan.add_fields(fields);
1781        let index = self.fresh_index();
1782        let node = self.add_node(Node::Values { index, columns: held, rows });
1783        let label =
1784            if alias == NONE { function.name().to_string() } else { ast.string(alias).to_string() };
1785        let mut scope = Scope::empty();
1786        for (at, field) in fields.iter().enumerate() {
1787            scope.push(Visible {
1788                table: label.clone(),
1789                name: field.name.clone(),
1790                binding: ColumnBinding::new(index, at as u32),
1791                ty: field.ty.clone(),
1792                not_null: false,
1793            });
1794        }
1795        if !columns.is_empty() {
1796            let names: Vec<&str> = ast.name(columns).collect();
1797            scope.rename(&names, &label)?;
1798        }
1799        Ok((node, scope))
1800    }
1801
1802    /// The name a pragma was called with, which has to be a constant.
1803    ///
1804    /// A null is a name spelled `NULL` rather than an error about nulls, because the pin turns
1805    /// whatever it was handed into text before it goes looking and then says a table of that name
1806    /// does not exist. Writing `pragma_table_info(NULL)` is a mistake either way and this is the
1807    /// sentence the mistake already has.
1808    ///
1809    /// `pragma_table_info('t' || 'x')` is the pin's `tx` and is turned away here, which is the same
1810    /// missing constant folding [`Binder::named_argument`] writes about and closes the same day.
1811    fn pragma_name(&self, argument: ExprRef, function: TableFunction) -> Result<String> {
1812        let Expr::Constant(reference) = *self.plan.expr(argument) else {
1813            return Err(Error::not_implemented(format!(
1814                "{}() given a name that is not a constant",
1815                function.name()
1816            )));
1817        };
1818        match self.plan.value(reference) {
1819            Value::Varchar(name) => Ok(name.clone()),
1820            Value::Null => Ok("NULL".to_string()),
1821            other => {
1822                Err(Error::internal(format!("a pragma name bound as VARCHAR arrived as {other}")))
1823            }
1824        }
1825    }
1826
1827    /// The columns of whatever a pragma was pointed at.
1828    ///
1829    /// A view is bound here, which is how it comes to have columns at all. Reading a view is what
1830    /// binds it and describing one counts as reading it, so a view the engine ships with reports a
1831    /// column count from this point on, the same as it would after a select. The node that binding
1832    /// produces is thrown away, because the answer is the scope and not the query.
1833    ///
1834    /// Every column of a view is nullable whatever the column underneath was declared as, which is
1835    /// the pin's answer through `pragma_table_info()`, `pragma_show()` and `duckdb_columns()` alike.
1836    /// [`Scope::fields`] drops the flag on its own, so there is nothing to clear here.
1837    fn described(&mut self, ast: &Ast, name: &QualifiedName) -> Result<Vec<Field>> {
1838        if self.catalog.entry(name)? == Entry::Table {
1839            return Ok(self.catalog.table(name)?.columns().to_vec());
1840        }
1841        let (_, scope) = self.bind_view(ast, name, NONE, ast::Slice::default())?;
1842        Ok(scope.fields())
1843    }
1844
1845    /// One row of `pragma_show()`, which is one row of `DESCRIBE` written by the other caller.
1846    fn describing(&mut self, field: &Field) -> Vec<ExprRef> {
1847        let written = [
1848            field.name.clone(),
1849            field.ty.to_string(),
1850            if field.not_null { "NO" } else { "YES" }.to_owned(),
1851        ];
1852        let mut items: Vec<ExprRef> =
1853            written.into_iter().map(|text| self.plan.add_constant(Value::Varchar(text))).collect();
1854        for _ in 0..3 {
1855            let empty = self.plan.add_constant(Value::Null);
1856            items.push(self.cast_to(empty, &LogicalType::Varchar));
1857        }
1858        items
1859    }
1860
1861    /// One row of `pragma_table_info()`, which is SQLite's six columns about the same column.
1862    ///
1863    /// `cid` counts from zero, which is SQLite's numbering and not the one based `ordinal_position`
1864    /// the standard views report. `dflt_value` and `pk` are the two nothings rudb has to report
1865    /// until `CREATE TABLE` takes a `DEFAULT` or a key.
1866    fn table_info(&mut self, at: usize, field: &Field) -> Vec<ExprRef> {
1867        let cid = self.plan.add_constant(Value::Integer(i32::try_from(at).unwrap_or(i32::MAX)));
1868        let name = self.plan.add_constant(Value::Varchar(field.name.clone()));
1869        let ty = self.plan.add_constant(Value::Varchar(field.ty.to_string()));
1870        let not_null = self.plan.add_constant(Value::Boolean(field.not_null));
1871        let default = self.plan.add_constant(Value::Null);
1872        let default = self.cast_to(default, &LogicalType::Varchar);
1873        let key = self.plan.add_constant(Value::Boolean(false));
1874        vec![cid, name, ty, not_null, default, key]
1875    }
1876
1877    /// One named parameter of a table function call, folded into what the call was given.
1878    ///
1879    /// The value has to be a constant of the type the parameter wants. It has to be constant
1880    /// because an option can decide what the columns are and the columns are settled here, and it
1881    /// has to be already of the type because there is no constant folding in front of the binder
1882    /// yet. DuckDB folds first, so `binary_as_string=1` and `binary_as_string='yes'` are both true
1883    /// there and both are turned away here, which is a gap that closes on its own the day the
1884    /// optimizer runs before the plan is finished. `binary_as_string=True` is what the ClickBench
1885    /// entry writes and is what has to work.
1886    ///
1887    /// A name that is not a parameter of this function is the binary's sentence followed by what it
1888    /// could have been. The binary puts the candidates on their own indented lines and this puts
1889    /// them on the same line, because an error is one line here.
1890    fn named_argument(
1891        &mut self,
1892        function: TableFunction,
1893        name: &str,
1894        expr: ExprRef,
1895    ) -> Result<(&'static str, Value)> {
1896        let known = function
1897            .parameters()
1898            .iter()
1899            .find(|(parameter, _)| parameter.eq_ignore_ascii_case(name));
1900        let Some((parameter, wanted)) = known else {
1901            let candidates: Vec<String> = function
1902                .parameters()
1903                .iter()
1904                .map(|(parameter, ty)| format!("    {parameter} {ty}"))
1905                .collect();
1906            return Err(Error::binder(format!(
1907                "Invalid named parameter \"{name}\" for function {}\nCandidates:\n{}\n",
1908                function.name(),
1909                candidates.join("\n")
1910            )));
1911        };
1912        let Expr::Constant(reference) = *self.plan.expr(expr) else {
1913            return Err(Error::not_implemented(format!(
1914                "the named parameter {parameter} with a value that is not a constant"
1915            )));
1916        };
1917        let value = self.plan.value(reference).clone();
1918        if value == Value::Null {
1919            return Err(Error::binder(null_parameter(function, parameter)));
1920        }
1921        let given = self.plan.expr_type(expr).clone();
1922        if given != *wanted {
1923            return Err(Error::not_implemented(format!(
1924                "the named parameter {parameter} given a {given} where a {wanted} was wanted"
1925            )));
1926        }
1927        Ok((parameter, value))
1928    }
1929
1930    /// A file where a table name goes, which is what DuckDB calls a replacement scan.
1931    ///
1932    /// `SELECT * FROM 'hits.parquet'` is how most DuckDB queries in the wild are written, ClickBench
1933    /// among them, so this is not sugar over `read_parquet` so much as the spelling people use. The
1934    /// catalog has already been asked and has already said no, and `missing` is what it said, so a
1935    /// name that is not a file comes back with the catalog's own answer rather than with a complaint
1936    /// about files.
1937    ///
1938    /// Only a single unqualified name is a candidate. A qualified one names a schema and a schema
1939    /// that does not exist is not a path.
1940    fn bind_replacement_scan(
1941        &mut self,
1942        ast: &Ast,
1943        parts: &[&str],
1944        alias: ast::StrRef,
1945        columns: ast::Slice,
1946        missing: Error,
1947    ) -> Result<(NodeRef, Scope)> {
1948        let [path] = parts else { return Err(missing) };
1949        let path = *path;
1950        let extension = path.rsplit_once('.').map(|(_, after)| after).unwrap_or_default();
1951        let Some(function) = Self::reader_for(extension) else {
1952            if is_file(path) {
1953                // A file that is really there and that nothing here can read is a different mistake
1954                // from a name that is not a file, and DuckDB says so with both lines, the second of
1955                // which is the way out. A file with no dot in it lands here too, which is why the
1956                // test is on the extension having a reader rather than on there being an extension.
1957                return Err(Error::binder(format!(
1958                    "No extension found that is capable of reading the file \"{path}\"\n* If this \
1959                     file is a supported file format you can explicitly use the reader functions, \
1960                     such as read_csv, read_json or read_parquet"
1961                )));
1962            }
1963            return Err(missing);
1964        };
1965        // The pattern is expanded before it is known to match anything, so a name that ends in .csv
1966        // and is not there gives the reader's own message rather than the catalog's. That is
1967        // DuckDB's order and it is the helpful one: somebody who wrote a file name wants to hear
1968        // about the file.
1969        let paths = files(path)?;
1970        let first = paths.first().map_or("", String::as_str);
1971        let fields = match function {
1972            TableFunction::ReadParquet => parquet_fields(first)?,
1973            _ => csv_fields(&paths, Given::default())?,
1974        };
1975        // The name the columns answer to is the file's stem, so `SELECT mixed.a FROM
1976        // 'data/mixed.parquet'` works. That is DuckDB's choice and it is the useful one, since the
1977        // alternative is a table name with a dot and a slash in it that nothing can write. A pattern
1978        // keeps the whole of what was written instead, which is DuckDB's choice too and was
1979        // measured: there is no stem to take when the name stands for a directory full of files.
1980        let label = if alias == NONE {
1981            if is_pattern(path) {
1982                path.to_string()
1983            } else {
1984                let file = path.rsplit_once('/').map_or(path, |(_, file)| file);
1985                file.rsplit_once('.').map_or(file, |(stem, _)| stem).to_string()
1986            }
1987        } else {
1988            ast.string(alias).to_string()
1989        };
1990        let arguments: Vec<ExprRef> = paths.iter().map(|path| self.path_constant(path)).collect();
1991        let names: Vec<&str> = ast.name(columns).collect();
1992        self.table_function_source(function, &arguments, &[], fields, &label, &names)
1993    }
1994
1995    /// One file name, as a constant expression in the plan.
1996    fn path_constant(&mut self, path: &str) -> ExprRef {
1997        let value = self.plan.add_value(Value::Varchar(path.to_string()));
1998        self.plan.add_expr(Expr::Constant(value), LogicalType::Varchar)
1999    }
2000
2001    /// The table function a file with this extension is read by, and `None` for one nothing reads.
2002    ///
2003    /// Both spellings of a tab separated file go to the CSV reader, which is not a shortcut: the
2004    /// extension picks the reader and the reader sniffs the punctuation, so a `.tsv` file that holds
2005    /// commas is read as commas. That was measured rather than assumed. The comparison ignores case
2006    /// because `UP.CSV` reads in duckdb v1.4.1.
2007    fn reader_for(extension: &str) -> Option<TableFunction> {
2008        if extension.eq_ignore_ascii_case("parquet") {
2009            return Some(TableFunction::ReadParquet);
2010        }
2011        if extension.eq_ignore_ascii_case("csv") || extension.eq_ignore_ascii_case("tsv") {
2012            return Some(TableFunction::ReadCsv);
2013        }
2014        None
2015    }
2016
2017    /// The node and the scope of a table function call whose arguments and columns are settled.
2018    ///
2019    /// The half a written out call shares with a replacement scan, which is everything after the
2020    /// question of what the file is called has been answered one way or the other.
2021    fn table_function_source(
2022        &mut self,
2023        function: TableFunction,
2024        args: &[ExprRef],
2025        written: &[(&'static str, Value, ExprRef)],
2026        fields: Vec<Field>,
2027        label: &str,
2028        names: &[&str],
2029    ) -> Result<(NodeRef, Scope)> {
2030        let index = self.fresh_index();
2031        let mut scope = Scope::empty();
2032        for (at, field) in fields.iter().enumerate() {
2033            scope.push(Visible {
2034                table: label.to_string(),
2035                name: field.name.clone(),
2036                binding: ColumnBinding::new(index, at as u32),
2037                ty: field.ty.clone(),
2038                // A reader takes what the file has, and no file format this reads says a column
2039                // cannot be null. The reference binary answers YES for every column of a Parquet.
2040                not_null: false,
2041            });
2042        }
2043        if !names.is_empty() {
2044            scope.rename(names, label)?;
2045        }
2046        let function = self.plan.intern(function.name());
2047        let args = self.plan.add_expr_list(args);
2048        let named: Vec<u32> =
2049            written.iter().map(|(parameter, _, _)| self.plan.intern(parameter)).collect();
2050        let settings: Vec<ExprRef> = written.iter().map(|(_, _, expr)| *expr).collect();
2051        let options = self.plan.add_name_list(&named);
2052        let settings = self.plan.add_expr_list(&settings);
2053        let columns = self.plan.add_fields(&fields);
2054        let node = self.add_node(Node::TableFunction {
2055            index,
2056            function,
2057            args,
2058            options,
2059            settings,
2060            columns,
2061        });
2062        Ok((node, scope))
2063    }
2064
2065    /// Every file a table function's file argument names, in the order they were written.
2066    ///
2067    /// Each pattern has to find at least one file of its own, which is DuckDB's rule and is why
2068    /// this expands one at a time rather than gathering everything and looking at the total. A
2069    /// list keeps its written order and its duplicates, so a file named twice is read twice, which
2070    /// was measured: the sort and the dedup belong to one pattern rather than to the list.
2071    fn file_paths(&self, expr: ExprRef, name: &str) -> Result<Vec<String>> {
2072        let mut paths = Vec::new();
2073        for pattern in self.file_patterns(expr, name)? {
2074            paths.extend(files(&pattern)?);
2075        }
2076        Ok(paths)
2077    }
2078
2079    /// The patterns a table function argument names, which have to be constants.
2080    ///
2081    /// A table function that reads a file is resolved by opening the file, and that happens here
2082    /// rather than when the query runs, because the rest of the statement cannot bind until the
2083    /// column names are known. So the path has to be something this binder can work out without
2084    /// running anything, and a literal is that. DuckDB folds a constant expression first, so
2085    /// `read_parquet('a' || '.parquet')` works there, and folding is M1 work that this will pick up
2086    /// for free once the optimizer runs before the plan is finished rather than after.
2087    ///
2088    /// One string is one pattern and a list is one pattern an item, which is DuckDB's pair of
2089    /// overloads. A null is a different sentence in each of them, both of them measured.
2090    fn file_patterns(&self, expr: ExprRef, name: &str) -> Result<Vec<String>> {
2091        let Expr::Constant(reference) = *self.plan.expr(expr) else {
2092            return Err(Error::not_implemented(
2093                "a table function file name that is not a constant",
2094            ));
2095        };
2096        match self.plan.value(reference) {
2097            Value::Varchar(path) => Ok(vec![path.clone()]),
2098            // DuckDB's own wording, which says list because its other overload takes one.
2099            Value::Null => Err(Error::parser(format!("{name} cannot take NULL list as parameter"))),
2100            Value::List { values, .. } => values
2101                .iter()
2102                .map(|value| match value {
2103                    Value::Varchar(path) => Ok(path.clone()),
2104                    _ => Err(Error::parser(format!(
2105                        "{name} reader cannot take NULL input as parameter"
2106                    ))),
2107                })
2108                .collect(),
2109            other => {
2110                Err(Error::internal(format!("a file name bound as VARCHAR arrived as {other}")))
2111            }
2112        }
2113    }
2114
2115    #[allow(clippy::too_many_arguments)]
2116    fn bind_join(
2117        &mut self,
2118        ast: &Ast,
2119        left: ast::SourceRef,
2120        right: ast::SourceRef,
2121        kind: ast::JoinKind,
2122        natural: bool,
2123        on: ast::ExprRef,
2124        using: ast::Slice,
2125    ) -> Result<(NodeRef, Scope)> {
2126        let (left_node, left_scope) = self.bind_source(ast, left)?;
2127        let (right_node, right_scope, correlated) = self.bind_lateral(ast, right, &left_scope)?;
2128        // A row of the right side exists only for the left row it was evaluated against, so a kind
2129        // that has to produce right rows with no left row has nothing to produce them from. The
2130        // pinned build says this and names only the two kinds that work.
2131        if !correlated.is_empty()
2132            && !matches!(kind, ast::JoinKind::Inner | ast::JoinKind::Cross | ast::JoinKind::Left)
2133        {
2134            return Err(Error::binder(
2135                "The combining JOIN type must be INNER or LEFT for a LATERAL reference",
2136            ));
2137        }
2138        let split = left_scope.len();
2139        let mut scope = left_scope.concat(right_scope);
2140
2141        // NATURAL is USING over whatever both sides happen to call the same thing, which is why it
2142        // is resolved here and never reaches the plan as its own idea.
2143        let merged: Vec<String> = if natural {
2144            let mut names = Vec::new();
2145            for (at, column) in scope.columns.iter().enumerate().take(split) {
2146                if scope.columns[split..].iter().any(|right| same_name(&right.name, &column.name))
2147                    && !names.iter().any(|held: &String| same_name(held, &column.name))
2148                {
2149                    let _ = at;
2150                    names.push(column.name.clone());
2151                }
2152            }
2153            names
2154        } else {
2155            // A name written twice is one column, not two. `USING (id, id)` is legal and means what
2156            // `USING (id)` means, and the reference binary agrees. Taking it twice would build the
2157            // same equality twice and, worse, drop the right side's copy twice, which takes a
2158            // column out of the answer that nobody named and runs off the end of the scope when the
2159            // copy was the last column in it.
2160            let mut names: Vec<String> = Vec::new();
2161            for name in ast.name(using) {
2162                if !names.iter().any(|held| same_name(held, name)) {
2163                    names.push(name.to_string());
2164                }
2165            }
2166            names
2167        };
2168
2169        let mut conditions = Vec::new();
2170        let mut dropped = Vec::new();
2171        for name in &merged {
2172            let left_at = scope.columns[..split]
2173                .iter()
2174                .position(|column| same_name(&column.name, name))
2175                .ok_or_else(|| {
2176                    Error::binder(format!(
2177                        "column \"{name}\" specified in USING clause does not exist in left table"
2178                    ))
2179                })?;
2180            let right_at = scope.columns[split..]
2181                .iter()
2182                .position(|column| same_name(&column.name, name))
2183                .map(|at| at + split)
2184                .ok_or_else(|| {
2185                    Error::binder(format!(
2186                        "column \"{name}\" specified in USING clause does not exist in right table"
2187                    ))
2188                })?;
2189            let left_column = &scope.columns[left_at];
2190            let (left_binding, left_type) = (left_column.binding, left_column.ty.clone());
2191            let right_column = &scope.columns[right_at];
2192            let (right_binding, right_type) = (right_column.binding, right_column.ty.clone());
2193            let left_expr = self.plan.add_expr(Expr::Column(left_binding), left_type);
2194            let right_expr = self.plan.add_expr(Expr::Column(right_binding), right_type);
2195            conditions.push(self.compare(rudb_plan::CompareOp::Equal, left_expr, right_expr)?);
2196            dropped.push(right_at);
2197        }
2198        // A joined-on column appears once, so the right side's copy goes. Dropping from the back
2199        // keeps the positions of the ones still to drop correct.
2200        dropped.sort_unstable();
2201        for at in dropped.into_iter().rev() {
2202            scope.remove(at);
2203        }
2204
2205        if on != NONE {
2206            if !merged.is_empty() {
2207                return Err(Error::binder("a join cannot have both ON and USING"));
2208            }
2209            self.clause = "JOIN condition";
2210            let predicate = self.bind_expr(ast, on, &scope)?;
2211            conditions.push(self.as_boolean(predicate, "JOIN")?);
2212        }
2213
2214        if kind == ast::JoinKind::Cross && !conditions.is_empty() {
2215            return Err(Error::binder("a CROSS JOIN cannot have a condition"));
2216        }
2217        // A product is the join with nothing to join on, and it is not one when the right side has
2218        // to be evaluated per left row, because then there is a dependency to lower even though
2219        // there is no condition to test.
2220        if correlated.is_empty()
2221            && conditions.is_empty()
2222            && matches!(kind, ast::JoinKind::Cross | ast::JoinKind::Inner)
2223        {
2224            let node = self.add_node(Node::CrossProduct { left: left_node, right: right_node });
2225            return Ok((node, scope));
2226        }
2227        // A semi join and an anti join ask a question about the right side rather than producing
2228        // any of it, so what is in scope after one is the left side alone. The condition is bound
2229        // above and is the last thing that can name the right side. Without this, `SELECT *` over
2230        // one expanded to both sides and the projection asked a join whose output is the left side
2231        // for columns it does not have, which came out as an internal error about a column not
2232        // being in the schema. That is tamnd/rudb#847. The reference binary refuses `b.w` here with
2233        // a binder error naming `a` as the only candidate table, which is the same rule said from
2234        // the other end.
2235        if matches!(kind, ast::JoinKind::Semi | ast::JoinKind::Anti) {
2236            scope.truncate(split);
2237        }
2238        let kind = match kind {
2239            ast::JoinKind::Inner | ast::JoinKind::Cross => JoinKind::Inner,
2240            ast::JoinKind::Left => JoinKind::Left,
2241            ast::JoinKind::Right => JoinKind::Right,
2242            ast::JoinKind::Full => JoinKind::Full,
2243            ast::JoinKind::Semi => JoinKind::Semi,
2244            ast::JoinKind::Anti => JoinKind::Anti,
2245            ast::JoinKind::Positional => JoinKind::Positional,
2246        };
2247        let conditions = self.plan.add_expr_list(&conditions);
2248        let node = if correlated.is_empty() {
2249            self.add_node(Node::Join {
2250                left: left_node,
2251                right: right_node,
2252                kind,
2253                conditions,
2254                build: BuildSide::default(),
2255            })
2256        } else {
2257            self.add_node(Node::DependentJoin {
2258                left: left_node,
2259                right: right_node,
2260                kind,
2261                conditions,
2262            })
2263        };
2264        Ok((node, scope))
2265    }
2266
2267    // -------------------------------------------------------------- aggregates
2268
2269    /// Binds a `FILTER (WHERE ...)` predicate, or says there was none.
2270    ///
2271    /// The predicate is a condition over the input rows and not over the answer, so it is bound in
2272    /// the scope the arguments are bound in, and it is cast to `BOOLEAN` the way a `WHERE` is:
2273    /// `FILTER (WHERE i)` over an integer column is a filter on whether the integer is not zero.
2274    fn bind_filter(
2275        &mut self,
2276        ast: &Ast,
2277        filter: ast::ExprRef,
2278        scope: &Scope,
2279    ) -> Result<Option<ExprRef>> {
2280        if filter == NONE {
2281            return Ok(None);
2282        }
2283        let bound = self.bind_expr(ast, filter, scope)?;
2284        Ok(Some(self.checked_cast_to(bound, &LogicalType::Boolean, false)?))
2285    }
2286
2287    /// Binds an aggregate call, records it, and hands back a reference to where its result lands.
2288    pub(crate) fn bind_aggregate(
2289        &mut self,
2290        ast: &Ast,
2291        name: &str,
2292        args: &[ast::ExprRef],
2293        distinct: bool,
2294        filter: ast::ExprRef,
2295        scope: &Scope,
2296    ) -> Result<ExprRef> {
2297        if self.in_filter {
2298            return Err(Error::binder("aggregate functions are not allowed in FILTER"));
2299        }
2300        if self.in_aggregate {
2301            return Err(Error::binder(format!(
2302                "aggregate function calls cannot be nested, and {name}() is inside one"
2303            )));
2304        }
2305        if self.aggregation.is_none() {
2306            return Err(Error::binder(format!(
2307                "aggregate function calls cannot be used in the {}",
2308                self.clause
2309            )));
2310        }
2311        // The predicate goes first, which is the order the messages come out in upstream: a call
2312        // whose argument and whose filter both name columns that are not there is refused over the
2313        // filter. It is bound as if it were inside the call, so an aggregate in it is caught, and a
2314        // window in it is refused with the words a window inside an aggregate is refused with.
2315        self.in_aggregate = true;
2316        self.in_filter = true;
2317        let filter = self.bind_filter(ast, filter, scope);
2318        self.in_filter = false;
2319        self.in_aggregate = false;
2320        let filter = filter?;
2321
2322        self.in_aggregate = true;
2323        let mut bound = Vec::with_capacity(args.len());
2324        let mut failure = None;
2325        for &arg in args {
2326            match self.bind_expr(ast, arg, scope) {
2327                Ok(expr) => bound.push(expr),
2328                Err(error) => {
2329                    failure = Some(error);
2330                    break;
2331                }
2332            }
2333        }
2334        self.in_aggregate = false;
2335        if let Some(error) = failure {
2336            return Err(error);
2337        }
2338
2339        let types: Vec<LogicalType> =
2340            bound.iter().map(|&arg| self.plan.expr_type(arg).clone()).collect();
2341        let resolved = resolve(name, &types)?;
2342        let mut cast = Vec::with_capacity(bound.len());
2343        for (arg, wanted) in bound.iter().zip(&resolved.arguments) {
2344            cast.push(self.checked_cast_to(*arg, wanted, false)?);
2345        }
2346        let args = self.plan.add_expr_list(&cast);
2347        let name = self.plan.intern(resolved.name);
2348        let ty = resolved.returns;
2349        let call = self.plan.add_expr(Expr::Aggregate { name, args, distinct, filter }, ty.clone());
2350
2351        // Two identical aggregates are one column of the aggregate's output. `SELECT sum(x),
2352        // sum(x) / count(*)` computes one sum, not two.
2353        let existing = self.aggregation.as_ref().map(|held| held.aggregates.clone());
2354        let existing = existing.unwrap_or_default();
2355        let at = match existing.iter().position(|&held| self.same_expr(held, call)) {
2356            Some(at) => at,
2357            None => {
2358                let aggregation = self.aggregation.as_mut().expect("checked above");
2359                aggregation.aggregates.push(call);
2360                aggregation.aggregates.len() - 1
2361            }
2362        };
2363        let aggregation = self.aggregation.as_ref().expect("checked above");
2364        let (index, groups) = (aggregation.index, aggregation.groups.len());
2365        Ok(self.column(index, groups + at, ty))
2366    }
2367
2368    // ----------------------------------------------------------------- windows
2369
2370    /// Binds a window call, files it under the run it belongs to, and hands back its column.
2371    ///
2372    /// The result is a column of a [`Node::Window`] rather than the call itself, for the reason the
2373    /// aggregate path returns a column too: the operator produces the value and everything above it
2374    /// reads the value, so a target that wraps a window in arithmetic is arithmetic over a column.
2375    pub(crate) fn bind_window(
2376        &mut self,
2377        ast: &Ast,
2378        written: &WindowCall<'_>,
2379        scope: &Scope,
2380    ) -> Result<ExprRef> {
2381        let WindowCall { name, args, distinct, filter, ignore_nulls, spec } = *written;
2382        if self.in_aggregate {
2383            return Err(Error::binder(
2384                "aggregate function calls cannot contain window function calls",
2385            ));
2386        }
2387        if self.in_window {
2388            return Err(Error::binder("window function calls cannot be nested"));
2389        }
2390        // A join condition is part of the `WHERE` clause as far as this one sentence is concerned,
2391        // which is upstream's wording and not a simplification: `ON sum(a.i) OVER () = b.i` is
2392        // refused there with the words a window in a `WHERE` is refused with.
2393        let clause = if self.clause == "JOIN condition" { "WHERE clause" } else { self.clause };
2394        if clause != "SELECT clause" && clause != "ORDER BY clause" {
2395            return Err(Error::binder(format!("{clause} cannot contain window functions!")));
2396        }
2397
2398        // `count(*)` is a different function from `count(x)` here for the reason it is a different
2399        // function in an ordinary call: one counts rows and the other counts the rows where its
2400        // argument is not null. A star is not an expression and nothing below this binds one.
2401        let starred = args.iter().any(|&arg| {
2402            matches!(ast.expr(arg), ast::Expr::Star { qualifier, replacements }
2403                if qualifier.is_empty() && replacements.is_empty())
2404        });
2405        let (name, args): (&str, &[ast::ExprRef]) = if starred {
2406            if !same_name(name, "count") || args.len() != 1 {
2407                return Err(Error::binder(format!("* is not allowed in {name}()")));
2408            }
2409            ("count_star", &[])
2410        } else if same_name(name, "count") && args.is_empty() {
2411            // `count()` with nothing in it is upstream's other spelling of `count(*)`. It counts
2412            // rows the same way and it is not an arity mistake.
2413            ("count_star", &[])
2414        } else {
2415            (name, args)
2416        };
2417
2418        let held = ast.window(spec);
2419        self.in_window = true;
2420        let parts = self.window_parts(ast, args, held, scope);
2421        // The predicate goes last here, which is the other way round from an ordinary aggregate and
2422        // is again the order the messages come out in upstream. It is still inside the window, so a
2423        // window in it is a nested window, while an aggregate in it is an ordinary aggregate over
2424        // the same rows and is answered.
2425        let filter = if parts.is_ok() { self.bind_filter(ast, filter, scope) } else { Ok(None) };
2426        self.in_window = false;
2427        let parts = parts?;
2428        let filter = filter?;
2429        // Upstream's rule, in its words. A `RANGE` offset is a distance from the current row's sort
2430        // key, so there has to be exactly one sort key for it to be a distance from.
2431        let offsets = [parts.frame.start, parts.frame.end]
2432            .iter()
2433            .any(|end| matches!(end, WindowBound::Preceding(_) | WindowBound::Following(_)));
2434        if parts.frame.unit == WindowUnit::Range && offsets && parts.order.len() != 1 {
2435            return Err(Error::binder("RANGE frames must have only one ORDER BY expression"));
2436        }
2437
2438        let types: Vec<LogicalType> =
2439            parts.args.iter().map(|&arg| self.plan.expr_type(arg).clone()).collect();
2440        let resolved = window_signature(name, &types)?;
2441        // `fill` reads the sort key rather than the frame, so what it needs from the query is not
2442        // what any other window needs and it is refused on its own terms.
2443        if resolved.name == "fill" {
2444            let keys: Vec<LogicalType> =
2445                parts.order.iter().map(|key| self.plan.expr_type(key.expr).clone()).collect();
2446            refuse_fill(&types[0], &keys, distinct, ignore_nulls)?;
2447        }
2448        // Upstream's sentence, doubled quotes and all. A DISTINCT over an aggregate inside an OVER
2449        // is ordinary and answered, and a DISTINCT over a ranking window is refused there, because
2450        // there is nothing for it to collapse when the call reads no values in the first place.
2451        if distinct && kind_of(resolved.name) == Some(FunctionKind::Window) {
2452            return Err(Error::binder(format!(
2453                "DISTINCT is not implemented for the window function \"\"{name}\"\""
2454            )));
2455        }
2456        // The same sentence for the same reason. A ranking window reads no values, so there is
2457        // nothing for a predicate over the values to keep or drop.
2458        if filter.is_some() && kind_of(resolved.name) == Some(FunctionKind::Window) {
2459            return Err(Error::binder(format!(
2460                "FILTER is not implemented for the window function \"\"{name}\"\""
2461            )));
2462        }
2463        let mut cast = Vec::with_capacity(parts.args.len());
2464        for (arg, wanted) in parts.args.iter().zip(&resolved.arguments) {
2465            cast.push(self.checked_cast_to(*arg, wanted, false)?);
2466        }
2467        let args = self.plan.add_expr_list(&cast);
2468        let name = self.plan.intern(resolved.name);
2469        let ty = resolved.returns;
2470        let call = self
2471            .plan
2472            .add_expr(Expr::Window { name, args, distinct, filter, ignore_nulls }, ty.clone());
2473
2474        let at = self.window_run(parts.partition, parts.order, parts.frame, call);
2475        let index = self.windows.last().expect("the run was just filed").index;
2476        Ok(self.column(index, at, ty))
2477    }
2478
2479    /// Files a call under the run that matches it, or opens a new run, and says which column it is.
2480    ///
2481    /// The run that matches is only ever the last one, because a query that goes back to an earlier
2482    /// partitioning after using a different one in between wants the operators in the order it wrote
2483    /// them. Merging the two would be a rewrite, and a rewrite over a window is the optimizer's to
2484    /// make once it knows what the sort below each one costs.
2485    fn window_run(
2486        &mut self,
2487        partition: Vec<ExprRef>,
2488        order: Vec<SortKey>,
2489        frame: WindowFrame,
2490        call: ExprRef,
2491    ) -> usize {
2492        let matches = self.windows.last().is_some_and(|run| {
2493            run.frame == frame
2494                && run.partition.len() == partition.len()
2495                && run.order.len() == order.len()
2496                && run.partition.iter().zip(&partition).all(|(&l, &r)| self.same_expr(l, r))
2497                && run.order.iter().zip(&order).all(|(l, r)| {
2498                    l.descending == r.descending
2499                        && l.nulls_first == r.nulls_first
2500                        && self.same_expr(l.expr, r.expr)
2501                })
2502        });
2503        if !matches {
2504            let index = self.fresh_index();
2505            self.windows.push(WindowRun { index, partition, order, frame, calls: Vec::new() });
2506        }
2507        // Two identical calls over one run are one column, the same way two identical aggregates
2508        // over one grouping are. `SELECT sum(i) OVER (), sum(i) OVER () + 1` totals once.
2509        let calls = self.windows.last().expect("a run is open").calls.clone();
2510        if let Some(at) = calls.iter().position(|&held| self.same_expr(held, call)) {
2511            return at;
2512        }
2513        let run = self.windows.last_mut().expect("a run is open");
2514        run.calls.push(call);
2515        run.calls.len() - 1
2516    }
2517
2518    /// Binds the arguments and everything inside the `OVER`, with the aggregate rule applied.
2519    ///
2520    /// The aggregate rule applies to all of it, which is measured rather than assumed: over a
2521    /// grouped block `sum(count(i)) OVER ()` binds and `sum(i) OVER ()` is the ungrouped column
2522    /// complaint, and the same pair of answers comes back for a partition key and for an order key.
2523    fn window_parts(
2524        &mut self,
2525        ast: &Ast,
2526        args: &[ast::ExprRef],
2527        held: ast::WindowSpec,
2528        scope: &Scope,
2529    ) -> Result<WindowParts> {
2530        let mut bound = Vec::with_capacity(args.len());
2531        for &arg in args {
2532            let expr = self.bind_expr(ast, arg, scope)?;
2533            bound.push(self.over_aggregate(expr, scope)?);
2534        }
2535        let mut partition = Vec::new();
2536        for &key in ast.expr_list(held.partition) {
2537            let expr = self.bind_expr(ast, key, scope)?;
2538            partition.push(self.over_aggregate(expr, scope)?);
2539        }
2540        let mut order = Vec::new();
2541        for item in ast.order_list(held.order).to_vec() {
2542            let expr = self.bind_expr(ast, item.expr, scope)?;
2543            let expr = self.over_aggregate(expr, scope)?;
2544            order.push(self.sort_key(expr, item));
2545        }
2546        let frame = WindowFrame {
2547            unit: match held.unit {
2548                ast::WindowUnit::Rows => WindowUnit::Rows,
2549                ast::WindowUnit::Range => WindowUnit::Range,
2550                ast::WindowUnit::Groups => WindowUnit::Groups,
2551            },
2552            start: self.window_bound(ast, held.start, scope)?,
2553            end: self.window_bound(ast, held.end, scope)?,
2554            exclude: match held.exclude {
2555                ast::WindowExclude::NoOthers => WindowExclude::NoOthers,
2556                ast::WindowExclude::CurrentRow => WindowExclude::CurrentRow,
2557                ast::WindowExclude::Group => WindowExclude::Group,
2558                ast::WindowExclude::Ties => WindowExclude::Ties,
2559            },
2560        };
2561        Ok(WindowParts { args: bound, partition, order, frame })
2562    }
2563
2564    /// One end of a frame, with its offset bound where it has one.
2565    fn window_bound(
2566        &mut self,
2567        ast: &Ast,
2568        bound: ast::WindowBound,
2569        scope: &Scope,
2570    ) -> Result<WindowBound> {
2571        let offset = |binder: &mut Self, written| {
2572            let expr = binder.bind_expr(ast, written, scope)?;
2573            binder.over_aggregate(expr, scope)
2574        };
2575        Ok(match bound {
2576            ast::WindowBound::UnboundedPreceding => WindowBound::UnboundedPreceding,
2577            ast::WindowBound::CurrentRow => WindowBound::CurrentRow,
2578            ast::WindowBound::UnboundedFollowing => WindowBound::UnboundedFollowing,
2579            ast::WindowBound::Preceding(written) => WindowBound::Preceding(offset(self, written)?),
2580            ast::WindowBound::Following(written) => WindowBound::Following(offset(self, written)?),
2581        })
2582    }
2583
2584    /// Whether a column is the result of a window this block is building.
2585    fn is_window_output(&self, binding: ColumnBinding) -> bool {
2586        self.windows.iter().any(|run| run.index == binding.table)
2587    }
2588
2589    /// Rewrites a bound expression into one the aggregate's output can answer.
2590    ///
2591    /// A subexpression that is one of the group expressions becomes a reference to that group. A
2592    /// column that is neither grouped nor inside an aggregate is the error every SQL user has seen,
2593    /// and it is reported here because this is the first point where it is knowable.
2594    pub(crate) fn over_aggregate(&mut self, expr: ExprRef, scope: &Scope) -> Result<ExprRef> {
2595        let Some(aggregation) = self.aggregation.as_ref() else {
2596            return Ok(expr);
2597        };
2598        let index = aggregation.index;
2599        let groups = aggregation.groups.clone();
2600        for (at, group) in groups.iter().enumerate() {
2601            if self.same_expr(expr, *group) {
2602                let ty = self.plan.expr_type(*group).clone();
2603                return Ok(self.column(index, at, ty));
2604            }
2605        }
2606        let ty = self.plan.expr_type(expr).clone();
2607        match self.plan.expr(expr).clone() {
2608            Expr::Column(binding) if binding.table == index => Ok(expr),
2609            // A window result is not a column of the input and the grouping rule has nothing to say
2610            // about it. It reads the aggregate's output rather than the table's, which is why
2611            // `SELECT sum(count(i)) OVER () FROM t GROUP BY j` binds and `sum(i) OVER ()` over the
2612            // same block does not.
2613            Expr::Column(binding) if self.is_window_output(binding) => Ok(expr),
2614            // The same argument for a query joined in above the grouping. `HAVING sum(x) > (SELECT
2615            // ...)` reads one row out of a query that has nothing to do with the groups, and the
2616            // join that produces it sits on top of the `Aggregate`, so what it produces is not one
2617            // of the grouped table's columns either.
2618            Expr::Column(binding) if self.joined_above.contains(&binding.table) => Ok(expr),
2619            Expr::Column(binding) => {
2620                let name =
2621                    scope.columns.iter().find(|column| column.binding == binding).map_or_else(
2622                        || "a column".to_string(),
2623                        |column| format!("\"{}\"", column.name),
2624                    );
2625                Err(Error::binder(format!(
2626                    "column {name} must appear in the GROUP BY clause or must be part of an aggregate function"
2627                )))
2628            }
2629            Expr::Constant(_) | Expr::Aggregate { .. } | Expr::Window { .. } => Ok(expr),
2630            Expr::Cast { input, try_cast } => {
2631                let input = self.over_aggregate(input, scope)?;
2632                Ok(self.plan.add_expr(Expr::Cast { input, try_cast }, ty))
2633            }
2634            Expr::Compare { op, left, right } => {
2635                let left = self.over_aggregate(left, scope)?;
2636                let right = self.over_aggregate(right, scope)?;
2637                Ok(self.plan.add_expr(Expr::Compare { op, left, right }, ty))
2638            }
2639            Expr::Conjunction { op, children } => {
2640                let written = self.plan.expr_list(children).to_vec();
2641                let mut rewritten = Vec::with_capacity(written.len());
2642                for child in written {
2643                    rewritten.push(self.over_aggregate(child, scope)?);
2644                }
2645                let children = self.plan.add_expr_list(&rewritten);
2646                Ok(self.plan.add_expr(Expr::Conjunction { op, children }, ty))
2647            }
2648            Expr::Function { name, args } => {
2649                let written = self.plan.expr_list(args).to_vec();
2650                let mut rewritten = Vec::with_capacity(written.len());
2651                for arg in written {
2652                    rewritten.push(self.over_aggregate(arg, scope)?);
2653                }
2654                let args = self.plan.add_expr_list(&rewritten);
2655                Ok(self.plan.add_expr(Expr::Function { name, args }, ty))
2656            }
2657            Expr::Case { arms, otherwise } => {
2658                let written = self.plan.arm_list(arms).to_vec();
2659                let mut rewritten = Vec::with_capacity(written.len());
2660                for arm in written {
2661                    let when = self.over_aggregate(arm.when, scope)?;
2662                    let then = self.over_aggregate(arm.then, scope)?;
2663                    rewritten.push(rudb_plan::Arm { when, then });
2664                }
2665                let otherwise = match otherwise {
2666                    Some(expr) => Some(self.over_aggregate(expr, scope)?),
2667                    None => None,
2668                };
2669                let arms = self.plan.add_arms(&rewritten);
2670                Ok(self.plan.add_expr(Expr::Case { arms, otherwise }, ty))
2671            }
2672        }
2673    }
2674
2675    /// Whether two bound expressions are the same expression, by shape rather than by reference.
2676    pub(crate) fn same_expr(&self, left: ExprRef, right: ExprRef) -> bool {
2677        same_expr(&self.plan, left, right)
2678    }
2679}
2680
2681/// The named parameters a table function call was written with.
2682///
2683/// A struct rather than the fields loose, because the seventeen DuckDB has on `read_parquet` and the
2684/// thirty on `read_csv` are all going to want somewhere to go, and because a call with none of them
2685/// written should read as the default of this rather than as a bare false somewhere.
2686///
2687/// The CSV half goes on to the reader and is opened with, here and again in the executor. The
2688/// Parquet half is answered here and nothing downstream sees it, which is what `binary_as_string`
2689/// turning a BLOB column into a VARCHAR one is.
2690#[derive(Debug, Default)]
2691struct Options {
2692    /// `binary_as_string`, which says an unannotated byte array column in a Parquet file holds
2693    /// text. The ClickBench file has twenty eight of those and every query reads them as strings.
2694    binary_as_string: bool,
2695    /// `all_varchar`, which reads every column of a CSV file as text rather than sniffing a type.
2696    all_varchar: bool,
2697    /// `file_row_number`, which adds a column holding each row's ordinal inside its own file.
2698    ///
2699    /// The one Parquet option here that the executor has to act on rather than the binder, since
2700    /// the column is not in the file and has to be counted as the rows come out of it.
2701    file_row_number: bool,
2702    /// `delim`, `sep`, `quote`, `escape` and `header`, which are what the sniffer would decide.
2703    given: Given,
2704}
2705
2706impl Options {
2707    /// What these named parameters add up to.
2708    ///
2709    /// Each one was already checked against the function's list, so a name in here is a name that
2710    /// function takes and the value is already the type it wants. What is left is reading them, and
2711    /// the last one written wins, which is DuckDB's answer to `delim='|', delim=','` and was
2712    /// measured rather than assumed.
2713    fn of(written: &[(&'static str, Value, ExprRef)]) -> Result<Self> {
2714        let mut options = Self::default();
2715        for (parameter, value, _) in written {
2716            match (*parameter, value) {
2717                ("binary_as_string", Value::Boolean(on)) => options.binary_as_string = *on,
2718                ("all_varchar", Value::Boolean(on)) => options.all_varchar = *on,
2719                ("file_row_number", Value::Boolean(on)) => options.file_row_number = *on,
2720                _ => {}
2721            }
2722        }
2723        let named: Vec<(&str, Value)> =
2724            written.iter().map(|(parameter, value, _)| (*parameter, value.clone())).collect();
2725        options.given = csv_given(&named)?;
2726        Ok(options)
2727    }
2728}
2729
2730/// DuckDB's complaint about a named parameter that was given a null, which is a different sentence
2731/// for almost every parameter.
2732///
2733/// Three of them were measured on `v2.0.0-dev84237` and no two agree: `binary_as_string` is the
2734/// first, `all_varchar` is the second and `header` is the third. They read like three people each
2735/// writing the message in front of them, which is what they are, and a harness that compares error
2736/// text compares all of it. Anything not measured gets the first one, which is the most general of
2737/// the three.
2738fn null_parameter(function: TableFunction, parameter: &str) -> String {
2739    match parameter {
2740        "header" => format!("\"{parameter}\" expects a non-null boolean value (e.g. TRUE or 1)"),
2741        "all_varchar" => format!("{} \"{parameter}\" cannot be NULL", function.name()),
2742        _ => format!("Cannot use NULL as argument to \"{parameter}\""),
2743    }
2744}
2745
2746/// The complaint about a `REPLACE` entry that named a column the star did not stand for.
2747///
2748/// It reads like the complaint about any other name that is not there, down to the list of names
2749/// that are, because from the writer's side it is the same mistake.
2750fn missing_replacement(name: &str, input: &Scope) -> Error {
2751    Error::binder(format!(
2752        "Column \"{name}\" in REPLACE list not found in FROM clause{}",
2753        input.candidates()
2754    ))
2755}
2756
2757/// Whether a type is one `fill` can interpolate over, which is the pin's phrase for it.
2758///
2759/// The pin refuses `fill` with `FILL argument must support subtraction` and its sort key with
2760/// `FILL ordering must support subtraction`, and the two lists are not the same list, which is why
2761/// this takes a flag rather than answering one question. Every number is on both, so are `DATE`,
2762/// `TIME` and the two timestamps, and `TIME WITH TIME ZONE` is a sort key there but not an
2763/// argument. `INTERVAL` is on neither, which is worth saying out loud because an interval does
2764/// subtract: the sentence names subtraction and the rule is narrower than the sentence.
2765fn subtractable(ty: &LogicalType, ordering: bool) -> bool {
2766    if ty.is_numeric() {
2767        return true;
2768    }
2769    match ty {
2770        LogicalType::Date
2771        | LogicalType::Time
2772        | LogicalType::Timestamp
2773        | LogicalType::TimestampS
2774        | LogicalType::TimestampMs
2775        | LogicalType::TimestampNs
2776        | LogicalType::TimestampTz => true,
2777        LogicalType::TimeTz => ordering,
2778        _ => false,
2779    }
2780}
2781
2782/// Refuses a `fill` call the way the pin refuses one, in the pin's order.
2783///
2784/// The order was measured and it is not the order the clauses are written in. A `fill` over a
2785/// `VARCHAR` with no `ORDER BY` at all complains about the argument, so the argument is looked at
2786/// before the sort key is counted, and a `fill` with `DISTINCT` and no `ORDER BY` complains about
2787/// the `ORDER BY`, so the count comes before the clauses. `IGNORE NULLS` is refused here rather
2788/// than being answered as a no-op, since there is nothing for it to skip: `fill` is the one window
2789/// whose whole job is the nulls.
2790fn refuse_fill(
2791    argument: &LogicalType,
2792    order: &[LogicalType],
2793    distinct: bool,
2794    ignore_nulls: bool,
2795) -> Result<()> {
2796    if !subtractable(argument, false) {
2797        return Err(Error::binder("FILL argument must support subtraction"));
2798    }
2799    let [key] = order else {
2800        return Err(Error::binder("FILL functions must have only one ORDER BY expression"));
2801    };
2802    if !subtractable(key, true) {
2803        return Err(Error::binder("FILL ordering must support subtraction"));
2804    }
2805    if distinct {
2806        return Err(Error::binder(
2807            "DISTINCT is not implemented for the window function \"\"fill\"\"",
2808        ));
2809    }
2810    if ignore_nulls {
2811        return Err(Error::binder(
2812            "RESPECT/IGNORE NULLS is not supported for the window function \"fill\"",
2813        ));
2814    }
2815    Ok(())
2816}
2817
2818/// Resolves the call written inside an `OVER`.
2819///
2820/// Every aggregate is also a window, which is why this goes through the same signature table the
2821/// aggregate path uses, and the ranking windows go through it too because they are rows in the same
2822/// table. Everything else is one of three refusals, and all three are the reference binary's: a name
2823/// it knows as a scalar and a name it does not know at all each get their own sentence there.
2824fn window_signature(name: &str, types: &[LogicalType]) -> Result<Resolved> {
2825    match kind_of(name) {
2826        Some(FunctionKind::Aggregate | FunctionKind::Window) => resolve(name, types),
2827        Some(FunctionKind::Scalar) => {
2828            Err(Error::catalog(format!("{name} is not an aggregate function")))
2829        }
2830        None => Err(Error::catalog(format!("Aggregate Function with name {name} does not exist!"))),
2831    }
2832}
2833
2834/// Structural equality over two expressions of one plan.
2835fn same_expr(plan: &Plan, left: ExprRef, right: ExprRef) -> bool {
2836    if left == right {
2837        return true;
2838    }
2839    if plan.expr_type(left) != plan.expr_type(right) {
2840        return false;
2841    }
2842    let lists = |left, right| {
2843        let left: &[ExprRef] = plan.expr_list(left);
2844        let right: &[ExprRef] = plan.expr_list(right);
2845        left.len() == right.len()
2846            && left.iter().zip(right).all(|(&left, &right)| same_expr(plan, left, right))
2847    };
2848    match (plan.expr(left), plan.expr(right)) {
2849        (Expr::Column(left), Expr::Column(right)) => left == right,
2850        (Expr::Constant(left), Expr::Constant(right)) => plan.value(*left) == plan.value(*right),
2851        (
2852            Expr::Cast { input: left, try_cast: left_try },
2853            Expr::Cast { input: right, try_cast: right_try },
2854        ) => left_try == right_try && same_expr(plan, *left, *right),
2855        (
2856            Expr::Compare { op: left_op, left: left_a, right: left_b },
2857            Expr::Compare { op: right_op, left: right_a, right: right_b },
2858        ) => {
2859            left_op == right_op
2860                && same_expr(plan, *left_a, *right_a)
2861                && same_expr(plan, *left_b, *right_b)
2862        }
2863        (
2864            Expr::Conjunction { op: left_op, children: left_children },
2865            Expr::Conjunction { op: right_op, children: right_children },
2866        ) => left_op == right_op && lists(*left_children, *right_children),
2867        (
2868            Expr::Function { name: left_name, args: left_args },
2869            Expr::Function { name: right_name, args: right_args },
2870        ) => plan.string(*left_name) == plan.string(*right_name) && lists(*left_args, *right_args),
2871        (
2872            Expr::Aggregate {
2873                name: left_name,
2874                args: left_args,
2875                distinct: left_distinct,
2876                filter: left_filter,
2877            },
2878            Expr::Aggregate {
2879                name: right_name,
2880                args: right_args,
2881                distinct: right_distinct,
2882                filter: right_filter,
2883            },
2884        ) => {
2885            plan.string(*left_name) == plan.string(*right_name)
2886                && left_distinct == right_distinct
2887                && match (left_filter, right_filter) {
2888                    (None, None) => true,
2889                    (Some(left), Some(right)) => same_expr(plan, *left, *right),
2890                    _ => false,
2891                }
2892                && lists(*left_args, *right_args)
2893        }
2894        // The partition, the order and the frame are not compared here and do not need to be. Two
2895        // window calls are only ever asked about when they are already in the same run, which is
2896        // what agreeing on all three means.
2897        (
2898            Expr::Window {
2899                name: left_name,
2900                args: left_args,
2901                distinct: left_distinct,
2902                filter: left_filter,
2903                ignore_nulls: left_nulls,
2904            },
2905            Expr::Window {
2906                name: right_name,
2907                args: right_args,
2908                distinct: right_distinct,
2909                filter: right_filter,
2910                ignore_nulls: right_nulls,
2911            },
2912        ) => {
2913            plan.string(*left_name) == plan.string(*right_name)
2914                && left_distinct == right_distinct
2915                && left_nulls == right_nulls
2916                && match (left_filter, right_filter) {
2917                    (None, None) => true,
2918                    (Some(left), Some(right)) => same_expr(plan, *left, *right),
2919                    _ => false,
2920                }
2921                && lists(*left_args, *right_args)
2922        }
2923        (
2924            Expr::Case { arms: left_arms, otherwise: left_otherwise },
2925            Expr::Case { arms: right_arms, otherwise: right_otherwise },
2926        ) => {
2927            let left_arms = plan.arm_list(*left_arms);
2928            let right_arms = plan.arm_list(*right_arms);
2929            left_arms.len() == right_arms.len()
2930                && left_arms.iter().zip(right_arms).all(|(left, right)| {
2931                    same_expr(plan, left.when, right.when) && same_expr(plan, left.then, right.then)
2932                })
2933                && match (left_otherwise, right_otherwise) {
2934                    (None, None) => true,
2935                    (Some(left), Some(right)) => same_expr(plan, *left, *right),
2936                    _ => false,
2937                }
2938        }
2939        _ => false,
2940    }
2941}