pub struct BoundUpdate {Show 17 fields
pub table: TableInfo,
pub source: usize,
pub from: Vec<BoundSource>,
pub assignments: Vec<BoundAssignment>,
pub generated: Vec<BoundAssignment>,
pub filter: Option<BoundExpr>,
pub on_conflict: Option<ConflictAction>,
pub checks: Vec<BoundCheck>,
pub not_null_defaults: Vec<BoundDefault>,
pub index_exprs: Vec<BoundIndexExprs>,
pub index_hint: IndexChoice,
pub returning: Vec<BoundResultColumn>,
pub order_by: Vec<BoundOrderTerm>,
pub limit: Option<BoundExpr>,
pub offset: Option<BoundExpr>,
pub triggers: Vec<BoundTrigger>,
pub view_rows: Option<Box<BoundSelect>>,
}Expand description
A bound UPDATE.
Fields§
§table: TableInfoThe table being written.
source: usizeThe statement-wide number of the FROM term being written.
It used to be implicitly zero, because a DML statement had exactly one source. A trigger body is compiled into the statement that fires it, so its target takes the next number after the firing statement’s - and a compiler that assumed zero read the wrong cursor for every fire after the first.
from: Vec<BoundSource>The extra FROM terms of an UPDATE ... FROM, in written order.
The rows being updated come from a join. UPDATE t SET v = s.v FROM s WHERE s.a = t.a is the shape a migration writes to copy a column across
tables, and the values it assigns are not expressions over the target
row: they read a different row, one the join found. So the query that
finds the keys carries these terms too, and projects the assigned values
beside the key; see BoundUpdate::from, which is this field.
Empty for every ordinary UPDATE, which is what keeps the wider row off
the path the gate’s txn.large measures.
assignments: Vec<BoundAssignment>The assignments, in table column order with duplicates already refused.
generated: Vec<BoundAssignment>The STORED generated columns, recomputed after the assignments.
A stored generated column is part of the row, so a row that is
rewritten rewrites it (task-1913). It is never named in a SET, so
an UPDATE used to leave whatever was written when the row was
inserted: c GENERATED ALWAYS AS (a + 1) STORED still read 2 after
UPDATE g SET a = 5, where SQLite reads 6. The wrong value is on the
disk rather than in an answer, so a later read of the same file is
wrong too, and an index on the column indexes the stale value.
A VIRTUAL column is not here: it has no slot in the record and is
computed when it is read, which is why only this half needed fixing.
These are evaluated against the row after the assignments, which is
the one difference from BoundUpdate::assignments - those read the
before image so SET a = b, b = a swaps.
filter: Option<BoundExpr>The WHERE clause.
on_conflict: Option<ConflictAction>The statement’s conflict algorithm, when it wrote one.
checks: Vec<BoundCheck>The table’s CHECK constraints.
not_null_defaults: Vec<BoundDefault>The DEFAULTs a REPLACE may stand in for a NULL, by column.
index_exprs: Vec<BoundIndexExprs>The expressions the table’s partial and expression indexes need.
index_hint: IndexChoiceINDEXED BY or NOT INDEXED on the target, which the query that finds
the rows to change obeys; inillucent_exec::dml::hint_target puts it there.
returning: Vec<BoundResultColumn>The RETURNING columns.
order_by: Vec<BoundOrderTerm>The ORDER BY that decides which rows a LIMIT keeps.
Empty unless the statement wrote one, and then always with a LIMIT,
because the binder refuses an order with nothing to limit. It goes onto
the query that finds the rows to change, which is where SQLite puts it
too: a limited write is WHERE rowid IN (SELECT rowid ... ORDER BY ... LIMIT ...) there.
limit: Option<BoundExpr>The LIMIT.
offset: Option<BoundExpr>The OFFSET.
triggers: Vec<BoundTrigger>The triggers this write fires, in schema order.
view_rows: Option<Box<BoundSelect>>The rows to fire an INSTEAD OF trigger for, when the target is a view.
A view has no rows of its own, so OLD has to come from running the
view. This is that query, with the statement’s WHERE on it and one
result column per view column.