Skip to main content

inillucent_sql/
bind.rs

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