Merge 'Make cursor seek reentrant' from Pedro Muniz

Closes #1628.  Every function that calls `process_overflow_read` needs
to be reentrant. I did not change it here, but it would include
`get_prev_record` and `get_next_record`. Maybe `tablebtree_move_to` did
not need to use the state machine, but I included it as a safeguard.
Edit: Closes #1625 . When I implemented `restore_context`, I forgot to
add a `return_if_io` after calling it in `next` 🤦‍♂️
Edit: Closes #1617 . Just tested it and it also solves this bug.

Reviewed-by: Jussi Saurio <jussi.saurio@gmail.com>

Closes #1636
This commit is contained in:
Jussi Saurio
2025-06-03 14:24:40 +03:00
5 changed files with 538 additions and 205 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -3907,6 +3907,7 @@ pub fn op_delete(
Ok(InsnFunctionStepResult::Step)
}
#[derive(Debug)]
pub enum OpIdxDeleteState {
Seeking(ImmutableRecord), // First seek row to delete
Deleting,

View File

@@ -20,7 +20,10 @@ def stub_memory_test(
# zero_blob_size = 1024 **2
zero_blob = "0" * blob_size * 2
# vals = 100
big_stmt = ["CREATE TABLE temp (t1 BLOB, t2 INTEGER);"]
big_stmt = [
"CREATE TABLE temp (t1 BLOB, t2 INTEGER);",
"CREATE INDEX temp_index ON temp(t1);",
]
big_stmt = big_stmt + [
f"INSERT INTO temp (t1) VALUES (zeroblob({blob_size}));"
if i % 2 == 0 and blobs
@@ -39,6 +42,10 @@ def stub_memory_test(
big_stmt.append("SELECT count(*) FROM temp;")
expected.append(str(vals * 2))
big_stmt.append("DELETE FROM temp;")
big_stmt.append("SELECT count(*) FROM temp;")
expected.append(str(0))
big_stmt = "".join(big_stmt)
expected = "\n".join(expected)

View File

@@ -19,7 +19,7 @@ class InsertTest(BaseModel):
def run(self, limbo: TestLimboShell):
zero_blob = "0" * self.blob_size * 2
big_stmt = [self.db_schema]
big_stmt = [self.db_schema, "CREATE INDEX test_index ON test(t1);"]
big_stmt = big_stmt + [
f"INSERT INTO test (t1) VALUES (zeroblob({self.blob_size}));"
if i % 2 == 0 and self.has_blob
@@ -37,6 +37,10 @@ class InsertTest(BaseModel):
big_stmt.append("SELECT count(*) FROM test;")
expected.append(str(self.vals * 2))
big_stmt.append("DELETE FROM temp;")
big_stmt.append("SELECT count(*) FROM temp;")
expected.append(str(0))
big_stmt = "".join(big_stmt)
expected = "\n".join(expected)

View File

@@ -163,3 +163,10 @@ do_execsql_test_on_specific_db {:memory:} update-true-expr {
} {10|20|30
10|20|30}
# https://github.com/tursodatabase/limbo/issues/1625
do_execsql_test_on_specific_db {:memory:} update_cache_full_regression_test_#1625 {
CREATE TABLE t(x);
INSERT INTO t VALUES (randomblob(4096));
UPDATE t SET x = randomblob(4096) WHERE rowid = 1;
SELECT count(*) FROM t;
} {1}