Skip to main content

rudb_bind/
binder.rs

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