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