mirror of
https://github.com/aljazceru/turso.git
synced 2025-12-25 12:04:21 +01:00
Current table B-Tree seek code rely on the invariant that if key `K` is present in interior page then it also must be present in the leaf page. This is generally not true if data was ever deleted from the table because leaf row which key was used as a divider in the interior pages can be deleted. Also, SQLite spec says nothing about such invariant - so `turso-db` implementation of B-Tree should not rely on it. This PR introduce 3 options for B-Tree `seek` result: `Found` / `NotFound` and `TryAdvance` which is generated when leaf page have no match for `seek_op` but DB don't know if neighbor page can have matching data. There is an alternative approach where we can move cursor in the `seek` itself to the neighbor page - but I was afraid to introduce such changes because analogue `seek` function from SQLite works exactly like current version of the code and I think some query planner internals (for insertion) can rely on the fact that repositioning will leave cursor at the position of insertion: > ** If an exact match is not found, then the cursor is always ** left pointing at a leaf page which would hold the entry if it ** were present. The cursor might point to an entry that comes ** before or after the key. Also, this PR introduces new B-tree fuzz tests which generate table B-tree from scratch and execute opreations over it. This can help to reach some non trivial states and also generate huge DBs faster (that's how this bug was discovered) Reviewed-by: Jussi Saurio <jussi.saurio@gmail.com> Reviewed-by: Pere Diaz Bou <pere-altea@homail.com> Closes #2065