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