From baf18835bee0ec5a7760901edba972dbbc61e095 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Wed, 7 Jan 2026 12:14:30 +0200 Subject: [PATCH] fix(client/lightweight): SQL nested transactions not supported --- apps/client/src/lightweight/sql_provider.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/apps/client/src/lightweight/sql_provider.ts b/apps/client/src/lightweight/sql_provider.ts index 05916adda..8d2dfe839 100644 --- a/apps/client/src/lightweight/sql_provider.ts +++ b/apps/client/src/lightweight/sql_provider.ts @@ -274,9 +274,26 @@ export default class BrowserSqlProvider implements DatabaseProvider { this.ensureDb(); const self = this; + let savepointCounter = 0; // Helper function to execute within a transaction const executeTransaction = (beginStatement: string, ...args: unknown[]): T => { + // If we're already in a transaction, use SAVEPOINTs for nesting + // This mimics better-sqlite3's behavior + if (self._inTransaction) { + const savepointName = `sp_${++savepointCounter}_${Date.now()}`; + self.db!.exec(`SAVEPOINT ${savepointName}`); + try { + const result = func.apply(null, args as [Statement]); + self.db!.exec(`RELEASE SAVEPOINT ${savepointName}`); + return result; + } catch (e) { + self.db!.exec(`ROLLBACK TO SAVEPOINT ${savepointName}`); + throw e; + } + } + + // Not in a transaction, start a new one self._inTransaction = true; self.db!.exec(beginStatement); try {