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