Skip to main content

inillucent_sql/
bind.rs

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