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 let Some(column) = block.columns.first() else {
2611 return Err(unsupported("a subquery with no result column", span));
2612 };
2613 let (affinity, collation) = comparison_rules(&operand, &column.expr);
2614 Ok(BoundExpr::Subquery {
2615 id: self.next_subquery_id(),
2616 kind: SubqueryKind::In,
2617 negated,
2618 operand: Some(Box::new(operand)),
2619 block: Box::new(block),
2620 affinity,
2621 collation,
2622 })
2623 }
2624
2625 /// Binds a subquery FROM term and registers it as a source.
2626 fn bind_subquery_term(
2627 &mut self,
2628 select: SelectId,
2629 alias: Option<Vec<u8>>,
2630 columns: Vec<Vec<u8>>,
2631 join: JoinKind,
2632 span: Span,
2633 ) -> Result<(), ParseError> {
2634 let bound = self.bind_select(select)?;
2635 let alias = alias.unwrap_or_else(|| b"subquery".to_vec());
2636 self.push_subquery_source(bound, alias, columns, join, span)
2637 }
2638
2639 /// Registers a bound block as one FROM term of the current block.
2640 fn push_subquery_source(
2641 &mut self,
2642 bound: BoundSelect,
2643 alias: Vec<u8>,
2644 columns: Vec<Vec<u8>>,
2645 join: JoinKind,
2646 span: Span,
2647 ) -> Result<(), ParseError> {
2648 if !columns.is_empty() && columns.len() != bound.columns.len() {
2649 return Err(ParseError::new(
2650 ParseErrorKind::Unsupported("the named column list does not match the query"),
2651 span,
2652 ));
2653 }
2654 let table = subquery_table(&alias, &columns, &bound);
2655 let id = self.sources.len();
2656 self.sources.push(BoundSource {
2657 index_hint: crate::bind::IndexChoice::Any,
2658 id,
2659 rows: SourceRows::Subquery(Box::new(bound)),
2660 table: std::rc::Rc::new(table),
2661 alias,
2662 join,
2663 constraint: None,
2664 suppressed: Vec::new(),
2665 index_exprs: Vec::new(),
2666 });
2667 if let Some(scope) = self.scopes.last_mut() {
2668 scope.push(id);
2669 }
2670 Ok(())
2671 }
2672
2673 /// Records the named windows a `WINDOW` clause declares.
2674 fn declare_windows(
2675 &mut self,
2676 windows: &[(ast::NameId, ast::WindowId)],
2677 ) -> Result<(), ParseError> {
2678 for (name, window) in windows {
2679 self.named_windows
2680 .push((self.ast.folded(*name).to_vec(), *window));
2681 }
2682 Ok(())
2683 }
2684
2685 /// Binds a call carrying an `OVER` clause.
2686 ///
2687 /// The window is resolved first, because a call over a named window that
2688 /// does not exist is an error about the name rather than about the
2689 /// function - and because `OVER w` and `OVER (w ORDER BY x)` both have to
2690 /// end up as one fully-resolved specification before the frame defaults can
2691 /// be applied.
2692 fn bind_window_call(
2693 &mut self,
2694 name: ast::NameId,
2695 distinct: bool,
2696 arguments: Option<Vec<ExprId>>,
2697 filter: Option<ExprId>,
2698 over: ast::WindowId,
2699 span: Span,
2700 ) -> Result<BoundExpr, ParseError> {
2701 let folded = self.ast.folded(name).to_vec();
2702 let spec = self.resolve_window(over, span)?;
2703 let star = arguments.is_none();
2704 let mut bound_arguments = Vec::new();
2705 for argument in arguments.unwrap_or_default() {
2706 bound_arguments.push(self.bind_expr(argument)?);
2707 }
2708 let call = match function::lookup_window(&folded) {
2709 Some(func) => {
2710 let (least, most) = func.arity();
2711 if bound_arguments.len() < least || bound_arguments.len() > most {
2712 return Err(wrong_arguments(&folded, span));
2713 }
2714 if distinct {
2715 return Err(unsupported("DISTINCT in a window function", span));
2716 }
2717 WindowCall::Plain(func)
2718 }
2719 None => match window_aggregate(&folded, bound_arguments.len()) {
2720 Some(func) => WindowCall::Aggregate(func),
2721 None => return Err(no_such_function(&folded, span)),
2722 },
2723 };
2724 let bound_filter = match filter {
2725 Some(expr) => Some(self.bind_expr(expr)?),
2726 None => None,
2727 };
2728 let collation = bound_arguments
2729 .first()
2730 .and_then(BoundExpr::collation)
2731 .unwrap_or(Collation::Binary);
2732
2733 let mut partition_by = Vec::new();
2734 for expr in &spec.partition_by {
2735 partition_by.push(self.bind_expr(*expr)?);
2736 }
2737 let order_by = self.bind_order_by(&spec.order_by, &[], &[])?;
2738 // SQLite's defaults, and they are not the same clause: with an
2739 // `ORDER BY` the frame ends at the current row's peer group, and
2740 // without one it covers the whole partition. Using one default for both
2741 // makes every ordered `sum() OVER ()` a running total or none of them.
2742 let unit = spec.unit.unwrap_or(FrameUnit::Range);
2743 let (start, end) = match (spec.start, spec.end) {
2744 (None, None) => (
2745 BoundFrameBound::UnboundedPreceding,
2746 if order_by.is_empty() {
2747 BoundFrameBound::UnboundedFollowing
2748 } else {
2749 BoundFrameBound::CurrentRow
2750 },
2751 ),
2752 (Some(start), None) => (
2753 self.bind_frame_bound(start, span)?,
2754 BoundFrameBound::CurrentRow,
2755 ),
2756 (Some(start), Some(end)) => (
2757 self.bind_frame_bound(start, span)?,
2758 self.bind_frame_bound(end, span)?,
2759 ),
2760 (None, Some(end)) => (
2761 BoundFrameBound::UnboundedPreceding,
2762 self.bind_frame_bound(end, span)?,
2763 ),
2764 };
2765 if matches!(start, BoundFrameBound::UnboundedFollowing)
2766 || matches!(end, BoundFrameBound::UnboundedPreceding)
2767 {
2768 return Err(ParseError::new(
2769 ParseErrorKind::Unsupported("unsupported frame specification"),
2770 span,
2771 ));
2772 }
2773 // Only `RANGE` measures an offset in ordering values, so only `RANGE`
2774 // needs a single ordering term. A `GROUPS` offset counts peer groups,
2775 // which any number of terms defines, and SQLite accepts it with none.
2776 if unit == FrameUnit::Range
2777 && matches!(
2778 (&start, &end),
2779 (BoundFrameBound::Preceding(_), _)
2780 | (BoundFrameBound::Following(_), _)
2781 | (_, BoundFrameBound::Preceding(_))
2782 | (_, BoundFrameBound::Following(_))
2783 )
2784 && order_by.len() != 1
2785 {
2786 return Err(ParseError::new(
2787 ParseErrorKind::Unsupported(
2788 "RANGE with offset PRECEDING/FOLLOWING requires exactly one ORDER BY expression",
2789 ),
2790 span,
2791 ));
2792 }
2793 let slot = self.windows.len();
2794 let explicit = explicit_argument_collation(&bound_arguments);
2795 self.windows.push(BoundWindow {
2796 call,
2797 distinct,
2798 collation,
2799 arguments: bound_arguments,
2800 star,
2801 filter: bound_filter,
2802 partition_by,
2803 order_by,
2804 unit,
2805 start,
2806 end,
2807 exclude: spec.exclude,
2808 });
2809 Ok(BoundExpr::WindowRef {
2810 slot,
2811 collation: explicit,
2812 })
2813 }
2814
2815 /// Resolves an `OVER` clause into one fully-written window specification.
2816 fn resolve_window(&self, id: ast::WindowId, span: Span) -> Result<ast::Window, ParseError> {
2817 let Some(window) = self.ast.window(id) else {
2818 return Err(unsupported("missing window", span));
2819 };
2820 let mut spec = window.clone();
2821 let mut guard = 0usize;
2822 while let Some(base) = spec.base {
2823 guard = guard.saturating_add(1);
2824 if guard > MAX_COMPOUND_SELECT {
2825 return Err(unsupported("a window that inherits from itself", span));
2826 }
2827 let folded = self.ast.folded(base).to_vec();
2828 let Some((_, id)) = self.named_windows.iter().find(|(name, _)| *name == folded) else {
2829 return Err(no_such_window(&folded, span));
2830 };
2831 let Some(parent) = self.ast.window(*id) else {
2832 return Err(unsupported("missing window", span));
2833 };
2834 // The inheriting window may add an `ORDER BY` and a frame; it may
2835 // not replace the base's `PARTITION BY`, which is SQLite's rule and
2836 // the reason the merge is one-directional.
2837 let parent = parent.clone();
2838 spec.base = parent.base;
2839 spec.partition_by = parent.partition_by.clone();
2840 if spec.order_by.is_empty() {
2841 spec.order_by = parent.order_by.clone();
2842 }
2843 if spec.unit.is_none() {
2844 spec.unit = parent.unit;
2845 spec.start = parent.start;
2846 spec.end = parent.end;
2847 spec.exclude = parent.exclude;
2848 }
2849 }
2850 Ok(spec)
2851 }
2852
2853 /// Binds one end of a frame.
2854 fn bind_frame_bound(
2855 &mut self,
2856 bound: FrameBound,
2857 span: Span,
2858 ) -> Result<BoundFrameBound, ParseError> {
2859 let bound = match bound {
2860 FrameBound::UnboundedPreceding => BoundFrameBound::UnboundedPreceding,
2861 FrameBound::CurrentRow => BoundFrameBound::CurrentRow,
2862 FrameBound::UnboundedFollowing => BoundFrameBound::UnboundedFollowing,
2863 FrameBound::Preceding(expr) => {
2864 BoundFrameBound::Preceding(self.bind_frame_offset(expr, span)?)
2865 }
2866 FrameBound::Following(expr) => {
2867 BoundFrameBound::Following(self.bind_frame_offset(expr, span)?)
2868 }
2869 };
2870 Ok(bound)
2871 }
2872
2873 /// Binds a frame offset, which may not read a column.
2874 fn bind_frame_offset(&mut self, expr: ExprId, span: Span) -> Result<BoundExpr, ParseError> {
2875 let bound = self.bind_expr(expr)?;
2876 if !bound.is_constant() {
2877 return Err(ParseError::new(
2878 ParseErrorKind::Unsupported("a frame offset must be a constant"),
2879 span,
2880 ));
2881 }
2882 Ok(bound)
2883 }
2884
2885 /// Records that the statement depends on a database's schema cookie.
2886 fn record_dependency(&mut self, database: usize) {
2887 if self
2888 .dependencies
2889 .schemas
2890 .iter()
2891 .any(|(index, _)| *index == database)
2892 {
2893 return;
2894 }
2895 let cookie = self.catalog.schema_cookie(database);
2896 self.dependencies.schemas.push((database, cookie));
2897 }
2898
2899 /// Binds the result columns, expanding `*` and `table.*`.
2900 fn bind_result_columns(
2901 &mut self,
2902 columns: &[ast::ResultColumn],
2903 ) -> Result<Vec<BoundResultColumn>, ParseError> {
2904 // One column of the AST is usually one bound column, so this is the
2905 // right answer rather than a guess; `*` expands to more and the vector
2906 // grows from here, which is still fewer growths than starting empty.
2907 // `Vec::new` grew to four for a one-column select, which is 704 bytes
2908 // asked for to hold 176 (task-2026).
2909 let mut bound = Vec::with_capacity(columns.len());
2910 for column in columns {
2911 match self.ast.expr(column.expr) {
2912 Some(Expr::Star { table }) => {
2913 let qualifier = table.map(|id| self.ast.folded(id).to_vec());
2914 self.expand_star(qualifier.as_deref(), column.span, &mut bound)?;
2915 }
2916 _ => {
2917 let expr = self.bind_expr(column.expr)?;
2918 let name = match column.alias {
2919 Some(alias) => self.ast.text(alias).to_vec(),
2920 None => self.default_column_name(column.expr, &expr, column.span),
2921 };
2922 let (origin, declared_type) = self.column_origin(&expr);
2923 bound.push(BoundResultColumn {
2924 expr,
2925 name,
2926 origin,
2927 declared_type,
2928 });
2929 }
2930 }
2931 }
2932 if bound.is_empty() {
2933 return Err(unsupported(
2934 "a SELECT must have result columns",
2935 Span::default(),
2936 ));
2937 }
2938 Ok(bound)
2939 }
2940
2941 /// Turns a table-valued function's arguments into hidden-column equalities.
2942 ///
2943 /// The nth argument constrains the nth *hidden* column, which is the rule
2944 /// that makes `generate_series(1,5)` mean `start = 1 AND stop = 5`. More
2945 /// arguments than hidden columns is an error at bind time, because there is
2946 /// nothing for the extra one to constrain.
2947 fn bind_table_arguments(&mut self, arguments: &[ExprId], span: Span) -> Result<(), ParseError> {
2948 let Some(id) = self.scope().last().copied() else {
2949 return Err(unsupported("a table-valued function with no term", span));
2950 };
2951 let Some(source) = self.sources.get(id) else {
2952 return Err(unsupported("a table-valued function with no term", span));
2953 };
2954 if source.table.kind != TableKind::Virtual {
2955 return Err(unsupported(
2956 "arguments on a table that is not virtual",
2957 span,
2958 ));
2959 }
2960 let hidden: Vec<(u16, Affinity, Collation)> = source
2961 .table
2962 .columns
2963 .iter()
2964 .enumerate()
2965 .filter(|(_, column)| column.hidden)
2966 .map(|(index, column)| {
2967 (
2968 index as u16,
2969 column.affinity,
2970 self.collation_named(&column.collation)
2971 .unwrap_or(Collation::Binary),
2972 )
2973 })
2974 .collect();
2975 if arguments.len() > hidden.len() {
2976 return Err(wrong_arguments(&source.table.name.clone(), span));
2977 }
2978 for (position, argument) in arguments.iter().enumerate() {
2979 let Some((column, affinity, collation)) = hidden.get(position).copied() else {
2980 break;
2981 };
2982 let value = self.bind_expr(*argument)?;
2983 self.pending_constraints.push(BoundExpr::Compare {
2984 op: BinaryOp::Equal,
2985 left: Box::new(BoundExpr::Column {
2986 source: id,
2987 column,
2988 slot: column,
2989 affinity,
2990 collation,
2991 }),
2992 right: Box::new(value),
2993 affinity: None,
2994 collation,
2995 });
2996 }
2997 Ok(())
2998 }
2999
3000 /// Returns the collation a name selects.
3001 ///
3002 /// A connection's own definitions come first, so an application that
3003 /// defines `NOCASE` gets its own rather than the built-in - which is what
3004 /// SQLite does, and is the only way `sqlite3_create_collation` can be used
3005 /// to change how an existing schema compares.
3006 fn collation_named(&self, name: &[u8]) -> Option<Collation> {
3007 // **The name is compared where it is (task-2026).** `create_collation`
3008 // stores the name uppercased, so an uppercase-insensitive comparison
3009 // against a stored name answers exactly what building an uppercase copy
3010 // of `name` and comparing bytes answered. Building the copy cost an
3011 // allocation per column reference, whether or not the connection had
3012 // registered any collation at all - two of the 109 allocations
3013 // `SELECT a FROM t WHERE id = ?1` made.
3014 if let Some((_, collation)) = self
3015 .collations
3016 .iter()
3017 .find(|(candidate, _)| candidate.as_bytes().eq_ignore_ascii_case(name))
3018 {
3019 return Some(*collation);
3020 }
3021 Collation::from_name(core::str::from_utf8(name).unwrap_or(""))
3022 }
3023
3024 /// Binds `f(table, ...)` as a module's auxiliary function, if that is what
3025 /// it is.
3026 ///
3027 /// The tell is the first argument: a bare reference to a virtual table's
3028 /// own hidden column, which is a thing no ordinary function is ever handed
3029 /// on purpose. `bm25(docs)` takes this path; an unknown name is refused by
3030 /// the module rather than here, because the module is what knows its own
3031 /// functions.
3032 fn bind_auxiliary_call(
3033 &mut self,
3034 name: &[u8],
3035 arguments: &[ExprId],
3036 span: Span,
3037 ) -> Result<Option<BoundExpr>, ParseError> {
3038 let Some(first) = arguments.first() else {
3039 return Ok(None);
3040 };
3041 let Some(&Expr::Column {
3042 database: None,
3043 table: None,
3044 column,
3045 }) = self.ast.expr(*first)
3046 else {
3047 return Ok(None);
3048 };
3049 let Ok(BoundExpr::Column { source, column, .. }) =
3050 self.bind_column_reference(None, None, column, span)
3051 else {
3052 return Ok(None);
3053 };
3054 let Some(entry) = self.sources.get(source) else {
3055 return Ok(None);
3056 };
3057 if entry.table.kind != TableKind::Virtual {
3058 return Ok(None);
3059 }
3060 // The self column is the hidden one named after the table, and only
3061 // that one: `rank` is a column, not a handle.
3062 let self_column = entry
3063 .table
3064 .column(column)
3065 .is_some_and(|info| info.folded == entry.table.folded);
3066 if !self_column {
3067 return Ok(None);
3068 }
3069 let mut rest = Vec::with_capacity(arguments.len() - 1);
3070 for argument in arguments.iter().skip(1) {
3071 rest.push(self.bind_expr(*argument)?);
3072 }
3073 Ok(Some(BoundExpr::VirtualFunction {
3074 source,
3075 name: name.to_ascii_lowercase(),
3076 arguments: rest,
3077 }))
3078 }
3079
3080 /// Returns whether an expression is a column of a virtual table.
3081 fn is_virtual_column(&self, expr: &BoundExpr) -> bool {
3082 let BoundExpr::Column { source, .. } = expr else {
3083 return false;
3084 };
3085 self.sources
3086 .get(*source)
3087 .is_some_and(|source| source.table.kind == TableKind::Virtual)
3088 }
3089
3090 /// Expands `*` or `table.*` into one bound column per visible column.
3091 ///
3092 /// Only the block's own FROM terms are expanded. An enclosing block's terms
3093 /// are visible to a *name*, which is what makes a subquery correlated, but
3094 /// they are not part of this block's `*`.
3095 fn expand_star(
3096 &mut self,
3097 qualifier: Option<&[u8]>,
3098 span: Span,
3099 into: &mut Vec<BoundResultColumn>,
3100 ) -> Result<(), ParseError> {
3101 let scope: Vec<usize> = self.scope().to_vec();
3102 if scope.is_empty() {
3103 return Err(ParseError::new(
3104 ParseErrorKind::Unexpected {
3105 found: "*".to_string(),
3106 expected: vec!["a FROM clause"],
3107 },
3108 span,
3109 ));
3110 }
3111 let mut matched = false;
3112 let scope_ids = scope.clone();
3113 for id in scope {
3114 let Some(source) = self.sources.get(id) else {
3115 continue;
3116 };
3117 if let Some(qualifier) = qualifier {
3118 if !source.alias.eq_ignore_ascii_case(qualifier) {
3119 continue;
3120 }
3121 }
3122 matched = true;
3123 let columns = source.table.columns.clone();
3124 let suppressed = source.suppressed.clone();
3125 let database = self.catalog.database_name(source.table.database).to_vec();
3126 let table_name = source.table.name.clone();
3127 let synthetic = source.table.kind == TableKind::Subquery;
3128 for (index, column) in columns.iter().enumerate() {
3129 let position_u16 = index as u16;
3130 // A `USING` column is left out of a bare `*` only. `r.*` names
3131 // the term, and SQLite shows every column of it.
3132 if column.hidden || (qualifier.is_none() && suppressed.contains(&position_u16)) {
3133 continue;
3134 }
3135 if self.authorizer.authorize(AuthAction::Read {
3136 database: &database,
3137 table: &table_name,
3138 column: &column.name,
3139 }) == Authorization::Deny
3140 {
3141 return Err(denied("not authorized", span));
3142 }
3143 // `l.*` goes through the same rule as `*`: SQLite expands a
3144 // column a later `USING` names as the bare name even when the
3145 // star is qualified, so `l.*` over `l FULL JOIN r USING (a)`
3146 // shows `coalesce(l.a, r.a)`.
3147 let expr = self.star_using_column(&scope_ids, id, position_u16, span)?;
3148 into.push(BoundResultColumn {
3149 expr,
3150 name: column.name.clone(),
3151 // A subquery's column has no table of origin: it came from
3152 // an expression, and reporting the synthetic name as one
3153 // would make `sqlite3_column_table_name` invent a table.
3154 origin: (!synthetic)
3155 .then(|| (database.clone(), table_name.clone(), column.name.clone())),
3156 declared_type: column.declared_type.clone(),
3157 });
3158 }
3159 }
3160 if !matched {
3161 return Err(no_such_table(qualifier.unwrap_or(b"*"), span));
3162 }
3163 Ok(())
3164 }
3165
3166 /// Returns the name an unaliased result column reports.
3167 ///
3168 /// A bare column reference is named after its declared name rather than
3169 /// the query's text - `rowid`/`oid`/`_rowid_` resolve to the column they
3170 /// alias and take its name too. Everything else keeps the source text.
3171 ///
3172 /// @param id - the expression as written
3173 /// @param bound - the expression, bound
3174 /// @param written - the result column's span, which ends where the next
3175 /// token starts
3176 fn default_column_name(&self, id: ExprId, bound: &BoundExpr, written: Span) -> Vec<u8> {
3177 let name = match bound {
3178 BoundExpr::Column { source, column, .. } => self
3179 .sources
3180 .get(*source)
3181 .and_then(|held| held.table.column(*column)),
3182 BoundExpr::Rowid { source } => self
3183 .sources
3184 .get(*source)
3185 .and_then(|held| held.table.column(held.table.rowid_alias?)),
3186 _ => None,
3187 };
3188 if let Some(name) = name {
3189 return name.name.clone();
3190 }
3191 // **The three spellings of the rowid are one column name (task-1979,
3192 // F22).** `SELECT rowid, oid, _rowid_ FROM t` answers three columns
3193 // called `rowid` in SQLite, whichever way each was written. On a table
3194 // with no INTEGER PRIMARY KEY there is no declared column to take the
3195 // name from, and the fallback below took the text as typed, so the
3196 // last two came back called `oid` and `_rowid_` - names no caller
3197 // could match against the one SQLite reports.
3198 if matches!(bound, BoundExpr::Rowid { .. }) {
3199 return b"rowid".to_vec();
3200 }
3201 if let Some(Expr::Column { column, .. }) = self.ast.expr(id) {
3202 return self.ast.text(*column).to_vec();
3203 }
3204 // Everything else is named after the text it was written as,
3205 // exactly as written - `SELECT 1 + 2` has a column called
3206 // `1 + 2`, spaces and all, because SQLite cuts the span rather
3207 // than re-rendering the expression.
3208 //
3209 // **The span runs to where the next token starts**, so a comment
3210 // between the expression and the comma, the `FROM` or the end of the
3211 // statement is part of the name: `SELECT 1 -- trailing` has a column
3212 // called `1 -- trailing`. Only the whitespace at the end is trimmed,
3213 // which is what SQLite's `sqlite3DbSpanDup` does. The expression's
3214 // own span stopped at its last token and left the comment out.
3215 let start = self.ast.expr_span(id).start;
3216 let text = Span::new(start as usize, written.end as usize).slice(self.source);
3217 let kept = text
3218 .iter()
3219 .rposition(|byte| !byte.is_ascii_whitespace())
3220 .map_or(0, |last| last.saturating_add(1));
3221 text.get(..kept).unwrap_or(text).to_vec()
3222 }
3223
3224 /// Returns the origin triple and declared type of a bound column.
3225 fn column_origin(&self, expr: &BoundExpr) -> (Option<ColumnOrigin>, Vec<u8>) {
3226 // A rowid alias is a column, and `SELECT a FROM t` where `a` is the
3227 // INTEGER PRIMARY KEY binds to the rowid rather than to a record slot.
3228 // It still has an origin and a declared type, and reporting neither
3229 // made `sqlite3_column_decltype` empty for the commonest column there
3230 // is - and `PRAGMA table_info` on a view over one report no type.
3231 let expr = match expr {
3232 BoundExpr::Rowid { source } => {
3233 let alias = self
3234 .sources
3235 .get(*source)
3236 .and_then(|source| source.table.rowid_alias);
3237 match alias {
3238 Some(column) => &BoundExpr::Column {
3239 source: *source,
3240 column,
3241 slot: column,
3242 affinity: Affinity::Integer,
3243 collation: Collation::Binary,
3244 },
3245 None => return (None, Vec::new()),
3246 }
3247 }
3248 other => other,
3249 };
3250 let BoundExpr::Column { source, column, .. } = expr else {
3251 return (None, Vec::new());
3252 };
3253 let Some(source) = self.sources.get(*source) else {
3254 return (None, Vec::new());
3255 };
3256 let Some(info) = source.table.column(*column) else {
3257 return (None, Vec::new());
3258 };
3259 (
3260 Some((
3261 self.catalog.database_name(source.table.database).to_vec(),
3262 source.table.name.clone(),
3263 info.name.clone(),
3264 )),
3265 info.declared_type.clone(),
3266 )
3267 }
3268
3269 /// Binds one `GROUP BY` term, which may be an ordinal or a result alias.
3270 fn bind_group_term(
3271 &mut self,
3272 id: ExprId,
3273 columns: &[BoundResultColumn],
3274 ) -> Result<BoundExpr, ParseError> {
3275 if let Some(index) = self.as_ordinal(id) {
3276 let Some(column) = columns.get(index.saturating_sub(1)) else {
3277 return Err(unsupported(
3278 "GROUP BY term is out of range",
3279 self.ast.expr_span(id),
3280 ));
3281 };
3282 return Ok(column.expr.clone());
3283 }
3284 self.bind_expr(id)
3285 }
3286
3287 /// Returns the one-based ordinal an expression is, if it is an integer.
3288 fn as_ordinal(&self, id: ExprId) -> Option<usize> {
3289 let Some(Expr::Literal(Literal::Integer(text))) = self.ast.expr(id) else {
3290 return None;
3291 };
3292 let mut value: usize = 0;
3293 for byte in text {
3294 if !byte.is_ascii_digit() {
3295 return None;
3296 }
3297 value = value
3298 .saturating_mul(10)
3299 .saturating_add(usize::from(byte.saturating_sub(b'0')));
3300 }
3301 Some(value)
3302 }
3303
3304 /// Binds an `ORDER BY` list, resolving ordinals and result aliases.
3305 ///
3306 /// @param terms - the terms as written
3307 /// @param columns - the result columns an ordinal or an alias names
3308 /// @param aliases - the written aliases, which a bare identifier matches
3309 /// before a table column; see `bind::order_alias`
3310 fn bind_order_by(
3311 &mut self,
3312 terms: &[ast::OrderTerm],
3313 columns: &[BoundResultColumn],
3314 aliases: &[(Vec<u8>, usize)],
3315 ) -> Result<Vec<BoundOrderTerm>, ParseError> {
3316 let mut bound = Vec::with_capacity(terms.len());
3317 for term in terms {
3318 // A bare integer is an ordinal into the result columns; anything
3319 // else, including `1 + 0`, is an expression. SQLite draws the line
3320 // at a literal, and so does this.
3321 let expr = match self.as_ordinal(term.expr) {
3322 Some(ordinal) => {
3323 let Some(column) = ordinal.checked_sub(1).and_then(|index| columns.get(index))
3324 else {
3325 return Err(order_out_of_range(ordinal, self.ast.expr_span(term.expr)));
3326 };
3327 column.expr.clone()
3328 }
3329 None => match self
3330 .ordered_by_alias(term.expr, aliases)
3331 .and_then(|at| columns.get(at))
3332 {
3333 Some(column) => column.expr.clone(),
3334 None => self.bind_expr(term.expr)?,
3335 },
3336 };
3337 let collation = expr.collation().unwrap_or(Collation::Binary);
3338 let nulls = term.nulls.unwrap_or(match term.order {
3339 // SQLite sorts NULLs first ascending and last descending when
3340 // no explicit null ordering is written.
3341 SortOrder::Ascending => NullOrder::First,
3342 SortOrder::Descending => NullOrder::Last,
3343 });
3344 bound.push(BoundOrderTerm {
3345 expr,
3346 order: term.order,
3347 nulls,
3348 collation,
3349 });
3350 }
3351 Ok(bound)
3352 }
3353
3354 /// Binds the `ORDER BY` written inside an aggregate's argument list.
3355 ///
3356 /// Not [`Binder::bind_order_by`]: that one resolves a bare integer as an
3357 /// ordinal into the *result columns*, which an aggregate's own `ORDER BY`
3358 /// has none of. `group_concat(b ORDER BY 1)` sorts by the literal 1 in
3359 /// SQLite, which is to say by nothing. A limited write uses it too.
3360 ///
3361 /// @param terms - the terms as written
3362 pub(crate) fn bind_aggregate_order(
3363 &mut self,
3364 terms: &[ast::OrderTerm],
3365 ) -> Result<Vec<BoundOrderTerm>, ParseError> {
3366 let mut bound = Vec::with_capacity(terms.len());
3367 for term in terms {
3368 let expr = self.bind_expr(term.expr)?;
3369 let collation = expr.collation().unwrap_or(Collation::Binary);
3370 let nulls = term.nulls.unwrap_or(match term.order {
3371 SortOrder::Ascending => NullOrder::First,
3372 SortOrder::Descending => NullOrder::Last,
3373 });
3374 bound.push(BoundOrderTerm {
3375 expr,
3376 order: term.order,
3377 nulls,
3378 collation,
3379 });
3380 }
3381 Ok(bound)
3382 }
3383
3384 /// Returns a bound column reference, checking the authorizer.
3385 fn column_expr(&mut self, source: usize, column: u16) -> Result<BoundExpr, ParseError> {
3386 let Some(bound) = self.sources.get(source) else {
3387 return Err(unsupported("unknown source", Span::default()));
3388 };
3389 let Some(info) = bound.table.column(column) else {
3390 return Err(unsupported("unknown column", Span::default()));
3391 };
3392 let affinity = info.affinity;
3393 let collation = self
3394 .collation_named(&info.collation)
3395 .unwrap_or(Collation::Binary);
3396 if bound.table.rowid_alias == Some(column) {
3397 // An INTEGER PRIMARY KEY column *is* the rowid, and reading it
3398 // through the record would read a NULL placeholder.
3399 return Ok(BoundExpr::Rowid { source });
3400 }
3401 // A `VIRTUAL` generated column is not in the record at all: it is its
3402 // own expression, so the reference is replaced by the expression here
3403 // and nothing below the binder ever sees the column.
3404 if info.generated && !info.stored {
3405 let Some(sql) = info.generated_sql.clone() else {
3406 return Err(unsupported(
3407 "a generated column with no expression",
3408 Span::default(),
3409 ));
3410 };
3411 self.generating = self.generating.saturating_add(1);
3412 if self.generating > MAX_GENERATED_DEPTH {
3413 self.generating = self.generating.saturating_sub(1);
3414 return Err(ParseError::new(
3415 ParseErrorKind::Unsupported("a generated column refers to itself"),
3416 Span::default(),
3417 ));
3418 }
3419 let bound = self.bind_schema_expr_for(source, &sql);
3420 self.generating = self.generating.saturating_sub(1);
3421 return bound;
3422 }
3423 let slot = bound
3424 .table
3425 .record_slot(column)
3426 .unwrap_or(usize::from(column)) as u16;
3427 Ok(BoundExpr::Column {
3428 source,
3429 column,
3430 slot,
3431 affinity,
3432 collation,
3433 })
3434 }
3435
3436 /// Binds a schema expression against one FROM term's scope.
3437 ///
3438 /// A generated column's expression names other columns of its own table, so
3439 /// it is bound with exactly that term visible and nothing else - a name it
3440 /// cannot resolve there is an error rather than something it picks up from
3441 /// the query that happened to read it.
3442 fn bind_schema_expr_for(&mut self, source: usize, sql: &[u8]) -> Result<BoundExpr, ParseError> {
3443 let saved = core::mem::replace(&mut self.scopes, vec![vec![source]]);
3444 let bound = self.bind_schema_expr(sql);
3445 self.scopes = saved;
3446 bound
3447 }
3448
3449 /// Binds a result-column list against the current sources.
3450 ///
3451 /// `RETURNING` is a result-column list over the row a DML statement wrote,
3452 /// so it is bound by the same code that binds a `SELECT` list rather than
3453 /// by a second implementation that would have to be kept in step with it.
3454 pub fn bind_result_columns_public(
3455 &mut self,
3456 columns: &[ast::ResultColumn],
3457 ) -> Result<Vec<BoundResultColumn>, ParseError> {
3458 self.bind_result_columns(columns)
3459 }
3460
3461 /// Records that the statement depends on a database's schema.
3462 pub(crate) fn record_write_dependency(&mut self, database: usize) {
3463 self.record_dependency(database);
3464 }
3465
3466 /// Binds a unary operator over one expression.
3467 ///
3468 /// **A negated integer literal is one literal, not an operator over one.**
3469 /// `-9223372036854775808` is the smallest integer there is; `9223372036854775808` on
3470 /// its own is one past the largest, so binding the operand first turned it into a real
3471 /// and the negation then produced `-9.2233720368547758e+18`. Every comparison, every
3472 /// affinity and every write of that value is a different value from the one that was
3473 /// written. SQLite folds the sign into the literal in its own parser for exactly this
3474 /// reason.
3475 ///
3476 /// @param op - the operator
3477 /// @param operand - the expression it applies to
3478 fn bind_unary(&mut self, op: UnaryOp, operand: ExprId) -> Result<BoundExpr, ParseError> {
3479 if op == UnaryOp::Negate {
3480 if let Some(Expr::Literal(Literal::Integer(text))) = self.ast.expr(operand) {
3481 let mut negated = Vec::with_capacity(text.len().saturating_add(1));
3482 negated.push(b'-');
3483 negated.extend_from_slice(text);
3484 return Ok(integer_literal(&negated));
3485 }
3486 // A negated real literal is folded the same way, as SQLite's
3487 // `codeReal` does. Unary minus on anything else is `0 - x`, and
3488 // `0 - 0.0` is a positive zero, so without this `-0.0` would lose
3489 // the sign SQLite keeps: `INSERT INTO t VALUES (-0.0)` into an ANY
3490 // column of a STRICT table reads back `-0.0`.
3491 if let Some(Expr::Literal(Literal::Float(text))) = self.ast.expr(operand) {
3492 let parsed =
3493 inillucent_value::numeric::atof(text, inillucent_value::TextEncoding::Utf8);
3494 return Ok(BoundExpr::Real(-parsed.value));
3495 }
3496 }
3497 let operand = Box::new(self.bind_expr(operand)?);
3498 match op {
3499 UnaryOp::Not => Ok(BoundExpr::Not(operand)),
3500 _ => Ok(BoundExpr::Unary { op, operand }),
3501 }
3502 }
3503
3504 /// Binds one expression.
3505 pub fn bind_expr(&mut self, id: ExprId) -> Result<BoundExpr, ParseError> {
3506 let span = self.ast.expr_span(id);
3507 let Some(expr) = self.ast.expr(id) else {
3508 return Err(unsupported("missing expression", span));
3509 };
3510 // **A literal is bound off the arena, before the clone** (task-2006). `Literal`
3511 // owns its digits, so `SELECT 1` allocated one byte to copy the byte `1` in order
3512 // to match on it, and a statement full of literals paid that per literal. The
3513 // clone below is a borrow split rather than a choice - the arms call `&mut self`
3514 // methods and need the owned names and sub-expression lists their variants hold -
3515 // but a literal needs neither.
3516 if let Expr::Literal(literal) = expr {
3517 return self.bind_literal(literal, span);
3518 }
3519 match expr.clone() {
3520 Expr::Literal(literal) => self.bind_literal(&literal, span),
3521 Expr::Parameter { index, .. } => Ok(BoundExpr::Parameter(index)),
3522 Expr::Column {
3523 database,
3524 table,
3525 column,
3526 } => self.bind_column_reference(database, table, column, span),
3527 Expr::Star { .. } => Err(ParseError::new(
3528 ParseErrorKind::Unexpected {
3529 found: "*".to_string(),
3530 expected: vec!["an expression"],
3531 },
3532 span,
3533 )),
3534 Expr::Unary { op, operand } => self.bind_unary(op, operand),
3535 Expr::Binary { op, left, right } => self.bind_binary(op, left, right),
3536 Expr::Collate { operand, collation } => {
3537 let name = self.ast.text(collation);
3538 let Some(collation) = self.collation_named(name) else {
3539 return Err(no_such_collation(name, span));
3540 };
3541 let bound = self.bind_expr(operand)?;
3542 Ok(apply_collation(bound, collation))
3543 }
3544 Expr::Cast { operand, declared } => {
3545 let operand = Box::new(self.bind_expr(operand)?);
3546 let affinity =
3547 inillucent_value::affinity::affinity_of_declared_type(self.ast.text(declared));
3548 Ok(BoundExpr::Cast { operand, affinity })
3549 }
3550 Expr::Pattern {
3551 negated,
3552 op,
3553 operand,
3554 pattern,
3555 escape,
3556 } => {
3557 if op == PatternOp::Regexp {
3558 // `X REGEXP Y` is sugar for `regexp(Y, X)` - the pattern
3559 // first - and the operator exists only because the function
3560 // does. The reference shell registers one, so this engine
3561 // registers one too, and the operator binds to it here
3562 // rather than refusing.
3563 let subject = self.bind_expr(operand)?;
3564 let pattern = self.bind_expr(pattern)?;
3565 let call = BoundExpr::Function {
3566 func: ScalarFunc::Regexp,
3567 arguments: vec![pattern, subject],
3568 collation: Collation::Binary,
3569 };
3570 return Ok(if negated {
3571 BoundExpr::Not(Box::new(call))
3572 } else {
3573 call
3574 });
3575 }
3576 if op == PatternOp::Match {
3577 // `x MATCH y` is a call to a function called `match`, which
3578 // does not exist - unless `x` is a column of a virtual
3579 // table, in which case it is a constraint the module is
3580 // offered and the module says what it means. That is the
3581 // whole of how `t MATCH 'word'` reaches FTS5.
3582 let left = self.bind_expr(operand)?;
3583 if !self.is_virtual_column(&left) {
3584 return Err(no_such_function(b"match", span));
3585 }
3586 let pattern = Box::new(self.bind_expr(pattern)?);
3587 return Ok(BoundExpr::Pattern {
3588 negated,
3589 op: PatternOp::Match,
3590 operand: Box::new(left),
3591 pattern,
3592 escape: None,
3593 });
3594 }
3595 let operand = Box::new(self.bind_expr(operand)?);
3596 let pattern = Box::new(self.bind_expr(pattern)?);
3597 let escape = match escape {
3598 Some(expr) => Some(Box::new(self.bind_expr(expr)?)),
3599 None => None,
3600 };
3601 Ok(BoundExpr::Pattern {
3602 negated,
3603 op,
3604 operand,
3605 pattern,
3606 escape,
3607 })
3608 }
3609 Expr::Between {
3610 negated,
3611 operand,
3612 low,
3613 high,
3614 } => {
3615 if let Some(parts) = self.row_value_parts(operand) {
3616 return self.bind_row_between(negated, &parts, low, high, span);
3617 }
3618 let operand = self.bind_expr(operand)?;
3619 let low = self.bind_expr(low)?;
3620 let high = self.bind_expr(high)?;
3621 let (low_affinity, low_collation) = comparison_rules(&operand, &low);
3622 let (high_affinity, high_collation) = comparison_rules(&operand, &high);
3623 Ok(BoundExpr::Between {
3624 negated,
3625 operand: Box::new(operand),
3626 low: Box::new(low),
3627 high: Box::new(high),
3628 low_affinity,
3629 low_collation,
3630 high_affinity,
3631 high_collation,
3632 })
3633 }
3634 Expr::In {
3635 negated,
3636 operand,
3637 rhs,
3638 } => {
3639 // **The row-value `IN` form is an OR of equality chains**, which
3640 // is exactly what SQLite's `IN` over a value list means: `(a, b)
3641 // IN (VALUES (1,2),(3,4))` is `(a=1 AND b=2) OR (a=3 AND b=4)`,
3642 // with the same unknown-rather-than-false behaviour when a part
3643 // is NULL. The rows are written as a `VALUES` clause, which the
3644 // grammar parses as a select, so the desugaring reads them back
3645 // out of it rather than adding a second spelling.
3646 if let Some(parts) = self.row_value_parts(operand) {
3647 return self.bind_row_in(&parts, &rhs, negated, span);
3648 }
3649 let operand = self.bind_expr(operand)?;
3650 let rhs = match rhs {
3651 InRhs::Select(select) => {
3652 return self.bind_in_subquery(operand, select, negated, span)
3653 }
3654 InRhs::Table { .. } => {
3655 return Err(unsupported("IN over a table name", span));
3656 }
3657 other => other,
3658 };
3659 let InRhs::List(items) = rhs else {
3660 return Err(unsupported("IN over a subquery or table", span));
3661 };
3662 let mut list = Vec::with_capacity(items.len());
3663 for item in &items {
3664 list.push(self.bind_expr(*item)?);
3665 }
3666 let (affinity, collation) = match list.first() {
3667 Some(first) => comparison_rules(&operand, first),
3668 None => (None, Collation::Binary),
3669 };
3670 Ok(BoundExpr::InList {
3671 negated,
3672 operand: Box::new(operand),
3673 list,
3674 affinity,
3675 collation,
3676 })
3677 }
3678 Expr::IsNull { negated, operand } => Ok(BoundExpr::IsNull {
3679 negated,
3680 operand: Box::new(self.bind_expr(operand)?),
3681 }),
3682 Expr::Is {
3683 negated,
3684 distinct_from,
3685 left,
3686 right,
3687 } => {
3688 if let (Some(lefts), Some(rights)) =
3689 (self.row_value_parts(left), self.row_value_parts(right))
3690 {
3691 return self.bind_row_is(negated != distinct_from, &lefts, &rights, span);
3692 }
3693 let left = self.bind_expr(left)?;
3694 let right = self.bind_expr(right)?;
3695 let (affinity, collation) = comparison_rules(&left, &right);
3696 // **`DISTINCT FROM` inverts the sense, and it was being
3697 // dropped.** `a IS b` is already NULL-safe equality, so
3698 // `a IS NOT DISTINCT FROM b` is `a IS b` and
3699 // `a IS DISTINCT FROM b` is `a IS NOT b`. Binding the keyword
3700 // away left `1 IS DISTINCT FROM NULL` meaning `1 IS NULL` -
3701 // 0 where SQLite answers 1, and 0 again for
3702 // `1 IS NOT DISTINCT FROM 1`, so both spellings answered the
3703 // opposite of the truth.
3704 let negated = negated != distinct_from;
3705 Ok(BoundExpr::Is {
3706 negated,
3707 left: Box::new(left),
3708 right: Box::new(right),
3709 affinity,
3710 collation,
3711 })
3712 }
3713 Expr::Case {
3714 operand,
3715 branches,
3716 otherwise,
3717 } => {
3718 if let Some(parts) = operand.and_then(|operand| self.row_value_parts(operand)) {
3719 return self.bind_row_case(&parts, &branches, otherwise, span);
3720 }
3721 let bound_operand = match operand {
3722 Some(expr) => Some(Box::new(self.bind_expr(expr)?)),
3723 None => None,
3724 };
3725 let mut bound_branches = Vec::with_capacity(branches.len());
3726 for (when, then) in &branches {
3727 bound_branches.push((self.bind_expr(*when)?, self.bind_expr(*then)?));
3728 }
3729 let bound_otherwise = match otherwise {
3730 Some(expr) => Some(Box::new(self.bind_expr(expr)?)),
3731 None => None,
3732 };
3733 let comparisons = match &bound_operand {
3734 Some(operand) => bound_branches
3735 .iter()
3736 .map(|(when, _)| comparison_rules(operand, when))
3737 .collect(),
3738 None => Vec::new(),
3739 };
3740 Ok(BoundExpr::Case {
3741 operand: bound_operand,
3742 branches: bound_branches,
3743 otherwise: bound_otherwise,
3744 comparisons,
3745 })
3746 }
3747 Expr::Function {
3748 name,
3749 distinct,
3750 arguments,
3751 order_by,
3752 filter,
3753 over,
3754 } => {
3755 if let Some(over) = over {
3756 return self.bind_window_call(name, distinct, arguments, filter, over, span);
3757 }
3758 // **`FILTER` and an in-argument `ORDER BY` belong to the
3759 // aggregate, not to the window.** Both were refused here, so
3760 // `count(*) FILTER (WHERE a > 15)` and
3761 // `group_concat(b ORDER BY a DESC)` - two shapes an ordinary
3762 // report is written in - could not be asked at all. They are
3763 // bound onto the call and applied by the accumulator.
3764 self.bind_call_with(name, distinct, arguments, filter, &order_by, span)
3765 }
3766 Expr::Exists { negated, select } => {
3767 let block = self.bind_value_subquery(select, span)?;
3768 Ok(BoundExpr::Subquery {
3769 id: self.next_subquery_id(),
3770 kind: SubqueryKind::Exists,
3771 negated,
3772 operand: None,
3773 block: Box::new(block),
3774 affinity: None,
3775 collation: Collation::Binary,
3776 })
3777 }
3778 Expr::Subquery(select) => {
3779 let block = self.bind_value_subquery(select, span)?;
3780 if block.columns.len() != 1 {
3781 return Err(ParseError::new(
3782 ParseErrorKind::Unsupported("sub-select returns more than one column"),
3783 span,
3784 ));
3785 }
3786 Ok(BoundExpr::Subquery {
3787 id: self.next_subquery_id(),
3788 kind: SubqueryKind::Scalar,
3789 negated: false,
3790 operand: None,
3791 block: Box::new(block),
3792 affinity: None,
3793 collation: Collation::Binary,
3794 })
3795 }
3796 // **A row value anywhere else is SQLite's "row value misused"**, a
3797 // refusal with code 1 about the statement. Every place SQLite
3798 // takes a row value - a comparison, `IS`, `BETWEEN`, `IN`, a
3799 // `CASE` operand and a `SET` list - is handled before this is
3800 // reached, so what is left is a statement SQLite refuses too, and
3801 // reporting it as a feature not built yet told a caller to wait
3802 // for something that will never come.
3803 Expr::RowValue(_) => Err(rowvalue::misused(span)),
3804 Expr::Raise { action, message } => self.bind_raise(action, message, span),
3805 }
3806 }
3807
3808 /// Binds a literal, converting its written text into a value.
3809 fn bind_literal(&self, literal: &Literal, _span: Span) -> Result<BoundExpr, ParseError> {
3810 match literal {
3811 Literal::Null => Ok(BoundExpr::Null),
3812 Literal::Boolean(value) => Ok(BoundExpr::Integer(i64::from(*value))),
3813 Literal::Integer(text) => Ok(integer_literal(text)),
3814 Literal::Float(text) => {
3815 let parsed =
3816 inillucent_value::numeric::atof(text, inillucent_value::TextEncoding::Utf8);
3817 Ok(BoundExpr::Real(parsed.value))
3818 }
3819 Literal::String(text) => Ok(BoundExpr::Text(text.clone())),
3820 Literal::Blob(bytes) => Ok(BoundExpr::Blob(bytes.clone())),
3821 Literal::CurrentDate | Literal::CurrentTime | Literal::CurrentTimestamp => {
3822 // The three keywords are the three functions with no argument,
3823 // and `CURRENT_TIMESTAMP` is `datetime('now')` rather than a
3824 // fourth thing that formats differently.
3825 let func = match literal {
3826 Literal::CurrentDate => TimeFunc::Date,
3827 Literal::CurrentTime => TimeFunc::Time,
3828 _ => TimeFunc::DateTime,
3829 };
3830 Ok(BoundExpr::Time {
3831 func,
3832 arguments: Vec::new(),
3833 })
3834 }
3835 }
3836 }
3837
3838 /// Resolves `excluded.column` inside an upsert's `DO UPDATE`.
3839 ///
3840 /// `excluded` is only in scope there, so a query that uses the name
3841 /// anywhere else gets the ordinary "no such table" answer rather than a
3842 /// row that came from nowhere.
3843 fn bind_excluded_column(&mut self, folded: &[u8], span: Span) -> Result<BoundExpr, ParseError> {
3844 let Some(table) = self.excluded.clone() else {
3845 return Err(no_such_table(b"excluded", span));
3846 };
3847 if let Some(position) = table.column_position(folded) {
3848 if table.rowid_alias == Some(position) {
3849 return Ok(BoundExpr::Rowid {
3850 source: EXCLUDED_SOURCE,
3851 });
3852 }
3853 let Some(info) = table.column(position) else {
3854 return Err(no_such_column(folded, span));
3855 };
3856 let collation = self
3857 .collation_named(&info.collation)
3858 .unwrap_or(Collation::Binary);
3859 return Ok(BoundExpr::Column {
3860 source: EXCLUDED_SOURCE,
3861 column: position,
3862 // `excluded` is a row in registers rather than a record, so the
3863 // compiler substitutes it wholesale and the slot is never read.
3864 slot: position,
3865 affinity: info.affinity,
3866 collation,
3867 });
3868 }
3869 if table.is_rowid_name(folded) {
3870 return Ok(BoundExpr::Rowid {
3871 source: EXCLUDED_SOURCE,
3872 });
3873 }
3874 Err(no_such_column(folded, span))
3875 }
3876
3877 /// Resolves `old.column` or `new.column` inside a trigger body.
3878 ///
3879 /// The event decides which of the two exists: an INSERT has no previous row
3880 /// and a DELETE has no next one. Naming the missing one is the ordinary
3881 /// "no such table" error, because that is what it is - outside a trigger
3882 /// body neither name resolves at all.
3883 fn bind_row_alias_column(
3884 &mut self,
3885 source: usize,
3886 folded: &[u8],
3887 span: Span,
3888 ) -> Result<BoundExpr, ParseError> {
3889 let written: &[u8] = if source == OLD_SOURCE { b"old" } else { b"new" };
3890 let Some(aliases) = self.row_aliases.clone() else {
3891 return Err(no_such_table(written, span));
3892 };
3893 let available = if source == OLD_SOURCE {
3894 aliases.old
3895 } else {
3896 aliases.new
3897 };
3898 if !available {
3899 return Err(no_such_table(written, span));
3900 }
3901 let table = &aliases.table;
3902 if let Some(position) = table.column_position(folded) {
3903 if table.rowid_alias == Some(position) {
3904 return Ok(BoundExpr::Rowid { source });
3905 }
3906 let Some(info) = table.column(position) else {
3907 return Err(no_such_column(folded, span));
3908 };
3909 let collation = self
3910 .collation_named(&info.collation)
3911 .unwrap_or(Collation::Binary);
3912 return Ok(BoundExpr::Column {
3913 source,
3914 column: position,
3915 // The row lives in registers rather than in a record, so the
3916 // compiler substitutes it wholesale and the slot is never read.
3917 slot: position,
3918 affinity: info.affinity,
3919 collation,
3920 });
3921 }
3922 if table.is_rowid_name(folded) {
3923 return Ok(BoundExpr::Rowid { source });
3924 }
3925 Err(no_such_column(folded, span))
3926 }
3927
3928 /// Resolves a column reference against the scope stack.
3929 ///
3930 /// The innermost block is searched first and a hit there ends the search,
3931 /// so an inner name shadows an outer one. A hit in an enclosing block is
3932 /// recorded as a correlation, which is the fact the compiler uses to decide
3933 /// whether the block runs once or once per outer row.
3934 fn bind_column_reference(
3935 &mut self,
3936 database: Option<ast::NameId>,
3937 table: Option<ast::NameId>,
3938 column: ast::NameId,
3939 span: Span,
3940 ) -> Result<BoundExpr, ParseError> {
3941 let folded = self.ast.folded(column).to_vec();
3942 let table_folded = table.map(|id| self.ast.folded(id).to_vec());
3943 let database_folded = database.map(|id| self.ast.folded(id).to_vec());
3944 if table_folded.as_deref() == Some(b"excluded".as_slice()) {
3945 return self.bind_excluded_column(&folded, span);
3946 }
3947 // `OLD` and `NEW` shadow a table of the same name only inside a trigger
3948 // body, which is the one place they mean anything.
3949 if self.row_aliases.is_some() && database.is_none() {
3950 match table_folded.as_deref() {
3951 Some(b"old") => return self.bind_row_alias_column(OLD_SOURCE, &folded, span),
3952 Some(b"new") => return self.bind_row_alias_column(NEW_SOURCE, &folded, span),
3953 _ => {}
3954 }
3955 }
3956 let mut resolved: Option<(usize, u16)> = None;
3957 let mut rowid_of: Option<usize> = None;
3958 let levels = self.scopes.len();
3959 for level in (0..levels).rev() {
3960 let ids: Vec<usize> = self
3961 .scopes
3962 .get(level)
3963 .map_or(Vec::new(), |scope| scope.clone());
3964 let mut found: Option<(usize, u16)> = None;
3965 let mut coalesced: Vec<(usize, u16)> = Vec::new();
3966 let mut rowid_here: Option<usize> = None;
3967 for id in ids {
3968 let Some(source) = self.sources.get(id) else {
3969 continue;
3970 };
3971 if let Some(qualifier) = table_folded.as_deref() {
3972 if !source.alias.eq_ignore_ascii_case(qualifier) {
3973 continue;
3974 }
3975 }
3976 if let Some(qualifier) = database_folded.as_deref() {
3977 if !self
3978 .catalog
3979 .database_name(source.table.database)
3980 .eq_ignore_ascii_case(qualifier)
3981 {
3982 continue;
3983 }
3984 }
3985 if let Some(index) = source.table.column_position(&folded) {
3986 // **A `USING` or `NATURAL` join coalesces the named
3987 // column.** The join has one `k`, not two: it comes from
3988 // the left term, and the right term's copy is suppressed -
3989 // from `*`, which this already did, and from an
3990 // *unqualified* reference, which it did not. That is why
3991 // `SELECT * FROM a JOIN b USING (k) ORDER BY k` answered
3992 // `ambiguous column name: k`, and why four of the five join
3993 // spellings failed on one message. A qualified `b.k` still
3994 // reaches the right-hand copy, which is what SQLite does.
3995 //
3996 // **A `RIGHT` or `FULL` join is the exception.** Its left
3997 // copy is NULL on a row only the right side has, so SQLite
3998 // resolves the name to the right copy under `RIGHT` and to
3999 // `coalesce()` of every copy under `FULL`; see
4000 // `step_using_match`.
4001 if table_folded.is_none() && source.suppressed.contains(&index) {
4002 using::step_using_match(
4003 source.join,
4004 (id, index),
4005 &mut found,
4006 &mut coalesced,
4007 );
4008 continue;
4009 }
4010 if found.is_some() {
4011 return Err(ambiguous_column(self.ast.text(column), span));
4012 }
4013 found = Some((id, index));
4014 continue;
4015 }
4016 if source.table.is_rowid_name(&folded) && rowid_here.is_none() {
4017 rowid_here = Some(id);
4018 }
4019 }
4020 if coalesced.len() > 1 {
4021 return self.coalesce_using_copies(&coalesced, span);
4022 }
4023 if found.is_some() {
4024 resolved = found;
4025 break;
4026 }
4027 if let Some(id) = rowid_here {
4028 rowid_of = Some(id);
4029 break;
4030 }
4031 }
4032 if let Some((source, index)) = resolved {
4033 return self.authorized_column(source, index, span);
4034 }
4035 if let Some(source) = rowid_of {
4036 self.note_correlation(source);
4037 return Ok(BoundExpr::Rowid { source });
4038 }
4039 // A result alias is visible to GROUP BY, HAVING and ORDER BY, and only
4040 // after a real column has failed to match, which is SQLite's order.
4041 if table_folded.is_none() {
4042 if let Some((_, expr)) = self
4043 .result_aliases
4044 .iter()
4045 .find(|(name, _)| name.as_slice() == folded.as_slice())
4046 {
4047 return Ok(expr.clone());
4048 }
4049 }
4050 if self.sources.is_empty() && table_folded.is_none() {
4051 return Err(no_such_column_quoted(
4052 self.ast.text(column),
4053 self.ast
4054 .name(column)
4055 .map(|name| name.quote)
4056 .unwrap_or(QuoteForm::Bare),
4057 span,
4058 ));
4059 }
4060 match table_folded {
4061 Some(_)
4062 if !self.sources.iter().any(|source| {
4063 table_folded
4064 .as_deref()
4065 .is_some_and(|q| source.alias.eq_ignore_ascii_case(q))
4066 }) =>
4067 {
4068 Err(no_such_table(
4069 table.map(|id| self.ast.text(id)).unwrap_or(b""),
4070 span,
4071 ))
4072 }
4073 _ if table_folded.is_none() => Err(no_such_column_quoted(
4074 self.ast.text(column),
4075 self.ast
4076 .name(column)
4077 .map(|name| name.quote)
4078 .unwrap_or(QuoteForm::Bare),
4079 span,
4080 )),
4081 // A qualified reference names both halves, which is what the
4082 // reference prints: `no such column: t.b`, not `no such column: b`.
4083 _ => {
4084 let qualifier = table.map(|id| self.ast.text(id)).unwrap_or(b"");
4085 Err(no_such_column(
4086 &[qualifier, b".", self.ast.text(column)].concat(),
4087 span,
4088 ))
4089 }
4090 }
4091 }
4092
4093 /// Returns a column reference the authorizer has been asked about.
4094 ///
4095 /// The authorizer may allow the read, refuse the statement, or ask for
4096 /// the column to read as NULL, which is what `Ignore` means in SQLite.
4097 ///
4098 /// @param source - the source id the column belongs to
4099 /// @param index - the column's position in that source
4100 /// @param span - where the reference is, for an error
4101 pub(super) fn authorized_column(
4102 &mut self,
4103 source: usize,
4104 index: u16,
4105 span: Span,
4106 ) -> Result<BoundExpr, ParseError> {
4107 let (database_name, table_name, column_name) = {
4108 let Some(bound) = self.sources.get(source) else {
4109 return Err(unsupported("unknown source", span));
4110 };
4111 let Some(info) = bound.table.column(index) else {
4112 return Err(unsupported("unknown column", span));
4113 };
4114 (
4115 self.catalog.database_name(bound.table.database).to_vec(),
4116 bound.table.name.clone(),
4117 info.name.clone(),
4118 )
4119 };
4120 match self.authorizer.authorize(AuthAction::Read {
4121 database: &database_name,
4122 table: &table_name,
4123 column: &column_name,
4124 }) {
4125 Authorization::Allow => {}
4126 Authorization::Deny => return Err(denied("not authorized", span)),
4127 Authorization::Ignore => return Ok(BoundExpr::Null),
4128 }
4129 self.note_correlation(source);
4130 self.column_expr(source, index)
4131 }
4132
4133 /// Binds a binary operator, choosing comparison or arithmetic semantics.
4134 fn bind_binary(
4135 &mut self,
4136 op: BinaryOp,
4137 left: ExprId,
4138 right: ExprId,
4139 ) -> Result<BoundExpr, ParseError> {
4140 // **A row-value comparison is a comparison of its parts.** `(a, b) =
4141 // (1, 2)` is `a = 1 AND b = 2`, and the ordering operators are
4142 // lexicographic - `(a, b) < (x, y)` is `a < x OR (a = x AND b < y)`,
4143 // which is where the NULL behaviour comes from rather than being a rule
4144 // of its own. It is desugared here rather than carried into the plan
4145 // because there is nothing about it the executor would do differently:
4146 // the parts are ordinary comparisons over ordinary expressions.
4147 if let (Some(lefts), Some(rights)) =
4148 (self.row_value_parts(left), self.row_value_parts(right))
4149 {
4150 return self.bind_row_comparison(op, &lefts, &rights, self.ast.expr_span(left));
4151 }
4152 // **A row value against a query**, which is the form an application
4153 // actually writes: `WHERE (a, b) = (SELECT a, b FROM t WHERE id = 3)`.
4154 // Only the row-against-a-row spelling was desugared, so this was
4155 // `unsupported: row values`.
4156 if let (Some(lefts), Some(select)) = (
4157 self.row_value_parts(left),
4158 self.ast.expr(right).and_then(|expr| match expr {
4159 Expr::Subquery(select) => Some(*select),
4160 _ => None,
4161 }),
4162 ) {
4163 return self.bind_row_against_query(op, &lefts, select, self.ast.expr_span(left));
4164 }
4165 let bound_left = self.bind_expr(left)?;
4166 let bound_right = self.bind_expr(right)?;
4167 match op {
4168 BinaryOp::And => Ok(BoundExpr::And(Box::new(bound_left), Box::new(bound_right))),
4169 BinaryOp::Or => Ok(BoundExpr::Or(Box::new(bound_left), Box::new(bound_right))),
4170 BinaryOp::Equal
4171 | BinaryOp::NotEqual
4172 | BinaryOp::Less
4173 | BinaryOp::LessEqual
4174 | BinaryOp::Greater
4175 | BinaryOp::GreaterEqual => {
4176 let (affinity, collation) = comparison_rules(&bound_left, &bound_right);
4177 Ok(BoundExpr::Compare {
4178 op,
4179 left: Box::new(bound_left),
4180 right: Box::new(bound_right),
4181 affinity,
4182 collation,
4183 })
4184 }
4185 BinaryOp::Regexp => Ok(BoundExpr::Function {
4186 func: ScalarFunc::Regexp,
4187 arguments: vec![bound_right, bound_left],
4188 collation: Collation::Binary,
4189 }),
4190 // **pgvector's distance operators are sugar for the functions**,
4191 // which is exactly what they are in pgvector too: an operator class
4192 // over a function, so that an index can be asked for the same
4193 // ordering the expression writes. `<#>` is the odd one, and it is
4194 // odd in pgvector as well - it answers the *negative* inner product,
4195 // so that a smaller number is a better match and one index
4196 // direction serves every operator.
4197 BinaryOp::L2Distance
4198 | BinaryOp::CosineDistance
4199 | BinaryOp::L1Distance
4200 | BinaryOp::HammingDistance
4201 | BinaryOp::JaccardDistance => Ok(BoundExpr::Function {
4202 func: match op {
4203 BinaryOp::L2Distance => ScalarFunc::VectorDistanceL2,
4204 BinaryOp::CosineDistance => ScalarFunc::VectorDistanceCos,
4205 BinaryOp::L1Distance => ScalarFunc::VectorDistanceL1,
4206 BinaryOp::HammingDistance => ScalarFunc::VectorDistanceHamming,
4207 _ => ScalarFunc::VectorDistanceJaccard,
4208 },
4209 arguments: vec![bound_left, bound_right],
4210 collation: Collation::Binary,
4211 }),
4212 BinaryOp::NegativeInnerProduct => Ok(BoundExpr::Unary {
4213 op: UnaryOp::Negate,
4214 operand: Box::new(BoundExpr::Function {
4215 func: ScalarFunc::VectorDot,
4216 arguments: vec![bound_left, bound_right],
4217 collation: Collation::Binary,
4218 }),
4219 }),
4220 BinaryOp::Match => Err(no_such_function(b"match", self.ast.expr_span(right))),
4221 BinaryOp::Extract | BinaryOp::ExtractText => Ok(BoundExpr::Json {
4222 func: if op == BinaryOp::Extract {
4223 JsonFunc::Arrow
4224 } else {
4225 JsonFunc::ArrowShift
4226 },
4227 arguments: vec![bound_left, bound_right],
4228 }),
4229 _ => {
4230 // **A vector has no arithmetic, and answering zero is worse
4231 // than refusing.** `v + v` used to be accepted and answer
4232 // `0.0`: the blob went through numeric affinity, which reads no
4233 // leading digits and calls that nothing. pgvector defines `+`
4234 // element-wise; this engine does not implement it, and a
4235 // caller who wrote it gets told so rather than getting a
4236 // column of zeroes.
4237 // **Element-wise, which is what pgvector defines.** `+`, `-`
4238 // and `*` over two vectors work component by component, and
4239 // `*` with a number on one side scales. Anything else over a
4240 // vector - a division, a modulo, a shift - has no pgvector
4241 // meaning, and answering `0.0` for it is worse than refusing:
4242 // the blob would go through numeric affinity, which reads no
4243 // leading digits and calls that nothing.
4244 if let Some(func) = match op {
4245 BinaryOp::Add => Some(ScalarFunc::VectorAdd),
4246 BinaryOp::Subtract => Some(ScalarFunc::VectorSubtract),
4247 BinaryOp::Multiply => Some(ScalarFunc::VectorMultiply),
4248 _ => None,
4249 } {
4250 if self.reads_a_vector(&bound_left) || self.reads_a_vector(&bound_right) {
4251 return Ok(BoundExpr::Function {
4252 func,
4253 arguments: vec![bound_left, bound_right],
4254 collation: Collation::Binary,
4255 });
4256 }
4257 }
4258 if self.reads_a_vector(&bound_left) || self.reads_a_vector(&bound_right) {
4259 return Err(unsupported(
4260 "arithmetic over a vector column",
4261 self.ast.expr_span(left),
4262 ));
4263 }
4264 Ok(BoundExpr::Arithmetic {
4265 op,
4266 left: Box::new(bound_left),
4267 right: Box::new(bound_right),
4268 })
4269 }
4270 }
4271 }
4272
4273 /// Reports whether an expression is a reference to a `VECTOR` column.
4274 ///
4275 /// Only a bare reference, and deliberately: `length(v)` and `hex(v)` are
4276 /// questions about the bytes and answer them, and a general "does this
4277 /// expression have vector in it anywhere" rule would refuse those too.
4278 ///
4279 /// @param expr - the bound expression to look at
4280 fn reads_a_vector(&self, expr: &BoundExpr) -> bool {
4281 let BoundExpr::Column { source, column, .. } = expr else {
4282 return false;
4283 };
4284 self.sources
4285 .iter()
4286 .find(|held| held.id == *source)
4287 .and_then(|held| held.table.columns.get(usize::from(*column)))
4288 .is_some_and(crate::catalog_view::ColumnInfo::is_vector)
4289 }
4290
4291 /// Binds a call that may carry a `FILTER` and an in-argument `ORDER BY`.
4292 ///
4293 /// Both belong to an *aggregate* call and are dropped for anything else,
4294 /// which is what the arity and aggregate checks below already establish:
4295 /// a scalar call cannot reach the arm that reads them.
4296 ///
4297 /// @param name - the function name
4298 /// @param distinct - whether `DISTINCT` was written
4299 /// @param arguments - the argument list, or `None` for `count(*)`
4300 /// @param filter - the `FILTER (WHERE ...)` clause, when one was written
4301 /// @param order_by - the `ORDER BY` inside the argument list
4302 /// @param span - where the call was written
4303 fn bind_call_with(
4304 &mut self,
4305 name: ast::NameId,
4306 distinct: bool,
4307 arguments: Option<Vec<ExprId>>,
4308 filter: Option<ExprId>,
4309 order_by: &[ast::OrderTerm],
4310 span: Span,
4311 ) -> Result<BoundExpr, ParseError> {
4312 let folded = self.ast.folded(name).to_vec();
4313 if self
4314 .authorizer
4315 .authorize(AuthAction::Function { name: &folded })
4316 == Authorization::Deny
4317 {
4318 return Err(denied("not authorized", span));
4319 }
4320 let star = arguments.is_none();
4321 let list = arguments.unwrap_or_default();
4322 if !star && !distinct && !list.is_empty() {
4323 if let Some(bound) = self.bind_auxiliary_call(&folded, &list, span)? {
4324 return Ok(bound);
4325 }
4326 }
4327 if !star {
4328 if let Some(bound) = self.bind_external_call(&folded, &list, distinct, span)? {
4329 return Ok(bound);
4330 }
4331 }
4332 if function::is_aggregate_call(&folded, list.len(), star) {
4333 let Some(func) =
4334 function::lookup_aggregate(&folded).or_else(|| function::minmax_aggregate(&folded))
4335 else {
4336 return Err(no_such_function(&folded, span));
4337 };
4338 if !self.allow_aggregates || self.inside_aggregate {
4339 return Err(unsupported("misuse of aggregate function", span));
4340 }
4341 if star && func != AggregateFunc::Count {
4342 return Err(wrong_arguments(&folded, span));
4343 }
4344 if !function::aggregate_arity_ok(func, if star { 0 } else { list.len() }, star) {
4345 return Err(wrong_arguments(&folded, span));
4346 }
4347 self.inside_aggregate = true;
4348 let mut bound = Vec::with_capacity(list.len());
4349 for argument in &list {
4350 bound.push(self.bind_expr(*argument)?);
4351 }
4352 self.inside_aggregate = false;
4353 // The `FILTER` and the `ORDER BY` read the row the aggregate is
4354 // folding, so they bind in the same scope the arguments did - and
4355 // outside `inside_aggregate`, because neither may itself contain
4356 // an aggregate.
4357 let bound_filter = match filter {
4358 Some(expr) => Some(self.bind_expr(expr)?),
4359 None => None,
4360 };
4361 let bound_order = self.bind_aggregate_order(order_by)?;
4362 let collation = bound
4363 .first()
4364 .and_then(BoundExpr::collation)
4365 .unwrap_or(Collation::Binary);
4366 // The same reason `v + v` refuses: `sum(v)` and `avg(v)` coerced
4367 // the blob through numeric affinity and answered `0.0` for a whole
4368 // column of embeddings. pgvector's `avg(vector)` is an element-wise
4369 // mean; this engine does not compute one, and says so.
4370 // **A vector column folds component by component.** `sum(v)` and
4371 // `avg(v)` over embeddings used to coerce the blob through numeric
4372 // affinity and answer `0.0` for a whole column; pgvector defines
4373 // them as element-wise, and this is that - chosen here, where the
4374 // argument's type is known, rather than at run time where a blob is
4375 // just a blob.
4376 let func = match func {
4377 function::AggregateFunc::Sum | function::AggregateFunc::Total
4378 if bound.iter().any(|argument| self.reads_a_vector(argument)) =>
4379 {
4380 function::AggregateFunc::VectorSum
4381 }
4382 function::AggregateFunc::Avg
4383 if bound.iter().any(|argument| self.reads_a_vector(argument)) =>
4384 {
4385 function::AggregateFunc::VectorAvg
4386 }
4387 other => other,
4388 };
4389 // **`DISTINCT` takes exactly one argument (task-1913).** SQLite
4390 // answers `DISTINCT aggregates must have exactly one argument`,
4391 // and this accepted `group_concat(DISTINCT s, ',')` and answered
4392 // it - a statement the reference cannot read, which is the same
4393 // class `refusals_match_the_oracle` exists to stop. There is
4394 // nothing for the second argument to be distinct *by*: the
4395 // de-duplication compares the first value alone, so the separator
4396 // of whichever duplicate arrived first is the one that survives.
4397 if distinct && bound.len() > 1 {
4398 return Err(refused(
4399 "DISTINCT aggregates must have exactly one argument",
4400 span,
4401 ));
4402 }
4403 let candidate = BoundAggregate {
4404 func,
4405 external: None,
4406 distinct,
4407 arguments: bound,
4408 star,
4409 collation,
4410 filter: bound_filter,
4411 order_by: bound_order,
4412 };
4413 return Ok(self.aggregate_slot(candidate));
4414 }
4415 if let Some(func) = function::lookup_time(&folded) {
4416 if star {
4417 return Err(wrong_arguments(&folded, span));
4418 }
4419 if func == function::TimeFunc::TimeDiff && list.len() != 2 {
4420 return Err(wrong_arguments(&folded, span));
4421 }
4422 if func == function::TimeFunc::StrfTime && list.is_empty() {
4423 return Err(wrong_arguments(&folded, span));
4424 }
4425 let mut bound = Vec::with_capacity(list.len());
4426 for argument in &list {
4427 bound.push(self.bind_expr(*argument)?);
4428 }
4429 return Ok(BoundExpr::Time {
4430 func,
4431 arguments: bound,
4432 });
4433 }
4434 if let Some(func) = function::lookup_math(&folded) {
4435 if star {
4436 return Err(wrong_arguments(&folded, span));
4437 }
4438 let (least, most) = func.arity();
4439 if list.len() < least || list.len() > most {
4440 return Err(wrong_arguments(&folded, span));
4441 }
4442 let mut bound = Vec::with_capacity(list.len());
4443 for argument in &list {
4444 bound.push(self.bind_expr(*argument)?);
4445 }
4446 return Ok(BoundExpr::Math {
4447 func,
4448 arguments: bound,
4449 });
4450 }
4451 if let Some(func) = function::lookup_json(&folded) {
4452 if star {
4453 return Err(wrong_arguments(&folded, span));
4454 }
4455 if !func.arity_ok(list.len()) {
4456 return Err(wrong_arguments(&folded, span));
4457 }
4458 let mut bound = Vec::with_capacity(list.len());
4459 for argument in &list {
4460 let argument = self.bind_expr(*argument)?;
4461 bound.push(self.marked_as_json(argument));
4462 }
4463 return Ok(BoundExpr::Json {
4464 func,
4465 arguments: bound,
4466 });
4467 }
4468 if folded == b"subtype" && list.len() == 1 {
4469 let Some(argument) = list.first().copied() else {
4470 return Err(wrong_arguments(&folded, span));
4471 };
4472 return self.bind_subtype(argument);
4473 }
4474 let Some(func) = function::lookup_scalar(&folded) else {
4475 return Err(no_such_function(&folded, span));
4476 };
4477 if star {
4478 return Err(wrong_arguments(&folded, span));
4479 }
4480 // **`DISTINCT` in a function that is not an aggregate is ignored, as in
4481 // SQLite.** The pinned 3.53.4 answers `abs(DISTINCT a)` as `abs(a)`, and
4482 // the same for the date, math and JSON functions and for `coalesce`. It
4483 // used to be refused here and in the three branches above, and the
4484 // capability note said SQLite refused it too, which nobody had run.
4485 if !function::scalar_arity_ok(func, list.len()) {
4486 return Err(wrong_arguments(&folded, span));
4487 }
4488 let mut bound = Vec::with_capacity(list.len());
4489 for argument in &list {
4490 bound.push(self.bind_expr(*argument)?);
4491 }
4492 let collation = bound
4493 .first()
4494 .and_then(BoundExpr::collation)
4495 .unwrap_or(Collation::Binary);
4496 Ok(BoundExpr::Function {
4497 func,
4498 arguments: bound,
4499 collation,
4500 })
4501 }
4502}
4503
4504/// Returns a refusal whose text is computed rather than a fixed phrase.
4505///
4506/// `Unsupported` carries a `&'static str` because most refusals are one of a
4507/// closed set of phrases and interning them keeps the error type cheap. A
4508/// refusal that has to name a column or count something cannot be one of those,
4509/// so it carries the whole sentence.
4510///
4511/// **`Refused`, not `Unexpected`.** It used to be reported as
4512/// an unexpected-input failure carrying the sentence, on the reasoning that
4513/// this is the shape SQLite's own messages take - and it is not.
4514/// `ParseErrorKind::Unexpected` renders as `near "X": syntax error`, so
4515/// `CREATE TABLE t(a)` on a table that exists answered
4516/// `near "table t already exists": syntax error` where the reference answers
4517/// `table t already exists`. Forty-seven refusals in `directive.rs` alone took
4518/// that shape, and the register audit's own probe is what printed it side by
4519/// side. `Refused` is the variant whose whole purpose is a sentence the schema
4520/// wants said in the reference's words, and it renders as one.
4521pub(crate) fn refused(detail: impl Into<String>, span: Span) -> ParseError {
4522 ParseError::new(ParseErrorKind::Refused(detail.into()), span)
4523}
4524
4525/// Builds the table a nested query's rows are read through.
4526///
4527/// The columns are the block's result columns. Their affinity and collation
4528/// come from the expressions behind them, so a comparison against a subquery
4529/// column applies the rules it would have applied one level down; a column with
4530/// no affinity of its own gets none, which is what SQLite does for an
4531/// expression that is not a bare column or a cast.
4532/// Returns the columns a nested query's result presents to a reader.
4533///
4534/// Public because a write to a view needs them before there is a FROM term to
4535/// hang them on: the view's catalog entry carries no column list at all.
4536pub fn subquery_columns(select: &BoundSelect, names: &[Vec<u8>]) -> Vec<ColumnInfo> {
4537 select
4538 .columns
4539 .iter()
4540 .enumerate()
4541 .map(|(index, column)| {
4542 let name = names
4543 .get(index)
4544 .cloned()
4545 .unwrap_or_else(|| column.name.clone());
4546 let folded = name.to_ascii_lowercase();
4547 let collation = column.expr.collation().unwrap_or(Collation::Binary);
4548 ColumnInfo {
4549 name,
4550 folded,
4551 declared_type: column.declared_type.clone(),
4552 affinity: column.expr.affinity().unwrap_or(Affinity::Blob),
4553 collation: collation.name().as_bytes().to_ascii_lowercase(),
4554 not_null: false,
4555 not_null_conflict: None,
4556 primary_key_conflict: None,
4557 default_sql: None,
4558 primary_key_position: None,
4559 hidden: false,
4560 generated: false,
4561 stored: false,
4562 generated_sql: None,
4563 }
4564 })
4565 .collect()
4566}
4567
4568/// Returns a block that reads one FROM term and nothing else.
4569///
4570/// Everything a `SELECT` can carry is empty here on purpose: this exists to
4571/// wrap a term the binder has already produced so the compiler can iterate it,
4572/// not to stand in for a query somebody wrote.
4573pub fn block_over(
4574 source: BoundSource,
4575 filter: Option<BoundExpr>,
4576 columns: Vec<BoundResultColumn>,
4577) -> BoundSelect {
4578 BoundSelect {
4579 sources: vec![source],
4580 filter,
4581 group_by: Vec::new(),
4582 having: None,
4583 columns,
4584 distinct: false,
4585 order_by: Vec::new(),
4586 limit: None,
4587 offset: None,
4588 aggregates: Vec::new(),
4589 values: Vec::new(),
4590 compounds: Vec::new(),
4591 windows: Vec::new(),
4592 correlations: Vec::new(),
4593 }
4594}
4595
4596fn subquery_table(alias: &[u8], names: &[Vec<u8>], select: &BoundSelect) -> TableInfo {
4597 TableInfo::subquery(alias.to_vec(), 0, subquery_columns(select, names))
4598}
4599
4600/// Returns the aggregate a name spells inside an `OVER` clause.
4601///
4602/// `min` and `max` are the awkward pair: with one argument they are aggregates
4603/// and with two or more they are scalars, and only the argument count tells
4604/// them apart. Inside a window the one-argument form is always the aggregate,
4605/// which is why the ordinary aggregate lookup - which has to leave them out -
4606/// is not enough here.
4607fn window_aggregate(folded: &[u8], arguments: usize) -> Option<AggregateFunc> {
4608 if let Some(func) = function::lookup_aggregate(folded) {
4609 return Some(func);
4610 }
4611 match (folded, arguments) {
4612 (b"min", 1) => Some(AggregateFunc::Min),
4613 (b"max", 1) => Some(AggregateFunc::Max),
4614 _ => None,
4615 }
4616}
4617
4618/// Returns a "no such window" failure.
4619fn no_such_window(name: &[u8], span: Span) -> ParseError {
4620 ParseError::new(
4621 ParseErrorKind::Refused(format!("no such window: {}", String::from_utf8_lossy(name))),
4622 span,
4623 )
4624}
4625
4626/// Returns an authorizer refusal.
4627fn denied(what: &'static str, span: Span) -> ParseError {
4628 ParseError::new(ParseErrorKind::Unsupported(what), span)
4629}