Skip to content

Commit 8345b14

Browse files
author
CloudLobster
committed
fix: PRAGMA defer_foreign_keys must run BEFORE batch transaction
SQLite rule: PRAGMA foreign_keys/defer_foreign_keys cannot be changed inside a transaction. D1 batch() is an implicit transaction. Previous fix put PRAGMA inside the batch where it had no effect. Now runs PRAGMA defer_foreign_keys = ON as a separate .run() call before the batch, which correctly defers FK checks for the duration of the batch transaction.
1 parent c980671 commit 8345b14

2 files changed

Lines changed: 8 additions & 7 deletions

File tree

worker/src/routes/register.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -301,9 +301,11 @@ registerRoutes.put('/upgrade', authMiddleware(), async (c) => {
301301
return c.json({ error: 'This Basename handle is already registered by another wallet' }, 409);
302302
}
303303

304-
// 更新帳號 handle + 遷移所有 FK 子表(D1 不支援 PRAGMA defer_foreign_keys)
304+
// 更新帳號 handle + 遷移所有 FK 子表
305+
// SQLite: PRAGMA defer_foreign_keys must be set BEFORE the transaction starts.
306+
// D1 batch() is an implicit transaction, so PRAGMA goes before it.
307+
await c.env.DB.prepare("PRAGMA defer_foreign_keys = ON").run();
305308
const batchResults = await c.env.DB.batch([
306-
c.env.DB.prepare("PRAGMA foreign_keys = OFF"),
307309
// 1. 更新主表
308310
c.env.DB.prepare(
309311
'UPDATE accounts SET handle = ?, basename = ? WHERE wallet = ?'
@@ -348,9 +350,8 @@ registerRoutes.put('/upgrade', authMiddleware(), async (c) => {
348350
c.env.DB.prepare(
349351
'UPDATE escrow_claims SET claimer_handle = ? WHERE claimer_handle = ?'
350352
).bind(newHandle, oldHandle),
351-
c.env.DB.prepare("PRAGMA foreign_keys = ON"),
352353
]);
353-
const migratedCount = batchResults[2]?.meta?.changes || 0;
354+
const migratedCount = batchResults[1]?.meta?.changes || 0;
354355

355356
// Insert into basename_aliases with is_primary=1
356357
if (basenames) {

worker/src/routes/settings.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -185,9 +185,10 @@ settingsRoutes.put('/primary', async (c) => {
185185
return c.json({ error: 'Handle already taken by another wallet' }, 409);
186186
}
187187

188-
// Batch update: switch primary(更新所有 FK 子表,D1 不支援 defer_foreign_keys)
188+
// Batch update: switch primary(更新所有 FK 子表)
189+
// SQLite: PRAGMA defer_foreign_keys must be set BEFORE the transaction starts.
190+
await c.env.DB.prepare("PRAGMA defer_foreign_keys = ON").run();
189191
await c.env.DB.batch([
190-
c.env.DB.prepare("PRAGMA foreign_keys = OFF"),
191192
// Update account handle
192193
c.env.DB.prepare('UPDATE accounts SET handle = ?, basename = ? WHERE wallet = ?')
193194
.bind(newHandle, alias.basename, auth.wallet),
@@ -224,7 +225,6 @@ settingsRoutes.put('/primary', async (c) => {
224225
// Set new primary
225226
c.env.DB.prepare('UPDATE basename_aliases SET is_primary = 1 WHERE handle = ? AND wallet = ?')
226227
.bind(newHandle, auth.wallet),
227-
c.env.DB.prepare("PRAGMA foreign_keys = ON"),
228228
]);
229229

230230
// Issue new token

0 commit comments

Comments
 (0)