inillucent_sql/dml.rs
1//! Binding INSERT, UPDATE and DELETE.
2//!
3//! Invariant: a bound DML statement names every value it will write, in table
4//! column order, before anything is compiled. A column the statement did not
5//! mention is not left to be filled in later by whoever runs it - it carries
6//! its `DEFAULT`, or a NULL, as an expression like any other. That is what
7//! makes `INSERT INTO t(b) VALUES(1)` and `INSERT INTO t VALUES(NULL, 1)`
8//! compile to the same shape, and it is why the constraint checks can be
9//! written once against a row image rather than twice against two.
10//!
11//! Constraints are bound here too, out of the `CREATE TABLE` text the file
12//! stores. The catalog keeps them as source, because the catalog sits below
13//! the binder and cannot bind anything; the binder parses that source against
14//! the table it belongs to and gets an ordinary expression back. A CHECK is
15//! therefore evaluated by exactly the machinery that evaluates a WHERE clause,
16//! which is the only way to be sure the two agree about what `x > 0` means
17//! when `x` is text.
18
19use inillucent_base::limits::Limits;
20use inillucent_value::Collation;
21
22use crate::ast::{self, ConflictAction};
23use crate::bind::{
24 no_such_column, refused, unsupported, Binder, BoundExpr, BoundOrderTerm, BoundResultColumn,
25 BoundSelect, BoundSource,
26};
27use crate::catalog_view::{IndexInfo, TableInfo, TableKind, TriggerEventInfo, TriggerInfo};
28use crate::diagnostic::ParseError;
29use crate::lexer::Span;
30use crate::parser::parse_expression;
31
32/// The internal tables an application may write, as SQLite allows.
33///
34/// **Four, and two of them are the schema.** Every table whose
35/// name begins with `sqlite_` used to be refused, which is wrong for all four,
36/// because writing them is the documented way to use them:
37///
38/// - `sqlite_schema`, and `sqlite_master` which is its other name, are what
39/// `PRAGMA writable_schema` is for, and `.dump` emits
40/// `INSERT INTO sqlite_schema(type,name,tbl_name,rootpage,sql)VALUES(...)`
41/// for a virtual table - which is the only way a dump can restore one
42/// without building empty shadow tables over the ones it is about to fill
43/// (task-1979, R2). Whether the pragma is on is the *engine's* question and
44/// not the binder's: `ImportedDatabase::refuse_schema_write` refuses the
45/// statement when it is off, the way `refuse_shadow_write` refuses a write a
46/// defensive connection may not make.
47///
48/// - `sqlite_sequence` holds one row per `AUTOINCREMENT` table, and
49/// `UPDATE sqlite_sequence SET seq = 0 WHERE name = 't'` is how the counter is
50/// reset. `DELETE FROM sqlite_sequence` is how it is reset for every table at
51/// once. Refusing them left no way at all to do either.
52/// - `sqlite_stat1` is what `ANALYZE` writes, and `.dump` emits
53/// `INSERT INTO sqlite_stat1 VALUES(...)` for it - so a dump this engine
54/// produced could not be replayed into it.
55///
56/// They are ordinary tables in every other respect: the rows are what they are,
57/// and a value written into one is used exactly as `ANALYZE` or the rowid
58/// allocator would have used the one it replaced.
59const WRITABLE_INTERNAL: [&[u8]; 4] = [
60 b"sqlite_sequence",
61 b"sqlite_stat1",
62 b"sqlite_schema",
63 b"sqlite_master",
64];
65
66/// Where one column's value comes from in an INSERT.
67#[derive(Clone, Debug, PartialEq)]
68pub enum ColumnSource {
69 /// The value at this position of the source row.
70 Row(usize),
71 /// An expression evaluated once per row, which is what a `DEFAULT` is.
72 Expr(BoundExpr),
73 /// A generated column, computed from the rest of the row rather than from
74 /// anything the statement supplied.
75 ///
76 /// It is its own variant because it is evaluated at a different *time*: a
77 /// `DEFAULT` is a value like any other, while a generated column reads the
78 /// row it is part of and so cannot be computed until the rest of it is.
79 Generated(BoundExpr),
80}
81
82/// What an INSERT inserts.
83#[derive(Clone, Debug, PartialEq)]
84pub enum BoundInsertSource {
85 /// Literal rows, each already bound.
86 Values(Vec<Vec<BoundExpr>>),
87 /// A query, whose result columns feed the target columns in order.
88 Select(Box<BoundSelect>),
89}
90
91/// One `CHECK` constraint, bound against its table.
92#[derive(Clone, Debug, PartialEq)]
93pub struct BoundCheck {
94 /// The constraint's name, when it was written with one.
95 pub name: Option<Vec<u8>>,
96 /// The predicate.
97 pub expr: BoundExpr,
98}
99
100/// A `NOT NULL` column's `DEFAULT`, bound so a `REPLACE` can stand it in.
101///
102/// **REPLACE's rule for a `NOT NULL` violation is to substitute the column's
103/// default, and to fall back to `ABORT` only when there is no default.** So
104/// `UPDATE OR REPLACE t SET c = NULL` on `c TEXT NOT NULL DEFAULT 'd'` stores
105/// `'d'`, and this engine used to refuse the statement instead.
106///
107/// The write path cannot bind one for itself: a default is schema text, and by
108/// the time a row is being checked the parser is long out of scope. The binder
109/// already binds one for every column a statement *omits*; these are the same
110/// expressions bound for the columns it supplies, which is where a NULL that
111/// needs replacing can come from.
112///
113/// Only the columns that can need it are here - `NOT NULL` and with a default -
114/// so an ordinary table carries an empty vector and the write path skips the
115/// whole apparatus.
116#[derive(Clone, Debug, PartialEq)]
117pub struct BoundDefault {
118 /// The column the default belongs to.
119 pub column: u16,
120 /// The default expression, bound.
121 pub expr: BoundExpr,
122}
123
124/// The expressions one index needs evaluated per row to be maintained.
125///
126/// **An index is usually just columns of the row, and then it needs none of
127/// this.** A partial index holds only the rows its predicate accepts, and an
128/// index on an expression holds a value no column carries - so for those two,
129/// maintaining the index means evaluating something per row rather than
130/// copying a slot. They travel on the bound statement for the same reason the
131/// table's `CHECK` predicates do: the binder is what can turn schema text into
132/// a `BoundExpr`, and the write path is what runs it.
133///
134/// The list holds only the indexes that need it, so a table with neither kind
135/// leaves it empty and the write path's loop runs zero times - which is every
136/// table the gate measures.
137#[derive(Clone, Debug, PartialEq)]
138pub struct BoundIndexExprs {
139 /// The index's position in the table's `indexes`.
140 pub position: usize,
141 /// The partial-index predicate, when it has one.
142 pub predicate: Option<BoundExpr>,
143 /// One per key column: the expression it indexes, or `None` for a column.
144 pub keys: Vec<Option<BoundExpr>>,
145}
146
147/// One statement of a trigger body, bound.
148///
149/// The four the grammar allows and no more. A trigger body is not a general
150/// statement list: it cannot create objects, cannot open transactions, and
151/// cannot return rows to the caller, so a variant for anything else would be a
152/// shape the binder is required to refuse.
153#[derive(Clone, Debug, PartialEq)]
154pub enum BoundTriggerStatement {
155 /// `INSERT`.
156 Insert(Box<BoundInsert>),
157 /// `UPDATE`.
158 Update(Box<BoundUpdate>),
159 /// `DELETE`.
160 Delete(Box<BoundDelete>),
161 /// `SELECT`, which a body runs for its side effects - in practice for the
162 /// `RAISE()` inside it.
163 Select(Box<BoundSelect>),
164}
165
166/// A trigger, bound against the write that fires it.
167///
168/// It is bound per statement rather than once per schema because the body's
169/// FROM terms take statement-wide source numbers, and those only exist relative
170/// to the statement they are inlined into.
171#[derive(Clone, Debug, PartialEq)]
172pub struct BoundTrigger {
173 /// The trigger's name, for the diagnostic when its body fails.
174 pub name: Vec<u8>,
175 /// The folded name of the table it is attached to.
176 ///
177 /// Read by the executor to decide whether a body statement is writing the
178 /// trigger's *own* table, which is what `PRAGMA recursive_triggers` is
179 /// about: with it on, such a write fires this trigger again.
180 pub table: Vec<u8>,
181 /// Whether it fires before or after the row is written.
182 pub time: ast::TriggerTime,
183 /// The `WHEN` guard, when one was written.
184 pub when: Option<BoundExpr>,
185 /// The body statements, in written order.
186 pub body: Vec<BoundTriggerStatement>,
187 /// Whether the binder synthesised this from a `REFERENCES` clause rather
188 /// than reading it from a `CREATE TRIGGER`.
189 ///
190 /// **Read by `DROP TABLE` (task-1979, F6).** Dropping a table with foreign
191 /// keys on runs an implicit `DELETE FROM` first, so the keys that reference
192 /// it are enforced - and SQLite's rule is that the implicit delete fires no
193 /// triggers of its own while still performing every foreign key action. A
194 /// delete bound for that purpose keeps the triggers this flag marks and
195 /// drops the rest.
196 pub foreign_key: bool,
197 /// Whether the foreign key this enforces has one table as both its child
198 /// and its parent.
199 ///
200 /// **Also read by `DROP TABLE` (task-1979, F6).** The implicit delete keeps
201 /// the foreign key triggers and drops this one, because emptying a table
202 /// cannot leave a row of that same table pointing at nothing - see
203 /// `ForeignKeyTrigger::self_referencing`, which is where the value comes
204 /// from. Always false on a trigger the schema wrote.
205 pub self_referencing: bool,
206}
207
208/// A bound `INSERT`.
209#[derive(Clone, Debug, PartialEq)]
210pub struct BoundInsert {
211 /// The table being written.
212 pub table: TableInfo,
213 /// The statement-wide number of the FROM term being written.
214 ///
215 /// It used to be implicitly zero, because a DML statement had exactly one
216 /// source. A trigger body is compiled into the statement that fires it, so
217 /// its target takes the next number after the firing statement's - and a
218 /// compiler that assumed zero read the wrong cursor for every fire after
219 /// the first.
220 pub target_source: usize,
221 /// Where each table column's value comes from, in column order.
222 pub columns: Vec<ColumnSource>,
223 /// Where the rowid comes from, when the statement supplies one.
224 pub rowid: Option<ColumnSource>,
225 /// Which value of the supplied row is the rowid, when the statement named
226 /// it outright.
227 ///
228 /// `INSERT INTO t(rowid, a) VALUES (7, 'x')` is legal on any rowid table,
229 /// including one with no `INTEGER PRIMARY KEY` to alias it and including a
230 /// virtual table. It is recorded separately from `rowid` because it is not
231 /// a column: nothing writes it into the record.
232 pub named_rowid: Option<usize>,
233 /// The rows.
234 pub source: BoundInsertSource,
235 /// How many values each source row supplies.
236 pub arity: usize,
237 /// The statement's conflict algorithm, when it wrote one.
238 pub on_conflict: Option<ConflictAction>,
239 /// The table's `CHECK` constraints.
240 pub checks: Vec<BoundCheck>,
241 /// The `DEFAULT`s a `REPLACE` may stand in for a NULL, by column.
242 pub not_null_defaults: Vec<BoundDefault>,
243 /// The expressions the table's partial and expression indexes need.
244 pub index_exprs: Vec<BoundIndexExprs>,
245 /// The `ON CONFLICT ... DO UPDATE` clause, when there is one.
246 pub upsert: Vec<BoundUpsert>,
247 /// `sqlite_sequence`'s root page, when the target is `AUTOINCREMENT`.
248 ///
249 /// Resolved here rather than in the compiler because it is a fact about the
250 /// catalog, and the catalog is what the binder holds. It is zero for every
251 /// other table, which is also what it reads as before the first
252 /// `AUTOINCREMENT` table in a database is created.
253 pub sequence_root: u32,
254 /// The `RETURNING` columns.
255 pub returning: Vec<BoundResultColumn>,
256 /// The triggers this write fires, in schema order.
257 pub triggers: Vec<BoundTrigger>,
258 /// The foreign-key actions a `REPLACE` fires for the row it removes.
259 ///
260 /// A `REPLACE` that deletes a row to make room for another is a delete,
261 /// and the keys pointing at that row have to be told. Written `DELETE`
262 /// triggers are *not* fired - that is SQLite's rule with its default
263 /// `recursive_triggers = off` - so these are only the ones a key implies.
264 pub replace_triggers: Vec<BoundTrigger>,
265}
266
267/// A bound `ON CONFLICT ... DO UPDATE` clause.
268#[derive(Clone, Debug, PartialEq)]
269pub struct BoundUpsert {
270 /// The conflict target columns, when written; empty means any constraint.
271 ///
272 /// Sorted, because a conflict target names a *set* of columns and
273 /// `ON CONFLICT(a,b)` and `ON CONFLICT(b,a)` name the same one. Matching
274 /// them against an index's columns is a set comparison, and sorting here
275 /// is what makes it one comparison rather than a search per column.
276 pub target: Vec<u16>,
277 /// The assignments, or empty for `DO NOTHING`.
278 pub assignments: Vec<BoundAssignment>,
279 /// Whether the action is `DO UPDATE`.
280 pub do_update: bool,
281 /// The `WHERE` on the `DO UPDATE`.
282 pub filter: Option<BoundExpr>,
283}
284
285/// One `SET` assignment.
286#[derive(Clone, Debug, PartialEq)]
287pub struct BoundAssignment {
288 /// The column being assigned, as a declared position.
289 pub column: u16,
290 /// Whether the assignment names the row's own rowid rather than a declared
291 /// column, in which case `column` says nothing.
292 ///
293 /// **`UPDATE t SET rowid = 100` was `no such column: rowid` (task-1979,
294 /// F9).** An assignment target was looked up with `column_position`, which
295 /// only knows the columns the table declares, and a table with no INTEGER
296 /// PRIMARY KEY declares none for its rowid. SQLite accepts all three
297 /// spellings of the rowid on either kind of table and moves the row to the
298 /// new key.
299 pub rowid: bool,
300 /// The new value.
301 pub value: BoundExpr,
302}
303
304/// A bound `UPDATE`.
305#[derive(Clone, Debug, PartialEq)]
306pub struct BoundUpdate {
307 /// The table being written.
308 pub table: TableInfo,
309 /// The statement-wide number of the FROM term being written.
310 ///
311 /// It used to be implicitly zero, because a DML statement had exactly one
312 /// source. A trigger body is compiled into the statement that fires it, so
313 /// its target takes the next number after the firing statement's - and a
314 /// compiler that assumed zero read the wrong cursor for every fire after
315 /// the first.
316 pub source: usize,
317 /// The extra FROM terms of an `UPDATE ... FROM`, in written order.
318 ///
319 /// **The rows being updated come from a join.** `UPDATE t SET v = s.v FROM s
320 /// WHERE s.a = t.a` is the shape a migration writes to copy a column across
321 /// tables, and the values it assigns are not expressions over the target
322 /// row: they read a *different* row, one the join found. So the query that
323 /// finds the keys carries these terms too, and projects the assigned values
324 /// beside the key; see [`BoundUpdate::from`], which is this field.
325 ///
326 /// Empty for every ordinary `UPDATE`, which is what keeps the wider row off
327 /// the path the gate's `txn.large` measures.
328 pub from: Vec<crate::bind::BoundSource>,
329 /// The assignments, in table column order with duplicates already refused.
330 pub assignments: Vec<BoundAssignment>,
331 /// The `STORED` generated columns, recomputed after the assignments.
332 ///
333 /// **A stored generated column is part of the row, so a row that is
334 /// rewritten rewrites it (task-1913).** It is never named in a `SET`, so
335 /// an `UPDATE` used to leave whatever was written when the row was
336 /// inserted: `c GENERATED ALWAYS AS (a + 1) STORED` still read 2 after
337 /// `UPDATE g SET a = 5`, where SQLite reads 6. The wrong value is on the
338 /// disk rather than in an answer, so a later read of the same file is
339 /// wrong too, and an index on the column indexes the stale value.
340 ///
341 /// A `VIRTUAL` column is not here: it has no slot in the record and is
342 /// computed when it is read, which is why only this half needed fixing.
343 ///
344 /// These are evaluated against the row *after* the assignments, which is
345 /// the one difference from [`BoundUpdate::assignments`] - those read the
346 /// before image so `SET a = b, b = a` swaps.
347 pub generated: Vec<BoundAssignment>,
348 /// The `WHERE` clause.
349 pub filter: Option<BoundExpr>,
350 /// The statement's conflict algorithm, when it wrote one.
351 pub on_conflict: Option<ConflictAction>,
352 /// The table's `CHECK` constraints.
353 pub checks: Vec<BoundCheck>,
354 /// The `DEFAULT`s a `REPLACE` may stand in for a NULL, by column.
355 pub not_null_defaults: Vec<BoundDefault>,
356 /// The expressions the table's partial and expression indexes need.
357 pub index_exprs: Vec<BoundIndexExprs>,
358 /// `INDEXED BY` or `NOT INDEXED` on the target, which the query that finds
359 /// the rows to change obeys; `inillucent_exec::dml::hint_target` puts it there.
360 pub index_hint: crate::bind::IndexChoice,
361 /// The `RETURNING` columns.
362 pub returning: Vec<BoundResultColumn>,
363 /// The `ORDER BY` that decides which rows a `LIMIT` keeps.
364 ///
365 /// Empty unless the statement wrote one, and then always with a `LIMIT`,
366 /// because the binder refuses an order with nothing to limit. It goes onto
367 /// the query that finds the rows to change, which is where SQLite puts it
368 /// too: a limited write is `WHERE rowid IN (SELECT rowid ... ORDER BY ...
369 /// LIMIT ...)` there.
370 pub order_by: Vec<BoundOrderTerm>,
371 /// The `LIMIT`.
372 pub limit: Option<BoundExpr>,
373 /// The `OFFSET`.
374 pub offset: Option<BoundExpr>,
375 /// The triggers this write fires, in schema order.
376 pub triggers: Vec<BoundTrigger>,
377 /// The rows to fire an `INSTEAD OF` trigger for, when the target is a view.
378 ///
379 /// A view has no rows of its own, so `OLD` has to come from running the
380 /// view. This is that query, with the statement's `WHERE` on it and one
381 /// result column per view column.
382 pub view_rows: Option<Box<BoundSelect>>,
383}
384
385/// A bound `DELETE`.
386#[derive(Clone, Debug, PartialEq)]
387pub struct BoundDelete {
388 /// The table being written.
389 pub table: TableInfo,
390 /// The expressions the table's partial and expression indexes need.
391 ///
392 /// A delete needs them too: an entry only comes out of a partial index if
393 /// the row was in it, and a key the index computed has to be recomputed to
394 /// be found.
395 pub index_exprs: Vec<BoundIndexExprs>,
396 /// `INDEXED BY` or `NOT INDEXED` on the target, as on [`BoundUpdate`].
397 pub index_hint: crate::bind::IndexChoice,
398 /// The statement-wide number of the FROM term being written.
399 ///
400 /// It used to be implicitly zero, because a DML statement had exactly one
401 /// source. A trigger body is compiled into the statement that fires it, so
402 /// its target takes the next number after the firing statement's - and a
403 /// compiler that assumed zero read the wrong cursor for every fire after
404 /// the first.
405 pub source: usize,
406 /// The `WHERE` clause.
407 pub filter: Option<BoundExpr>,
408 /// The `RETURNING` columns.
409 pub returning: Vec<BoundResultColumn>,
410 /// The `ORDER BY` that decides which rows a `LIMIT` keeps.
411 ///
412 /// Empty unless the statement wrote one, and then always with a `LIMIT`,
413 /// because the binder refuses an order with nothing to limit. It goes onto
414 /// the query that finds the rows to change, which is where SQLite puts it
415 /// too: a limited write is `WHERE rowid IN (SELECT rowid ... ORDER BY ...
416 /// LIMIT ...)` there.
417 pub order_by: Vec<BoundOrderTerm>,
418 /// The `LIMIT`.
419 pub limit: Option<BoundExpr>,
420 /// The `OFFSET`.
421 pub offset: Option<BoundExpr>,
422 /// The triggers this write fires, in schema order.
423 pub triggers: Vec<BoundTrigger>,
424 /// The rows to fire an `INSTEAD OF` trigger for, when the target is a view.
425 pub view_rows: Option<Box<BoundSelect>>,
426}
427
428/// Reports whether an `INSERT` can resolve a conflict by deleting a row.
429///
430/// Either the statement said so, or one of the table's own constraints did.
431/// It is asked before the delete's keys are bound, because binding them costs
432/// a parse and a bind each and the answer is no for almost every insert.
433fn can_replace(table: &TableInfo, statement: Option<ConflictAction>) -> bool {
434 if statement == Some(ConflictAction::Replace) {
435 return true;
436 }
437 table
438 .indexes
439 .iter()
440 .any(|index| index.conflict == Some(ConflictAction::Replace))
441 || table.columns.iter().any(|column| {
442 column.not_null_conflict == Some(ConflictAction::Replace)
443 || column.primary_key_conflict == Some(ConflictAction::Replace)
444 })
445}
446
447/// Reports whether an unusable key's fault is one this write has to report.
448///
449/// A child's write reports a missing parent; a parent's write reports a
450/// mismatch. A statement that touches neither side of the broken key does not
451/// have to care, which is why the fault is carried rather than raised when the
452/// schema was read.
453fn fault_applies(
454 planned: &crate::catalog_view::ForeignKeyTrigger,
455 event: &TriggerEventInfo,
456) -> bool {
457 match event {
458 TriggerEventInfo::Insert => planned.is_check,
459 TriggerEventInfo::Delete => !planned.is_check,
460 TriggerEventInfo::Update(_) => true,
461 }
462}
463
464/// Marks a synthesised body's aborts as the foreign key's rather than a
465/// trigger's.
466///
467/// The generated text says `RAISE(ABORT, ...)` because that is what a person
468/// would have written, and what a person writes reports
469/// `SQLITE_CONSTRAINT_TRIGGER`. A foreign key reports its own code, and the
470/// only difference between the two is which constraint asked - so it is set
471/// here, on the bodies this binder generated, and nowhere else.
472fn report_as_foreign_key(trigger: &mut BoundTrigger) {
473 trigger.foreign_key = true;
474 for statement in &mut trigger.body {
475 let BoundTriggerStatement::Select(select) = statement else {
476 continue;
477 };
478 for column in &mut select.columns {
479 if let BoundExpr::Raise { foreign_key, .. } = &mut column.expr {
480 *foreign_key = true;
481 }
482 }
483 }
484}
485
486/// Returns whether a view has an `INSTEAD OF` trigger for one event.
487fn has_instead_of(table: &TableInfo, event: &TriggerEventInfo) -> bool {
488 table
489 .triggers
490 .iter()
491 .any(|trigger| trigger.time == ast::TriggerTime::InsteadOf && trigger.fires_for(event, &[]))
492}
493
494/// The target position that stands for the rowid rather than a column.
495///
496/// A table cannot have this many columns - SQLite's limit is two thousand - so
497/// there is no position it can collide with, and one sentinel is cheaper than
498/// a parallel `Option` threaded through every target list.
499const ROWID_TARGET: u16 = u16::MAX;
500
501/// Returns whether a name is one of the rowid's three spellings.
502fn is_rowid_name(folded: &[u8]) -> bool {
503 matches!(folded, b"rowid" | b"oid" | b"_rowid_")
504}
505
506/// How deep one write may drive triggers firing other triggers.
507///
508/// SQLite's own limit is `SQLITE_MAX_TRIGGER_DEPTH`, enforced when the frame is
509/// pushed. Trigger bodies are inlined here rather than run as frames, so the
510/// same limit is enforced where the inlining happens - and it has to be, or a
511/// schema in which two triggers write each other's tables would compile until
512/// the compiler ran out of memory.
513///
514/// **This is one number now, and it is the one `.limit` reports.** There used
515/// to be two constants of this name: this one at 32, which was the number
516/// actually enforced, and `inillucent-exec`'s at 1000, checked at run time over
517/// a tree the binder had already capped at 32 - so that check could never fire.
518/// `crates/inillucent-base/manifests/limits.toml` advertised 1000 and
519/// `inillucent diagnose` printed 1000, and a chain of forty distinct triggers
520/// that the oracle ran was refused here (task-1946, H3). The binder reads
521/// `Limit::TriggerDepth` from the connection now, which `.limit trigger_depth`
522/// and the driver both set; this constant is what a binder built without limits
523/// falls back to, and it is the manifest's default.
524pub const MAX_TRIGGER_DEPTH: usize = 1000;
525
526/// How deep one chain of foreign-key actions may go.
527///
528/// A cascade reaches this only when the keys form a cycle, which in practice
529/// means a table whose parent column points at itself. SQLite's own limit is a
530/// run-time recursion depth; this one is a compile-time inlining depth, and it
531/// is smaller for that reason.
532pub const MAX_FOREIGN_KEY_DEPTH: usize = 64;
533
534/// How many foreign-key action bodies one statement may inline in total.
535///
536/// The depth limit alone is not enough: a table with three keys that all cycle
537/// would inline three bodies per level, so the limit that matters is the total.
538/// A chain, which is what a self-referencing tree produces, spends one per
539/// level and reaches the depth limit first.
540pub const MAX_FOREIGN_KEY_STATEMENTS: usize = 256;
541
542impl<'a> Binder<'a> {
543 /// Binds an `INSERT` or `REPLACE`.
544 pub fn bind_insert(&mut self, insert: &ast::Insert) -> Result<BoundInsert, ParseError> {
545 // **A `WITH` on a DML statement is the same `WITH` a `SELECT` has.** The
546 // CTEs are in scope for the whole statement - the source query of an
547 // `INSERT`, the `WHERE` of an `UPDATE` or `DELETE` - and the binder's
548 // CTE stack already handles nesting, so pushing them here is all it
549 // takes. They were refused rather than bound, which is what a migration
550 // script written for SQLite hits first.
551 let pushed = self.push_ctes(&insert.with)?;
552 let bound = self.bind_insert_body(insert);
553 if pushed {
554 self.pop_ctes();
555 }
556 bound
557 }
558
559 /// Binds an `INSERT` with its CTEs already in scope.
560 fn bind_insert_body(&mut self, insert: &ast::Insert) -> Result<BoundInsert, ParseError> {
561 let table = self.writable_target(
562 insert.database,
563 insert.table,
564 Span::default(),
565 &TriggerEventInfo::Insert,
566 )?;
567 let alias = match insert.alias {
568 Some(alias) => self.ast.text(alias).to_vec(),
569 None => table.name.clone(),
570 };
571 let target_source = self.push_write_source(table.clone(), alias);
572 // `DEFAULT VALUES` supplies nothing, so every column takes its default
573 // - which is what an empty target list means here. The grammar does
574 // not allow a column list with it, so there is none to honour.
575 let targets = match insert.source {
576 ast::InsertSource::DefaultValues => Vec::new(),
577 ast::InsertSource::Select(_) => self.insert_targets(&table, &insert.columns)?,
578 };
579 let (source, arity) = self.bind_insert_source(&insert.source, &table, &targets)?;
580 if arity != targets.len() {
581 return Err(refused(
582 format!("{} values for {} columns", arity, targets.len()),
583 Span::default(),
584 ));
585 }
586 let (columns, rowid) = self.column_sources(&table, &targets)?;
587 let named_rowid = targets.iter().position(|target| *target == ROWID_TARGET);
588 let checks = self.bind_checks(&table)?;
589 let not_null_defaults = self.bind_not_null_defaults(&table)?;
590 let index_exprs = self.bind_index_exprs(&table)?;
591 let upsert = self.bind_upsert(&table, insert)?;
592 let returning = self.bind_returning(&insert.returning)?;
593 let mut triggers = self.bind_triggers(&table, TriggerEventInfo::Insert, &[])?;
594 triggers.extend(self.bind_foreign_keys(&table, TriggerEventInfo::Insert, &[])?);
595 let replace_triggers = if can_replace(&table, insert.on_conflict) {
596 self.bind_foreign_keys(&table, TriggerEventInfo::Delete, &[])?
597 } else {
598 Vec::new()
599 };
600 let sequence_root = if table.autoincrement {
601 self.catalog
602 .find_table(None, b"sqlite_sequence")
603 .map_or(0, |sequence| sequence.root)
604 } else {
605 0
606 };
607 Ok(BoundInsert {
608 table,
609 index_exprs,
610 target_source,
611 columns,
612 rowid,
613 named_rowid,
614 source,
615 arity,
616 on_conflict: insert.on_conflict,
617 checks,
618 not_null_defaults,
619 upsert,
620 sequence_root,
621 returning,
622 triggers,
623 replace_triggers,
624 })
625 }
626
627 /// Binds an `UPDATE`.
628 pub fn bind_update(&mut self, update: &ast::Update) -> Result<BoundUpdate, ParseError> {
629 let pushed = self.push_ctes(&update.with)?;
630 let bound = self.bind_update_body(update);
631 if pushed {
632 self.pop_ctes();
633 }
634 bound
635 }
636
637 /// Binds an `UPDATE ... FROM` clause, after the target.
638 ///
639 /// Returns the terms the clause adds and the constraints its table-valued
640 /// functions' arguments became, which belong in the statement's `WHERE`.
641 ///
642 /// **A table-valued function's arguments are constraints on its hidden
643 /// columns**, which `bind_table_arguments` leaves for the statement's
644 /// `WHERE`. A `SELECT` adds them there; the `UPDATE` did not, so `UPDATE
645 /// todo SET position = j.key FROM json_each('[3,1,2]') AS j WHERE todo.id =
646 /// j.value` ran `json_each` with no document, found no rows and reported
647 /// success with nothing changed.
648 ///
649 /// **The terms this block owns, not every source bound since.** A derived
650 /// table binds its own inner terms into the same list, and taking
651 /// everything bound after the target made them top level terms of the
652 /// `UPDATE` as well: `FROM (SELECT id, pos FROM ord) AS p` joined `ord`
653 /// again, beside `p`, so every row was found once per row of `ord` and the
654 /// statement reported 9 changes for 3.
655 ///
656 /// @param from - the clause's terms, in written order
657 fn bind_update_from(
658 &mut self,
659 from: &[ast::FromTermId],
660 ) -> Result<(Vec<crate::bind::BoundSource>, Vec<BoundExpr>), ParseError> {
661 let before = self.sources.len();
662 for term in from {
663 self.bind_from_term(*term)?;
664 }
665 self.desugar_join_constraints(from)?;
666 let arguments = core::mem::take(&mut self.pending_constraints);
667 let joined: Vec<crate::bind::BoundSource> = self
668 .scope()
669 .iter()
670 .filter(|id| **id >= before)
671 .filter_map(|id| self.sources.get(*id).cloned())
672 .collect();
673 Ok((joined, arguments))
674 }
675
676 /// Binds an `UPDATE` with its CTEs already in scope.
677 fn bind_update_body(&mut self, update: &ast::Update) -> Result<BoundUpdate, ParseError> {
678 if let Some(refusal) = order_without_limit(update.limited_at, update.limit, "UPDATE") {
679 return Err(refusal);
680 }
681 let (table, source) =
682 self.write_target_from_term(update.target, &TriggerEventInfo::Update(Vec::new()))?;
683 // **The `FROM` terms are bound after the target**, so the target keeps
684 // the lowest source number and every reference to an unqualified column
685 // resolves to it first - which is SQLite's rule and the reason
686 // `UPDATE t SET v = v + 1 FROM s` means the target's `v`.
687 let (joined, arguments) = self.bind_update_from(&update.from)?;
688 let mut assignments = Vec::new();
689 for (names, value) in &update.assignments {
690 let bound = self.bind_expr(*value)?;
691 for name in names {
692 let folded = self.ast.folded(*name).to_vec();
693 // `rowid`, `oid` and `_rowid_` name the row's key rather than a
694 // declared column, unless the table declares a column by one of
695 // those names - which is what `is_rowid_name` decides.
696 if table.is_rowid_name(&folded) {
697 if assignments.iter().any(|held: &BoundAssignment| held.rowid) {
698 return Err(refused(
699 format!(
700 "column {} is assigned twice",
701 String::from_utf8_lossy(self.ast.text(*name))
702 ),
703 Span::default(),
704 ));
705 }
706 assignments.push(BoundAssignment {
707 column: 0,
708 rowid: true,
709 value: bound.clone(),
710 });
711 continue;
712 }
713 let Some(position) = table.column_position(&folded) else {
714 return Err(no_such_column(self.ast.text(*name), Span::default()));
715 };
716 // **An assignment to a generated column is refused, not
717 // ignored (task-1913).** SQLite answers `cannot UPDATE
718 // generated column "c"`; this accepted the statement, reported
719 // it as a success, and wrote nothing the caller asked for -
720 // either the record took the value and the column stopped
721 // agreeing with its own expression, or the recompute above put
722 // it back and the assignment was silently dropped. `INSERT`
723 // already refused the same thing.
724 self.refuse_generated(&table, position, "UPDATE", Span::default())?;
725 if assignments
726 .iter()
727 .any(|existing: &BoundAssignment| existing.column == position)
728 {
729 return Err(refused(
730 format!(
731 "column {} is assigned twice",
732 String::from_utf8_lossy(self.ast.text(*name))
733 ),
734 Span::default(),
735 ));
736 }
737 assignments.push(BoundAssignment {
738 column: position,
739 rowid: false,
740 value: bound.clone(),
741 });
742 }
743 }
744 // The rowid assignment sorts with the declared columns rather than
745 // ahead of them, because `column` says nothing for it and the order
746 // only has to be stable.
747 assignments.sort_by_key(|assignment| (assignment.rowid, assignment.column));
748 let mut filter = match update.filter {
749 Some(expr) => Some(self.bind_expr(expr)?),
750 None => None,
751 };
752 for constraint in arguments {
753 filter = Some(match filter.take() {
754 Some(existing) => BoundExpr::And(Box::new(existing), Box::new(constraint)),
755 None => constraint,
756 });
757 }
758 let generated = self.bind_stored_generated(&table)?;
759 let checks = self.bind_checks(&table)?;
760 let not_null_defaults = self.bind_not_null_defaults(&table)?;
761 let index_exprs = self.bind_index_exprs(&table)?;
762 let returning = self.bind_returning(&update.returning)?;
763 // Bound as expressions, the way an aggregate's own `ORDER BY` is: a
764 // write has no result columns, so a bare integer names no ordinal.
765 let order_by = self.bind_aggregate_order(&update.order_by)?;
766 let limit = match update.limit {
767 Some(expr) => Some(self.bind_expr(expr)?),
768 None => None,
769 };
770 let offset = match update.offset {
771 Some(expr) => Some(self.bind_expr(expr)?),
772 None => None,
773 };
774 // The rowid is not a declared column, so no `UPDATE OF` trigger and no
775 // foreign key can be keyed on it and it contributes no name here.
776 let changed: Vec<Vec<u8>> = assignments
777 .iter()
778 .filter(|assignment| !assignment.rowid)
779 .filter_map(|assignment| table.column(assignment.column))
780 .map(|column| column.folded.clone())
781 .collect();
782 let mut triggers =
783 self.bind_triggers(&table, TriggerEventInfo::Update(Vec::new()), &changed)?;
784 triggers.extend(self.bind_foreign_keys(
785 &table,
786 TriggerEventInfo::Update(Vec::new()),
787 &changed,
788 )?);
789 let view_rows = self
790 .view_rows(&table, filter.clone())
791 .map(|rows| limit_view_rows(rows, &order_by, &limit, &offset));
792 let index_hint = self.write_hint(source, &index_exprs, filter.as_ref(), &joined)?;
793 Ok(BoundUpdate {
794 table,
795 index_exprs,
796 index_hint,
797 source,
798 from: joined,
799 assignments,
800 generated,
801 filter,
802 on_conflict: update.on_conflict,
803 checks,
804 not_null_defaults,
805 returning,
806 order_by,
807 limit,
808 offset,
809 triggers,
810 view_rows,
811 })
812 }
813
814 /// Binds a `DELETE`.
815 pub fn bind_delete(&mut self, delete: &ast::Delete) -> Result<BoundDelete, ParseError> {
816 let pushed = self.push_ctes(&delete.with)?;
817 let bound = self.bind_delete_body(delete);
818 if pushed {
819 self.pop_ctes();
820 }
821 bound
822 }
823
824 /// Binds a `DELETE` with its CTEs already in scope.
825 fn bind_delete_body(&mut self, delete: &ast::Delete) -> Result<BoundDelete, ParseError> {
826 if let Some(refusal) = order_without_limit(delete.limited_at, delete.limit, "DELETE") {
827 return Err(refusal);
828 }
829 let (table, source) =
830 self.write_target_from_term(delete.target, &TriggerEventInfo::Delete)?;
831 let index_exprs = self.bind_index_exprs(&table)?;
832 let filter = match delete.filter {
833 Some(expr) => Some(self.bind_expr(expr)?),
834 None => None,
835 };
836 let returning = self.bind_returning(&delete.returning)?;
837 let order_by = self.bind_aggregate_order(&delete.order_by)?;
838 let limit = match delete.limit {
839 Some(expr) => Some(self.bind_expr(expr)?),
840 None => None,
841 };
842 let offset = match delete.offset {
843 Some(expr) => Some(self.bind_expr(expr)?),
844 None => None,
845 };
846 let mut triggers = self.bind_triggers(&table, TriggerEventInfo::Delete, &[])?;
847 triggers.extend(self.bind_foreign_keys(&table, TriggerEventInfo::Delete, &[])?);
848 let view_rows = self
849 .view_rows(&table, filter.clone())
850 .map(|rows| limit_view_rows(rows, &order_by, &limit, &offset));
851 let index_hint = self.write_hint(source, &index_exprs, filter.as_ref(), &[])?;
852 Ok(BoundDelete {
853 table,
854 index_exprs,
855 index_hint,
856 source,
857 filter,
858 returning,
859 order_by,
860 limit,
861 offset,
862 triggers,
863 view_rows,
864 })
865 }
866
867 /// Binds the triggers one write fires, bodies and all.
868 ///
869 /// The bodies are bound here, into the same binder, so their FROM terms take
870 /// statement-wide source numbers alongside the write's own. That is what
871 /// lets the compiler inline them: a trigger body is not a separate program
872 /// with a separate cursor space, it is more of this statement.
873 ///
874 /// A trigger already being bound is skipped rather than bound again, which
875 /// is SQLite's behaviour with its default `recursive_triggers = off` and is
876 /// also the only reason inlining terminates.
877 ///
878 /// **Walked newest first.** `live.triggers` is in the order
879 /// `inillucent_catalog::paged::tables_from_entries` appended them while
880 /// reading `sqlite_schema` - the order the triggers were created in - and
881 /// SQLite fires two triggers of the same timing and event in the opposite
882 /// order: it keeps each table's trigger list with the most recently
883 /// created one first, so that one fires first.
884 /// `dml_differential.rs`'s `row_triggers_match_sqlite` has two `AFTER
885 /// INSERT` triggers on one table - `t_ai`, created first, and `t_high`,
886 /// created after it - and the pinned reference fires `t_high` before
887 /// `t_ai` on every insert. Reversing the walk here, once, at the one place
888 /// that reads `live.triggers` into a statement's own trigger list, is
889 /// enough: nothing downstream reorders it again.
890 fn bind_triggers(
891 &mut self,
892 table: &TableInfo,
893 event: TriggerEventInfo,
894 changed: &[Vec<u8>],
895 ) -> Result<Vec<BoundTrigger>, ParseError> {
896 // The catalog reference is copied out of `self` first: the trigger's
897 // arena has to outlive the binder for the body to be bound in place,
898 // and a borrow taken through `&self` would end at the first `&mut self`.
899 let catalog = self.catalog;
900 let database = catalog.database_name(table.database).to_vec();
901 let Some(live) = catalog.find_table(Some(database.as_slice()), &table.folded) else {
902 return Ok(Vec::new());
903 };
904 let (old, new) = match event {
905 TriggerEventInfo::Insert => (false, true),
906 TriggerEventInfo::Delete => (true, false),
907 TriggerEventInfo::Update(_) => (true, true),
908 };
909 let mut bound = Vec::new();
910 for trigger in live.triggers.iter().rev() {
911 if !trigger.fires_for(&event, changed) {
912 continue;
913 }
914 if self.firing.contains(&trigger.folded) {
915 continue;
916 }
917 if self.firing.len() >= self.trigger_depth {
918 // The number is in the message because a settable limit that
919 // refuses without saying what it was leaves a reader guessing
920 // between the default and whatever `.limit` last set.
921 return Err(refused(
922 format!(
923 "too many levels of trigger recursion: the limit is {}",
924 self.trigger_depth
925 ),
926 Span::default(),
927 ));
928 }
929 self.firing.push(trigger.folded.clone());
930 let saved_ast = self.ast;
931 let saved_scopes = core::mem::take(&mut self.scopes);
932 let saved_aliases = self.row_aliases.take();
933 let saved_target = self.view_target.take();
934 // A trigger body is schema text: the statements in it were written
935 // by whoever wrote the file, and they run because a write happened
936 // rather than because anybody submitted them.
937 let saved_site = self.call_site;
938 self.call_site = crate::function::CallSite::Schema;
939 self.ast = &trigger.ast;
940 self.row_aliases = Some(crate::bind::RowAliases {
941 table: table.clone(),
942 old,
943 new,
944 });
945 let result = self.bind_trigger_body(trigger, table);
946 self.call_site = saved_site;
947 self.ast = saved_ast;
948 self.scopes = saved_scopes;
949 self.row_aliases = saved_aliases;
950 self.view_target = saved_target;
951 self.firing.pop();
952 bound.push(result?);
953 }
954 Ok(bound)
955 }
956
957 /// Binds the triggers this write's foreign keys imply.
958 ///
959 /// The triggers themselves were generated when the schema was read - both
960 /// directions of every key, since nothing in the file records the reverse
961 /// one. What is decided here is which of them apply: whether keys are
962 /// enforced at all, whether a check waits for the commit, and whether this
963 /// particular write touches the columns a check is about.
964 fn bind_foreign_keys(
965 &mut self,
966 table: &TableInfo,
967 event: TriggerEventInfo,
968 changed: &[Vec<u8>],
969 ) -> Result<Vec<BoundTrigger>, ParseError> {
970 if !self.foreign_keys || table.kind != TableKind::Table {
971 return Ok(Vec::new());
972 }
973 let catalog = self.catalog;
974 let database = catalog.database_name(table.database).to_vec();
975 let Some(live) = catalog.find_table(Some(database.as_slice()), &table.folded) else {
976 return Ok(Vec::new());
977 };
978 let mut bound = Vec::new();
979 for planned in &live.foreign_key_triggers {
980 if planned.is_check && (planned.deferred || self.defer_foreign_keys) {
981 continue;
982 }
983 let Some(trigger) = planned.trigger.as_ref() else {
984 if fault_applies(planned, &event) {
985 return Err(crate::bind::schema_refused(
986 String::from_utf8_lossy(&planned.fault).into_owned(),
987 Span::default(),
988 ));
989 }
990 continue;
991 };
992 if !trigger.fires_for(&event, changed) {
993 continue;
994 }
995 if self.firing_foreign_keys.contains(&trigger.folded) {
996 continue;
997 }
998 let mut one = self.bind_foreign_key_trigger(table, trigger, &event)?;
999 one.self_referencing = planned.self_referencing;
1000 bound.push(one);
1001 }
1002 Ok(bound)
1003 }
1004
1005 /// Binds one synthesised trigger, inside the recursion budget.
1006 ///
1007 /// The budget is spent here rather than where the trigger was generated,
1008 /// because what a cascade costs is the *bound* body: one copy per level it
1009 /// can reach, and it can reach itself only when the keys form a cycle.
1010 fn bind_foreign_key_trigger(
1011 &mut self,
1012 table: &TableInfo,
1013 trigger: &'a TriggerInfo,
1014 event: &TriggerEventInfo,
1015 ) -> Result<BoundTrigger, ParseError> {
1016 if self.foreign_key_depth >= MAX_FOREIGN_KEY_DEPTH || self.foreign_key_budget == 0 {
1017 return Err(refused(
1018 "too many levels of foreign key recursion",
1019 Span::default(),
1020 ));
1021 }
1022 self.foreign_key_depth = self.foreign_key_depth.saturating_add(1);
1023 self.foreign_key_budget = self.foreign_key_budget.saturating_sub(1);
1024 self.firing_foreign_keys.push(trigger.folded.clone());
1025 let (old, new) = match event {
1026 TriggerEventInfo::Insert => (false, true),
1027 TriggerEventInfo::Delete => (true, false),
1028 TriggerEventInfo::Update(_) => (true, true),
1029 };
1030 let saved_ast = self.ast;
1031 let saved_scopes = core::mem::take(&mut self.scopes);
1032 let saved_aliases = self.row_aliases.take();
1033 let saved_target = self.view_target.take();
1034 // A synthesised key action is generated from a `REFERENCES` clause the
1035 // schema wrote, so it is schema too - the same site a written trigger
1036 // gets, because the binder turns both into the same text.
1037 let saved_site = self.call_site;
1038 self.call_site = crate::function::CallSite::Schema;
1039 self.ast = &trigger.ast;
1040 self.row_aliases = Some(crate::bind::RowAliases {
1041 table: table.clone(),
1042 old,
1043 new,
1044 });
1045 let result = self.bind_trigger_body(trigger, table);
1046 self.call_site = saved_site;
1047 self.ast = saved_ast;
1048 self.scopes = saved_scopes;
1049 self.row_aliases = saved_aliases;
1050 self.view_target = saved_target;
1051 self.foreign_key_depth = self.foreign_key_depth.saturating_sub(1);
1052 self.firing_foreign_keys.pop();
1053 let mut bound = result?;
1054 report_as_foreign_key(&mut bound);
1055 Ok(bound)
1056 }
1057
1058 /// Binds one trigger's guard and body statements.
1059 fn bind_trigger_body(
1060 &mut self,
1061 trigger: &TriggerInfo,
1062 table: &TableInfo,
1063 ) -> Result<BoundTrigger, ParseError> {
1064 let when = match trigger.when {
1065 Some(expr) => Some(self.bind_expr(expr)?),
1066 None => None,
1067 };
1068 let mut body = Vec::new();
1069 for statement in &trigger.body {
1070 // Each statement gets a fresh scope stack. A body statement's names
1071 // resolve against its own tables and against OLD and NEW, never
1072 // outward into the statement that fired it.
1073 let saved = core::mem::take(&mut self.scopes);
1074 let one = self.bind_trigger_statement(statement);
1075 self.scopes = saved;
1076 body.push(one?);
1077 }
1078 Ok(BoundTrigger {
1079 name: trigger.name.clone(),
1080 table: table.folded.clone(),
1081 time: trigger.time,
1082 when,
1083 body,
1084 foreign_key: false,
1085 self_referencing: false,
1086 })
1087 }
1088
1089 /// Binds one statement of a trigger body.
1090 pub(crate) fn bind_trigger_statement(
1091 &mut self,
1092 statement: &ast::Statement,
1093 ) -> Result<BoundTriggerStatement, ParseError> {
1094 match statement {
1095 ast::Statement::Insert(insert) => {
1096 if !insert.returning.is_empty() {
1097 return Err(refused(
1098 "RETURNING is not allowed on a trigger body statement",
1099 Span::default(),
1100 ));
1101 }
1102 Ok(BoundTriggerStatement::Insert(Box::new(
1103 self.bind_insert(insert)?,
1104 )))
1105 }
1106 ast::Statement::Update(update) => {
1107 if !update.returning.is_empty() {
1108 return Err(refused(
1109 "RETURNING is not allowed on a trigger body statement",
1110 Span::default(),
1111 ));
1112 }
1113 Ok(BoundTriggerStatement::Update(Box::new(
1114 self.bind_update(update)?,
1115 )))
1116 }
1117 ast::Statement::Delete(delete) => {
1118 if !delete.returning.is_empty() {
1119 return Err(refused(
1120 "RETURNING is not allowed on a trigger body statement",
1121 Span::default(),
1122 ));
1123 }
1124 Ok(BoundTriggerStatement::Delete(Box::new(
1125 self.bind_delete(delete)?,
1126 )))
1127 }
1128 ast::Statement::Select(select) => Ok(BoundTriggerStatement::Select(Box::new(
1129 self.bind_select(*select)?,
1130 ))),
1131 _ => Err(unsupported(
1132 "that statement in a trigger body",
1133 Span::default(),
1134 )),
1135 }
1136 }
1137
1138 /// Resolves a write target and refuses the things that cannot be written.
1139 fn writable_target(
1140 &mut self,
1141 database: Option<ast::NameId>,
1142 name: ast::NameId,
1143 span: Span,
1144 event: &TriggerEventInfo,
1145 ) -> Result<TableInfo, ParseError> {
1146 let qualifier = database.map(|id| self.ast.folded(id).to_vec());
1147 let folded = self.ast.folded(name).to_vec();
1148 let Some(table) = self
1149 .catalog
1150 .find_table(qualifier.as_deref(), &folded)
1151 .cloned()
1152 else {
1153 return Err(crate::bind::no_such_table(self.ast.text(name), span));
1154 };
1155 match table.kind {
1156 TableKind::View => {
1157 // A view is writable exactly when it has an `INSTEAD OF`
1158 // trigger for this event: the trigger *is* the write, and the
1159 // view itself is never touched.
1160 if !has_instead_of(&table, event) {
1161 return Err(unsupported("writing to a view", span));
1162 }
1163 let expanded = self.expanded_view(&table, span)?;
1164 self.record_write_dependency(table.database);
1165 return Ok(expanded);
1166 }
1167 TableKind::Virtual => {
1168 // A module decides whether it can be written; a module that
1169 // cannot refuses the call rather than the statement, because
1170 // "this table is read-only" is the module's fact and not the
1171 // binder's. What the binder still checks is that the table has
1172 // a module at all - a virtual table this build has no module
1173 // for has no columns either, and nothing can be written to it.
1174 if table.columns.is_empty() {
1175 return Err(unsupported("that virtual table's module", span));
1176 }
1177 self.record_write_dependency(table.database);
1178 return Ok(table);
1179 }
1180 TableKind::Subquery => return Err(unsupported("writing to a subquery", span)),
1181 TableKind::Table => {}
1182 }
1183 if table.folded.starts_with(b"sqlite_")
1184 && !WRITABLE_INTERNAL.contains(&table.folded.as_slice())
1185 {
1186 return Err(unsupported(
1187 "writing to a table whose name begins with sqlite_",
1188 span,
1189 ));
1190 }
1191 self.record_write_dependency(table.database);
1192 Ok(table)
1193 }
1194
1195 /// Resolves the target of an UPDATE or DELETE, which is a FROM term.
1196 fn write_target_from_term(
1197 &mut self,
1198 id: ast::FromTermId,
1199 event: &TriggerEventInfo,
1200 ) -> Result<(TableInfo, usize), ParseError> {
1201 let Some(term) = self.ast.from_term(id) else {
1202 return Err(unsupported("missing target", Span::default()));
1203 };
1204 let ast::FromSource::Table {
1205 database,
1206 name,
1207 indexed_by,
1208 ..
1209 } = term.source
1210 else {
1211 return Err(unsupported("a target that is not a table", term.span));
1212 };
1213 let table = self.writable_target(database, name, term.span, event)?;
1214 // The same rule as a SELECT's: an `INDEXED BY` that names no index of
1215 // the table is refused rather than ignored (task-1979, F7). This path
1216 // has the table in hand rather than a bound source, so it asks the
1217 // table directly.
1218 if let ast::IndexHint::IndexedBy(index) = indexed_by {
1219 let folded = self.ast.folded(index).to_vec();
1220 if !table.indexes.iter().any(|held| held.folded == folded) {
1221 return Err(crate::bind::no_such_index(self.ast.text(index), term.span));
1222 }
1223 }
1224 let alias = match term.alias {
1225 Some(alias) => self.ast.text(alias).to_vec(),
1226 None => table.name.clone(),
1227 };
1228 if table.kind == TableKind::View {
1229 // The view goes in as an ordinary nested query, so the statement's
1230 // WHERE and SET bind against the view's own columns and against the
1231 // term the block producing OLD will iterate. Binding first and
1232 // re-pointing afterwards would be two chances to disagree.
1233 let inner = self.view_query(&table, term.span)?;
1234 let source = BoundSource {
1235 index_hint: crate::bind::IndexChoice::Any,
1236 id: self.sources.len(),
1237 rows: crate::bind::SourceRows::Subquery(Box::new(inner)),
1238 table: std::rc::Rc::new(table.clone()),
1239 alias,
1240 join: ast::JoinKind::Comma,
1241 constraint: None,
1242 suppressed: Vec::new(),
1243 index_exprs: Vec::new(),
1244 };
1245 self.view_target = Some(source.id);
1246 let scope = source.id;
1247 self.sources.push(source);
1248 self.scopes.push(vec![scope]);
1249 return Ok((table, scope));
1250 }
1251 let scope = self.push_write_source(table.clone(), alias);
1252 let choice = self.index_choice(indexed_by);
1253 if let Some(source) = self.sources.get_mut(scope) {
1254 source.index_hint = choice;
1255 }
1256 Ok((table, scope))
1257 }
1258
1259 /// Returns a view's `TableInfo` with the columns its body produces.
1260 ///
1261 /// A view's catalog entry carries no column list - its columns are whatever
1262 /// binding its `SELECT` says they are - so a statement that writes one needs
1263 /// the body bound before `new.column` can resolve to anything at all.
1264 pub(crate) fn expanded_view(
1265 &mut self,
1266 table: &TableInfo,
1267 span: Span,
1268 ) -> Result<TableInfo, ParseError> {
1269 let bound = self.view_query(table, span)?;
1270 let mut expanded = table.clone();
1271 expanded.columns = crate::bind::subquery_columns(&bound, &[]);
1272 Ok(expanded)
1273 }
1274
1275 /// Binds a view's body, out of the arena the catalog snapshot holds.
1276 fn view_query(&mut self, table: &TableInfo, span: Span) -> Result<BoundSelect, ParseError> {
1277 let catalog = self.catalog;
1278 let database = catalog.database_name(table.database).to_vec();
1279 let Some(live) = catalog.find_table(Some(database.as_slice()), &table.folded) else {
1280 return Err(crate::bind::no_such_table(&table.name, span));
1281 };
1282 let Some(body) = live.view.as_ref() else {
1283 return Err(unsupported(
1284 "a view whose definition could not be parsed",
1285 span,
1286 ));
1287 };
1288 let names = body.columns.clone();
1289 let saved_ast = self.ast;
1290 let saved_scopes = core::mem::take(&mut self.scopes);
1291 self.ast = &body.ast;
1292 let bound = self.bind_select(body.select);
1293 self.ast = saved_ast;
1294 self.scopes = saved_scopes;
1295 let mut bound = bound?;
1296 // `CREATE VIEW v (a, b)` renames the body's columns, and those are the
1297 // names `new.a` resolves against.
1298 for (position, name) in names.iter().enumerate() {
1299 if let Some(column) = bound.columns.get_mut(position) {
1300 column.name = name.clone();
1301 }
1302 }
1303 Ok(bound)
1304 }
1305
1306 /// Builds the block whose rows an `INSTEAD OF UPDATE` or `DELETE` fires for.
1307 ///
1308 /// It reads the term `write_target_from_term` already pushed, so the filter
1309 /// handed in here - bound against that same term - needs no adjustment.
1310 fn view_rows(
1311 &mut self,
1312 table: &TableInfo,
1313 filter: Option<BoundExpr>,
1314 ) -> Option<Box<BoundSelect>> {
1315 // The kind is checked before the target is taken. A trigger body's own
1316 // UPDATE binds through here too, and taking first meant the body's
1317 // statement - whose target is an ordinary table - consumed the view
1318 // target belonging to the statement that fired it, which then compiled
1319 // as a write to a view's root page of zero.
1320 if table.kind != TableKind::View {
1321 return None;
1322 }
1323 let id = self.view_target.take()?;
1324 let source = self.sources.get(id)?.clone();
1325 let columns = table
1326 .columns
1327 .iter()
1328 .enumerate()
1329 .map(|(position, column)| BoundResultColumn {
1330 expr: BoundExpr::Column {
1331 source: id,
1332 column: position as u16,
1333 slot: position as u16,
1334 affinity: column.affinity,
1335 collation: Collation::from_name(
1336 core::str::from_utf8(&column.collation).unwrap_or("BINARY"),
1337 )
1338 .unwrap_or(Collation::Binary),
1339 },
1340 name: column.name.clone(),
1341 origin: None,
1342 declared_type: column.declared_type.clone(),
1343 })
1344 .collect();
1345 Some(Box::new(crate::bind::block_over(source, filter, columns)))
1346 }
1347
1348 /// Returns the target's index hint, or refuses a write whose `INDEXED BY`
1349 /// index cannot find its rows.
1350 ///
1351 /// The same rule and the same test a `SELECT` gets from
1352 /// `crate::bind::refuse_unanswerable_hints`, asked of the query the write
1353 /// will run to find its rows: the target, any `UPDATE ... FROM` terms, and
1354 /// the statement's `WHERE`. The pinned 3.53.4 shell refuses
1355 /// `DELETE FROM h INDEXED BY h_part WHERE a = 1`, where `h_part` is declared
1356 /// `WHERE c > 3`, with `no query solution`.
1357 /// @param source - the target's statement-wide number
1358 /// @param index_exprs - the target's bound index expressions
1359 /// @param filter - the statement's `WHERE`
1360 /// @param joined - the `UPDATE ... FROM` terms, empty for a `DELETE`
1361 fn write_hint(
1362 &self,
1363 source: usize,
1364 index_exprs: &[BoundIndexExprs],
1365 filter: Option<&BoundExpr>,
1366 joined: &[BoundSource],
1367 ) -> Result<crate::bind::IndexChoice, ParseError> {
1368 let Some(target) = self.sources.get(source) else {
1369 return Ok(crate::bind::IndexChoice::Any);
1370 };
1371 if target.index_hint == crate::bind::IndexChoice::Any {
1372 return Ok(crate::bind::IndexChoice::Any);
1373 }
1374 let mut probe = target.clone();
1375 probe.index_exprs = index_exprs.to_vec();
1376 let mut block = crate::bind::block_over(probe, filter.cloned(), Vec::new());
1377 block.sources.extend(joined.iter().cloned());
1378 if crate::plan::unanswerable_index_hint(&block).is_some() {
1379 return Err(crate::bind::no_query_solution(Span::default()));
1380 }
1381 Ok(target.index_hint.clone())
1382 }
1383
1384 /// Makes the target table the statement's one visible source.
1385 ///
1386 /// It opens a scope holding just the target, so every name in the
1387 /// statement's `SET`, `WHERE` and `RETURNING` resolves against the table
1388 /// being written and nothing else.
1389 fn push_write_source(&mut self, table: TableInfo, alias: Vec<u8>) -> usize {
1390 let id = self.sources.len();
1391 self.sources.push(BoundSource {
1392 index_hint: crate::bind::IndexChoice::Any,
1393 id,
1394 rows: crate::bind::SourceRows::Table,
1395 table: std::rc::Rc::new(table),
1396 alias,
1397 join: ast::JoinKind::Comma,
1398 constraint: None,
1399 suppressed: Vec::new(),
1400 index_exprs: Vec::new(),
1401 });
1402 self.scopes.push(vec![id]);
1403 id
1404 }
1405
1406 /// Refuses an attempt to write a generated column.
1407 ///
1408 /// SQLite's message names the column, because the usual cause is a script
1409 /// that inserts every column of a table one of whose columns has since been
1410 /// made generated. It names the statement too - `INSERT` or `UPDATE` - and
1411 /// so does this.
1412 ///
1413 /// @param table - the table being written
1414 /// @param position - the column the statement named
1415 /// @param verb - `INSERT into` or `UPDATE`, as SQLite writes it
1416 /// @param span - where the name was written
1417 fn refuse_generated(
1418 &self,
1419 table: &TableInfo,
1420 position: u16,
1421 verb: &str,
1422 span: Span,
1423 ) -> Result<(), ParseError> {
1424 let Some(column) = table.column(position) else {
1425 return Ok(());
1426 };
1427 if !column.generated {
1428 return Ok(());
1429 }
1430 Err(refused(
1431 format!(
1432 "cannot {verb} generated column \"{}\"",
1433 String::from_utf8_lossy(&column.name)
1434 ),
1435 span,
1436 ))
1437 }
1438
1439 /// Returns the target column positions an INSERT writes, in source order.
1440 ///
1441 /// With no column list the targets are every column in declaration order,
1442 /// which is why adding a column to a table changes what a positional
1443 /// INSERT means - SQLite's behaviour, and the reason the column list is
1444 /// worth writing.
1445 fn insert_targets(
1446 &self,
1447 table: &TableInfo,
1448 columns: &[ast::NameId],
1449 ) -> Result<Vec<u16>, ParseError> {
1450 if columns.is_empty() {
1451 // A bare `INSERT INTO t VALUES (...)` supplies the columns a person
1452 // can write, which is every column that is not generated - so a
1453 // table with a generated column takes fewer values than it has
1454 // columns, exactly as SQLite counts them.
1455 // A hidden column is not one of them either: a module's arguments
1456 // and its `rank` are named by an application that wants them, and
1457 // an `INSERT INTO fts VALUES ('a', 'b')` supplies the two indexed
1458 // columns and nothing else.
1459 return Ok((0..table.columns.len() as u16)
1460 .filter(|position| {
1461 table
1462 .column(*position)
1463 .is_some_and(|column| !column.generated && !column.hidden)
1464 })
1465 .collect());
1466 }
1467 let mut targets = Vec::with_capacity(columns.len());
1468 for name in columns {
1469 let folded = self.ast.folded(*name).to_vec();
1470 let position = match table.column_position(&folded) {
1471 Some(position) => position,
1472 // A rowid table lets the statement name its rowid, under any
1473 // of its three spellings, and that is not a column: it is the
1474 // key. A declared column of the same name wins, which is why
1475 // this is the fallback rather than the first thing tried.
1476 None if table.has_rowid() && is_rowid_name(&folded) => ROWID_TARGET,
1477 None => return Err(no_such_column(self.ast.text(*name), Span::default())),
1478 };
1479 if targets.contains(&position) {
1480 return Err(refused(
1481 format!(
1482 "column {} is named twice",
1483 String::from_utf8_lossy(self.ast.text(*name))
1484 ),
1485 Span::default(),
1486 ));
1487 }
1488 if position != ROWID_TARGET {
1489 self.refuse_generated(table, position, "INSERT into", Span::default())?;
1490 }
1491 targets.push(position);
1492 }
1493 Ok(targets)
1494 }
1495
1496 /// Binds the rows an INSERT supplies.
1497 fn bind_insert_source(
1498 &mut self,
1499 source: &ast::InsertSource,
1500 table: &TableInfo,
1501 targets: &[u16],
1502 ) -> Result<(BoundInsertSource, usize), ParseError> {
1503 match source {
1504 ast::InsertSource::DefaultValues => {
1505 let _ = (table, targets);
1506 Ok((BoundInsertSource::Values(vec![Vec::new()]), 0))
1507 }
1508 ast::InsertSource::Select(id) => {
1509 // The target table is source zero while the rows are bound, so
1510 // that `INSERT INTO t SELECT ... FROM u` resolves `u`'s columns
1511 // and not `t`'s. Binding a SELECT replaces the source list, and
1512 // the target is pushed back afterwards.
1513 // The scope stack is emptied rather than pushed to, because a
1514 // pushed scope would still be searched *outward* into the
1515 // target's, and `INSERT INTO t SELECT a FROM u` would then
1516 // resolve `a` against `t` when `u` has no such column.
1517 let saved = core::mem::take(&mut self.scopes);
1518 let select = self.bind_select(*id);
1519 let bound = match select {
1520 Ok(bound) => bound,
1521 Err(error) => {
1522 self.scopes = saved;
1523 return Err(error);
1524 }
1525 };
1526 self.scopes = saved;
1527 if bound.values.is_empty() {
1528 let arity = bound.columns.len();
1529 return Ok((BoundInsertSource::Select(Box::new(bound)), arity));
1530 }
1531 let arity = bound.values.first().map_or(0, Vec::len);
1532 for row in &bound.values {
1533 if row.len() != arity {
1534 return Err(unsupported(
1535 "all VALUES rows must have the same number of columns",
1536 Span::default(),
1537 ));
1538 }
1539 }
1540 Ok((BoundInsertSource::Values(bound.values), arity))
1541 }
1542 }
1543 }
1544
1545 /// Works out where every table column's value comes from.
1546 ///
1547 /// A column the statement named takes its value from the source row; a
1548 /// column it did not takes its `DEFAULT`, and a column with no default
1549 /// takes NULL. The rowid is separated out here rather than in the
1550 /// compiler, because an `INTEGER PRIMARY KEY` column *is* the rowid and
1551 /// writing it into the record as well would store a duplicate that SQLite
1552 /// does not.
1553 fn column_sources(
1554 &mut self,
1555 table: &TableInfo,
1556 targets: &[u16],
1557 ) -> Result<(Vec<ColumnSource>, Option<ColumnSource>), ParseError> {
1558 let mut columns = Vec::with_capacity(table.columns.len());
1559 for position in 0..table.columns.len() as u16 {
1560 if let Some(expr) = self.generated_expr(table, position)? {
1561 columns.push(ColumnSource::Generated(expr));
1562 continue;
1563 }
1564 let source = match targets.iter().position(|target| *target == position) {
1565 Some(index) => ColumnSource::Row(index),
1566 None => ColumnSource::Expr(self.default_expr(table, position)?),
1567 };
1568 columns.push(source);
1569 }
1570 let rowid = match table.rowid_alias {
1571 Some(position) => columns.get(position as usize).cloned(),
1572 None => None,
1573 };
1574 Ok((columns, rowid))
1575 }
1576
1577 /// Binds a generated column's expression, when the column is one.
1578 fn generated_expr(
1579 &mut self,
1580 table: &TableInfo,
1581 position: u16,
1582 ) -> Result<Option<BoundExpr>, ParseError> {
1583 let Some(column) = table.column(position) else {
1584 return Ok(None);
1585 };
1586 if !column.generated {
1587 return Ok(None);
1588 }
1589 let Some(sql) = column.generated_sql.clone() else {
1590 return Ok(Some(BoundExpr::Null));
1591 };
1592 Ok(Some(self.bind_schema_expr(&sql)?))
1593 }
1594
1595 /// Binds every `STORED` generated column's expression.
1596 ///
1597 /// Returns them as assignments, because that is what they are on the write
1598 /// path: a value the statement did not write and the row has to carry. See
1599 /// [`BoundUpdate::generated`] for why an `UPDATE` needs them and a
1600 /// `VIRTUAL` column does not.
1601 ///
1602 /// @param table - the table being written
1603 fn bind_stored_generated(
1604 &mut self,
1605 table: &TableInfo,
1606 ) -> Result<Vec<BoundAssignment>, ParseError> {
1607 let mut generated = Vec::new();
1608 for position in 0..table.columns.len() as u16 {
1609 let Some(column) = table.column(position) else {
1610 continue;
1611 };
1612 if !column.generated || !column.stored {
1613 continue;
1614 }
1615 let Some(expr) = self.generated_expr(table, position)? else {
1616 continue;
1617 };
1618 generated.push(BoundAssignment {
1619 column: position,
1620 rowid: false,
1621 value: expr,
1622 });
1623 }
1624 Ok(generated)
1625 }
1626
1627 /// Binds a column's `DEFAULT`, or NULL when it has none.
1628 fn default_expr(&mut self, table: &TableInfo, position: u16) -> Result<BoundExpr, ParseError> {
1629 let Some(column) = table.column(position) else {
1630 return Ok(BoundExpr::Null);
1631 };
1632 let Some(sql) = column.default_sql.as_ref() else {
1633 return Ok(BoundExpr::Null);
1634 };
1635 if sql.is_empty() {
1636 return Ok(BoundExpr::Null);
1637 }
1638 self.bind_schema_expr(sql)
1639 }
1640
1641 /// Binds the `DEFAULT` of every `NOT NULL` column that declares one.
1642 ///
1643 /// What `REPLACE` substitutes for a NULL in such a column - see
1644 /// [`BoundDefault`]. A column with no default is left out, which is what
1645 /// makes the write path's fallback to `ABORT` the absence of an entry
1646 /// rather than a second test.
1647 ///
1648 /// The rowid alias is left out too: the row image carries the key the
1649 /// statement is about to allocate, and the write path does not check it.
1650 ///
1651 /// @param table - the table being written
1652 fn bind_not_null_defaults(
1653 &mut self,
1654 table: &TableInfo,
1655 ) -> Result<Vec<BoundDefault>, ParseError> {
1656 let mut defaults = Vec::new();
1657 for (position, column) in table.columns.iter().enumerate() {
1658 if !column.not_null || Some(position as u16) == table.rowid_alias {
1659 continue;
1660 }
1661 let Some(sql) = column.default_sql.as_ref() else {
1662 continue;
1663 };
1664 if sql.is_empty() {
1665 continue;
1666 }
1667 let expr = self.bind_schema_expr(&sql.clone())?;
1668 defaults.push(BoundDefault {
1669 column: position as u16,
1670 expr,
1671 });
1672 }
1673 Ok(defaults)
1674 }
1675
1676 /// Binds every `CHECK` the table declares.
1677 fn bind_checks(&mut self, table: &TableInfo) -> Result<Vec<BoundCheck>, ParseError> {
1678 let mut checks = Vec::with_capacity(table.checks.len());
1679 for check in &table.checks {
1680 checks.push(BoundCheck {
1681 name: check.name.clone(),
1682 expr: self.bind_schema_expr(&check.expr_sql)?,
1683 });
1684 }
1685 Ok(checks)
1686 }
1687
1688 /// Binds the expressions the table's indexes need per row.
1689 ///
1690 /// Only the indexes that need any: a partial one, and one with an
1691 /// expression key. Everything else is a slot of the row and needs nothing.
1692 ///
1693 /// @param table - the table being written
1694 fn bind_index_exprs(&mut self, table: &TableInfo) -> Result<Vec<BoundIndexExprs>, ParseError> {
1695 let mut bound = Vec::new();
1696 for (position, index) in table.indexes.iter().enumerate() {
1697 let needs = index.partial_sql.is_some()
1698 || index.columns.iter().any(|key| key.expr_sql.is_some());
1699 if !needs {
1700 continue;
1701 }
1702 let predicate = match index.partial_sql.as_ref() {
1703 Some(sql) => Some(self.bind_schema_expr(sql)?),
1704 None => None,
1705 };
1706 let mut keys = Vec::with_capacity(index.columns.len());
1707 for key in &index.columns {
1708 keys.push(match key.expr_sql.as_ref() {
1709 Some(sql) => Some(self.bind_schema_expr(sql)?),
1710 None => None,
1711 });
1712 }
1713 bound.push(BoundIndexExprs {
1714 position,
1715 predicate,
1716 keys,
1717 });
1718 }
1719 Ok(bound)
1720 }
1721
1722 /// Parses and binds an expression that was written in the schema.
1723 ///
1724 /// It is parsed into its own arena and bound against the statement's
1725 /// current sources, so the result is an ordinary `BoundExpr` that refers to
1726 /// the target table by position and carries no reference to the schema
1727 /// text it came from.
1728 pub fn bind_schema_expr(&mut self, sql: &[u8]) -> Result<BoundExpr, ParseError> {
1729 let limits = Limits::default();
1730 let (ast, expr) = parse_expression(sql, &limits)?;
1731 let mut nested = Binder::new(self.catalog, &ast, self.authorizer);
1732 nested.trigger_depth = self.trigger_depth;
1733 // **This is where a `DEFAULT`, a `CHECK`, a generated column, an index
1734 // expression and a partial-index predicate all become a bound tree, so
1735 // it is where all five are told they are a schema (task-1972).** The
1736 // nested binder also inherits the connection's registrations and
1737 // collations, which it did not before: without the registrations
1738 // `bind_external_call` never sees the call at all, because the name
1739 // does not resolve to a registered function and the expression fails as
1740 // "no such function" - an error for the wrong reason, and one that
1741 // disappears the moment an application registers the same name at a
1742 // different arity.
1743 nested.externals = self.externals;
1744 nested.collations = self.collations;
1745 nested.trusted_schema = self.trusted_schema;
1746 nested.call_site = crate::function::CallSite::Schema;
1747 nested.sources = self.sources.clone();
1748 nested.scopes = self.scopes.clone();
1749 let bound = nested.bind_expr(expr)?;
1750 Ok(bound)
1751 }
1752
1753 /// Binds an `ON CONFLICT` clause.
1754 fn bind_upsert(
1755 &mut self,
1756 table: &TableInfo,
1757 insert: &ast::Insert,
1758 ) -> Result<Vec<BoundUpsert>, ParseError> {
1759 if insert.upserts.is_empty() {
1760 return Ok(Vec::new());
1761 }
1762 // **Every clause is bound, in written order.** A statement may carry
1763 // several - `ON CONFLICT(k) DO UPDATE ... ON CONFLICT(id) DO UPDATE ...`
1764 // - and which one runs is decided at *run time*, by which constraint
1765 // the row actually collided with. Binding only the first was the whole
1766 // of the old refusal.
1767 for upsert in &insert.upserts {
1768 if upsert.target_filter.is_some() {
1769 return Err(unsupported(
1770 "a partial-index conflict target",
1771 Span::default(),
1772 ));
1773 }
1774 }
1775 // A clause with no conflict target matches any constraint, so anything
1776 // written after it could never run. SQLite refuses that rather than
1777 // accepting a clause it will never reach.
1778 if let Some(position) = insert
1779 .upserts
1780 .iter()
1781 .position(|upsert| upsert.target.is_empty())
1782 {
1783 if position + 1 < insert.upserts.len() {
1784 return Err(crate::bind::schema_refused(
1785 "ON CONFLICT clause with no conflict target must be last",
1786 Span::default(),
1787 ));
1788 }
1789 }
1790 // `excluded` is in scope for the assignments and the WHERE, and only
1791 // there. Setting it around the binding rather than pushing a second
1792 // FROM term keeps unqualified names resolving to the target row, which
1793 // is what SQLite does and what a second source would have made
1794 // ambiguous - every column of the target is also a column of
1795 // `excluded`.
1796 self.excluded = Some(table.clone());
1797 let mut bound = Vec::with_capacity(insert.upserts.len());
1798 for upsert in &insert.upserts {
1799 match self.bind_upsert_body(table, upsert) {
1800 Ok(Some(one)) => bound.push(one),
1801 Ok(None) => {}
1802 Err(error) => {
1803 self.excluded = None;
1804 return Err(error);
1805 }
1806 }
1807 }
1808 self.excluded = None;
1809 Ok(bound)
1810 }
1811
1812 /// Binds an upsert's target, assignments and filter.
1813 fn bind_upsert_body(
1814 &mut self,
1815 table: &TableInfo,
1816 upsert: &ast::Upsert,
1817 ) -> Result<Option<BoundUpsert>, ParseError> {
1818 let mut target = Vec::new();
1819 for column in &upsert.target {
1820 let Some(name) = bare_indexed_column(self.ast, column) else {
1821 return Err(unsupported(
1822 "an expression in a conflict target",
1823 Span::default(),
1824 ));
1825 };
1826 let Some(position) = table.column_position(&name) else {
1827 return Err(no_such_column(&name, Span::default()));
1828 };
1829 target.push(position);
1830 }
1831 target.sort_unstable();
1832 let mut assignments = Vec::new();
1833 for (names, value) in &upsert.assignments {
1834 let bound = self.bind_expr(*value)?;
1835 for name in names {
1836 let folded = self.ast.folded(*name).to_vec();
1837 let Some(position) = table.column_position(&folded) else {
1838 return Err(no_such_column(self.ast.text(*name), Span::default()));
1839 };
1840 assignments.push(BoundAssignment {
1841 column: position,
1842 rowid: false,
1843 value: bound.clone(),
1844 });
1845 }
1846 }
1847 assignments.sort_by_key(|assignment| assignment.column);
1848 let filter = match upsert.filter {
1849 Some(expr) => Some(self.bind_expr(expr)?),
1850 None => None,
1851 };
1852 Ok(Some(BoundUpsert {
1853 target,
1854 assignments,
1855 do_update: upsert.do_update,
1856 filter,
1857 }))
1858 }
1859
1860 /// Binds a `RETURNING` list, which is a result-column list over the row
1861 /// that was written.
1862 fn bind_returning(
1863 &mut self,
1864 columns: &[ast::ResultColumn],
1865 ) -> Result<Vec<BoundResultColumn>, ParseError> {
1866 if columns.is_empty() {
1867 return Ok(Vec::new());
1868 }
1869 self.bind_result_columns_public(columns)
1870 }
1871}
1872
1873/// Returns an indexed column's bare folded name, when it names a column.
1874fn bare_indexed_column(ast: &crate::Ast, column: &ast::IndexedColumn) -> Option<Vec<u8>> {
1875 match ast.expr(column.expr) {
1876 Some(ast::Expr::Column {
1877 table: None,
1878 column: name,
1879 ..
1880 }) => Some(ast.folded(*name).to_vec()),
1881 _ => None,
1882 }
1883}
1884
1885/// The extended result codes a rejected write reports.
1886///
1887/// The numbers are SQLite's own extended codes. They are written out rather
1888/// than derived because an application matches on them, and a code that was
1889/// computed from an enum's discriminant would change the day the enum did.
1890///
1891/// They live here, beside the binder that decides which constraint a statement
1892/// can violate, because **both** engines report them: the virtual machine
1893/// compiles them into a `HaltError` and the vectorised executor returns them
1894/// from its write path. Two copies would agree until one of them was corrected.
1895pub mod codes {
1896 /// `SQLITE_CONSTRAINT_CHECK`.
1897 pub const CHECK: i32 = 275;
1898 /// `SQLITE_CONSTRAINT_DATATYPE`, which a STRICT table reports.
1899 pub const DATATYPE: i32 = 3091;
1900 /// `SQLITE_CONSTRAINT_NOTNULL`.
1901 pub const NOT_NULL: i32 = 1299;
1902 /// `SQLITE_CONSTRAINT_PRIMARYKEY`.
1903 pub const PRIMARY_KEY: i32 = 1555;
1904 /// `SQLITE_CONSTRAINT_UNIQUE`.
1905 pub const UNIQUE: i32 = 2067;
1906 /// `SQLITE_CONSTRAINT_ROWID`.
1907 pub const ROWID: i32 = 2579;
1908 /// `SQLITE_MISMATCH`, which an `INTEGER PRIMARY KEY` reports for a value
1909 /// that is not an integer.
1910 pub const MISMATCH: i32 = 20;
1911 /// `SQLITE_CONSTRAINT_TRIGGER`, which `RAISE()` reports.
1912 pub const TRIGGER: i32 = 1811;
1913 /// `SQLITE_CONSTRAINT_FOREIGNKEY`.
1914 pub const FOREIGN_KEY: i32 = 787;
1915}
1916
1917/// Returns the message a unique-index violation reports.
1918///
1919/// SQLite names every column of the index, comma separated, which is what an
1920/// application parses to find out which key collided.
1921///
1922/// @param table - the table the index belongs to
1923/// @param index - the index whose key collided
1924pub fn unique_message(table: &TableInfo, index: &IndexInfo) -> String {
1925 let names: Vec<String> = index
1926 .columns
1927 .iter()
1928 .filter_map(|key| key.column)
1929 .filter_map(|column| table.column(column))
1930 .map(|column| {
1931 format!(
1932 "{}.{}",
1933 String::from_utf8_lossy(&table.name),
1934 String::from_utf8_lossy(&column.name)
1935 )
1936 })
1937 .collect();
1938 format!("UNIQUE constraint failed: {}", names.join(", "))
1939}
1940
1941/// Returns the message a duplicate rowid reports, and its extended code.
1942///
1943/// SQLite names the aliasing column when the table has an `INTEGER PRIMARY
1944/// KEY` - and reports `SQLITE_CONSTRAINT_PRIMARYKEY` for it - and names the
1945/// hidden `rowid` under `SQLITE_CONSTRAINT_ROWID` when it does not.
1946///
1947/// **A `WITHOUT ROWID` table has no rowid to name.** Its own key *is* its
1948/// primary key, held in the one index whose root is the table's, so a collision
1949/// reports every column of that key under `SQLITE_CONSTRAINT_PRIMARYKEY` -
1950/// `UNIQUE constraint failed: t.a, t.b`. It used to answer `t.rowid`, naming a
1951/// column the table does not have, on `INSERT` as well as `UPDATE`.
1952///
1953/// @param table - the table whose key collided
1954pub fn rowid_message(table: &TableInfo) -> (i32, String) {
1955 if table.without_rowid {
1956 if let Some(index) = table.indexes.iter().find(|index| index.root == table.root) {
1957 return (codes::PRIMARY_KEY, unique_message(table, index));
1958 }
1959 }
1960 match table.rowid_alias.and_then(|column| table.column(column)) {
1961 Some(column) => (
1962 codes::PRIMARY_KEY,
1963 format!(
1964 "UNIQUE constraint failed: {}.{}",
1965 String::from_utf8_lossy(&table.name),
1966 String::from_utf8_lossy(&column.name)
1967 ),
1968 ),
1969 None => (
1970 codes::ROWID,
1971 format!(
1972 "UNIQUE constraint failed: {}.rowid",
1973 String::from_utf8_lossy(&table.name)
1974 ),
1975 ),
1976 }
1977}
1978
1979/// Puts a limited write's order, limit and offset on the query that finds a
1980/// view's rows.
1981///
1982/// A write through a view's `INSTEAD OF` trigger fires once per row the view
1983/// produces under the statement's `WHERE`, so a `LIMIT` on the write limits
1984/// that query. SQLite's `sqlite3MaterializeView` is handed the same three
1985/// clauses for the same reason.
1986///
1987/// @param rows - the query over the view the binder built
1988/// @param order_by - the statement's bound `ORDER BY`
1989/// @param limit - the statement's bound `LIMIT`
1990/// @param offset - the statement's bound `OFFSET`
1991fn limit_view_rows(
1992 mut rows: Box<BoundSelect>,
1993 order_by: &[BoundOrderTerm],
1994 limit: &Option<BoundExpr>,
1995 offset: &Option<BoundExpr>,
1996) -> Box<BoundSelect> {
1997 rows.order_by = order_by.to_vec();
1998 rows.limit = limit.clone();
1999 rows.offset = offset.clone();
2000 rows
2001}
2002
2003/// Returns the refusal a `DELETE` or `UPDATE` with `ORDER BY` and no `LIMIT`
2004/// earns, or `None` when the clause is allowed.
2005///
2006/// **`ORDER BY` and `LIMIT` on a write are run, not refused (task-2120).** They
2007/// were refused in the pinned reference's words, `near "ORDER": syntax error`,
2008/// because that build is not compiled with `SQLITE_ENABLE_UPDATE_DELETE_LIMIT`
2009/// and has no grammar for the clause. But the builds applications actually link
2010/// often are - Apple's is - and `DELETE FROM t WHERE ... LIMIT 1000` in a loop
2011/// is the ordinary way to trim a large table without one large transaction. A
2012/// consumer probing 0.1.8 against the macOS `sqlite3` reported the refusal as a
2013/// real gap, which it was.
2014///
2015/// What remains is the one rule a build compiled with the option enforces:
2016/// an order with nothing to limit is refused, in SQLite's own words, because
2017/// sorting the rows a statement changes all of changes nothing.
2018///
2019/// @param limited - which of the two words came first and where, from the parser
2020/// @param limit - the statement's `LIMIT`, when it wrote one
2021/// @param statement - `DELETE` or `UPDATE`, for the message
2022fn order_without_limit(
2023 limited: Option<(ast::Limited, Span)>,
2024 limit: Option<ast::ExprId>,
2025 statement: &str,
2026) -> Option<ParseError> {
2027 let (word, span) = limited?;
2028 if word != ast::Limited::OrderBy || limit.is_some() {
2029 return None;
2030 }
2031 Some(refused(
2032 format!("ORDER BY without LIMIT on {statement}"),
2033 span,
2034 ))
2035}
2036
2037#[cfg(test)]
2038mod tests {
2039 use super::*;
2040 use crate::catalog_view::{
2041 ColumnInfo, IndexColumnInfo, IndexInfo, IndexOrigin, TableInfo, TableKind,
2042 };
2043 use inillucent_value::Affinity;
2044
2045 /// Returns one plain column.
2046 ///
2047 /// @param name - the column's name
2048 fn a_column(name: &str) -> ColumnInfo {
2049 ColumnInfo {
2050 name: name.as_bytes().to_vec(),
2051 folded: name.to_ascii_lowercase().into_bytes(),
2052 declared_type: b"INTEGER".to_vec(),
2053 affinity: Affinity::Integer,
2054 collation: b"binary".to_vec(),
2055 not_null: false,
2056 not_null_conflict: None,
2057 primary_key_conflict: None,
2058 default_sql: None,
2059 primary_key_position: None,
2060 hidden: false,
2061 generated: false,
2062 stored: false,
2063 generated_sql: None,
2064 }
2065 }
2066
2067 /// Returns a rowid table with the columns named.
2068 ///
2069 /// @param name - the table's name
2070 /// @param columns - the column names, in declaration order
2071 fn a_table(name: &str, columns: &[&str]) -> TableInfo {
2072 TableInfo {
2073 name: name.as_bytes().to_vec(),
2074 folded: name.to_ascii_lowercase().into_bytes(),
2075 database: 0,
2076 root: 2,
2077 columns: columns.iter().map(|held| a_column(held)).collect(),
2078 rowid_alias: None,
2079 without_rowid: false,
2080 strict: false,
2081 autoincrement: false,
2082 kind: TableKind::Table,
2083 create_sql: Vec::new(),
2084 indexes: Vec::new(),
2085 view: None,
2086 triggers: Vec::new(),
2087 analysed_rows: None,
2088 foreign_key_triggers: Vec::new(),
2089 foreign_keys: Vec::new(),
2090 checks: Vec::new(),
2091 module: None,
2092 }
2093 }
2094
2095 /// Returns an index over the table columns named.
2096 ///
2097 /// @param name - the index's name
2098 /// @param root - its own tree, or the table's for a `WITHOUT ROWID` key
2099 /// @param columns - the table columns it keys on
2100 fn an_index(name: &str, root: u32, columns: &[u16]) -> IndexInfo {
2101 IndexInfo {
2102 name: name.as_bytes().to_vec(),
2103 folded: name.to_ascii_lowercase().into_bytes(),
2104 root,
2105 unique: true,
2106 columns: columns
2107 .iter()
2108 .map(|held| IndexColumnInfo {
2109 column: Some(*held),
2110 expr_sql: None,
2111 collation: b"binary".to_vec(),
2112 descending: false,
2113 declared_descending: false,
2114 })
2115 .collect(),
2116 partial_sql: None,
2117 origin: IndexOrigin::Unique,
2118 conflict: None,
2119 prefix_rows: Vec::new(),
2120 analysed_rows: None,
2121 metric: None,
2122 }
2123 }
2124
2125 /// The three spellings of the rowid are the three SQLite accepts.
2126 ///
2127 /// **A fourth would be a column name a table could not have (T3,
2128 /// task-1962).** `rowid`, `oid` and `_rowid_` all name the hidden key, and
2129 /// a table that declares a column called any of them shadows it - so the
2130 /// list decides which names a `SELECT rowid` can mean.
2131 #[test]
2132 fn the_rowid_has_three_names() {
2133 assert!(is_rowid_name(b"rowid"));
2134 assert!(is_rowid_name(b"oid"));
2135 assert!(is_rowid_name(b"_rowid_"));
2136 assert!(!is_rowid_name(b"row_id"));
2137 assert!(!is_rowid_name(b"id"));
2138 assert!(
2139 !is_rowid_name(b"ROWID"),
2140 "the argument is already folded, so an unfolded name is not one this asks about"
2141 );
2142 }
2143
2144 /// A unique violation names every column of the index, table-qualified.
2145 ///
2146 /// **The message is what an application matches on.** SQLite's wording is
2147 /// `UNIQUE constraint failed: t.a, t.b`, and a library that switched on it
2148 /// would stop recognising a collision if the columns were listed any other
2149 /// way.
2150 #[test]
2151 fn a_unique_violation_names_every_column_of_the_index() {
2152 let table = a_table("t", &["a", "b", "c"]);
2153 let one = an_index("by_a", 3, &[0]);
2154 assert_eq!(
2155 unique_message(&table, &one),
2156 "UNIQUE constraint failed: t.a"
2157 );
2158 let two = an_index("by_a_b", 4, &[0, 1]);
2159 assert_eq!(
2160 unique_message(&table, &two),
2161 "UNIQUE constraint failed: t.a, t.b",
2162 "both columns, in key order, separated the way the reference separates them"
2163 );
2164 }
2165
2166 /// A rowid collision names the aliasing column when there is one, and the
2167 /// hidden `rowid` when there is not.
2168 ///
2169 /// The extended code differs with it: `SQLITE_CONSTRAINT_PRIMARYKEY` for an
2170 /// `INTEGER PRIMARY KEY` and `SQLITE_CONSTRAINT_ROWID` for the hidden one.
2171 #[test]
2172 fn a_rowid_collision_names_the_column_that_aliases_it() {
2173 let hidden = a_table("t", &["a"]);
2174 assert_eq!(
2175 rowid_message(&hidden),
2176 (
2177 codes::ROWID,
2178 "UNIQUE constraint failed: t.rowid".to_string()
2179 )
2180 );
2181 let mut aliased = a_table("t", &["id", "a"]);
2182 aliased.rowid_alias = Some(0);
2183 assert_eq!(
2184 rowid_message(&aliased),
2185 (
2186 codes::PRIMARY_KEY,
2187 "UNIQUE constraint failed: t.id".to_string()
2188 )
2189 );
2190 }
2191
2192 /// A `WITHOUT ROWID` table has no rowid to name, so it names its key.
2193 ///
2194 /// **It used to answer `t.rowid`, naming a column the table does not
2195 /// have.** Its own key *is* its primary key, held in the one index whose
2196 /// root is the table's.
2197 #[test]
2198 fn a_without_rowid_collision_names_the_primary_key() {
2199 let mut table = a_table("t", &["a", "b"]);
2200 table.without_rowid = true;
2201 table.indexes = vec![an_index("sqlite_autoindex_t_1", table.root, &[0, 1])];
2202 assert_eq!(
2203 rowid_message(&table),
2204 (
2205 codes::PRIMARY_KEY,
2206 "UNIQUE constraint failed: t.a, t.b".to_string()
2207 )
2208 );
2209 }
2210
2211 /// A constraint's own `ON CONFLICT REPLACE` makes a statement able to
2212 /// replace, with no `OR REPLACE` written anywhere.
2213 #[test]
2214 fn a_constraint_can_make_a_plain_insert_replace() {
2215 let plain = a_table("t", &["a"]);
2216 assert!(!can_replace(&plain, None));
2217 assert!(can_replace(&plain, Some(ConflictAction::Replace)));
2218
2219 let mut on_the_index = a_table("t", &["a"]);
2220 let mut index = an_index("by_a", 3, &[0]);
2221 index.conflict = Some(ConflictAction::Replace);
2222 on_the_index.indexes = vec![index];
2223 assert!(
2224 can_replace(&on_the_index, None),
2225 "`a UNIQUE ON CONFLICT REPLACE` replaces without the statement saying so"
2226 );
2227
2228 let mut on_the_column = a_table("t", &["a"]);
2229 if let Some(column) = on_the_column.columns.first_mut() {
2230 column.not_null_conflict = Some(ConflictAction::Replace);
2231 }
2232 assert!(can_replace(&on_the_column, None));
2233 }
2234}