Skip to main content

inillucent_sql/
bind.rs

1//! The binder: names to columns, and the bound relational tree.
2//!
3//! Invariant: the binder is a pure function of one SQL text and one immutable
4//! catalog snapshot. It resolves every name, expands every star, decides every
5//! affinity and collation, and extracts every aggregate, and it does all of
6//! that before a single page is read. A bound statement therefore says exactly
7//! what it will touch, which is what lets the authorizer run here rather than
8//! part-way through execution.
9//!
10//! Resolution order is SQLite's: FROM terms left to right, then result aliases
11//! where SQLite permits them, with a column always preferred over an alias of
12//! the same name. `rowid`, `_rowid_` and `oid` resolve only on a rowid table
13//! and only when no real column shadows them.
14
15mod cte;
16mod refusal;
17mod using;
18// The refusals live in `bind/refusal.rs` and are named here so every call
19// site reads as it did. See that file for why they moved.
20pub(crate) use refusal::{
21    ambiguous_column, compound_order_unmatched, no_query_solution, no_such_collation,
22    no_such_column, no_such_column_quoted, no_such_function, no_such_index, no_such_table,
23    order_out_of_range, schema_refused, unsupported, wrong_arguments,
24};
25mod aggregate;
26mod collation;
27mod having;
28mod json_subtype;
29mod literal;
30mod matching;
31mod order_alias;
32mod raise;
33mod rowvalue;
34mod scratch;
35
36use collation::{apply_collation, explicit_argument_collation};
37pub use collation::{comparison_rules, result_collation};
38use literal::integer_literal;
39
40pub use cte::CteBinding;
41use cte::RecursiveTarget;
42pub use scratch::BinderScratch;
43
44use inillucent_value::{Affinity, Collation};
45
46use crate::ast::{
47    self, Ast, BinaryOp, CompoundOp, Expr, ExprId, FromSource, InRhs, JoinConstraint, JoinKind,
48    Literal, NullOrder, PatternOp, SelectBody, SelectId, SortOrder, UnaryOp,
49};
50use crate::ast::{FrameBound, FrameExclude, FrameUnit};
51use crate::catalog_view::{CatalogView, ColumnInfo, TableInfo, TableKind};
52use crate::diagnostic::{ParseError, ParseErrorKind};
53use crate::function::{self, AggregateFunc, JsonFunc, MathFunc, ScalarFunc, TimeFunc, WindowFunc};
54use crate::lexer::{QuoteForm, Span};
55
56/// What an authorizer decided about one action.
57#[derive(Clone, Copy, Debug, PartialEq, Eq)]
58pub enum Authorization {
59    /// The action is allowed.
60    Allow,
61    /// The action is refused and the statement fails.
62    Deny,
63    /// The action is allowed but the column reads as NULL.
64    Ignore,
65}
66
67/// One action an authorizer is asked about.
68#[derive(Clone, Copy, Debug, PartialEq, Eq)]
69pub enum AuthAction<'a> {
70    /// Reading a column of a table.
71    Read {
72        /// The database name.
73        database: &'a [u8],
74        /// The table name.
75        table: &'a [u8],
76        /// The column name.
77        column: &'a [u8],
78    },
79    /// Running a SELECT at all.
80    Select,
81    /// Calling a function.
82    Function {
83        /// The function name.
84        name: &'a [u8],
85    },
86}
87
88/// The callback the binder consults before it binds an action.
89pub trait Authorizer {
90    /// Returns what to do about one action.
91    fn authorize(&self, action: AuthAction<'_>) -> Authorization;
92
93    /// Reports whether this authorizer allows every action unconditionally.
94    ///
95    /// A plan cache may only reuse a compiled program when re-running the
96    /// authorizer could not have changed the outcome, and the only authorizer
97    /// that is true of is one that allows everything. Defaulting to `false`
98    /// means an application's authorizer opts out by doing nothing, which is
99    /// the safe direction: a new authorizer that forgot to answer this question
100    /// gets its callbacks, it does not get silently skipped.
101    fn allows_everything(&self) -> bool {
102        false
103    }
104}
105
106/// An authorizer that allows everything, which is the default.
107#[derive(Clone, Copy, Debug, Default)]
108pub struct AllowAll;
109
110/// Where a result column came from: database, table, and column name.
111///
112/// Absent for an expression, which has no single column behind it - which is
113/// exactly what `sqlite3_column_database_name` and its two siblings report.
114pub type ColumnOrigin = (Vec<u8>, Vec<u8>, Vec<u8>);
115
116impl Authorizer for AllowAll {
117    /// Reports that nothing this authorizer is asked can be refused.
118    fn allows_everything(&self) -> bool {
119        true
120    }
121
122    /// Allows every action.
123    fn authorize(&self, _action: AuthAction<'_>) -> Authorization {
124        Authorization::Allow
125    }
126}
127
128/// What a nested query used as a value does with its rows.
129#[derive(Clone, Copy, Debug, PartialEq, Eq)]
130pub enum SubqueryKind {
131    /// `EXISTS (...)`: true when the block produced a row.
132    Exists,
133    /// `(SELECT ...)` in a value position: the first row's first column, or
134    /// NULL when it produced nothing.
135    Scalar,
136    /// The right side of an `IN`.
137    In,
138}
139
140/// A bound expression, with every name resolved and every rule decided.
141#[derive(Clone, Debug, PartialEq)]
142pub enum BoundExpr {
143    /// A NULL literal.
144    Null,
145    /// An integer literal.
146    Integer(i64),
147    /// A real literal.
148    Real(f64),
149    /// A text literal.
150    Text(Vec<u8>),
151    /// A blob literal.
152    Blob(Vec<u8>),
153    /// A bound parameter.
154    Parameter(u32),
155    /// `RAISE(...)` inside a trigger body.
156    ///
157    /// It is an expression in the grammar and it never produces a value: every
158    /// action either stops the statement or abandons the row. It is bound as one
159    /// anyway because that is where it is written - `SELECT RAISE(ABORT, 'no')
160    /// WHERE new.x < 0` puts it in a result column, guarded by a WHERE - and a
161    /// statement form would not reach that position.
162    Raise {
163        /// Which action.
164        action: crate::ast::RaiseAction,
165        /// The message, when the action takes one and it is a string literal.
166        message: Option<Vec<u8>>,
167        /// The message, when it is any other expression.
168        ///
169        /// Evaluated when the `RAISE` fires, and read as text: NULL is an empty
170        /// message and a number is its text, which is what SQLite reports. A
171        /// literal stays in `message`, so the bodies the binder synthesises for
172        /// foreign keys compile as they always have.
173        computed: Option<Box<BoundExpr>>,
174        /// Whether the abort is a foreign key's rather than a trigger's.
175        ///
176        /// The two are the same expression and report different codes, and
177        /// nothing in the SQL says which: the foreign-key bodies the binder
178        /// synthesises set it, and `RAISE` as anybody writes it does not.
179        foreign_key: bool,
180    },
181    /// A column of a FROM term.
182    Column {
183        /// Which FROM term, by position.
184        source: usize,
185        /// Which column of it, by declared position.
186        column: u16,
187        /// Which slot of the row's record holds it.
188        ///
189        /// Not the same number as the declared position once the table has a
190        /// `VIRTUAL` generated column: that column takes no slot, so every
191        /// column after it sits one place earlier in the record. Carrying both
192        /// is what keeps an index key - which names declared positions - and a
193        /// record read - which names slots - from being confused for each
194        /// other.
195        slot: u16,
196        /// The column's affinity.
197        affinity: Affinity,
198        /// The column's declared collation.
199        collation: Collation,
200    },
201    /// The rowid of a FROM term.
202    Rowid {
203        /// Which FROM term.
204        source: usize,
205    },
206    /// A call to a function an application registered.
207    ///
208    /// It carries the name and nothing else: the binder resolved that such a
209    /// function exists and takes this many arguments, and the machine looks up
210    /// what it does when it runs. A closure in a bound tree would make the tree
211    /// depend on who was holding it.
212    External {
213        /// The folded name.
214        name: Vec<u8>,
215        /// The arguments, already bound.
216        arguments: Vec<BoundExpr>,
217    },
218    /// One of a module's auxiliary functions, written `f(table, ...)`.
219    ///
220    /// It reads the module's cursor rather than a column, which is why it
221    /// names a FROM term instead of taking the table as an argument: `bm25`
222    /// wants to know which phrase matched where in the row the cursor is on,
223    /// and no column carries that.
224    VirtualFunction {
225        /// Which FROM term - the virtual table the call is about.
226        source: usize,
227        /// The function's folded name, for the module to recognise.
228        name: Vec<u8>,
229        /// The arguments after the table.
230        arguments: Vec<BoundExpr>,
231    },
232    /// A unary operator.
233    Unary {
234        /// Which operator.
235        op: UnaryOp,
236        /// The operand.
237        operand: Box<BoundExpr>,
238    },
239    /// An arithmetic, bitwise or concatenation operator.
240    Arithmetic {
241        /// Which operator.
242        op: BinaryOp,
243        /// The left operand.
244        left: Box<BoundExpr>,
245        /// The right operand.
246        right: Box<BoundExpr>,
247    },
248    /// A comparison, with the affinity and collation it applies.
249    Compare {
250        /// Which comparison.
251        op: BinaryOp,
252        /// The left operand.
253        left: Box<BoundExpr>,
254        /// The right operand.
255        right: Box<BoundExpr>,
256        /// The affinity applied to both sides before comparing.
257        affinity: Option<Affinity>,
258        /// The collation the comparison uses.
259        collation: Collation,
260    },
261    /// `AND`, with three-valued semantics.
262    And(Box<BoundExpr>, Box<BoundExpr>),
263    /// `OR`, with three-valued semantics.
264    Or(Box<BoundExpr>, Box<BoundExpr>),
265    /// `NOT`.
266    Not(Box<BoundExpr>),
267    /// `IS NULL` or `NOT NULL`.
268    IsNull {
269        /// Whether the test is for not-null.
270        negated: bool,
271        /// The operand.
272        operand: Box<BoundExpr>,
273    },
274    /// `IS` / `IS NOT`, which never yields NULL.
275    Is {
276        /// Whether `NOT` was written.
277        negated: bool,
278        /// The left operand.
279        left: Box<BoundExpr>,
280        /// The right operand.
281        right: Box<BoundExpr>,
282        /// The affinity applied before comparing.
283        affinity: Option<Affinity>,
284        /// The collation the comparison uses.
285        collation: Collation,
286    },
287    /// `BETWEEN`, kept as one node so its operand is evaluated once.
288    ///
289    /// **Each bound has its own affinity and collation (task-2088).** SQLite
290    /// codes `x BETWEEN lo AND hi` as `x >= lo AND x <= hi`, and each of those
291    /// comparisons takes its rules from its own two operands. One pair of rules
292    /// taken from `x` and `lo` ignored `hi` entirely: measured against 3.53.4,
293    /// `s BETWEEN 'a' AND 'B' COLLATE NOCASE` returned no rows where SQLite
294    /// returns `a` and `b`, and `'5' BETWEEN 1 AND CAST('9' AS INTEGER)`
295    /// answered 0 where SQLite applies the upper bound's INTEGER affinity and
296    /// answers 1.
297    Between {
298        /// Whether `NOT` was written.
299        negated: bool,
300        /// The value being tested.
301        operand: Box<BoundExpr>,
302        /// The lower bound.
303        low: Box<BoundExpr>,
304        /// The upper bound.
305        high: Box<BoundExpr>,
306        /// The affinity `operand >= low` applies.
307        low_affinity: Option<Affinity>,
308        /// The collation `operand >= low` uses.
309        low_collation: Collation,
310        /// The affinity `operand <= high` applies.
311        high_affinity: Option<Affinity>,
312        /// The collation `operand <= high` uses.
313        high_collation: Collation,
314    },
315    /// `IN` over a value list.
316    InList {
317        /// Whether `NOT` was written.
318        negated: bool,
319        /// The value being tested.
320        operand: Box<BoundExpr>,
321        /// The list.
322        list: Vec<BoundExpr>,
323        /// The affinity applied before comparing.
324        affinity: Option<Affinity>,
325        /// The collation the comparison uses.
326        collation: Collation,
327    },
328    /// `CASE`.
329    Case {
330        /// The base operand, when the form has one.
331        operand: Option<Box<BoundExpr>>,
332        /// The `WHEN`/`THEN` pairs.
333        branches: Vec<(BoundExpr, BoundExpr)>,
334        /// The `ELSE` arm.
335        otherwise: Option<Box<BoundExpr>>,
336        /// The affinity and collation each `WHEN` comparison uses in the base
337        /// form, one per branch, and empty in the searched form.
338        ///
339        /// SQLite codes `CASE x WHEN y` as `x = y` for each branch, so each
340        /// comparison takes its rules from `x` and its own `y` through
341        /// [`comparison_rules`]. One collation taken from `x` for every branch
342        /// made `CASE 'a' WHEN 'A' COLLATE NOCASE` answer 0 where 3.53.4
343        /// answers 1, and no affinity made `CASE id WHEN '1'` answer 0 on an
344        /// INTEGER column where 3.53.4 answers 1 (task-2094).
345        comparisons: Vec<(Option<Affinity>, Collation)>,
346    },
347    /// `CAST`.
348    Cast {
349        /// The operand.
350        operand: Box<BoundExpr>,
351        /// The affinity the declared type maps to.
352        affinity: Affinity,
353    },
354    /// `LIKE`, `GLOB`, `REGEXP` or `MATCH`.
355    Pattern {
356        /// Whether `NOT` was written.
357        negated: bool,
358        /// Which operator.
359        op: PatternOp,
360        /// The value being matched.
361        operand: Box<BoundExpr>,
362        /// The pattern.
363        pattern: Box<BoundExpr>,
364        /// The `ESCAPE` argument.
365        escape: Option<Box<BoundExpr>>,
366    },
367    /// A date or time function call.
368    Time {
369        /// Which function.
370        func: TimeFunc,
371        /// The arguments.
372        arguments: Vec<BoundExpr>,
373    },
374    /// A math function call.
375    ///
376    /// It is its own variant rather than a `Function` with a different tag
377    /// because a math function has no collation to carry: none of them
378    /// compares anything.
379    Math {
380        /// Which function.
381        func: MathFunc,
382        /// The arguments.
383        arguments: Vec<BoundExpr>,
384    },
385    /// A JSON function call.
386    ///
387    /// Its own variant for the reason `JsonFunc` is its own enum: every one of
388    /// these can fail, and every one of them reads the JSON mark its arguments
389    /// carry. A `Function` node promises neither.
390    Json {
391        /// Which function.
392        func: JsonFunc,
393        /// The arguments.
394        arguments: Vec<BoundExpr>,
395    },
396    /// A scalar function call.
397    Function {
398        /// Which function.
399        func: ScalarFunc,
400        /// The arguments.
401        arguments: Vec<BoundExpr>,
402        /// The collation the function's comparisons use.
403        collation: Collation,
404    },
405    /// A reference to a window value computed for this row.
406    WindowRef {
407        /// Which window call, by position in the block's list.
408        slot: usize,
409        /// The explicit collation the call's arguments carry, if one does.
410        ///
411        /// The arguments live in the block's window list, out of reach of
412        /// [`BoundExpr::explicit_collation`], so the binder copies the answer
413        /// here (task-2094). The `PARTITION BY` and the `ORDER BY` of the
414        /// window do not count: 3.53.4 answers `max(s) OVER (PARTITION BY s
415        /// COLLATE NOCASE) = 'C'` with 0.
416        collation: Option<Collation>,
417    },
418    /// A reference to an aggregate accumulator computed for this row group.
419    Aggregate {
420        /// Which accumulator, by position.
421        slot: usize,
422        /// The explicit collation the call's arguments carry, if one does.
423        ///
424        /// SQLite marks the aggregate call `EP_Collate` from its arguments, so
425        /// `max(s COLLATE NOCASE) = 'C'` compares with NOCASE. The arguments
426        /// live in the binder's aggregate list, out of reach of
427        /// [`BoundExpr::explicit_collation`], so the binder copies the answer
428        /// here (task-2094). An argument's `ORDER BY` and a `FILTER` do not
429        /// count: 3.53.4 answers `group_concat(s ORDER BY s COLLATE NOCASE) =
430        /// 'A,A,B,B,C,C'` with 0.
431        collation: Option<Collation>,
432    },
433    /// A column of the current sorter row, used after an ORDER BY sort.
434    SorterColumn {
435        /// Which column of the sorted record.
436        column: u16,
437    },
438    /// A nested query used as a value: `EXISTS`, a scalar, or the right side
439    /// of an `IN`.
440    ///
441    /// The three are one variant because they differ only in what they do with
442    /// the block's rows, and the machinery underneath - a store, filled once or
443    /// once per outer row depending on correlation - is identical. Splitting
444    /// them would mean three copies of the correlation rule, which is the part
445    /// that is easy to get wrong.
446    Subquery {
447        /// The statement-wide number of this subquery, so the compiler can
448        /// build it once even when the expression is compiled twice.
449        id: usize,
450        /// What the rows are used for.
451        kind: SubqueryKind,
452        /// Whether `NOT` was written.
453        negated: bool,
454        /// The left side of an `IN`.
455        operand: Option<Box<BoundExpr>>,
456        /// The block.
457        block: Box<BoundSelect>,
458        /// The affinity an `IN` applies to both sides before comparing.
459        affinity: Option<Affinity>,
460        /// The collation an `IN` compares with.
461        collation: Collation,
462    },
463    /// An explicit `COLLATE` on an expression that is not a column.
464    ///
465    /// The node exists so the collation survives to the comparison that uses
466    /// it. Attaching it only to columns loses `x = 'BLUE' COLLATE BINARY`,
467    /// where the operand carrying the collation is a literal - and losing it
468    /// means the column's own collation wins and the comparison quietly
469    /// answers a different question.
470    Collate {
471        /// The operand, which evaluates unchanged.
472        operand: Box<BoundExpr>,
473        /// The collation the operand forces on a comparison.
474        collation: Collation,
475    },
476}
477
478impl BoundExpr {
479    /// Returns the affinity this expression has as an operand.
480    ///
481    /// SQLite's rule: a column has its own affinity, a cast has the cast's, a
482    /// parenthesised expression has its operand's, and everything else has
483    /// none. "None" is a real answer here, not a missing one.
484    pub fn affinity(&self) -> Option<Affinity> {
485        match self {
486            BoundExpr::Column { affinity, .. } => Some(*affinity),
487            BoundExpr::Cast { affinity, .. } => Some(*affinity),
488            BoundExpr::Rowid { .. } => Some(Affinity::Integer),
489            BoundExpr::Collate { operand, .. } => operand.affinity(),
490            _ => None,
491        }
492    }
493
494    /// Returns whether the expression reads any column or aggregate.
495    pub fn is_constant(&self) -> bool {
496        match self {
497            BoundExpr::Null
498            | BoundExpr::Integer(_)
499            | BoundExpr::Real(_)
500            | BoundExpr::Text(_)
501            | BoundExpr::Blob(_)
502            | BoundExpr::Parameter(_) => true,
503            // RAISE never produces a value, so it is not constant: folding it
504            // away would delete the abort it exists to perform.
505            BoundExpr::Raise { .. }
506            | BoundExpr::Column { .. }
507            | BoundExpr::Rowid { .. }
508            | BoundExpr::External { .. }
509            | BoundExpr::VirtualFunction { .. }
510            | BoundExpr::Aggregate { .. }
511            | BoundExpr::WindowRef { .. }
512            | BoundExpr::SorterColumn { .. } => false,
513            BoundExpr::Unary { operand, .. } => operand.is_constant(),
514            BoundExpr::Collate { operand, .. } => operand.is_constant(),
515            BoundExpr::Json { arguments, .. } => arguments.iter().all(BoundExpr::is_constant),
516            BoundExpr::Not(operand) => operand.is_constant(),
517            BoundExpr::IsNull { operand, .. } => operand.is_constant(),
518            BoundExpr::Cast { operand, .. } => operand.is_constant(),
519            BoundExpr::Arithmetic { left, right, .. }
520            | BoundExpr::Compare { left, right, .. }
521            | BoundExpr::Is { left, right, .. } => left.is_constant() && right.is_constant(),
522            BoundExpr::And(left, right) | BoundExpr::Or(left, right) => {
523                left.is_constant() && right.is_constant()
524            }
525            BoundExpr::Between {
526                operand, low, high, ..
527            } => operand.is_constant() && low.is_constant() && high.is_constant(),
528            BoundExpr::InList { operand, list, .. } => {
529                operand.is_constant() && list.iter().all(BoundExpr::is_constant)
530            }
531            BoundExpr::Case {
532                operand,
533                branches,
534                otherwise,
535                ..
536            } => {
537                operand.as_ref().is_none_or(|e| e.is_constant())
538                    && branches
539                        .iter()
540                        .all(|(when, then)| when.is_constant() && then.is_constant())
541                    && otherwise.as_ref().is_none_or(|e| e.is_constant())
542            }
543            BoundExpr::Pattern {
544                operand,
545                pattern,
546                escape,
547                ..
548            } => {
549                operand.is_constant()
550                    && pattern.is_constant()
551                    && escape.as_ref().is_none_or(|e| e.is_constant())
552            }
553            BoundExpr::Function { arguments, .. }
554            | BoundExpr::Math { arguments, .. }
555            | BoundExpr::Time { arguments, .. } => arguments.iter().all(BoundExpr::is_constant),
556            // A subquery is never constant. It may read no column of the query
557            // that encloses it, but it reads the database, and hoisting it out
558            // of a loop is the compiler's decision to make from its correlation
559            // list rather than one this predicate can make.
560            BoundExpr::Subquery { .. } => false,
561        }
562    }
563
564    /// Returns which declared column positions the expression reads.
565    ///
566    /// The declared position rather than the record slot, because the callers
567    /// that ask - a generated column's dependency order, and the index-key
568    /// matcher - both think in declared positions.
569    pub fn columns_used(&self, into: &mut Vec<u16>) {
570        if let BoundExpr::Column { column, .. } = self {
571            if !into.contains(column) {
572                into.push(*column);
573            }
574        }
575        for child in self.children() {
576            child.columns_used(into);
577        }
578    }
579
580    /// Returns every sub-expression one expression holds, in no order.
581    ///
582    /// The match is exhaustive on purpose: there is no `_` arm, so a variant
583    /// added later is a compilation error here rather than a silently unvisited
584    /// subtree. That matters because the covering-index decision is built on
585    /// this walk, and a missed subtree there would be a column read from an
586    /// index that does not hold it.
587    ///
588    /// A subquery's *block* is deliberately not a child. It is a query of its
589    /// own with its own FROM terms, and the only thing about it that concerns
590    /// an enclosing term is which of that term's columns it correlates to -
591    /// which the block records separately and which the caller reads.
592    pub fn children(&self) -> Vec<&BoundExpr> {
593        match self {
594            BoundExpr::Null
595            | BoundExpr::Integer(_)
596            | BoundExpr::Real(_)
597            | BoundExpr::Text(_)
598            | BoundExpr::Blob(_)
599            | BoundExpr::Parameter(_)
600            | BoundExpr::Raise { computed: None, .. }
601            | BoundExpr::Column { .. }
602            | BoundExpr::Rowid { .. }
603            | BoundExpr::WindowRef { .. }
604            | BoundExpr::Aggregate { .. }
605            | BoundExpr::SorterColumn { .. } => Vec::new(),
606            BoundExpr::Unary { operand, .. }
607            | BoundExpr::Not(operand)
608            | BoundExpr::IsNull { operand, .. }
609            | BoundExpr::Collate { operand, .. }
610            | BoundExpr::Cast { operand, .. }
611            | BoundExpr::Raise {
612                computed: Some(operand),
613                ..
614            } => vec![operand],
615            BoundExpr::Arithmetic { left, right, .. }
616            | BoundExpr::Compare { left, right, .. }
617            | BoundExpr::Is { left, right, .. }
618            | BoundExpr::And(left, right)
619            | BoundExpr::Or(left, right) => vec![left, right],
620            BoundExpr::Between {
621                operand, low, high, ..
622            } => vec![operand, low, high],
623            BoundExpr::InList { operand, list, .. } => {
624                let mut found: Vec<&BoundExpr> = vec![operand];
625                found.extend(list.iter());
626                found
627            }
628            BoundExpr::Case {
629                operand,
630                branches,
631                otherwise,
632                ..
633            } => {
634                let mut found: Vec<&BoundExpr> = Vec::new();
635                if let Some(operand) = operand {
636                    found.push(operand);
637                }
638                for (when, then) in branches {
639                    found.push(when);
640                    found.push(then);
641                }
642                if let Some(otherwise) = otherwise {
643                    found.push(otherwise);
644                }
645                found
646            }
647            BoundExpr::Pattern {
648                operand,
649                pattern,
650                escape,
651                ..
652            } => {
653                let mut found: Vec<&BoundExpr> = vec![operand, pattern];
654                if let Some(escape) = escape {
655                    found.push(escape);
656                }
657                found
658            }
659            BoundExpr::External { arguments, .. }
660            | BoundExpr::VirtualFunction { arguments, .. }
661            | BoundExpr::Function { arguments, .. }
662            | BoundExpr::Math { arguments, .. }
663            | BoundExpr::Json { arguments, .. }
664            | BoundExpr::Time { arguments, .. } => arguments.iter().collect(),
665            BoundExpr::Subquery { operand, .. } => operand.iter().map(|held| &**held).collect(),
666        }
667    }
668
669    /// Returns every sub-expression one expression holds, mutably.
670    ///
671    /// The mirror of [`BoundExpr::children`], and exhaustive for the same
672    /// reason: a variant added later is a compilation error here rather than a
673    /// subtree some rewrite silently skips. `crate::rewrite` is the only caller
674    /// and the trigger firing point is why it exists - a body's `OLD` and `NEW`
675    /// reads are replaced by the values the row actually holds, and one missed
676    /// subtree there is a trigger that reads a NULL where a value was.
677    ///
678    /// A subquery's *block* is not a child here either, for the reason it is
679    /// not one there: it is a query of its own. `crate::rewrite` descends into
680    /// it separately, because a correlated block is exactly where a foreign
681    /// key's `NOT EXISTS (SELECT 1 FROM parent WHERE p.k = NEW.c)` keeps its
682    /// `NEW`.
683    pub fn children_mut(&mut self) -> Vec<&mut BoundExpr> {
684        match self {
685            BoundExpr::Null
686            | BoundExpr::Integer(_)
687            | BoundExpr::Real(_)
688            | BoundExpr::Text(_)
689            | BoundExpr::Blob(_)
690            | BoundExpr::Parameter(_)
691            | BoundExpr::Raise { computed: None, .. }
692            | BoundExpr::Column { .. }
693            | BoundExpr::Rowid { .. }
694            | BoundExpr::WindowRef { .. }
695            | BoundExpr::Aggregate { .. }
696            | BoundExpr::SorterColumn { .. } => Vec::new(),
697            BoundExpr::Unary { operand, .. }
698            | BoundExpr::Not(operand)
699            | BoundExpr::IsNull { operand, .. }
700            | BoundExpr::Collate { operand, .. }
701            | BoundExpr::Cast { operand, .. }
702            | BoundExpr::Raise {
703                computed: Some(operand),
704                ..
705            } => vec![operand],
706            BoundExpr::Arithmetic { left, right, .. }
707            | BoundExpr::Compare { left, right, .. }
708            | BoundExpr::Is { left, right, .. }
709            | BoundExpr::And(left, right)
710            | BoundExpr::Or(left, right) => vec![left, right],
711            BoundExpr::Between {
712                operand, low, high, ..
713            } => vec![operand, low, high],
714            BoundExpr::InList { operand, list, .. } => {
715                let mut found: Vec<&mut BoundExpr> = vec![operand];
716                found.extend(list.iter_mut());
717                found
718            }
719            BoundExpr::Case {
720                operand,
721                branches,
722                otherwise,
723                ..
724            } => {
725                let mut found: Vec<&mut BoundExpr> = Vec::new();
726                if let Some(operand) = operand {
727                    found.push(operand);
728                }
729                for (when, then) in branches {
730                    found.push(when);
731                    found.push(then);
732                }
733                if let Some(otherwise) = otherwise {
734                    found.push(otherwise);
735                }
736                found
737            }
738            BoundExpr::Pattern {
739                operand,
740                pattern,
741                escape,
742                ..
743            } => {
744                let mut found: Vec<&mut BoundExpr> = vec![operand, pattern];
745                if let Some(escape) = escape {
746                    found.push(escape);
747                }
748                found
749            }
750            BoundExpr::External { arguments, .. }
751            | BoundExpr::VirtualFunction { arguments, .. }
752            | BoundExpr::Function { arguments, .. }
753            | BoundExpr::Math { arguments, .. }
754            | BoundExpr::Json { arguments, .. }
755            | BoundExpr::Time { arguments, .. } => arguments.iter_mut().collect(),
756            BoundExpr::Subquery { operand, .. } => {
757                operand.iter_mut().map(|held| &mut **held).collect()
758            }
759        }
760    }
761
762    /// Returns the block a subquery expression holds, when it is one.
763    ///
764    /// Separate from [`BoundExpr::children_mut`] because a block is not a
765    /// sub-expression: it is a query, with its own FROM terms and its own
766    /// scope. A rewrite that treats it as one would run over the wrong tree.
767    pub fn block_mut(&mut self) -> Option<&mut BoundSelect> {
768        match self {
769            BoundExpr::Subquery { block, .. } => Some(block),
770            _ => None,
771        }
772    }
773
774    /// Records which of one FROM term's columns this expression reads.
775    ///
776    /// A correlated subquery makes the answer unknowable from here - the block
777    /// is a query of its own and could read any column of the term it
778    /// correlates to - so it is recorded as opaque rather than guessed at.
779    /// @param source - the FROM term to look for
780    /// @param into - what has been found so far
781    pub fn columns_read(&self, source: usize, into: &mut ColumnUse) {
782        match self {
783            BoundExpr::Column {
784                source: held, slot, ..
785            } if *held == source => into.add(*slot),
786            BoundExpr::Rowid { source: held } if *held == source => into.rowid = true,
787            BoundExpr::Subquery { block, .. } if block.correlations.contains(&source) => {
788                into.opaque = true;
789            }
790            BoundExpr::VirtualFunction {
791                source: held,
792                name,
793                arguments,
794            } if *held == source => into.add_function(name, arguments),
795            _ => {}
796        }
797        for child in self.children() {
798            child.columns_read(source, into);
799        }
800    }
801}
802
803/// Which of one FROM term's columns a query reads.
804#[derive(Clone, Debug, Default, PartialEq)]
805pub struct ColumnUse {
806    /// The record slots read, ascending and without duplicates.
807    pub columns: Vec<u16>,
808    /// Whether the term's rowid is read.
809    pub rowid: bool,
810    /// Whether something was met whose column reads cannot be enumerated.
811    ///
812    /// An opaque use is never coverable. It is set rather than ignored because
813    /// the whole value of this answer is that it is complete: a covering path
814    /// that turned out not to cover a column would read it from an index that
815    /// does not hold it.
816    pub opaque: bool,
817    /// The module's auxiliary functions this term is asked for, in the order
818    /// they were met, as a folded name and the arguments after the table.
819    ///
820    /// `score(t)` and `bm25(t)` read the *cursor* rather than a column, so they
821    /// are neither a column read nor an opaque one: the module can answer them
822    /// per row, and a materialised virtual scan carries the answers beside the
823    /// columns. Recorded here because this is already the answer to "what does
824    /// this term have to produce", and a second list would be a second thing
825    /// that can disagree with it.
826    /// **The arguments, not their count.** `highlight(t, 0, '[', ']')` and
827    /// `bm25(t, 10.0, 1.0)` are answered by the module from the cursor, and the
828    /// module cannot answer either without the values - which used to be
829    /// dropped here and replaced with an empty list at the call, so every
830    /// auxiliary function saw no arguments at all. Two calls of one name with
831    /// different arguments are also two different answers, so the arguments are
832    /// part of what identifies a slot rather than a detail hanging off one.
833    pub functions: Vec<(Vec<u8>, Vec<BoundExpr>)>,
834}
835
836impl ColumnUse {
837    /// Records that one slot is read.
838    pub fn add(&mut self, slot: u16) {
839        if let Err(position) = self.columns.binary_search(&slot) {
840            self.columns.insert(position, slot);
841        }
842    }
843
844    /// Records that one of the module's auxiliary functions is read.
845    ///
846    /// @param name - the function's folded name
847    /// @param arguments - the arguments after the table
848    pub fn add_function(&mut self, name: &[u8], arguments: &[BoundExpr]) {
849        let held = (name.to_vec(), arguments.to_vec());
850        if !self.functions.contains(&held) {
851            self.functions.push(held);
852        }
853    }
854
855    /// Folds another use into this one.
856    pub fn merge(&mut self, other: &ColumnUse) {
857        for slot in &other.columns {
858            self.add(*slot);
859        }
860        self.rowid |= other.rowid;
861        self.opaque |= other.opaque;
862        for (name, arguments) in &other.functions {
863            self.add_function(name, arguments);
864        }
865    }
866}
867
868impl BoundExpr {
869    /// Returns which FROM terms the expression reads.
870    pub fn sources_used(&self, into: &mut Vec<usize>) {
871        match self {
872            BoundExpr::Column { source, .. } | BoundExpr::Rowid { source }
873                if !into.contains(source) =>
874            {
875                into.push(*source);
876            }
877            BoundExpr::Unary { operand, .. }
878            | BoundExpr::Not(operand)
879            | BoundExpr::IsNull { operand, .. }
880            | BoundExpr::Collate { operand, .. }
881            | BoundExpr::Cast { operand, .. }
882            | BoundExpr::Raise {
883                computed: Some(operand),
884                ..
885            } => operand.sources_used(into),
886            BoundExpr::Arithmetic { left, right, .. }
887            | BoundExpr::Compare { left, right, .. }
888            | BoundExpr::Is { left, right, .. }
889            | BoundExpr::And(left, right)
890            | BoundExpr::Or(left, right) => {
891                left.sources_used(into);
892                right.sources_used(into);
893            }
894            BoundExpr::Between {
895                operand, low, high, ..
896            } => {
897                operand.sources_used(into);
898                low.sources_used(into);
899                high.sources_used(into);
900            }
901            BoundExpr::InList { operand, list, .. } => {
902                operand.sources_used(into);
903                for item in list {
904                    item.sources_used(into);
905                }
906            }
907            BoundExpr::Case {
908                operand,
909                branches,
910                otherwise,
911                ..
912            } => {
913                if let Some(operand) = operand {
914                    operand.sources_used(into);
915                }
916                for (when, then) in branches {
917                    when.sources_used(into);
918                    then.sources_used(into);
919                }
920                if let Some(otherwise) = otherwise {
921                    otherwise.sources_used(into);
922                }
923            }
924            BoundExpr::Pattern {
925                operand,
926                pattern,
927                escape,
928                ..
929            } => {
930                operand.sources_used(into);
931                pattern.sources_used(into);
932                if let Some(escape) = escape {
933                    escape.sources_used(into);
934                }
935            }
936            // **A JSON call and a registered function's call read their
937            // arguments' terms too.** Both were missing here, so `i.id =
938            // c.value ->> '$.id'` looked like it read no term: the planner put
939            // `i` first and sought it with a key that reads `c`, which had not
940            // been read yet, and the statement failed with "a seek key or range
941            // bound reads a column".
942            BoundExpr::Function { arguments, .. }
943            | BoundExpr::Math { arguments, .. }
944            | BoundExpr::Time { arguments, .. }
945            | BoundExpr::Json { arguments, .. }
946            | BoundExpr::External { arguments, .. } => {
947                for argument in arguments {
948                    argument.sources_used(into);
949                }
950            }
951            BoundExpr::VirtualFunction {
952                source, arguments, ..
953            } => {
954                if !into.contains(source) {
955                    into.push(*source);
956                }
957                for argument in arguments {
958                    argument.sources_used(into);
959                }
960            }
961            BoundExpr::Subquery { operand, block, .. } => {
962                if let Some(operand) = operand {
963                    operand.sources_used(into);
964                }
965                // The block's correlations are terms of the *enclosing* query,
966                // so they decide which loop level the subquery can first be
967                // evaluated at. Leaving them out put a correlated `EXISTS`
968                // before the loop whose row it reads.
969                for source in &block.correlations {
970                    if !into.contains(source) {
971                        into.push(*source);
972                    }
973                }
974            }
975            _ => {}
976        }
977    }
978}
979
980/// Where one FROM term's rows come from.
981///
982/// A subquery, a view and a CTE are all the same thing to everything below the
983/// binder: a block of SQL whose rows are materialised into an ephemeral table
984/// and then scanned like any other. Keeping them one variant is what stops the
985/// planner and the compiler growing three nearly-identical paths.
986#[derive(Clone, Debug, PartialEq)]
987pub enum SourceRows {
988    /// A real table's B-tree.
989    Table,
990    /// A nested query, materialised before the loop that scans it.
991    Subquery(Box<BoundSelect>),
992    /// A recursive CTE, filled by running its seed and then its step arms
993    /// until the step arms stop producing rows that are new.
994    Recursive(Box<RecursiveBody>),
995    /// A reference to the recursive CTE being filled, which stands for exactly
996    /// the one row the fill loop is currently on.
997    ///
998    /// It shares the enclosing CTE's store, so it is not a source that produces
999    /// rows of its own: it is a window onto the row the queue is at.
1000    RecursiveSelf {
1001        /// The statement-wide number of the CTE term whose store it reads.
1002        cte: usize,
1003    },
1004}
1005
1006/// A recursive CTE's arms, split by whether they refer to the CTE.
1007///
1008/// SQLite's rule is that the arms which do not reference the CTE are its seed
1009/// and run once, and the arms which do are its step and run against each row
1010/// the seed and earlier steps produced. Splitting them at bind time rather than
1011/// at compile time is what lets the compiler emit one queue walk rather than
1012/// re-deciding per arm what each one is.
1013#[derive(Clone, Debug, PartialEq)]
1014pub struct RecursiveBody {
1015    /// The arms that do not reference the CTE, with the operator before each.
1016    pub seeds: Vec<(CompoundOp, BoundSelect)>,
1017    /// The arms that do.
1018    pub steps: Vec<(CompoundOp, BoundSelect)>,
1019}
1020
1021/// One FROM term, bound to a table.
1022#[derive(Clone, Debug, PartialEq)]
1023pub struct BoundSource {
1024    /// The statement-wide number every bound expression refers to it by.
1025    ///
1026    /// A block's own position in its FROM clause is not enough: a correlated
1027    /// subquery reads a column of a term belonging to an enclosing block, and
1028    /// the two numbering schemes would collide. One number per FROM term in
1029    /// the whole statement means a column reference is unambiguous wherever it
1030    /// is evaluated, and the compiler can map it to the cursor that is already
1031    /// open.
1032    pub id: usize,
1033    /// Where the rows come from.
1034    pub rows: SourceRows,
1035    /// The table, view or virtual table.
1036    /// The table this source reads, shared with the catalog rather than copied.
1037    ///
1038    /// **It used to be a `TableInfo` by value.** Every table reference
1039    /// in every statement therefore deep-cloned the catalog's entry - two name
1040    /// vectors, a `ColumnInfo` per column each with its own heap fields, the
1041    /// full `CREATE` text, and an `IndexInfo` per index with its own column
1042    /// vector - which measured at 2,938 ns of `prepare.point`'s 6,093 ns
1043    /// compile, 48% of it. Every read of it still goes through `Deref`, so
1044    /// nothing above this line had to change.
1045    pub table: std::rc::Rc<TableInfo>,
1046    /// The name the query refers to it by.
1047    pub alias: Vec<u8>,
1048    /// The join that attaches it to the term before it.
1049    pub join: JoinKind,
1050    /// The join constraint, already desugared from NATURAL and USING.
1051    pub constraint: Option<BoundExpr>,
1052    /// Columns suppressed from `*` by a NATURAL or USING join.
1053    pub suppressed: Vec<u16>,
1054    /// The expressions this table's partial and expression indexes are built
1055    /// from, bound against **this term alone**.
1056    ///
1057    /// **The planner cannot bind, and the binder is the only thing that can.**
1058    /// An index's predicate and its expression keys are schema *text*; deciding
1059    /// whether a query's `WHERE` implies the predicate, or whether a `WHERE`
1060    /// names the key an index computes, is a comparison between bound
1061    /// expressions. So they are bound here and carried, in a list that is empty
1062    /// for every table with neither - which is every table the gate measures,
1063    /// and the reason this costs a compile nothing.
1064    ///
1065    /// They are bound against a scope holding only this term, never against the
1066    /// statement's whole FROM clause: a predicate reading `b` must mean *this*
1067    /// table's `b` even when another term in the query has one too. An index
1068    /// whose expressions do not bind is simply left out, which leaves the
1069    /// planner unable to choose it - the conservative answer, and the one that
1070    /// was in force while these forms were refused outright.
1071    pub index_exprs: Vec<crate::dml::BoundIndexExprs>,
1072    /// `INDEXED BY name` or `NOT INDEXED`, as the FROM term wrote it.
1073    ///
1074    /// **The planner could not see this until task-2066 section 4.4.14.** The
1075    /// parser built it, `check_index_hint` checked that an `INDEXED BY` named a
1076    /// real index, and then nothing carried it any further - so both hints were
1077    /// accepted and ignored. Measured against the pinned 3.53.4 shell on a
1078    /// 2,000 row table with an index on each of two columns:
1079    /// `SELECT count(*) FROM h NOT INDEXED WHERE a = 3 AND b = 100` planned as
1080    /// `SCAN h` there and as `SEARCH h USING INDEX h_b (b=?)` here.
1081    ///
1082    /// Both are honoured now. `INDEXED BY` was the second half, in task-2078:
1083    /// the same statement with `INDEXED BY h_a` planned as
1084    /// `SEARCH h USING INDEX h_a (a=?)` there and as `h_b` here, and it is
1085    /// held as the index's folded name rather than as the parser's name id
1086    /// because the planner has no syntax tree to look the id up in.
1087    pub index_hint: IndexChoice,
1088}
1089
1090/// Which indexes the planner may use for one FROM term.
1091///
1092/// SQLite's two clauses are opposite restrictions and the planner reads them
1093/// in one place, `choose_path`. `NOT INDEXED` takes every index away and leaves
1094/// the rowid. `INDEXED BY` takes everything *else* away, the rowid and the
1095/// table scan included: the pinned 3.53.4 shell plans
1096/// `SELECT * FROM h INDEXED BY h_a WHERE id = 5` as `SCAN h USING INDEX h_a`,
1097/// a walk of the whole index, with a rowid seek sitting unused beside it.
1098#[derive(Clone, Debug, Default, PartialEq, Eq)]
1099pub enum IndexChoice {
1100    /// Nothing was written, so every path is a candidate.
1101    #[default]
1102    Any,
1103    /// `NOT INDEXED`: no index, and the rowid is still allowed.
1104    NotIndexed,
1105    /// `INDEXED BY name`: that index and nothing else, by its folded name.
1106    Only(Vec<u8>),
1107}
1108
1109/// Refuses a block, or one of its compound arms, that forces an index which
1110/// cannot answer it.
1111///
1112/// Here rather than in the planner because this is the last point with a
1113/// `Result` to put the refusal in, and every block reaches it: a nested query,
1114/// a view body and a CTE body are all bound through `bind_select`. The block's
1115/// sources and its `ORDER BY` and `LIMIT` are attached by now, which the
1116/// nearest neighbour probe needs.
1117/// The refusal points at nothing, because SQLite's does not: the pinned 3.53.4
1118/// shell prints `no query solution` with no caret under the statement.
1119/// @param bound - the block, with its sources attached
1120fn refuse_unanswerable_hints(bound: &BoundSelect) -> Result<(), ParseError> {
1121    let arms = core::iter::once(bound).chain(bound.compounds.iter().map(|(_, arm)| arm));
1122    for arm in arms {
1123        if crate::plan::unanswerable_index_hint(arm).is_some() {
1124            return Err(no_query_solution(Span::default()));
1125        }
1126    }
1127    Ok(())
1128}
1129
1130/// One aggregate the statement computes.
1131#[derive(Clone, Debug, PartialEq)]
1132pub struct BoundAggregate {
1133    /// Which aggregate.
1134    pub func: AggregateFunc,
1135    /// The name, when the aggregate is one an application registered.
1136    pub external: Option<Vec<u8>>,
1137    /// Whether `DISTINCT` was written.
1138    pub distinct: bool,
1139    /// The arguments, or empty for `count(*)`.
1140    pub arguments: Vec<BoundExpr>,
1141    /// Whether the call was `count(*)`.
1142    pub star: bool,
1143    /// The collation the aggregate compares with.
1144    pub collation: Collation,
1145    /// The `FILTER (WHERE ...)` clause, when one was written.
1146    ///
1147    /// A row the filter does not keep is not folded in at all - it does not
1148    /// count, it does not sum and it does not appear in a `group_concat`.
1149    pub filter: Option<BoundExpr>,
1150    /// The `ORDER BY` written inside the argument list.
1151    ///
1152    /// Empty for nearly every call. It matters to the aggregates whose answer
1153    /// depends on the order the rows arrive in - `group_concat` and the JSON
1154    /// group aggregates - and SQLite accepts it on any of them.
1155    pub order_by: Vec<BoundOrderTerm>,
1156}
1157
1158/// One result column, after star expansion.
1159#[derive(Clone, Debug, PartialEq)]
1160pub struct BoundResultColumn {
1161    /// The expression.
1162    pub expr: BoundExpr,
1163    /// The name the column reports.
1164    pub name: Vec<u8>,
1165    /// The table the column came from, when it came from one.
1166    pub origin: Option<(Vec<u8>, Vec<u8>, Vec<u8>)>,
1167    /// The declared type the column reports, when it has one.
1168    pub declared_type: Vec<u8>,
1169}
1170
1171/// One `ORDER BY` term, bound.
1172#[derive(Clone, Debug, PartialEq)]
1173pub struct BoundOrderTerm {
1174    /// The expression to sort by.
1175    pub expr: BoundExpr,
1176    /// The direction.
1177    pub order: SortOrder,
1178    /// Where NULLs sort.
1179    pub nulls: NullOrder,
1180    /// The collation the sort compares with.
1181    pub collation: Collation,
1182}
1183
1184/// What a window call computes.
1185#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1186pub enum WindowCall {
1187    /// An aggregate, over the frame.
1188    Aggregate(AggregateFunc),
1189    /// One of the eleven functions that only exist in a window.
1190    Plain(WindowFunc),
1191}
1192
1193/// One end of a window frame, bound.
1194#[derive(Clone, Debug, PartialEq)]
1195pub enum BoundFrameBound {
1196    /// `UNBOUNDED PRECEDING`.
1197    UnboundedPreceding,
1198    /// `expr PRECEDING`.
1199    Preceding(BoundExpr),
1200    /// `CURRENT ROW`.
1201    CurrentRow,
1202    /// `expr FOLLOWING`.
1203    Following(BoundExpr),
1204    /// `UNBOUNDED FOLLOWING`.
1205    UnboundedFollowing,
1206}
1207
1208/// One window function call, with the window it is computed over.
1209#[derive(Clone, Debug, PartialEq)]
1210pub struct BoundWindow {
1211    /// What it computes.
1212    pub call: WindowCall,
1213    /// Whether `DISTINCT` was written, which only an aggregate may carry.
1214    pub distinct: bool,
1215    /// The collation its comparisons use.
1216    pub collation: Collation,
1217    /// The arguments.
1218    pub arguments: Vec<BoundExpr>,
1219    /// Whether the call was `count(*)`.
1220    pub star: bool,
1221    /// The `FILTER (WHERE ...)` predicate.
1222    pub filter: Option<BoundExpr>,
1223    /// `PARTITION BY`.
1224    pub partition_by: Vec<BoundExpr>,
1225    /// `ORDER BY`, which also decides the peer groups.
1226    pub order_by: Vec<BoundOrderTerm>,
1227    /// The frame unit.
1228    pub unit: FrameUnit,
1229    /// The frame start.
1230    pub start: BoundFrameBound,
1231    /// The frame end.
1232    pub end: BoundFrameBound,
1233    /// The `EXCLUDE` clause.
1234    pub exclude: FrameExclude,
1235}
1236
1237/// A bound SELECT.
1238#[derive(Clone, Debug, PartialEq)]
1239pub struct BoundSelect {
1240    /// The FROM terms, in written order.
1241    pub sources: Vec<BoundSource>,
1242    /// The `WHERE` clause.
1243    pub filter: Option<BoundExpr>,
1244    /// The `GROUP BY` terms.
1245    pub group_by: Vec<BoundExpr>,
1246    /// The `HAVING` clause.
1247    pub having: Option<BoundExpr>,
1248    /// The result columns, after star expansion.
1249    pub columns: Vec<BoundResultColumn>,
1250    /// Whether `DISTINCT` was written.
1251    pub distinct: bool,
1252    /// The `ORDER BY` terms.
1253    pub order_by: Vec<BoundOrderTerm>,
1254    /// The `LIMIT` expression.
1255    pub limit: Option<BoundExpr>,
1256    /// The `OFFSET` expression.
1257    pub offset: Option<BoundExpr>,
1258    /// The aggregates the statement computes.
1259    pub aggregates: Vec<BoundAggregate>,
1260    /// The rows of a `VALUES` arm, when the statement is one.
1261    pub values: Vec<Vec<BoundExpr>>,
1262    /// The later arms of a compound, each with the operator that joined it.
1263    ///
1264    /// When this is not empty, the `order_by`, `limit` and `offset` on *this*
1265    /// block belong to the compound as a whole rather than to the first arm -
1266    /// which is exactly SQLite's rule, since an arm of a compound may not
1267    /// carry its own. `distinct` stays the first arm's own.
1268    pub compounds: Vec<(CompoundOp, BoundSelect)>,
1269    /// The window calls the block computes, in the order they were bound.
1270    pub windows: Vec<BoundWindow>,
1271    /// The FROM terms belonging to an enclosing block that this one reads.
1272    ///
1273    /// A block with an empty list is uncorrelated and can be evaluated once; a
1274    /// block with a non-empty one has to be re-evaluated for each row of the
1275    /// outermost term it names. The compiler needs no more than that, because
1276    /// the outer cursors are still open and positioned when the child runs.
1277    pub correlations: Vec<usize>,
1278}
1279
1280impl BoundSelect {
1281    /// Returns which of one FROM term's columns this block reads.
1282    ///
1283    /// Every expression the block holds is visited, because the question this
1284    /// answers is whether an index carries everything the query needs from a
1285    /// table - and a single missed expression would be a column read from an
1286    /// index that does not hold it. The walk is therefore written to be
1287    /// obviously complete rather than briefly: every field of the block that
1288    /// can hold an expression is named here, and `BoundExpr::children` is
1289    /// exhaustive so a new expression variant is a compilation error rather
1290    /// than an unvisited subtree.
1291    ///
1292    /// Anything it cannot enumerate marks the answer opaque, and an opaque
1293    /// answer is never coverable. A nested block that correlates to this term
1294    /// is the case that matters: it is a query of its own and could read any
1295    /// column of the term it correlates to.
1296    /// @param source - the statement-wide number of the FROM term
1297    pub fn columns_read(&self, source: usize) -> ColumnUse {
1298        let mut used = ColumnUse::default();
1299        self.gather_columns(source, &mut used);
1300        used
1301    }
1302
1303    /// Adds this block's reads of one FROM term, and its compounds' reads.
1304    fn gather_columns(&self, source: usize, into: &mut ColumnUse) {
1305        for term in &self.sources {
1306            if let Some(constraint) = &term.constraint {
1307                constraint.columns_read(source, into);
1308            }
1309            match &term.rows {
1310                SourceRows::Table | SourceRows::RecursiveSelf { .. } => {}
1311                SourceRows::Subquery(block) => {
1312                    if block.correlations.contains(&source) {
1313                        into.opaque = true;
1314                    }
1315                }
1316                SourceRows::Recursive(body) => {
1317                    for (_, arm) in body.seeds.iter().chain(body.steps.iter()) {
1318                        if arm.correlations.contains(&source) {
1319                            into.opaque = true;
1320                        }
1321                    }
1322                }
1323            }
1324        }
1325        for expr in self.filter.iter().chain(self.having.iter()) {
1326            expr.columns_read(source, into);
1327        }
1328        for expr in self
1329            .group_by
1330            .iter()
1331            .chain(self.limit.iter())
1332            .chain(self.offset.iter())
1333        {
1334            expr.columns_read(source, into);
1335        }
1336        for column in &self.columns {
1337            column.expr.columns_read(source, into);
1338        }
1339        for term in &self.order_by {
1340            term.expr.columns_read(source, into);
1341        }
1342        for aggregate in &self.aggregates {
1343            for argument in &aggregate.arguments {
1344                argument.columns_read(source, into);
1345            }
1346            // The call's own `FILTER` and `ORDER BY` read the row too. Missing
1347            // them here would let a covering index be chosen that does not hold
1348            // a column the filter tests, which reads as a wrong answer rather
1349            // than as a refusal.
1350            if let Some(filter) = &aggregate.filter {
1351                filter.columns_read(source, into);
1352            }
1353            for term in &aggregate.order_by {
1354                term.expr.columns_read(source, into);
1355            }
1356        }
1357        for window in &self.windows {
1358            for argument in &window.arguments {
1359                argument.columns_read(source, into);
1360            }
1361            if let Some(filter) = &window.filter {
1362                filter.columns_read(source, into);
1363            }
1364            for expr in &window.partition_by {
1365                expr.columns_read(source, into);
1366            }
1367            for term in &window.order_by {
1368                term.expr.columns_read(source, into);
1369            }
1370            // A frame bound is an expression when it is `n PRECEDING`, and a
1371            // window over a covering index would read it like anything else.
1372            for bound in [&window.start, &window.end] {
1373                if let BoundFrameBound::Preceding(expr) | BoundFrameBound::Following(expr) = bound {
1374                    expr.columns_read(source, into);
1375                }
1376            }
1377        }
1378        for row in &self.values {
1379            for expr in row {
1380                expr.columns_read(source, into);
1381            }
1382        }
1383        for (_, arm) in &self.compounds {
1384            arm.gather_columns(source, into);
1385        }
1386    }
1387
1388    /// Returns whether the statement aggregates its input into one group or
1389    /// into groups.
1390    pub fn is_aggregate(&self) -> bool {
1391        !self.aggregates.is_empty() || !self.group_by.is_empty()
1392    }
1393}
1394
1395/// Every database and cookie a bound statement depends on.
1396#[derive(Clone, Debug, Default, PartialEq, Eq)]
1397pub struct Dependencies {
1398    /// The `(database index, schema cookie)` pairs the statement was bound
1399    /// against.
1400    pub schemas: Vec<(usize, u32)>,
1401    /// The catalog generation the statement was bound against.
1402    pub generation: u64,
1403}
1404
1405/// A bound statement.
1406#[derive(Clone, Debug, PartialEq)]
1407pub enum BoundStatement {
1408    /// A SELECT or VALUES.
1409    Select(Box<BoundSelect>),
1410    /// An INSERT or REPLACE.
1411    Insert(Box<crate::dml::BoundInsert>),
1412    /// An UPDATE.
1413    Update(Box<crate::dml::BoundUpdate>),
1414    /// A DELETE.
1415    Delete(Box<crate::dml::BoundDelete>),
1416    /// A statement the session executes itself rather than compiling.
1417    Directive(Box<crate::directive::Directive>),
1418    /// A statement that compiles to no program.
1419    Empty,
1420}
1421
1422/// The binder's working state for one statement.
1423pub struct Binder<'a> {
1424    pub(crate) catalog: &'a dyn CatalogView,
1425    pub(crate) ast: &'a Ast,
1426    /// The statement text the parse came from.
1427    ///
1428    /// It is here for one reason: a result column with no alias that is
1429    /// not a bare column reference is named after the text it was written
1430    /// as, and the arena holds spans rather than the bytes they cut.
1431    pub(crate) source: &'a [u8],
1432    pub(crate) authorizer: &'a dyn Authorizer,
1433    /// The functions an application registered on this connection.
1434    ///
1435    /// Names and arities only - what they do is the machine's business - so a
1436    /// bound statement stays a pure function of the SQL, the catalog
1437    /// generation, and this list.
1438    pub(crate) externals: &'a [function::ExternalFunction],
1439    /// The collations an application defined on this connection.
1440    pub(crate) collations: &'a [(String, Collation)],
1441    /// Whether the expression being bound was written in the schema.
1442    ///
1443    /// **The whole of `direct_only` and `innocuous` enforcement (task-1972).**
1444    /// A `DEFAULT`, a `CHECK`, a generated column's expression, an index
1445    /// expression, a partial-index predicate, a view's body and a trigger's
1446    /// body are all strings in a file somebody else may have written, and a
1447    /// binder with no notion of where it was reading could not tell one from
1448    /// the statement an application submitted. `Registry::authorize_function`
1449    /// existed and had no caller for exactly that reason.
1450    ///
1451    /// It only ever moves from `Statement` to `Schema`: once inside a schema
1452    /// expression, everything the binder reaches through it - a view over a
1453    /// view, a generated column a `CHECK` reads, a subquery in a trigger body -
1454    /// is schema too, and each of those sites saves and restores this rather
1455    /// than clearing it.
1456    pub(crate) call_site: function::CallSite,
1457    /// Whether the connection trusts the schema it read, which
1458    /// `PRAGMA trusted_schema` decides.
1459    ///
1460    /// It is read with the call site above and nowhere else: a trusted schema
1461    /// may name a function that is merely not innocuous, and may still not name
1462    /// a direct-only one.
1463    pub(crate) trusted_schema: bool,
1464    pub(crate) sources: Vec<BoundSource>,
1465    /// One entry per query block currently being bound, innermost last, each
1466    /// holding the ids of the FROM terms that block owns.
1467    ///
1468    /// Resolution walks it from the back, so an inner name shadows an outer one
1469    /// and a name that only an outer block can satisfy makes the inner block
1470    /// correlated - which is exactly the information the compiler needs to
1471    /// decide whether the child runs once or once per outer row.
1472    pub(crate) scopes: Vec<Vec<usize>>,
1473    aggregates: Vec<BoundAggregate>,
1474    result_aliases: Vec<(Vec<u8>, BoundExpr)>,
1475    /// Whether anything bound after this block's result columns can name one of
1476    /// them by its alias.
1477    ///
1478    /// **Recording an alias costs an allocation per result column, and almost
1479    /// no statement reads one (task-2026).** `result_aliases` is consulted in
1480    /// exactly one place - `bind_column_reference`, after a real column has
1481    /// failed to match - and the only clauses that reach it are `GROUP BY`,
1482    /// `HAVING` and the statement's `ORDER BY`, `LIMIT` and `OFFSET`, all of
1483    /// which are bound after the result columns and inside the same block. A
1484    /// `SELECT` with none of them fills the list and never reads it, which on
1485    /// `SELECT 1` was a lowercased copy of the name `1`, and on a wider select
1486    /// is that plus a clone of every result expression.
1487    ///
1488    /// It is per block and restored by [`BlockFrame`] for the reason the alias
1489    /// list itself is: a subquery's tail clauses are its own, and an outer
1490    /// `ORDER BY` cannot name an inner block's alias.
1491    ///
1492    /// It starts `true`, so a binder reached by a path that does not set it
1493    /// records aliases exactly as it did before.
1494    tail_may_name_an_alias: bool,
1495    dependencies: Dependencies,
1496    inside_aggregate: bool,
1497    allow_aggregates: bool,
1498    /// The CTEs visible to the block being bound, innermost `WITH` last.
1499    pub(crate) ctes: Vec<Vec<CteBinding>>,
1500    /// The recursive CTEs whose own definition is being bound right now.
1501    ///
1502    /// A reference to a name on this stack is the recursion itself, and binding
1503    /// its definition again would not terminate - which is exactly what it did
1504    /// before this existed: the depth guard tripped a hundred frames down, in a
1505    /// function large enough that a hundred frames overflowed the stack.
1506    recursing: Vec<RecursiveTarget>,
1507    /// The CTEs being bound as ordinary subqueries right now, innermost last.
1508    ///
1509    /// **The guard against a cycle no recursion can carry (task-1913).** A CTE
1510    /// that names itself somewhere the recursion cannot read it - in a
1511    /// `WHERE (SELECT ... FROM c)`, or in a body with no compound arm to
1512    /// separate a seed from a step - used to bind its own definition again, and
1513    /// again, until the process ran out of stack and died. `inillucent` exited
1514    /// 127 with `has overflowed its stack` on three one-line queries, which in
1515    /// a library linked into an application is that application's crash.
1516    /// SQLite answers `circular reference: c`, and so does this now.
1517    ///
1518    /// Held as the definition's own `SelectId` rather than its name, because an
1519    /// inner `WITH` may bind the same name to a different query and that one is
1520    /// not a cycle - `WITH c AS (WITH c AS (SELECT 7) SELECT * FROM c)` is an
1521    /// ordinary query SQLite answers.
1522    binding_ctes: Vec<ast::SelectId>,
1523    /// The enclosing FROM terms the block being bound has read.
1524    correlations: Vec<usize>,
1525    /// How deep the binder is inside nested query blocks.
1526    depth: u32,
1527    /// How many nested queries used as values have been bound so far.
1528    subqueries: usize,
1529    /// How deep the binder is inside a generated column's own expression.
1530    generating: u32,
1531    /// The window calls bound in the block being bound.
1532    windows: Vec<BoundWindow>,
1533    /// The windows the block's `WINDOW` clause named.
1534    named_windows: Vec<(Vec<u8>, ast::WindowId)>,
1535    /// The table `excluded` names while an upsert's `DO UPDATE` is bound.
1536    pub(crate) excluded: Option<crate::catalog_view::TableInfo>,
1537    /// The row `OLD` and `NEW` name while a trigger body is bound.
1538    pub(crate) row_aliases: Option<RowAliases>,
1539    /// The FROM term a write to a view runs against, when the target is one.
1540    ///
1541    /// A view has no rows of its own, so an `UPDATE` or `DELETE` on one is
1542    /// pushed as an ordinary subquery term and the statement's `WHERE` and
1543    /// `SET` bind against that. Remembering its number is what lets the block
1544    /// that produces `OLD` be built out of the very same term, with no
1545    /// re-pointing of anything already bound.
1546    pub(crate) view_target: Option<usize>,
1547    /// Whether foreign keys are enforced, which `PRAGMA foreign_keys` decides.
1548    pub(crate) foreign_keys: bool,
1549    /// Whether every key's checks wait for the commit, which
1550    /// `PRAGMA defer_foreign_keys` decides for the transaction.
1551    pub(crate) defer_foreign_keys: bool,
1552    /// The synthesised triggers whose bodies are being bound.
1553    ///
1554    /// A key that can lead back to its own table would inline its body once per
1555    /// level the data happens to be deep, which is not knowable when the
1556    /// statement is compiled. Re-entry stops here instead, and the connection
1557    /// repeats the action after the statement until nothing changes.
1558    pub(crate) firing_foreign_keys: Vec<Vec<u8>>,
1559    /// How many foreign-key action bodies are currently being inlined.
1560    pub(crate) foreign_key_depth: usize,
1561    /// How many more foreign-key action bodies may be inlined at all.
1562    ///
1563    /// A foreign key's action is inlined rather than called, so a cascade that
1564    /// can reach the same table again - a tree with `ON DELETE CASCADE` on its
1565    /// parent column is the everyday case - needs the body once per level it
1566    /// can reach. An acyclic set of keys never touches this: each level is a
1567    /// different table and the inlining stops on its own. A cycle spends the
1568    /// budget, and running out is reported rather than silently leaving the
1569    /// rows the cascade did not reach.
1570    pub(crate) foreign_key_budget: usize,
1571    /// Equalities a table-valued function's arguments implied, waiting to be
1572    /// ANDed into the block's `WHERE`.
1573    ///
1574    /// They cannot be added when the term is bound, because the filter has not
1575    /// been bound yet and the arguments have to be inside it rather than beside
1576    /// it: `json_each(x) WHERE key > 1` is one conjunction, not two filters.
1577    pub(crate) pending_constraints: Vec<BoundExpr>,
1578    /// The folded names of the triggers whose bodies are being bound, outermost
1579    /// first.
1580    ///
1581    /// SQLite's default is `recursive_triggers = off`, which skips a trigger
1582    /// that is already on the stack rather than firing it again. Skipping is
1583    /// also what makes inlining terminate, so the two agree: this list is both
1584    /// the parity rule and the recursion guard.
1585    pub(crate) firing: Vec<Vec<u8>>,
1586    /// How deep `firing` may get, from the connection's `Limit::TriggerDepth`.
1587    ///
1588    /// The limit is settable - `.limit trigger_depth 10` and the driver's limit
1589    /// setter both reach it - so it is a field rather than the constant it used
1590    /// to be, and the refusal names the number that was in force.
1591    pub(crate) trigger_depth: usize,
1592}
1593
1594/// How deeply query blocks may nest.
1595///
1596/// SQLite's own limit is expression depth rather than a separate select depth,
1597/// but a subquery per level costs a scope, a frame and a compiled subprogram,
1598/// so the recursion is bounded here where the recursion happens.
1599pub const MAX_SELECT_DEPTH: u32 = 64;
1600
1601/// How many arms a compound SELECT may have, which is `SQLITE_MAX_COMPOUND_SELECT`.
1602pub const MAX_COMPOUND_SELECT: usize = 500;
1603
1604/// How deep one generated column may reach through others.
1605///
1606/// A cycle is refused when the table is created, so this is a second line of
1607/// defence for a schema that arrived from somewhere else: a file whose
1608/// `CREATE TABLE` describes a cycle would otherwise recurse until the stack ran
1609/// out, and a corrupt file must not be able to do that.
1610pub const MAX_GENERATED_DEPTH: u32 = 32;
1611
1612/// The source number a column of an upsert's `excluded` row carries.
1613///
1614/// It is not a FROM term: `excluded` is the row the INSERT was about to write,
1615/// which lives in registers rather than under a cursor. Giving it a number no
1616/// real source can have means the compiler must substitute it - and a compiler
1617/// that forgot to would try to open a cursor two billion and be refused by the
1618/// verifier, rather than reading the wrong row.
1619pub const EXCLUDED_SOURCE: usize = usize::MAX;
1620
1621/// The source number a column of a trigger's `OLD` row carries.
1622///
1623/// Like [`EXCLUDED_SOURCE`], it is not a FROM term: `OLD` and `NEW` are the row
1624/// the write is about, which the compiler already holds in registers by the
1625/// time a trigger fires. Numbering them where no real source can reach means a
1626/// compiler that forgot to substitute one is caught by the verifier rather than
1627/// quietly reading whatever cursor happened to be open.
1628pub const OLD_SOURCE: usize = usize::MAX - 1;
1629
1630/// The source number a column of a trigger's `NEW` row carries.
1631pub const NEW_SOURCE: usize = usize::MAX - 2;
1632
1633/// The row a trigger body's `OLD` and `NEW` name.
1634///
1635/// Which of the two are in scope is decided by the event: an INSERT has no
1636/// previous row and a DELETE has no next one, and SQLite refuses the name that
1637/// does not apply rather than reading NULLs out of it.
1638#[derive(Clone, Debug)]
1639pub(crate) struct RowAliases {
1640    /// The table the trigger is attached to, whose columns the names carry.
1641    pub(crate) table: crate::catalog_view::TableInfo,
1642    /// Whether `OLD` is in scope.
1643    pub(crate) old: bool,
1644    /// Whether `NEW` is in scope.
1645    pub(crate) new: bool,
1646}
1647
1648impl<'a> Binder<'a> {
1649    /// Points the binder at the text its parse came from.
1650    ///
1651    /// A binder with no source names an unaliased expression column with
1652    /// the empty string, which is what a nested parse of schema text
1653    /// wants: those columns are never returned to anybody.
1654    pub fn with_source(mut self, source: &'a [u8]) -> Binder<'a> {
1655        self.source = source;
1656        self
1657    }
1658
1659    /// Names the functions an application registered on this connection.
1660    pub fn with_functions(mut self, functions: &'a [function::ExternalFunction]) -> Binder<'a> {
1661        self.externals = functions;
1662        self
1663    }
1664
1665    /// Names the collations an application defined on this connection.
1666    pub fn with_collations(mut self, collations: &'a [(String, Collation)]) -> Binder<'a> {
1667        self.collations = collations;
1668        self
1669    }
1670
1671    /// Says whether the connection trusts the schema it read.
1672    ///
1673    /// `PRAGMA trusted_schema` is the lever, and it is read at bind time, so a
1674    /// connection that changes it throws its compiled statements away - a plan
1675    /// bound under one answer is that answer.
1676    ///
1677    /// @param trusted - whether a schema may name a function that is not
1678    ///   innocuous
1679    pub fn with_trusted_schema(mut self, trusted: bool) -> Binder<'a> {
1680        self.trusted_schema = trusted;
1681        self
1682    }
1683
1684    /// Binds as though every expression had been written in the schema.
1685    ///
1686    /// For a caller that already knows what it is holding is schema text and
1687    /// has no enclosing statement to inherit the site from: the query
1688    /// `CREATE INDEX` builds to fill an index on an expression, and the view
1689    /// body `PRAGMA table_info` binds to find out a view's columns.
1690    ///
1691    /// **The index build is why this exists (task-1972).** An index on an
1692    /// expression is filled by running a `SELECT` the engine writes out of that
1693    /// expression, and a `SELECT` is a statement - so the build was the one
1694    /// place a schema expression reached the machine with a statement's
1695    /// permissions, and `CREATE INDEX i ON t (embed(body))` loaded a 275 MB
1696    /// model once per row before any later write of the table was refused for
1697    /// naming it.
1698    pub fn in_schema(mut self) -> Binder<'a> {
1699        self.call_site = function::CallSite::Schema;
1700        self
1701    }
1702
1703    /// Returns a binder over one catalog snapshot and one parse.
1704    pub fn new(
1705        catalog: &'a dyn CatalogView,
1706        ast: &'a Ast,
1707        authorizer: &'a dyn Authorizer,
1708    ) -> Binder<'a> {
1709        Binder {
1710            catalog,
1711            ast,
1712            source: &[],
1713            authorizer,
1714            externals: &[],
1715            collations: &[],
1716            call_site: function::CallSite::Statement,
1717            // SQLite's default, and `Policy::default()`'s. A connection that
1718            // wants the stricter stance says so; a binder built with no
1719            // connection behind it - a test over a hand-built catalog - gets
1720            // the same answer the engine's default gives.
1721            trusted_schema: true,
1722            sources: Vec::new(),
1723            scopes: Vec::new(),
1724            aggregates: Vec::new(),
1725            result_aliases: Vec::new(),
1726            tail_may_name_an_alias: true,
1727            dependencies: Dependencies {
1728                schemas: Vec::new(),
1729                generation: catalog.generation(),
1730            },
1731            inside_aggregate: false,
1732            allow_aggregates: false,
1733            ctes: Vec::new(),
1734            recursing: Vec::new(),
1735            binding_ctes: Vec::new(),
1736            correlations: Vec::new(),
1737            depth: 0,
1738            subqueries: 0,
1739            generating: 0,
1740            windows: Vec::new(),
1741            named_windows: Vec::new(),
1742            excluded: None,
1743            row_aliases: None,
1744            view_target: None,
1745            firing: Vec::new(),
1746            trigger_depth: crate::dml::MAX_TRIGGER_DEPTH,
1747            pending_constraints: Vec::new(),
1748            foreign_keys: false,
1749            defer_foreign_keys: false,
1750            firing_foreign_keys: Vec::new(),
1751            foreign_key_depth: 0,
1752            foreign_key_budget: crate::dml::MAX_FOREIGN_KEY_STATEMENTS,
1753        }
1754    }
1755
1756    /// Names the limits this connection is configured with.
1757    ///
1758    /// Only `Limit::TriggerDepth` is read here; the parser reads the rest for
1759    /// itself. A limit below one would refuse the first trigger of any chain,
1760    /// which is not what a limit of zero means anywhere else, so it is floored
1761    /// at one the way `limits.toml`'s own `minimum` says.
1762    ///
1763    /// @param limits - the connection's limits
1764    pub fn with_limits(mut self, limits: &inillucent_base::limits::Limits) -> Binder<'a> {
1765        let configured = limits.get(inillucent_base::limits::Limit::TriggerDepth);
1766        self.trigger_depth = configured.max(1) as usize;
1767        self
1768    }
1769
1770    /// Turns foreign-key enforcement on, and says whether it is deferred.
1771    ///
1772    /// Off is the default, and it is SQLite's: a constraint that has never been
1773    /// enforced on an existing database would refuse writes the application has
1774    /// always made, so the application asks for it.
1775    pub fn with_foreign_keys(mut self, enforced: bool, deferred: bool) -> Binder<'a> {
1776        self.foreign_keys = enforced;
1777        self.defer_foreign_keys = deferred;
1778        self
1779    }
1780
1781    /// Returns what the bound statement depends on.
1782    pub fn dependencies(&self) -> &Dependencies {
1783        &self.dependencies
1784    }
1785
1786    /// Binds a statement, or reports why it cannot be bound.
1787    pub fn bind_statement(
1788        &mut self,
1789        statement: &ast::Statement,
1790    ) -> Result<BoundStatement, ParseError> {
1791        match statement {
1792            ast::Statement::Empty => Ok(BoundStatement::Empty),
1793            ast::Statement::Select(select) => {
1794                let bound = self.bind_select(*select)?;
1795                Ok(BoundStatement::Select(Box::new(bound)))
1796            }
1797            ast::Statement::Insert(insert) => {
1798                let bound = self.bind_insert(insert)?;
1799                Ok(BoundStatement::Insert(Box::new(bound)))
1800            }
1801            ast::Statement::Update(update) => {
1802                let bound = self.bind_update(update)?;
1803                Ok(BoundStatement::Update(Box::new(bound)))
1804            }
1805            ast::Statement::Delete(delete) => {
1806                let bound = self.bind_delete(delete)?;
1807                Ok(BoundStatement::Delete(Box::new(bound)))
1808            }
1809            // `EXPLAIN` is handled a level up, where the inner statement's
1810            // program is available to render. Reaching it here means a nested
1811            // one, which SQLite refuses too.
1812            ast::Statement::Explain { .. } => Err(unsupported("nested EXPLAIN", Span::default())),
1813            other => {
1814                let directive = self.bind_directive(other)?;
1815                Ok(BoundStatement::Directive(Box::new(directive)))
1816            }
1817        }
1818    }
1819
1820    /// Binds a SELECT, including its `WITH` prefix and every compound arm.
1821    ///
1822    /// The block's scope is pushed here rather than in the arm binder because
1823    /// `ORDER BY` belongs to the statement and resolves in the first arm's
1824    /// scope: pushing and popping around the arm alone made every qualified
1825    /// name in an `ORDER BY` report "no such table".
1826    pub fn bind_select(&mut self, id: SelectId) -> Result<BoundSelect, ParseError> {
1827        let Some(select) = self.ast.select(id) else {
1828            return Err(unsupported("missing select", Span::default()));
1829        };
1830        if self.authorizer.authorize(AuthAction::Select) == Authorization::Deny {
1831            return Err(denied("not authorized", select.span));
1832        }
1833        self.depth = self.depth.saturating_add(1);
1834        if self.depth > MAX_SELECT_DEPTH {
1835            self.depth = self.depth.saturating_sub(1);
1836            return Err(ParseError::new(
1837                ParseErrorKind::Unsupported("too many levels of nested SELECT"),
1838                select.span,
1839            ));
1840        }
1841        let result = self.bind_select_body(id);
1842        self.depth = self.depth.saturating_sub(1);
1843        result
1844    }
1845
1846    /// Binds one SELECT's `WITH`, arms and tail clauses.
1847    fn bind_select_body(&mut self, id: SelectId) -> Result<BoundSelect, ParseError> {
1848        let Some(select) = self.ast.select(id) else {
1849            return Err(unsupported("missing select", Span::default()));
1850        };
1851        let pushed = self.push_ctes(&select.with)?;
1852        let bound = self.bind_arms(select);
1853        if pushed {
1854            self.ctes.pop();
1855        }
1856        bound
1857    }
1858
1859    /// Binds the first arm, every compound arm, and the tail clauses.
1860    fn bind_arms(&mut self, select: &'a ast::Select) -> Result<BoundSelect, ParseError> {
1861        if select.compounds.len() > MAX_COMPOUND_SELECT {
1862            return Err(ParseError::new(
1863                ParseErrorKind::Unsupported("too many terms in compound SELECT"),
1864                select.span,
1865            ));
1866        }
1867        let frame = self.enter_block();
1868        // Decided here because this is the only place that holds both the block
1869        // and the tail clauses bound into it. A compound arm opens its own
1870        // frame inside `finish_select` and inherits this, which is right: the
1871        // statement's `ORDER BY` is resolved against the compound's columns
1872        // rather than through any one arm's aliases, so an arm that inherits a
1873        // `true` records aliases it will not read, and never the other way.
1874        self.tail_may_name_an_alias =
1875            !select.order_by.is_empty() || select.limit.is_some() || select.offset.is_some();
1876        let bound = self.bind_arm(select.first);
1877        let mut bound = match bound {
1878            Ok(bound) => bound,
1879            Err(reason) => {
1880                self.leave_block(frame);
1881                return Err(reason);
1882            }
1883        };
1884        let outcome = self.finish_select(select, &mut bound);
1885        let ids = self.leave_block(frame);
1886        outcome?;
1887        bound.sources = ids
1888            .iter()
1889            .filter_map(|id| self.sources.get(*id).cloned())
1890            .collect();
1891        refuse_unanswerable_hints(&bound)?;
1892        Ok(bound)
1893    }
1894
1895    /// Binds the compound arms and the tail clauses onto a first arm.
1896    ///
1897    /// **An arm goes through [`Binder::bind_isolated_arm`] (task-2042).** A
1898    /// bare `enter_block` / `bind_arm` / `leave_block` threw the arm's
1899    /// aggregates and windows away, because `leave_block` restores the
1900    /// enclosing block's lists, so every arm but the head reached the planner
1901    /// claiming to compute nothing: refused, or - with a `GROUP BY` on that
1902    /// arm - one blank row per group. `compound.arm.aggregate` and
1903    /// `compound.arm.grouped` in `tests/semantics.rs` name both shapes.
1904    ///
1905    /// @param select - the statement as written
1906    /// @param bound - the head arm the arms and clauses are added to
1907    fn finish_select(
1908        &mut self,
1909        select: &'a ast::Select,
1910        bound: &mut BoundSelect,
1911    ) -> Result<(), ParseError> {
1912        for (op, arm) in &select.compounds {
1913            let armed = self.bind_isolated_arm(*arm)?;
1914            if armed.columns.len() != bound.columns.len() {
1915                return Err(ParseError::new(
1916                    ParseErrorKind::Unsupported(
1917                        "SELECTs to the left and right of a compound operator do not have the same number of result columns",
1918                    ),
1919                    select.span,
1920                ));
1921            }
1922            bound.compounds.push((*op, armed));
1923        }
1924        // **The result columns are read where they are, not copied first
1925        // (task-2026).** `bound` is a parameter rather than a field, so a
1926        // shared borrow of its columns and the mutable borrow of the binder are
1927        // two different objects and the compiler accepts both at once. The
1928        // clone that used to stand here was a `Vec<BoundResultColumn>` plus one
1929        // allocation for every name, origin and declared type in it - six of
1930        // the 109 allocations `SELECT a FROM t WHERE id = ?1` made, and two of
1931        // `SELECT 1`'s 21 - spent to hand `bind_order_by` a copy of something
1932        // it only reads, on every statement including the ones with no
1933        // `ORDER BY` at all.
1934        let order_by = match bound.compounds.is_empty() {
1935            true => {
1936                let aliases = self.order_aliases(select, &bound.columns);
1937                self.bind_order_by(&select.order_by, &bound.columns, &aliases)?
1938            }
1939            false => self.bind_compound_order_by(&select.order_by, &bound.columns)?,
1940        };
1941        bound.order_by = order_by;
1942        bound.limit = match select.limit {
1943            Some(expr) => Some(self.bind_expr(expr)?),
1944            None => None,
1945        };
1946        bound.offset = match select.offset {
1947            Some(expr) => Some(self.bind_expr(expr)?),
1948            None => None,
1949        };
1950        bound.aggregates = self.aggregates.clone();
1951        bound.windows = self.windows.clone();
1952        bound.correlations = self.correlations.clone();
1953        Ok(())
1954    }
1955
1956    /// Binds one arm of a compound: a `SELECT` core or a `VALUES` list.
1957    fn bind_arm(&mut self, id: ast::SelectCoreId) -> Result<BoundSelect, ParseError> {
1958        let Some(core) = self.ast.core(id) else {
1959            return Err(unsupported("missing select core", Span::default()));
1960        };
1961        match &core.body {
1962            SelectBody::Values(rows) => self.bind_values(rows, core.span),
1963            SelectBody::Select { .. } => self.bind_select_core(id),
1964        }
1965    }
1966
1967    /// Binds a compound's `ORDER BY`, which may only name a result column.
1968    ///
1969    /// SQLite resolves a compound's `ORDER BY` against the output of the
1970    /// compound rather than against any arm's FROM clause, because the arms do
1971    /// not share one. A term that is neither an ordinal nor the name of a
1972    /// result column is an error there and is an error here.
1973    fn bind_compound_order_by(
1974        &mut self,
1975        terms: &[ast::OrderTerm],
1976        columns: &[BoundResultColumn],
1977    ) -> Result<Vec<BoundOrderTerm>, ParseError> {
1978        let mut bound = Vec::with_capacity(terms.len());
1979        for term in terms {
1980            let span = self.ast.expr_span(term.expr);
1981            let (target, named) = self.order_term_collation(term.expr, span)?;
1982            let index = match self.as_ordinal(target) {
1983                Some(ordinal) => match ordinal.checked_sub(1) {
1984                    Some(index) if index < columns.len() => index,
1985                    _ => return Err(order_out_of_range(ordinal, span)),
1986                },
1987                None => {
1988                    let Some(Expr::Column {
1989                        database: None,
1990                        table: None,
1991                        column,
1992                    }) = self.ast.expr(target)
1993                    else {
1994                        return Err(compound_order_unmatched(span));
1995                    };
1996                    let folded = self.ast.folded(*column).to_vec();
1997                    let Some(index) = columns
1998                        .iter()
1999                        .position(|candidate| candidate.name.eq_ignore_ascii_case(&folded))
2000                    else {
2001                        return Err(compound_order_unmatched(span));
2002                    };
2003                    index
2004                }
2005            };
2006            let Some(column) = columns.get(index) else {
2007                return Err(order_out_of_range(index.saturating_add(1), span));
2008            };
2009            // With no `COLLATE` on the term, the result column's own collation
2010            // governs, read the same way the compound's duplicate removal reads
2011            // it - an explicit `COLLATE` on the result column beats the implicit
2012            // one - so the sort and the duplicate removal cannot disagree about
2013            // a column.
2014            let collation = named.unwrap_or_else(|| result_collation(&column.expr));
2015            let nulls = term.nulls.unwrap_or(match term.order {
2016                SortOrder::Ascending => NullOrder::First,
2017                SortOrder::Descending => NullOrder::Last,
2018            });
2019            bound.push(BoundOrderTerm {
2020                expr: BoundExpr::SorterColumn {
2021                    column: index as u16,
2022                },
2023                order: term.order,
2024                nulls,
2025                collation,
2026            });
2027        }
2028        Ok(bound)
2029    }
2030
2031    /// Splits a compound `ORDER BY` term into the term itself and the
2032    /// collation an explicit `COLLATE` named on it.
2033    ///
2034    /// **`UNION ... ORDER BY a COLLATE NOCASE` was a parse error (task-1979,
2035    /// F15).** A compound's `ORDER BY` may only name a result column, and the
2036    /// match was made against the term exactly as written, so `a COLLATE
2037    /// NOCASE` was an `Expr::Collate` rather than an `Expr::Column` and the
2038    /// term matched nothing. SQLite reads through the `COLLATE`, matches the
2039    /// name underneath it, and sorts that column with the collation the term
2040    /// named rather than the one the column carries.
2041    ///
2042    /// @param expr - the term as written
2043    /// @param span - where to point a `no such collation` diagnostic
2044    fn order_term_collation(
2045        &self,
2046        expr: ExprId,
2047        span: Span,
2048    ) -> Result<(ExprId, Option<Collation>), ParseError> {
2049        let Some(Expr::Collate { operand, collation }) = self.ast.expr(expr) else {
2050            return Ok((expr, None));
2051        };
2052        let name = self.ast.text(*collation);
2053        let Some(named) = self.collation_named(name) else {
2054            return Err(no_such_collation(name, span));
2055        };
2056        Ok((*operand, Some(named)))
2057    }
2058    /// Returns the FROM-term ids the innermost block owns.
2059    pub(crate) fn scope(&self) -> &[usize] {
2060        self.scopes.last().map_or(&[], |scope| scope.as_slice())
2061    }
2062
2063    /// Returns the statement-wide id of the innermost block's nth FROM term.
2064    fn scope_id(&self, position: usize) -> Option<usize> {
2065        self.scope().get(position).copied()
2066    }
2067
2068    /// Records that the block being bound reads a FROM term it does not own.
2069    fn note_correlation(&mut self, id: usize) {
2070        if self.scope().contains(&id) || self.correlations.contains(&id) {
2071            return;
2072        }
2073        self.correlations.push(id);
2074    }
2075
2076    /// Binds a `VALUES` arm, which has no FROM and no names to resolve.
2077    fn bind_values(&mut self, rows: &[Vec<ExprId>], span: Span) -> Result<BoundSelect, ParseError> {
2078        let mut bound_rows = Vec::with_capacity(rows.len());
2079        let mut width = 0usize;
2080        for row in rows {
2081            let mut values = Vec::with_capacity(row.len());
2082            for expr in row {
2083                values.push(self.bind_expr(*expr)?);
2084            }
2085            if bound_rows.is_empty() {
2086                width = values.len();
2087            } else if values.len() != width {
2088                return Err(ParseError::new(
2089                    ParseErrorKind::Unsupported("all VALUES rows must have the same width"),
2090                    span,
2091                ));
2092            }
2093            bound_rows.push(values);
2094        }
2095        let columns = (0..width)
2096            .map(|index| BoundResultColumn {
2097                expr: BoundExpr::SorterColumn {
2098                    column: index as u16,
2099                },
2100                name: format!("column{}", index.saturating_add(1)).into_bytes(),
2101                origin: None,
2102                declared_type: Vec::new(),
2103            })
2104            .collect();
2105        Ok(BoundSelect {
2106            sources: Vec::new(),
2107            filter: None,
2108            group_by: Vec::new(),
2109            having: None,
2110            columns,
2111            distinct: false,
2112            order_by: Vec::new(),
2113            limit: None,
2114            offset: None,
2115            aggregates: Vec::new(),
2116            values: bound_rows,
2117            compounds: Vec::new(),
2118            windows: Vec::new(),
2119            correlations: Vec::new(),
2120        })
2121    }
2122
2123    /// Binds a `SELECT` arm: FROM, WHERE, GROUP BY, HAVING, and the results.
2124    fn bind_select_core(&mut self, id: ast::SelectCoreId) -> Result<BoundSelect, ParseError> {
2125        let Some(core) = self.ast.core(id) else {
2126            return Err(unsupported("missing select core", Span::default()));
2127        };
2128        let SelectBody::Select {
2129            distinct,
2130            columns,
2131            from,
2132            filter,
2133            group_by,
2134            having,
2135            windows,
2136            ..
2137        } = &core.body
2138        else {
2139            return Err(unsupported("expected a select core", core.span));
2140        };
2141        self.declare_windows(windows)?;
2142        for term in from {
2143            self.bind_from_term(*term)?;
2144        }
2145        self.desugar_join_constraints(from)?;
2146        let pending = core::mem::take(&mut self.pending_constraints);
2147        let mut bound_filter = match filter {
2148            Some(expr) => Some(self.bind_expr(*expr)?),
2149            None => None,
2150        };
2151        for constraint in pending {
2152            bound_filter = Some(match bound_filter.take() {
2153                Some(existing) => BoundExpr::And(Box::new(existing), Box::new(constraint)),
2154                None => constraint,
2155            });
2156        }
2157        // See `matching`: a `MATCH` the planner cannot offer to its module.
2158        if let Some(filter) = bound_filter.as_mut() {
2159            self.match_by_rowid(filter)?;
2160        }
2161        self.allow_aggregates = true;
2162        let bound_columns = self.bind_result_columns(columns)?;
2163        // Read before the `HAVING` is bound, because by then `self.aggregates`
2164        // holds the ones the `HAVING` itself introduced. `bind::having` says
2165        // why that distinction is the whole rule.
2166        let aggregates_in_columns = self.aggregates.len();
2167        // See `tail_may_name_an_alias`. This core's own `GROUP BY` and `HAVING`
2168        // are read here rather than from the flag because they belong to the
2169        // core and the flag belongs to the statement around it.
2170        if self.tail_may_name_an_alias || !group_by.is_empty() || having.is_some() {
2171            for column in &bound_columns {
2172                if !column.name.is_empty() {
2173                    self.result_aliases
2174                        .push((column.name.to_ascii_lowercase(), column.expr.clone()));
2175                }
2176            }
2177        }
2178        let mut bound_group = Vec::with_capacity(group_by.len());
2179        for expr in group_by {
2180            bound_group.push(self.bind_group_term(*expr, &bound_columns)?);
2181        }
2182        let bound_having = match having {
2183            Some(expr) => Some(self.bind_expr(*expr)?),
2184            None => None,
2185        };
2186        having::refuse_when_nothing_aggregates(
2187            bound_having.is_some(),
2188            bound_group.len(),
2189            aggregates_in_columns,
2190        )?;
2191        // The sources stay in the binder's scope: `ORDER BY` and `LIMIT` belong
2192        // to the whole statement and are bound after this returns, and
2193        // `ORDER BY b.id` needs the same scope the result columns had.
2194        Ok(BoundSelect {
2195            sources: Vec::new(),
2196            filter: bound_filter,
2197            group_by: bound_group,
2198            having: bound_having,
2199            columns: bound_columns,
2200            distinct: *distinct,
2201            order_by: Vec::new(),
2202            limit: None,
2203            offset: None,
2204            aggregates: Vec::new(),
2205            values: Vec::new(),
2206            compounds: Vec::new(),
2207            windows: Vec::new(),
2208            correlations: Vec::new(),
2209        })
2210    }
2211
2212    /// Refuses an `INDEXED BY` that names no index of the table just bound.
2213    ///
2214    /// **It was read and thrown away (task-1979, F7).** The hint reached the
2215    /// AST and nothing below the parser looked at it, so
2216    /// `SELECT * FROM t INDEXED BY nosuch WHERE a = 1` answered rows where
2217    /// SQLite refuses the statement with `no such index: nosuch`. A caller who
2218    /// wrote the hint to make a plan use a particular index, and misspelled it,
2219    /// got a plan that did something else and no way to tell.
2220    ///
2221    /// `NOT INDEXED` names nothing and is a planner instruction rather than a
2222    /// reference, so it passes through here untouched.
2223    ///
2224    /// @param hint - the hint as written
2225    /// @param span - where to point the diagnostic
2226    fn check_index_hint(&mut self, hint: ast::IndexHint, span: Span) -> Result<(), ParseError> {
2227        let ast::IndexHint::IndexedBy(name) = hint else {
2228            return Ok(());
2229        };
2230        let folded = self.ast.folded(name).to_vec();
2231        let Some(source) = self.sources.last() else {
2232            return Ok(());
2233        };
2234        if source
2235            .table
2236            .indexes
2237            .iter()
2238            .any(|index| index.folded == folded)
2239        {
2240            return Ok(());
2241        }
2242        Err(no_such_index(self.ast.text(name), span))
2243    }
2244
2245    /// Turns a hint as the parser wrote it into the form the planner reads.
2246    ///
2247    /// @param hint - the hint as written
2248    pub(crate) fn index_choice(&self, hint: ast::IndexHint) -> IndexChoice {
2249        match hint {
2250            ast::IndexHint::None => IndexChoice::Any,
2251            ast::IndexHint::NotIndexed => IndexChoice::NotIndexed,
2252            ast::IndexHint::IndexedBy(name) => IndexChoice::Only(self.ast.folded(name).to_vec()),
2253        }
2254    }
2255
2256    /// Binds one FROM term, registering it as a source of the current block.
2257    ///
2258    /// A table, a CTE reference, a view and a parenthesised subquery all end up
2259    /// as one entry in the block's scope. The last three carry the block they
2260    /// stand for, and everything below the binder treats them alike.
2261    pub(crate) fn bind_from_term(&mut self, id: ast::FromTermId) -> Result<(), ParseError> {
2262        let Some(term) = self.ast.from_term(id) else {
2263            return Err(unsupported("missing FROM term", Span::default()));
2264        };
2265        let join = term.join;
2266        let span = term.span;
2267        match &term.source {
2268            FromSource::Table {
2269                database,
2270                name,
2271                arguments,
2272                indexed_by,
2273                ..
2274            } => {
2275                let arguments = arguments.clone();
2276                let indexed_by = *indexed_by;
2277                self.bind_table_term(*database, *name, term.alias, join, span)?;
2278                self.check_index_hint(indexed_by, span)?;
2279                // The hint belongs to the term that was just pushed, and this
2280                // is the only place that knows both.
2281                let choice = self.index_choice(indexed_by);
2282                if let Some(source) = self.sources.last_mut() {
2283                    source.index_hint = choice;
2284                }
2285                if let Some(arguments) = arguments {
2286                    self.bind_table_arguments(&arguments, span)?;
2287                }
2288                Ok(())
2289            }
2290            FromSource::Subquery(select) => {
2291                let alias = term.alias.map(|alias| self.ast.text(alias).to_vec());
2292                self.bind_subquery_term(*select, alias, Vec::new(), join, span)
2293            }
2294            FromSource::Join(terms) => {
2295                // A parenthesised join is a term to whatever contains it, and
2296                // SQLite flattens it into the enclosing FROM list. The first
2297                // inner term inherits the join that attached the parentheses;
2298                // the rest keep their own.
2299                let inner = terms.clone();
2300                for (position, nested) in inner.iter().enumerate() {
2301                    let before = self.scope().len();
2302                    self.bind_from_term(*nested)?;
2303                    if position == 0 {
2304                        if let Some(id) = self.scope_id(before) {
2305                            if let Some(source) = self.sources.get_mut(id) {
2306                                source.join = join;
2307                            }
2308                        }
2309                    }
2310                }
2311                self.desugar_join_constraints(&inner)?;
2312                Ok(())
2313            }
2314        }
2315    }
2316
2317    /// Binds a named FROM term: a CTE, a view, or a real table.
2318    fn bind_table_term(
2319        &mut self,
2320        database: Option<ast::NameId>,
2321        name: ast::NameId,
2322        alias: Option<ast::NameId>,
2323        join: JoinKind,
2324        span: Span,
2325    ) -> Result<(), ParseError> {
2326        let folded = self.ast.folded(name).to_vec();
2327        let written = self.ast.text(name).to_vec();
2328        if database.is_none() {
2329            // A reference to the CTE whose own definition is being bound is
2330            // the recursion. It reads the row the fill loop is on rather than
2331            // being another materialisation of the same query.
2332            if let Some(position) = self
2333                .recursing
2334                .iter()
2335                .rposition(|target| target.folded == folded)
2336            {
2337                return self.push_recursive_self(position, alias, join);
2338            }
2339            if let Some(cte) = self.find_cte(&folded) {
2340                let alias = match alias {
2341                    Some(alias) => self.ast.text(alias).to_vec(),
2342                    None => cte.name.clone(),
2343                };
2344                // A definition already being bound cannot be bound again: that
2345                // is a cycle, and following it does not end.
2346                if self.binding_ctes.contains(&cte.select) {
2347                    return Err(ParseError::new(
2348                        ParseErrorKind::Unsupported("circular reference in a CTE"),
2349                        span,
2350                    ));
2351                }
2352                self.binding_ctes.push(cte.select);
2353                // **`RECURSIVE` is a keyword SQLite does not require.** A CTE
2354                // whose FROM names itself *is* the recursion, written or not,
2355                // and reading the keyword as the only evidence sent this
2356                // binder round the same definition until the stack ran out.
2357                let outcome = if cte.recursive || self.select_names_itself(cte.select, &folded) {
2358                    self.bind_recursive_cte(&cte, alias, join, span)
2359                } else {
2360                    self.bind_subquery_term(
2361                        cte.select,
2362                        Some(alias),
2363                        cte.columns.clone(),
2364                        join,
2365                        span,
2366                    )
2367                };
2368                self.binding_ctes.pop();
2369                return outcome;
2370            }
2371        }
2372        let database_name = database.map(|id| self.ast.folded(id).to_vec());
2373        let Some(table) = self.catalog.find_table(database_name.as_deref(), &folded) else {
2374            return Err(no_such_table(&written, span));
2375        };
2376        if table.kind == TableKind::Virtual && table.columns.is_empty() {
2377            // A virtual table with no declared columns is one whose module this
2378            // build does not have. The schema still loaded - every other table
2379            // in the file works - and naming this one is what fails.
2380            return Err(unsupported("that virtual table's module", span));
2381        }
2382        if table.kind == TableKind::View {
2383            let view_alias = match alias {
2384                Some(alias) => self.ast.text(alias).to_vec(),
2385                None => table.name.clone(),
2386            };
2387            let database_index = table.database;
2388            let Some(body) = table.view.as_ref() else {
2389                return Err(ParseError::new(
2390                    ParseErrorKind::Unsupported("the view's definition could not be parsed"),
2391                    span,
2392                ));
2393            };
2394            self.record_dependency(database_index);
2395            // The view's own arena outlives the binder because it belongs to
2396            // the catalog snapshot the binder holds, which is what lets the
2397            // body be bound in place rather than re-parsed here.
2398            let columns = body.columns.clone();
2399            let saved = self.ast;
2400            // A view's body is a string in the schema, so everything it names
2401            // is named from a schema - including anything a further view or a
2402            // generated column it reads goes on to name. The site is saved and
2403            // restored rather than set, because a view inside a view is still
2404            // inside the outer one.
2405            let saved_site = self.call_site;
2406            self.ast = &body.ast;
2407            self.call_site = function::CallSite::Schema;
2408            let bound = self.bind_select(body.select);
2409            self.call_site = saved_site;
2410            self.ast = saved;
2411            let bound = bound?;
2412            return self.push_subquery_source(bound, view_alias, columns, join, span);
2413        }
2414        self.record_dependency(table.database);
2415        let alias = match alias {
2416            Some(alias) => self.ast.text(alias).to_vec(),
2417            None => table.name.clone(),
2418        };
2419        // The shared pointer, taken here rather than above: a view binds its
2420        // body out of the catalog's own arena, and only the borrow keeps that
2421        // alive. The second lookup is a folded-name comparison over the
2422        // catalog's tables and costs a fraction of the clone it replaces.
2423        let Some(table) = self.catalog.shared_table(database_name.as_deref(), &folded) else {
2424            return Err(no_such_table(&written, span));
2425        };
2426        let id = self.sources.len();
2427        self.sources.push(BoundSource {
2428            index_hint: crate::bind::IndexChoice::Any,
2429            id,
2430            rows: SourceRows::Table,
2431            table,
2432            alias,
2433            join,
2434            constraint: None,
2435            suppressed: Vec::new(),
2436            index_exprs: Vec::new(),
2437        });
2438        if let Some(scope) = self.scopes.last_mut() {
2439            scope.push(id);
2440        }
2441        self.attach_index_exprs(id);
2442        Ok(())
2443    }
2444
2445    /// Binds a term's partial-index predicates and expression keys onto it.
2446    ///
2447    /// **Scoped to the one term, and tolerant of a schema it cannot bind.** The
2448    /// expressions are bound in a nested binder holding only this source, so a
2449    /// predicate reading `b` means *this* table's `b` and not another term's;
2450    /// and an index whose expressions do not bind is left out rather than
2451    /// failing the statement, which leaves the planner unable to choose it.
2452    /// That is the same answer the planner gave while these forms were refused
2453    /// outright, so a schema this cannot read is slower and never wrong.
2454    ///
2455    /// It returns immediately for a table with neither kind of index, which is
2456    /// every table in the performance gate.
2457    ///
2458    /// @param id - the FROM term's statement-wide number
2459    fn attach_index_exprs(&mut self, id: usize) {
2460        let Some(source) = self.sources.get(id) else {
2461            return;
2462        };
2463        let table = std::rc::Rc::clone(&source.table);
2464        let wanted: Vec<usize> = table
2465            .indexes
2466            .iter()
2467            .enumerate()
2468            .filter(|(_, index)| {
2469                index.partial_sql.is_some()
2470                    || index.columns.iter().any(|key| key.expr_sql.is_some())
2471            })
2472            .map(|(position, _)| position)
2473            .collect();
2474        if wanted.is_empty() {
2475            return;
2476        }
2477        let alone = source.clone();
2478        let mut bound = Vec::with_capacity(wanted.len());
2479        for position in wanted {
2480            let Some(index) = table.indexes.get(position) else {
2481                continue;
2482            };
2483            let predicate = match index.partial_sql.as_ref() {
2484                Some(sql) => match self.bind_alone(&alone, sql) {
2485                    Some(expr) => Some(expr),
2486                    None => continue,
2487                },
2488                None => None,
2489            };
2490            let mut keys = Vec::with_capacity(index.columns.len());
2491            let mut readable = true;
2492            for key in &index.columns {
2493                match key.expr_sql.as_ref() {
2494                    Some(sql) => match self.bind_alone(&alone, sql) {
2495                        Some(expr) => keys.push(Some(expr)),
2496                        None => {
2497                            readable = false;
2498                            break;
2499                        }
2500                    },
2501                    None => keys.push(None),
2502                }
2503            }
2504            if !readable {
2505                continue;
2506            }
2507            bound.push(crate::dml::BoundIndexExprs {
2508                position,
2509                predicate,
2510                keys,
2511            });
2512        }
2513        if let Some(source) = self.sources.get_mut(id) {
2514            source.index_exprs = bound;
2515        }
2516    }
2517
2518    /// Binds one piece of schema text against a single FROM term.
2519    ///
2520    /// `None` when it does not parse or does not bind, which the caller reads
2521    /// as "this index cannot be reasoned about" rather than as an error.
2522    ///
2523    /// @param alone - the only term the expression may name
2524    /// @param sql - the expression as it was written in the schema
2525    fn bind_alone(&self, alone: &BoundSource, sql: &[u8]) -> Option<BoundExpr> {
2526        let limits = inillucent_base::limits::Limits::default();
2527        let (ast, expr) = crate::parser::parse_expression(sql, &limits).ok()?;
2528        let mut nested = Binder::new(self.catalog, &ast, self.authorizer);
2529        nested.trigger_depth = self.trigger_depth;
2530        // **The nested binder inherits what the connection registered, and
2531        // reads as a schema (task-1972).** It used to inherit neither, so an
2532        // index expression naming a registered function did not resolve at all
2533        // here and the planner silently left the index out; and had it
2534        // resolved, it would have resolved with a statement's permissions.
2535        nested.externals = self.externals;
2536        nested.collations = self.collations;
2537        nested.trusted_schema = self.trusted_schema;
2538        nested.call_site = function::CallSite::Schema;
2539        // **The term sits at its own id, not at zero (task-2078).** A column is
2540        // resolved by looking its term up in `sources` by statement-wide id,
2541        // and this list used to hold the one term at position zero. For the
2542        // first FROM term those agree. For every later one the lookup found
2543        // nothing, the expression did not bind, and the index was left out
2544        // without a word: `CREATE INDEX h_part ON h(c) WHERE c > 3` served
2545        // `FROM h, s WHERE h.c > 3` and not `FROM s, h WHERE h.c > 3`. The
2546        // positions below the term's are filled with copies of it, and the
2547        // scope names only the term's own id, so nothing can resolve to them.
2548        nested.sources = vec![alone.clone(); alone.id.saturating_add(1)];
2549        nested.scopes = vec![vec![alone.id]];
2550        nested.bind_expr(expr).ok()
2551    }
2552
2553    /// Binds one compound arm in a scope of its own.
2554    fn bind_isolated_arm(&mut self, arm: ast::SelectCoreId) -> Result<BoundSelect, ParseError> {
2555        let frame = self.enter_block();
2556        let mut bound = self.bind_arm(arm);
2557        // The arm owns whatever aggregates and correlations it accumulated, and
2558        // they have to be read off the binder before the frame is restored.
2559        if let Ok(bound) = bound.as_mut() {
2560            bound.aggregates = self.aggregates.clone();
2561            bound.windows = self.windows.clone();
2562            bound.correlations = self.correlations.clone();
2563        }
2564        let ids = self.leave_block(frame);
2565        let mut bound = bound?;
2566        bound.sources = ids
2567            .iter()
2568            .filter_map(|id| self.sources.get(*id).cloned())
2569            .collect();
2570        Ok(bound)
2571    }
2572
2573    /// Returns the next statement-wide number for a nested query used as a
2574    /// value.
2575    fn next_subquery_id(&mut self) -> usize {
2576        let id = self.subqueries;
2577        self.subqueries = self.subqueries.saturating_add(1);
2578        id
2579    }
2580
2581    /// Binds a nested query that is used as a value rather than as a source.
2582    ///
2583    /// It gets a scope of its own, so its own FROM terms shadow the enclosing
2584    /// query's, and a name it can only resolve outward is recorded as a
2585    /// correlation - which is what tells the compiler to rebuild it per row.
2586    fn bind_value_subquery(
2587        &mut self,
2588        select: SelectId,
2589        span: Span,
2590    ) -> Result<BoundSelect, ParseError> {
2591        let _ = span;
2592        self.bind_select(select)
2593    }
2594
2595    /// Binds `x IN (SELECT ...)`.
2596    fn bind_in_subquery(
2597        &mut self,
2598        operand: BoundExpr,
2599        select: SelectId,
2600        negated: bool,
2601        span: Span,
2602    ) -> Result<BoundExpr, ParseError> {
2603        let block = self.bind_value_subquery(select, span)?;
2604        if block.columns.len() != 1 {
2605            return Err(ParseError::new(
2606                ParseErrorKind::Unsupported("sub-select returns more than one column"),
2607                span,
2608            ));
2609        }
2610        let Some(column) = block.columns.first() else {
2611            return Err(unsupported("a subquery with no result column", span));
2612        };
2613        let (affinity, collation) = comparison_rules(&operand, &column.expr);
2614        Ok(BoundExpr::Subquery {
2615            id: self.next_subquery_id(),
2616            kind: SubqueryKind::In,
2617            negated,
2618            operand: Some(Box::new(operand)),
2619            block: Box::new(block),
2620            affinity,
2621            collation,
2622        })
2623    }
2624
2625    /// Binds a subquery FROM term and registers it as a source.
2626    fn bind_subquery_term(
2627        &mut self,
2628        select: SelectId,
2629        alias: Option<Vec<u8>>,
2630        columns: Vec<Vec<u8>>,
2631        join: JoinKind,
2632        span: Span,
2633    ) -> Result<(), ParseError> {
2634        let bound = self.bind_select(select)?;
2635        let alias = alias.unwrap_or_else(|| b"subquery".to_vec());
2636        self.push_subquery_source(bound, alias, columns, join, span)
2637    }
2638
2639    /// Registers a bound block as one FROM term of the current block.
2640    fn push_subquery_source(
2641        &mut self,
2642        bound: BoundSelect,
2643        alias: Vec<u8>,
2644        columns: Vec<Vec<u8>>,
2645        join: JoinKind,
2646        span: Span,
2647    ) -> Result<(), ParseError> {
2648        if !columns.is_empty() && columns.len() != bound.columns.len() {
2649            return Err(ParseError::new(
2650                ParseErrorKind::Unsupported("the named column list does not match the query"),
2651                span,
2652            ));
2653        }
2654        let table = subquery_table(&alias, &columns, &bound);
2655        let id = self.sources.len();
2656        self.sources.push(BoundSource {
2657            index_hint: crate::bind::IndexChoice::Any,
2658            id,
2659            rows: SourceRows::Subquery(Box::new(bound)),
2660            table: std::rc::Rc::new(table),
2661            alias,
2662            join,
2663            constraint: None,
2664            suppressed: Vec::new(),
2665            index_exprs: Vec::new(),
2666        });
2667        if let Some(scope) = self.scopes.last_mut() {
2668            scope.push(id);
2669        }
2670        Ok(())
2671    }
2672
2673    /// Records the named windows a `WINDOW` clause declares.
2674    fn declare_windows(
2675        &mut self,
2676        windows: &[(ast::NameId, ast::WindowId)],
2677    ) -> Result<(), ParseError> {
2678        for (name, window) in windows {
2679            self.named_windows
2680                .push((self.ast.folded(*name).to_vec(), *window));
2681        }
2682        Ok(())
2683    }
2684
2685    /// Binds a call carrying an `OVER` clause.
2686    ///
2687    /// The window is resolved first, because a call over a named window that
2688    /// does not exist is an error about the name rather than about the
2689    /// function - and because `OVER w` and `OVER (w ORDER BY x)` both have to
2690    /// end up as one fully-resolved specification before the frame defaults can
2691    /// be applied.
2692    fn bind_window_call(
2693        &mut self,
2694        name: ast::NameId,
2695        distinct: bool,
2696        arguments: Option<Vec<ExprId>>,
2697        filter: Option<ExprId>,
2698        over: ast::WindowId,
2699        span: Span,
2700    ) -> Result<BoundExpr, ParseError> {
2701        let folded = self.ast.folded(name).to_vec();
2702        let spec = self.resolve_window(over, span)?;
2703        let star = arguments.is_none();
2704        let mut bound_arguments = Vec::new();
2705        for argument in arguments.unwrap_or_default() {
2706            bound_arguments.push(self.bind_expr(argument)?);
2707        }
2708        let call = match function::lookup_window(&folded) {
2709            Some(func) => {
2710                let (least, most) = func.arity();
2711                if bound_arguments.len() < least || bound_arguments.len() > most {
2712                    return Err(wrong_arguments(&folded, span));
2713                }
2714                if distinct {
2715                    return Err(unsupported("DISTINCT in a window function", span));
2716                }
2717                WindowCall::Plain(func)
2718            }
2719            None => match window_aggregate(&folded, bound_arguments.len()) {
2720                Some(func) => WindowCall::Aggregate(func),
2721                None => return Err(no_such_function(&folded, span)),
2722            },
2723        };
2724        let bound_filter = match filter {
2725            Some(expr) => Some(self.bind_expr(expr)?),
2726            None => None,
2727        };
2728        let collation = bound_arguments
2729            .first()
2730            .and_then(BoundExpr::collation)
2731            .unwrap_or(Collation::Binary);
2732
2733        let mut partition_by = Vec::new();
2734        for expr in &spec.partition_by {
2735            partition_by.push(self.bind_expr(*expr)?);
2736        }
2737        let order_by = self.bind_order_by(&spec.order_by, &[], &[])?;
2738        // SQLite's defaults, and they are not the same clause: with an
2739        // `ORDER BY` the frame ends at the current row's peer group, and
2740        // without one it covers the whole partition. Using one default for both
2741        // makes every ordered `sum() OVER ()` a running total or none of them.
2742        let unit = spec.unit.unwrap_or(FrameUnit::Range);
2743        let (start, end) = match (spec.start, spec.end) {
2744            (None, None) => (
2745                BoundFrameBound::UnboundedPreceding,
2746                if order_by.is_empty() {
2747                    BoundFrameBound::UnboundedFollowing
2748                } else {
2749                    BoundFrameBound::CurrentRow
2750                },
2751            ),
2752            (Some(start), None) => (
2753                self.bind_frame_bound(start, span)?,
2754                BoundFrameBound::CurrentRow,
2755            ),
2756            (Some(start), Some(end)) => (
2757                self.bind_frame_bound(start, span)?,
2758                self.bind_frame_bound(end, span)?,
2759            ),
2760            (None, Some(end)) => (
2761                BoundFrameBound::UnboundedPreceding,
2762                self.bind_frame_bound(end, span)?,
2763            ),
2764        };
2765        if matches!(start, BoundFrameBound::UnboundedFollowing)
2766            || matches!(end, BoundFrameBound::UnboundedPreceding)
2767        {
2768            return Err(ParseError::new(
2769                ParseErrorKind::Unsupported("unsupported frame specification"),
2770                span,
2771            ));
2772        }
2773        // Only `RANGE` measures an offset in ordering values, so only `RANGE`
2774        // needs a single ordering term. A `GROUPS` offset counts peer groups,
2775        // which any number of terms defines, and SQLite accepts it with none.
2776        if unit == FrameUnit::Range
2777            && matches!(
2778                (&start, &end),
2779                (BoundFrameBound::Preceding(_), _)
2780                    | (BoundFrameBound::Following(_), _)
2781                    | (_, BoundFrameBound::Preceding(_))
2782                    | (_, BoundFrameBound::Following(_))
2783            )
2784            && order_by.len() != 1
2785        {
2786            return Err(ParseError::new(
2787                ParseErrorKind::Unsupported(
2788                    "RANGE with offset PRECEDING/FOLLOWING requires exactly one ORDER BY expression",
2789                ),
2790                span,
2791            ));
2792        }
2793        let slot = self.windows.len();
2794        let explicit = explicit_argument_collation(&bound_arguments);
2795        self.windows.push(BoundWindow {
2796            call,
2797            distinct,
2798            collation,
2799            arguments: bound_arguments,
2800            star,
2801            filter: bound_filter,
2802            partition_by,
2803            order_by,
2804            unit,
2805            start,
2806            end,
2807            exclude: spec.exclude,
2808        });
2809        Ok(BoundExpr::WindowRef {
2810            slot,
2811            collation: explicit,
2812        })
2813    }
2814
2815    /// Resolves an `OVER` clause into one fully-written window specification.
2816    fn resolve_window(&self, id: ast::WindowId, span: Span) -> Result<ast::Window, ParseError> {
2817        let Some(window) = self.ast.window(id) else {
2818            return Err(unsupported("missing window", span));
2819        };
2820        let mut spec = window.clone();
2821        let mut guard = 0usize;
2822        while let Some(base) = spec.base {
2823            guard = guard.saturating_add(1);
2824            if guard > MAX_COMPOUND_SELECT {
2825                return Err(unsupported("a window that inherits from itself", span));
2826            }
2827            let folded = self.ast.folded(base).to_vec();
2828            let Some((_, id)) = self.named_windows.iter().find(|(name, _)| *name == folded) else {
2829                return Err(no_such_window(&folded, span));
2830            };
2831            let Some(parent) = self.ast.window(*id) else {
2832                return Err(unsupported("missing window", span));
2833            };
2834            // The inheriting window may add an `ORDER BY` and a frame; it may
2835            // not replace the base's `PARTITION BY`, which is SQLite's rule and
2836            // the reason the merge is one-directional.
2837            let parent = parent.clone();
2838            spec.base = parent.base;
2839            spec.partition_by = parent.partition_by.clone();
2840            if spec.order_by.is_empty() {
2841                spec.order_by = parent.order_by.clone();
2842            }
2843            if spec.unit.is_none() {
2844                spec.unit = parent.unit;
2845                spec.start = parent.start;
2846                spec.end = parent.end;
2847                spec.exclude = parent.exclude;
2848            }
2849        }
2850        Ok(spec)
2851    }
2852
2853    /// Binds one end of a frame.
2854    fn bind_frame_bound(
2855        &mut self,
2856        bound: FrameBound,
2857        span: Span,
2858    ) -> Result<BoundFrameBound, ParseError> {
2859        let bound = match bound {
2860            FrameBound::UnboundedPreceding => BoundFrameBound::UnboundedPreceding,
2861            FrameBound::CurrentRow => BoundFrameBound::CurrentRow,
2862            FrameBound::UnboundedFollowing => BoundFrameBound::UnboundedFollowing,
2863            FrameBound::Preceding(expr) => {
2864                BoundFrameBound::Preceding(self.bind_frame_offset(expr, span)?)
2865            }
2866            FrameBound::Following(expr) => {
2867                BoundFrameBound::Following(self.bind_frame_offset(expr, span)?)
2868            }
2869        };
2870        Ok(bound)
2871    }
2872
2873    /// Binds a frame offset, which may not read a column.
2874    fn bind_frame_offset(&mut self, expr: ExprId, span: Span) -> Result<BoundExpr, ParseError> {
2875        let bound = self.bind_expr(expr)?;
2876        if !bound.is_constant() {
2877            return Err(ParseError::new(
2878                ParseErrorKind::Unsupported("a frame offset must be a constant"),
2879                span,
2880            ));
2881        }
2882        Ok(bound)
2883    }
2884
2885    /// Records that the statement depends on a database's schema cookie.
2886    fn record_dependency(&mut self, database: usize) {
2887        if self
2888            .dependencies
2889            .schemas
2890            .iter()
2891            .any(|(index, _)| *index == database)
2892        {
2893            return;
2894        }
2895        let cookie = self.catalog.schema_cookie(database);
2896        self.dependencies.schemas.push((database, cookie));
2897    }
2898
2899    /// Binds the result columns, expanding `*` and `table.*`.
2900    fn bind_result_columns(
2901        &mut self,
2902        columns: &[ast::ResultColumn],
2903    ) -> Result<Vec<BoundResultColumn>, ParseError> {
2904        // One column of the AST is usually one bound column, so this is the
2905        // right answer rather than a guess; `*` expands to more and the vector
2906        // grows from here, which is still fewer growths than starting empty.
2907        // `Vec::new` grew to four for a one-column select, which is 704 bytes
2908        // asked for to hold 176 (task-2026).
2909        let mut bound = Vec::with_capacity(columns.len());
2910        for column in columns {
2911            match self.ast.expr(column.expr) {
2912                Some(Expr::Star { table }) => {
2913                    let qualifier = table.map(|id| self.ast.folded(id).to_vec());
2914                    self.expand_star(qualifier.as_deref(), column.span, &mut bound)?;
2915                }
2916                _ => {
2917                    let expr = self.bind_expr(column.expr)?;
2918                    let name = match column.alias {
2919                        Some(alias) => self.ast.text(alias).to_vec(),
2920                        None => self.default_column_name(column.expr, &expr, column.span),
2921                    };
2922                    let (origin, declared_type) = self.column_origin(&expr);
2923                    bound.push(BoundResultColumn {
2924                        expr,
2925                        name,
2926                        origin,
2927                        declared_type,
2928                    });
2929                }
2930            }
2931        }
2932        if bound.is_empty() {
2933            return Err(unsupported(
2934                "a SELECT must have result columns",
2935                Span::default(),
2936            ));
2937        }
2938        Ok(bound)
2939    }
2940
2941    /// Turns a table-valued function's arguments into hidden-column equalities.
2942    ///
2943    /// The nth argument constrains the nth *hidden* column, which is the rule
2944    /// that makes `generate_series(1,5)` mean `start = 1 AND stop = 5`. More
2945    /// arguments than hidden columns is an error at bind time, because there is
2946    /// nothing for the extra one to constrain.
2947    fn bind_table_arguments(&mut self, arguments: &[ExprId], span: Span) -> Result<(), ParseError> {
2948        let Some(id) = self.scope().last().copied() else {
2949            return Err(unsupported("a table-valued function with no term", span));
2950        };
2951        let Some(source) = self.sources.get(id) else {
2952            return Err(unsupported("a table-valued function with no term", span));
2953        };
2954        if source.table.kind != TableKind::Virtual {
2955            return Err(unsupported(
2956                "arguments on a table that is not virtual",
2957                span,
2958            ));
2959        }
2960        let hidden: Vec<(u16, Affinity, Collation)> = source
2961            .table
2962            .columns
2963            .iter()
2964            .enumerate()
2965            .filter(|(_, column)| column.hidden)
2966            .map(|(index, column)| {
2967                (
2968                    index as u16,
2969                    column.affinity,
2970                    self.collation_named(&column.collation)
2971                        .unwrap_or(Collation::Binary),
2972                )
2973            })
2974            .collect();
2975        if arguments.len() > hidden.len() {
2976            return Err(wrong_arguments(&source.table.name.clone(), span));
2977        }
2978        for (position, argument) in arguments.iter().enumerate() {
2979            let Some((column, affinity, collation)) = hidden.get(position).copied() else {
2980                break;
2981            };
2982            let value = self.bind_expr(*argument)?;
2983            self.pending_constraints.push(BoundExpr::Compare {
2984                op: BinaryOp::Equal,
2985                left: Box::new(BoundExpr::Column {
2986                    source: id,
2987                    column,
2988                    slot: column,
2989                    affinity,
2990                    collation,
2991                }),
2992                right: Box::new(value),
2993                affinity: None,
2994                collation,
2995            });
2996        }
2997        Ok(())
2998    }
2999
3000    /// Returns the collation a name selects.
3001    ///
3002    /// A connection's own definitions come first, so an application that
3003    /// defines `NOCASE` gets its own rather than the built-in - which is what
3004    /// SQLite does, and is the only way `sqlite3_create_collation` can be used
3005    /// to change how an existing schema compares.
3006    fn collation_named(&self, name: &[u8]) -> Option<Collation> {
3007        // **The name is compared where it is (task-2026).** `create_collation`
3008        // stores the name uppercased, so an uppercase-insensitive comparison
3009        // against a stored name answers exactly what building an uppercase copy
3010        // of `name` and comparing bytes answered. Building the copy cost an
3011        // allocation per column reference, whether or not the connection had
3012        // registered any collation at all - two of the 109 allocations
3013        // `SELECT a FROM t WHERE id = ?1` made.
3014        if let Some((_, collation)) = self
3015            .collations
3016            .iter()
3017            .find(|(candidate, _)| candidate.as_bytes().eq_ignore_ascii_case(name))
3018        {
3019            return Some(*collation);
3020        }
3021        Collation::from_name(core::str::from_utf8(name).unwrap_or(""))
3022    }
3023
3024    /// Binds `f(table, ...)` as a module's auxiliary function, if that is what
3025    /// it is.
3026    ///
3027    /// The tell is the first argument: a bare reference to a virtual table's
3028    /// own hidden column, which is a thing no ordinary function is ever handed
3029    /// on purpose. `bm25(docs)` takes this path; an unknown name is refused by
3030    /// the module rather than here, because the module is what knows its own
3031    /// functions.
3032    fn bind_auxiliary_call(
3033        &mut self,
3034        name: &[u8],
3035        arguments: &[ExprId],
3036        span: Span,
3037    ) -> Result<Option<BoundExpr>, ParseError> {
3038        let Some(first) = arguments.first() else {
3039            return Ok(None);
3040        };
3041        let Some(&Expr::Column {
3042            database: None,
3043            table: None,
3044            column,
3045        }) = self.ast.expr(*first)
3046        else {
3047            return Ok(None);
3048        };
3049        let Ok(BoundExpr::Column { source, column, .. }) =
3050            self.bind_column_reference(None, None, column, span)
3051        else {
3052            return Ok(None);
3053        };
3054        let Some(entry) = self.sources.get(source) else {
3055            return Ok(None);
3056        };
3057        if entry.table.kind != TableKind::Virtual {
3058            return Ok(None);
3059        }
3060        // The self column is the hidden one named after the table, and only
3061        // that one: `rank` is a column, not a handle.
3062        let self_column = entry
3063            .table
3064            .column(column)
3065            .is_some_and(|info| info.folded == entry.table.folded);
3066        if !self_column {
3067            return Ok(None);
3068        }
3069        let mut rest = Vec::with_capacity(arguments.len() - 1);
3070        for argument in arguments.iter().skip(1) {
3071            rest.push(self.bind_expr(*argument)?);
3072        }
3073        Ok(Some(BoundExpr::VirtualFunction {
3074            source,
3075            name: name.to_ascii_lowercase(),
3076            arguments: rest,
3077        }))
3078    }
3079
3080    /// Returns whether an expression is a column of a virtual table.
3081    fn is_virtual_column(&self, expr: &BoundExpr) -> bool {
3082        let BoundExpr::Column { source, .. } = expr else {
3083            return false;
3084        };
3085        self.sources
3086            .get(*source)
3087            .is_some_and(|source| source.table.kind == TableKind::Virtual)
3088    }
3089
3090    /// Expands `*` or `table.*` into one bound column per visible column.
3091    ///
3092    /// Only the block's own FROM terms are expanded. An enclosing block's terms
3093    /// are visible to a *name*, which is what makes a subquery correlated, but
3094    /// they are not part of this block's `*`.
3095    fn expand_star(
3096        &mut self,
3097        qualifier: Option<&[u8]>,
3098        span: Span,
3099        into: &mut Vec<BoundResultColumn>,
3100    ) -> Result<(), ParseError> {
3101        let scope: Vec<usize> = self.scope().to_vec();
3102        if scope.is_empty() {
3103            return Err(ParseError::new(
3104                ParseErrorKind::Unexpected {
3105                    found: "*".to_string(),
3106                    expected: vec!["a FROM clause"],
3107                },
3108                span,
3109            ));
3110        }
3111        let mut matched = false;
3112        let scope_ids = scope.clone();
3113        for id in scope {
3114            let Some(source) = self.sources.get(id) else {
3115                continue;
3116            };
3117            if let Some(qualifier) = qualifier {
3118                if !source.alias.eq_ignore_ascii_case(qualifier) {
3119                    continue;
3120                }
3121            }
3122            matched = true;
3123            let columns = source.table.columns.clone();
3124            let suppressed = source.suppressed.clone();
3125            let database = self.catalog.database_name(source.table.database).to_vec();
3126            let table_name = source.table.name.clone();
3127            let synthetic = source.table.kind == TableKind::Subquery;
3128            for (index, column) in columns.iter().enumerate() {
3129                let position_u16 = index as u16;
3130                // A `USING` column is left out of a bare `*` only. `r.*` names
3131                // the term, and SQLite shows every column of it.
3132                if column.hidden || (qualifier.is_none() && suppressed.contains(&position_u16)) {
3133                    continue;
3134                }
3135                if self.authorizer.authorize(AuthAction::Read {
3136                    database: &database,
3137                    table: &table_name,
3138                    column: &column.name,
3139                }) == Authorization::Deny
3140                {
3141                    return Err(denied("not authorized", span));
3142                }
3143                // `l.*` goes through the same rule as `*`: SQLite expands a
3144                // column a later `USING` names as the bare name even when the
3145                // star is qualified, so `l.*` over `l FULL JOIN r USING (a)`
3146                // shows `coalesce(l.a, r.a)`.
3147                let expr = self.star_using_column(&scope_ids, id, position_u16, span)?;
3148                into.push(BoundResultColumn {
3149                    expr,
3150                    name: column.name.clone(),
3151                    // A subquery's column has no table of origin: it came from
3152                    // an expression, and reporting the synthetic name as one
3153                    // would make `sqlite3_column_table_name` invent a table.
3154                    origin: (!synthetic)
3155                        .then(|| (database.clone(), table_name.clone(), column.name.clone())),
3156                    declared_type: column.declared_type.clone(),
3157                });
3158            }
3159        }
3160        if !matched {
3161            return Err(no_such_table(qualifier.unwrap_or(b"*"), span));
3162        }
3163        Ok(())
3164    }
3165
3166    /// Returns the name an unaliased result column reports.
3167    ///
3168    /// A bare column reference is named after its declared name rather than
3169    /// the query's text - `rowid`/`oid`/`_rowid_` resolve to the column they
3170    /// alias and take its name too. Everything else keeps the source text.
3171    ///
3172    /// @param id - the expression as written
3173    /// @param bound - the expression, bound
3174    /// @param written - the result column's span, which ends where the next
3175    ///   token starts
3176    fn default_column_name(&self, id: ExprId, bound: &BoundExpr, written: Span) -> Vec<u8> {
3177        let name = match bound {
3178            BoundExpr::Column { source, column, .. } => self
3179                .sources
3180                .get(*source)
3181                .and_then(|held| held.table.column(*column)),
3182            BoundExpr::Rowid { source } => self
3183                .sources
3184                .get(*source)
3185                .and_then(|held| held.table.column(held.table.rowid_alias?)),
3186            _ => None,
3187        };
3188        if let Some(name) = name {
3189            return name.name.clone();
3190        }
3191        // **The three spellings of the rowid are one column name (task-1979,
3192        // F22).** `SELECT rowid, oid, _rowid_ FROM t` answers three columns
3193        // called `rowid` in SQLite, whichever way each was written. On a table
3194        // with no INTEGER PRIMARY KEY there is no declared column to take the
3195        // name from, and the fallback below took the text as typed, so the
3196        // last two came back called `oid` and `_rowid_` - names no caller
3197        // could match against the one SQLite reports.
3198        if matches!(bound, BoundExpr::Rowid { .. }) {
3199            return b"rowid".to_vec();
3200        }
3201        if let Some(Expr::Column { column, .. }) = self.ast.expr(id) {
3202            return self.ast.text(*column).to_vec();
3203        }
3204        // Everything else is named after the text it was written as,
3205        // exactly as written - `SELECT 1 +  2` has a column called
3206        // `1 +  2`, spaces and all, because SQLite cuts the span rather
3207        // than re-rendering the expression.
3208        //
3209        // **The span runs to where the next token starts**, so a comment
3210        // between the expression and the comma, the `FROM` or the end of the
3211        // statement is part of the name: `SELECT 1 -- trailing` has a column
3212        // called `1 -- trailing`. Only the whitespace at the end is trimmed,
3213        // which is what SQLite's `sqlite3DbSpanDup` does. The expression's
3214        // own span stopped at its last token and left the comment out.
3215        let start = self.ast.expr_span(id).start;
3216        let text = Span::new(start as usize, written.end as usize).slice(self.source);
3217        let kept = text
3218            .iter()
3219            .rposition(|byte| !byte.is_ascii_whitespace())
3220            .map_or(0, |last| last.saturating_add(1));
3221        text.get(..kept).unwrap_or(text).to_vec()
3222    }
3223
3224    /// Returns the origin triple and declared type of a bound column.
3225    fn column_origin(&self, expr: &BoundExpr) -> (Option<ColumnOrigin>, Vec<u8>) {
3226        // A rowid alias is a column, and `SELECT a FROM t` where `a` is the
3227        // INTEGER PRIMARY KEY binds to the rowid rather than to a record slot.
3228        // It still has an origin and a declared type, and reporting neither
3229        // made `sqlite3_column_decltype` empty for the commonest column there
3230        // is - and `PRAGMA table_info` on a view over one report no type.
3231        let expr = match expr {
3232            BoundExpr::Rowid { source } => {
3233                let alias = self
3234                    .sources
3235                    .get(*source)
3236                    .and_then(|source| source.table.rowid_alias);
3237                match alias {
3238                    Some(column) => &BoundExpr::Column {
3239                        source: *source,
3240                        column,
3241                        slot: column,
3242                        affinity: Affinity::Integer,
3243                        collation: Collation::Binary,
3244                    },
3245                    None => return (None, Vec::new()),
3246                }
3247            }
3248            other => other,
3249        };
3250        let BoundExpr::Column { source, column, .. } = expr else {
3251            return (None, Vec::new());
3252        };
3253        let Some(source) = self.sources.get(*source) else {
3254            return (None, Vec::new());
3255        };
3256        let Some(info) = source.table.column(*column) else {
3257            return (None, Vec::new());
3258        };
3259        (
3260            Some((
3261                self.catalog.database_name(source.table.database).to_vec(),
3262                source.table.name.clone(),
3263                info.name.clone(),
3264            )),
3265            info.declared_type.clone(),
3266        )
3267    }
3268
3269    /// Binds one `GROUP BY` term, which may be an ordinal or a result alias.
3270    fn bind_group_term(
3271        &mut self,
3272        id: ExprId,
3273        columns: &[BoundResultColumn],
3274    ) -> Result<BoundExpr, ParseError> {
3275        if let Some(index) = self.as_ordinal(id) {
3276            let Some(column) = columns.get(index.saturating_sub(1)) else {
3277                return Err(unsupported(
3278                    "GROUP BY term is out of range",
3279                    self.ast.expr_span(id),
3280                ));
3281            };
3282            return Ok(column.expr.clone());
3283        }
3284        self.bind_expr(id)
3285    }
3286
3287    /// Returns the one-based ordinal an expression is, if it is an integer.
3288    fn as_ordinal(&self, id: ExprId) -> Option<usize> {
3289        let Some(Expr::Literal(Literal::Integer(text))) = self.ast.expr(id) else {
3290            return None;
3291        };
3292        let mut value: usize = 0;
3293        for byte in text {
3294            if !byte.is_ascii_digit() {
3295                return None;
3296            }
3297            value = value
3298                .saturating_mul(10)
3299                .saturating_add(usize::from(byte.saturating_sub(b'0')));
3300        }
3301        Some(value)
3302    }
3303
3304    /// Binds an `ORDER BY` list, resolving ordinals and result aliases.
3305    ///
3306    /// @param terms - the terms as written
3307    /// @param columns - the result columns an ordinal or an alias names
3308    /// @param aliases - the written aliases, which a bare identifier matches
3309    ///   before a table column; see `bind::order_alias`
3310    fn bind_order_by(
3311        &mut self,
3312        terms: &[ast::OrderTerm],
3313        columns: &[BoundResultColumn],
3314        aliases: &[(Vec<u8>, usize)],
3315    ) -> Result<Vec<BoundOrderTerm>, ParseError> {
3316        let mut bound = Vec::with_capacity(terms.len());
3317        for term in terms {
3318            // A bare integer is an ordinal into the result columns; anything
3319            // else, including `1 + 0`, is an expression. SQLite draws the line
3320            // at a literal, and so does this.
3321            let expr = match self.as_ordinal(term.expr) {
3322                Some(ordinal) => {
3323                    let Some(column) = ordinal.checked_sub(1).and_then(|index| columns.get(index))
3324                    else {
3325                        return Err(order_out_of_range(ordinal, self.ast.expr_span(term.expr)));
3326                    };
3327                    column.expr.clone()
3328                }
3329                None => match self
3330                    .ordered_by_alias(term.expr, aliases)
3331                    .and_then(|at| columns.get(at))
3332                {
3333                    Some(column) => column.expr.clone(),
3334                    None => self.bind_expr(term.expr)?,
3335                },
3336            };
3337            let collation = expr.collation().unwrap_or(Collation::Binary);
3338            let nulls = term.nulls.unwrap_or(match term.order {
3339                // SQLite sorts NULLs first ascending and last descending when
3340                // no explicit null ordering is written.
3341                SortOrder::Ascending => NullOrder::First,
3342                SortOrder::Descending => NullOrder::Last,
3343            });
3344            bound.push(BoundOrderTerm {
3345                expr,
3346                order: term.order,
3347                nulls,
3348                collation,
3349            });
3350        }
3351        Ok(bound)
3352    }
3353
3354    /// Binds the `ORDER BY` written inside an aggregate's argument list.
3355    ///
3356    /// Not [`Binder::bind_order_by`]: that one resolves a bare integer as an
3357    /// ordinal into the *result columns*, which an aggregate's own `ORDER BY`
3358    /// has none of. `group_concat(b ORDER BY 1)` sorts by the literal 1 in
3359    /// SQLite, which is to say by nothing. A limited write uses it too.
3360    ///
3361    /// @param terms - the terms as written
3362    pub(crate) fn bind_aggregate_order(
3363        &mut self,
3364        terms: &[ast::OrderTerm],
3365    ) -> Result<Vec<BoundOrderTerm>, ParseError> {
3366        let mut bound = Vec::with_capacity(terms.len());
3367        for term in terms {
3368            let expr = self.bind_expr(term.expr)?;
3369            let collation = expr.collation().unwrap_or(Collation::Binary);
3370            let nulls = term.nulls.unwrap_or(match term.order {
3371                SortOrder::Ascending => NullOrder::First,
3372                SortOrder::Descending => NullOrder::Last,
3373            });
3374            bound.push(BoundOrderTerm {
3375                expr,
3376                order: term.order,
3377                nulls,
3378                collation,
3379            });
3380        }
3381        Ok(bound)
3382    }
3383
3384    /// Returns a bound column reference, checking the authorizer.
3385    fn column_expr(&mut self, source: usize, column: u16) -> Result<BoundExpr, ParseError> {
3386        let Some(bound) = self.sources.get(source) else {
3387            return Err(unsupported("unknown source", Span::default()));
3388        };
3389        let Some(info) = bound.table.column(column) else {
3390            return Err(unsupported("unknown column", Span::default()));
3391        };
3392        let affinity = info.affinity;
3393        let collation = self
3394            .collation_named(&info.collation)
3395            .unwrap_or(Collation::Binary);
3396        if bound.table.rowid_alias == Some(column) {
3397            // An INTEGER PRIMARY KEY column *is* the rowid, and reading it
3398            // through the record would read a NULL placeholder.
3399            return Ok(BoundExpr::Rowid { source });
3400        }
3401        // A `VIRTUAL` generated column is not in the record at all: it is its
3402        // own expression, so the reference is replaced by the expression here
3403        // and nothing below the binder ever sees the column.
3404        if info.generated && !info.stored {
3405            let Some(sql) = info.generated_sql.clone() else {
3406                return Err(unsupported(
3407                    "a generated column with no expression",
3408                    Span::default(),
3409                ));
3410            };
3411            self.generating = self.generating.saturating_add(1);
3412            if self.generating > MAX_GENERATED_DEPTH {
3413                self.generating = self.generating.saturating_sub(1);
3414                return Err(ParseError::new(
3415                    ParseErrorKind::Unsupported("a generated column refers to itself"),
3416                    Span::default(),
3417                ));
3418            }
3419            let bound = self.bind_schema_expr_for(source, &sql);
3420            self.generating = self.generating.saturating_sub(1);
3421            return bound;
3422        }
3423        let slot = bound
3424            .table
3425            .record_slot(column)
3426            .unwrap_or(usize::from(column)) as u16;
3427        Ok(BoundExpr::Column {
3428            source,
3429            column,
3430            slot,
3431            affinity,
3432            collation,
3433        })
3434    }
3435
3436    /// Binds a schema expression against one FROM term's scope.
3437    ///
3438    /// A generated column's expression names other columns of its own table, so
3439    /// it is bound with exactly that term visible and nothing else - a name it
3440    /// cannot resolve there is an error rather than something it picks up from
3441    /// the query that happened to read it.
3442    fn bind_schema_expr_for(&mut self, source: usize, sql: &[u8]) -> Result<BoundExpr, ParseError> {
3443        let saved = core::mem::replace(&mut self.scopes, vec![vec![source]]);
3444        let bound = self.bind_schema_expr(sql);
3445        self.scopes = saved;
3446        bound
3447    }
3448
3449    /// Binds a result-column list against the current sources.
3450    ///
3451    /// `RETURNING` is a result-column list over the row a DML statement wrote,
3452    /// so it is bound by the same code that binds a `SELECT` list rather than
3453    /// by a second implementation that would have to be kept in step with it.
3454    pub fn bind_result_columns_public(
3455        &mut self,
3456        columns: &[ast::ResultColumn],
3457    ) -> Result<Vec<BoundResultColumn>, ParseError> {
3458        self.bind_result_columns(columns)
3459    }
3460
3461    /// Records that the statement depends on a database's schema.
3462    pub(crate) fn record_write_dependency(&mut self, database: usize) {
3463        self.record_dependency(database);
3464    }
3465
3466    /// Binds a unary operator over one expression.
3467    ///
3468    /// **A negated integer literal is one literal, not an operator over one.**
3469    /// `-9223372036854775808` is the smallest integer there is; `9223372036854775808` on
3470    /// its own is one past the largest, so binding the operand first turned it into a real
3471    /// and the negation then produced `-9.2233720368547758e+18`. Every comparison, every
3472    /// affinity and every write of that value is a different value from the one that was
3473    /// written. SQLite folds the sign into the literal in its own parser for exactly this
3474    /// reason.
3475    ///
3476    /// @param op - the operator
3477    /// @param operand - the expression it applies to
3478    fn bind_unary(&mut self, op: UnaryOp, operand: ExprId) -> Result<BoundExpr, ParseError> {
3479        if op == UnaryOp::Negate {
3480            if let Some(Expr::Literal(Literal::Integer(text))) = self.ast.expr(operand) {
3481                let mut negated = Vec::with_capacity(text.len().saturating_add(1));
3482                negated.push(b'-');
3483                negated.extend_from_slice(text);
3484                return Ok(integer_literal(&negated));
3485            }
3486            // A negated real literal is folded the same way, as SQLite's
3487            // `codeReal` does. Unary minus on anything else is `0 - x`, and
3488            // `0 - 0.0` is a positive zero, so without this `-0.0` would lose
3489            // the sign SQLite keeps: `INSERT INTO t VALUES (-0.0)` into an ANY
3490            // column of a STRICT table reads back `-0.0`.
3491            if let Some(Expr::Literal(Literal::Float(text))) = self.ast.expr(operand) {
3492                let parsed =
3493                    inillucent_value::numeric::atof(text, inillucent_value::TextEncoding::Utf8);
3494                return Ok(BoundExpr::Real(-parsed.value));
3495            }
3496        }
3497        let operand = Box::new(self.bind_expr(operand)?);
3498        match op {
3499            UnaryOp::Not => Ok(BoundExpr::Not(operand)),
3500            _ => Ok(BoundExpr::Unary { op, operand }),
3501        }
3502    }
3503
3504    /// Binds one expression.
3505    pub fn bind_expr(&mut self, id: ExprId) -> Result<BoundExpr, ParseError> {
3506        let span = self.ast.expr_span(id);
3507        let Some(expr) = self.ast.expr(id) else {
3508            return Err(unsupported("missing expression", span));
3509        };
3510        // **A literal is bound off the arena, before the clone** (task-2006). `Literal`
3511        // owns its digits, so `SELECT 1` allocated one byte to copy the byte `1` in order
3512        // to match on it, and a statement full of literals paid that per literal. The
3513        // clone below is a borrow split rather than a choice - the arms call `&mut self`
3514        // methods and need the owned names and sub-expression lists their variants hold -
3515        // but a literal needs neither.
3516        if let Expr::Literal(literal) = expr {
3517            return self.bind_literal(literal, span);
3518        }
3519        match expr.clone() {
3520            Expr::Literal(literal) => self.bind_literal(&literal, span),
3521            Expr::Parameter { index, .. } => Ok(BoundExpr::Parameter(index)),
3522            Expr::Column {
3523                database,
3524                table,
3525                column,
3526            } => self.bind_column_reference(database, table, column, span),
3527            Expr::Star { .. } => Err(ParseError::new(
3528                ParseErrorKind::Unexpected {
3529                    found: "*".to_string(),
3530                    expected: vec!["an expression"],
3531                },
3532                span,
3533            )),
3534            Expr::Unary { op, operand } => self.bind_unary(op, operand),
3535            Expr::Binary { op, left, right } => self.bind_binary(op, left, right),
3536            Expr::Collate { operand, collation } => {
3537                let name = self.ast.text(collation);
3538                let Some(collation) = self.collation_named(name) else {
3539                    return Err(no_such_collation(name, span));
3540                };
3541                let bound = self.bind_expr(operand)?;
3542                Ok(apply_collation(bound, collation))
3543            }
3544            Expr::Cast { operand, declared } => {
3545                let operand = Box::new(self.bind_expr(operand)?);
3546                let affinity =
3547                    inillucent_value::affinity::affinity_of_declared_type(self.ast.text(declared));
3548                Ok(BoundExpr::Cast { operand, affinity })
3549            }
3550            Expr::Pattern {
3551                negated,
3552                op,
3553                operand,
3554                pattern,
3555                escape,
3556            } => {
3557                if op == PatternOp::Regexp {
3558                    // `X REGEXP Y` is sugar for `regexp(Y, X)` - the pattern
3559                    // first - and the operator exists only because the function
3560                    // does. The reference shell registers one, so this engine
3561                    // registers one too, and the operator binds to it here
3562                    // rather than refusing.
3563                    let subject = self.bind_expr(operand)?;
3564                    let pattern = self.bind_expr(pattern)?;
3565                    let call = BoundExpr::Function {
3566                        func: ScalarFunc::Regexp,
3567                        arguments: vec![pattern, subject],
3568                        collation: Collation::Binary,
3569                    };
3570                    return Ok(if negated {
3571                        BoundExpr::Not(Box::new(call))
3572                    } else {
3573                        call
3574                    });
3575                }
3576                if op == PatternOp::Match {
3577                    // `x MATCH y` is a call to a function called `match`, which
3578                    // does not exist - unless `x` is a column of a virtual
3579                    // table, in which case it is a constraint the module is
3580                    // offered and the module says what it means. That is the
3581                    // whole of how `t MATCH 'word'` reaches FTS5.
3582                    let left = self.bind_expr(operand)?;
3583                    if !self.is_virtual_column(&left) {
3584                        return Err(no_such_function(b"match", span));
3585                    }
3586                    let pattern = Box::new(self.bind_expr(pattern)?);
3587                    return Ok(BoundExpr::Pattern {
3588                        negated,
3589                        op: PatternOp::Match,
3590                        operand: Box::new(left),
3591                        pattern,
3592                        escape: None,
3593                    });
3594                }
3595                let operand = Box::new(self.bind_expr(operand)?);
3596                let pattern = Box::new(self.bind_expr(pattern)?);
3597                let escape = match escape {
3598                    Some(expr) => Some(Box::new(self.bind_expr(expr)?)),
3599                    None => None,
3600                };
3601                Ok(BoundExpr::Pattern {
3602                    negated,
3603                    op,
3604                    operand,
3605                    pattern,
3606                    escape,
3607                })
3608            }
3609            Expr::Between {
3610                negated,
3611                operand,
3612                low,
3613                high,
3614            } => {
3615                if let Some(parts) = self.row_value_parts(operand) {
3616                    return self.bind_row_between(negated, &parts, low, high, span);
3617                }
3618                let operand = self.bind_expr(operand)?;
3619                let low = self.bind_expr(low)?;
3620                let high = self.bind_expr(high)?;
3621                let (low_affinity, low_collation) = comparison_rules(&operand, &low);
3622                let (high_affinity, high_collation) = comparison_rules(&operand, &high);
3623                Ok(BoundExpr::Between {
3624                    negated,
3625                    operand: Box::new(operand),
3626                    low: Box::new(low),
3627                    high: Box::new(high),
3628                    low_affinity,
3629                    low_collation,
3630                    high_affinity,
3631                    high_collation,
3632                })
3633            }
3634            Expr::In {
3635                negated,
3636                operand,
3637                rhs,
3638            } => {
3639                // **The row-value `IN` form is an OR of equality chains**, which
3640                // is exactly what SQLite's `IN` over a value list means: `(a, b)
3641                // IN (VALUES (1,2),(3,4))` is `(a=1 AND b=2) OR (a=3 AND b=4)`,
3642                // with the same unknown-rather-than-false behaviour when a part
3643                // is NULL. The rows are written as a `VALUES` clause, which the
3644                // grammar parses as a select, so the desugaring reads them back
3645                // out of it rather than adding a second spelling.
3646                if let Some(parts) = self.row_value_parts(operand) {
3647                    return self.bind_row_in(&parts, &rhs, negated, span);
3648                }
3649                let operand = self.bind_expr(operand)?;
3650                let rhs = match rhs {
3651                    InRhs::Select(select) => {
3652                        return self.bind_in_subquery(operand, select, negated, span)
3653                    }
3654                    InRhs::Table { .. } => {
3655                        return Err(unsupported("IN over a table name", span));
3656                    }
3657                    other => other,
3658                };
3659                let InRhs::List(items) = rhs else {
3660                    return Err(unsupported("IN over a subquery or table", span));
3661                };
3662                let mut list = Vec::with_capacity(items.len());
3663                for item in &items {
3664                    list.push(self.bind_expr(*item)?);
3665                }
3666                let (affinity, collation) = match list.first() {
3667                    Some(first) => comparison_rules(&operand, first),
3668                    None => (None, Collation::Binary),
3669                };
3670                Ok(BoundExpr::InList {
3671                    negated,
3672                    operand: Box::new(operand),
3673                    list,
3674                    affinity,
3675                    collation,
3676                })
3677            }
3678            Expr::IsNull { negated, operand } => Ok(BoundExpr::IsNull {
3679                negated,
3680                operand: Box::new(self.bind_expr(operand)?),
3681            }),
3682            Expr::Is {
3683                negated,
3684                distinct_from,
3685                left,
3686                right,
3687            } => {
3688                if let (Some(lefts), Some(rights)) =
3689                    (self.row_value_parts(left), self.row_value_parts(right))
3690                {
3691                    return self.bind_row_is(negated != distinct_from, &lefts, &rights, span);
3692                }
3693                let left = self.bind_expr(left)?;
3694                let right = self.bind_expr(right)?;
3695                let (affinity, collation) = comparison_rules(&left, &right);
3696                // **`DISTINCT FROM` inverts the sense, and it was being
3697                // dropped.** `a IS b` is already NULL-safe equality, so
3698                // `a IS NOT DISTINCT FROM b` is `a IS b` and
3699                // `a IS DISTINCT FROM b` is `a IS NOT b`. Binding the keyword
3700                // away left `1 IS DISTINCT FROM NULL` meaning `1 IS NULL` -
3701                // 0 where SQLite answers 1, and 0 again for
3702                // `1 IS NOT DISTINCT FROM 1`, so both spellings answered the
3703                // opposite of the truth.
3704                let negated = negated != distinct_from;
3705                Ok(BoundExpr::Is {
3706                    negated,
3707                    left: Box::new(left),
3708                    right: Box::new(right),
3709                    affinity,
3710                    collation,
3711                })
3712            }
3713            Expr::Case {
3714                operand,
3715                branches,
3716                otherwise,
3717            } => {
3718                if let Some(parts) = operand.and_then(|operand| self.row_value_parts(operand)) {
3719                    return self.bind_row_case(&parts, &branches, otherwise, span);
3720                }
3721                let bound_operand = match operand {
3722                    Some(expr) => Some(Box::new(self.bind_expr(expr)?)),
3723                    None => None,
3724                };
3725                let mut bound_branches = Vec::with_capacity(branches.len());
3726                for (when, then) in &branches {
3727                    bound_branches.push((self.bind_expr(*when)?, self.bind_expr(*then)?));
3728                }
3729                let bound_otherwise = match otherwise {
3730                    Some(expr) => Some(Box::new(self.bind_expr(expr)?)),
3731                    None => None,
3732                };
3733                let comparisons = match &bound_operand {
3734                    Some(operand) => bound_branches
3735                        .iter()
3736                        .map(|(when, _)| comparison_rules(operand, when))
3737                        .collect(),
3738                    None => Vec::new(),
3739                };
3740                Ok(BoundExpr::Case {
3741                    operand: bound_operand,
3742                    branches: bound_branches,
3743                    otherwise: bound_otherwise,
3744                    comparisons,
3745                })
3746            }
3747            Expr::Function {
3748                name,
3749                distinct,
3750                arguments,
3751                order_by,
3752                filter,
3753                over,
3754            } => {
3755                if let Some(over) = over {
3756                    return self.bind_window_call(name, distinct, arguments, filter, over, span);
3757                }
3758                // **`FILTER` and an in-argument `ORDER BY` belong to the
3759                // aggregate, not to the window.** Both were refused here, so
3760                // `count(*) FILTER (WHERE a > 15)` and
3761                // `group_concat(b ORDER BY a DESC)` - two shapes an ordinary
3762                // report is written in - could not be asked at all. They are
3763                // bound onto the call and applied by the accumulator.
3764                self.bind_call_with(name, distinct, arguments, filter, &order_by, span)
3765            }
3766            Expr::Exists { negated, select } => {
3767                let block = self.bind_value_subquery(select, span)?;
3768                Ok(BoundExpr::Subquery {
3769                    id: self.next_subquery_id(),
3770                    kind: SubqueryKind::Exists,
3771                    negated,
3772                    operand: None,
3773                    block: Box::new(block),
3774                    affinity: None,
3775                    collation: Collation::Binary,
3776                })
3777            }
3778            Expr::Subquery(select) => {
3779                let block = self.bind_value_subquery(select, span)?;
3780                if block.columns.len() != 1 {
3781                    return Err(ParseError::new(
3782                        ParseErrorKind::Unsupported("sub-select returns more than one column"),
3783                        span,
3784                    ));
3785                }
3786                Ok(BoundExpr::Subquery {
3787                    id: self.next_subquery_id(),
3788                    kind: SubqueryKind::Scalar,
3789                    negated: false,
3790                    operand: None,
3791                    block: Box::new(block),
3792                    affinity: None,
3793                    collation: Collation::Binary,
3794                })
3795            }
3796            // **A row value anywhere else is SQLite's "row value misused"**, a
3797            // refusal with code 1 about the statement. Every place SQLite
3798            // takes a row value - a comparison, `IS`, `BETWEEN`, `IN`, a
3799            // `CASE` operand and a `SET` list - is handled before this is
3800            // reached, so what is left is a statement SQLite refuses too, and
3801            // reporting it as a feature not built yet told a caller to wait
3802            // for something that will never come.
3803            Expr::RowValue(_) => Err(rowvalue::misused(span)),
3804            Expr::Raise { action, message } => self.bind_raise(action, message, span),
3805        }
3806    }
3807
3808    /// Binds a literal, converting its written text into a value.
3809    fn bind_literal(&self, literal: &Literal, _span: Span) -> Result<BoundExpr, ParseError> {
3810        match literal {
3811            Literal::Null => Ok(BoundExpr::Null),
3812            Literal::Boolean(value) => Ok(BoundExpr::Integer(i64::from(*value))),
3813            Literal::Integer(text) => Ok(integer_literal(text)),
3814            Literal::Float(text) => {
3815                let parsed =
3816                    inillucent_value::numeric::atof(text, inillucent_value::TextEncoding::Utf8);
3817                Ok(BoundExpr::Real(parsed.value))
3818            }
3819            Literal::String(text) => Ok(BoundExpr::Text(text.clone())),
3820            Literal::Blob(bytes) => Ok(BoundExpr::Blob(bytes.clone())),
3821            Literal::CurrentDate | Literal::CurrentTime | Literal::CurrentTimestamp => {
3822                // The three keywords are the three functions with no argument,
3823                // and `CURRENT_TIMESTAMP` is `datetime('now')` rather than a
3824                // fourth thing that formats differently.
3825                let func = match literal {
3826                    Literal::CurrentDate => TimeFunc::Date,
3827                    Literal::CurrentTime => TimeFunc::Time,
3828                    _ => TimeFunc::DateTime,
3829                };
3830                Ok(BoundExpr::Time {
3831                    func,
3832                    arguments: Vec::new(),
3833                })
3834            }
3835        }
3836    }
3837
3838    /// Resolves `excluded.column` inside an upsert's `DO UPDATE`.
3839    ///
3840    /// `excluded` is only in scope there, so a query that uses the name
3841    /// anywhere else gets the ordinary "no such table" answer rather than a
3842    /// row that came from nowhere.
3843    fn bind_excluded_column(&mut self, folded: &[u8], span: Span) -> Result<BoundExpr, ParseError> {
3844        let Some(table) = self.excluded.clone() else {
3845            return Err(no_such_table(b"excluded", span));
3846        };
3847        if let Some(position) = table.column_position(folded) {
3848            if table.rowid_alias == Some(position) {
3849                return Ok(BoundExpr::Rowid {
3850                    source: EXCLUDED_SOURCE,
3851                });
3852            }
3853            let Some(info) = table.column(position) else {
3854                return Err(no_such_column(folded, span));
3855            };
3856            let collation = self
3857                .collation_named(&info.collation)
3858                .unwrap_or(Collation::Binary);
3859            return Ok(BoundExpr::Column {
3860                source: EXCLUDED_SOURCE,
3861                column: position,
3862                // `excluded` is a row in registers rather than a record, so the
3863                // compiler substitutes it wholesale and the slot is never read.
3864                slot: position,
3865                affinity: info.affinity,
3866                collation,
3867            });
3868        }
3869        if table.is_rowid_name(folded) {
3870            return Ok(BoundExpr::Rowid {
3871                source: EXCLUDED_SOURCE,
3872            });
3873        }
3874        Err(no_such_column(folded, span))
3875    }
3876
3877    /// Resolves `old.column` or `new.column` inside a trigger body.
3878    ///
3879    /// The event decides which of the two exists: an INSERT has no previous row
3880    /// and a DELETE has no next one. Naming the missing one is the ordinary
3881    /// "no such table" error, because that is what it is - outside a trigger
3882    /// body neither name resolves at all.
3883    fn bind_row_alias_column(
3884        &mut self,
3885        source: usize,
3886        folded: &[u8],
3887        span: Span,
3888    ) -> Result<BoundExpr, ParseError> {
3889        let written: &[u8] = if source == OLD_SOURCE { b"old" } else { b"new" };
3890        let Some(aliases) = self.row_aliases.clone() else {
3891            return Err(no_such_table(written, span));
3892        };
3893        let available = if source == OLD_SOURCE {
3894            aliases.old
3895        } else {
3896            aliases.new
3897        };
3898        if !available {
3899            return Err(no_such_table(written, span));
3900        }
3901        let table = &aliases.table;
3902        if let Some(position) = table.column_position(folded) {
3903            if table.rowid_alias == Some(position) {
3904                return Ok(BoundExpr::Rowid { source });
3905            }
3906            let Some(info) = table.column(position) else {
3907                return Err(no_such_column(folded, span));
3908            };
3909            let collation = self
3910                .collation_named(&info.collation)
3911                .unwrap_or(Collation::Binary);
3912            return Ok(BoundExpr::Column {
3913                source,
3914                column: position,
3915                // The row lives in registers rather than in a record, so the
3916                // compiler substitutes it wholesale and the slot is never read.
3917                slot: position,
3918                affinity: info.affinity,
3919                collation,
3920            });
3921        }
3922        if table.is_rowid_name(folded) {
3923            return Ok(BoundExpr::Rowid { source });
3924        }
3925        Err(no_such_column(folded, span))
3926    }
3927
3928    /// Resolves a column reference against the scope stack.
3929    ///
3930    /// The innermost block is searched first and a hit there ends the search,
3931    /// so an inner name shadows an outer one. A hit in an enclosing block is
3932    /// recorded as a correlation, which is the fact the compiler uses to decide
3933    /// whether the block runs once or once per outer row.
3934    fn bind_column_reference(
3935        &mut self,
3936        database: Option<ast::NameId>,
3937        table: Option<ast::NameId>,
3938        column: ast::NameId,
3939        span: Span,
3940    ) -> Result<BoundExpr, ParseError> {
3941        let folded = self.ast.folded(column).to_vec();
3942        let table_folded = table.map(|id| self.ast.folded(id).to_vec());
3943        let database_folded = database.map(|id| self.ast.folded(id).to_vec());
3944        if table_folded.as_deref() == Some(b"excluded".as_slice()) {
3945            return self.bind_excluded_column(&folded, span);
3946        }
3947        // `OLD` and `NEW` shadow a table of the same name only inside a trigger
3948        // body, which is the one place they mean anything.
3949        if self.row_aliases.is_some() && database.is_none() {
3950            match table_folded.as_deref() {
3951                Some(b"old") => return self.bind_row_alias_column(OLD_SOURCE, &folded, span),
3952                Some(b"new") => return self.bind_row_alias_column(NEW_SOURCE, &folded, span),
3953                _ => {}
3954            }
3955        }
3956        let mut resolved: Option<(usize, u16)> = None;
3957        let mut rowid_of: Option<usize> = None;
3958        let levels = self.scopes.len();
3959        for level in (0..levels).rev() {
3960            let ids: Vec<usize> = self
3961                .scopes
3962                .get(level)
3963                .map_or(Vec::new(), |scope| scope.clone());
3964            let mut found: Option<(usize, u16)> = None;
3965            let mut coalesced: Vec<(usize, u16)> = Vec::new();
3966            let mut rowid_here: Option<usize> = None;
3967            for id in ids {
3968                let Some(source) = self.sources.get(id) else {
3969                    continue;
3970                };
3971                if let Some(qualifier) = table_folded.as_deref() {
3972                    if !source.alias.eq_ignore_ascii_case(qualifier) {
3973                        continue;
3974                    }
3975                }
3976                if let Some(qualifier) = database_folded.as_deref() {
3977                    if !self
3978                        .catalog
3979                        .database_name(source.table.database)
3980                        .eq_ignore_ascii_case(qualifier)
3981                    {
3982                        continue;
3983                    }
3984                }
3985                if let Some(index) = source.table.column_position(&folded) {
3986                    // **A `USING` or `NATURAL` join coalesces the named
3987                    // column.** The join has one `k`, not two: it comes from
3988                    // the left term, and the right term's copy is suppressed -
3989                    // from `*`, which this already did, and from an
3990                    // *unqualified* reference, which it did not. That is why
3991                    // `SELECT * FROM a JOIN b USING (k) ORDER BY k` answered
3992                    // `ambiguous column name: k`, and why four of the five join
3993                    // spellings failed on one message. A qualified `b.k` still
3994                    // reaches the right-hand copy, which is what SQLite does.
3995                    //
3996                    // **A `RIGHT` or `FULL` join is the exception.** Its left
3997                    // copy is NULL on a row only the right side has, so SQLite
3998                    // resolves the name to the right copy under `RIGHT` and to
3999                    // `coalesce()` of every copy under `FULL`; see
4000                    // `step_using_match`.
4001                    if table_folded.is_none() && source.suppressed.contains(&index) {
4002                        using::step_using_match(
4003                            source.join,
4004                            (id, index),
4005                            &mut found,
4006                            &mut coalesced,
4007                        );
4008                        continue;
4009                    }
4010                    if found.is_some() {
4011                        return Err(ambiguous_column(self.ast.text(column), span));
4012                    }
4013                    found = Some((id, index));
4014                    continue;
4015                }
4016                if source.table.is_rowid_name(&folded) && rowid_here.is_none() {
4017                    rowid_here = Some(id);
4018                }
4019            }
4020            if coalesced.len() > 1 {
4021                return self.coalesce_using_copies(&coalesced, span);
4022            }
4023            if found.is_some() {
4024                resolved = found;
4025                break;
4026            }
4027            if let Some(id) = rowid_here {
4028                rowid_of = Some(id);
4029                break;
4030            }
4031        }
4032        if let Some((source, index)) = resolved {
4033            return self.authorized_column(source, index, span);
4034        }
4035        if let Some(source) = rowid_of {
4036            self.note_correlation(source);
4037            return Ok(BoundExpr::Rowid { source });
4038        }
4039        // A result alias is visible to GROUP BY, HAVING and ORDER BY, and only
4040        // after a real column has failed to match, which is SQLite's order.
4041        if table_folded.is_none() {
4042            if let Some((_, expr)) = self
4043                .result_aliases
4044                .iter()
4045                .find(|(name, _)| name.as_slice() == folded.as_slice())
4046            {
4047                return Ok(expr.clone());
4048            }
4049        }
4050        if self.sources.is_empty() && table_folded.is_none() {
4051            return Err(no_such_column_quoted(
4052                self.ast.text(column),
4053                self.ast
4054                    .name(column)
4055                    .map(|name| name.quote)
4056                    .unwrap_or(QuoteForm::Bare),
4057                span,
4058            ));
4059        }
4060        match table_folded {
4061            Some(_)
4062                if !self.sources.iter().any(|source| {
4063                    table_folded
4064                        .as_deref()
4065                        .is_some_and(|q| source.alias.eq_ignore_ascii_case(q))
4066                }) =>
4067            {
4068                Err(no_such_table(
4069                    table.map(|id| self.ast.text(id)).unwrap_or(b""),
4070                    span,
4071                ))
4072            }
4073            _ if table_folded.is_none() => Err(no_such_column_quoted(
4074                self.ast.text(column),
4075                self.ast
4076                    .name(column)
4077                    .map(|name| name.quote)
4078                    .unwrap_or(QuoteForm::Bare),
4079                span,
4080            )),
4081            // A qualified reference names both halves, which is what the
4082            // reference prints: `no such column: t.b`, not `no such column: b`.
4083            _ => {
4084                let qualifier = table.map(|id| self.ast.text(id)).unwrap_or(b"");
4085                Err(no_such_column(
4086                    &[qualifier, b".", self.ast.text(column)].concat(),
4087                    span,
4088                ))
4089            }
4090        }
4091    }
4092
4093    /// Returns a column reference the authorizer has been asked about.
4094    ///
4095    /// The authorizer may allow the read, refuse the statement, or ask for
4096    /// the column to read as NULL, which is what `Ignore` means in SQLite.
4097    ///
4098    /// @param source - the source id the column belongs to
4099    /// @param index - the column's position in that source
4100    /// @param span - where the reference is, for an error
4101    pub(super) fn authorized_column(
4102        &mut self,
4103        source: usize,
4104        index: u16,
4105        span: Span,
4106    ) -> Result<BoundExpr, ParseError> {
4107        let (database_name, table_name, column_name) = {
4108            let Some(bound) = self.sources.get(source) else {
4109                return Err(unsupported("unknown source", span));
4110            };
4111            let Some(info) = bound.table.column(index) else {
4112                return Err(unsupported("unknown column", span));
4113            };
4114            (
4115                self.catalog.database_name(bound.table.database).to_vec(),
4116                bound.table.name.clone(),
4117                info.name.clone(),
4118            )
4119        };
4120        match self.authorizer.authorize(AuthAction::Read {
4121            database: &database_name,
4122            table: &table_name,
4123            column: &column_name,
4124        }) {
4125            Authorization::Allow => {}
4126            Authorization::Deny => return Err(denied("not authorized", span)),
4127            Authorization::Ignore => return Ok(BoundExpr::Null),
4128        }
4129        self.note_correlation(source);
4130        self.column_expr(source, index)
4131    }
4132
4133    /// Binds a binary operator, choosing comparison or arithmetic semantics.
4134    fn bind_binary(
4135        &mut self,
4136        op: BinaryOp,
4137        left: ExprId,
4138        right: ExprId,
4139    ) -> Result<BoundExpr, ParseError> {
4140        // **A row-value comparison is a comparison of its parts.** `(a, b) =
4141        // (1, 2)` is `a = 1 AND b = 2`, and the ordering operators are
4142        // lexicographic - `(a, b) < (x, y)` is `a < x OR (a = x AND b < y)`,
4143        // which is where the NULL behaviour comes from rather than being a rule
4144        // of its own. It is desugared here rather than carried into the plan
4145        // because there is nothing about it the executor would do differently:
4146        // the parts are ordinary comparisons over ordinary expressions.
4147        if let (Some(lefts), Some(rights)) =
4148            (self.row_value_parts(left), self.row_value_parts(right))
4149        {
4150            return self.bind_row_comparison(op, &lefts, &rights, self.ast.expr_span(left));
4151        }
4152        // **A row value against a query**, which is the form an application
4153        // actually writes: `WHERE (a, b) = (SELECT a, b FROM t WHERE id = 3)`.
4154        // Only the row-against-a-row spelling was desugared, so this was
4155        // `unsupported: row values`.
4156        if let (Some(lefts), Some(select)) = (
4157            self.row_value_parts(left),
4158            self.ast.expr(right).and_then(|expr| match expr {
4159                Expr::Subquery(select) => Some(*select),
4160                _ => None,
4161            }),
4162        ) {
4163            return self.bind_row_against_query(op, &lefts, select, self.ast.expr_span(left));
4164        }
4165        let bound_left = self.bind_expr(left)?;
4166        let bound_right = self.bind_expr(right)?;
4167        match op {
4168            BinaryOp::And => Ok(BoundExpr::And(Box::new(bound_left), Box::new(bound_right))),
4169            BinaryOp::Or => Ok(BoundExpr::Or(Box::new(bound_left), Box::new(bound_right))),
4170            BinaryOp::Equal
4171            | BinaryOp::NotEqual
4172            | BinaryOp::Less
4173            | BinaryOp::LessEqual
4174            | BinaryOp::Greater
4175            | BinaryOp::GreaterEqual => {
4176                let (affinity, collation) = comparison_rules(&bound_left, &bound_right);
4177                Ok(BoundExpr::Compare {
4178                    op,
4179                    left: Box::new(bound_left),
4180                    right: Box::new(bound_right),
4181                    affinity,
4182                    collation,
4183                })
4184            }
4185            BinaryOp::Regexp => Ok(BoundExpr::Function {
4186                func: ScalarFunc::Regexp,
4187                arguments: vec![bound_right, bound_left],
4188                collation: Collation::Binary,
4189            }),
4190            // **pgvector's distance operators are sugar for the functions**,
4191            // which is exactly what they are in pgvector too: an operator class
4192            // over a function, so that an index can be asked for the same
4193            // ordering the expression writes. `<#>` is the odd one, and it is
4194            // odd in pgvector as well - it answers the *negative* inner product,
4195            // so that a smaller number is a better match and one index
4196            // direction serves every operator.
4197            BinaryOp::L2Distance
4198            | BinaryOp::CosineDistance
4199            | BinaryOp::L1Distance
4200            | BinaryOp::HammingDistance
4201            | BinaryOp::JaccardDistance => Ok(BoundExpr::Function {
4202                func: match op {
4203                    BinaryOp::L2Distance => ScalarFunc::VectorDistanceL2,
4204                    BinaryOp::CosineDistance => ScalarFunc::VectorDistanceCos,
4205                    BinaryOp::L1Distance => ScalarFunc::VectorDistanceL1,
4206                    BinaryOp::HammingDistance => ScalarFunc::VectorDistanceHamming,
4207                    _ => ScalarFunc::VectorDistanceJaccard,
4208                },
4209                arguments: vec![bound_left, bound_right],
4210                collation: Collation::Binary,
4211            }),
4212            BinaryOp::NegativeInnerProduct => Ok(BoundExpr::Unary {
4213                op: UnaryOp::Negate,
4214                operand: Box::new(BoundExpr::Function {
4215                    func: ScalarFunc::VectorDot,
4216                    arguments: vec![bound_left, bound_right],
4217                    collation: Collation::Binary,
4218                }),
4219            }),
4220            BinaryOp::Match => Err(no_such_function(b"match", self.ast.expr_span(right))),
4221            BinaryOp::Extract | BinaryOp::ExtractText => Ok(BoundExpr::Json {
4222                func: if op == BinaryOp::Extract {
4223                    JsonFunc::Arrow
4224                } else {
4225                    JsonFunc::ArrowShift
4226                },
4227                arguments: vec![bound_left, bound_right],
4228            }),
4229            _ => {
4230                // **A vector has no arithmetic, and answering zero is worse
4231                // than refusing.** `v + v` used to be accepted and answer
4232                // `0.0`: the blob went through numeric affinity, which reads no
4233                // leading digits and calls that nothing. pgvector defines `+`
4234                // element-wise; this engine does not implement it, and a
4235                // caller who wrote it gets told so rather than getting a
4236                // column of zeroes.
4237                // **Element-wise, which is what pgvector defines.** `+`, `-`
4238                // and `*` over two vectors work component by component, and
4239                // `*` with a number on one side scales. Anything else over a
4240                // vector - a division, a modulo, a shift - has no pgvector
4241                // meaning, and answering `0.0` for it is worse than refusing:
4242                // the blob would go through numeric affinity, which reads no
4243                // leading digits and calls that nothing.
4244                if let Some(func) = match op {
4245                    BinaryOp::Add => Some(ScalarFunc::VectorAdd),
4246                    BinaryOp::Subtract => Some(ScalarFunc::VectorSubtract),
4247                    BinaryOp::Multiply => Some(ScalarFunc::VectorMultiply),
4248                    _ => None,
4249                } {
4250                    if self.reads_a_vector(&bound_left) || self.reads_a_vector(&bound_right) {
4251                        return Ok(BoundExpr::Function {
4252                            func,
4253                            arguments: vec![bound_left, bound_right],
4254                            collation: Collation::Binary,
4255                        });
4256                    }
4257                }
4258                if self.reads_a_vector(&bound_left) || self.reads_a_vector(&bound_right) {
4259                    return Err(unsupported(
4260                        "arithmetic over a vector column",
4261                        self.ast.expr_span(left),
4262                    ));
4263                }
4264                Ok(BoundExpr::Arithmetic {
4265                    op,
4266                    left: Box::new(bound_left),
4267                    right: Box::new(bound_right),
4268                })
4269            }
4270        }
4271    }
4272
4273    /// Reports whether an expression is a reference to a `VECTOR` column.
4274    ///
4275    /// Only a bare reference, and deliberately: `length(v)` and `hex(v)` are
4276    /// questions about the bytes and answer them, and a general "does this
4277    /// expression have vector in it anywhere" rule would refuse those too.
4278    ///
4279    /// @param expr - the bound expression to look at
4280    fn reads_a_vector(&self, expr: &BoundExpr) -> bool {
4281        let BoundExpr::Column { source, column, .. } = expr else {
4282            return false;
4283        };
4284        self.sources
4285            .iter()
4286            .find(|held| held.id == *source)
4287            .and_then(|held| held.table.columns.get(usize::from(*column)))
4288            .is_some_and(crate::catalog_view::ColumnInfo::is_vector)
4289    }
4290
4291    /// Binds a call that may carry a `FILTER` and an in-argument `ORDER BY`.
4292    ///
4293    /// Both belong to an *aggregate* call and are dropped for anything else,
4294    /// which is what the arity and aggregate checks below already establish:
4295    /// a scalar call cannot reach the arm that reads them.
4296    ///
4297    /// @param name - the function name
4298    /// @param distinct - whether `DISTINCT` was written
4299    /// @param arguments - the argument list, or `None` for `count(*)`
4300    /// @param filter - the `FILTER (WHERE ...)` clause, when one was written
4301    /// @param order_by - the `ORDER BY` inside the argument list
4302    /// @param span - where the call was written
4303    fn bind_call_with(
4304        &mut self,
4305        name: ast::NameId,
4306        distinct: bool,
4307        arguments: Option<Vec<ExprId>>,
4308        filter: Option<ExprId>,
4309        order_by: &[ast::OrderTerm],
4310        span: Span,
4311    ) -> Result<BoundExpr, ParseError> {
4312        let folded = self.ast.folded(name).to_vec();
4313        if self
4314            .authorizer
4315            .authorize(AuthAction::Function { name: &folded })
4316            == Authorization::Deny
4317        {
4318            return Err(denied("not authorized", span));
4319        }
4320        let star = arguments.is_none();
4321        let list = arguments.unwrap_or_default();
4322        if !star && !distinct && !list.is_empty() {
4323            if let Some(bound) = self.bind_auxiliary_call(&folded, &list, span)? {
4324                return Ok(bound);
4325            }
4326        }
4327        if !star {
4328            if let Some(bound) = self.bind_external_call(&folded, &list, distinct, span)? {
4329                return Ok(bound);
4330            }
4331        }
4332        if function::is_aggregate_call(&folded, list.len(), star) {
4333            let Some(func) =
4334                function::lookup_aggregate(&folded).or_else(|| function::minmax_aggregate(&folded))
4335            else {
4336                return Err(no_such_function(&folded, span));
4337            };
4338            if !self.allow_aggregates || self.inside_aggregate {
4339                return Err(unsupported("misuse of aggregate function", span));
4340            }
4341            if star && func != AggregateFunc::Count {
4342                return Err(wrong_arguments(&folded, span));
4343            }
4344            if !function::aggregate_arity_ok(func, if star { 0 } else { list.len() }, star) {
4345                return Err(wrong_arguments(&folded, span));
4346            }
4347            self.inside_aggregate = true;
4348            let mut bound = Vec::with_capacity(list.len());
4349            for argument in &list {
4350                bound.push(self.bind_expr(*argument)?);
4351            }
4352            self.inside_aggregate = false;
4353            // The `FILTER` and the `ORDER BY` read the row the aggregate is
4354            // folding, so they bind in the same scope the arguments did - and
4355            // outside `inside_aggregate`, because neither may itself contain
4356            // an aggregate.
4357            let bound_filter = match filter {
4358                Some(expr) => Some(self.bind_expr(expr)?),
4359                None => None,
4360            };
4361            let bound_order = self.bind_aggregate_order(order_by)?;
4362            let collation = bound
4363                .first()
4364                .and_then(BoundExpr::collation)
4365                .unwrap_or(Collation::Binary);
4366            // The same reason `v + v` refuses: `sum(v)` and `avg(v)` coerced
4367            // the blob through numeric affinity and answered `0.0` for a whole
4368            // column of embeddings. pgvector's `avg(vector)` is an element-wise
4369            // mean; this engine does not compute one, and says so.
4370            // **A vector column folds component by component.** `sum(v)` and
4371            // `avg(v)` over embeddings used to coerce the blob through numeric
4372            // affinity and answer `0.0` for a whole column; pgvector defines
4373            // them as element-wise, and this is that - chosen here, where the
4374            // argument's type is known, rather than at run time where a blob is
4375            // just a blob.
4376            let func = match func {
4377                function::AggregateFunc::Sum | function::AggregateFunc::Total
4378                    if bound.iter().any(|argument| self.reads_a_vector(argument)) =>
4379                {
4380                    function::AggregateFunc::VectorSum
4381                }
4382                function::AggregateFunc::Avg
4383                    if bound.iter().any(|argument| self.reads_a_vector(argument)) =>
4384                {
4385                    function::AggregateFunc::VectorAvg
4386                }
4387                other => other,
4388            };
4389            // **`DISTINCT` takes exactly one argument (task-1913).** SQLite
4390            // answers `DISTINCT aggregates must have exactly one argument`,
4391            // and this accepted `group_concat(DISTINCT s, ',')` and answered
4392            // it - a statement the reference cannot read, which is the same
4393            // class `refusals_match_the_oracle` exists to stop. There is
4394            // nothing for the second argument to be distinct *by*: the
4395            // de-duplication compares the first value alone, so the separator
4396            // of whichever duplicate arrived first is the one that survives.
4397            if distinct && bound.len() > 1 {
4398                return Err(refused(
4399                    "DISTINCT aggregates must have exactly one argument",
4400                    span,
4401                ));
4402            }
4403            let candidate = BoundAggregate {
4404                func,
4405                external: None,
4406                distinct,
4407                arguments: bound,
4408                star,
4409                collation,
4410                filter: bound_filter,
4411                order_by: bound_order,
4412            };
4413            return Ok(self.aggregate_slot(candidate));
4414        }
4415        if let Some(func) = function::lookup_time(&folded) {
4416            if star {
4417                return Err(wrong_arguments(&folded, span));
4418            }
4419            if func == function::TimeFunc::TimeDiff && list.len() != 2 {
4420                return Err(wrong_arguments(&folded, span));
4421            }
4422            if func == function::TimeFunc::StrfTime && list.is_empty() {
4423                return Err(wrong_arguments(&folded, span));
4424            }
4425            let mut bound = Vec::with_capacity(list.len());
4426            for argument in &list {
4427                bound.push(self.bind_expr(*argument)?);
4428            }
4429            return Ok(BoundExpr::Time {
4430                func,
4431                arguments: bound,
4432            });
4433        }
4434        if let Some(func) = function::lookup_math(&folded) {
4435            if star {
4436                return Err(wrong_arguments(&folded, span));
4437            }
4438            let (least, most) = func.arity();
4439            if list.len() < least || list.len() > most {
4440                return Err(wrong_arguments(&folded, span));
4441            }
4442            let mut bound = Vec::with_capacity(list.len());
4443            for argument in &list {
4444                bound.push(self.bind_expr(*argument)?);
4445            }
4446            return Ok(BoundExpr::Math {
4447                func,
4448                arguments: bound,
4449            });
4450        }
4451        if let Some(func) = function::lookup_json(&folded) {
4452            if star {
4453                return Err(wrong_arguments(&folded, span));
4454            }
4455            if !func.arity_ok(list.len()) {
4456                return Err(wrong_arguments(&folded, span));
4457            }
4458            let mut bound = Vec::with_capacity(list.len());
4459            for argument in &list {
4460                let argument = self.bind_expr(*argument)?;
4461                bound.push(self.marked_as_json(argument));
4462            }
4463            return Ok(BoundExpr::Json {
4464                func,
4465                arguments: bound,
4466            });
4467        }
4468        if folded == b"subtype" && list.len() == 1 {
4469            let Some(argument) = list.first().copied() else {
4470                return Err(wrong_arguments(&folded, span));
4471            };
4472            return self.bind_subtype(argument);
4473        }
4474        let Some(func) = function::lookup_scalar(&folded) else {
4475            return Err(no_such_function(&folded, span));
4476        };
4477        if star {
4478            return Err(wrong_arguments(&folded, span));
4479        }
4480        // **`DISTINCT` in a function that is not an aggregate is ignored, as in
4481        // SQLite.** The pinned 3.53.4 answers `abs(DISTINCT a)` as `abs(a)`, and
4482        // the same for the date, math and JSON functions and for `coalesce`. It
4483        // used to be refused here and in the three branches above, and the
4484        // capability note said SQLite refused it too, which nobody had run.
4485        if !function::scalar_arity_ok(func, list.len()) {
4486            return Err(wrong_arguments(&folded, span));
4487        }
4488        let mut bound = Vec::with_capacity(list.len());
4489        for argument in &list {
4490            bound.push(self.bind_expr(*argument)?);
4491        }
4492        let collation = bound
4493            .first()
4494            .and_then(BoundExpr::collation)
4495            .unwrap_or(Collation::Binary);
4496        Ok(BoundExpr::Function {
4497            func,
4498            arguments: bound,
4499            collation,
4500        })
4501    }
4502}
4503
4504/// Returns a refusal whose text is computed rather than a fixed phrase.
4505///
4506/// `Unsupported` carries a `&'static str` because most refusals are one of a
4507/// closed set of phrases and interning them keeps the error type cheap. A
4508/// refusal that has to name a column or count something cannot be one of those,
4509/// so it carries the whole sentence.
4510///
4511/// **`Refused`, not `Unexpected`.** It used to be reported as
4512/// an unexpected-input failure carrying the sentence, on the reasoning that
4513/// this is the shape SQLite's own messages take - and it is not.
4514/// `ParseErrorKind::Unexpected` renders as `near "X": syntax error`, so
4515/// `CREATE TABLE t(a)` on a table that exists answered
4516/// `near "table t already exists": syntax error` where the reference answers
4517/// `table t already exists`. Forty-seven refusals in `directive.rs` alone took
4518/// that shape, and the register audit's own probe is what printed it side by
4519/// side. `Refused` is the variant whose whole purpose is a sentence the schema
4520/// wants said in the reference's words, and it renders as one.
4521pub(crate) fn refused(detail: impl Into<String>, span: Span) -> ParseError {
4522    ParseError::new(ParseErrorKind::Refused(detail.into()), span)
4523}
4524
4525/// Builds the table a nested query's rows are read through.
4526///
4527/// The columns are the block's result columns. Their affinity and collation
4528/// come from the expressions behind them, so a comparison against a subquery
4529/// column applies the rules it would have applied one level down; a column with
4530/// no affinity of its own gets none, which is what SQLite does for an
4531/// expression that is not a bare column or a cast.
4532/// Returns the columns a nested query's result presents to a reader.
4533///
4534/// Public because a write to a view needs them before there is a FROM term to
4535/// hang them on: the view's catalog entry carries no column list at all.
4536pub fn subquery_columns(select: &BoundSelect, names: &[Vec<u8>]) -> Vec<ColumnInfo> {
4537    select
4538        .columns
4539        .iter()
4540        .enumerate()
4541        .map(|(index, column)| {
4542            let name = names
4543                .get(index)
4544                .cloned()
4545                .unwrap_or_else(|| column.name.clone());
4546            let folded = name.to_ascii_lowercase();
4547            let collation = column.expr.collation().unwrap_or(Collation::Binary);
4548            ColumnInfo {
4549                name,
4550                folded,
4551                declared_type: column.declared_type.clone(),
4552                affinity: column.expr.affinity().unwrap_or(Affinity::Blob),
4553                collation: collation.name().as_bytes().to_ascii_lowercase(),
4554                not_null: false,
4555                not_null_conflict: None,
4556                primary_key_conflict: None,
4557                default_sql: None,
4558                primary_key_position: None,
4559                hidden: false,
4560                generated: false,
4561                stored: false,
4562                generated_sql: None,
4563            }
4564        })
4565        .collect()
4566}
4567
4568/// Returns a block that reads one FROM term and nothing else.
4569///
4570/// Everything a `SELECT` can carry is empty here on purpose: this exists to
4571/// wrap a term the binder has already produced so the compiler can iterate it,
4572/// not to stand in for a query somebody wrote.
4573pub fn block_over(
4574    source: BoundSource,
4575    filter: Option<BoundExpr>,
4576    columns: Vec<BoundResultColumn>,
4577) -> BoundSelect {
4578    BoundSelect {
4579        sources: vec![source],
4580        filter,
4581        group_by: Vec::new(),
4582        having: None,
4583        columns,
4584        distinct: false,
4585        order_by: Vec::new(),
4586        limit: None,
4587        offset: None,
4588        aggregates: Vec::new(),
4589        values: Vec::new(),
4590        compounds: Vec::new(),
4591        windows: Vec::new(),
4592        correlations: Vec::new(),
4593    }
4594}
4595
4596fn subquery_table(alias: &[u8], names: &[Vec<u8>], select: &BoundSelect) -> TableInfo {
4597    TableInfo::subquery(alias.to_vec(), 0, subquery_columns(select, names))
4598}
4599
4600/// Returns the aggregate a name spells inside an `OVER` clause.
4601///
4602/// `min` and `max` are the awkward pair: with one argument they are aggregates
4603/// and with two or more they are scalars, and only the argument count tells
4604/// them apart. Inside a window the one-argument form is always the aggregate,
4605/// which is why the ordinary aggregate lookup - which has to leave them out -
4606/// is not enough here.
4607fn window_aggregate(folded: &[u8], arguments: usize) -> Option<AggregateFunc> {
4608    if let Some(func) = function::lookup_aggregate(folded) {
4609        return Some(func);
4610    }
4611    match (folded, arguments) {
4612        (b"min", 1) => Some(AggregateFunc::Min),
4613        (b"max", 1) => Some(AggregateFunc::Max),
4614        _ => None,
4615    }
4616}
4617
4618/// Returns a "no such window" failure.
4619fn no_such_window(name: &[u8], span: Span) -> ParseError {
4620    ParseError::new(
4621        ParseErrorKind::Refused(format!("no such window: {}", String::from_utf8_lossy(name))),
4622        span,
4623    )
4624}
4625
4626/// Returns an authorizer refusal.
4627fn denied(what: &'static str, span: Span) -> ParseError {
4628    ParseError::new(ParseErrorKind::Unsupported(what), span)
4629}