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