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