@voltro/database 0.37.0 → 0.39.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/CHANGELOG.md +316 -0
- package/dist/{frameworkLiveTables-CeuTYhWm.js → frameworkLiveTables-BS6FuivX.js} +1 -1
- package/dist/index.js +6 -6
- package/dist/sql.js +407 -407
- package/package.json +2 -2
package/dist/sql.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { It as e, Jt as t, Lt as n, X as r, Z as i, _ as a, a as o, bt as s, c, et as l, i as u, l as d, m as f, mt as p, n as m, o as h, p as g, qt as _, r as v, tt as y } from "./frameworkLiveTables-
|
|
1
|
+
import { It as e, Jt as t, Lt as n, X as r, Z as i, _ as a, a as o, bt as s, c, et as l, i as u, l as d, m as f, mt as p, n as m, o as h, p as g, qt as _, r as v, tt as y } from "./frameworkLiveTables-BS6FuivX.js";
|
|
2
2
|
import { Effect as b, Schedule as x } from "effect";
|
|
3
3
|
import { createLogger as S } from "@voltro/logger";
|
|
4
4
|
import { SqlClient as C } from "@effect/sql";
|
|
@@ -38,20 +38,21 @@ var ie = (e, t, n, r = 400) => {
|
|
|
38
38
|
let t = o(e);
|
|
39
39
|
t !== void 0 && s.push(`db.${e}: ${t}`);
|
|
40
40
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
let c = ae(o("code"));
|
|
42
|
+
return c !== void 0 && s.push("", c), s.push(""), s.join("\n");
|
|
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;
|
|
44
45
|
let n = { ...e.fields }, r = [], i = [];
|
|
45
46
|
for (let t of e.appliedIndexes) {
|
|
46
|
-
if (!
|
|
47
|
+
if (!oe(t)) {
|
|
47
48
|
r.push(t);
|
|
48
49
|
continue;
|
|
49
50
|
}
|
|
50
|
-
let a =
|
|
51
|
+
let a = se(t.where), o = [];
|
|
51
52
|
for (let r of t.fields) {
|
|
52
|
-
let i =
|
|
53
|
+
let i = ce(r);
|
|
53
54
|
if (!(i in e.fields)) throw Error(`@voltro/migrate: uniqueActive '${t.name}' on '${e.tableName}' references unknown column '${i}'.`);
|
|
54
|
-
let s =
|
|
55
|
+
let s = le(t.name, i);
|
|
55
56
|
o.push(s), n[s] = {
|
|
56
57
|
type: "text",
|
|
57
58
|
nullable: !0,
|
|
@@ -74,7 +75,7 @@ var ie = (e, t, n, r = 400) => {
|
|
|
74
75
|
appliedIndexes: r,
|
|
75
76
|
appliedUniques: [...e.appliedUniques ?? [], ...i]
|
|
76
77
|
};
|
|
77
|
-
}, w = (e, t) => `${e}::${t}`,
|
|
78
|
+
}, w = (e, t) => `${e}::${t}`, de = (e, t) => {
|
|
78
79
|
let n = /* @__PURE__ */ new Set(), r = /* @__PURE__ */ new Set(), i = /* @__PURE__ */ new Set(), a = (e) => {
|
|
79
80
|
n.add(e);
|
|
80
81
|
let o = [...t(e)].filter((t) => t.target !== e).sort((e, t) => e.column.localeCompare(t.column));
|
|
@@ -83,21 +84,21 @@ var ie = (e, t, n, r = 400) => {
|
|
|
83
84
|
};
|
|
84
85
|
for (let t of [...e].sort()) r.has(t) || a(t);
|
|
85
86
|
return i;
|
|
86
|
-
},
|
|
87
|
+
}, fe = 6322741009312437n, pe = (e) => {
|
|
87
88
|
let t = e?.trim();
|
|
88
89
|
return t === void 0 || t === "" || t === "public" ? void 0 : t;
|
|
89
|
-
},
|
|
90
|
-
let t =
|
|
91
|
-
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;
|
|
92
93
|
return t;
|
|
93
|
-
}, ve = (e) => {
|
|
94
|
-
let t = fe(e);
|
|
95
|
-
return t === void 0 ? de : _e(`voltro_migration_lock:${t}`) & 9223372036854775807n;
|
|
96
94
|
}, ye = (e) => {
|
|
97
|
-
let t =
|
|
95
|
+
let t = pe(e);
|
|
96
|
+
return t === void 0 ? fe : ve(`voltro_migration_lock:${t}`) & 9223372036854775807n;
|
|
97
|
+
}, T = (e) => {
|
|
98
|
+
let t = `voltro_migration_${fe.toString(36)}`, n = pe(e);
|
|
98
99
|
if (n === void 0) return t;
|
|
99
100
|
let r = `${t}_${n}`;
|
|
100
|
-
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)}`;
|
|
101
102
|
}, be = 250, xe = () => {
|
|
102
103
|
let e = Number(process.env.VOLTRO_MIGRATION_LOCK_TIMEOUT_MS);
|
|
103
104
|
return Number.isFinite(e) && e > 0 ? e : 3e4;
|
|
@@ -124,23 +125,23 @@ var ie = (e, t, n, r = 400) => {
|
|
|
124
125
|
(n[0]?.res ?? -999) < 0 && (yield* b.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${t}' (sp_getapplock returned ${n[0]?.res ?? "no row"}; another migration is in progress).`)));
|
|
125
126
|
}), ke = (e, t) => b.gen(function* () {
|
|
126
127
|
yield* e`EXEC sp_releaseapplock @Resource = ${t}, @LockOwner = 'Session'`;
|
|
127
|
-
}), Ae = b.void,
|
|
128
|
-
let n =
|
|
128
|
+
}), Ae = b.void, E = (e, t) => {
|
|
129
|
+
let n = me(t);
|
|
129
130
|
return e.onDialectOrElse({
|
|
130
|
-
mysql: () => Te(e,
|
|
131
|
-
mssql: () => Oe(e,
|
|
131
|
+
mysql: () => Te(e, T(n)),
|
|
132
|
+
mssql: () => Oe(e, T(n)),
|
|
132
133
|
sqlite: () => Ae,
|
|
133
|
-
orElse: () => Se(e,
|
|
134
|
+
orElse: () => Se(e, ye(n))
|
|
134
135
|
});
|
|
135
|
-
},
|
|
136
|
-
let n =
|
|
136
|
+
}, D = (e, t) => {
|
|
137
|
+
let n = me(t);
|
|
137
138
|
return e.onDialectOrElse({
|
|
138
|
-
mysql: () => Ee(e,
|
|
139
|
-
mssql: () => ke(e,
|
|
139
|
+
mysql: () => Ee(e, T(n)),
|
|
140
|
+
mssql: () => ke(e, T(n)),
|
|
140
141
|
sqlite: () => Ae,
|
|
141
|
-
orElse: () => Ce(e,
|
|
142
|
+
orElse: () => Ce(e, ye(n))
|
|
142
143
|
});
|
|
143
|
-
}, je = (e, t, n) => b.acquireUseRelease(
|
|
144
|
+
}, je = (e, t, n) => b.acquireUseRelease(E(e, n), () => t, () => D(e, n).pipe(b.orDie)), Me = (e) => e.onDialectOrElse({
|
|
144
145
|
pg: () => "postgres",
|
|
145
146
|
mysql: () => "mysql",
|
|
146
147
|
mssql: () => "mssql",
|
|
@@ -153,7 +154,7 @@ var ie = (e, t, n, r = 400) => {
|
|
|
153
154
|
mariadb: "per-operation",
|
|
154
155
|
sqlite: "per-operation",
|
|
155
156
|
turso: "per-operation"
|
|
156
|
-
}, Pe = (e) => Ne[e],
|
|
157
|
+
}, Pe = (e) => Ne[e], O = "_voltro_migration_ops", Fe = l(O, {
|
|
157
158
|
id: e({ prefix: "mop" }),
|
|
158
159
|
runId: _(),
|
|
159
160
|
planFingerprint: _(),
|
|
@@ -216,9 +217,9 @@ var ie = (e, t, n, r = 400) => {
|
|
|
216
217
|
Object.keys(Ne);
|
|
217
218
|
//#endregion
|
|
218
219
|
//#region src/migrations/reactiveTriggerName.ts
|
|
219
|
-
var
|
|
220
|
+
var k = "framework_changes", Ke = "framework_changes_", qe = (e, t) => t === "framework_changes" ? `${Ke}${e}` : `${Ke}${t}_${e}`, Je = (e) => e === "framework_changes" ? "framework_notify_change" : `framework_notify_change_${e}`, Ye = "voltro:notify:v2", Xe = S({ scope: "voltro:migrate" }), A = (e) => {
|
|
220
221
|
Xe.warn(e.replace(/^\[voltro:migrate\]\s*/, ""));
|
|
221
|
-
},
|
|
222
|
+
}, j = (e, t) => {
|
|
222
223
|
let n = e.type;
|
|
223
224
|
if (e.spatial) {
|
|
224
225
|
if (t === "postgres") return `${e.spatial.kind}(${e.spatial.geomKind},${e.spatial.srid})`;
|
|
@@ -229,7 +230,7 @@ var O = "framework_changes", Ke = "framework_changes_", qe = (e, t) => t === "fr
|
|
|
229
230
|
return e.rawDdl;
|
|
230
231
|
}
|
|
231
232
|
if (n === "array" && e.arrayElement) {
|
|
232
|
-
if (t === "postgres") return `${
|
|
233
|
+
if (t === "postgres") return `${j({
|
|
233
234
|
...e,
|
|
234
235
|
type: e.arrayElement,
|
|
235
236
|
arrayElement: void 0
|
|
@@ -332,19 +333,19 @@ var O = "framework_changes", Ke = "framework_changes_", qe = (e, t) => t === "fr
|
|
|
332
333
|
}, Ze = (e, t) => {
|
|
333
334
|
if (!e.hasDefault || e.defaultFactory !== void 0) return null;
|
|
334
335
|
let n = e.defaultValue;
|
|
335
|
-
return n === "now" ? r(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) ? Qe(n, e, t) : typeof n == "object" && n ?
|
|
336
|
+
return n === "now" ? r(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) ? Qe(n, e, t) : typeof n == "object" && n ? M(n, t) : null;
|
|
336
337
|
}, Qe = (e, t, n) => {
|
|
337
|
-
if (n !== "postgres" || t.type !== "array" || t.arrayElement === void 0) return
|
|
338
|
-
let r =
|
|
338
|
+
if (n !== "postgres" || t.type !== "array" || t.arrayElement === void 0) return M(e, n);
|
|
339
|
+
let r = j({
|
|
339
340
|
...t,
|
|
340
341
|
type: t.arrayElement,
|
|
341
342
|
arrayElement: void 0
|
|
342
343
|
}, n);
|
|
343
344
|
return `DEFAULT '{${e.map((e) => typeof e == "number" || typeof e == "boolean" ? String(e) : `"${String(e).replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"`).join(",").replace(/'/g, "''")}}'::${r}[]`;
|
|
344
|
-
},
|
|
345
|
+
}, M = (e, t) => {
|
|
345
346
|
let n = JSON.stringify(e).replace(/'/g, "''");
|
|
346
347
|
return t === "postgres" ? `DEFAULT '${n}'::jsonb` : t === "mysql" || t === "mariadb" ? `DEFAULT (CONVERT('${n}' USING utf8mb4))` : `DEFAULT '${n}'`;
|
|
347
|
-
},
|
|
348
|
+
}, N = (e, t) => {
|
|
348
349
|
switch (t) {
|
|
349
350
|
case "postgres": return `"${e}" BIGSERIAL PRIMARY KEY`;
|
|
350
351
|
case "mysql":
|
|
@@ -366,19 +367,19 @@ var O = "framework_changes", Ke = "framework_changes_", qe = (e, t) => t === "fr
|
|
|
366
367
|
if (n !== "mysql" && n !== "mariadb") return r;
|
|
367
368
|
let a = t[e];
|
|
368
369
|
if (!a) return r;
|
|
369
|
-
let o =
|
|
370
|
+
let o = j(a, n).toUpperCase();
|
|
370
371
|
return o.endsWith("TEXT") || o.endsWith("BLOB") ? `${r}(${tt})` : r;
|
|
371
372
|
}, rt = (e, t) => {
|
|
372
373
|
if (!e.generatedAs) return null;
|
|
373
374
|
let { expr: n, stored: r } = e.generatedAs;
|
|
374
|
-
if (t === "postgres") return r ||
|
|
375
|
+
if (t === "postgres") return r || A("[voltro:migrate] generated column requested as VIRTUAL but postgres only supports STORED — promoting"), `GENERATED ALWAYS AS (${n}) STORED`;
|
|
375
376
|
if (t === "mysql" || t === "mariadb") return `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
|
|
376
377
|
if (t === "mssql") return `AS (${n})${r ? " PERSISTED" : ""}`;
|
|
377
378
|
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.");
|
|
378
379
|
return `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
|
|
379
380
|
}, it = (e, t, n, a, o = !1, s = !1) => {
|
|
380
|
-
if (t.type === "id" && t.idScheme?.kind === "numeric") return
|
|
381
|
-
let c = n === "mssql" && t.type === "text" && !t.generatedAs && t.maxLength === void 0 && a?.has(e) ? "NVARCHAR(450)" :
|
|
381
|
+
if (t.type === "id" && t.idScheme?.kind === "numeric") return N(e, n);
|
|
382
|
+
let c = n === "mssql" && t.type === "text" && !t.generatedAs && t.maxLength === void 0 && a?.has(e) ? "NVARCHAR(450)" : j(t, n), l = [i(e, n), c];
|
|
382
383
|
t.type === "id" && !s && l.push("PRIMARY KEY");
|
|
383
384
|
let u = rt(t, n);
|
|
384
385
|
if (u) l.push(u);
|
|
@@ -445,21 +446,21 @@ var O = "framework_changes", Ke = "framework_changes_", qe = (e, t) => t === "fr
|
|
|
445
446
|
using: " USING GIST",
|
|
446
447
|
withSuffix: "",
|
|
447
448
|
skip: !1
|
|
448
|
-
} : (
|
|
449
|
+
} : (A(`[voltro:migrate] index '${e}' on '${n}': ${t} doesn't support GiST — falling back to btree. Spatial queries on this column will fall back to sequential scan.`), a);
|
|
449
450
|
if (r === "gin") return t === "postgres" ? {
|
|
450
451
|
using: " USING GIN",
|
|
451
452
|
withSuffix: "",
|
|
452
453
|
skip: !1
|
|
453
|
-
} : t === "mysql" || t === "mariadb" ? (
|
|
454
|
+
} : t === "mysql" || t === "mariadb" ? (A(`[voltro:migrate] gin index '${e}' on '${n}': ${t} has no GIN access method — skipping (a btree on a JSON/array column can't serve containment/membership queries). Add a generated column for the specific path you query, then index that with .expressionIndex(...).`), {
|
|
454
455
|
using: "",
|
|
455
456
|
withSuffix: "",
|
|
456
457
|
skip: !0
|
|
457
|
-
}) : (
|
|
458
|
+
}) : (A(`[voltro:migrate] gin index '${e}' on '${n}': ${t} has no GIN access method — falling back to btree. Containment/membership queries won't use this index efficiently.`), a);
|
|
458
459
|
if (r === "brin") return t === "postgres" ? {
|
|
459
460
|
using: " USING BRIN",
|
|
460
461
|
withSuffix: "",
|
|
461
462
|
skip: !1
|
|
462
|
-
} : (
|
|
463
|
+
} : (A(`[voltro:migrate] brin index '${e}' on '${n}': ${t} has no BRIN access method — falling back to btree (larger on disk, but the range scan still works).`), a);
|
|
463
464
|
if (r === "hnsw") {
|
|
464
465
|
if (t === "postgres") {
|
|
465
466
|
let e = i?.hnsw?.m ?? 16, t = i?.hnsw?.efConstruction ?? 64, n = i?.hnsw?.opclass ?? y(i?.hnsw?.distance);
|
|
@@ -470,7 +471,7 @@ var O = "framework_changes", Ke = "framework_changes_", qe = (e, t) => t === "fr
|
|
|
470
471
|
skip: !1
|
|
471
472
|
};
|
|
472
473
|
}
|
|
473
|
-
return
|
|
474
|
+
return A(`[voltro:migrate] hnsw index '${e}' on '${n}': ${t} has no pgvector / HNSW access method — skipping. Nearest-neighbour queries on this column fall back to a sequential scan.`), {
|
|
474
475
|
using: "",
|
|
475
476
|
withSuffix: "",
|
|
476
477
|
skip: !0
|
|
@@ -503,15 +504,15 @@ var O = "framework_changes", Ke = "framework_changes_", qe = (e, t) => t === "fr
|
|
|
503
504
|
let a = n.columns.map((e) => i(e, t)).join(", ");
|
|
504
505
|
r.push(`CREATE FULLTEXT INDEX ${i(n.name, t)} ON ${i(e.tableName, t)} (${a});`);
|
|
505
506
|
} 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.`);
|
|
506
|
-
else t === "sqlite" ? r.push(...ot(e.tableName, n, t)) :
|
|
507
|
+
else t === "sqlite" ? r.push(...ot(e.tableName, n, t)) : A(`[voltro:migrate] full-text index '${n.name}' on '${e.tableName}': ${t} uses a ranked LIKE search at query time (no native FTS catalog required).`);
|
|
507
508
|
for (let n of e.appliedIndexes) {
|
|
508
509
|
if ((t === "mariadb" || t === "mssql") && n.fields.some((e) => typeof e != "string" && "jsonPath" in e)) {
|
|
509
|
-
|
|
510
|
+
A(`[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(...).`);
|
|
510
511
|
continue;
|
|
511
512
|
}
|
|
512
513
|
if (n.unique && n.where !== void 0 && n.where.length > 0 && (t === "mysql" || t === "mariadb")) throw Error(`@voltro/migrate: uniqueActive index '${n.name}' on '${e.tableName}' cannot be expressed on ${t} — it has no partial (WHERE) index support, and a full UNIQUE index would forbid re-creating a soft-deleted row. Use a generated STORED column (text().generatedAs("CASE WHEN \`deletedAt\` IS NULL THEN <key> ELSE NULL END", { stored: true })) + .unique([...]) on ${t}, or move this table to postgres/sqlite/mssql.`);
|
|
513
514
|
let i = "";
|
|
514
|
-
n.where !== void 0 && n.where.length > 0 && (t === "mysql" || t === "mariadb" ?
|
|
515
|
+
n.where !== void 0 && n.where.length > 0 && (t === "mysql" || t === "mariadb" ? A(`[voltro:migrate] partial index '${n.name}' on '${e.tableName}': ${t} does not support WHERE clauses on indexes — emitting a full index`) : i = ` WHERE ${n.where}`);
|
|
515
516
|
let s = l(n.name, e.tableName, n.fields, n.kind, n.kindOptions, i, n.unique === !0);
|
|
516
517
|
s !== "" && r.push(s), n.fields.every((e) => typeof e == "string") && a.add(o(n.fields));
|
|
517
518
|
}
|
|
@@ -521,7 +522,7 @@ var O = "framework_changes", Ke = "framework_changes_", qe = (e, t) => t === "fr
|
|
|
521
522
|
r.push(l(i, e.tableName, [t])), a.add(o([t]));
|
|
522
523
|
}
|
|
523
524
|
return r.join("\n");
|
|
524
|
-
}, ct = (e, t, n =
|
|
525
|
+
}, ct = (e, t, n = k) => {
|
|
525
526
|
if (t !== "postgres") return [];
|
|
526
527
|
let r = e.filter((e) => e.isReactive !== !1);
|
|
527
528
|
return r.length === 0 ? [] : [lt(n), ...r.map((e) => dt(e, n))];
|
|
@@ -600,7 +601,7 @@ $$ LANGUAGE plpgsql;
|
|
|
600
601
|
for (let n of e.stale) r.push(`DROP TRIGGER IF EXISTS ${qe(n, t)} ON "${n}"`), r.push(`ALTER TABLE "${n}" REPLICA IDENTITY DEFAULT`);
|
|
601
602
|
return r;
|
|
602
603
|
}, pt = (e) => e.some((e) => Object.values(e.fields).some((e) => e.type === "vector")), mt = (e) => e.some((e) => Object.values(e.fields).some((e) => e.spatial !== void 0)), ht = (e) => {
|
|
603
|
-
let t = new Map(e.map((e) => [e.tableName, e])), n =
|
|
604
|
+
let t = new Map(e.map((e) => [e.tableName, e])), n = de(e.map((e) => e.tableName), (e) => {
|
|
604
605
|
let n = t.get(e);
|
|
605
606
|
return n ? Object.entries(n.fields).flatMap(([e, n]) => {
|
|
606
607
|
if (n.type !== "reference" || !n.references) return [];
|
|
@@ -696,8 +697,8 @@ BEGIN
|
|
|
696
697
|
tables: t,
|
|
697
698
|
views: n
|
|
698
699
|
};
|
|
699
|
-
}, xt = (e, t, n =
|
|
700
|
-
let { tables: i, views: o } = bt(e), { sorted: s, cyclic: c } = ht(i.map((e) =>
|
|
700
|
+
}, xt = (e, t, n = k) => {
|
|
701
|
+
let { tables: i, views: o } = bt(e), { sorted: s, cyclic: c } = ht(i.map((e) => ue(e, t))), l = _t(c, t), u = [];
|
|
701
702
|
t === "postgres" && pt(s) && u.push("CREATE EXTENSION IF NOT EXISTS vector;"), t === "postgres" && mt(s) && u.push("CREATE EXTENSION IF NOT EXISTS postgis;");
|
|
702
703
|
let d = yt(s, t);
|
|
703
704
|
d && u.push(d);
|
|
@@ -734,7 +735,7 @@ BEGIN
|
|
|
734
735
|
r && d.push(r);
|
|
735
736
|
}
|
|
736
737
|
return d.join("\n\n") + "\n";
|
|
737
|
-
}, wt = (e, t, n =
|
|
738
|
+
}, wt = (e, t, n = k) => {
|
|
738
739
|
let { sorted: r, cyclic: i } = ht(e), a = _t(i, t), o = [], s = yt(r, t);
|
|
739
740
|
s && o.push(s);
|
|
740
741
|
let c = vt(r, t);
|
|
@@ -742,7 +743,7 @@ BEGIN
|
|
|
742
743
|
for (let e of r) o.push(at(e, t, null, a.get(e.tableName)));
|
|
743
744
|
for (let e of i) o.push(gt(e, t));
|
|
744
745
|
return o.push(...ct(r, t, n)), o.join("\n\n") + "\n";
|
|
745
|
-
}, Tt = (e, t = "postgres", n =
|
|
746
|
+
}, Tt = (e, t = "postgres", n = k, r = {}) => b.gen(function* () {
|
|
746
747
|
let i = yield* C.SqlClient;
|
|
747
748
|
yield* je(i, Mt(i, xt(e, t, n), t, r.retryFilter), { schema: r.lockSchema }).pipe(b.orDie);
|
|
748
749
|
}), Et = (e, t) => {
|
|
@@ -825,10 +826,10 @@ BEGIN
|
|
|
825
826
|
name: e.name,
|
|
826
827
|
columns: Bt(e.columns),
|
|
827
828
|
indexes: Vt(e.indexes)
|
|
828
|
-
})).sort((e, t) => e.name.localeCompare(t.name)),
|
|
829
|
+
})).sort((e, t) => e.name.localeCompare(t.name)), P = (e) => {
|
|
829
830
|
let t = { tables: Ht(e.tables) }, n = JSON.stringify(Rt(t));
|
|
830
831
|
return ee("sha256").update(n).digest("hex");
|
|
831
|
-
},
|
|
832
|
+
}, F = (e) => e.slice(0, 16), Ut = (e, t) => {
|
|
832
833
|
let n = t.references ? {
|
|
833
834
|
table: t.references().tableName,
|
|
834
835
|
column: "id",
|
|
@@ -940,10 +941,10 @@ BEGIN
|
|
|
940
941
|
if (r !== void 0 && r !== n.name) throw Error(`duplicate index name '${e.name}' across tables '${r}' and '${n.name}'. Index names must be unique per SCHEMA, not just per table — the DB creates only one, so the other never applies and 'db plan' re-emits it forever. Give each an explicit, table-prefixed name (e.g. '${n.name}_${e.name}').`);
|
|
941
942
|
t.set(e.name, n.name);
|
|
942
943
|
}
|
|
943
|
-
},
|
|
944
|
-
let n = e.map((e) => Gt(
|
|
944
|
+
}, I = (e, t) => {
|
|
945
|
+
let n = e.map((e) => Gt(ue(e, t)));
|
|
945
946
|
return Kt(n), { tables: n };
|
|
946
|
-
}, qt = (e, t, n =
|
|
947
|
+
}, qt = (e, t, n = k) => b.gen(function* () {
|
|
947
948
|
let r = (yield* e`
|
|
948
949
|
SELECT p.prosrc
|
|
949
950
|
FROM pg_proc p
|
|
@@ -1017,29 +1018,29 @@ BEGIN
|
|
|
1017
1018
|
snapshot: n.get(e.tableName),
|
|
1018
1019
|
columnDefs: e.fields
|
|
1019
1020
|
}]));
|
|
1020
|
-
},
|
|
1021
|
+
}, L = (e) => {
|
|
1021
1022
|
if (typeof e != "object" || !e) return JSON.stringify(e);
|
|
1022
|
-
if (Array.isArray(e)) return `[${e.map(
|
|
1023
|
+
if (Array.isArray(e)) return `[${e.map(L).join(",")}]`;
|
|
1023
1024
|
let t = e;
|
|
1024
|
-
return `{${Object.keys(t).sort().map((e) => `${JSON.stringify(e)}:${
|
|
1025
|
+
return `{${Object.keys(t).sort().map((e) => `${JSON.stringify(e)}:${L(t[e])}`).join(",")}}`;
|
|
1025
1026
|
}, $t = (e) => {
|
|
1026
1027
|
if (!e.hasDefault || e.defaultValue === void 0 || e.defaultValue === null) return null;
|
|
1027
1028
|
let t = e.defaultValue;
|
|
1028
1029
|
if (typeof t == "boolean") return t ? "__BOOL_TRUE__" : "__BOOL_FALSE__";
|
|
1029
1030
|
if (typeof t == "number") return String(t);
|
|
1030
|
-
if (typeof t != "string") return
|
|
1031
|
+
if (typeof t != "string") return L(t);
|
|
1031
1032
|
let n = t.trim(), r = n.toLowerCase().replace(/\s+/g, "");
|
|
1032
1033
|
if (r === "now" || r === "now()" || /^current_timestamp(\(\d*\))?$/.test(r) || r === "sysutcdatetime()" || r === "sysdatetime()" || r === "getutcdate()" || r === "getdate()") return "__NOW__";
|
|
1033
1034
|
let i = n.replace(/::[a-zA-Z0-9_ "]+$/, "").trim(), a = /^'(.*)'$/.test(i) ? i.slice(1, -1).replace(/''/g, "'") : i, o = /^cast\(\s*(?:_\w+\s*)?\\?'(.*?)\\?'\s+as\s+json\s*\)$/i.exec(a);
|
|
1034
1035
|
if (o) try {
|
|
1035
|
-
return
|
|
1036
|
+
return L(JSON.parse(o[1]));
|
|
1036
1037
|
} catch {}
|
|
1037
1038
|
let s = /^convert\(\s*(?:_\w+\s*)?\\?'(.*?)\\?'\s+using\s+[\w]+\s*\)$/i.exec(a);
|
|
1038
1039
|
if (s) try {
|
|
1039
|
-
return
|
|
1040
|
+
return L(JSON.parse(s[1]));
|
|
1040
1041
|
} catch {}
|
|
1041
1042
|
if (a.startsWith("{") || a.startsWith("[")) try {
|
|
1042
|
-
return
|
|
1043
|
+
return L(JSON.parse(a));
|
|
1043
1044
|
} catch {}
|
|
1044
1045
|
return /^-?\d+(\.\d+)?$/.test(a) ? String(Number(a)) : a;
|
|
1045
1046
|
}, en = (e, t) => {
|
|
@@ -1064,12 +1065,12 @@ BEGIN
|
|
|
1064
1065
|
return i.every((e, t) => e === a[t]);
|
|
1065
1066
|
}, rn = (e, t) => {
|
|
1066
1067
|
try {
|
|
1067
|
-
let n = /\((\d+)\)/.exec(
|
|
1068
|
+
let n = /\((\d+)\)/.exec(j(e, t));
|
|
1068
1069
|
return n ? Number(n[1]) : void 0;
|
|
1069
1070
|
} catch {
|
|
1070
1071
|
return;
|
|
1071
1072
|
}
|
|
1072
|
-
}, an = (e, t, n) => n === void 0 || r(n) ? !0 : e.type !== "text" || t.type !== "text" || rn(e, n) === t.maxLength, on = (e, t, n) => e.type === t.type && e.nullable === t.nullable && e.unique === t.unique && en(e, t) && an(e, t, n) && JSON.stringify(tn(e.references)) === JSON.stringify(tn(t.references)) && nn(e.oneOf, t.oneOf), sn = (e, t) => t.oneOf && t.oneOf.length > 0 ?
|
|
1073
|
+
}, an = (e, t, n) => n === void 0 || r(n) ? !0 : e.type !== "text" || t.type !== "text" || rn(e, n) === t.maxLength, on = (e, t, n) => e.type === t.type && e.nullable === t.nullable && e.unique === t.unique && en(e, t) && an(e, t, n) && JSON.stringify(tn(e.references)) === JSON.stringify(tn(t.references)) && nn(e.oneOf, t.oneOf), sn = (e, t) => t.oneOf && t.oneOf.length > 0 ? R({
|
|
1073
1074
|
kind: "add-check",
|
|
1074
1075
|
table: e,
|
|
1075
1076
|
column: t.name,
|
|
@@ -1104,7 +1105,7 @@ BEGIN
|
|
|
1104
1105
|
added: i,
|
|
1105
1106
|
removed: a
|
|
1106
1107
|
};
|
|
1107
|
-
},
|
|
1108
|
+
}, R = (e, t, n, r) => ({
|
|
1108
1109
|
op: e,
|
|
1109
1110
|
classification: t,
|
|
1110
1111
|
atomicByDialect: Zt(e.kind),
|
|
@@ -1116,21 +1117,21 @@ BEGIN
|
|
|
1116
1117
|
table: e,
|
|
1117
1118
|
column: t
|
|
1118
1119
|
};
|
|
1119
|
-
return t.nullable ?
|
|
1120
|
+
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` });
|
|
1120
1121
|
}, fn = (e, t, n) => {
|
|
1121
1122
|
let r = {
|
|
1122
1123
|
kind: "drop-column",
|
|
1123
1124
|
table: e,
|
|
1124
1125
|
column: t.name
|
|
1125
1126
|
};
|
|
1126
|
-
return n?.dropped ?
|
|
1127
|
-
}, pn = (e, t, n, r, i) =>
|
|
1127
|
+
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` });
|
|
1128
|
+
}, pn = (e, t, n, r, i) => R({
|
|
1128
1129
|
kind: "create-table",
|
|
1129
1130
|
table: e,
|
|
1130
1131
|
columns: t,
|
|
1131
1132
|
indexes: n,
|
|
1132
1133
|
...r && r.length > 0 ? { primaryKey: r } : {}
|
|
1133
|
-
}, "safe", i ?? "new table — no data to preserve"), mn = (e) =>
|
|
1134
|
+
}, "safe", i ?? "new table — no data to preserve"), mn = (e) => R({
|
|
1134
1135
|
kind: "drop-table",
|
|
1135
1136
|
table: e
|
|
1136
1137
|
}, "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" }), hn = 5e4, gn = (e, t, n, r) => {
|
|
@@ -1148,12 +1149,12 @@ BEGIN
|
|
|
1148
1149
|
kind: "add-index",
|
|
1149
1150
|
table: e,
|
|
1150
1151
|
index: t
|
|
1151
|
-
}, i ?
|
|
1152
|
-
}, _n = (e, t) => t.unique && t.columns.length > 1 ?
|
|
1152
|
+
}, 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");
|
|
1153
|
+
}, _n = (e, t) => t.unique && t.columns.length > 1 ? R({
|
|
1153
1154
|
kind: "drop-unique-composite",
|
|
1154
1155
|
table: e,
|
|
1155
1156
|
name: t.name
|
|
1156
|
-
}, "safe", "drop composite UNIQUE constraint (no data loss — constraint is derived metadata)") :
|
|
1157
|
+
}, "safe", "drop composite UNIQUE constraint (no data loss — constraint is derived metadata)") : R({
|
|
1157
1158
|
kind: "drop-index",
|
|
1158
1159
|
table: e,
|
|
1159
1160
|
index: t.name
|
|
@@ -1174,20 +1175,22 @@ BEGIN
|
|
|
1174
1175
|
column: t.name,
|
|
1175
1176
|
toNullable: t.nullable
|
|
1176
1177
|
};
|
|
1177
|
-
s.push(t.nullable ?
|
|
1178
|
+
s.push(t.nullable ? R(n, "safe", `loosen ${e}.${t.name} to nullable`) : R(n, "needs-backfill", `tighten ${e}.${t.name} to NOT NULL — existing rows must already be non-null`));
|
|
1178
1179
|
}
|
|
1179
|
-
if (t.unique !== n.unique)
|
|
1180
|
-
|
|
1181
|
-
|
|
1180
|
+
if (t.unique !== n.unique) {
|
|
1181
|
+
if (t.unique) {
|
|
1182
|
+
let n = {
|
|
1183
|
+
kind: "add-unique",
|
|
1184
|
+
table: e,
|
|
1185
|
+
column: t.name
|
|
1186
|
+
}, r = (a ?? 0) >= o;
|
|
1187
|
+
s.push(r ? R(n, "online-required", `online unique build on ${a} rows — CONCURRENTLY / INPLACE / WITH(ONLINE=ON) depending on dialect`) : R(n, "safe", `add unique constraint on ${e}.${t.name} — existing rows must already be distinct (else the DB rejects at migrate)`));
|
|
1188
|
+
} else s.push(R({
|
|
1189
|
+
kind: "drop-unique",
|
|
1182
1190
|
table: e,
|
|
1183
1191
|
column: t.name
|
|
1184
|
-
},
|
|
1185
|
-
|
|
1186
|
-
} else s.push(L({
|
|
1187
|
-
kind: "drop-unique",
|
|
1188
|
-
table: e,
|
|
1189
|
-
column: t.name
|
|
1190
|
-
}, "safe", `drop unique constraint on ${e}.${t.name} — constraint is derived metadata, no data loss`));
|
|
1192
|
+
}, "safe", `drop unique constraint on ${e}.${t.name} — constraint is derived metadata, no data loss`));
|
|
1193
|
+
}
|
|
1191
1194
|
if (vn(t.type, i) !== vn(n.type, i)) {
|
|
1192
1195
|
let r = t.narrowedFrom;
|
|
1193
1196
|
if (r && r.from === n.type) {
|
|
@@ -1199,7 +1202,7 @@ BEGIN
|
|
|
1199
1202
|
to: t.type,
|
|
1200
1203
|
...r.using === void 0 ? {} : { using: r.using }
|
|
1201
1204
|
};
|
|
1202
|
-
s.push(
|
|
1205
|
+
s.push(R(i, "needs-backfill", `type change ${n.type} → ${t.type} on ${e}.${t.name} — narrowedFrom('${r.from}') declared` + (r.using ? ` with USING ${r.using}` : " (implicit cast)")));
|
|
1203
1206
|
} else {
|
|
1204
1207
|
let r = {
|
|
1205
1208
|
kind: "alter-column-type",
|
|
@@ -1208,12 +1211,12 @@ BEGIN
|
|
|
1208
1211
|
from: n.type,
|
|
1209
1212
|
to: t.type
|
|
1210
1213
|
};
|
|
1211
|
-
s.push(
|
|
1214
|
+
s.push(R(r, "lossy", `type change ${n.type} → ${t.type} on ${e}.${t.name} may not be value-preserving`, { fix: `acknowledge it on the column: \`.narrowedFrom('${n.type}', { using: '${t.name}::${t.type}' })\` (drop \`using\` if the cast is implicit), or use a file-based migration` }));
|
|
1212
1215
|
}
|
|
1213
1216
|
}
|
|
1214
1217
|
if (t.type === "text" && n.type === "text" && !r(i ?? "postgres") && t.maxLength !== n.maxLength) {
|
|
1215
1218
|
let r = t.maxLength === void 0 || n.maxLength !== void 0 && t.maxLength > n.maxLength, i = n.maxLength === void 0 ? "unbounded" : `varchar(${n.maxLength})`, a = t.maxLength === void 0 ? "unbounded" : `varchar(${t.maxLength})`;
|
|
1216
|
-
s.push(
|
|
1219
|
+
s.push(R({
|
|
1217
1220
|
kind: "alter-column-type",
|
|
1218
1221
|
table: e,
|
|
1219
1222
|
column: t.name,
|
|
@@ -1229,10 +1232,10 @@ BEGIN
|
|
|
1229
1232
|
hasDefault: t.hasDefault,
|
|
1230
1233
|
...t.defaultValue === void 0 ? {} : { defaultValue: t.defaultValue }
|
|
1231
1234
|
};
|
|
1232
|
-
s.push(
|
|
1235
|
+
s.push(R(n, "safe", `default change on ${e}.${t.name} affects only future inserts`));
|
|
1233
1236
|
}
|
|
1234
1237
|
if (!nn(t.oneOf, n.oneOf)) {
|
|
1235
|
-
n.oneOf && n.oneOf.length > 0 && s.push(
|
|
1238
|
+
n.oneOf && n.oneOf.length > 0 && s.push(R({
|
|
1236
1239
|
kind: "drop-check",
|
|
1237
1240
|
table: e,
|
|
1238
1241
|
column: t.name
|
|
@@ -1240,7 +1243,7 @@ BEGIN
|
|
|
1240
1243
|
let r = sn(e, t);
|
|
1241
1244
|
r && s.push(r);
|
|
1242
1245
|
}
|
|
1243
|
-
return JSON.stringify(tn(t.references)) !== JSON.stringify(tn(n.references)) && (n.references && s.push(
|
|
1246
|
+
return JSON.stringify(tn(t.references)) !== JSON.stringify(tn(n.references)) && (n.references && s.push(R({
|
|
1244
1247
|
kind: "drop-foreign-key",
|
|
1245
1248
|
table: e,
|
|
1246
1249
|
column: t.name
|
|
@@ -1257,15 +1260,15 @@ BEGIN
|
|
|
1257
1260
|
...t.references.onDelete ? { onDelete: t.references.onDelete } : {},
|
|
1258
1261
|
...t.references.onUpdate ? { onUpdate: t.references.onUpdate } : {}
|
|
1259
1262
|
};
|
|
1260
|
-
return i === "null" && !t.nullable ? n.push(
|
|
1263
|
+
return i === "null" && !t.nullable ? n.push(R(a, "lossy", `add FK ${e}.${t.name} → ${r}: orphanPolicy 'null' needs a nullable column (the NULL-out would violate NOT NULL)`, { fix: `make ${t.name} \`.nullable()\`, OR use \`orphanPolicy: 'delete'\`, OR clean the orphans and drop the policy` })) : i === "null" || i === "delete" ? n.push(R({
|
|
1261
1264
|
...a,
|
|
1262
1265
|
orphanPolicy: i
|
|
1263
|
-
}, "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(
|
|
1266
|
+
}, "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;
|
|
1264
1267
|
}, xn = (e, t, n) => {
|
|
1265
1268
|
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));
|
|
1266
1269
|
for (let [n, c] of Object.entries(t)) {
|
|
1267
1270
|
let t = c.renamedFrom;
|
|
1268
|
-
t && o.has(t) && s.has(n) && (i.add(n), a.add(t), r.push(
|
|
1271
|
+
t && o.has(t) && s.has(n) && (i.add(n), a.add(t), r.push(R({
|
|
1269
1272
|
kind: "rename-column",
|
|
1270
1273
|
table: e.tableName,
|
|
1271
1274
|
from: t,
|
|
@@ -1296,7 +1299,7 @@ BEGIN
|
|
|
1296
1299
|
let t = o(n), r = a.filter((e) => !l.has(e.name) && s(e) === t);
|
|
1297
1300
|
if (r.length !== 1) continue;
|
|
1298
1301
|
let i = r[0];
|
|
1299
|
-
i.name !== n.name && (l.add(i.name), u.add(n.name), c.push(
|
|
1302
|
+
i.name !== n.name && (l.add(i.name), u.add(n.name), c.push(R({
|
|
1300
1303
|
kind: "rename-index",
|
|
1301
1304
|
table: e,
|
|
1302
1305
|
from: n.name,
|
|
@@ -1319,7 +1322,7 @@ BEGIN
|
|
|
1319
1322
|
continue;
|
|
1320
1323
|
}
|
|
1321
1324
|
if (t.has(c.name)) {
|
|
1322
|
-
r.push(
|
|
1325
|
+
r.push(R({
|
|
1323
1326
|
kind: "rename-table",
|
|
1324
1327
|
from: e,
|
|
1325
1328
|
to: c.name
|
|
@@ -1327,14 +1330,14 @@ BEGIN
|
|
|
1327
1330
|
continue;
|
|
1328
1331
|
}
|
|
1329
1332
|
if ((s.get(e) ?? 0) !== 1) {
|
|
1330
|
-
r.push(
|
|
1333
|
+
r.push(R({
|
|
1331
1334
|
kind: "rename-table",
|
|
1332
1335
|
from: e,
|
|
1333
1336
|
to: c.name
|
|
1334
1337
|
}, "needs-rename-annotation", `.renamedFrom('${e}') is claimed by ${s.get(e)} tables — nothing says which receives its rows`, { fix: `remove the \`.renamedFrom('${e}')\` marker from all but one of them.` }));
|
|
1335
1338
|
continue;
|
|
1336
1339
|
}
|
|
1337
|
-
i.set(c.name, e), a.add(e), r.push(
|
|
1340
|
+
i.set(c.name, e), a.add(e), r.push(R({
|
|
1338
1341
|
kind: "rename-table",
|
|
1339
1342
|
from: e,
|
|
1340
1343
|
to: c.name
|
|
@@ -1360,7 +1363,7 @@ BEGIN
|
|
|
1360
1363
|
...e,
|
|
1361
1364
|
name: r,
|
|
1362
1365
|
table: n
|
|
1363
|
-
} : i ? (a.push(
|
|
1366
|
+
} : i ? (a.push(R({
|
|
1364
1367
|
kind: "rename-index",
|
|
1365
1368
|
table: n,
|
|
1366
1369
|
from: e.name,
|
|
@@ -1409,13 +1412,11 @@ BEGIN
|
|
|
1409
1412
|
case "online-required":
|
|
1410
1413
|
t.onlineRequired++;
|
|
1411
1414
|
break;
|
|
1412
|
-
case "multi-step":
|
|
1413
|
-
t.multiStep++;
|
|
1414
|
-
break;
|
|
1415
|
+
case "multi-step": t.multiStep++;
|
|
1415
1416
|
}
|
|
1416
1417
|
return t;
|
|
1417
1418
|
}, kn = (e) => {
|
|
1418
|
-
let t =
|
|
1419
|
+
let t = I(e.declared, e.dialect), n = Qt(e.declared, t), r = new Map(e.live.tables.map((e) => [e.name, e])), i = e.onlineAfter ?? hn, a = [], o = En(t, r, n);
|
|
1419
1420
|
a.push(...o.ops);
|
|
1420
1421
|
for (let e of t.tables) if (!o.renamedInto.has(e.name) && !r.has(e.name)) {
|
|
1421
1422
|
a.push(pn(e.name, e.columns, e.indexes, e.primaryKey, o.refusals.get(e.name)));
|
|
@@ -1457,8 +1458,8 @@ BEGIN
|
|
|
1457
1458
|
column: e.name,
|
|
1458
1459
|
target: e.references.table
|
|
1459
1460
|
}] : []) : [];
|
|
1460
|
-
}, d =
|
|
1461
|
-
for (let e of t.tables) if (c.has(e.name)) for (let t of e.columns) !t.references || !d.has(w(e.name, t.name)) || f.push(
|
|
1461
|
+
}, d = de([...c], u), f = [];
|
|
1462
|
+
for (let e of t.tables) if (c.has(e.name)) for (let t of e.columns) !t.references || !d.has(w(e.name, t.name)) || f.push(R({
|
|
1462
1463
|
kind: "add-foreign-key",
|
|
1463
1464
|
table: e.name,
|
|
1464
1465
|
column: t.name,
|
|
@@ -1530,8 +1531,8 @@ BEGIN
|
|
|
1530
1531
|
});
|
|
1531
1532
|
return {
|
|
1532
1533
|
operations: S,
|
|
1533
|
-
fromFingerprint:
|
|
1534
|
-
toFingerprint:
|
|
1534
|
+
fromFingerprint: P(e.live),
|
|
1535
|
+
toFingerprint: P(t),
|
|
1535
1536
|
summary: On(S)
|
|
1536
1537
|
};
|
|
1537
1538
|
}, An = (e) => {
|
|
@@ -1569,7 +1570,7 @@ BEGIN
|
|
|
1569
1570
|
case "USER-DEFINED": return "text";
|
|
1570
1571
|
default: return "text";
|
|
1571
1572
|
}
|
|
1572
|
-
},
|
|
1573
|
+
}, z = (e) => {
|
|
1573
1574
|
switch (e.toUpperCase()) {
|
|
1574
1575
|
case "CASCADE": return "cascade";
|
|
1575
1576
|
case "RESTRICT": return "restrict";
|
|
@@ -1738,17 +1739,17 @@ BEGIN
|
|
|
1738
1739
|
}
|
|
1739
1740
|
let te = [];
|
|
1740
1741
|
for (let e of c) {
|
|
1741
|
-
let t = /* @__PURE__ */ new Set(), n = (_.get(e.table_name) ?? []).filter((e) => t.has(e.column_name)
|
|
1742
|
+
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 = S.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) => {
|
|
1742
1743
|
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" : jn(t.data_type, t.udt_name), c = a ? {
|
|
1743
1744
|
table: a.target_table,
|
|
1744
1745
|
column: a.target_column,
|
|
1745
|
-
onDelete:
|
|
1746
|
-
onUpdate:
|
|
1746
|
+
onDelete: z(a.delete_rule),
|
|
1747
|
+
onUpdate: z(a.update_rule)
|
|
1747
1748
|
} : void 0, l = m.get(`${e.table_name}.${t.column_name}`);
|
|
1748
1749
|
return {
|
|
1749
1750
|
name: t.column_name,
|
|
1750
1751
|
type: s,
|
|
1751
|
-
...
|
|
1752
|
+
...H(t.data_type, t.character_maximum_length) === void 0 ? {} : { maxLength: H(t.data_type, t.character_maximum_length) },
|
|
1752
1753
|
nullable: t.is_nullable === "YES",
|
|
1753
1754
|
unique: i.has(t.column_name) || n && t.column_name === "id",
|
|
1754
1755
|
hasDefault: t.column_default !== null,
|
|
@@ -1760,7 +1761,7 @@ BEGIN
|
|
|
1760
1761
|
if (u) for (let [t, n] of u) {
|
|
1761
1762
|
let r = /* @__PURE__ */ new Set(), i = [...n].filter((e) => e.column_name !== null && e.position !== null).sort((e, t) => (e.position ?? 0) - (t.position ?? 0)).filter((e) => {
|
|
1762
1763
|
let t = e.position;
|
|
1763
|
-
return r.has(t)
|
|
1764
|
+
return !r.has(t) && (r.add(t), !0);
|
|
1764
1765
|
});
|
|
1765
1766
|
if (i.some((e) => s.has(e.column_name))) continue;
|
|
1766
1767
|
let a = n.some((e) => e.has_expression);
|
|
@@ -1825,21 +1826,21 @@ BEGIN
|
|
|
1825
1826
|
case "json": return "json";
|
|
1826
1827
|
default: return "text";
|
|
1827
1828
|
}
|
|
1828
|
-
},
|
|
1829
|
+
}, B = (e) => e.map((e) => {
|
|
1829
1830
|
let t = e, n = {};
|
|
1830
1831
|
for (let e of Object.keys(t)) n[e.toLowerCase()] = t[e];
|
|
1831
1832
|
return n;
|
|
1832
1833
|
}), zn = (e) => b.gen(function* () {
|
|
1833
|
-
let t =
|
|
1834
|
+
let t = B(yield* e`
|
|
1834
1835
|
SELECT table_name, COALESCE(table_rows, 0) AS table_rows
|
|
1835
1836
|
FROM information_schema.tables
|
|
1836
1837
|
WHERE table_schema = DATABASE() AND table_type = 'BASE TABLE'
|
|
1837
|
-
ORDER BY table_name`), n =
|
|
1838
|
+
ORDER BY table_name`), n = B(yield* e`
|
|
1838
1839
|
SELECT table_name, column_name, data_type, column_type, is_nullable, column_default, column_key,
|
|
1839
1840
|
character_maximum_length
|
|
1840
1841
|
FROM information_schema.columns
|
|
1841
1842
|
WHERE table_schema = DATABASE()
|
|
1842
|
-
ORDER BY table_name, ordinal_position`), r =
|
|
1843
|
+
ORDER BY table_name, ordinal_position`), r = B(yield* e`
|
|
1843
1844
|
SELECT k.table_name AS source_table,
|
|
1844
1845
|
k.column_name AS source_column,
|
|
1845
1846
|
k.referenced_table_name AS target_table,
|
|
@@ -1849,11 +1850,11 @@ BEGIN
|
|
|
1849
1850
|
JOIN information_schema.referential_constraints r
|
|
1850
1851
|
ON k.constraint_name = r.constraint_name
|
|
1851
1852
|
AND k.table_schema = r.constraint_schema
|
|
1852
|
-
WHERE k.table_schema = DATABASE() AND k.referenced_table_name IS NOT NULL`), i =
|
|
1853
|
+
WHERE k.table_schema = DATABASE() AND k.referenced_table_name IS NOT NULL`), i = B(yield* e`
|
|
1853
1854
|
SELECT table_name, index_name, non_unique, column_name, seq_in_index
|
|
1854
1855
|
FROM information_schema.statistics
|
|
1855
1856
|
WHERE table_schema = DATABASE() AND index_name <> 'PRIMARY'
|
|
1856
|
-
ORDER BY table_name, index_name, seq_in_index`), a =
|
|
1857
|
+
ORDER BY table_name, index_name, seq_in_index`), a = B(yield* e`
|
|
1857
1858
|
SELECT table_name, check_clause
|
|
1858
1859
|
FROM information_schema.check_constraints
|
|
1859
1860
|
WHERE constraint_schema = DATABASE()`.unprepared.pipe(b.orElseSucceed(() => []))), o = /* @__PURE__ */ new Set(), s = /* @__PURE__ */ new Map();
|
|
@@ -1889,14 +1890,14 @@ BEGIN
|
|
|
1889
1890
|
let n = i.includes(t.column_name) && i.length === 1, c = r.get(t.column_name), l = c ? "reference" : n && t.column_name === "id" ? "id" : o.has(`${e.table_name}.${t.column_name}`) ? "json" : Rn(t.data_type, t.column_type), u = c ? {
|
|
1890
1891
|
table: c.target_table,
|
|
1891
1892
|
column: c.target_column,
|
|
1892
|
-
onDelete:
|
|
1893
|
-
onUpdate:
|
|
1893
|
+
onDelete: z(c.delete_rule),
|
|
1894
|
+
onUpdate: z(c.update_rule)
|
|
1894
1895
|
} : void 0, d = a.has(t.column_name) || n && t.column_name === "id", f = t.column_default === "NULL" ? null : t.column_default, p = s.get(`${e.table_name}.${t.column_name}`);
|
|
1895
1896
|
return {
|
|
1896
1897
|
name: t.column_name,
|
|
1897
1898
|
type: l,
|
|
1898
1899
|
nullable: t.is_nullable === "YES",
|
|
1899
|
-
...
|
|
1900
|
+
...H(t.data_type, t.character_maximum_length) === void 0 ? {} : { maxLength: H(t.data_type, t.character_maximum_length) },
|
|
1900
1901
|
unique: d,
|
|
1901
1902
|
hasDefault: f !== null,
|
|
1902
1903
|
...f === null ? {} : { defaultValue: f },
|
|
@@ -1906,12 +1907,12 @@ BEGIN
|
|
|
1906
1907
|
}), m = new Set(n.map((e) => e.source_column)), h = [];
|
|
1907
1908
|
if (f) for (let [t, n] of f) {
|
|
1908
1909
|
let r = [...n].sort((e, t) => e.seq_in_index - t.seq_in_index);
|
|
1909
|
-
r.length
|
|
1910
|
+
(r.length !== 1 || r[0].non_unique !== 0) && (r.length === 1 && r[0].non_unique !== 0 && m.has(r[0].column_name) && t !== `${e.table_name}_${r[0].column_name}_idx` || h.push({
|
|
1910
1911
|
name: t,
|
|
1911
1912
|
table: e.table_name,
|
|
1912
1913
|
columns: r.map((e) => e.column_name),
|
|
1913
1914
|
unique: r[0].non_unique === 0
|
|
1914
|
-
});
|
|
1915
|
+
}));
|
|
1915
1916
|
}
|
|
1916
1917
|
i.length > 0 && h.push({
|
|
1917
1918
|
name: `${e.table_name}_pkey`,
|
|
@@ -1951,8 +1952,8 @@ BEGIN
|
|
|
1951
1952
|
let n = u.length === 1 && u[0] === e.name, r = l.get(e.name), i = r ? "reference" : n && e.name === "id" ? "id" : Bn(e.type), a = r ? {
|
|
1952
1953
|
table: r.table,
|
|
1953
1954
|
column: r.to,
|
|
1954
|
-
onDelete:
|
|
1955
|
-
onUpdate:
|
|
1955
|
+
onDelete: z(r.on_delete),
|
|
1956
|
+
onUpdate: z(r.on_update)
|
|
1956
1957
|
} : void 0, o = t.get(e.name);
|
|
1957
1958
|
return {
|
|
1958
1959
|
name: e.name,
|
|
@@ -1968,12 +1969,12 @@ BEGIN
|
|
|
1968
1969
|
for (let e of c) {
|
|
1969
1970
|
if (e.origin === "pk") continue;
|
|
1970
1971
|
let t = d.get(e.name) ?? [];
|
|
1971
|
-
t.length
|
|
1972
|
+
(t.length !== 1 || e.unique !== 1) && (t.length === 1 && e.unique !== 1 && m.has(t[0]) && e.name !== `${i}_${t[0]}_idx` || h.push({
|
|
1972
1973
|
name: e.name,
|
|
1973
1974
|
table: i,
|
|
1974
1975
|
columns: t,
|
|
1975
1976
|
unique: e.unique === 1
|
|
1976
|
-
});
|
|
1977
|
+
}));
|
|
1977
1978
|
}
|
|
1978
1979
|
u.length > 0 && h.push({
|
|
1979
1980
|
name: `${i}_pkey`,
|
|
@@ -2009,7 +2010,7 @@ BEGIN
|
|
|
2009
2010
|
case "image": return "bytes";
|
|
2010
2011
|
default: return "text";
|
|
2011
2012
|
}
|
|
2012
|
-
},
|
|
2013
|
+
}, V = (e) => e === !0 || e === 1, Un = (e) => b.gen(function* () {
|
|
2013
2014
|
let t = yield* e`
|
|
2014
2015
|
SELECT TABLE_NAME AS table_name FROM INFORMATION_SCHEMA.TABLES
|
|
2015
2016
|
WHERE TABLE_TYPE = 'BASE TABLE' ORDER BY TABLE_NAME`, n = yield* e`
|
|
@@ -2066,8 +2067,8 @@ BEGIN
|
|
|
2066
2067
|
let t = s.get(e) ?? [], n = c.get(e) ?? [], r = new Map(n.map((e) => [e.source_column, e])), i = new Set(n.map((e) => e.source_column)), a = l.get(e), d = [], f = /* @__PURE__ */ new Set();
|
|
2067
2068
|
if (a) for (let [, e] of a) {
|
|
2068
2069
|
let t = [...e].sort((e, t) => e.key_ordinal - t.key_ordinal);
|
|
2069
|
-
if (
|
|
2070
|
-
else
|
|
2070
|
+
if (V(t[0].is_primary)) for (let e of t) d.push(e.column_name);
|
|
2071
|
+
else V(t[0].is_unique) && t.length === 1 && f.add(t[0].column_name);
|
|
2071
2072
|
}
|
|
2072
2073
|
let p = t.map((t) => {
|
|
2073
2074
|
let n = d.length === 1 && d[0] === t.column_name, i = r.get(t.column_name), a = i ? "reference" : n && t.column_name === "id" ? "id" : Hn(t.data_type), s = i ? {
|
|
@@ -2080,7 +2081,7 @@ BEGIN
|
|
|
2080
2081
|
name: t.column_name,
|
|
2081
2082
|
type: a,
|
|
2082
2083
|
nullable: t.is_nullable === "YES",
|
|
2083
|
-
...
|
|
2084
|
+
...H(t.data_type, t.character_maximum_length) === void 0 ? {} : { maxLength: H(t.data_type, t.character_maximum_length) },
|
|
2084
2085
|
unique: f.has(t.column_name) || n && t.column_name === "id",
|
|
2085
2086
|
hasDefault: c !== null,
|
|
2086
2087
|
...c === null ? {} : { defaultValue: c },
|
|
@@ -2090,11 +2091,11 @@ BEGIN
|
|
|
2090
2091
|
}), m = [];
|
|
2091
2092
|
if (a) for (let [t, n] of a) {
|
|
2092
2093
|
let r = [...n].sort((e, t) => e.key_ordinal - t.key_ordinal);
|
|
2093
|
-
|
|
2094
|
+
V(r[0].is_primary) || r.length === 1 && V(r[0].is_unique) || r.length === 1 && !V(r[0].is_unique) && i.has(r[0].column_name) && t !== `${e}_${r[0].column_name}_idx` || m.push({
|
|
2094
2095
|
name: t,
|
|
2095
2096
|
table: e,
|
|
2096
2097
|
columns: r.map((e) => e.column_name),
|
|
2097
|
-
unique:
|
|
2098
|
+
unique: V(r[0].is_unique)
|
|
2098
2099
|
});
|
|
2099
2100
|
}
|
|
2100
2101
|
d.length > 0 && m.push({
|
|
@@ -2127,11 +2128,11 @@ BEGIN
|
|
|
2127
2128
|
"char",
|
|
2128
2129
|
"character",
|
|
2129
2130
|
"nchar"
|
|
2130
|
-
]),
|
|
2131
|
+
]), H = (e, t) => {
|
|
2131
2132
|
if (!Kn.has(e.toLowerCase())) return;
|
|
2132
2133
|
let n = Number(t);
|
|
2133
2134
|
if (!(!Number.isFinite(n) || n <= 0)) return n;
|
|
2134
|
-
}, qn = /* @__PURE__ */ new Set([
|
|
2135
|
+
}, qn = /* @__PURE__ */ new Set([O]), Jn = (e) => e.onDialectOrElse({
|
|
2135
2136
|
mysql: () => zn(e),
|
|
2136
2137
|
mssql: () => Un(e),
|
|
2137
2138
|
sqlite: () => Vn(e),
|
|
@@ -2139,14 +2140,14 @@ BEGIN
|
|
|
2139
2140
|
}).pipe(b.map((e) => ({
|
|
2140
2141
|
...e,
|
|
2141
2142
|
tables: e.tables.filter((e) => !qn.has(e.name))
|
|
2142
|
-
}))),
|
|
2143
|
+
}))), U = (e, t) => e.onDialectOrElse({
|
|
2143
2144
|
mysql: () => b.succeed(t.replace("T", " ").replace("Z", "")),
|
|
2144
2145
|
orElse: () => b.succeed(t)
|
|
2145
2146
|
}), Yn = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, Xn = (e, t) => {
|
|
2146
|
-
if (
|
|
2147
|
+
if ((e.type !== "text" || e.maxLength === void 0) && !e.spatial && e.type !== "vector" && e.type !== "array" && e.type !== "enum") return;
|
|
2147
2148
|
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;
|
|
2148
2149
|
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.`);
|
|
2149
|
-
return
|
|
2150
|
+
return j(e, t);
|
|
2150
2151
|
}, Zn = (e) => {
|
|
2151
2152
|
let t = Xn(e, "postgres");
|
|
2152
2153
|
return t === void 0 ? Qn(e) : t;
|
|
@@ -2192,57 +2193,57 @@ BEGIN
|
|
|
2192
2193
|
case "interval": return "BIGINT";
|
|
2193
2194
|
case "raw": return e.rawDdl ?? "LONGTEXT";
|
|
2194
2195
|
}
|
|
2195
|
-
},
|
|
2196
|
+
}, W = (e) => `"${e}"`, G = (e) => `\`${e.replace(/`/g, "``")}\``, er = (e, t) => `ALTER TABLE ${t(e.table)} DROP COLUMN IF EXISTS ${t(e.column)};`, tr = (e) => `ALTER TABLE ${G(e.table)} DROP COLUMN IF EXISTS ${G(e.column)}, ALGORITHM=COPY;`, nr = (e, t) => `ALTER TABLE ${t(e.table)} RENAME COLUMN ${t(e.from)} TO ${t(e.to)};`, rr = (e, t, n) => `ALTER TABLE ${n(e.table)} RENAME COLUMN ${n(e.column)} TO ${n(`${e.column}${kr(t)}`)};`, ir = (e, t, n) => e.hasDefault && e.defaultValue !== void 0 ? `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} SET ${ar(e, n)};` : `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} DROP DEFAULT;`, ar = (e, t) => {
|
|
2196
2197
|
let n = t(e.defaultValue);
|
|
2197
2198
|
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.`);
|
|
2198
2199
|
return n;
|
|
2199
|
-
},
|
|
2200
|
-
let r =
|
|
2200
|
+
}, K = (e, t, n) => e.find((e) => e.tableName === t)?.fields[n], or = (e, t, n) => {
|
|
2201
|
+
let r = K(e, t, n);
|
|
2201
2202
|
return r ? Ut(n, r) : void 0;
|
|
2202
2203
|
}, sr = (e, t, n) => {
|
|
2203
2204
|
let r = n ?? e.nullable, i = Ze(e, "mariadb");
|
|
2204
2205
|
return [
|
|
2205
|
-
|
|
2206
|
-
|
|
2206
|
+
G(t),
|
|
2207
|
+
j(e, "mariadb"),
|
|
2207
2208
|
r ? null : "NOT NULL",
|
|
2208
2209
|
i
|
|
2209
2210
|
].filter(Boolean).join(" ");
|
|
2210
|
-
}, cr = (e, t) => e == null ? null : Array.isArray(e) ? lr(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" ?
|
|
2211
|
+
}, cr = (e, t) => e == null ? null : Array.isArray(e) ? lr(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" ? M(e, "mariadb") : null, lr = (e, t, n) => Qe(e, t ?? { type: "json" }, n), ur = (e, t) => e == null ? null : Array.isArray(e) ? lr(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" ? M(e, "postgres") : null, q = (e, t) => {
|
|
2211
2212
|
if (!e.generatedAs) return null;
|
|
2212
2213
|
let { expr: n, stored: r } = e.generatedAs;
|
|
2213
2214
|
return t === "postgres" ? `GENERATED ALWAYS AS (${n}) STORED` : t === "mssql" ? `AS (${n})${r ? " PERSISTED" : ""}` : `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
|
|
2214
2215
|
}, dr = (e) => {
|
|
2215
|
-
if (e.type === "id" && e.idScheme?.kind === "numeric") return
|
|
2216
|
-
let t =
|
|
2217
|
-
if (t) return `${
|
|
2218
|
-
let n = [
|
|
2216
|
+
if (e.type === "id" && e.idScheme?.kind === "numeric") return N(e.name, "postgres");
|
|
2217
|
+
let t = q(e, "postgres");
|
|
2218
|
+
if (t) return `${W(e.name)} ${Zn(e)} ${t}`;
|
|
2219
|
+
let n = [W(e.name), Zn(e)];
|
|
2219
2220
|
if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && n.push("UNIQUE"), e.hasDefault) {
|
|
2220
2221
|
let t = ur(e.defaultValue, e);
|
|
2221
2222
|
t && n.push(t);
|
|
2222
2223
|
}
|
|
2223
|
-
return e.references && (n.push(`REFERENCES ${
|
|
2224
|
+
return e.references && (n.push(`REFERENCES ${W(e.references.table)} (${W(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${{
|
|
2224
2225
|
cascade: "CASCADE",
|
|
2225
2226
|
restrict: "RESTRICT",
|
|
2226
2227
|
setNull: "SET NULL",
|
|
2227
2228
|
noAction: "NO ACTION"
|
|
2228
2229
|
}[e.references.onDelete]}`)), n.join(" ");
|
|
2229
2230
|
}, fr = (e, t) => e.primaryKey && e.primaryKey.length > 0 ? `,\n PRIMARY KEY (${e.primaryKey.map(t).join(", ")})` : "", pr = (e) => {
|
|
2230
|
-
let t = e.columns.map((e) => ` ${dr(e)}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${
|
|
2231
|
-
for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${
|
|
2231
|
+
let t = e.columns.map((e) => ` ${dr(e)}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${W(e.table)} (\n${t}${fr(e, W)}\n)`];
|
|
2232
|
+
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(Pr).join(", ")})`);
|
|
2232
2233
|
return n;
|
|
2233
2234
|
}, mr = 191, hr = (e) => {
|
|
2234
2235
|
let t = $n(e).toUpperCase();
|
|
2235
2236
|
return t.endsWith("TEXT") || t.endsWith("BLOB");
|
|
2236
2237
|
}, gr = (e) => {
|
|
2237
|
-
if (e.type === "id" && e.idScheme?.kind === "numeric") return
|
|
2238
|
-
let t =
|
|
2239
|
-
if (t) return `${
|
|
2240
|
-
let n = [
|
|
2238
|
+
if (e.type === "id" && e.idScheme?.kind === "numeric") return N(e.name, "mariadb");
|
|
2239
|
+
let t = q(e, "mariadb");
|
|
2240
|
+
if (t) return `${G(e.name)} ${$n(e)} ${t}`;
|
|
2241
|
+
let n = [G(e.name), $n(e)];
|
|
2241
2242
|
if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && !hr(e) && n.push("UNIQUE"), e.hasDefault) {
|
|
2242
2243
|
let t = cr(e.defaultValue, e);
|
|
2243
2244
|
t && n.push(t);
|
|
2244
2245
|
}
|
|
2245
|
-
return e.references && (n.push(`REFERENCES ${
|
|
2246
|
+
return e.references && (n.push(`REFERENCES ${G(e.references.table)} (${G(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${{
|
|
2246
2247
|
cascade: "CASCADE",
|
|
2247
2248
|
restrict: "RESTRICT",
|
|
2248
2249
|
setNull: "SET NULL",
|
|
@@ -2250,11 +2251,11 @@ BEGIN
|
|
|
2250
2251
|
}[e.references.onDelete]}`)), n.join(" ");
|
|
2251
2252
|
}, _r = (e) => {
|
|
2252
2253
|
let t = new Map(e.columns.map((e) => [e.name, e])), n = (e) => {
|
|
2253
|
-
let n =
|
|
2254
|
-
return n === void 0 ?
|
|
2255
|
-
}, r = e.columns.map((e) => ` ${gr(e)}`).join(",\n"), i = [`CREATE TABLE IF NOT EXISTS ${
|
|
2256
|
-
for (let t of e.columns) t.unique && t.type !== "id" && hr(t) && i.push(`CREATE UNIQUE INDEX IF NOT EXISTS ${
|
|
2257
|
-
for (let t of e.indexes) t.name !== `${e.table}_pkey` && i.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${
|
|
2254
|
+
let n = Mr(t.get(e));
|
|
2255
|
+
return n === void 0 ? G(e) : `${G(e)}(${n})`;
|
|
2256
|
+
}, r = e.columns.map((e) => ` ${gr(e)}`).join(",\n"), i = [`CREATE TABLE IF NOT EXISTS ${G(e.table)} (\n${r}${fr(e, n)}\n)`];
|
|
2257
|
+
for (let t of e.columns) t.unique && t.type !== "id" && hr(t) && i.push(`CREATE UNIQUE INDEX IF NOT EXISTS ${G(`${e.table}_${t.name}_key`)} ON ${G(e.table)} (${n(t.name)})`);
|
|
2258
|
+
for (let t of e.indexes) t.name !== `${e.table}_pkey` && i.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${G(t.name)} ON ${G(e.table)} (${t.columns.map(n).join(", ")})`);
|
|
2258
2259
|
return i;
|
|
2259
2260
|
}, vr = {
|
|
2260
2261
|
cascade: "CASCADE",
|
|
@@ -2278,52 +2279,52 @@ BEGIN
|
|
|
2278
2279
|
case "bytes": return "BLOB";
|
|
2279
2280
|
default: return "TEXT";
|
|
2280
2281
|
}
|
|
2281
|
-
},
|
|
2282
|
-
if (e.type === "id" && e.idScheme?.kind === "numeric") return
|
|
2283
|
-
let t =
|
|
2284
|
-
if (t) return `${
|
|
2285
|
-
let n = [
|
|
2282
|
+
}, xr = (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" ? M(e, "sqlite") : null, Sr = (e) => {
|
|
2283
|
+
if (e.type === "id" && e.idScheme?.kind === "numeric") return N(e.name, "sqlite");
|
|
2284
|
+
let t = q(e, "sqlite");
|
|
2285
|
+
if (t) return `${W(e.name)} ${br(e)} ${t}`;
|
|
2286
|
+
let n = [W(e.name), br(e)];
|
|
2286
2287
|
if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && n.push("UNIQUE"), e.hasDefault) {
|
|
2287
|
-
let t =
|
|
2288
|
+
let t = xr(e.defaultValue, "CURRENT_TIMESTAMP");
|
|
2288
2289
|
t && n.push(t);
|
|
2289
2290
|
}
|
|
2290
|
-
if (e.references && (n.push(`REFERENCES ${
|
|
2291
|
+
if (e.references && (n.push(`REFERENCES ${W(e.references.table)} (${W(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${vr[e.references.onDelete]}`)), e.oneOf && e.oneOf.length > 0) {
|
|
2291
2292
|
let t = e.oneOf.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
|
|
2292
|
-
n.push(`CHECK (${
|
|
2293
|
+
n.push(`CHECK (${W(e.name)} IN (${t}))`);
|
|
2293
2294
|
}
|
|
2294
2295
|
return n.join(" ");
|
|
2295
|
-
},
|
|
2296
|
-
let t = e.columns.map((e) => ` ${
|
|
2297
|
-
for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${
|
|
2296
|
+
}, Cr = (e) => {
|
|
2297
|
+
let t = e.columns.map((e) => ` ${Sr(e)}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${W(e.table)} (\n${t}${fr(e, W)}\n)`];
|
|
2298
|
+
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(", ")})`);
|
|
2298
2299
|
return n;
|
|
2299
2300
|
}, J = (e, t) => {
|
|
2300
2301
|
let n = t.find((t) => t.tableName === e);
|
|
2301
2302
|
if (!n) return [];
|
|
2302
|
-
let r =
|
|
2303
|
-
...
|
|
2303
|
+
let r = I([n]).tables[0], i = `${e}__voltro_rebuild`, a = r.columns.map((e) => W(e.name)).join(", "), o = [
|
|
2304
|
+
...Cr({
|
|
2304
2305
|
kind: "create-table",
|
|
2305
2306
|
table: i,
|
|
2306
2307
|
columns: r.columns,
|
|
2307
2308
|
indexes: [],
|
|
2308
2309
|
...r.primaryKey ? { primaryKey: r.primaryKey } : {}
|
|
2309
2310
|
}),
|
|
2310
|
-
`INSERT INTO ${
|
|
2311
|
-
`DROP TABLE ${
|
|
2312
|
-
`ALTER TABLE ${
|
|
2311
|
+
`INSERT INTO ${W(i)} (${a}) SELECT ${a} FROM ${W(e)}`,
|
|
2312
|
+
`DROP TABLE ${W(e)}`,
|
|
2313
|
+
`ALTER TABLE ${W(i)} RENAME TO ${W(e)}`
|
|
2313
2314
|
];
|
|
2314
|
-
for (let t of r.indexes) t.name !== `${e}_pkey` && o.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${
|
|
2315
|
+
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(", ")})`);
|
|
2315
2316
|
return o;
|
|
2316
|
-
},
|
|
2317
|
+
}, wr = (e, t, n, r) => {
|
|
2317
2318
|
let i = r ?? e.nullable;
|
|
2318
|
-
return `ALTER TABLE ${Y(n)} ALTER COLUMN ${Y(t)} ${
|
|
2319
|
-
},
|
|
2319
|
+
return `ALTER TABLE ${Y(n)} ALTER COLUMN ${Y(t)} ${j(e, "mssql")} ${i ? "NULL" : "NOT NULL"};`;
|
|
2320
|
+
}, Tr = (e) => {
|
|
2320
2321
|
let t = `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 + ']');`;
|
|
2321
2322
|
if (!e.hasDefault) return t;
|
|
2322
|
-
let n =
|
|
2323
|
+
let n = xr(e.defaultValue, "SYSUTCDATETIME()");
|
|
2323
2324
|
if (!n) return t;
|
|
2324
2325
|
let r = n.replace(/^DEFAULT\s+/i, "");
|
|
2325
2326
|
return `${t} ALTER TABLE ${Y(e.table)} ADD DEFAULT ${r} FOR ${Y(e.column)};`;
|
|
2326
|
-
}, Y = (e) => `[${e.replace(/]/g, "]]")}]`,
|
|
2327
|
+
}, Y = (e) => `[${e.replace(/]/g, "]]")}]`, Er = (e) => {
|
|
2327
2328
|
let t = Xn(e, "mssql");
|
|
2328
2329
|
if (t !== void 0) return t;
|
|
2329
2330
|
switch (e.type) {
|
|
@@ -2339,44 +2340,44 @@ BEGIN
|
|
|
2339
2340
|
case "bytes": return "VARBINARY(MAX)";
|
|
2340
2341
|
default: return "NVARCHAR(MAX)";
|
|
2341
2342
|
}
|
|
2342
|
-
},
|
|
2343
|
-
if (e.type === "id" && e.idScheme?.kind === "numeric") return
|
|
2344
|
-
let n = e.type === "text" && t?.has(e.name) ? "NVARCHAR(450)" :
|
|
2343
|
+
}, Dr = (e, t) => {
|
|
2344
|
+
if (e.type === "id" && e.idScheme?.kind === "numeric") return N(e.name, "mssql");
|
|
2345
|
+
let n = e.type === "text" && t?.has(e.name) ? "NVARCHAR(450)" : Er(e), r = q(e, "mssql");
|
|
2345
2346
|
if (r) return `${Y(e.name)} ${r}`;
|
|
2346
2347
|
let i = [Y(e.name), n];
|
|
2347
2348
|
if (e.type === "id" && i.push("PRIMARY KEY"), e.nullable || i.push("NOT NULL"), e.unique && e.type !== "id" && i.push("UNIQUE"), e.hasDefault) {
|
|
2348
|
-
let t =
|
|
2349
|
+
let t = xr(e.defaultValue, "SYSUTCDATETIME()");
|
|
2349
2350
|
t && i.push(t);
|
|
2350
2351
|
}
|
|
2351
2352
|
return e.references && (i.push(`REFERENCES ${Y(e.references.table)} (${Y(e.references.column)})`), e.references.onDelete && i.push(`ON DELETE ${yr[e.references.onDelete]}`)), i.join(" ");
|
|
2352
|
-
},
|
|
2353
|
-
let t = (e) => e.replace(/'/g, "''"), n = new Set(e.indexes.flatMap((e) => e.columns)), r = e.columns.map((e) => ` ${
|
|
2353
|
+
}, Or = (e) => {
|
|
2354
|
+
let t = (e) => e.replace(/'/g, "''"), n = new Set(e.indexes.flatMap((e) => e.columns)), r = e.columns.map((e) => ` ${Dr(e, n)}`).join(",\n"), i = `CREATE TABLE ${Y(e.table)} (\n${r}${fr(e, Y)}\n)`, a = [`IF OBJECT_ID(N'${t(e.table)}', N'U') IS NULL EXEC(N'${t(i)}')`];
|
|
2354
2355
|
for (let n of e.indexes) {
|
|
2355
2356
|
if (n.name === `${e.table}_pkey`) continue;
|
|
2356
2357
|
let r = `CREATE ${n.unique ? "UNIQUE " : ""}INDEX ${Y(n.name)} ON ${Y(e.table)} (${n.columns.map(Y).join(", ")})`;
|
|
2357
2358
|
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)}')`);
|
|
2358
2359
|
}
|
|
2359
2360
|
return a;
|
|
2360
|
-
},
|
|
2361
|
-
let r = `${e.table}${
|
|
2361
|
+
}, kr = (e) => `__dropped_${e.replace(/[-:T.Z]/g, "").slice(0, 14)}`, Ar = (e, t) => `DROP TABLE IF EXISTS ${t(e.table)};`, jr = (e, t, n) => {
|
|
2362
|
+
let r = `${e.table}${kr(t)}`;
|
|
2362
2363
|
return `ALTER TABLE ${n(e.table)} RENAME TO ${n(r)};`;
|
|
2363
|
-
},
|
|
2364
|
+
}, Mr = (e) => {
|
|
2364
2365
|
if (e === void 0 || !hr(e)) return;
|
|
2365
2366
|
let t = typeof e.maxLength == "number" && e.maxLength > 0 ? e.maxLength : void 0;
|
|
2366
2367
|
return t === void 0 ? mr : Math.min(mr, t);
|
|
2367
|
-
},
|
|
2368
|
-
let r =
|
|
2369
|
-
return r === void 0 ?
|
|
2370
|
-
},
|
|
2368
|
+
}, Nr = (e, t, n) => {
|
|
2369
|
+
let r = Mr(or(e, t, n));
|
|
2370
|
+
return r === void 0 ? G(n) : `${G(n)}(${r})`;
|
|
2371
|
+
}, Pr = (e) => e.startsWith("(") ? e : W(e), Fr = (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(Pr).join(", ")});`, Ir = (e, t) => `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${G(e.index.name)} ON ${G(e.table)} (${e.index.columns.map((n) => Nr(t, e.table, n)).join(", ")});`, Lr = (e) => `DROP INDEX IF EXISTS ${W(e.index)};`, Rr = (e) => `DROP INDEX ${G(e.index)} ON ${G(e.table)};`, zr = (e) => `DROP INDEX IF EXISTS ${Y(e.index)} ON ${Y(e.table)};`, Br = (e, t) => `ALTER TABLE ${t(e.from)} RENAME TO ${t(e.to)};`, Vr = (e) => {
|
|
2371
2372
|
let t = (e) => e.replace(/'/g, "''");
|
|
2372
2373
|
return `EXEC sp_rename N'${t(e.from)}', N'${t(e.to)}';`;
|
|
2373
|
-
},
|
|
2374
|
+
}, Hr = (e) => `ALTER INDEX ${W(e.from)} RENAME TO ${W(e.to)};`, Ur = (e) => `ALTER TABLE ${G(e.table)} RENAME INDEX ${G(e.from)} TO ${G(e.to)};`, Wr = (e) => {
|
|
2374
2375
|
let t = (e) => e.replace(/'/g, "''");
|
|
2375
2376
|
return `EXEC sp_rename N'${t(e.table)}.${t(e.from)}', N'${t(e.to)}', N'INDEX';`;
|
|
2376
|
-
},
|
|
2377
|
+
}, Gr = (e) => {
|
|
2377
2378
|
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(", ")})`;
|
|
2378
2379
|
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)}');`;
|
|
2379
|
-
},
|
|
2380
|
+
}, Kr = (e, t, n) => {
|
|
2380
2381
|
let r = n.find((t) => t.tableName === e);
|
|
2381
2382
|
if (!r) return [];
|
|
2382
2383
|
let i = [];
|
|
@@ -2385,13 +2386,13 @@ BEGIN
|
|
|
2385
2386
|
t && t.type === "text" && !t.generatedAs && i.push(`ALTER TABLE ${Y(e)} ALTER COLUMN ${Y(n)} NVARCHAR(450) ${t.nullable ? "NULL" : "NOT NULL"};`);
|
|
2386
2387
|
}
|
|
2387
2388
|
return i;
|
|
2388
|
-
},
|
|
2389
|
-
let t = e.fields.map((e) =>
|
|
2390
|
-
return `ALTER TABLE ${
|
|
2391
|
-
},
|
|
2392
|
-
let n = e.fields.map((n) =>
|
|
2393
|
-
return `ALTER TABLE ${
|
|
2394
|
-
},
|
|
2389
|
+
}, qr = (e) => `ALTER TABLE ${W(e.table)} ADD CONSTRAINT ${W(`${e.table}_${e.column}_key`)} UNIQUE (${W(e.column)});`, Jr = (e, t) => `ALTER TABLE ${G(e.table)} ADD CONSTRAINT ${G(`${e.table}_${e.column}_key`)} UNIQUE (${Nr(t, e.table, e.column)});`, Yr = (e) => {
|
|
2390
|
+
let t = e.fields.map((e) => W(e)).join(", ");
|
|
2391
|
+
return `ALTER TABLE ${W(e.table)} ADD CONSTRAINT ${W(e.name)} UNIQUE (${t});`;
|
|
2392
|
+
}, Xr = (e, t) => {
|
|
2393
|
+
let n = e.fields.map((n) => Nr(t, e.table, n)).join(", ");
|
|
2394
|
+
return `ALTER TABLE ${G(e.table)} ADD CONSTRAINT ${G(e.name)} UNIQUE (${n});`;
|
|
2395
|
+
}, Zr = (e) => `ALTER TABLE ${W(e.table)} DROP CONSTRAINT IF EXISTS ${W(e.name)};`, Qr = (e) => `ALTER TABLE ${G(e.table)} DROP INDEX ${G(e.name)};`, $r = (e) => `ALTER TABLE ${W(e.table)} DROP CONSTRAINT IF EXISTS ${W(`${e.table}_${e.column}_key`)};`, ei = (e) => `ALTER TABLE ${G(e.table)} DROP INDEX ${G(`${e.table}_${e.column}_key`)};`, ti = (e, t) => {
|
|
2395
2396
|
let n = [], r = t(e.table), i = t(e.column), a = t(e.targetTable), o = t(e.targetColumn);
|
|
2396
2397
|
if (e.orphanPolicy) {
|
|
2397
2398
|
let t = `${i} IS NOT NULL AND ${i} NOT IN (SELECT ${o} FROM ${a})`;
|
|
@@ -2409,11 +2410,11 @@ BEGIN
|
|
|
2409
2410
|
setNull: "SET NULL",
|
|
2410
2411
|
noAction: "NO ACTION"
|
|
2411
2412
|
}[e.onDelete]}`), n.push(s.join(" ") + ";"), n;
|
|
2412
|
-
},
|
|
2413
|
+
}, ni = (e) => `ALTER TABLE ${W(e.table)} DROP CONSTRAINT IF EXISTS ${W(`${e.table}_${e.column}_fkey`)};`, ri = (e) => `ALTER TABLE ${G(e.table)} DROP FOREIGN KEY ${G(`${e.table}_${e.column}_fkey`)};`, ii = (e, t) => {
|
|
2413
2414
|
let n = e.values.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
|
|
2414
2415
|
return `ALTER TABLE ${t(e.table)} ADD CONSTRAINT ${t(`${e.table}_${e.column}_check`)} CHECK (${t(e.column)} IN (${n}));`;
|
|
2415
|
-
},
|
|
2416
|
-
let i = e.column, a = r === "mariadb", o = a ?
|
|
2416
|
+
}, ai = (e) => `ALTER TABLE ${W(e.table)} DROP CONSTRAINT IF EXISTS ${W(`${e.table}_${e.column}_check`)};`, oi = (e) => `ALTER TABLE ${G(e.table)} DROP CHECK ${G(`${e.table}_${e.column}_check`)};`, si = (e, t, n, r) => {
|
|
2417
|
+
let i = e.column, a = r === "mariadb", o = a ? G : r === "mssql" ? Y : W, s = a ? $n(i) : r === "mssql" ? Er(i) : r === "sqlite" ? br(i) : Zn(i), c = r === "mssql" ? "ADD" : "ADD COLUMN", l = (e) => a ? cr(e, i) : r === "mssql" ? xr(e, "SYSUTCDATETIME()") : r === "sqlite" ? xr(e, "CURRENT_TIMESTAMP") : ur(e, i), u = q(i, r);
|
|
2417
2418
|
if (u) {
|
|
2418
2419
|
let t = r === "mssql" ? `${o(i.name)} ${u}` : `${o(i.name)} ${s} ${u}`;
|
|
2419
2420
|
return {
|
|
@@ -2441,7 +2442,7 @@ BEGIN
|
|
|
2441
2442
|
post: f ? [f] : []
|
|
2442
2443
|
};
|
|
2443
2444
|
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;
|
|
2444
|
-
},
|
|
2445
|
+
}, ci = (e) => {
|
|
2445
2446
|
let t = new Map(e.map((e) => [e.tableName, e]));
|
|
2446
2447
|
return (e, n) => {
|
|
2447
2448
|
let r = t.get(e);
|
|
@@ -2466,29 +2467,29 @@ BEGIN
|
|
|
2466
2467
|
})), b.mapError((e) => {
|
|
2467
2468
|
let r = ie(`applier: statement failed (op=${n})`, t, e, 400).trim();
|
|
2468
2469
|
return Object.assign(e, { message: r });
|
|
2469
|
-
}), b.map(() => void 0)), Z = (e, t, n) => b.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 ? "*" : i(r, t)} FROM ${i(n, t)} WHERE 1=0`).pipe(b.as(!0), b.catchAll(() => b.succeed(!1))),
|
|
2470
|
-
let n =
|
|
2470
|
+
}), b.map(() => void 0)), Z = (e, t, n) => b.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 ? "*" : i(r, t)} FROM ${i(n, t)} WHERE 1=0`).pipe(b.as(!0), b.catchAll(() => b.succeed(!1))), li = (e, t) => b.gen(function* () {
|
|
2471
|
+
let n = I([Fe], t).tables[0];
|
|
2471
2472
|
if (!n) return yield* b.die(/* @__PURE__ */ Error("migration applier: the resume-ledger table descriptor produced no snapshot. This is a framework bug."));
|
|
2472
2473
|
let r = {
|
|
2473
2474
|
kind: "create-table",
|
|
2474
|
-
table:
|
|
2475
|
+
table: O,
|
|
2475
2476
|
columns: n.columns,
|
|
2476
2477
|
indexes: []
|
|
2477
2478
|
}, i = yield* e.onDialectOrElse({
|
|
2478
2479
|
mysql: () => b.succeed(_r(r)),
|
|
2479
|
-
mssql: () => b.succeed(
|
|
2480
|
-
sqlite: () => b.succeed(
|
|
2480
|
+
mssql: () => b.succeed(Or(r)),
|
|
2481
|
+
sqlite: () => b.succeed(Cr(r)),
|
|
2481
2482
|
orElse: () => b.succeed(pr(r))
|
|
2482
2483
|
});
|
|
2483
2484
|
yield* b.forEach(i, (t) => X(e, t, "resume-ledger-bootstrap"), { discard: !0 });
|
|
2484
|
-
}),
|
|
2485
|
+
}), ui = (e) => e`
|
|
2485
2486
|
SELECT ${e("runId")}, ${e("planFingerprint")}, ${e("opIndex")},
|
|
2486
2487
|
${e("status")}, ${e("payload")}
|
|
2487
|
-
FROM ${e(
|
|
2488
|
-
`,
|
|
2489
|
-
let i = yield*
|
|
2488
|
+
FROM ${e(O)}
|
|
2489
|
+
`, di = (e, t, n, r) => b.gen(function* () {
|
|
2490
|
+
let i = yield* U(e, (/* @__PURE__ */ new Date()).toISOString());
|
|
2490
2491
|
yield* b.forEach(r, ({ index: r, planned: a }) => e`
|
|
2491
|
-
INSERT INTO ${e(
|
|
2492
|
+
INSERT INTO ${e(O)}
|
|
2492
2493
|
(${e("id")}, ${e("runId")}, ${e("planFingerprint")}, ${e("opIndex")},
|
|
2493
2494
|
${e("opKind")}, ${e("opTarget")}, ${e("status")}, ${e("payload")},
|
|
2494
2495
|
${e("createdAt")})
|
|
@@ -2497,11 +2498,11 @@ BEGIN
|
|
|
2497
2498
|
${a.op.kind}, ${Le(a.op)}, ${"pending"},
|
|
2498
2499
|
${JSON.stringify(a)}, ${i})
|
|
2499
2500
|
`, { discard: !0 });
|
|
2500
|
-
}),
|
|
2501
|
-
let a = yield*
|
|
2501
|
+
}), fi = (e, t, n, r, i) => b.gen(function* () {
|
|
2502
|
+
let a = yield* U(e, (/* @__PURE__ */ new Date()).toISOString());
|
|
2502
2503
|
if (r === "applied") {
|
|
2503
2504
|
yield* e`
|
|
2504
|
-
UPDATE ${e(
|
|
2505
|
+
UPDATE ${e(O)}
|
|
2505
2506
|
SET ${e("status")} = ${r}, ${e("appliedAt")} = ${a},
|
|
2506
2507
|
${e("durationMs")} = ${i ?? null}
|
|
2507
2508
|
WHERE ${e("runId")} = ${t} AND ${e("opIndex")} = ${n}
|
|
@@ -2509,22 +2510,22 @@ BEGIN
|
|
|
2509
2510
|
return;
|
|
2510
2511
|
}
|
|
2511
2512
|
yield* e`
|
|
2512
|
-
UPDATE ${e(
|
|
2513
|
+
UPDATE ${e(O)}
|
|
2513
2514
|
SET ${e("status")} = ${r}, ${e("startedAt")} = ${a}
|
|
2514
2515
|
WHERE ${e("runId")} = ${t} AND ${e("opIndex")} = ${n}
|
|
2515
2516
|
`;
|
|
2516
|
-
}),
|
|
2517
|
-
let i = yield*
|
|
2517
|
+
}), pi = (e, t, n, r) => b.gen(function* () {
|
|
2518
|
+
let i = yield* U(e, (/* @__PURE__ */ new Date()).toISOString());
|
|
2518
2519
|
r.length > 0 && (yield* e`
|
|
2519
|
-
UPDATE ${e(
|
|
2520
|
+
UPDATE ${e(O)}
|
|
2520
2521
|
SET ${e("status")} = ${"applied"}, ${e("appliedAt")} = ${i}
|
|
2521
2522
|
WHERE ${e("runId")} = ${t} AND ${e("opIndex")} IN ${e.in(r)}
|
|
2522
2523
|
`), n.length > 0 && (yield* e`
|
|
2523
|
-
UPDATE ${e(
|
|
2524
|
+
UPDATE ${e(O)}
|
|
2524
2525
|
SET ${e("status")} = ${"pending"}
|
|
2525
2526
|
WHERE ${e("runId")} = ${t} AND ${e("opIndex")} IN ${e.in(n)}
|
|
2526
2527
|
`);
|
|
2527
|
-
}),
|
|
2528
|
+
}), mi = (e, t) => t === void 0 ? e`DELETE FROM ${e(O)}`.pipe(b.asVoid) : e`DELETE FROM ${e(O)} WHERE ${e("runId")} = ${t}`.pipe(b.asVoid), hi = (e, t, n) => b.gen(function* () {
|
|
2528
2529
|
if (Ge(n.op, n.classification, t) !== "artefact-repair") return "clean";
|
|
2529
2530
|
let r = n.op, a = (e) => i(e, t);
|
|
2530
2531
|
if (t === "sqlite" || t === "turso") {
|
|
@@ -2535,129 +2536,130 @@ BEGIN
|
|
|
2535
2536
|
if (r.kind !== "alter-column-type") return "clean";
|
|
2536
2537
|
let o = `${r.column}${Ve}`, s = `${r.column}${He}`, c = yield* $(e, t, r.table, r.column), l = yield* $(e, t, r.table, o), u = yield* $(e, t, r.table, s), d = (e) => b.logWarning(`migration resume: ${e}`).pipe(b.annotateLogs({ scope: "voltro:migrate" }));
|
|
2537
2538
|
return !l && !u ? "clean" : c && l && !u ? (yield* X(e, `ALTER TABLE ${a(r.table)} DROP COLUMN ${a(o)}`, "resume-repair"), yield* d(`dropped a half-populated shadow column '${r.table}.${o}' — replaying the type change`), "outstanding") : !c && l && u ? (yield* X(e, `ALTER TABLE ${a(r.table)} RENAME COLUMN ${a(o)} TO ${a(r.column)}`, "resume-repair"), yield* X(e, `ALTER TABLE ${a(r.table)} DROP COLUMN ${a(s)}`, "resume-repair"), yield* d(`completed an interrupted shadow swap on '${r.table}.${r.column}'`), "applied") : c && !l && u ? (yield* X(e, `ALTER TABLE ${a(r.table)} DROP COLUMN ${a(s)}`, "resume-repair"), yield* d(`dropped the leftover pre-swap column '${r.table}.${s}'`), "applied") : yield* b.die(/* @__PURE__ */ Error(`applyPlan: an interrupted online type change on '${r.table}.${r.column}' left a shadow-swap state this resume cannot classify (column=${c}, ${o}=${l}, ${s}=${u}).\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.`));
|
|
2538
|
-
}),
|
|
2539
|
-
let i = process.hrtime.bigint(), a =
|
|
2539
|
+
}), gi = (e, t, n, r = "fresh") => b.gen(function* () {
|
|
2540
|
+
let i = process.hrtime.bigint(), a = ci(n.declared), o = t.op;
|
|
2540
2541
|
switch (o.kind) {
|
|
2541
2542
|
case "create-table": {
|
|
2542
2543
|
let t = yield* e.onDialectOrElse({
|
|
2543
2544
|
mysql: () => b.succeed(_r(o)),
|
|
2544
|
-
mssql: () => b.succeed(
|
|
2545
|
-
sqlite: () => b.succeed(
|
|
2545
|
+
mssql: () => b.succeed(Or(o)),
|
|
2546
|
+
sqlite: () => b.succeed(Cr(o)),
|
|
2546
2547
|
orElse: () => b.succeed(pr(o))
|
|
2547
2548
|
});
|
|
2548
2549
|
for (let n of t) yield* X(e, n, o.kind);
|
|
2549
2550
|
break;
|
|
2550
2551
|
}
|
|
2551
2552
|
case "drop-table": {
|
|
2552
|
-
let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString(), r = (e) => t ?
|
|
2553
|
+
let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString(), r = (e) => t ? jr(o, n, e) : Ar(o, e);
|
|
2553
2554
|
yield* e.onDialectOrElse({
|
|
2554
|
-
mysql: () => X(e, r(
|
|
2555
|
-
orElse: () => X(e, r(
|
|
2555
|
+
mysql: () => X(e, r(G), o.kind),
|
|
2556
|
+
orElse: () => X(e, r(W), o.kind)
|
|
2556
2557
|
});
|
|
2557
2558
|
break;
|
|
2558
2559
|
}
|
|
2559
2560
|
case "drop-column": {
|
|
2560
2561
|
let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString();
|
|
2561
2562
|
yield* e.onDialectOrElse({
|
|
2562
|
-
mysql: () => X(e, t ? rr(o, n,
|
|
2563
|
-
orElse: () => X(e, t ? rr(o, n,
|
|
2563
|
+
mysql: () => X(e, t ? rr(o, n, G) : tr(o), o.kind),
|
|
2564
|
+
orElse: () => X(e, t ? rr(o, n, W) : er(o, W), o.kind)
|
|
2564
2565
|
});
|
|
2565
2566
|
break;
|
|
2566
2567
|
}
|
|
2567
2568
|
case "rename-column":
|
|
2568
2569
|
yield* e.onDialectOrElse({
|
|
2569
|
-
mysql: () => X(e, nr(o,
|
|
2570
|
+
mysql: () => X(e, nr(o, G), o.kind),
|
|
2570
2571
|
mssql: () => X(e, `EXEC sp_rename N'${o.table.replace(/'/g, "''")}.${o.from.replace(/'/g, "''")}', N'${o.to.replace(/'/g, "''")}', 'COLUMN';`, o.kind),
|
|
2571
|
-
orElse: () => X(e, nr(o,
|
|
2572
|
+
orElse: () => X(e, nr(o, W), o.kind)
|
|
2572
2573
|
});
|
|
2573
2574
|
break;
|
|
2574
2575
|
case "add-index":
|
|
2575
2576
|
yield* e.onDialectOrElse({
|
|
2576
|
-
mysql: () => X(e,
|
|
2577
|
-
mssql: () => Z(e, [...
|
|
2578
|
-
orElse: () => X(e,
|
|
2577
|
+
mysql: () => X(e, Ir(o, n.declared), o.kind),
|
|
2578
|
+
mssql: () => Z(e, [...Kr(o.table, o.index.columns, n.declared), Gr(o)], o.kind),
|
|
2579
|
+
orElse: () => X(e, Fr(o, t.classification === "online-required"), o.kind)
|
|
2579
2580
|
});
|
|
2580
2581
|
break;
|
|
2581
2582
|
case "drop-index":
|
|
2582
2583
|
yield* e.onDialectOrElse({
|
|
2583
|
-
mysql: () => X(e,
|
|
2584
|
-
mssql: () => X(e,
|
|
2585
|
-
orElse: () => X(e,
|
|
2584
|
+
mysql: () => X(e, Rr(o), o.kind),
|
|
2585
|
+
mssql: () => X(e, zr(o), o.kind),
|
|
2586
|
+
orElse: () => X(e, Lr(o), o.kind)
|
|
2586
2587
|
});
|
|
2587
2588
|
break;
|
|
2588
2589
|
case "rename-table":
|
|
2589
2590
|
yield* e.onDialectOrElse({
|
|
2590
|
-
mysql: () => X(e,
|
|
2591
|
-
mssql: () => X(e,
|
|
2592
|
-
orElse: () => X(e,
|
|
2591
|
+
mysql: () => X(e, Br(o, G), o.kind),
|
|
2592
|
+
mssql: () => X(e, Vr(o), o.kind),
|
|
2593
|
+
orElse: () => X(e, Br(o, W), o.kind)
|
|
2593
2594
|
});
|
|
2594
2595
|
break;
|
|
2595
2596
|
case "rename-index":
|
|
2596
2597
|
yield* e.onDialectOrElse({
|
|
2597
|
-
mysql: () => X(e,
|
|
2598
|
-
mssql: () => X(e,
|
|
2599
|
-
orElse: () => X(e,
|
|
2598
|
+
mysql: () => X(e, Ur(o), o.kind),
|
|
2599
|
+
mssql: () => X(e, Wr(o), o.kind),
|
|
2600
|
+
orElse: () => X(e, Hr(o), o.kind)
|
|
2600
2601
|
});
|
|
2601
2602
|
break;
|
|
2602
2603
|
case "add-unique":
|
|
2603
2604
|
yield* e.onDialectOrElse({
|
|
2604
|
-
mysql: () => X(e,
|
|
2605
|
+
mysql: () => X(e, Jr(o, n.declared), o.kind),
|
|
2605
2606
|
sqlite: () => Z(e, J(o.table, n.declared), o.kind),
|
|
2606
|
-
mssql: () => Z(e, [...
|
|
2607
|
-
orElse: () => X(e,
|
|
2607
|
+
mssql: () => Z(e, [...Kr(o.table, [o.column], n.declared), qr(o)], o.kind),
|
|
2608
|
+
orElse: () => X(e, qr(o), o.kind)
|
|
2608
2609
|
});
|
|
2609
2610
|
break;
|
|
2610
2611
|
case "drop-unique":
|
|
2611
2612
|
yield* e.onDialectOrElse({
|
|
2612
|
-
mysql: () => X(e,
|
|
2613
|
+
mysql: () => X(e, ei(o), o.kind),
|
|
2613
2614
|
sqlite: () => Z(e, J(o.table, n.declared), o.kind),
|
|
2614
|
-
orElse: () => X(e,
|
|
2615
|
+
orElse: () => X(e, $r(o), o.kind)
|
|
2615
2616
|
});
|
|
2616
2617
|
break;
|
|
2617
2618
|
case "add-unique-composite":
|
|
2618
2619
|
yield* e.onDialectOrElse({
|
|
2619
|
-
mysql: () => X(e,
|
|
2620
|
+
mysql: () => X(e, Xr(o, n.declared), o.kind),
|
|
2620
2621
|
sqlite: () => Z(e, J(o.table, n.declared), o.kind),
|
|
2621
|
-
mssql: () => Z(e, [...
|
|
2622
|
-
orElse: () => X(e,
|
|
2622
|
+
mssql: () => Z(e, [...Kr(o.table, o.fields, n.declared), Yr(o)], o.kind),
|
|
2623
|
+
orElse: () => X(e, Yr(o), o.kind)
|
|
2623
2624
|
});
|
|
2624
2625
|
break;
|
|
2625
2626
|
case "drop-unique-composite":
|
|
2626
2627
|
yield* e.onDialectOrElse({
|
|
2627
|
-
mysql: () => X(e,
|
|
2628
|
+
mysql: () => X(e, Qr(o), o.kind),
|
|
2628
2629
|
sqlite: () => Z(e, J(o.table, n.declared), o.kind),
|
|
2629
|
-
orElse: () => X(e,
|
|
2630
|
+
orElse: () => X(e, Zr(o), o.kind)
|
|
2630
2631
|
});
|
|
2631
2632
|
break;
|
|
2632
2633
|
case "add-foreign-key":
|
|
2633
2634
|
yield* e.onDialectOrElse({
|
|
2634
|
-
mysql: () => Z(e,
|
|
2635
|
+
mysql: () => Z(e, ti(o, G), o.kind),
|
|
2635
2636
|
sqlite: () => Z(e, J(o.table, n.declared), o.kind),
|
|
2636
|
-
orElse: () => Z(e,
|
|
2637
|
+
orElse: () => Z(e, ti(o, W), o.kind)
|
|
2637
2638
|
});
|
|
2638
2639
|
break;
|
|
2639
2640
|
case "add-column": {
|
|
2640
|
-
let n =
|
|
2641
|
+
let n = si(o, t, a, yield* e.onDialectOrElse({
|
|
2641
2642
|
mysql: () => b.succeed("mariadb"),
|
|
2642
2643
|
mssql: () => b.succeed("mssql"),
|
|
2643
2644
|
sqlite: () => b.succeed("sqlite"),
|
|
2644
2645
|
orElse: () => b.succeed("postgres")
|
|
2645
2646
|
}));
|
|
2646
2647
|
if (!(r === "resume" && (yield* $(e, Me(e), o.table, o.column.name)))) for (let t of n.pre) yield* X(e, t, o.kind);
|
|
2647
|
-
if (n.backfillKind === "sql" && n.backfillSql)
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2648
|
+
if (n.backfillKind === "sql" && n.backfillSql) {
|
|
2649
|
+
if (t.classification !== "online-required" && n.batchSize === void 0) yield* e`UPDATE ${e(o.table)} SET ${e(o.column.name)} = ${n.backfillSql}`;
|
|
2650
|
+
else {
|
|
2651
|
+
let t = n.batchSize ?? 5e3, r = n.sleepMs ?? 0, i, a = 0;
|
|
2652
|
+
for (;;) {
|
|
2653
|
+
let s = i === void 0 ? yield* e`SELECT ${e("id")} FROM ${e(o.table)} WHERE ${e(o.column.name)} IS NULL ORDER BY ${e("id")} ${Q(e, t)}` : yield* e`SELECT ${e("id")} FROM ${e(o.table)} WHERE ${e(o.column.name)} IS NULL AND ${e("id")} > ${i} ORDER BY ${e("id")} ${Q(e, t)}`;
|
|
2654
|
+
if (s.length === 0) break;
|
|
2655
|
+
let c = s.map((e) => e.id);
|
|
2656
|
+
yield* e`UPDATE ${e(o.table)} SET ${e(o.column.name)} = ${n.backfillSql} WHERE ${e("id")} IN ${e.in(c)}`, a += s.length, yield* b.logInfo(`backfill ${o.table}.${o.column.name}: ${a} rows`).pipe(b.annotateLogs({
|
|
2657
|
+
scope: "voltro:migrate",
|
|
2658
|
+
mode: "sql-batched"
|
|
2659
|
+
})), i = s[s.length - 1].id, r > 0 && (yield* b.sleep(`${r} millis`));
|
|
2660
|
+
}
|
|
2658
2661
|
}
|
|
2659
|
-
}
|
|
2660
|
-
else if (n.backfillKind === "js" && n.backfillJs) {
|
|
2662
|
+
} else if (n.backfillKind === "js" && n.backfillJs) {
|
|
2661
2663
|
let t = n.batchSize ?? 1e3, r = n.sleepMs ?? 0, i, a = 0;
|
|
2662
2664
|
for (;;) {
|
|
2663
2665
|
let s = i === void 0 ? yield* e`SELECT ${e("id")} FROM ${e(o.table)} WHERE ${e(o.column.name)} IS NULL ORDER BY ${e("id")} ${Q(e, t)}` : yield* e`SELECT ${e("id")} FROM ${e(o.table)} WHERE ${e(o.column.name)} IS NULL AND ${e("id")} > ${i} ORDER BY ${e("id")} ${Q(e, t)}`;
|
|
@@ -2682,24 +2684,24 @@ BEGIN
|
|
|
2682
2684
|
case "alter-column-nullability":
|
|
2683
2685
|
yield* e.onDialectOrElse({
|
|
2684
2686
|
mysql: () => {
|
|
2685
|
-
let t =
|
|
2686
|
-
return t ? X(e, `ALTER TABLE ${
|
|
2687
|
+
let t = K(n.declared, o.table, o.column);
|
|
2688
|
+
return t ? X(e, `ALTER TABLE ${G(o.table)} MODIFY COLUMN ${sr(t, o.column, o.toNullable)};`, o.kind) : b.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.`));
|
|
2687
2689
|
},
|
|
2688
2690
|
mssql: () => {
|
|
2689
|
-
let t =
|
|
2690
|
-
return t ? X(e,
|
|
2691
|
+
let t = K(n.declared, o.table, o.column);
|
|
2692
|
+
return t ? X(e, wr(t, o.column, o.table, o.toNullable), o.kind) : b.die(/* @__PURE__ */ Error(`alter-column-nullability on mssql needs the declared column '${o.table}.${o.column}'.`));
|
|
2691
2693
|
},
|
|
2692
2694
|
sqlite: () => Z(e, J(o.table, n.declared), o.kind),
|
|
2693
|
-
orElse: () => X(e, `ALTER TABLE ${
|
|
2695
|
+
orElse: () => X(e, `ALTER TABLE ${W(o.table)} ALTER COLUMN ${W(o.column)} ${o.toNullable ? "DROP NOT NULL" : "SET NOT NULL"};`, o.kind)
|
|
2694
2696
|
});
|
|
2695
2697
|
break;
|
|
2696
2698
|
case "alter-column-default": {
|
|
2697
2699
|
let t = or(n.declared, o.table, o.column);
|
|
2698
2700
|
yield* e.onDialectOrElse({
|
|
2699
|
-
mysql: () => X(e, ir(o,
|
|
2700
|
-
mssql: () => X(e,
|
|
2701
|
+
mysql: () => X(e, ir(o, G, (e) => cr(e, t)), o.kind),
|
|
2702
|
+
mssql: () => X(e, Tr(o), o.kind),
|
|
2701
2703
|
sqlite: () => Z(e, J(o.table, n.declared), o.kind),
|
|
2702
|
-
orElse: () => X(e, ir(o,
|
|
2704
|
+
orElse: () => X(e, ir(o, W, (e) => ur(e, t)), o.kind)
|
|
2703
2705
|
});
|
|
2704
2706
|
break;
|
|
2705
2707
|
}
|
|
@@ -2708,15 +2710,15 @@ BEGIN
|
|
|
2708
2710
|
if (t.classification !== "online-required") {
|
|
2709
2711
|
yield* e.onDialectOrElse({
|
|
2710
2712
|
mysql: () => {
|
|
2711
|
-
let t =
|
|
2712
|
-
return t ? X(e, `ALTER TABLE ${
|
|
2713
|
+
let t = K(n.declared, o.table, o.column);
|
|
2714
|
+
return t ? X(e, `ALTER TABLE ${G(o.table)} MODIFY COLUMN ${sr(t, o.column)};`, o.kind) : b.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.`));
|
|
2713
2715
|
},
|
|
2714
2716
|
mssql: () => {
|
|
2715
|
-
let t =
|
|
2716
|
-
return t ? X(e,
|
|
2717
|
+
let t = K(n.declared, o.table, o.column);
|
|
2718
|
+
return t ? X(e, wr(t, o.column, o.table), o.kind) : b.die(/* @__PURE__ */ Error(`alter-column-type on mssql needs the declared column '${o.table}.${o.column}'.`));
|
|
2717
2719
|
},
|
|
2718
2720
|
sqlite: () => Z(e, J(o.table, n.declared), o.kind),
|
|
2719
|
-
orElse: () => X(e, `ALTER TABLE ${
|
|
2721
|
+
orElse: () => X(e, `ALTER TABLE ${W(o.table)} ALTER COLUMN ${W(o.column)} TYPE ${r}${i};`, o.kind)
|
|
2720
2722
|
});
|
|
2721
2723
|
break;
|
|
2722
2724
|
}
|
|
@@ -2725,58 +2727,56 @@ BEGIN
|
|
|
2725
2727
|
orElse: () => b.void
|
|
2726
2728
|
});
|
|
2727
2729
|
let a = `${o.column}__shadow`, s = `${o.column}__old`;
|
|
2728
|
-
yield* e.unsafe(`ALTER TABLE ${
|
|
2729
|
-
let c = o.using ??
|
|
2730
|
+
yield* e.unsafe(`ALTER TABLE ${W(o.table)} ADD COLUMN ${W(a)} ${r}`);
|
|
2731
|
+
let c = o.using ?? W(o.column), l;
|
|
2730
2732
|
for (;;) {
|
|
2731
2733
|
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)}`;
|
|
2732
2734
|
if (t.length === 0) break;
|
|
2733
|
-
yield* e.unsafe(`UPDATE ${
|
|
2735
|
+
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;
|
|
2734
2736
|
}
|
|
2735
|
-
yield* b.logInfo(`alter-column-type shadow ${o.table}.${o.column}: shadow populated`).pipe(b.annotateLogs({ scope: "voltro:migrate" })), yield* e.unsafe(`ALTER TABLE ${
|
|
2737
|
+
yield* b.logInfo(`alter-column-type shadow ${o.table}.${o.column}: shadow populated`).pipe(b.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)}`);
|
|
2736
2738
|
break;
|
|
2737
2739
|
}
|
|
2738
2740
|
case "drop-foreign-key":
|
|
2739
2741
|
yield* e.onDialectOrElse({
|
|
2740
|
-
mysql: () => X(e,
|
|
2742
|
+
mysql: () => X(e, ri(o), o.kind),
|
|
2741
2743
|
sqlite: () => Z(e, J(o.table, n.declared), o.kind),
|
|
2742
|
-
orElse: () => X(e,
|
|
2744
|
+
orElse: () => X(e, ni(o), o.kind)
|
|
2743
2745
|
});
|
|
2744
2746
|
break;
|
|
2745
2747
|
case "add-check":
|
|
2746
2748
|
yield* e.onDialectOrElse({
|
|
2747
|
-
mysql: () => X(e,
|
|
2748
|
-
sqlite: () => Z(e, J(o.table, n.declared), o.kind),
|
|
2749
|
-
orElse: () => X(e, ri(o, U), o.kind)
|
|
2750
|
-
});
|
|
2751
|
-
break;
|
|
2752
|
-
case "drop-check":
|
|
2753
|
-
yield* e.onDialectOrElse({
|
|
2754
|
-
mysql: () => X(e, ai(o), o.kind),
|
|
2749
|
+
mysql: () => X(e, ii(o, G), o.kind),
|
|
2755
2750
|
sqlite: () => Z(e, J(o.table, n.declared), o.kind),
|
|
2756
|
-
orElse: () => X(e, ii(o), o.kind)
|
|
2751
|
+
orElse: () => X(e, ii(o, W), o.kind)
|
|
2757
2752
|
});
|
|
2758
2753
|
break;
|
|
2754
|
+
case "drop-check": yield* e.onDialectOrElse({
|
|
2755
|
+
mysql: () => X(e, oi(o), o.kind),
|
|
2756
|
+
sqlite: () => Z(e, J(o.table, n.declared), o.kind),
|
|
2757
|
+
orElse: () => X(e, ai(o), o.kind)
|
|
2758
|
+
});
|
|
2759
2759
|
}
|
|
2760
2760
|
return {
|
|
2761
2761
|
op: o,
|
|
2762
2762
|
status: "applied",
|
|
2763
2763
|
durationMs: Number((process.hrtime.bigint() - i) / 1000000n)
|
|
2764
2764
|
};
|
|
2765
|
-
}),
|
|
2765
|
+
}), _i = (e, t, n, r) => b.gen(function* () {
|
|
2766
2766
|
let i = [...new Set(r.map((e) => e.runId))];
|
|
2767
|
-
if (i.length > 1) return yield* b.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 \`${
|
|
2767
|
+
if (i.length > 1) return yield* b.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 \`${O}\`, reconcile the schema by hand, and delete the rows of the run you have finished.`));
|
|
2768
2768
|
let a = i[0], o = [...r].map((e) => ({
|
|
2769
2769
|
index: Number(e.opIndex),
|
|
2770
2770
|
status: e.status,
|
|
2771
2771
|
planned: JSON.parse(e.payload)
|
|
2772
2772
|
})).sort((e, t) => e.index - t.index), s = o.find((e) => e.status === "started"), c = o.filter((e) => e.status === "started").length;
|
|
2773
|
-
if (c > 1) return yield* b.die(/* @__PURE__ */ Error(`applyPlan: the resume ledger records ${c} operations as in-flight for run ${a}. It is written strictly sequentially, so at most one can be — this ledger is corrupt and the schema state it describes cannot be trusted.\nNothing was changed. Reconcile \`${
|
|
2773
|
+
if (c > 1) return yield* b.die(/* @__PURE__ */ Error(`applyPlan: the resume ledger records ${c} operations as in-flight for run ${a}. It is written strictly sequentially, so at most one can be — this ledger is corrupt and the schema state it describes cannot be trusted.\nNothing was changed. Reconcile \`${O}\` by hand before re-running.`));
|
|
2774
2774
|
if (yield* b.logWarning(`migration resume: found an interrupted run (${a}) — ${o.filter((e) => e.status === "applied").length} of ${o.length} operation(s) completed${s ? `, in flight: ${s.planned.op.kind} ${Le(s.planned.op)}` : ""}`).pipe(b.annotateLogs({ scope: "voltro:migrate" })), o.every((e) => e.status === "pending")) return {
|
|
2775
2775
|
kind: "discard",
|
|
2776
2776
|
runId: a,
|
|
2777
2777
|
why: "no operation had started — no DDL ran"
|
|
2778
2778
|
};
|
|
2779
|
-
let l = s ? yield*
|
|
2779
|
+
let l = s ? yield* hi(e, t, s.planned) : "clean", u = r[0].planFingerprint;
|
|
2780
2780
|
if (u !== n.toFingerprint) return {
|
|
2781
2781
|
kind: "discard",
|
|
2782
2782
|
runId: a,
|
|
@@ -2787,7 +2787,7 @@ BEGIN
|
|
|
2787
2787
|
kind: "discard",
|
|
2788
2788
|
runId: a,
|
|
2789
2789
|
why: "every recorded operation had already taken effect"
|
|
2790
|
-
} : (yield*
|
|
2790
|
+
} : (yield* pi(e, a, f.map((e) => e.index), p.map((e) => e.index)), yield* b.logWarning(`migration resume: continuing run ${a} — replaying ${f.length} operation(s), ${o.length - f.length} already applied`).pipe(b.annotateLogs({ scope: "voltro:migrate" })), {
|
|
2791
2791
|
kind: "resume",
|
|
2792
2792
|
runId: a,
|
|
2793
2793
|
ops: f.map((e) => ({
|
|
@@ -2795,39 +2795,39 @@ BEGIN
|
|
|
2795
2795
|
planned: e.planned
|
|
2796
2796
|
}))
|
|
2797
2797
|
});
|
|
2798
|
-
}),
|
|
2798
|
+
}), vi = (e, t, n) => b.gen(function* () {
|
|
2799
2799
|
let r = t.operations.filter((e) => e.blocked);
|
|
2800
2800
|
if (r.length > 0) return yield* b.die(/* @__PURE__ */ Error(`applyPlan: refusing to execute — ${r.length} blocked operations. Run \`voltro db plan\` to see the fixes.`));
|
|
2801
|
-
yield*
|
|
2801
|
+
yield* E(e, { schema: n.lockSchema });
|
|
2802
2802
|
let i = Date.now(), a = [], o = Me(e), s = Pe(o) === "plan-transactional", l = s ? t.operations.filter((e) => e.classification !== "online-required") : [], u = s ? t.operations.filter((e) => e.classification === "online-required") : t.operations, d = `plan_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`, f = u.map((e, t) => ({
|
|
2803
2803
|
index: t,
|
|
2804
2804
|
planned: e
|
|
2805
2805
|
})), p = "fresh";
|
|
2806
2806
|
try {
|
|
2807
|
-
yield*
|
|
2808
|
-
let r = yield*
|
|
2807
|
+
yield* li(e, o);
|
|
2808
|
+
let r = yield* ui(e);
|
|
2809
2809
|
if (r.length > 0) {
|
|
2810
|
-
let n = yield*
|
|
2811
|
-
n.kind === "resume" ? (d = n.runId, f = n.ops, p = "resume") : (yield* b.logWarning(`migration resume: discarding the ledger of run ${n.runId} — ${n.why}`).pipe(b.annotateLogs({ scope: "voltro:migrate" })), yield*
|
|
2810
|
+
let n = yield* _i(e, o, t, r);
|
|
2811
|
+
n.kind === "resume" ? (d = n.runId, f = n.ops, p = "resume") : (yield* b.logWarning(`migration resume: discarding the ledger of run ${n.runId} — ${n.why}`).pipe(b.annotateLogs({ scope: "voltro:migrate" })), yield* mi(e, n.runId));
|
|
2812
2812
|
}
|
|
2813
|
-
p === "fresh" && f.length > 0 && (yield*
|
|
2813
|
+
p === "fresh" && f.length > 0 && (yield* di(e, d, t.toFingerprint, f)), l.length > 0 && (yield* e.withTransaction(b.gen(function* () {
|
|
2814
2814
|
let e = yield* C.SqlClient;
|
|
2815
|
-
for (let t of l) a.push(yield*
|
|
2815
|
+
for (let t of l) a.push(yield* gi(e, t, n));
|
|
2816
2816
|
})));
|
|
2817
2817
|
for (let { index: t, planned: r } of f) {
|
|
2818
|
-
yield*
|
|
2819
|
-
let i = yield*
|
|
2820
|
-
a.push(i), yield*
|
|
2818
|
+
yield* fi(e, d, t, "started");
|
|
2819
|
+
let i = yield* gi(e, r, n, p);
|
|
2820
|
+
a.push(i), yield* fi(e, d, t, "applied", i.durationMs);
|
|
2821
2821
|
}
|
|
2822
2822
|
} finally {
|
|
2823
|
-
yield*
|
|
2823
|
+
yield* D(e, { schema: n.lockSchema }).pipe(b.orDie);
|
|
2824
2824
|
}
|
|
2825
2825
|
let m = yield* n.replan(e);
|
|
2826
2826
|
if (m.operations.length > 0) {
|
|
2827
2827
|
let e = m.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");
|
|
2828
2828
|
return yield* b.die(/* @__PURE__ */ Error(`applyPlan: the migration did not converge. ${t.operations.length} operation(s) were executed without error, but re-planning against the live schema still finds ${m.operations.length}:\n${e}${m.operations.length > 10 ? `\n … and ${m.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.`));
|
|
2829
2829
|
}
|
|
2830
|
-
let h = a.filter((e) => e.status === "applied").length, g = Date.now() - i, _ = d, v = (/* @__PURE__ */ new Date()).toISOString(), y = yield*
|
|
2830
|
+
let h = a.filter((e) => e.status === "applied").length, g = Date.now() - i, _ = d, v = (/* @__PURE__ */ new Date()).toISOString(), y = yield* U(e, v), x = [...l, ...f.map((e) => e.planned)];
|
|
2831
2831
|
yield* e`
|
|
2832
2832
|
INSERT INTO ${e("_voltro_migration_plans")}
|
|
2833
2833
|
(${e("id")}, ${e("fingerprint")}, ${e("liveFingerprint")}, ${e("operations")},
|
|
@@ -2837,7 +2837,7 @@ BEGIN
|
|
|
2837
2837
|
(${_}, ${t.toFingerprint}, ${m.fromFingerprint}, ${JSON.stringify(x)},
|
|
2838
2838
|
${n.appliedBy}, ${n.environment}, ${n.source},
|
|
2839
2839
|
${g}, ${y}, ${n.notes ?? null})
|
|
2840
|
-
`, yield*
|
|
2840
|
+
`, yield* mi(e, d);
|
|
2841
2841
|
let S = [...new Set(x.flatMap((e) => e.op.kind === "rename-table" ? [e.op.to] : [e.op.table]))];
|
|
2842
2842
|
return yield* b.promise(() => c({ changedTables: S }).catch(() => {})), {
|
|
2843
2843
|
id: _,
|
|
@@ -2851,14 +2851,14 @@ BEGIN
|
|
|
2851
2851
|
source: n.source,
|
|
2852
2852
|
...n.notes ? { notes: n.notes } : {}
|
|
2853
2853
|
};
|
|
2854
|
-
}),
|
|
2854
|
+
}), yi = (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"), bi = (e) => e`
|
|
2855
2855
|
SELECT fingerprint
|
|
2856
2856
|
FROM _voltro_migration_plans
|
|
2857
2857
|
ORDER BY ${e("appliedAt")} DESC
|
|
2858
2858
|
LIMIT 1
|
|
2859
|
-
`.pipe(b.map((e) => e.length > 0 ? e[0].fingerprint : void 0), b.catchAll(() => b.succeed(void 0))),
|
|
2860
|
-
if ((yield*
|
|
2861
|
-
let r = `plan_${Date.now().toString(36)}`, i = yield*
|
|
2859
|
+
`.pipe(b.map((e) => e.length > 0 ? e[0].fingerprint : void 0), b.catchAll(() => b.succeed(void 0))), xi = (e, t, n) => b.gen(function* () {
|
|
2860
|
+
if ((yield* bi(e)) === t.toFingerprint) return "already-current";
|
|
2861
|
+
let r = `plan_${Date.now().toString(36)}`, i = yield* U(e, (/* @__PURE__ */ new Date()).toISOString());
|
|
2862
2862
|
return yield* e`
|
|
2863
2863
|
INSERT INTO ${e("_voltro_migration_plans")}
|
|
2864
2864
|
(${e("id")}, ${e("fingerprint")}, ${e("liveFingerprint")}, ${e("operations")},
|
|
@@ -2869,8 +2869,8 @@ BEGIN
|
|
|
2869
2869
|
${n.appliedBy}, ${n.environment}, ${n.source},
|
|
2870
2870
|
${0}, ${i}, ${"no DDL — the declared schema already matched the database"})
|
|
2871
2871
|
`, "recorded";
|
|
2872
|
-
}).pipe(b.catchAll(() => b.succeed("already-current"))),
|
|
2873
|
-
let n =
|
|
2872
|
+
}).pipe(b.catchAll(() => b.succeed("already-current"))), Si = (e, t) => b.gen(function* () {
|
|
2873
|
+
let n = P(I(t, Me(e))), r = yield* bi(e);
|
|
2874
2874
|
return r === n ? {
|
|
2875
2875
|
kind: "up-to-date",
|
|
2876
2876
|
fingerprint: n
|
|
@@ -2879,23 +2879,23 @@ BEGIN
|
|
|
2879
2879
|
expected: n,
|
|
2880
2880
|
...r === void 0 ? {} : { actual: r }
|
|
2881
2881
|
};
|
|
2882
|
-
}),
|
|
2882
|
+
}), Ci = [
|
|
2883
2883
|
"pgeagertest_",
|
|
2884
2884
|
"mig_e2e_",
|
|
2885
2885
|
"mig_test_",
|
|
2886
2886
|
"mysqleagertest_",
|
|
2887
2887
|
"mssqleagertest_",
|
|
2888
2888
|
"sqliteeagertest_"
|
|
2889
|
-
],
|
|
2889
|
+
], wi = (e) => Ci.some((t) => e.startsWith(t)), Ti = (e, t) => b.gen(function* () {
|
|
2890
2890
|
if (process.env.VOLTRO_TEST_FIXTURE_GC === "off") return [];
|
|
2891
|
-
let n = t.filter((e) =>
|
|
2891
|
+
let n = t.filter((e) => wi(e.name)).map((e) => e.name);
|
|
2892
2892
|
if (n.length === 0) return [];
|
|
2893
2893
|
for (let t of n) yield* e.unsafe(`DROP TABLE IF EXISTS "${t}" CASCADE`).pipe(b.catchAll(() => b.void));
|
|
2894
2894
|
return n;
|
|
2895
|
-
}),
|
|
2895
|
+
}), Ei = () => {
|
|
2896
2896
|
let e = (process.env.VOLTRO_DB_IGNORE_TABLES ?? "").split(",").map((e) => e.trim()).filter((e) => e.length > 0);
|
|
2897
2897
|
return e.length > 0 ? { ignoreTables: e } : {};
|
|
2898
|
-
},
|
|
2898
|
+
}, Di = (e) => {
|
|
2899
2899
|
if (e === void 0) return;
|
|
2900
2900
|
let t = e.trim();
|
|
2901
2901
|
if (t === "") return;
|
|
@@ -2905,30 +2905,30 @@ BEGIN
|
|
|
2905
2905
|
kind: "tables",
|
|
2906
2906
|
tables: new Set(n)
|
|
2907
2907
|
} : void 0;
|
|
2908
|
-
},
|
|
2908
|
+
}, Oi = (e) => typeof e.table == "string" ? e.table : void 0, ki = (e, t = { kind: "all" }) => ({
|
|
2909
2909
|
...e,
|
|
2910
2910
|
operations: e.operations.map((e) => {
|
|
2911
2911
|
if (!e.blocked || e.classification !== "lossy") return e;
|
|
2912
2912
|
if (t?.kind === "tables") {
|
|
2913
|
-
let n =
|
|
2913
|
+
let n = Oi(e.op);
|
|
2914
2914
|
if (n === void 0 || !t.tables.has(n)) return e;
|
|
2915
2915
|
}
|
|
2916
2916
|
let { blocked: n, ...r } = e;
|
|
2917
2917
|
return r;
|
|
2918
2918
|
})
|
|
2919
|
-
}),
|
|
2919
|
+
}), Ai = (e, t, n) => t === "postgres" ? qt(e, n).pipe(b.flatMap((e) => {
|
|
2920
2920
|
let t = Jt(e);
|
|
2921
2921
|
return t === void 0 ? b.void : b.logWarning(`auto-migrate: ${t}`).pipe(b.annotateLogs({ scope: "voltro:migrate" }));
|
|
2922
|
-
}), b.catchAll(() => b.void)) : b.void,
|
|
2922
|
+
}), b.catchAll(() => b.void)) : b.void, ji = (e, t, n) => b.gen(function* () {
|
|
2923
2923
|
let r = Me(e), i = t;
|
|
2924
2924
|
if (process.env.VOLTRO_MIGRATE_FORCE !== "1") {
|
|
2925
|
-
let t =
|
|
2926
|
-
if ((yield*
|
|
2925
|
+
let t = P(I(i, r));
|
|
2926
|
+
if ((yield* bi(e)) === t) return yield* Ai(e, r, i), {
|
|
2927
2927
|
kind: "up-to-date",
|
|
2928
2928
|
fingerprint: t
|
|
2929
2929
|
};
|
|
2930
2930
|
}
|
|
2931
|
-
let a = yield* Jn(e), o = yield*
|
|
2931
|
+
let a = yield* Jn(e), o = yield* Ti(e, a.tables);
|
|
2932
2932
|
o.length > 0 && (yield* b.logInfo(`auto-migrate: reaped ${o.length} test-fixture leftover(s)`).pipe(b.annotateLogs({
|
|
2933
2933
|
scope: "voltro:migrate",
|
|
2934
2934
|
count: o.length
|
|
@@ -2937,16 +2937,16 @@ BEGIN
|
|
|
2937
2937
|
declared: i,
|
|
2938
2938
|
live: { tables: c(a.tables) },
|
|
2939
2939
|
dialect: r,
|
|
2940
|
-
...
|
|
2940
|
+
...Ei()
|
|
2941
2941
|
});
|
|
2942
2942
|
if (l.summary.blocked > 0) {
|
|
2943
|
-
let e = l.operations.filter((e) => e.blocked).every((e) => e.classification === "lossy"), t =
|
|
2944
|
-
if (t === void 0 || !e || (l =
|
|
2943
|
+
let e = l.operations.filter((e) => e.blocked).every((e) => e.classification === "lossy"), t = Di(process.env.VOLTRO_DESTRUCTIVE_OK);
|
|
2944
|
+
if (t === void 0 || !e || (l = ki(l, t), l.operations.some((e) => e.blocked))) return {
|
|
2945
2945
|
kind: "refused-blocked",
|
|
2946
2946
|
plan: l
|
|
2947
2947
|
};
|
|
2948
2948
|
}
|
|
2949
|
-
return l.operations.length === 0 ? (yield*
|
|
2949
|
+
return l.operations.length === 0 ? (yield* xi(e, l, {
|
|
2950
2950
|
appliedBy: n.appliedBy,
|
|
2951
2951
|
environment: n.environment === "prod" ? "dev" : n.environment,
|
|
2952
2952
|
source: "auto-diff"
|
|
@@ -2955,7 +2955,7 @@ BEGIN
|
|
|
2955
2955
|
fingerprint: l.toFingerprint
|
|
2956
2956
|
}) : {
|
|
2957
2957
|
kind: "applied",
|
|
2958
|
-
applied: yield*
|
|
2958
|
+
applied: yield* vi(e, l, {
|
|
2959
2959
|
declared: t,
|
|
2960
2960
|
appliedBy: n.appliedBy,
|
|
2961
2961
|
environment: n.environment === "prod" ? "dev" : n.environment,
|
|
@@ -2966,26 +2966,26 @@ BEGIN
|
|
|
2966
2966
|
declared: i,
|
|
2967
2967
|
live: { tables: c(t.tables) },
|
|
2968
2968
|
dialect: r,
|
|
2969
|
-
...
|
|
2969
|
+
...Ei()
|
|
2970
2970
|
});
|
|
2971
2971
|
})
|
|
2972
2972
|
}),
|
|
2973
2973
|
plan: l
|
|
2974
2974
|
};
|
|
2975
|
-
}),
|
|
2975
|
+
}), Mi = (e, t, n) => process.env.VOLTRO_AUTO_MIGRATE === "0" ? b.succeed({
|
|
2976
2976
|
kind: "skipped",
|
|
2977
2977
|
reason: "VOLTRO_AUTO_MIGRATE=0"
|
|
2978
|
-
}) : n.environment === "prod" ?
|
|
2978
|
+
}) : n.environment === "prod" ? Si(e, t) : ji(e, t, n), Ni = (e, t) => {
|
|
2979
2979
|
switch (e.kind) {
|
|
2980
2980
|
case "skipped": return `auto-migrate: skipped (${e.reason})`;
|
|
2981
|
-
case "up-to-date": return `auto-migrate: schema up to date (${t}, fingerprint=${
|
|
2981
|
+
case "up-to-date": return `auto-migrate: schema up to date (${t}, fingerprint=${F(e.fingerprint)})`;
|
|
2982
2982
|
case "applied": {
|
|
2983
2983
|
let t = e.plan.summary;
|
|
2984
|
-
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=${
|
|
2984
|
+
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=${F(e.applied.fingerprint)}`;
|
|
2985
2985
|
}
|
|
2986
|
-
case "prod-mismatch": return `auto-migrate: SCHEMA FINGERPRINT MISMATCH — declared=${
|
|
2986
|
+
case "prod-mismatch": return `auto-migrate: SCHEMA FINGERPRINT MISMATCH — declared=${F(e.expected)}` + (e.actual ? ` live=${F(e.actual)}` : " live=<no _voltro_migration_plans row>") + ". Run `voltro db apply --plan plan.json` from the deploy pipeline before serving.";
|
|
2987
2987
|
case "refused-blocked": {
|
|
2988
|
-
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` +
|
|
2988
|
+
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` + yi(e.plan), c = [""];
|
|
2989
2989
|
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) {
|
|
2990
2990
|
let t = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map();
|
|
2991
2991
|
for (let r of e.plan.operations) {
|
|
@@ -3002,7 +3002,7 @@ BEGIN
|
|
|
3002
3002
|
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");
|
|
3003
3003
|
}
|
|
3004
3004
|
}
|
|
3005
|
-
},
|
|
3005
|
+
}, Pi = /* @__PURE__ */ new Set([
|
|
3006
3006
|
"node_modules",
|
|
3007
3007
|
"dist",
|
|
3008
3008
|
"build",
|
|
@@ -3011,11 +3011,11 @@ BEGIN
|
|
|
3011
3011
|
".next",
|
|
3012
3012
|
".git",
|
|
3013
3013
|
".framework"
|
|
3014
|
-
]),
|
|
3014
|
+
]), Fi = async (e) => {
|
|
3015
3015
|
let t = [], n = async (e) => {
|
|
3016
3016
|
let r = await te.readdir(e, { withFileTypes: !0 }).catch(() => []);
|
|
3017
3017
|
for (let i of r) {
|
|
3018
|
-
if (
|
|
3018
|
+
if (Pi.has(i.name)) continue;
|
|
3019
3019
|
let r = ne(e, i.name);
|
|
3020
3020
|
i.isDirectory() ? await n(r) : i.isFile() && u.test(i.name) && t.push(r);
|
|
3021
3021
|
}
|
|
@@ -3024,7 +3024,7 @@ BEGIN
|
|
|
3024
3024
|
let n = e.split("/").pop() ?? e, r = t.split("/").pop() ?? t;
|
|
3025
3025
|
return n.localeCompare(r);
|
|
3026
3026
|
});
|
|
3027
|
-
},
|
|
3027
|
+
}, Ii = async (e) => {
|
|
3028
3028
|
let t = [];
|
|
3029
3029
|
for (let n of e) {
|
|
3030
3030
|
let e = (await import(re(n).href)).default;
|
|
@@ -3038,11 +3038,11 @@ BEGIN
|
|
|
3038
3038
|
});
|
|
3039
3039
|
}
|
|
3040
3040
|
return t;
|
|
3041
|
-
},
|
|
3041
|
+
}, Li = (e) => e`
|
|
3042
3042
|
SELECT ${e("id")}
|
|
3043
3043
|
FROM ${e("_voltro_migration_plans")}
|
|
3044
3044
|
WHERE ${e("source")} = 'file'
|
|
3045
|
-
`.pipe(b.map((e) => e.map((e) => e.id)), b.catchAll(() => b.succeed([]))),
|
|
3045
|
+
`.pipe(b.map((e) => e.map((e) => e.id)), b.catchAll(() => b.succeed([]))), Ri = class extends Error {
|
|
3046
3046
|
migrationId;
|
|
3047
3047
|
file;
|
|
3048
3048
|
cause;
|
|
@@ -3050,7 +3050,7 @@ BEGIN
|
|
|
3050
3050
|
constructor(e, t, n) {
|
|
3051
3051
|
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";
|
|
3052
3052
|
}
|
|
3053
|
-
},
|
|
3053
|
+
}, zi = (e, t, n, r) => b.gen(function* () {
|
|
3054
3054
|
let i = Date.now(), a = (/* @__PURE__ */ new Date()).toISOString(), o = {
|
|
3055
3055
|
sql: e,
|
|
3056
3056
|
log: {
|
|
@@ -3071,7 +3071,7 @@ BEGIN
|
|
|
3071
3071
|
});
|
|
3072
3072
|
let c = Date.now() - i;
|
|
3073
3073
|
!b.isEffect(s) && c < 2 && (yield* b.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(b.annotateLogs({ scope: `migrations:file:${t.migration.id}` })));
|
|
3074
|
-
let l = yield*
|
|
3074
|
+
let l = yield* U(e, a);
|
|
3075
3075
|
return yield* e`
|
|
3076
3076
|
INSERT INTO ${e("_voltro_migration_plans")}
|
|
3077
3077
|
(${e("id")}, ${e("fingerprint")}, ${e("operations")},
|
|
@@ -3084,10 +3084,10 @@ BEGIN
|
|
|
3084
3084
|
}])},
|
|
3085
3085
|
${r}, ${n}, ${"file"},
|
|
3086
3086
|
${c}, ${l}, ${t.migration.description})
|
|
3087
|
-
`.pipe(b.mapError((e) => new
|
|
3088
|
-
}),
|
|
3087
|
+
`.pipe(b.mapError((e) => new Ri(t.migration.id, t.file, e))), { durationMs: c };
|
|
3088
|
+
}), Bi = (e, t) => b.gen(function* () {
|
|
3089
3089
|
let n = yield* b.tryPromise({
|
|
3090
|
-
try: () =>
|
|
3090
|
+
try: () => Fi(ne(t, "migrations")),
|
|
3091
3091
|
catch: (e) => e
|
|
3092
3092
|
});
|
|
3093
3093
|
if (n.length === 0) return {
|
|
@@ -3095,25 +3095,25 @@ BEGIN
|
|
|
3095
3095
|
skipped: []
|
|
3096
3096
|
};
|
|
3097
3097
|
let r = yield* b.tryPromise({
|
|
3098
|
-
try: () =>
|
|
3098
|
+
try: () => Ii(n),
|
|
3099
3099
|
catch: (e) => e
|
|
3100
3100
|
});
|
|
3101
3101
|
if (r.length === 0) return {
|
|
3102
3102
|
pending: [],
|
|
3103
3103
|
skipped: []
|
|
3104
3104
|
};
|
|
3105
|
-
let i = new Set(yield*
|
|
3105
|
+
let i = new Set(yield* Li(e));
|
|
3106
3106
|
return {
|
|
3107
3107
|
pending: r.filter((e) => !i.has(e.migration.id)),
|
|
3108
3108
|
skipped: r.filter((e) => i.has(e.migration.id)).map((e) => e.migration.id)
|
|
3109
3109
|
};
|
|
3110
|
-
}),
|
|
3111
|
-
let { pending: n, skipped: r } = yield*
|
|
3110
|
+
}), Vi = (e, t) => Bi(e, t).pipe(b.map((e) => e.pending.map((e) => e.migration.id))), Hi = (e, t) => b.gen(function* () {
|
|
3111
|
+
let { pending: n, skipped: r } = yield* Bi(e, t.projectRoot);
|
|
3112
3112
|
if (n.length === 0) return {
|
|
3113
3113
|
applied: [],
|
|
3114
3114
|
skipped: r
|
|
3115
3115
|
};
|
|
3116
|
-
yield*
|
|
3116
|
+
yield* E(e, { schema: t.lockSchema });
|
|
3117
3117
|
let i = [];
|
|
3118
3118
|
try {
|
|
3119
3119
|
for (let r of n) {
|
|
@@ -3122,7 +3122,7 @@ BEGIN
|
|
|
3122
3122
|
id: r.migration.id,
|
|
3123
3123
|
file: r.file
|
|
3124
3124
|
}));
|
|
3125
|
-
let { durationMs: n } = yield*
|
|
3125
|
+
let { durationMs: n } = yield* zi(e, r, t.env, t.appliedBy);
|
|
3126
3126
|
i.push({
|
|
3127
3127
|
id: r.migration.id,
|
|
3128
3128
|
durationMs: n
|
|
@@ -3133,28 +3133,28 @@ BEGIN
|
|
|
3133
3133
|
}));
|
|
3134
3134
|
}
|
|
3135
3135
|
} finally {
|
|
3136
|
-
yield*
|
|
3136
|
+
yield* D(e, { schema: t.lockSchema }).pipe(b.orDie);
|
|
3137
3137
|
}
|
|
3138
3138
|
return {
|
|
3139
3139
|
applied: i,
|
|
3140
3140
|
skipped: r
|
|
3141
3141
|
};
|
|
3142
|
-
}),
|
|
3142
|
+
}), Ui = (e, t) => e`
|
|
3143
3143
|
SELECT ${e("id")}
|
|
3144
3144
|
FROM ${e("_voltro_migration_plans")}
|
|
3145
3145
|
WHERE ${e("id")} = ${t} AND ${e("source")} = 'file'
|
|
3146
3146
|
LIMIT 1
|
|
3147
|
-
`,
|
|
3148
|
-
if (!(yield*
|
|
3147
|
+
`, Wi = (e, t) => b.gen(function* () {
|
|
3148
|
+
if (!(yield* Ui(e, t.id))[0]) return yield* b.fail(/* @__PURE__ */ Error(`rollback: ${t.id} not found in _voltro_migration_plans (file source)`));
|
|
3149
3149
|
let n = yield* b.tryPromise({
|
|
3150
|
-
try: () =>
|
|
3150
|
+
try: () => Fi(ne(t.projectRoot, "migrations")),
|
|
3151
3151
|
catch: (e) => e
|
|
3152
3152
|
}), r = (yield* b.tryPromise({
|
|
3153
|
-
try: () =>
|
|
3153
|
+
try: () => Ii(n),
|
|
3154
3154
|
catch: (e) => e
|
|
3155
3155
|
})).find((e) => e.migration.id === t.id);
|
|
3156
3156
|
if (!r) return yield* b.fail(/* @__PURE__ */ Error(`rollback: file for migration ${t.id} not found on disk under ${t.projectRoot}/migrations/`));
|
|
3157
|
-
yield*
|
|
3157
|
+
yield* E(e, { schema: t.lockSchema });
|
|
3158
3158
|
let i = Date.now();
|
|
3159
3159
|
try {
|
|
3160
3160
|
let n = {
|
|
@@ -3181,9 +3181,9 @@ BEGIN
|
|
|
3181
3181
|
durationMs: o
|
|
3182
3182
|
};
|
|
3183
3183
|
} finally {
|
|
3184
|
-
yield*
|
|
3184
|
+
yield* D(e, { schema: t.lockSchema }).pipe(b.orDie);
|
|
3185
3185
|
}
|
|
3186
|
-
}),
|
|
3186
|
+
}), Gi = (e) => b.gen(function* () {
|
|
3187
3187
|
let t = yield* C.SqlClient, n = yield* t`
|
|
3188
3188
|
SELECT id, fingerprint, appliedAt FROM _voltro_migration_plans
|
|
3189
3189
|
WHERE source = 'auto-diff'
|
|
@@ -3228,7 +3228,7 @@ BEGIN
|
|
|
3228
3228
|
snapshotFingerprint: e.fingerprint,
|
|
3229
3229
|
snapshotId: i
|
|
3230
3230
|
};
|
|
3231
|
-
}),
|
|
3231
|
+
}), Ki = { safe: !0 }, qi = (e) => {
|
|
3232
3232
|
switch (e.kind) {
|
|
3233
3233
|
case "drop-column": return {
|
|
3234
3234
|
safe: !1,
|
|
@@ -3255,7 +3255,7 @@ BEGIN
|
|
|
3255
3255
|
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`,
|
|
3256
3256
|
remedy: "add a new column of the target type + backfill + dual-write, cut code over, then drop the old column in a LATER deploy"
|
|
3257
3257
|
};
|
|
3258
|
-
case "alter-column-nullability": return e.toNullable ?
|
|
3258
|
+
case "alter-column-nullability": return e.toNullable ? Ki : {
|
|
3259
3259
|
safe: !1,
|
|
3260
3260
|
reason: `old instances may INSERT "${e.table}" without (or with NULL in) "${e.column}", which the new NOT NULL rejects`,
|
|
3261
3261
|
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)`
|
|
@@ -3285,12 +3285,12 @@ BEGIN
|
|
|
3285
3285
|
case "drop-unique":
|
|
3286
3286
|
case "drop-unique-composite":
|
|
3287
3287
|
case "drop-foreign-key":
|
|
3288
|
-
case "drop-check": return
|
|
3288
|
+
case "drop-check": return Ki;
|
|
3289
3289
|
}
|
|
3290
|
-
},
|
|
3290
|
+
}, Ji = (e) => {
|
|
3291
3291
|
let t = [];
|
|
3292
3292
|
for (let n of e) {
|
|
3293
|
-
let e =
|
|
3293
|
+
let e = qi(n.op);
|
|
3294
3294
|
e.safe || t.push({
|
|
3295
3295
|
op: n,
|
|
3296
3296
|
reason: e.reason,
|
|
@@ -3298,7 +3298,7 @@ BEGIN
|
|
|
3298
3298
|
});
|
|
3299
3299
|
}
|
|
3300
3300
|
return t;
|
|
3301
|
-
},
|
|
3301
|
+
}, Yi = (e) => {
|
|
3302
3302
|
if (!e.enabled || e.unsafeCount === 0) return {
|
|
3303
3303
|
refuse: !1,
|
|
3304
3304
|
warnForced: !1,
|
|
@@ -3314,18 +3314,18 @@ BEGIN
|
|
|
3314
3314
|
warnForced: !1,
|
|
3315
3315
|
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.`
|
|
3316
3316
|
};
|
|
3317
|
-
},
|
|
3317
|
+
}, Xi = (e) => {
|
|
3318
3318
|
let t = e.table;
|
|
3319
3319
|
if (typeof t == "string") return t;
|
|
3320
3320
|
let n = e.from;
|
|
3321
3321
|
return typeof n == "string" ? n : void 0;
|
|
3322
|
-
},
|
|
3322
|
+
}, Zi = (e) => ({
|
|
3323
3323
|
kind: e.op.kind,
|
|
3324
|
-
table:
|
|
3324
|
+
table: Xi(e.op),
|
|
3325
3325
|
classification: e.classification,
|
|
3326
3326
|
reason: e.reason,
|
|
3327
3327
|
blockedFix: e.blocked?.fix
|
|
3328
|
-
}),
|
|
3328
|
+
}), Qi = (e) => e.operations.map(Zi), $i = async (e) => {
|
|
3329
3329
|
let t = e.log ?? (() => {}), n = {
|
|
3330
3330
|
branchId: e.branchId,
|
|
3331
3331
|
mechanism: e.mechanism,
|
|
@@ -3344,10 +3344,10 @@ BEGIN
|
|
|
3344
3344
|
applied: !1,
|
|
3345
3345
|
converged: !1,
|
|
3346
3346
|
residual: r,
|
|
3347
|
-
infidelity:
|
|
3347
|
+
infidelity: Qi(o)
|
|
3348
3348
|
};
|
|
3349
3349
|
else {
|
|
3350
|
-
let i = await e.plan(), o =
|
|
3350
|
+
let i = await e.plan(), o = Qi(i), s = o.filter((e) => e.classification === "lossy"), c = ki(i), l = c.operations.filter((e) => e.blocked !== void 0).map(Zi);
|
|
3351
3351
|
if (l.length > 0) a = {
|
|
3352
3352
|
...n,
|
|
3353
3353
|
outcome: "blocked",
|
|
@@ -3372,7 +3372,7 @@ BEGIN
|
|
|
3372
3372
|
};
|
|
3373
3373
|
else {
|
|
3374
3374
|
await e.apply(c), t(`branch ${e.branchId}: applied ${o.length} operation(s)`);
|
|
3375
|
-
let i =
|
|
3375
|
+
let i = Qi(await e.replan());
|
|
3376
3376
|
a = {
|
|
3377
3377
|
...n,
|
|
3378
3378
|
outcome: i.length > 0 ? "diverged" : s.length > 0 ? "lossy" : "clean",
|
|
@@ -3410,7 +3410,7 @@ BEGIN
|
|
|
3410
3410
|
...a,
|
|
3411
3411
|
tornDown: o
|
|
3412
3412
|
};
|
|
3413
|
-
},
|
|
3413
|
+
}, ea = (e) => {
|
|
3414
3414
|
switch (e.outcome) {
|
|
3415
3415
|
case "clean": return 0;
|
|
3416
3416
|
case "lossy": return 2;
|
|
@@ -3419,22 +3419,22 @@ BEGIN
|
|
|
3419
3419
|
case "infidelity": return 1;
|
|
3420
3420
|
case "failed": return 1;
|
|
3421
3421
|
}
|
|
3422
|
-
},
|
|
3422
|
+
}, ta = (e) => ` ${e.classification === "lossy" ? "✗" : "•"} ${e.kind}${e.table ? ` ${e.table}` : ""} [${e.classification}]${e.reason ? ` — ${e.reason}` : ""}${e.blockedFix ? `\n ! ${e.blockedFix}` : ""}`, na = (e) => {
|
|
3423
3423
|
let t = [];
|
|
3424
3424
|
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"}`);
|
|
3425
3425
|
else if (e.outcome === "infidelity") {
|
|
3426
3426
|
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:");
|
|
3427
|
-
for (let n of e.infidelity) t.push(
|
|
3427
|
+
for (let n of e.infidelity) t.push(ta(n));
|
|
3428
3428
|
} else {
|
|
3429
3429
|
t.push(` plan: ${e.operations.length} operation(s), ${e.lossy.length} lossy, ${e.blocked.length} refused`);
|
|
3430
|
-
for (let n of e.operations) t.push(
|
|
3431
|
-
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(
|
|
3430
|
+
for (let n of e.operations) t.push(ta(n));
|
|
3431
|
+
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(ta(n));
|
|
3432
3432
|
}
|
|
3433
3433
|
return t.push(e.tornDown ? ` branch ${e.branchId} torn down.` : ` branch ${e.branchId} KEPT — drop it when you are done.`), t.join("\n");
|
|
3434
|
-
},
|
|
3434
|
+
}, ra = (e, ...t) => ({
|
|
3435
3435
|
_tag: "RawSqlFragment",
|
|
3436
3436
|
strings: [...e],
|
|
3437
3437
|
values: [...t]
|
|
3438
|
-
}),
|
|
3438
|
+
}), ia = (e) => typeof e == "object" && !!e && e._tag === "RawSqlFragment";
|
|
3439
3439
|
//#endregion
|
|
3440
|
-
export {
|
|
3440
|
+
export { k as DEFAULT_CDC_CHANNEL, u as FILE_MIGRATION_PATTERN, Ri as FileMigrationLedgerError, Ke as REACTIVE_TRIGGER_PREFIX, fe as VOLTRO_MIGRATION_LOCK_KEY, E as acquireMigrationLock, U as appliedAtValue, Ft as applyNamespacedSchema, vi as applyPlan, Tt as applySchema, Yi as assessRollingDeployGate, ea as branchRehearsalExitCode, In as chunkTables, qi as classifyRollingDeploySafety, I as declaredSnapshot, Qe as defaultArrayClause, Ze as defaultClause, M as defaultJsonClause, Ni as describeOutcome, Di as destructiveScope, qt as detectReactiveTriggerDrift, Ir as emitAddIndexMysql, _r as emitCreateTableMysql, er as emitDropColumnDdl, tr as emitDropColumnDdlMysql, wt as emitFrameworkBootstrapSql, St as emitNamespaceProvisionDdl, Ct as emitNamespacedSchemaSql, xt as emitSchemaSql, P as fingerprintSchema, ve as fnv1a64, na as formatBranchRehearsal, Jt as formatReactiveTriggerDrift, Ei as ignoreTablesFromEnv, Jn as introspectSchema, o as isFileMigration, ia as isRawSqlFragment, Dt as isReRunSafeDdl, jn as mapPgType, h as migration, ye as migrationLockKeyForSchema, T as migrationLockNameForSchema, Mr as mysqlIndexPrefixFor, Je as notifyFunctionName, N as numericIdSql, An as parseEnumCheck, Vi as pendingFileMigrationIds, kn as planMigrations, It as provisionTenantNamespace, qe as reactiveTriggerName, ft as reactiveTriggerRepairSql, xi as recordUpToDate, $i as rehearseMigrationOnBranch, Zi as rehearsedOperation, D as releaseMigrationLock, gr as renderColumnMysql, dr as renderColumnPg, me as resolveMigrationLockSchema, Wi as rollbackFileBasedMigration, Ji as rollingDeployUnsafeOps, Hi as runFileBasedMigrations, Lt as runFrameworkBootstrap, Pt as runMigrate, Mi as runPlannedMigrations, F as shortFingerprint, Ut as snapshotColumn, ra as sql, j as sqlType, Gi as squashMigrationPlans, ki as unblockLossy, je as withMigrationLock };
|