Merge 'Fix VDBE program abort' from Nikita Sivukhin

This PR add proper program abort in case of unfinished statement reset
and interruption.
Also, this PR makes rollback methods non-failing because otherwise of
their callers usually unclear (if rollback failed - what is the state of
statement/connection/transaction?)

Reviewed-by: Preston Thorpe <preston@turso.tech>

Closes #3591
This commit is contained in:
Pekka Enberg
2025-10-07 09:07:07 +03:00
committed by GitHub
15 changed files with 199 additions and 201 deletions

View File

@@ -1,4 +1,4 @@
use crate::common::TempDatabase;
use crate::common::{limbo_exec_rows, TempDatabase};
use turso_core::{StepResult, Value};
#[test]
@@ -876,3 +876,24 @@ fn test_upsert_parameters_order() -> anyhow::Result<()> {
);
Ok(())
}
#[test]
fn test_multiple_connections_visibility() -> anyhow::Result<()> {
let tmp_db = TempDatabase::new_with_rusqlite(
"CREATE TABLE test (k INTEGER PRIMARY KEY, v INTEGER);",
false,
);
let conn1 = tmp_db.connect_limbo();
let conn2 = tmp_db.connect_limbo();
conn1.execute("BEGIN")?;
conn1.execute("INSERT INTO test VALUES (1, 2), (3, 4)")?;
let mut stmt = conn2.prepare("SELECT COUNT(*) FROM test").unwrap();
let _ = stmt.step().unwrap();
// intentionally drop not-fully-consumed statement in order to check that on Drop statement will execute reset with proper cleanup
drop(stmt);
conn1.execute("COMMIT")?;
let rows = limbo_exec_rows(&tmp_db, &conn2, "SELECT COUNT(*) FROM test");
assert_eq!(rows, vec![vec![rusqlite::types::Value::Integer(2)]]);
Ok(())
}

View File

@@ -95,6 +95,7 @@ fn test_deferred_transaction_no_restart() {
.execute("INSERT INTO test (id, value) VALUES (2, 'second')")
.unwrap();
conn2.execute("COMMIT").unwrap();
drop(stmt);
let mut stmt = conn1.query("SELECT COUNT(*) FROM test").unwrap().unwrap();
if let StepResult::Row = stmt.step().unwrap() {