Skip to main content

inillucent_sql/
bind.rs

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