Skip to main content

rudb_bind/
binder.rs

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