Regression test: deferred FK violations are checked before commit

This commit is contained in:
Jussi Saurio
2025-10-20 13:59:02 +03:00
parent 00e6ed82b6
commit bebe230b05

View File

@@ -208,6 +208,37 @@ fn test_constraint_error_aborts_transaction() {
assert_eq!(row, vec![Value::Integer(0)]);
}
#[test]
/// Regression test for https://github.com/tursodatabase/turso/issues/3784 where dirty pages
/// were flushed to WAL _before_ deferred FK violations were checked. This resulted in the
/// violations being persisted to the database, even though the transaction was aborted.
/// This test ensures that dirty pages are not flushed to WAL until after deferred violations are checked.
fn test_deferred_fk_violation_rollback_in_autocommit() {
let tmp_db = TempDatabase::new("test_deferred_fk_violation_rollback.db", true);
let conn = tmp_db.connect_limbo();
// Enable foreign keys
conn.execute("PRAGMA foreign_keys = ON").unwrap();
// Create parent and child tables with deferred FK constraint
conn.execute("CREATE TABLE parent(a PRIMARY KEY)").unwrap();
conn.execute("CREATE TABLE child(a, b, FOREIGN KEY(b) REFERENCES parent(a) DEFERRABLE INITIALLY DEFERRED)")
.unwrap();
// This insert should fail because parent(1) doesn't exist
// and the deferred FK violation should be caught at statement end in autocommit mode
let result = conn.execute("INSERT INTO child VALUES(1,1)");
assert!(matches!(result, Err(LimboError::Constraint(_))));
// Do a truncating checkpoint
conn.execute("PRAGMA wal_checkpoint(TRUNCATE)").unwrap();
// Verify that the child table is empty (the insert was rolled back)
let stmt = conn.query("SELECT COUNT(*) FROM child").unwrap().unwrap();
let row = helper_read_single_row(stmt);
assert_eq!(row, vec![Value::Integer(0)]);
}
#[test]
fn test_mvcc_transactions_autocommit() {
let tmp_db = TempDatabase::new_with_opts(