Expand description
The in-memory batch delta (designs/306-BATCH-OVERLAY-DESIGN.md §4, impl plan §3):
a per-TableSource fold of the current transaction’s SourceChanges, standing in for
the throwaway derivation writes the historical write-then-abort path performed
(deleted with 306 S5). During a
derivation, change k+1 must read a base state that already includes changes 1..k;
this structure holds exactly that divergence from the pinned base snapshot, so the
derivation connection can stay read-only.
Three parts, each a [rindle::btree::BTree] (the engine’s own COW B+tree, reused
as-is so the delta inherits the already-fuzzed compare_rows ordering — plan §3.5):
touched— every pk the batch touched (present OR removed), keyed under the pk sort. A base row whose pk is here is suppressed from the scan: its authoritative content now lives inprimary, or nowhere if the batch removed it.primary— the current derived content of each touched-and-present pk.secondary— the same rows under each index sort a fetch has asked for, created lazily byBatchDelta::rows_for_fetchand maintained eagerly byBatchDelta::applyfor the rest of the transaction (plan §3.3).
The delta is shared, not forked: TableSource::fork
clones the Rc<BatchDelta> because the delta models storage, which forks share
(plan D1). Range reads vend the tree’s owning [BTreeCursor] (an Rc<BNode>
spine — the OQ-1 design), constructed under a momentary RefCell borrow, so no
borrow is ever held across a vend (plan §3.4 as amended 2026-08-10: the original
materialize-to-Vec rule assumed a borrowing cursor and cost O(|delta|) per fetch
— O(N²) per batch under per-change ordered re-fetches). A later apply cannot
invalidate an in-flight stream either way: it runs at write-after-drain (the same
quiet point write_change occupied, with the in-flight change carried by the push
overlay), and if a cursor ever were alive, Rc::make_mut path-copies around every
node it pins, leaving the cursor its as-of-fetch snapshot.
Structs§
- Batch
Delta - The per-source batch delta. Interior-
RefCellso oneRc<BatchDelta>can be shared between aTableSource, its forks, and the engine that drives the lifecycle (plan D1 — the same idiom ascursors_open/fetch_error). - Delta
Budget - The derivation memory budget (design 306 D4) — what bounds a batch delta, in place of a row count.
- Delta
Rows - The lazily-pulled delta side of one fetch (
BatchDelta::rows_for_fetch): the owning [BTreeCursor] plus the request’s narrowing, applied per pull — constraint group-break, multi-constraintany, then the predicate (arbitrary user-compiled code, safe to run here because noRefCellborrow is held; the same guarantee materializing used to buy, now free).
Enums§
- Delta
Lookup - What the delta knows about a primary key (
BatchDelta::lookup_pk).
Constants§
- DEFAULT_
MAX_ DELTA_ BYTES - D4’s default derivation memory budget: 256 MiB of accounted delta (see
DeltaBudget), shared by every table a transaction touches. High enough that no OLTP transaction or existing test fires it; a bulk load that does trips [RindleError::DeltaOverflow] — the load-shed signal (the host commits the data and re-hydrates the affected queries) — instead of an OOM. The spill (design §7 / plan S6) lifts it later.