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, FileStamp, 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, Footers, FunctionKind, Given, Resolved, TYPES_SET, TableFunction,
24    csv_fields, csv_given, files, is_file, is_pattern, kind_of, parquet_footers, parquet_outline,
25    resolve, resolve_pragma, resolve_table,
26};
27use rudb_kernels::{percentage, row_count};
28use rudb_parse::ast::{self, Ast, Distinct, LiteralKind, Nulls, Order, Quantifier, SetOp};
29use rudb_parse::{NONE, identifier_parts, parse_ast_with_case};
30use rudb_plan::{
31    Bound, BuildSide, ColumnBinding, ConjunctionOp, Expr, ExprRef, JoinKind, Node, NodeRef, Plan,
32    SetOpKind, Share, SortKey, WindowBound, WindowExclude, WindowFrame, WindowUnit,
33};
34
35use crate::expr::{describe, has_aggregate};
36use crate::fold;
37use crate::parameters::Parameters;
38use crate::scope::{Scope, Visible};
39
40/// Binds a parsed statement against a catalog.
41///
42/// # Errors
43///
44/// If the script does not hold exactly one statement, if a name does not resolve, if a type does
45/// not work out, or if the query uses something M0 does not bind yet.
46pub fn bind(ast: &Ast, catalog: &Catalog) -> Result<Plan> {
47    bind_with(ast, catalog, &Parameters::new(), &Session::new())
48}
49
50/// Binds a parsed query against a catalog, with values for its parameters and its settings.
51///
52/// The session is what `current_setting()` reads, and a caller with no database behind it passes an
53/// empty one, which makes every setting name unrecognized rather than making up an answer.
54///
55/// # Errors
56///
57/// Everything [`bind`] reports, plus an error for a parameter that was given no value.
58pub fn bind_with(
59    ast: &Ast,
60    catalog: &Catalog,
61    parameters: &Parameters,
62    session: &Session,
63) -> Result<Plan> {
64    let query = match ast.statements.as_slice() {
65        [ast::Statement::Query(query)] => *query,
66        [] => return Err(Error::binder("no statement to bind")),
67        // One statement that is not a query is its own answer. Reporting it as a script of several
68        // reads as a count being wrong, and the count is right.
69        [_] => return Err(Error::not_implemented("a statement that is not a query")),
70        _ => return Err(Error::not_implemented("a script of more than one statement")),
71    };
72    let mut binder = Binder::with(catalog, parameters, session);
73    let (root, _) = binder.bind_query(ast, query)?;
74    let mut plan = binder.into_plan();
75    plan.set_root(root);
76    plan.validate()?;
77    Ok(plan)
78}
79
80/// Parses and binds one query, which is the whole front end in one call.
81///
82/// # Errors
83///
84/// Anything the parser or the binder reports.
85pub fn bind_sql(query: &str, catalog: &Catalog) -> Result<Plan> {
86    bind_sql_with(query, catalog, &Session::new())
87}
88
89/// Parses and binds one query, with the settings a call to `current_setting()` reads.
90///
91/// # Errors
92///
93/// Anything the parser or the binder reports.
94pub fn bind_sql_with(query: &str, catalog: &Catalog, session: &Session) -> Result<Plan> {
95    let ast = parse_ast_with_case(query, session.semantics().identifier_case())?;
96    bind_with(&ast, catalog, &Parameters::new(), session)
97}
98
99/// What an aggregating select block has decided so far.
100#[derive(Debug)]
101pub(crate) struct Aggregation {
102    /// The table index the aggregate's output binds against.
103    pub(crate) index: u32,
104    /// The group expressions, over the input, which are the first output columns.
105    pub(crate) groups: Vec<ExprRef>,
106    /// The aggregate calls found so far, which follow the groups in the output.
107    pub(crate) aggregates: Vec<ExprRef>,
108}
109
110/// One run of window calls that agree on where the rows come from and in what order.
111///
112/// The run is the unit the plan has an operator for, so two calls that write the same partition,
113/// the same order and the same frame are one operator and one sort, and a third that writes a
114/// different order is a second operator stacked on the first. Nothing here merges runs that only
115/// look compatible, because a window is evaluated over the rows the operator below it produced and
116/// deciding two runs are the same is the optimizer's job rather than the binder's.
117#[derive(Debug)]
118pub(crate) struct WindowRun {
119    /// The table index the run's result columns bind against.
120    index: u32,
121    /// What divides the input into independent partitions.
122    partition: Vec<ExprRef>,
123    /// The order within a partition.
124    order: Vec<SortKey>,
125    /// The frame every call in the run shares.
126    frame: WindowFrame,
127    /// The calls, in the order their columns are appended.
128    calls: Vec<ExprRef>,
129}
130
131/// One aggregate call as it was written, before any of it has been bound.
132#[derive(Clone, Copy)]
133pub(crate) struct AggregateCall<'a> {
134    /// The function name, as written and not yet resolved.
135    name: &'a str,
136    /// The arguments.
137    args: &'a [ast::ExprRef],
138    /// Whether `DISTINCT` was written inside the parens.
139    distinct: bool,
140    /// The `FILTER (WHERE ...)` predicate, or `NONE`.
141    filter: ast::ExprRef,
142    /// The `ORDER BY` written inside the parens.
143    sorted: &'a [ast::OrderItem],
144}
145
146/// One window call as it was written, before any of it has been bound.
147///
148/// These six travel together from the parser all the way to the run they end up filed under, and
149/// carrying them as one thing keeps the call that binds them readable.
150pub(crate) struct WindowCall<'a> {
151    /// The function name, as written and not yet resolved.
152    pub(crate) name: &'a str,
153    /// The arguments, which may include a star that only `count` is allowed to be given.
154    pub(crate) args: &'a [ast::ExprRef],
155    /// Whether `DISTINCT` was written inside the parens.
156    pub(crate) distinct: bool,
157    /// The `FILTER (WHERE ...)` predicate, which is written before the `OVER`, or `NONE`.
158    pub(crate) filter: ast::ExprRef,
159    /// Whether `IGNORE NULLS` was written inside the parens, which is where DuckDB puts it.
160    pub(crate) ignore_nulls: bool,
161    /// The `ORDER BY` written inside the parens, which says what order the call reads the rows of
162    /// its frame in and is a different clause from the one in the `OVER`.
163    pub(crate) order: ast::Slice,
164    /// The `OVER`, which the parser has already resolved against any `WINDOW` clause.
165    pub(crate) spec: ast::WindowRef,
166}
167
168/// Everything inside one window call once it is bound, which is what decides its run.
169struct WindowParts {
170    /// The arguments, before the casts the resolved signature asks for.
171    args: Vec<ExprRef>,
172    /// What divides the input into independent partitions.
173    partition: Vec<ExprRef>,
174    /// The order within a partition.
175    order: Vec<SortKey>,
176    /// The order the call reads the rows of its frame in, which is the `ORDER BY` written inside
177    /// the brackets rather than the one in the `OVER` and is empty far more often than not.
178    inner: Vec<SortKey>,
179    /// The frame, with both ends and the exclusion.
180    frame: WindowFrame,
181}
182
183/// What opening the files behind a table function call said about them.
184///
185/// The answers travel together because they come out of the same footer. A Parquet file states its
186/// columns, its row count and its statistics in the same few kilobytes at the end of it, so a
187/// binder that has read one has read all of them, and splitting them into four arguments would
188/// mean four ways to forget one.
189#[derive(Debug)]
190struct Read {
191    /// The columns the call produces, in the order the file stores them.
192    fields: Vec<Field>,
193    /// How many rows all of the files hold, where anybody counted.
194    rows: Stat<u64>,
195    /// How many distinct values a column holds, by name, for the columns anybody counted.
196    distincts: Vec<(String, Stat<u64>)>,
197    /// The bounds the files keep per part of themselves, where anything can answer for them.
198    zones: Option<Arc<dyn Zones>>,
199}
200
201impl Read {
202    /// Columns that came from somewhere other than a file, so nothing counted anything.
203    fn uncounted(fields: Vec<Field>) -> Self {
204        Self { fields, rows: Stat::Unknown, distincts: Vec::new(), zones: None }
205    }
206}
207
208/// A materialised `WITH` definition that has been bound and can be read by name.
209#[derive(Debug)]
210struct Materialized {
211    /// Which written definition this is, as an index into `Ast::ctes`.
212    written: u32,
213    /// The number the plan uses to pair a read with what it reads.
214    cte: u32,
215    /// The name it was written with, which is the table name a read is reachable through.
216    name: String,
217    /// What it produces, in order, under the declared names when a column list was written.
218    fields: Vec<Field>,
219}
220
221#[derive(Debug)]
222pub(crate) struct PendingSubquery {
223    pub(crate) node: NodeRef,
224    pub(crate) kind: JoinKind,
225    pub(crate) conditions: Vec<ExprRef>,
226    pub(crate) dependent: bool,
227    /// The outer columns the query's body read, which is what `dependent` counts.
228    ///
229    /// Kept rather than reduced to the flag because a join's `ON` has to decide which of its two
230    /// inputs the query is joined into, and the answer is the side those columns come from. A
231    /// query that reads neither side can go on either.
232    pub(crate) reads: Vec<ColumnBinding>,
233    /// The table index this query's join adds to the rows it is joined into.
234    ///
235    /// Kept so that a `HAVING` which reads one of these can say which columns came from a query
236    /// joined above the grouping rather than from the table underneath it. Those columns are not
237    /// the table's and the grouping rule has nothing to say about them.
238    pub(crate) index: u32,
239    /// Whether the query was written inside an aggregate call's argument or its `FILTER`.
240    ///
241    /// One written there is read once per row going into the aggregate, so it has to be joined in
242    /// underneath the grouping however uncorrelated it is. Every other query a grouped block writes
243    /// is one row for the whole block and is lifted over the grouping instead, which is what
244    /// [`Binder::lift_over_aggregate`] decides.
245    pub(crate) inside_aggregate: bool,
246}
247
248/// Which input of a join a query written in that join's `ON` is joined into.
249#[derive(Debug, Clone, Copy, PartialEq, Eq)]
250enum Side {
251    Left,
252    Right,
253}
254
255/// The state one binding run carries.
256#[derive(Debug)]
257pub(crate) struct Binder<'a> {
258    catalog: &'a Catalog,
259    /// What the parameters were given, empty for a statement that is not prepared.
260    pub(crate) parameters: &'a Parameters,
261    /// What the settings are now, which is what `current_setting()` folds to.
262    pub(crate) session: &'a Session,
263    /// Meaning-changing choices copied once and resolved into the plan above execution.
264    pub(crate) semantics: Semantics,
265    plan: Plan,
266    next_index: u32,
267    /// Source range inherited by plan objects built for the current AST expression or query.
268    pub(crate) current_span: Span,
269    /// The span every expression is placed at while a built-in macro's body is bound, which is the
270    /// span of the call. See `crate::macros`.
271    pub(crate) pinned_span: Option<Span>,
272    /// Set while a select block aggregates, which changes what a bare column means.
273    pub(crate) aggregation: Option<Aggregation>,
274    /// A grouped block may need stored column order to close groups while it scans. Other queries
275    /// leave the summaries in the file instead of reading every column's section while binding.
276    want_ascending: bool,
277    /// Whether this binds the query of an `ON CONFLICT DO UPDATE`, whose `excluded` reads the new
278    /// rows rather than the table.
279    pub(crate) upsert: bool,
280    /// The type and the default of each column an `INSERT` writes, handed to the `VALUES` right
281    /// under it so that a `DEFAULT` item there can be the default of the column it lands in.
282    pub(crate) insert_defaults: Option<Vec<(LogicalType, Option<String>)>>,
283    /// The columns a `COPY t FROM` loads, in the order the file holds them, handed to the
284    /// `read_csv` the statement was rewritten into so that the file is read as the table's types
285    /// under the table's names rather than as whatever the sniffer guessed.
286    pub(crate) copy_into: Option<Vec<Field>>,
287    /// Whether a `DEFAULT` binds as a null that the statement replaces afterwards, which is what an
288    /// `UPDATE` does with `SET c = DEFAULT`.
289    pub(crate) default_as_null: bool,
290    /// Set while an aggregate's own arguments are being bound, so nesting is caught.
291    pub(crate) in_aggregate: bool,
292    /// Set while an aggregate's `FILTER` is being bound, which is refused its own aggregate.
293    pub(crate) in_filter: bool,
294    /// The window runs this select block has collected, in the order they were first written.
295    pub(crate) windows: Vec<WindowRun>,
296    /// The `unnest` calls this select block has written, in the order they were written.
297    pub(crate) unnests: Vec<crate::unnest::UnnestCall>,
298    /// The table index the block's `unnest` calls produce their columns under, once there is one.
299    pub(crate) unnest_index: Option<u32>,
300    /// Whether an `unnest` may be written where the binder is, which is the select list and the
301    /// `ORDER BY` of a select block.
302    pub(crate) unnest_here: bool,
303    /// Set while an `unnest` call's own argument is being bound, so nesting is caught.
304    pub(crate) in_unnest: bool,
305    /// Set while a select target that is an `unnest` call and nothing more is being bound, which is
306    /// the one place an `unnest` of a struct may be written.
307    pub(crate) unnest_root: bool,
308    /// The struct such a target left to be taken apart into columns.
309    pub(crate) unnest_struct: Option<crate::unnest::UnnestStruct>,
310    /// Set while the block's `GROUP BY` is being bound, where an `unnest` runs under the grouping.
311    /// It is `Some(true)` for `GROUP BY ALL`, which is not allowed to group on one.
312    pub(crate) unnest_grouping: Option<bool>,
313    /// The `unnest` calls the block's `GROUP BY` wrote, so the same call in the select list reads
314    /// the grouped column rather than taking the list apart a second time.
315    pub(crate) grouped_unnests: Vec<crate::unnest::GroupedUnnest>,
316    /// The sequences a `nextval`, `currval` or `setval` named, which a table's default depends on.
317    pub(crate) sequences: Vec<QualifiedName>,
318    /// Set while a window call's own arguments and keys are being bound, so nesting is caught.
319    pub(crate) in_window: bool,
320    /// Uncorrelated scalar queries waiting to be joined into the select block that uses them.
321    pub(crate) scalar_subqueries: Vec<PendingSubquery>,
322    /// Table indices of the queries this block will join in above its grouping, not below it.
323    ///
324    /// Only ever set while a `HAVING` is being rewritten over the aggregate. A column from one of
325    /// these is not a column of the grouped table, so the rule about grouping every column does not
326    /// reach it, and the join that produces it goes on top of the `Aggregate` rather than under it.
327    pub(crate) joined_above: Vec<u32>,
328    pub(crate) outer_scopes: Vec<Scope>,
329    /// Which of the outer scopes are a FROM entry's left neighbours rather than an enclosing query.
330    ///
331    /// The two are resolved the same way and refused differently. An aggregate may read a column of
332    /// the query it is written in and may not read one a LATERAL brought in from the left, so the
333    /// check needs to know which scope the name came out of. Each entry is a position in
334    /// `outer_scopes`.
335    pub(crate) lateral_scopes: Vec<usize>,
336    pub(crate) correlations: Vec<Vec<ColumnBinding>>,
337    /// The lambdas whose bodies are being bound, innermost last. See `crate::lambda`.
338    pub(crate) lambda_frames: Vec<crate::lambda::Frame>,
339    /// Whether the expression being bound is inside a `TRY`, which refuses what it cannot rerun.
340    pub(crate) trying: bool,
341    /// Where we are, for an error message that says which clause the writer should look at.
342    pub(crate) clause: &'static str,
343    /// Whether a Parquet file that could be read through a native mirror is bound from its outline
344    /// alone, which is the columns and the row count and none of the row groups.
345    ///
346    /// Set by a bind whose plan is thrown away: a `CREATE VIEW`, and the first bind of a query that
347    /// may be bound again once its mirrors are in. A plan bound this way knows no bounds and no
348    /// distinct counts for the file, so the caller must not run it, and every read it did this for
349    /// asked for a mirror, which is how the caller knows to bind again. See
350    /// [`rudb_parquet::Outline`].
351    pub(crate) outlined: bool,
352    /// The views whose bodies are open on the stack, which is what catches a cycle.
353    expanding: Vec<String>,
354    /// The materialised `WITH` definitions whose bodies are being bound, innermost last.
355    ///
356    /// A stack rather than a map from what was written, because a plain `WITH` is put into every
357    /// place it is named, so a materialised one written inside a plain one is bound once per use
358    /// and each of those is a materialisation of its own with a number of its own.
359    materialized: Vec<Materialized>,
360    /// How many materialisations have been numbered, which is where the next number comes from.
361    next_cte: u32,
362    /// When this statement started, read once and kept, which is what `now()` folds to.
363    started: Option<i64>,
364}
365
366impl<'a> Binder<'a> {
367    pub(crate) fn with(
368        catalog: &'a Catalog,
369        parameters: &'a Parameters,
370        session: &'a Session,
371    ) -> Self {
372        Self {
373            catalog,
374            parameters,
375            session,
376            semantics: session.semantics(),
377            plan: Plan::new(),
378            next_index: 0,
379            current_span: Span::new(0, 0),
380            pinned_span: None,
381            aggregation: None,
382            want_ascending: false,
383            upsert: false,
384            insert_defaults: None,
385            copy_into: None,
386            default_as_null: false,
387            in_aggregate: false,
388            in_filter: false,
389            windows: Vec::new(),
390            unnests: Vec::new(),
391            unnest_index: None,
392            unnest_here: false,
393            in_unnest: false,
394            unnest_root: false,
395            unnest_struct: None,
396            unnest_grouping: None,
397            grouped_unnests: Vec::new(),
398            sequences: Vec::new(),
399            in_window: false,
400            scalar_subqueries: Vec::new(),
401            joined_above: Vec::new(),
402            outer_scopes: Vec::new(),
403            lateral_scopes: Vec::new(),
404            correlations: Vec::new(),
405            lambda_frames: Vec::new(),
406            trying: false,
407            clause: "SELECT clause",
408            outlined: false,
409            expanding: Vec::new(),
410            materialized: Vec::new(),
411            next_cte: 0,
412            started: None,
413        }
414    }
415
416    pub(crate) fn catalog(&self) -> &Catalog {
417        self.catalog
418    }
419
420    /// When this statement started, in microseconds since the epoch.
421    ///
422    /// Read from the clock the first time something asks and kept after that, so a query that
423    /// writes `now()` twice gets one answer for both. That is what the pin does and what it reports
424    /// in the `stability` column of `duckdb_functions()`, where every one of these is
425    /// `CONSISTENT_WITHIN_QUERY`. A query that never asks never reads the clock.
426    pub(crate) fn instant(&mut self) -> i64 {
427        *self.started.get_or_insert_with(crate::context::micros_now)
428    }
429
430    pub(crate) fn plan(&self) -> &Plan {
431        &self.plan
432    }
433
434    pub(crate) fn plan_mut(&mut self) -> &mut Plan {
435        &mut self.plan
436    }
437
438    pub(crate) fn add_expr(&mut self, expr: Expr, ty: LogicalType) -> ExprRef {
439        self.plan.add_expr_at(expr, ty, self.current_span)
440    }
441
442    pub(crate) fn add_constant(&mut self, value: Value) -> ExprRef {
443        let ty = value.logical_type();
444        let reference = self.plan.add_value(value);
445        self.plan.add_expr_at(Expr::Constant(reference), ty, self.current_span)
446    }
447
448    pub(crate) fn add_node(&mut self, node: Node) -> NodeRef {
449        self.plan.add_node_at(node, self.current_span)
450    }
451
452    pub(crate) fn into_plan(self) -> Plan {
453        self.plan
454    }
455
456    /// A table index nothing else has.
457    pub(crate) fn fresh_index(&mut self) -> u32 {
458        let index = self.next_index;
459        self.next_index += 1;
460        index
461    }
462
463    /// A reference to one column of an operator's output.
464    fn column(&mut self, index: u32, position: usize, ty: LogicalType) -> ExprRef {
465        let binding = ColumnBinding::new(index, position as u32);
466        self.plan.add_expr(Expr::Column(binding), ty)
467    }
468
469    /// Joins scalar query results into the row stream that contains their expressions.
470    fn attach_scalar_subqueries(&mut self, mut input: NodeRef) -> NodeRef {
471        let subqueries = std::mem::take(&mut self.scalar_subqueries);
472        for pending in subqueries {
473            input = self.attach_subquery(input, pending);
474        }
475        input
476    }
477
478    /// Joins one query's result into a row stream, which is where its columns come from.
479    ///
480    /// Split out from [`Self::attach_scalar_subqueries`] because a join's `ON` does not attach its
481    /// queries to the rows the whole `FROM` produced. It attaches them to one of the join's two
482    /// inputs, since a join condition is evaluated by the join and can only read what the join was
483    /// given.
484    fn attach_subquery(&mut self, input: NodeRef, pending: PendingSubquery) -> NodeRef {
485        let PendingSubquery {
486            node: mut right,
487            kind,
488            conditions,
489            dependent,
490            reads: _,
491            index: _,
492            inside_aggregate: _,
493        } = pending;
494        if kind == JoinKind::Single && !self.semantics.scalar_subquery_error_on_multiple_rows() {
495            right = self.add_node(Node::Limit {
496                input: right,
497                count: Bound::Rows(1),
498                offset: Bound::Rows(0),
499            });
500        }
501        let conditions = self.plan.add_expr_list(&conditions);
502        if dependent {
503            self.add_node(Node::DependentJoin { left: input, right, kind, conditions })
504        } else {
505            self.add_node(Node::Join {
506                left: input,
507                right,
508                kind,
509                conditions,
510                build: BuildSide::default(),
511            })
512        }
513    }
514
515    // ---------------------------------------------------------------- queries
516
517    pub(crate) fn bind_query(
518        &mut self,
519        ast: &Ast,
520        query: ast::QueryRef,
521    ) -> Result<(NodeRef, Scope)> {
522        let span = ast.query_span(query);
523        let outer = std::mem::replace(&mut self.current_span, span);
524        let result =
525            self.bind_query_inner(ast, query).map_err(|error| error.with_fallback_span(span));
526        self.current_span = outer;
527        result
528    }
529
530    fn bind_query_inner(&mut self, ast: &Ast, query: ast::QueryRef) -> Result<(NodeRef, Scope)> {
531        let written = ast.query(query);
532        if written.ctes.is_empty() {
533            return self.bind_body(ast, &written);
534        }
535        // The names a query introduces are gone again once it is bound, and they go whether the
536        // binding worked or not, which is why the stack is cut back here rather than at the end of
537        // the call that pushed onto it.
538        let depth = self.materialized.len();
539        let result = self.bind_materialized(ast, &written);
540        self.materialized.truncate(depth);
541        result
542    }
543
544    /// A query with materialised `WITH` definitions in front of it.
545    ///
546    /// The definitions are bound first and in the order they were written, so that a later one can
547    /// read an earlier one, and then the body. The wrapping runs backwards so that the first
548    /// definition ends up outermost, which is the order they have to be filled in.
549    fn bind_materialized(&mut self, ast: &Ast, written: &ast::Query) -> Result<(NodeRef, Scope)> {
550        let depth = self.materialized.len();
551        let held = ast.cte_list(written.ctes).to_vec();
552        let mut definitions = Vec::with_capacity(held.len());
553        for &index in &held {
554            definitions.push(self.bind_definition(ast, index)?);
555        }
556        let (mut node, scope) = self.bind_body(ast, written)?;
557        for (at, definition) in definitions.into_iter().enumerate().rev() {
558            let entry = &self.materialized[depth + at];
559            let cte = entry.cte;
560            let name = entry.name.clone();
561            let fields = entry.fields.clone();
562            let name = self.plan.intern(&name);
563            let columns = self.plan.add_fields(&fields);
564            node =
565                self.add_node(Node::MaterializedCte { definition, body: node, name, cte, columns });
566        }
567        Ok((node, scope))
568    }
569
570    /// Binds one materialised `WITH` definition and makes its name readable from there on.
571    ///
572    /// The definition is projected onto exactly the columns a read of it sees, under the names the
573    /// column list declared when there was one. That projection is not decoration: what is held is
574    /// what a read gets back, so the held rows have to be the rows of the definition's own select
575    /// list and nothing it happened to carry along underneath.
576    ///
577    /// A column list with more names in it than the definition has columns is not an error here,
578    /// which is the pinned build's rule and is written out on [`Scope::rename_prefix`].
579    fn bind_definition(&mut self, ast: &Ast, index: u32) -> Result<NodeRef> {
580        let held = ast.cte(index);
581        let name = ast.string(held.name).to_string();
582        let (node, mut scope) = self.bind_query(ast, held.query)?;
583        if !held.columns.is_empty() {
584            let names: Vec<&str> = ast.name(held.columns).collect();
585            scope.rename_prefix(&names);
586        }
587        let table = self.fresh_index();
588        let mut exprs = Vec::with_capacity(scope.len());
589        let mut names = Vec::with_capacity(scope.len());
590        for column in &scope.columns {
591            exprs.push(self.plan.add_expr(Expr::Column(column.binding), column.ty.clone()));
592            names.push(self.plan.intern(&column.name));
593        }
594        let exprs = self.plan.add_expr_list(&exprs);
595        let names = self.plan.add_name_list(&names);
596        let node = self.add_node(Node::Project { input: node, index: table, exprs, names });
597        let cte = self.next_cte;
598        self.next_cte += 1;
599        self.materialized.push(Materialized { written: index, cte, name, fields: scope.fields() });
600        Ok(node)
601    }
602
603    fn bind_body(&mut self, ast: &Ast, written: &ast::Query) -> Result<(NodeRef, Scope)> {
604        match written.body {
605            ast::QueryBody::Select(select) => self.bind_select(ast, select, written),
606            ast::QueryBody::SetOp { op, quantifier, by_name, left, right } => {
607                let operator = Operator { op, quantifier, by_name };
608                self.bind_set_op(ast, written, operator, left, right)
609            }
610            ast::QueryBody::Values(rows) => self.bind_values(ast, written, rows),
611            ast::QueryBody::Describe(inner) => self.bind_describe(ast, written, inner),
612            ast::QueryBody::Show { name, relation } => self.bind_show(ast, written, name, relation),
613        }
614    }
615
616    /// `SHOW name`, resolved while binding so execution receives an ordinary constant plan.
617    fn bind_show(
618        &mut self,
619        ast: &Ast,
620        query: &ast::Query,
621        name: ast::Slice,
622        relation: ast::QueryRef,
623    ) -> Result<(NodeRef, Scope)> {
624        let text = ast.name_text(name);
625        let parts: Vec<&str> = ast.name(name).collect();
626        let table_exists = self.catalog.resolve(&parts).is_ok();
627        let as_table = match self.semantics.show_behavior() {
628            ShowBehavior::Auto => table_exists,
629            ShowBehavior::Setting => false,
630            ShowBehavior::Table => true,
631        };
632        if as_table {
633            return self.bind_describe(ast, query, relation);
634        }
635        // A name the session has no answer for is either a setting rudb has and DuckDB does not, in
636        // which case [`Binder::beyond`] reads it, or it is nothing, in which case that says so in
637        // upstream's words. `SHOW` prints and printing is text, so a rule's boolean comes back here
638        // as the word it reads back as rather than as a boolean column.
639        let shown = match self.session.iter().find(|(name, _)| name.eq_ignore_ascii_case(&text)) {
640            Some((_, value)) => value.to_string(),
641            None => match self.beyond(&text)? {
642                Some(Value::Varchar(declared)) => declared,
643                Some(other) => other.to_string(),
644                None => {
645                    return Err(Error::catalog(format!(
646                        "Setting with name \"{text}\" does not exist"
647                    )));
648                }
649            },
650        };
651        let field = Field::new(text, LogicalType::Varchar);
652        let expr = self.plan.add_constant(Value::Varchar(shown));
653        let row = self.plan.add_expr_list(&[expr]);
654        let rows = self.plan.add_rows(&[row]);
655        let columns = self.plan.add_fields(std::slice::from_ref(&field));
656        let index = self.fresh_index();
657        let node = self.add_node(Node::Values { index, columns, rows });
658        let mut scope = Scope::empty();
659        scope.push(Visible {
660            table: String::new(),
661            name: field.name,
662            binding: ColumnBinding::new(index, 0),
663            ty: LogicalType::Varchar,
664            not_null: false,
665            key: None,
666            default: None,
667            qualified: false,
668            also: None,
669        });
670        Ok((node, scope))
671    }
672
673    /// `DESCRIBE <query>`, which is six VARCHAR columns saying what the query returns.
674    ///
675    /// The query is bound and never run, because binding is the whole of the answer: the names and
676    /// the types of a query's columns are settled by the time the binder is done with it, so the
677    /// rows of a describe are a constant from there on. That is why this comes out as a `VALUES`
678    /// whose rows were computed here rather than as an operator of its own, and it is what makes
679    /// `SELECT column_name FROM (DESCRIBE ...) WHERE ...` an ordinary query over an ordinary
680    /// relation with no special case above it.
681    ///
682    /// The six columns, their order and their types are the reference binary's. `key` says which
683    /// key of its table a column passed straight through from one is in. `default` is the SQL of the column's `DEFAULT` in the pin's spelling, and
684    /// `extra` is empty upstream as well on every table it was asked about. They are here rather
685    /// than left out because the width of a result is part of the result, and a program that reads
686    /// the fifth column has to find one.
687    fn bind_describe(
688        &mut self,
689        ast: &Ast,
690        query: &ast::Query,
691        inner: ast::QueryRef,
692    ) -> Result<(NodeRef, Scope)> {
693        let (_, described) = self.bind_query(ast, inner)?;
694        let fields: Vec<Field> = ["column_name", "column_type", "null", "key", "default", "extra"]
695            .iter()
696            .map(|name| Field::new(*name, LogicalType::Varchar))
697            .collect();
698        let mut slices = Vec::with_capacity(described.columns.len());
699        for column in described.columns.clone() {
700            // `NO` and `YES` and not a boolean, because the column is VARCHAR upstream and a
701            // client that prints the result has to get the same four or three characters.
702            let written = [
703                column.name.clone(),
704                column.ty.to_string(),
705                if column.not_null { "NO" } else { "YES" }.to_owned(),
706            ];
707            let mut items: Vec<ExprRef> = written
708                .into_iter()
709                .map(|text| self.plan.add_constant(Value::Varchar(text)))
710                .collect();
711            let mark = match column.key {
712                Some(mark) => self.plan.add_constant(Value::Varchar(mark.to_owned())),
713                None => {
714                    let empty = self.plan.add_constant(Value::Null);
715                    self.cast_to(empty, &LogicalType::Varchar)
716                }
717            };
718            items.push(mark);
719            if let Some(default) = &column.default {
720                items.push(self.plan.add_constant(Value::Varchar(default.clone())));
721            }
722            while items.len() < 6 {
723                let empty = self.plan.add_constant(Value::Null);
724                items.push(self.cast_to(empty, &LogicalType::Varchar));
725            }
726            slices.push(self.plan.add_expr_list(&items));
727        }
728        let rows = self.plan.add_rows(&slices);
729        let columns = self.plan.add_fields(&fields);
730        let index = self.fresh_index();
731        let mut node = self.add_node(Node::Values { index, columns, rows });
732        let mut scope = Scope::empty();
733        for (at, field) in fields.iter().enumerate() {
734            scope.push(Visible {
735                table: String::new(),
736                name: field.name.clone(),
737                binding: ColumnBinding::new(index, at as u32),
738                ty: field.ty.clone(),
739                not_null: false,
740                key: None,
741                default: None,
742                qualified: false,
743                also: None,
744            });
745        }
746        let keys = self.sort_keys(ast, query, &scope, &[])?;
747        if !keys.is_empty() {
748            let keys = self.plan.add_sort_keys(&keys);
749            node = self.add_node(Node::Sort { input: node, keys });
750        }
751        node = self.apply_limit(ast, query, node, &mut scope)?;
752        Ok((node, scope))
753    }
754
755    /// A column's default as an expression of the column's type, or a null of that type for a
756    /// column with none. A typed null rather than `add_constant`, which would give it the null
757    /// type and make the column's type depend on whether a row happened to be inserted into it.
758    pub(crate) fn bind_default(&mut self, text: Option<&str>, ty: &LogicalType) -> Result<ExprRef> {
759        let Some(text) = text else {
760            let value = self.plan.add_value(Value::Null);
761            return Ok(self.plan.add_expr(Expr::Constant(value), ty.clone()));
762        };
763        let ast = rudb_parse::parse_ast(&format!("SELECT {text}"))?;
764        let found = match ast.statements.first() {
765            Some(&ast::Statement::Query(query)) => match ast.query(query).body {
766                ast::QueryBody::Select(select) => {
767                    ast.target_list(ast.select(select).targets).first().map(|target| target.expr)
768                }
769                _ => None,
770            },
771            _ => None,
772        };
773        let Some(expr) = found else {
774            return Err(Error::internal(format!("a default that is not an expression: {text}")));
775        };
776        let expr = self.bind_expr(&ast, expr, &Scope::empty())?;
777        self.checked_cast_to(expr, ty, false)
778    }
779
780    /// Whether a projected expression is a column passed straight through from below.
781    ///
782    /// Only `DESCRIBE` asks, and only to decide whether the `null` column says `NO`. Anything that
783    /// is computed is nullable however strict its inputs were, which is both the safe reading and
784    /// the one the reference binary gives.
785    fn passes_through(&self, expr: ExprRef, input: &Scope) -> bool {
786        let Expr::Column(binding) = *self.plan.expr(expr) else { return false };
787        input.columns.iter().any(|column| column.binding == binding && column.not_null)
788    }
789
790    /// The key a projected expression is in, when it is a column passed straight through from a
791    /// table that has one. The same question as [`Self::passes_through`], asked for `DESCRIBE`'s
792    /// `key` column.
793    fn key_through(&self, expr: ExprRef, input: &Scope) -> Option<&'static str> {
794        self.through(expr, input).and_then(|column| column.key)
795    }
796
797    /// The column a projected expression passes straight through from below, if it is one.
798    fn through<'s>(&self, expr: ExprRef, input: &'s Scope) -> Option<&'s Visible> {
799        let Expr::Column(binding) = *self.plan.expr(expr) else { return None };
800        input.columns.iter().find(|column| column.binding == binding)
801    }
802
803    /// `VALUES (1, 'a'), (2, 'b')`, as a query in its own right.
804    ///
805    /// The column names are `col0`, `col1` and so on, which is what DuckDB calls them, and the
806    /// column types are what every row in that position promotes to. Promotion is the same rule a
807    /// set operation uses, and for the same reason: a column has one type and the rows have to
808    /// agree on it before anything downstream can read the column.
809    fn bind_values(
810        &mut self,
811        ast: &Ast,
812        query: &ast::Query,
813        rows: ast::Slice,
814    ) -> Result<(NodeRef, Scope)> {
815        let written = ast.rows(rows).to_vec();
816        let Some(first) = written.first() else {
817            return Err(Error::binder("VALUES needs at least one row"));
818        };
819        let width = first.len as usize;
820        for (at, row) in written.iter().enumerate() {
821            if row.len as usize != width {
822                return Err(Error::binder(format!(
823                    "VALUES lists must all be the same length, expected {width} columns but row {} has {}",
824                    at + 1,
825                    row.len
826                )));
827            }
828        }
829        // A row of a `VALUES` cannot see a column, because there is nothing under it to see.
830        let empty = Scope::empty();
831        let defaults = self.insert_defaults.take();
832        let previous = std::mem::replace(&mut self.clause, "VALUES clause");
833        let mut bound: Vec<Vec<ExprRef>> = Vec::with_capacity(written.len());
834        for row in &written {
835            let mut items = Vec::with_capacity(width);
836            for (at, &expr) in ast.expr_list(*row).iter().enumerate() {
837                let column = defaults.as_ref().and_then(|defaults| defaults.get(at));
838                items.push(match (ast.expr(expr), column) {
839                    (ast::Expr::Default, Some((ty, default))) => {
840                        self.bind_default(default.as_deref(), ty)?
841                    }
842                    _ => self.bind_expr(ast, expr, &empty)?,
843                });
844            }
845            bound.push(items);
846        }
847        self.clause = previous;
848        let mut types = Vec::with_capacity(width);
849        for at in 0..width {
850            let mut ty = self.plan.expr_type(bound[0][at]).clone();
851            for row in &bound[1..] {
852                let other = self.plan.expr_type(row[at]).clone();
853                ty = ty.promote(&other).ok_or_else(|| {
854                    Error::binder(format!(
855                        "Cannot combine a value of type {ty} with a value of type {other} in column {} of a VALUES",
856                        at + 1
857                    ))
858                })?;
859            }
860            types.push(ty);
861        }
862        let mut slices = Vec::with_capacity(bound.len());
863        for row in &bound {
864            let items: Vec<ExprRef> = row
865                .iter()
866                .zip(&types)
867                .map(|(&expr, ty)| self.checked_cast_to(expr, ty, false))
868                .collect::<Result<_>>()?;
869            slices.push(self.plan.add_expr_list(&items));
870        }
871        let rows = self.plan.add_rows(&slices);
872        let fields: Vec<Field> = types
873            .iter()
874            .enumerate()
875            .map(|(at, ty)| Field::new(format!("col{at}"), ty.clone()))
876            .collect();
877        let columns = self.plan.add_fields(&fields);
878        let index = self.fresh_index();
879        let mut node = self.add_node(Node::Values { index, columns, rows });
880        let mut scope = Scope::empty();
881        for (at, field) in fields.iter().enumerate() {
882            scope.push(Visible {
883                table: String::new(),
884                name: field.name.clone(),
885                binding: ColumnBinding::new(index, at as u32),
886                ty: field.ty.clone(),
887                not_null: false,
888                key: None,
889                default: None,
890                qualified: false,
891                also: None,
892            });
893        }
894        let keys = self.sort_keys(ast, query, &scope, &[])?;
895        if !keys.is_empty() {
896            let keys = self.plan.add_sort_keys(&keys);
897            node = self.add_node(Node::Sort { input: node, keys });
898        }
899        node = self.apply_limit(ast, query, node, &mut scope)?;
900        Ok((node, scope))
901    }
902
903    fn bind_set_op(
904        &mut self,
905        ast: &Ast,
906        query: &ast::Query,
907        operator: Operator,
908        left: ast::QueryRef,
909        right: ast::QueryRef,
910    ) -> Result<(NodeRef, Scope)> {
911        let (left_node, left_scope) = self.bind_query(ast, left)?;
912        let (right_node, right_scope) = self.bind_query(ast, right)?;
913        let merged = if operator.by_name {
914            match_by_name(&left_scope, &right_scope)?
915        } else {
916            match_by_position(&left_scope, &right_scope)?
917        };
918        let left_node = self.conform(left_node, &left_scope, &merged, |column| column.left)?;
919        let right_node = self.conform(right_node, &right_scope, &merged, |column| column.right)?;
920        let index = self.fresh_index();
921        let kind = match operator.op {
922            SetOp::Union => SetOpKind::Union,
923            SetOp::Except => SetOpKind::Except,
924            SetOp::Intersect => SetOpKind::Intersect,
925        };
926        // UNION alone removes duplicates and UNION ALL keeps them, which is the one place the
927        // unwritten quantifier and ALL disagree.
928        let all = operator.quantifier == Quantifier::All;
929        let mut node =
930            self.add_node(Node::SetOp { left: left_node, right: right_node, kind, all, index });
931        let mut scope = Scope::empty();
932        for (at, column) in merged.iter().enumerate() {
933            scope.push(Visible {
934                table: String::new(),
935                name: column.name.clone(),
936                binding: ColumnBinding::new(index, at as u32),
937                ty: column.ty.clone(),
938                // A column of a set operation is nullable whatever the two sides were, because a
939                // column that refuses nulls on one side and takes them on the other takes them.
940                not_null: false,
941                key: None,
942                default: None,
943                qualified: false,
944                also: None,
945            });
946        }
947        // Above a set operation there is nothing but the output columns, so an ORDER BY term is
948        // either a position, an output name, or an expression over the output, and never needs a
949        // column projected for it that the query did not ask for.
950        let keys = self.sort_keys(ast, query, &scope, &[])?;
951        if !keys.is_empty() {
952            let keys = self.plan.add_sort_keys(&keys);
953            node = self.add_node(Node::Sort { input: node, keys });
954        }
955        node = self.apply_limit(ast, query, node, &mut scope)?;
956        Ok((node, scope))
957    }
958
959    /// Projects one side of a set operation onto the columns the operation comes out with.
960    ///
961    /// `pick` says which column of this side each output column is. It answers nothing for a
962    /// column only the other side wrote, which happens under `BY NAME` and which this side fills
963    /// with a null, since that is the row it would have written if it had written the column.
964    fn conform(
965        &mut self,
966        node: NodeRef,
967        scope: &Scope,
968        merged: &[Merged],
969        pick: impl Fn(&Merged) -> Option<usize>,
970    ) -> Result<NodeRef> {
971        let unchanged = merged.len() == scope.len()
972            && merged
973                .iter()
974                .enumerate()
975                .all(|(at, column)| pick(column) == Some(at) && column.ty == scope.columns[at].ty);
976        if unchanged {
977            return Ok(node);
978        }
979        let index = self.fresh_index();
980        let mut exprs = Vec::with_capacity(merged.len());
981        let mut names = Vec::with_capacity(merged.len());
982        for column in merged {
983            let expr = match pick(column) {
984                Some(at) => {
985                    let held = &scope.columns[at];
986                    self.plan.add_expr(Expr::Column(held.binding), held.ty.clone())
987                }
988                None => self.plan.add_constant(Value::Null),
989            };
990            exprs.push(self.checked_cast_to(expr, &column.ty, false)?);
991            names.push(self.plan.intern(&column.name));
992        }
993        let exprs = self.plan.add_expr_list(&exprs);
994        let names = self.plan.add_name_list(&names);
995        Ok(self.add_node(Node::Project { input: node, index, exprs, names }))
996    }
997
998    // ----------------------------------------------------------------- select
999
1000    fn bind_select(
1001        &mut self,
1002        ast: &Ast,
1003        select: ast::SelectRef,
1004        query: &ast::Query,
1005    ) -> Result<(NodeRef, Scope)> {
1006        let written = ast.select(select);
1007        self.want_ascending |= !written.group_by.is_empty() || written.group_by_all;
1008        // A window belongs to the block that wrote it, and a block can be bound inside another one
1009        // without a subquery in between, so the outer block's runs are put aside for the duration
1010        // rather than left where a nested block would append to them.
1011        let outer_windows = std::mem::take(&mut self.windows);
1012        // The same for the unnests, which also run over this block's rows and nobody else's.
1013        let outer_unnests = std::mem::take(&mut self.unnests);
1014        let outer_unnest_index = self.unnest_index.take();
1015        let outer_unnest_here = std::mem::replace(&mut self.unnest_here, false);
1016        let outer_in_unnest = std::mem::replace(&mut self.in_unnest, false);
1017        let outer_unnest_grouping = self.unnest_grouping.take();
1018        let outer_grouped_unnests = std::mem::take(&mut self.grouped_unnests);
1019        // Same argument for the queries lifted over this block's grouping. They are recorded while
1020        // the select list is being bound and read until the sort keys are done, and a block bound
1021        // inside that stretch has its own set, so the outer block's is put aside rather than left
1022        // where the inner one would clear it.
1023        let outer_joined_above = std::mem::take(&mut self.joined_above);
1024        let (mut node, input) = self.bind_from(ast, written.from)?;
1025        node = self.attach_scalar_subqueries(node);
1026
1027        if written.filter != NONE {
1028            self.clause = "WHERE clause";
1029            let predicate = self.bind_expr(ast, written.filter, &input)?;
1030            let predicate = self.as_boolean(predicate, "WHERE")?;
1031            node = self.attach_scalar_subqueries(node);
1032            node = self.add_node(Node::Filter { input: node, predicate });
1033        }
1034
1035        let targets = ast.target_list(written.targets).to_vec();
1036        if targets.is_empty() {
1037            return Err(Error::binder("a SELECT needs at least one expression to select"));
1038        }
1039
1040        let group_items = self.group_items(ast, &written, &targets)?;
1041        let aggregating = !group_items.is_empty()
1042            || written.having != NONE
1043            || targets.iter().any(|target| has_aggregate(ast, target.expr));
1044        if aggregating {
1045            self.clause = "GROUP BY clause";
1046            // An unnest in a grouping key runs under the grouping, over the rows of the `FROM`,
1047            // and makes the rows that are grouped. `SELECT unnest(tags) AS tag, count(*) ... GROUP
1048            // BY tag` counts the rows each tag appears in.
1049            self.unnest_here = true;
1050            self.unnest_grouping = Some(written.group_by_all);
1051            let mut groups = Vec::with_capacity(group_items.len());
1052            for item in &group_items {
1053                groups.push(self.bind_expr(ast, *item, &input)?);
1054            }
1055            self.unnest_here = false;
1056            self.unnest_grouping = None;
1057            let unnests = std::mem::take(&mut self.unnests);
1058            if let Some(index) = self.unnest_index.take() {
1059                node = self.plan_unnests(node, index, &unnests)?;
1060            }
1061            let index = self.fresh_index();
1062            self.aggregation = Some(Aggregation { index, groups, aggregates: Vec::new() });
1063        }
1064
1065        // The queries this block's clauses wrote that are joined in above the grouping rather than
1066        // below it. TPC-H q11 is the case in a `HAVING`: `HAVING sum(ps_supplycost * ps_availqty) >
1067        // (SELECT sum(...))` compares one group's total against a total over the whole table, and
1068        // the second total is one row that has nothing to do with the groups. Joined underneath the
1069        // grouping it would be a column of every input row and the grouping rule would ask for it in
1070        // the GROUP BY, which is the complaint this used to make.
1071        let mut above = Vec::new();
1072
1073        self.clause = "SELECT clause";
1074        self.unnest_here = true;
1075        let (mut exprs, mut names) = self.bind_targets(ast, &targets, &input, &mut above)?;
1076        self.unnest_here = false;
1077        let visible = exprs.len();
1078
1079        let mut having = None;
1080        if written.having != NONE {
1081            self.clause = "HAVING clause";
1082            let before = self.scalar_subqueries.len();
1083            let predicate = self.bind_expr(ast, written.having, &input)?;
1084            self.lift_over_aggregate(before, &mut above, &input)?;
1085            let predicate = self.over_aggregate(predicate, &input)?;
1086            having = Some(self.as_boolean(predicate, "HAVING")?);
1087        }
1088
1089        // The projection's index has to exist before the sort keys are built, because a key is a
1090        // reference to a projected column even when the expression it sorts on is not selected.
1091        let project = self.fresh_index();
1092        let mut output = Scope::empty();
1093        for (at, (expr, name)) in exprs.iter().zip(&names).enumerate() {
1094            output.push(Visible {
1095                table: String::new(),
1096                name: name.clone(),
1097                binding: ColumnBinding::new(project, at as u32),
1098                ty: self.plan.expr_type(*expr).clone(),
1099                not_null: self.passes_through(*expr, &input),
1100                key: self.key_through(*expr, &input),
1101                default: self.through(*expr, &input).and_then(|column| column.default.clone()),
1102                qualified: false,
1103                also: None,
1104            });
1105        }
1106
1107        self.clause = "ORDER BY clause";
1108        let mut extra = Vec::new();
1109        self.unnest_here = true;
1110        let keys = self.select_sort_keys(
1111            ast, query, &input, &output, project, &mut exprs, &mut names, &mut extra, &mut above,
1112        )?;
1113        self.unnest_here = outer_unnest_here;
1114        self.in_unnest = outer_in_unnest;
1115        self.unnest_grouping = outer_unnest_grouping;
1116        self.grouped_unnests = outer_grouped_unnests;
1117        self.joined_above = outer_joined_above;
1118        if !extra.is_empty() && written.distinct != Distinct::No {
1119            return Err(Error::binder(
1120                "For SELECT DISTINCT, ORDER BY expressions must appear in the select list",
1121            ));
1122        }
1123        let on = self.distinct_on(ast, written.distinct, &output)?;
1124
1125        node = self.attach_scalar_subqueries(node);
1126
1127        if let Some(aggregation) = self.aggregation.take() {
1128            let index = aggregation.index;
1129            let groups = self.plan.add_expr_list(&aggregation.groups);
1130            let aggregates = self.plan.add_expr_list(&aggregation.aggregates);
1131            node = self.add_node(Node::Aggregate { input: node, index, groups, aggregates });
1132        }
1133        if !above.is_empty() {
1134            debug_assert!(self.scalar_subqueries.is_empty(), "a query is waiting to be joined");
1135            self.scalar_subqueries = above;
1136            node = self.attach_scalar_subqueries(node);
1137        }
1138        if let Some(predicate) = having {
1139            node = self.add_node(Node::Filter { input: node, predicate });
1140        }
1141
1142        // After the grouping and after `HAVING`, which is where the reference binary puts it:
1143        // `SELECT j, sum(count(i)) OVER () FROM t GROUP BY j HAVING count(i) > 1` totals only the
1144        // groups that survived the filter.
1145        for run in std::mem::replace(&mut self.windows, outer_windows) {
1146            let partition = self.plan.add_expr_list(&run.partition);
1147            let order = self.plan.add_sort_keys(&run.order);
1148            let expressions = self.plan.add_expr_list(&run.calls);
1149            node = self.add_node(Node::Window {
1150                input: node,
1151                index: run.index,
1152                partition,
1153                order,
1154                frame: run.frame,
1155                expressions,
1156            });
1157        }
1158        // After the windows, which is also the pin's order: `SELECT unnest([1, 2]), count(*) OVER
1159        // ()` counts one row and then makes two of it.
1160        let unnests = std::mem::replace(&mut self.unnests, outer_unnests);
1161        if let Some(index) = std::mem::replace(&mut self.unnest_index, outer_unnest_index) {
1162            node = self.plan_unnests(node, index, &unnests)?;
1163        }
1164
1165        let interned: Vec<u32> = names.iter().map(|name| self.plan.intern(name)).collect();
1166        let exprs_slice = self.plan.add_expr_list(&exprs);
1167        let names_slice = self.plan.add_name_list(&interned);
1168        node = self.add_node(Node::Project {
1169            input: node,
1170            index: project,
1171            exprs: exprs_slice,
1172            names: names_slice,
1173        });
1174
1175        if written.distinct != Distinct::No {
1176            let on = self.plan.add_expr_list(&on);
1177            node = self.add_node(Node::Distinct { input: node, on });
1178        }
1179        if !keys.is_empty() {
1180            let keys = self.plan.add_sort_keys(&keys);
1181            node = self.add_node(Node::Sort { input: node, keys });
1182        }
1183        node = self.apply_limit(ast, query, node, &mut output)?;
1184
1185        if extra.is_empty() {
1186            output.columns.truncate(visible);
1187            return Ok((node, output));
1188        }
1189        // An expression sorted on but not selected was carried this far to make the sort possible,
1190        // and now it goes, because the query did not ask for it.
1191        let index = self.fresh_index();
1192        let mut kept = Vec::with_capacity(visible);
1193        let mut kept_names = Vec::with_capacity(visible);
1194        let mut scope = Scope::empty();
1195        for (at, name) in names.iter().enumerate().take(visible) {
1196            let ty = output.columns[at].ty.clone();
1197            // Through the scope rather than through `project`, because a limit that had a query
1198            // joined in under it put a projection of its own over the top and these columns are
1199            // that projection's now.
1200            let binding = output.columns[at].binding;
1201            kept.push(self.plan.add_expr(Expr::Column(binding), ty.clone()));
1202            kept_names.push(self.plan.intern(name));
1203            scope.push(Visible {
1204                table: String::new(),
1205                name: name.clone(),
1206                binding: ColumnBinding::new(index, at as u32),
1207                ty,
1208                not_null: output.columns[at].not_null,
1209                key: output.columns[at].key,
1210                default: output.columns[at].default.clone(),
1211                qualified: false,
1212                also: None,
1213            });
1214        }
1215        let exprs = self.plan.add_expr_list(&kept);
1216        let names = self.plan.add_name_list(&kept_names);
1217        node = self.add_node(Node::Project { input: node, index, exprs, names });
1218        Ok((node, scope))
1219    }
1220
1221    /// Binds the target list, expanding every star into the columns it stands for.
1222    /// Moves the queries a clause just wrote from under this block's grouping to over it.
1223    ///
1224    /// A query written in a select list, a `HAVING` or an `ORDER BY` is one row that has nothing to
1225    /// do with the groups, so it belongs on top of the grouping and not underneath it. Underneath,
1226    /// its column is a column of every row going into the aggregate, which the grouping rule then
1227    /// asks for in the `GROUP BY`, and the aggregate carries nothing but its groups and its
1228    /// aggregates upward, so the projection could not read the column even if the rule let it
1229    /// through. That is both halves of #1027.
1230    ///
1231    /// A correlated one goes over the grouping too when what it correlates to is a column the block
1232    /// groups by, which is [`Self::lift_correlated`], and stays underneath when it is not. One
1233    /// written inside an aggregate call stays underneath whatever it correlates to, since that is
1234    /// read once per row going into the aggregate and lifting it over would put it where the
1235    /// aggregate that reads it cannot.
1236    ///
1237    /// `before` is what [`Self::scalar_subqueries`] held before the clause was bound, so only the
1238    /// queries that clause wrote are considered.
1239    fn lift_over_aggregate(
1240        &mut self,
1241        before: usize,
1242        above: &mut Vec<PendingSubquery>,
1243        scope: &Scope,
1244    ) -> Result<()> {
1245        if self.aggregation.is_none() {
1246            return Ok(());
1247        }
1248        let mut lifted = Vec::new();
1249        for mut pending in self.scalar_subqueries.split_off(before) {
1250            let stays = pending.inside_aggregate
1251                || (pending.dependent && !self.lift_correlated(&mut pending));
1252            if stays {
1253                self.scalar_subqueries.push(pending);
1254            } else {
1255                self.joined_above.push(pending.index);
1256                lifted.push(pending);
1257            }
1258        }
1259        // A mark join carries its comparison rather than the expression carrying it, and that
1260        // comparison is written over the outer rows, so it needs the same rewrite the expression
1261        // gets. It is done in a second pass so that a comparison reading another query lifted by
1262        // the same clause finds that query's index already recorded.
1263        for pending in &mut lifted {
1264            let conditions = std::mem::take(&mut pending.conditions);
1265            let mut over = Vec::with_capacity(conditions.len());
1266            for condition in conditions {
1267                over.push(self.over_aggregate(condition, scope)?);
1268            }
1269            pending.conditions = over;
1270        }
1271        above.append(&mut lifted);
1272        Ok(())
1273    }
1274
1275    /// Moves one correlated query over this block's grouping, if the grouping lets it.
1276    ///
1277    /// It does when every outer column the query reads is a column this block groups by. That value
1278    /// is the group's own column above the aggregate, the same value read from a different operator,
1279    /// so the query can be joined against the groups instead of against the rows going into them,
1280    /// and what the query answers per group is what it answered per row of a group since every row
1281    /// of a group agreed on it. The rewrite is the references inside the query's body, which were
1282    /// bound against the table underneath and have to read the aggregate's output instead.
1283    ///
1284    /// A correlation on a column that is neither grouped nor aggregated is a different question with
1285    /// a different answer and there is nothing above the grouping that holds it, so that query stays
1286    /// where it is and [`Self::over_aggregate`] reports it as the missing `GROUP BY` it is. That is
1287    /// #1032.
1288    ///
1289    /// The query stays a dependent join either way. What changed is which operator the outer rows
1290    /// come from, not that there are any.
1291    fn lift_correlated(&mut self, pending: &mut PendingSubquery) -> bool {
1292        let Some(index) = self.aggregation.as_ref().map(|aggregation| aggregation.index) else {
1293            return false;
1294        };
1295        let mut moved = Vec::with_capacity(pending.reads.len());
1296        for read in &pending.reads {
1297            let Some(at) = self.group_of(*read) else {
1298                return false;
1299            };
1300            moved.push((*read, ColumnBinding::new(index, at as u32)));
1301        }
1302        let mut rewrites = Vec::new();
1303        self.plan.subtree_columns(pending.node, &mut |reference, binding| {
1304            if let Some(&(_, to)) = moved.iter().find(|(from, _)| *from == binding) {
1305                rewrites.push((reference, to));
1306            }
1307        });
1308        for (reference, to) in rewrites {
1309            self.plan.rebind(reference, to);
1310        }
1311        pending.reads = moved.into_iter().map(|(_, to)| to).collect();
1312        true
1313    }
1314
1315    fn bind_targets(
1316        &mut self,
1317        ast: &Ast,
1318        targets: &[ast::Target],
1319        input: &Scope,
1320        above: &mut Vec<PendingSubquery>,
1321    ) -> Result<(Vec<ExprRef>, Vec<String>)> {
1322        let mut exprs = Vec::with_capacity(targets.len());
1323        let mut names = Vec::with_capacity(targets.len());
1324        for target in targets {
1325            if let ast::Expr::Star { qualifier, replacements } = ast.expr(target.expr) {
1326                let table = ast.name(qualifier).last().map(str::to_string);
1327                let expanded: Vec<Visible> =
1328                    input.star(table.as_deref())?.into_iter().cloned().collect();
1329                let replacements = ast.target_list(replacements).to_vec();
1330                let mut used = vec![false; replacements.len()];
1331                for column in expanded {
1332                    let found = replacements.iter().zip(&mut used).find(|(replacement, _)| {
1333                        same_name(ast.string(replacement.alias), &column.name)
1334                    });
1335                    // The replacement takes the column's place and its position, and it is named the
1336                    // way the replace list spells it rather than the way the table does. That only
1337                    // shows when the two differ in case, and `AS EventDate` over a column called
1338                    // `eventdate` is exactly the case that shows it.
1339                    let before = self.scalar_subqueries.len();
1340                    let (expr, name) = match found {
1341                        Some((replacement, used)) => {
1342                            *used = true;
1343                            let expr = self.bind_expr(ast, replacement.expr, input)?;
1344                            (expr, ast.string(replacement.alias).to_string())
1345                        }
1346                        None => (
1347                            self.plan.add_expr(Expr::Column(column.binding), column.ty),
1348                            column.name,
1349                        ),
1350                    };
1351                    self.lift_over_aggregate(before, above, input)?;
1352                    exprs.push(self.over_aggregate(expr, input)?);
1353                    names.push(name);
1354                }
1355                // A replace list that named something the star did not stand for is a mistake and
1356                // not a no op, and it is caught here because this is the first point at which the
1357                // set of names the star stands for is known.
1358                if let Some((replacement, _)) =
1359                    replacements.iter().zip(&used).find(|(_, used)| !**used)
1360                {
1361                    return Err(missing_replacement(ast.string(replacement.alias), input));
1362                }
1363                continue;
1364            }
1365            let before = self.scalar_subqueries.len();
1366            self.unnest_root = matches!(ast.expr(target.expr), ast::Expr::Function { name, .. }
1367                if name.len == 1 && same_name(ast.name(name).last().unwrap_or_default(), "unnest"));
1368            let expr = self.bind_expr(ast, target.expr, input);
1369            self.unnest_root = false;
1370            let expr = expr?;
1371            self.lift_over_aggregate(before, above, input)?;
1372            if let Some(taking) = self.unnest_struct.take() {
1373                // A struct is a column per field, named by the fields whatever the target's alias.
1374                let expr = self.over_aggregate(expr, input)?;
1375                self.unnest_fields(expr, taking, None, &mut exprs, &mut names)?;
1376                continue;
1377            }
1378            exprs.push(self.over_aggregate(expr, input)?);
1379            names.push(if target.alias == NONE {
1380                self.output_name(ast, target.expr, input)
1381            } else {
1382                ast.string(target.alias).to_string()
1383            });
1384        }
1385        Ok((exprs, names))
1386    }
1387
1388    /// The name an unaliased target gets.
1389    ///
1390    /// A bare column keeps the spelling the table was created with rather than the spelling the
1391    /// query used, so `SELECT USERID FROM hits` has a column called `UserID`. Identifiers match
1392    /// without regard to case and the catalog is the one that holds the case.
1393    fn output_name(&self, ast: &Ast, target: ast::ExprRef, input: &Scope) -> String {
1394        if let ast::Expr::Column { name } = ast.expr(target) {
1395            let parts: Vec<&str> = ast.name(name).collect();
1396            if let Ok(found) = input.resolve(&parts) {
1397                // A column found by its second name is headed by that name, so `t.range` over
1398                // `range(2) t` is a column called `range` on the pin while `SELECT *` calls it `t`.
1399                let written = parts.last().copied().unwrap_or_default();
1400                if let Some(also) = &found.also
1401                    && !same_name(&found.name, written)
1402                    && same_name(also, written)
1403                {
1404                    return also.clone();
1405                }
1406                return found.name.clone();
1407            }
1408        }
1409        describe(ast, target, self.semantics)
1410    }
1411
1412    /// The expressions a `GROUP BY` clause names, with positions and output aliases followed.
1413    fn group_items(
1414        &self,
1415        ast: &Ast,
1416        select: &ast::Select,
1417        targets: &[ast::Target],
1418    ) -> Result<Vec<ast::ExprRef>> {
1419        if select.group_by_all {
1420            // GROUP BY ALL means every target that is not itself an aggregate, which is the set
1421            // that would otherwise have to be written out again by hand.
1422            return Ok(targets
1423                .iter()
1424                .filter(|target| !has_aggregate(ast, target.expr))
1425                .map(|target| target.expr)
1426                .collect());
1427        }
1428        let mut items = Vec::new();
1429        for &item in ast.expr_list(select.group_by) {
1430            items.push(self.output_reference(ast, item, targets, "GROUP BY")?.unwrap_or(item));
1431        }
1432        Ok(items)
1433    }
1434
1435    /// The target a `GROUP BY` or `ORDER BY` term names, when it names one by position or alias.
1436    fn output_reference(
1437        &self,
1438        ast: &Ast,
1439        item: ast::ExprRef,
1440        targets: &[ast::Target],
1441        clause: &str,
1442    ) -> Result<Option<ast::ExprRef>> {
1443        match ast.expr(item) {
1444            ast::Expr::Literal { kind: LiteralKind::Number, text } => {
1445                let written = ast.string(text);
1446                let position: usize = written.parse().map_err(|_| {
1447                    Error::binder(format!("{clause} term {written} is not a column"))
1448                })?;
1449                if position == 0 || position > targets.len() {
1450                    return Err(Error::binder(format!(
1451                        "{clause} term out of range - should be between 1 and {}",
1452                        targets.len()
1453                    )));
1454                }
1455                Ok(Some(targets[position - 1].expr))
1456            }
1457            ast::Expr::Column { name } => {
1458                let parts: Vec<&str> = ast.name(name).collect();
1459                let [written] = parts.as_slice() else { return Ok(None) };
1460                let mut found = None;
1461                for target in targets {
1462                    if target.alias != NONE && same_name(ast.string(target.alias), written) {
1463                        if found.is_some() {
1464                            return Ok(None);
1465                        }
1466                        found = Some(target.expr);
1467                    }
1468                }
1469                Ok(found)
1470            }
1471            _ => Ok(None),
1472        }
1473    }
1474
1475    // -------------------------------------------------------------- modifiers
1476
1477    /// Sort keys for a select, projecting anything sorted on that is not already selected.
1478    #[allow(clippy::too_many_arguments)]
1479    fn select_sort_keys(
1480        &mut self,
1481        ast: &Ast,
1482        query: &ast::Query,
1483        input: &Scope,
1484        output: &Scope,
1485        project: u32,
1486        exprs: &mut Vec<ExprRef>,
1487        names: &mut Vec<String>,
1488        extra: &mut Vec<usize>,
1489        above: &mut Vec<PendingSubquery>,
1490    ) -> Result<Vec<SortKey>> {
1491        if query.order_by_all {
1492            return Ok(self.every_column(output));
1493        }
1494        let items = ast.order_list(query.order_by).to_vec();
1495        let mut keys = Vec::with_capacity(items.len());
1496        for item in items {
1497            self.check_order_literal(ast, item.expr)?;
1498            let position = match self.output_position(ast, item.expr, output)? {
1499                Some(position) => position,
1500                None => {
1501                    let before = self.scalar_subqueries.len();
1502                    let bound = self.bind_expr(ast, item.expr, input)?;
1503                    self.lift_over_aggregate(before, above, input)?;
1504                    let bound = self.over_aggregate(bound, input)?;
1505                    match exprs.iter().position(|&held| self.same_expr(held, bound)) {
1506                        Some(position) => position,
1507                        None => {
1508                            exprs.push(bound);
1509                            names.push(describe(ast, item.expr, self.semantics));
1510                            extra.push(exprs.len() - 1);
1511                            exprs.len() - 1
1512                        }
1513                    }
1514                }
1515            };
1516            let ty = self.plan.expr_type(exprs[position]).clone();
1517            let expr = self.column(project, position, ty);
1518            keys.push(self.sort_key(expr, item));
1519        }
1520        Ok(keys)
1521    }
1522
1523    /// Sort keys over an output that has nothing behind it to project, which is a set operation.
1524    fn sort_keys(
1525        &mut self,
1526        ast: &Ast,
1527        query: &ast::Query,
1528        output: &Scope,
1529        targets: &[ast::Target],
1530    ) -> Result<Vec<SortKey>> {
1531        if query.order_by_all {
1532            return Ok(self.every_column(output));
1533        }
1534        let items = ast.order_list(query.order_by).to_vec();
1535        let mut keys = Vec::with_capacity(items.len());
1536        for item in items {
1537            self.check_order_literal(ast, item.expr)?;
1538            let expr = match self.output_position(ast, item.expr, output)? {
1539                Some(position) => {
1540                    let column = &output.columns[position];
1541                    let (binding, ty) = (column.binding, column.ty.clone());
1542                    self.plan.add_expr(Expr::Column(binding), ty)
1543                }
1544                None => {
1545                    let _ = targets;
1546                    self.bind_expr(ast, item.expr, output)?
1547                }
1548            };
1549            keys.push(self.sort_key(expr, item));
1550        }
1551        Ok(keys)
1552    }
1553
1554    fn every_column(&mut self, output: &Scope) -> Vec<SortKey> {
1555        let columns: Vec<(ColumnBinding, LogicalType)> =
1556            output.columns.iter().map(|column| (column.binding, column.ty.clone())).collect();
1557        columns
1558            .into_iter()
1559            .map(|(binding, ty)| {
1560                let expr = self.plan.add_expr(Expr::Column(binding), ty);
1561                let expr = self.by_position(expr);
1562                let descending = self.semantics.default_descending();
1563                SortKey { expr, descending, nulls_first: self.semantics.nulls_first(descending) }
1564            })
1565            .collect()
1566    }
1567
1568    /// A sort key with the session defaults filled in.
1569    fn sort_key(&mut self, expr: ExprRef, item: ast::OrderItem) -> SortKey {
1570        let expr = self.by_position(expr);
1571        let descending = match item.order {
1572            Order::Unstated => self.semantics.default_descending(),
1573            Order::Ascending => false,
1574            Order::Descending => true,
1575        };
1576        let nulls_first = match item.nulls {
1577            Nulls::First => true,
1578            Nulls::Last => false,
1579            Nulls::Unstated => self.semantics.nulls_first(descending),
1580        };
1581        SortKey { expr, descending, nulls_first }
1582    }
1583
1584    /// Which output column a term names, by position or by name.
1585    fn output_position(
1586        &self,
1587        ast: &Ast,
1588        item: ast::ExprRef,
1589        output: &Scope,
1590    ) -> Result<Option<usize>> {
1591        match ast.expr(item) {
1592            ast::Expr::Literal { kind: LiteralKind::Number, text } => {
1593                let written = ast.string(text);
1594                if written.contains(['.', 'e', 'E']) {
1595                    return Ok(None);
1596                }
1597                let position: usize = written.parse().map_err(|_| {
1598                    Error::binder(format!("ORDER BY term {written} is not a column"))
1599                })?;
1600                if position == 0 || position > output.len() {
1601                    return Err(Error::binder(format!(
1602                        "ORDER BY term out of range - should be between 1 and {}",
1603                        output.len()
1604                    )));
1605                }
1606                Ok(Some(position - 1))
1607            }
1608            ast::Expr::Column { name } => {
1609                let parts: Vec<&str> = ast.name(name).collect();
1610                let [written] = parts.as_slice() else { return Ok(None) };
1611                Ok(output.position_of(None, written))
1612            }
1613            _ => Ok(None),
1614        }
1615    }
1616
1617    /// Refuses a literal sort key unless the session explicitly accepts its no-op behavior.
1618    fn check_order_literal(&self, ast: &Ast, item: ast::ExprRef) -> Result<()> {
1619        if !self.semantics.order_by_non_integer_literal()
1620            && matches!(
1621                ast.expr(item),
1622                ast::Expr::Literal { kind, text }
1623                    if kind != LiteralKind::Number
1624                        || ast.string(text).contains(['.', 'e', 'E'])
1625            )
1626        {
1627            return Err(Error::binder(
1628                "ORDER BY non-integer literal has no effect.\n* SET order_by_non_integer_literal=true to allow this behavior.",
1629            ));
1630        }
1631        Ok(())
1632    }
1633
1634    /// The expressions a `DISTINCT ON` names, which have to be columns of the output.
1635    fn distinct_on(
1636        &mut self,
1637        ast: &Ast,
1638        distinct: Distinct,
1639        output: &Scope,
1640    ) -> Result<Vec<ExprRef>> {
1641        let Distinct::On(items) = distinct else {
1642            return Ok(Vec::new());
1643        };
1644        let items = ast.expr_list(items).to_vec();
1645        let mut on = Vec::with_capacity(items.len());
1646        for item in items {
1647            let Some(position) = self.output_position(ast, item, output)? else {
1648                return Err(Error::not_implemented(
1649                    "DISTINCT ON an expression that is not in the select list",
1650                ));
1651            };
1652            let column = &output.columns[position];
1653            let (binding, ty) = (column.binding, column.ty.clone());
1654            on.push(self.plan.add_expr(Expr::Column(binding), ty));
1655        }
1656        Ok(on)
1657    }
1658
1659    /// The `LIMIT` and the `OFFSET`, over the rows everything else in the query produced.
1660    ///
1661    /// The scope is taken by reference because a limit the binder could not work out reads its
1662    /// number off a query joined in underneath, and that join puts a column in the rows which the
1663    /// query did not ask for. A projection over the limit drops it again, and the scope has to say
1664    /// so, since its bindings are what anything above this reads.
1665    fn apply_limit(
1666        &mut self,
1667        ast: &Ast,
1668        query: &ast::Query,
1669        input: NodeRef,
1670        scope: &mut Scope,
1671    ) -> Result<NodeRef> {
1672        let waiting = self.scalar_subqueries.len();
1673        if query.limit_percent {
1674            let percent = self.share(ast, query.limit)?;
1675            let offset = self.skipped(ast, query.offset)?;
1676            let node = |binder: &mut Self, input| match percent {
1677                Some(percent) => binder.add_node(Node::LimitPercent { input, percent, offset }),
1678                // A null share is no limit at all, the same as a null row count, so what is left
1679                // is whatever the offset asked for.
1680                None => binder.limited(input, Bound::All, offset),
1681            };
1682            return self.over_subqueries(waiting, input, scope, node);
1683        }
1684        let count = self.count_bound(ast, query.limit, "LIMIT")?;
1685        let offset = self.skipped(ast, query.offset)?;
1686        let node = |binder: &mut Self, input| binder.limited(input, count, offset);
1687        self.over_subqueries(waiting, input, scope, node)
1688    }
1689
1690    /// The offset a query wrote, as nought rows skipped when it wrote none.
1691    ///
1692    /// An offset the query left off is nought rows skipped, where a limit it left off is every row
1693    /// emitted, so the two clauses read the same word differently.
1694    fn skipped(&mut self, ast: &Ast, written: ast::ExprRef) -> Result<Bound> {
1695        Ok(match self.count_bound(ast, written, "OFFSET")? {
1696            Bound::All => Bound::Rows(0),
1697            named => named,
1698        })
1699    }
1700
1701    /// Builds a limit node over `input`, joining in whatever queries its bounds turned out to need.
1702    ///
1703    /// A bound the binder could not work out reads its number off a column, and that column comes
1704    /// from a query joined in underneath. The join puts a column in the rows nobody asked for, so a
1705    /// projection over the limit drops it again and the scope is told to read that projection. When
1706    /// no query had to be joined in there is nothing to drop and the limit stands on its own.
1707    fn over_subqueries(
1708        &mut self,
1709        waiting: usize,
1710        input: NodeRef,
1711        scope: &mut Scope,
1712        node: impl FnOnce(&mut Self, NodeRef) -> NodeRef,
1713    ) -> Result<NodeRef> {
1714        let joined = self.scalar_subqueries.split_off(waiting);
1715        if joined.is_empty() {
1716            return Ok(node(self, input));
1717        }
1718        let mut input = input;
1719        for pending in joined {
1720            input = self.attach_subquery(input, pending);
1721        }
1722        let limit = node(self, input);
1723        Ok(self.reproject(limit, scope))
1724    }
1725
1726    /// A row count limit over `input`, or `input` itself when neither half of the clause asks for
1727    /// anything.
1728    fn limited(&mut self, input: NodeRef, count: Bound, offset: Bound) -> NodeRef {
1729        if count == Bound::All && offset == Bound::Rows(0) {
1730            return input;
1731        }
1732        self.add_node(Node::Limit { input, count, offset })
1733    }
1734
1735    /// A projection over `node` handing back exactly the columns `scope` names.
1736    ///
1737    /// The scope's bindings are rewritten to this projection's, because its columns are the ones
1738    /// anything above reads. Only a limit that had a query joined in under it wants this, and only
1739    /// because there is not always a projection above to drop the column that join added.
1740    fn reproject(&mut self, node: NodeRef, scope: &mut Scope) -> NodeRef {
1741        let index = self.fresh_index();
1742        let mut exprs = Vec::with_capacity(scope.columns.len());
1743        let mut names = Vec::with_capacity(scope.columns.len());
1744        for column in &scope.columns {
1745            exprs.push(self.plan.add_expr(Expr::Column(column.binding), column.ty.clone()));
1746            names.push(self.plan.intern(&column.name));
1747        }
1748        for (at, column) in scope.columns.iter_mut().enumerate() {
1749            column.binding = ColumnBinding::new(index, at as u32);
1750        }
1751        let exprs = self.plan.add_expr_list(&exprs);
1752        let names = self.plan.add_name_list(&names);
1753        self.add_node(Node::Project { input: node, index, exprs, names })
1754    }
1755
1756    /// The share of the input a `LIMIT n PERCENT` names.
1757    ///
1758    /// The same evaluation as a row count and a different type at the end of it: the value is cast
1759    /// to `DOUBLE` rather than to `BIGINT`, so `LIMIT '30'%` is thirty percent and `LIMIT true%` is
1760    /// one percent, which is what the pin answers. A null is no limit at all.
1761    ///
1762    /// The range is checked here because the pin checks it here. `LIMIT 101 PERCENT` fails an
1763    /// `EXPLAIN` on the pinned binary, so it is refused while the query is planned and not when it
1764    /// is run, and a `NAN` is outside the range like any other value that is not between nought and
1765    /// a hundred.
1766    ///
1767    /// What the binder cannot work out is a subquery and a call that answers differently every
1768    /// time, the same two things a row count cannot work out, and those become a [`Share::Read`]
1769    /// over the expression. The value is checked where it turns up instead, which is the executor.
1770    /// Only the sign can be written that way, because the grammar refuses `PERCENT` after a closing
1771    /// bracket, but nothing below here depends on which of the two was typed.
1772    fn share(&mut self, ast: &Ast, written: ast::ExprRef) -> Result<Option<Share>> {
1773        if written == NONE {
1774            return Ok(None);
1775        }
1776        self.clause = "LIMIT clause";
1777        let scope = Scope::empty();
1778        let bound = self.bind_expr(ast, written, &scope)?;
1779        let Some(value) = fold::value_of(&self.plan, bound)? else {
1780            return Ok(Some(Share::Read(bound)));
1781        };
1782        if value.is_null() {
1783            return Ok(None);
1784        }
1785        let percent = percentage(&value)?;
1786        if !(0.0..=100.0).contains(&percent) {
1787            return Err(Error::out_of_range(
1788                "Limit percent out of range, should be between 0% and 100%",
1789            ));
1790        }
1791        Ok(Some(Share::Percent(percent)))
1792    }
1793
1794    /// The row count a `LIMIT` or an `OFFSET` names.
1795    ///
1796    /// It does not have to be a literal. Anything whose value is settled before the first row is
1797    /// read will do, so `LIMIT 1 + 1` and `LIMIT CAST(3 AS BIGINT)` are both two, and that is what
1798    /// the pin does with them: its binder evaluates the expression and writes the number down.
1799    ///
1800    /// What is left over is an expression the binder cannot settle, which is a subquery, because it
1801    /// has to run first, and a call that answers differently every time it is made, such as
1802    /// `RANDOM()` or `nextval`. Those become a [`Bound::Read`] holding the expression, and the
1803    /// number comes off the first chunk that reaches the limit. The pin takes both and answers them
1804    /// the same way.
1805    ///
1806    /// The value is cast to `BIGINT` whatever it was written as, which is the whole of the type
1807    /// rule. `LIMIT '3'` is three rows because the string converts, `LIMIT 2.5` is three rows
1808    /// because the conversion rounds, `LIMIT true` is one row, and `LIMIT DATE '2020-01-01'` is the
1809    /// cast refusing a date. Every one of those messages is the cast's own, which is why there is
1810    /// no type check here to write a worse one. A limit that is read while the query runs is cast
1811    /// the same way by the operator that reads it, so the two paths answer alike.
1812    fn count_bound(&mut self, ast: &Ast, written: ast::ExprRef, clause: &str) -> Result<Bound> {
1813        if written == NONE {
1814            return Ok(Bound::All);
1815        }
1816        self.clause = "LIMIT clause";
1817        let scope = Scope::empty();
1818        let bound = self.bind_expr(ast, written, &scope)?;
1819        let Some(value) = fold::value_of(&self.plan, bound)? else {
1820            return Ok(Bound::Read(bound));
1821        };
1822        // A null is no limit at all, the same as leaving the clause off, and the pin agrees:
1823        // `LIMIT NULL` and `LIMIT CAST(NULL AS INTEGER)` both answer every row.
1824        if value.is_null() {
1825            return Ok(Bound::All);
1826        }
1827        row_count(&value, clause).map(Bound::Rows)
1828    }
1829
1830    // ------------------------------------------------------------------- from
1831
1832    fn bind_from(&mut self, ast: &Ast, from: ast::Slice) -> Result<(NodeRef, Scope)> {
1833        let sources = ast.source_list(from).to_vec();
1834        let Some((first, rest)) = sources.split_first() else {
1835            // No FROM clause is one row of no columns, which is what SELECT 1 sits on. Not an
1836            // empty table: an empty table would make SELECT 1 return nothing.
1837            return Ok((self.add_node(Node::Dummy), Scope::empty()));
1838        };
1839        let (mut node, mut scope) = self.bind_source(ast, *first)?;
1840        for source in rest {
1841            let (right, right_scope, correlations) = self.bind_lateral(ast, *source, &scope)?;
1842            node = if correlations.is_empty() {
1843                self.add_node(Node::CrossProduct { left: node, right })
1844            } else {
1845                let conditions = self.plan.add_expr_list(&[]);
1846                self.add_node(Node::DependentJoin {
1847                    left: node,
1848                    right,
1849                    kind: JoinKind::Inner,
1850                    conditions,
1851                })
1852            };
1853            scope = scope.concat(right_scope);
1854        }
1855        Ok((node, scope))
1856    }
1857
1858    /// Binds one FROM entry with everything written to its left already visible.
1859    ///
1860    /// That is what LATERAL means, and it is what a comma separated FROM does here whether the word
1861    /// was written or not, because the pinned build resolves `FROM o, (SELECT o.k + 1)` without it.
1862    /// The keyword therefore changes nothing and is accepted rather than acted on.
1863    ///
1864    /// The columns of the left that the entry read come back with it, and an entry that read none
1865    /// is an ordinary product. The rest are somebody else's: a name that resolved past the left
1866    /// neighbours belongs to an enclosing query, so it is handed up to whichever frame is waiting
1867    /// for it rather than counted here, or the subquery this FROM sits in would lose track of its
1868    /// own correlation.
1869    fn bind_lateral(
1870        &mut self,
1871        ast: &Ast,
1872        source: ast::SourceRef,
1873        left: &Scope,
1874    ) -> Result<(NodeRef, Scope, Vec<ColumnBinding>)> {
1875        self.lateral_scopes.push(self.outer_scopes.len());
1876        self.outer_scopes.push(left.clone());
1877        self.correlations.push(Vec::new());
1878        let bound = self.bind_source(ast, source);
1879        let read = self.correlations.pop().expect("correlation frame");
1880        self.outer_scopes.pop();
1881        self.lateral_scopes.pop();
1882        let (node, scope) = bound?;
1883
1884        let mut here = Vec::new();
1885        for binding in read {
1886            if left.columns.iter().any(|column| column.binding == binding) {
1887                here.push(binding);
1888            } else if let Some(enclosing) = self.correlations.last_mut()
1889                && !enclosing.contains(&binding)
1890            {
1891                enclosing.push(binding);
1892            }
1893        }
1894        // A table function is allowed to read the left the same as anything else here. There is
1895        // nothing underneath one for the domain to be pushed into, since its arguments are what
1896        // produce its rows, so the unnesting pass turns it into a `LateralFunction` and the call is
1897        // made once per domain value. That is `domain.rs`.
1898        //
1899        // Nothing has to be turned down here for the functions that would not survive it. The only
1900        // table functions taking an argument that is not a name are the series family, which is the
1901        // family that operator answers, and a name that is not a constant is refused where the
1902        // columns are settled, because settling them means opening the file or reading the catalog.
1903        Ok((node, scope, here))
1904    }
1905
1906    fn bind_source(&mut self, ast: &Ast, source: ast::SourceRef) -> Result<(NodeRef, Scope)> {
1907        match ast.source(source) {
1908            ast::Source::Table { name, alias, columns } => {
1909                self.bind_table(ast, name, alias, columns)
1910            }
1911            ast::Source::Function { name, args, alias, columns, pragma } => {
1912                self.bind_table_function(ast, name, args, alias, columns, pragma)
1913            }
1914            ast::Source::Subquery { query, alias, columns } => {
1915                let (node, mut scope) = self.bind_query(ast, query)?;
1916                let label = if alias == NONE {
1917                    "unnamed_subquery".to_string()
1918                } else {
1919                    ast.string(alias).to_string()
1920                };
1921                scope.relabel(&label);
1922                if !columns.is_empty() {
1923                    let names: Vec<&str> = ast.name(columns).collect();
1924                    scope.rename(&names, &label)?;
1925                }
1926                Ok((node, scope))
1927            }
1928            ast::Source::Values { rows, alias, columns } => {
1929                let bare = ast::Query::bare(ast::QueryBody::Values(rows));
1930                let (node, mut scope) = self.bind_values(ast, &bare, rows)?;
1931                let label =
1932                    if alias == NONE { String::new() } else { ast.string(alias).to_string() };
1933                scope.relabel(&label);
1934                if !columns.is_empty() {
1935                    let names: Vec<&str> = ast.name(columns).collect();
1936                    scope.rename(&names, &label)?;
1937                }
1938                Ok((node, scope))
1939            }
1940            ast::Source::Cte { cte, alias, columns } => {
1941                self.bind_cte_scan(ast, cte, alias, columns)
1942            }
1943            ast::Source::Join { left, right, kind, natural, on, using } => {
1944                self.bind_join(ast, left, right, kind, natural, on, using)
1945            }
1946        }
1947    }
1948
1949    /// A read of a materialised `WITH`, which is a leaf the same way a table scan is.
1950    ///
1951    /// Which definition it reads was settled by the parser, so there is no name to look up here and
1952    /// no shadowing left to think about. What is looked up is the materialisation that definition
1953    /// turned into, and the search runs backwards because the same definition is bound again for
1954    /// each use of a plain `WITH` it sits inside, and a read means the innermost of those.
1955    fn bind_cte_scan(
1956        &mut self,
1957        ast: &Ast,
1958        written: u32,
1959        alias: ast::StrRef,
1960        columns: ast::Slice,
1961    ) -> Result<(NodeRef, Scope)> {
1962        let Some(held) = self.materialized.iter().rev().find(|held| held.written == written) else {
1963            let name = ast.string(ast.cte(written).name);
1964            return Err(Error::binder(format!("Table with name {name} does not exist!")));
1965        };
1966        let cte = held.cte;
1967        let fields = held.fields.clone();
1968        let text = held.name.clone();
1969        let label = if alias == NONE { text.clone() } else { ast.string(alias).to_string() };
1970        let name = self.plan.intern(&text);
1971        let index = self.fresh_index();
1972        let mut scope = Scope::empty();
1973        for (at, field) in fields.iter().enumerate() {
1974            scope.push(Visible {
1975                table: label.clone(),
1976                name: field.name.clone(),
1977                binding: ColumnBinding::new(index, at as u32),
1978                ty: field.ty.clone(),
1979                not_null: field.not_null,
1980                key: None,
1981                default: None,
1982                qualified: false,
1983                also: None,
1984            });
1985        }
1986        if !columns.is_empty() {
1987            let names: Vec<&str> = ast.name(columns).collect();
1988            scope.rename(&names, &label)?;
1989        }
1990        let columns = self.plan.add_fields(&fields);
1991        let node = self.add_node(Node::CteScan { index, cte, name, columns });
1992        Ok((node, scope))
1993    }
1994
1995    fn bind_table(
1996        &mut self,
1997        ast: &Ast,
1998        name: ast::Slice,
1999        alias: ast::StrRef,
2000        columns: ast::Slice,
2001    ) -> Result<(NodeRef, Scope)> {
2002        let parts: Vec<&str> = ast.name(name).collect();
2003        let catalog = self.catalog;
2004        // The catalog is asked first and the file is the fallback, which is the order DuckDB uses:
2005        // a table really called `mixed.parquet` wins over a file of that name sitting next to it.
2006        let resolved = match catalog.resolve(&parts) {
2007            Ok(resolved) => resolved,
2008            Err(missing) => {
2009                return self.bind_replacement_scan(ast, &parts, alias, columns, missing);
2010            }
2011        };
2012        if catalog.entry(&resolved)? == Entry::View {
2013            return self.bind_view(ast, &resolved, alias, columns);
2014        }
2015        let label =
2016            if alias == NONE { resolved.table.clone() } else { ast.string(alias).to_string() };
2017        self.bind_catalog_table(ast, &resolved, label, columns)
2018    }
2019
2020    /// A table the catalog holds, under the name `label`, which is where [`Self::bind_table`] ends
2021    /// and where a Parquet file with a native mirror goes instead of to its reader.
2022    pub(crate) fn bind_catalog_table(
2023        &mut self,
2024        ast: &Ast,
2025        resolved: &QualifiedName,
2026        label: String,
2027        columns: ast::Slice,
2028    ) -> Result<(NodeRef, Scope)> {
2029        let catalog = self.catalog;
2030        let table = catalog.table(resolved)?;
2031        let fields: &[Field] = table.columns();
2032        // The new rows of an `ON CONFLICT DO UPDATE`, which the write puts in a table of their own
2033        // before it runs the query. Nothing the table knows about its own rows holds for them.
2034        let excluded = self.upsert && same_name(&label, "excluded");
2035        // `PRI` for a column of the primary key and `UNI` for one of a unique key, the primary key
2036        // winning where a column is in both.
2037        let mut marks = vec![None; fields.len()];
2038        for key in table.keys() {
2039            for &column in &key.columns {
2040                if key.primary || marks[column].is_none() {
2041                    marks[column] = Some(if key.primary { "PRI" } else { "UNI" });
2042                }
2043            }
2044        }
2045        let index = self.fresh_index();
2046        let mut scope = Scope::empty();
2047        for (at, field) in fields.iter().enumerate() {
2048            scope.push(Visible {
2049                table: label.clone(),
2050                name: field.name.clone(),
2051                binding: ColumnBinding::new(index, at as u32),
2052                ty: field.ty.clone(),
2053                not_null: field.not_null,
2054                key: marks[at],
2055                default: table.default(at).map(str::to_owned),
2056                qualified: excluded,
2057                also: None,
2058            });
2059        }
2060        if !columns.is_empty() {
2061            let names: Vec<&str> = ast.name(columns).collect();
2062            scope.rename(&names, &label)?;
2063        }
2064        let resolved = if excluded { &QualifiedName::excluded() } else { resolved };
2065        let catalog_name = self.plan.intern(&resolved.catalog);
2066        let schema = self.plan.intern(&resolved.schema);
2067        let table_name = self.plan.intern(&resolved.table);
2068        let alias = self.plan.intern(&label);
2069        let columns = self.plan.add_fields(fields);
2070        // What the store wrote down about itself, against the table index the same way a Parquet
2071        // footer is. A table with nothing to say records nothing and the estimate falls back to the
2072        // constants it used before, which is what every table did until the file had a directory
2073        // worth asking.
2074        if let Some(zones) = table.rows().zones().filter(|_| !excluded) {
2075            self.plan.set_zones(index, zones);
2076        }
2077        if let Some(frequencies) = table.frequencies().filter(|_| !excluded) {
2078            self.plan.set_frequencies(index, frequencies);
2079        }
2080        // A stored table hands over what it gathered once for the whole plan to share. Only a table
2081        // whose rows can change is asked column by column.
2082        let facts = table.facts().filter(|_| !excluded);
2083        if let Some(facts) = facts {
2084            self.plan.set_facts(index, facts, self.want_ascending);
2085        } else if !excluded {
2086            for (column, distinct) in table.distincts() {
2087                self.plan.measure_distinct(index, &column, distinct);
2088            }
2089            if self.want_ascending {
2090                for column in table.ascending() {
2091                    self.plan.mark_ascending(index, &column);
2092                }
2093            }
2094            for (column, bytes) in table.widths() {
2095                self.plan.measure_width(index, &column, bytes);
2096            }
2097        }
2098        let node = self.add_node(Node::Get {
2099            catalog: catalog_name,
2100            schema,
2101            table: table_name,
2102            alias,
2103            index,
2104            columns,
2105        });
2106        Ok((node, scope))
2107    }
2108
2109    /// A view where a table goes, which is the body bound again right here.
2110    ///
2111    /// Inline and not behind a node. The view is gone by the time the plan exists, so everything
2112    /// downstream sees the query somebody would have written by hand, and the column pruning that
2113    /// makes `SELECT COUNT(*) FROM 'hits.parquet'` read no columns at all keeps working through
2114    /// `FROM hits`. A `Node::View` would be a barrier with nothing on the other side of it.
2115    ///
2116    /// The scope this builds is a subquery's, right down to the name in the error message. duckdb
2117    /// v1.5.1 reports a view whose column list has gone stale as `table "unnamed_subquery" has 1
2118    /// columns available but 2 columns specified`, which is the sentence its subquery alias rule
2119    /// produces, so a view there is a subquery with the view's name written over it afterwards.
2120    fn bind_view(
2121        &mut self,
2122        ast: &Ast,
2123        name: &QualifiedName,
2124        alias: ast::StrRef,
2125        columns: ast::Slice,
2126    ) -> Result<(NodeRef, Scope)> {
2127        let view = self.catalog.view(name)?;
2128        let full = name.to_string();
2129        if self.expanding.contains(&full) {
2130            // Two quotes each side, which is what the binary prints. It quotes the name on the way
2131            // in and then formats the quoted name into a quoted slot, so a view called `a` comes
2132            // back as `""a""`. That is upstream's wart and copying it is the whole job here.
2133            return Err(Error::binder(format!(
2134                "infinite recursion detected: attempting to recursively bind view \"\"{}\"\"",
2135                name.table
2136            )));
2137        }
2138        let body = parse_ast_with_case(view.sql(), self.semantics.identifier_case())?;
2139        let query = match body.statements.as_slice() {
2140            [ast::Statement::Query(query)] => *query,
2141            // Only a query can have got past the binder at creation, so this is a view the catalog
2142            // was handed some other way rather than anything a statement can produce.
2143            _ => return Err(Error::binder(format!("view \"{}\" is not a query", name.table))),
2144        };
2145        self.expanding.push(full);
2146        let bound = self.bind_query(&body, query);
2147        self.expanding.pop();
2148        let (node, mut scope) = bound?;
2149
2150        let aliases: Vec<&str> = view.aliases().iter().map(String::as_str).collect();
2151        if !aliases.is_empty() {
2152            scope.rename(&aliases, "unnamed_subquery")?;
2153        }
2154        // What the catalog tables report as this view's columns, written down here because this is
2155        // the moment they are known. Upstream refreshes the same cache at the same point, which was
2156        // measured: both `duckdb_columns()` and `duckdb_views().column_count` keep reporting the old
2157        // list after an `ALTER TABLE` underneath until something reads the view, and then both move.
2158        // It is written before the label and before the `AS t(a, b)` list below, because those two
2159        // rename the view for one query and not for everyone.
2160        view.remember(scope.fields());
2161        let label = if alias == NONE { name.table.clone() } else { ast.string(alias).to_string() };
2162        scope.relabel(&label);
2163        if !columns.is_empty() {
2164            let names: Vec<&str> = ast.name(columns).collect();
2165            scope.rename(&names, &label)?;
2166        }
2167        Ok((node, scope))
2168    }
2169
2170    /// A function call where a table goes, such as `range(10)`.
2171    ///
2172    /// The arguments are bound against an empty scope. A table function that can see the row on its
2173    /// left is `LATERAL`, and this is not it, so a column name in here is not resolved against
2174    /// whatever happens to be to the left in the `FROM` list. Letting it would mean `FROM t,
2175    /// range(t.n)` quietly binding to something whose meaning depends on the order the sources were
2176    /// written in.
2177    fn bind_table_function(
2178        &mut self,
2179        ast: &Ast,
2180        name: ast::Slice,
2181        args: ast::Slice,
2182        alias: ast::StrRef,
2183        columns: ast::Slice,
2184        pragma: bool,
2185    ) -> Result<(NodeRef, Scope)> {
2186        // The column names written after the alias, kept under a name of their own because the
2187        // match on what the function's columns are below binds `columns` to something else.
2188        let renamed = columns;
2189        let parts: Vec<&str> = ast.name(name).collect();
2190        // A qualified call names a schema, and the two schemas that exist are the ones every
2191        // built-in lives in. Anything else is a name that has to fail rather than fall through to
2192        // the unqualified lookup and be found somewhere it was not asked for.
2193        let function_name = *parts.last().unwrap_or(&"");
2194        if let Some(schema) = parts.iter().rev().nth(1)
2195            && !schema.eq_ignore_ascii_case("main")
2196            && !schema.eq_ignore_ascii_case("system")
2197        {
2198            return Err(Error::catalog(format!(
2199                "Table Function with name {} does not exist!",
2200                parts.join(".")
2201            )));
2202        }
2203        // The name is looked up before the arguments are bound so that a call of something that is
2204        // not a table function says that, rather than reporting whatever is wrong with the
2205        // arguments of a function that was never going to exist.
2206        let Some(called) = TableFunction::lookup(function_name) else {
2207            if pragma {
2208                // `PRAGMA database_list` is a view upstream and not a function, and the pragma
2209                // namespace holds both, so a name that is not a function gets one more look in the
2210                // catalog before it is turned down. It has to be the no argument form: a view
2211                // takes none, and `pragma_database_list()` with parentheses is a missing function
2212                // on the pin too.
2213                if args.is_empty() && self.catalog.resolve(&parts).is_ok() {
2214                    return self.bind_table(ast, name, alias, columns);
2215                }
2216                let spelled = function_name.strip_prefix("pragma_").unwrap_or(function_name);
2217                return Err(Error::catalog(format!(
2218                    "Pragma Function with name {spelled} does not exist!"
2219                )));
2220            }
2221            return Err(Error::catalog(format!(
2222                "Table Function with name {function_name} does not exist!"
2223            )));
2224        };
2225        let written = ast.target_list(args).to_vec();
2226        let empty = Scope::empty();
2227        let waiting = self.scalar_subqueries.len();
2228        let previous = std::mem::replace(&mut self.clause, "table function arguments");
2229        let mut bound = Vec::new();
2230        let mut written_options = Vec::new();
2231        for argument in written {
2232            let expr = self.bind_expr(ast, argument.expr, &empty)?;
2233            if argument.alias == NONE {
2234                bound.push(expr);
2235            } else {
2236                let name = ast.string(argument.alias).to_string();
2237                let (parameter, value) = self.named_argument(called, &name, expr)?;
2238                written_options.push((parameter, value, expr));
2239            }
2240        }
2241        self.clause = previous;
2242        let options = Options::of(&written_options)?;
2243
2244        // The types are what resolve the call, not the count, because `read_parquet(3)` is a
2245        // different answer from `read_parquet('3')` and only the types tell them apart.
2246        let given: Vec<LogicalType> =
2247            bound.iter().map(|&expr| self.plan.expr_type(expr).clone()).collect();
2248        let resolved = if pragma {
2249            resolve_pragma(function_name, &given)?
2250        } else {
2251            resolve_table(function_name, &given)?
2252        };
2253        let mut cast: Vec<ExprRef> = bound
2254            .iter()
2255            .zip(&resolved.arguments)
2256            .map(|(&expr, ty)| self.checked_cast_to(expr, ty, false))
2257            .collect::<Result<_>>()?;
2258
2259        if resolved.function.answered_when_bound() {
2260            let Columns::Fixed(fields) = resolved.columns else {
2261                return Err(Error::internal("a pragma that resolved to a file"));
2262            };
2263            let [argument] = cast[..] else {
2264                return Err(Error::internal("a pragma that resolved to more than one name"));
2265            };
2266            return self.bind_pragma(ast, resolved.function, &fields, argument, alias, columns);
2267        }
2268        // Filled in by the arm below that has the file names, and left alone by a function whose
2269        // columns are fixed, because none of those reads a file to find out how tall it is.
2270        let mut measured = Stat::Unknown;
2271        let mut counted: Vec<(String, Stat<u64>)> = Vec::new();
2272        let mut bounded: Option<Arc<dyn Zones>> = None;
2273        let fields = match resolved.columns {
2274            Columns::Fixed(fields) => fields,
2275            columns => {
2276                // The one argument is a pattern, and what replaces it is one constant per file it
2277                // matched. The executor is handed names rather than a pattern, so it never walks a
2278                // directory and the answer cannot change between binding a prepared statement and
2279                // running it, which is the same reason the schema is settled here.
2280                let paths = self.file_paths(cast[0], resolved.function.name())?;
2281                let mut mirrorable = None;
2282                if resolved.function == TableFunction::ReadParquet
2283                    && !options.file_row_number
2284                    && let Some((path, stamp)) = mirror_target(&paths)
2285                {
2286                    if let Some(name) = self.catalog.mirror(&path, options.binary_as_string, stamp)
2287                    {
2288                        let name = name.clone();
2289                        let label = if alias == NONE {
2290                            resolved.function.name().to_string()
2291                        } else {
2292                            ast.string(alias).to_string()
2293                        };
2294                        return self.bind_catalog_table(ast, &name, label, renamed);
2295                    }
2296                    mirrorable = Some(path);
2297                }
2298                let copy_into = match columns {
2299                    Columns::Csv => self.copy_into.take(),
2300                    _ => None,
2301                };
2302                let mut fields = match columns {
2303                    Columns::Csv if copy_into.is_some() => {
2304                        let into = copy_into.unwrap_or_default();
2305                        self.copy_fields(&paths, &options.given, &into, &mut written_options)?
2306                    }
2307                    // Parquet takes the first file's footer as the answer and CSV sniffs all of
2308                    // them, which is not a choice made here. See `csv_fields`.
2309                    Columns::Csv => csv_fields(&paths, options.given.clone())?,
2310                    _ => {
2311                        let footers = self.footers(&paths, mirrorable.as_deref())?;
2312                        if let Some(path) = mirrorable.as_deref() {
2313                            self.want_mirror(path, options.binary_as_string, &footers.rows);
2314                        }
2315                        measured = footers.rows;
2316                        counted = footers.distincts;
2317                        bounded = footers.zones;
2318                        footers.fields
2319                    }
2320                };
2321                if options.all_varchar {
2322                    // The sniffer still ran, because the names come out of the same pass over the
2323                    // front of the file and only the types are being overruled. The executor reads
2324                    // the text as VARCHAR because this is the schema it is told to read into, which
2325                    // is the same road a file in a glob takes when the set is wider than the file.
2326                    for field in &mut fields {
2327                        field.ty = LogicalType::Varchar;
2328                    }
2329                }
2330                if options.binary_as_string {
2331                    // A byte array column with no annotation on it is a BLOB, and this is the caller
2332                    // saying that the file's writer meant text. The reader already holds both in the
2333                    // same string column and already validates the bytes, so the whole of the option
2334                    // is what the column is called from here on.
2335                    for field in &mut fields {
2336                        if field.ty == LogicalType::Blob {
2337                            field.ty = LogicalType::Varchar;
2338                        }
2339                    }
2340                }
2341                if options.file_row_number {
2342                    // Not a column of the file, so it goes on the end where a projection cannot be
2343                    // confused about which one it is, and the executor counts it as the rows come
2344                    // out. A file that already has a column of that name is the one case where the
2345                    // option cannot be honoured, and saying so is better than handing back two
2346                    // columns with the same name and letting a reference to it pick one.
2347                    if fields.iter().any(|field| field.name == FILE_ROW_NUMBER) {
2348                        return Err(Error::binder(format!(
2349                            "Duplicate column name \"{FILE_ROW_NUMBER}\": the file already has a \
2350                             column of that name, so file_row_number cannot add one"
2351                        )));
2352                    }
2353                    fields.push(Field::required(FILE_ROW_NUMBER.to_string(), LogicalType::BigInt));
2354                }
2355                cast = paths.iter().map(|path| self.path_constant(path)).collect();
2356                fields
2357            }
2358        };
2359        let label = if alias == NONE {
2360            resolved.function.name().to_string()
2361        } else {
2362            ast.string(alias).to_string()
2363        };
2364        let names: Vec<&str> = ast.name(columns).collect();
2365        let (node, scope) = self.table_function_source(
2366            resolved.function,
2367            &cast,
2368            &written_options,
2369            Read { fields, rows: measured, distincts: counted, zones: bounded },
2370            &label,
2371            &names,
2372        )?;
2373        Ok((self.lateral_over_subqueries(node, waiting), scope))
2374    }
2375
2376    /// A series or an unnest whose arguments read a query, `range((SELECT 3))`, as the same call
2377    /// made laterally over the one row that query makes.
2378    ///
2379    /// The query cannot be joined in above the call the way it is above a table, because the call
2380    /// is what reads it. So it is joined into a row with nothing in it, and the call runs over that
2381    /// row the way it runs over the rows of a table to its left.
2382    fn lateral_over_subqueries(&mut self, node: NodeRef, waiting: usize) -> NodeRef {
2383        if self.scalar_subqueries.len() <= waiting {
2384            return node;
2385        }
2386        let Node::TableFunction { index, function, args, options, settings, columns } =
2387            self.plan.node(node).clone()
2388        else {
2389            return node;
2390        };
2391        let series = matches!(
2392            TableFunction::lookup(self.plan.string(function)),
2393            Some(TableFunction::Range | TableFunction::GenerateSeries | TableFunction::Unnest)
2394        );
2395        if !series {
2396            return node;
2397        }
2398        let mut input = self.add_node(Node::Dummy);
2399        for pending in self.scalar_subqueries.split_off(waiting) {
2400            input = self.attach_subquery(input, pending);
2401        }
2402        self.add_node(Node::LateralFunction {
2403            input,
2404            index,
2405            function,
2406            args,
2407            options,
2408            settings,
2409            columns,
2410        })
2411    }
2412
2413    /// The columns of the `read_csv` a `COPY t FROM` became, which are the table's.
2414    ///
2415    /// The file is still sniffed, since the delimiter and whether the first line is a header are
2416    /// still the file's to say when the statement did not, and so is how many columns it has. That
2417    /// has to be how many the statement loads, and a file that disagrees gets the line of DuckDB's
2418    /// sniffer error that says so. The rest of that error is a list of fixes for a sniffer this one
2419    /// is not, and is left out.
2420    ///
2421    /// The names go into the plan as a `names` parameter and the flag that the types were set as
2422    /// `types_set`, because the executor opens the file again from what the plan says, and the
2423    /// columns it finds have to be the ones the plan was built against. The types need nothing,
2424    /// since the executor already reads a CSV file as the types the plan holds.
2425    fn copy_fields(
2426        &mut self,
2427        paths: &[String],
2428        given: &Given,
2429        into: &[Field],
2430        written: &mut Vec<(&'static str, Value, ExprRef)>,
2431    ) -> Result<Vec<Field>> {
2432        let sniffed = csv_fields(paths, given.clone())?;
2433        if sniffed.len() != into.len() {
2434            let set: Vec<String> =
2435                into.iter().map(|field| format!("'{}' : '{}'", field.name, field.ty)).collect();
2436            return Err(Error::invalid_input(format!(
2437                "Error when sniffing file \"{}\".\nIt was not possible to automatically detect the \
2438                 CSV parsing dialect\n* Columns are set as: \"columns = {{ {}}}\", and they \
2439                 contain: {} columns. It does not match the number of columns found by the \
2440                 sniffer: {}. Verify the columns parameter is correctly set.",
2441                paths.first().map_or("", String::as_str),
2442                set.join(", "),
2443                into.len(),
2444                sniffed.len()
2445            )));
2446        }
2447        let names: Vec<Value> =
2448            into.iter().map(|field| Value::Varchar(field.name.clone())).collect();
2449        let names = Value::List { element: LogicalType::Varchar, values: names };
2450        let list = LogicalType::List(Box::new(LogicalType::Varchar));
2451        for (parameter, value, ty) in
2452            [("names", names, list), (TYPES_SET, Value::Boolean(true), LogicalType::Boolean)]
2453        {
2454            let reference = self.plan.add_value(value.clone());
2455            let expr = self.plan.add_expr(Expr::Constant(reference), ty);
2456            written.push((parameter, value, expr));
2457        }
2458        Ok(into.to_vec())
2459    }
2460
2461    /// `pragma_table_info('t')` or `pragma_show('t')`, answered while it is bound.
2462    ///
2463    /// The same trick `DESCRIBE` uses and for the same reason: the columns of a table are settled by
2464    /// the time the name has resolved, so the rows are a constant from there on and this comes out
2465    /// as a `VALUES` rather than as an operator that reads a catalog while the query runs. It also
2466    /// means `SELECT name FROM pragma_table_info('t') WHERE notnull` is an ordinary query over an
2467    /// ordinary relation, which is the whole reason these exist as functions rather than only as
2468    /// statements.
2469    ///
2470    /// The name arrives as a string rather than as something the parser read, so it is split here
2471    /// under the identifier rule and then resolved like any other name. A name that is not there
2472    /// comes back as the catalog's own complaint, which is what the pin answers with too.
2473    fn bind_pragma(
2474        &mut self,
2475        ast: &Ast,
2476        function: TableFunction,
2477        fields: &[Field],
2478        argument: ExprRef,
2479        alias: ast::StrRef,
2480        columns: ast::Slice,
2481    ) -> Result<(NodeRef, Scope)> {
2482        let written = self.pragma_name(argument, function)?;
2483        let parts = identifier_parts(&written);
2484        let spelled: Vec<&str> = parts.iter().map(String::as_str).collect();
2485        let name = self.catalog.resolve(&spelled)?;
2486        let described = self.described(ast, &name)?;
2487        let mut rows = Vec::with_capacity(described.len());
2488        for (at, field) in described.iter().enumerate() {
2489            let items = if matches!(function, TableFunction::PragmaShow) {
2490                self.describing(field)
2491            } else {
2492                self.table_info(at, field)
2493            };
2494            rows.push(self.plan.add_expr_list(&items));
2495        }
2496        let rows = self.plan.add_rows(&rows);
2497        let held = self.plan.add_fields(fields);
2498        let index = self.fresh_index();
2499        let node = self.add_node(Node::Values { index, columns: held, rows });
2500        let label =
2501            if alias == NONE { function.name().to_string() } else { ast.string(alias).to_string() };
2502        let mut scope = Scope::empty();
2503        for (at, field) in fields.iter().enumerate() {
2504            scope.push(Visible {
2505                table: label.clone(),
2506                name: field.name.clone(),
2507                binding: ColumnBinding::new(index, at as u32),
2508                ty: field.ty.clone(),
2509                not_null: false,
2510                key: None,
2511                default: None,
2512                qualified: false,
2513                also: None,
2514            });
2515        }
2516        if !columns.is_empty() {
2517            let names: Vec<&str> = ast.name(columns).collect();
2518            scope.rename(&names, &label)?;
2519        }
2520        Ok((node, scope))
2521    }
2522
2523    /// The name a pragma was called with, which has to be a constant.
2524    ///
2525    /// A null is a name spelled `NULL` rather than an error about nulls, because the pin turns
2526    /// whatever it was handed into text before it goes looking and then says a table of that name
2527    /// does not exist. Writing `pragma_table_info(NULL)` is a mistake either way and this is the
2528    /// sentence the mistake already has.
2529    ///
2530    /// `pragma_table_info('t' || 'x')` is the pin's `tx` and is turned away here, which is the same
2531    /// missing constant folding [`Binder::named_argument`] writes about and closes the same day.
2532    fn pragma_name(&self, argument: ExprRef, function: TableFunction) -> Result<String> {
2533        let Expr::Constant(reference) = *self.plan.expr(argument) else {
2534            return Err(Error::not_implemented(format!(
2535                "{}() given a name that is not a constant",
2536                function.name()
2537            )));
2538        };
2539        match self.plan.value(reference) {
2540            Value::Varchar(name) => Ok(name.clone()),
2541            Value::Null => Ok("NULL".to_string()),
2542            other => {
2543                Err(Error::internal(format!("a pragma name bound as VARCHAR arrived as {other}")))
2544            }
2545        }
2546    }
2547
2548    /// The columns of whatever a pragma was pointed at.
2549    ///
2550    /// A view is bound here, which is how it comes to have columns at all. Reading a view is what
2551    /// binds it and describing one counts as reading it, so a view the engine ships with reports a
2552    /// column count from this point on, the same as it would after a select. The node that binding
2553    /// produces is thrown away, because the answer is the scope and not the query.
2554    ///
2555    /// Every column of a view is nullable whatever the column underneath was declared as, which is
2556    /// the pin's answer through `pragma_table_info()`, `pragma_show()` and `duckdb_columns()` alike.
2557    /// [`Scope::fields`] drops the flag on its own, so there is nothing to clear here.
2558    fn described(&mut self, ast: &Ast, name: &QualifiedName) -> Result<Vec<Field>> {
2559        if self.catalog.entry(name)? == Entry::Table {
2560            return Ok(self.catalog.table(name)?.columns().to_vec());
2561        }
2562        let (_, scope) = self.bind_view(ast, name, NONE, ast::Slice::default())?;
2563        Ok(scope.fields())
2564    }
2565
2566    /// One row of `pragma_show()`, which is one row of `DESCRIBE` written by the other caller.
2567    fn describing(&mut self, field: &Field) -> Vec<ExprRef> {
2568        let written = [
2569            field.name.clone(),
2570            field.ty.to_string(),
2571            if field.not_null { "NO" } else { "YES" }.to_owned(),
2572        ];
2573        let mut items: Vec<ExprRef> =
2574            written.into_iter().map(|text| self.plan.add_constant(Value::Varchar(text))).collect();
2575        for _ in 0..3 {
2576            let empty = self.plan.add_constant(Value::Null);
2577            items.push(self.cast_to(empty, &LogicalType::Varchar));
2578        }
2579        items
2580    }
2581
2582    /// One row of `pragma_table_info()`, which is SQLite's six columns about the same column.
2583    ///
2584    /// `cid` counts from zero, which is SQLite's numbering and not the one based `ordinal_position`
2585    /// the standard views report. `dflt_value` and `pk` are the two nothings rudb has to report
2586    /// until `CREATE TABLE` takes a `DEFAULT` or a key.
2587    fn table_info(&mut self, at: usize, field: &Field) -> Vec<ExprRef> {
2588        let cid = self.plan.add_constant(Value::Integer(i32::try_from(at).unwrap_or(i32::MAX)));
2589        let name = self.plan.add_constant(Value::Varchar(field.name.clone()));
2590        let ty = self.plan.add_constant(Value::Varchar(field.ty.to_string()));
2591        let not_null = self.plan.add_constant(Value::Boolean(field.not_null));
2592        let default = self.plan.add_constant(Value::Null);
2593        let default = self.cast_to(default, &LogicalType::Varchar);
2594        let key = self.plan.add_constant(Value::Boolean(false));
2595        vec![cid, name, ty, not_null, default, key]
2596    }
2597
2598    /// One named parameter of a table function call, folded into what the call was given.
2599    ///
2600    /// The value has to be a constant of the type the parameter wants. It has to be constant
2601    /// because an option can decide what the columns are and the columns are settled here, and it
2602    /// has to be already of the type because there is no constant folding in front of the binder
2603    /// yet. DuckDB folds first, so `binary_as_string=1` and `binary_as_string='yes'` are both true
2604    /// there and both are turned away here, which is a gap that closes on its own the day the
2605    /// optimizer runs before the plan is finished. `binary_as_string=True` is what the ClickBench
2606    /// entry writes and is what has to work.
2607    ///
2608    /// A name that is not a parameter of this function is the binary's sentence followed by what it
2609    /// could have been. The binary puts the candidates on their own indented lines and this puts
2610    /// them on the same line, because an error is one line here.
2611    fn named_argument(
2612        &mut self,
2613        function: TableFunction,
2614        name: &str,
2615        expr: ExprRef,
2616    ) -> Result<(&'static str, Value)> {
2617        let known = function
2618            .parameters()
2619            .iter()
2620            .find(|(parameter, _)| parameter.eq_ignore_ascii_case(name));
2621        let Some((parameter, wanted)) = known else {
2622            let candidates: Vec<String> = function
2623                .parameters()
2624                .iter()
2625                .map(|(parameter, ty)| format!("    {parameter} {ty}"))
2626                .collect();
2627            // A function with no named parameters at all says so rather than listing none.
2628            if candidates.is_empty() {
2629                return Err(Error::binder(format!(
2630                    "Invalid named parameter \"{name}\" for function {}\nFunction does not \
2631                     accept any named parameters.",
2632                    function.name()
2633                )));
2634            }
2635            return Err(Error::binder(format!(
2636                "Invalid named parameter \"{name}\" for function {}\nCandidates:\n{}\n",
2637                function.name(),
2638                candidates.join("\n")
2639            )));
2640        };
2641        // Folded rather than read off a literal, for the reason [`Binder::file_patterns`] gives: a
2642        // list is a call to `list_value`, and `nullstr = ['NA', '-']` has to arrive as a list.
2643        let Some(value) = fold::value_of(&self.plan, expr)? else {
2644            return Err(Error::not_implemented(format!(
2645                "the named parameter {parameter} with a value that is not a constant"
2646            )));
2647        };
2648        if value == Value::Null {
2649            return Err(Error::binder(null_parameter(function, parameter)));
2650        }
2651        let given = self.plan.expr_type(expr).clone();
2652        // `nullstr` takes one string or a list of them, which is the one parameter so far that
2653        // takes two types, and the parameter table has room for one.
2654        let listed = *parameter == "nullstr" && given == LogicalType::list(LogicalType::Varchar);
2655        if *parameter == "nullstr" && given != *wanted && !listed {
2656            return Err(Error::binder(
2657                "CSV Reader function option \"nullstr\" requires a string or a list as input",
2658            ));
2659        }
2660        if given != *wanted && !listed {
2661            return Err(Error::not_implemented(format!(
2662                "the named parameter {parameter} given a {given} where a {wanted} was wanted"
2663            )));
2664        }
2665        Ok((parameter, value))
2666    }
2667
2668    /// A file where a table name goes, which is what DuckDB calls a replacement scan.
2669    ///
2670    /// `SELECT * FROM 'hits.parquet'` is how most DuckDB queries in the wild are written, ClickBench
2671    /// among them, so this is not sugar over `read_parquet` so much as the spelling people use. The
2672    /// catalog has already been asked and has already said no, and `missing` is what it said, so a
2673    /// name that is not a file comes back with the catalog's own answer rather than with a complaint
2674    /// about files.
2675    ///
2676    /// Only a single unqualified name is a candidate. A qualified one names a schema and a schema
2677    /// that does not exist is not a path.
2678    fn bind_replacement_scan(
2679        &mut self,
2680        ast: &Ast,
2681        parts: &[&str],
2682        alias: ast::StrRef,
2683        columns: ast::Slice,
2684        missing: Error,
2685    ) -> Result<(NodeRef, Scope)> {
2686        let [path] = parts else { return Err(missing) };
2687        let path = *path;
2688        let extension = path.rsplit_once('.').map(|(_, after)| after).unwrap_or_default();
2689        let Some(function) = Self::reader_for(extension) else {
2690            if is_file(path) {
2691                // A file that is really there and that nothing here can read is a different mistake
2692                // from a name that is not a file, and DuckDB says so with both lines, the second of
2693                // which is the way out. A file with no dot in it lands here too, which is why the
2694                // test is on the extension having a reader rather than on there being an extension.
2695                return Err(Error::binder(format!(
2696                    "No extension found that is capable of reading the file \"{path}\"\n* If this \
2697                     file is a supported file format you can explicitly use the reader functions, \
2698                     such as read_csv, read_json or read_parquet"
2699                )));
2700            }
2701            return Err(missing);
2702        };
2703        // The pattern is expanded before it is known to match anything, so a name that ends in .csv
2704        // and is not there gives the reader's own message rather than the catalog's. That is
2705        // DuckDB's order and it is the helpful one: somebody who wrote a file name wants to hear
2706        // about the file.
2707        let paths = files(path)?;
2708        // The name the columns answer to is the file's stem, so `SELECT mixed.a FROM
2709        // 'data/mixed.parquet'` works. That is DuckDB's choice and it is the useful one, since the
2710        // alternative is a table name with a dot and a slash in it that nothing can write. A pattern
2711        // keeps the whole of what was written instead, which is DuckDB's choice too and was
2712        // measured: there is no stem to take when the name stands for a directory full of files.
2713        let label = if alias == NONE {
2714            if is_pattern(path) {
2715                path.to_string()
2716            } else {
2717                let file = path.rsplit_once('/').map_or(path, |(_, file)| file);
2718                file.rsplit_once('.').map_or(file, |(stem, _)| stem).to_string()
2719            }
2720        } else {
2721            ast.string(alias).to_string()
2722        };
2723        let mut mirrorable = None;
2724        if function == TableFunction::ReadParquet
2725            && let Some((canonical, stamp)) = mirror_target(&paths)
2726        {
2727            if let Some(name) = self.catalog.mirror(&canonical, false, stamp) {
2728                let name = name.clone();
2729                return self.bind_catalog_table(ast, &name, label, columns);
2730            }
2731            mirrorable = Some(canonical);
2732        }
2733        let read = match function {
2734            TableFunction::ReadParquet => {
2735                let footers = self.footers(&paths, mirrorable.as_deref())?;
2736                if let Some(canonical) = mirrorable.as_deref() {
2737                    self.want_mirror(canonical, false, &footers.rows);
2738                }
2739                Read {
2740                    fields: footers.fields,
2741                    rows: footers.rows,
2742                    distincts: footers.distincts,
2743                    zones: footers.zones,
2744                }
2745            }
2746            _ => Read::uncounted(csv_fields(&paths, Given::default())?),
2747        };
2748        let arguments: Vec<ExprRef> = paths.iter().map(|path| self.path_constant(path)).collect();
2749        let names: Vec<&str> = ast.name(columns).collect();
2750        self.table_function_source(function, &arguments, &[], read, &label, &names)
2751    }
2752
2753    /// What the footers of `paths` say, from the outline alone where this bind is outlined and the
2754    /// read could go through a mirror.
2755    ///
2756    /// An outline that does not state a row count is read again in full, because a read that asks
2757    /// for no mirror would leave the plan outlined with nothing telling the caller to bind again.
2758    fn footers(&self, paths: &[String], mirrorable: Option<&str>) -> Result<Footers> {
2759        if let Some(path) = mirrorable.filter(|_| self.outlined) {
2760            let outline = parquet_outline(path)?;
2761            if outline.rows.value().is_some() {
2762                return Ok(outline);
2763            }
2764        }
2765        parquet_footers(paths)
2766    }
2767
2768    /// Says the Parquet file at `path` could have been read through a native mirror, when its
2769    /// footer says how many rows it holds, which is what the database decides whether one would
2770    /// repay itself by.
2771    fn want_mirror(&mut self, path: &str, binary_as_string: bool, rows: &Stat<u64>) {
2772        if let Some(&rows) = rows.value() {
2773            self.plan.want_mirror(path, binary_as_string, rows);
2774        }
2775    }
2776
2777    /// One file name, as a constant expression in the plan.
2778    fn path_constant(&mut self, path: &str) -> ExprRef {
2779        let value = self.plan.add_value(Value::Varchar(path.to_string()));
2780        self.plan.add_expr(Expr::Constant(value), LogicalType::Varchar)
2781    }
2782
2783    /// The table function a file with this extension is read by, and `None` for one nothing reads.
2784    ///
2785    /// Both spellings of a tab separated file go to the CSV reader, which is not a shortcut: the
2786    /// extension picks the reader and the reader sniffs the punctuation, so a `.tsv` file that holds
2787    /// commas is read as commas. That was measured rather than assumed. The comparison ignores case
2788    /// because `UP.CSV` reads in duckdb v1.4.1.
2789    fn reader_for(extension: &str) -> Option<TableFunction> {
2790        if extension.eq_ignore_ascii_case("parquet") {
2791            return Some(TableFunction::ReadParquet);
2792        }
2793        if extension.eq_ignore_ascii_case("csv") || extension.eq_ignore_ascii_case("tsv") {
2794            return Some(TableFunction::ReadCsv);
2795        }
2796        None
2797    }
2798
2799    /// The node and the scope of a table function call whose arguments and columns are settled.
2800    ///
2801    /// The half a written out call shares with a replacement scan, which is everything after the
2802    /// question of what the file is called has been answered one way or the other.
2803    ///
2804    /// `read` is what the caller found out about the files, which comes in here rather than being
2805    /// read here because this function has the names and not the files: a replacement scan has
2806    /// already expanded its pattern and a written out call has already cast its argument, and
2807    /// neither of them wants to do it twice.
2808    fn table_function_source(
2809        &mut self,
2810        function: TableFunction,
2811        args: &[ExprRef],
2812        written: &[(&'static str, Value, ExprRef)],
2813        read: Read,
2814        label: &str,
2815        names: &[&str],
2816    ) -> Result<(NodeRef, Scope)> {
2817        let Read { fields, rows, distincts, zones } = read;
2818        let index = self.fresh_index();
2819        // Against the table index rather than against the node, because a pass is free to move the
2820        // node and none of them can move an index: an index is what a column reference names and
2821        // rewriting one would mean rewriting every expression above it. Nothing is recorded for a
2822        // function nobody measured, since an absent entry already reads back as unknown.
2823        if rows.is_known() {
2824            self.plan.measure(index, rows);
2825        }
2826        for (column, distinct) in distincts {
2827            self.plan.measure_distinct(index, &column, distinct);
2828        }
2829        if let Some(zones) = zones {
2830            self.plan.set_zones(index, zones);
2831        }
2832        let mut scope = Scope::empty();
2833        for (at, field) in fields.iter().enumerate() {
2834            scope.push(Visible {
2835                table: label.to_string(),
2836                name: field.name.clone(),
2837                binding: ColumnBinding::new(index, at as u32),
2838                ty: field.ty.clone(),
2839                // A reader takes what the file has, and no file format this reads says a column
2840                // cannot be null. The reference binary answers YES for every column of a Parquet.
2841                not_null: false,
2842                key: None,
2843                default: None,
2844                qualified: false,
2845                also: None,
2846            });
2847        }
2848        if !names.is_empty() {
2849            scope.rename(names, label)?;
2850        } else if matches!(
2851            function,
2852            TableFunction::Range | TableFunction::GenerateSeries | TableFunction::Unnest
2853        ) {
2854            // The PostgreSQL naming, which the pin follows for these three and for no reader: the
2855            // alias names the one column, and the column keeps answering to its own name too.
2856            for column in &mut scope.columns {
2857                column.also = Some(std::mem::replace(&mut column.name, label.to_string()));
2858            }
2859        }
2860        let function = self.plan.intern(function.name());
2861        let args = self.plan.add_expr_list(args);
2862        let named: Vec<u32> =
2863            written.iter().map(|(parameter, _, _)| self.plan.intern(parameter)).collect();
2864        let settings: Vec<ExprRef> = written.iter().map(|(_, _, expr)| *expr).collect();
2865        let options = self.plan.add_name_list(&named);
2866        let settings = self.plan.add_expr_list(&settings);
2867        let columns = self.plan.add_fields(&fields);
2868        let node = self.add_node(Node::TableFunction {
2869            index,
2870            function,
2871            args,
2872            options,
2873            settings,
2874            columns,
2875        });
2876        Ok((node, scope))
2877    }
2878
2879    /// Every file a table function's file argument names, in the order they were written.
2880    ///
2881    /// Each pattern has to find at least one file of its own, which is DuckDB's rule and is why
2882    /// this expands one at a time rather than gathering everything and looking at the total. A
2883    /// list keeps its written order and its duplicates, so a file named twice is read twice, which
2884    /// was measured: the sort and the dedup belong to one pattern rather than to the list.
2885    fn file_paths(&self, expr: ExprRef, name: &str) -> Result<Vec<String>> {
2886        let mut paths = Vec::new();
2887        for pattern in self.file_patterns(expr, name)? {
2888            paths.extend(files(&pattern)?);
2889        }
2890        Ok(paths)
2891    }
2892
2893    /// The patterns a table function argument names, which have to be constants.
2894    ///
2895    /// A table function that reads a file is resolved by opening the file, and that happens here
2896    /// rather than when the query runs, because the rest of the statement cannot bind until the
2897    /// column names are known. So the path has to be something this binder can work out without
2898    /// running anything, and a literal is that. DuckDB folds a constant expression first, so
2899    /// `read_parquet('a' || '.parquet')` works there, and folding is M1 work that this will pick up
2900    /// for free once the optimizer runs before the plan is finished rather than after.
2901    ///
2902    /// One string is one pattern and a list is one pattern an item, which is DuckDB's pair of
2903    /// overloads. A null is a different sentence in each of them, both of them measured.
2904    ///
2905    /// The argument is folded rather than required to be a literal. A list is a call to `list_value`
2906    /// as of the work on #467, so requiring a literal here would have turned every `read_parquet`
2907    /// over a list into the message about a name that is not a constant, and the sentence this
2908    /// comment used to carry about folding being picked up for free was the plan for exactly that.
2909    /// What it buys beyond keeping the list working is `read_parquet('a' || '.parquet')`, which the
2910    /// pin answers and which used to be refused here.
2911    fn file_patterns(&self, expr: ExprRef, name: &str) -> Result<Vec<String>> {
2912        let Some(value) = fold::value_of(&self.plan, expr)? else {
2913            return Err(Error::not_implemented(
2914                "a table function file name that is not a constant",
2915            ));
2916        };
2917        match value {
2918            Value::Varchar(path) => Ok(vec![path]),
2919            // DuckDB's own wording, which says list because its other overload takes one.
2920            Value::Null => Err(Error::parser(format!("{name} cannot take NULL list as parameter"))),
2921            // An empty list reaches the reader rather than failing to bind, because `[]` carries an
2922            // element type of the untyped null and a null promotes to VARCHAR, so the call resolves.
2923            // The pin says this, and it says it as an IO error rather than as a binder one, since
2924            // the list was a fine list and the objection is that there is no file in it.
2925            Value::List { values, .. } if values.is_empty() => {
2926                Err(Error::io(format!("\"{name}\" needs at least one file to read")))
2927            }
2928            Value::List { values, .. } => values
2929                .iter()
2930                .map(|value| match value {
2931                    Value::Varchar(path) => Ok(path.clone()),
2932                    _ => Err(Error::parser(format!(
2933                        "{name} reader cannot take NULL input as parameter"
2934                    ))),
2935                })
2936                .collect(),
2937            other => {
2938                Err(Error::internal(format!("a file name bound as VARCHAR arrived as {other}")))
2939            }
2940        }
2941    }
2942
2943    /// Which input of a join a query written in its `ON` has to be joined into.
2944    ///
2945    /// A join condition is evaluated by the join, over the rows its two inputs handed it, so a
2946    /// column the condition reads has to be produced by one of those two. A query written in the
2947    /// `ON` produces columns the condition reads, which means the query cannot be joined in above
2948    /// the join the way one written in a `WHERE` or a `SELECT` is. It has to go underneath, into
2949    /// one input or the other.
2950    ///
2951    /// Which input is decided by what the query reads. A query whose body reads the right side can
2952    /// only be evaluated where those rows are, so it goes into the right input, and the same for
2953    /// the left. A query that reads neither could go into either and goes into the left, which is
2954    /// also where an `IN` puts one whose left hand side reads the left and whose body reads
2955    /// nothing.
2956    ///
2957    /// The one that has no answer is a query that reads both sides. There is no single input that
2958    /// produces what it needs, and the shape upstream calls a pair dependent join is what handles
2959    /// it. `None` is that case, and the caller turns it into a refusal rather than a plan.
2960    fn side_of(
2961        &self,
2962        pending: &PendingSubquery,
2963        left_tables: &[u32],
2964        right_tables: &[u32],
2965    ) -> Option<Side> {
2966        let mut needs_left = false;
2967        let mut needs_right = false;
2968        let mut note = |binding: ColumnBinding| {
2969            needs_left |= left_tables.contains(&binding.table);
2970            needs_right |= right_tables.contains(&binding.table);
2971        };
2972        for &binding in &pending.reads {
2973            note(binding);
2974        }
2975        // A mark join carries the comparison rather than the condition carrying it, and that
2976        // comparison is written over the join's own rows. `l.a IN (SELECT ...)` reads the left side
2977        // there and nowhere else, so leaving it out would put the query on whichever side its body
2978        // happened to name and let the comparison ask a join for a column it was not given.
2979        for &condition in &pending.conditions {
2980            self.plan.read_columns(condition, &mut |_, binding| note(binding));
2981        }
2982        match (needs_left, needs_right) {
2983            (true, true) => None,
2984            (_, true) => Some(Side::Right),
2985            _ => Some(Side::Left),
2986        }
2987    }
2988
2989    /// A join whose condition holds a query that reads rows from both of its inputs.
2990    ///
2991    /// This is the one [`Binder::side_of`] has no side for. The query has to be evaluated once per
2992    /// pair of rows, and there is no input that produces a pair, so it cannot go into either input
2993    /// the way the other two cases do. What produces a pair is the join itself, so the join becomes
2994    /// a product, the query is joined into the product's rows the way a query in a `WHERE` is joined
2995    /// into the rows the whole `FROM` produced, and the condition becomes a filter above that.
2996    ///
2997    /// That rewrite is only the same query for an inner join. An inner join keeps the pairs its
2998    /// condition holds and drops the rest, which is what a product and a filter do. Every other kind
2999    /// does something with the pairs it dropped, a left join pads them, a semi join counts them, and
3000    /// a filter above a product has already thrown away which left row a dropped pair came from, so
3001    /// those are refused by name. Upstream plans them as a pair dependent join and rudb does not
3002    /// have one yet, which is what tamnd/rudb#913 stays open for.
3003    ///
3004    /// The product is not the plan that runs. The condition goes back into the join as a condition
3005    /// when filter pushdown looks at it, which is the pass that already turns a filter over an inner
3006    /// join into a join condition, so an equality in the `ON` is still an equality the hash join can
3007    /// build on. What cannot be pushed back down is the part that reads the query's output, and that
3008    /// part could not have been a join condition in the first place.
3009    #[allow(clippy::too_many_arguments)]
3010    fn bind_pair_dependent_join(
3011        &mut self,
3012        kind: ast::JoinKind,
3013        independent: bool,
3014        left: NodeRef,
3015        right: NodeRef,
3016        pair: Vec<PendingSubquery>,
3017        conditions: Vec<ExprRef>,
3018        scope: Scope,
3019    ) -> Result<(NodeRef, Scope)> {
3020        if kind != ast::JoinKind::Inner {
3021            return Err(Error::not_implemented(
3022                "a subquery that reads both sides of that join, written in the condition of a join \
3023                 that is not an inner join"
3024                    .to_string(),
3025            ));
3026        }
3027        // A lateral right side is already evaluated per left row, so the product this would build is
3028        // not the product the query means.
3029        if !independent {
3030            return Err(Error::not_implemented(
3031                "a subquery that reads both sides of that join, written in the condition of a join \
3032                 whose right side is lateral"
3033                    .to_string(),
3034            ));
3035        }
3036        let mut node = self.add_node(Node::CrossProduct { left, right });
3037        for pending in pair {
3038            node = self.attach_subquery(node, pending);
3039        }
3040        // `ON` and `USING` cannot both be written, and this is only reached from the `ON` path, so
3041        // the list is the one bound condition. The fold is here so that it stays right if that stops
3042        // being true rather than for a case that exists today.
3043        let mut conditions = conditions.into_iter();
3044        let mut predicate = conditions.next().expect("a join condition was bound");
3045        for next in conditions {
3046            let children = self.plan.add_expr_list(&[predicate, next]);
3047            let conjunction = Expr::Conjunction { op: ConjunctionOp::And, children };
3048            predicate = self.plan.add_expr(conjunction, LogicalType::Boolean);
3049        }
3050        let node = self.add_node(Node::Filter { input: node, predicate });
3051        Ok((node, scope))
3052    }
3053
3054    #[allow(clippy::too_many_arguments)]
3055    fn bind_join(
3056        &mut self,
3057        ast: &Ast,
3058        left: ast::SourceRef,
3059        right: ast::SourceRef,
3060        kind: ast::JoinKind,
3061        natural: bool,
3062        on: ast::ExprRef,
3063        using: ast::Slice,
3064    ) -> Result<(NodeRef, Scope)> {
3065        let (left_node, left_scope) = self.bind_source(ast, left)?;
3066        let (right_node, right_scope, correlated) = self.bind_lateral(ast, right, &left_scope)?;
3067        // A row of the right side exists only for the left row it was evaluated against, so a kind
3068        // that has to produce right rows with no left row has nothing to produce them from. The
3069        // pinned build says this and names only the two kinds that work.
3070        if !correlated.is_empty()
3071            && !matches!(kind, ast::JoinKind::Inner | ast::JoinKind::Cross | ast::JoinKind::Left)
3072        {
3073            return Err(Error::binder(
3074                "The combining JOIN type must be INNER or LEFT for a LATERAL reference",
3075            ));
3076        }
3077        let split = left_scope.len();
3078        // Which table index came from which side, kept before the two scopes become one. A query
3079        // written in the `ON` is joined into one of the inputs rather than above the join, and this
3080        // is what says which. A `USING` drops the right side's copy of a joined-on column out of
3081        // the scope below, and dropping a column does not change the index it came from, so the
3082        // answer this gives is still right afterwards.
3083        let left_tables: Vec<u32> =
3084            left_scope.columns.iter().map(|column| column.binding.table).collect();
3085        let right_tables: Vec<u32> =
3086            right_scope.columns.iter().map(|column| column.binding.table).collect();
3087        let mut scope = left_scope.concat(right_scope);
3088
3089        // NATURAL is USING over whatever both sides happen to call the same thing, which is why it
3090        // is resolved here and never reaches the plan as its own idea.
3091        let merged: Vec<String> = if natural {
3092            let mut names = Vec::new();
3093            for (at, column) in scope.columns.iter().enumerate().take(split) {
3094                if scope.columns[split..].iter().any(|right| same_name(&right.name, &column.name))
3095                    && !names.iter().any(|held: &String| same_name(held, &column.name))
3096                {
3097                    let _ = at;
3098                    names.push(column.name.clone());
3099                }
3100            }
3101            names
3102        } else {
3103            // A name written twice is one column, not two. `USING (id, id)` is legal and means what
3104            // `USING (id)` means, and the reference binary agrees. Taking it twice would build the
3105            // same equality twice and, worse, drop the right side's copy twice, which takes a
3106            // column out of the answer that nobody named and runs off the end of the scope when the
3107            // copy was the last column in it.
3108            let mut names: Vec<String> = Vec::new();
3109            for name in ast.name(using) {
3110                if !names.iter().any(|held| same_name(held, name)) {
3111                    names.push(name.to_string());
3112                }
3113            }
3114            names
3115        };
3116
3117        let mut conditions = Vec::new();
3118        let mut dropped = Vec::new();
3119        for name in &merged {
3120            let left_at = scope.columns[..split]
3121                .iter()
3122                .position(|column| same_name(&column.name, name))
3123                .ok_or_else(|| {
3124                    Error::binder(format!(
3125                        "column \"{name}\" specified in USING clause does not exist in left table"
3126                    ))
3127                })?;
3128            let right_at = scope.columns[split..]
3129                .iter()
3130                .position(|column| same_name(&column.name, name))
3131                .map(|at| at + split)
3132                .ok_or_else(|| {
3133                    Error::binder(format!(
3134                        "column \"{name}\" specified in USING clause does not exist in right table"
3135                    ))
3136                })?;
3137            let left_column = &scope.columns[left_at];
3138            let (left_binding, left_type) = (left_column.binding, left_column.ty.clone());
3139            let right_column = &scope.columns[right_at];
3140            let (right_binding, right_type) = (right_column.binding, right_column.ty.clone());
3141            let left_expr = self.plan.add_expr(Expr::Column(left_binding), left_type);
3142            let right_expr = self.plan.add_expr(Expr::Column(right_binding), right_type);
3143            conditions.push(self.compare(rudb_plan::CompareOp::Equal, left_expr, right_expr)?);
3144            dropped.push(right_at);
3145        }
3146        // A joined-on column appears once, so the right side's copy goes. Dropping from the back
3147        // keeps the positions of the ones still to drop correct.
3148        dropped.sort_unstable();
3149        for at in dropped.into_iter().rev() {
3150            scope.remove(at);
3151        }
3152
3153        let mut left_node = left_node;
3154        let mut right_node = right_node;
3155        let mut pair = Vec::new();
3156        if on != NONE {
3157            if !merged.is_empty() {
3158                return Err(Error::binder("a join cannot have both ON and USING"));
3159            }
3160            self.clause = "JOIN condition";
3161            let waiting = self.scalar_subqueries.len();
3162            let predicate = self.bind_expr(ast, on, &scope)?;
3163            conditions.push(self.as_boolean(predicate, "JOIN")?);
3164            for pending in self.scalar_subqueries.split_off(waiting) {
3165                match self.side_of(&pending, &left_tables, &right_tables) {
3166                    Some(Side::Right) => right_node = self.attach_subquery(right_node, pending),
3167                    Some(Side::Left) => left_node = self.attach_subquery(left_node, pending),
3168                    None => pair.push(pending),
3169                }
3170            }
3171        }
3172
3173        if kind == ast::JoinKind::Cross && !conditions.is_empty() {
3174            return Err(Error::binder("a CROSS JOIN cannot have a condition"));
3175        }
3176        if !pair.is_empty() {
3177            return self.bind_pair_dependent_join(
3178                kind,
3179                correlated.is_empty(),
3180                left_node,
3181                right_node,
3182                pair,
3183                conditions,
3184                scope,
3185            );
3186        }
3187        // A product is the join with nothing to join on, and it is not one when the right side has
3188        // to be evaluated per left row, because then there is a dependency to lower even though
3189        // there is no condition to test.
3190        if correlated.is_empty()
3191            && conditions.is_empty()
3192            && matches!(kind, ast::JoinKind::Cross | ast::JoinKind::Inner)
3193        {
3194            let node = self.add_node(Node::CrossProduct { left: left_node, right: right_node });
3195            return Ok((node, scope));
3196        }
3197        // A semi join and an anti join ask a question about the right side rather than producing
3198        // any of it, so what is in scope after one is the left side alone. The condition is bound
3199        // above and is the last thing that can name the right side. Without this, `SELECT *` over
3200        // one expanded to both sides and the projection asked a join whose output is the left side
3201        // for columns it does not have, which came out as an internal error about a column not
3202        // being in the schema. That is tamnd/rudb#847. The reference binary refuses `b.w` here with
3203        // a binder error naming `a` as the only candidate table, which is the same rule said from
3204        // the other end.
3205        if matches!(kind, ast::JoinKind::Semi | ast::JoinKind::Anti) {
3206            scope.truncate(split);
3207        }
3208        let kind = match kind {
3209            ast::JoinKind::Inner | ast::JoinKind::Cross => JoinKind::Inner,
3210            ast::JoinKind::Left => JoinKind::Left,
3211            ast::JoinKind::Right => JoinKind::Right,
3212            ast::JoinKind::Full => JoinKind::Full,
3213            ast::JoinKind::Semi => JoinKind::Semi,
3214            ast::JoinKind::Anti => JoinKind::Anti,
3215            ast::JoinKind::Positional => JoinKind::Positional,
3216        };
3217        let conditions = self.plan.add_expr_list(&conditions);
3218        let node = if correlated.is_empty() {
3219            self.add_node(Node::Join {
3220                left: left_node,
3221                right: right_node,
3222                kind,
3223                conditions,
3224                build: BuildSide::default(),
3225            })
3226        } else {
3227            self.add_node(Node::DependentJoin {
3228                left: left_node,
3229                right: right_node,
3230                kind,
3231                conditions,
3232            })
3233        };
3234        Ok((node, scope))
3235    }
3236
3237    // -------------------------------------------------------------- aggregates
3238
3239    /// Binds a `FILTER (WHERE ...)` predicate, or says there was none.
3240    ///
3241    /// The predicate is a condition over the input rows and not over the answer, so it is bound in
3242    /// the scope the arguments are bound in, and it is cast to `BOOLEAN` the way a `WHERE` is:
3243    /// `FILTER (WHERE i)` over an integer column is a filter on whether the integer is not zero.
3244    fn bind_filter(
3245        &mut self,
3246        ast: &Ast,
3247        filter: ast::ExprRef,
3248        scope: &Scope,
3249    ) -> Result<Option<ExprRef>> {
3250        if filter == NONE {
3251            return Ok(None);
3252        }
3253        let bound = self.bind_expr(ast, filter, scope)?;
3254        Ok(Some(self.checked_cast_to(bound, &LogicalType::Boolean, false)?))
3255    }
3256
3257    /// Binds an aggregate call, records it, and hands back a reference to where its result lands.
3258    ///
3259    /// An aggregate inside a lambda's body is computed over the rows and not over the elements,
3260    /// so its arguments cannot see the lambda's parameters. See `crate::lambda`.
3261    #[allow(clippy::too_many_arguments)]
3262    pub(crate) fn bind_aggregate(
3263        &mut self,
3264        ast: &Ast,
3265        name: &str,
3266        args: &[ast::ExprRef],
3267        distinct: bool,
3268        filter: ast::ExprRef,
3269        sorted: &[ast::OrderItem],
3270        scope: &Scope,
3271    ) -> Result<ExprRef> {
3272        if self.trying {
3273            return Err(Error::binder("aggregates are not allowed inside the TRY expression"));
3274        }
3275        let frames = std::mem::take(&mut self.lambda_frames);
3276        let call = AggregateCall { name, args, distinct, filter, sorted };
3277        let bound = self.bind_aggregate_over_rows(ast, &call, scope);
3278        self.lambda_frames = frames;
3279        bound
3280    }
3281
3282    fn bind_aggregate_over_rows(
3283        &mut self,
3284        ast: &Ast,
3285        written: &AggregateCall<'_>,
3286        scope: &Scope,
3287    ) -> Result<ExprRef> {
3288        let AggregateCall { name, args, distinct, filter, sorted } = *written;
3289        if self.in_filter {
3290            return Err(Error::binder("aggregate functions are not allowed in FILTER"));
3291        }
3292        if self.in_aggregate {
3293            return Err(Error::binder(format!(
3294                "aggregate function calls cannot be nested, and {name}() is inside one"
3295            )));
3296        }
3297        if self.aggregation.is_none() {
3298            // A join condition is the `WHERE` clause here too, the way it is for a window.
3299            let clause = if self.clause == "JOIN condition" { "WHERE clause" } else { self.clause };
3300            return Err(Error::binder(format!("{clause} cannot contain aggregates!")));
3301        }
3302        // The predicate goes first, which is the order the messages come out in upstream: a call
3303        // whose argument and whose filter both name columns that are not there is refused over the
3304        // filter. It is bound as if it were inside the call, so an aggregate in it is caught, and a
3305        // window in it is refused with the words a window inside an aggregate is refused with.
3306        self.in_aggregate = true;
3307        self.in_filter = true;
3308        let filter = self.bind_filter(ast, filter, scope);
3309        self.in_filter = false;
3310        self.in_aggregate = false;
3311        let filter = filter?;
3312
3313        // The ordered-set aggregates take the value they read from their `ORDER BY` when the call
3314        // does not write it, which is what `percentile_cont(0.5) WITHIN GROUP (ORDER BY x)` is
3315        // parsed into, and a descending order counts their fractions from the top.
3316        let (ordered_set, taken) = ordered_set(name, args.len(), sorted);
3317        let injected = sorted.iter().map(|item| item.expr).take(usize::from(taken));
3318        let args: Vec<ast::ExprRef> = injected.chain(args.iter().copied()).collect();
3319        let from_top = ordered_set
3320            && sorted.len() == 1
3321            && match sorted[0].order {
3322                Order::Unstated => self.semantics.default_descending(),
3323                Order::Ascending => false,
3324                Order::Descending => true,
3325            };
3326
3327        self.in_aggregate = true;
3328        let mut bound = Vec::with_capacity(args.len());
3329        let mut failure = None;
3330        let written_keys = sorted.iter().map(|item| item.expr);
3331        for arg in args.iter().copied().chain(written_keys) {
3332            match self.bind_expr(ast, arg, scope) {
3333                Ok(expr) => bound.push(expr),
3334                Err(error) => {
3335                    failure = Some(error);
3336                    break;
3337                }
3338            }
3339        }
3340        self.in_aggregate = false;
3341        if let Some(error) = failure {
3342            return Err(error);
3343        }
3344        let keys = bound.split_off(args.len());
3345        // A distinct aggregate sees each value once, and a key that is not one of the values would
3346        // have more than one of them to sort that value by.
3347        if distinct && !keys.iter().all(|&key| bound.iter().any(|&arg| self.same_expr(arg, key))) {
3348            return Err(Error::binder(
3349                "In a DISTINCT aggregate, ORDER BY expressions must appear in the argument list",
3350            ));
3351        }
3352
3353        let types: Vec<LogicalType> =
3354            bound.iter().map(|&arg| self.plan.expr_type(arg).clone()).collect();
3355        let resolved = resolve(name, &types)?;
3356        // The separator is read once per group and not once per row, so the pin wants it to be the
3357        // same on every row and says so in these words.
3358        if resolved.name == "string_agg"
3359            && bound.len() == 2
3360            && !matches!(fold::value_of(&self.plan, bound[1]), Ok(Some(_)))
3361        {
3362            return Err(Error::binder(
3363                "The \"separator\" argument in function \"string_agg\" must be a constant expression",
3364            ));
3365        }
3366        if matches!(resolved.name, "quantile_cont" | "quantile_disc") {
3367            let ordered = ordered_set && sorted.len() == 1;
3368            bound[1] = self.quantile_fraction(resolved.name, bound[1], ordered, from_top)?;
3369        }
3370        if resolved.name == "approx_quantile" {
3371            self.digest_arguments(&bound)?;
3372        }
3373        if resolved.name == "reservoir_quantile" {
3374            self.reservoir_arguments(&bound)?;
3375        }
3376        if resolved.name == "approx_top_k" {
3377            self.top_k_argument(&bound)?;
3378        }
3379        let mut cast = Vec::with_capacity(bound.len());
3380        for (arg, wanted) in bound.iter().zip(&resolved.arguments) {
3381            cast.push(self.checked_cast_to(*arg, wanted, false)?);
3382        }
3383        let name = self.ordered_aggregate(resolved.name, sorted, &keys, &mut cast);
3384        let args = self.plan.add_expr_list(&cast);
3385        let name = self.plan.intern(&name);
3386        let ty = resolved.returns;
3387        let call = self.plan.add_expr(Expr::Aggregate { name, args, distinct, filter }, ty.clone());
3388
3389        // Two identical aggregates are one column of the aggregate's output. `SELECT sum(x),
3390        // sum(x) / count(*)` computes one sum, not two.
3391        let existing = self.aggregation.as_ref().map(|held| held.aggregates.clone());
3392        let existing = existing.unwrap_or_default();
3393        let at = match existing.iter().position(|&held| self.same_expr(held, call)) {
3394            Some(at) => at,
3395            None => {
3396                let aggregation = self.aggregation.as_mut().expect("checked above");
3397                aggregation.aggregates.push(call);
3398                aggregation.aggregates.len() - 1
3399            }
3400        };
3401        let aggregation = self.aggregation.as_ref().expect("checked above");
3402        let (index, groups) = (aggregation.index, aggregation.groups.len());
3403        Ok(self.column(index, groups + at, ty))
3404    }
3405
3406    /// The fraction of a quantile call, checked the way the pin checks it and counted from the top
3407    /// when the call's `ORDER BY` is descending.
3408    ///
3409    /// A negative fraction already means counting from the top, so a call that also writes an
3410    /// order may not have one, and a list may not mix the two directions.
3411    fn quantile_fraction(
3412        &mut self,
3413        name: &str,
3414        fraction: ExprRef,
3415        ordered: bool,
3416        from_top: bool,
3417    ) -> Result<ExprRef> {
3418        let Ok(Some(value)) = fold::value_of(&self.plan, fraction) else {
3419            return Err(Error::binder(format!(
3420                "The \"quantile\" argument in function \"{name}\" must be a constant expression"
3421            )));
3422        };
3423        if value.is_null() {
3424            return Err(Error::binder(format!(
3425                "The \"quantile\" argument in function '\"{name}\"' must not be NULL"
3426            )));
3427        }
3428        let each = match &value {
3429            Value::List { values, .. } => values.as_slice(),
3430            one => std::slice::from_ref(one),
3431        };
3432        let mut signs = (false, false);
3433        for one in each {
3434            if one.is_null() {
3435                return Err(Error::binder("QUANTILE parameter cannot be NULL"));
3436            }
3437            let share = share(one).unwrap_or(f64::NAN);
3438            if !(-1.0..=1.0).contains(&share) {
3439                return Err(Error::binder(
3440                    "QUANTILE can only take parameters in the range [-1, 1]",
3441                ));
3442            }
3443            if share < 0.0 {
3444                signs.0 = true;
3445            } else {
3446                signs.1 = true;
3447            }
3448        }
3449        if ordered && signs.0 {
3450            return Err(Error::binder("PERCENTILEs can only take parameters in the range [0, 1]"));
3451        }
3452        if signs.0 && signs.1 {
3453            return Err(Error::binder("QUANTILE parameters must have consistent signs"));
3454        }
3455        if !from_top {
3456            return Ok(fraction);
3457        }
3458        let negated = match value {
3459            Value::List { element, values } => {
3460                Value::List { element, values: values.iter().map(negated).collect() }
3461            }
3462            one => negated(&one),
3463        };
3464        Ok(self.add_constant(negated))
3465    }
3466
3467    /// Refuses an `approx_top_k` whose `k` is not a constant, over a group or over a window.
3468    ///
3469    /// The pin names the argument `col1` whatever it was written as, and the sentence is its own.
3470    fn top_k_argument(&self, bound: &[ExprRef]) -> Result<()> {
3471        if matches!(fold::value_of(&self.plan, bound[1]), Ok(Some(_))) {
3472            return Ok(());
3473        }
3474        Err(Error::binder(
3475            "The \"col1\" argument in function \"approx_top_k\" must be a constant expression",
3476        ))
3477    }
3478
3479    /// Checks the fraction and the sample size of a `reservoir_quantile` call the way the pin does,
3480    /// which is in words of its own rather than the ones the other quantiles use.
3481    fn reservoir_arguments(&self, bound: &[ExprRef]) -> Result<()> {
3482        let constant = |arg: ExprRef, parameter: &str| match fold::value_of(&self.plan, arg) {
3483            Ok(Some(value)) => Ok(value),
3484            _ => Err(Error::binder(format!(
3485                "The \"{parameter}\" argument in function \"reservoir_quantile\" must be a constant \
3486                 expression"
3487            ))),
3488        };
3489        let fraction = constant(bound[1], "quantile")?;
3490        let each = match &fraction {
3491            Value::List { values, .. } => values.as_slice(),
3492            one => std::slice::from_ref(one),
3493        };
3494        for one in each {
3495            if one.is_null() {
3496                return Err(Error::binder("RESERVOIR_QUANTILE QUANTILE parameter cannot be NULL"));
3497            }
3498            if !(0.0..=1.0).contains(&share(one).unwrap_or(f64::NAN)) {
3499                return Err(Error::binder(
3500                    "RESERVOIR_QUANTILE can only take parameters in the range [0, 1]",
3501                ));
3502            }
3503        }
3504        let Some(&size) = bound.get(2) else {
3505            return Ok(());
3506        };
3507        let size = constant(size, "sample_size")?;
3508        if size.is_null() {
3509            return Err(Error::binder(
3510                "The \"sample_size\" argument in function '\"reservoir_quantile\"' must not be NULL",
3511            ));
3512        }
3513        if share(&size).is_none_or(|n| n <= 0.0) {
3514            return Err(Error::binder(
3515                "Size of the RESERVOIR_QUANTILE sample must be bigger than 0",
3516            ));
3517        }
3518        Ok(())
3519    }
3520
3521    /// Checks the fractions of an `approx_quantile` call the way the pin does, which is in words of
3522    /// its own again.
3523    fn digest_arguments(&self, bound: &[ExprRef]) -> Result<()> {
3524        let Ok(Some(fraction)) = fold::value_of(&self.plan, bound[1]) else {
3525            return Err(Error::binder(
3526                "The \"quantile\" argument in function \"approx_quantile\" must be a constant \
3527                 expression",
3528            ));
3529        };
3530        if fraction.is_null() {
3531            return Err(Error::binder(
3532                "The \"quantile\" argument in function '\"approx_quantile\"' must not be NULL",
3533            ));
3534        }
3535        let each = match &fraction {
3536            Value::List { values, .. } => values.as_slice(),
3537            one => std::slice::from_ref(one),
3538        };
3539        for one in each {
3540            if one.is_null() {
3541                return Err(Error::binder("APPROXIMATE QUANTILE parameter cannot be NULL"));
3542            }
3543            if !(0.0..=1.0).contains(&share(one).unwrap_or(f64::NAN)) {
3544                return Err(Error::binder(
3545                    "APPROXIMATE QUANTILE can only take parameters in range [0, 1]",
3546                ));
3547            }
3548        }
3549        Ok(())
3550    }
3551
3552    /// The name of an aggregate with the `ORDER BY` of its call folded in, with the keys that matter
3553    /// added to the end of its arguments.
3554    ///
3555    /// Only the aggregates whose answer depends on the order the rows come in keep their keys, which
3556    /// is what the pin does too: `sum(x ORDER BY y)` is `sum(x)` there, named as written and computed
3557    /// without a sort. A key that is a constant orders nothing and is dropped, so `list(x ORDER BY
3558    /// 1)` is a plain `list` and not the first column, which is what a number means in the query's
3559    /// own `ORDER BY` and not what it means here.
3560    fn ordered_aggregate(
3561        &mut self,
3562        name: &str,
3563        sorted: &[ast::OrderItem],
3564        keys: &[ExprRef],
3565        args: &mut Vec<ExprRef>,
3566    ) -> String {
3567        const DEPENDS_ON_ORDER: &[&str] = &["list", "first", "last", "any_value", "string_agg"];
3568        if !DEPENDS_ON_ORDER.contains(&name) {
3569            return name.to_string();
3570        }
3571        let mut flags = Vec::new();
3572        for (&key, item) in keys.iter().zip(sorted) {
3573            if matches!(fold::value_of(&self.plan, key), Ok(Some(_))) {
3574                continue;
3575            }
3576            let descending = match item.order {
3577                Order::Unstated => self.semantics.default_descending(),
3578                Order::Ascending => false,
3579                Order::Descending => true,
3580            };
3581            let nulls_first = match item.nulls {
3582                Nulls::First => true,
3583                Nulls::Last => false,
3584                Nulls::Unstated => self.semantics.nulls_first(descending),
3585            };
3586            flags.push((descending, nulls_first));
3587            args.push(key);
3588        }
3589        if flags.is_empty() {
3590            return name.to_string();
3591        }
3592        rudb_kernels::ordered_name(name, &flags)
3593    }
3594
3595    // ----------------------------------------------------------------- windows
3596
3597    /// Binds a window call, files it under the run it belongs to, and hands back its column.
3598    ///
3599    /// The result is a column of a [`Node::Window`] rather than the call itself, for the reason the
3600    /// aggregate path returns a column too: the operator produces the value and everything above it
3601    /// reads the value, so a target that wraps a window in arithmetic is arithmetic over a column.
3602    ///
3603    /// A window inside a lambda's body is computed over the rows for the reason an aggregate is,
3604    /// so it cannot see the lambda's parameters either.
3605    pub(crate) fn bind_window(
3606        &mut self,
3607        ast: &Ast,
3608        written: &WindowCall<'_>,
3609        scope: &Scope,
3610    ) -> Result<ExprRef> {
3611        if self.trying {
3612            return Err(Error::binder("window functions are not allowed in try"));
3613        }
3614        let frames = std::mem::take(&mut self.lambda_frames);
3615        let bound = self.bind_window_over_rows(ast, written, scope);
3616        self.lambda_frames = frames;
3617        bound
3618    }
3619
3620    fn bind_window_over_rows(
3621        &mut self,
3622        ast: &Ast,
3623        written: &WindowCall<'_>,
3624        scope: &Scope,
3625    ) -> Result<ExprRef> {
3626        let WindowCall { name, args, distinct, filter, ignore_nulls, spec, .. } = *written;
3627        if self.in_aggregate {
3628            return Err(Error::binder(
3629                "aggregate function calls cannot contain window function calls",
3630            ));
3631        }
3632        if self.in_window {
3633            return Err(Error::binder("window function calls cannot be nested"));
3634        }
3635        // A join condition is part of the `WHERE` clause as far as this one sentence is concerned,
3636        // which is upstream's wording and not a simplification: `ON sum(a.i) OVER () = b.i` is
3637        // refused there with the words a window in a `WHERE` is refused with.
3638        let clause = if self.clause == "JOIN condition" { "WHERE clause" } else { self.clause };
3639        if clause != "SELECT clause" && clause != "ORDER BY clause" {
3640            return Err(Error::binder(format!("{clause} cannot contain window functions!")));
3641        }
3642
3643        // `count(*)` is a different function from `count(x)` here for the reason it is a different
3644        // function in an ordinary call: one counts rows and the other counts the rows where its
3645        // argument is not null. A star is not an expression and nothing below this binds one.
3646        let starred = args.iter().any(|&arg| {
3647            matches!(ast.expr(arg), ast::Expr::Star { qualifier, replacements }
3648                if qualifier.is_empty() && replacements.is_empty())
3649        });
3650        let (name, args): (&str, &[ast::ExprRef]) = if starred {
3651            if !same_name(name, "count") || args.len() != 1 {
3652                return Err(Error::binder(format!("* is not allowed in {name}()")));
3653            }
3654            ("count_star", &[])
3655        } else if same_name(name, "count") && args.is_empty() {
3656            // `count()` with nothing in it is upstream's other spelling of `count(*)`. It counts
3657            // rows the same way and it is not an arity mistake.
3658            ("count_star", &[])
3659        } else {
3660            (name, args)
3661        };
3662
3663        let held = ast.window(spec);
3664        self.in_window = true;
3665        let parts = self.window_parts(ast, written, args, held, scope);
3666        // The predicate goes last here, which is the other way round from an ordinary aggregate and
3667        // is again the order the messages come out in upstream. It is still inside the window, so a
3668        // window in it is a nested window, while an aggregate in it is an ordinary aggregate over
3669        // the same rows and is answered.
3670        let filter = if parts.is_ok() { self.bind_filter(ast, filter, scope) } else { Ok(None) };
3671        self.in_window = false;
3672        let parts = parts?;
3673        let filter = filter?;
3674        // Upstream's rule, in its words. A `RANGE` offset is a distance from the current row's sort
3675        // key, so there has to be exactly one sort key for it to be a distance from.
3676        let offsets = [parts.frame.start, parts.frame.end]
3677            .iter()
3678            .any(|end| matches!(end, WindowBound::Preceding(_) | WindowBound::Following(_)));
3679        if parts.frame.unit == WindowUnit::Range && offsets && parts.order.len() != 1 {
3680            return Err(Error::binder("RANGE frames must have only one ORDER BY expression"));
3681        }
3682
3683        let types: Vec<LogicalType> =
3684            parts.args.iter().map(|&arg| self.plan.expr_type(arg).clone()).collect();
3685        let resolved = window_signature(name, &types)?;
3686        // `fill` reads the sort key rather than the frame, so what it needs from the query is not
3687        // what any other window needs and it is refused on its own terms.
3688        if resolved.name == "fill" {
3689            let keys: Vec<LogicalType> =
3690                parts.order.iter().map(|key| self.plan.expr_type(key.expr).clone()).collect();
3691            refuse_fill(&types[0], &keys, distinct, ignore_nulls)?;
3692        }
3693        // Upstream's sentence, doubled quotes and all. A DISTINCT over an aggregate inside an OVER
3694        // is ordinary and answered, and a DISTINCT over a ranking window is refused there, because
3695        // there is nothing for it to collapse when the call reads no values in the first place.
3696        if distinct && kind_of(resolved.name) == Some(FunctionKind::Window) {
3697            return Err(Error::binder(format!(
3698                "DISTINCT is not implemented for the window function \"\"{name}\"\""
3699            )));
3700        }
3701        // The same sentence for the same reason. A ranking window reads no values, so there is
3702        // nothing for a predicate over the values to keep or drop.
3703        if filter.is_some() && kind_of(resolved.name) == Some(FunctionKind::Window) {
3704            return Err(Error::binder(format!(
3705                "FILTER is not implemented for the window function \"\"{name}\"\""
3706            )));
3707        }
3708        // An `ORDER BY` inside the brackets puts the rows of the frame in a different order for
3709        // this one call to read them in, which is a question every aggregate and the three that
3710        // count through the frame have an answer to. The rest of the window functions read
3711        // something other than the frame, and what the reference binary does with them under an
3712        // order of their own is a different reading again, so they are turned down rather than
3713        // guessed at. The exclusion is refused first and in the reference binary's own sentence,
3714        // because that is the one it reaches for when both apply. Per #1204.
3715        if !parts.inner.is_empty() && kind_of(resolved.name) == Some(FunctionKind::Window) {
3716            let counts = matches!(resolved.name, "first_value" | "last_value" | "nth_value");
3717            if !counts {
3718                if parts.frame.exclude != WindowExclude::NoOthers {
3719                    return Err(Error::binder(format!(
3720                        "EXCLUDE is not supported for the window function \"\"{}\"\"",
3721                        resolved.name
3722                    )));
3723                }
3724                return Err(Error::not_implemented(format!(
3725                    "ORDER BY inside the arguments of the window function \"{}\"",
3726                    resolved.name
3727                )));
3728            }
3729        }
3730        if resolved.name == "approx_top_k" {
3731            self.top_k_argument(&parts.args)?;
3732        }
3733        let mut cast = Vec::with_capacity(parts.args.len());
3734        for (arg, wanted) in parts.args.iter().zip(&resolved.arguments) {
3735            cast.push(self.checked_cast_to(*arg, wanted, false)?);
3736        }
3737        let args = self.plan.add_expr_list(&cast);
3738        let order = self.plan.add_sort_keys(&parts.inner);
3739        let name = self.plan.intern(resolved.name);
3740        let ty = resolved.returns;
3741        let call = self.plan.add_expr(
3742            Expr::Window { name, args, distinct, filter, ignore_nulls, order },
3743            ty.clone(),
3744        );
3745
3746        let at = self.window_run(parts.partition, parts.order, parts.frame, call);
3747        let index = self.windows.last().expect("the run was just filed").index;
3748        Ok(self.column(index, at, ty))
3749    }
3750
3751    /// Files a call under the run that matches it, or opens a new run, and says which column it is.
3752    ///
3753    /// The run that matches is only ever the last one, because a query that goes back to an earlier
3754    /// partitioning after using a different one in between wants the operators in the order it wrote
3755    /// them. Merging the two would be a rewrite, and a rewrite over a window is the optimizer's to
3756    /// make once it knows what the sort below each one costs.
3757    fn window_run(
3758        &mut self,
3759        partition: Vec<ExprRef>,
3760        order: Vec<SortKey>,
3761        frame: WindowFrame,
3762        call: ExprRef,
3763    ) -> usize {
3764        let matches = self.windows.last().is_some_and(|run| {
3765            run.frame == frame
3766                && run.partition.len() == partition.len()
3767                && run.order.len() == order.len()
3768                && run.partition.iter().zip(&partition).all(|(&l, &r)| self.same_expr(l, r))
3769                && run.order.iter().zip(&order).all(|(l, r)| {
3770                    l.descending == r.descending
3771                        && l.nulls_first == r.nulls_first
3772                        && self.same_expr(l.expr, r.expr)
3773                })
3774        });
3775        if !matches {
3776            let index = self.fresh_index();
3777            self.windows.push(WindowRun { index, partition, order, frame, calls: Vec::new() });
3778        }
3779        // Two identical calls over one run are one column, the same way two identical aggregates
3780        // over one grouping are. `SELECT sum(i) OVER (), sum(i) OVER () + 1` totals once.
3781        let calls = self.windows.last().expect("a run is open").calls.clone();
3782        if let Some(at) = calls.iter().position(|&held| self.same_expr(held, call)) {
3783            return at;
3784        }
3785        let run = self.windows.last_mut().expect("a run is open");
3786        run.calls.push(call);
3787        run.calls.len() - 1
3788    }
3789
3790    /// Binds the arguments and everything inside the `OVER`, with the aggregate rule applied.
3791    ///
3792    /// The aggregate rule applies to all of it, which is measured rather than assumed: over a
3793    /// grouped block `sum(count(i)) OVER ()` binds and `sum(i) OVER ()` is the ungrouped column
3794    /// complaint, and the same pair of answers comes back for a partition key and for an order key.
3795    fn window_parts(
3796        &mut self,
3797        ast: &Ast,
3798        written: &WindowCall<'_>,
3799        args: &[ast::ExprRef],
3800        held: ast::WindowSpec,
3801        scope: &Scope,
3802    ) -> Result<WindowParts> {
3803        let mut bound = Vec::with_capacity(args.len());
3804        for &arg in args {
3805            let expr = self.bind_expr(ast, arg, scope)?;
3806            bound.push(self.over_aggregate(expr, scope)?);
3807        }
3808        // The keys inside the brackets are bound against the same rows the arguments are, because
3809        // that is what they sort: the call reads its frame in this order, and the frame is made of
3810        // the operator's input rows.
3811        let mut inner = Vec::new();
3812        for item in ast.order_list(written.order).to_vec() {
3813            let expr = self.bind_expr(ast, item.expr, scope)?;
3814            let expr = self.over_aggregate(expr, scope)?;
3815            inner.push(self.sort_key(expr, item));
3816        }
3817        let mut partition = Vec::new();
3818        for &key in ast.expr_list(held.partition) {
3819            let expr = self.bind_expr(ast, key, scope)?;
3820            partition.push(self.over_aggregate(expr, scope)?);
3821        }
3822        let mut order = Vec::new();
3823        for item in ast.order_list(held.order).to_vec() {
3824            let expr = self.bind_expr(ast, item.expr, scope)?;
3825            let expr = self.over_aggregate(expr, scope)?;
3826            order.push(self.sort_key(expr, item));
3827        }
3828        let frame = WindowFrame {
3829            unit: match held.unit {
3830                ast::WindowUnit::Rows => WindowUnit::Rows,
3831                ast::WindowUnit::Range => WindowUnit::Range,
3832                ast::WindowUnit::Groups => WindowUnit::Groups,
3833            },
3834            start: self.window_bound(ast, held.start, scope)?,
3835            end: self.window_bound(ast, held.end, scope)?,
3836            exclude: match held.exclude {
3837                ast::WindowExclude::NoOthers => WindowExclude::NoOthers,
3838                ast::WindowExclude::CurrentRow => WindowExclude::CurrentRow,
3839                ast::WindowExclude::Group => WindowExclude::Group,
3840                ast::WindowExclude::Ties => WindowExclude::Ties,
3841            },
3842        };
3843        Ok(WindowParts { args: bound, partition, order, inner, frame })
3844    }
3845
3846    /// One end of a frame, with its offset bound where it has one.
3847    fn window_bound(
3848        &mut self,
3849        ast: &Ast,
3850        bound: ast::WindowBound,
3851        scope: &Scope,
3852    ) -> Result<WindowBound> {
3853        let offset = |binder: &mut Self, written| {
3854            let expr = binder.bind_expr(ast, written, scope)?;
3855            binder.over_aggregate(expr, scope)
3856        };
3857        Ok(match bound {
3858            ast::WindowBound::UnboundedPreceding => WindowBound::UnboundedPreceding,
3859            ast::WindowBound::CurrentRow => WindowBound::CurrentRow,
3860            ast::WindowBound::UnboundedFollowing => WindowBound::UnboundedFollowing,
3861            ast::WindowBound::Preceding(written) => WindowBound::Preceding(offset(self, written)?),
3862            ast::WindowBound::Following(written) => WindowBound::Following(offset(self, written)?),
3863        })
3864    }
3865
3866    /// Which of this block's groups is exactly that column, if one of them is.
3867    ///
3868    /// Exactly the column and not an expression over it, because the caller is looking for the same
3869    /// value read from the aggregate instead of from the table underneath it, and `GROUP BY k + 1`
3870    /// carries the sum and not the column.
3871    fn group_of(&self, read: ColumnBinding) -> Option<usize> {
3872        self.aggregation.as_ref()?.groups.iter().position(
3873            |group| matches!(*self.plan.expr(*group), Expr::Column(binding) if binding == read),
3874        )
3875    }
3876
3877    /// The outer column a query still waiting under this grouping correlates to and the grouping
3878    /// does not carry upward, which is the column an error should name.
3879    ///
3880    /// `None` when the binding is not one of those queries, which is every ordinary case of a
3881    /// column read without a group.
3882    fn ungrouped_correlation(&self, binding: ColumnBinding) -> Option<ColumnBinding> {
3883        let pending =
3884            self.scalar_subqueries.iter().find(|pending| pending.index == binding.table)?;
3885        pending.reads.iter().copied().find(|read| self.group_of(*read).is_none())
3886    }
3887
3888    /// Whether a column is the result of a window this block is building.
3889    fn is_window_output(&self, binding: ColumnBinding) -> bool {
3890        self.windows.iter().any(|run| run.index == binding.table)
3891    }
3892
3893    /// Whether a column was resolved in an enclosing query rather than in this one.
3894    ///
3895    /// Every such read is written into the frame of the query being bound as it is resolved, and
3896    /// the frame is only handed up once that query's body is done, so while a select list or a
3897    /// `HAVING` is being bound the frame still holds everything this query read from outside it.
3898    fn is_correlation(&self, binding: ColumnBinding) -> bool {
3899        self.correlations.last().is_some_and(|frame| frame.contains(&binding))
3900    }
3901
3902    /// The name a column is written under, for an error message to say which one it means.
3903    ///
3904    /// A column of an enclosing query is not in this query's scope, so the outer scopes are searched
3905    /// as well. Without that the message names no column at all, which is how `column a column must
3906    /// appear in the GROUP BY clause` came to be a sentence this engine printed.
3907    fn name_of(&self, binding: ColumnBinding, scope: &Scope) -> String {
3908        std::iter::once(scope)
3909            .chain(self.outer_scopes.iter().rev())
3910            .flat_map(|visible| visible.columns.iter())
3911            .find(|column| column.binding == binding)
3912            .map_or_else(|| "a column".to_string(), |column| format!("\"{}\"", column.name))
3913    }
3914
3915    /// Rewrites a bound expression into one the aggregate's output can answer.
3916    ///
3917    /// A subexpression that is one of the group expressions becomes a reference to that group. A
3918    /// column that is neither grouped nor inside an aggregate is the error every SQL user has seen,
3919    /// and it is reported here because this is the first point where it is knowable.
3920    pub(crate) fn over_aggregate(&mut self, expr: ExprRef, scope: &Scope) -> Result<ExprRef> {
3921        let Some(aggregation) = self.aggregation.as_ref() else {
3922            return Ok(expr);
3923        };
3924        let index = aggregation.index;
3925        let groups = aggregation.groups.clone();
3926        for (at, group) in groups.iter().enumerate() {
3927            if self.same_expr(expr, *group) {
3928                let ty = self.plan.expr_type(*group).clone();
3929                return Ok(self.column(index, at, ty));
3930            }
3931        }
3932        let ty = self.plan.expr_type(expr).clone();
3933        match self.plan.expr(expr).clone() {
3934            Expr::Column(binding) if binding.table == index => Ok(expr),
3935            // A window result is not a column of the input and the grouping rule has nothing to say
3936            // about it. It reads the aggregate's output rather than the table's, which is why
3937            // `SELECT sum(count(i)) OVER () FROM t GROUP BY j` binds and `sum(i) OVER ()` over the
3938            // same block does not.
3939            Expr::Column(binding) if self.is_window_output(binding) => Ok(expr),
3940            // An unnest runs over the grouping too, and what it takes apart was checked against the
3941            // groups when it was bound.
3942            Expr::Column(binding) if self.is_unnest_output(binding) => Ok(expr),
3943            // The same argument for a query joined in above the grouping. `HAVING sum(x) > (SELECT
3944            // ...)` reads one row out of a query that has nothing to do with the groups, and the
3945            // join that produces it sits on top of the `Aggregate`, so what it produces is not one
3946            // of the grouped table's columns either.
3947            Expr::Column(binding) if self.joined_above.contains(&binding.table) => Ok(expr),
3948            // A column of an enclosing query is one value for the whole of this one, because this
3949            // query is evaluated once per outer row. It is a constant here in the sense the grouping
3950            // rule cares about, so it is allowed wherever a grouped column is and needs no group of
3951            // its own. The grouping rule is about columns of this query's own `FROM`, and a name
3952            // that resolved past it is not one of those. That is #995.
3953            Expr::Column(binding) if self.is_correlation(binding) => Ok(expr),
3954            // A query this block wrote that is still waiting to be joined in underneath the
3955            // grouping lands here as well, and the column the complaint should name is the one that
3956            // query correlates to rather than the column the query produces, which belongs to no
3957            // table anybody wrote. An uncorrelated query and a correlated one whose correlation is
3958            // grouped were both moved over the grouping by [`Self::lift_over_aggregate`] and are
3959            // not here, so what is left correlates to something this block neither grouped nor
3960            // aggregated, and that is an ordinary missing GROUP BY however far inside a query it
3961            // was written. That is #1032.
3962            Expr::Column(binding) => {
3963                let read = self.ungrouped_correlation(binding).unwrap_or(binding);
3964                let name = self.name_of(read, scope);
3965                Err(Error::binder(format!(
3966                    "column {name} must appear in the GROUP BY clause or must be part of an aggregate function"
3967                )))
3968            }
3969            Expr::Constant(_)
3970            | Expr::Aggregate { .. }
3971            | Expr::Window { .. }
3972            | Expr::LambdaParam(_) => Ok(expr),
3973            // The body is over the elements and the columns it captures, and a captured column is
3974            // held to the grouping rule like any other, which is the pin's error for
3975            // `list_transform(l, lambda x: x * k) ... GROUP BY l`.
3976            Expr::Lambda { table, params, body } => {
3977                let body = self.over_aggregate(body, scope)?;
3978                Ok(self.plan.add_expr(Expr::Lambda { table, params, body }, ty))
3979            }
3980            Expr::Cast { input, try_cast } => {
3981                let input = self.over_aggregate(input, scope)?;
3982                Ok(self.plan.add_expr(Expr::Cast { input, try_cast }, ty))
3983            }
3984            Expr::Compare { op, left, right } => {
3985                let left = self.over_aggregate(left, scope)?;
3986                let right = self.over_aggregate(right, scope)?;
3987                Ok(self.plan.add_expr(Expr::Compare { op, left, right }, ty))
3988            }
3989            Expr::Conjunction { op, children } => {
3990                let written = self.plan.expr_list(children).to_vec();
3991                let mut rewritten = Vec::with_capacity(written.len());
3992                for child in written {
3993                    rewritten.push(self.over_aggregate(child, scope)?);
3994                }
3995                let children = self.plan.add_expr_list(&rewritten);
3996                Ok(self.plan.add_expr(Expr::Conjunction { op, children }, ty))
3997            }
3998            Expr::Function { name, args } => {
3999                let written = self.plan.expr_list(args).to_vec();
4000                let mut rewritten = Vec::with_capacity(written.len());
4001                for arg in written {
4002                    rewritten.push(self.over_aggregate(arg, scope)?);
4003                }
4004                let args = self.plan.add_expr_list(&rewritten);
4005                Ok(self.plan.add_expr(Expr::Function { name, args }, ty))
4006            }
4007            Expr::Case { arms, otherwise } => {
4008                let written = self.plan.arm_list(arms).to_vec();
4009                let mut rewritten = Vec::with_capacity(written.len());
4010                for arm in written {
4011                    let when = self.over_aggregate(arm.when, scope)?;
4012                    let then = self.over_aggregate(arm.then, scope)?;
4013                    rewritten.push(rudb_plan::Arm { when, then });
4014                }
4015                let otherwise = match otherwise {
4016                    Some(expr) => Some(self.over_aggregate(expr, scope)?),
4017                    None => None,
4018                };
4019                let arms = self.plan.add_arms(&rewritten);
4020                Ok(self.plan.add_expr(Expr::Case { arms, otherwise }, ty))
4021            }
4022        }
4023    }
4024
4025    /// Whether two bound expressions are the same expression, by shape rather than by reference.
4026    pub(crate) fn same_expr(&self, left: ExprRef, right: ExprRef) -> bool {
4027        same_expr(&self.plan, left, right)
4028    }
4029}
4030
4031/// The named parameters a table function call was written with.
4032///
4033/// A struct rather than the fields loose, because the seventeen DuckDB has on `read_parquet` and the
4034/// thirty on `read_csv` are all going to want somewhere to go, and because a call with none of them
4035/// written should read as the default of this rather than as a bare false somewhere.
4036///
4037/// The CSV half goes on to the reader and is opened with, here and again in the executor. The
4038/// Parquet half is answered here and nothing downstream sees it, which is what `binary_as_string`
4039/// turning a BLOB column into a VARCHAR one is.
4040#[derive(Debug, Default)]
4041struct Options {
4042    /// `binary_as_string`, which says an unannotated byte array column in a Parquet file holds
4043    /// text. The ClickBench file has twenty eight of those and every query reads them as strings.
4044    binary_as_string: bool,
4045    /// `all_varchar`, which reads every column of a CSV file as text rather than sniffing a type.
4046    all_varchar: bool,
4047    /// `file_row_number`, which adds a column holding each row's ordinal inside its own file.
4048    ///
4049    /// The one Parquet option here that the executor has to act on rather than the binder, since
4050    /// the column is not in the file and has to be counted as the rows come out of it.
4051    file_row_number: bool,
4052    /// `delim`, `sep`, `quote`, `escape` and `header`, which are what the sniffer would decide.
4053    given: Given,
4054}
4055
4056impl Options {
4057    /// What these named parameters add up to.
4058    ///
4059    /// Each one was already checked against the function's list, so a name in here is a name that
4060    /// function takes and the value is already the type it wants. What is left is reading them, and
4061    /// the last one written wins, which is DuckDB's answer to `delim='|', delim=','` and was
4062    /// measured rather than assumed.
4063    fn of(written: &[(&'static str, Value, ExprRef)]) -> Result<Self> {
4064        let mut options = Self::default();
4065        for (parameter, value, _) in written {
4066            match (*parameter, value) {
4067                ("binary_as_string", Value::Boolean(on)) => options.binary_as_string = *on,
4068                ("all_varchar", Value::Boolean(on)) => options.all_varchar = *on,
4069                ("file_row_number", Value::Boolean(on)) => options.file_row_number = *on,
4070                _ => {}
4071            }
4072        }
4073        let named: Vec<(&str, Value)> =
4074            written.iter().map(|(parameter, value, _)| (*parameter, value.clone())).collect();
4075        options.given = csv_given(&named)?;
4076        Ok(options)
4077    }
4078}
4079
4080/// The one file a read names, canonical, with what the file system says about it now, or `None`
4081/// for a read of several files or of something that is not a regular file with a UTF-8 name.
4082fn mirror_target(paths: &[String]) -> Option<(String, FileStamp)> {
4083    let [path] = paths else { return None };
4084    let canonical = std::fs::canonicalize(path).ok()?;
4085    let stamp = FileStamp::of(&canonical)?;
4086    Some((canonical.to_str()?.to_string(), stamp))
4087}
4088
4089/// What was written between the two sides of a set operation.
4090#[derive(Clone, Copy)]
4091struct Operator {
4092    /// `UNION`, `EXCEPT` or `INTERSECT`.
4093    op: SetOp,
4094    /// `ALL`, `DISTINCT`, or neither, which means `DISTINCT` everywhere it is allowed.
4095    quantifier: Quantifier,
4096    /// Whether `BY NAME` was written, which only `UNION` takes.
4097    by_name: bool,
4098}
4099
4100/// One column of the result of a set operation, and where each side keeps it.
4101struct Merged {
4102    /// The name it comes out under, which is the left side's when both sides wrote it.
4103    name: String,
4104    /// What it is, after the two sides' types have met.
4105    ty: LogicalType,
4106    /// Which column of the left side it is, absent when only the right side wrote it.
4107    left: Option<usize>,
4108    /// Which column of the right side it is, absent when only the left side wrote it.
4109    right: Option<usize>,
4110}
4111
4112/// Matches the two sides of an ordinary set operation, which is first column to first column.
4113///
4114/// The names are the left side's, so `SELECT a FROM t UNION SELECT b FROM u` comes out as `a`.
4115fn match_by_position(left: &Scope, right: &Scope) -> Result<Vec<Merged>> {
4116    if left.len() != right.len() {
4117        return Err(Error::binder(format!(
4118            "Set operations can only apply to expressions with the same number of result columns, but left side has {} and right side has {}",
4119            left.len(),
4120            right.len()
4121        )));
4122    }
4123    let mut merged = Vec::with_capacity(left.len());
4124    for (at, (held, other)) in left.columns.iter().zip(&right.columns).enumerate() {
4125        merged.push(Merged {
4126            name: held.name.clone(),
4127            ty: meet(&held.ty, &other.ty)?,
4128            left: Some(at),
4129            right: Some(at),
4130        });
4131    }
4132    Ok(merged)
4133}
4134
4135/// Matches the two sides of a `UNION BY NAME`, which is by column name and not by position.
4136///
4137/// The result has the left side's columns in the order the left side wrote them, then the right
4138/// side's columns the left side did not write, in the order the right side wrote them. A column
4139/// only one side wrote is that side's type and the other side fills it with a null, which is why
4140/// nothing here needs the two sides to be the same width. Names match without regard to case, and
4141/// the spelling that comes out is the left side's, both of which follow the rest of the engine.
4142fn match_by_name(left: &Scope, right: &Scope) -> Result<Vec<Merged>> {
4143    named_once(left)?;
4144    named_once(right)?;
4145    let mut merged = Vec::with_capacity(left.len() + right.len());
4146    for (at, held) in left.columns.iter().enumerate() {
4147        let other = right.columns.iter().position(|column| same_name(&column.name, &held.name));
4148        let ty = match other {
4149            Some(other) => meet(&held.ty, &right.columns[other].ty)?,
4150            None => held.ty.clone(),
4151        };
4152        merged.push(Merged { name: held.name.clone(), ty, left: Some(at), right: other });
4153    }
4154    for (at, held) in right.columns.iter().enumerate() {
4155        if left.columns.iter().any(|column| same_name(&column.name, &held.name)) {
4156            continue;
4157        }
4158        merged.push(Merged {
4159            name: held.name.clone(),
4160            ty: held.ty.clone(),
4161            left: None,
4162            right: Some(at),
4163        });
4164    }
4165    Ok(merged)
4166}
4167
4168/// Refuses a side of a `UNION BY NAME` that wrote one name twice.
4169///
4170/// Matching by name needs the name to say which column, and a side that wrote `a` twice has no
4171/// answer to give. An ordinary union does not care, because there the position says which column.
4172/// The doubled quotes around the name are the reference binary's and not a mistake here.
4173fn named_once(scope: &Scope) -> Result<()> {
4174    for (at, held) in scope.columns.iter().enumerate() {
4175        if scope.columns[..at].iter().any(|column| same_name(&column.name, &held.name)) {
4176            return Err(Error::binder(format!(
4177                "UNION (ALL) BY NAME operation doesn't support duplicate names in the SELECT list - the name \"\"{}\"\" occurs multiple times",
4178                held.name
4179            )));
4180        }
4181    }
4182    Ok(())
4183}
4184
4185/// The one type a column of a set operation comes out as, given what each side wrote.
4186fn meet(left: &LogicalType, right: &LogicalType) -> Result<LogicalType> {
4187    left.promote(right).ok_or_else(|| {
4188        Error::binder(format!(
4189            "Cannot combine a column of type {left} with a column of type {right} in a set operation"
4190        ))
4191    })
4192}
4193
4194/// DuckDB's complaint about a named parameter that was given a null, which is a different sentence
4195/// for almost every parameter.
4196///
4197/// Three of them were measured on `v2.0.0-dev84237` and no two agree: `binary_as_string` is the
4198/// first, `all_varchar` is the second and `header` is the third. They read like three people each
4199/// writing the message in front of them, which is what they are, and a harness that compares error
4200/// text compares all of it. Anything not measured gets the first one, which is the most general of
4201/// the three.
4202fn null_parameter(function: TableFunction, parameter: &str) -> String {
4203    match parameter {
4204        "header" => format!("\"{parameter}\" expects a non-null boolean value (e.g. TRUE or 1)"),
4205        "all_varchar" => format!("{} \"{parameter}\" cannot be NULL", function.name()),
4206        _ => format!("Cannot use NULL as argument to \"{parameter}\""),
4207    }
4208}
4209
4210/// The complaint about a `REPLACE` entry that named a column the star did not stand for.
4211///
4212/// It reads like the complaint about any other name that is not there, down to the list of names
4213/// that are, because from the writer's side it is the same mistake.
4214fn missing_replacement(name: &str, input: &Scope) -> Error {
4215    Error::binder(format!(
4216        "Column \"{name}\" in REPLACE list not found in FROM clause{}",
4217        input.candidates()
4218    ))
4219}
4220
4221/// Whether a type is one `fill` can interpolate over, which is the pin's phrase for it.
4222///
4223/// The pin refuses `fill` with `FILL argument must support subtraction` and its sort key with
4224/// `FILL ordering must support subtraction`, and the two lists are not the same list, which is why
4225/// this takes a flag rather than answering one question. Every number is on both, so are `DATE`,
4226/// `TIME` and the two timestamps, and `TIME WITH TIME ZONE` is a sort key there but not an
4227/// argument. `INTERVAL` is on neither, which is worth saying out loud because an interval does
4228/// subtract: the sentence names subtraction and the rule is narrower than the sentence.
4229fn subtractable(ty: &LogicalType, ordering: bool) -> bool {
4230    if ty.is_numeric() {
4231        return true;
4232    }
4233    match ty {
4234        LogicalType::Date
4235        | LogicalType::Time
4236        | LogicalType::Timestamp
4237        | LogicalType::TimestampS
4238        | LogicalType::TimestampMs
4239        | LogicalType::TimestampNs
4240        | LogicalType::TimestampTz => true,
4241        LogicalType::TimeTz => ordering,
4242        _ => false,
4243    }
4244}
4245
4246/// Refuses a `fill` call the way the pin refuses one, in the pin's order.
4247///
4248/// The order was measured and it is not the order the clauses are written in. A `fill` over a
4249/// `VARCHAR` with no `ORDER BY` at all complains about the argument, so the argument is looked at
4250/// before the sort key is counted, and a `fill` with `DISTINCT` and no `ORDER BY` complains about
4251/// the `ORDER BY`, so the count comes before the clauses. `IGNORE NULLS` is refused here rather
4252/// than being answered as a no-op, since there is nothing for it to skip: `fill` is the one window
4253/// whose whole job is the nulls.
4254fn refuse_fill(
4255    argument: &LogicalType,
4256    order: &[LogicalType],
4257    distinct: bool,
4258    ignore_nulls: bool,
4259) -> Result<()> {
4260    if !subtractable(argument, false) {
4261        return Err(Error::binder("FILL argument must support subtraction"));
4262    }
4263    let [key] = order else {
4264        return Err(Error::binder("FILL functions must have only one ORDER BY expression"));
4265    };
4266    if !subtractable(key, true) {
4267        return Err(Error::binder("FILL ordering must support subtraction"));
4268    }
4269    if distinct {
4270        return Err(Error::binder(
4271            "DISTINCT is not implemented for the window function \"\"fill\"\"",
4272        ));
4273    }
4274    if ignore_nulls {
4275        return Err(Error::binder(
4276            "RESPECT/IGNORE NULLS is not supported for the window function \"fill\"",
4277        ));
4278    }
4279    Ok(())
4280}
4281
4282/// Resolves the call written inside an `OVER`.
4283///
4284/// Every aggregate is also a window, which is why this goes through the same signature table the
4285/// aggregate path uses, and the ranking windows go through it too because they are rows in the same
4286/// table. Everything else is one of three refusals, and all three are the reference binary's: a name
4287/// it knows as a scalar and a name it does not know at all each get their own sentence there.
4288fn window_signature(name: &str, types: &[LogicalType]) -> Result<Resolved> {
4289    match kind_of(name) {
4290        Some(FunctionKind::Aggregate | FunctionKind::Window) => resolve(name, types),
4291        Some(FunctionKind::Scalar) => {
4292            Err(Error::catalog(format!("{name} is not an aggregate function")))
4293        }
4294        None => Err(Error::catalog(format!("Aggregate Function with name {name} does not exist!"))),
4295    }
4296}
4297
4298/// Structural equality over two expressions of one plan.
4299fn same_expr(plan: &Plan, left: ExprRef, right: ExprRef) -> bool {
4300    if left == right {
4301        return true;
4302    }
4303    if plan.expr_type(left) != plan.expr_type(right) {
4304        return false;
4305    }
4306    let lists = |left, right| {
4307        let left: &[ExprRef] = plan.expr_list(left);
4308        let right: &[ExprRef] = plan.expr_list(right);
4309        left.len() == right.len()
4310            && left.iter().zip(right).all(|(&left, &right)| same_expr(plan, left, right))
4311    };
4312    match (plan.expr(left), plan.expr(right)) {
4313        (Expr::Column(left), Expr::Column(right)) => left == right,
4314        (Expr::Constant(left), Expr::Constant(right)) => plan.value(*left) == plan.value(*right),
4315        (
4316            Expr::Cast { input: left, try_cast: left_try },
4317            Expr::Cast { input: right, try_cast: right_try },
4318        ) => left_try == right_try && same_expr(plan, *left, *right),
4319        (
4320            Expr::Compare { op: left_op, left: left_a, right: left_b },
4321            Expr::Compare { op: right_op, left: right_a, right: right_b },
4322        ) => {
4323            left_op == right_op
4324                && same_expr(plan, *left_a, *right_a)
4325                && same_expr(plan, *left_b, *right_b)
4326        }
4327        (
4328            Expr::Conjunction { op: left_op, children: left_children },
4329            Expr::Conjunction { op: right_op, children: right_children },
4330        ) => left_op == right_op && lists(*left_children, *right_children),
4331        (
4332            Expr::Function { name: left_name, args: left_args },
4333            Expr::Function { name: right_name, args: right_args },
4334        ) => plan.string(*left_name) == plan.string(*right_name) && lists(*left_args, *right_args),
4335        (
4336            Expr::Aggregate {
4337                name: left_name,
4338                args: left_args,
4339                distinct: left_distinct,
4340                filter: left_filter,
4341            },
4342            Expr::Aggregate {
4343                name: right_name,
4344                args: right_args,
4345                distinct: right_distinct,
4346                filter: right_filter,
4347            },
4348        ) => {
4349            plan.string(*left_name) == plan.string(*right_name)
4350                && left_distinct == right_distinct
4351                && match (left_filter, right_filter) {
4352                    (None, None) => true,
4353                    (Some(left), Some(right)) => same_expr(plan, *left, *right),
4354                    _ => false,
4355                }
4356                && lists(*left_args, *right_args)
4357        }
4358        // The partition, the order and the frame are not compared here and do not need to be. Two
4359        // window calls are only ever asked about when they are already in the same run, which is
4360        // what agreeing on all three means.
4361        (
4362            Expr::Window {
4363                name: left_name,
4364                args: left_args,
4365                distinct: left_distinct,
4366                filter: left_filter,
4367                ignore_nulls: left_nulls,
4368                order: left_order,
4369            },
4370            Expr::Window {
4371                name: right_name,
4372                args: right_args,
4373                distinct: right_distinct,
4374                filter: right_filter,
4375                ignore_nulls: right_nulls,
4376                order: right_order,
4377            },
4378        ) => {
4379            // The keys inside the brackets are compared, unlike the ones in the `OVER`, because two
4380            // calls in the same run can still read their frame in different orders.
4381            let left_keys = plan.sort_key_list(*left_order);
4382            let right_keys = plan.sort_key_list(*right_order);
4383            plan.string(*left_name) == plan.string(*right_name)
4384                && left_distinct == right_distinct
4385                && left_nulls == right_nulls
4386                && left_keys.len() == right_keys.len()
4387                && left_keys.iter().zip(right_keys).all(|(left, right)| {
4388                    left.descending == right.descending
4389                        && left.nulls_first == right.nulls_first
4390                        && same_expr(plan, left.expr, right.expr)
4391                })
4392                && match (left_filter, right_filter) {
4393                    (None, None) => true,
4394                    (Some(left), Some(right)) => same_expr(plan, *left, *right),
4395                    _ => false,
4396                }
4397                && lists(*left_args, *right_args)
4398        }
4399        (
4400            Expr::Case { arms: left_arms, otherwise: left_otherwise },
4401            Expr::Case { arms: right_arms, otherwise: right_otherwise },
4402        ) => {
4403            let left_arms = plan.arm_list(*left_arms);
4404            let right_arms = plan.arm_list(*right_arms);
4405            left_arms.len() == right_arms.len()
4406                && left_arms.iter().zip(right_arms).all(|(left, right)| {
4407                    same_expr(plan, left.when, right.when) && same_expr(plan, left.then, right.then)
4408                })
4409                && match (left_otherwise, right_otherwise) {
4410                    (None, None) => true,
4411                    (Some(left), Some(right)) => same_expr(plan, *left, *right),
4412                    _ => false,
4413                }
4414        }
4415        _ => false,
4416    }
4417}
4418
4419/// Whether a call is to one of the ordered-set aggregates, and whether it takes the value it reads
4420/// from its one `ORDER BY` key because it does not write one.
4421fn ordered_set(name: &str, written: usize, sorted: &[ast::OrderItem]) -> (bool, bool) {
4422    let name = name.to_ascii_lowercase();
4423    let wants = match name.as_str() {
4424        "quantile_cont" | "quantile_disc" | "quantile" => 1,
4425        "mode" => 0,
4426        _ => return (false, false),
4427    };
4428    (true, sorted.len() == 1 && written == wants)
4429}
4430
4431/// A quantile fraction counted from the other end.
4432fn negated(value: &Value) -> Value {
4433    match *value {
4434        Value::Decimal { unscaled, width, scale } => {
4435            Value::Decimal { unscaled: -unscaled, width, scale }
4436        }
4437        Value::Double(share) => Value::Double(-share),
4438        Value::Float(share) => Value::Float(-share),
4439        ref whole => match share(whole) {
4440            Some(share) => Value::Double(-share),
4441            None => whole.clone(),
4442        },
4443    }
4444}
4445
4446/// A numeric fraction as a double, or `None` for a value that is not a number.
4447#[expect(
4448    clippy::cast_precision_loss,
4449    reason = "a fraction is compared with -1 and 1, which a double holds exactly"
4450)]
4451fn share(value: &Value) -> Option<f64> {
4452    Some(match *value {
4453        Value::TinyInt(v) => f64::from(v),
4454        Value::SmallInt(v) => f64::from(v),
4455        Value::Integer(v) => f64::from(v),
4456        Value::BigInt(v) => v as f64,
4457        Value::HugeInt(v) => v as f64,
4458        Value::UTinyInt(v) => f64::from(v),
4459        Value::USmallInt(v) => f64::from(v),
4460        Value::UInteger(v) => f64::from(v),
4461        Value::UBigInt(v) => v as f64,
4462        Value::UHugeInt(v) => v as f64,
4463        Value::Float(v) => f64::from(v),
4464        Value::Double(v) => v,
4465        Value::Decimal { unscaled, scale, .. } => unscaled as f64 / 10f64.powi(i32::from(scale)),
4466        _ => return None,
4467    })
4468}