Skip to content

Commit f9dfc3c

Browse files
MagicalTuxclaude
andcommitted
feat(vdbe): seek an N-table left-deep chain of ipk joins with live cursors (B5b-2d)
Generalizes the live inner-cursor seek (B5b-2a/b/c) from a single join to a bounded left-deep chain: the leftmost source is scanned, then each of up to three joined tables is fetched by seeking its INTEGER PRIMARY KEY to a value already assembled in the running prefix. This covers both a "star" (`… JOIN t ON o.x=t.id JOIN u ON o.z=u.uid`, both seeks keyed off the outer) and a "chain" (`… JOIN u ON t.id=u.uid`, the second seek keyed off the first seeked inner). The single-join block became a fold over the joins that grows the combined schema and re-seeks per prefix row. Each seek is a unique rowid seek followed by a full re-check of that join's `ON`, so the superset invariant holds per join and composes by induction over the fold — the whole chain is affinity-safe (same `to_i64` coercion, no new comparison semantics). A 2+ chain must be all INNER (a single join may still be LEFT); a fourth join, a non-ipk join, RIGHT/FULL, LEFT inside a chain, or a comma-join in the mix falls through to the materialized path, so correctness cannot regress. Verified VDBE-vs-tree-walker and vs sqlite3 3.50.4 (`tests/vdbe_live_cursor.rs`). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 5ef9bb4 commit f9dfc3c

3 files changed

Lines changed: 290 additions & 202 deletions

File tree

ROADMAP.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1201,14 +1201,24 @@ gated on VDBE-vs-tree-walker parity, so it can't regress correctness):
12011201
`ON` is re-evaluated after the seek (superset invariant), so the extra conjunct
12021202
just filters the seeked row. Affinity-neutral (same `to_i64` rowid coercion).
12031203
Verified vs the tree-walker and sqlite3 3.50.4.
1204+
- **B5b-2d — N-table left-deep chain of ipk seeks. DONE.** The single-join block
1205+
became a *fold*: the leftmost source is scanned, then each of up to three joins
1206+
seeks its ipk to a column already in the running prefix (`… JOIN t ON o.x=t.id
1207+
JOIN u ON o.z=u.uid` — a "star", or `… JOIN u ON t.id=u.uid` — chained off an
1208+
earlier seeked inner). Every seek is a unique rowid seek + full-`ON` re-check, so
1209+
the superset invariant holds per join and composes by induction → the whole chain
1210+
is affinity-safe. A 2+ chain must be all INNER (a single join may still be LEFT);
1211+
a 4th join, a non-ipk join, RIGHT/FULL, or a comma-join in the mix falls through
1212+
to the materialized path. Verified vs the tree-walker and sqlite3 3.50.4.
12041213
- **Remaining:** in-*interpreter* `OpenRead`/`SeekRowid` opcodes over B5b-1's
12051214
multi-cursor foundation (so the seek lives in bytecode, not row-assembly); seek
12061215
by a **secondary index** / `WITHOUT ROWID` PK (*affinity-blocked*: `index_seek_rowids`
12071216
compares raw keys with the index collation and skips the comparison-affinity that
12081217
`o.x = t.k` applies, so routing it risks a silent false-negative that would not
12091218
fall back — needs the tree-walker's affinity machinery first); the bare-`rowid`-alias
12101219
`ON` spelling (blocked on a pre-existing divergence — `t.rowid` in a join projection
1211-
already errors on the tree-walker); N-table chains.
1220+
already errors on the tree-walker); LEFT chains (null-propagation still owned by
1221+
the materialized path).
12121222
- **B1c — RIGHT/FULL join inner seeks.** INNER/LEFT already seek; RIGHT/FULL still
12131223
materialize the inner table.
12141224

0 commit comments

Comments
 (0)