@metaobjectsdev/migrate-ts 0.24.3 → 0.24.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/apply/apply.js +32 -6
- package/dist/apply/apply.js.map +1 -1
- package/dist/apply/runner-transaction-pass.d.ts +35 -7
- package/dist/apply/runner-transaction-pass.d.ts.map +1 -1
- package/dist/apply/runner-transaction-pass.js +14 -6
- package/dist/apply/runner-transaction-pass.js.map +1 -1
- package/package.json +2 -2
- package/src/apply/apply.ts +36 -6
- package/src/apply/runner-transaction-pass.ts +49 -13
package/dist/apply/apply.js
CHANGED
|
@@ -203,13 +203,39 @@ async function runSqlFileWithLedgerMutation(db, sqlText, mutateLedger) {
|
|
|
203
203
|
// rejects a nested BEGIN, which made table-rebuild migrations un-appliable on the
|
|
204
204
|
// scaffold's default dialect) and its own `PRAGMA foreign_keys = OFF`, which is a
|
|
205
205
|
// no-op inside a transaction. See runner-transaction-pass.ts for the full rationale.
|
|
206
|
-
const { statements } = prepareForRunnerTransaction(sqlText);
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
206
|
+
const { statements, requiresForeignKeysOff, postTransactionChecks } = prepareForRunnerTransaction(sqlText);
|
|
207
|
+
// OUTSIDE the transaction, deliberately: `PRAGMA foreign_keys` is a no-op inside one,
|
|
208
|
+
// and `defer_foreign_keys` cannot stand in for it here — `DROP TABLE`'s implicit delete
|
|
209
|
+
// records a deferred violation per referencing row that the repairing RENAME never
|
|
210
|
+
// decrements, so COMMIT fails. See runner-transaction-pass.ts.
|
|
211
|
+
if (requiresForeignKeysOff) {
|
|
212
|
+
await sql.raw("PRAGMA foreign_keys = OFF").execute(db);
|
|
213
|
+
}
|
|
214
|
+
try {
|
|
215
|
+
await db.transaction().execute(async (trx) => {
|
|
216
|
+
for (const stmt of statements) {
|
|
217
|
+
await sql.raw(stmt).execute(trx);
|
|
218
|
+
}
|
|
219
|
+
await mutateLedger(trx);
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
finally {
|
|
223
|
+
// Restore before anything else touches this connection, even if the migration threw.
|
|
224
|
+
if (requiresForeignKeysOff) {
|
|
225
|
+
await sql.raw("PRAGMA foreign_keys = ON").execute(db);
|
|
210
226
|
}
|
|
211
|
-
|
|
212
|
-
|
|
227
|
+
}
|
|
228
|
+
// The file's own safety net, finally able to report. Running it inside the transaction
|
|
229
|
+
// discarded its rows, so a rebuild that DID strand a reference passed silently.
|
|
230
|
+
for (const check of postTransactionChecks) {
|
|
231
|
+
const result = await sql.raw(check).execute(db);
|
|
232
|
+
const rows = result.rows ?? [];
|
|
233
|
+
if (rows.length > 0) {
|
|
234
|
+
throw new Error(`migration left ${rows.length} dangling foreign-key reference(s): ${check} reported ` +
|
|
235
|
+
`${JSON.stringify(rows.slice(0, 5))}. The database is NOT consistent — restore from ` +
|
|
236
|
+
`backup rather than continuing.`);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
213
239
|
}
|
|
214
240
|
async function discoverMigrations(dir) {
|
|
215
241
|
let entries;
|
package/dist/apply/apply.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apply.js","sourceRoot":"","sources":["../../src/apply/apply.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"apply.js","sourceRoot":"","sources":["../../src/apply/apply.ts"],"names":[],"mappings":"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"}
|
|
@@ -32,13 +32,33 @@
|
|
|
32
32
|
* <h3>What it does</h3>
|
|
33
33
|
* 1. **Drops transaction control** (`BEGIN`/`COMMIT`/`ROLLBACK`/`SAVEPOINT`/`RELEASE`).
|
|
34
34
|
* The runner's transaction supplies the atomicity the file was asking for.
|
|
35
|
-
* 2. **
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
35
|
+
* 2. **Reports `PRAGMA foreign_keys = OFF` to the caller as `requiresForeignKeysOff`**
|
|
36
|
+
* instead of executing it, because the pragma is a **no-op inside a transaction** and
|
|
37
|
+
* must be issued BEFORE the transaction opens. That is SQLite's own documented
|
|
38
|
+
* recreate-and-copy procedure, and it is the only form that works.
|
|
39
|
+
*
|
|
40
|
+
* This used to rewrite it to `PRAGMA defer_foreign_keys = ON`, reasoning that deferral
|
|
41
|
+
* is "the in-transaction equivalent". **It is not, for this recipe.** Deferral makes
|
|
42
|
+
* COMMIT check the violations rather than skipping them, and the rebuild's repair step
|
|
43
|
+
* is `ALTER TABLE __new_x RENAME TO x` — a RENAME, not an INSERT. `DROP TABLE x`'s
|
|
44
|
+
* implicit delete records one deferred violation per referencing row, nothing ever
|
|
45
|
+
* decrements that counter, and COMMIT fails:
|
|
46
|
+
*
|
|
47
|
+
* SQLITE_CONSTRAINT_FOREIGNKEY: FOREIGN KEY constraint failed
|
|
48
|
+
*
|
|
49
|
+
* So ANY rebuild of a table another populated table references — a CHECK added by
|
|
50
|
+
* adopting a `field.enum`, an evolved `@values`, a column type change — was
|
|
51
|
+
* un-appliable on the scaffold's default dialect. Found by adopting MetaObjects into an
|
|
52
|
+
* existing three-table app (`authors <- books <- reviews`), which is the documented
|
|
53
|
+
* migration path. Proven with a controlled pair on identical database copies: deferral
|
|
54
|
+
* fails, `foreign_keys = OFF` outside the transaction applies cleanly with every row
|
|
55
|
+
* preserved. (D1 cannot do this — its implicit transaction owns the connection — which
|
|
56
|
+
* is why D1 needed the full referrer cascade of #241 instead.)
|
|
57
|
+
* 3. **Drops the matching `PRAGMA foreign_keys = ON`.** Restoring it is the caller's job,
|
|
58
|
+
* since the caller is now the one that turned it off.
|
|
59
|
+
* 4. **Lifts `PRAGMA foreign_key_check` out** as `postTransactionChecks`. Run inside the
|
|
60
|
+
* transaction its result set was simply discarded, so the file's own safety net never
|
|
61
|
+
* caught anything; the caller now runs it after commit and fails on any row.
|
|
42
62
|
*
|
|
43
63
|
* Postgres migrations contain none of these constructs, so this is a no-op for them —
|
|
44
64
|
* which is why it keys on statement text rather than needing the dialect threaded in.
|
|
@@ -48,6 +68,14 @@ export interface RunnerTransactionPassResult {
|
|
|
48
68
|
statements: string[];
|
|
49
69
|
/** Human-readable adaptations made, for `--verbose`/diagnostics. Empty when untouched. */
|
|
50
70
|
notes: string[];
|
|
71
|
+
/**
|
|
72
|
+
* The file asked for FK enforcement to be off. The caller MUST issue
|
|
73
|
+
* `PRAGMA foreign_keys = OFF` before opening its transaction and restore it after —
|
|
74
|
+
* inside a transaction the pragma does nothing (see the class doc).
|
|
75
|
+
*/
|
|
76
|
+
requiresForeignKeysOff: boolean;
|
|
77
|
+
/** Statements to run AFTER the transaction commits; any returned row is a failure. */
|
|
78
|
+
postTransactionChecks: string[];
|
|
51
79
|
}
|
|
52
80
|
export declare function prepareForRunnerTransaction(sqlText: string): RunnerTransactionPassResult;
|
|
53
81
|
//# sourceMappingURL=runner-transaction-pass.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runner-transaction-pass.d.ts","sourceRoot":"","sources":["../../src/apply/runner-transaction-pass.ts"],"names":[],"mappings":"AAEA
|
|
1
|
+
{"version":3,"file":"runner-transaction-pass.d.ts","sourceRoot":"","sources":["../../src/apply/runner-transaction-pass.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgEG;AACH,MAAM,WAAW,2BAA2B;IAC1C,wEAAwE;IACxE,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,0FAA0F;IAC1F,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB;;;;OAIG;IACH,sBAAsB,EAAE,OAAO,CAAC;IAChC,sFAAsF;IACtF,qBAAqB,EAAE,MAAM,EAAE,CAAC;CACjC;AAOD,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,MAAM,GAAG,2BAA2B,CA+BxF"}
|
|
@@ -2,28 +2,36 @@ import { splitSqlStatements } from "../sql/split-statements.js";
|
|
|
2
2
|
const TRANSACTION_CONTROL = /^\s*(BEGIN|COMMIT|END\s+TRANSACTION|ROLLBACK|SAVEPOINT|RELEASE)\b/i;
|
|
3
3
|
const FK_OFF = /^\s*PRAGMA\s+foreign_keys\s*=\s*(OFF|0|false)\s*$/i;
|
|
4
4
|
const FK_ON = /^\s*PRAGMA\s+foreign_keys\s*=\s*(ON|1|true)\s*$/i;
|
|
5
|
+
const FK_CHECK = /^\s*PRAGMA\s+foreign_key_check\s*$/i;
|
|
5
6
|
export function prepareForRunnerTransaction(sqlText) {
|
|
6
7
|
const notes = [];
|
|
7
8
|
const statements = [];
|
|
9
|
+
const postTransactionChecks = [];
|
|
10
|
+
let requiresForeignKeysOff = false;
|
|
8
11
|
for (const stmt of splitSqlStatements(sqlText)) {
|
|
9
12
|
if (TRANSACTION_CONTROL.test(stmt)) {
|
|
10
13
|
notes.push(`dropped transaction control (runner owns the transaction): ${firstWords(stmt)}`);
|
|
11
14
|
continue;
|
|
12
15
|
}
|
|
13
16
|
if (FK_OFF.test(stmt)) {
|
|
14
|
-
//
|
|
15
|
-
// transaction,
|
|
16
|
-
|
|
17
|
-
notes.push("
|
|
17
|
+
// Hand the INTENT to the caller rather than executing it here. The pragma is a
|
|
18
|
+
// no-op inside a transaction, and deferral is not a substitute for this recipe.
|
|
19
|
+
requiresForeignKeysOff = true;
|
|
20
|
+
notes.push("lifted `PRAGMA foreign_keys = OFF` out of the transaction (it is a no-op inside one)");
|
|
18
21
|
continue;
|
|
19
22
|
}
|
|
20
23
|
if (FK_ON.test(stmt)) {
|
|
21
|
-
notes.push("dropped `PRAGMA foreign_keys = ON` (
|
|
24
|
+
notes.push("dropped `PRAGMA foreign_keys = ON` (the caller restores what the caller disabled)");
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
if (FK_CHECK.test(stmt)) {
|
|
28
|
+
postTransactionChecks.push(stmt);
|
|
29
|
+
notes.push("deferred `PRAGMA foreign_key_check` to after commit (its rows are discarded inside a transaction)");
|
|
22
30
|
continue;
|
|
23
31
|
}
|
|
24
32
|
statements.push(stmt);
|
|
25
33
|
}
|
|
26
|
-
return { statements, notes };
|
|
34
|
+
return { statements, notes, requiresForeignKeysOff, postTransactionChecks };
|
|
27
35
|
}
|
|
28
36
|
function firstWords(stmt) {
|
|
29
37
|
return stmt.trim().split(/\s+/).slice(0, 3).join(" ");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runner-transaction-pass.js","sourceRoot":"","sources":["../../src/apply/runner-transaction-pass.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"runner-transaction-pass.js","sourceRoot":"","sources":["../../src/apply/runner-transaction-pass.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAkFhE,MAAM,mBAAmB,GAAG,oEAAoE,CAAC;AACjG,MAAM,MAAM,GAAG,oDAAoD,CAAC;AACpE,MAAM,KAAK,GAAG,kDAAkD,CAAC;AACjE,MAAM,QAAQ,GAAG,qCAAqC,CAAC;AAEvD,MAAM,UAAU,2BAA2B,CAAC,OAAe;IACzD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,MAAM,qBAAqB,GAAa,EAAE,CAAC;IAC3C,IAAI,sBAAsB,GAAG,KAAK,CAAC;IAEnC,KAAK,MAAM,IAAI,IAAI,kBAAkB,CAAC,OAAO,CAAC,EAAE,CAAC;QAC/C,IAAI,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACnC,KAAK,CAAC,IAAI,CAAC,8DAA8D,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC7F,SAAS;QACX,CAAC;QACD,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACtB,+EAA+E;YAC/E,gFAAgF;YAChF,sBAAsB,GAAG,IAAI,CAAC;YAC9B,KAAK,CAAC,IAAI,CAAC,sFAAsF,CAAC,CAAC;YACnG,SAAS;QACX,CAAC;QACD,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACrB,KAAK,CAAC,IAAI,CAAC,mFAAmF,CAAC,CAAC;YAChG,SAAS;QACX,CAAC;QACD,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACxB,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACjC,KAAK,CAAC,IAAI,CAAC,mGAAmG,CAAC,CAAC;YAChH,SAAS;QACX,CAAC;QACD,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC;IAED,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,CAAC;AAC9E,CAAC;AAED,SAAS,UAAU,CAAC,IAAY;IAC9B,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACxD,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@metaobjectsdev/migrate-ts",
|
|
3
|
-
"version": "0.24.
|
|
3
|
+
"version": "0.24.5",
|
|
4
4
|
"description": "Schema migration tooling for MetaObjects: diff metadata vs DB and emit SQL for Postgres and SQLite.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"@iarna/toml": "^2.2.5",
|
|
48
|
-
"@metaobjectsdev/metadata": "0.24.
|
|
48
|
+
"@metaobjectsdev/metadata": "0.24.5"
|
|
49
49
|
},
|
|
50
50
|
"peerDependencies": {
|
|
51
51
|
"kysely": ">=0.27.0 <0.30.0",
|
package/src/apply/apply.ts
CHANGED
|
@@ -304,13 +304,43 @@ async function runSqlFileWithLedgerMutation(
|
|
|
304
304
|
// rejects a nested BEGIN, which made table-rebuild migrations un-appliable on the
|
|
305
305
|
// scaffold's default dialect) and its own `PRAGMA foreign_keys = OFF`, which is a
|
|
306
306
|
// no-op inside a transaction. See runner-transaction-pass.ts for the full rationale.
|
|
307
|
-
const { statements } =
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
307
|
+
const { statements, requiresForeignKeysOff, postTransactionChecks } =
|
|
308
|
+
prepareForRunnerTransaction(sqlText);
|
|
309
|
+
|
|
310
|
+
// OUTSIDE the transaction, deliberately: `PRAGMA foreign_keys` is a no-op inside one,
|
|
311
|
+
// and `defer_foreign_keys` cannot stand in for it here — `DROP TABLE`'s implicit delete
|
|
312
|
+
// records a deferred violation per referencing row that the repairing RENAME never
|
|
313
|
+
// decrements, so COMMIT fails. See runner-transaction-pass.ts.
|
|
314
|
+
if (requiresForeignKeysOff) {
|
|
315
|
+
await sql.raw("PRAGMA foreign_keys = OFF").execute(db);
|
|
316
|
+
}
|
|
317
|
+
try {
|
|
318
|
+
await db.transaction().execute(async (trx) => {
|
|
319
|
+
for (const stmt of statements) {
|
|
320
|
+
await sql.raw(stmt).execute(trx);
|
|
321
|
+
}
|
|
322
|
+
await mutateLedger(trx);
|
|
323
|
+
});
|
|
324
|
+
} finally {
|
|
325
|
+
// Restore before anything else touches this connection, even if the migration threw.
|
|
326
|
+
if (requiresForeignKeysOff) {
|
|
327
|
+
await sql.raw("PRAGMA foreign_keys = ON").execute(db);
|
|
311
328
|
}
|
|
312
|
-
|
|
313
|
-
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// The file's own safety net, finally able to report. Running it inside the transaction
|
|
332
|
+
// discarded its rows, so a rebuild that DID strand a reference passed silently.
|
|
333
|
+
for (const check of postTransactionChecks) {
|
|
334
|
+
const result = await sql.raw(check).execute(db);
|
|
335
|
+
const rows = (result as { rows?: unknown[] }).rows ?? [];
|
|
336
|
+
if (rows.length > 0) {
|
|
337
|
+
throw new Error(
|
|
338
|
+
`migration left ${rows.length} dangling foreign-key reference(s): ${check} reported ` +
|
|
339
|
+
`${JSON.stringify(rows.slice(0, 5))}. The database is NOT consistent — restore from ` +
|
|
340
|
+
`backup rather than continuing.`,
|
|
341
|
+
);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
314
344
|
}
|
|
315
345
|
|
|
316
346
|
async function discoverMigrations(dir: string): Promise<DiscoveredMigration[]> {
|
|
@@ -34,13 +34,33 @@ import { splitSqlStatements } from "../sql/split-statements.js";
|
|
|
34
34
|
* <h3>What it does</h3>
|
|
35
35
|
* 1. **Drops transaction control** (`BEGIN`/`COMMIT`/`ROLLBACK`/`SAVEPOINT`/`RELEASE`).
|
|
36
36
|
* The runner's transaction supplies the atomicity the file was asking for.
|
|
37
|
-
* 2. **
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
37
|
+
* 2. **Reports `PRAGMA foreign_keys = OFF` to the caller as `requiresForeignKeysOff`**
|
|
38
|
+
* instead of executing it, because the pragma is a **no-op inside a transaction** and
|
|
39
|
+
* must be issued BEFORE the transaction opens. That is SQLite's own documented
|
|
40
|
+
* recreate-and-copy procedure, and it is the only form that works.
|
|
41
|
+
*
|
|
42
|
+
* This used to rewrite it to `PRAGMA defer_foreign_keys = ON`, reasoning that deferral
|
|
43
|
+
* is "the in-transaction equivalent". **It is not, for this recipe.** Deferral makes
|
|
44
|
+
* COMMIT check the violations rather than skipping them, and the rebuild's repair step
|
|
45
|
+
* is `ALTER TABLE __new_x RENAME TO x` — a RENAME, not an INSERT. `DROP TABLE x`'s
|
|
46
|
+
* implicit delete records one deferred violation per referencing row, nothing ever
|
|
47
|
+
* decrements that counter, and COMMIT fails:
|
|
48
|
+
*
|
|
49
|
+
* SQLITE_CONSTRAINT_FOREIGNKEY: FOREIGN KEY constraint failed
|
|
50
|
+
*
|
|
51
|
+
* So ANY rebuild of a table another populated table references — a CHECK added by
|
|
52
|
+
* adopting a `field.enum`, an evolved `@values`, a column type change — was
|
|
53
|
+
* un-appliable on the scaffold's default dialect. Found by adopting MetaObjects into an
|
|
54
|
+
* existing three-table app (`authors <- books <- reviews`), which is the documented
|
|
55
|
+
* migration path. Proven with a controlled pair on identical database copies: deferral
|
|
56
|
+
* fails, `foreign_keys = OFF` outside the transaction applies cleanly with every row
|
|
57
|
+
* preserved. (D1 cannot do this — its implicit transaction owns the connection — which
|
|
58
|
+
* is why D1 needed the full referrer cascade of #241 instead.)
|
|
59
|
+
* 3. **Drops the matching `PRAGMA foreign_keys = ON`.** Restoring it is the caller's job,
|
|
60
|
+
* since the caller is now the one that turned it off.
|
|
61
|
+
* 4. **Lifts `PRAGMA foreign_key_check` out** as `postTransactionChecks`. Run inside the
|
|
62
|
+
* transaction its result set was simply discarded, so the file's own safety net never
|
|
63
|
+
* caught anything; the caller now runs it after commit and fails on any row.
|
|
44
64
|
*
|
|
45
65
|
* Postgres migrations contain none of these constructs, so this is a no-op for them —
|
|
46
66
|
* which is why it keys on statement text rather than needing the dialect threaded in.
|
|
@@ -50,15 +70,26 @@ export interface RunnerTransactionPassResult {
|
|
|
50
70
|
statements: string[];
|
|
51
71
|
/** Human-readable adaptations made, for `--verbose`/diagnostics. Empty when untouched. */
|
|
52
72
|
notes: string[];
|
|
73
|
+
/**
|
|
74
|
+
* The file asked for FK enforcement to be off. The caller MUST issue
|
|
75
|
+
* `PRAGMA foreign_keys = OFF` before opening its transaction and restore it after —
|
|
76
|
+
* inside a transaction the pragma does nothing (see the class doc).
|
|
77
|
+
*/
|
|
78
|
+
requiresForeignKeysOff: boolean;
|
|
79
|
+
/** Statements to run AFTER the transaction commits; any returned row is a failure. */
|
|
80
|
+
postTransactionChecks: string[];
|
|
53
81
|
}
|
|
54
82
|
|
|
55
83
|
const TRANSACTION_CONTROL = /^\s*(BEGIN|COMMIT|END\s+TRANSACTION|ROLLBACK|SAVEPOINT|RELEASE)\b/i;
|
|
56
84
|
const FK_OFF = /^\s*PRAGMA\s+foreign_keys\s*=\s*(OFF|0|false)\s*$/i;
|
|
57
85
|
const FK_ON = /^\s*PRAGMA\s+foreign_keys\s*=\s*(ON|1|true)\s*$/i;
|
|
86
|
+
const FK_CHECK = /^\s*PRAGMA\s+foreign_key_check\s*$/i;
|
|
58
87
|
|
|
59
88
|
export function prepareForRunnerTransaction(sqlText: string): RunnerTransactionPassResult {
|
|
60
89
|
const notes: string[] = [];
|
|
61
90
|
const statements: string[] = [];
|
|
91
|
+
const postTransactionChecks: string[] = [];
|
|
92
|
+
let requiresForeignKeysOff = false;
|
|
62
93
|
|
|
63
94
|
for (const stmt of splitSqlStatements(sqlText)) {
|
|
64
95
|
if (TRANSACTION_CONTROL.test(stmt)) {
|
|
@@ -66,20 +97,25 @@ export function prepareForRunnerTransaction(sqlText: string): RunnerTransactionP
|
|
|
66
97
|
continue;
|
|
67
98
|
}
|
|
68
99
|
if (FK_OFF.test(stmt)) {
|
|
69
|
-
//
|
|
70
|
-
// transaction,
|
|
71
|
-
|
|
72
|
-
notes.push("
|
|
100
|
+
// Hand the INTENT to the caller rather than executing it here. The pragma is a
|
|
101
|
+
// no-op inside a transaction, and deferral is not a substitute for this recipe.
|
|
102
|
+
requiresForeignKeysOff = true;
|
|
103
|
+
notes.push("lifted `PRAGMA foreign_keys = OFF` out of the transaction (it is a no-op inside one)");
|
|
73
104
|
continue;
|
|
74
105
|
}
|
|
75
106
|
if (FK_ON.test(stmt)) {
|
|
76
|
-
notes.push("dropped `PRAGMA foreign_keys = ON` (
|
|
107
|
+
notes.push("dropped `PRAGMA foreign_keys = ON` (the caller restores what the caller disabled)");
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
if (FK_CHECK.test(stmt)) {
|
|
111
|
+
postTransactionChecks.push(stmt);
|
|
112
|
+
notes.push("deferred `PRAGMA foreign_key_check` to after commit (its rows are discarded inside a transaction)");
|
|
77
113
|
continue;
|
|
78
114
|
}
|
|
79
115
|
statements.push(stmt);
|
|
80
116
|
}
|
|
81
117
|
|
|
82
|
-
return { statements, notes };
|
|
118
|
+
return { statements, notes, requiresForeignKeysOff, postTransactionChecks };
|
|
83
119
|
}
|
|
84
120
|
|
|
85
121
|
function firstWords(stmt: string): string {
|