fix: use the correct index max_local threshold, not table's - #613
Merged
Conversation
iheitlager
force-pushed
the
feat/req7-btree-overflow-index-key-fixture
branch
from
August 27, 2026 21:04
4b97e2e to
7785626
Compare
local_payload_size computed max_local as usable_size - 35 unconditionally, but SQLite defines a smaller max_local for index cells (leaf AND interior) than for table leaf cells: (usable_size - 12) * 64 / 255 - 23 vs usable_size - 35. Every index cell whose payload landed between the two thresholds was read with a local_size far larger than what SQLite actually reserved on the page. Found while closing 006-btree Req 7's documented coverage gap: adding overflow_index_key.db (an ~8000-byte indexed TEXT key) immediately hit PayloadTooShort, since the payload cleared the correct (smaller) index threshold while staying under the wrong (larger) table one that had been masking the bug. Fixing the threshold surfaced a second latent bug: index delete (src/btree/index/delete.rs) never freed a removed entry's overflow chain at all (table delete already does). Index entries essentially never overflowed under the old, too-generous threshold, so the gap was never exercised. Added free_overflow_chain there, wired into both delete_from_leaf and the interior-match outright-delete path (remove_entry_by_child). spend: ~2x the trivial fixture-generation estimate — the fixture work surfaced two real correctness bugs (wrong max_local, leaked index overflow chains on delete) that needed fixing, not just a missing fixture.
iheitlager
force-pushed
the
feat/req7-btree-overflow-index-key-fixture
branch
from
August 27, 2026 21:06
7785626 to
8221349
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
overflow_index_key.db, an ~8000-byte indexed TEXT key against a 4096-byte page) immediately hitPayloadTooShort— the gap was hiding an actual bug, not just missing coverage.local_payload_sizecomputedmax_localasusable_size - 35unconditionally, but SQLite defines a smallermax_localfor index cells (leaf AND interior) than for table leaf cells:(usable_size - 12) * 64 / 255 - 23vsusable_size - 35. Every index cell whose payload landed between the two thresholds was read with alocal_sizefar larger than what SQLite actually reserved on the page.src/btree/index/delete.rs) never freed a removed entry's overflow chain at all (table delete already does). Index entries essentially never overflowed under the old, too-generous threshold, so the gap was never exercised. Addedfree_overflow_chain, wired into bothdelete_from_leafand the interior-match outright-delete path (remove_entry_by_child).Test plan
overflowing_index_key_reassembles_byte_identical_to_oracleagainst the new fixturedeleting_an_entry_with_overflow_frees_its_overflow_chaindeleting_all_entries_orphans_no_page(which started failing once the threshold was corrected, exposing the orphaned-overflow-page bug) now passescargo test --lib(925 tests), full corpus suite (373 tests, including fixture-regeneration reproducibility), clippy,make assurance(006-btree 18/18, no dead links) all cleanspend: ~2x the trivial fixture-generation estimate — the fixture work surfaced two real correctness bugs (wrong
max_local, leaked index overflow chains on delete) that needed fixing, not just a missing fixture.🤖 Generated with Claude Code