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, Value};
17use rudb_functions::{
18    Columns, TableFunction, csv_fields, files, is_file, is_pattern, parquet_fields, resolve,
19    resolve_table,
20};
21use rudb_parse::ast::{self, Ast, Distinct, LiteralKind, Nulls, Order, Quantifier, SetOp};
22use rudb_parse::{NONE, parse_ast};
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())
37}
38
39/// Binds a parsed query against a catalog, with values for its parameters.
40///
41/// # Errors
42///
43/// Everything [`bind`] reports, plus an error for a parameter that was given no value.
44pub fn bind_with(ast: &Ast, catalog: &Catalog, parameters: &Parameters) -> Result<Plan> {
45    let query = match ast.statements.as_slice() {
46        [ast::Statement::Query(query)] => *query,
47        [] => return Err(Error::binder("no statement to bind")),
48        _ => return Err(Error::not_implemented("a script of more than one statement")),
49    };
50    let mut binder = Binder::with(catalog, parameters);
51    let (root, _) = binder.bind_query(ast, query)?;
52    let mut plan = binder.into_plan();
53    plan.set_root(root);
54    plan.validate()?;
55    Ok(plan)
56}
57
58/// Parses and binds one query, which is the whole front end in one call.
59///
60/// # Errors
61///
62/// Anything the parser or the binder reports.
63pub fn bind_sql(query: &str, catalog: &Catalog) -> Result<Plan> {
64    let ast = parse_ast(query)?;
65    bind(&ast, catalog)
66}
67
68/// What an aggregating select block has decided so far.
69#[derive(Debug)]
70pub(crate) struct Aggregation {
71    /// The table index the aggregate's output binds against.
72    pub(crate) index: u32,
73    /// The group expressions, over the input, which are the first output columns.
74    pub(crate) groups: Vec<ExprRef>,
75    /// The aggregate calls found so far, which follow the groups in the output.
76    pub(crate) aggregates: Vec<ExprRef>,
77}
78
79/// The state one binding run carries.
80#[derive(Debug)]
81pub(crate) struct Binder<'a> {
82    catalog: &'a Catalog,
83    /// What the parameters were given, empty for a statement that is not prepared.
84    pub(crate) parameters: &'a Parameters,
85    plan: Plan,
86    next_index: u32,
87    /// Set while a select block aggregates, which changes what a bare column means.
88    pub(crate) aggregation: Option<Aggregation>,
89    /// Set while an aggregate's own arguments are being bound, so nesting is caught.
90    pub(crate) in_aggregate: bool,
91    /// Where we are, for an error message that says which clause the writer should look at.
92    pub(crate) clause: &'static str,
93    /// The views whose bodies are open on the stack, which is what catches a cycle.
94    expanding: Vec<String>,
95}
96
97impl<'a> Binder<'a> {
98    pub(crate) fn with(catalog: &'a Catalog, parameters: &'a Parameters) -> Self {
99        Self {
100            catalog,
101            parameters,
102            plan: Plan::new(),
103            next_index: 0,
104            aggregation: None,
105            in_aggregate: false,
106            clause: "SELECT clause",
107            expanding: Vec::new(),
108        }
109    }
110
111    pub(crate) fn plan(&self) -> &Plan {
112        &self.plan
113    }
114
115    pub(crate) fn plan_mut(&mut self) -> &mut Plan {
116        &mut self.plan
117    }
118
119    pub(crate) fn into_plan(self) -> Plan {
120        self.plan
121    }
122
123    /// A table index nothing else has.
124    pub(crate) fn fresh_index(&mut self) -> u32 {
125        let index = self.next_index;
126        self.next_index += 1;
127        index
128    }
129
130    /// A reference to one column of an operator's output.
131    fn column(&mut self, index: u32, position: usize, ty: LogicalType) -> ExprRef {
132        let binding = ColumnBinding::new(index, position as u32);
133        self.plan.add_expr(Expr::Column(binding), ty)
134    }
135
136    // ---------------------------------------------------------------- queries
137
138    pub(crate) fn bind_query(
139        &mut self,
140        ast: &Ast,
141        query: ast::QueryRef,
142    ) -> Result<(NodeRef, Scope)> {
143        let written = ast.query(query);
144        match written.body {
145            ast::QueryBody::Select(select) => self.bind_select(ast, select, &written),
146            ast::QueryBody::SetOp { op, quantifier, by_name, left, right } => {
147                if by_name {
148                    return Err(Error::not_implemented("UNION BY NAME"));
149                }
150                self.bind_set_op(ast, &written, op, quantifier, left, right)
151            }
152            ast::QueryBody::Values(rows) => self.bind_values(ast, &written, rows),
153        }
154    }
155
156    /// `VALUES (1, 'a'), (2, 'b')`, as a query in its own right.
157    ///
158    /// The column names are `col0`, `col1` and so on, which is what DuckDB calls them, and the
159    /// column types are what every row in that position promotes to. Promotion is the same rule a
160    /// set operation uses, and for the same reason: a column has one type and the rows have to
161    /// agree on it before anything downstream can read the column.
162    fn bind_values(
163        &mut self,
164        ast: &Ast,
165        query: &ast::Query,
166        rows: ast::Slice,
167    ) -> Result<(NodeRef, Scope)> {
168        let written = ast.rows(rows).to_vec();
169        let Some(first) = written.first() else {
170            return Err(Error::binder("VALUES needs at least one row"));
171        };
172        let width = first.len as usize;
173        for (at, row) in written.iter().enumerate() {
174            if row.len as usize != width {
175                return Err(Error::binder(format!(
176                    "VALUES lists must all be the same length, expected {width} columns but row {} has {}",
177                    at + 1,
178                    row.len
179                )));
180            }
181        }
182        // A row of a `VALUES` cannot see a column, because there is nothing under it to see.
183        let empty = Scope::empty();
184        let previous = std::mem::replace(&mut self.clause, "VALUES clause");
185        let mut bound: Vec<Vec<ExprRef>> = Vec::with_capacity(written.len());
186        for row in &written {
187            let mut items = Vec::with_capacity(width);
188            for &expr in ast.expr_list(*row) {
189                items.push(self.bind_expr(ast, expr, &empty)?);
190            }
191            bound.push(items);
192        }
193        self.clause = previous;
194        let mut types = Vec::with_capacity(width);
195        for at in 0..width {
196            let mut ty = self.plan.expr_type(bound[0][at]).clone();
197            for row in &bound[1..] {
198                let other = self.plan.expr_type(row[at]).clone();
199                ty = ty.promote(&other).ok_or_else(|| {
200                    Error::binder(format!(
201                        "Cannot combine a value of type {ty} with a value of type {other} in column {} of a VALUES",
202                        at + 1
203                    ))
204                })?;
205            }
206            types.push(ty);
207        }
208        let mut slices = Vec::with_capacity(bound.len());
209        for row in &bound {
210            let items: Vec<ExprRef> =
211                row.iter().zip(&types).map(|(&expr, ty)| self.cast_to(expr, ty)).collect();
212            slices.push(self.plan.add_expr_list(&items));
213        }
214        let rows = self.plan.add_rows(&slices);
215        let fields: Vec<Field> = types
216            .iter()
217            .enumerate()
218            .map(|(at, ty)| Field::new(format!("col{at}"), ty.clone()))
219            .collect();
220        let columns = self.plan.add_fields(&fields);
221        let index = self.fresh_index();
222        let mut node = self.plan.add_node(Node::Values { index, columns, rows });
223        let mut scope = Scope::empty();
224        for (at, field) in fields.iter().enumerate() {
225            scope.push(Visible {
226                table: String::new(),
227                name: field.name.clone(),
228                binding: ColumnBinding::new(index, at as u32),
229                ty: field.ty.clone(),
230            });
231        }
232        let keys = self.sort_keys(ast, query, &scope, &[])?;
233        if !keys.is_empty() {
234            let keys = self.plan.add_sort_keys(&keys);
235            node = self.plan.add_node(Node::Sort { input: node, keys });
236        }
237        node = self.apply_limit(ast, query, node)?;
238        Ok((node, scope))
239    }
240
241    fn bind_set_op(
242        &mut self,
243        ast: &Ast,
244        query: &ast::Query,
245        op: SetOp,
246        quantifier: Quantifier,
247        left: ast::QueryRef,
248        right: ast::QueryRef,
249    ) -> Result<(NodeRef, Scope)> {
250        let (left_node, left_scope) = self.bind_query(ast, left)?;
251        let (right_node, right_scope) = self.bind_query(ast, right)?;
252        if left_scope.len() != right_scope.len() {
253            return Err(Error::binder(format!(
254                "Set operations can only apply to expressions with the same number of result columns, but left side has {} and right side has {}",
255                left_scope.len(),
256                right_scope.len()
257            )));
258        }
259        // Both sides have to hand back one set of types, so each column meets the other side's.
260        let mut types = Vec::with_capacity(left_scope.len());
261        for (left, right) in left_scope.columns.iter().zip(&right_scope.columns) {
262            let common = left.ty.promote(&right.ty).ok_or_else(|| {
263                Error::binder(format!(
264                    "Cannot combine a column of type {} with a column of type {} in a set operation",
265                    left.ty, right.ty
266                ))
267            })?;
268            types.push(common);
269        }
270        let left_node = self.conform(left_node, &left_scope, &types);
271        let right_node = self.conform(right_node, &right_scope, &types);
272        let index = self.fresh_index();
273        let kind = match op {
274            SetOp::Union => SetOpKind::Union,
275            SetOp::Except => SetOpKind::Except,
276            SetOp::Intersect => SetOpKind::Intersect,
277        };
278        // UNION alone removes duplicates and UNION ALL keeps them, which is the one place the
279        // unwritten quantifier and ALL disagree.
280        let all = quantifier == Quantifier::All;
281        let mut node = self.plan.add_node(Node::SetOp {
282            left: left_node,
283            right: right_node,
284            kind,
285            all,
286            index,
287        });
288        let mut scope = Scope::empty();
289        for (at, (column, ty)) in left_scope.columns.iter().zip(&types).enumerate() {
290            scope.push(Visible {
291                table: String::new(),
292                name: column.name.clone(),
293                binding: ColumnBinding::new(index, at as u32),
294                ty: ty.clone(),
295            });
296        }
297        // Above a set operation there is nothing but the output columns, so an ORDER BY term is
298        // either a position, an output name, or an expression over the output, and never needs a
299        // column projected for it that the query did not ask for.
300        let keys = self.sort_keys(ast, query, &scope, &[])?;
301        if !keys.is_empty() {
302            let keys = self.plan.add_sort_keys(&keys);
303            node = self.plan.add_node(Node::Sort { input: node, keys });
304        }
305        node = self.apply_limit(ast, query, node)?;
306        Ok((node, scope))
307    }
308
309    /// Projects one side of a set operation so that its columns have the agreed types.
310    fn conform(&mut self, node: NodeRef, scope: &Scope, types: &[LogicalType]) -> NodeRef {
311        if scope.columns.iter().zip(types).all(|(column, ty)| &column.ty == ty) {
312            return node;
313        }
314        let index = self.fresh_index();
315        let mut exprs = Vec::with_capacity(types.len());
316        let mut names = Vec::with_capacity(types.len());
317        for (column, ty) in scope.columns.iter().zip(types) {
318            let expr = self.plan.add_expr(Expr::Column(column.binding), column.ty.clone());
319            exprs.push(self.cast_to(expr, ty));
320            names.push(self.plan.intern(&column.name));
321        }
322        let exprs = self.plan.add_expr_list(&exprs);
323        let names = self.plan.add_name_list(&names);
324        self.plan.add_node(Node::Project { input: node, index, exprs, names })
325    }
326
327    // ----------------------------------------------------------------- select
328
329    fn bind_select(
330        &mut self,
331        ast: &Ast,
332        select: ast::SelectRef,
333        query: &ast::Query,
334    ) -> Result<(NodeRef, Scope)> {
335        let written = ast.select(select);
336        let (mut node, input) = self.bind_from(ast, written.from)?;
337
338        if written.filter != NONE {
339            self.clause = "WHERE clause";
340            let predicate = self.bind_expr(ast, written.filter, &input)?;
341            let predicate = self.as_boolean(predicate, "WHERE")?;
342            node = self.plan.add_node(Node::Filter { input: node, predicate });
343        }
344
345        let targets = ast.target_list(written.targets).to_vec();
346        if targets.is_empty() {
347            return Err(Error::binder("a SELECT needs at least one expression to select"));
348        }
349
350        let group_items = self.group_items(ast, &written, &targets)?;
351        let aggregating = !group_items.is_empty()
352            || written.having != NONE
353            || targets.iter().any(|target| has_aggregate(ast, target.expr));
354        if aggregating {
355            self.clause = "GROUP BY clause";
356            let mut groups = Vec::with_capacity(group_items.len());
357            for item in &group_items {
358                groups.push(self.bind_expr(ast, *item, &input)?);
359            }
360            let index = self.fresh_index();
361            self.aggregation = Some(Aggregation { index, groups, aggregates: Vec::new() });
362        }
363
364        self.clause = "SELECT clause";
365        let (mut exprs, mut names) = self.bind_targets(ast, &targets, &input)?;
366        let visible = exprs.len();
367
368        let mut having = None;
369        if written.having != NONE {
370            self.clause = "HAVING clause";
371            let predicate = self.bind_expr(ast, written.having, &input)?;
372            let predicate = self.over_aggregate(predicate, &input)?;
373            having = Some(self.as_boolean(predicate, "HAVING")?);
374        }
375
376        // The projection's index has to exist before the sort keys are built, because a key is a
377        // reference to a projected column even when the expression it sorts on is not selected.
378        let project = self.fresh_index();
379        let mut output = Scope::empty();
380        for (at, (expr, name)) in exprs.iter().zip(&names).enumerate() {
381            output.push(Visible {
382                table: String::new(),
383                name: name.clone(),
384                binding: ColumnBinding::new(project, at as u32),
385                ty: self.plan.expr_type(*expr).clone(),
386            });
387        }
388
389        self.clause = "ORDER BY clause";
390        let mut extra = Vec::new();
391        let keys = self.select_sort_keys(
392            ast, query, &input, &output, project, &mut exprs, &mut names, &mut extra,
393        )?;
394        if !extra.is_empty() && written.distinct != Distinct::No {
395            return Err(Error::binder(
396                "For SELECT DISTINCT, ORDER BY expressions must appear in the select list",
397            ));
398        }
399        let on = self.distinct_on(ast, written.distinct, &output)?;
400
401        if let Some(aggregation) = self.aggregation.take() {
402            let index = aggregation.index;
403            let groups = self.plan.add_expr_list(&aggregation.groups);
404            let aggregates = self.plan.add_expr_list(&aggregation.aggregates);
405            node = self.plan.add_node(Node::Aggregate { input: node, index, groups, aggregates });
406        }
407        if let Some(predicate) = having {
408            node = self.plan.add_node(Node::Filter { input: node, predicate });
409        }
410
411        let interned: Vec<u32> = names.iter().map(|name| self.plan.intern(name)).collect();
412        let exprs_slice = self.plan.add_expr_list(&exprs);
413        let names_slice = self.plan.add_name_list(&interned);
414        node = self.plan.add_node(Node::Project {
415            input: node,
416            index: project,
417            exprs: exprs_slice,
418            names: names_slice,
419        });
420
421        if written.distinct != Distinct::No {
422            let on = self.plan.add_expr_list(&on);
423            node = self.plan.add_node(Node::Distinct { input: node, on });
424        }
425        if !keys.is_empty() {
426            let keys = self.plan.add_sort_keys(&keys);
427            node = self.plan.add_node(Node::Sort { input: node, keys });
428        }
429        node = self.apply_limit(ast, query, node)?;
430
431        if extra.is_empty() {
432            output.columns.truncate(visible);
433            return Ok((node, output));
434        }
435        // An expression sorted on but not selected was carried this far to make the sort possible,
436        // and now it goes, because the query did not ask for it.
437        let index = self.fresh_index();
438        let mut kept = Vec::with_capacity(visible);
439        let mut kept_names = Vec::with_capacity(visible);
440        let mut scope = Scope::empty();
441        for (at, name) in names.iter().enumerate().take(visible) {
442            let ty = output.columns[at].ty.clone();
443            kept.push(self.column(project, at, ty.clone()));
444            kept_names.push(self.plan.intern(name));
445            scope.push(Visible {
446                table: String::new(),
447                name: name.clone(),
448                binding: ColumnBinding::new(index, at as u32),
449                ty,
450            });
451        }
452        let exprs = self.plan.add_expr_list(&kept);
453        let names = self.plan.add_name_list(&kept_names);
454        node = self.plan.add_node(Node::Project { input: node, index, exprs, names });
455        Ok((node, scope))
456    }
457
458    /// Binds the target list, expanding every star into the columns it stands for.
459    fn bind_targets(
460        &mut self,
461        ast: &Ast,
462        targets: &[ast::Target],
463        input: &Scope,
464    ) -> Result<(Vec<ExprRef>, Vec<String>)> {
465        let mut exprs = Vec::with_capacity(targets.len());
466        let mut names = Vec::with_capacity(targets.len());
467        for target in targets {
468            if let ast::Expr::Star { qualifier, replacements } = ast.expr(target.expr) {
469                let table = ast.name(qualifier).last().map(str::to_string);
470                let expanded: Vec<Visible> =
471                    input.star(table.as_deref())?.into_iter().cloned().collect();
472                let replacements = ast.target_list(replacements).to_vec();
473                let mut used = vec![false; replacements.len()];
474                for column in expanded {
475                    let found = replacements.iter().zip(&mut used).find(|(replacement, _)| {
476                        same_name(ast.string(replacement.alias), &column.name)
477                    });
478                    // The replacement takes the column's place and its position, and it is named the
479                    // way the replace list spells it rather than the way the table does. That only
480                    // shows when the two differ in case, and `AS EventDate` over a column called
481                    // `eventdate` is exactly the case that shows it.
482                    let (expr, name) = match found {
483                        Some((replacement, used)) => {
484                            *used = true;
485                            let expr = self.bind_expr(ast, replacement.expr, input)?;
486                            (expr, ast.string(replacement.alias).to_string())
487                        }
488                        None => (
489                            self.plan.add_expr(Expr::Column(column.binding), column.ty),
490                            column.name,
491                        ),
492                    };
493                    exprs.push(self.over_aggregate(expr, input)?);
494                    names.push(name);
495                }
496                // A replace list that named something the star did not stand for is a mistake and
497                // not a no op, and it is caught here because this is the first point at which the
498                // set of names the star stands for is known.
499                if let Some((replacement, _)) =
500                    replacements.iter().zip(&used).find(|(_, used)| !**used)
501                {
502                    return Err(missing_replacement(ast.string(replacement.alias), input));
503                }
504                continue;
505            }
506            let expr = self.bind_expr(ast, target.expr, input)?;
507            exprs.push(self.over_aggregate(expr, input)?);
508            names.push(if target.alias == NONE {
509                self.output_name(ast, target.expr, input)
510            } else {
511                ast.string(target.alias).to_string()
512            });
513        }
514        Ok((exprs, names))
515    }
516
517    /// The name an unaliased target gets.
518    ///
519    /// A bare column keeps the spelling the table was created with rather than the spelling the
520    /// query used, so `SELECT USERID FROM hits` has a column called `UserID`. Identifiers match
521    /// without regard to case and the catalog is the one that holds the case.
522    fn output_name(&self, ast: &Ast, target: ast::ExprRef, input: &Scope) -> String {
523        if let ast::Expr::Column { name } = ast.expr(target) {
524            let parts: Vec<&str> = ast.name(name).collect();
525            if let Ok(found) = input.resolve(&parts) {
526                return found.name.clone();
527            }
528        }
529        describe(ast, target)
530    }
531
532    /// The expressions a `GROUP BY` clause names, with positions and output aliases followed.
533    fn group_items(
534        &self,
535        ast: &Ast,
536        select: &ast::Select,
537        targets: &[ast::Target],
538    ) -> Result<Vec<ast::ExprRef>> {
539        if select.group_by_all {
540            // GROUP BY ALL means every target that is not itself an aggregate, which is the set
541            // that would otherwise have to be written out again by hand.
542            return Ok(targets
543                .iter()
544                .filter(|target| !has_aggregate(ast, target.expr))
545                .map(|target| target.expr)
546                .collect());
547        }
548        let mut items = Vec::new();
549        for &item in ast.expr_list(select.group_by) {
550            items.push(self.output_reference(ast, item, targets, "GROUP BY")?.unwrap_or(item));
551        }
552        Ok(items)
553    }
554
555    /// The target a `GROUP BY` or `ORDER BY` term names, when it names one by position or alias.
556    fn output_reference(
557        &self,
558        ast: &Ast,
559        item: ast::ExprRef,
560        targets: &[ast::Target],
561        clause: &str,
562    ) -> Result<Option<ast::ExprRef>> {
563        match ast.expr(item) {
564            ast::Expr::Literal { kind: LiteralKind::Number, text } => {
565                let written = ast.string(text);
566                let position: usize = written.parse().map_err(|_| {
567                    Error::binder(format!("{clause} term {written} is not a column"))
568                })?;
569                if position == 0 || position > targets.len() {
570                    return Err(Error::binder(format!(
571                        "{clause} term out of range - should be between 1 and {}",
572                        targets.len()
573                    )));
574                }
575                Ok(Some(targets[position - 1].expr))
576            }
577            ast::Expr::Column { name } => {
578                let parts: Vec<&str> = ast.name(name).collect();
579                let [written] = parts.as_slice() else { return Ok(None) };
580                let mut found = None;
581                for target in targets {
582                    if target.alias != NONE && same_name(ast.string(target.alias), written) {
583                        if found.is_some() {
584                            return Ok(None);
585                        }
586                        found = Some(target.expr);
587                    }
588                }
589                Ok(found)
590            }
591            _ => Ok(None),
592        }
593    }
594
595    // -------------------------------------------------------------- modifiers
596
597    /// Sort keys for a select, projecting anything sorted on that is not already selected.
598    #[allow(clippy::too_many_arguments)]
599    fn select_sort_keys(
600        &mut self,
601        ast: &Ast,
602        query: &ast::Query,
603        input: &Scope,
604        output: &Scope,
605        project: u32,
606        exprs: &mut Vec<ExprRef>,
607        names: &mut Vec<String>,
608        extra: &mut Vec<usize>,
609    ) -> Result<Vec<SortKey>> {
610        if query.order_by_all {
611            return Ok(self.every_column(output));
612        }
613        let items = ast.order_list(query.order_by).to_vec();
614        let mut keys = Vec::with_capacity(items.len());
615        for item in items {
616            let position = match self.output_position(ast, item.expr, output)? {
617                Some(position) => position,
618                None => {
619                    let bound = self.bind_expr(ast, item.expr, input)?;
620                    let bound = self.over_aggregate(bound, input)?;
621                    match exprs.iter().position(|&held| self.same_expr(held, bound)) {
622                        Some(position) => position,
623                        None => {
624                            exprs.push(bound);
625                            names.push(describe(ast, item.expr));
626                            extra.push(exprs.len() - 1);
627                            exprs.len() - 1
628                        }
629                    }
630                }
631            };
632            let ty = self.plan.expr_type(exprs[position]).clone();
633            let expr = self.column(project, position, ty);
634            keys.push(sort_key(expr, item));
635        }
636        Ok(keys)
637    }
638
639    /// Sort keys over an output that has nothing behind it to project, which is a set operation.
640    fn sort_keys(
641        &mut self,
642        ast: &Ast,
643        query: &ast::Query,
644        output: &Scope,
645        targets: &[ast::Target],
646    ) -> Result<Vec<SortKey>> {
647        if query.order_by_all {
648            return Ok(self.every_column(output));
649        }
650        let items = ast.order_list(query.order_by).to_vec();
651        let mut keys = Vec::with_capacity(items.len());
652        for item in items {
653            let expr = match self.output_position(ast, item.expr, output)? {
654                Some(position) => {
655                    let column = &output.columns[position];
656                    let (binding, ty) = (column.binding, column.ty.clone());
657                    self.plan.add_expr(Expr::Column(binding), ty)
658                }
659                None => {
660                    let _ = targets;
661                    self.bind_expr(ast, item.expr, output)?
662                }
663            };
664            keys.push(sort_key(expr, item));
665        }
666        Ok(keys)
667    }
668
669    fn every_column(&mut self, output: &Scope) -> Vec<SortKey> {
670        let columns: Vec<(ColumnBinding, LogicalType)> =
671            output.columns.iter().map(|column| (column.binding, column.ty.clone())).collect();
672        columns
673            .into_iter()
674            .map(|(binding, ty)| {
675                let expr = self.plan.add_expr(Expr::Column(binding), ty);
676                SortKey { expr, descending: false, nulls_first: false }
677            })
678            .collect()
679    }
680
681    /// Which output column a term names, by position or by name.
682    fn output_position(
683        &self,
684        ast: &Ast,
685        item: ast::ExprRef,
686        output: &Scope,
687    ) -> Result<Option<usize>> {
688        match ast.expr(item) {
689            ast::Expr::Literal { kind: LiteralKind::Number, text } => {
690                let written = ast.string(text);
691                if written.contains(['.', 'e', 'E']) {
692                    return Ok(None);
693                }
694                let position: usize = written.parse().map_err(|_| {
695                    Error::binder(format!("ORDER BY term {written} is not a column"))
696                })?;
697                if position == 0 || position > output.len() {
698                    return Err(Error::binder(format!(
699                        "ORDER BY term out of range - should be between 1 and {}",
700                        output.len()
701                    )));
702                }
703                Ok(Some(position - 1))
704            }
705            ast::Expr::Column { name } => {
706                let parts: Vec<&str> = ast.name(name).collect();
707                let [written] = parts.as_slice() else { return Ok(None) };
708                Ok(output.position_of(None, written))
709            }
710            _ => Ok(None),
711        }
712    }
713
714    /// The expressions a `DISTINCT ON` names, which have to be columns of the output.
715    fn distinct_on(
716        &mut self,
717        ast: &Ast,
718        distinct: Distinct,
719        output: &Scope,
720    ) -> Result<Vec<ExprRef>> {
721        let Distinct::On(items) = distinct else {
722            return Ok(Vec::new());
723        };
724        let items = ast.expr_list(items).to_vec();
725        let mut on = Vec::with_capacity(items.len());
726        for item in items {
727            let Some(position) = self.output_position(ast, item, output)? else {
728                return Err(Error::not_implemented(
729                    "DISTINCT ON an expression that is not in the select list",
730                ));
731            };
732            let column = &output.columns[position];
733            let (binding, ty) = (column.binding, column.ty.clone());
734            on.push(self.plan.add_expr(Expr::Column(binding), ty));
735        }
736        Ok(on)
737    }
738
739    fn apply_limit(&mut self, ast: &Ast, query: &ast::Query, input: NodeRef) -> Result<NodeRef> {
740        if query.limit_percent {
741            return Err(Error::not_implemented("LIMIT with a percentage"));
742        }
743        let count = self.constant_count(ast, query.limit, "LIMIT")?;
744        let offset = self.constant_count(ast, query.offset, "OFFSET")?.unwrap_or(0);
745        if count.is_none() && offset == 0 {
746            return Ok(input);
747        }
748        Ok(self.plan.add_node(Node::Limit { input, count, offset }))
749    }
750
751    /// The row count a `LIMIT` or an `OFFSET` names, which has to be a constant.
752    fn constant_count(
753        &mut self,
754        ast: &Ast,
755        written: ast::ExprRef,
756        clause: &str,
757    ) -> Result<Option<u64>> {
758        if written == NONE {
759            return Ok(None);
760        }
761        self.clause = "LIMIT clause";
762        let scope = Scope::empty();
763        let bound = self.bind_expr(ast, written, &scope)?;
764        let Expr::Constant(value) = *self.plan.expr(bound) else {
765            return Err(Error::not_implemented(format!("a {clause} that is not a constant")));
766        };
767        let count = match self.plan.value(value) {
768            Value::Null => return Ok(None),
769            Value::TinyInt(count) => i128::from(*count),
770            Value::SmallInt(count) => i128::from(*count),
771            Value::Integer(count) => i128::from(*count),
772            Value::BigInt(count) => i128::from(*count),
773            Value::HugeInt(count) => *count,
774            other => {
775                return Err(Error::binder(format!(
776                    "{clause} takes a whole number of rows, not a value of type {}",
777                    other.logical_type()
778                )));
779            }
780        };
781        u64::try_from(count)
782            .map(Some)
783            .map_err(|_| Error::binder(format!("{clause} must not be negative")))
784    }
785
786    // ------------------------------------------------------------------- from
787
788    fn bind_from(&mut self, ast: &Ast, from: ast::Slice) -> Result<(NodeRef, Scope)> {
789        let sources = ast.source_list(from).to_vec();
790        let Some((first, rest)) = sources.split_first() else {
791            // No FROM clause is one row of no columns, which is what SELECT 1 sits on. Not an
792            // empty table: an empty table would make SELECT 1 return nothing.
793            return Ok((self.plan.add_node(Node::Dummy), Scope::empty()));
794        };
795        let (mut node, mut scope) = self.bind_source(ast, *first)?;
796        for source in rest {
797            let (right, right_scope) = self.bind_source(ast, *source)?;
798            node = self.plan.add_node(Node::CrossProduct { left: node, right });
799            scope = scope.concat(right_scope);
800        }
801        Ok((node, scope))
802    }
803
804    fn bind_source(&mut self, ast: &Ast, source: ast::SourceRef) -> Result<(NodeRef, Scope)> {
805        match ast.source(source) {
806            ast::Source::Table { name, alias, columns } => {
807                self.bind_table(ast, name, alias, columns)
808            }
809            ast::Source::Function { name, args, alias, columns } => {
810                self.bind_table_function(ast, name, args, alias, columns)
811            }
812            ast::Source::Subquery { query, alias, columns } => {
813                let (node, mut scope) = self.bind_query(ast, query)?;
814                let label = if alias == NONE {
815                    "unnamed_subquery".to_string()
816                } else {
817                    ast.string(alias).to_string()
818                };
819                scope.relabel(&label);
820                if !columns.is_empty() {
821                    let names: Vec<&str> = ast.name(columns).collect();
822                    scope.rename(&names, &label)?;
823                }
824                Ok((node, scope))
825            }
826            ast::Source::Values { rows, alias, columns } => {
827                let bare = ast::Query::bare(ast::QueryBody::Values(rows));
828                let (node, mut scope) = self.bind_values(ast, &bare, rows)?;
829                let label =
830                    if alias == NONE { String::new() } else { ast.string(alias).to_string() };
831                scope.relabel(&label);
832                if !columns.is_empty() {
833                    let names: Vec<&str> = ast.name(columns).collect();
834                    scope.rename(&names, &label)?;
835                }
836                Ok((node, scope))
837            }
838            ast::Source::Join { left, right, kind, natural, on, using } => {
839                self.bind_join(ast, left, right, kind, natural, on, using)
840            }
841        }
842    }
843
844    fn bind_table(
845        &mut self,
846        ast: &Ast,
847        name: ast::Slice,
848        alias: ast::StrRef,
849        columns: ast::Slice,
850    ) -> Result<(NodeRef, Scope)> {
851        let parts: Vec<&str> = ast.name(name).collect();
852        let catalog = self.catalog;
853        // The catalog is asked first and the file is the fallback, which is the order DuckDB uses:
854        // a table really called `mixed.parquet` wins over a file of that name sitting next to it.
855        let resolved = match catalog.resolve(&parts) {
856            Ok(resolved) => resolved,
857            Err(missing) => {
858                return self.bind_replacement_scan(ast, &parts, alias, columns, missing);
859            }
860        };
861        if catalog.entry(&resolved)? == Entry::View {
862            return self.bind_view(ast, &resolved, alias, columns);
863        }
864        let table = catalog.table(&resolved)?;
865        let fields: Vec<Field> = table.columns().to_vec();
866        let label =
867            if alias == NONE { resolved.table.clone() } else { ast.string(alias).to_string() };
868        let index = self.fresh_index();
869        let mut scope = Scope::empty();
870        for (at, field) in fields.iter().enumerate() {
871            scope.push(Visible {
872                table: label.clone(),
873                name: field.name.clone(),
874                binding: ColumnBinding::new(index, at as u32),
875                ty: field.ty.clone(),
876            });
877        }
878        if !columns.is_empty() {
879            let names: Vec<&str> = ast.name(columns).collect();
880            scope.rename(&names, &label)?;
881        }
882        let catalog_name = self.plan.intern(&resolved.catalog);
883        let schema = self.plan.intern(&resolved.schema);
884        let table_name = self.plan.intern(&resolved.table);
885        let alias = self.plan.intern(&label);
886        let columns = self.plan.add_fields(&fields);
887        let node = self.plan.add_node(Node::Get {
888            catalog: catalog_name,
889            schema,
890            table: table_name,
891            alias,
892            index,
893            columns,
894        });
895        Ok((node, scope))
896    }
897
898    /// A view where a table goes, which is the body bound again right here.
899    ///
900    /// Inline and not behind a node. The view is gone by the time the plan exists, so everything
901    /// downstream sees the query somebody would have written by hand, and the column pruning that
902    /// makes `SELECT COUNT(*) FROM 'hits.parquet'` read no columns at all keeps working through
903    /// `FROM hits`. A `Node::View` would be a barrier with nothing on the other side of it.
904    ///
905    /// The scope this builds is a subquery's, right down to the name in the error message. duckdb
906    /// v1.5.1 reports a view whose column list has gone stale as `table "unnamed_subquery" has 1
907    /// columns available but 2 columns specified`, which is the sentence its subquery alias rule
908    /// produces, so a view there is a subquery with the view's name written over it afterwards.
909    fn bind_view(
910        &mut self,
911        ast: &Ast,
912        name: &QualifiedName,
913        alias: ast::StrRef,
914        columns: ast::Slice,
915    ) -> Result<(NodeRef, Scope)> {
916        let view = self.catalog.view(name)?;
917        let full = name.to_string();
918        if self.expanding.contains(&full) {
919            // Two quotes each side, which is what the binary prints. It quotes the name on the way
920            // in and then formats the quoted name into a quoted slot, so a view called `a` comes
921            // back as `""a""`. That is upstream's wart and copying it is the whole job here.
922            return Err(Error::binder(format!(
923                "infinite recursion detected: attempting to recursively bind view \"\"{}\"\"",
924                name.table
925            )));
926        }
927        let body = parse_ast(view.sql())?;
928        let query = match body.statements.as_slice() {
929            [ast::Statement::Query(query)] => *query,
930            // Only a query can have got past the binder at creation, so this is a view the catalog
931            // was handed some other way rather than anything a statement can produce.
932            _ => return Err(Error::binder(format!("view \"{}\" is not a query", name.table))),
933        };
934        self.expanding.push(full);
935        let bound = self.bind_query(&body, query);
936        self.expanding.pop();
937        let (node, mut scope) = bound?;
938
939        let aliases: Vec<&str> = view.aliases().iter().map(String::as_str).collect();
940        if !aliases.is_empty() {
941            scope.rename(&aliases, "unnamed_subquery")?;
942        }
943        let label = if alias == NONE { name.table.clone() } else { ast.string(alias).to_string() };
944        scope.relabel(&label);
945        if !columns.is_empty() {
946            let names: Vec<&str> = ast.name(columns).collect();
947            scope.rename(&names, &label)?;
948        }
949        Ok((node, scope))
950    }
951
952    /// A function call where a table goes, such as `range(10)`.
953    ///
954    /// The arguments are bound against an empty scope. A table function that can see the row on its
955    /// left is `LATERAL`, and this is not it, so a column name in here is not resolved against
956    /// whatever happens to be to the left in the `FROM` list. Letting it would mean `FROM t,
957    /// range(t.n)` quietly binding to something whose meaning depends on the order the sources were
958    /// written in.
959    fn bind_table_function(
960        &mut self,
961        ast: &Ast,
962        name: ast::Slice,
963        args: ast::Slice,
964        alias: ast::StrRef,
965        columns: ast::Slice,
966    ) -> Result<(NodeRef, Scope)> {
967        let parts: Vec<&str> = ast.name(name).collect();
968        // A qualified call names a schema, and the two schemas that exist are the ones every
969        // built-in lives in. Anything else is a name that has to fail rather than fall through to
970        // the unqualified lookup and be found somewhere it was not asked for.
971        let function_name = *parts.last().unwrap_or(&"");
972        if let Some(schema) = parts.iter().rev().nth(1) {
973            if !schema.eq_ignore_ascii_case("main") && !schema.eq_ignore_ascii_case("system") {
974                return Err(Error::catalog(format!(
975                    "Table Function with name {} does not exist!",
976                    parts.join(".")
977                )));
978            }
979        }
980        // The name is looked up before the arguments are bound so that a call of something that is
981        // not a table function says that, rather than reporting whatever is wrong with the
982        // arguments of a function that was never going to exist.
983        let Some(called) = TableFunction::lookup(function_name) else {
984            return Err(Error::catalog(format!(
985                "Table Function with name {function_name} does not exist!"
986            )));
987        };
988        let written = ast.target_list(args).to_vec();
989        let empty = Scope::empty();
990        let previous = std::mem::replace(&mut self.clause, "table function arguments");
991        let mut bound = Vec::new();
992        let mut options = Options::default();
993        for argument in written {
994            let expr = self.bind_expr(ast, argument.expr, &empty)?;
995            if argument.alias == NONE {
996                bound.push(expr);
997            } else {
998                self.named_argument(called, ast.string(argument.alias), expr, &mut options)?;
999            }
1000        }
1001        self.clause = previous;
1002
1003        // The types are what resolve the call, not the count, because `read_parquet(3)` is a
1004        // different answer from `read_parquet('3')` and only the types tell them apart.
1005        let given: Vec<LogicalType> =
1006            bound.iter().map(|&expr| self.plan.expr_type(expr).clone()).collect();
1007        let resolved = resolve_table(function_name, &given)?;
1008        let mut cast: Vec<ExprRef> = bound
1009            .iter()
1010            .zip(&resolved.arguments)
1011            .map(|(&expr, ty)| self.cast_to(expr, ty))
1012            .collect();
1013
1014        let fields = match resolved.columns {
1015            Columns::Fixed(fields) => fields,
1016            columns => {
1017                // The one argument is a pattern, and what replaces it is one constant per file it
1018                // matched. The executor is handed names rather than a pattern, so it never walks a
1019                // directory and the answer cannot change between binding a prepared statement and
1020                // running it, which is the same reason the schema is settled here.
1021                let paths = self.file_paths(cast[0], resolved.function.name())?;
1022                let first = paths.first().map_or("", String::as_str);
1023                let mut fields = match columns {
1024                    // Parquet takes the first file's footer as the answer and CSV sniffs all of
1025                    // them, which is not a choice made here. See `csv_fields`.
1026                    Columns::Csv => csv_fields(&paths)?,
1027                    _ => parquet_fields(first)?,
1028                };
1029                if options.binary_as_string {
1030                    // A byte array column with no annotation on it is a BLOB, and this is the caller
1031                    // saying that the file's writer meant text. The reader already holds both in the
1032                    // same string column and already validates the bytes, so the whole of the option
1033                    // is what the column is called from here on.
1034                    for field in &mut fields {
1035                        if field.ty == LogicalType::Blob {
1036                            field.ty = LogicalType::Varchar;
1037                        }
1038                    }
1039                }
1040                cast = paths.iter().map(|path| self.path_constant(path)).collect();
1041                fields
1042            }
1043        };
1044        let label = if alias == NONE {
1045            resolved.function.name().to_string()
1046        } else {
1047            ast.string(alias).to_string()
1048        };
1049        let names: Vec<&str> = ast.name(columns).collect();
1050        self.table_function_source(resolved.function, &cast, fields, &label, &names)
1051    }
1052
1053    /// One named parameter of a table function call, folded into what the call was given.
1054    ///
1055    /// The value has to be a constant of the type the parameter wants. It has to be constant
1056    /// because an option can decide what the columns are and the columns are settled here, and it
1057    /// has to be already of the type because there is no constant folding in front of the binder
1058    /// yet. DuckDB folds first, so `binary_as_string=1` and `binary_as_string='yes'` are both true
1059    /// there and both are turned away here, which is a gap that closes on its own the day the
1060    /// optimizer runs before the plan is finished. `binary_as_string=True` is what the ClickBench
1061    /// entry writes and is what has to work.
1062    ///
1063    /// A name that is not a parameter of this function is the binary's sentence followed by what it
1064    /// could have been. The binary puts the candidates on their own indented lines and this puts
1065    /// them on the same line, because an error is one line here.
1066    fn named_argument(
1067        &mut self,
1068        function: TableFunction,
1069        name: &str,
1070        expr: ExprRef,
1071        options: &mut Options,
1072    ) -> Result<()> {
1073        let known = function
1074            .parameters()
1075            .iter()
1076            .find(|(parameter, _)| parameter.eq_ignore_ascii_case(name));
1077        let Some((parameter, wanted)) = known else {
1078            let candidates: Vec<String> = function
1079                .parameters()
1080                .iter()
1081                .map(|(parameter, ty)| format!("{parameter} {ty}"))
1082                .collect();
1083            return Err(Error::binder(format!(
1084                "Invalid named parameter \"{name}\" for function {} Candidates: {}",
1085                function.name(),
1086                candidates.join(", ")
1087            )));
1088        };
1089        let Expr::Constant(reference) = *self.plan.expr(expr) else {
1090            return Err(Error::not_implemented(format!(
1091                "the named parameter {parameter} with a value that is not a constant"
1092            )));
1093        };
1094        let value = self.plan.value(reference).clone();
1095        if value == Value::Null {
1096            return Err(Error::binder(format!("Cannot use NULL as argument to \"{parameter}\"")));
1097        }
1098        let given = self.plan.expr_type(expr).clone();
1099        match (*parameter, value) {
1100            ("binary_as_string", Value::Boolean(on)) => options.binary_as_string = on,
1101            _ => {
1102                return Err(Error::not_implemented(format!(
1103                    "the named parameter {parameter} given a {given} where a {wanted} was wanted"
1104                )));
1105            }
1106        }
1107        Ok(())
1108    }
1109
1110    /// A file where a table name goes, which is what DuckDB calls a replacement scan.
1111    ///
1112    /// `SELECT * FROM 'hits.parquet'` is how most DuckDB queries in the wild are written, ClickBench
1113    /// among them, so this is not sugar over `read_parquet` so much as the spelling people use. The
1114    /// catalog has already been asked and has already said no, and `missing` is what it said, so a
1115    /// name that is not a file comes back with the catalog's own answer rather than with a complaint
1116    /// about files.
1117    ///
1118    /// Only a single unqualified name is a candidate. A qualified one names a schema and a schema
1119    /// that does not exist is not a path.
1120    fn bind_replacement_scan(
1121        &mut self,
1122        ast: &Ast,
1123        parts: &[&str],
1124        alias: ast::StrRef,
1125        columns: ast::Slice,
1126        missing: Error,
1127    ) -> Result<(NodeRef, Scope)> {
1128        let [path] = parts else { return Err(missing) };
1129        let path = *path;
1130        let extension = path.rsplit_once('.').map(|(_, after)| after).unwrap_or_default();
1131        let Some(function) = Self::reader_for(extension) else {
1132            if is_file(path) {
1133                // A file that is really there and that nothing here can read is a different mistake
1134                // from a name that is not a file, and DuckDB says so with both lines, the second of
1135                // which is the way out. A file with no dot in it lands here too, which is why the
1136                // test is on the extension having a reader rather than on there being an extension.
1137                return Err(Error::binder(format!(
1138                    "No extension found that is capable of reading the file \"{path}\"\n* If this \
1139                     file is a supported file format you can explicitly use the reader functions, \
1140                     such as read_csv, read_json or read_parquet"
1141                )));
1142            }
1143            return Err(missing);
1144        };
1145        // The pattern is expanded before it is known to match anything, so a name that ends in .csv
1146        // and is not there gives the reader's own message rather than the catalog's. That is
1147        // DuckDB's order and it is the helpful one: somebody who wrote a file name wants to hear
1148        // about the file.
1149        let paths = files(path)?;
1150        let first = paths.first().map_or("", String::as_str);
1151        let fields = match function {
1152            TableFunction::ReadParquet => parquet_fields(first)?,
1153            _ => csv_fields(&paths)?,
1154        };
1155        // The name the columns answer to is the file's stem, so `SELECT mixed.a FROM
1156        // 'data/mixed.parquet'` works. That is DuckDB's choice and it is the useful one, since the
1157        // alternative is a table name with a dot and a slash in it that nothing can write. A pattern
1158        // keeps the whole of what was written instead, which is DuckDB's choice too and was
1159        // measured: there is no stem to take when the name stands for a directory full of files.
1160        let label = if alias == NONE {
1161            if is_pattern(path) {
1162                path.to_string()
1163            } else {
1164                let file = path.rsplit_once('/').map_or(path, |(_, file)| file);
1165                file.rsplit_once('.').map_or(file, |(stem, _)| stem).to_string()
1166            }
1167        } else {
1168            ast.string(alias).to_string()
1169        };
1170        let arguments: Vec<ExprRef> = paths.iter().map(|path| self.path_constant(path)).collect();
1171        let names: Vec<&str> = ast.name(columns).collect();
1172        self.table_function_source(function, &arguments, fields, &label, &names)
1173    }
1174
1175    /// One file name, as a constant expression in the plan.
1176    fn path_constant(&mut self, path: &str) -> ExprRef {
1177        let value = self.plan.add_value(Value::Varchar(path.to_string()));
1178        self.plan.add_expr(Expr::Constant(value), LogicalType::Varchar)
1179    }
1180
1181    /// The table function a file with this extension is read by, and `None` for one nothing reads.
1182    ///
1183    /// Both spellings of a tab separated file go to the CSV reader, which is not a shortcut: the
1184    /// extension picks the reader and the reader sniffs the punctuation, so a `.tsv` file that holds
1185    /// commas is read as commas. That was measured rather than assumed. The comparison ignores case
1186    /// because `UP.CSV` reads in duckdb v1.4.1.
1187    fn reader_for(extension: &str) -> Option<TableFunction> {
1188        if extension.eq_ignore_ascii_case("parquet") {
1189            return Some(TableFunction::ReadParquet);
1190        }
1191        if extension.eq_ignore_ascii_case("csv") || extension.eq_ignore_ascii_case("tsv") {
1192            return Some(TableFunction::ReadCsv);
1193        }
1194        None
1195    }
1196
1197    /// The node and the scope of a table function call whose arguments and columns are settled.
1198    ///
1199    /// The half a written out call shares with a replacement scan, which is everything after the
1200    /// question of what the file is called has been answered one way or the other.
1201    fn table_function_source(
1202        &mut self,
1203        function: TableFunction,
1204        args: &[ExprRef],
1205        fields: Vec<Field>,
1206        label: &str,
1207        names: &[&str],
1208    ) -> Result<(NodeRef, Scope)> {
1209        let index = self.fresh_index();
1210        let mut scope = Scope::empty();
1211        for (at, field) in fields.iter().enumerate() {
1212            scope.push(Visible {
1213                table: label.to_string(),
1214                name: field.name.clone(),
1215                binding: ColumnBinding::new(index, at as u32),
1216                ty: field.ty.clone(),
1217            });
1218        }
1219        if !names.is_empty() {
1220            scope.rename(names, label)?;
1221        }
1222        let function = self.plan.intern(function.name());
1223        let args = self.plan.add_expr_list(args);
1224        let columns = self.plan.add_fields(&fields);
1225        let node = self.plan.add_node(Node::TableFunction { index, function, args, columns });
1226        Ok((node, scope))
1227    }
1228
1229    /// Every file a table function's file argument names, in the order they were written.
1230    ///
1231    /// Each pattern has to find at least one file of its own, which is DuckDB's rule and is why
1232    /// this expands one at a time rather than gathering everything and looking at the total. A
1233    /// list keeps its written order and its duplicates, so a file named twice is read twice, which
1234    /// was measured: the sort and the dedup belong to one pattern rather than to the list.
1235    fn file_paths(&self, expr: ExprRef, name: &str) -> Result<Vec<String>> {
1236        let mut paths = Vec::new();
1237        for pattern in self.file_patterns(expr, name)? {
1238            paths.extend(files(&pattern)?);
1239        }
1240        Ok(paths)
1241    }
1242
1243    /// The patterns a table function argument names, which have to be constants.
1244    ///
1245    /// A table function that reads a file is resolved by opening the file, and that happens here
1246    /// rather than when the query runs, because the rest of the statement cannot bind until the
1247    /// column names are known. So the path has to be something this binder can work out without
1248    /// running anything, and a literal is that. DuckDB folds a constant expression first, so
1249    /// `read_parquet('a' || '.parquet')` works there, and folding is M1 work that this will pick up
1250    /// for free once the optimizer runs before the plan is finished rather than after.
1251    ///
1252    /// One string is one pattern and a list is one pattern an item, which is DuckDB's pair of
1253    /// overloads. A null is a different sentence in each of them, both of them measured.
1254    fn file_patterns(&self, expr: ExprRef, name: &str) -> Result<Vec<String>> {
1255        let Expr::Constant(reference) = *self.plan.expr(expr) else {
1256            return Err(Error::not_implemented(
1257                "a table function file name that is not a constant",
1258            ));
1259        };
1260        match self.plan.value(reference) {
1261            Value::Varchar(path) => Ok(vec![path.clone()]),
1262            // DuckDB's own wording, which says list because its other overload takes one.
1263            Value::Null => Err(Error::parser(format!("{name} cannot take NULL list as parameter"))),
1264            Value::List { values, .. } => values
1265                .iter()
1266                .map(|value| match value {
1267                    Value::Varchar(path) => Ok(path.clone()),
1268                    _ => Err(Error::parser(format!(
1269                        "{name} reader cannot take NULL input as parameter"
1270                    ))),
1271                })
1272                .collect(),
1273            other => {
1274                Err(Error::internal(format!("a file name bound as VARCHAR arrived as {other}")))
1275            }
1276        }
1277    }
1278
1279    #[allow(clippy::too_many_arguments)]
1280    fn bind_join(
1281        &mut self,
1282        ast: &Ast,
1283        left: ast::SourceRef,
1284        right: ast::SourceRef,
1285        kind: ast::JoinKind,
1286        natural: bool,
1287        on: ast::ExprRef,
1288        using: ast::Slice,
1289    ) -> Result<(NodeRef, Scope)> {
1290        let (left_node, left_scope) = self.bind_source(ast, left)?;
1291        let (right_node, right_scope) = self.bind_source(ast, right)?;
1292        let split = left_scope.len();
1293        let mut scope = left_scope.concat(right_scope);
1294
1295        // NATURAL is USING over whatever both sides happen to call the same thing, which is why it
1296        // is resolved here and never reaches the plan as its own idea.
1297        let merged: Vec<String> = if natural {
1298            let mut names = Vec::new();
1299            for (at, column) in scope.columns.iter().enumerate().take(split) {
1300                if scope.columns[split..].iter().any(|right| same_name(&right.name, &column.name))
1301                    && !names.iter().any(|held: &String| same_name(held, &column.name))
1302                {
1303                    let _ = at;
1304                    names.push(column.name.clone());
1305                }
1306            }
1307            names
1308        } else {
1309            ast.name(using).map(str::to_string).collect()
1310        };
1311
1312        let mut conditions = Vec::new();
1313        let mut dropped = Vec::new();
1314        for name in &merged {
1315            let left_at = scope.columns[..split]
1316                .iter()
1317                .position(|column| same_name(&column.name, name))
1318                .ok_or_else(|| {
1319                    Error::binder(format!(
1320                        "column \"{name}\" specified in USING clause does not exist in left table"
1321                    ))
1322                })?;
1323            let right_at = scope.columns[split..]
1324                .iter()
1325                .position(|column| same_name(&column.name, name))
1326                .map(|at| at + split)
1327                .ok_or_else(|| {
1328                    Error::binder(format!(
1329                        "column \"{name}\" specified in USING clause does not exist in right table"
1330                    ))
1331                })?;
1332            let left_column = &scope.columns[left_at];
1333            let (left_binding, left_type) = (left_column.binding, left_column.ty.clone());
1334            let right_column = &scope.columns[right_at];
1335            let (right_binding, right_type) = (right_column.binding, right_column.ty.clone());
1336            let left_expr = self.plan.add_expr(Expr::Column(left_binding), left_type);
1337            let right_expr = self.plan.add_expr(Expr::Column(right_binding), right_type);
1338            conditions.push(self.compare(rudb_plan::CompareOp::Equal, left_expr, right_expr)?);
1339            dropped.push(right_at);
1340        }
1341        // A joined-on column appears once, so the right side's copy goes. Dropping from the back
1342        // keeps the positions of the ones still to drop correct.
1343        dropped.sort_unstable();
1344        for at in dropped.into_iter().rev() {
1345            scope.remove(at);
1346        }
1347
1348        if on != NONE {
1349            if !merged.is_empty() {
1350                return Err(Error::binder("a join cannot have both ON and USING"));
1351            }
1352            self.clause = "JOIN condition";
1353            let predicate = self.bind_expr(ast, on, &scope)?;
1354            conditions.push(self.as_boolean(predicate, "JOIN")?);
1355        }
1356
1357        if kind == ast::JoinKind::Cross {
1358            if !conditions.is_empty() {
1359                return Err(Error::binder("a CROSS JOIN cannot have a condition"));
1360            }
1361            let node =
1362                self.plan.add_node(Node::CrossProduct { left: left_node, right: right_node });
1363            return Ok((node, scope));
1364        }
1365        if conditions.is_empty() && kind == ast::JoinKind::Inner {
1366            let node =
1367                self.plan.add_node(Node::CrossProduct { left: left_node, right: right_node });
1368            return Ok((node, scope));
1369        }
1370        let kind = match kind {
1371            ast::JoinKind::Inner | ast::JoinKind::Cross => JoinKind::Inner,
1372            ast::JoinKind::Left => JoinKind::Left,
1373            ast::JoinKind::Right => JoinKind::Right,
1374            ast::JoinKind::Full => JoinKind::Full,
1375            ast::JoinKind::Semi => JoinKind::Semi,
1376            ast::JoinKind::Anti => JoinKind::Anti,
1377            ast::JoinKind::Positional => JoinKind::Positional,
1378        };
1379        let conditions = self.plan.add_expr_list(&conditions);
1380        let node =
1381            self.plan.add_node(Node::Join { left: left_node, right: right_node, kind, conditions });
1382        Ok((node, scope))
1383    }
1384
1385    // -------------------------------------------------------------- aggregates
1386
1387    /// Binds an aggregate call, records it, and hands back a reference to where its result lands.
1388    pub(crate) fn bind_aggregate(
1389        &mut self,
1390        ast: &Ast,
1391        name: &str,
1392        args: &[ast::ExprRef],
1393        distinct: bool,
1394        scope: &Scope,
1395    ) -> Result<ExprRef> {
1396        if self.in_aggregate {
1397            return Err(Error::binder(format!(
1398                "aggregate function calls cannot be nested, and {name}() is inside one"
1399            )));
1400        }
1401        if self.aggregation.is_none() {
1402            return Err(Error::binder(format!(
1403                "aggregate function calls cannot be used in the {}",
1404                self.clause
1405            )));
1406        }
1407        self.in_aggregate = true;
1408        let mut bound = Vec::with_capacity(args.len());
1409        let mut failure = None;
1410        for &arg in args {
1411            match self.bind_expr(ast, arg, scope) {
1412                Ok(expr) => bound.push(expr),
1413                Err(error) => {
1414                    failure = Some(error);
1415                    break;
1416                }
1417            }
1418        }
1419        self.in_aggregate = false;
1420        if let Some(error) = failure {
1421            return Err(error);
1422        }
1423
1424        let types: Vec<LogicalType> =
1425            bound.iter().map(|&arg| self.plan.expr_type(arg).clone()).collect();
1426        let resolved = resolve(name, &types)?;
1427        let mut cast = Vec::with_capacity(bound.len());
1428        for (arg, wanted) in bound.iter().zip(&resolved.arguments) {
1429            cast.push(self.cast_to(*arg, wanted));
1430        }
1431        let args = self.plan.add_expr_list(&cast);
1432        let name = self.plan.intern(resolved.name);
1433        let ty = resolved.returns;
1434        let call =
1435            self.plan.add_expr(Expr::Aggregate { name, args, distinct, filter: None }, ty.clone());
1436
1437        // Two identical aggregates are one column of the aggregate's output. `SELECT sum(x),
1438        // sum(x) / count(*)` computes one sum, not two.
1439        let existing = self.aggregation.as_ref().map(|held| held.aggregates.clone());
1440        let existing = existing.unwrap_or_default();
1441        let at = match existing.iter().position(|&held| self.same_expr(held, call)) {
1442            Some(at) => at,
1443            None => {
1444                let aggregation = self.aggregation.as_mut().expect("checked above");
1445                aggregation.aggregates.push(call);
1446                aggregation.aggregates.len() - 1
1447            }
1448        };
1449        let aggregation = self.aggregation.as_ref().expect("checked above");
1450        let (index, groups) = (aggregation.index, aggregation.groups.len());
1451        Ok(self.column(index, groups + at, ty))
1452    }
1453
1454    /// Rewrites a bound expression into one the aggregate's output can answer.
1455    ///
1456    /// A subexpression that is one of the group expressions becomes a reference to that group. A
1457    /// column that is neither grouped nor inside an aggregate is the error every SQL user has seen,
1458    /// and it is reported here because this is the first point where it is knowable.
1459    pub(crate) fn over_aggregate(&mut self, expr: ExprRef, scope: &Scope) -> Result<ExprRef> {
1460        let Some(aggregation) = self.aggregation.as_ref() else {
1461            return Ok(expr);
1462        };
1463        let index = aggregation.index;
1464        let groups = aggregation.groups.clone();
1465        for (at, group) in groups.iter().enumerate() {
1466            if self.same_expr(expr, *group) {
1467                let ty = self.plan.expr_type(*group).clone();
1468                return Ok(self.column(index, at, ty));
1469            }
1470        }
1471        let ty = self.plan.expr_type(expr).clone();
1472        match self.plan.expr(expr).clone() {
1473            Expr::Column(binding) if binding.table == index => Ok(expr),
1474            Expr::Column(binding) => {
1475                let name =
1476                    scope.columns.iter().find(|column| column.binding == binding).map_or_else(
1477                        || "a column".to_string(),
1478                        |column| format!("\"{}\"", column.name),
1479                    );
1480                Err(Error::binder(format!(
1481                    "column {name} must appear in the GROUP BY clause or must be part of an aggregate function"
1482                )))
1483            }
1484            Expr::Constant(_) | Expr::Aggregate { .. } => Ok(expr),
1485            Expr::Cast { input, try_cast } => {
1486                let input = self.over_aggregate(input, scope)?;
1487                Ok(self.plan.add_expr(Expr::Cast { input, try_cast }, ty))
1488            }
1489            Expr::Compare { op, left, right } => {
1490                let left = self.over_aggregate(left, scope)?;
1491                let right = self.over_aggregate(right, scope)?;
1492                Ok(self.plan.add_expr(Expr::Compare { op, left, right }, ty))
1493            }
1494            Expr::Conjunction { op, children } => {
1495                let written = self.plan.expr_list(children).to_vec();
1496                let mut rewritten = Vec::with_capacity(written.len());
1497                for child in written {
1498                    rewritten.push(self.over_aggregate(child, scope)?);
1499                }
1500                let children = self.plan.add_expr_list(&rewritten);
1501                Ok(self.plan.add_expr(Expr::Conjunction { op, children }, ty))
1502            }
1503            Expr::Function { name, args } => {
1504                let written = self.plan.expr_list(args).to_vec();
1505                let mut rewritten = Vec::with_capacity(written.len());
1506                for arg in written {
1507                    rewritten.push(self.over_aggregate(arg, scope)?);
1508                }
1509                let args = self.plan.add_expr_list(&rewritten);
1510                Ok(self.plan.add_expr(Expr::Function { name, args }, ty))
1511            }
1512            Expr::Case { arms, otherwise } => {
1513                let written = self.plan.arm_list(arms).to_vec();
1514                let mut rewritten = Vec::with_capacity(written.len());
1515                for arm in written {
1516                    let when = self.over_aggregate(arm.when, scope)?;
1517                    let then = self.over_aggregate(arm.then, scope)?;
1518                    rewritten.push(rudb_plan::Arm { when, then });
1519                }
1520                let otherwise = match otherwise {
1521                    Some(expr) => Some(self.over_aggregate(expr, scope)?),
1522                    None => None,
1523                };
1524                let arms = self.plan.add_arms(&rewritten);
1525                Ok(self.plan.add_expr(Expr::Case { arms, otherwise }, ty))
1526            }
1527        }
1528    }
1529
1530    /// Whether two bound expressions are the same expression, by shape rather than by reference.
1531    pub(crate) fn same_expr(&self, left: ExprRef, right: ExprRef) -> bool {
1532        same_expr(&self.plan, left, right)
1533    }
1534}
1535
1536/// The named parameters a table function call was written with.
1537///
1538/// One field so far. It is a struct rather than the one boolean because the seventeen DuckDB has on
1539/// `read_parquet` alone are all going to want somewhere to go, and because a call with none of them
1540/// written should read as the default of this rather than as a bare false somewhere.
1541#[derive(Debug, Default)]
1542struct Options {
1543    /// `binary_as_string`, which says an unannotated byte array column in a Parquet file holds
1544    /// text. The ClickBench file has twenty eight of those and every query reads them as strings.
1545    binary_as_string: bool,
1546}
1547
1548/// The complaint about a `REPLACE` entry that named a column the star did not stand for.
1549///
1550/// It reads like the complaint about any other name that is not there, down to the list of names
1551/// that are, because from the writer's side it is the same mistake.
1552fn missing_replacement(name: &str, input: &Scope) -> Error {
1553    Error::binder(format!(
1554        "Column \"{name}\" in REPLACE list not found in FROM clause{}",
1555        input.candidates()
1556    ))
1557}
1558
1559/// A sort key with SQL's defaults filled in.
1560///
1561/// Unstated is ascending, and unstated nulls go where the direction puts them, which is last for
1562/// ascending and first for descending. That is DuckDB's rule and it is the one that makes
1563/// `ORDER BY x DESC` the exact reverse of `ORDER BY x`.
1564fn sort_key(expr: ExprRef, item: ast::OrderItem) -> SortKey {
1565    let descending = item.order == Order::Descending;
1566    let nulls_first = match item.nulls {
1567        Nulls::First => true,
1568        Nulls::Last => false,
1569        Nulls::Unstated => descending,
1570    };
1571    SortKey { expr, descending, nulls_first }
1572}
1573
1574/// Structural equality over two expressions of one plan.
1575fn same_expr(plan: &Plan, left: ExprRef, right: ExprRef) -> bool {
1576    if left == right {
1577        return true;
1578    }
1579    if plan.expr_type(left) != plan.expr_type(right) {
1580        return false;
1581    }
1582    let lists = |left, right| {
1583        let left: &[ExprRef] = plan.expr_list(left);
1584        let right: &[ExprRef] = plan.expr_list(right);
1585        left.len() == right.len()
1586            && left.iter().zip(right).all(|(&left, &right)| same_expr(plan, left, right))
1587    };
1588    match (plan.expr(left), plan.expr(right)) {
1589        (Expr::Column(left), Expr::Column(right)) => left == right,
1590        (Expr::Constant(left), Expr::Constant(right)) => plan.value(*left) == plan.value(*right),
1591        (
1592            Expr::Cast { input: left, try_cast: left_try },
1593            Expr::Cast { input: right, try_cast: right_try },
1594        ) => left_try == right_try && same_expr(plan, *left, *right),
1595        (
1596            Expr::Compare { op: left_op, left: left_a, right: left_b },
1597            Expr::Compare { op: right_op, left: right_a, right: right_b },
1598        ) => {
1599            left_op == right_op
1600                && same_expr(plan, *left_a, *right_a)
1601                && same_expr(plan, *left_b, *right_b)
1602        }
1603        (
1604            Expr::Conjunction { op: left_op, children: left_children },
1605            Expr::Conjunction { op: right_op, children: right_children },
1606        ) => left_op == right_op && lists(*left_children, *right_children),
1607        (
1608            Expr::Function { name: left_name, args: left_args },
1609            Expr::Function { name: right_name, args: right_args },
1610        ) => plan.string(*left_name) == plan.string(*right_name) && lists(*left_args, *right_args),
1611        (
1612            Expr::Aggregate {
1613                name: left_name,
1614                args: left_args,
1615                distinct: left_distinct,
1616                filter: left_filter,
1617            },
1618            Expr::Aggregate {
1619                name: right_name,
1620                args: right_args,
1621                distinct: right_distinct,
1622                filter: right_filter,
1623            },
1624        ) => {
1625            plan.string(*left_name) == plan.string(*right_name)
1626                && left_distinct == right_distinct
1627                && match (left_filter, right_filter) {
1628                    (None, None) => true,
1629                    (Some(left), Some(right)) => same_expr(plan, *left, *right),
1630                    _ => false,
1631                }
1632                && lists(*left_args, *right_args)
1633        }
1634        (
1635            Expr::Case { arms: left_arms, otherwise: left_otherwise },
1636            Expr::Case { arms: right_arms, otherwise: right_otherwise },
1637        ) => {
1638            let left_arms = plan.arm_list(*left_arms);
1639            let right_arms = plan.arm_list(*right_arms);
1640            left_arms.len() == right_arms.len()
1641                && left_arms.iter().zip(right_arms).all(|(left, right)| {
1642                    same_expr(plan, left.when, right.when) && same_expr(plan, left.then, right.then)
1643                })
1644                && match (left_otherwise, right_otherwise) {
1645                    (None, None) => true,
1646                    (Some(left), Some(right)) => same_expr(plan, *left, *right),
1647                    _ => false,
1648                }
1649        }
1650        _ => false,
1651    }
1652}