@voltro/database 0.62.3 → 0.63.0
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/sql.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { $ as e, $t as t, Ht as n, Ut as r, a as i, at as a, c as o, d as s, en as c, et as l, g as u, h as d, i as f, it as p, o as m, r as h, s as g, tt as _, u as v, vt as y, wt as b, y as x } from "./frameworkLiveTables-
|
|
1
|
+
import { $ as e, $t as t, Ht as n, Ut as r, a as i, at as a, c as o, d as s, en as c, et as l, g as u, h as d, i as f, it as p, o as m, r as h, s as g, tt as _, u as v, vt as y, wt as b, y as x } from "./frameworkLiveTables-X6rOAleu.js";
|
|
2
2
|
import { Effect as S, Schedule as C } from "effect";
|
|
3
|
-
import { createHash as
|
|
4
|
-
import { createLogger as
|
|
5
|
-
import { SqlClient as
|
|
6
|
-
import { promises as
|
|
7
|
-
import { join as
|
|
8
|
-
import { pathToFileURL as
|
|
3
|
+
import { createHash as ee } from "node:crypto";
|
|
4
|
+
import { createLogger as w } from "@voltro/logger";
|
|
5
|
+
import { SqlClient as T } from "@effect/sql";
|
|
6
|
+
import { promises as te } from "node:fs";
|
|
7
|
+
import { join as ne } from "node:path";
|
|
8
|
+
import { pathToFileURL as re } from "node:url";
|
|
9
9
|
//#region src/migrations/ddlError.ts
|
|
10
|
-
var
|
|
10
|
+
var ie = (e, t, n, r = 400) => {
|
|
11
11
|
let i = n, a = i.cause ?? {}, o = (e) => {
|
|
12
12
|
let t = a[e];
|
|
13
13
|
return t == null || t === "" ? void 0 : String(t);
|
|
@@ -38,21 +38,21 @@ var re = (e, t, n, r = 400) => {
|
|
|
38
38
|
let t = o(e);
|
|
39
39
|
t !== void 0 && s.push(`db.${e}: ${t}`);
|
|
40
40
|
}
|
|
41
|
-
let c =
|
|
41
|
+
let c = ae(o("code"));
|
|
42
42
|
return c !== void 0 && s.push("", c), s.push(""), s.join("\n");
|
|
43
|
-
},
|
|
44
|
-
if (t !== "mysql" && t !== "mariadb" || !e.appliedIndexes.some(
|
|
43
|
+
}, ae = (e) => e === "3F000" ? "remedy: the connection's search_path names a schema that does not exist. Voltro sets it from DB_SCHEMA — create the schema (`CREATE SCHEMA \"<name>\"`) or unset DB_SCHEMA to use the connection default. Voltro creates TABLES, never the schema itself: that is a namespace decision, and inventing one from a typo is how a migration lands somewhere nobody is looking." : void 0, oe = (e) => e.unique === !0 && typeof e.where == "string" && e.where.length > 0, se = (e) => e.replace(/"/g, "`"), ce = (e) => typeof e == "string" ? e : e.name ?? String(e), le = (e, t) => `_ua_${t}_${e}`.slice(0, 64), ue = (e, t) => {
|
|
44
|
+
if (t !== "mysql" && t !== "mariadb" || !e.appliedIndexes.some(oe)) return e;
|
|
45
45
|
let n = { ...e.fields }, r = [], i = [];
|
|
46
46
|
for (let t of e.appliedIndexes) {
|
|
47
|
-
if (!
|
|
47
|
+
if (!oe(t)) {
|
|
48
48
|
r.push(t);
|
|
49
49
|
continue;
|
|
50
50
|
}
|
|
51
|
-
let a =
|
|
51
|
+
let a = se(t.where), o = [];
|
|
52
52
|
for (let r of t.fields) {
|
|
53
|
-
let i =
|
|
53
|
+
let i = ce(r);
|
|
54
54
|
if (!(i in e.fields)) throw Error(`@voltro/migrate: uniqueActive '${t.name}' on '${e.tableName}' references unknown column '${i}'.`);
|
|
55
|
-
let s =
|
|
55
|
+
let s = le(t.name, i);
|
|
56
56
|
o.push(s), n[s] = {
|
|
57
57
|
type: "text",
|
|
58
58
|
nullable: !0,
|
|
@@ -75,30 +75,30 @@ var re = (e, t, n, r = 400) => {
|
|
|
75
75
|
appliedIndexes: r,
|
|
76
76
|
appliedUniques: [...e.appliedUniques ?? [], ...i]
|
|
77
77
|
};
|
|
78
|
-
},
|
|
78
|
+
}, E = (e, t) => `${e}::${t}`, de = (e, t) => {
|
|
79
79
|
let n = /* @__PURE__ */ new Set(), r = /* @__PURE__ */ new Set(), i = /* @__PURE__ */ new Set(), a = (e) => {
|
|
80
80
|
n.add(e);
|
|
81
81
|
let o = [...t(e)].filter((t) => t.target !== e).sort((e, t) => e.column.localeCompare(t.column));
|
|
82
|
-
for (let t of o) n.has(t.target) ? i.add(
|
|
82
|
+
for (let t of o) n.has(t.target) ? i.add(E(e, t.column)) : r.has(t.target) || a(t.target);
|
|
83
83
|
n.delete(e), r.add(e);
|
|
84
84
|
};
|
|
85
85
|
for (let t of [...e].sort()) r.has(t) || a(t);
|
|
86
86
|
return i;
|
|
87
|
-
},
|
|
87
|
+
}, fe = 6322741009312437n, pe = (e) => {
|
|
88
88
|
let t = e?.trim();
|
|
89
89
|
return t === void 0 || t === "" || t === "public" ? void 0 : t;
|
|
90
|
-
},
|
|
91
|
-
let t =
|
|
92
|
-
for (let n of new TextEncoder().encode(e)) t ^= BigInt(n), t = t *
|
|
90
|
+
}, me = (e) => e?.schema === void 0 ? pe(process.env.DB_SCHEMA) : pe(e.schema), he = 14695981039346656037n, ge = 1099511628211n, _e = 18446744073709551615n, ve = (e) => {
|
|
91
|
+
let t = he;
|
|
92
|
+
for (let n of new TextEncoder().encode(e)) t ^= BigInt(n), t = t * ge & _e;
|
|
93
93
|
return t;
|
|
94
|
-
}, ve = (e) => {
|
|
95
|
-
let t = fe(e);
|
|
96
|
-
return t === void 0 ? de : _e(`voltro_migration_lock:${t}`) & 9223372036854775807n;
|
|
97
94
|
}, ye = (e) => {
|
|
98
|
-
let t =
|
|
95
|
+
let t = pe(e);
|
|
96
|
+
return t === void 0 ? fe : ve(`voltro_migration_lock:${t}`) & 9223372036854775807n;
|
|
97
|
+
}, D = (e) => {
|
|
98
|
+
let t = `voltro_migration_${fe.toString(36)}`, n = pe(e);
|
|
99
99
|
if (n === void 0) return t;
|
|
100
100
|
let r = `${t}_${n}`;
|
|
101
|
-
return /^[A-Za-z0-9_]+$/.test(n) && r.length <= 64 ? r : `${t}_h${(
|
|
101
|
+
return /^[A-Za-z0-9_]+$/.test(n) && r.length <= 64 ? r : `${t}_h${(ve(`voltro_migration_lock:${n}`) & _e).toString(16)}`;
|
|
102
102
|
}, be = 250, xe = () => {
|
|
103
103
|
let e = Number(process.env.VOLTRO_MIGRATION_LOCK_TIMEOUT_MS);
|
|
104
104
|
return Number.isFinite(e) && e > 0 ? e : 3e4;
|
|
@@ -126,20 +126,20 @@ var re = (e, t, n, r = 400) => {
|
|
|
126
126
|
}), ke = (e, t) => S.gen(function* () {
|
|
127
127
|
yield* e`EXEC sp_releaseapplock @Resource = ${t}, @LockOwner = 'Session'`;
|
|
128
128
|
}), Ae = S.void, je = (e, t) => {
|
|
129
|
-
let n =
|
|
129
|
+
let n = me(t);
|
|
130
130
|
return e.onDialectOrElse({
|
|
131
|
-
mysql: () => Te(e,
|
|
132
|
-
mssql: () => Oe(e,
|
|
131
|
+
mysql: () => Te(e, D(n)),
|
|
132
|
+
mssql: () => Oe(e, D(n)),
|
|
133
133
|
sqlite: () => Ae,
|
|
134
|
-
orElse: () => Se(e,
|
|
134
|
+
orElse: () => Se(e, ye(n))
|
|
135
135
|
});
|
|
136
136
|
}, O = (e, t) => {
|
|
137
|
-
let n =
|
|
137
|
+
let n = me(t);
|
|
138
138
|
return e.onDialectOrElse({
|
|
139
|
-
mysql: () => Ee(e,
|
|
140
|
-
mssql: () => ke(e,
|
|
139
|
+
mysql: () => Ee(e, D(n)),
|
|
140
|
+
mssql: () => ke(e, D(n)),
|
|
141
141
|
sqlite: () => Ae,
|
|
142
|
-
orElse: () => Ce(e,
|
|
142
|
+
orElse: () => Ce(e, ye(n))
|
|
143
143
|
});
|
|
144
144
|
}, Me = (e, t, n) => S.acquireUseRelease(je(e, n), () => t, () => O(e, n).pipe(S.orDie)), Ne = (e) => e.onDialectOrElse({
|
|
145
145
|
pg: () => "postgres",
|
|
@@ -217,8 +217,13 @@ var re = (e, t, n, r = 400) => {
|
|
|
217
217
|
Object.keys(Pe);
|
|
218
218
|
//#endregion
|
|
219
219
|
//#region src/migrations/reactiveTriggerName.ts
|
|
220
|
-
var A = "framework_changes", qe = "framework_changes_", Je = (e, t) => t === "framework_changes" ? `${qe}${e}` : `${qe}${t}_${e}`, Ye = (e) => e === "framework_changes" ? "framework_notify_change" : `framework_notify_change_${e}`, Xe = "voltro:notify:v2", Ze =
|
|
221
|
-
|
|
220
|
+
var A = "framework_changes", qe = "framework_changes_", Je = (e, t) => t === "framework_changes" ? `${qe}${e}` : `${qe}${t}_${e}`, Ye = (e) => e === "framework_changes" ? "framework_notify_change" : `framework_notify_change_${e}`, Xe = "voltro:notify:v2", Ze = (e, t) => {
|
|
221
|
+
if (e.type === "text" && e.generatedAs === void 0) {
|
|
222
|
+
if (e.maxLength !== void 0) return e.maxLength;
|
|
223
|
+
if (t || e.hasDefault && e.defaultFactory === void 0 || e.oneOf !== void 0 && e.oneOf.length > 0) return 450;
|
|
224
|
+
}
|
|
225
|
+
}, Qe = w({ scope: "voltro:migrate" }), j = (e) => {
|
|
226
|
+
Qe.warn(e.replace(/^\[voltro:migrate\]\s*/, ""));
|
|
222
227
|
}, M = (e, t) => {
|
|
223
228
|
let n = e.type;
|
|
224
229
|
if (e.spatial) {
|
|
@@ -300,7 +305,10 @@ var A = "framework_changes", qe = "framework_changes_", Je = (e, t) => t === "fr
|
|
|
300
305
|
}
|
|
301
306
|
if (t === "mssql") switch (n) {
|
|
302
307
|
case "id": return "NVARCHAR(64)";
|
|
303
|
-
case "text":
|
|
308
|
+
case "text": {
|
|
309
|
+
let t = Ze(e, !1);
|
|
310
|
+
return t === void 0 ? "NVARCHAR(MAX)" : `NVARCHAR(${t})`;
|
|
311
|
+
}
|
|
304
312
|
case "integer": return "INT";
|
|
305
313
|
case "real": return "FLOAT";
|
|
306
314
|
case "boolean": return "BIT";
|
|
@@ -330,11 +338,11 @@ var A = "framework_changes", qe = "framework_changes_", Je = (e, t) => t === "fr
|
|
|
330
338
|
case "array": return "TEXT[]";
|
|
331
339
|
case "interval": return "INTERVAL";
|
|
332
340
|
}
|
|
333
|
-
},
|
|
341
|
+
}, $e = (e, t) => {
|
|
334
342
|
if (!e.hasDefault || e.defaultFactory !== void 0) return null;
|
|
335
343
|
let n = e.defaultValue;
|
|
336
|
-
return n === "now" ? l(t) ? "DEFAULT CURRENT_TIMESTAMP" : t === "mssql" ? "DEFAULT SYSUTCDATETIME()" : t === "mysql" || t === "mariadb" ? "DEFAULT CURRENT_TIMESTAMP(6)" : "DEFAULT now()" : typeof n == "boolean" ? t === "postgres" ? `DEFAULT ${n}` : `DEFAULT ${+!!n}` : typeof n == "number" ? `DEFAULT ${n}` : typeof n == "string" ? `DEFAULT '${n.replace(/'/g, "''")}'` : Array.isArray(n) ?
|
|
337
|
-
},
|
|
344
|
+
return n === "now" ? l(t) ? "DEFAULT CURRENT_TIMESTAMP" : t === "mssql" ? "DEFAULT SYSUTCDATETIME()" : t === "mysql" || t === "mariadb" ? "DEFAULT CURRENT_TIMESTAMP(6)" : "DEFAULT now()" : typeof n == "boolean" ? t === "postgres" ? `DEFAULT ${n}` : `DEFAULT ${+!!n}` : typeof n == "number" ? `DEFAULT ${n}` : typeof n == "string" ? `DEFAULT '${n.replace(/'/g, "''")}'` : Array.isArray(n) ? et(n, e, t) : typeof n == "object" && n ? N(n, t) : null;
|
|
345
|
+
}, et = (e, t, n) => {
|
|
338
346
|
if (n !== "postgres" || t.type !== "array" || t.arrayElement === void 0) return N(e, n);
|
|
339
347
|
let r = M({
|
|
340
348
|
...t,
|
|
@@ -362,18 +370,18 @@ var A = "framework_changes", qe = "framework_changes_", Je = (e, t) => t === "fr
|
|
|
362
370
|
case "setNull": return "SET NULL";
|
|
363
371
|
case "noAction": return "NO ACTION";
|
|
364
372
|
}
|
|
365
|
-
},
|
|
373
|
+
}, tt = (e, t, n) => n === null ? _(e, t) : `${_(n, t)}.${_(e, t)}`, nt = 191, rt = (e, t) => {
|
|
366
374
|
if (!e || t !== "mysql" && t !== "mariadb") return !1;
|
|
367
375
|
let n = M(e, t).toUpperCase();
|
|
368
376
|
return n.endsWith("TEXT") || n.endsWith("BLOB");
|
|
369
|
-
},
|
|
377
|
+
}, it = (e, t, n) => {
|
|
370
378
|
let r = _(e, n);
|
|
371
379
|
if (n !== "mysql" && n !== "mariadb") return r;
|
|
372
380
|
let i = t[e];
|
|
373
381
|
if (!i) return r;
|
|
374
382
|
let a = M(i, n).toUpperCase();
|
|
375
|
-
return a.endsWith("TEXT") || a.endsWith("BLOB") ? `${r}(${
|
|
376
|
-
},
|
|
383
|
+
return a.endsWith("TEXT") || a.endsWith("BLOB") ? `${r}(${nt})` : r;
|
|
384
|
+
}, at = (e, t) => {
|
|
377
385
|
if (!e.generatedAs) return null;
|
|
378
386
|
let { expr: n, stored: r } = e.generatedAs;
|
|
379
387
|
if (t === "postgres") return r || j("[voltro:migrate] generated column requested as VIRTUAL but postgres only supports STORED — promoting"), `GENERATED ALWAYS AS (${n}) STORED`;
|
|
@@ -381,56 +389,57 @@ var A = "framework_changes", qe = "framework_changes_", Je = (e, t) => t === "fr
|
|
|
381
389
|
if (t === "mssql") return `AS (${n})${r ? " PERSISTED" : ""}`;
|
|
382
390
|
if (t === "turso") throw Error("@voltro/sql-turso: generated columns (.generatedAs(...)) are not supported — Turso's MVCC mode (journal_mode=experimental_mvcc) rejects them. Drop the generated column, or use the 'sqlite' / 'postgres' dialect for this table.");
|
|
383
391
|
return `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
|
|
384
|
-
},
|
|
392
|
+
}, ot = (t, n, r, i, a = !1, o = !1) => {
|
|
385
393
|
if (n.type === "id" && n.idScheme?.kind === "numeric") return P(t, r);
|
|
386
|
-
let s = r === "mssql"
|
|
387
|
-
n.type === "id" && !o &&
|
|
388
|
-
let
|
|
389
|
-
if (
|
|
394
|
+
let s = r === "mssql" ? Ze(n, i?.has(t) ?? !1) : void 0, c = s === void 0 ? M(n, r) : `NVARCHAR(${s})`, u = [_(t, r), c];
|
|
395
|
+
n.type === "id" && !o && u.push("PRIMARY KEY");
|
|
396
|
+
let d = at(n, r);
|
|
397
|
+
if (d) u.push(d);
|
|
390
398
|
else {
|
|
391
|
-
n.nullable ||
|
|
392
|
-
let e =
|
|
393
|
-
e &&
|
|
399
|
+
n.nullable || u.push("NOT NULL"), n.unique && n.type !== "id" && !rt(n, r) && u.push("UNIQUE");
|
|
400
|
+
let e = $e(n, r);
|
|
401
|
+
e && u.push(e);
|
|
394
402
|
}
|
|
395
403
|
if (n.type === "reference" && n.references && !a && !e(r)) {
|
|
396
404
|
let e = n.references();
|
|
397
|
-
|
|
405
|
+
u.push(`REFERENCES ${_(e.tableName, r)} (${_("id", r)})`);
|
|
398
406
|
let t = F(n.onDelete ?? "restrict", r);
|
|
399
|
-
|
|
407
|
+
u.push(`ON DELETE ${t}`);
|
|
400
408
|
let i = F(n.refOnUpdate ?? "noAction", r);
|
|
401
|
-
i !== "NO ACTION" &&
|
|
409
|
+
i !== "NO ACTION" && u.push(`ON UPDATE ${i}`);
|
|
402
410
|
}
|
|
403
411
|
if (n.oneOf && n.oneOf.length > 0) {
|
|
404
412
|
let e = n.oneOf.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
|
|
405
|
-
|
|
413
|
+
u.push(`CHECK (${_(t, r)} IN (${e}))`);
|
|
406
414
|
}
|
|
407
|
-
if (n.checks && n.checks.length > 0) for (let e of n.checks)
|
|
415
|
+
if (n.checks && n.checks.length > 0) for (let e of n.checks) u.push(`CHECK (${e})`);
|
|
408
416
|
if (n.type === "enum" && n.enumValues && n.enumValues.length > 0 && (r === "mssql" || l(r))) {
|
|
409
417
|
let e = n.enumValues.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
|
|
410
|
-
|
|
418
|
+
u.push(`CHECK (${_(t, r)} IN (${e}))`);
|
|
411
419
|
}
|
|
412
420
|
if (n.type === "json" || n.type === "array") {
|
|
413
421
|
let e = _(t, r);
|
|
414
|
-
l(r) ?
|
|
422
|
+
l(r) ? u.push(`CHECK (${e} IS NULL OR json_valid(${e}))`) : r === "mssql" && u.push(`CHECK (${e} IS NULL OR ISJSON(${e}) = 1)`);
|
|
415
423
|
}
|
|
416
|
-
return
|
|
417
|
-
},
|
|
424
|
+
return u.join(" ");
|
|
425
|
+
}, st = (t, n, r = null, i) => {
|
|
418
426
|
let a = /* @__PURE__ */ new Set();
|
|
419
427
|
for (let e of t.appliedIndexes ?? []) for (let t of e.fields) typeof t == "string" && a.add(t);
|
|
420
428
|
for (let e of t.appliedUniques ?? []) for (let t of e.fields) typeof t == "string" && a.add(t);
|
|
421
|
-
let
|
|
422
|
-
|
|
429
|
+
for (let [e, n] of Object.entries(t.fields)) n.unique && a.add(e);
|
|
430
|
+
let o = t.appliedPrimaryKey ?? [], s = o.length > 0, c = Object.entries(t.fields).map(([e, t]) => ` ${ot(e, t, n, a, i?.has(e) ?? !1, s)}`).join(",\n"), l = (t.appliedUniques ?? []).map((e) => {
|
|
431
|
+
let r = e.fields.map((e) => it(e, t.fields, n)).join(", ");
|
|
423
432
|
return ` CONSTRAINT ${_(e.name, n)} UNIQUE (${r})`;
|
|
424
|
-
}), u = (t.appliedChecks ?? []).map((e) => ` CONSTRAINT ${_(e.name, n)} CHECK (${e.expr})`), d = s ? [` PRIMARY KEY (${o.map((e) =>
|
|
433
|
+
}), u = (t.appliedChecks ?? []).map((e) => ` CONSTRAINT ${_(e.name, n)} CHECK (${e.expr})`), d = s ? [` PRIMARY KEY (${o.map((e) => it(e, t.fields, n)).join(", ")})`] : [], f = e(n) ? Object.entries(t.fields).flatMap(([e, a]) => {
|
|
425
434
|
if (a.type !== "reference" || !a.references || (i?.has(e) ?? !1)) return [];
|
|
426
435
|
let o = a.references(), s = F(a.onDelete ?? "restrict", n), c = F(a.refOnUpdate ?? "noAction", n);
|
|
427
|
-
return [` CONSTRAINT ${_(`${t.tableName}_${e}_fkey`, n)} FOREIGN KEY (${_(e, n)}) REFERENCES ${
|
|
436
|
+
return [` CONSTRAINT ${_(`${t.tableName}_${e}_fkey`, n)} FOREIGN KEY (${_(e, n)}) REFERENCES ${tt(o.tableName, n, r)} (${_("id", n)}) ON DELETE ${s}${c === "NO ACTION" ? "" : ` ON UPDATE ${c}`}`];
|
|
428
437
|
}) : [], p = [
|
|
429
438
|
...d,
|
|
430
439
|
...l,
|
|
431
440
|
...u,
|
|
432
441
|
...f
|
|
433
|
-
], m = p.length > 0 ? `${c},\n${p.join(",\n")}` : c, h =
|
|
442
|
+
], m = p.length > 0 ? `${c},\n${p.join(",\n")}` : c, h = tt(t.tableName, n, r);
|
|
434
443
|
if (n === "mssql") {
|
|
435
444
|
let e = r === null ? t.tableName : `${r}.${t.tableName}`, n = `CREATE TABLE ${h} (\n${m}\n)`;
|
|
436
445
|
return `IF OBJECT_ID('${e.replace(/'/g, "''")}', 'U') IS NULL EXEC(N'${n.replace(/'/g, "''")}');`;
|
|
@@ -440,10 +449,10 @@ var A = "framework_changes", qe = "framework_changes_", Je = (e, t) => t === "fr
|
|
|
440
449
|
m,
|
|
441
450
|
");"
|
|
442
451
|
].join("\n");
|
|
443
|
-
},
|
|
452
|
+
}, ct = (e, t, n) => {
|
|
444
453
|
let r = `${e}_${t.name}_fts`, i = (e) => _(e, n), a = t.columns.map(i).join(", "), o = t.columns.map((e) => `new.${i(e)}`).join(", "), s = [];
|
|
445
454
|
return s.push(`CREATE VIRTUAL TABLE IF NOT EXISTS ${i(r)} USING fts5(${a}, row_id UNINDEXED, tokenize='porter');`), s.push(`CREATE TRIGGER IF NOT EXISTS ${i(`${r}_ai`)} AFTER INSERT ON ${i(e)} BEGIN\n INSERT INTO ${i(r)} (${a}, row_id) VALUES (${o}, new.${i("id")});\nEND;`), s.push(`CREATE TRIGGER IF NOT EXISTS ${i(`${r}_ad`)} AFTER DELETE ON ${i(e)} BEGIN\n DELETE FROM ${i(r)} WHERE row_id = old.${i("id")};\nEND;`), s.push(`CREATE TRIGGER IF NOT EXISTS ${i(`${r}_au`)} AFTER UPDATE ON ${i(e)} BEGIN\n DELETE FROM ${i(r)} WHERE row_id = old.${i("id")};\n INSERT INTO ${i(r)} (${a}, row_id) VALUES (${o}, new.${i("id")});\nEND;`), s;
|
|
446
|
-
},
|
|
455
|
+
}, lt = (e, t, n = null) => {
|
|
447
456
|
let r = [], i = /* @__PURE__ */ new Set(), o = (e) => e.join("\0"), s = (e, n, r, i) => {
|
|
448
457
|
let o = {
|
|
449
458
|
using: "",
|
|
@@ -489,7 +498,7 @@ var A = "framework_changes", qe = "framework_changes_", Je = (e, t) => t === "fr
|
|
|
489
498
|
return o;
|
|
490
499
|
}, c = (n, r) => {
|
|
491
500
|
let i = n.map((n) => {
|
|
492
|
-
if (typeof n == "string") return
|
|
501
|
+
if (typeof n == "string") return it(n, e.fields, t);
|
|
493
502
|
if ("jsonPath" in n) {
|
|
494
503
|
let { column: e, path: r, numeric: i } = n.jsonPath;
|
|
495
504
|
return `(${d(e, r, t, { numeric: i })})`;
|
|
@@ -500,11 +509,11 @@ var A = "framework_changes", qe = "framework_changes_", Je = (e, t) => t === "fr
|
|
|
500
509
|
}, l = (e, r, i, a, o, l = "", u = !1) => {
|
|
501
510
|
let d = s(e, r, a, o);
|
|
502
511
|
if (d.skip) return "";
|
|
503
|
-
let f = c(i, d.opclass), p = `${d.withSuffix}${l}`, m =
|
|
512
|
+
let f = c(i, d.opclass), p = `${d.withSuffix}${l}`, m = tt(r, t, n), h = u ? "UNIQUE " : "";
|
|
504
513
|
return t === "mssql" ? `IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = '${e}') CREATE ${h}INDEX ${_(e, t)} ON ${m}${d.using} (${f})${p};` : t === "mysql" ? `CREATE ${h}INDEX ${_(e, t)} ON ${m}${d.using} (${f})${p};` : `CREATE ${h}INDEX IF NOT EXISTS ${_(e, t)} ON ${m}${d.using} (${f})${p};`;
|
|
505
514
|
};
|
|
506
515
|
if (t === "mysql" || t === "mariadb") for (let [n, i] of Object.entries(e.fields)) {
|
|
507
|
-
if (!i.unique || i.type === "id" || !
|
|
516
|
+
if (!i.unique || i.type === "id" || !rt(i, t)) continue;
|
|
508
517
|
let a = l(`${e.tableName}_${n}_key`, e.tableName, [n], void 0, void 0, "", !0);
|
|
509
518
|
a && r.push(a);
|
|
510
519
|
}
|
|
@@ -518,7 +527,7 @@ var A = "framework_changes", qe = "framework_changes_", Je = (e, t) => t === "fr
|
|
|
518
527
|
let i = n.columns.map((e) => _(e, t)).join(", ");
|
|
519
528
|
r.push(`CREATE FULLTEXT INDEX ${_(n.name, t)} ON ${_(e.tableName, t)} (${i});`);
|
|
520
529
|
} else if (t === "turso") throw Error(`@voltro/sql-turso: full-text index '${n.name}' on '${e.tableName}' is not supported — Turso's MVCC mode has no FTS5 virtual tables. Drop .fullTextIndex(), or use the 'sqlite' / 'postgres' dialect for this table.`);
|
|
521
|
-
else t === "sqlite" ? r.push(...
|
|
530
|
+
else t === "sqlite" ? r.push(...ct(e.tableName, n, t)) : j(`[voltro:migrate] full-text index '${n.name}' on '${e.tableName}': ${t} uses a ranked LIKE search at query time (no native FTS catalog required).`);
|
|
522
531
|
for (let n of e.appliedIndexes) {
|
|
523
532
|
if ((t === "mariadb" || t === "mssql") && n.fields.some((e) => typeof e != "string" && "jsonPath" in e)) {
|
|
524
533
|
j(`[voltro:migrate] json-path index '${n.name}' on '${e.tableName}': ${t} cannot index a JSON expression directly — skipping. For an indexed JSON path on ${t}, add a generated column for the path (text().generatedAs(...) / .stored()) and .index([...]) it, then filter on that column instead of jsonField(...).`);
|
|
@@ -536,11 +545,11 @@ var A = "framework_changes", qe = "framework_changes_", Je = (e, t) => t === "fr
|
|
|
536
545
|
r.push(l(a, e.tableName, [t])), i.add(o([t]));
|
|
537
546
|
}
|
|
538
547
|
return r.join("\n");
|
|
539
|
-
},
|
|
548
|
+
}, ut = (e, t, n = A) => {
|
|
540
549
|
if (t !== "postgres") return [];
|
|
541
550
|
let r = e.filter((e) => e.isReactive !== !1);
|
|
542
|
-
return r.length === 0 ? [] : [
|
|
543
|
-
},
|
|
551
|
+
return r.length === 0 ? [] : [dt(n), ...r.map((e) => pt(e, n))];
|
|
552
|
+
}, dt = (e) => `
|
|
544
553
|
CREATE OR REPLACE FUNCTION ${Ye(e)}() RETURNS trigger AS $$
|
|
545
554
|
DECLARE
|
|
546
555
|
payload TEXT;
|
|
@@ -600,22 +609,22 @@ BEGIN
|
|
|
600
609
|
RETURN COALESCE(NEW, OLD);
|
|
601
610
|
END;
|
|
602
611
|
$$ LANGUAGE plpgsql;
|
|
603
|
-
`.trim(),
|
|
612
|
+
`.trim(), ft = (e, t) => {
|
|
604
613
|
let n = Je(e.tableName, t);
|
|
605
614
|
return [
|
|
606
615
|
`ALTER TABLE "${e.tableName}" REPLICA IDENTITY FULL`,
|
|
607
616
|
`DROP TRIGGER IF EXISTS ${n} ON "${e.tableName}"`,
|
|
608
617
|
`CREATE TRIGGER ${n}\nAFTER INSERT OR UPDATE OR DELETE ON "${e.tableName}"\nFOR EACH ROW EXECUTE FUNCTION ${Ye(t)}()`
|
|
609
618
|
];
|
|
610
|
-
},
|
|
619
|
+
}, pt = (e, t) => ft(e, t).map((e) => `${e};`).join("\n"), mt = (e) => {
|
|
611
620
|
if (e.dialect !== "postgres") return [];
|
|
612
621
|
let t = e.channel ?? "framework_changes", n = new Map(e.tables.map((e) => [e.tableName, e])), r = [], i = e.missing.filter((e) => n.has(e));
|
|
613
|
-
(i.length > 0 || e.functionOutdated === !0) && r.push(
|
|
614
|
-
for (let e of i) r.push(...
|
|
622
|
+
(i.length > 0 || e.functionOutdated === !0) && r.push(dt(t));
|
|
623
|
+
for (let e of i) r.push(...ft(n.get(e), t));
|
|
615
624
|
for (let n of e.stale) r.push(`DROP TRIGGER IF EXISTS ${Je(n, t)} ON "${n}"`), r.push(`ALTER TABLE "${n}" REPLICA IDENTITY DEFAULT`);
|
|
616
625
|
return r;
|
|
617
|
-
},
|
|
618
|
-
let t = new Map(e.map((e) => [e.tableName, e])), n =
|
|
626
|
+
}, ht = (e) => e.some((e) => Object.values(e.fields).some((e) => e.type === "vector")), gt = (e) => e.some((e) => Object.values(e.fields).some((e) => e.spatial !== void 0)), _t = (e) => {
|
|
627
|
+
let t = new Map(e.map((e) => [e.tableName, e])), n = de(e.map((e) => e.tableName), (e) => {
|
|
619
628
|
let n = t.get(e);
|
|
620
629
|
return n ? Object.entries(n.fields).flatMap(([e, n]) => {
|
|
621
630
|
if (n.type !== "reference" || !n.references) return [];
|
|
@@ -626,7 +635,7 @@ $$ LANGUAGE plpgsql;
|
|
|
626
635
|
}] : [];
|
|
627
636
|
}) : [];
|
|
628
637
|
}), r = [];
|
|
629
|
-
for (let t of e) for (let [e, i] of Object.entries(t.fields)) i.type !== "reference" || !i.references || n.has(
|
|
638
|
+
for (let t of e) for (let [e, i] of Object.entries(t.fields)) i.type !== "reference" || !i.references || n.has(E(t.tableName, e)) && r.push({
|
|
630
639
|
table: t.tableName,
|
|
631
640
|
column: e,
|
|
632
641
|
targetTable: i.references().tableName,
|
|
@@ -637,7 +646,7 @@ $$ LANGUAGE plpgsql;
|
|
|
637
646
|
if (!(i.has(e.tableName) || a.has(e.tableName))) {
|
|
638
647
|
a.add(e.tableName);
|
|
639
648
|
for (let [r, i] of Object.entries(e.fields)) {
|
|
640
|
-
if (i.type !== "reference" || !i.references || n.has(
|
|
649
|
+
if (i.type !== "reference" || !i.references || n.has(E(e.tableName, r))) continue;
|
|
641
650
|
let a = i.references();
|
|
642
651
|
if (a.tableName === e.tableName) continue;
|
|
643
652
|
let o = t.get(a.tableName);
|
|
@@ -651,7 +660,7 @@ $$ LANGUAGE plpgsql;
|
|
|
651
660
|
sorted: o,
|
|
652
661
|
cyclic: r
|
|
653
662
|
};
|
|
654
|
-
},
|
|
663
|
+
}, vt = (e, t, n = null) => {
|
|
655
664
|
let r = (e) => n ? `${_(n, t)}.${_(e, t)}` : _(e, t), i = `${e.table}_${e.column}_fkey`, a = F(e.onDelete, t), o = F(e.onUpdate, t), s = ` ON DELETE ${a}${o === "NO ACTION" ? "" : ` ON UPDATE ${o}`}`, c = (n) => `ADD CONSTRAINT ${_(i, t)} FOREIGN KEY ${n ? "IF NOT EXISTS " : ""}(${_(e.column, t)}) REFERENCES ${r(e.targetTable)} (${_("id", t)})${s}`;
|
|
656
665
|
switch (t) {
|
|
657
666
|
case "postgres": return [
|
|
@@ -666,7 +675,7 @@ $$ LANGUAGE plpgsql;
|
|
|
666
675
|
case "mariadb": return `ALTER TABLE ${r(e.table)} ${c(!0)};`;
|
|
667
676
|
default: return `ALTER TABLE ${r(e.table)} ${c(!1)};`;
|
|
668
677
|
}
|
|
669
|
-
},
|
|
678
|
+
}, yt = (e, t) => {
|
|
670
679
|
let n = /* @__PURE__ */ new Map();
|
|
671
680
|
if (l(t)) return n;
|
|
672
681
|
for (let t of e) {
|
|
@@ -674,7 +683,7 @@ $$ LANGUAGE plpgsql;
|
|
|
674
683
|
e.add(t.column), n.set(t.table, e);
|
|
675
684
|
}
|
|
676
685
|
return n;
|
|
677
|
-
},
|
|
686
|
+
}, bt = (e, t) => {
|
|
678
687
|
if (t !== "postgres") return "";
|
|
679
688
|
let n = /* @__PURE__ */ new Map();
|
|
680
689
|
for (let t of e) for (let e of Object.values(t.fields)) {
|
|
@@ -690,7 +699,7 @@ $$ LANGUAGE plpgsql;
|
|
|
690
699
|
r.push(`DO $$ BEGIN\n IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = '${e.replace(/'/g, "''")}') THEN\n CREATE TYPE "${e}" AS ENUM (${n});\n END IF;\nEND $$;`);
|
|
691
700
|
}
|
|
692
701
|
return r.join("\n\n");
|
|
693
|
-
},
|
|
702
|
+
}, xt = (e, t) => {
|
|
694
703
|
if (t !== "postgres") return "";
|
|
695
704
|
let n = /* @__PURE__ */ new Set();
|
|
696
705
|
for (let t of e) for (let e of Object.values(t.fields)) e.type === "enum" && e.enumName && n.add(e.enumName);
|
|
@@ -704,30 +713,30 @@ BEGIN
|
|
|
704
713
|
SELECT oid INTO type_oid FROM pg_type WHERE typname = '${i}';\n IF type_oid IS NOT NULL\n AND EXISTS (SELECT 1 FROM pg_enum WHERE enumtypid = type_oid AND enumlabel = '${a}')\n AND NOT EXISTS (SELECT 1 FROM pg_enum WHERE enumtypid = type_oid AND enumlabel = '${o}') THEN\n IF current_setting('server_version_num')::int >= 140000 THEN\n EXECUTE format('ALTER TYPE %I RENAME VALUE %L TO %L', '${i}', '${a}', '${o}');\n ELSE\n UPDATE pg_enum SET enumlabel = '${o}' WHERE enumtypid = type_oid AND enumlabel = '${a}';\n END IF;\n END IF;\nEND $$;`);
|
|
705
714
|
}
|
|
706
715
|
return r.join("\n\n");
|
|
707
|
-
},
|
|
716
|
+
}, St = (e) => {
|
|
708
717
|
let t = [], n = [];
|
|
709
718
|
for (let r of e) u(r) ? n.push(r) : t.push(r);
|
|
710
719
|
return {
|
|
711
720
|
tables: t,
|
|
712
721
|
views: n
|
|
713
722
|
};
|
|
714
|
-
},
|
|
715
|
-
let { tables: r, views: i } =
|
|
716
|
-
t === "postgres" &&
|
|
717
|
-
let u =
|
|
723
|
+
}, Ct = (e, t, n = A) => {
|
|
724
|
+
let { tables: r, views: i } = St(e), { sorted: a, cyclic: o } = _t(r.map((e) => ue(e, t))), s = yt(o, t), c = [];
|
|
725
|
+
t === "postgres" && ht(a) && c.push("CREATE EXTENSION IF NOT EXISTS vector;"), t === "postgres" && gt(a) && c.push("CREATE EXTENSION IF NOT EXISTS postgis;");
|
|
726
|
+
let u = xt(a, t);
|
|
718
727
|
u && c.push(u);
|
|
719
|
-
let d =
|
|
728
|
+
let d = bt(a, t);
|
|
720
729
|
d && c.push(d);
|
|
721
|
-
for (let e of a) c.push(
|
|
722
|
-
if (!l(t)) for (let e of o) c.push(
|
|
730
|
+
for (let e of a) c.push(st(e, t, null, s.get(e.tableName)));
|
|
731
|
+
if (!l(t)) for (let e of o) c.push(vt(e, t));
|
|
723
732
|
for (let e of a) {
|
|
724
|
-
let n =
|
|
733
|
+
let n = lt(e, t);
|
|
725
734
|
n && c.push(n);
|
|
726
735
|
}
|
|
727
|
-
c.push(...
|
|
736
|
+
c.push(...ut(a, t, n));
|
|
728
737
|
for (let e of i) c.push(x(e, t));
|
|
729
738
|
return c.join("\n\n") + "\n";
|
|
730
|
-
},
|
|
739
|
+
}, wt = (e, t, n) => {
|
|
731
740
|
let r = _(e, t);
|
|
732
741
|
switch (t) {
|
|
733
742
|
case "postgres": return `CREATE SCHEMA IF NOT EXISTS ${r};`;
|
|
@@ -737,62 +746,62 @@ BEGIN
|
|
|
737
746
|
case "turso":
|
|
738
747
|
case "sqlite": return `ATTACH DATABASE '${(n ?? `${e}.db`).replace(/'/g, "''")}' AS ${r};`;
|
|
739
748
|
}
|
|
740
|
-
},
|
|
741
|
-
let i =
|
|
742
|
-
if (t === "postgres") return `${i}\n\nSET search_path TO ${a};\n\n${
|
|
743
|
-
if (t === "mysql" || t === "mariadb") return `${i}\n\nUSE ${a};\n\n${
|
|
744
|
-
let { sorted: o, cyclic: s } =
|
|
745
|
-
for (let e of o) u.push(
|
|
746
|
-
if (!l(t)) for (let e of s) u.push(
|
|
749
|
+
}, Tt = (e, t, n, r) => {
|
|
750
|
+
let i = wt(n, t, r), a = _(n, t);
|
|
751
|
+
if (t === "postgres") return `${i}\n\nSET search_path TO ${a};\n\n${Ct(e, t)}`;
|
|
752
|
+
if (t === "mysql" || t === "mariadb") return `${i}\n\nUSE ${a};\n\n${Ct(e, t)}`;
|
|
753
|
+
let { sorted: o, cyclic: s } = _t(e), c = yt(s, t), u = [i];
|
|
754
|
+
for (let e of o) u.push(st(e, t, n, c.get(e.tableName)));
|
|
755
|
+
if (!l(t)) for (let e of s) u.push(vt(e, t, n));
|
|
747
756
|
for (let e of o) {
|
|
748
|
-
let r =
|
|
757
|
+
let r = lt(e, t, n);
|
|
749
758
|
r && u.push(r);
|
|
750
759
|
}
|
|
751
760
|
return u.join("\n\n") + "\n";
|
|
752
|
-
},
|
|
753
|
-
let { sorted: r, cyclic: i } =
|
|
761
|
+
}, Et = (e, t, n = A) => {
|
|
762
|
+
let { sorted: r, cyclic: i } = _t(e), a = yt(i, t), o = [], s = xt(r, t);
|
|
754
763
|
s && o.push(s);
|
|
755
|
-
let c =
|
|
764
|
+
let c = bt(r, t);
|
|
756
765
|
c && o.push(c);
|
|
757
|
-
for (let e of r) o.push(
|
|
758
|
-
for (let e of i) o.push(
|
|
759
|
-
return o.push(...
|
|
760
|
-
},
|
|
761
|
-
let i = yield*
|
|
762
|
-
yield* Me(i,
|
|
763
|
-
}),
|
|
766
|
+
for (let e of r) o.push(st(e, t, null, a.get(e.tableName)));
|
|
767
|
+
for (let e of i) o.push(vt(e, t));
|
|
768
|
+
return o.push(...ut(r, t, n)), o.join("\n\n") + "\n";
|
|
769
|
+
}, Dt = (e, t = "postgres", n = A, r = {}) => S.gen(function* () {
|
|
770
|
+
let i = yield* T.SqlClient;
|
|
771
|
+
yield* Me(i, Pt(i, Ct(e, t, n), t, r.retryFilter), { schema: r.lockSchema }).pipe(S.orDie);
|
|
772
|
+
}), Ot = (e, t) => {
|
|
764
773
|
let n = t.cause ?? {};
|
|
765
774
|
return (n.errno === 1061 || n.code === "ER_DUP_KEYNAME") && /^\s*CREATE\s+(UNIQUE\s+|FULLTEXT\s+)?INDEX\b/i.test(e);
|
|
766
|
-
},
|
|
775
|
+
}, kt = (e, t) => {
|
|
767
776
|
let n = e.trimStart();
|
|
768
777
|
return !!(/\bIF NOT EXISTS\b/i.test(n) || /^CREATE OR REPLACE\b/i.test(n) || /^DROP\s[\s\S]*?\bIF EXISTS\b/i.test(n) || /^SET search_path\b/i.test(n) || /^USE[\s`"[]/i.test(n) || /^IF\s/i.test(n) || (t === "mysql" || t === "mariadb") && /^CREATE\s+(UNIQUE\s+|FULLTEXT\s+)?INDEX\b/i.test(n));
|
|
769
|
-
},
|
|
778
|
+
}, At = () => {
|
|
770
779
|
let e = Number(process.env.VOLTRO_MIGRATION_DDL_RETRIES);
|
|
771
780
|
return Number.isInteger(e) && e >= 0 ? e : 4;
|
|
772
|
-
},
|
|
781
|
+
}, jt = (e) => ({
|
|
773
782
|
while: e,
|
|
774
|
-
times:
|
|
783
|
+
times: At(),
|
|
775
784
|
schedule: C.jittered(C.exponential("50 millis"))
|
|
776
|
-
}),
|
|
785
|
+
}), Mt = class {
|
|
777
786
|
statement;
|
|
778
787
|
error;
|
|
779
788
|
_tag = "DdlStatementFailed";
|
|
780
789
|
constructor(e, t) {
|
|
781
790
|
this.statement = e, this.error = t;
|
|
782
791
|
}
|
|
783
|
-
},
|
|
784
|
-
let r = yield*
|
|
785
|
-
for (let a of
|
|
786
|
-
process.env.VOLTRO_MIGRATE_DEBUG === "1" &&
|
|
787
|
-
let e = r.unsafe(a).pipe(S.catchIf((e) =>
|
|
788
|
-
|
|
792
|
+
}, Nt = (e, t, n) => S.gen(function* () {
|
|
793
|
+
let r = yield* T.SqlClient, i = n !== void 0 && Fe(t) === "per-operation";
|
|
794
|
+
for (let a of Ft(e)) {
|
|
795
|
+
process.env.VOLTRO_MIGRATE_DEBUG === "1" && Qe.debug(`EXEC: ${a.replace(/\s+/g, " ").slice(0, 180)}`);
|
|
796
|
+
let e = r.unsafe(a).pipe(S.catchIf((e) => Ot(a, e), () => S.succeed([])), S.tapError((e) => S.sync(() => {
|
|
797
|
+
Qe.error(ie("migrate: statement failed", a, e, 200));
|
|
789
798
|
})));
|
|
790
|
-
yield* (i && n !== void 0 &&
|
|
799
|
+
yield* (i && n !== void 0 && kt(a, t) ? e.pipe(S.retry(jt((e) => n(e) === "retry"))) : e).pipe(S.mapError((e) => new Mt(a, e)));
|
|
791
800
|
}
|
|
792
|
-
}),
|
|
793
|
-
let i = n === "turso" ?
|
|
794
|
-
return (r !== void 0 && Fe(n) === "plan-transactional" ? i.pipe(S.retry(
|
|
795
|
-
},
|
|
801
|
+
}), Pt = (e, t, n, r) => {
|
|
802
|
+
let i = n === "turso" ? Nt(t, n, r) : e.withTransaction(Nt(t, n, r)), a = (e) => e instanceof Mt ? e.error : e;
|
|
803
|
+
return (r !== void 0 && Fe(n) === "plan-transactional" ? i.pipe(S.retry(jt((e) => r(a(e)) === "retry"))) : i).pipe(S.orDieWith((e) => e instanceof Mt ? Error(ie("migrate: statement failed", e.statement, e.error, 400).trim()) : e));
|
|
804
|
+
}, Ft = (e) => {
|
|
796
805
|
let t = [], n = "", r = !1;
|
|
797
806
|
for (let i = 0; i < e.length; i++) {
|
|
798
807
|
if (e.slice(i, i + 2) === "$$") {
|
|
@@ -807,43 +816,43 @@ BEGIN
|
|
|
807
816
|
}
|
|
808
817
|
let i = n.trim();
|
|
809
818
|
return i.length > 0 && t.push(i), t;
|
|
810
|
-
},
|
|
811
|
-
await S.runPromise(
|
|
812
|
-
},
|
|
813
|
-
let i =
|
|
814
|
-
yield* Me(a,
|
|
815
|
-
}),
|
|
816
|
-
await S.runPromise(
|
|
819
|
+
}, It = async (e, t, n = "postgres", r = {}) => {
|
|
820
|
+
await S.runPromise(Dt(e, n, void 0, r).pipe(S.provide(t)));
|
|
821
|
+
}, Lt = (e, t, n = "postgres", r = {}) => S.gen(function* () {
|
|
822
|
+
let i = Tt(e, n, t), a = yield* T.SqlClient;
|
|
823
|
+
yield* Me(a, Pt(a, i, n, r.retryFilter), { schema: r.lockSchema }).pipe(S.orDie);
|
|
824
|
+
}), Rt = async (e, t, n, r = "postgres", i = {}) => {
|
|
825
|
+
await S.runPromise(Lt(e, t, r, i).pipe(S.provide(n))), await s({
|
|
817
826
|
namespace: t,
|
|
818
827
|
dialect: r
|
|
819
828
|
});
|
|
820
|
-
},
|
|
829
|
+
}, zt = async (e, t, n = "postgres", r = {}) => {
|
|
821
830
|
await S.runPromise(S.gen(function* () {
|
|
822
|
-
let t =
|
|
823
|
-
yield* Me(i,
|
|
831
|
+
let t = Et(e, n), i = yield* T.SqlClient;
|
|
832
|
+
yield* Me(i, Pt(i, t, n, r.retryFilter), { schema: r.lockSchema }).pipe(S.orDie);
|
|
824
833
|
}).pipe(S.provide(t)));
|
|
825
|
-
},
|
|
834
|
+
}, Bt = (e) => {
|
|
826
835
|
if (e == null) return e;
|
|
827
|
-
if (Array.isArray(e)) return e.map(
|
|
836
|
+
if (Array.isArray(e)) return e.map(Bt);
|
|
828
837
|
if (typeof e != "object") return e;
|
|
829
838
|
let t = {};
|
|
830
839
|
for (let n of Object.keys(e).sort()) {
|
|
831
840
|
let r = e[n];
|
|
832
|
-
r !== void 0 && (t[n] =
|
|
841
|
+
r !== void 0 && (t[n] = Bt(r));
|
|
833
842
|
}
|
|
834
843
|
return t;
|
|
835
|
-
},
|
|
844
|
+
}, Vt = (e) => {
|
|
836
845
|
if (!e.idScheme && !e.sensitive && !e.safe && !e.generatedAs) return e;
|
|
837
846
|
let { idScheme: t, sensitive: n, safe: r, generatedAs: i, ...a } = e;
|
|
838
847
|
return a;
|
|
839
|
-
},
|
|
848
|
+
}, Ht = (e) => [...e].map(Vt).sort((e, t) => e.name.localeCompare(t.name)), Ut = (e) => [...e].sort((e, t) => e.name.localeCompare(t.name)), Wt = (e) => [...e].map((e) => ({
|
|
840
849
|
name: e.name,
|
|
841
|
-
columns:
|
|
842
|
-
indexes:
|
|
843
|
-
})).sort((e, t) => e.name.localeCompare(t.name)),
|
|
844
|
-
let t = { tables:
|
|
845
|
-
return
|
|
846
|
-
},
|
|
850
|
+
columns: Ht(e.columns),
|
|
851
|
+
indexes: Ut(e.indexes)
|
|
852
|
+
})).sort((e, t) => e.name.localeCompare(t.name)), Gt = (e) => {
|
|
853
|
+
let t = { tables: Wt(e.tables) }, n = JSON.stringify(Bt(t));
|
|
854
|
+
return ee("sha256").update(n).digest("hex");
|
|
855
|
+
}, Kt = (e) => e.slice(0, 16), qt = (e, t) => {
|
|
847
856
|
let n = t.references ? {
|
|
848
857
|
table: t.references().tableName,
|
|
849
858
|
column: "id",
|
|
@@ -882,7 +891,7 @@ BEGIN
|
|
|
882
891
|
...t.enumValues === void 0 ? {} : { enumValues: t.enumValues },
|
|
883
892
|
...t.spatial === void 0 ? {} : { spatial: t.spatial }
|
|
884
893
|
};
|
|
885
|
-
},
|
|
894
|
+
}, Jt = (e) => {
|
|
886
895
|
let t = [], n = /* @__PURE__ */ new Set(), r = (e) => {
|
|
887
896
|
n.has(e.name) || (n.add(e.name), t.push(e));
|
|
888
897
|
}, i = e.appliedPrimaryKey ?? [];
|
|
@@ -930,11 +939,11 @@ BEGIN
|
|
|
930
939
|
});
|
|
931
940
|
}
|
|
932
941
|
return t;
|
|
933
|
-
},
|
|
942
|
+
}, Yt = (e) => {
|
|
934
943
|
let t = new Set((e.appliedUniques ?? []).filter((e) => e.fields.length === 1).map((e) => e.fields[0])), n = [];
|
|
935
944
|
for (let [r, i] of Object.entries(e.fields)) {
|
|
936
945
|
if (i.dropped) continue;
|
|
937
|
-
let e =
|
|
946
|
+
let e = qt(r, i);
|
|
938
947
|
n.push(t.has(r) ? {
|
|
939
948
|
...e,
|
|
940
949
|
unique: !0
|
|
@@ -944,11 +953,11 @@ BEGIN
|
|
|
944
953
|
return {
|
|
945
954
|
name: e.tableName,
|
|
946
955
|
columns: n,
|
|
947
|
-
indexes:
|
|
956
|
+
indexes: Jt(e),
|
|
948
957
|
...r.length > 0 ? { primaryKey: [...r] } : {},
|
|
949
958
|
...i === void 0 ? {} : { renamedFrom: i }
|
|
950
959
|
};
|
|
951
|
-
},
|
|
960
|
+
}, Xt = (e) => {
|
|
952
961
|
let t = /* @__PURE__ */ new Map();
|
|
953
962
|
for (let n of e) for (let e of n.indexes) {
|
|
954
963
|
let r = t.get(e.name);
|
|
@@ -956,9 +965,9 @@ BEGIN
|
|
|
956
965
|
t.set(e.name, n.name);
|
|
957
966
|
}
|
|
958
967
|
}, I = (e, t) => {
|
|
959
|
-
let n = e.filter((e) => !i(e.tableName)).map((e) =>
|
|
960
|
-
return
|
|
961
|
-
},
|
|
968
|
+
let n = e.filter((e) => !i(e.tableName)).map((e) => Yt(ue(e, t)));
|
|
969
|
+
return Xt(n), { tables: n };
|
|
970
|
+
}, Zt = (e, t, n = A) => S.gen(function* () {
|
|
962
971
|
let r = (yield* e`
|
|
963
972
|
SELECT p.prosrc
|
|
964
973
|
FROM pg_proc p
|
|
@@ -989,7 +998,7 @@ BEGIN
|
|
|
989
998
|
stale: l.sort(),
|
|
990
999
|
functionOutdated: i
|
|
991
1000
|
};
|
|
992
|
-
}),
|
|
1001
|
+
}), Qt = (e) => {
|
|
993
1002
|
let t = [];
|
|
994
1003
|
if (e.missing.length > 0) {
|
|
995
1004
|
let n = e.missing.slice(0, 8).join(", "), r = e.missing.length > 8 ? `, … (+${e.missing.length - 8})` : "";
|
|
@@ -1000,19 +1009,19 @@ BEGIN
|
|
|
1000
1009
|
t.push(`${e.stale.length} .nonReactive() table(s) still carry a change trigger — ${n}. They keep paying REPLICA IDENTITY FULL and a NOTIFY on every write for a subscription nobody receives. \`voltro db apply\` removes them.`);
|
|
1001
1010
|
}
|
|
1002
1011
|
return e.functionOutdated && t.push("The change-notify function in this database is OLDER than the framework installed here. Its triggers fire, so nothing looks wrong — but a row too large for a NOTIFY payload (postgres caps it at 8000 bytes) is emitted without its primary key, and a change that carries no key cannot be re-read: it reaches subscriptions as a re-query and reaches every TAP — search index, analytics mirror, cdc-out, row history — as nothing at all. Run `voltro db apply` to replace it."), t.length > 0 ? t.join("\n") : void 0;
|
|
1003
|
-
},
|
|
1012
|
+
}, $t = {
|
|
1004
1013
|
postgres: !0,
|
|
1005
1014
|
mysql: !0,
|
|
1006
1015
|
mariadb: !0,
|
|
1007
1016
|
mssql: !0,
|
|
1008
1017
|
sqlite: !0
|
|
1009
|
-
},
|
|
1018
|
+
}, en = {
|
|
1010
1019
|
postgres: !0,
|
|
1011
1020
|
mysql: !1,
|
|
1012
1021
|
mariadb: !1,
|
|
1013
1022
|
mssql: !0,
|
|
1014
1023
|
sqlite: !0
|
|
1015
|
-
},
|
|
1024
|
+
}, tn = (e) => {
|
|
1016
1025
|
switch (e) {
|
|
1017
1026
|
case "add-column":
|
|
1018
1027
|
case "drop-column":
|
|
@@ -1022,10 +1031,10 @@ BEGIN
|
|
|
1022
1031
|
case "add-foreign-key":
|
|
1023
1032
|
case "add-unique":
|
|
1024
1033
|
case "add-unique-composite":
|
|
1025
|
-
case "add-check": return
|
|
1026
|
-
default: return
|
|
1034
|
+
case "add-check": return en;
|
|
1035
|
+
default: return $t;
|
|
1027
1036
|
}
|
|
1028
|
-
},
|
|
1037
|
+
}, nn = (e, t) => {
|
|
1029
1038
|
let n = new Map(t.tables.map((e) => [e.name, e]));
|
|
1030
1039
|
return new Map(e.map((e) => [e.tableName, {
|
|
1031
1040
|
table: e,
|
|
@@ -1037,7 +1046,7 @@ BEGIN
|
|
|
1037
1046
|
if (Array.isArray(e)) return `[${e.map(L).join(",")}]`;
|
|
1038
1047
|
let t = e;
|
|
1039
1048
|
return `{${Object.keys(t).sort().map((e) => `${JSON.stringify(e)}:${L(t[e])}`).join(",")}}`;
|
|
1040
|
-
},
|
|
1049
|
+
}, rn = (e) => {
|
|
1041
1050
|
if (!e.hasDefault || e.defaultValue === void 0 || e.defaultValue === null) return null;
|
|
1042
1051
|
let t = e.defaultValue;
|
|
1043
1052
|
if (typeof t == "boolean") return t ? "__BOOL_TRUE__" : "__BOOL_FALSE__";
|
|
@@ -1057,12 +1066,12 @@ BEGIN
|
|
|
1057
1066
|
return L(JSON.parse(a));
|
|
1058
1067
|
} catch {}
|
|
1059
1068
|
return /^-?\d+(\.\d+)?$/.test(a) ? String(Number(a)) : a;
|
|
1060
|
-
},
|
|
1061
|
-
let n =
|
|
1069
|
+
}, an = (e, t) => {
|
|
1070
|
+
let n = rn(e), r = rn(t);
|
|
1062
1071
|
if (n === r) return !0;
|
|
1063
1072
|
let i = (e) => e === "1" || e === "true" ? "__BOOL_TRUE__" : e === "0" || e === "false" ? "__BOOL_FALSE__" : e;
|
|
1064
1073
|
return i(n) === i(r);
|
|
1065
|
-
},
|
|
1074
|
+
}, on = (e) => {
|
|
1066
1075
|
if (!e) return null;
|
|
1067
1076
|
let t = (e) => e === "restrict" ? "noAction" : e;
|
|
1068
1077
|
return {
|
|
@@ -1071,33 +1080,37 @@ BEGIN
|
|
|
1071
1080
|
onDelete: t(e.onDelete),
|
|
1072
1081
|
onUpdate: t(e.onUpdate)
|
|
1073
1082
|
};
|
|
1074
|
-
},
|
|
1083
|
+
}, sn = (e, t) => {
|
|
1075
1084
|
let n = e && e.length > 0 ? e : void 0, r = t && t.length > 0 ? t : void 0;
|
|
1076
1085
|
if (!n && !r) return !0;
|
|
1077
1086
|
if (!n || !r || n.length !== r.length) return !1;
|
|
1078
1087
|
let i = [...n].sort(), a = [...r].sort();
|
|
1079
1088
|
return i.every((e, t) => e === a[t]);
|
|
1080
|
-
},
|
|
1089
|
+
}, cn = (e, t, n) => {
|
|
1090
|
+
if (t === "mssql") {
|
|
1091
|
+
let t = Ze(e, n);
|
|
1092
|
+
if (t !== void 0) return t;
|
|
1093
|
+
}
|
|
1081
1094
|
try {
|
|
1082
1095
|
let n = /\((\d+)\)/.exec(M(e, t));
|
|
1083
1096
|
return n ? Number(n[1]) : void 0;
|
|
1084
1097
|
} catch {
|
|
1085
1098
|
return;
|
|
1086
1099
|
}
|
|
1087
|
-
},
|
|
1100
|
+
}, ln = (e, t, n, r) => n === void 0 || l(n) ? !0 : e.type !== "text" || t.type !== "text" || cn(e, n, r) === t.maxLength, un = (e, t, n, r) => e.type === t.type && e.nullable === t.nullable && e.unique === t.unique && an(e, t) && ln(e, t, n, r) && JSON.stringify(on(e.references)) === JSON.stringify(on(t.references)) && sn(e.oneOf, t.oneOf), dn = (e, t) => t.oneOf && t.oneOf.length > 0 ? R({
|
|
1088
1101
|
kind: "add-check",
|
|
1089
1102
|
table: e,
|
|
1090
1103
|
column: t.name,
|
|
1091
1104
|
values: t.oneOf
|
|
1092
|
-
}, "safe", `enum-membership CHECK on ${e}.${t.name}`) : void 0,
|
|
1093
|
-
let r = new Map(t.columns.map((e) => [e.name, e])), i = new Map(e.columns.map((e) => [e.name, e])), a = [], o = [], s = [];
|
|
1105
|
+
}, "safe", `enum-membership CHECK on ${e}.${t.name}`) : void 0, fn = (e, t) => e.unique === t.unique && (e.expression || t.expression ? !0 : e.columns.length === t.columns.length && e.columns.every((e, n) => e === t.columns[n])), pn = (e, t, n) => {
|
|
1106
|
+
let r = new Map(t.columns.map((e) => [e.name, e])), i = new Map(e.columns.map((e) => [e.name, e])), a = [], o = [], s = [], c = new Set(e.indexes.flatMap((e) => e.columns));
|
|
1094
1107
|
for (let t of e.columns) {
|
|
1095
1108
|
let e = r.get(t.name);
|
|
1096
1109
|
if (!e) {
|
|
1097
1110
|
a.push(t);
|
|
1098
1111
|
continue;
|
|
1099
1112
|
}
|
|
1100
|
-
|
|
1113
|
+
un(t, e, n, c.has(t.name) || t.unique) || s.push({
|
|
1101
1114
|
declared: t,
|
|
1102
1115
|
live: e
|
|
1103
1116
|
});
|
|
@@ -1108,47 +1121,47 @@ BEGIN
|
|
|
1108
1121
|
removed: o,
|
|
1109
1122
|
changed: s
|
|
1110
1123
|
};
|
|
1111
|
-
},
|
|
1112
|
-
let n = new Map(t.indexes.map((e) => [e.name, e])),
|
|
1124
|
+
}, mn = (e, t, n) => {
|
|
1125
|
+
let r = (e) => n === "turso" || n === "sqlite" ? e.toLowerCase() : e, i = new Map(t.indexes.map((e) => [r(e.name), e])), a = new Map(e.indexes.map((e) => [r(e.name), e])), o = [], s = [];
|
|
1113
1126
|
for (let t of e.indexes) {
|
|
1114
|
-
let e =
|
|
1115
|
-
(!e || !
|
|
1127
|
+
let e = i.get(r(t.name));
|
|
1128
|
+
(!e || !fn(t, e)) && o.push(t);
|
|
1116
1129
|
}
|
|
1117
|
-
for (let e of t.indexes)
|
|
1130
|
+
for (let e of t.indexes) a.has(r(e.name)) || s.push(e);
|
|
1118
1131
|
return {
|
|
1119
|
-
added:
|
|
1120
|
-
removed:
|
|
1132
|
+
added: o,
|
|
1133
|
+
removed: s
|
|
1121
1134
|
};
|
|
1122
1135
|
}, R = (e, t, n, r) => ({
|
|
1123
1136
|
op: e,
|
|
1124
1137
|
classification: t,
|
|
1125
|
-
atomicByDialect:
|
|
1138
|
+
atomicByDialect: tn(e.kind),
|
|
1126
1139
|
...n ? { reason: n } : {},
|
|
1127
1140
|
...r ? { blocked: r } : {}
|
|
1128
|
-
}),
|
|
1141
|
+
}), hn = (e, t, n) => {
|
|
1129
1142
|
let r = {
|
|
1130
1143
|
kind: "add-column",
|
|
1131
1144
|
table: e,
|
|
1132
1145
|
column: t
|
|
1133
1146
|
};
|
|
1134
1147
|
return t.nullable ? R(r, "safe", "nullable column add — no backfill needed") : t.hasDefault && t.defaultValue !== void 0 ? R(r, "needs-default", "NOT NULL with literal default — DDL DEFAULT will populate existing rows") : n?.backfill ? R(r, "needs-backfill", `backfill declared (kind=${n.backfill.kind}) — applier will run 3-step add/update/set-not-null`) : R(r, "needs-backfill", "NOT NULL column on a table whose row count is unknown", { fix: `declare \`${t.name}: <type>().backfill(sql\`...\`)\` OR \`.default(value)\` so existing rows survive the migration` });
|
|
1135
|
-
},
|
|
1148
|
+
}, gn = (e, t, n) => {
|
|
1136
1149
|
let r = {
|
|
1137
1150
|
kind: "drop-column",
|
|
1138
1151
|
table: e,
|
|
1139
1152
|
column: t.name
|
|
1140
1153
|
};
|
|
1141
1154
|
return n?.dropped ? R(r, "lossy", `column dropped via \`${t.name}: dropped()\` marker — intentional`) : R(r, "lossy", "column missing from declared schema", { fix: `if intentional, add \`${t.name}: dropped()\` to the schema. If a typo, restore the field` });
|
|
1142
|
-
},
|
|
1155
|
+
}, _n = (e, t, n, r, i) => R({
|
|
1143
1156
|
kind: "create-table",
|
|
1144
1157
|
table: e,
|
|
1145
1158
|
columns: t,
|
|
1146
1159
|
indexes: n,
|
|
1147
1160
|
...r && r.length > 0 ? { primaryKey: r } : {}
|
|
1148
|
-
}, "safe", i ?? "new table — no data to preserve"),
|
|
1161
|
+
}, "safe", i ?? "new table — no data to preserve"), vn = (e) => R({
|
|
1149
1162
|
kind: "drop-table",
|
|
1150
1163
|
table: e
|
|
1151
|
-
}, "lossy", "table missing from declared schema", { fix: "if intentional, set VOLTRO_DESTRUCTIVE_OK=1 OR add a file-based migration. If a typo, restore the table declaration" }),
|
|
1164
|
+
}, "lossy", "table missing from declared schema", { fix: "if intentional, set VOLTRO_DESTRUCTIVE_OK=1 OR add a file-based migration. If a typo, restore the table declaration" }), yn = 5e4, bn = (e, t, n, r) => {
|
|
1152
1165
|
let i = (n ?? 0) >= r, a;
|
|
1153
1166
|
return a = t.unique ? t.columns.length === 1 ? {
|
|
1154
1167
|
kind: "add-unique",
|
|
@@ -1164,7 +1177,7 @@ BEGIN
|
|
|
1164
1177
|
table: e,
|
|
1165
1178
|
index: t
|
|
1166
1179
|
}, i ? R(a, "online-required", `online build on ${n} rows — CONCURRENTLY / INPLACE / WITH(ONLINE=ON) depending on dialect`) : R(a, "safe", t.unique ? t.columns.length === 1 ? "add unique constraint" : "add composite UNIQUE constraint" : "add B-tree index");
|
|
1167
|
-
},
|
|
1180
|
+
}, xn = (e, t) => t.unique && t.columns.length > 1 ? R({
|
|
1168
1181
|
kind: "drop-unique-composite",
|
|
1169
1182
|
table: e,
|
|
1170
1183
|
name: t.name
|
|
@@ -1172,7 +1185,7 @@ BEGIN
|
|
|
1172
1185
|
kind: "drop-index",
|
|
1173
1186
|
table: e,
|
|
1174
1187
|
index: t.name
|
|
1175
|
-
}, "safe", "drop index (no data loss — index is derived data)"),
|
|
1188
|
+
}, "safe", "drop index (no data loss — index is derived data)"), Sn = (e, t) => {
|
|
1176
1189
|
if (e === "reference") return "text";
|
|
1177
1190
|
switch (t) {
|
|
1178
1191
|
case "sqlite":
|
|
@@ -1180,10 +1193,10 @@ BEGIN
|
|
|
1180
1193
|
case "mssql": return e === "json" ? "text" : e;
|
|
1181
1194
|
default: return e;
|
|
1182
1195
|
}
|
|
1183
|
-
},
|
|
1196
|
+
}, Cn = (e, t, n) => {
|
|
1184
1197
|
let r = `acknowledge it on the column: \`.narrowedFrom('${e}')\``;
|
|
1185
1198
|
return n === "postgres" ? `${r} — add \`{ using: '${t.name}::${t.type}' }\` when the cast is not implicit, or use a file-based migration` : `${r} — ${n === void 0 ? "this dialect" : n} converts in place (\`using\` is postgres-only and is ignored here), so verify the conversion is value-preserving for your data, or use a file-based migration`;
|
|
1186
|
-
},
|
|
1199
|
+
}, wn = (e, t, n, r, i, a) => {
|
|
1187
1200
|
let o = [];
|
|
1188
1201
|
if (t.nullable !== n.nullable) {
|
|
1189
1202
|
let n = {
|
|
@@ -1208,7 +1221,7 @@ BEGIN
|
|
|
1208
1221
|
column: t.name
|
|
1209
1222
|
}, "safe", `drop unique constraint on ${e}.${t.name} — constraint is derived metadata, no data loss`));
|
|
1210
1223
|
}
|
|
1211
|
-
if (
|
|
1224
|
+
if (Sn(t.type, r) !== Sn(n.type, r)) {
|
|
1212
1225
|
let i = t.narrowedFrom;
|
|
1213
1226
|
if (i && i.from === n.type) {
|
|
1214
1227
|
let r = {
|
|
@@ -1228,7 +1241,7 @@ BEGIN
|
|
|
1228
1241
|
from: n.type,
|
|
1229
1242
|
to: t.type
|
|
1230
1243
|
};
|
|
1231
|
-
o.push(R(i, "lossy", `type change ${n.type} → ${t.type} on ${e}.${t.name} may not be value-preserving`, { fix:
|
|
1244
|
+
o.push(R(i, "lossy", `type change ${n.type} → ${t.type} on ${e}.${t.name} may not be value-preserving`, { fix: Cn(n.type, t, r) }));
|
|
1232
1245
|
}
|
|
1233
1246
|
}
|
|
1234
1247
|
if (t.type === "text" && n.type === "text" && !l(r ?? "postgres") && t.maxLength !== n.maxLength) {
|
|
@@ -1241,7 +1254,7 @@ BEGIN
|
|
|
1241
1254
|
to: "text"
|
|
1242
1255
|
}, r ? "safe" : "needs-backfill", r ? `text length ${i} → ${a} on ${e}.${t.name} — widening, no data can be lost` : `text length ${i} → ${a} on ${e}.${t.name} — NARROWING; the ALTER fails if any existing value is longer than ${String(t.maxLength)}. Check first: SELECT COUNT(*) FROM ${e} WHERE LENGTH(${t.name}) > ${String(t.maxLength)}`));
|
|
1243
1256
|
}
|
|
1244
|
-
if (!
|
|
1257
|
+
if (!an(t, n)) {
|
|
1245
1258
|
let n = {
|
|
1246
1259
|
kind: "alter-column-default",
|
|
1247
1260
|
table: e,
|
|
@@ -1251,21 +1264,21 @@ BEGIN
|
|
|
1251
1264
|
};
|
|
1252
1265
|
o.push(R(n, "safe", `default change on ${e}.${t.name} affects only future inserts`));
|
|
1253
1266
|
}
|
|
1254
|
-
if (!
|
|
1267
|
+
if (!sn(t.oneOf, n.oneOf)) {
|
|
1255
1268
|
n.oneOf && n.oneOf.length > 0 && o.push(R({
|
|
1256
1269
|
kind: "drop-check",
|
|
1257
1270
|
table: e,
|
|
1258
1271
|
column: t.name
|
|
1259
1272
|
}, "safe", `drop stale enum CHECK on ${e}.${t.name}`));
|
|
1260
|
-
let r =
|
|
1273
|
+
let r = dn(e, t);
|
|
1261
1274
|
r && o.push(r);
|
|
1262
1275
|
}
|
|
1263
|
-
return JSON.stringify(
|
|
1276
|
+
return JSON.stringify(on(t.references)) !== JSON.stringify(on(n.references)) && (n.references && o.push(R({
|
|
1264
1277
|
kind: "drop-foreign-key",
|
|
1265
1278
|
table: e,
|
|
1266
1279
|
column: t.name
|
|
1267
|
-
}, "safe", `drop FK on ${e}.${t.name} (→ ${n.references.table})`)), o.push(...
|
|
1268
|
-
},
|
|
1280
|
+
}, "safe", `drop FK on ${e}.${t.name} (→ ${n.references.table})`)), o.push(...Tn(e, t))), o;
|
|
1281
|
+
}, Tn = (e, t) => {
|
|
1269
1282
|
let n = [];
|
|
1270
1283
|
if (!t.references) return n;
|
|
1271
1284
|
let r = t.references.table, i = t.references.orphanPolicy ?? "fail", a = {
|
|
@@ -1281,7 +1294,7 @@ BEGIN
|
|
|
1281
1294
|
...a,
|
|
1282
1295
|
orphanPolicy: i
|
|
1283
1296
|
}, "lossy", i === "delete" ? `add FK ${e}.${t.name} → ${r}: orphanPolicy 'delete' first DELETES rows whose ${t.name} points at a missing ${r}` : `add FK ${e}.${t.name} → ${r}: orphanPolicy 'null' first NULLs ${t.name} where it points at a missing ${r}`)) : n.push(R(a, "needs-backfill", `add FK ${e}.${t.name} → ${r} — existing rows must already reference a valid ${r} (else set orphanPolicy:'null'/'delete')`)), n;
|
|
1284
|
-
},
|
|
1297
|
+
}, En = (e, t, n) => {
|
|
1285
1298
|
let r = [], i = /* @__PURE__ */ new Set(), a = /* @__PURE__ */ new Set(), o = new Set(n.removed.map((e) => e.name)), s = new Set(n.added.map((e) => e.name));
|
|
1286
1299
|
for (let [n, c] of Object.entries(t)) {
|
|
1287
1300
|
let t = c.renamedFrom;
|
|
@@ -1297,22 +1310,22 @@ BEGIN
|
|
|
1297
1310
|
consumedAddedNames: i,
|
|
1298
1311
|
consumedRemovedNames: a
|
|
1299
1312
|
};
|
|
1300
|
-
},
|
|
1313
|
+
}, Dn = /* @__PURE__ */ new Set([
|
|
1301
1314
|
"postgres",
|
|
1302
1315
|
"mysql",
|
|
1303
1316
|
"mariadb",
|
|
1304
1317
|
"mssql"
|
|
1305
|
-
]),
|
|
1318
|
+
]), On = {
|
|
1306
1319
|
ops: [],
|
|
1307
1320
|
consumedAddedNames: /* @__PURE__ */ new Set(),
|
|
1308
1321
|
consumedRemovedNames: /* @__PURE__ */ new Set()
|
|
1309
|
-
},
|
|
1310
|
-
if (i === void 0 || !
|
|
1311
|
-
let a = t.added.filter((e) =>
|
|
1312
|
-
if (a.length === 0) return
|
|
1322
|
+
}, kn = (e) => !e.unique && !e.expression, An = (e, t, n, r, i) => {
|
|
1323
|
+
if (i === void 0 || !Dn.has(i)) return On;
|
|
1324
|
+
let a = t.added.filter((e) => kn(e) && !r.has(e.name));
|
|
1325
|
+
if (a.length === 0) return On;
|
|
1313
1326
|
let o = (e) => e.columns.map((e) => n.get(e) ?? e).join("\0"), s = (e) => e.columns.join("\0"), c = [], l = /* @__PURE__ */ new Set(), u = /* @__PURE__ */ new Set();
|
|
1314
1327
|
for (let n of t.removed) {
|
|
1315
|
-
if (!
|
|
1328
|
+
if (!kn(n)) continue;
|
|
1316
1329
|
let t = o(n), r = a.filter((e) => !l.has(e.name) && s(e) === t);
|
|
1317
1330
|
if (r.length !== 1) continue;
|
|
1318
1331
|
let i = r[0];
|
|
@@ -1328,7 +1341,7 @@ BEGIN
|
|
|
1328
1341
|
consumedAddedNames: l,
|
|
1329
1342
|
consumedRemovedNames: u
|
|
1330
1343
|
};
|
|
1331
|
-
},
|
|
1344
|
+
}, jn = (e, t, n) => {
|
|
1332
1345
|
let r = [], i = /* @__PURE__ */ new Map(), a = /* @__PURE__ */ new Set(), o = /* @__PURE__ */ new Map(), s = /* @__PURE__ */ new Map(), c = /* @__PURE__ */ new Set();
|
|
1333
1346
|
for (let t of e.tables) t.renamedFrom !== void 0 && (s.set(t.renamedFrom, (s.get(t.renamedFrom) ?? 0) + 1), c.add(t.renamedFrom));
|
|
1334
1347
|
for (let c of e.tables) {
|
|
@@ -1368,12 +1381,12 @@ BEGIN
|
|
|
1368
1381
|
claimedOldNames: c,
|
|
1369
1382
|
refusals: o
|
|
1370
1383
|
};
|
|
1371
|
-
},
|
|
1384
|
+
}, Mn = (e, t, n, r) => {
|
|
1372
1385
|
if (t === void 0) return {
|
|
1373
1386
|
live: e,
|
|
1374
1387
|
ops: []
|
|
1375
1388
|
};
|
|
1376
|
-
let i = r !== void 0 &&
|
|
1389
|
+
let i = r !== void 0 && Dn.has(r), a = [], o = e.indexes.map((e) => {
|
|
1377
1390
|
if (!e.name.startsWith(t)) return e;
|
|
1378
1391
|
let r = `${n}${e.name.slice(t.length)}`;
|
|
1379
1392
|
return r === e.name ? e : e.name === `${t}_pkey` ? {
|
|
@@ -1399,7 +1412,7 @@ BEGIN
|
|
|
1399
1412
|
},
|
|
1400
1413
|
ops: a
|
|
1401
1414
|
};
|
|
1402
|
-
},
|
|
1415
|
+
}, Nn = (e) => {
|
|
1403
1416
|
let t = {
|
|
1404
1417
|
safe: 0,
|
|
1405
1418
|
needsDefault: 0,
|
|
@@ -1432,42 +1445,42 @@ BEGIN
|
|
|
1432
1445
|
case "multi-step": t.multiStep++;
|
|
1433
1446
|
}
|
|
1434
1447
|
return t;
|
|
1435
|
-
},
|
|
1436
|
-
let t = I(e.declared, e.dialect), n =
|
|
1448
|
+
}, Pn = (e) => {
|
|
1449
|
+
let t = I(e.declared, e.dialect), n = nn(e.declared, t), r = new Map(e.live.tables.map((e) => [e.name, e])), i = e.onlineAfter ?? yn, a = [], o = jn(t, r, n);
|
|
1437
1450
|
a.push(...o.ops);
|
|
1438
1451
|
for (let e of t.tables) if (!o.renamedInto.has(e.name) && !r.has(e.name)) {
|
|
1439
|
-
a.push(
|
|
1452
|
+
a.push(_n(e.name, e.columns, e.indexes, e.primaryKey, o.refusals.get(e.name)));
|
|
1440
1453
|
for (let t of e.columns) {
|
|
1441
|
-
let n =
|
|
1454
|
+
let n = dn(e.name, t);
|
|
1442
1455
|
n && a.push(n);
|
|
1443
1456
|
}
|
|
1444
1457
|
}
|
|
1445
1458
|
let s = new Set(e.ignoreTables ?? []);
|
|
1446
|
-
for (let t of e.live.tables) n.has(t.name) || o.claimedOldNames.has(t.name) || h(t.name) || f(t.name) || s.has(t.name) || a.push(
|
|
1459
|
+
for (let t of e.live.tables) n.has(t.name) || o.claimedOldNames.has(t.name) || h(t.name) || f(t.name) || s.has(t.name) || a.push(vn(t.name));
|
|
1447
1460
|
for (let s of t.tables) {
|
|
1448
1461
|
let t = o.renamedInto.get(s.name), c = r.get(s.name) ?? (t === void 0 ? void 0 : r.get(t));
|
|
1449
1462
|
if (!c) continue;
|
|
1450
|
-
let l =
|
|
1463
|
+
let l = Mn(c, t, s.name, e.dialect);
|
|
1451
1464
|
a.push(...l.ops);
|
|
1452
|
-
let u = l.live, d = n.get(s.name), p =
|
|
1465
|
+
let u = l.live, d = n.get(s.name), p = pn(s, u, e.dialect), m = mn(s, u, e.dialect), h = En(d.table, d.columnDefs, p);
|
|
1453
1466
|
a.push(...h.ops);
|
|
1454
1467
|
for (let e of p.removed) {
|
|
1455
1468
|
if (h.consumedRemovedNames.has(e.name) || f(e.name)) continue;
|
|
1456
1469
|
let t = d.columnDefs[e.name];
|
|
1457
|
-
a.push(
|
|
1470
|
+
a.push(gn(s.name, e, t));
|
|
1458
1471
|
}
|
|
1459
1472
|
for (let e of p.added) {
|
|
1460
1473
|
if (h.consumedAddedNames.has(e.name)) continue;
|
|
1461
1474
|
let t = d.columnDefs[e.name];
|
|
1462
|
-
a.push(
|
|
1463
|
-
let n =
|
|
1464
|
-
n && a.push(n), a.push(...
|
|
1475
|
+
a.push(hn(s.name, e, t));
|
|
1476
|
+
let n = dn(s.name, e);
|
|
1477
|
+
n && a.push(n), a.push(...Tn(s.name, e));
|
|
1465
1478
|
}
|
|
1466
|
-
let g = new Map(h.ops.flatMap((e) => e.op.kind === "rename-column" ? [[e.op.from, e.op.to]] : [])), _ =
|
|
1479
|
+
let g = new Map(h.ops.flatMap((e) => e.op.kind === "rename-column" ? [[e.op.from, e.op.to]] : [])), _ = An(s.name, m, g, new Set(u.indexes.map((e) => e.name)), e.dialect);
|
|
1467
1480
|
a.push(..._.ops);
|
|
1468
|
-
for (let e of m.added) _.consumedAddedNames.has(e.name) || a.push(
|
|
1469
|
-
for (let e of m.removed) _.consumedRemovedNames.has(e.name) || a.push(
|
|
1470
|
-
for (let { declared: t, live: n } of p.changed) a.push(...
|
|
1481
|
+
for (let e of m.added) _.consumedAddedNames.has(e.name) || a.push(bn(s.name, e, u.rowCount, i));
|
|
1482
|
+
for (let e of m.removed) _.consumedRemovedNames.has(e.name) || a.push(xn(s.name, e));
|
|
1483
|
+
for (let { declared: t, live: n } of p.changed) a.push(...wn(s.name, t, n, e.dialect, u.rowCount, i));
|
|
1471
1484
|
}
|
|
1472
1485
|
let c = new Set(a.flatMap((e) => e.op.kind === "create-table" ? [e.op.table] : [])), l = new Map(t.tables.map((e) => [e.name, e])), u = (e) => {
|
|
1473
1486
|
let t = l.get(e);
|
|
@@ -1475,8 +1488,8 @@ BEGIN
|
|
|
1475
1488
|
column: e.name,
|
|
1476
1489
|
target: e.references.table
|
|
1477
1490
|
}] : []) : [];
|
|
1478
|
-
}, d =
|
|
1479
|
-
for (let e of t.tables) if (c.has(e.name)) for (let t of e.columns) !t.references || !d.has(
|
|
1491
|
+
}, d = de([...c], u), p = [];
|
|
1492
|
+
for (let e of t.tables) if (c.has(e.name)) for (let t of e.columns) !t.references || !d.has(E(e.name, t.name)) || p.push(R({
|
|
1480
1493
|
kind: "add-foreign-key",
|
|
1481
1494
|
table: e.name,
|
|
1482
1495
|
column: t.name,
|
|
@@ -1491,8 +1504,8 @@ BEGIN
|
|
|
1491
1504
|
let n = a[t];
|
|
1492
1505
|
if (n.op.kind !== "create-table") continue;
|
|
1493
1506
|
let r = n.op;
|
|
1494
|
-
if (!r.columns.some((e) => d.has(
|
|
1495
|
-
let i = r.columns.map((t) => d.has(
|
|
1507
|
+
if (!r.columns.some((e) => d.has(E(r.table, e.name)))) continue;
|
|
1508
|
+
let i = r.columns.map((t) => d.has(E(r.table, t.name)) ? e(t) : t);
|
|
1496
1509
|
a[t] = {
|
|
1497
1510
|
...n,
|
|
1498
1511
|
op: {
|
|
@@ -1512,7 +1525,7 @@ BEGIN
|
|
|
1512
1525
|
let i = new Set(t).add(e), a = 0;
|
|
1513
1526
|
for (let t of r.columns) {
|
|
1514
1527
|
let n = t.references?.table;
|
|
1515
|
-
n && n !== e && !d.has(
|
|
1528
|
+
n && n !== e && !d.has(E(e, t.name)) && (a = Math.max(a, _(n, i) + 1));
|
|
1516
1529
|
}
|
|
1517
1530
|
return g.set(e, a), a;
|
|
1518
1531
|
}, v = (e) => e === "rename-table" ? -1 : e === "create-table" ? 0 : e === "drop-table" ? 2 : 1, y = (e) => {
|
|
@@ -1548,11 +1561,11 @@ BEGIN
|
|
|
1548
1561
|
});
|
|
1549
1562
|
return {
|
|
1550
1563
|
operations: S,
|
|
1551
|
-
fromFingerprint:
|
|
1552
|
-
toFingerprint:
|
|
1553
|
-
summary:
|
|
1564
|
+
fromFingerprint: Gt(e.live),
|
|
1565
|
+
toFingerprint: Gt(t),
|
|
1566
|
+
summary: Nn(S)
|
|
1554
1567
|
};
|
|
1555
|
-
},
|
|
1568
|
+
}, Fn = (e) => {
|
|
1556
1569
|
let t = /[`"[]?([A-Za-z_][A-Za-z0-9_]*)[`"\]]?\s*(?:in\b|=)/i.exec(e);
|
|
1557
1570
|
if (!t) return null;
|
|
1558
1571
|
let n = [...e.replace(/\\'/g, "'").matchAll(/'((?:[^']|'')*)'/g)].map((e) => e[1].replace(/''/g, "'")).filter((e) => e.length > 0);
|
|
@@ -1560,7 +1573,7 @@ BEGIN
|
|
|
1560
1573
|
column: t[1],
|
|
1561
1574
|
values: n
|
|
1562
1575
|
};
|
|
1563
|
-
},
|
|
1576
|
+
}, In = (e, t) => {
|
|
1564
1577
|
if (t === "vector") return "vector";
|
|
1565
1578
|
switch (e) {
|
|
1566
1579
|
case "text":
|
|
@@ -1587,7 +1600,7 @@ BEGIN
|
|
|
1587
1600
|
case "USER-DEFINED": return "text";
|
|
1588
1601
|
default: return "text";
|
|
1589
1602
|
}
|
|
1590
|
-
},
|
|
1603
|
+
}, Ln = (e, t) => e == null || e === "" ? void 0 : { generatedAs: {
|
|
1591
1604
|
expr: e,
|
|
1592
1605
|
stored: t
|
|
1593
1606
|
} }, z = (e) => {
|
|
@@ -1598,25 +1611,25 @@ BEGIN
|
|
|
1598
1611
|
case "SET DEFAULT": return "noAction";
|
|
1599
1612
|
default: return "noAction";
|
|
1600
1613
|
}
|
|
1601
|
-
},
|
|
1614
|
+
}, Rn = (e, t) => {
|
|
1602
1615
|
let n = e !== void 0 && e !== "" ? Number(e) : NaN;
|
|
1603
1616
|
return Number.isInteger(n) && n > 0 ? n : t;
|
|
1604
|
-
},
|
|
1617
|
+
}, zn = () => Rn(process.env.VOLTRO_INTROSPECT_BATCH, 20), Bn = 300, Vn = () => {
|
|
1605
1618
|
let e = process.env.VOLTRO_INTROSPECT_TIMEOUT_MS;
|
|
1606
|
-
return e !== void 0 && e.trim() === "0" ? 0 :
|
|
1607
|
-
},
|
|
1619
|
+
return e !== void 0 && e.trim() === "0" ? 0 : Rn(e, 3e4);
|
|
1620
|
+
}, Hn = (e, t) => {
|
|
1608
1621
|
let n = Number.isFinite(t) && t >= 1 ? Math.floor(t) : 1, r = [];
|
|
1609
1622
|
for (let t = 0; t < e.length; t += n) r.push(e.slice(t, t + n));
|
|
1610
1623
|
return r;
|
|
1611
|
-
},
|
|
1612
|
-
let t =
|
|
1624
|
+
}, Un = (e) => {
|
|
1625
|
+
let t = Vn(), n = S.gen(function* () {
|
|
1613
1626
|
t > 0 && (yield* e.unsafe(`SET LOCAL statement_timeout = ${t}`));
|
|
1614
|
-
let n = (t) => e.unsafe("(" + t.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ") + ")"), r = (t) => e.unsafe(String(Math.max(0, Math.trunc(t)))), i =
|
|
1627
|
+
let n = (t) => e.unsafe("(" + t.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ") + ")"), r = (t) => e.unsafe(String(Math.max(0, Math.trunc(t)))), i = zn(), a = (e, t) => S.gen(function* () {
|
|
1615
1628
|
let r = [];
|
|
1616
|
-
for (let a of
|
|
1629
|
+
for (let a of Hn(e, i)) a.length !== 0 && r.push(...yield* t(n(a)));
|
|
1617
1630
|
return r;
|
|
1618
1631
|
}), o = [];
|
|
1619
|
-
for (let t = 0;; t +=
|
|
1632
|
+
for (let t = 0;; t += Bn) {
|
|
1620
1633
|
let n = yield* e`
|
|
1621
1634
|
SELECT c.relname AS table_name,
|
|
1622
1635
|
COALESCE(c.reltuples::bigint, 0) AS row_count
|
|
@@ -1624,9 +1637,9 @@ BEGIN
|
|
|
1624
1637
|
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
1625
1638
|
WHERE n.nspname = current_schema() AND c.relkind = 'r'
|
|
1626
1639
|
ORDER BY c.relname
|
|
1627
|
-
LIMIT ${r(
|
|
1640
|
+
LIMIT ${r(Bn)} OFFSET ${r(t)}
|
|
1628
1641
|
`;
|
|
1629
|
-
if (o.push(...n), n.length <
|
|
1642
|
+
if (o.push(...n), n.length < Bn) break;
|
|
1630
1643
|
}
|
|
1631
1644
|
let s = /* @__PURE__ */ new Set(), c = [];
|
|
1632
1645
|
for (let e of o) s.has(e.table_name) || (s.add(e.table_name), c.push(e));
|
|
@@ -1721,18 +1734,18 @@ BEGIN
|
|
|
1721
1734
|
let t = v.get(e.table_name);
|
|
1722
1735
|
t || (t = /* @__PURE__ */ new Set(), v.set(e.table_name, t)), t.add(e.column_name);
|
|
1723
1736
|
}
|
|
1724
|
-
let
|
|
1737
|
+
let ee = /* @__PURE__ */ new Map();
|
|
1725
1738
|
for (let e of f) {
|
|
1726
|
-
let t = `${e.table_name}\u0000${e.constraint_name}`, n =
|
|
1739
|
+
let t = `${e.table_name}\u0000${e.constraint_name}`, n = ee.get(t);
|
|
1727
1740
|
n || (n = {
|
|
1728
1741
|
table: e.table_name,
|
|
1729
1742
|
columns: []
|
|
1730
|
-
},
|
|
1743
|
+
}, ee.set(t, n)), n.columns.push({
|
|
1731
1744
|
name: e.column_name,
|
|
1732
1745
|
position: e.position
|
|
1733
1746
|
});
|
|
1734
1747
|
}
|
|
1735
|
-
for (let [e, t] of
|
|
1748
|
+
for (let [e, t] of ee) {
|
|
1736
1749
|
let n = [...t.columns].sort((e, t) => e.position - t.position).map((e) => e.name);
|
|
1737
1750
|
if (n.length === 1) {
|
|
1738
1751
|
let e = y.get(t.table);
|
|
@@ -1757,10 +1770,10 @@ BEGIN
|
|
|
1757
1770
|
let n = t.get(e.index_name);
|
|
1758
1771
|
n || (n = [], t.set(e.index_name, n)), n.push(e);
|
|
1759
1772
|
}
|
|
1760
|
-
let
|
|
1773
|
+
let w = [];
|
|
1761
1774
|
for (let e of c) {
|
|
1762
1775
|
let t = /* @__PURE__ */ new Set(), n = (_.get(e.table_name) ?? []).filter((e) => !t.has(e.column_name) && (t.add(e.column_name), !0)), r = v.get(e.table_name) ?? /* @__PURE__ */ new Set(), i = y.get(e.table_name) ?? /* @__PURE__ */ new Set(), a = x.get(e.table_name) ?? [], o = new Map(a.map((e) => [e.source_column, e])), s = new Set(n.filter((e) => e.udt_name === "tsvector").map((e) => e.column_name)), c = n.filter((e) => !s.has(e.column_name)).map((t) => {
|
|
1763
|
-
let n = r.has(t.column_name) && r.size === 1, a = o.get(t.column_name), s = a ? "reference" : n && t.column_name === "id" ? "id" :
|
|
1776
|
+
let n = r.has(t.column_name) && r.size === 1, a = o.get(t.column_name), s = a ? "reference" : n && t.column_name === "id" ? "id" : In(t.data_type, t.udt_name), c = a ? {
|
|
1764
1777
|
table: a.target_table,
|
|
1765
1778
|
column: a.target_column,
|
|
1766
1779
|
onDelete: z(a.delete_rule),
|
|
@@ -1776,7 +1789,7 @@ BEGIN
|
|
|
1776
1789
|
...t.column_default === null ? {} : { defaultValue: t.column_default },
|
|
1777
1790
|
...c ? { references: c } : {},
|
|
1778
1791
|
...l ? { oneOf: l } : {},
|
|
1779
|
-
...
|
|
1792
|
+
...Ln(t.is_generated === "ALWAYS" ? t.generation_expression ?? "generated" : null, !0) ?? {}
|
|
1780
1793
|
};
|
|
1781
1794
|
}), l = [], u = C.get(e.table_name);
|
|
1782
1795
|
if (u) for (let [t, n] of u) {
|
|
@@ -1802,20 +1815,20 @@ BEGIN
|
|
|
1802
1815
|
unique: !0
|
|
1803
1816
|
});
|
|
1804
1817
|
let d = Number(e.row_count ?? 0);
|
|
1805
|
-
|
|
1818
|
+
w.push({
|
|
1806
1819
|
name: e.table_name,
|
|
1807
1820
|
columns: c,
|
|
1808
1821
|
indexes: l,
|
|
1809
1822
|
...d > 0 ? { rowCount: d } : {}
|
|
1810
1823
|
});
|
|
1811
1824
|
}
|
|
1812
|
-
return { tables:
|
|
1825
|
+
return { tables: w };
|
|
1813
1826
|
});
|
|
1814
1827
|
return (t > 0 ? e.withTransaction(n) : n).pipe(S.catchAll((e) => {
|
|
1815
1828
|
let n = `${String(e)} ${String(e.cause ?? "")}`.toLowerCase();
|
|
1816
1829
|
return n.includes("statement timeout") || n.includes("57014") ? S.die(/* @__PURE__ */ Error(`schema introspection exceeded VOLTRO_INTROSPECT_TIMEOUT_MS (${t}ms) — the schema is very large / FK-dense or the database is slow. Raise VOLTRO_INTROSPECT_TIMEOUT_MS, set it to 0 to disable the ceiling, or use DB_DIRECT_URL for a non-pooler connection.`)) : S.fail(e);
|
|
1817
1830
|
}));
|
|
1818
|
-
},
|
|
1831
|
+
}, Wn = (e, t) => {
|
|
1819
1832
|
switch (e.toLowerCase()) {
|
|
1820
1833
|
case "varchar":
|
|
1821
1834
|
case "char":
|
|
@@ -1851,7 +1864,7 @@ BEGIN
|
|
|
1851
1864
|
let t = e, n = {};
|
|
1852
1865
|
for (let e of Object.keys(t)) n[e.toLowerCase()] = t[e];
|
|
1853
1866
|
return n;
|
|
1854
|
-
}),
|
|
1867
|
+
}), Gn = (e) => S.gen(function* () {
|
|
1855
1868
|
let t = B(yield* e`
|
|
1856
1869
|
SELECT table_name, COALESCE(table_rows, 0) AS table_rows
|
|
1857
1870
|
FROM information_schema.tables
|
|
@@ -1891,7 +1904,7 @@ BEGIN
|
|
|
1891
1904
|
c.add(`${e.table_name}.${t[1]}`);
|
|
1892
1905
|
continue;
|
|
1893
1906
|
}
|
|
1894
|
-
let n =
|
|
1907
|
+
let n = Fn(e.check_clause);
|
|
1895
1908
|
n && l.set(`${e.table_name}.${n.column}`, n.values);
|
|
1896
1909
|
}
|
|
1897
1910
|
let u = /* @__PURE__ */ new Map(), d = /* @__PURE__ */ new Map(), f = /* @__PURE__ */ new Map();
|
|
@@ -1914,7 +1927,7 @@ BEGIN
|
|
|
1914
1927
|
let t = u.get(e.table_name) ?? [], n = d.get(e.table_name) ?? [], r = new Map(n.map((e) => [e.source_column, e])), i = t.filter((e) => e.column_key === "PRI").map((e) => e.column_name), a = /* @__PURE__ */ new Set(), o = f.get(e.table_name);
|
|
1915
1928
|
if (o) for (let e of o.values()) e.length === 1 && e[0].non_unique === 0 && a.add(e[0].column_name);
|
|
1916
1929
|
let s = t.map((t) => {
|
|
1917
|
-
let n = i.includes(t.column_name) && i.length === 1, o = r.get(t.column_name), s = o ? "reference" : n && t.column_name === "id" ? "id" : c.has(`${e.table_name}.${t.column_name}`) ? "json" :
|
|
1930
|
+
let n = i.includes(t.column_name) && i.length === 1, o = r.get(t.column_name), s = o ? "reference" : n && t.column_name === "id" ? "id" : c.has(`${e.table_name}.${t.column_name}`) ? "json" : Wn(t.data_type, t.column_type), u = o ? {
|
|
1918
1931
|
table: o.target_table,
|
|
1919
1932
|
column: o.target_column,
|
|
1920
1933
|
onDelete: z(o.delete_rule),
|
|
@@ -1930,7 +1943,7 @@ BEGIN
|
|
|
1930
1943
|
...f === null ? {} : { defaultValue: f },
|
|
1931
1944
|
...u ? { references: u } : {},
|
|
1932
1945
|
...p ? { oneOf: p } : {},
|
|
1933
|
-
...
|
|
1946
|
+
...Ln(t.generation_expression, /STORED/i.test(t.extra ?? "")) ?? {}
|
|
1934
1947
|
};
|
|
1935
1948
|
}), m = new Set(n.map((e) => e.source_column)), h = [];
|
|
1936
1949
|
if (o) for (let [t, n] of o) {
|
|
@@ -1957,10 +1970,10 @@ BEGIN
|
|
|
1957
1970
|
});
|
|
1958
1971
|
}
|
|
1959
1972
|
return { tables: p };
|
|
1960
|
-
}),
|
|
1973
|
+
}), Kn = (e) => {
|
|
1961
1974
|
let t = e.toUpperCase();
|
|
1962
1975
|
return t.includes("INT") ? "integer" : t.includes("REAL") || t.includes("FLOA") || t.includes("DOUB") ? "real" : t.includes("BLOB") ? "bytes" : "text";
|
|
1963
|
-
},
|
|
1976
|
+
}, qn = (e) => e === 1 || e === !0, Jn = (e) => S.gen(function* () {
|
|
1964
1977
|
let t = yield* e`
|
|
1965
1978
|
SELECT name, sql FROM sqlite_master
|
|
1966
1979
|
WHERE type = 'table' AND name NOT LIKE 'sqlite_%'
|
|
@@ -1971,13 +1984,13 @@ BEGIN
|
|
|
1971
1984
|
let n = [...e[2].matchAll(/'((?:[^']|'')*)'/g)].map((e) => e[1].replace(/''/g, "'"));
|
|
1972
1985
|
n.length > 0 && t.set(e[1], n);
|
|
1973
1986
|
}
|
|
1974
|
-
let o = yield* e.unsafe(`PRAGMA table_xinfo(${n(i)})`), s = yield* e.unsafe(`PRAGMA foreign_key_list(${n(i)})`), c = yield* e.unsafe(`PRAGMA index_list(${n(i)})`), l = new Map(s.map((e) => [e.from, e])), u = o.filter((e) => e.pk > 0).sort((e, t) => e.pk - t.pk).map((e) => e.name), d = /* @__PURE__ */ new Map(),
|
|
1987
|
+
let o = yield* e.unsafe(`PRAGMA table_xinfo(${n(i)})`), s = yield* e.unsafe(`PRAGMA foreign_key_list(${n(i)})`), c = yield* e.unsafe(`PRAGMA index_list(${n(i)})`), l = new Map(s.map((e) => [e.from, e])), u = o.filter((e) => e.pk > 0).sort((e, t) => e.pk - t.pk).map((e) => e.name), d = new Map(o.map((e) => [e.name.toLowerCase(), e.name])), f = /* @__PURE__ */ new Map(), p = /* @__PURE__ */ new Set();
|
|
1975
1988
|
for (let t of c) {
|
|
1976
|
-
let r = (yield* e.unsafe(`PRAGMA index_info(${n(t.name)})`)).map((e) => e.name).filter((e) => e !== null);
|
|
1977
|
-
|
|
1989
|
+
let r = (yield* e.unsafe(`PRAGMA index_info(${n(t.name)})`)).map((e) => e.name).filter((e) => e !== null).map((e) => d.get(e.toLowerCase()) ?? e);
|
|
1990
|
+
f.set(t.name, r), qn(t.unique) && r.length === 1 && p.add(r[0]);
|
|
1978
1991
|
}
|
|
1979
|
-
let
|
|
1980
|
-
let n = u.length === 1 && u[0] === e.name, r = l.get(e.name), i = r ? "reference" : n && e.name === "id" ? "id" :
|
|
1992
|
+
let m = o.map((e) => {
|
|
1993
|
+
let n = u.length === 1 && u[0] === e.name, r = l.get(e.name), i = r ? "reference" : n && e.name === "id" ? "id" : Kn(e.type), a = r ? {
|
|
1981
1994
|
table: r.table,
|
|
1982
1995
|
column: r.to,
|
|
1983
1996
|
onDelete: z(r.on_delete),
|
|
@@ -1987,37 +2000,37 @@ BEGIN
|
|
|
1987
2000
|
name: e.name,
|
|
1988
2001
|
type: i,
|
|
1989
2002
|
nullable: e.notnull === 0,
|
|
1990
|
-
unique:
|
|
2003
|
+
unique: p.has(e.name) || n && e.name === "id",
|
|
1991
2004
|
hasDefault: e.dflt_value !== null,
|
|
1992
2005
|
...e.dflt_value === null ? {} : { defaultValue: e.dflt_value },
|
|
1993
2006
|
...a ? { references: a } : {},
|
|
1994
2007
|
...o ? { oneOf: o } : {},
|
|
1995
|
-
...
|
|
2008
|
+
...Ln(e.hidden === 2 || e.hidden === 3 ? "generated" : null, e.hidden === 3) ?? {}
|
|
1996
2009
|
};
|
|
1997
|
-
}),
|
|
2010
|
+
}), h = new Set(s.map((e) => e.from)), g = [];
|
|
1998
2011
|
for (let e of c) {
|
|
1999
2012
|
if (e.origin === "pk") continue;
|
|
2000
|
-
let t =
|
|
2001
|
-
|
|
2013
|
+
let t = f.get(e.name) ?? [];
|
|
2014
|
+
t.length === 1 && qn(e.unique) || t.length === 1 && !qn(e.unique) && h.has(t[0]) && e.name !== `${i}_${t[0]}_idx` || g.push({
|
|
2002
2015
|
name: e.name,
|
|
2003
2016
|
table: i,
|
|
2004
2017
|
columns: t,
|
|
2005
|
-
unique: e.unique
|
|
2006
|
-
})
|
|
2018
|
+
unique: qn(e.unique)
|
|
2019
|
+
});
|
|
2007
2020
|
}
|
|
2008
|
-
u.length > 0 &&
|
|
2021
|
+
u.length > 0 && g.push({
|
|
2009
2022
|
name: `${i}_pkey`,
|
|
2010
2023
|
table: i,
|
|
2011
2024
|
columns: u,
|
|
2012
2025
|
unique: !0
|
|
2013
2026
|
}), r.push({
|
|
2014
2027
|
name: i,
|
|
2015
|
-
columns:
|
|
2016
|
-
indexes:
|
|
2028
|
+
columns: m,
|
|
2029
|
+
indexes: g
|
|
2017
2030
|
});
|
|
2018
2031
|
}
|
|
2019
2032
|
return { tables: r };
|
|
2020
|
-
}),
|
|
2033
|
+
}), Yn = (e) => {
|
|
2021
2034
|
switch (e.toLowerCase()) {
|
|
2022
2035
|
case "int":
|
|
2023
2036
|
case "smallint":
|
|
@@ -2039,7 +2052,7 @@ BEGIN
|
|
|
2039
2052
|
case "image": return "bytes";
|
|
2040
2053
|
default: return "text";
|
|
2041
2054
|
}
|
|
2042
|
-
}, V = (e) => e === !0 || e === 1,
|
|
2055
|
+
}, V = (e) => e === !0 || e === 1, Xn = (e) => S.gen(function* () {
|
|
2043
2056
|
let t = yield* e`
|
|
2044
2057
|
SELECT TABLE_NAME AS table_name FROM INFORMATION_SCHEMA.TABLES
|
|
2045
2058
|
WHERE TABLE_TYPE = 'BASE TABLE' ORDER BY TABLE_NAME`, n = yield* e`
|
|
@@ -2105,12 +2118,12 @@ BEGIN
|
|
|
2105
2118
|
else V(t[0].is_unique) && t.length === 1 && p.add(t[0].column_name);
|
|
2106
2119
|
}
|
|
2107
2120
|
let m = t.map((t) => {
|
|
2108
|
-
let n = s.length === 1 && s[0] === t.column_name, a = r.get(t.column_name), o = a ? "reference" : n && t.column_name === "id" ? "id" :
|
|
2121
|
+
let n = s.length === 1 && s[0] === t.column_name, a = r.get(t.column_name), o = a ? "reference" : n && t.column_name === "id" ? "id" : Yn(t.data_type), l = a ? {
|
|
2109
2122
|
table: a.target_table,
|
|
2110
2123
|
column: a.target_column,
|
|
2111
|
-
onDelete:
|
|
2112
|
-
onUpdate:
|
|
2113
|
-
} : void 0, u = t.column_default === null ? null :
|
|
2124
|
+
onDelete: Zn(a.delete_rule),
|
|
2125
|
+
onUpdate: Zn(a.update_rule)
|
|
2126
|
+
} : void 0, u = t.column_default === null ? null : Qn(t.column_default), d = c.get(`${e}.${t.column_name}`);
|
|
2114
2127
|
return {
|
|
2115
2128
|
name: t.column_name,
|
|
2116
2129
|
type: o,
|
|
@@ -2121,7 +2134,7 @@ BEGIN
|
|
|
2121
2134
|
...u === null ? {} : { defaultValue: u },
|
|
2122
2135
|
...l ? { references: l } : {},
|
|
2123
2136
|
...d ? { oneOf: d } : {},
|
|
2124
|
-
...
|
|
2137
|
+
...Ln(i.get(`${e}.${t.column_name}`)?.definition ?? null, V(i.get(`${e}.${t.column_name}`)?.is_persisted ?? !1)) ?? {}
|
|
2125
2138
|
};
|
|
2126
2139
|
}), h = [];
|
|
2127
2140
|
if (o) for (let [t, n] of o) {
|
|
@@ -2145,18 +2158,18 @@ BEGIN
|
|
|
2145
2158
|
});
|
|
2146
2159
|
}
|
|
2147
2160
|
return { tables: f };
|
|
2148
|
-
}),
|
|
2161
|
+
}), Zn = (e) => {
|
|
2149
2162
|
switch (e.toUpperCase().replace(/_/g, " ")) {
|
|
2150
2163
|
case "CASCADE": return "cascade";
|
|
2151
2164
|
case "SET NULL": return "setNull";
|
|
2152
2165
|
case "SET DEFAULT": return "noAction";
|
|
2153
2166
|
default: return "noAction";
|
|
2154
2167
|
}
|
|
2155
|
-
},
|
|
2168
|
+
}, Qn = (e) => {
|
|
2156
2169
|
let t = e.trim();
|
|
2157
2170
|
for (; t.startsWith("(") && t.endsWith(")");) t = t.slice(1, -1).trim();
|
|
2158
2171
|
return t.startsWith("N'") && t.endsWith("'") ? t = t.slice(2, -1) : t.startsWith("'") && t.endsWith("'") && (t = t.slice(1, -1)), t;
|
|
2159
|
-
},
|
|
2172
|
+
}, $n = /* @__PURE__ */ new Set([
|
|
2160
2173
|
"character varying",
|
|
2161
2174
|
"varchar",
|
|
2162
2175
|
"nvarchar",
|
|
@@ -2164,71 +2177,71 @@ BEGIN
|
|
|
2164
2177
|
"character",
|
|
2165
2178
|
"nchar"
|
|
2166
2179
|
]), H = (e, t) => {
|
|
2167
|
-
if (
|
|
2180
|
+
if (!$n.has(e.toLowerCase())) return;
|
|
2168
2181
|
let n = Number(t);
|
|
2169
2182
|
if (!(!Number.isFinite(n) || n <= 0)) return n;
|
|
2170
|
-
},
|
|
2171
|
-
mysql: () =>
|
|
2172
|
-
mssql: () =>
|
|
2173
|
-
sqlite: () =>
|
|
2174
|
-
orElse: () =>
|
|
2183
|
+
}, er = /* @__PURE__ */ new Set([k]), tr = (e) => e.onDialectOrElse({
|
|
2184
|
+
mysql: () => Gn(e),
|
|
2185
|
+
mssql: () => Xn(e),
|
|
2186
|
+
sqlite: () => Jn(e),
|
|
2187
|
+
orElse: () => Un(e)
|
|
2175
2188
|
}).pipe(S.map((e) => ({
|
|
2176
2189
|
...e,
|
|
2177
|
-
tables: e.tables.filter((e) => !
|
|
2178
|
-
}))),
|
|
2179
|
-
let t =
|
|
2180
|
-
return t === void 0 ?
|
|
2181
|
-
}),
|
|
2190
|
+
tables: e.tables.filter((e) => !er.has(e.name))
|
|
2191
|
+
}))), nr = (e) => /mariadb/i.test(e) ? "mariadb" : "mysql", rr = /* @__PURE__ */ new WeakMap(), ir = (e) => S.suspend(() => {
|
|
2192
|
+
let t = rr.get(e);
|
|
2193
|
+
return t === void 0 ? ar(e).pipe(S.tap((t) => S.sync(() => rr.set(e, t)))) : S.succeed(t);
|
|
2194
|
+
}), ar = (e) => e.unsafe("SELECT VERSION() AS v").pipe(S.map((e) => {
|
|
2182
2195
|
let t = e[0]?.v;
|
|
2183
|
-
return typeof t == "string" ?
|
|
2184
|
-
}), S.catchAll(() => S.succeed("mysql"))),
|
|
2196
|
+
return typeof t == "string" ? nr(t) : "mysql";
|
|
2197
|
+
}), S.catchAll(() => S.succeed("mysql"))), or = (e) => {
|
|
2185
2198
|
let t = e;
|
|
2186
2199
|
for (let e = 0; e < 6 && typeof t == "object" && t; e++) {
|
|
2187
2200
|
let e = t;
|
|
2188
2201
|
if (typeof e.errno == "number") return e.errno;
|
|
2189
2202
|
t = e.cause;
|
|
2190
2203
|
}
|
|
2191
|
-
},
|
|
2204
|
+
}, sr = (e) => {
|
|
2192
2205
|
let t = [], n = e;
|
|
2193
2206
|
for (let e = 0; e < 6 && typeof n == "object" && n; e++) {
|
|
2194
2207
|
let e = n;
|
|
2195
2208
|
typeof e.message == "string" && t.push(e.message), n = e.cause;
|
|
2196
2209
|
}
|
|
2197
2210
|
return t.join(" | ");
|
|
2198
|
-
},
|
|
2211
|
+
}, cr = (e, t) => {
|
|
2199
2212
|
if (t.length === 0) return !1;
|
|
2200
|
-
let n =
|
|
2213
|
+
let n = or(e), r = sr(e);
|
|
2201
2214
|
return t.some((e) => e.errno !== void 0 && n !== void 0 && e.errno.includes(n) || e.messageIncludes !== void 0 && e.messageIncludes.some((e) => r.includes(e)));
|
|
2202
|
-
},
|
|
2215
|
+
}, lr = {
|
|
2203
2216
|
why: "mysql has no CREATE INDEX IF NOT EXISTS; 1061 is exactly that condition",
|
|
2204
2217
|
errno: [1061]
|
|
2205
|
-
},
|
|
2218
|
+
}, ur = {
|
|
2206
2219
|
why: "mysql has no DROP COLUMN IF EXISTS; 1091 is exactly that condition",
|
|
2207
2220
|
errno: [1091]
|
|
2208
|
-
},
|
|
2221
|
+
}, dr = {
|
|
2209
2222
|
why: "sqlite has no DROP COLUMN IF EXISTS, and reports the absent column only in the message",
|
|
2210
2223
|
messageIncludes: ["no such column"]
|
|
2211
|
-
},
|
|
2224
|
+
}, fr = {
|
|
2212
2225
|
why: "mysql/mariadb DROP CONSTRAINT has no portable IF EXISTS; 1091 / 3940 are exactly \"already gone\"",
|
|
2213
2226
|
errno: [1091, 3940]
|
|
2214
|
-
},
|
|
2227
|
+
}, U = (e, t) => e.onDialectOrElse({
|
|
2215
2228
|
mysql: () => S.succeed(t.replace("T", " ").replace("Z", "")),
|
|
2216
2229
|
orElse: () => S.succeed(t)
|
|
2217
|
-
}),
|
|
2218
|
-
if ((e.type !== "text" || e.maxLength === void 0) && !
|
|
2230
|
+
}), pr = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, mr = (e) => e.type === "text" && (e.hasDefault && e.defaultValue !== void 0 || e.oneOf !== void 0 && e.oneOf.length > 0), hr = (e, t) => {
|
|
2231
|
+
if ((e.type !== "text" || e.maxLength === void 0) && !mr(e) && !e.spatial && e.type !== "vector" && e.type !== "array" && e.type !== "enum") return;
|
|
2219
2232
|
let n = e.type === "vector" && e.vectorDim === void 0 ? "vector dimension" : e.type === "array" && e.arrayElement === void 0 ? "array element type" : e.type === "enum" && e.enumName === void 0 && e.enumValues === void 0 ? "enum name/values" : void 0;
|
|
2220
2233
|
if (n !== void 0) throw Error(`migration applier: cannot render '${e.name}' (${e.type}) — the schema snapshot carries no ${n}. Rendering it as 'text' would emit DDL that applies successfully and changes nothing, so this fails instead. This is a framework bug: declaredSchema.ts must carry the parameter into the ColumnSnapshot.`);
|
|
2221
2234
|
return M(e, t);
|
|
2222
|
-
},
|
|
2223
|
-
let t =
|
|
2224
|
-
return t === void 0 ?
|
|
2225
|
-
},
|
|
2235
|
+
}, gr = (e) => {
|
|
2236
|
+
let t = hr(e, "postgres");
|
|
2237
|
+
return t === void 0 ? _r(e) : t;
|
|
2238
|
+
}, _r = (e) => {
|
|
2226
2239
|
switch (e.type) {
|
|
2227
2240
|
case "id": return "text";
|
|
2228
2241
|
case "text": return "text";
|
|
2229
2242
|
case "integer": return "integer";
|
|
2230
2243
|
case "real": return "double precision";
|
|
2231
|
-
case "decimal": return
|
|
2244
|
+
case "decimal": return pr(e, "NUMERIC");
|
|
2232
2245
|
case "bigint": return "bigint";
|
|
2233
2246
|
case "boolean": return "boolean";
|
|
2234
2247
|
case "timestamp": return "timestamptz";
|
|
@@ -2242,15 +2255,15 @@ BEGIN
|
|
|
2242
2255
|
case "interval": return "interval";
|
|
2243
2256
|
case "raw": return e.rawDdl ?? "text";
|
|
2244
2257
|
}
|
|
2245
|
-
},
|
|
2246
|
-
let t =
|
|
2258
|
+
}, vr = (e) => {
|
|
2259
|
+
let t = hr(e, "mariadb");
|
|
2247
2260
|
if (t !== void 0) return t;
|
|
2248
2261
|
switch (e.type) {
|
|
2249
2262
|
case "id": return "VARCHAR(64)";
|
|
2250
2263
|
case "text": return "LONGTEXT";
|
|
2251
2264
|
case "integer": return "INT";
|
|
2252
2265
|
case "real": return "DOUBLE";
|
|
2253
|
-
case "decimal": return
|
|
2266
|
+
case "decimal": return pr(e, "DECIMAL");
|
|
2254
2267
|
case "bigint": return "BIGINT";
|
|
2255
2268
|
case "boolean": return "TINYINT(1)";
|
|
2256
2269
|
case "timestamp": return "DATETIME(6)";
|
|
@@ -2264,64 +2277,64 @@ BEGIN
|
|
|
2264
2277
|
case "interval": return "BIGINT";
|
|
2265
2278
|
case "raw": return e.rawDdl ?? "LONGTEXT";
|
|
2266
2279
|
}
|
|
2267
|
-
},
|
|
2280
|
+
}, W = (e) => `"${e}"`, G = (e) => `\`${e.replace(/`/g, "``")}\``, yr = (e) => e === "mariadb" ? "IF NOT EXISTS " : "", br = (e, t, n = !0) => `ALTER TABLE ${t(e.table)} DROP COLUMN ${n ? "IF EXISTS " : ""}${t(e.column)};`, xr = (e, t = "mariadb") => `ALTER TABLE ${G(e.table)} DROP COLUMN ${t === "mariadb" ? "IF EXISTS " : ""}${G(e.column)}, ALGORITHM=COPY;`, Sr = (e, t) => `ALTER TABLE ${t(e.table)} RENAME COLUMN ${t(e.from)} TO ${t(e.to)};`, Cr = (e, t, n) => `ALTER TABLE ${n(e.table)} RENAME COLUMN ${n(e.column)} TO ${n(`${e.column}${Zr(t)}`)};`, wr = (e, t, n) => e.hasDefault && e.defaultValue !== void 0 ? `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} SET ${Er(e, n)};` : `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} DROP DEFAULT;`, Tr = (e, t) => {
|
|
2268
2281
|
let { defaultFactory: n, ...r } = e;
|
|
2269
2282
|
return M(e, t) !== M({
|
|
2270
2283
|
...r,
|
|
2271
2284
|
hasDefault: !1
|
|
2272
2285
|
}, t);
|
|
2273
|
-
},
|
|
2286
|
+
}, Er = (e, t) => {
|
|
2274
2287
|
let n = t(e.defaultValue);
|
|
2275
2288
|
if (n === null) throw Error(`migration applier: cannot render the declared default for '${e.table}.${e.column}' (${JSON.stringify(e.defaultValue)}). Emitting 'DEFAULT NULL' would apply cleanly and drop the default silently, so this fails instead. This is a framework bug — report the column type + default.`);
|
|
2276
2289
|
return n;
|
|
2277
|
-
},
|
|
2278
|
-
let r =
|
|
2279
|
-
return r ?
|
|
2280
|
-
},
|
|
2281
|
-
let r = n ?? e.nullable, i =
|
|
2290
|
+
}, K = (e, t, n) => e.find((e) => e.tableName === t)?.fields[n], Dr = (e, t, n) => {
|
|
2291
|
+
let r = K(e, t, n);
|
|
2292
|
+
return r ? qt(n, r) : void 0;
|
|
2293
|
+
}, Or = (e, t, n) => {
|
|
2294
|
+
let r = n ?? e.nullable, i = $e(e, "mariadb");
|
|
2282
2295
|
return [
|
|
2283
|
-
|
|
2296
|
+
G(t),
|
|
2284
2297
|
M(e, "mariadb"),
|
|
2285
2298
|
r ? null : "NOT NULL",
|
|
2286
2299
|
i
|
|
2287
2300
|
].filter(Boolean).join(" ");
|
|
2288
|
-
},
|
|
2301
|
+
}, kr = (e, t) => e == null ? null : Array.isArray(e) ? Ar(e, t, "mariadb") : e === "now" ? "DEFAULT CURRENT_TIMESTAMP(6)" : typeof e == "boolean" ? `DEFAULT ${+!!e}` : typeof e == "number" ? `DEFAULT ${e}` : typeof e == "string" ? /[()]|^'/.test(e) ? `DEFAULT ${e}` : `DEFAULT '${e.replace(/'/g, "''")}'` : typeof e == "object" ? N(e, "mariadb") : null, Ar = (e, t, n) => et(e, t ?? { type: "json" }, n), jr = (e, t) => e == null ? null : Array.isArray(e) ? Ar(e, t, "postgres") : e === "now" ? "DEFAULT now()" : typeof e == "boolean" || typeof e == "number" ? `DEFAULT ${e}` : typeof e == "string" ? /[()]|::|^'/.test(e) ? `DEFAULT ${e}` : `DEFAULT '${e.replace(/'/g, "''")}'` : typeof e == "object" ? N(e, "postgres") : null, q = (e, t) => {
|
|
2289
2302
|
if (!e.generatedAs) return null;
|
|
2290
2303
|
let { expr: n, stored: r } = e.generatedAs;
|
|
2291
2304
|
return t === "postgres" ? `GENERATED ALWAYS AS (${n}) STORED` : t === "mssql" ? `AS (${n})${r ? " PERSISTED" : ""}` : `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
|
|
2292
|
-
},
|
|
2305
|
+
}, Mr = (e) => {
|
|
2293
2306
|
if (e.type === "id" && e.idScheme?.kind === "numeric") return P(e.name, "postgres");
|
|
2294
|
-
let t =
|
|
2295
|
-
if (t) return `${
|
|
2296
|
-
let n = [
|
|
2307
|
+
let t = q(e, "postgres");
|
|
2308
|
+
if (t) return `${W(e.name)} ${gr(e)} ${t}`;
|
|
2309
|
+
let n = [W(e.name), gr(e)];
|
|
2297
2310
|
if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && n.push("UNIQUE"), e.hasDefault) {
|
|
2298
|
-
let t =
|
|
2311
|
+
let t = jr(e.defaultValue, e);
|
|
2299
2312
|
t && n.push(t);
|
|
2300
2313
|
}
|
|
2301
|
-
return e.references && (n.push(`REFERENCES ${
|
|
2314
|
+
return e.references && (n.push(`REFERENCES ${W(e.references.table)} (${W(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${{
|
|
2302
2315
|
cascade: "CASCADE",
|
|
2303
2316
|
restrict: "RESTRICT",
|
|
2304
2317
|
setNull: "SET NULL",
|
|
2305
2318
|
noAction: "NO ACTION"
|
|
2306
2319
|
}[e.references.onDelete]}`)), n.join(" ");
|
|
2307
|
-
},
|
|
2308
|
-
let t = e.columns.map((e) => ` ${
|
|
2309
|
-
for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${
|
|
2320
|
+
}, Nr = (e, t) => e.primaryKey && e.primaryKey.length > 0 ? `,\n PRIMARY KEY (${e.primaryKey.map(t).join(", ")})` : "", Pr = (e) => {
|
|
2321
|
+
let t = e.columns.map((e) => ` ${Mr(e)}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${W(e.table)} (\n${t}${Nr(e, W)}\n)`];
|
|
2322
|
+
for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${W(t.name)} ON ${W(e.table)} (${t.columns.map(ni).join(", ")})`);
|
|
2310
2323
|
return n;
|
|
2311
|
-
},
|
|
2312
|
-
let t =
|
|
2324
|
+
}, Fr = 191, Ir = (e) => {
|
|
2325
|
+
let t = vr(e).toUpperCase();
|
|
2313
2326
|
return t.endsWith("TEXT") || t.endsWith("BLOB");
|
|
2314
|
-
},
|
|
2327
|
+
}, Lr = (e) => {
|
|
2315
2328
|
if (e.type === "id" && e.idScheme?.kind === "numeric") return P(e.name, "mariadb");
|
|
2316
|
-
let t =
|
|
2317
|
-
if (t) return `${
|
|
2318
|
-
let n = [
|
|
2319
|
-
if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && !
|
|
2320
|
-
let t =
|
|
2329
|
+
let t = q(e, "mariadb");
|
|
2330
|
+
if (t) return `${G(e.name)} ${vr(e)} ${t}`;
|
|
2331
|
+
let n = [G(e.name), vr(e)];
|
|
2332
|
+
if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && !Ir(e) && n.push("UNIQUE"), e.hasDefault) {
|
|
2333
|
+
let t = kr(e.defaultValue, e);
|
|
2321
2334
|
t && n.push(t);
|
|
2322
2335
|
}
|
|
2323
2336
|
return n.join(" ");
|
|
2324
|
-
},
|
|
2337
|
+
}, Rr = (e) => e.columns.flatMap((t) => {
|
|
2325
2338
|
if (!t.references) return [];
|
|
2326
2339
|
let n = t.references.onDelete ? ` ON DELETE ${{
|
|
2327
2340
|
cascade: "CASCADE",
|
|
@@ -2329,27 +2342,27 @@ BEGIN
|
|
|
2329
2342
|
setNull: "SET NULL",
|
|
2330
2343
|
noAction: "NO ACTION"
|
|
2331
2344
|
}[t.references.onDelete]}` : "";
|
|
2332
|
-
return [` CONSTRAINT ${
|
|
2333
|
-
}),
|
|
2345
|
+
return [` CONSTRAINT ${G(`${e.table}_${t.name}_fkey`)} FOREIGN KEY (${G(t.name)}) REFERENCES ${G(t.references.table)} (${G(t.references.column)})${n}`];
|
|
2346
|
+
}), zr = (e, t = "mariadb") => {
|
|
2334
2347
|
let n = new Map(e.columns.map((e) => [e.name, e])), r = (e) => {
|
|
2335
|
-
let t =
|
|
2336
|
-
return t === void 0 ?
|
|
2337
|
-
}, i = e.columns.map((e) => ` ${
|
|
2338
|
-
for (let n of e.columns) n.unique && n.type !== "id" &&
|
|
2339
|
-
for (let n of e.indexes) n.name !== `${e.table}_pkey` && s.push(`CREATE ${n.unique ? "UNIQUE " : ""}INDEX ${
|
|
2348
|
+
let t = ei(n.get(e));
|
|
2349
|
+
return t === void 0 ? G(e) : `${G(e)}(${t})`;
|
|
2350
|
+
}, i = e.columns.map((e) => ` ${Lr(e)}`).join(",\n"), a = Rr(e), o = a.length > 0 ? `${i},\n${a.join(",\n")}` : i, s = [`CREATE TABLE IF NOT EXISTS ${G(e.table)} (\n${o}${Nr(e, r)}\n)`];
|
|
2351
|
+
for (let n of e.columns) n.unique && n.type !== "id" && Ir(n) && s.push(`CREATE UNIQUE INDEX ${yr(t)}${G(`${e.table}_${n.name}_key`)} ON ${G(e.table)} (${r(n.name)})`);
|
|
2352
|
+
for (let n of e.indexes) n.name !== `${e.table}_pkey` && s.push(`CREATE ${n.unique ? "UNIQUE " : ""}INDEX ${yr(t)}${G(n.name)} ON ${G(e.table)} (${n.columns.map(r).join(", ")})`);
|
|
2340
2353
|
return s;
|
|
2341
|
-
},
|
|
2354
|
+
}, Br = {
|
|
2342
2355
|
cascade: "CASCADE",
|
|
2343
2356
|
restrict: "RESTRICT",
|
|
2344
2357
|
setNull: "SET NULL",
|
|
2345
2358
|
noAction: "NO ACTION"
|
|
2346
|
-
},
|
|
2359
|
+
}, Vr = {
|
|
2347
2360
|
cascade: "CASCADE",
|
|
2348
2361
|
restrict: "NO ACTION",
|
|
2349
2362
|
setNull: "SET NULL",
|
|
2350
2363
|
noAction: "NO ACTION"
|
|
2351
|
-
},
|
|
2352
|
-
let t =
|
|
2364
|
+
}, Hr = (e) => {
|
|
2365
|
+
let t = hr(e, "sqlite");
|
|
2353
2366
|
if (t !== void 0) return t;
|
|
2354
2367
|
switch (e.type) {
|
|
2355
2368
|
case "integer":
|
|
@@ -2360,60 +2373,60 @@ BEGIN
|
|
|
2360
2373
|
case "bytes": return "BLOB";
|
|
2361
2374
|
default: return "TEXT";
|
|
2362
2375
|
}
|
|
2363
|
-
},
|
|
2376
|
+
}, Ur = (e, t) => e == null ? null : e === "now" ? `DEFAULT ${t}` : typeof e == "boolean" ? `DEFAULT ${+!!e}` : typeof e == "number" ? `DEFAULT ${e}` : typeof e == "string" ? /[()]|^'/.test(e) ? `DEFAULT ${e}` : `DEFAULT '${e.replace(/'/g, "''")}'` : typeof e == "object" ? N(e, "sqlite") : null, Wr = (e) => {
|
|
2364
2377
|
if (e.type === "id" && e.idScheme?.kind === "numeric") return P(e.name, "sqlite");
|
|
2365
|
-
let t =
|
|
2366
|
-
if (t) return `${
|
|
2367
|
-
let n = [
|
|
2378
|
+
let t = q(e, "sqlite");
|
|
2379
|
+
if (t) return `${W(e.name)} ${Hr(e)} ${t}`;
|
|
2380
|
+
let n = [W(e.name), Hr(e)];
|
|
2368
2381
|
if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && n.push("UNIQUE"), e.hasDefault) {
|
|
2369
|
-
let t =
|
|
2382
|
+
let t = Ur(e.defaultValue, "CURRENT_TIMESTAMP");
|
|
2370
2383
|
t && n.push(t);
|
|
2371
2384
|
}
|
|
2372
|
-
if (e.references && (n.push(`REFERENCES ${
|
|
2385
|
+
if (e.references && (n.push(`REFERENCES ${W(e.references.table)} (${W(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${Br[e.references.onDelete]}`)), e.oneOf && e.oneOf.length > 0) {
|
|
2373
2386
|
let t = e.oneOf.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
|
|
2374
|
-
n.push(`CHECK (${
|
|
2387
|
+
n.push(`CHECK (${W(e.name)} IN (${t}))`);
|
|
2375
2388
|
}
|
|
2376
2389
|
return n.join(" ");
|
|
2377
|
-
},
|
|
2378
|
-
let t = e.columns.map((e) => ` ${
|
|
2379
|
-
for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${
|
|
2390
|
+
}, Gr = (e) => {
|
|
2391
|
+
let t = e.columns.map((e) => ` ${Wr(e)}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${W(e.table)} (\n${t}${Nr(e, W)}\n)`];
|
|
2392
|
+
for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${W(t.name)} ON ${W(e.table)} (${t.columns.map(W).join(", ")})`);
|
|
2380
2393
|
return n;
|
|
2381
2394
|
}, J = (e, t) => {
|
|
2382
2395
|
let n = t.find((t) => t.tableName === e);
|
|
2383
2396
|
if (!n) return [];
|
|
2384
|
-
let r = I([n]).tables[0], i = `${e}__voltro_rebuild`, a = r.columns.map((e) =>
|
|
2385
|
-
...
|
|
2397
|
+
let r = I([n]).tables[0], i = `${e}__voltro_rebuild`, a = r.columns.map((e) => W(e.name)).join(", "), o = [
|
|
2398
|
+
...Gr({
|
|
2386
2399
|
kind: "create-table",
|
|
2387
2400
|
table: i,
|
|
2388
2401
|
columns: r.columns,
|
|
2389
2402
|
indexes: [],
|
|
2390
2403
|
...r.primaryKey ? { primaryKey: r.primaryKey } : {}
|
|
2391
2404
|
}),
|
|
2392
|
-
`INSERT INTO ${
|
|
2393
|
-
`DROP TABLE ${
|
|
2394
|
-
`ALTER TABLE ${
|
|
2405
|
+
`INSERT INTO ${W(i)} (${a}) SELECT ${a} FROM ${W(e)}`,
|
|
2406
|
+
`DROP TABLE ${W(e)}`,
|
|
2407
|
+
`ALTER TABLE ${W(i)} RENAME TO ${W(e)}`
|
|
2395
2408
|
];
|
|
2396
|
-
for (let t of r.indexes) t.name !== `${e}_pkey` && o.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${
|
|
2409
|
+
for (let t of r.indexes) t.name !== `${e}_pkey` && o.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${W(t.name)} ON ${W(e)} (${t.columns.map(W).join(", ")})`);
|
|
2397
2410
|
return o;
|
|
2398
|
-
},
|
|
2411
|
+
}, Kr = (e, t, n, r) => {
|
|
2399
2412
|
let i = r ?? e.nullable;
|
|
2400
2413
|
return `ALTER TABLE ${Y(n)} ALTER COLUMN ${Y(t)} ${M(e, "mssql")} ${i ? "NULL" : "NOT NULL"};`;
|
|
2401
|
-
},
|
|
2414
|
+
}, qr = (e, t) => {
|
|
2402
2415
|
let n = `DECLARE @dc sysname; SELECT @dc = dc.name FROM sys.default_constraints dc JOIN sys.columns col ON col.object_id = dc.parent_object_id AND col.column_id = dc.parent_column_id WHERE dc.parent_object_id = OBJECT_ID(N'${e.table.replace(/'/g, "''")}') AND col.name = N'${e.column.replace(/'/g, "''")}'; IF @dc IS NOT NULL EXEC(N'ALTER TABLE ${Y(e.table)} DROP CONSTRAINT [' + @dc + ']');` + (t ? ` ${t}` : "");
|
|
2403
2416
|
if (!e.hasDefault) return n;
|
|
2404
|
-
let r =
|
|
2417
|
+
let r = Ur(e.defaultValue, "SYSUTCDATETIME()");
|
|
2405
2418
|
if (!r) return n;
|
|
2406
2419
|
let i = r.replace(/^DEFAULT\s+/i, "");
|
|
2407
2420
|
return `${n} ALTER TABLE ${Y(e.table)} ADD DEFAULT ${i} FOR ${Y(e.column)};`;
|
|
2408
|
-
}, Y = (e) => `[${e.replace(/]/g, "]]")}]`,
|
|
2409
|
-
let t =
|
|
2421
|
+
}, Y = (e) => `[${e.replace(/]/g, "]]")}]`, Jr = (e) => {
|
|
2422
|
+
let t = hr(e, "mssql");
|
|
2410
2423
|
if (t !== void 0) return t;
|
|
2411
2424
|
switch (e.type) {
|
|
2412
2425
|
case "id":
|
|
2413
2426
|
case "reference": return "NVARCHAR(64)";
|
|
2414
2427
|
case "integer": return "INT";
|
|
2415
2428
|
case "real": return "FLOAT";
|
|
2416
|
-
case "decimal": return
|
|
2429
|
+
case "decimal": return pr(e, "DECIMAL");
|
|
2417
2430
|
case "bigint": return "BIGINT";
|
|
2418
2431
|
case "boolean": return "BIT";
|
|
2419
2432
|
case "timestamp": return "DATETIME2(6)";
|
|
@@ -2421,44 +2434,44 @@ BEGIN
|
|
|
2421
2434
|
case "bytes": return "VARBINARY(MAX)";
|
|
2422
2435
|
default: return "NVARCHAR(MAX)";
|
|
2423
2436
|
}
|
|
2424
|
-
},
|
|
2437
|
+
}, Yr = (e, t) => {
|
|
2425
2438
|
if (e.type === "id" && e.idScheme?.kind === "numeric") return P(e.name, "mssql");
|
|
2426
|
-
let n = e.type === "text" && t?.has(e.name) ? "NVARCHAR(450)" :
|
|
2439
|
+
let n = e.type === "text" && t?.has(e.name) ? "NVARCHAR(450)" : Jr(e), r = q(e, "mssql");
|
|
2427
2440
|
if (r) return `${Y(e.name)} ${r}`;
|
|
2428
2441
|
let i = [Y(e.name), n];
|
|
2429
2442
|
if (e.type === "id" && i.push("PRIMARY KEY"), e.nullable || i.push("NOT NULL"), e.unique && e.type !== "id" && i.push("UNIQUE"), e.hasDefault) {
|
|
2430
|
-
let t =
|
|
2443
|
+
let t = Ur(e.defaultValue, "SYSUTCDATETIME()");
|
|
2431
2444
|
t && i.push(t);
|
|
2432
2445
|
}
|
|
2433
|
-
return e.references && (i.push(`REFERENCES ${Y(e.references.table)} (${Y(e.references.column)})`), e.references.onDelete && i.push(`ON DELETE ${
|
|
2434
|
-
},
|
|
2435
|
-
let t = (e) => e.replace(/'/g, "''"), n = new Set(e.indexes.flatMap((e) => e.columns)), r = e.columns.map((e) => ` ${
|
|
2446
|
+
return e.references && (i.push(`REFERENCES ${Y(e.references.table)} (${Y(e.references.column)})`), e.references.onDelete && i.push(`ON DELETE ${Vr[e.references.onDelete]}`)), i.join(" ");
|
|
2447
|
+
}, Xr = (e) => {
|
|
2448
|
+
let t = (e) => e.replace(/'/g, "''"), n = /* @__PURE__ */ new Set([...e.indexes.flatMap((e) => e.columns), ...e.columns.filter((e) => e.unique).map((e) => e.name)]), r = e.columns.map((e) => ` ${Yr(e, n)}`).join(",\n"), i = `CREATE TABLE ${Y(e.table)} (\n${r}${Nr(e, Y)}\n)`, a = [`IF OBJECT_ID(N'${t(e.table)}', N'U') IS NULL EXEC(N'${t(i)}')`];
|
|
2436
2449
|
for (let n of e.indexes) {
|
|
2437
2450
|
if (n.name === `${e.table}_pkey`) continue;
|
|
2438
2451
|
let r = `CREATE ${n.unique ? "UNIQUE " : ""}INDEX ${Y(n.name)} ON ${Y(e.table)} (${n.columns.map(Y).join(", ")})`;
|
|
2439
2452
|
a.push(`IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = N'${t(n.name)}' AND object_id = OBJECT_ID(N'${t(e.table)}')) EXEC(N'${t(r)}')`);
|
|
2440
2453
|
}
|
|
2441
2454
|
return a;
|
|
2442
|
-
},
|
|
2443
|
-
let r = `${e.table}${
|
|
2455
|
+
}, Zr = (e) => `__dropped_${e.replace(/[-:T.Z]/g, "").slice(0, 14)}`, Qr = (e, t) => `DROP TABLE IF EXISTS ${t(e.table)};`, $r = (e, t, n) => {
|
|
2456
|
+
let r = `${e.table}${Zr(t)}`;
|
|
2444
2457
|
return `ALTER TABLE ${n(e.table)} RENAME TO ${n(r)};`;
|
|
2445
|
-
},
|
|
2446
|
-
if (e === void 0 || !
|
|
2458
|
+
}, ei = (e) => {
|
|
2459
|
+
if (e === void 0 || !Ir(e)) return;
|
|
2447
2460
|
let t = typeof e.maxLength == "number" && e.maxLength > 0 ? e.maxLength : void 0;
|
|
2448
|
-
return t === void 0 ?
|
|
2449
|
-
},
|
|
2450
|
-
let r =
|
|
2451
|
-
return r === void 0 ?
|
|
2452
|
-
},
|
|
2461
|
+
return t === void 0 ? Fr : Math.min(Fr, t);
|
|
2462
|
+
}, ti = (e, t, n) => {
|
|
2463
|
+
let r = ei(Dr(e, t, n));
|
|
2464
|
+
return r === void 0 ? G(n) : `${G(n)}(${r})`;
|
|
2465
|
+
}, ni = (e) => e.startsWith("(") ? e : W(e), ri = (e, t) => `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX ${t ? "CONCURRENTLY " : ""}IF NOT EXISTS ${W(e.index.name)} ON ${W(e.table)} (${e.index.columns.map(ni).join(", ")});`, ii = (e, t, n = "mariadb") => `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX ${yr(n)}${G(e.index.name)} ON ${G(e.table)} (${e.index.columns.map((n) => ti(t, e.table, n)).join(", ")});`, ai = (e) => `DROP INDEX IF EXISTS ${W(e.index)};`, oi = (e) => `DROP INDEX ${G(e.index)} ON ${G(e.table)};`, si = (e) => `DROP INDEX IF EXISTS ${Y(e.index)} ON ${Y(e.table)};`, ci = (e, t) => `ALTER TABLE ${t(e.from)} RENAME TO ${t(e.to)};`, li = (e) => {
|
|
2453
2466
|
let t = (e) => e.replace(/'/g, "''");
|
|
2454
2467
|
return `EXEC sp_rename N'${t(e.from)}', N'${t(e.to)}';`;
|
|
2455
|
-
},
|
|
2468
|
+
}, ui = (e) => `ALTER INDEX ${W(e.from)} RENAME TO ${W(e.to)};`, di = (e) => `ALTER TABLE ${G(e.table)} RENAME INDEX ${G(e.from)} TO ${G(e.to)};`, fi = (e) => {
|
|
2456
2469
|
let t = (e) => e.replace(/'/g, "''");
|
|
2457
2470
|
return `EXEC sp_rename N'${t(e.table)}.${t(e.from)}', N'${t(e.to)}', N'INDEX';`;
|
|
2458
|
-
},
|
|
2471
|
+
}, pi = (e) => {
|
|
2459
2472
|
let t = (e) => e.replace(/'/g, "''"), n = `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX ${Y(e.index.name)} ON ${Y(e.table)} (${e.index.columns.map(Y).join(", ")})`;
|
|
2460
2473
|
return `IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = N'${t(e.index.name)}' AND object_id = OBJECT_ID(N'${t(e.table)}')) EXEC(N'${t(n)}');`;
|
|
2461
|
-
},
|
|
2474
|
+
}, mi = (e, t, n) => {
|
|
2462
2475
|
let r = n.find((t) => t.tableName === e);
|
|
2463
2476
|
if (!r) return [];
|
|
2464
2477
|
let i = [];
|
|
@@ -2467,13 +2480,13 @@ BEGIN
|
|
|
2467
2480
|
t && t.type === "text" && !t.generatedAs && i.push(`ALTER TABLE ${Y(e)} ALTER COLUMN ${Y(n)} NVARCHAR(450) ${t.nullable ? "NULL" : "NOT NULL"};`);
|
|
2468
2481
|
}
|
|
2469
2482
|
return i;
|
|
2470
|
-
},
|
|
2471
|
-
let t = e.fields.map((e) =>
|
|
2472
|
-
return `ALTER TABLE ${
|
|
2473
|
-
},
|
|
2474
|
-
let n = e.fields.map((n) =>
|
|
2475
|
-
return `ALTER TABLE ${
|
|
2476
|
-
},
|
|
2483
|
+
}, hi = (e) => `ALTER TABLE ${W(e.table)} ADD CONSTRAINT ${W(`${e.table}_${e.column}_key`)} UNIQUE (${W(e.column)});`, gi = (e, t) => `ALTER TABLE ${G(e.table)} ADD CONSTRAINT ${G(`${e.table}_${e.column}_key`)} UNIQUE (${ti(t, e.table, e.column)});`, _i = (e) => {
|
|
2484
|
+
let t = e.fields.map((e) => W(e)).join(", ");
|
|
2485
|
+
return `ALTER TABLE ${W(e.table)} ADD CONSTRAINT ${W(e.name)} UNIQUE (${t});`;
|
|
2486
|
+
}, vi = (e, t) => {
|
|
2487
|
+
let n = e.fields.map((n) => ti(t, e.table, n)).join(", ");
|
|
2488
|
+
return `ALTER TABLE ${G(e.table)} ADD CONSTRAINT ${G(e.name)} UNIQUE (${n});`;
|
|
2489
|
+
}, yi = (e) => `ALTER TABLE ${W(e.table)} DROP CONSTRAINT IF EXISTS ${W(e.name)};`, bi = (e) => `ALTER TABLE ${G(e.table)} DROP INDEX ${G(e.name)};`, xi = (e) => `ALTER TABLE ${W(e.table)} DROP CONSTRAINT IF EXISTS ${W(`${e.table}_${e.column}_key`)};`, Si = (e) => `ALTER TABLE ${G(e.table)} DROP INDEX ${G(`${e.table}_${e.column}_key`)};`, Ci = (e, t) => {
|
|
2477
2490
|
let n = [], r = t(e.table), i = t(e.column), a = t(e.targetTable), o = t(e.targetColumn);
|
|
2478
2491
|
if (e.orphanPolicy) {
|
|
2479
2492
|
let t = `${i} IS NOT NULL AND ${i} NOT IN (SELECT ${o} FROM ${a})`;
|
|
@@ -2491,10 +2504,10 @@ BEGIN
|
|
|
2491
2504
|
setNull: "SET NULL",
|
|
2492
2505
|
noAction: "NO ACTION"
|
|
2493
2506
|
}[e.onDelete]}`), n.push(s.join(" ") + ";"), n;
|
|
2494
|
-
},
|
|
2507
|
+
}, wi = (e) => `ALTER TABLE ${W(e.table)} DROP CONSTRAINT IF EXISTS ${W(`${e.table}_${e.column}_fkey`)};`, Ti = (e) => `ALTER TABLE ${G(e.table)} DROP FOREIGN KEY ${G(`${e.table}_${e.column}_fkey`)};`, Ei = (e, t) => {
|
|
2495
2508
|
let n = e.values.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
|
|
2496
2509
|
return `ALTER TABLE ${t(e.table)} ADD CONSTRAINT ${t(`${e.table}_${e.column}_check`)} CHECK (${t(e.column)} IN (${n}));`;
|
|
2497
|
-
},
|
|
2510
|
+
}, Di = (e) => `ALTER TABLE ${W(e.table)} DROP CONSTRAINT IF EXISTS ${W(`${e.table}_${e.column}_check`)};`, Oi = (e, t) => S.gen(function* () {
|
|
2498
2511
|
let n = yield* e`
|
|
2499
2512
|
SELECT cc.constraint_name AS n, cc.check_clause AS c
|
|
2500
2513
|
FROM information_schema.check_constraints cc
|
|
@@ -2507,18 +2520,18 @@ BEGIN
|
|
|
2507
2520
|
WHERE tc.table_schema = DATABASE() AND tc.table_name = ${t.table}`), S.orElseSucceed(() => []));
|
|
2508
2521
|
for (let e of n) {
|
|
2509
2522
|
let n = String(e.n ?? "");
|
|
2510
|
-
if (n !== "" &&
|
|
2523
|
+
if (n !== "" && Fn(String(e.c ?? ""))?.column === t.column) return n;
|
|
2511
2524
|
}
|
|
2512
|
-
}),
|
|
2513
|
-
let r = yield*
|
|
2514
|
-
r !== void 0 && (yield* X(e, `ALTER TABLE ${
|
|
2515
|
-
let i = yield*
|
|
2525
|
+
}), ki = (e, t, n) => S.gen(function* () {
|
|
2526
|
+
let r = yield* Oi(e, t);
|
|
2527
|
+
r !== void 0 && (yield* X(e, `ALTER TABLE ${G(t.table)} DROP CONSTRAINT ${G(r)};`, t.kind, [fr]));
|
|
2528
|
+
let i = yield* Oi(e, t);
|
|
2516
2529
|
if (i === void 0) return;
|
|
2517
|
-
let a =
|
|
2530
|
+
let a = K(n, t.table, t.column);
|
|
2518
2531
|
if (!a) return yield* S.die(/* @__PURE__ */ Error(`applier: cannot drop the CHECK on '${t.table}.${t.column}' — it is column-level (catalog name '${i}'), which this family removes only by redefining the column, and the declared column is not available to redefine it from.`));
|
|
2519
|
-
yield* X(e, `ALTER TABLE ${
|
|
2520
|
-
}),
|
|
2521
|
-
let i = e.column, a = r === "mariadb", o = a ?
|
|
2532
|
+
yield* X(e, `ALTER TABLE ${G(t.table)} MODIFY COLUMN ${Or(a, t.column)};`, t.kind);
|
|
2533
|
+
}), Ai = (e, t, n, r) => {
|
|
2534
|
+
let i = e.column, a = r === "mariadb", o = a ? G : r === "mssql" ? Y : W, s = a ? vr(i) : r === "mssql" ? Jr(i) : r === "sqlite" ? Hr(i) : gr(i), c = r === "mssql" ? "ADD" : "ADD COLUMN", l = (e) => a ? kr(e, i) : r === "mssql" ? Ur(e, "SYSUTCDATETIME()") : r === "sqlite" ? Ur(e, "CURRENT_TIMESTAMP") : jr(e, i), u = q(i, r);
|
|
2522
2535
|
if (u) {
|
|
2523
2536
|
let t = r === "mssql" ? `${o(i.name)} ${u}` : `${o(i.name)} ${s} ${u}`;
|
|
2524
2537
|
return {
|
|
@@ -2546,7 +2559,7 @@ BEGIN
|
|
|
2546
2559
|
post: f ? [f] : []
|
|
2547
2560
|
};
|
|
2548
2561
|
return d?.sql && (p.backfillKind = "sql", p.backfillSql = d.sql), d?.js && (p.backfillKind = "js", p.backfillJs = d.js), d?.batchSize !== void 0 && (p.batchSize = d.batchSize), d?.sleepMs !== void 0 && (p.sleepMs = d.sleepMs), p;
|
|
2549
|
-
},
|
|
2562
|
+
}, ji = (e) => {
|
|
2550
2563
|
let t = new Map(e.map((e) => [e.tableName, e]));
|
|
2551
2564
|
return (e, n) => {
|
|
2552
2565
|
let r = t.get(e);
|
|
@@ -2566,12 +2579,12 @@ BEGIN
|
|
|
2566
2579
|
...o
|
|
2567
2580
|
};
|
|
2568
2581
|
};
|
|
2569
|
-
}, X = (e, t, n, r = []) => e.unsafe(t).pipe(S.catchIf((e) =>
|
|
2570
|
-
process.stderr.write(
|
|
2582
|
+
}, X = (e, t, n, r = []) => e.unsafe(t).pipe(S.catchIf((e) => cr(e, r), () => S.void), S.tapError((e) => S.sync(() => {
|
|
2583
|
+
process.stderr.write(ie(`applier: statement failed (op=${n})`, t, e, 400));
|
|
2571
2584
|
})), S.mapError((e) => {
|
|
2572
|
-
let r =
|
|
2585
|
+
let r = ie(`applier: statement failed (op=${n})`, t, e, 400).trim();
|
|
2573
2586
|
return Object.assign(e, { message: r });
|
|
2574
|
-
}), S.map(() => void 0)), Z = (e, t, n) => S.forEach(t, (t) => X(e, t, n), { discard: !0 }), Q = (e, t) => e.literal(`LIMIT ${Math.max(1, Math.floor(Number.isFinite(t) ? t : 1))}`), $ = (e, t, n, r) => e.unsafe(`SELECT ${r === void 0 ? "*" : _(r, t)} FROM ${_(n, t)} WHERE 1=0`).pipe(S.as(!0), S.catchAll(() => S.succeed(!1))),
|
|
2587
|
+
}), S.map(() => void 0)), Z = (e, t, n) => S.forEach(t, (t) => X(e, t, n), { discard: !0 }), Q = (e, t) => e.literal(`LIMIT ${Math.max(1, Math.floor(Number.isFinite(t) ? t : 1))}`), $ = (e, t, n, r) => e.unsafe(`SELECT ${r === void 0 ? "*" : _(r, t)} FROM ${_(n, t)} WHERE 1=0`).pipe(S.as(!0), S.catchAll(() => S.succeed(!1))), Mi = (e, t) => S.gen(function* () {
|
|
2575
2588
|
let n = I([Ie], t).tables[0];
|
|
2576
2589
|
if (!n) return yield* S.die(/* @__PURE__ */ Error("migration applier: the resume-ledger table descriptor produced no snapshot. This is a framework bug."));
|
|
2577
2590
|
let r = {
|
|
@@ -2580,18 +2593,18 @@ BEGIN
|
|
|
2580
2593
|
columns: n.columns,
|
|
2581
2594
|
indexes: []
|
|
2582
2595
|
}, i = yield* e.onDialectOrElse({
|
|
2583
|
-
mysql: () =>
|
|
2584
|
-
mssql: () => S.succeed(
|
|
2585
|
-
sqlite: () => S.succeed(
|
|
2586
|
-
orElse: () => S.succeed(
|
|
2596
|
+
mysql: () => ir(e).pipe(S.map((e) => zr(r, e))),
|
|
2597
|
+
mssql: () => S.succeed(Xr(r)),
|
|
2598
|
+
sqlite: () => S.succeed(Gr(r)),
|
|
2599
|
+
orElse: () => S.succeed(Pr(r))
|
|
2587
2600
|
});
|
|
2588
2601
|
yield* S.forEach(i, (t) => X(e, t, "resume-ledger-bootstrap"), { discard: !0 });
|
|
2589
|
-
}),
|
|
2602
|
+
}), Ni = (e) => e`
|
|
2590
2603
|
SELECT ${e("runId")}, ${e("planFingerprint")}, ${e("opIndex")},
|
|
2591
2604
|
${e("status")}, ${e("payload")}
|
|
2592
2605
|
FROM ${e(k)}
|
|
2593
|
-
`,
|
|
2594
|
-
let i = yield*
|
|
2606
|
+
`, Pi = (e, t, n, r) => S.gen(function* () {
|
|
2607
|
+
let i = yield* U(e, (/* @__PURE__ */ new Date()).toISOString());
|
|
2595
2608
|
yield* S.forEach(r, ({ index: r, planned: a }) => e`
|
|
2596
2609
|
INSERT INTO ${e(k)}
|
|
2597
2610
|
(${e("id")}, ${e("runId")}, ${e("planFingerprint")}, ${e("opIndex")},
|
|
@@ -2602,8 +2615,8 @@ BEGIN
|
|
|
2602
2615
|
${a.op.kind}, ${Re(a.op)}, ${"pending"},
|
|
2603
2616
|
${JSON.stringify(a)}, ${i})
|
|
2604
2617
|
`, { discard: !0 });
|
|
2605
|
-
}),
|
|
2606
|
-
let a = yield*
|
|
2618
|
+
}), Fi = (e, t, n, r, i) => S.gen(function* () {
|
|
2619
|
+
let a = yield* U(e, (/* @__PURE__ */ new Date()).toISOString());
|
|
2607
2620
|
if (r === "applied") {
|
|
2608
2621
|
yield* e`
|
|
2609
2622
|
UPDATE ${e(k)}
|
|
@@ -2618,8 +2631,8 @@ BEGIN
|
|
|
2618
2631
|
SET ${e("status")} = ${r}, ${e("startedAt")} = ${a}
|
|
2619
2632
|
WHERE ${e("runId")} = ${t} AND ${e("opIndex")} = ${n}
|
|
2620
2633
|
`;
|
|
2621
|
-
}),
|
|
2622
|
-
let i = yield*
|
|
2634
|
+
}), Ii = (e, t, n, r) => S.gen(function* () {
|
|
2635
|
+
let i = yield* U(e, (/* @__PURE__ */ new Date()).toISOString());
|
|
2623
2636
|
r.length > 0 && (yield* e`
|
|
2624
2637
|
UPDATE ${e(k)}
|
|
2625
2638
|
SET ${e("status")} = ${"applied"}, ${e("appliedAt")} = ${i}
|
|
@@ -2629,7 +2642,7 @@ BEGIN
|
|
|
2629
2642
|
SET ${e("status")} = ${"pending"}
|
|
2630
2643
|
WHERE ${e("runId")} = ${t} AND ${e("opIndex")} IN ${e.in(n)}
|
|
2631
2644
|
`);
|
|
2632
|
-
}),
|
|
2645
|
+
}), Li = (e, t) => t === void 0 ? e`DELETE FROM ${e(k)}`.pipe(S.asVoid) : e`DELETE FROM ${e(k)} WHERE ${e("runId")} = ${t}`.pipe(S.asVoid), Ri = (e, t, n) => S.gen(function* () {
|
|
2633
2646
|
if (Ke(n.op, n.classification, t) !== "artefact-repair") return "clean";
|
|
2634
2647
|
let r = n.op, i = (e) => _(e, t);
|
|
2635
2648
|
if (t === "sqlite" || t === "turso") {
|
|
@@ -2640,113 +2653,113 @@ BEGIN
|
|
|
2640
2653
|
if (r.kind !== "alter-column-type") return "clean";
|
|
2641
2654
|
let a = `${r.column}${He}`, o = `${r.column}${Ue}`, s = yield* $(e, t, r.table, r.column), c = yield* $(e, t, r.table, a), l = yield* $(e, t, r.table, o), u = (e) => S.logWarning(`migration resume: ${e}`).pipe(S.annotateLogs({ scope: "voltro:migrate" }));
|
|
2642
2655
|
return !c && !l ? "clean" : s && c && !l ? (yield* X(e, `ALTER TABLE ${i(r.table)} DROP COLUMN ${i(a)}`, "resume-repair"), yield* u(`dropped a half-populated shadow column '${r.table}.${a}' — replaying the type change`), "outstanding") : !s && c && l ? (yield* X(e, `ALTER TABLE ${i(r.table)} RENAME COLUMN ${i(a)} TO ${i(r.column)}`, "resume-repair"), yield* X(e, `ALTER TABLE ${i(r.table)} DROP COLUMN ${i(o)}`, "resume-repair"), yield* u(`completed an interrupted shadow swap on '${r.table}.${r.column}'`), "applied") : s && !c && l ? (yield* X(e, `ALTER TABLE ${i(r.table)} DROP COLUMN ${i(o)}`, "resume-repair"), yield* u(`dropped the leftover pre-swap column '${r.table}.${o}'`), "applied") : yield* S.die(/* @__PURE__ */ Error(`applyPlan: an interrupted online type change on '${r.table}.${r.column}' left a shadow-swap state this resume cannot classify (column=${s}, ${a}=${c}, ${o}=${l}).\nNothing was changed. Inspect those three columns and reconcile them by hand — the data is in whichever of them is populated — then re-run the migration.`));
|
|
2643
|
-
}),
|
|
2644
|
-
let i = process.hrtime.bigint(), a =
|
|
2656
|
+
}), zi = (e, t, n, r = "fresh") => S.gen(function* () {
|
|
2657
|
+
let i = process.hrtime.bigint(), a = ji(n.declared), o = t.op;
|
|
2645
2658
|
switch (o.kind) {
|
|
2646
2659
|
case "create-table": {
|
|
2647
2660
|
let t = yield* e.onDialectOrElse({
|
|
2648
|
-
mysql: () =>
|
|
2649
|
-
mssql: () => S.succeed(
|
|
2650
|
-
sqlite: () => S.succeed(
|
|
2651
|
-
orElse: () => S.succeed(
|
|
2661
|
+
mysql: () => ir(e).pipe(S.map((e) => zr(o, e))),
|
|
2662
|
+
mssql: () => S.succeed(Xr(o)),
|
|
2663
|
+
sqlite: () => S.succeed(Gr(o)),
|
|
2664
|
+
orElse: () => S.succeed(Pr(o))
|
|
2652
2665
|
}), n = yield* e.onDialectOrElse({
|
|
2653
|
-
mysql: () => S.succeed([
|
|
2666
|
+
mysql: () => S.succeed([lr]),
|
|
2654
2667
|
orElse: () => S.succeed([])
|
|
2655
2668
|
});
|
|
2656
2669
|
for (let r of t) yield* X(e, r, o.kind, n);
|
|
2657
2670
|
break;
|
|
2658
2671
|
}
|
|
2659
2672
|
case "drop-table": {
|
|
2660
|
-
let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString(), r = (e) => t ?
|
|
2673
|
+
let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString(), r = (e) => t ? $r(o, n, e) : Qr(o, e);
|
|
2661
2674
|
yield* e.onDialectOrElse({
|
|
2662
|
-
mysql: () => X(e, r(
|
|
2663
|
-
orElse: () => X(e, r(
|
|
2675
|
+
mysql: () => X(e, r(G), o.kind),
|
|
2676
|
+
orElse: () => X(e, r(W), o.kind)
|
|
2664
2677
|
});
|
|
2665
2678
|
break;
|
|
2666
2679
|
}
|
|
2667
2680
|
case "drop-column": {
|
|
2668
2681
|
let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString();
|
|
2669
2682
|
yield* e.onDialectOrElse({
|
|
2670
|
-
mysql: () =>
|
|
2671
|
-
sqlite: () => X(e, t ?
|
|
2672
|
-
orElse: () => X(e, t ?
|
|
2683
|
+
mysql: () => ir(e).pipe(S.flatMap((r) => X(e, t ? Cr(o, n, G) : xr(o, r), o.kind, t ? [] : [ur]))),
|
|
2684
|
+
sqlite: () => X(e, t ? Cr(o, n, W) : br(o, W, !1), o.kind, t ? [] : [dr]),
|
|
2685
|
+
orElse: () => X(e, t ? Cr(o, n, W) : br(o, W), o.kind)
|
|
2673
2686
|
});
|
|
2674
2687
|
break;
|
|
2675
2688
|
}
|
|
2676
2689
|
case "rename-column":
|
|
2677
2690
|
yield* e.onDialectOrElse({
|
|
2678
|
-
mysql: () => X(e,
|
|
2691
|
+
mysql: () => X(e, Sr(o, G), o.kind),
|
|
2679
2692
|
mssql: () => X(e, `EXEC sp_rename N'${o.table.replace(/'/g, "''")}.${o.from.replace(/'/g, "''")}', N'${o.to.replace(/'/g, "''")}', 'COLUMN';`, o.kind),
|
|
2680
|
-
orElse: () => X(e,
|
|
2693
|
+
orElse: () => X(e, Sr(o, W), o.kind)
|
|
2681
2694
|
});
|
|
2682
2695
|
break;
|
|
2683
2696
|
case "add-index":
|
|
2684
2697
|
yield* e.onDialectOrElse({
|
|
2685
|
-
mysql: () =>
|
|
2686
|
-
mssql: () => Z(e, [...
|
|
2687
|
-
orElse: () => X(e,
|
|
2698
|
+
mysql: () => ir(e).pipe(S.flatMap((t) => X(e, ii(o, n.declared, t), o.kind, [lr]))),
|
|
2699
|
+
mssql: () => Z(e, [...mi(o.table, o.index.columns, n.declared), pi(o)], o.kind),
|
|
2700
|
+
orElse: () => X(e, ri(o, t.classification === "online-required"), o.kind)
|
|
2688
2701
|
});
|
|
2689
2702
|
break;
|
|
2690
2703
|
case "drop-index":
|
|
2691
2704
|
yield* e.onDialectOrElse({
|
|
2692
|
-
mysql: () => X(e,
|
|
2693
|
-
mssql: () => X(e,
|
|
2694
|
-
orElse: () => X(e,
|
|
2705
|
+
mysql: () => X(e, oi(o), o.kind),
|
|
2706
|
+
mssql: () => X(e, si(o), o.kind),
|
|
2707
|
+
orElse: () => X(e, ai(o), o.kind)
|
|
2695
2708
|
});
|
|
2696
2709
|
break;
|
|
2697
2710
|
case "rename-table":
|
|
2698
2711
|
yield* e.onDialectOrElse({
|
|
2699
|
-
mysql: () => X(e,
|
|
2700
|
-
mssql: () => X(e,
|
|
2701
|
-
orElse: () => X(e,
|
|
2712
|
+
mysql: () => X(e, ci(o, G), o.kind),
|
|
2713
|
+
mssql: () => X(e, li(o), o.kind),
|
|
2714
|
+
orElse: () => X(e, ci(o, W), o.kind)
|
|
2702
2715
|
});
|
|
2703
2716
|
break;
|
|
2704
2717
|
case "rename-index":
|
|
2705
2718
|
yield* e.onDialectOrElse({
|
|
2706
|
-
mysql: () => X(e,
|
|
2707
|
-
mssql: () => X(e,
|
|
2708
|
-
orElse: () => X(e,
|
|
2719
|
+
mysql: () => X(e, di(o), o.kind),
|
|
2720
|
+
mssql: () => X(e, fi(o), o.kind),
|
|
2721
|
+
orElse: () => X(e, ui(o), o.kind)
|
|
2709
2722
|
});
|
|
2710
2723
|
break;
|
|
2711
2724
|
case "add-unique":
|
|
2712
2725
|
yield* e.onDialectOrElse({
|
|
2713
|
-
mysql: () => X(e,
|
|
2726
|
+
mysql: () => X(e, gi(o, n.declared), o.kind),
|
|
2714
2727
|
sqlite: () => Z(e, J(o.table, n.declared), o.kind),
|
|
2715
|
-
mssql: () => Z(e, [...
|
|
2716
|
-
orElse: () => X(e,
|
|
2728
|
+
mssql: () => Z(e, [...mi(o.table, [o.column], n.declared), hi(o)], o.kind),
|
|
2729
|
+
orElse: () => X(e, hi(o), o.kind)
|
|
2717
2730
|
});
|
|
2718
2731
|
break;
|
|
2719
2732
|
case "drop-unique":
|
|
2720
2733
|
yield* e.onDialectOrElse({
|
|
2721
|
-
mysql: () => X(e,
|
|
2734
|
+
mysql: () => X(e, Si(o), o.kind),
|
|
2722
2735
|
sqlite: () => Z(e, J(o.table, n.declared), o.kind),
|
|
2723
|
-
orElse: () => X(e,
|
|
2736
|
+
orElse: () => X(e, xi(o), o.kind)
|
|
2724
2737
|
});
|
|
2725
2738
|
break;
|
|
2726
2739
|
case "add-unique-composite":
|
|
2727
2740
|
yield* e.onDialectOrElse({
|
|
2728
|
-
mysql: () => X(e,
|
|
2741
|
+
mysql: () => X(e, vi(o, n.declared), o.kind),
|
|
2729
2742
|
sqlite: () => Z(e, J(o.table, n.declared), o.kind),
|
|
2730
|
-
mssql: () => Z(e, [...
|
|
2731
|
-
orElse: () => X(e,
|
|
2743
|
+
mssql: () => Z(e, [...mi(o.table, o.fields, n.declared), _i(o)], o.kind),
|
|
2744
|
+
orElse: () => X(e, _i(o), o.kind)
|
|
2732
2745
|
});
|
|
2733
2746
|
break;
|
|
2734
2747
|
case "drop-unique-composite":
|
|
2735
2748
|
yield* e.onDialectOrElse({
|
|
2736
|
-
mysql: () => X(e,
|
|
2749
|
+
mysql: () => X(e, bi(o), o.kind),
|
|
2737
2750
|
sqlite: () => Z(e, J(o.table, n.declared), o.kind),
|
|
2738
|
-
orElse: () => X(e,
|
|
2751
|
+
orElse: () => X(e, yi(o), o.kind)
|
|
2739
2752
|
});
|
|
2740
2753
|
break;
|
|
2741
2754
|
case "add-foreign-key":
|
|
2742
2755
|
yield* e.onDialectOrElse({
|
|
2743
|
-
mysql: () => Z(e,
|
|
2756
|
+
mysql: () => Z(e, Ci(o, G), o.kind),
|
|
2744
2757
|
sqlite: () => Z(e, J(o.table, n.declared), o.kind),
|
|
2745
|
-
orElse: () => Z(e,
|
|
2758
|
+
orElse: () => Z(e, Ci(o, W), o.kind)
|
|
2746
2759
|
});
|
|
2747
2760
|
break;
|
|
2748
2761
|
case "add-column": {
|
|
2749
|
-
let n =
|
|
2762
|
+
let n = Ai(o, t, a, yield* e.onDialectOrElse({
|
|
2750
2763
|
mysql: () => S.succeed("mariadb"),
|
|
2751
2764
|
mssql: () => S.succeed("mssql"),
|
|
2752
2765
|
sqlite: () => S.succeed("sqlite"),
|
|
@@ -2792,47 +2805,47 @@ BEGIN
|
|
|
2792
2805
|
case "alter-column-nullability":
|
|
2793
2806
|
yield* e.onDialectOrElse({
|
|
2794
2807
|
mysql: () => {
|
|
2795
|
-
let t =
|
|
2796
|
-
return t ? X(e, `ALTER TABLE ${
|
|
2808
|
+
let t = K(n.declared, o.table, o.column);
|
|
2809
|
+
return t ? X(e, `ALTER TABLE ${G(o.table)} MODIFY COLUMN ${Or(t, o.column, o.toNullable)};`, o.kind) : S.die(/* @__PURE__ */ Error(`alter-column-nullability on mariadb needs the declared column '${o.table}.${o.column}' (to render MODIFY COLUMN); it was not in ctx.declared.`));
|
|
2797
2810
|
},
|
|
2798
2811
|
mssql: () => {
|
|
2799
|
-
let t =
|
|
2800
|
-
return t ? X(e,
|
|
2812
|
+
let t = K(n.declared, o.table, o.column);
|
|
2813
|
+
return t ? X(e, Kr(t, o.column, o.table, o.toNullable), o.kind) : S.die(/* @__PURE__ */ Error(`alter-column-nullability on mssql needs the declared column '${o.table}.${o.column}'.`));
|
|
2801
2814
|
},
|
|
2802
2815
|
sqlite: () => Z(e, J(o.table, n.declared), o.kind),
|
|
2803
|
-
orElse: () => X(e, `ALTER TABLE ${
|
|
2816
|
+
orElse: () => X(e, `ALTER TABLE ${W(o.table)} ALTER COLUMN ${W(o.column)} ${o.toNullable ? "DROP NOT NULL" : "SET NOT NULL"};`, o.kind)
|
|
2804
2817
|
});
|
|
2805
2818
|
break;
|
|
2806
2819
|
case "alter-column-default": {
|
|
2807
|
-
let t =
|
|
2820
|
+
let t = Dr(n.declared, o.table, o.column), r = K(n.declared, o.table, o.column), i = (e) => o.hasDefault && r !== void 0 && Tr(r, e) ? r : void 0;
|
|
2808
2821
|
yield* e.onDialectOrElse({
|
|
2809
2822
|
mysql: () => {
|
|
2810
2823
|
let n = i("mariadb");
|
|
2811
|
-
return X(e, n ? `ALTER TABLE ${
|
|
2824
|
+
return X(e, n ? `ALTER TABLE ${G(o.table)} MODIFY COLUMN ${Or(n, o.column)};` : wr(o, G, (e) => kr(e, t)), o.kind);
|
|
2812
2825
|
},
|
|
2813
2826
|
mssql: () => {
|
|
2814
2827
|
let t = i("mssql");
|
|
2815
|
-
return X(e,
|
|
2828
|
+
return X(e, qr(o, t ? Kr(t, o.column, o.table) : void 0), o.kind);
|
|
2816
2829
|
},
|
|
2817
2830
|
sqlite: () => Z(e, J(o.table, n.declared), o.kind),
|
|
2818
|
-
orElse: () => X(e,
|
|
2831
|
+
orElse: () => X(e, wr(o, W, (e) => jr(e, t)), o.kind)
|
|
2819
2832
|
});
|
|
2820
2833
|
break;
|
|
2821
2834
|
}
|
|
2822
2835
|
case "alter-column-type": {
|
|
2823
|
-
let r =
|
|
2836
|
+
let r = gr(Dr(n.declared, o.table, o.column) ?? { type: o.to }), i = o.using ? ` USING ${o.using}` : "";
|
|
2824
2837
|
if (t.classification !== "online-required") {
|
|
2825
2838
|
yield* e.onDialectOrElse({
|
|
2826
2839
|
mysql: () => {
|
|
2827
|
-
let t =
|
|
2828
|
-
return t ? X(e, `ALTER TABLE ${
|
|
2840
|
+
let t = K(n.declared, o.table, o.column);
|
|
2841
|
+
return t ? X(e, `ALTER TABLE ${G(o.table)} MODIFY COLUMN ${Or(t, o.column)};`, o.kind) : S.die(/* @__PURE__ */ Error(`alter-column-type on mariadb needs the declared column '${o.table}.${o.column}' (to render MODIFY COLUMN); it was not in ctx.declared.`));
|
|
2829
2842
|
},
|
|
2830
2843
|
mssql: () => {
|
|
2831
|
-
let t =
|
|
2832
|
-
return t ? X(e,
|
|
2844
|
+
let t = K(n.declared, o.table, o.column);
|
|
2845
|
+
return t ? X(e, Kr(t, o.column, o.table), o.kind) : S.die(/* @__PURE__ */ Error(`alter-column-type on mssql needs the declared column '${o.table}.${o.column}'.`));
|
|
2833
2846
|
},
|
|
2834
2847
|
sqlite: () => Z(e, J(o.table, n.declared), o.kind),
|
|
2835
|
-
orElse: () => X(e, `ALTER TABLE ${
|
|
2848
|
+
orElse: () => X(e, `ALTER TABLE ${W(o.table)} ALTER COLUMN ${W(o.column)} TYPE ${r}${i};`, o.kind)
|
|
2836
2849
|
});
|
|
2837
2850
|
break;
|
|
2838
2851
|
}
|
|
@@ -2841,34 +2854,34 @@ BEGIN
|
|
|
2841
2854
|
orElse: () => S.void
|
|
2842
2855
|
});
|
|
2843
2856
|
let a = `${o.column}__shadow`, s = `${o.column}__old`;
|
|
2844
|
-
yield* e.unsafe(`ALTER TABLE ${
|
|
2845
|
-
let c = o.using ??
|
|
2857
|
+
yield* e.unsafe(`ALTER TABLE ${W(o.table)} ADD COLUMN ${W(a)} ${r}`);
|
|
2858
|
+
let c = o.using ?? W(o.column), l;
|
|
2846
2859
|
for (;;) {
|
|
2847
2860
|
let t = l === void 0 ? yield* e`SELECT ${e("id")} FROM ${e(o.table)} WHERE ${e(a)} IS NULL ORDER BY ${e("id")} ${Q(e, 5e3)}` : yield* e`SELECT ${e("id")} FROM ${e(o.table)} WHERE ${e(a)} IS NULL AND ${e("id")} > ${l} ORDER BY ${e("id")} ${Q(e, 5e3)}`;
|
|
2848
2861
|
if (t.length === 0) break;
|
|
2849
|
-
yield* e.unsafe(`UPDATE ${
|
|
2862
|
+
yield* e.unsafe(`UPDATE ${W(o.table)} SET ${W(a)} = ${c} WHERE ${W(o.column)} IS NOT NULL AND ${W(a)} IS NULL AND ${W("id")} IN (${t.map((e) => `'${e.id.replace(/'/g, "''")}'`).join(",")})`), l = t[t.length - 1].id;
|
|
2850
2863
|
}
|
|
2851
|
-
yield* S.logInfo(`alter-column-type shadow ${o.table}.${o.column}: shadow populated`).pipe(S.annotateLogs({ scope: "voltro:migrate" })), yield* e.unsafe(`ALTER TABLE ${
|
|
2864
|
+
yield* S.logInfo(`alter-column-type shadow ${o.table}.${o.column}: shadow populated`).pipe(S.annotateLogs({ scope: "voltro:migrate" })), yield* e.unsafe(`ALTER TABLE ${W(o.table)} RENAME COLUMN ${W(o.column)} TO ${W(s)}`), yield* e.unsafe(`ALTER TABLE ${W(o.table)} RENAME COLUMN ${W(a)} TO ${W(o.column)}`), yield* e.unsafe(`ALTER TABLE ${W(o.table)} DROP COLUMN ${W(s)}`);
|
|
2852
2865
|
break;
|
|
2853
2866
|
}
|
|
2854
2867
|
case "drop-foreign-key":
|
|
2855
2868
|
yield* e.onDialectOrElse({
|
|
2856
|
-
mysql: () => X(e,
|
|
2869
|
+
mysql: () => X(e, Ti(o), o.kind),
|
|
2857
2870
|
sqlite: () => Z(e, J(o.table, n.declared), o.kind),
|
|
2858
|
-
orElse: () => X(e,
|
|
2871
|
+
orElse: () => X(e, wi(o), o.kind)
|
|
2859
2872
|
});
|
|
2860
2873
|
break;
|
|
2861
2874
|
case "add-check":
|
|
2862
2875
|
yield* e.onDialectOrElse({
|
|
2863
|
-
mysql: () => X(e,
|
|
2876
|
+
mysql: () => X(e, Ei(o, G), o.kind),
|
|
2864
2877
|
sqlite: () => Z(e, J(o.table, n.declared), o.kind),
|
|
2865
|
-
orElse: () => X(e,
|
|
2878
|
+
orElse: () => X(e, Ei(o, W), o.kind)
|
|
2866
2879
|
});
|
|
2867
2880
|
break;
|
|
2868
2881
|
case "drop-check": yield* e.onDialectOrElse({
|
|
2869
|
-
mysql: () =>
|
|
2882
|
+
mysql: () => ki(e, o, n.declared),
|
|
2870
2883
|
sqlite: () => Z(e, J(o.table, n.declared), o.kind),
|
|
2871
|
-
orElse: () => X(e,
|
|
2884
|
+
orElse: () => X(e, Di(o), o.kind)
|
|
2872
2885
|
});
|
|
2873
2886
|
}
|
|
2874
2887
|
return {
|
|
@@ -2876,7 +2889,7 @@ BEGIN
|
|
|
2876
2889
|
status: "applied",
|
|
2877
2890
|
durationMs: Number((process.hrtime.bigint() - i) / 1000000n)
|
|
2878
2891
|
};
|
|
2879
|
-
}),
|
|
2892
|
+
}), Bi = (e, t, n, r) => S.gen(function* () {
|
|
2880
2893
|
let i = [...new Set(r.map((e) => e.runId))];
|
|
2881
2894
|
if (i.length > 1) return yield* S.die(/* @__PURE__ */ Error(`applyPlan: the resume ledger holds ${i.length} unfinished runs (${i.join(", ")}). Only one migration may be in flight at a time — the advisory lock enforces it — so this means a run was interrupted and a LATER one wrote over it without clearing.\nNothing was changed. Inspect \`${k}\`, reconcile the schema by hand, and delete the rows of the run you have finished.`));
|
|
2882
2895
|
let a = i[0], o = [...r].map((e) => ({
|
|
@@ -2890,7 +2903,7 @@ BEGIN
|
|
|
2890
2903
|
runId: a,
|
|
2891
2904
|
why: "no operation had started — no DDL ran"
|
|
2892
2905
|
};
|
|
2893
|
-
let l = s ? yield*
|
|
2906
|
+
let l = s ? yield* Ri(e, t, s.planned) : "clean", u = r[0].planFingerprint;
|
|
2894
2907
|
if (u !== n.toFingerprint) return {
|
|
2895
2908
|
kind: "discard",
|
|
2896
2909
|
runId: a,
|
|
@@ -2901,7 +2914,7 @@ BEGIN
|
|
|
2901
2914
|
kind: "discard",
|
|
2902
2915
|
runId: a,
|
|
2903
2916
|
why: "every recorded operation had already taken effect"
|
|
2904
|
-
} : (yield*
|
|
2917
|
+
} : (yield* Ii(e, a, f.map((e) => e.index), p.map((e) => e.index)), yield* S.logWarning(`migration resume: continuing run ${a} — replaying ${f.length} operation(s), ${o.length - f.length} already applied`).pipe(S.annotateLogs({ scope: "voltro:migrate" })), {
|
|
2905
2918
|
kind: "resume",
|
|
2906
2919
|
runId: a,
|
|
2907
2920
|
ops: f.map((e) => ({
|
|
@@ -2909,7 +2922,7 @@ BEGIN
|
|
|
2909
2922
|
planned: e.planned
|
|
2910
2923
|
}))
|
|
2911
2924
|
});
|
|
2912
|
-
}),
|
|
2925
|
+
}), Vi = (e) => {
|
|
2913
2926
|
let t = e.op, n = (e) => typeof t[e] == "string" ? t[e] : "";
|
|
2914
2927
|
return [
|
|
2915
2928
|
t.kind,
|
|
@@ -2918,14 +2931,14 @@ BEGIN
|
|
|
2918
2931
|
n("name"),
|
|
2919
2932
|
n("to")
|
|
2920
2933
|
].join("\0");
|
|
2921
|
-
},
|
|
2934
|
+
}, Hi = (e, t, n) => S.gen(function* () {
|
|
2922
2935
|
let r = t.operations.filter((e) => e.blocked);
|
|
2923
2936
|
if (r.length > 0) return yield* S.die(/* @__PURE__ */ Error(`applyPlan: refusing to execute — ${r.length} blocked operations. Run \`voltro db plan\` to see the fixes.`));
|
|
2924
2937
|
yield* je(e, { schema: n.lockSchema });
|
|
2925
|
-
let i = Date.now(), a = [], o = Ne(e), s = yield* n.replan(e), c = new Set(t.operations.filter((e) => !e.blocked).map((e) =>
|
|
2938
|
+
let i = Date.now(), a = [], o = Ne(e), s = yield* n.replan(e), c = new Set(t.operations.filter((e) => !e.blocked).map((e) => Vi(e))), l = {
|
|
2926
2939
|
...s,
|
|
2927
2940
|
operations: s.operations.map((e) => {
|
|
2928
|
-
if (!e.blocked || !c.has(
|
|
2941
|
+
if (!e.blocked || !c.has(Vi(e))) return e;
|
|
2929
2942
|
let { blocked: t, ...n } = e;
|
|
2930
2943
|
return n;
|
|
2931
2944
|
})
|
|
@@ -2938,20 +2951,20 @@ BEGIN
|
|
|
2938
2951
|
planned: e
|
|
2939
2952
|
})), g = "fresh";
|
|
2940
2953
|
try {
|
|
2941
|
-
yield*
|
|
2942
|
-
let t = yield*
|
|
2954
|
+
yield* Mi(e, o);
|
|
2955
|
+
let t = yield* Ni(e);
|
|
2943
2956
|
if (t.length > 0) {
|
|
2944
|
-
let n = yield*
|
|
2945
|
-
n.kind === "resume" ? (m = n.runId, h = n.ops, g = "resume") : (yield* S.logWarning(`migration resume: discarding the ledger of run ${n.runId} — ${n.why}`).pipe(S.annotateLogs({ scope: "voltro:migrate" })), yield*
|
|
2957
|
+
let n = yield* Bi(e, o, l, t);
|
|
2958
|
+
n.kind === "resume" ? (m = n.runId, h = n.ops, g = "resume") : (yield* S.logWarning(`migration resume: discarding the ledger of run ${n.runId} — ${n.why}`).pipe(S.annotateLogs({ scope: "voltro:migrate" })), yield* Li(e, n.runId));
|
|
2946
2959
|
}
|
|
2947
|
-
g === "fresh" && h.length > 0 && (yield*
|
|
2948
|
-
let e = yield*
|
|
2949
|
-
for (let t of f) a.push(yield*
|
|
2960
|
+
g === "fresh" && h.length > 0 && (yield* Pi(e, m, l.toFingerprint, h)), f.length > 0 && (yield* e.withTransaction(S.gen(function* () {
|
|
2961
|
+
let e = yield* T.SqlClient;
|
|
2962
|
+
for (let t of f) a.push(yield* zi(e, t, n));
|
|
2950
2963
|
})));
|
|
2951
2964
|
for (let { index: t, planned: r } of h) {
|
|
2952
|
-
yield*
|
|
2953
|
-
let i = a.length, o = yield*
|
|
2954
|
-
a.push(o), yield*
|
|
2965
|
+
yield* Fi(e, m, t, "started");
|
|
2966
|
+
let i = a.length, o = yield* zi(e, r, n, g).pipe(S.mapError((e) => Object.assign(e, { message: `${String(e?.message ?? e)}\n\n progress: ${i} of ${h.length + f.length} operation(s) applied before this one${f.length > 0 ? ` (${f.length} of them in a transaction)` : ""}.\n` + (d ? " This dialect applies a plan atomically, so the run is rolled back.\n" : ` This dialect does NOT apply a plan atomically: those ${i} are COMMITTED and there is no rollback.\n The next \`voltro db apply\` resumes from operation ${t} — the ledger records the sequence.\n`) })));
|
|
2967
|
+
a.push(o), yield* Fi(e, m, t, "applied", o.durationMs);
|
|
2955
2968
|
}
|
|
2956
2969
|
} finally {
|
|
2957
2970
|
yield* O(e, { schema: n.lockSchema }).pipe(S.orDie);
|
|
@@ -2961,23 +2974,23 @@ BEGIN
|
|
|
2961
2974
|
let e = _.operations.slice(0, 10).map((e) => ` - ${e.op.kind} ${"table" in e.op ? e.op.table : ""}${"column" in e.op ? `.${String(e.op.column)}` : ""}`).join("\n");
|
|
2962
2975
|
return yield* S.die(/* @__PURE__ */ Error(`applyPlan: the migration did not converge. ${l.operations.length} operation(s) were executed without error, but re-planning against the live schema still finds ${_.operations.length}:\n${e}${_.operations.length > 10 ? `\n … and ${_.operations.length - 10} more` : ""}\nNo fingerprint was recorded — recording one would make the next boot report "schema up to date" for a schema that was never applied. This is a framework bug; the schema is unchanged and safe.\nTwo causes look identical from here, so read the list before assuming either:\n - the DDL for those operations is a no-op (it succeeded and changed nothing), or\n - the planner cannot see what the DDL did, so it proposes the same work again — which is what an\n operation naming an object a PREVIOUS operation created or renamed usually means.\nReport the operation kinds above with the column types involved.`));
|
|
2963
2976
|
}
|
|
2964
|
-
let y = a.filter((e) => e.status === "applied").length, b = Date.now() - i, x = m, C = (/* @__PURE__ */ new Date()).toISOString(),
|
|
2977
|
+
let y = a.filter((e) => e.status === "applied").length, b = Date.now() - i, x = m, C = (/* @__PURE__ */ new Date()).toISOString(), ee = yield* U(e, C), w = [...f, ...h.map((e) => e.planned)];
|
|
2965
2978
|
yield* e`
|
|
2966
2979
|
INSERT INTO ${e("_voltro_migration_plans")}
|
|
2967
2980
|
(${e("id")}, ${e("fingerprint")}, ${e("liveFingerprint")}, ${e("operations")},
|
|
2968
2981
|
${e("appliedBy")}, ${e("environment")}, ${e("source")},
|
|
2969
2982
|
${e("durationMs")}, ${e("appliedAt")}, ${e("notes")})
|
|
2970
2983
|
VALUES
|
|
2971
|
-
(${x}, ${l.toFingerprint}, ${_.fromFingerprint}, ${JSON.stringify(
|
|
2984
|
+
(${x}, ${l.toFingerprint}, ${_.fromFingerprint}, ${JSON.stringify(w)},
|
|
2972
2985
|
${n.appliedBy}, ${n.environment}, ${n.source},
|
|
2973
|
-
${b}, ${
|
|
2974
|
-
`, yield*
|
|
2975
|
-
let
|
|
2976
|
-
return yield* S.promise(() => v({ changedTables:
|
|
2986
|
+
${b}, ${ee}, ${n.notes ?? null})
|
|
2987
|
+
`, yield* Li(e, m);
|
|
2988
|
+
let te = [...new Set(w.flatMap((e) => e.op.kind === "rename-table" ? [e.op.to] : [e.op.table]))];
|
|
2989
|
+
return yield* S.promise(() => v({ changedTables: te }).catch(() => {})), {
|
|
2977
2990
|
id: x,
|
|
2978
2991
|
appliedAt: C,
|
|
2979
2992
|
fingerprint: l.toFingerprint,
|
|
2980
|
-
operations:
|
|
2993
|
+
operations: w,
|
|
2981
2994
|
appliedBy: n.appliedBy,
|
|
2982
2995
|
environment: n.environment,
|
|
2983
2996
|
durationMs: b,
|
|
@@ -2985,14 +2998,14 @@ BEGIN
|
|
|
2985
2998
|
source: n.source,
|
|
2986
2999
|
...n.notes ? { notes: n.notes } : {}
|
|
2987
3000
|
};
|
|
2988
|
-
}),
|
|
3001
|
+
}), Ui = (e) => e.operations.filter((e) => e.blocked).map((e) => ` - ${e.op.kind} ${"table" in e.op ? `[${e.op.table}]` : ""}: ${e.reason ?? "<no reason>"}\n fix: ${e.blocked?.fix ?? "<no fix>"}`).join("\n"), Wi = (e) => e`
|
|
2989
3002
|
SELECT fingerprint
|
|
2990
3003
|
FROM _voltro_migration_plans
|
|
2991
3004
|
ORDER BY ${e("appliedAt")} DESC
|
|
2992
3005
|
LIMIT 1
|
|
2993
|
-
`.pipe(S.map((e) => e.length > 0 ? e[0].fingerprint : void 0), S.catchAll(() => S.succeed(void 0))),
|
|
2994
|
-
if ((yield*
|
|
2995
|
-
let r = `plan_${Date.now().toString(36)}`, i = yield*
|
|
3006
|
+
`.pipe(S.map((e) => e.length > 0 ? e[0].fingerprint : void 0), S.catchAll(() => S.succeed(void 0))), Gi = (e, t, n) => S.gen(function* () {
|
|
3007
|
+
if ((yield* Wi(e)) === t.toFingerprint) return "already-current";
|
|
3008
|
+
let r = `plan_${Date.now().toString(36)}`, i = yield* U(e, (/* @__PURE__ */ new Date()).toISOString());
|
|
2996
3009
|
return yield* e`
|
|
2997
3010
|
INSERT INTO ${e("_voltro_migration_plans")}
|
|
2998
3011
|
(${e("id")}, ${e("fingerprint")}, ${e("liveFingerprint")}, ${e("operations")},
|
|
@@ -3003,8 +3016,8 @@ BEGIN
|
|
|
3003
3016
|
${n.appliedBy}, ${n.environment}, ${n.source},
|
|
3004
3017
|
${0}, ${i}, ${"no DDL — the declared schema already matched the database"})
|
|
3005
3018
|
`, "recorded";
|
|
3006
|
-
}).pipe(S.catchAll(() => S.succeed("already-current"))),
|
|
3007
|
-
let n =
|
|
3019
|
+
}).pipe(S.catchAll(() => S.succeed("already-current"))), Ki = (e, t) => S.gen(function* () {
|
|
3020
|
+
let n = Gt(I(t, Ne(e))), r = yield* Wi(e);
|
|
3008
3021
|
return r === n ? {
|
|
3009
3022
|
kind: "up-to-date",
|
|
3010
3023
|
fingerprint: n
|
|
@@ -3013,23 +3026,23 @@ BEGIN
|
|
|
3013
3026
|
expected: n,
|
|
3014
3027
|
...r === void 0 ? {} : { actual: r }
|
|
3015
3028
|
};
|
|
3016
|
-
}),
|
|
3029
|
+
}), qi = [
|
|
3017
3030
|
"pgeagertest_",
|
|
3018
3031
|
"mig_e2e_",
|
|
3019
3032
|
"mig_test_",
|
|
3020
3033
|
"mysqleagertest_",
|
|
3021
3034
|
"mssqleagertest_",
|
|
3022
3035
|
"sqliteeagertest_"
|
|
3023
|
-
],
|
|
3036
|
+
], Ji = (e) => qi.some((t) => e.startsWith(t)), Yi = (e, t) => S.gen(function* () {
|
|
3024
3037
|
if (process.env.VOLTRO_TEST_FIXTURE_GC === "off") return [];
|
|
3025
|
-
let n = t.filter((e) =>
|
|
3038
|
+
let n = t.filter((e) => Ji(e.name)).map((e) => e.name);
|
|
3026
3039
|
if (n.length === 0) return [];
|
|
3027
3040
|
for (let t of n) yield* e.unsafe(`DROP TABLE IF EXISTS "${t}" CASCADE`).pipe(S.catchAll(() => S.void));
|
|
3028
3041
|
return n;
|
|
3029
|
-
}),
|
|
3042
|
+
}), Xi = () => {
|
|
3030
3043
|
let e = (process.env.VOLTRO_DB_IGNORE_TABLES ?? "").split(",").map((e) => e.trim()).filter((e) => e.length > 0);
|
|
3031
3044
|
return e.length > 0 ? { ignoreTables: e } : {};
|
|
3032
|
-
},
|
|
3045
|
+
}, Zi = (e) => {
|
|
3033
3046
|
if (e === void 0) return;
|
|
3034
3047
|
let t = e.trim();
|
|
3035
3048
|
if (t === "") return;
|
|
@@ -3039,48 +3052,48 @@ BEGIN
|
|
|
3039
3052
|
kind: "tables",
|
|
3040
3053
|
tables: new Set(n)
|
|
3041
3054
|
} : void 0;
|
|
3042
|
-
},
|
|
3055
|
+
}, Qi = (e) => typeof e.table == "string" ? e.table : void 0, $i = (e, t = { kind: "all" }) => ({
|
|
3043
3056
|
...e,
|
|
3044
3057
|
operations: e.operations.map((e) => {
|
|
3045
3058
|
if (!e.blocked || e.classification !== "lossy") return e;
|
|
3046
3059
|
if (t?.kind === "tables") {
|
|
3047
|
-
let n =
|
|
3060
|
+
let n = Qi(e.op);
|
|
3048
3061
|
if (n === void 0 || !t.tables.has(n)) return e;
|
|
3049
3062
|
}
|
|
3050
3063
|
let { blocked: n, ...r } = e;
|
|
3051
3064
|
return r;
|
|
3052
3065
|
})
|
|
3053
|
-
}),
|
|
3054
|
-
let t =
|
|
3066
|
+
}), ea = (e, t, n) => t === "postgres" ? Zt(e, n).pipe(S.flatMap((e) => {
|
|
3067
|
+
let t = Qt(e);
|
|
3055
3068
|
return t === void 0 ? S.void : S.logWarning(`auto-migrate: ${t}`).pipe(S.annotateLogs({ scope: "voltro:migrate" }));
|
|
3056
|
-
}), S.catchAll(() => S.void)) : S.void,
|
|
3069
|
+
}), S.catchAll(() => S.void)) : S.void, ta = (e, t, n) => S.gen(function* () {
|
|
3057
3070
|
let r = Ne(e), i = t;
|
|
3058
3071
|
if (process.env.VOLTRO_MIGRATE_FORCE !== "1") {
|
|
3059
|
-
let t =
|
|
3060
|
-
if ((yield*
|
|
3072
|
+
let t = Gt(I(i, r));
|
|
3073
|
+
if ((yield* Wi(e)) === t) return yield* ea(e, r, i), {
|
|
3061
3074
|
kind: "up-to-date",
|
|
3062
3075
|
fingerprint: t
|
|
3063
3076
|
};
|
|
3064
3077
|
}
|
|
3065
|
-
let a = yield*
|
|
3078
|
+
let a = yield* tr(e), o = yield* Yi(e, a.tables);
|
|
3066
3079
|
o.length > 0 && (yield* S.logInfo(`auto-migrate: reaped ${o.length} test-fixture leftover(s)`).pipe(S.annotateLogs({
|
|
3067
3080
|
scope: "voltro:migrate",
|
|
3068
3081
|
count: o.length
|
|
3069
|
-
})), a = yield*
|
|
3070
|
-
let s = new Set(t.map((e) => e.tableName)), c = (e) => e.filter((e) => !h(e.name) || s.has(e.name)), l =
|
|
3082
|
+
})), a = yield* tr(e));
|
|
3083
|
+
let s = new Set(t.map((e) => e.tableName)), c = (e) => e.filter((e) => !h(e.name) || s.has(e.name)), l = Pn({
|
|
3071
3084
|
declared: i,
|
|
3072
3085
|
live: { tables: c(a.tables) },
|
|
3073
3086
|
dialect: r,
|
|
3074
|
-
...
|
|
3087
|
+
...Xi()
|
|
3075
3088
|
});
|
|
3076
3089
|
if (l.summary.blocked > 0) {
|
|
3077
|
-
let e = l.operations.filter((e) => e.blocked).every((e) => e.classification === "lossy"), t =
|
|
3078
|
-
if (t === void 0 || !e || (l =
|
|
3090
|
+
let e = l.operations.filter((e) => e.blocked).every((e) => e.classification === "lossy"), t = Zi(process.env.VOLTRO_DESTRUCTIVE_OK);
|
|
3091
|
+
if (t === void 0 || !e || (l = $i(l, t), l.operations.some((e) => e.blocked))) return {
|
|
3079
3092
|
kind: "refused-blocked",
|
|
3080
3093
|
plan: l
|
|
3081
3094
|
};
|
|
3082
3095
|
}
|
|
3083
|
-
return l.operations.length === 0 ? (yield*
|
|
3096
|
+
return l.operations.length === 0 ? (yield* Gi(e, l, {
|
|
3084
3097
|
appliedBy: n.appliedBy,
|
|
3085
3098
|
environment: n.environment === "prod" ? "dev" : n.environment,
|
|
3086
3099
|
source: "auto-diff"
|
|
@@ -3089,37 +3102,37 @@ BEGIN
|
|
|
3089
3102
|
fingerprint: l.toFingerprint
|
|
3090
3103
|
}) : {
|
|
3091
3104
|
kind: "applied",
|
|
3092
|
-
applied: yield*
|
|
3105
|
+
applied: yield* Hi(e, l, {
|
|
3093
3106
|
declared: t,
|
|
3094
3107
|
appliedBy: n.appliedBy,
|
|
3095
3108
|
environment: n.environment === "prod" ? "dev" : n.environment,
|
|
3096
3109
|
source: "auto-diff",
|
|
3097
3110
|
replan: (e) => S.gen(function* () {
|
|
3098
|
-
let t = yield*
|
|
3099
|
-
return
|
|
3111
|
+
let t = yield* tr(e);
|
|
3112
|
+
return Pn({
|
|
3100
3113
|
declared: i,
|
|
3101
3114
|
live: { tables: c(t.tables) },
|
|
3102
3115
|
dialect: r,
|
|
3103
|
-
...
|
|
3116
|
+
...Xi()
|
|
3104
3117
|
});
|
|
3105
3118
|
})
|
|
3106
3119
|
}),
|
|
3107
3120
|
plan: l
|
|
3108
3121
|
};
|
|
3109
|
-
}),
|
|
3122
|
+
}), na = (e, t, n) => process.env.VOLTRO_AUTO_MIGRATE === "0" ? S.succeed({
|
|
3110
3123
|
kind: "skipped",
|
|
3111
3124
|
reason: "VOLTRO_AUTO_MIGRATE=0"
|
|
3112
|
-
}) : n.environment === "prod" ?
|
|
3125
|
+
}) : n.environment === "prod" ? Ki(e, t) : ta(e, t, n), ra = (e, t) => {
|
|
3113
3126
|
switch (e.kind) {
|
|
3114
3127
|
case "skipped": return `auto-migrate: skipped (${e.reason})`;
|
|
3115
|
-
case "up-to-date": return `auto-migrate: schema up to date (${t}, fingerprint=${
|
|
3128
|
+
case "up-to-date": return `auto-migrate: schema up to date (${t}, fingerprint=${Kt(e.fingerprint)})`;
|
|
3116
3129
|
case "applied": {
|
|
3117
3130
|
let t = e.plan.summary;
|
|
3118
|
-
return `auto-migrate: applied ${e.applied.appliedOps} op(s) in ${e.applied.durationMs}ms [safe=${t.safe} needs-default=${t.needsDefault} needs-backfill=${t.needsBackfill} rename=${t.needsRenameAnnotation} lossy=${t.lossy}] fingerprint=${
|
|
3131
|
+
return `auto-migrate: applied ${e.applied.appliedOps} op(s) in ${e.applied.durationMs}ms [safe=${t.safe} needs-default=${t.needsDefault} needs-backfill=${t.needsBackfill} rename=${t.needsRenameAnnotation} lossy=${t.lossy}] fingerprint=${Kt(e.applied.fingerprint)}`;
|
|
3119
3132
|
}
|
|
3120
|
-
case "prod-mismatch": return `auto-migrate: SCHEMA FINGERPRINT MISMATCH — declared=${
|
|
3133
|
+
case "prod-mismatch": return `auto-migrate: SCHEMA FINGERPRINT MISMATCH — declared=${Kt(e.expected)}` + (e.actual ? ` live=${Kt(e.actual)}` : " live=<no _voltro_migration_plans row>") + ". Run `voltro db apply --plan plan.json` from the deploy pipeline before serving.";
|
|
3121
3134
|
case "refused-blocked": {
|
|
3122
|
-
let t = e.plan.operations.filter((e) => e.blocked), n = t.filter((e) => e.op.kind === "drop-table").length, r = t.filter((e) => e.op.kind === "drop-table").map((e) => "table" in e.op ? e.op.table : "").filter(Boolean), i = t.filter((e) => e.op.kind === "add-column").length, a = t.filter((e) => e.op.kind === "drop-column").length, o = t.filter((e) => e.classification === "needs-rename-annotation").length, s = `auto-migrate: REFUSED — ${e.plan.summary.blocked} blocked operation(s):\n` +
|
|
3135
|
+
let t = e.plan.operations.filter((e) => e.blocked), n = t.filter((e) => e.op.kind === "drop-table").length, r = t.filter((e) => e.op.kind === "drop-table").map((e) => "table" in e.op ? e.op.table : "").filter(Boolean), i = t.filter((e) => e.op.kind === "add-column").length, a = t.filter((e) => e.op.kind === "drop-column").length, o = t.filter((e) => e.classification === "needs-rename-annotation").length, s = `auto-migrate: REFUSED — ${e.plan.summary.blocked} blocked operation(s):\n` + Ui(e.plan), c = [""];
|
|
3123
3136
|
if (n > 0 && c.push(`${n} table(s) exist in the live DB but aren't in your declared schema.`, "This is usually one of three things:", " (a) You're iterating on the schema — the table file got renamed, moved, or temporarily commented out.", " → Restore the declaration. Your data stays intact.", " (b) You want to KEEP the table but NOT manage it with Voltro (a leftover from another tool —", " a Strapi/Rails/legacy migration artifact, or an externally-owned table).", ` → Set \`VOLTRO_DB_IGNORE_TABLES=${r.join(",")}\` (comma-separated).`, " The planner excludes those tables from the diff entirely — it never drops them, and they", " stop blocking your OTHER (additive) changes. This is the fix when a leftover freezes your schema.", " (c) You actually want to drop the table.", ` → Set \`VOLTRO_DESTRUCTIVE_OK=${r.join(",")}\` for ONE run — it acknowledges`, " the data loss for THOSE tables only; every other lossy op in this plan stays blocked.", " (`VOLTRO_DESTRUCTIVE_OK=1` acknowledges all of them, which is rarely what you mean.)", " There is deliberately no `dropped()` marker for a TABLE, unlike for a column: a", " dropped column leaves a slot worth documenting in the declaration, a dropped table", " leaves nothing — the marker would be a dead entry you must remember to delete.", " Soft-drop: set `VOLTRO_SOFT_DROP=1` alongside DESTRUCTIVE_OK to RENAME instead of DROP", " (data survives as `<name>__dropped_<ts>` for ~7d; restorable via `voltro db restore-snapshot`)."), i > 0 && c.push(`${i} required column(s) need a backfill strategy before adding to a populated table.`, " → Annotate the column: `.backfill(sql`<expr>`)` or `.backfill(row => <fn>)` or `.default(<value>)`.", " Existing rows get the backfill value; the column then lands as NOT NULL."), a > 0) {
|
|
3124
3137
|
let t = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map();
|
|
3125
3138
|
for (let r of e.plan.operations) {
|
|
@@ -3136,7 +3149,7 @@ BEGIN
|
|
|
3136
3149
|
return o > 0 && c.push(`${o} column(s) look like renames (one column gone + a new one of same shape appeared).`, " → On the NEW column add `.renamedFrom('<oldName>')` so the planner emits RENAME instead of DROP+ADD."), c.push("", "See `voltro db plan` for the full machine-readable diff."), s + "\n" + c.join("\n");
|
|
3137
3150
|
}
|
|
3138
3151
|
}
|
|
3139
|
-
},
|
|
3152
|
+
}, ia = w({ scope: "voltro:migrate" }), aa = /* @__PURE__ */ new Set([
|
|
3140
3153
|
"node_modules",
|
|
3141
3154
|
"dist",
|
|
3142
3155
|
"build",
|
|
@@ -3145,12 +3158,12 @@ BEGIN
|
|
|
3145
3158
|
".next",
|
|
3146
3159
|
".git",
|
|
3147
3160
|
".framework"
|
|
3148
|
-
]),
|
|
3161
|
+
]), oa = async (e) => {
|
|
3149
3162
|
let t = [], n = async (e) => {
|
|
3150
|
-
let r = await
|
|
3163
|
+
let r = await te.readdir(e, { withFileTypes: !0 }).catch(() => []);
|
|
3151
3164
|
for (let i of r) {
|
|
3152
|
-
if (
|
|
3153
|
-
let r =
|
|
3165
|
+
if (aa.has(i.name)) continue;
|
|
3166
|
+
let r = ne(e, i.name);
|
|
3154
3167
|
i.isDirectory() ? await n(r) : i.isFile() && m.test(i.name) && t.push(r);
|
|
3155
3168
|
}
|
|
3156
3169
|
};
|
|
@@ -3158,12 +3171,12 @@ BEGIN
|
|
|
3158
3171
|
let n = e.split("/").pop() ?? e, r = t.split("/").pop() ?? t;
|
|
3159
3172
|
return n.localeCompare(r);
|
|
3160
3173
|
});
|
|
3161
|
-
},
|
|
3174
|
+
}, sa = async (e) => {
|
|
3162
3175
|
let t = [];
|
|
3163
3176
|
for (let n of e) {
|
|
3164
|
-
let e = (await import(
|
|
3177
|
+
let e = (await import(re(n).href)).default;
|
|
3165
3178
|
if (!g(e)) {
|
|
3166
|
-
|
|
3179
|
+
ia.warn("migration file has no default-exported `migration(...)` — skipped", { file: n });
|
|
3167
3180
|
continue;
|
|
3168
3181
|
}
|
|
3169
3182
|
t.push({
|
|
@@ -3172,11 +3185,11 @@ BEGIN
|
|
|
3172
3185
|
});
|
|
3173
3186
|
}
|
|
3174
3187
|
return t;
|
|
3175
|
-
},
|
|
3188
|
+
}, ca = (e) => e`
|
|
3176
3189
|
SELECT ${e("id")}
|
|
3177
3190
|
FROM ${e("_voltro_migration_plans")}
|
|
3178
3191
|
WHERE ${e("source")} = 'file'
|
|
3179
|
-
`.pipe(S.map((e) => e.map((e) => e.id)), S.catchAll(() => S.succeed([]))),
|
|
3192
|
+
`.pipe(S.map((e) => e.map((e) => e.id)), S.catchAll(() => S.succeed([]))), la = class extends Error {
|
|
3180
3193
|
migrationId;
|
|
3181
3194
|
file;
|
|
3182
3195
|
cause;
|
|
@@ -3184,7 +3197,7 @@ BEGIN
|
|
|
3184
3197
|
constructor(e, t, n) {
|
|
3185
3198
|
super(`migration ${e}: up() SUCCEEDED but the ledger row could not be written.\n The change IS in the database. It is NOT recorded, so the next run would apply it AGAIN.\n Do not re-run ${t} until this is resolved.\n Cause: ${n instanceof Error ? n.message : String(n)}`), this.migrationId = e, this.file = t, this.cause = n, this.name = "FileMigrationLedgerError";
|
|
3186
3199
|
}
|
|
3187
|
-
},
|
|
3200
|
+
}, ua = (e, t, n, r) => S.gen(function* () {
|
|
3188
3201
|
let i = Date.now(), a = (/* @__PURE__ */ new Date()).toISOString(), o = {
|
|
3189
3202
|
sql: e,
|
|
3190
3203
|
log: {
|
|
@@ -3205,7 +3218,7 @@ BEGIN
|
|
|
3205
3218
|
});
|
|
3206
3219
|
let c = Date.now() - i;
|
|
3207
3220
|
!S.isEffect(s) && c < 2 && (yield* S.logWarning(`migration ${t.migration.id}: up() resolved in ${c}ms — did the body \`await\` an \`@effect/sql\` Effect by accident? \`sql.unsafe(...)\` returns an Effect, not a Promise; \`await\` on it is a silent no-op. Switch the body to \`Effect.gen(function* () { yield* sql.unsafe(...) })\` form.`).pipe(S.annotateLogs({ scope: `migrations:file:${t.migration.id}` })));
|
|
3208
|
-
let l = yield*
|
|
3221
|
+
let l = yield* U(e, a);
|
|
3209
3222
|
return yield* e`
|
|
3210
3223
|
INSERT INTO ${e("_voltro_migration_plans")}
|
|
3211
3224
|
(${e("id")}, ${e("fingerprint")}, ${e("operations")},
|
|
@@ -3218,10 +3231,10 @@ BEGIN
|
|
|
3218
3231
|
}])},
|
|
3219
3232
|
${r}, ${n}, ${"file"},
|
|
3220
3233
|
${c}, ${l}, ${t.migration.description})
|
|
3221
|
-
`.pipe(S.mapError((e) => new
|
|
3222
|
-
}),
|
|
3234
|
+
`.pipe(S.mapError((e) => new la(t.migration.id, t.file, e))), { durationMs: c };
|
|
3235
|
+
}), da = (e, t) => S.gen(function* () {
|
|
3223
3236
|
let n = yield* S.tryPromise({
|
|
3224
|
-
try: () =>
|
|
3237
|
+
try: () => oa(ne(t, "migrations")),
|
|
3225
3238
|
catch: (e) => e
|
|
3226
3239
|
});
|
|
3227
3240
|
if (n.length === 0) return {
|
|
@@ -3229,20 +3242,20 @@ BEGIN
|
|
|
3229
3242
|
skipped: []
|
|
3230
3243
|
};
|
|
3231
3244
|
let r = yield* S.tryPromise({
|
|
3232
|
-
try: () =>
|
|
3245
|
+
try: () => sa(n),
|
|
3233
3246
|
catch: (e) => e
|
|
3234
3247
|
});
|
|
3235
3248
|
if (r.length === 0) return {
|
|
3236
3249
|
pending: [],
|
|
3237
3250
|
skipped: []
|
|
3238
3251
|
};
|
|
3239
|
-
let i = new Set(yield*
|
|
3252
|
+
let i = new Set(yield* ca(e));
|
|
3240
3253
|
return {
|
|
3241
3254
|
pending: r.filter((e) => !i.has(e.migration.id)),
|
|
3242
3255
|
skipped: r.filter((e) => i.has(e.migration.id)).map((e) => e.migration.id)
|
|
3243
3256
|
};
|
|
3244
|
-
}),
|
|
3245
|
-
let { pending: n, skipped: r } = yield*
|
|
3257
|
+
}), fa = (e, t) => da(e, t).pipe(S.map((e) => e.pending.map((e) => e.migration.id))), pa = (e, t) => S.gen(function* () {
|
|
3258
|
+
let { pending: n, skipped: r } = yield* da(e, t.projectRoot);
|
|
3246
3259
|
if (n.length === 0) return {
|
|
3247
3260
|
applied: [],
|
|
3248
3261
|
skipped: r
|
|
@@ -3256,7 +3269,7 @@ BEGIN
|
|
|
3256
3269
|
id: r.migration.id,
|
|
3257
3270
|
file: r.file
|
|
3258
3271
|
}));
|
|
3259
|
-
let { durationMs: n } = yield*
|
|
3272
|
+
let { durationMs: n } = yield* ua(e, r, t.env, t.appliedBy);
|
|
3260
3273
|
i.push({
|
|
3261
3274
|
id: r.migration.id,
|
|
3262
3275
|
durationMs: n
|
|
@@ -3273,18 +3286,18 @@ BEGIN
|
|
|
3273
3286
|
applied: i,
|
|
3274
3287
|
skipped: r
|
|
3275
3288
|
};
|
|
3276
|
-
}),
|
|
3289
|
+
}), ma = (e, t) => e`
|
|
3277
3290
|
SELECT ${e("id")}
|
|
3278
3291
|
FROM ${e("_voltro_migration_plans")}
|
|
3279
3292
|
WHERE ${e("id")} = ${t} AND ${e("source")} = 'file'
|
|
3280
3293
|
LIMIT 1
|
|
3281
|
-
`,
|
|
3282
|
-
if (!(yield*
|
|
3294
|
+
`, ha = (e, t) => S.gen(function* () {
|
|
3295
|
+
if (!(yield* ma(e, t.id))[0]) return yield* S.fail(/* @__PURE__ */ Error(`rollback: ${t.id} not found in _voltro_migration_plans (file source)`));
|
|
3283
3296
|
let n = yield* S.tryPromise({
|
|
3284
|
-
try: () =>
|
|
3297
|
+
try: () => oa(ne(t.projectRoot, "migrations")),
|
|
3285
3298
|
catch: (e) => e
|
|
3286
3299
|
}), r = (yield* S.tryPromise({
|
|
3287
|
-
try: () =>
|
|
3300
|
+
try: () => sa(n),
|
|
3288
3301
|
catch: (e) => e
|
|
3289
3302
|
})).find((e) => e.migration.id === t.id);
|
|
3290
3303
|
if (!r) return yield* S.fail(/* @__PURE__ */ Error(`rollback: file for migration ${t.id} not found on disk under ${t.projectRoot}/migrations/`));
|
|
@@ -3317,8 +3330,8 @@ BEGIN
|
|
|
3317
3330
|
} finally {
|
|
3318
3331
|
yield* O(e, { schema: t.lockSchema }).pipe(S.orDie);
|
|
3319
3332
|
}
|
|
3320
|
-
}),
|
|
3321
|
-
let t = yield*
|
|
3333
|
+
}), ga = (e) => S.gen(function* () {
|
|
3334
|
+
let t = yield* T.SqlClient, n = yield* t`
|
|
3322
3335
|
SELECT id, fingerprint, appliedAt FROM _voltro_migration_plans
|
|
3323
3336
|
WHERE source = 'auto-diff'
|
|
3324
3337
|
AND squashedAt IS NULL
|
|
@@ -3362,7 +3375,7 @@ BEGIN
|
|
|
3362
3375
|
snapshotFingerprint: e.fingerprint,
|
|
3363
3376
|
snapshotId: i
|
|
3364
3377
|
};
|
|
3365
|
-
}),
|
|
3378
|
+
}), _a = { safe: !0 }, va = (e) => {
|
|
3366
3379
|
switch (e.kind) {
|
|
3367
3380
|
case "drop-column": return {
|
|
3368
3381
|
safe: !1,
|
|
@@ -3389,7 +3402,7 @@ BEGIN
|
|
|
3389
3402
|
reason: `old instances read/write "${e.table}"."${e.column}" as ${e.from}; the new ${e.to} type can reject their writes or fail to decode their reads`,
|
|
3390
3403
|
remedy: "add a new column of the target type + backfill + dual-write, cut code over, then drop the old column in a LATER deploy"
|
|
3391
3404
|
};
|
|
3392
|
-
case "alter-column-nullability": return e.toNullable ?
|
|
3405
|
+
case "alter-column-nullability": return e.toNullable ? _a : {
|
|
3393
3406
|
safe: !1,
|
|
3394
3407
|
reason: `old instances may INSERT "${e.table}" without (or with NULL in) "${e.column}", which the new NOT NULL rejects`,
|
|
3395
3408
|
remedy: `make code always write "${e.column}" and deploy that first; add NOT NULL in a LATER deploy (with a default to cover the gap)`
|
|
@@ -3419,12 +3432,12 @@ BEGIN
|
|
|
3419
3432
|
case "drop-unique":
|
|
3420
3433
|
case "drop-unique-composite":
|
|
3421
3434
|
case "drop-foreign-key":
|
|
3422
|
-
case "drop-check": return
|
|
3435
|
+
case "drop-check": return _a;
|
|
3423
3436
|
}
|
|
3424
|
-
},
|
|
3437
|
+
}, ya = (e) => {
|
|
3425
3438
|
let t = [];
|
|
3426
3439
|
for (let n of e) {
|
|
3427
|
-
let e =
|
|
3440
|
+
let e = va(n.op);
|
|
3428
3441
|
e.safe || t.push({
|
|
3429
3442
|
op: n,
|
|
3430
3443
|
reason: e.reason,
|
|
@@ -3432,7 +3445,7 @@ BEGIN
|
|
|
3432
3445
|
});
|
|
3433
3446
|
}
|
|
3434
3447
|
return t;
|
|
3435
|
-
},
|
|
3448
|
+
}, ba = (e) => {
|
|
3436
3449
|
if (!e.enabled || e.unsafeCount === 0) return {
|
|
3437
3450
|
refuse: !1,
|
|
3438
3451
|
warnForced: !1,
|
|
@@ -3448,18 +3461,18 @@ BEGIN
|
|
|
3448
3461
|
warnForced: !1,
|
|
3449
3462
|
message: `${t}. Old instances would break against the new schema mid-rollout. Split into expand → deploy → contract (see the ⚠ list above), deploy with no overlap (maintenance window / scale-to-zero), or pass --force to override.`
|
|
3450
3463
|
};
|
|
3451
|
-
},
|
|
3464
|
+
}, xa = (e) => {
|
|
3452
3465
|
let t = e.table;
|
|
3453
3466
|
if (typeof t == "string") return t;
|
|
3454
3467
|
let n = e.from;
|
|
3455
3468
|
return typeof n == "string" ? n : void 0;
|
|
3456
|
-
},
|
|
3469
|
+
}, Sa = (e) => ({
|
|
3457
3470
|
kind: e.op.kind,
|
|
3458
|
-
table:
|
|
3471
|
+
table: xa(e.op),
|
|
3459
3472
|
classification: e.classification,
|
|
3460
3473
|
reason: e.reason,
|
|
3461
3474
|
blockedFix: e.blocked?.fix
|
|
3462
|
-
}),
|
|
3475
|
+
}), Ca = (e) => e.operations.map(Sa), wa = async (e) => {
|
|
3463
3476
|
let t = e.log ?? (() => {}), n = {
|
|
3464
3477
|
branchId: e.branchId,
|
|
3465
3478
|
mechanism: e.mechanism,
|
|
@@ -3478,10 +3491,10 @@ BEGIN
|
|
|
3478
3491
|
applied: !1,
|
|
3479
3492
|
converged: !1,
|
|
3480
3493
|
residual: r,
|
|
3481
|
-
infidelity:
|
|
3494
|
+
infidelity: Ca(o)
|
|
3482
3495
|
};
|
|
3483
3496
|
else {
|
|
3484
|
-
let i = await e.plan(), o =
|
|
3497
|
+
let i = await e.plan(), o = Ca(i), s = o.filter((e) => e.classification === "lossy"), c = $i(i), l = c.operations.filter((e) => e.blocked !== void 0).map(Sa);
|
|
3485
3498
|
if (l.length > 0) a = {
|
|
3486
3499
|
...n,
|
|
3487
3500
|
outcome: "blocked",
|
|
@@ -3506,7 +3519,7 @@ BEGIN
|
|
|
3506
3519
|
};
|
|
3507
3520
|
else {
|
|
3508
3521
|
await e.apply(c), t(`branch ${e.branchId}: applied ${o.length} operation(s)`);
|
|
3509
|
-
let i =
|
|
3522
|
+
let i = Ca(await e.replan());
|
|
3510
3523
|
a = {
|
|
3511
3524
|
...n,
|
|
3512
3525
|
outcome: i.length > 0 ? "diverged" : s.length > 0 ? "lossy" : "clean",
|
|
@@ -3544,7 +3557,7 @@ BEGIN
|
|
|
3544
3557
|
...a,
|
|
3545
3558
|
tornDown: o
|
|
3546
3559
|
};
|
|
3547
|
-
},
|
|
3560
|
+
}, Ta = (e) => {
|
|
3548
3561
|
switch (e.outcome) {
|
|
3549
3562
|
case "clean": return 0;
|
|
3550
3563
|
case "lossy": return 2;
|
|
@@ -3553,22 +3566,22 @@ BEGIN
|
|
|
3553
3566
|
case "infidelity": return 1;
|
|
3554
3567
|
case "failed": return 1;
|
|
3555
3568
|
}
|
|
3556
|
-
},
|
|
3569
|
+
}, Ea = (e) => ` ${e.classification === "lossy" ? "✗" : "•"} ${e.kind}${e.table ? ` ${e.table}` : ""} [${e.classification}]${e.reason ? ` — ${e.reason}` : ""}${e.blockedFix ? `\n ! ${e.blockedFix}` : ""}`, Da = (e) => {
|
|
3557
3570
|
let t = [];
|
|
3558
3571
|
if (t.push(`branch rehearsal · ${e.branchId} · mechanism ${e.mechanism}`), t.push(` branched ${e.branchedTables} table(s), replayed ${e.replayedForeignKeys} foreign key(s)`), e.outcome === "failed") t.push(` FAILED: ${e.error ?? "unknown error"}`);
|
|
3559
3572
|
else if (e.outcome === "infidelity") {
|
|
3560
3573
|
t.push(" BRANCH IS NOT A FAITHFUL COPY of the parent — the rehearsal proves nothing about your migration."), t.push(" The parent's own schema still differs from the branch by:");
|
|
3561
|
-
for (let n of e.infidelity) t.push(
|
|
3574
|
+
for (let n of e.infidelity) t.push(Ea(n));
|
|
3562
3575
|
} else {
|
|
3563
3576
|
t.push(` plan: ${e.operations.length} operation(s), ${e.lossy.length} lossy, ${e.blocked.length} refused`);
|
|
3564
|
-
for (let n of e.operations) t.push(
|
|
3565
|
-
if (e.lossy.length > 0 && (t.push(""), t.push(` ⚠ ${e.lossy.length} operation(s) DESTROY DATA. They were executed on the branch (it is`), t.push(" disposable) so they are rehearsed, but production refuses them until you set"), t.push(" VOLTRO_DESTRUCTIVE_OK — naming the tables, not `1`.")), e.blocked.length > 0 && (t.push(""), t.push(` ${e.blocked.length} operation(s) the planner will not auto-apply anywhere — the plan was NOT executed.`)), e.applied && (t.push(""), t.push(e.converged ? " ✓ applied on the branch, and the re-plan is EMPTY (the migration converges)." : ` ✗ applied, but the re-plan STILL proposes ${e.residual.length} operation(s) — this migration does not converge:`), !e.converged)) for (let n of e.residual) t.push(
|
|
3577
|
+
for (let n of e.operations) t.push(Ea(n));
|
|
3578
|
+
if (e.lossy.length > 0 && (t.push(""), t.push(` ⚠ ${e.lossy.length} operation(s) DESTROY DATA. They were executed on the branch (it is`), t.push(" disposable) so they are rehearsed, but production refuses them until you set"), t.push(" VOLTRO_DESTRUCTIVE_OK — naming the tables, not `1`.")), e.blocked.length > 0 && (t.push(""), t.push(` ${e.blocked.length} operation(s) the planner will not auto-apply anywhere — the plan was NOT executed.`)), e.applied && (t.push(""), t.push(e.converged ? " ✓ applied on the branch, and the re-plan is EMPTY (the migration converges)." : ` ✗ applied, but the re-plan STILL proposes ${e.residual.length} operation(s) — this migration does not converge:`), !e.converged)) for (let n of e.residual) t.push(Ea(n));
|
|
3566
3579
|
}
|
|
3567
3580
|
return t.push(e.tornDown ? ` branch ${e.branchId} torn down.` : ` branch ${e.branchId} KEPT — drop it when you are done.`), t.join("\n");
|
|
3568
|
-
},
|
|
3581
|
+
}, Oa = (e, ...t) => ({
|
|
3569
3582
|
_tag: "RawSqlFragment",
|
|
3570
3583
|
strings: [...e],
|
|
3571
3584
|
values: [...t]
|
|
3572
|
-
}),
|
|
3585
|
+
}), ka = (e) => typeof e == "object" && !!e && e._tag === "RawSqlFragment";
|
|
3573
3586
|
//#endregion
|
|
3574
|
-
export { A as DEFAULT_CDC_CHANNEL, m as FILE_MIGRATION_PATTERN,
|
|
3587
|
+
export { A as DEFAULT_CDC_CHANNEL, m as FILE_MIGRATION_PATTERN, la as FileMigrationLedgerError, qe as REACTIVE_TRIGGER_PREFIX, fe as VOLTRO_MIGRATION_LOCK_KEY, je as acquireMigrationLock, U as appliedAtValue, Lt as applyNamespacedSchema, Hi as applyPlan, Dt as applySchema, ba as assessRollingDeployGate, Ta as branchRehearsalExitCode, Hn as chunkTables, va as classifyRollingDeploySafety, I as declaredSnapshot, et as defaultArrayClause, $e as defaultClause, N as defaultJsonClause, ra as describeOutcome, Zi as destructiveScope, Zt as detectReactiveTriggerDrift, ii as emitAddIndexMysql, zr as emitCreateTableMysql, br as emitDropColumnDdl, xr as emitDropColumnDdlMysql, Et as emitFrameworkBootstrapSql, wt as emitNamespaceProvisionDdl, Tt as emitNamespacedSchemaSql, Ct as emitSchemaSql, nr as engineFromVersion, Gt as fingerprintSchema, ve as fnv1a64, Da as formatBranchRehearsal, Qt as formatReactiveTriggerDrift, Xi as ignoreTablesFromEnv, tr as introspectSchema, cr as isAlreadySatisfied, g as isFileMigration, ka as isRawSqlFragment, kt as isReRunSafeDdl, In as mapPgType, o as migration, ye as migrationLockKeyForSchema, D as migrationLockNameForSchema, ei as mysqlIndexPrefixFor, Ye as notifyFunctionName, P as numericIdSql, Fn as parseEnumCheck, fa as pendingFileMigrationIds, Pn as planMigrations, Rt as provisionTenantNamespace, Je as reactiveTriggerName, mt as reactiveTriggerRepairSql, Gi as recordUpToDate, wa as rehearseMigrationOnBranch, Sa as rehearsedOperation, O as releaseMigrationLock, Lr as renderColumnMysql, Mr as renderColumnPg, me as resolveMigrationLockSchema, ir as resolveMysqlEngine, ha as rollbackFileBasedMigration, ya as rollingDeployUnsafeOps, pa as runFileBasedMigrations, zt as runFrameworkBootstrap, It as runMigrate, na as runPlannedMigrations, Kt as shortFingerprint, qt as snapshotColumn, Oa as sql, M as sqlType, ga as squashMigrationPlans, $i as unblockLossy, Me as withMigrationLock };
|