diff --git a/compat.js b/compat.js index f3f922d..2fe5ab4 100644 --- a/compat.js +++ b/compat.js @@ -119,7 +119,7 @@ class Database { db.exec("COMMIT"); return result; } catch (err) { - db.exec("ROLLBACK"); + if (db.inTransaction) db.exec("ROLLBACK"); throw err; } }; diff --git a/integration-tests/tests/async.test.js b/integration-tests/tests/async.test.js index f6536a7..0251791 100644 --- a/integration-tests/tests/async.test.js +++ b/integration-tests/tests/async.test.js @@ -414,6 +414,28 @@ test.serial("Database.transaction().immediate()", async (t) => { t.is(db.inTransaction, false); }); +test.serial("Database.transaction() rethrows the error when SQLite already rolled back", async (t) => { + const db = t.context.db; + const insert = await db.prepare( + "INSERT OR ROLLBACK INTO users(id, name, email) VALUES (?, ?, ?)" + ); + const insertMany = db.transaction(async (users) => { + for (const user of users) await insert.run(user.id, user.name, user.email); + }); + await t.throwsAsync(async () => { + await insertMany([ + { id: 3, name: "Joey", email: "joey@example.org" }, + { id: 1, name: "Sally", email: "sally@example.org" }, + ]); + }, { + instanceOf: t.context.errorType, + code: "SQLITE_CONSTRAINT_PRIMARYKEY", + }); + t.is(db.inTransaction, false); + const stmt = await db.prepare("SELECT * FROM users WHERE id = ?"); + t.is(await stmt.get(3), undefined); +}); + test.serial("Database.pragma()", async (t) => { const db = t.context.db; await db.pragma("cache_size = 2000"); diff --git a/integration-tests/tests/sync.test.js b/integration-tests/tests/sync.test.js index 7bcb05c..add7938 100644 --- a/integration-tests/tests/sync.test.js +++ b/integration-tests/tests/sync.test.js @@ -380,6 +380,27 @@ test.serial("Database.transaction().immediate()", async (t) => { t.is(db.inTransaction, false); }); +test.serial("Database.transaction() rethrows the error when SQLite already rolled back", async (t) => { + const db = t.context.db; + const insert = db.prepare( + "INSERT OR ROLLBACK INTO users(id, name, email) VALUES (?, ?, ?)" + ); + const insertMany = db.transaction((users) => { + for (const user of users) insert.run(user.id, user.name, user.email); + }); + t.throws(() => { + insertMany([ + { id: 3, name: "Joey", email: "joey@example.org" }, + { id: 1, name: "Sally", email: "sally@example.org" }, + ]); + }, { + instanceOf: t.context.errorType, + code: "SQLITE_CONSTRAINT_PRIMARYKEY", + }); + t.is(db.inTransaction, false); + t.is(db.prepare("SELECT * FROM users WHERE id = ?").get(3), undefined); +}); + test.serial("values", async (t) => { const db = t.context.db; diff --git a/promise.js b/promise.js index f507a52..3128862 100644 --- a/promise.js +++ b/promise.js @@ -157,7 +157,7 @@ class Database { await db.exec("COMMIT"); return result; } catch (err) { - await db.exec("ROLLBACK"); + if (db.inTransaction) await db.exec("ROLLBACK"); throw err; } };