@voltro/database 0.69.0 → 0.70.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 +168 -0
- package/dist/index.d.ts +71 -8
- package/dist/index.js +812 -809
- package/dist/sql.d.ts +21 -0
- package/dist/sql.js +806 -754
- package/package.json +2 -2
package/dist/sql.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { C as e, Jt as t, Ot as n, St as r, a as i, an as a, at as o, b as s, c, ct as l, d as u, f as d, h as f, i as p, it as m, lt as h, m as g, o as _, on as v, qt as y, rt as b, s as x, u as S, y as C } from "./frameworkLiveTables-CWbTSnjk.js";
|
|
2
|
-
import { Effect as w, Exit as
|
|
3
|
-
import { createHash as
|
|
4
|
-
import { createLogger as
|
|
5
|
-
import { SqlClient as
|
|
6
|
-
import { promises as
|
|
7
|
-
import { join as
|
|
8
|
-
import { pathToFileURL as
|
|
2
|
+
import { Effect as w, Exit as T, Schedule as ee, Scope as te } from "effect";
|
|
3
|
+
import { createHash as ne } from "node:crypto";
|
|
4
|
+
import { createLogger as re } from "@voltro/logger";
|
|
5
|
+
import { SqlClient as E } from "@effect/sql";
|
|
6
|
+
import { promises as ie } from "node:fs";
|
|
7
|
+
import { join as ae } from "node:path";
|
|
8
|
+
import { pathToFileURL as oe } from "node:url";
|
|
9
9
|
//#region src/migrations/ddlError.ts
|
|
10
|
-
var
|
|
10
|
+
var se = (e, t, n, r = 400) => {
|
|
11
11
|
let i = n, a = i.cause ?? {}, o = (e) => {
|
|
12
12
|
let t = a[e];
|
|
13
13
|
return t == null || t === "" ? void 0 : String(t);
|
|
@@ -38,21 +38,21 @@ var ce = (e, t, n, r = 400) => {
|
|
|
38
38
|
let t = o(e);
|
|
39
39
|
t !== void 0 && s.push(`db.${e}: ${t}`);
|
|
40
40
|
}
|
|
41
|
-
let c =
|
|
41
|
+
let c = ce(o("code"));
|
|
42
42
|
return c !== void 0 && s.push("", c), s.push(""), s.join("\n");
|
|
43
|
-
},
|
|
44
|
-
if (t !== "mysql" && t !== "mariadb" || !e.appliedIndexes.some(
|
|
43
|
+
}, ce = (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, le = (e) => e.unique === !0 && typeof e.where == "string" && e.where.length > 0, ue = (e) => e.replace(/"/g, "`"), de = (e) => typeof e == "string" ? e : e.name ?? String(e), fe = (e, t) => `_ua_${t}_${e}`.slice(0, 64), pe = (e, t) => {
|
|
44
|
+
if (t !== "mysql" && t !== "mariadb" || !e.appliedIndexes.some(le)) return e;
|
|
45
45
|
let n = { ...e.fields }, r = [], i = [];
|
|
46
46
|
for (let t of e.appliedIndexes) {
|
|
47
|
-
if (!
|
|
47
|
+
if (!le(t)) {
|
|
48
48
|
r.push(t);
|
|
49
49
|
continue;
|
|
50
50
|
}
|
|
51
|
-
let a =
|
|
51
|
+
let a = ue(t.where), o = [];
|
|
52
52
|
for (let r of t.fields) {
|
|
53
|
-
let i =
|
|
53
|
+
let i = de(r);
|
|
54
54
|
if (!(i in e.fields)) throw Error(`@voltro/migrate: uniqueActive '${t.name}' on '${e.tableName}' references unknown column '${i}'.`);
|
|
55
|
-
let s =
|
|
55
|
+
let s = fe(t.name, i);
|
|
56
56
|
o.push(s), n[s] = {
|
|
57
57
|
type: "text",
|
|
58
58
|
nullable: !0,
|
|
@@ -75,82 +75,82 @@ var ce = (e, t, n, r = 400) => {
|
|
|
75
75
|
appliedIndexes: r,
|
|
76
76
|
appliedUniques: [...e.appliedUniques ?? [], ...i]
|
|
77
77
|
};
|
|
78
|
-
},
|
|
78
|
+
}, D = (e, t) => `${e}::${t}`, me = (e, t) => {
|
|
79
79
|
let n = /* @__PURE__ */ new Set(), r = /* @__PURE__ */ new Set(), i = /* @__PURE__ */ new Set(), a = (e) => {
|
|
80
80
|
n.add(e);
|
|
81
81
|
let o = [...t(e)].filter((t) => t.target !== e).sort((e, t) => e.column.localeCompare(t.column));
|
|
82
|
-
for (let t of o) n.has(t.target) ? i.add(
|
|
82
|
+
for (let t of o) n.has(t.target) ? i.add(D(e, t.column)) : r.has(t.target) || a(t.target);
|
|
83
83
|
n.delete(e), r.add(e);
|
|
84
84
|
};
|
|
85
85
|
for (let t of [...e].sort()) r.has(t) || a(t);
|
|
86
86
|
return i;
|
|
87
|
-
},
|
|
87
|
+
}, O = (e, t) => e.executeUnprepared(t, [], void 0), he = 6322741009312437n, ge = (e) => {
|
|
88
88
|
let t = e?.trim();
|
|
89
89
|
return t === void 0 || t === "" || t === "public" ? void 0 : t;
|
|
90
|
-
},
|
|
91
|
-
let t =
|
|
92
|
-
for (let n of new TextEncoder().encode(e)) t ^= BigInt(n), t = t *
|
|
90
|
+
}, _e = (e) => e?.schema === void 0 ? ge(process.env.DB_SCHEMA) : ge(e.schema), ve = 14695981039346656037n, ye = 1099511628211n, be = 18446744073709551615n, xe = (e) => {
|
|
91
|
+
let t = ve;
|
|
92
|
+
for (let n of new TextEncoder().encode(e)) t ^= BigInt(n), t = t * ye & be;
|
|
93
93
|
return t;
|
|
94
|
+
}, Se = (e) => {
|
|
95
|
+
let t = ge(e);
|
|
96
|
+
return t === void 0 ? he : xe(`voltro_migration_lock:${t}`) & 9223372036854775807n;
|
|
94
97
|
}, Ce = (e) => {
|
|
95
|
-
let t =
|
|
96
|
-
return t === void 0 ? ge : Se(`voltro_migration_lock:${t}`) & 9223372036854775807n;
|
|
97
|
-
}, we = (e) => {
|
|
98
|
-
let t = `voltro_migration_${ge.toString(36)}`, n = _e(e);
|
|
98
|
+
let t = `voltro_migration_${he.toString(36)}`, n = ge(e);
|
|
99
99
|
if (n === void 0) return t;
|
|
100
100
|
let r = `${t}_${n}`;
|
|
101
|
-
return /^[A-Za-z0-9_]+$/.test(n) && r.length <= 64 ? r : `${t}_h${(
|
|
102
|
-
},
|
|
101
|
+
return /^[A-Za-z0-9_]+$/.test(n) && r.length <= 64 ? r : `${t}_h${(xe(`voltro_migration_lock:${n}`) & be).toString(16)}`;
|
|
102
|
+
}, we = 250, Te = () => {
|
|
103
103
|
let e = Number(process.env.VOLTRO_MIGRATION_LOCK_TIMEOUT_MS);
|
|
104
104
|
return Number.isFinite(e) && e > 0 ? e : 3e4;
|
|
105
|
-
},
|
|
106
|
-
let n =
|
|
105
|
+
}, Ee = (e, t) => w.gen(function* () {
|
|
106
|
+
let n = Te(), r = Date.now();
|
|
107
107
|
for (;;) {
|
|
108
|
-
if ((yield*
|
|
109
|
-
Date.now() - r >= n && (yield* w.die(/* @__PURE__ */ Error(`could not acquire the postgres migration advisory lock within ${Math.round(n / 1e3)}s. Another migration is in progress, or a prior boot crashed while holding it. (A crashed process's session-level advisory lock is released once its DB connection closes; if this persists, find + terminate the holder via pg_stat_activity, or raise VOLTRO_MIGRATION_LOCK_TIMEOUT_MS.)`))), yield* w.sleep(`${
|
|
108
|
+
if ((yield* O(e, `SELECT pg_try_advisory_lock(${t.toString()}::bigint) AS got`))[0]?.got) return;
|
|
109
|
+
Date.now() - r >= n && (yield* w.die(/* @__PURE__ */ Error(`could not acquire the postgres migration advisory lock within ${Math.round(n / 1e3)}s. Another migration is in progress, or a prior boot crashed while holding it. (A crashed process's session-level advisory lock is released once its DB connection closes; if this persists, find + terminate the holder via pg_stat_activity, or raise VOLTRO_MIGRATION_LOCK_TIMEOUT_MS.)`))), yield* w.sleep(`${we} millis`);
|
|
110
110
|
}
|
|
111
|
-
}),
|
|
112
|
-
(yield*
|
|
113
|
-
}),
|
|
114
|
-
let n = yield*
|
|
111
|
+
}), De = (e, t) => w.asVoid(O(e, `SELECT pg_advisory_unlock(${t.toString()}::bigint)`)), Oe = 30, ke = (e, t) => w.gen(function* () {
|
|
112
|
+
(yield* O(e, `SELECT GET_LOCK('${t}', ${String(Oe)}) AS got`))[0]?.got !== 1 && (yield* w.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${t}' within ${Oe}s (another migration is in progress, or a prior one left it held).`)));
|
|
113
|
+
}), Ae = (e, t) => w.asVoid(O(e, `SELECT RELEASE_LOCK('${t}')`)), je = 3e4, Me = (e, t) => w.gen(function* () {
|
|
114
|
+
let n = yield* O(e, `
|
|
115
115
|
DECLARE @res int;
|
|
116
116
|
EXEC @res = sp_getapplock @Resource = '${t}', @LockMode = 'Exclusive',
|
|
117
|
-
@LockOwner = 'Session', @LockTimeout = ${String(
|
|
117
|
+
@LockOwner = 'Session', @LockTimeout = ${String(je)};
|
|
118
118
|
SELECT @res AS res`);
|
|
119
119
|
(n[0]?.res ?? -999) < 0 && (yield* w.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${t}' (sp_getapplock returned ${n[0]?.res ?? "no row"}; another migration is in progress).`)));
|
|
120
|
-
}),
|
|
121
|
-
let n =
|
|
120
|
+
}), Ne = (e, t) => w.asVoid(O(e, `EXEC sp_releaseapplock @Resource = '${t}', @LockOwner = 'Session'`)), Pe = w.void, Fe = (e, t) => w.gen(function* () {
|
|
121
|
+
let n = _e(t), r = Ce(n), i = Se(n);
|
|
122
122
|
if (!e.onDialectOrElse({
|
|
123
123
|
mysql: () => !0,
|
|
124
124
|
mssql: () => !0,
|
|
125
125
|
sqlite: () => !1,
|
|
126
126
|
orElse: () => !0
|
|
127
|
-
})) return { release:
|
|
128
|
-
let a = yield*
|
|
127
|
+
})) return { release: Pe };
|
|
128
|
+
let a = yield* te.make(), o = yield* w.provideService(e.reserve, te.Scope, a), s = te.close(a, T.void);
|
|
129
129
|
return yield* e.onDialectOrElse({
|
|
130
|
+
mysql: () => ke(o, r),
|
|
131
|
+
mssql: () => Me(o, r),
|
|
132
|
+
sqlite: () => Pe,
|
|
133
|
+
orElse: () => Ee(o, i)
|
|
134
|
+
}).pipe(w.onExit((e) => T.isSuccess(e) ? w.void : s)), { release: e.onDialectOrElse({
|
|
130
135
|
mysql: () => Ae(o, r),
|
|
131
136
|
mssql: () => Ne(o, r),
|
|
132
|
-
sqlite: () =>
|
|
137
|
+
sqlite: () => Pe,
|
|
133
138
|
orElse: () => De(o, i)
|
|
134
|
-
}).pipe(w.onExit((e) => ee.isSuccess(e) ? w.void : s)), { release: e.onDialectOrElse({
|
|
135
|
-
mysql: () => je(o, r),
|
|
136
|
-
mssql: () => Pe(o, r),
|
|
137
|
-
sqlite: () => Fe,
|
|
138
|
-
orElse: () => Oe(o, i)
|
|
139
139
|
}).pipe(w.ensuring(s)) };
|
|
140
|
-
}),
|
|
140
|
+
}), Ie = (e, t, n) => w.acquireUseRelease(Fe(e, n), () => t, (e) => e.release.pipe(w.orDie)), Le = (e) => e.onDialectOrElse({
|
|
141
141
|
pg: () => "postgres",
|
|
142
142
|
mysql: () => "mysql",
|
|
143
143
|
mssql: () => "mssql",
|
|
144
144
|
sqlite: () => "sqlite",
|
|
145
145
|
orElse: () => "sqlite"
|
|
146
|
-
}),
|
|
146
|
+
}), Re = {
|
|
147
147
|
postgres: "plan-transactional",
|
|
148
148
|
mssql: "plan-transactional",
|
|
149
149
|
mysql: "per-operation",
|
|
150
150
|
mariadb: "per-operation",
|
|
151
151
|
sqlite: "per-operation",
|
|
152
152
|
turso: "per-operation"
|
|
153
|
-
},
|
|
153
|
+
}, ze = (e) => Re[e], k = "_voltro_migration_ops", Be = l(k, {
|
|
154
154
|
id: y({ prefix: "mop" }),
|
|
155
155
|
runId: a(),
|
|
156
156
|
planFingerprint: a(),
|
|
@@ -163,7 +163,7 @@ var ce = (e, t, n, r = 400) => {
|
|
|
163
163
|
appliedAt: v().nullable(),
|
|
164
164
|
durationMs: t().nullable(),
|
|
165
165
|
createdAt: v().default("now")
|
|
166
|
-
}),
|
|
166
|
+
}), Ve = (e) => {
|
|
167
167
|
switch (e.kind) {
|
|
168
168
|
case "create-table": return /* @__PURE__ */ new Set([
|
|
169
169
|
`table:${e.table}`,
|
|
@@ -190,11 +190,11 @@ var ce = (e, t, n, r = 400) => {
|
|
|
190
190
|
case "add-unique-composite":
|
|
191
191
|
case "drop-unique-composite": return /* @__PURE__ */ new Set([`unique:${e.table}.${e.name}`]);
|
|
192
192
|
}
|
|
193
|
-
},
|
|
194
|
-
let n =
|
|
195
|
-
for (let t of
|
|
193
|
+
}, He = (e) => [...Ve(e)].join(" "), Ue = (e, t) => {
|
|
194
|
+
let n = Ve(t);
|
|
195
|
+
for (let t of Ve(e)) if (n.has(t)) return !0;
|
|
196
196
|
return !1;
|
|
197
|
-
},
|
|
197
|
+
}, We = (e, t) => e.operations.some((e) => Ue(e.op, t)), Ge = "__voltro_rebuild", Ke = "__shadow", qe = "__old", Je = /* @__PURE__ */ new Set([
|
|
198
198
|
"add-unique",
|
|
199
199
|
"drop-unique",
|
|
200
200
|
"add-unique-composite",
|
|
@@ -206,21 +206,21 @@ var ce = (e, t, n, r = 400) => {
|
|
|
206
206
|
"alter-column-nullability",
|
|
207
207
|
"alter-column-type",
|
|
208
208
|
"alter-column-default"
|
|
209
|
-
]),
|
|
209
|
+
]), Ye = /* @__PURE__ */ new Set(["alter-column-default", "alter-column-nullability"]), Xe = (e, t, n) => {
|
|
210
210
|
let r = n === "sqlite" || n === "turso";
|
|
211
|
-
return e.kind === "alter-column-type" && t === "online-required" || r &&
|
|
211
|
+
return e.kind === "alter-column-type" && t === "online-required" || r && Je.has(e.kind) ? "artefact-repair" : Ye.has(e.kind) ? "idempotent" : "probe-then-replay";
|
|
212
212
|
};
|
|
213
|
-
Object.keys(
|
|
213
|
+
Object.keys(Re);
|
|
214
214
|
//#endregion
|
|
215
215
|
//#region src/migrations/reactiveTriggerName.ts
|
|
216
|
-
var
|
|
216
|
+
var A = "framework_changes", Ze = "framework_changes_", Qe = (e, t) => t === "framework_changes" ? `${Ze}${e}` : `${Ze}${t}_${e}`, $e = (e) => e === "framework_changes" ? "framework_notify_change" : `framework_notify_change_${e}`, et = "voltro:notify:v2", tt = (e, t) => {
|
|
217
217
|
if (e.type === "text" && e.generatedAs === void 0) {
|
|
218
218
|
if (e.maxLength !== void 0) return e.maxLength;
|
|
219
219
|
if (t || e.hasDefault && e.defaultFactory === void 0 || e.oneOf !== void 0 && e.oneOf.length > 0) return 450;
|
|
220
220
|
}
|
|
221
|
-
},
|
|
222
|
-
|
|
223
|
-
},
|
|
221
|
+
}, nt = re({ scope: "voltro:migrate" }), j = (e) => {
|
|
222
|
+
nt.warn(e.replace(/^\[voltro:migrate\]\s*/, ""));
|
|
223
|
+
}, M = (e, t) => {
|
|
224
224
|
let n = e.type;
|
|
225
225
|
if (e.spatial) {
|
|
226
226
|
if (t === "postgres") return `${e.spatial.kind}(${e.spatial.geomKind},${e.spatial.srid})`;
|
|
@@ -231,7 +231,7 @@ var k = "framework_changes", Qe = "framework_changes_", $e = (e, t) => t === "fr
|
|
|
231
231
|
return e.rawDdl;
|
|
232
232
|
}
|
|
233
233
|
if (n === "array" && e.arrayElement) {
|
|
234
|
-
if (t === "postgres") return `${
|
|
234
|
+
if (t === "postgres") return `${M({
|
|
235
235
|
...e,
|
|
236
236
|
type: e.arrayElement,
|
|
237
237
|
arrayElement: void 0
|
|
@@ -302,7 +302,7 @@ var k = "framework_changes", Qe = "framework_changes_", $e = (e, t) => t === "fr
|
|
|
302
302
|
if (t === "mssql") switch (n) {
|
|
303
303
|
case "id": return "NVARCHAR(64)";
|
|
304
304
|
case "text": {
|
|
305
|
-
let t =
|
|
305
|
+
let t = tt(e, !1);
|
|
306
306
|
return t === void 0 ? "NVARCHAR(MAX)" : `NVARCHAR(${t})`;
|
|
307
307
|
}
|
|
308
308
|
case "integer": return "INT";
|
|
@@ -334,22 +334,22 @@ var k = "framework_changes", Qe = "framework_changes_", $e = (e, t) => t === "fr
|
|
|
334
334
|
case "array": return "TEXT[]";
|
|
335
335
|
case "interval": return "INTERVAL";
|
|
336
336
|
}
|
|
337
|
-
},
|
|
337
|
+
}, rt = (e, t) => {
|
|
338
338
|
if (!e.hasDefault || e.defaultFactory !== void 0) return null;
|
|
339
339
|
let n = e.defaultValue;
|
|
340
|
-
return n === "now" ? m(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) ?
|
|
341
|
-
},
|
|
342
|
-
if (n !== "postgres" || t.type !== "array" || t.arrayElement === void 0) return
|
|
343
|
-
let r =
|
|
340
|
+
return n === "now" ? m(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) ? it(n, e, t) : typeof n == "object" && n ? N(n, t) : null;
|
|
341
|
+
}, it = (e, t, n) => {
|
|
342
|
+
if (n !== "postgres" || t.type !== "array" || t.arrayElement === void 0) return N(e, n);
|
|
343
|
+
let r = M({
|
|
344
344
|
...t,
|
|
345
345
|
type: t.arrayElement,
|
|
346
346
|
arrayElement: void 0
|
|
347
347
|
}, n);
|
|
348
348
|
return `DEFAULT '{${e.map((e) => typeof e == "number" || typeof e == "boolean" ? String(e) : `"${String(e).replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"`).join(",").replace(/'/g, "''")}}'::${r}[]`;
|
|
349
|
-
},
|
|
349
|
+
}, N = (e, t) => {
|
|
350
350
|
let n = JSON.stringify(e).replace(/'/g, "''");
|
|
351
351
|
return t === "postgres" ? `DEFAULT '${n}'::jsonb` : t === "mysql" || t === "mariadb" ? `DEFAULT (CONVERT('${n}' USING utf8mb4))` : `DEFAULT '${n}'`;
|
|
352
|
-
},
|
|
352
|
+
}, P = (e, t) => {
|
|
353
353
|
switch (t) {
|
|
354
354
|
case "postgres": return `"${e}" BIGSERIAL PRIMARY KEY`;
|
|
355
355
|
case "mysql":
|
|
@@ -358,7 +358,7 @@ var k = "framework_changes", Qe = "framework_changes_", $e = (e, t) => t === "fr
|
|
|
358
358
|
case "sqlite": return `"${e}" INTEGER PRIMARY KEY AUTOINCREMENT`;
|
|
359
359
|
case "turso": return `"${e}" INTEGER PRIMARY KEY`;
|
|
360
360
|
}
|
|
361
|
-
},
|
|
361
|
+
}, F = (e, t) => {
|
|
362
362
|
if (e === "restrict" && t === "mssql") return "NO ACTION";
|
|
363
363
|
switch (e) {
|
|
364
364
|
case "cascade": return "CASCADE";
|
|
@@ -366,42 +366,42 @@ var k = "framework_changes", Qe = "framework_changes_", $e = (e, t) => t === "fr
|
|
|
366
366
|
case "setNull": return "SET NULL";
|
|
367
367
|
case "noAction": return "NO ACTION";
|
|
368
368
|
}
|
|
369
|
-
},
|
|
369
|
+
}, at = (e, t, n) => n === null ? o(e, t) : `${o(n, t)}.${o(e, t)}`, ot = 191, st = (e, t) => {
|
|
370
370
|
if (!e || t !== "mysql" && t !== "mariadb") return !1;
|
|
371
|
-
let n =
|
|
371
|
+
let n = M(e, t).toUpperCase();
|
|
372
372
|
return n.endsWith("TEXT") || n.endsWith("BLOB");
|
|
373
|
-
},
|
|
373
|
+
}, ct = (e, t, n) => {
|
|
374
374
|
let r = o(e, n);
|
|
375
375
|
if (n !== "mysql" && n !== "mariadb") return r;
|
|
376
376
|
let i = t[e];
|
|
377
377
|
if (!i) return r;
|
|
378
|
-
let a =
|
|
379
|
-
return a.endsWith("TEXT") || a.endsWith("BLOB") ? `${r}(${
|
|
380
|
-
},
|
|
378
|
+
let a = M(i, n).toUpperCase();
|
|
379
|
+
return a.endsWith("TEXT") || a.endsWith("BLOB") ? `${r}(${ot})` : r;
|
|
380
|
+
}, lt = (e, t) => {
|
|
381
381
|
if (!e.generatedAs) return null;
|
|
382
382
|
let { expr: n, stored: r } = e.generatedAs;
|
|
383
|
-
if (t === "postgres") return r ||
|
|
383
|
+
if (t === "postgres") return r || j("[voltro:migrate] generated column requested as VIRTUAL but postgres only supports STORED — promoting"), `GENERATED ALWAYS AS (${n}) STORED`;
|
|
384
384
|
if (t === "mysql" || t === "mariadb") return `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
|
|
385
385
|
if (t === "mssql") return `AS (${n})${r ? " PERSISTED" : ""}`;
|
|
386
386
|
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.");
|
|
387
387
|
return `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
|
|
388
|
-
},
|
|
389
|
-
if (t.type === "id" && t.idScheme?.kind === "numeric") return
|
|
390
|
-
let s = n === "mssql" ?
|
|
388
|
+
}, ut = (e, t, n, r, i = !1, a = !1) => {
|
|
389
|
+
if (t.type === "id" && t.idScheme?.kind === "numeric") return P(e, n);
|
|
390
|
+
let s = n === "mssql" ? tt(t, r?.has(e) ?? !1) : void 0, c = s === void 0 ? M(t, n) : `NVARCHAR(${s})`, l = [o(e, n), c];
|
|
391
391
|
t.type === "id" && !a && l.push("PRIMARY KEY");
|
|
392
|
-
let u =
|
|
392
|
+
let u = lt(t, n);
|
|
393
393
|
if (u) l.push(u);
|
|
394
394
|
else {
|
|
395
|
-
t.nullable || l.push("NOT NULL"), t.unique && t.type !== "id" && !
|
|
396
|
-
let e =
|
|
395
|
+
t.nullable || l.push("NOT NULL"), t.unique && t.type !== "id" && !st(t, n) && l.push("UNIQUE");
|
|
396
|
+
let e = rt(t, n);
|
|
397
397
|
e && l.push(e);
|
|
398
398
|
}
|
|
399
399
|
if (t.type === "reference" && t.references && !i && !b(n)) {
|
|
400
400
|
let e = t.references();
|
|
401
401
|
l.push(`REFERENCES ${o(e.tableName, n)} (${o(t.referenceColumn ?? "id", n)})`);
|
|
402
|
-
let r =
|
|
402
|
+
let r = F(t.onDelete ?? "restrict", n);
|
|
403
403
|
l.push(`ON DELETE ${r}`);
|
|
404
|
-
let i =
|
|
404
|
+
let i = F(t.refOnUpdate ?? "noAction", n);
|
|
405
405
|
i !== "NO ACTION" && l.push(`ON UPDATE ${i}`);
|
|
406
406
|
}
|
|
407
407
|
if (t.oneOf && t.oneOf.length > 0) {
|
|
@@ -418,26 +418,26 @@ var k = "framework_changes", Qe = "framework_changes_", $e = (e, t) => t === "fr
|
|
|
418
418
|
m(n) ? l.push(`CHECK (${t} IS NULL OR json_valid(${t}))`) : n === "mssql" && l.push(`CHECK (${t} IS NULL OR ISJSON(${t}) = 1)`);
|
|
419
419
|
}
|
|
420
420
|
return l.join(" ");
|
|
421
|
-
},
|
|
421
|
+
}, dt = (e, t, n = null, r) => {
|
|
422
422
|
let i = /* @__PURE__ */ new Set();
|
|
423
423
|
for (let t of e.appliedIndexes ?? []) for (let e of t.fields) typeof e == "string" && i.add(e);
|
|
424
424
|
for (let t of e.appliedUniques ?? []) for (let e of t.fields) typeof e == "string" && i.add(e);
|
|
425
425
|
for (let [t, n] of Object.entries(e.fields)) n.unique && i.add(t);
|
|
426
426
|
let a = e.appliedPrimaryKey ?? [];
|
|
427
427
|
for (let e of a) i.add(e);
|
|
428
|
-
let s = a.length > 0, c = Object.entries(e.fields).map(([e, n]) => ` ${
|
|
429
|
-
let r = n.fields.map((n) =>
|
|
428
|
+
let s = a.length > 0, c = Object.entries(e.fields).map(([e, n]) => ` ${ut(e, n, t, i, r?.has(e) ?? !1, s)}`).join(",\n"), l = (e.appliedUniques ?? []).map((n) => {
|
|
429
|
+
let r = n.fields.map((n) => ct(n, e.fields, t)).join(", ");
|
|
430
430
|
return ` CONSTRAINT ${o(n.name, t)} UNIQUE (${r})`;
|
|
431
|
-
}), u = (e.appliedChecks ?? []).map((e) => ` CONSTRAINT ${o(e.name, t)} CHECK (${e.expr})`), d = s ? [` PRIMARY KEY (${a.map((n) =>
|
|
431
|
+
}), u = (e.appliedChecks ?? []).map((e) => ` CONSTRAINT ${o(e.name, t)} CHECK (${e.expr})`), d = s ? [` PRIMARY KEY (${a.map((n) => ct(n, e.fields, t)).join(", ")})`] : [], f = b(t) ? Object.entries(e.fields).flatMap(([i, a]) => {
|
|
432
432
|
if (a.type !== "reference" || !a.references || (r?.has(i) ?? !1)) return [];
|
|
433
|
-
let s = a.references(), c =
|
|
434
|
-
return [` CONSTRAINT ${o(`${e.tableName}_${i}_fkey`, t)} FOREIGN KEY (${o(i, t)}) REFERENCES ${
|
|
433
|
+
let s = a.references(), c = F(a.onDelete ?? "restrict", t), l = F(a.refOnUpdate ?? "noAction", t);
|
|
434
|
+
return [` CONSTRAINT ${o(`${e.tableName}_${i}_fkey`, t)} FOREIGN KEY (${o(i, t)}) REFERENCES ${at(s.tableName, t, n)} (${o(a.referenceColumn ?? "id", t)}) ON DELETE ${c}${l === "NO ACTION" ? "" : ` ON UPDATE ${l}`}`];
|
|
435
435
|
}) : [], p = [
|
|
436
436
|
...d,
|
|
437
437
|
...l,
|
|
438
438
|
...u,
|
|
439
439
|
...f
|
|
440
|
-
], m = p.length > 0 ? `${c},\n${p.join(",\n")}` : c, h =
|
|
440
|
+
], m = p.length > 0 ? `${c},\n${p.join(",\n")}` : c, h = at(e.tableName, t, n);
|
|
441
441
|
if (t === "mssql") {
|
|
442
442
|
let t = n === null ? e.tableName : `${n}.${e.tableName}`, r = `CREATE TABLE ${h} (\n${m}\n)`;
|
|
443
443
|
return `IF OBJECT_ID('${t.replace(/'/g, "''")}', 'U') IS NULL EXEC(N'${r.replace(/'/g, "''")}');`;
|
|
@@ -447,10 +447,10 @@ var k = "framework_changes", Qe = "framework_changes_", $e = (e, t) => t === "fr
|
|
|
447
447
|
m,
|
|
448
448
|
");"
|
|
449
449
|
].join("\n");
|
|
450
|
-
},
|
|
450
|
+
}, ft = (e, t, n) => {
|
|
451
451
|
let r = `${e}_${t.name}_fts`, i = (e) => o(e, n), a = t.columns.map(i).join(", "), s = t.columns.map((e) => `new.${i(e)}`).join(", "), c = [];
|
|
452
452
|
return c.push(`CREATE VIRTUAL TABLE IF NOT EXISTS ${i(r)} USING fts5(${a}, row_id UNINDEXED, tokenize='porter');`), c.push(`CREATE TRIGGER IF NOT EXISTS ${i(`${r}_ai`)} AFTER INSERT ON ${i(e)} BEGIN\n INSERT INTO ${i(r)} (${a}, row_id) VALUES (${s}, new.${i("id")});\nEND;`), c.push(`CREATE TRIGGER IF NOT EXISTS ${i(`${r}_ad`)} AFTER DELETE ON ${i(e)} BEGIN\n DELETE FROM ${i(r)} WHERE row_id = old.${i("id")};\nEND;`), c.push(`CREATE TRIGGER IF NOT EXISTS ${i(`${r}_au`)} AFTER UPDATE ON ${i(e)} BEGIN\n DELETE FROM ${i(r)} WHERE row_id = old.${i("id")};\n INSERT INTO ${i(r)} (${a}, row_id) VALUES (${s}, new.${i("id")});\nEND;`), c;
|
|
453
|
-
},
|
|
453
|
+
}, pt = (e, t, n = null) => {
|
|
454
454
|
let r = [], i = /* @__PURE__ */ new Set(), a = (e) => e.join("\0"), s = (e, n, r, i) => {
|
|
455
455
|
let a = {
|
|
456
456
|
using: "",
|
|
@@ -462,21 +462,21 @@ var k = "framework_changes", Qe = "framework_changes_", $e = (e, t) => t === "fr
|
|
|
462
462
|
using: " USING GIST",
|
|
463
463
|
withSuffix: "",
|
|
464
464
|
skip: !1
|
|
465
|
-
} : (
|
|
465
|
+
} : (j(`[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);
|
|
466
466
|
if (r === "gin") return t === "postgres" ? {
|
|
467
467
|
using: " USING GIN",
|
|
468
468
|
withSuffix: "",
|
|
469
469
|
skip: !1
|
|
470
|
-
} : t === "mysql" || t === "mariadb" ? (
|
|
470
|
+
} : t === "mysql" || t === "mariadb" ? (j(`[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(...).`), {
|
|
471
471
|
using: "",
|
|
472
472
|
withSuffix: "",
|
|
473
473
|
skip: !0
|
|
474
|
-
}) : (
|
|
474
|
+
}) : (j(`[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);
|
|
475
475
|
if (r === "brin") return t === "postgres" ? {
|
|
476
476
|
using: " USING BRIN",
|
|
477
477
|
withSuffix: "",
|
|
478
478
|
skip: !1
|
|
479
|
-
} : (
|
|
479
|
+
} : (j(`[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);
|
|
480
480
|
if (r === "hnsw") {
|
|
481
481
|
if (t === "postgres") {
|
|
482
482
|
let e = i?.hnsw?.m ?? 16, t = i?.hnsw?.efConstruction ?? 64, n = i?.hnsw?.opclass ?? h(i?.hnsw?.distance);
|
|
@@ -487,7 +487,7 @@ var k = "framework_changes", Qe = "framework_changes_", $e = (e, t) => t === "fr
|
|
|
487
487
|
skip: !1
|
|
488
488
|
};
|
|
489
489
|
}
|
|
490
|
-
return
|
|
490
|
+
return j(`[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.`), {
|
|
491
491
|
using: "",
|
|
492
492
|
withSuffix: "",
|
|
493
493
|
skip: !0
|
|
@@ -496,7 +496,7 @@ var k = "framework_changes", Qe = "framework_changes_", $e = (e, t) => t === "fr
|
|
|
496
496
|
return a;
|
|
497
497
|
}, c = (n, r) => {
|
|
498
498
|
let i = n.map((n) => {
|
|
499
|
-
if (typeof n == "string") return
|
|
499
|
+
if (typeof n == "string") return ct(n, e.fields, t);
|
|
500
500
|
if ("jsonPath" in n) {
|
|
501
501
|
let { column: e, path: r, numeric: i } = n.jsonPath;
|
|
502
502
|
return `(${C(e, r, t, { numeric: i })})`;
|
|
@@ -507,11 +507,11 @@ var k = "framework_changes", Qe = "framework_changes_", $e = (e, t) => t === "fr
|
|
|
507
507
|
}, l = (e, r, i, a, l, u = "", d = !1) => {
|
|
508
508
|
let f = s(e, r, a, l);
|
|
509
509
|
if (f.skip) return "";
|
|
510
|
-
let p = c(i, f.opclass), m = `${f.withSuffix}${u}`, h =
|
|
510
|
+
let p = c(i, f.opclass), m = `${f.withSuffix}${u}`, h = at(r, t, n), g = d ? "UNIQUE " : "";
|
|
511
511
|
return t === "mssql" ? `IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = '${e}') CREATE ${g}INDEX ${o(e, t)} ON ${h}${f.using} (${p})${m};` : t === "mysql" ? `CREATE ${g}INDEX ${o(e, t)} ON ${h}${f.using} (${p})${m};` : `CREATE ${g}INDEX IF NOT EXISTS ${o(e, t)} ON ${h}${f.using} (${p})${m};`;
|
|
512
512
|
};
|
|
513
513
|
if (t === "mysql" || t === "mariadb") for (let [n, i] of Object.entries(e.fields)) {
|
|
514
|
-
if (!i.unique || i.type === "id" || !
|
|
514
|
+
if (!i.unique || i.type === "id" || !st(i, t)) continue;
|
|
515
515
|
let a = l(`${e.tableName}_${n}_key`, e.tableName, [n], void 0, void 0, "", !0);
|
|
516
516
|
a && r.push(a);
|
|
517
517
|
}
|
|
@@ -525,15 +525,15 @@ var k = "framework_changes", Qe = "framework_changes_", $e = (e, t) => t === "fr
|
|
|
525
525
|
let i = n.columns.map((e) => o(e, t)).join(", ");
|
|
526
526
|
r.push(`CREATE FULLTEXT INDEX ${o(n.name, t)} ON ${o(e.tableName, t)} (${i});`);
|
|
527
527
|
} 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.`);
|
|
528
|
-
else t === "sqlite" ? r.push(...
|
|
528
|
+
else t === "sqlite" ? r.push(...ft(e.tableName, n, t)) : j(`[voltro:migrate] full-text index '${n.name}' on '${e.tableName}': ${t} uses a ranked LIKE search at query time (no native FTS catalog required).`);
|
|
529
529
|
for (let n of e.appliedIndexes) {
|
|
530
530
|
if ((t === "mariadb" || t === "mssql") && n.fields.some((e) => typeof e != "string" && "jsonPath" in e)) {
|
|
531
|
-
|
|
531
|
+
j(`[voltro:migrate] json-path index '${n.name}' on '${e.tableName}': ${t} cannot index a JSON expression directly — skipping. For an indexed JSON path on ${t}, add a generated column for the path (text().generatedAs(...) / .stored()) and .index([...]) it, then filter on that column instead of jsonField(...).`);
|
|
532
532
|
continue;
|
|
533
533
|
}
|
|
534
534
|
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.`);
|
|
535
535
|
let o = "";
|
|
536
|
-
n.where !== void 0 && n.where.length > 0 && (t === "mysql" || t === "mariadb" ?
|
|
536
|
+
n.where !== void 0 && n.where.length > 0 && (t === "mysql" || t === "mariadb" ? j(`[voltro:migrate] partial index '${n.name}' on '${e.tableName}': ${t} does not support WHERE clauses on indexes — emitting a full index`) : o = ` WHERE ${n.where}`);
|
|
537
537
|
let s = l(n.name, e.tableName, n.fields, n.kind, n.kindOptions, o, n.unique === !0);
|
|
538
538
|
s !== "" && r.push(s), n.fields.every((e) => typeof e == "string") && i.add(a(n.fields));
|
|
539
539
|
}
|
|
@@ -543,17 +543,17 @@ var k = "framework_changes", Qe = "framework_changes_", $e = (e, t) => t === "fr
|
|
|
543
543
|
r.push(l(o, e.tableName, [t])), i.add(a([t]));
|
|
544
544
|
}
|
|
545
545
|
return r.join("\n");
|
|
546
|
-
},
|
|
546
|
+
}, mt = (e, t, n = A) => {
|
|
547
547
|
if (t !== "postgres") return [];
|
|
548
548
|
let r = e.filter((e) => e.isReactive !== !1);
|
|
549
|
-
return r.length === 0 ? [] : [
|
|
550
|
-
},
|
|
551
|
-
CREATE OR REPLACE FUNCTION ${
|
|
549
|
+
return r.length === 0 ? [] : [ht(n), ...r.map((e) => _t(e, n))];
|
|
550
|
+
}, ht = (e) => `
|
|
551
|
+
CREATE OR REPLACE FUNCTION ${$e(e)}() RETURNS trigger AS $$
|
|
552
552
|
DECLARE
|
|
553
553
|
payload TEXT;
|
|
554
554
|
pk JSONB;
|
|
555
555
|
BEGIN
|
|
556
|
-
-- ${
|
|
556
|
+
-- ${et}
|
|
557
557
|
payload := json_build_object(
|
|
558
558
|
'table', TG_TABLE_NAME,
|
|
559
559
|
-- The schema the write landed in. Under namespace isolation this is
|
|
@@ -607,22 +607,22 @@ BEGIN
|
|
|
607
607
|
RETURN COALESCE(NEW, OLD);
|
|
608
608
|
END;
|
|
609
609
|
$$ LANGUAGE plpgsql;
|
|
610
|
-
`.trim(),
|
|
611
|
-
let n =
|
|
610
|
+
`.trim(), gt = (e, t) => {
|
|
611
|
+
let n = Qe(e.tableName, t);
|
|
612
612
|
return [
|
|
613
613
|
`ALTER TABLE "${e.tableName}" REPLICA IDENTITY FULL`,
|
|
614
614
|
`DROP TRIGGER IF EXISTS ${n} ON "${e.tableName}"`,
|
|
615
|
-
`CREATE TRIGGER ${n}\nAFTER INSERT OR UPDATE OR DELETE ON "${e.tableName}"\nFOR EACH ROW EXECUTE FUNCTION ${
|
|
615
|
+
`CREATE TRIGGER ${n}\nAFTER INSERT OR UPDATE OR DELETE ON "${e.tableName}"\nFOR EACH ROW EXECUTE FUNCTION ${$e(t)}()`
|
|
616
616
|
];
|
|
617
|
-
},
|
|
617
|
+
}, _t = (e, t) => gt(e, t).map((e) => `${e};`).join("\n"), vt = (e) => {
|
|
618
618
|
if (e.dialect !== "postgres") return [];
|
|
619
619
|
let t = e.channel ?? "framework_changes", n = new Map(e.tables.map((e) => [e.tableName, e])), r = [], i = e.missing.filter((e) => n.has(e));
|
|
620
|
-
(i.length > 0 || e.functionOutdated === !0) && r.push(
|
|
621
|
-
for (let e of i) r.push(...
|
|
622
|
-
for (let n of e.stale) r.push(`DROP TRIGGER IF EXISTS ${
|
|
620
|
+
(i.length > 0 || e.functionOutdated === !0) && r.push(ht(t));
|
|
621
|
+
for (let e of i) r.push(...gt(n.get(e), t));
|
|
622
|
+
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`);
|
|
623
623
|
return r;
|
|
624
|
-
},
|
|
625
|
-
let t = new Map(e.map((e) => [e.tableName, e])), n =
|
|
624
|
+
}, yt = (e) => e.some((e) => Object.values(e.fields).some((e) => e.type === "vector")), bt = (e) => e.some((e) => Object.values(e.fields).some((e) => e.spatial !== void 0)), xt = (e) => {
|
|
625
|
+
let t = new Map(e.map((e) => [e.tableName, e])), n = me(e.map((e) => e.tableName), (e) => {
|
|
626
626
|
let n = t.get(e);
|
|
627
627
|
return n ? Object.entries(n.fields).flatMap(([e, n]) => {
|
|
628
628
|
if (n.type !== "reference" || !n.references) return [];
|
|
@@ -633,7 +633,7 @@ $$ LANGUAGE plpgsql;
|
|
|
633
633
|
}] : [];
|
|
634
634
|
}) : [];
|
|
635
635
|
}), r = [];
|
|
636
|
-
for (let t of e) for (let [e, i] of Object.entries(t.fields)) i.type === "reference" && i.references && n.has(
|
|
636
|
+
for (let t of e) for (let [e, i] of Object.entries(t.fields)) i.type === "reference" && i.references && n.has(D(t.tableName, e)) && r.push({
|
|
637
637
|
table: t.tableName,
|
|
638
638
|
column: e,
|
|
639
639
|
targetTable: i.references().tableName,
|
|
@@ -645,7 +645,7 @@ $$ LANGUAGE plpgsql;
|
|
|
645
645
|
if (!(i.has(e.tableName) || a.has(e.tableName))) {
|
|
646
646
|
a.add(e.tableName);
|
|
647
647
|
for (let [r, i] of Object.entries(e.fields)) {
|
|
648
|
-
if (i.type !== "reference" || !i.references || n.has(
|
|
648
|
+
if (i.type !== "reference" || !i.references || n.has(D(e.tableName, r))) continue;
|
|
649
649
|
let a = i.references();
|
|
650
650
|
if (a.tableName === e.tableName) continue;
|
|
651
651
|
let o = t.get(a.tableName);
|
|
@@ -659,8 +659,8 @@ $$ LANGUAGE plpgsql;
|
|
|
659
659
|
sorted: o,
|
|
660
660
|
cyclic: r
|
|
661
661
|
};
|
|
662
|
-
},
|
|
663
|
-
let r = (e) => n ? `${o(n, t)}.${o(e, t)}` : o(e, t), i = `${e.table}_${e.column}_fkey`, a =
|
|
662
|
+
}, St = (e, t, n = null) => {
|
|
663
|
+
let r = (e) => n ? `${o(n, t)}.${o(e, t)}` : o(e, t), i = `${e.table}_${e.column}_fkey`, a = F(e.onDelete, t), s = F(e.onUpdate, t), c = ` ON DELETE ${a}${s === "NO ACTION" ? "" : ` ON UPDATE ${s}`}`, l = (n) => `ADD CONSTRAINT ${o(i, t)} FOREIGN KEY ${n ? "IF NOT EXISTS " : ""}(${o(e.column, t)}) REFERENCES ${r(e.targetTable)} (${o(e.targetColumn, t)})${c}`;
|
|
664
664
|
switch (t) {
|
|
665
665
|
case "postgres": return [
|
|
666
666
|
"DO $$ BEGIN",
|
|
@@ -674,7 +674,7 @@ $$ LANGUAGE plpgsql;
|
|
|
674
674
|
case "mariadb": return `ALTER TABLE ${r(e.table)} ${l(!0)};`;
|
|
675
675
|
default: return `ALTER TABLE ${r(e.table)} ${l(!1)};`;
|
|
676
676
|
}
|
|
677
|
-
},
|
|
677
|
+
}, Ct = (e, t) => {
|
|
678
678
|
let n = /* @__PURE__ */ new Map();
|
|
679
679
|
if (m(t)) return n;
|
|
680
680
|
for (let t of e) {
|
|
@@ -682,7 +682,7 @@ $$ LANGUAGE plpgsql;
|
|
|
682
682
|
e.add(t.column), n.set(t.table, e);
|
|
683
683
|
}
|
|
684
684
|
return n;
|
|
685
|
-
},
|
|
685
|
+
}, wt = (e, t) => {
|
|
686
686
|
if (t !== "postgres") return "";
|
|
687
687
|
let n = /* @__PURE__ */ new Map();
|
|
688
688
|
for (let t of e) for (let e of Object.values(t.fields)) {
|
|
@@ -698,7 +698,7 @@ $$ LANGUAGE plpgsql;
|
|
|
698
698
|
r.push(`DO $$ BEGIN\n IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = '${e.replace(/'/g, "''")}') THEN\n CREATE TYPE "${e}" AS ENUM (${n});\n END IF;\nEND $$;`);
|
|
699
699
|
}
|
|
700
700
|
return r.join("\n\n");
|
|
701
|
-
},
|
|
701
|
+
}, Tt = (e, t) => {
|
|
702
702
|
if (t !== "postgres") return "";
|
|
703
703
|
let r = /* @__PURE__ */ new Set();
|
|
704
704
|
for (let t of e) for (let e of Object.values(t.fields)) e.type === "enum" && e.enumName && r.add(e.enumName);
|
|
@@ -712,30 +712,30 @@ BEGIN
|
|
|
712
712
|
SELECT oid INTO type_oid FROM pg_type WHERE typname = '${n}';\n IF type_oid IS NOT NULL\n AND EXISTS (SELECT 1 FROM pg_enum WHERE enumtypid = type_oid AND enumlabel = '${a}')\n AND NOT EXISTS (SELECT 1 FROM pg_enum WHERE enumtypid = type_oid AND enumlabel = '${o}') THEN\n IF current_setting('server_version_num')::int >= 140000 THEN\n EXECUTE format('ALTER TYPE %I RENAME VALUE %L TO %L', '${n}', '${a}', '${o}');\n ELSE\n UPDATE pg_enum SET enumlabel = '${o}' WHERE enumtypid = type_oid AND enumlabel = '${a}';\n END IF;\n END IF;\nEND $$;`);
|
|
713
713
|
}
|
|
714
714
|
return i.join("\n\n");
|
|
715
|
-
},
|
|
715
|
+
}, Et = (e) => {
|
|
716
716
|
let t = [], n = [];
|
|
717
717
|
for (let r of e) s(r) ? n.push(r) : t.push(r);
|
|
718
718
|
return {
|
|
719
719
|
tables: t,
|
|
720
720
|
views: n
|
|
721
721
|
};
|
|
722
|
-
},
|
|
723
|
-
let { tables: i, views: a } =
|
|
724
|
-
n === "postgres" &&
|
|
725
|
-
let u =
|
|
722
|
+
}, Dt = (t, n, r = A) => {
|
|
723
|
+
let { tables: i, views: a } = Et(t), { sorted: o, cyclic: s } = xt(i.map((e) => pe(e, n))), c = Ct(s, n), l = [];
|
|
724
|
+
n === "postgres" && yt(o) && l.push("CREATE EXTENSION IF NOT EXISTS vector;"), n === "postgres" && bt(o) && l.push("CREATE EXTENSION IF NOT EXISTS postgis;");
|
|
725
|
+
let u = Tt(o, n);
|
|
726
726
|
u && l.push(u);
|
|
727
|
-
let d =
|
|
727
|
+
let d = wt(o, n);
|
|
728
728
|
d && l.push(d);
|
|
729
|
-
for (let e of o) l.push(
|
|
730
|
-
if (!m(n)) for (let e of s) l.push(
|
|
729
|
+
for (let e of o) l.push(dt(e, n, null, c.get(e.tableName)));
|
|
730
|
+
if (!m(n)) for (let e of s) l.push(St(e, n));
|
|
731
731
|
for (let e of o) {
|
|
732
|
-
let t =
|
|
732
|
+
let t = pt(e, n);
|
|
733
733
|
t && l.push(t);
|
|
734
734
|
}
|
|
735
|
-
l.push(...
|
|
735
|
+
l.push(...mt(o, n, r));
|
|
736
736
|
for (let t of a) l.push(e(t, n));
|
|
737
737
|
return l.join("\n\n") + "\n";
|
|
738
|
-
},
|
|
738
|
+
}, Ot = (e, t, n) => {
|
|
739
739
|
let r = o(e, t);
|
|
740
740
|
switch (t) {
|
|
741
741
|
case "postgres": return `CREATE SCHEMA IF NOT EXISTS ${r};`;
|
|
@@ -745,62 +745,62 @@ BEGIN
|
|
|
745
745
|
case "turso":
|
|
746
746
|
case "sqlite": return `ATTACH DATABASE '${(n ?? `${e}.db`).replace(/'/g, "''")}' AS ${r};`;
|
|
747
747
|
}
|
|
748
|
-
},
|
|
749
|
-
let i =
|
|
750
|
-
if (t === "postgres") return `${i}\n\nSET search_path TO ${a};\n\n${
|
|
751
|
-
if (t === "mysql" || t === "mariadb") return `${i}\n\nUSE ${a};\n\n${
|
|
752
|
-
let { sorted: s, cyclic: c } =
|
|
753
|
-
for (let e of s) u.push(
|
|
754
|
-
if (!m(t)) for (let e of c) u.push(
|
|
748
|
+
}, kt = (e, t, n, r) => {
|
|
749
|
+
let i = Ot(n, t, r), a = o(n, t);
|
|
750
|
+
if (t === "postgres") return `${i}\n\nSET search_path TO ${a};\n\n${Dt(e, t)}`;
|
|
751
|
+
if (t === "mysql" || t === "mariadb") return `${i}\n\nUSE ${a};\n\n${Dt(e, t)}`;
|
|
752
|
+
let { sorted: s, cyclic: c } = xt(e), l = Ct(c, t), u = [i];
|
|
753
|
+
for (let e of s) u.push(dt(e, t, n, l.get(e.tableName)));
|
|
754
|
+
if (!m(t)) for (let e of c) u.push(St(e, t, n));
|
|
755
755
|
for (let e of s) {
|
|
756
|
-
let r =
|
|
756
|
+
let r = pt(e, t, n);
|
|
757
757
|
r && u.push(r);
|
|
758
758
|
}
|
|
759
759
|
return u.join("\n\n") + "\n";
|
|
760
|
-
},
|
|
761
|
-
let { sorted: r, cyclic: i } =
|
|
760
|
+
}, At = (e, t, n = A) => {
|
|
761
|
+
let { sorted: r, cyclic: i } = xt(e), a = Ct(i, t), o = [], s = Tt(r, t);
|
|
762
762
|
s && o.push(s);
|
|
763
|
-
let c =
|
|
763
|
+
let c = wt(r, t);
|
|
764
764
|
c && o.push(c);
|
|
765
|
-
for (let e of r) o.push(
|
|
766
|
-
for (let e of i) o.push(
|
|
767
|
-
return o.push(...
|
|
768
|
-
},
|
|
769
|
-
let i = yield*
|
|
770
|
-
yield*
|
|
771
|
-
}),
|
|
765
|
+
for (let e of r) o.push(dt(e, t, null, a.get(e.tableName)));
|
|
766
|
+
for (let e of i) o.push(St(e, t));
|
|
767
|
+
return o.push(...mt(r, t, n)), o.join("\n\n") + "\n";
|
|
768
|
+
}, jt = (e, t = "postgres", n = A, r = {}) => w.gen(function* () {
|
|
769
|
+
let i = yield* E.SqlClient;
|
|
770
|
+
yield* Ie(i, Rt(i, Dt(e, t, n), t, r.retryFilter), { schema: r.lockSchema }).pipe(w.orDie);
|
|
771
|
+
}), Mt = (e, t) => {
|
|
772
772
|
let n = t.cause ?? {};
|
|
773
773
|
return (n.errno === 1061 || n.code === "ER_DUP_KEYNAME") && /^\s*CREATE\s+(UNIQUE\s+|FULLTEXT\s+)?INDEX\b/i.test(e);
|
|
774
|
-
},
|
|
774
|
+
}, Nt = (e, t) => {
|
|
775
775
|
let n = e.trimStart();
|
|
776
776
|
return !!(/\bIF NOT EXISTS\b/i.test(n) || /^CREATE OR REPLACE\b/i.test(n) || /^DROP\s[\s\S]*?\bIF EXISTS\b/i.test(n) || /^SET search_path\b/i.test(n) || /^USE[\s`"[]/i.test(n) || /^IF\s/i.test(n) || (t === "mysql" || t === "mariadb") && /^CREATE\s+(UNIQUE\s+|FULLTEXT\s+)?INDEX\b/i.test(n));
|
|
777
|
-
},
|
|
777
|
+
}, Pt = () => {
|
|
778
778
|
let e = Number(process.env.VOLTRO_MIGRATION_DDL_RETRIES);
|
|
779
779
|
return Number.isInteger(e) && e >= 0 ? e : 4;
|
|
780
|
-
},
|
|
780
|
+
}, Ft = (e) => ({
|
|
781
781
|
while: e,
|
|
782
|
-
times:
|
|
783
|
-
schedule:
|
|
784
|
-
}),
|
|
782
|
+
times: Pt(),
|
|
783
|
+
schedule: ee.jittered(ee.exponential("50 millis"))
|
|
784
|
+
}), It = class {
|
|
785
785
|
statement;
|
|
786
786
|
error;
|
|
787
787
|
_tag = "DdlStatementFailed";
|
|
788
788
|
constructor(e, t) {
|
|
789
789
|
this.statement = e, this.error = t;
|
|
790
790
|
}
|
|
791
|
-
},
|
|
792
|
-
let r = yield*
|
|
793
|
-
for (let a of
|
|
794
|
-
process.env.VOLTRO_MIGRATE_DEBUG === "1" &&
|
|
795
|
-
let e = r.unsafe(a).pipe(w.catchIf((e) =>
|
|
796
|
-
|
|
791
|
+
}, Lt = (e, t, n) => w.gen(function* () {
|
|
792
|
+
let r = yield* E.SqlClient, i = n !== void 0 && ze(t) === "per-operation";
|
|
793
|
+
for (let a of zt(e)) {
|
|
794
|
+
process.env.VOLTRO_MIGRATE_DEBUG === "1" && nt.debug(`EXEC: ${a.replace(/\s+/g, " ").slice(0, 180)}`);
|
|
795
|
+
let e = r.unsafe(a).pipe(w.catchIf((e) => Mt(a, e), () => w.succeed([])), w.tapError((e) => w.sync(() => {
|
|
796
|
+
nt.error(se("migrate: statement failed", a, e, 200));
|
|
797
797
|
})));
|
|
798
|
-
yield* (i && n !== void 0 &&
|
|
798
|
+
yield* (i && n !== void 0 && Nt(a, t) ? e.pipe(w.retry(Ft((e) => n(e) === "retry"))) : e).pipe(w.mapError((e) => new It(a, e)));
|
|
799
799
|
}
|
|
800
|
-
}),
|
|
801
|
-
let i = n === "turso" ?
|
|
802
|
-
return (r !== void 0 &&
|
|
803
|
-
},
|
|
800
|
+
}), Rt = (e, t, n, r) => {
|
|
801
|
+
let i = n === "turso" ? Lt(t, n, r) : e.withTransaction(Lt(t, n, r)), a = (e) => e instanceof It ? e.error : e;
|
|
802
|
+
return (r !== void 0 && ze(n) === "plan-transactional" ? i.pipe(w.retry(Ft((e) => r(a(e)) === "retry"))) : i).pipe(w.orDieWith((e) => e instanceof It ? Error(se("migrate: statement failed", e.statement, e.error, 400).trim()) : e));
|
|
803
|
+
}, zt = (e) => {
|
|
804
804
|
let t = [], n = "", r = !1;
|
|
805
805
|
for (let i = 0; i < e.length; i++) {
|
|
806
806
|
if (e.slice(i, i + 2) === "$$") {
|
|
@@ -815,30 +815,78 @@ BEGIN
|
|
|
815
815
|
}
|
|
816
816
|
let i = n.trim();
|
|
817
817
|
return i.length > 0 && t.push(i), t;
|
|
818
|
-
},
|
|
819
|
-
await w.runPromise(
|
|
820
|
-
},
|
|
821
|
-
let i =
|
|
822
|
-
yield*
|
|
823
|
-
}),
|
|
824
|
-
await w.runPromise(
|
|
818
|
+
}, Bt = async (e, t, n = "postgres", r = {}) => {
|
|
819
|
+
await w.runPromise(jt(e, n, void 0, r).pipe(w.provide(t)));
|
|
820
|
+
}, Vt = (e, t, n = "postgres", r = {}) => w.gen(function* () {
|
|
821
|
+
let i = kt(e, n, t), a = yield* E.SqlClient;
|
|
822
|
+
yield* Ie(a, Rt(a, i, n, r.retryFilter), { schema: r.lockSchema }).pipe(w.orDie);
|
|
823
|
+
}), Ht = async (e, t, n, r = "postgres", i = {}) => {
|
|
824
|
+
await w.runPromise(Vt(e, t, r, i).pipe(w.provide(n))), await f({
|
|
825
825
|
namespace: t,
|
|
826
826
|
dialect: r
|
|
827
827
|
});
|
|
828
|
-
},
|
|
828
|
+
}, Ut = async (e, t, n = "postgres", r = {}) => {
|
|
829
829
|
await w.runPromise(w.gen(function* () {
|
|
830
|
-
let t =
|
|
831
|
-
yield*
|
|
830
|
+
let t = At(e, n), i = yield* E.SqlClient;
|
|
831
|
+
yield* Ie(i, Rt(i, t, n, r.retryFilter), { schema: r.lockSchema }).pipe(w.orDie);
|
|
832
832
|
}).pipe(w.provide(t)));
|
|
833
|
-
},
|
|
833
|
+
}, I = (e) => {
|
|
834
|
+
if (typeof e != "object" || !e) return JSON.stringify(e);
|
|
835
|
+
if (Array.isArray(e)) return `[${e.map(I).join(",")}]`;
|
|
836
|
+
let t = e;
|
|
837
|
+
return `{${Object.keys(t).sort().map((e) => `${JSON.stringify(e)}:${I(t[e])}`).join(",")}}`;
|
|
838
|
+
}, Wt = (e) => {
|
|
839
|
+
if (!e.hasDefault || e.defaultValue === void 0 || e.defaultValue === null) return null;
|
|
840
|
+
let t = e.defaultValue;
|
|
841
|
+
if (typeof t == "boolean") return t ? "__BOOL_TRUE__" : "__BOOL_FALSE__";
|
|
842
|
+
if (typeof t == "number") return String(t);
|
|
843
|
+
if (typeof t != "string") return I(t);
|
|
844
|
+
let n = t.trim(), r = n.toLowerCase().replace(/\s+/g, "");
|
|
845
|
+
if (r === "now" || r === "now()" || /^current_timestamp(\(\d*\))?$/.test(r) || r === "sysutcdatetime()" || r === "sysdatetime()" || r === "getutcdate()" || r === "getdate()") return "__NOW__";
|
|
846
|
+
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);
|
|
847
|
+
if (o) try {
|
|
848
|
+
return I(JSON.parse(o[1]));
|
|
849
|
+
} catch {}
|
|
850
|
+
let s = /^convert\(\s*(?:_\w+\s*)?\\?'(.*?)\\?'\s+using\s+[\w]+\s*\)$/i.exec(a);
|
|
851
|
+
if (s) try {
|
|
852
|
+
return I(JSON.parse(s[1]));
|
|
853
|
+
} catch {}
|
|
854
|
+
if (a.startsWith("{") || a.startsWith("[")) try {
|
|
855
|
+
return I(JSON.parse(a));
|
|
856
|
+
} catch {}
|
|
857
|
+
return /^-?\d+(\.\d+)?$/.test(a) ? String(Number(a)) : a;
|
|
858
|
+
}, Gt = (e) => {
|
|
859
|
+
let t = Wt(e);
|
|
860
|
+
return t === "1" || t === "true" ? "__BOOL_TRUE__" : t === "0" || t === "false" ? "__BOOL_FALSE__" : t;
|
|
861
|
+
}, Kt = (e) => typeof e.defaultValue == "string" && /^nextval\(.+::regclass\)$/i.test(e.defaultValue.trim()), qt = (e) => {
|
|
862
|
+
if (!e) return null;
|
|
863
|
+
let t = (e) => e === "restrict" ? "noAction" : e;
|
|
864
|
+
return {
|
|
865
|
+
table: e.table,
|
|
866
|
+
column: e.column,
|
|
867
|
+
onDelete: t(e.onDelete),
|
|
868
|
+
onUpdate: t(e.onUpdate)
|
|
869
|
+
};
|
|
870
|
+
}, Jt = (e, t, n) => {
|
|
871
|
+
if (t === "mssql") {
|
|
872
|
+
let t = tt(e, n);
|
|
873
|
+
if (t !== void 0) return t;
|
|
874
|
+
}
|
|
875
|
+
try {
|
|
876
|
+
let n = /^N?VARCHAR\((\d+)\)$/i.exec(M(e, t).trim());
|
|
877
|
+
return n ? Number(n[1]) : void 0;
|
|
878
|
+
} catch {
|
|
879
|
+
return;
|
|
880
|
+
}
|
|
881
|
+
}, Yt = /'(?:''|[^'])*'|"(?:""|[^"])*"|\[(?:\]\]|[^\]])*\]|`(?:``|[^`])*`|[A-Za-z_][A-Za-z_0-9$]*|\d+(?:\.\d+)?|::|<>|!=|<=|>=|\|\||[^\s]/g, Xt = (e) => {
|
|
834
882
|
let t = 0;
|
|
835
|
-
for (let n of e.matchAll(
|
|
836
|
-
},
|
|
883
|
+
for (let n of e.matchAll(Yt)) if (n[0] === "(" && t++, n[0] === ")" && t--, t === 0 && n[0].toLowerCase() === "where") return e.slice(n.index + n[0].length).trim().replace(/;$/, "").trim();
|
|
884
|
+
}, Zt = (e) => {
|
|
837
885
|
if (e === void 0) return;
|
|
838
|
-
let t = e.match(
|
|
886
|
+
let t = e.match(Yt) ?? [], n = "(?:'(?:''|[^'])*'(?:\\s*::\\s*text)?|[0-9]+)", r = RegExp(`^\\s*${n}(?:\\s*,\\s*${n})*\\s*$`, "i");
|
|
839
887
|
for (let e = 0; e < t.length - 5; e++) {
|
|
840
888
|
let n = t[e + 4];
|
|
841
|
-
t[e] === "=" && t[e + 1]?.toLowerCase() === "any" && t[e + 2] === "(" && t[e + 3]?.toLowerCase() === "array" && n.startsWith("[") && n.endsWith("]") && t[e + 5] === ")" && r.test(n.slice(1, -1)) && t.splice(e, 6, "in", "(", ...n.slice(1, -1).match(
|
|
889
|
+
t[e] === "=" && t[e + 1]?.toLowerCase() === "any" && t[e + 2] === "(" && t[e + 3]?.toLowerCase() === "array" && n.startsWith("[") && n.endsWith("]") && t[e + 5] === ")" && r.test(n.slice(1, -1)) && t.splice(e, 6, "in", "(", ...n.slice(1, -1).match(Yt) ?? [], ")");
|
|
842
890
|
}
|
|
843
891
|
let i = t.filter((e, n) => !(e === "::" && t[n - 1]?.startsWith("'") && t[n + 1]?.toLowerCase() === "text" || e.toLowerCase() === "text" && t[n - 1] === "::" && t[n - 2]?.startsWith("'"))).map((e) => {
|
|
844
892
|
if (e.startsWith("'")) return e;
|
|
@@ -876,31 +924,40 @@ BEGIN
|
|
|
876
924
|
return r;
|
|
877
925
|
};
|
|
878
926
|
return JSON.stringify(a(i));
|
|
879
|
-
},
|
|
927
|
+
}, Qt = (e) => {
|
|
880
928
|
if (e == null) return e;
|
|
881
|
-
if (Array.isArray(e)) return e.map(
|
|
929
|
+
if (Array.isArray(e)) return e.map(Qt);
|
|
882
930
|
if (typeof e != "object") return e;
|
|
883
931
|
let t = {};
|
|
884
932
|
for (let n of Object.keys(e).sort()) {
|
|
885
933
|
let r = e[n];
|
|
886
|
-
r !== void 0 && (t[n] =
|
|
934
|
+
r !== void 0 && (t[n] = Qt(r));
|
|
887
935
|
}
|
|
888
936
|
return t;
|
|
889
|
-
},
|
|
937
|
+
}, $t = (e) => {
|
|
890
938
|
if (!e.idScheme && !e.sensitive && !e.safe && !e.generatedAs) return e;
|
|
891
939
|
let { idScheme: t, sensitive: n, safe: r, generatedAs: i, ...a } = e;
|
|
892
940
|
return a;
|
|
893
|
-
},
|
|
941
|
+
}, en = (e) => {
|
|
942
|
+
let t = $t(e), { references: n, defaultValue: r, hasDefault: i, oneOf: a, ...o } = t, s = t.type === "id" && Kt(t) ? null : Gt(t), c = qt(t.references);
|
|
943
|
+
return {
|
|
944
|
+
...o,
|
|
945
|
+
hasDefault: s !== null,
|
|
946
|
+
...s === null ? {} : { defaultValue: s },
|
|
947
|
+
...c === null ? {} : { references: c },
|
|
948
|
+
...t.oneOf !== void 0 && t.oneOf.length > 0 ? { oneOf: [...t.oneOf].sort() } : {}
|
|
949
|
+
};
|
|
950
|
+
}, tn = (e) => e.filter((e) => !x(e.name)).map(en).sort((e, t) => e.name.localeCompare(t.name)), nn = (e) => [...e].map((e) => e.where === void 0 ? e : {
|
|
894
951
|
...e,
|
|
895
|
-
where:
|
|
896
|
-
}).sort((e, t) => e.name.localeCompare(t.name)),
|
|
952
|
+
where: Zt(e.where)
|
|
953
|
+
}).sort((e, t) => e.name.localeCompare(t.name)), rn = (e) => [...e].map((e) => ({
|
|
897
954
|
name: e.name,
|
|
898
|
-
columns:
|
|
899
|
-
indexes:
|
|
900
|
-
})).sort((e, t) => e.name.localeCompare(t.name)),
|
|
901
|
-
let t = { tables:
|
|
902
|
-
return
|
|
903
|
-
},
|
|
955
|
+
columns: tn(e.columns),
|
|
956
|
+
indexes: nn(e.indexes)
|
|
957
|
+
})).sort((e, t) => e.name.localeCompare(t.name)), L = (e) => {
|
|
958
|
+
let t = { tables: rn(e.tables) }, n = JSON.stringify(Qt(t));
|
|
959
|
+
return ne("sha256").update(n).digest("hex");
|
|
960
|
+
}, an = (e) => e.slice(0, 16), on = (e, t) => {
|
|
904
961
|
let n = t.references ? {
|
|
905
962
|
table: t.references().tableName,
|
|
906
963
|
column: t.referenceColumn ?? "id",
|
|
@@ -940,7 +997,7 @@ BEGIN
|
|
|
940
997
|
...t.enumValues === void 0 ? {} : { enumValues: t.enumValues },
|
|
941
998
|
...t.spatial === void 0 ? {} : { spatial: t.spatial }
|
|
942
999
|
};
|
|
943
|
-
},
|
|
1000
|
+
}, sn = (e) => {
|
|
944
1001
|
let t = [], n = /* @__PURE__ */ new Set(), i = (e) => {
|
|
945
1002
|
n.has(e.name) || (n.add(e.name), t.push(e));
|
|
946
1003
|
}, a = e.appliedPrimaryKey ?? [];
|
|
@@ -988,11 +1045,11 @@ BEGIN
|
|
|
988
1045
|
});
|
|
989
1046
|
}
|
|
990
1047
|
return t;
|
|
991
|
-
},
|
|
1048
|
+
}, cn = (e) => {
|
|
992
1049
|
let t = new Set((e.appliedUniques ?? []).filter((e) => e.fields.length === 1).map((e) => e.fields[0])), n = [];
|
|
993
1050
|
for (let [r, i] of Object.entries(e.fields)) {
|
|
994
1051
|
if (i.dropped) continue;
|
|
995
|
-
let e =
|
|
1052
|
+
let e = on(r, i);
|
|
996
1053
|
n.push(t.has(r) ? {
|
|
997
1054
|
...e,
|
|
998
1055
|
unique: !0
|
|
@@ -1002,30 +1059,43 @@ BEGIN
|
|
|
1002
1059
|
return {
|
|
1003
1060
|
name: e.tableName,
|
|
1004
1061
|
columns: n,
|
|
1005
|
-
indexes:
|
|
1062
|
+
indexes: sn(e),
|
|
1006
1063
|
...r.length > 0 ? { primaryKey: [...r] } : {},
|
|
1007
1064
|
...i === void 0 ? {} : { renamedFrom: i }
|
|
1008
1065
|
};
|
|
1009
|
-
},
|
|
1066
|
+
}, ln = (e) => {
|
|
1010
1067
|
let t = /* @__PURE__ */ new Map();
|
|
1011
1068
|
for (let n of e) for (let e of n.indexes) {
|
|
1012
1069
|
let r = t.get(e.name);
|
|
1013
1070
|
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}').`);
|
|
1014
1071
|
t.set(e.name, n.name);
|
|
1015
1072
|
}
|
|
1016
|
-
},
|
|
1017
|
-
let n = e.filter((e) => !c(e.tableName)).map((e) =>
|
|
1073
|
+
}, R = (e, t) => {
|
|
1074
|
+
let n = e.filter((e) => !c(e.tableName)).map((e) => cn(pe(e, t)));
|
|
1018
1075
|
if (t === "mysql" || t === "mariadb") {
|
|
1019
1076
|
for (let e of n) for (let n of e.indexes) if (n.where !== void 0) throw Error(`Partial index '${n.name}' on '${e.name}' is not supported by ${t}. Use uniqueActive for portable conditional uniqueness.`);
|
|
1020
1077
|
}
|
|
1021
|
-
return
|
|
1022
|
-
},
|
|
1078
|
+
return ln(n), { tables: t === void 0 ? n : n.map((e) => un(e, t)) };
|
|
1079
|
+
}, un = (e, t) => {
|
|
1080
|
+
let n = new Set(e.indexes.flatMap((e) => e.columns));
|
|
1081
|
+
return {
|
|
1082
|
+
...e,
|
|
1083
|
+
columns: e.columns.map((e) => {
|
|
1084
|
+
if (e.maxLength !== void 0) return e;
|
|
1085
|
+
let r = Jt(e, t, n.has(e.name) || e.unique);
|
|
1086
|
+
return r === void 0 ? e : {
|
|
1087
|
+
...e,
|
|
1088
|
+
maxLength: r
|
|
1089
|
+
};
|
|
1090
|
+
})
|
|
1091
|
+
};
|
|
1092
|
+
}, dn = (e, t, n = A) => w.gen(function* () {
|
|
1023
1093
|
let r = (yield* e`
|
|
1024
1094
|
SELECT p.prosrc
|
|
1025
1095
|
FROM pg_proc p
|
|
1026
1096
|
JOIN pg_namespace n ON n.oid = p.pronamespace
|
|
1027
1097
|
WHERE n.nspname = current_schema()
|
|
1028
|
-
AND p.proname = ${
|
|
1098
|
+
AND p.proname = ${$e(n)}
|
|
1029
1099
|
`)[0]?.prosrc, i = r !== void 0 && !r.includes("voltro:notify:v2"), a = t.filter((e) => !e.tableName.startsWith("_voltro_"));
|
|
1030
1100
|
if (a.length === 0) return {
|
|
1031
1101
|
missing: [],
|
|
@@ -1039,10 +1109,10 @@ BEGIN
|
|
|
1039
1109
|
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
1040
1110
|
WHERE NOT t.tgisinternal
|
|
1041
1111
|
AND n.nspname = current_schema()
|
|
1042
|
-
AND t.tgname LIKE ${`${
|
|
1112
|
+
AND t.tgname LIKE ${`${Ze}%`}
|
|
1043
1113
|
`, s = new Set(o.map((e) => e.tgname)), c = [], l = [];
|
|
1044
1114
|
for (let e of a) {
|
|
1045
|
-
let t = s.has(
|
|
1115
|
+
let t = s.has(Qe(e.tableName, n)), r = e.isReactive !== !1;
|
|
1046
1116
|
r && !t && c.push(e.tableName), !r && t && l.push(e.tableName);
|
|
1047
1117
|
}
|
|
1048
1118
|
return {
|
|
@@ -1050,7 +1120,7 @@ BEGIN
|
|
|
1050
1120
|
stale: l.sort(),
|
|
1051
1121
|
functionOutdated: i
|
|
1052
1122
|
};
|
|
1053
|
-
}),
|
|
1123
|
+
}), fn = (e) => {
|
|
1054
1124
|
let t = [];
|
|
1055
1125
|
if (e.missing.length > 0) {
|
|
1056
1126
|
let n = e.missing.slice(0, 8).join(", "), r = e.missing.length > 8 ? `, … (+${e.missing.length - 8})` : "";
|
|
@@ -1061,19 +1131,19 @@ BEGIN
|
|
|
1061
1131
|
t.push(`${e.stale.length} .nonReactive() table(s) still carry a change trigger — ${n}. They keep paying REPLICA IDENTITY FULL and a NOTIFY on every write for a subscription nobody receives. \`voltro db apply\` removes them.`);
|
|
1062
1132
|
}
|
|
1063
1133
|
return e.functionOutdated && t.push("The change-notify function in this database is OLDER than the framework installed here. Its triggers fire, so nothing looks wrong — but a row too large for a NOTIFY payload (postgres caps it at 8000 bytes) is emitted without its primary key, and a change that carries no key cannot be re-read: it reaches subscriptions as a re-query and reaches every TAP — search index, analytics mirror, cdc-out, row history — as nothing at all. Run `voltro db apply` to replace it."), t.length > 0 ? t.join("\n") : void 0;
|
|
1064
|
-
},
|
|
1134
|
+
}, pn = {
|
|
1065
1135
|
postgres: !0,
|
|
1066
1136
|
mysql: !0,
|
|
1067
1137
|
mariadb: !0,
|
|
1068
1138
|
mssql: !0,
|
|
1069
1139
|
sqlite: !0
|
|
1070
|
-
},
|
|
1140
|
+
}, mn = {
|
|
1071
1141
|
postgres: !0,
|
|
1072
1142
|
mysql: !1,
|
|
1073
1143
|
mariadb: !1,
|
|
1074
1144
|
mssql: !0,
|
|
1075
1145
|
sqlite: !0
|
|
1076
|
-
},
|
|
1146
|
+
}, hn = (e) => {
|
|
1077
1147
|
switch (e) {
|
|
1078
1148
|
case "add-column":
|
|
1079
1149
|
case "drop-column":
|
|
@@ -1083,80 +1153,33 @@ BEGIN
|
|
|
1083
1153
|
case "add-foreign-key":
|
|
1084
1154
|
case "add-unique":
|
|
1085
1155
|
case "add-unique-composite":
|
|
1086
|
-
case "add-check": return
|
|
1087
|
-
default: return
|
|
1156
|
+
case "add-check": return mn;
|
|
1157
|
+
default: return pn;
|
|
1088
1158
|
}
|
|
1089
|
-
},
|
|
1159
|
+
}, gn = (e, t) => {
|
|
1090
1160
|
let n = new Map(t.tables.map((e) => [e.name, e]));
|
|
1091
1161
|
return new Map(e.map((e) => [e.tableName, {
|
|
1092
1162
|
table: e,
|
|
1093
1163
|
snapshot: n.get(e.tableName),
|
|
1094
1164
|
columnDefs: e.fields
|
|
1095
1165
|
}]));
|
|
1096
|
-
},
|
|
1097
|
-
|
|
1098
|
-
if (Array.isArray(e)) return `[${e.map(I).join(",")}]`;
|
|
1099
|
-
let t = e;
|
|
1100
|
-
return `{${Object.keys(t).sort().map((e) => `${JSON.stringify(e)}:${I(t[e])}`).join(",")}}`;
|
|
1101
|
-
}, fn = (e) => {
|
|
1102
|
-
if (!e.hasDefault || e.defaultValue === void 0 || e.defaultValue === null) return null;
|
|
1103
|
-
let t = e.defaultValue;
|
|
1104
|
-
if (typeof t == "boolean") return t ? "__BOOL_TRUE__" : "__BOOL_FALSE__";
|
|
1105
|
-
if (typeof t == "number") return String(t);
|
|
1106
|
-
if (typeof t != "string") return I(t);
|
|
1107
|
-
let n = t.trim(), r = n.toLowerCase().replace(/\s+/g, "");
|
|
1108
|
-
if (r === "now" || r === "now()" || /^current_timestamp(\(\d*\))?$/.test(r) || r === "sysutcdatetime()" || r === "sysdatetime()" || r === "getutcdate()" || r === "getdate()") return "__NOW__";
|
|
1109
|
-
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);
|
|
1110
|
-
if (o) try {
|
|
1111
|
-
return I(JSON.parse(o[1]));
|
|
1112
|
-
} catch {}
|
|
1113
|
-
let s = /^convert\(\s*(?:_\w+\s*)?\\?'(.*?)\\?'\s+using\s+[\w]+\s*\)$/i.exec(a);
|
|
1114
|
-
if (s) try {
|
|
1115
|
-
return I(JSON.parse(s[1]));
|
|
1116
|
-
} catch {}
|
|
1117
|
-
if (a.startsWith("{") || a.startsWith("[")) try {
|
|
1118
|
-
return I(JSON.parse(a));
|
|
1119
|
-
} catch {}
|
|
1120
|
-
return /^-?\d+(\.\d+)?$/.test(a) ? String(Number(a)) : a;
|
|
1121
|
-
}, pn = (e, t) => {
|
|
1122
|
-
let n = fn(e), r = fn(t);
|
|
1166
|
+
}, _n = (e, t) => {
|
|
1167
|
+
let n = Wt(e), r = Wt(t);
|
|
1123
1168
|
if (n === r) return !0;
|
|
1124
|
-
let i =
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
return o(n) === o(r);
|
|
1128
|
-
}, mn = (e) => {
|
|
1129
|
-
if (!e) return null;
|
|
1130
|
-
let t = (e) => e === "restrict" ? "noAction" : e;
|
|
1131
|
-
return {
|
|
1132
|
-
table: e.table,
|
|
1133
|
-
column: e.column,
|
|
1134
|
-
onDelete: t(e.onDelete),
|
|
1135
|
-
onUpdate: t(e.onUpdate)
|
|
1136
|
-
};
|
|
1137
|
-
}, hn = (e, t) => {
|
|
1169
|
+
let i = Kt, a = (e) => e.type === "id" && e.idScheme?.kind === "numeric";
|
|
1170
|
+
return e.type === "id" && t.type === "id" && (a(e) && n === null && i(t) || a(t) && r === null && i(e)) ? !0 : Gt(e) === Gt(t);
|
|
1171
|
+
}, vn = (e, t) => {
|
|
1138
1172
|
let n = e && e.length > 0 ? e : void 0, r = t && t.length > 0 ? t : void 0;
|
|
1139
1173
|
if (!n && !r) return !0;
|
|
1140
1174
|
if (!n || !r || n.length !== r.length) return !1;
|
|
1141
1175
|
let i = [...n].sort(), a = [...r].sort();
|
|
1142
1176
|
return i.every((e, t) => e === a[t]);
|
|
1143
|
-
},
|
|
1144
|
-
if (t === "mssql") {
|
|
1145
|
-
let t = nt(e, n);
|
|
1146
|
-
if (t !== void 0) return t;
|
|
1147
|
-
}
|
|
1148
|
-
try {
|
|
1149
|
-
let n = /\((\d+)\)/.exec(j(e, t));
|
|
1150
|
-
return n ? Number(n[1]) : void 0;
|
|
1151
|
-
} catch {
|
|
1152
|
-
return;
|
|
1153
|
-
}
|
|
1154
|
-
}, _n = (e, t, n, r) => n === void 0 || m(n) ? !0 : e.type !== "text" || t.type !== "text" || gn(e, n, r) === t.maxLength, vn = (e, t, n, r) => e.type === t.type && e.nullable === t.nullable && e.unique === t.unique && pn(e, t) && _n(e, t, n, r) && (e.type !== "reference" || (e.referenceStorage ?? "text") === (t.referenceStorage ?? "text")) && JSON.stringify(mn(e.references)) === JSON.stringify(mn(t.references)) && hn(e.oneOf, t.oneOf), yn = (e, t) => t.oneOf && t.oneOf.length > 0 ? L({
|
|
1177
|
+
}, yn = (e, t, n, r) => n === void 0 || m(n) ? !0 : e.type !== "text" || t.type !== "text" || Jt(e, n, r) === t.maxLength, bn = (e, t, n, r) => e.type === t.type && e.nullable === t.nullable && e.unique === t.unique && _n(e, t) && yn(e, t, n, r) && (e.type !== "reference" || (e.referenceStorage ?? "text") === (t.referenceStorage ?? "text")) && JSON.stringify(qt(e.references)) === JSON.stringify(qt(t.references)) && vn(e.oneOf, t.oneOf), xn = (e, t) => t.oneOf && t.oneOf.length > 0 ? z({
|
|
1155
1178
|
kind: "add-check",
|
|
1156
1179
|
table: e,
|
|
1157
1180
|
column: t.name,
|
|
1158
1181
|
values: t.oneOf
|
|
1159
|
-
}, "safe", `enum-membership CHECK on ${e}.${t.name}`) : void 0,
|
|
1182
|
+
}, "safe", `enum-membership CHECK on ${e}.${t.name}`) : void 0, Sn = (e, t) => e.unique === t.unique && e.valid !== !1 && t.valid !== !1 && Zt(e.where) === Zt(t.where) && (e.expression || t.expression ? !0 : e.columns.length === t.columns.length && e.columns.every((e, n) => e === t.columns[n])), Cn = (e, t, n) => {
|
|
1160
1183
|
let r = new Map(t.columns.map((e) => [e.name, e])), i = new Map(e.columns.map((e) => [e.name, e])), a = [], o = [], s = [], c = new Set(e.indexes.flatMap((e) => e.columns));
|
|
1161
1184
|
for (let t of e.columns) {
|
|
1162
1185
|
let e = r.get(t.name);
|
|
@@ -1164,7 +1187,7 @@ BEGIN
|
|
|
1164
1187
|
a.push(t);
|
|
1165
1188
|
continue;
|
|
1166
1189
|
}
|
|
1167
|
-
|
|
1190
|
+
bn(t, e, n, c.has(t.name) || t.unique) || s.push({
|
|
1168
1191
|
declared: t,
|
|
1169
1192
|
live: e
|
|
1170
1193
|
});
|
|
@@ -1175,50 +1198,50 @@ BEGIN
|
|
|
1175
1198
|
removed: o,
|
|
1176
1199
|
changed: s
|
|
1177
1200
|
};
|
|
1178
|
-
},
|
|
1201
|
+
}, wn = (e, t, n) => {
|
|
1179
1202
|
let r = (e) => n === "turso" || n === "sqlite" ? e.toLowerCase() : e, i = new Map(t.indexes.map((e) => [r(e.name), e])), a = new Map(e.indexes.map((e) => [r(e.name), e])), o = [], s = [];
|
|
1180
1203
|
for (let t of e.indexes) {
|
|
1181
1204
|
let e = i.get(r(t.name));
|
|
1182
|
-
(!e || !
|
|
1205
|
+
(!e || !Sn(t, e)) && o.push(t);
|
|
1183
1206
|
}
|
|
1184
1207
|
for (let e of t.indexes) {
|
|
1185
1208
|
let t = a.get(r(e.name));
|
|
1186
|
-
(!t || (e.where !== void 0 || t.where !== void 0) && !
|
|
1209
|
+
(!t || (e.where !== void 0 || t.where !== void 0) && !Sn(t, e)) && s.push(e);
|
|
1187
1210
|
}
|
|
1188
1211
|
return {
|
|
1189
1212
|
added: o,
|
|
1190
1213
|
removed: s
|
|
1191
1214
|
};
|
|
1192
|
-
},
|
|
1215
|
+
}, z = (e, t, n, r) => ({
|
|
1193
1216
|
op: e,
|
|
1194
1217
|
classification: t,
|
|
1195
|
-
atomicByDialect:
|
|
1218
|
+
atomicByDialect: hn(e.kind),
|
|
1196
1219
|
...n ? { reason: n } : {},
|
|
1197
1220
|
...r ? { blocked: r } : {}
|
|
1198
|
-
}),
|
|
1221
|
+
}), Tn = (e, t, n) => {
|
|
1199
1222
|
let r = {
|
|
1200
1223
|
kind: "add-column",
|
|
1201
1224
|
table: e,
|
|
1202
1225
|
column: t
|
|
1203
1226
|
};
|
|
1204
|
-
return t.nullable ?
|
|
1205
|
-
},
|
|
1227
|
+
return t.nullable ? z(r, "safe", "nullable column add — no backfill needed") : t.hasDefault && t.defaultValue !== void 0 ? z(r, "needs-default", "NOT NULL with literal default — DDL DEFAULT will populate existing rows") : n?.backfill ? z(r, "needs-backfill", `backfill declared (kind=${n.backfill.kind}) — applier will run 3-step add/update/set-not-null`) : z(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` });
|
|
1228
|
+
}, En = (e, t, n) => {
|
|
1206
1229
|
let r = {
|
|
1207
1230
|
kind: "drop-column",
|
|
1208
1231
|
table: e,
|
|
1209
1232
|
column: t.name
|
|
1210
1233
|
};
|
|
1211
|
-
return n?.dropped ?
|
|
1212
|
-
},
|
|
1234
|
+
return n?.dropped ? z(r, "lossy", `column dropped via \`${t.name}: dropped()\` marker — intentional`) : z(r, "lossy", "column missing from declared schema", { fix: `if intentional, add \`${t.name}: dropped()\` to the schema. If a typo, restore the field` });
|
|
1235
|
+
}, Dn = (e, t, n, r, i) => z({
|
|
1213
1236
|
kind: "create-table",
|
|
1214
1237
|
table: e,
|
|
1215
1238
|
columns: t,
|
|
1216
1239
|
indexes: n,
|
|
1217
1240
|
...r && r.length > 0 ? { primaryKey: r } : {}
|
|
1218
|
-
}, "safe", i ?? "new table — no data to preserve"),
|
|
1241
|
+
}, "safe", i ?? "new table — no data to preserve"), On = (e) => z({
|
|
1219
1242
|
kind: "drop-table",
|
|
1220
1243
|
table: e
|
|
1221
|
-
}, "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" }),
|
|
1244
|
+
}, "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" }), kn = 5e4, An = (e, t, n, r) => {
|
|
1222
1245
|
let i = (n ?? 0) >= r, a;
|
|
1223
1246
|
return a = !t.unique || t.where !== void 0 ? {
|
|
1224
1247
|
kind: "add-index",
|
|
@@ -1233,16 +1256,16 @@ BEGIN
|
|
|
1233
1256
|
table: e,
|
|
1234
1257
|
name: t.name,
|
|
1235
1258
|
fields: t.columns
|
|
1236
|
-
}, i ?
|
|
1237
|
-
},
|
|
1259
|
+
}, i ? z(a, "online-required", `online build on ${n} rows — CONCURRENTLY / INPLACE / WITH(ONLINE=ON) depending on dialect`) : z(a, "safe", t.where === void 0 ? t.unique ? t.columns.length === 1 ? "add unique constraint" : "add composite UNIQUE constraint" : "add B-tree index" : `add ${t.unique ? "unique " : ""}partial index`);
|
|
1260
|
+
}, jn = (e, t) => t.unique && t.where === void 0 && t.columns.length > 1 ? z({
|
|
1238
1261
|
kind: "drop-unique-composite",
|
|
1239
1262
|
table: e,
|
|
1240
1263
|
name: t.name
|
|
1241
|
-
}, "safe", "drop composite UNIQUE constraint (no data loss — constraint is derived metadata)") :
|
|
1264
|
+
}, "safe", "drop composite UNIQUE constraint (no data loss — constraint is derived metadata)") : z({
|
|
1242
1265
|
kind: "drop-index",
|
|
1243
1266
|
table: e,
|
|
1244
1267
|
index: t.name
|
|
1245
|
-
}, "safe", "drop index (no data loss — index is derived data)"),
|
|
1268
|
+
}, "safe", "drop index (no data loss — index is derived data)"), Mn = (e, t) => {
|
|
1246
1269
|
let n = e.type;
|
|
1247
1270
|
if (n === "reference") return e.referenceStorage === "numeric" ? "bigint" : "text";
|
|
1248
1271
|
switch (t) {
|
|
@@ -1251,10 +1274,10 @@ BEGIN
|
|
|
1251
1274
|
case "mssql": return n === "json" ? "text" : n;
|
|
1252
1275
|
default: return n;
|
|
1253
1276
|
}
|
|
1254
|
-
},
|
|
1277
|
+
}, Nn = (e, t, n) => {
|
|
1255
1278
|
let r = `acknowledge it on the column: \`.narrowedFrom('${e}')\``;
|
|
1256
1279
|
return n === "postgres" ? `${r} — add \`{ using: '${t.name}::${t.type}' }\` when the cast is not implicit, or use a file-based migration` : `${r} — ${n === void 0 ? "this dialect" : n} converts in place (\`using\` is postgres-only and is ignored here), so verify the conversion is value-preserving for your data, or use a file-based migration`;
|
|
1257
|
-
},
|
|
1280
|
+
}, Pn = (e, t, n, r, i, a) => {
|
|
1258
1281
|
let o = [];
|
|
1259
1282
|
if (t.nullable !== n.nullable) {
|
|
1260
1283
|
let n = {
|
|
@@ -1263,7 +1286,7 @@ BEGIN
|
|
|
1263
1286
|
column: t.name,
|
|
1264
1287
|
toNullable: t.nullable
|
|
1265
1288
|
};
|
|
1266
|
-
o.push(t.nullable ?
|
|
1289
|
+
o.push(t.nullable ? z(n, "safe", `loosen ${e}.${t.name} to nullable`) : z(n, "needs-backfill", `tighten ${e}.${t.name} to NOT NULL — existing rows must already be non-null`));
|
|
1267
1290
|
}
|
|
1268
1291
|
if (t.unique !== n.unique) {
|
|
1269
1292
|
if (t.unique) {
|
|
@@ -1272,14 +1295,14 @@ BEGIN
|
|
|
1272
1295
|
table: e,
|
|
1273
1296
|
column: t.name
|
|
1274
1297
|
}, r = (i ?? 0) >= a;
|
|
1275
|
-
o.push(r ?
|
|
1276
|
-
} else o.push(
|
|
1298
|
+
o.push(r ? z(n, "online-required", `online unique build on ${i} rows — CONCURRENTLY / INPLACE / WITH(ONLINE=ON) depending on dialect`) : z(n, "safe", `add unique constraint on ${e}.${t.name} — existing rows must already be distinct (else the DB rejects at migrate)`));
|
|
1299
|
+
} else o.push(z({
|
|
1277
1300
|
kind: "drop-unique",
|
|
1278
1301
|
table: e,
|
|
1279
1302
|
column: t.name
|
|
1280
1303
|
}, "safe", `drop unique constraint on ${e}.${t.name} — constraint is derived metadata, no data loss`));
|
|
1281
1304
|
}
|
|
1282
|
-
if (
|
|
1305
|
+
if (Mn(t, r) !== Mn(n, r)) {
|
|
1283
1306
|
let i = t.narrowedFrom;
|
|
1284
1307
|
if (i && i.from === n.type) {
|
|
1285
1308
|
let r = {
|
|
@@ -1290,7 +1313,7 @@ BEGIN
|
|
|
1290
1313
|
to: t.type,
|
|
1291
1314
|
...i.using === void 0 ? {} : { using: i.using }
|
|
1292
1315
|
};
|
|
1293
|
-
o.push(
|
|
1316
|
+
o.push(z(r, "needs-backfill", `type change ${n.type} → ${t.type} on ${e}.${t.name} — narrowedFrom('${i.from}') declared` + (i.using ? ` with USING ${i.using}` : " (implicit cast)")));
|
|
1294
1317
|
} else {
|
|
1295
1318
|
let i = {
|
|
1296
1319
|
kind: "alter-column-type",
|
|
@@ -1299,12 +1322,12 @@ BEGIN
|
|
|
1299
1322
|
from: n.type,
|
|
1300
1323
|
to: t.type
|
|
1301
1324
|
};
|
|
1302
|
-
o.push(
|
|
1325
|
+
o.push(z(i, "lossy", `type change ${n.type} → ${t.type} on ${e}.${t.name} may not be value-preserving`, { fix: Nn(n.type, t, r) }));
|
|
1303
1326
|
}
|
|
1304
1327
|
}
|
|
1305
1328
|
if (t.type === "text" && n.type === "text" && !m(r ?? "postgres") && t.maxLength !== n.maxLength) {
|
|
1306
1329
|
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})`;
|
|
1307
|
-
o.push(
|
|
1330
|
+
o.push(z({
|
|
1308
1331
|
kind: "alter-column-type",
|
|
1309
1332
|
table: e,
|
|
1310
1333
|
column: t.name,
|
|
@@ -1312,7 +1335,7 @@ BEGIN
|
|
|
1312
1335
|
to: "text"
|
|
1313
1336
|
}, r ? "safe" : "needs-backfill", r ? `text length ${i} → ${a} on ${e}.${t.name} — widening, no data can be lost` : `text length ${i} → ${a} on ${e}.${t.name} — NARROWING; the ALTER fails if any existing value is longer than ${String(t.maxLength)}. Check first: SELECT COUNT(*) FROM ${e} WHERE LENGTH(${t.name}) > ${String(t.maxLength)}`));
|
|
1314
1337
|
}
|
|
1315
|
-
if (!
|
|
1338
|
+
if (!_n(t, n)) {
|
|
1316
1339
|
let n = {
|
|
1317
1340
|
kind: "alter-column-default",
|
|
1318
1341
|
table: e,
|
|
@@ -1320,23 +1343,23 @@ BEGIN
|
|
|
1320
1343
|
hasDefault: t.hasDefault,
|
|
1321
1344
|
...t.defaultValue === void 0 ? {} : { defaultValue: t.defaultValue }
|
|
1322
1345
|
};
|
|
1323
|
-
o.push(
|
|
1346
|
+
o.push(z(n, "safe", `default change on ${e}.${t.name} affects only future inserts`));
|
|
1324
1347
|
}
|
|
1325
|
-
if (!
|
|
1326
|
-
n.oneOf && n.oneOf.length > 0 && o.push(
|
|
1348
|
+
if (!vn(t.oneOf, n.oneOf)) {
|
|
1349
|
+
n.oneOf && n.oneOf.length > 0 && o.push(z({
|
|
1327
1350
|
kind: "drop-check",
|
|
1328
1351
|
table: e,
|
|
1329
1352
|
column: t.name
|
|
1330
1353
|
}, "safe", `drop stale enum CHECK on ${e}.${t.name}`));
|
|
1331
|
-
let r =
|
|
1354
|
+
let r = xn(e, t);
|
|
1332
1355
|
r && o.push(r);
|
|
1333
1356
|
}
|
|
1334
|
-
return JSON.stringify(
|
|
1357
|
+
return JSON.stringify(qt(t.references)) !== JSON.stringify(qt(n.references)) && (n.references && o.push(z({
|
|
1335
1358
|
kind: "drop-foreign-key",
|
|
1336
1359
|
table: e,
|
|
1337
1360
|
column: t.name
|
|
1338
|
-
}, "safe", `drop FK on ${e}.${t.name} (→ ${n.references.table})`)), o.push(...
|
|
1339
|
-
},
|
|
1361
|
+
}, "safe", `drop FK on ${e}.${t.name} (→ ${n.references.table})`)), o.push(...Fn(e, t))), o;
|
|
1362
|
+
}, Fn = (e, t) => {
|
|
1340
1363
|
let n = [];
|
|
1341
1364
|
if (!t.references) return n;
|
|
1342
1365
|
let r = t.references.table, i = t.references.orphanPolicy ?? "fail", a = {
|
|
@@ -1348,15 +1371,15 @@ BEGIN
|
|
|
1348
1371
|
...t.references.onDelete ? { onDelete: t.references.onDelete } : {},
|
|
1349
1372
|
...t.references.onUpdate ? { onUpdate: t.references.onUpdate } : {}
|
|
1350
1373
|
};
|
|
1351
|
-
return i === "null" && !t.nullable ? n.push(
|
|
1374
|
+
return i === "null" && !t.nullable ? n.push(z(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(z({
|
|
1352
1375
|
...a,
|
|
1353
1376
|
orphanPolicy: i
|
|
1354
|
-
}, "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(
|
|
1355
|
-
},
|
|
1377
|
+
}, "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(z(a, "needs-backfill", `add FK ${e}.${t.name} → ${r} — existing rows must already reference a valid ${r} (else set orphanPolicy:'null'/'delete')`)), n;
|
|
1378
|
+
}, In = (e, t, n) => {
|
|
1356
1379
|
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));
|
|
1357
1380
|
for (let [n, c] of Object.entries(t)) {
|
|
1358
1381
|
let t = c.renamedFrom;
|
|
1359
|
-
t && o.has(t) && s.has(n) && (i.add(n), a.add(t), r.push(
|
|
1382
|
+
t && o.has(t) && s.has(n) && (i.add(n), a.add(t), r.push(z({
|
|
1360
1383
|
kind: "rename-column",
|
|
1361
1384
|
table: e.tableName,
|
|
1362
1385
|
from: t,
|
|
@@ -1368,26 +1391,26 @@ BEGIN
|
|
|
1368
1391
|
consumedAddedNames: i,
|
|
1369
1392
|
consumedRemovedNames: a
|
|
1370
1393
|
};
|
|
1371
|
-
},
|
|
1394
|
+
}, Ln = /* @__PURE__ */ new Set([
|
|
1372
1395
|
"postgres",
|
|
1373
1396
|
"mysql",
|
|
1374
1397
|
"mariadb",
|
|
1375
1398
|
"mssql"
|
|
1376
|
-
]),
|
|
1399
|
+
]), Rn = {
|
|
1377
1400
|
ops: [],
|
|
1378
1401
|
consumedAddedNames: /* @__PURE__ */ new Set(),
|
|
1379
1402
|
consumedRemovedNames: /* @__PURE__ */ new Set()
|
|
1380
|
-
},
|
|
1381
|
-
if (i === void 0 || !
|
|
1382
|
-
let a = t.added.filter((e) =>
|
|
1383
|
-
if (a.length === 0) return
|
|
1403
|
+
}, zn = (e) => !e.unique && !e.expression && e.where === void 0, Bn = (e, t, n, r, i) => {
|
|
1404
|
+
if (i === void 0 || !Ln.has(i)) return Rn;
|
|
1405
|
+
let a = t.added.filter((e) => zn(e) && !r.has(e.name));
|
|
1406
|
+
if (a.length === 0) return Rn;
|
|
1384
1407
|
let o = (e) => e.columns.map((e) => n.get(e) ?? e).join("\0"), s = (e) => e.columns.join("\0"), c = [], l = /* @__PURE__ */ new Set(), u = /* @__PURE__ */ new Set();
|
|
1385
1408
|
for (let n of t.removed) {
|
|
1386
|
-
if (!
|
|
1409
|
+
if (!zn(n)) continue;
|
|
1387
1410
|
let t = o(n), r = a.filter((e) => !l.has(e.name) && s(e) === t);
|
|
1388
1411
|
if (r.length !== 1) continue;
|
|
1389
1412
|
let i = r[0];
|
|
1390
|
-
i.name !== n.name && (l.add(i.name), u.add(n.name), c.push(
|
|
1413
|
+
i.name !== n.name && (l.add(i.name), u.add(n.name), c.push(z({
|
|
1391
1414
|
kind: "rename-index",
|
|
1392
1415
|
table: e,
|
|
1393
1416
|
from: n.name,
|
|
@@ -1399,7 +1422,7 @@ BEGIN
|
|
|
1399
1422
|
consumedAddedNames: l,
|
|
1400
1423
|
consumedRemovedNames: u
|
|
1401
1424
|
};
|
|
1402
|
-
},
|
|
1425
|
+
}, Vn = (e, t, n) => {
|
|
1403
1426
|
let r = [], i = /* @__PURE__ */ new Map(), a = /* @__PURE__ */ new Set(), o = /* @__PURE__ */ new Map(), s = /* @__PURE__ */ new Map(), c = /* @__PURE__ */ new Set();
|
|
1404
1427
|
for (let t of e.tables) t.renamedFrom !== void 0 && (s.set(t.renamedFrom, (s.get(t.renamedFrom) ?? 0) + 1), c.add(t.renamedFrom));
|
|
1405
1428
|
for (let c of e.tables) {
|
|
@@ -1410,7 +1433,7 @@ BEGIN
|
|
|
1410
1433
|
continue;
|
|
1411
1434
|
}
|
|
1412
1435
|
if (t.has(c.name)) {
|
|
1413
|
-
r.push(
|
|
1436
|
+
r.push(z({
|
|
1414
1437
|
kind: "rename-table",
|
|
1415
1438
|
from: e,
|
|
1416
1439
|
to: c.name
|
|
@@ -1418,14 +1441,14 @@ BEGIN
|
|
|
1418
1441
|
continue;
|
|
1419
1442
|
}
|
|
1420
1443
|
if ((s.get(e) ?? 0) !== 1) {
|
|
1421
|
-
r.push(
|
|
1444
|
+
r.push(z({
|
|
1422
1445
|
kind: "rename-table",
|
|
1423
1446
|
from: e,
|
|
1424
1447
|
to: c.name
|
|
1425
1448
|
}, "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.` }));
|
|
1426
1449
|
continue;
|
|
1427
1450
|
}
|
|
1428
|
-
i.set(c.name, e), a.add(e), r.push(
|
|
1451
|
+
i.set(c.name, e), a.add(e), r.push(z({
|
|
1429
1452
|
kind: "rename-table",
|
|
1430
1453
|
from: e,
|
|
1431
1454
|
to: c.name
|
|
@@ -1439,19 +1462,19 @@ BEGIN
|
|
|
1439
1462
|
claimedOldNames: c,
|
|
1440
1463
|
refusals: o
|
|
1441
1464
|
};
|
|
1442
|
-
},
|
|
1465
|
+
}, Hn = (e, t, n, r) => {
|
|
1443
1466
|
if (t === void 0) return {
|
|
1444
1467
|
live: e,
|
|
1445
1468
|
ops: []
|
|
1446
1469
|
};
|
|
1447
|
-
let i = r !== void 0 &&
|
|
1470
|
+
let i = r !== void 0 && Ln.has(r), a = [], o = e.indexes.map((e) => {
|
|
1448
1471
|
if (!e.name.startsWith(t)) return e;
|
|
1449
1472
|
let r = `${n}${e.name.slice(t.length)}`;
|
|
1450
1473
|
return r === e.name ? e : e.name === `${t}_pkey` ? {
|
|
1451
1474
|
...e,
|
|
1452
1475
|
name: r,
|
|
1453
1476
|
table: n
|
|
1454
|
-
} : i ? (a.push(
|
|
1477
|
+
} : i ? (a.push(z({
|
|
1455
1478
|
kind: "rename-index",
|
|
1456
1479
|
table: n,
|
|
1457
1480
|
from: e.name,
|
|
@@ -1470,7 +1493,7 @@ BEGIN
|
|
|
1470
1493
|
},
|
|
1471
1494
|
ops: a
|
|
1472
1495
|
};
|
|
1473
|
-
},
|
|
1496
|
+
}, Un = (e) => {
|
|
1474
1497
|
let t = {
|
|
1475
1498
|
safe: 0,
|
|
1476
1499
|
needsDefault: 0,
|
|
@@ -1503,51 +1526,69 @@ BEGIN
|
|
|
1503
1526
|
case "multi-step": t.multiStep++;
|
|
1504
1527
|
}
|
|
1505
1528
|
return t;
|
|
1506
|
-
},
|
|
1507
|
-
let t =
|
|
1529
|
+
}, Wn = (e) => {
|
|
1530
|
+
let t = R(e.declared, e.dialect), n = gn(e.declared, t), r = new Map(e.live.tables.map((e) => [e.name, e])), i = e.onlineAfter ?? kn, a = [], o = Vn(t, r, n);
|
|
1508
1531
|
a.push(...o.ops);
|
|
1509
1532
|
for (let e of t.tables) if (!o.renamedInto.has(e.name) && !r.has(e.name)) {
|
|
1510
|
-
a.push(
|
|
1533
|
+
a.push(Dn(e.name, e.columns, e.indexes, e.primaryKey, o.refusals.get(e.name)));
|
|
1511
1534
|
for (let t of e.columns) {
|
|
1512
|
-
let n =
|
|
1535
|
+
let n = xn(e.name, t);
|
|
1513
1536
|
n && a.push(n);
|
|
1514
1537
|
}
|
|
1515
1538
|
}
|
|
1516
|
-
let s = new Set(e.ignoreTables ?? []);
|
|
1517
|
-
for (let t of e.live.tables) n.has(t.name)
|
|
1539
|
+
let s = new Set(e.ignoreTables ?? []), c = [];
|
|
1540
|
+
for (let t of e.live.tables) if (!n.has(t.name)) {
|
|
1541
|
+
if (o.claimedOldNames.has(t.name)) {
|
|
1542
|
+
c.push(t.name);
|
|
1543
|
+
continue;
|
|
1544
|
+
}
|
|
1545
|
+
if (_(t.name)) {
|
|
1546
|
+
c.push(t.name);
|
|
1547
|
+
continue;
|
|
1548
|
+
}
|
|
1549
|
+
if (x(t.name)) {
|
|
1550
|
+
c.push(t.name);
|
|
1551
|
+
continue;
|
|
1552
|
+
}
|
|
1553
|
+
if (s.has(t.name)) {
|
|
1554
|
+
c.push(t.name);
|
|
1555
|
+
continue;
|
|
1556
|
+
}
|
|
1557
|
+
a.push(On(t.name));
|
|
1558
|
+
}
|
|
1518
1559
|
for (let s of t.tables) {
|
|
1519
1560
|
let t = o.renamedInto.get(s.name), c = r.get(s.name) ?? (t === void 0 ? void 0 : r.get(t));
|
|
1520
1561
|
if (!c) continue;
|
|
1521
|
-
let l =
|
|
1562
|
+
let l = Hn(c, t, s.name, e.dialect);
|
|
1522
1563
|
a.push(...l.ops);
|
|
1523
|
-
let u = l.live, d = n.get(s.name), f =
|
|
1564
|
+
let u = l.live, d = n.get(s.name), f = Cn(s, u, e.dialect), p = wn(s, u, e.dialect), m = In(d.table, d.columnDefs, f);
|
|
1524
1565
|
a.push(...m.ops);
|
|
1525
1566
|
for (let e of f.removed) {
|
|
1526
1567
|
if (m.consumedRemovedNames.has(e.name) || x(e.name)) continue;
|
|
1527
1568
|
let t = d.columnDefs[e.name];
|
|
1528
|
-
a.push(
|
|
1569
|
+
a.push(En(s.name, e, t));
|
|
1529
1570
|
}
|
|
1530
1571
|
for (let e of f.added) {
|
|
1531
1572
|
if (m.consumedAddedNames.has(e.name)) continue;
|
|
1532
1573
|
let t = d.columnDefs[e.name];
|
|
1533
|
-
a.push(
|
|
1534
|
-
let n =
|
|
1535
|
-
n && a.push(n), a.push(...
|
|
1574
|
+
a.push(Tn(s.name, e, t));
|
|
1575
|
+
let n = xn(s.name, e);
|
|
1576
|
+
n && a.push(n), a.push(...Fn(s.name, e));
|
|
1536
1577
|
}
|
|
1537
|
-
let h = new Map(m.ops.flatMap((e) => e.op.kind === "rename-column" ? [[e.op.from, e.op.to]] : [])), g =
|
|
1578
|
+
let h = new Map(m.ops.flatMap((e) => e.op.kind === "rename-column" ? [[e.op.from, e.op.to]] : [])), g = Bn(s.name, p, h, new Set(u.indexes.map((e) => e.name)), e.dialect);
|
|
1538
1579
|
a.push(...g.ops);
|
|
1539
|
-
for (let e of p.added) g.consumedAddedNames.has(e.name) || a.push(
|
|
1540
|
-
for (let e of p.removed) g.consumedRemovedNames.has(e.name) || a.push(
|
|
1541
|
-
for (let { declared: t, live: n } of f.changed) a.push(...
|
|
1580
|
+
for (let e of p.added) g.consumedAddedNames.has(e.name) || a.push(An(s.name, e, u.rowCount, i));
|
|
1581
|
+
for (let e of p.removed) g.consumedRemovedNames.has(e.name) || a.push(jn(s.name, e));
|
|
1582
|
+
for (let { declared: t, live: n } of f.changed) a.push(...Pn(s.name, t, n, e.dialect, u.rowCount, i));
|
|
1542
1583
|
}
|
|
1543
|
-
let
|
|
1544
|
-
let t =
|
|
1545
|
-
return t ? t.columns.flatMap((e) => e.references &&
|
|
1584
|
+
let l = new Set(a.flatMap((e) => e.op.kind === "create-table" ? [e.op.table] : [])), u = new Map(t.tables.map((e) => [e.name, e])), d = (e) => {
|
|
1585
|
+
let t = u.get(e);
|
|
1586
|
+
return t ? t.columns.flatMap((e) => e.references && l.has(e.references.table) ? [{
|
|
1546
1587
|
column: e.name,
|
|
1547
1588
|
target: e.references.table
|
|
1548
1589
|
}] : []) : [];
|
|
1549
|
-
},
|
|
1550
|
-
for (let e of t.tables) if (
|
|
1590
|
+
}, f = me([...l], d), p = [];
|
|
1591
|
+
for (let e of t.tables) if (l.has(e.name)) for (let t of e.columns) t.references && f.has(D(e.name, t.name)) && p.push(z({
|
|
1551
1592
|
kind: "add-foreign-key",
|
|
1552
1593
|
table: e.name,
|
|
1553
1594
|
column: t.name,
|
|
@@ -1556,14 +1597,14 @@ BEGIN
|
|
|
1556
1597
|
...t.references.onDelete ? { onDelete: t.references.onDelete } : {},
|
|
1557
1598
|
...t.references.onUpdate ? { onUpdate: t.references.onUpdate } : {}
|
|
1558
1599
|
}, "safe", `deferred FK ${e.name}.${t.name} → ${t.references.table} — breaks a create-time table cycle`));
|
|
1559
|
-
if (
|
|
1600
|
+
if (f.size > 0) {
|
|
1560
1601
|
let e = (e) => e.references ? Object.fromEntries(Object.entries(e).filter(([e]) => e !== "references")) : e;
|
|
1561
1602
|
for (let t = 0; t < a.length; t += 1) {
|
|
1562
1603
|
let n = a[t];
|
|
1563
1604
|
if (n.op.kind !== "create-table") continue;
|
|
1564
1605
|
let r = n.op;
|
|
1565
|
-
if (!r.columns.some((e) =>
|
|
1566
|
-
let i = r.columns.map((t) =>
|
|
1606
|
+
if (!r.columns.some((e) => f.has(D(r.table, e.name)))) continue;
|
|
1607
|
+
let i = r.columns.map((t) => f.has(D(r.table, t.name)) ? e(t) : t);
|
|
1567
1608
|
a[t] = {
|
|
1568
1609
|
...n,
|
|
1569
1610
|
op: {
|
|
@@ -1572,24 +1613,24 @@ BEGIN
|
|
|
1572
1613
|
}
|
|
1573
1614
|
};
|
|
1574
1615
|
}
|
|
1575
|
-
a.push(...
|
|
1616
|
+
a.push(...p);
|
|
1576
1617
|
}
|
|
1577
|
-
let
|
|
1578
|
-
let n =
|
|
1618
|
+
let m = new Map(t.tables.map((e) => [e.name, e])), h = /* @__PURE__ */ new Map(), g = (e, t = /* @__PURE__ */ new Set()) => {
|
|
1619
|
+
let n = h.get(e);
|
|
1579
1620
|
if (n !== void 0) return n;
|
|
1580
1621
|
if (t.has(e)) return 0;
|
|
1581
|
-
let r =
|
|
1622
|
+
let r = m.get(e);
|
|
1582
1623
|
if (!r) return 0;
|
|
1583
1624
|
let i = new Set(t).add(e), a = 0;
|
|
1584
1625
|
for (let t of r.columns) {
|
|
1585
1626
|
let n = t.references?.table;
|
|
1586
|
-
n && n !== e && !
|
|
1627
|
+
n && n !== e && !f.has(D(e, t.name)) && (a = Math.max(a, g(n, i) + 1));
|
|
1587
1628
|
}
|
|
1588
|
-
return
|
|
1589
|
-
},
|
|
1629
|
+
return h.set(e, a), a;
|
|
1630
|
+
}, v = (e) => e === "rename-table" ? -1 : e === "create-table" ? 0 : e === "drop-table" ? 2 : 1, y = (e) => {
|
|
1590
1631
|
let t = "table" in e ? e.table : "";
|
|
1591
|
-
return e.kind === "create-table" ?
|
|
1592
|
-
},
|
|
1632
|
+
return e.kind === "create-table" ? g(t) : e.kind === "drop-table" ? -g(t) : 0;
|
|
1633
|
+
}, b = {
|
|
1593
1634
|
"add-column": 0,
|
|
1594
1635
|
"rename-column": 1,
|
|
1595
1636
|
"rename-index": 1,
|
|
@@ -1607,23 +1648,34 @@ BEGIN
|
|
|
1607
1648
|
"add-unique-composite": 5,
|
|
1608
1649
|
"add-foreign-key": 5,
|
|
1609
1650
|
"add-check": 5
|
|
1610
|
-
},
|
|
1611
|
-
let n =
|
|
1651
|
+
}, S = (e) => b[e] ?? 9, C = [...a].sort((e, t) => {
|
|
1652
|
+
let n = v(e.op.kind), r = v(t.op.kind);
|
|
1612
1653
|
if (n !== r) return n - r;
|
|
1613
|
-
let i =
|
|
1654
|
+
let i = y(e.op), a = y(t.op);
|
|
1614
1655
|
if (i !== a) return i - a;
|
|
1615
1656
|
let o = "table" in e.op ? e.op.table : "", s = "table" in t.op ? t.op.table : "";
|
|
1616
1657
|
if (o !== s) return o.localeCompare(s);
|
|
1617
|
-
let c =
|
|
1658
|
+
let c = S(e.op.kind), l = S(t.op.kind);
|
|
1618
1659
|
return c === l ? e.op.kind.localeCompare(t.op.kind) : c - l;
|
|
1619
|
-
});
|
|
1660
|
+
}), w = /* @__PURE__ */ new Set();
|
|
1661
|
+
for (let e of C) "table" in e.op && w.add(e.op.table);
|
|
1662
|
+
let T = [];
|
|
1663
|
+
for (let e of t.tables) {
|
|
1664
|
+
if (w.has(e.name) || o.renamedInto.has(e.name)) continue;
|
|
1665
|
+
let t = r.get(e.name);
|
|
1666
|
+
t !== void 0 && L({ tables: [t] }) !== L({ tables: [e] }) && T.push(e.name);
|
|
1667
|
+
}
|
|
1620
1668
|
return {
|
|
1621
|
-
operations:
|
|
1622
|
-
fromFingerprint:
|
|
1623
|
-
toFingerprint:
|
|
1624
|
-
summary:
|
|
1669
|
+
operations: C,
|
|
1670
|
+
fromFingerprint: L(e.live),
|
|
1671
|
+
toFingerprint: L(t),
|
|
1672
|
+
summary: Un(C),
|
|
1673
|
+
fingerprintDivergence: {
|
|
1674
|
+
outsideDiff: c,
|
|
1675
|
+
diffEquivalent: T
|
|
1676
|
+
}
|
|
1625
1677
|
};
|
|
1626
|
-
},
|
|
1678
|
+
}, Gn = (e) => {
|
|
1627
1679
|
let t = /[`"[]?([A-Za-z_][A-Za-z0-9_]*)[`"\]]?\s*(?:in\b|=)/i.exec(e);
|
|
1628
1680
|
if (!t) return null;
|
|
1629
1681
|
let n = [...e.replace(/\\'/g, "'").matchAll(/'((?:[^']|'')*)'/g)].map((e) => e[1].replace(/''/g, "'")).filter((e) => e.length > 0);
|
|
@@ -1631,7 +1683,7 @@ BEGIN
|
|
|
1631
1683
|
column: t[1],
|
|
1632
1684
|
values: n
|
|
1633
1685
|
};
|
|
1634
|
-
},
|
|
1686
|
+
}, Kn = (e, t) => {
|
|
1635
1687
|
if (t === "vector") return "vector";
|
|
1636
1688
|
switch (e) {
|
|
1637
1689
|
case "text":
|
|
@@ -1658,10 +1710,10 @@ BEGIN
|
|
|
1658
1710
|
case "USER-DEFINED": return "text";
|
|
1659
1711
|
default: return "text";
|
|
1660
1712
|
}
|
|
1661
|
-
},
|
|
1713
|
+
}, qn = (e, t) => e == null || e === "" ? void 0 : { generatedAs: {
|
|
1662
1714
|
expr: e,
|
|
1663
1715
|
stored: t
|
|
1664
|
-
} },
|
|
1716
|
+
} }, B = (e) => {
|
|
1665
1717
|
switch (e.toUpperCase()) {
|
|
1666
1718
|
case "CASCADE": return "cascade";
|
|
1667
1719
|
case "RESTRICT": return "restrict";
|
|
@@ -1669,25 +1721,25 @@ BEGIN
|
|
|
1669
1721
|
case "SET DEFAULT": return "noAction";
|
|
1670
1722
|
default: return "noAction";
|
|
1671
1723
|
}
|
|
1672
|
-
},
|
|
1724
|
+
}, Jn = (e, t) => {
|
|
1673
1725
|
let n = e !== void 0 && e !== "" ? Number(e) : NaN;
|
|
1674
1726
|
return Number.isInteger(n) && n > 0 ? n : t;
|
|
1675
|
-
},
|
|
1727
|
+
}, Yn = () => Jn(process.env.VOLTRO_INTROSPECT_BATCH, 20), Xn = 300, Zn = () => {
|
|
1676
1728
|
let e = process.env.VOLTRO_INTROSPECT_TIMEOUT_MS;
|
|
1677
|
-
return e !== void 0 && e.trim() === "0" ? 0 :
|
|
1678
|
-
},
|
|
1729
|
+
return e !== void 0 && e.trim() === "0" ? 0 : Jn(e, 3e4);
|
|
1730
|
+
}, Qn = (e, t) => {
|
|
1679
1731
|
let n = Number.isFinite(t) && t >= 1 ? Math.floor(t) : 1, r = [];
|
|
1680
1732
|
for (let t = 0; t < e.length; t += n) r.push(e.slice(t, t + n));
|
|
1681
1733
|
return r;
|
|
1682
|
-
},
|
|
1683
|
-
let t =
|
|
1734
|
+
}, $n = (e) => {
|
|
1735
|
+
let t = Zn(), n = w.gen(function* () {
|
|
1684
1736
|
t > 0 && (yield* e.unsafe(`SET LOCAL statement_timeout = ${t}`));
|
|
1685
|
-
let n = (t) => e.unsafe("(" + t.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ") + ")"), r = (t) => e.unsafe(String(Math.max(0, Math.trunc(t)))), i =
|
|
1737
|
+
let n = (t) => e.unsafe("(" + t.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ") + ")"), r = (t) => e.unsafe(String(Math.max(0, Math.trunc(t)))), i = Yn(), a = (e, t) => w.gen(function* () {
|
|
1686
1738
|
let r = [];
|
|
1687
|
-
for (let a of
|
|
1739
|
+
for (let a of Qn(e, i)) a.length !== 0 && r.push(...yield* t(n(a)));
|
|
1688
1740
|
return r;
|
|
1689
1741
|
}), o = [];
|
|
1690
|
-
for (let t = 0;; t +=
|
|
1742
|
+
for (let t = 0;; t += Xn) {
|
|
1691
1743
|
let n = yield* e`
|
|
1692
1744
|
SELECT c.relname AS table_name,
|
|
1693
1745
|
COALESCE(c.reltuples::bigint, 0) AS row_count
|
|
@@ -1695,9 +1747,9 @@ BEGIN
|
|
|
1695
1747
|
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
1696
1748
|
WHERE n.nspname = current_schema() AND c.relkind = 'r'
|
|
1697
1749
|
ORDER BY c.relname
|
|
1698
|
-
LIMIT ${r(
|
|
1750
|
+
LIMIT ${r(Xn)} OFFSET ${r(t)}
|
|
1699
1751
|
`;
|
|
1700
|
-
if (o.push(...n), n.length <
|
|
1752
|
+
if (o.push(...n), n.length < Xn) break;
|
|
1701
1753
|
}
|
|
1702
1754
|
let s = /* @__PURE__ */ new Set(), c = [];
|
|
1703
1755
|
for (let e of o) s.has(e.table_name) || (s.add(e.table_name), c.push(e));
|
|
@@ -1830,27 +1882,27 @@ BEGIN
|
|
|
1830
1882
|
let n = t.get(e.index_name);
|
|
1831
1883
|
n || (n = [], t.set(e.index_name, n)), n.push(e);
|
|
1832
1884
|
}
|
|
1833
|
-
let
|
|
1885
|
+
let T = [];
|
|
1834
1886
|
for (let e of c) {
|
|
1835
1887
|
let t = /* @__PURE__ */ new Set(), n = (_.get(e.table_name) ?? []).filter((e) => !t.has(e.column_name) && (t.add(e.column_name), !0)), r = v.get(e.table_name) ?? /* @__PURE__ */ new Set(), i = y.get(e.table_name) ?? /* @__PURE__ */ new Set(), a = x.get(e.table_name) ?? [], o = new Map(a.map((e) => [e.source_column, e])), s = new Set(n.filter((e) => e.udt_name === "tsvector").map((e) => e.column_name)), c = n.filter((e) => !s.has(e.column_name)).map((t) => {
|
|
1836
|
-
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" :
|
|
1888
|
+
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" : Kn(t.data_type, t.udt_name), c = a ? {
|
|
1837
1889
|
table: a.target_table,
|
|
1838
1890
|
column: a.target_column,
|
|
1839
|
-
onDelete:
|
|
1840
|
-
onUpdate:
|
|
1891
|
+
onDelete: B(a.delete_rule),
|
|
1892
|
+
onUpdate: B(a.update_rule)
|
|
1841
1893
|
} : void 0, l = m.get(`${e.table_name}.${t.column_name}`);
|
|
1842
1894
|
return {
|
|
1843
1895
|
name: t.column_name,
|
|
1844
1896
|
type: s,
|
|
1845
|
-
...
|
|
1897
|
+
...H(t.data_type, t.character_maximum_length) === void 0 ? {} : { maxLength: H(t.data_type, t.character_maximum_length) },
|
|
1846
1898
|
nullable: t.is_nullable === "YES",
|
|
1847
1899
|
unique: i.has(t.column_name) || n && t.column_name === "id",
|
|
1848
1900
|
hasDefault: t.column_default !== null,
|
|
1849
1901
|
...t.column_default === null ? {} : { defaultValue: t.column_default },
|
|
1850
1902
|
...c ? { references: c } : {},
|
|
1851
|
-
...a ? { referenceStorage: ["integer", "bigint"].includes(
|
|
1903
|
+
...a ? { referenceStorage: ["integer", "bigint"].includes(Kn(t.data_type, t.udt_name)) ? "numeric" : "text" } : {},
|
|
1852
1904
|
...l ? { oneOf: l } : {},
|
|
1853
|
-
...
|
|
1905
|
+
...qn(t.is_generated === "ALWAYS" ? t.generation_expression ?? "generated" : null, !0) ?? {}
|
|
1854
1906
|
};
|
|
1855
1907
|
}), l = [], u = S.get(e.table_name);
|
|
1856
1908
|
if (u) for (let [t, n] of u) {
|
|
@@ -1878,20 +1930,20 @@ BEGIN
|
|
|
1878
1930
|
unique: !0
|
|
1879
1931
|
});
|
|
1880
1932
|
let d = Number(e.row_count ?? 0);
|
|
1881
|
-
|
|
1933
|
+
T.push({
|
|
1882
1934
|
name: e.table_name,
|
|
1883
1935
|
columns: c,
|
|
1884
1936
|
indexes: l,
|
|
1885
1937
|
...d > 0 ? { rowCount: d } : {}
|
|
1886
1938
|
});
|
|
1887
1939
|
}
|
|
1888
|
-
return { tables:
|
|
1940
|
+
return { tables: T };
|
|
1889
1941
|
});
|
|
1890
1942
|
return (t > 0 ? e.withTransaction(n) : n).pipe(w.catchAll((e) => {
|
|
1891
1943
|
let n = `${String(e)} ${String(e.cause ?? "")}`.toLowerCase();
|
|
1892
1944
|
return n.includes("statement timeout") || n.includes("57014") ? w.die(/* @__PURE__ */ Error(`schema introspection exceeded VOLTRO_INTROSPECT_TIMEOUT_MS (${t}ms) — the schema is very large / FK-dense or the database is slow. Raise VOLTRO_INTROSPECT_TIMEOUT_MS, set it to 0 to disable the ceiling, or use DB_DIRECT_URL for a non-pooler connection.`)) : w.fail(e);
|
|
1893
1945
|
}));
|
|
1894
|
-
},
|
|
1946
|
+
}, er = (e, t) => {
|
|
1895
1947
|
switch (e.toLowerCase()) {
|
|
1896
1948
|
case "varchar":
|
|
1897
1949
|
case "char":
|
|
@@ -1923,21 +1975,21 @@ BEGIN
|
|
|
1923
1975
|
case "json": return "json";
|
|
1924
1976
|
default: return "text";
|
|
1925
1977
|
}
|
|
1926
|
-
},
|
|
1978
|
+
}, tr = (e) => e.map((e) => {
|
|
1927
1979
|
let t = e, n = {};
|
|
1928
1980
|
for (let e of Object.keys(t)) n[e.toLowerCase()] = t[e];
|
|
1929
1981
|
return n;
|
|
1930
|
-
}),
|
|
1931
|
-
let t =
|
|
1982
|
+
}), nr = (e) => w.gen(function* () {
|
|
1983
|
+
let t = tr(yield* e`
|
|
1932
1984
|
SELECT table_name, COALESCE(table_rows, 0) AS table_rows
|
|
1933
1985
|
FROM information_schema.tables
|
|
1934
1986
|
WHERE table_schema = DATABASE() AND table_type = 'BASE TABLE'
|
|
1935
|
-
ORDER BY table_name`), n =
|
|
1987
|
+
ORDER BY table_name`), n = tr(yield* e`
|
|
1936
1988
|
SELECT table_name, column_name, data_type, column_type, is_nullable, column_default, column_key,
|
|
1937
1989
|
character_maximum_length, generation_expression, extra
|
|
1938
1990
|
FROM information_schema.columns
|
|
1939
1991
|
WHERE table_schema = DATABASE()
|
|
1940
|
-
ORDER BY table_name, ordinal_position`), r =
|
|
1992
|
+
ORDER BY table_name, ordinal_position`), r = tr(yield* e`
|
|
1941
1993
|
SELECT k.table_name AS source_table,
|
|
1942
1994
|
k.column_name AS source_column,
|
|
1943
1995
|
k.referenced_table_name AS target_table,
|
|
@@ -1947,7 +1999,7 @@ BEGIN
|
|
|
1947
1999
|
JOIN information_schema.referential_constraints r
|
|
1948
2000
|
ON k.constraint_name = r.constraint_name
|
|
1949
2001
|
AND k.table_schema = r.constraint_schema
|
|
1950
|
-
WHERE k.table_schema = DATABASE() AND k.referenced_table_name IS NOT NULL`), i =
|
|
2002
|
+
WHERE k.table_schema = DATABASE() AND k.referenced_table_name IS NOT NULL`), i = tr(yield* e`
|
|
1951
2003
|
SELECT table_name, index_name, non_unique, column_name, seq_in_index
|
|
1952
2004
|
FROM information_schema.statistics
|
|
1953
2005
|
WHERE table_schema = DATABASE() AND index_name <> 'PRIMARY'
|
|
@@ -1960,14 +2012,14 @@ BEGIN
|
|
|
1960
2012
|
JOIN information_schema.table_constraints tc
|
|
1961
2013
|
ON tc.constraint_schema = cc.constraint_schema
|
|
1962
2014
|
AND tc.constraint_name = cc.constraint_name
|
|
1963
|
-
WHERE cc.constraint_schema = DATABASE()`.unprepared, s =
|
|
2015
|
+
WHERE cc.constraint_schema = DATABASE()`.unprepared, s = tr(yield* a.pipe(w.orElse(() => o), w.orElseSucceed(() => []))), c = /* @__PURE__ */ new Set(), l = /* @__PURE__ */ new Map();
|
|
1964
2016
|
for (let e of s) {
|
|
1965
2017
|
let t = /json_valid\(`?([^`)]+)`?\)/i.exec(e.check_clause);
|
|
1966
2018
|
if (t) {
|
|
1967
2019
|
c.add(`${e.table_name}.${t[1]}`);
|
|
1968
2020
|
continue;
|
|
1969
2021
|
}
|
|
1970
|
-
let n =
|
|
2022
|
+
let n = Gn(e.check_clause);
|
|
1971
2023
|
n && l.set(`${e.table_name}.${n.column}`, n.values);
|
|
1972
2024
|
}
|
|
1973
2025
|
let u = /* @__PURE__ */ new Map(), d = /* @__PURE__ */ new Map(), f = /* @__PURE__ */ new Map();
|
|
@@ -1990,24 +2042,24 @@ BEGIN
|
|
|
1990
2042
|
let t = u.get(e.table_name) ?? [], n = d.get(e.table_name) ?? [], r = new Map(n.map((e) => [e.source_column, e])), i = t.filter((e) => e.column_key === "PRI").map((e) => e.column_name), a = /* @__PURE__ */ new Set(), o = f.get(e.table_name);
|
|
1991
2043
|
if (o) for (let e of o.values()) e.length === 1 && e[0].non_unique === 0 && a.add(e[0].column_name);
|
|
1992
2044
|
let s = t.map((t) => {
|
|
1993
|
-
let n = i.includes(t.column_name) && i.length === 1, o = r.get(t.column_name), s = o ? "reference" : n && t.column_name === "id" ? "id" : c.has(`${e.table_name}.${t.column_name}`) ? "json" :
|
|
2045
|
+
let n = i.includes(t.column_name) && i.length === 1, o = r.get(t.column_name), s = o ? "reference" : n && t.column_name === "id" ? "id" : c.has(`${e.table_name}.${t.column_name}`) ? "json" : er(t.data_type, t.column_type), u = o ? {
|
|
1994
2046
|
table: o.target_table,
|
|
1995
2047
|
column: o.target_column,
|
|
1996
|
-
onDelete:
|
|
1997
|
-
onUpdate:
|
|
2048
|
+
onDelete: B(o.delete_rule),
|
|
2049
|
+
onUpdate: B(o.update_rule)
|
|
1998
2050
|
} : void 0, d = a.has(t.column_name) || n && t.column_name === "id", f = t.column_default === "NULL" ? null : t.column_default, p = l.get(`${e.table_name}.${t.column_name}`);
|
|
1999
2051
|
return {
|
|
2000
2052
|
name: t.column_name,
|
|
2001
2053
|
type: s,
|
|
2002
2054
|
nullable: t.is_nullable === "YES",
|
|
2003
|
-
...
|
|
2055
|
+
...H(t.data_type, t.character_maximum_length) === void 0 ? {} : { maxLength: H(t.data_type, t.character_maximum_length) },
|
|
2004
2056
|
unique: d,
|
|
2005
2057
|
hasDefault: f !== null,
|
|
2006
2058
|
...f === null ? {} : { defaultValue: f },
|
|
2007
2059
|
...u ? { references: u } : {},
|
|
2008
|
-
...o ? { referenceStorage: ["integer", "bigint"].includes(
|
|
2060
|
+
...o ? { referenceStorage: ["integer", "bigint"].includes(er(t.data_type, t.column_type)) ? "numeric" : "text" } : {},
|
|
2009
2061
|
...p ? { oneOf: p } : {},
|
|
2010
|
-
...
|
|
2062
|
+
...qn(t.generation_expression, /STORED/i.test(t.extra ?? "")) ?? {}
|
|
2011
2063
|
};
|
|
2012
2064
|
}), m = new Set(n.map((e) => e.source_column)), h = [];
|
|
2013
2065
|
if (o) for (let [t, n] of o) {
|
|
@@ -2034,10 +2086,10 @@ BEGIN
|
|
|
2034
2086
|
});
|
|
2035
2087
|
}
|
|
2036
2088
|
return { tables: p };
|
|
2037
|
-
}),
|
|
2089
|
+
}), rr = (e) => {
|
|
2038
2090
|
let t = e.toUpperCase();
|
|
2039
2091
|
return t.includes("INT") ? "integer" : t.includes("REAL") || t.includes("FLOA") || t.includes("DOUB") ? "real" : t.includes("BLOB") ? "bytes" : "text";
|
|
2040
|
-
},
|
|
2092
|
+
}, ir = (e) => e === 1 || e === !0, ar = (e) => w.gen(function* () {
|
|
2041
2093
|
let t = yield* e`
|
|
2042
2094
|
SELECT name, sql FROM sqlite_master
|
|
2043
2095
|
WHERE type = 'table' AND name NOT LIKE 'sqlite_%'
|
|
@@ -2051,18 +2103,18 @@ BEGIN
|
|
|
2051
2103
|
let o = yield* e.unsafe(`PRAGMA table_xinfo(${n(i)})`), s = yield* e.unsafe(`PRAGMA foreign_key_list(${n(i)})`), c = yield* e.unsafe(`PRAGMA index_list(${n(i)})`), l = new Map(s.map((e) => [e.from, e])), u = o.filter((e) => e.pk > 0).sort((e, t) => e.pk - t.pk).map((e) => e.name), d = new Map(o.map((e) => [e.name.toLowerCase(), e.name])), f = /* @__PURE__ */ new Map(), p = /* @__PURE__ */ new Map(), m = /* @__PURE__ */ new Set();
|
|
2052
2104
|
for (let t of c) {
|
|
2053
2105
|
let r = (yield* e.unsafe(`PRAGMA index_info(${n(t.name)})`)).map((e) => e.name).filter((e) => e !== null).map((e) => d.get(e.toLowerCase()) ?? e);
|
|
2054
|
-
if (f.set(t.name, r), t.partial !== void 0 &&
|
|
2055
|
-
let n =
|
|
2106
|
+
if (f.set(t.name, r), t.partial !== void 0 && ir(t.partial)) {
|
|
2107
|
+
let n = Xt((yield* e`SELECT sql FROM sqlite_master WHERE type = 'index' AND name = ${t.name}`)[0]?.sql ?? "");
|
|
2056
2108
|
n !== void 0 && p.set(t.name, n);
|
|
2057
2109
|
}
|
|
2058
|
-
!p.has(t.name) &&
|
|
2110
|
+
!p.has(t.name) && ir(t.unique) && r.length === 1 && m.add(r[0]);
|
|
2059
2111
|
}
|
|
2060
2112
|
let h = o.map((e) => {
|
|
2061
|
-
let n = u.length === 1 && u[0] === e.name, r = l.get(e.name), i = r ? "reference" : n && e.name === "id" ? "id" :
|
|
2113
|
+
let n = u.length === 1 && u[0] === e.name, r = l.get(e.name), i = r ? "reference" : n && e.name === "id" ? "id" : rr(e.type), a = r ? {
|
|
2062
2114
|
table: r.table,
|
|
2063
2115
|
column: r.to,
|
|
2064
|
-
onDelete:
|
|
2065
|
-
onUpdate:
|
|
2116
|
+
onDelete: B(r.on_delete),
|
|
2117
|
+
onUpdate: B(r.on_update)
|
|
2066
2118
|
} : void 0, o = t.get(e.name);
|
|
2067
2119
|
return {
|
|
2068
2120
|
name: e.name,
|
|
@@ -2072,19 +2124,19 @@ BEGIN
|
|
|
2072
2124
|
hasDefault: e.dflt_value !== null,
|
|
2073
2125
|
...e.dflt_value === null ? {} : { defaultValue: e.dflt_value },
|
|
2074
2126
|
...a ? { references: a } : {},
|
|
2075
|
-
...r ? { referenceStorage: ["integer", "bigint"].includes(
|
|
2127
|
+
...r ? { referenceStorage: ["integer", "bigint"].includes(rr(e.type)) ? "numeric" : "text" } : {},
|
|
2076
2128
|
...o ? { oneOf: o } : {},
|
|
2077
|
-
...
|
|
2129
|
+
...qn(e.hidden === 2 || e.hidden === 3 ? "generated" : null, e.hidden === 3) ?? {}
|
|
2078
2130
|
};
|
|
2079
2131
|
}), g = new Set(s.map((e) => e.from)), _ = [];
|
|
2080
2132
|
for (let e of c) {
|
|
2081
2133
|
if (e.origin === "pk") continue;
|
|
2082
2134
|
let t = f.get(e.name) ?? [], n = p.get(e.name);
|
|
2083
|
-
n === void 0 && t.length === 1 &&
|
|
2135
|
+
n === void 0 && t.length === 1 && ir(e.unique) || (n !== void 0 || t.length !== 1 || ir(e.unique) || !g.has(t[0]) || e.name === `${i}_${t[0]}_idx`) && _.push({
|
|
2084
2136
|
name: e.name,
|
|
2085
2137
|
table: i,
|
|
2086
2138
|
columns: t,
|
|
2087
|
-
unique:
|
|
2139
|
+
unique: ir(e.unique),
|
|
2088
2140
|
...n === void 0 ? {} : { where: n }
|
|
2089
2141
|
});
|
|
2090
2142
|
}
|
|
@@ -2100,7 +2152,7 @@ BEGIN
|
|
|
2100
2152
|
});
|
|
2101
2153
|
}
|
|
2102
2154
|
return { tables: r };
|
|
2103
|
-
}),
|
|
2155
|
+
}), or = (e) => {
|
|
2104
2156
|
switch (e.toLowerCase()) {
|
|
2105
2157
|
case "int":
|
|
2106
2158
|
case "smallint":
|
|
@@ -2122,7 +2174,7 @@ BEGIN
|
|
|
2122
2174
|
case "image": return "bytes";
|
|
2123
2175
|
default: return "text";
|
|
2124
2176
|
}
|
|
2125
|
-
},
|
|
2177
|
+
}, V = (e) => e === !0 || e === 1, sr = (e) => w.gen(function* () {
|
|
2126
2178
|
let t = yield* e`
|
|
2127
2179
|
SELECT TABLE_NAME AS table_name FROM INFORMATION_SCHEMA.TABLES
|
|
2128
2180
|
WHERE TABLE_TYPE = 'BASE TABLE' ORDER BY TABLE_NAME`, n = yield* e`
|
|
@@ -2185,39 +2237,39 @@ BEGIN
|
|
|
2185
2237
|
let t = l.get(e) ?? [], n = u.get(e) ?? [], r = new Map(n.map((e) => [e.source_column, e])), a = new Set(n.map((e) => e.source_column)), o = d.get(e), s = [], p = /* @__PURE__ */ new Set();
|
|
2186
2238
|
if (o) for (let [, e] of o) {
|
|
2187
2239
|
let t = [...e].sort((e, t) => e.key_ordinal - t.key_ordinal);
|
|
2188
|
-
if (
|
|
2189
|
-
else t[0].predicate == null &&
|
|
2240
|
+
if (V(t[0].is_primary)) for (let e of t) s.push(e.column_name);
|
|
2241
|
+
else t[0].predicate == null && V(t[0].is_unique) && t.length === 1 && p.add(t[0].column_name);
|
|
2190
2242
|
}
|
|
2191
2243
|
let m = t.map((t) => {
|
|
2192
|
-
let n = s.length === 1 && s[0] === t.column_name, a = r.get(t.column_name), o = a ? "reference" : n && t.column_name === "id" ? "id" :
|
|
2244
|
+
let n = s.length === 1 && s[0] === t.column_name, a = r.get(t.column_name), o = a ? "reference" : n && t.column_name === "id" ? "id" : or(t.data_type), l = a ? {
|
|
2193
2245
|
table: a.target_table,
|
|
2194
2246
|
column: a.target_column,
|
|
2195
|
-
onDelete:
|
|
2196
|
-
onUpdate:
|
|
2197
|
-
} : void 0, u = t.column_default === null ? null :
|
|
2247
|
+
onDelete: cr(a.delete_rule),
|
|
2248
|
+
onUpdate: cr(a.update_rule)
|
|
2249
|
+
} : void 0, u = t.column_default === null ? null : lr(t.column_default), d = c.get(`${e}.${t.column_name}`);
|
|
2198
2250
|
return {
|
|
2199
2251
|
name: t.column_name,
|
|
2200
2252
|
type: o,
|
|
2201
2253
|
nullable: t.is_nullable === "YES",
|
|
2202
|
-
...
|
|
2254
|
+
...H(t.data_type, t.character_maximum_length) === void 0 ? {} : { maxLength: H(t.data_type, t.character_maximum_length) },
|
|
2203
2255
|
unique: p.has(t.column_name) || n && t.column_name === "id",
|
|
2204
2256
|
hasDefault: u !== null,
|
|
2205
2257
|
...u === null ? {} : { defaultValue: u },
|
|
2206
2258
|
...l ? { references: l } : {},
|
|
2207
|
-
...a ? { referenceStorage: ["integer", "bigint"].includes(
|
|
2259
|
+
...a ? { referenceStorage: ["integer", "bigint"].includes(or(t.data_type)) ? "numeric" : "text" } : {},
|
|
2208
2260
|
...d ? { oneOf: d } : {},
|
|
2209
|
-
...
|
|
2261
|
+
...qn(i.get(`${e}.${t.column_name}`)?.definition ?? null, V(i.get(`${e}.${t.column_name}`)?.is_persisted ?? !1)) ?? {}
|
|
2210
2262
|
};
|
|
2211
2263
|
}), h = [];
|
|
2212
2264
|
if (o) for (let [t, n] of o) {
|
|
2213
2265
|
let r = [...n].sort((e, t) => e.key_ordinal - t.key_ordinal);
|
|
2214
|
-
if (
|
|
2266
|
+
if (V(r[0].is_primary)) continue;
|
|
2215
2267
|
let i = r[0].predicate ?? void 0;
|
|
2216
|
-
i === void 0 && r.length === 1 &&
|
|
2268
|
+
i === void 0 && r.length === 1 && V(r[0].is_unique) || (i !== void 0 || r.length !== 1 || V(r[0].is_unique) || !a.has(r[0].column_name) || t === `${e}_${r[0].column_name}_idx`) && h.push({
|
|
2217
2269
|
name: t,
|
|
2218
2270
|
table: e,
|
|
2219
2271
|
columns: r.map((e) => e.column_name),
|
|
2220
|
-
unique:
|
|
2272
|
+
unique: V(r[0].is_unique),
|
|
2221
2273
|
...i === void 0 ? {} : { where: i }
|
|
2222
2274
|
});
|
|
2223
2275
|
}
|
|
@@ -2233,90 +2285,90 @@ BEGIN
|
|
|
2233
2285
|
});
|
|
2234
2286
|
}
|
|
2235
2287
|
return { tables: f };
|
|
2236
|
-
}),
|
|
2288
|
+
}), cr = (e) => {
|
|
2237
2289
|
switch (e.toUpperCase().replace(/_/g, " ")) {
|
|
2238
2290
|
case "CASCADE": return "cascade";
|
|
2239
2291
|
case "SET NULL": return "setNull";
|
|
2240
2292
|
case "SET DEFAULT": return "noAction";
|
|
2241
2293
|
default: return "noAction";
|
|
2242
2294
|
}
|
|
2243
|
-
},
|
|
2295
|
+
}, lr = (e) => {
|
|
2244
2296
|
let t = e.trim();
|
|
2245
2297
|
for (; t.startsWith("(") && t.endsWith(")");) t = t.slice(1, -1).trim();
|
|
2246
2298
|
return t.startsWith("N'") && t.endsWith("'") ? t = t.slice(2, -1) : t.startsWith("'") && t.endsWith("'") && (t = t.slice(1, -1)), t;
|
|
2247
|
-
},
|
|
2299
|
+
}, ur = /* @__PURE__ */ new Set([
|
|
2248
2300
|
"character varying",
|
|
2249
2301
|
"varchar",
|
|
2250
2302
|
"nvarchar",
|
|
2251
2303
|
"char",
|
|
2252
2304
|
"character",
|
|
2253
2305
|
"nchar"
|
|
2254
|
-
]),
|
|
2255
|
-
if (!
|
|
2306
|
+
]), H = (e, t) => {
|
|
2307
|
+
if (!ur.has(e.toLowerCase())) return;
|
|
2256
2308
|
let n = Number(t);
|
|
2257
2309
|
if (!(!Number.isFinite(n) || n <= 0)) return n;
|
|
2258
|
-
},
|
|
2259
|
-
mysql: () =>
|
|
2260
|
-
mssql: () =>
|
|
2261
|
-
sqlite: () =>
|
|
2262
|
-
orElse: () =>
|
|
2310
|
+
}, dr = /* @__PURE__ */ new Set([k]), fr = (e) => e.onDialectOrElse({
|
|
2311
|
+
mysql: () => nr(e),
|
|
2312
|
+
mssql: () => sr(e),
|
|
2313
|
+
sqlite: () => ar(e),
|
|
2314
|
+
orElse: () => $n(e)
|
|
2263
2315
|
}).pipe(w.map((e) => ({
|
|
2264
2316
|
...e,
|
|
2265
|
-
tables: e.tables.filter((e) => !
|
|
2266
|
-
}))),
|
|
2267
|
-
let t =
|
|
2268
|
-
return t === void 0 ?
|
|
2269
|
-
}),
|
|
2317
|
+
tables: e.tables.filter((e) => !dr.has(e.name))
|
|
2318
|
+
}))), pr = (e) => /mariadb/i.test(e) ? "mariadb" : "mysql", mr = /* @__PURE__ */ new WeakMap(), hr = (e) => w.suspend(() => {
|
|
2319
|
+
let t = mr.get(e);
|
|
2320
|
+
return t === void 0 ? gr(e).pipe(w.tap((t) => w.sync(() => mr.set(e, t)))) : w.succeed(t);
|
|
2321
|
+
}), gr = (e) => e.unsafe("SELECT VERSION() AS v").pipe(w.map((e) => {
|
|
2270
2322
|
let t = e[0]?.v;
|
|
2271
|
-
return typeof t == "string" ?
|
|
2272
|
-
}), w.catchAll(() => w.succeed("mysql"))),
|
|
2323
|
+
return typeof t == "string" ? pr(t) : "mysql";
|
|
2324
|
+
}), w.catchAll(() => w.succeed("mysql"))), _r = (e) => {
|
|
2273
2325
|
let t = e;
|
|
2274
2326
|
for (let e = 0; e < 6 && typeof t == "object" && t; e++) {
|
|
2275
2327
|
let e = t;
|
|
2276
2328
|
if (typeof e.errno == "number") return e.errno;
|
|
2277
2329
|
t = e.cause;
|
|
2278
2330
|
}
|
|
2279
|
-
},
|
|
2331
|
+
}, vr = (e) => {
|
|
2280
2332
|
let t = [], n = e;
|
|
2281
2333
|
for (let e = 0; e < 6 && typeof n == "object" && n; e++) {
|
|
2282
2334
|
let e = n;
|
|
2283
2335
|
typeof e.message == "string" && t.push(e.message), n = e.cause;
|
|
2284
2336
|
}
|
|
2285
2337
|
return t.join(" | ");
|
|
2286
|
-
},
|
|
2338
|
+
}, yr = (e, t) => {
|
|
2287
2339
|
if (t.length === 0) return !1;
|
|
2288
|
-
let n =
|
|
2340
|
+
let n = _r(e), r = vr(e);
|
|
2289
2341
|
return t.some((e) => e.errno !== void 0 && n !== void 0 && e.errno.includes(n) || e.messageIncludes !== void 0 && e.messageIncludes.some((e) => r.includes(e)));
|
|
2290
|
-
},
|
|
2342
|
+
}, br = {
|
|
2291
2343
|
why: "mysql has no CREATE INDEX IF NOT EXISTS; 1061 is exactly that condition",
|
|
2292
2344
|
errno: [1061]
|
|
2293
|
-
},
|
|
2345
|
+
}, xr = {
|
|
2294
2346
|
why: "mysql has no DROP COLUMN IF EXISTS; 1091 is exactly that condition",
|
|
2295
2347
|
errno: [1091]
|
|
2296
|
-
},
|
|
2348
|
+
}, Sr = {
|
|
2297
2349
|
why: "sqlite has no DROP COLUMN IF EXISTS, and reports the absent column only in the message",
|
|
2298
2350
|
messageIncludes: ["no such column"]
|
|
2299
|
-
},
|
|
2351
|
+
}, Cr = {
|
|
2300
2352
|
why: "mysql/mariadb DROP CONSTRAINT has no portable IF EXISTS; 1091 / 3940 are exactly \"already gone\"",
|
|
2301
2353
|
errno: [1091, 3940]
|
|
2302
2354
|
}, U = (e, t) => e.onDialectOrElse({
|
|
2303
2355
|
mysql: () => w.succeed(t.replace("T", " ").replace("Z", "")),
|
|
2304
2356
|
orElse: () => w.succeed(t)
|
|
2305
|
-
}),
|
|
2306
|
-
if ((e.type !== "text" || e.maxLength === void 0) && !
|
|
2357
|
+
}), wr = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, Tr = (e) => e.type === "text" && (e.hasDefault && e.defaultValue !== void 0 || e.oneOf !== void 0 && e.oneOf.length > 0), Er = (e, t) => {
|
|
2358
|
+
if ((e.type !== "text" || e.maxLength === void 0) && !Tr(e) && !e.spatial && e.type !== "vector" && e.type !== "array" && e.type !== "enum") return;
|
|
2307
2359
|
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;
|
|
2308
2360
|
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.`);
|
|
2309
|
-
return
|
|
2310
|
-
},
|
|
2311
|
-
let t =
|
|
2312
|
-
return t === void 0 ?
|
|
2313
|
-
},
|
|
2361
|
+
return M(e, t);
|
|
2362
|
+
}, Dr = (e) => {
|
|
2363
|
+
let t = Er(e, "postgres");
|
|
2364
|
+
return t === void 0 ? Or(e) : t;
|
|
2365
|
+
}, Or = (e) => {
|
|
2314
2366
|
switch (e.type) {
|
|
2315
2367
|
case "id": return "text";
|
|
2316
2368
|
case "text": return "text";
|
|
2317
2369
|
case "integer": return "integer";
|
|
2318
2370
|
case "real": return "double precision";
|
|
2319
|
-
case "decimal": return
|
|
2371
|
+
case "decimal": return wr(e, "NUMERIC");
|
|
2320
2372
|
case "bigint": return "bigint";
|
|
2321
2373
|
case "boolean": return "boolean";
|
|
2322
2374
|
case "timestamp": return "timestamptz";
|
|
@@ -2330,15 +2382,15 @@ BEGIN
|
|
|
2330
2382
|
case "interval": return "interval";
|
|
2331
2383
|
case "raw": return e.rawDdl ?? "text";
|
|
2332
2384
|
}
|
|
2333
|
-
},
|
|
2334
|
-
let t =
|
|
2385
|
+
}, kr = (e) => {
|
|
2386
|
+
let t = Er(e, "mariadb");
|
|
2335
2387
|
if (t !== void 0) return t;
|
|
2336
2388
|
switch (e.type) {
|
|
2337
2389
|
case "id": return "VARCHAR(64)";
|
|
2338
2390
|
case "text": return "LONGTEXT";
|
|
2339
2391
|
case "integer": return "INT";
|
|
2340
2392
|
case "real": return "DOUBLE";
|
|
2341
|
-
case "decimal": return
|
|
2393
|
+
case "decimal": return wr(e, "DECIMAL");
|
|
2342
2394
|
case "bigint": return "BIGINT";
|
|
2343
2395
|
case "boolean": return "TINYINT(1)";
|
|
2344
2396
|
case "timestamp": return "DATETIME(6)";
|
|
@@ -2352,38 +2404,38 @@ BEGIN
|
|
|
2352
2404
|
case "interval": return "BIGINT";
|
|
2353
2405
|
case "raw": return e.rawDdl ?? "LONGTEXT";
|
|
2354
2406
|
}
|
|
2355
|
-
}, W = (e) => `"${e}"`, G = (e) => `\`${e.replace(/`/g, "``")}\``,
|
|
2407
|
+
}, W = (e) => `"${e}"`, G = (e) => `\`${e.replace(/`/g, "``")}\``, Ar = (e) => e === "mariadb" ? "IF NOT EXISTS " : "", jr = (e, t, n = !0) => `ALTER TABLE ${t(e.table)} DROP COLUMN ${n ? "IF EXISTS " : ""}${t(e.column)};`, Mr = (e, t = "mariadb") => `ALTER TABLE ${G(e.table)} DROP COLUMN ${t === "mariadb" ? "IF EXISTS " : ""}${G(e.column)}, ALGORITHM=COPY;`, Nr = (e, t) => `ALTER TABLE ${t(e.table)} RENAME COLUMN ${t(e.from)} TO ${t(e.to)};`, Pr = (e, t, n) => `ALTER TABLE ${n(e.table)} RENAME COLUMN ${n(e.column)} TO ${n(`${e.column}${li(t)}`)};`, Fr = (e, t, n) => e.hasDefault && e.defaultValue !== void 0 ? `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} SET ${Lr(e, n)};` : `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} DROP DEFAULT;`, Ir = (e, t) => {
|
|
2356
2408
|
let { defaultFactory: n, ...r } = e;
|
|
2357
|
-
return
|
|
2409
|
+
return M(e, t) !== M({
|
|
2358
2410
|
...r,
|
|
2359
2411
|
hasDefault: !1
|
|
2360
2412
|
}, t);
|
|
2361
|
-
},
|
|
2413
|
+
}, Lr = (e, t) => {
|
|
2362
2414
|
let n = t(e.defaultValue);
|
|
2363
2415
|
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.`);
|
|
2364
2416
|
return n;
|
|
2365
|
-
}, K = (e, t, n) => e.find((e) => e.tableName === t)?.fields[n],
|
|
2417
|
+
}, K = (e, t, n) => e.find((e) => e.tableName === t)?.fields[n], Rr = (e, t, n) => {
|
|
2366
2418
|
let r = K(e, t, n);
|
|
2367
|
-
return r ?
|
|
2368
|
-
},
|
|
2369
|
-
let r = n ?? e.nullable, i =
|
|
2419
|
+
return r ? on(n, r) : void 0;
|
|
2420
|
+
}, zr = (e, t, n) => {
|
|
2421
|
+
let r = n ?? e.nullable, i = rt(e, "mariadb");
|
|
2370
2422
|
return [
|
|
2371
2423
|
G(t),
|
|
2372
|
-
|
|
2424
|
+
M(e, "mariadb"),
|
|
2373
2425
|
r ? null : "NOT NULL",
|
|
2374
2426
|
i
|
|
2375
2427
|
].filter(Boolean).join(" ");
|
|
2376
|
-
},
|
|
2428
|
+
}, Br = (e, t) => e == null ? null : Array.isArray(e) ? Vr(e, t, "mariadb") : e === "now" ? "DEFAULT CURRENT_TIMESTAMP(6)" : typeof e == "boolean" ? `DEFAULT ${+!!e}` : typeof e == "number" ? `DEFAULT ${e}` : typeof e == "string" ? /[()]|^'/.test(e) ? `DEFAULT ${e}` : `DEFAULT '${e.replace(/'/g, "''")}'` : typeof e == "object" ? N(e, "mariadb") : null, Vr = (e, t, n) => it(e, t ?? { type: "json" }, n), Hr = (e, t) => e == null ? null : Array.isArray(e) ? Vr(e, t, "postgres") : e === "now" ? "DEFAULT now()" : typeof e == "boolean" || typeof e == "number" ? `DEFAULT ${e}` : typeof e == "string" ? /[()]|::|^'/.test(e) ? `DEFAULT ${e}` : `DEFAULT '${e.replace(/'/g, "''")}'` : typeof e == "object" ? N(e, "postgres") : null, Ur = (e, t) => {
|
|
2377
2429
|
if (!e.generatedAs) return null;
|
|
2378
2430
|
let { expr: n, stored: r } = e.generatedAs;
|
|
2379
2431
|
return t === "postgres" ? `GENERATED ALWAYS AS (${n}) STORED` : t === "mssql" ? `AS (${n})${r ? " PERSISTED" : ""}` : `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
|
|
2380
|
-
},
|
|
2381
|
-
if (e.type === "id" && e.idScheme?.kind === "numeric") return
|
|
2382
|
-
let t =
|
|
2383
|
-
if (t) return `${W(e.name)} ${
|
|
2384
|
-
let n = [W(e.name),
|
|
2432
|
+
}, Wr = (e) => {
|
|
2433
|
+
if (e.type === "id" && e.idScheme?.kind === "numeric") return P(e.name, "postgres");
|
|
2434
|
+
let t = Ur(e, "postgres");
|
|
2435
|
+
if (t) return `${W(e.name)} ${Dr(e)} ${t}`;
|
|
2436
|
+
let n = [W(e.name), Dr(e)];
|
|
2385
2437
|
if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && n.push("UNIQUE"), e.hasDefault) {
|
|
2386
|
-
let t =
|
|
2438
|
+
let t = Hr(e.defaultValue, e);
|
|
2387
2439
|
t && n.push(t);
|
|
2388
2440
|
}
|
|
2389
2441
|
return e.references && (n.push(`REFERENCES ${W(e.references.table)} (${W(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${{
|
|
@@ -2392,24 +2444,24 @@ BEGIN
|
|
|
2392
2444
|
setNull: "SET NULL",
|
|
2393
2445
|
noAction: "NO ACTION"
|
|
2394
2446
|
}[e.references.onDelete]}`)), n.join(" ");
|
|
2395
|
-
},
|
|
2396
|
-
let t = e.columns.map((e) => ` ${
|
|
2397
|
-
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(
|
|
2447
|
+
}, Gr = (e, t) => e.primaryKey && e.primaryKey.length > 0 ? `,\n PRIMARY KEY (${e.primaryKey.map(t).join(", ")})` : "", Kr = (e) => {
|
|
2448
|
+
let t = e.columns.map((e) => ` ${Wr(e)}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${W(e.table)} (\n${t}${Gr(e, W)}\n)`];
|
|
2449
|
+
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(mi).join(", ")})${Y(t)}`);
|
|
2398
2450
|
return n;
|
|
2399
|
-
},
|
|
2400
|
-
let t =
|
|
2451
|
+
}, qr = 191, Jr = (e) => {
|
|
2452
|
+
let t = kr(e).toUpperCase();
|
|
2401
2453
|
return t.endsWith("TEXT") || t.endsWith("BLOB");
|
|
2402
|
-
},
|
|
2403
|
-
if (e.type === "id" && e.idScheme?.kind === "numeric") return
|
|
2404
|
-
let t =
|
|
2405
|
-
if (t) return `${G(e.name)} ${
|
|
2406
|
-
let n = [G(e.name),
|
|
2407
|
-
if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && !
|
|
2408
|
-
let t =
|
|
2454
|
+
}, Yr = (e) => {
|
|
2455
|
+
if (e.type === "id" && e.idScheme?.kind === "numeric") return P(e.name, "mariadb");
|
|
2456
|
+
let t = Ur(e, "mariadb");
|
|
2457
|
+
if (t) return `${G(e.name)} ${kr(e)} ${t}`;
|
|
2458
|
+
let n = [G(e.name), kr(e)];
|
|
2459
|
+
if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && !Jr(e) && n.push("UNIQUE"), e.hasDefault) {
|
|
2460
|
+
let t = Br(e.defaultValue, e);
|
|
2409
2461
|
t && n.push(t);
|
|
2410
2462
|
}
|
|
2411
2463
|
return n.join(" ");
|
|
2412
|
-
},
|
|
2464
|
+
}, Xr = (e) => e.columns.flatMap((t) => {
|
|
2413
2465
|
if (!t.references) return [];
|
|
2414
2466
|
let n = t.references.onDelete ? ` ON DELETE ${{
|
|
2415
2467
|
cascade: "CASCADE",
|
|
@@ -2418,27 +2470,27 @@ BEGIN
|
|
|
2418
2470
|
noAction: "NO ACTION"
|
|
2419
2471
|
}[t.references.onDelete]}` : "";
|
|
2420
2472
|
return [` CONSTRAINT ${G(`${e.table}_${t.name}_fkey`)} FOREIGN KEY (${G(t.name)}) REFERENCES ${G(t.references.table)} (${G(t.references.column)})${n}`];
|
|
2421
|
-
}),
|
|
2422
|
-
for (let n of e.indexes)
|
|
2473
|
+
}), Zr = (e, t = "mariadb") => {
|
|
2474
|
+
for (let n of e.indexes) _i(n, t);
|
|
2423
2475
|
let n = new Map(e.columns.map((e) => [e.name, e])), r = (e) => {
|
|
2424
|
-
let t =
|
|
2476
|
+
let t = fi(n.get(e));
|
|
2425
2477
|
return t === void 0 ? G(e) : `${G(e)}(${t})`;
|
|
2426
|
-
}, i = e.columns.map((e) => ` ${
|
|
2427
|
-
for (let n of e.columns) n.unique && n.type !== "id" &&
|
|
2428
|
-
for (let n of e.indexes) n.name !== `${e.table}_pkey` && s.push(`CREATE ${n.unique ? "UNIQUE " : ""}INDEX ${
|
|
2478
|
+
}, i = e.columns.map((e) => ` ${Yr(e)}`).join(",\n"), a = Xr(e), o = a.length > 0 ? `${i},\n${a.join(",\n")}` : i, s = [`CREATE TABLE IF NOT EXISTS ${G(e.table)} (\n${o}${Gr(e, r)}\n)`];
|
|
2479
|
+
for (let n of e.columns) n.unique && n.type !== "id" && Jr(n) && s.push(`CREATE UNIQUE INDEX ${Ar(t)}${G(`${e.table}_${n.name}_key`)} ON ${G(e.table)} (${r(n.name)})`);
|
|
2480
|
+
for (let n of e.indexes) n.name !== `${e.table}_pkey` && s.push(`CREATE ${n.unique ? "UNIQUE " : ""}INDEX ${Ar(t)}${G(n.name)} ON ${G(e.table)} (${n.columns.map(r).join(", ")})`);
|
|
2429
2481
|
return s;
|
|
2430
|
-
},
|
|
2482
|
+
}, Qr = {
|
|
2431
2483
|
cascade: "CASCADE",
|
|
2432
2484
|
restrict: "RESTRICT",
|
|
2433
2485
|
setNull: "SET NULL",
|
|
2434
2486
|
noAction: "NO ACTION"
|
|
2435
|
-
},
|
|
2487
|
+
}, $r = {
|
|
2436
2488
|
cascade: "CASCADE",
|
|
2437
2489
|
restrict: "NO ACTION",
|
|
2438
2490
|
setNull: "SET NULL",
|
|
2439
2491
|
noAction: "NO ACTION"
|
|
2440
|
-
},
|
|
2441
|
-
let t =
|
|
2492
|
+
}, ei = (e) => {
|
|
2493
|
+
let t = Er(e, "sqlite");
|
|
2442
2494
|
if (t !== void 0) return t;
|
|
2443
2495
|
switch (e.type) {
|
|
2444
2496
|
case "integer":
|
|
@@ -2450,29 +2502,29 @@ BEGIN
|
|
|
2450
2502
|
case "bytes": return "BLOB";
|
|
2451
2503
|
default: return "TEXT";
|
|
2452
2504
|
}
|
|
2453
|
-
},
|
|
2454
|
-
if (e.type === "id" && e.idScheme?.kind === "numeric") return
|
|
2455
|
-
let t =
|
|
2456
|
-
if (t) return `${W(e.name)} ${
|
|
2457
|
-
let n = [W(e.name),
|
|
2505
|
+
}, ti = (e, t) => e == null ? null : e === "now" ? `DEFAULT ${t}` : typeof e == "boolean" ? `DEFAULT ${+!!e}` : typeof e == "number" ? `DEFAULT ${e}` : typeof e == "string" ? /[()]|^'/.test(e) ? `DEFAULT ${e}` : `DEFAULT '${e.replace(/'/g, "''")}'` : typeof e == "object" ? N(e, "sqlite") : null, ni = (e) => {
|
|
2506
|
+
if (e.type === "id" && e.idScheme?.kind === "numeric") return P(e.name, "sqlite");
|
|
2507
|
+
let t = Ur(e, "sqlite");
|
|
2508
|
+
if (t) return `${W(e.name)} ${ei(e)} ${t}`;
|
|
2509
|
+
let n = [W(e.name), ei(e)];
|
|
2458
2510
|
if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && n.push("UNIQUE"), e.hasDefault) {
|
|
2459
|
-
let t =
|
|
2511
|
+
let t = ti(e.defaultValue, "CURRENT_TIMESTAMP");
|
|
2460
2512
|
t && n.push(t);
|
|
2461
2513
|
}
|
|
2462
|
-
if (e.references && (n.push(`REFERENCES ${W(e.references.table)} (${W(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${
|
|
2514
|
+
if (e.references && (n.push(`REFERENCES ${W(e.references.table)} (${W(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${Qr[e.references.onDelete]}`)), e.oneOf && e.oneOf.length > 0) {
|
|
2463
2515
|
let t = e.oneOf.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
|
|
2464
2516
|
n.push(`CHECK (${W(e.name)} IN (${t}))`);
|
|
2465
2517
|
}
|
|
2466
2518
|
return n.join(" ");
|
|
2467
|
-
},
|
|
2468
|
-
let t = e.columns.map((e) => ` ${
|
|
2519
|
+
}, ri = (e) => {
|
|
2520
|
+
let t = e.columns.map((e) => ` ${ni(e)}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${W(e.table)} (\n${t}${Gr(e, W)}\n)`];
|
|
2469
2521
|
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(", ")})${Y(t)}`);
|
|
2470
2522
|
return n;
|
|
2471
2523
|
}, q = (e, t) => {
|
|
2472
2524
|
let n = t.find((t) => t.tableName === e);
|
|
2473
2525
|
if (!n) return [];
|
|
2474
|
-
let r =
|
|
2475
|
-
|
|
2526
|
+
let r = R([n]).tables[0], i = `${e}__voltro_rebuild`, a = r.columns.map((e) => W(e.name)).join(", "), o = [
|
|
2527
|
+
...ri({
|
|
2476
2528
|
kind: "create-table",
|
|
2477
2529
|
table: i,
|
|
2478
2530
|
columns: r.columns,
|
|
@@ -2485,25 +2537,25 @@ BEGIN
|
|
|
2485
2537
|
];
|
|
2486
2538
|
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(", ")})${Y(t)}`);
|
|
2487
2539
|
return o;
|
|
2488
|
-
},
|
|
2540
|
+
}, ii = (e, t, n, r) => {
|
|
2489
2541
|
let i = r ?? e.nullable;
|
|
2490
|
-
return `ALTER TABLE ${J(n)} ALTER COLUMN ${J(t)} ${
|
|
2491
|
-
},
|
|
2542
|
+
return `ALTER TABLE ${J(n)} ALTER COLUMN ${J(t)} ${M(e, "mssql")} ${i ? "NULL" : "NOT NULL"};`;
|
|
2543
|
+
}, ai = (e, t) => {
|
|
2492
2544
|
let n = `DECLARE @dc sysname; SELECT @dc = dc.name FROM sys.default_constraints dc JOIN sys.columns col ON col.object_id = dc.parent_object_id AND col.column_id = dc.parent_column_id WHERE dc.parent_object_id = OBJECT_ID(N'${e.table.replace(/'/g, "''")}') AND col.name = N'${e.column.replace(/'/g, "''")}'; IF @dc IS NOT NULL EXEC(N'ALTER TABLE ${J(e.table)} DROP CONSTRAINT [' + @dc + ']');` + (t ? ` ${t}` : "");
|
|
2493
2545
|
if (!e.hasDefault) return n;
|
|
2494
|
-
let r =
|
|
2546
|
+
let r = ti(e.defaultValue, "SYSUTCDATETIME()");
|
|
2495
2547
|
if (!r) return n;
|
|
2496
2548
|
let i = r.replace(/^DEFAULT\s+/i, "");
|
|
2497
2549
|
return `${n} ALTER TABLE ${J(e.table)} ADD DEFAULT ${i} FOR ${J(e.column)};`;
|
|
2498
|
-
}, J = (e) => `[${e.replace(/]/g, "]]")}]`,
|
|
2499
|
-
let t =
|
|
2550
|
+
}, J = (e) => `[${e.replace(/]/g, "]]")}]`, oi = (e) => {
|
|
2551
|
+
let t = Er(e, "mssql");
|
|
2500
2552
|
if (t !== void 0) return t;
|
|
2501
2553
|
switch (e.type) {
|
|
2502
2554
|
case "id": return "NVARCHAR(64)";
|
|
2503
2555
|
case "reference": return e.referenceStorage === "numeric" ? "BIGINT" : "NVARCHAR(64)";
|
|
2504
2556
|
case "integer": return "INT";
|
|
2505
2557
|
case "real": return "FLOAT";
|
|
2506
|
-
case "decimal": return
|
|
2558
|
+
case "decimal": return wr(e, "DECIMAL");
|
|
2507
2559
|
case "bigint": return "BIGINT";
|
|
2508
2560
|
case "boolean": return "BIT";
|
|
2509
2561
|
case "timestamp": return "DATETIME2(6)";
|
|
@@ -2511,46 +2563,46 @@ BEGIN
|
|
|
2511
2563
|
case "bytes": return "VARBINARY(MAX)";
|
|
2512
2564
|
default: return "NVARCHAR(MAX)";
|
|
2513
2565
|
}
|
|
2514
|
-
},
|
|
2515
|
-
if (e.type === "id" && e.idScheme?.kind === "numeric") return
|
|
2516
|
-
let n = e.type === "text" && t?.has(e.name) ? "NVARCHAR(450)" :
|
|
2566
|
+
}, si = (e, t) => {
|
|
2567
|
+
if (e.type === "id" && e.idScheme?.kind === "numeric") return P(e.name, "mssql");
|
|
2568
|
+
let n = e.type === "text" && t?.has(e.name) ? "NVARCHAR(450)" : oi(e), r = Ur(e, "mssql");
|
|
2517
2569
|
if (r) return `${J(e.name)} ${r}`;
|
|
2518
2570
|
let i = [J(e.name), n];
|
|
2519
2571
|
if (e.type === "id" && i.push("PRIMARY KEY"), e.nullable || i.push("NOT NULL"), e.unique && e.type !== "id" && i.push("UNIQUE"), e.hasDefault) {
|
|
2520
|
-
let t =
|
|
2572
|
+
let t = ti(e.defaultValue, "SYSUTCDATETIME()");
|
|
2521
2573
|
t && i.push(t);
|
|
2522
2574
|
}
|
|
2523
|
-
return e.references && (i.push(`REFERENCES ${J(e.references.table)} (${J(e.references.column)})`), e.references.onDelete && i.push(`ON DELETE ${
|
|
2524
|
-
},
|
|
2525
|
-
let t = (e) => e.replace(/'/g, "''"), n = /* @__PURE__ */ new Set([...e.indexes.flatMap((e) => e.columns), ...e.columns.filter((e) => e.unique).map((e) => e.name)]), r = e.columns.map((e) => ` ${
|
|
2575
|
+
return e.references && (i.push(`REFERENCES ${J(e.references.table)} (${J(e.references.column)})`), e.references.onDelete && i.push(`ON DELETE ${$r[e.references.onDelete]}`)), i.join(" ");
|
|
2576
|
+
}, ci = (e) => {
|
|
2577
|
+
let t = (e) => e.replace(/'/g, "''"), n = /* @__PURE__ */ new Set([...e.indexes.flatMap((e) => e.columns), ...e.columns.filter((e) => e.unique).map((e) => e.name)]), r = e.columns.map((e) => ` ${si(e, n)}`).join(",\n"), i = `CREATE TABLE ${J(e.table)} (\n${r}${Gr(e, J)}\n)`, a = [`IF OBJECT_ID(N'${t(e.table)}', N'U') IS NULL EXEC(N'${t(i)}')`];
|
|
2526
2578
|
for (let n of e.indexes) {
|
|
2527
2579
|
if (n.name === `${e.table}_pkey`) continue;
|
|
2528
2580
|
let r = `CREATE ${n.unique ? "UNIQUE " : ""}INDEX ${J(n.name)} ON ${J(e.table)} (${n.columns.map(J).join(", ")})${Y(n)}`;
|
|
2529
2581
|
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)}')`);
|
|
2530
2582
|
}
|
|
2531
2583
|
return a;
|
|
2532
|
-
},
|
|
2533
|
-
let r = `${e.table}${
|
|
2584
|
+
}, li = (e) => `__dropped_${e.replace(/[-:T.Z]/g, "").slice(0, 14)}`, ui = (e, t) => `DROP TABLE IF EXISTS ${t(e.table)};`, di = (e, t, n) => {
|
|
2585
|
+
let r = `${e.table}${li(t)}`;
|
|
2534
2586
|
return `ALTER TABLE ${n(e.table)} RENAME TO ${n(r)};`;
|
|
2535
|
-
},
|
|
2536
|
-
if (e === void 0 || !
|
|
2587
|
+
}, fi = (e) => {
|
|
2588
|
+
if (e === void 0 || !Jr(e)) return;
|
|
2537
2589
|
let t = typeof e.maxLength == "number" && e.maxLength > 0 ? e.maxLength : void 0;
|
|
2538
|
-
return t === void 0 ?
|
|
2539
|
-
},
|
|
2540
|
-
let r =
|
|
2590
|
+
return t === void 0 ? qr : Math.min(qr, t);
|
|
2591
|
+
}, pi = (e, t, n) => {
|
|
2592
|
+
let r = fi(Rr(e, t, n));
|
|
2541
2593
|
return r === void 0 ? G(n) : `${G(n)}(${r})`;
|
|
2542
|
-
},
|
|
2594
|
+
}, mi = (e) => e.startsWith("(") ? e : W(e), Y = (e) => e.where === void 0 ? "" : ` WHERE ${e.where}`, hi = (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(mi).join(", ")})${Y(e.index)};`, gi = (e, t, n = "mariadb") => (_i(e.index, n), `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX ${Ar(n)}${G(e.index.name)} ON ${G(e.table)} (${e.index.columns.map((n) => pi(t, e.table, n)).join(", ")});`), _i = (e, t) => {
|
|
2543
2595
|
if (e.where !== void 0) throw Error(`Partial index '${e.name}' is not supported by ${t}; uniqueActive must be lowered before applying the plan.`);
|
|
2544
|
-
},
|
|
2596
|
+
}, vi = (e) => `DROP INDEX IF EXISTS ${W(e.index)};`, yi = (e) => `DROP INDEX ${G(e.index)} ON ${G(e.table)};`, bi = (e) => `DROP INDEX IF EXISTS ${J(e.index)} ON ${J(e.table)};`, xi = (e, t) => `ALTER TABLE ${t(e.from)} RENAME TO ${t(e.to)};`, Si = (e) => {
|
|
2545
2597
|
let t = (e) => e.replace(/'/g, "''");
|
|
2546
2598
|
return `EXEC sp_rename N'${t(e.from)}', N'${t(e.to)}';`;
|
|
2547
|
-
},
|
|
2599
|
+
}, Ci = (e) => `ALTER INDEX ${W(e.from)} RENAME TO ${W(e.to)};`, wi = (e) => `ALTER TABLE ${G(e.table)} RENAME INDEX ${G(e.from)} TO ${G(e.to)};`, Ti = (e) => {
|
|
2548
2600
|
let t = (e) => e.replace(/'/g, "''");
|
|
2549
2601
|
return `EXEC sp_rename N'${t(e.table)}.${t(e.from)}', N'${t(e.to)}', N'INDEX';`;
|
|
2550
|
-
},
|
|
2602
|
+
}, Ei = (e) => {
|
|
2551
2603
|
let t = (e) => e.replace(/'/g, "''"), n = `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX ${J(e.index.name)} ON ${J(e.table)} (${e.index.columns.map(J).join(", ")})${Y(e.index)}`;
|
|
2552
2604
|
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)}');`;
|
|
2553
|
-
},
|
|
2605
|
+
}, Di = (e, t, n) => {
|
|
2554
2606
|
let r = n.find((t) => t.tableName === e);
|
|
2555
2607
|
if (!r) return [];
|
|
2556
2608
|
let i = [];
|
|
@@ -2559,13 +2611,13 @@ BEGIN
|
|
|
2559
2611
|
t && t.type === "text" && !t.generatedAs && i.push(`ALTER TABLE ${J(e)} ALTER COLUMN ${J(n)} NVARCHAR(450) ${t.nullable ? "NULL" : "NOT NULL"};`);
|
|
2560
2612
|
}
|
|
2561
2613
|
return i;
|
|
2562
|
-
},
|
|
2614
|
+
}, Oi = (e) => `ALTER TABLE ${W(e.table)} ADD CONSTRAINT ${W(`${e.table}_${e.column}_key`)} UNIQUE (${W(e.column)});`, ki = (e, t) => `ALTER TABLE ${G(e.table)} ADD CONSTRAINT ${G(`${e.table}_${e.column}_key`)} UNIQUE (${pi(t, e.table, e.column)});`, Ai = (e) => {
|
|
2563
2615
|
let t = e.fields.map((e) => W(e)).join(", ");
|
|
2564
2616
|
return `ALTER TABLE ${W(e.table)} ADD CONSTRAINT ${W(e.name)} UNIQUE (${t});`;
|
|
2565
|
-
},
|
|
2566
|
-
let n = e.fields.map((n) =>
|
|
2617
|
+
}, ji = (e, t) => {
|
|
2618
|
+
let n = e.fields.map((n) => pi(t, e.table, n)).join(", ");
|
|
2567
2619
|
return `ALTER TABLE ${G(e.table)} ADD CONSTRAINT ${G(e.name)} UNIQUE (${n});`;
|
|
2568
|
-
},
|
|
2620
|
+
}, Mi = (e) => `ALTER TABLE ${W(e.table)} DROP CONSTRAINT IF EXISTS ${W(e.name)};`, Ni = (e) => `ALTER TABLE ${G(e.table)} DROP INDEX ${G(e.name)};`, Pi = (e) => `ALTER TABLE ${W(e.table)} DROP CONSTRAINT IF EXISTS ${W(`${e.table}_${e.column}_key`)};`, Fi = (e) => `ALTER TABLE ${G(e.table)} DROP INDEX ${G(`${e.table}_${e.column}_key`)};`, Ii = (e, t) => {
|
|
2569
2621
|
let n = [], r = t(e.table), i = t(e.column), a = t(e.targetTable), o = t(e.targetColumn);
|
|
2570
2622
|
if (e.orphanPolicy) {
|
|
2571
2623
|
let t = `${i} IS NOT NULL AND ${i} NOT IN (SELECT ${o} FROM ${a})`;
|
|
@@ -2583,10 +2635,10 @@ BEGIN
|
|
|
2583
2635
|
setNull: "SET NULL",
|
|
2584
2636
|
noAction: "NO ACTION"
|
|
2585
2637
|
}[e.onDelete]}`), n.push(s.join(" ") + ";"), n;
|
|
2586
|
-
},
|
|
2638
|
+
}, Li = (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`)};`, zi = (e, t) => {
|
|
2587
2639
|
let n = e.values.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
|
|
2588
2640
|
return `ALTER TABLE ${t(e.table)} ADD CONSTRAINT ${t(`${e.table}_${e.column}_check`)} CHECK (${t(e.column)} IN (${n}));`;
|
|
2589
|
-
},
|
|
2641
|
+
}, Bi = (e) => `ALTER TABLE ${W(e.table)} DROP CONSTRAINT IF EXISTS ${W(`${e.table}_${e.column}_check`)};`, Vi = (e, t) => w.gen(function* () {
|
|
2590
2642
|
let n = yield* e`
|
|
2591
2643
|
SELECT cc.constraint_name AS n, cc.check_clause AS c
|
|
2592
2644
|
FROM information_schema.check_constraints cc
|
|
@@ -2599,18 +2651,18 @@ BEGIN
|
|
|
2599
2651
|
WHERE tc.table_schema = DATABASE() AND tc.table_name = ${t.table}`), w.orElseSucceed(() => []));
|
|
2600
2652
|
for (let e of n) {
|
|
2601
2653
|
let n = String(e.n ?? "");
|
|
2602
|
-
if (n !== "" &&
|
|
2654
|
+
if (n !== "" && Gn(String(e.c ?? ""))?.column === t.column) return n;
|
|
2603
2655
|
}
|
|
2604
|
-
}),
|
|
2605
|
-
let r = yield*
|
|
2606
|
-
r !== void 0 && (yield* X(e, `ALTER TABLE ${G(t.table)} DROP CONSTRAINT ${G(r)};`, t.kind, [
|
|
2607
|
-
let i = yield*
|
|
2656
|
+
}), Hi = (e, t, n) => w.gen(function* () {
|
|
2657
|
+
let r = yield* Vi(e, t);
|
|
2658
|
+
r !== void 0 && (yield* X(e, `ALTER TABLE ${G(t.table)} DROP CONSTRAINT ${G(r)};`, t.kind, [Cr]));
|
|
2659
|
+
let i = yield* Vi(e, t);
|
|
2608
2660
|
if (i === void 0) return;
|
|
2609
2661
|
let a = K(n, t.table, t.column);
|
|
2610
2662
|
if (!a) return yield* w.die(/* @__PURE__ */ Error(`applier: cannot drop the CHECK on '${t.table}.${t.column}' — it is column-level (catalog name '${i}'), which this family removes only by redefining the column, and the declared column is not available to redefine it from.`));
|
|
2611
|
-
yield* X(e, `ALTER TABLE ${G(t.table)} MODIFY COLUMN ${
|
|
2612
|
-
}),
|
|
2613
|
-
let i = e.column, a = r === "mariadb", o = a ? G : r === "mssql" ? J : W, s = a ?
|
|
2663
|
+
yield* X(e, `ALTER TABLE ${G(t.table)} MODIFY COLUMN ${zr(a, t.column)};`, t.kind);
|
|
2664
|
+
}), Ui = (e, t, n, r) => {
|
|
2665
|
+
let i = e.column, a = r === "mariadb", o = a ? G : r === "mssql" ? J : W, s = a ? kr(i) : r === "mssql" ? oi(i) : r === "sqlite" ? ei(i) : Dr(i), c = r === "mssql" ? "ADD" : "ADD COLUMN", l = (e) => a ? Br(e, i) : r === "mssql" ? ti(e, "SYSUTCDATETIME()") : r === "sqlite" ? ti(e, "CURRENT_TIMESTAMP") : Hr(e, i), u = Ur(i, r);
|
|
2614
2666
|
if (u) {
|
|
2615
2667
|
let t = r === "mssql" ? `${o(i.name)} ${u}` : `${o(i.name)} ${s} ${u}`;
|
|
2616
2668
|
return {
|
|
@@ -2638,7 +2690,7 @@ BEGIN
|
|
|
2638
2690
|
post: f ? [f] : []
|
|
2639
2691
|
};
|
|
2640
2692
|
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;
|
|
2641
|
-
},
|
|
2693
|
+
}, Wi = (e) => {
|
|
2642
2694
|
let t = new Map(e.map((e) => [e.tableName, e]));
|
|
2643
2695
|
return (e, n) => {
|
|
2644
2696
|
let r = t.get(e);
|
|
@@ -2658,47 +2710,47 @@ BEGIN
|
|
|
2658
2710
|
...o
|
|
2659
2711
|
};
|
|
2660
2712
|
};
|
|
2661
|
-
}, X = (e, t, n, r = []) => e.unsafe(t).pipe(w.catchIf((e) =>
|
|
2662
|
-
process.stderr.write(
|
|
2713
|
+
}, X = (e, t, n, r = []) => e.unsafe(t).pipe(w.catchIf((e) => yr(e, r), () => w.void), w.tapError((e) => w.sync(() => {
|
|
2714
|
+
process.stderr.write(se(`applier: statement failed (op=${n})`, t, e, 400));
|
|
2663
2715
|
})), w.mapError((e) => {
|
|
2664
|
-
let r =
|
|
2716
|
+
let r = se(`applier: statement failed (op=${n})`, t, e, 400).trim();
|
|
2665
2717
|
return Object.assign(e, { message: r });
|
|
2666
|
-
}), w.map(() => void 0)), Z = (e, t, n) => w.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 ? "*" : o(r, t)} FROM ${o(n, t)} WHERE 1=0`).pipe(w.as(!0), w.catchAll(() => w.succeed(!1))),
|
|
2667
|
-
let n =
|
|
2718
|
+
}), w.map(() => void 0)), Z = (e, t, n) => w.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 ? "*" : o(r, t)} FROM ${o(n, t)} WHERE 1=0`).pipe(w.as(!0), w.catchAll(() => w.succeed(!1))), Gi = (e, t) => w.gen(function* () {
|
|
2719
|
+
let n = R([Be], t).tables[0];
|
|
2668
2720
|
if (!n) return yield* w.die(/* @__PURE__ */ Error("migration applier: the resume-ledger table descriptor produced no snapshot. This is a framework bug."));
|
|
2669
2721
|
let r = {
|
|
2670
2722
|
kind: "create-table",
|
|
2671
|
-
table:
|
|
2723
|
+
table: k,
|
|
2672
2724
|
columns: n.columns,
|
|
2673
2725
|
indexes: []
|
|
2674
2726
|
}, i = yield* e.onDialectOrElse({
|
|
2675
|
-
mysql: () =>
|
|
2676
|
-
mssql: () => w.succeed(
|
|
2677
|
-
sqlite: () => w.succeed(
|
|
2678
|
-
orElse: () => w.succeed(
|
|
2727
|
+
mysql: () => hr(e).pipe(w.map((e) => Zr(r, e))),
|
|
2728
|
+
mssql: () => w.succeed(ci(r)),
|
|
2729
|
+
sqlite: () => w.succeed(ri(r)),
|
|
2730
|
+
orElse: () => w.succeed(Kr(r))
|
|
2679
2731
|
});
|
|
2680
2732
|
yield* w.forEach(i, (t) => X(e, t, "resume-ledger-bootstrap"), { discard: !0 });
|
|
2681
|
-
}),
|
|
2733
|
+
}), Ki = (e) => e`
|
|
2682
2734
|
SELECT ${e("runId")}, ${e("planFingerprint")}, ${e("opIndex")},
|
|
2683
2735
|
${e("status")}, ${e("payload")}
|
|
2684
|
-
FROM ${e(
|
|
2685
|
-
`,
|
|
2736
|
+
FROM ${e(k)}
|
|
2737
|
+
`, qi = (e, t, n, r) => w.gen(function* () {
|
|
2686
2738
|
let i = yield* U(e, (/* @__PURE__ */ new Date()).toISOString());
|
|
2687
2739
|
yield* w.forEach(r, ({ index: r, planned: a }) => e`
|
|
2688
|
-
INSERT INTO ${e(
|
|
2740
|
+
INSERT INTO ${e(k)}
|
|
2689
2741
|
(${e("id")}, ${e("runId")}, ${e("planFingerprint")}, ${e("opIndex")},
|
|
2690
2742
|
${e("opKind")}, ${e("opTarget")}, ${e("status")}, ${e("payload")},
|
|
2691
2743
|
${e("createdAt")})
|
|
2692
2744
|
VALUES
|
|
2693
2745
|
(${`mop_${t}_${r}`}, ${t}, ${n}, ${r},
|
|
2694
|
-
${a.op.kind}, ${
|
|
2746
|
+
${a.op.kind}, ${He(a.op)}, ${"pending"},
|
|
2695
2747
|
${JSON.stringify(a)}, ${i})
|
|
2696
2748
|
`, { discard: !0 });
|
|
2697
|
-
}),
|
|
2749
|
+
}), Ji = (e, t, n, r, i) => w.gen(function* () {
|
|
2698
2750
|
let a = yield* U(e, (/* @__PURE__ */ new Date()).toISOString());
|
|
2699
2751
|
if (r === "applied") {
|
|
2700
2752
|
yield* e`
|
|
2701
|
-
UPDATE ${e(
|
|
2753
|
+
UPDATE ${e(k)}
|
|
2702
2754
|
SET ${e("status")} = ${r}, ${e("appliedAt")} = ${a},
|
|
2703
2755
|
${e("durationMs")} = ${i ?? null}
|
|
2704
2756
|
WHERE ${e("runId")} = ${t} AND ${e("opIndex")} = ${n}
|
|
@@ -2706,50 +2758,50 @@ BEGIN
|
|
|
2706
2758
|
return;
|
|
2707
2759
|
}
|
|
2708
2760
|
yield* e`
|
|
2709
|
-
UPDATE ${e(
|
|
2761
|
+
UPDATE ${e(k)}
|
|
2710
2762
|
SET ${e("status")} = ${r}, ${e("startedAt")} = ${a}
|
|
2711
2763
|
WHERE ${e("runId")} = ${t} AND ${e("opIndex")} = ${n}
|
|
2712
2764
|
`;
|
|
2713
|
-
}),
|
|
2765
|
+
}), Yi = (e, t, n, r) => w.gen(function* () {
|
|
2714
2766
|
let i = yield* U(e, (/* @__PURE__ */ new Date()).toISOString());
|
|
2715
2767
|
r.length > 0 && (yield* e`
|
|
2716
|
-
UPDATE ${e(
|
|
2768
|
+
UPDATE ${e(k)}
|
|
2717
2769
|
SET ${e("status")} = ${"applied"}, ${e("appliedAt")} = ${i}
|
|
2718
2770
|
WHERE ${e("runId")} = ${t} AND ${e("opIndex")} IN ${e.in(r)}
|
|
2719
2771
|
`), n.length > 0 && (yield* e`
|
|
2720
|
-
UPDATE ${e(
|
|
2772
|
+
UPDATE ${e(k)}
|
|
2721
2773
|
SET ${e("status")} = ${"pending"}
|
|
2722
2774
|
WHERE ${e("runId")} = ${t} AND ${e("opIndex")} IN ${e.in(n)}
|
|
2723
2775
|
`);
|
|
2724
|
-
}),
|
|
2725
|
-
if (
|
|
2776
|
+
}), Xi = (e, t) => t === void 0 ? e`DELETE FROM ${e(k)}`.pipe(w.asVoid) : e`DELETE FROM ${e(k)} WHERE ${e("runId")} = ${t}`.pipe(w.asVoid), Zi = (e, t, n) => w.gen(function* () {
|
|
2777
|
+
if (Xe(n.op, n.classification, t) !== "artefact-repair") return "clean";
|
|
2726
2778
|
let r = n.op, i = (e) => o(e, t);
|
|
2727
2779
|
if (t === "sqlite" || t === "turso") {
|
|
2728
2780
|
if (!("table" in r)) return "clean";
|
|
2729
|
-
let n = `${r.table}${
|
|
2781
|
+
let n = `${r.table}${Ge}`;
|
|
2730
2782
|
return (yield* $(e, t, n)) ? ((yield* $(e, t, r.table)) ? yield* X(e, `DROP TABLE ${i(n)}`, "resume-repair") : yield* X(e, `ALTER TABLE ${i(n)} RENAME TO ${i(r.table)}`, "resume-repair"), yield* w.logWarning(`migration resume: reconciled an interrupted sqlite table rebuild on '${r.table}' — replaying the operation`).pipe(w.annotateLogs({ scope: "voltro:migrate" })), "outstanding") : "clean";
|
|
2731
2783
|
}
|
|
2732
2784
|
if (r.kind !== "alter-column-type") return "clean";
|
|
2733
|
-
let a = `${r.column}${
|
|
2785
|
+
let a = `${r.column}${Ke}`, s = `${r.column}${qe}`, c = yield* $(e, t, r.table, r.column), l = yield* $(e, t, r.table, a), u = yield* $(e, t, r.table, s), d = (e) => w.logWarning(`migration resume: ${e}`).pipe(w.annotateLogs({ scope: "voltro:migrate" }));
|
|
2734
2786
|
return !l && !u ? "clean" : c && l && !u ? (yield* X(e, `ALTER TABLE ${i(r.table)} DROP COLUMN ${i(a)}`, "resume-repair"), yield* d(`dropped a half-populated shadow column '${r.table}.${a}' — replaying the type change`), "outstanding") : !c && l && u ? (yield* X(e, `ALTER TABLE ${i(r.table)} RENAME COLUMN ${i(a)} TO ${i(r.column)}`, "resume-repair"), yield* X(e, `ALTER TABLE ${i(r.table)} DROP COLUMN ${i(s)}`, "resume-repair"), yield* d(`completed an interrupted shadow swap on '${r.table}.${r.column}'`), "applied") : c && !l && u ? (yield* X(e, `ALTER TABLE ${i(r.table)} DROP COLUMN ${i(s)}`, "resume-repair"), yield* d(`dropped the leftover pre-swap column '${r.table}.${s}'`), "applied") : yield* w.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}, ${a}=${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.`));
|
|
2735
|
-
}),
|
|
2736
|
-
let i = process.hrtime.bigint(), a =
|
|
2787
|
+
}), Qi = (e, t, n, r = "fresh") => w.gen(function* () {
|
|
2788
|
+
let i = process.hrtime.bigint(), a = Wi(n.declared), o = t.op;
|
|
2737
2789
|
switch (o.kind) {
|
|
2738
2790
|
case "create-table": {
|
|
2739
2791
|
let t = yield* e.onDialectOrElse({
|
|
2740
|
-
mysql: () =>
|
|
2741
|
-
mssql: () => w.succeed(
|
|
2742
|
-
sqlite: () => w.succeed(
|
|
2743
|
-
orElse: () => w.succeed(
|
|
2792
|
+
mysql: () => hr(e).pipe(w.map((e) => Zr(o, e))),
|
|
2793
|
+
mssql: () => w.succeed(ci(o)),
|
|
2794
|
+
sqlite: () => w.succeed(ri(o)),
|
|
2795
|
+
orElse: () => w.succeed(Kr(o))
|
|
2744
2796
|
}), n = yield* e.onDialectOrElse({
|
|
2745
|
-
mysql: () => w.succeed([
|
|
2797
|
+
mysql: () => w.succeed([br]),
|
|
2746
2798
|
orElse: () => w.succeed([])
|
|
2747
2799
|
});
|
|
2748
2800
|
for (let r of t) yield* X(e, r, o.kind, n);
|
|
2749
2801
|
break;
|
|
2750
2802
|
}
|
|
2751
2803
|
case "drop-table": {
|
|
2752
|
-
let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString(), r = (e) => t ?
|
|
2804
|
+
let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString(), r = (e) => t ? di(o, n, e) : ui(o, e);
|
|
2753
2805
|
yield* e.onDialectOrElse({
|
|
2754
2806
|
mysql: () => X(e, r(G), o.kind),
|
|
2755
2807
|
orElse: () => X(e, r(W), o.kind)
|
|
@@ -2759,93 +2811,93 @@ BEGIN
|
|
|
2759
2811
|
case "drop-column": {
|
|
2760
2812
|
let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString();
|
|
2761
2813
|
yield* e.onDialectOrElse({
|
|
2762
|
-
mysql: () =>
|
|
2763
|
-
sqlite: () => X(e, t ?
|
|
2764
|
-
orElse: () => X(e, t ?
|
|
2814
|
+
mysql: () => hr(e).pipe(w.flatMap((r) => X(e, t ? Pr(o, n, G) : Mr(o, r), o.kind, t ? [] : [xr]))),
|
|
2815
|
+
sqlite: () => X(e, t ? Pr(o, n, W) : jr(o, W, !1), o.kind, t ? [] : [Sr]),
|
|
2816
|
+
orElse: () => X(e, t ? Pr(o, n, W) : jr(o, W), o.kind)
|
|
2765
2817
|
});
|
|
2766
2818
|
break;
|
|
2767
2819
|
}
|
|
2768
2820
|
case "rename-column":
|
|
2769
2821
|
yield* e.onDialectOrElse({
|
|
2770
|
-
mysql: () => X(e,
|
|
2822
|
+
mysql: () => X(e, Nr(o, G), o.kind),
|
|
2771
2823
|
mssql: () => X(e, `EXEC sp_rename N'${o.table.replace(/'/g, "''")}.${o.from.replace(/'/g, "''")}', N'${o.to.replace(/'/g, "''")}', 'COLUMN';`, o.kind),
|
|
2772
|
-
orElse: () => X(e,
|
|
2824
|
+
orElse: () => X(e, Nr(o, W), o.kind)
|
|
2773
2825
|
});
|
|
2774
2826
|
break;
|
|
2775
2827
|
case "add-index":
|
|
2776
2828
|
yield* e.onDialectOrElse({
|
|
2777
|
-
sqlite: () => X(e,
|
|
2778
|
-
mysql: () =>
|
|
2779
|
-
mssql: () => Z(e, [...
|
|
2780
|
-
orElse: () => X(e,
|
|
2829
|
+
sqlite: () => X(e, hi(o, !1), o.kind),
|
|
2830
|
+
mysql: () => hr(e).pipe(w.flatMap((t) => X(e, gi(o, n.declared, t), o.kind, [br]))),
|
|
2831
|
+
mssql: () => Z(e, [...Di(o.table, o.index.columns, n.declared), Ei(o)], o.kind),
|
|
2832
|
+
orElse: () => X(e, hi(o, t.classification === "online-required"), o.kind)
|
|
2781
2833
|
});
|
|
2782
2834
|
break;
|
|
2783
2835
|
case "drop-index":
|
|
2784
2836
|
yield* e.onDialectOrElse({
|
|
2785
|
-
mysql: () => X(e,
|
|
2786
|
-
mssql: () => X(e,
|
|
2787
|
-
orElse: () => X(e,
|
|
2837
|
+
mysql: () => X(e, yi(o), o.kind),
|
|
2838
|
+
mssql: () => X(e, bi(o), o.kind),
|
|
2839
|
+
orElse: () => X(e, vi(o), o.kind)
|
|
2788
2840
|
});
|
|
2789
2841
|
break;
|
|
2790
2842
|
case "rename-table":
|
|
2791
2843
|
yield* e.onDialectOrElse({
|
|
2792
|
-
mysql: () => X(e,
|
|
2793
|
-
mssql: () => X(e,
|
|
2794
|
-
orElse: () => X(e,
|
|
2844
|
+
mysql: () => X(e, xi(o, G), o.kind),
|
|
2845
|
+
mssql: () => X(e, Si(o), o.kind),
|
|
2846
|
+
orElse: () => X(e, xi(o, W), o.kind)
|
|
2795
2847
|
});
|
|
2796
2848
|
break;
|
|
2797
2849
|
case "rename-index":
|
|
2798
2850
|
yield* e.onDialectOrElse({
|
|
2799
|
-
mysql: () => X(e,
|
|
2800
|
-
mssql: () => X(e,
|
|
2801
|
-
orElse: () => X(e,
|
|
2851
|
+
mysql: () => X(e, wi(o), o.kind),
|
|
2852
|
+
mssql: () => X(e, Ti(o), o.kind),
|
|
2853
|
+
orElse: () => X(e, Ci(o), o.kind)
|
|
2802
2854
|
});
|
|
2803
2855
|
break;
|
|
2804
2856
|
case "add-unique":
|
|
2805
2857
|
yield* e.onDialectOrElse({
|
|
2806
|
-
mysql: () => X(e,
|
|
2858
|
+
mysql: () => X(e, ki(o, n.declared), o.kind),
|
|
2807
2859
|
sqlite: () => Z(e, q(o.table, n.declared), o.kind),
|
|
2808
|
-
mssql: () => Z(e, [...
|
|
2809
|
-
orElse: () => X(e,
|
|
2860
|
+
mssql: () => Z(e, [...Di(o.table, [o.column], n.declared), Oi(o)], o.kind),
|
|
2861
|
+
orElse: () => X(e, Oi(o), o.kind)
|
|
2810
2862
|
});
|
|
2811
2863
|
break;
|
|
2812
2864
|
case "drop-unique":
|
|
2813
2865
|
yield* e.onDialectOrElse({
|
|
2814
|
-
mysql: () => X(e,
|
|
2866
|
+
mysql: () => X(e, Fi(o), o.kind),
|
|
2815
2867
|
sqlite: () => Z(e, q(o.table, n.declared), o.kind),
|
|
2816
|
-
orElse: () => X(e,
|
|
2868
|
+
orElse: () => X(e, Pi(o), o.kind)
|
|
2817
2869
|
});
|
|
2818
2870
|
break;
|
|
2819
2871
|
case "add-unique-composite":
|
|
2820
2872
|
yield* e.onDialectOrElse({
|
|
2821
|
-
mysql: () => X(e,
|
|
2873
|
+
mysql: () => X(e, ji(o, n.declared), o.kind),
|
|
2822
2874
|
sqlite: () => Z(e, q(o.table, n.declared), o.kind),
|
|
2823
|
-
mssql: () => Z(e, [...
|
|
2824
|
-
orElse: () => X(e,
|
|
2875
|
+
mssql: () => Z(e, [...Di(o.table, o.fields, n.declared), Ai(o)], o.kind),
|
|
2876
|
+
orElse: () => X(e, Ai(o), o.kind)
|
|
2825
2877
|
});
|
|
2826
2878
|
break;
|
|
2827
2879
|
case "drop-unique-composite":
|
|
2828
2880
|
yield* e.onDialectOrElse({
|
|
2829
|
-
mysql: () => X(e,
|
|
2881
|
+
mysql: () => X(e, Ni(o), o.kind),
|
|
2830
2882
|
sqlite: () => Z(e, q(o.table, n.declared), o.kind),
|
|
2831
|
-
orElse: () => X(e,
|
|
2883
|
+
orElse: () => X(e, Mi(o), o.kind)
|
|
2832
2884
|
});
|
|
2833
2885
|
break;
|
|
2834
2886
|
case "add-foreign-key":
|
|
2835
2887
|
yield* e.onDialectOrElse({
|
|
2836
|
-
mysql: () => Z(e,
|
|
2888
|
+
mysql: () => Z(e, Ii(o, G), o.kind),
|
|
2837
2889
|
sqlite: () => Z(e, q(o.table, n.declared), o.kind),
|
|
2838
|
-
orElse: () => Z(e,
|
|
2890
|
+
orElse: () => Z(e, Ii(o, W), o.kind)
|
|
2839
2891
|
});
|
|
2840
2892
|
break;
|
|
2841
2893
|
case "add-column": {
|
|
2842
|
-
let n =
|
|
2894
|
+
let n = Ui(o, t, a, yield* e.onDialectOrElse({
|
|
2843
2895
|
mysql: () => w.succeed("mariadb"),
|
|
2844
2896
|
mssql: () => w.succeed("mssql"),
|
|
2845
2897
|
sqlite: () => w.succeed("sqlite"),
|
|
2846
2898
|
orElse: () => w.succeed("postgres")
|
|
2847
2899
|
}));
|
|
2848
|
-
if (!(r === "resume" && (yield* $(e,
|
|
2900
|
+
if (!(r === "resume" && (yield* $(e, Le(e), o.table, o.column.name)))) for (let t of n.pre) yield* X(e, t, o.kind);
|
|
2849
2901
|
if (n.backfillKind === "sql" && n.backfillSql) {
|
|
2850
2902
|
if (t.classification !== "online-required" && n.batchSize === void 0) yield* e`UPDATE ${e(o.table)} SET ${e(o.column.name)} = ${n.backfillSql}`;
|
|
2851
2903
|
else {
|
|
@@ -2886,43 +2938,43 @@ BEGIN
|
|
|
2886
2938
|
yield* e.onDialectOrElse({
|
|
2887
2939
|
mysql: () => {
|
|
2888
2940
|
let t = K(n.declared, o.table, o.column);
|
|
2889
|
-
return t ? X(e, `ALTER TABLE ${G(o.table)} MODIFY COLUMN ${
|
|
2941
|
+
return t ? X(e, `ALTER TABLE ${G(o.table)} MODIFY COLUMN ${zr(t, o.column, o.toNullable)};`, o.kind) : w.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.`));
|
|
2890
2942
|
},
|
|
2891
2943
|
mssql: () => {
|
|
2892
2944
|
let t = K(n.declared, o.table, o.column);
|
|
2893
|
-
return t ? X(e,
|
|
2945
|
+
return t ? X(e, ii(t, o.column, o.table, o.toNullable), o.kind) : w.die(/* @__PURE__ */ Error(`alter-column-nullability on mssql needs the declared column '${o.table}.${o.column}'.`));
|
|
2894
2946
|
},
|
|
2895
2947
|
sqlite: () => Z(e, q(o.table, n.declared), o.kind),
|
|
2896
2948
|
orElse: () => X(e, `ALTER TABLE ${W(o.table)} ALTER COLUMN ${W(o.column)} ${o.toNullable ? "DROP NOT NULL" : "SET NOT NULL"};`, o.kind)
|
|
2897
2949
|
});
|
|
2898
2950
|
break;
|
|
2899
2951
|
case "alter-column-default": {
|
|
2900
|
-
let t =
|
|
2952
|
+
let t = Rr(n.declared, o.table, o.column), r = K(n.declared, o.table, o.column), i = (e) => o.hasDefault && r !== void 0 && Ir(r, e) ? r : void 0;
|
|
2901
2953
|
yield* e.onDialectOrElse({
|
|
2902
2954
|
mysql: () => {
|
|
2903
2955
|
let n = i("mariadb");
|
|
2904
|
-
return X(e, n ? `ALTER TABLE ${G(o.table)} MODIFY COLUMN ${
|
|
2956
|
+
return X(e, n ? `ALTER TABLE ${G(o.table)} MODIFY COLUMN ${zr(n, o.column)};` : Fr(o, G, (e) => Br(e, t)), o.kind);
|
|
2905
2957
|
},
|
|
2906
2958
|
mssql: () => {
|
|
2907
2959
|
let t = i("mssql");
|
|
2908
|
-
return X(e,
|
|
2960
|
+
return X(e, ai(o, t ? ii(t, o.column, o.table) : void 0), o.kind);
|
|
2909
2961
|
},
|
|
2910
2962
|
sqlite: () => Z(e, q(o.table, n.declared), o.kind),
|
|
2911
|
-
orElse: () => X(e,
|
|
2963
|
+
orElse: () => X(e, Fr(o, W, (e) => Hr(e, t)), o.kind)
|
|
2912
2964
|
});
|
|
2913
2965
|
break;
|
|
2914
2966
|
}
|
|
2915
2967
|
case "alter-column-type": {
|
|
2916
|
-
let r =
|
|
2968
|
+
let r = Dr(Rr(n.declared, o.table, o.column) ?? { type: o.to }), i = o.using ? ` USING ${o.using}` : "";
|
|
2917
2969
|
if (t.classification !== "online-required") {
|
|
2918
2970
|
yield* e.onDialectOrElse({
|
|
2919
2971
|
mysql: () => {
|
|
2920
2972
|
let t = K(n.declared, o.table, o.column);
|
|
2921
|
-
return t ? X(e, `ALTER TABLE ${G(o.table)} MODIFY COLUMN ${
|
|
2973
|
+
return t ? X(e, `ALTER TABLE ${G(o.table)} MODIFY COLUMN ${zr(t, o.column)};`, o.kind) : w.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.`));
|
|
2922
2974
|
},
|
|
2923
2975
|
mssql: () => {
|
|
2924
2976
|
let t = K(n.declared, o.table, o.column);
|
|
2925
|
-
return t ? X(e,
|
|
2977
|
+
return t ? X(e, ii(t, o.column, o.table), o.kind) : w.die(/* @__PURE__ */ Error(`alter-column-type on mssql needs the declared column '${o.table}.${o.column}'.`));
|
|
2926
2978
|
},
|
|
2927
2979
|
sqlite: () => Z(e, q(o.table, n.declared), o.kind),
|
|
2928
2980
|
orElse: () => X(e, `ALTER TABLE ${W(o.table)} ALTER COLUMN ${W(o.column)} TYPE ${r}${i};`, o.kind)
|
|
@@ -2946,22 +2998,22 @@ BEGIN
|
|
|
2946
2998
|
}
|
|
2947
2999
|
case "drop-foreign-key":
|
|
2948
3000
|
yield* e.onDialectOrElse({
|
|
2949
|
-
mysql: () => X(e,
|
|
3001
|
+
mysql: () => X(e, Ri(o), o.kind),
|
|
2950
3002
|
sqlite: () => Z(e, q(o.table, n.declared), o.kind),
|
|
2951
|
-
orElse: () => X(e,
|
|
3003
|
+
orElse: () => X(e, Li(o), o.kind)
|
|
2952
3004
|
});
|
|
2953
3005
|
break;
|
|
2954
3006
|
case "add-check":
|
|
2955
3007
|
yield* e.onDialectOrElse({
|
|
2956
|
-
mysql: () => X(e,
|
|
3008
|
+
mysql: () => X(e, zi(o, G), o.kind),
|
|
2957
3009
|
sqlite: () => Z(e, q(o.table, n.declared), o.kind),
|
|
2958
|
-
orElse: () => X(e,
|
|
3010
|
+
orElse: () => X(e, zi(o, W), o.kind)
|
|
2959
3011
|
});
|
|
2960
3012
|
break;
|
|
2961
3013
|
case "drop-check": yield* e.onDialectOrElse({
|
|
2962
|
-
mysql: () =>
|
|
3014
|
+
mysql: () => Hi(e, o, n.declared),
|
|
2963
3015
|
sqlite: () => Z(e, q(o.table, n.declared), o.kind),
|
|
2964
|
-
orElse: () => X(e,
|
|
3016
|
+
orElse: () => X(e, Bi(o), o.kind)
|
|
2965
3017
|
});
|
|
2966
3018
|
}
|
|
2967
3019
|
return {
|
|
@@ -2969,32 +3021,32 @@ BEGIN
|
|
|
2969
3021
|
status: "applied",
|
|
2970
3022
|
durationMs: Number((process.hrtime.bigint() - i) / 1000000n)
|
|
2971
3023
|
};
|
|
2972
|
-
}),
|
|
3024
|
+
}), $i = (e, t, n, r) => w.gen(function* () {
|
|
2973
3025
|
let i = [...new Set(r.map((e) => e.runId))];
|
|
2974
|
-
if (i.length > 1) return yield* w.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 \`${
|
|
3026
|
+
if (i.length > 1) return yield* w.die(/* @__PURE__ */ Error(`applyPlan: the resume ledger holds ${i.length} unfinished runs (${i.join(", ")}). Only one migration may be in flight at a time — the advisory lock enforces it — so this means a run was interrupted and a LATER one wrote over it without clearing.\nNothing was changed. Inspect \`${k}\`, reconcile the schema by hand, and delete the rows of the run you have finished.`));
|
|
2975
3027
|
let a = i[0], o = [...r].map((e) => ({
|
|
2976
3028
|
index: Number(e.opIndex),
|
|
2977
3029
|
status: e.status,
|
|
2978
3030
|
planned: JSON.parse(e.payload)
|
|
2979
3031
|
})).sort((e, t) => e.index - t.index), s = o.find((e) => e.status === "started"), c = o.filter((e) => e.status === "started").length;
|
|
2980
|
-
if (c > 1) return yield* w.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 \`${
|
|
2981
|
-
if (yield* w.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} ${
|
|
3032
|
+
if (c > 1) return yield* w.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 \`${k}\` by hand before re-running.`));
|
|
3033
|
+
if (yield* w.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} ${He(s.planned.op)}` : ""}`).pipe(w.annotateLogs({ scope: "voltro:migrate" })), o.every((e) => e.status === "pending")) return {
|
|
2982
3034
|
kind: "discard",
|
|
2983
3035
|
runId: a,
|
|
2984
3036
|
why: "no operation had started — no DDL ran"
|
|
2985
3037
|
};
|
|
2986
|
-
let l = s ? yield*
|
|
3038
|
+
let l = s ? yield* Zi(e, t, s.planned) : "clean", u = r[0].planFingerprint;
|
|
2987
3039
|
if (u !== n.toFingerprint) return {
|
|
2988
3040
|
kind: "discard",
|
|
2989
3041
|
runId: a,
|
|
2990
3042
|
why: `the declared schema changed since the interruption (recorded target ${u.slice(0, 12)}…, current ${n.toFingerprint.slice(0, 12)}…) — applying the freshly-diffed plan instead`
|
|
2991
3043
|
};
|
|
2992
|
-
let d = (e) => e.status === "applied" ? !1 : s && e.index === s.index && l !== "clean" ? l === "outstanding" :
|
|
3044
|
+
let d = (e) => e.status === "applied" ? !1 : s && e.index === s.index && l !== "clean" ? l === "outstanding" : We(n, e.planned.op), f = o.filter(d), p = o.filter((e) => e.status !== "applied" && !d(e));
|
|
2993
3045
|
return f.length === 0 ? {
|
|
2994
3046
|
kind: "discard",
|
|
2995
3047
|
runId: a,
|
|
2996
3048
|
why: "every recorded operation had already taken effect"
|
|
2997
|
-
} : (yield*
|
|
3049
|
+
} : (yield* Yi(e, a, f.map((e) => e.index), p.map((e) => e.index)), yield* w.logWarning(`migration resume: continuing run ${a} — replaying ${f.length} operation(s), ${o.length - f.length} already applied`).pipe(w.annotateLogs({ scope: "voltro:migrate" })), {
|
|
2998
3050
|
kind: "resume",
|
|
2999
3051
|
runId: a,
|
|
3000
3052
|
ops: f.map((e) => ({
|
|
@@ -3002,7 +3054,7 @@ BEGIN
|
|
|
3002
3054
|
planned: e.planned
|
|
3003
3055
|
}))
|
|
3004
3056
|
});
|
|
3005
|
-
}),
|
|
3057
|
+
}), ea = (e, t, n) => w.gen(function* () {
|
|
3006
3058
|
for (let r of t.operations) {
|
|
3007
3059
|
let i = r.op;
|
|
3008
3060
|
if (i.kind !== "add-index" || !i.index.unique || i.index.where === void 0 || t.operations.some((e) => e.op.kind === "rename-table" ? e.op.to === i.table : e.op.table === i.table && [
|
|
@@ -3013,7 +3065,7 @@ BEGIN
|
|
|
3013
3065
|
let a = i.index.columns.map((e) => e.startsWith("(") ? e : o(e, n)), s = n === "mssql" ? "" : a.map((e) => ` AND ${e} IS NOT NULL`).join(""), c = n === "mssql" ? "SELECT TOP (1) 1" : "SELECT 1", l = n === "mssql" ? "" : " LIMIT 1";
|
|
3014
3066
|
if ((yield* e.unsafe(`${c} FROM ${o(i.table, n)} WHERE (${i.index.where})${s} GROUP BY ${a.join(", ")} HAVING COUNT(*) > 1${l}`)).length > 0) return yield* w.die(/* @__PURE__ */ Error(`applyPlan: partial unique index '${i.index.name}' on '${i.table}' conflicts with existing qualifying rows. No schema or row changes were applied. Resolve the conflicting data explicitly before retrying.`));
|
|
3015
3067
|
}
|
|
3016
|
-
}),
|
|
3068
|
+
}), ta = (e) => {
|
|
3017
3069
|
let t = e.op, n = (e) => typeof t[e] == "string" ? t[e] : "";
|
|
3018
3070
|
return [
|
|
3019
3071
|
t.kind,
|
|
@@ -3022,13 +3074,13 @@ BEGIN
|
|
|
3022
3074
|
n("name"),
|
|
3023
3075
|
n("to")
|
|
3024
3076
|
].join("\0");
|
|
3025
|
-
},
|
|
3077
|
+
}, na = (e, t, n) => w.acquireUseRelease(Fe(e, { schema: n.lockSchema }), () => ra(e, t, n), (e) => e.release.pipe(w.orDie)), ra = (e, t, n) => w.gen(function* () {
|
|
3026
3078
|
let r = t.operations.filter((e) => e.blocked);
|
|
3027
3079
|
if (r.length > 0) return yield* w.die(/* @__PURE__ */ Error(`applyPlan: refusing to execute — ${r.length} blocked operations. Run \`voltro db plan\` to see the fixes.`));
|
|
3028
|
-
let i = Date.now(), a = [], o =
|
|
3080
|
+
let i = Date.now(), a = [], o = Le(e), s = yield* n.replan(e), c = new Set(t.operations.filter((e) => !e.blocked).map((e) => ta(e))), l = {
|
|
3029
3081
|
...s,
|
|
3030
3082
|
operations: s.operations.map((e) => {
|
|
3031
|
-
if (!e.blocked || !c.has(
|
|
3083
|
+
if (!e.blocked || !c.has(ta(e))) return e;
|
|
3032
3084
|
let { blocked: t, ...n } = e;
|
|
3033
3085
|
return n;
|
|
3034
3086
|
})
|
|
@@ -3036,47 +3088,47 @@ BEGIN
|
|
|
3036
3088
|
(l.operations.length !== t.operations.length || l.toFingerprint !== t.toFingerprint) && (yield* w.logInfo(`migration: re-planned under the lock — ${t.operations.length} operation(s) became ${l.operations.length}. Another writer changed the schema while this plan waited.`).pipe(w.annotateLogs({ scope: "voltro:migrate" })));
|
|
3037
3089
|
let u = l.operations.filter((e) => e.blocked);
|
|
3038
3090
|
if (u.length > 0) return yield* w.die(/* @__PURE__ */ Error(`applyPlan: refusing to execute — re-planning under the migration lock found ${u.length} blocked operation(s). Run \`voltro db plan\` to see the fixes.`));
|
|
3039
|
-
let d =
|
|
3091
|
+
let d = ze(o) === "plan-transactional", f = d ? l.operations.filter((e) => e.classification !== "online-required") : [], p = d ? l.operations.filter((e) => e.classification === "online-required") : l.operations, m = `plan_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`, h = p.map((e, t) => ({
|
|
3040
3092
|
index: t,
|
|
3041
3093
|
planned: e
|
|
3042
3094
|
})), _ = "fresh";
|
|
3043
|
-
yield*
|
|
3044
|
-
let v = yield*
|
|
3095
|
+
yield* ea(e, l, o), yield* Gi(e, o);
|
|
3096
|
+
let v = yield* Ki(e);
|
|
3045
3097
|
if (v.length > 0) {
|
|
3046
|
-
let t = yield*
|
|
3047
|
-
t.kind === "resume" ? (m = t.runId, h = t.ops, _ = "resume") : (yield* w.logWarning(`migration resume: discarding the ledger of run ${t.runId} — ${t.why}`).pipe(w.annotateLogs({ scope: "voltro:migrate" })), yield*
|
|
3098
|
+
let t = yield* $i(e, o, l, v);
|
|
3099
|
+
t.kind === "resume" ? (m = t.runId, h = t.ops, _ = "resume") : (yield* w.logWarning(`migration resume: discarding the ledger of run ${t.runId} — ${t.why}`).pipe(w.annotateLogs({ scope: "voltro:migrate" })), yield* Xi(e, t.runId));
|
|
3048
3100
|
}
|
|
3049
|
-
_ === "fresh" && h.length > 0 && (yield*
|
|
3050
|
-
let e = yield*
|
|
3051
|
-
for (let t of f) a.push(yield*
|
|
3101
|
+
_ === "fresh" && h.length > 0 && (yield* qi(e, m, l.toFingerprint, h)), f.length > 0 && (yield* e.withTransaction(w.gen(function* () {
|
|
3102
|
+
let e = yield* E.SqlClient;
|
|
3103
|
+
for (let t of f) a.push(yield* Qi(e, t, n));
|
|
3052
3104
|
})));
|
|
3053
3105
|
for (let { index: t, planned: r } of h) {
|
|
3054
|
-
yield*
|
|
3055
|
-
let i = a.length, o = yield*
|
|
3056
|
-
a.push(o), yield*
|
|
3106
|
+
yield* Ji(e, m, t, "started");
|
|
3107
|
+
let i = a.length, o = yield* Qi(e, r, n, _).pipe(w.mapError((e) => Object.assign(e, { message: `${String(e?.message ?? e)}\n\n progress: ${i} of ${h.length + f.length} operation(s) applied before this one${f.length > 0 ? ` (${f.length} of them in a transaction)` : ""}.\n` + (d ? " This dialect applies a plan atomically, so the run is rolled back.\n" : ` This dialect does NOT apply a plan atomically: those ${i} are COMMITTED and there is no rollback.\n The next \`voltro db apply\` resumes from operation ${t} — the ledger records the sequence.\n`) })));
|
|
3108
|
+
a.push(o), yield* Ji(e, m, t, "applied", o.durationMs);
|
|
3057
3109
|
}
|
|
3058
3110
|
let y = yield* n.replan(e);
|
|
3059
3111
|
if (y.operations.length > 0) {
|
|
3060
3112
|
let e = y.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");
|
|
3061
3113
|
return yield* w.die(/* @__PURE__ */ Error(`applyPlan: the migration did not converge. ${l.operations.length} operation(s) were executed without error, but re-planning against the live schema still finds ${y.operations.length}:\n${e}${y.operations.length > 10 ? `\n … and ${y.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.`));
|
|
3062
3114
|
}
|
|
3063
|
-
let b = a.filter((e) => e.status === "applied").length, x = Date.now() - i, S = m, C = (/* @__PURE__ */ new Date()).toISOString(),
|
|
3115
|
+
let b = a.filter((e) => e.status === "applied").length, x = Date.now() - i, S = m, C = (/* @__PURE__ */ new Date()).toISOString(), T = yield* U(e, C), ee = [...f, ...h.map((e) => e.planned)];
|
|
3064
3116
|
yield* e`
|
|
3065
3117
|
INSERT INTO ${e("_voltro_migration_plans")}
|
|
3066
3118
|
(${e("id")}, ${e("fingerprint")}, ${e("liveFingerprint")}, ${e("operations")},
|
|
3067
3119
|
${e("appliedBy")}, ${e("environment")}, ${e("source")},
|
|
3068
3120
|
${e("durationMs")}, ${e("appliedAt")}, ${e("notes")})
|
|
3069
3121
|
VALUES
|
|
3070
|
-
(${S}, ${l.toFingerprint}, ${y.fromFingerprint}, ${JSON.stringify(
|
|
3122
|
+
(${S}, ${l.toFingerprint}, ${y.fromFingerprint}, ${JSON.stringify(ee)},
|
|
3071
3123
|
${n.appliedBy}, ${n.environment}, ${n.source},
|
|
3072
|
-
${x}, ${
|
|
3073
|
-
`, yield*
|
|
3074
|
-
let
|
|
3075
|
-
return yield* w.promise(() => g({ changedTables:
|
|
3124
|
+
${x}, ${T}, ${n.notes ?? null})
|
|
3125
|
+
`, yield* Xi(e, m);
|
|
3126
|
+
let te = [...new Set(ee.flatMap((e) => e.op.kind === "rename-table" ? [e.op.to] : [e.op.table]))];
|
|
3127
|
+
return yield* w.promise(() => g({ changedTables: te }).catch(() => {})), {
|
|
3076
3128
|
id: S,
|
|
3077
3129
|
appliedAt: C,
|
|
3078
3130
|
fingerprint: l.toFingerprint,
|
|
3079
|
-
operations:
|
|
3131
|
+
operations: ee,
|
|
3080
3132
|
appliedBy: n.appliedBy,
|
|
3081
3133
|
environment: n.environment,
|
|
3082
3134
|
durationMs: x,
|
|
@@ -3084,13 +3136,13 @@ BEGIN
|
|
|
3084
3136
|
source: n.source,
|
|
3085
3137
|
...n.notes ? { notes: n.notes } : {}
|
|
3086
3138
|
};
|
|
3087
|
-
}),
|
|
3139
|
+
}), ia = (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"), aa = (e) => e`
|
|
3088
3140
|
SELECT fingerprint
|
|
3089
3141
|
FROM _voltro_migration_plans
|
|
3090
3142
|
ORDER BY ${e("appliedAt")} DESC
|
|
3091
3143
|
LIMIT 1
|
|
3092
|
-
`.pipe(w.map((e) => e.length > 0 ? e[0].fingerprint : void 0), w.catchAll(() => w.succeed(void 0))),
|
|
3093
|
-
if ((yield*
|
|
3144
|
+
`.pipe(w.map((e) => e.length > 0 ? e[0].fingerprint : void 0), w.catchAll(() => w.succeed(void 0))), oa = (e, t, n) => w.gen(function* () {
|
|
3145
|
+
if ((yield* aa(e)) === t.toFingerprint) return "already-current";
|
|
3094
3146
|
let r = `plan_${Date.now().toString(36)}`, i = yield* U(e, (/* @__PURE__ */ new Date()).toISOString());
|
|
3095
3147
|
return yield* e`
|
|
3096
3148
|
INSERT INTO ${e("_voltro_migration_plans")}
|
|
@@ -3102,8 +3154,8 @@ BEGIN
|
|
|
3102
3154
|
${n.appliedBy}, ${n.environment}, ${n.source},
|
|
3103
3155
|
${0}, ${i}, ${"no DDL — the declared schema already matched the database"})
|
|
3104
3156
|
`, "recorded";
|
|
3105
|
-
}).pipe(w.catchAll(() => w.succeed("already-current"))),
|
|
3106
|
-
let n =
|
|
3157
|
+
}).pipe(w.catchAll(() => w.succeed("already-current"))), sa = (e, t) => w.gen(function* () {
|
|
3158
|
+
let n = L(R(t, Le(e))), r = yield* aa(e);
|
|
3107
3159
|
return r === n ? {
|
|
3108
3160
|
kind: "up-to-date",
|
|
3109
3161
|
fingerprint: n
|
|
@@ -3112,23 +3164,23 @@ BEGIN
|
|
|
3112
3164
|
expected: n,
|
|
3113
3165
|
...r === void 0 ? {} : { actual: r }
|
|
3114
3166
|
};
|
|
3115
|
-
}),
|
|
3167
|
+
}), ca = [
|
|
3116
3168
|
"pgeagertest_",
|
|
3117
3169
|
"mig_e2e_",
|
|
3118
3170
|
"mig_test_",
|
|
3119
3171
|
"mysqleagertest_",
|
|
3120
3172
|
"mssqleagertest_",
|
|
3121
3173
|
"sqliteeagertest_"
|
|
3122
|
-
],
|
|
3174
|
+
], la = (e) => ca.some((t) => e.startsWith(t)), ua = (e, t) => w.gen(function* () {
|
|
3123
3175
|
if (process.env.VOLTRO_TEST_FIXTURE_GC === "off") return [];
|
|
3124
|
-
let n = t.filter((e) =>
|
|
3176
|
+
let n = t.filter((e) => la(e.name)).map((e) => e.name);
|
|
3125
3177
|
if (n.length === 0) return [];
|
|
3126
3178
|
for (let t of n) yield* e.unsafe(`DROP TABLE IF EXISTS "${t}" CASCADE`).pipe(w.catchAll(() => w.void));
|
|
3127
3179
|
return n;
|
|
3128
|
-
}),
|
|
3180
|
+
}), da = () => {
|
|
3129
3181
|
let e = (process.env.VOLTRO_DB_IGNORE_TABLES ?? "").split(",").map((e) => e.trim()).filter((e) => e.length > 0);
|
|
3130
3182
|
return e.length > 0 ? { ignoreTables: e } : {};
|
|
3131
|
-
},
|
|
3183
|
+
}, fa = (e) => {
|
|
3132
3184
|
if (e === void 0) return;
|
|
3133
3185
|
let t = e.trim();
|
|
3134
3186
|
if (t === "") return;
|
|
@@ -3138,34 +3190,34 @@ BEGIN
|
|
|
3138
3190
|
kind: "tables",
|
|
3139
3191
|
tables: new Set(n)
|
|
3140
3192
|
} : void 0;
|
|
3141
|
-
},
|
|
3193
|
+
}, pa = (e) => typeof e.table == "string" ? e.table : void 0, ma = (e, t = { kind: "all" }) => ({
|
|
3142
3194
|
...e,
|
|
3143
3195
|
operations: e.operations.map((e) => {
|
|
3144
3196
|
if (!e.blocked || e.classification !== "lossy") return e;
|
|
3145
3197
|
if (t?.kind === "tables") {
|
|
3146
|
-
let n =
|
|
3198
|
+
let n = pa(e.op);
|
|
3147
3199
|
if (n === void 0 || !t.tables.has(n)) return e;
|
|
3148
3200
|
}
|
|
3149
3201
|
let { blocked: n, ...r } = e;
|
|
3150
3202
|
return r;
|
|
3151
3203
|
})
|
|
3152
|
-
}),
|
|
3153
|
-
let t =
|
|
3204
|
+
}), ha = (e, t, n) => t === "postgres" ? dn(e, n).pipe(w.flatMap((e) => {
|
|
3205
|
+
let t = fn(e);
|
|
3154
3206
|
return t === void 0 ? w.void : w.logWarning(`auto-migrate: ${t}`).pipe(w.annotateLogs({ scope: "voltro:migrate" }));
|
|
3155
|
-
}), w.catchAll(() => w.void)) : w.void,
|
|
3156
|
-
let r =
|
|
3207
|
+
}), w.catchAll(() => w.void)) : w.void, ga = (e, t, n) => w.gen(function* () {
|
|
3208
|
+
let r = Le(e), a = t;
|
|
3157
3209
|
if (process.env.VOLTRO_MIGRATE_FORCE !== "1") {
|
|
3158
|
-
let t =
|
|
3159
|
-
if ((yield*
|
|
3210
|
+
let t = L(R(a, r));
|
|
3211
|
+
if ((yield* aa(e)) === t) return yield* ha(e, r, a), {
|
|
3160
3212
|
kind: "up-to-date",
|
|
3161
3213
|
fingerprint: t
|
|
3162
3214
|
};
|
|
3163
3215
|
}
|
|
3164
|
-
let o = yield*
|
|
3216
|
+
let o = yield* fr(e), s = yield* ua(e, o.tables);
|
|
3165
3217
|
s.length > 0 && (yield* w.logInfo(`auto-migrate: reaped ${s.length} test-fixture leftover(s)`).pipe(w.annotateLogs({
|
|
3166
3218
|
scope: "voltro:migrate",
|
|
3167
3219
|
count: s.length
|
|
3168
|
-
})), o = yield*
|
|
3220
|
+
})), o = yield* fr(e));
|
|
3169
3221
|
{
|
|
3170
3222
|
let e = n.softDropRetentionDays ?? 7, t = p(o, { retentionDays: e });
|
|
3171
3223
|
t.length > 0 && (yield* w.logWarning(`auto-migrate: ${i(t, e)}`).pipe(w.annotateLogs({
|
|
@@ -3173,20 +3225,20 @@ BEGIN
|
|
|
3173
3225
|
snapshots: t.map((e) => e.name)
|
|
3174
3226
|
})));
|
|
3175
3227
|
}
|
|
3176
|
-
let c = new Set(t.map((e) => e.tableName)), l = (e) => e.filter((e) => !_(e.name) || c.has(e.name)), u =
|
|
3228
|
+
let c = new Set(t.map((e) => e.tableName)), l = (e) => e.filter((e) => !_(e.name) || c.has(e.name)), u = Wn({
|
|
3177
3229
|
declared: a,
|
|
3178
3230
|
live: { tables: l(o.tables) },
|
|
3179
3231
|
dialect: r,
|
|
3180
|
-
...
|
|
3232
|
+
...da()
|
|
3181
3233
|
});
|
|
3182
3234
|
if (u.summary.blocked > 0) {
|
|
3183
|
-
let e = u.operations.filter((e) => e.blocked).every((e) => e.classification === "lossy"), t =
|
|
3184
|
-
if (t === void 0 || !e || (u =
|
|
3235
|
+
let e = u.operations.filter((e) => e.blocked).every((e) => e.classification === "lossy"), t = fa(process.env.VOLTRO_DESTRUCTIVE_OK);
|
|
3236
|
+
if (t === void 0 || !e || (u = ma(u, t), u.operations.some((e) => e.blocked))) return {
|
|
3185
3237
|
kind: "refused-blocked",
|
|
3186
3238
|
plan: u
|
|
3187
3239
|
};
|
|
3188
3240
|
}
|
|
3189
|
-
return u.operations.length === 0 ? (yield*
|
|
3241
|
+
return u.operations.length === 0 ? (yield* oa(e, u, {
|
|
3190
3242
|
appliedBy: n.appliedBy,
|
|
3191
3243
|
environment: n.environment === "prod" ? "dev" : n.environment,
|
|
3192
3244
|
source: "auto-diff"
|
|
@@ -3195,37 +3247,37 @@ BEGIN
|
|
|
3195
3247
|
fingerprint: u.toFingerprint
|
|
3196
3248
|
}) : {
|
|
3197
3249
|
kind: "applied",
|
|
3198
|
-
applied: yield*
|
|
3250
|
+
applied: yield* na(e, u, {
|
|
3199
3251
|
declared: t,
|
|
3200
3252
|
appliedBy: n.appliedBy,
|
|
3201
3253
|
environment: n.environment === "prod" ? "dev" : n.environment,
|
|
3202
3254
|
source: "auto-diff",
|
|
3203
3255
|
replan: (e) => w.gen(function* () {
|
|
3204
|
-
let t = yield*
|
|
3205
|
-
return
|
|
3256
|
+
let t = yield* fr(e);
|
|
3257
|
+
return Wn({
|
|
3206
3258
|
declared: a,
|
|
3207
3259
|
live: { tables: l(t.tables) },
|
|
3208
3260
|
dialect: r,
|
|
3209
|
-
...
|
|
3261
|
+
...da()
|
|
3210
3262
|
});
|
|
3211
3263
|
})
|
|
3212
3264
|
}),
|
|
3213
3265
|
plan: u
|
|
3214
3266
|
};
|
|
3215
|
-
}),
|
|
3267
|
+
}), _a = (e, t, n) => process.env.VOLTRO_AUTO_MIGRATE === "0" ? w.succeed({
|
|
3216
3268
|
kind: "skipped",
|
|
3217
3269
|
reason: "VOLTRO_AUTO_MIGRATE=0"
|
|
3218
|
-
}) : n.environment === "prod" ?
|
|
3270
|
+
}) : n.environment === "prod" ? sa(e, t) : ga(e, t, n), va = (e, t) => {
|
|
3219
3271
|
switch (e.kind) {
|
|
3220
3272
|
case "skipped": return `auto-migrate: skipped (${e.reason})`;
|
|
3221
|
-
case "up-to-date": return `auto-migrate: schema up to date (${t}, fingerprint=${
|
|
3273
|
+
case "up-to-date": return `auto-migrate: schema up to date (${t}, fingerprint=${an(e.fingerprint)})`;
|
|
3222
3274
|
case "applied": {
|
|
3223
3275
|
let t = e.plan.summary;
|
|
3224
|
-
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=${
|
|
3276
|
+
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=${an(e.applied.fingerprint)}`;
|
|
3225
3277
|
}
|
|
3226
|
-
case "prod-mismatch": return `auto-migrate: SCHEMA FINGERPRINT MISMATCH — declared=${
|
|
3278
|
+
case "prod-mismatch": return `auto-migrate: SCHEMA FINGERPRINT MISMATCH — declared=${an(e.expected)}` + (e.actual ? ` live=${an(e.actual)}` : " live=<no _voltro_migration_plans row>") + ". Run `voltro db apply --plan plan.json` from the deploy pipeline before serving.";
|
|
3227
3279
|
case "refused-blocked": {
|
|
3228
|
-
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` +
|
|
3280
|
+
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` + ia(e.plan), c = [""];
|
|
3229
3281
|
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) {
|
|
3230
3282
|
let t = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map();
|
|
3231
3283
|
for (let r of e.plan.operations) {
|
|
@@ -3242,7 +3294,7 @@ BEGIN
|
|
|
3242
3294
|
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");
|
|
3243
3295
|
}
|
|
3244
3296
|
}
|
|
3245
|
-
},
|
|
3297
|
+
}, ya = re({ scope: "voltro:migrate" }), ba = /* @__PURE__ */ new Set([
|
|
3246
3298
|
"node_modules",
|
|
3247
3299
|
"dist",
|
|
3248
3300
|
"build",
|
|
@@ -3251,12 +3303,12 @@ BEGIN
|
|
|
3251
3303
|
".next",
|
|
3252
3304
|
".git",
|
|
3253
3305
|
".framework"
|
|
3254
|
-
]),
|
|
3306
|
+
]), xa = async (e) => {
|
|
3255
3307
|
let t = [], n = async (e) => {
|
|
3256
|
-
let r = await
|
|
3308
|
+
let r = await ie.readdir(e, { withFileTypes: !0 }).catch(() => []);
|
|
3257
3309
|
for (let i of r) {
|
|
3258
|
-
if (
|
|
3259
|
-
let r =
|
|
3310
|
+
if (ba.has(i.name)) continue;
|
|
3311
|
+
let r = ae(e, i.name);
|
|
3260
3312
|
i.isDirectory() ? await n(r) : i.isFile() && S.test(i.name) && t.push(r);
|
|
3261
3313
|
}
|
|
3262
3314
|
};
|
|
@@ -3264,12 +3316,12 @@ BEGIN
|
|
|
3264
3316
|
let n = e.split("/").pop() ?? e, r = t.split("/").pop() ?? t;
|
|
3265
3317
|
return n.localeCompare(r);
|
|
3266
3318
|
});
|
|
3267
|
-
},
|
|
3319
|
+
}, Sa = async (e) => {
|
|
3268
3320
|
let t = [];
|
|
3269
3321
|
for (let n of e) {
|
|
3270
|
-
let e = (await import(
|
|
3322
|
+
let e = (await import(oe(n).href)).default;
|
|
3271
3323
|
if (!u(e)) {
|
|
3272
|
-
|
|
3324
|
+
ya.warn("migration file has no default-exported `migration(...)` — skipped", { file: n });
|
|
3273
3325
|
continue;
|
|
3274
3326
|
}
|
|
3275
3327
|
t.push({
|
|
@@ -3278,11 +3330,11 @@ BEGIN
|
|
|
3278
3330
|
});
|
|
3279
3331
|
}
|
|
3280
3332
|
return t;
|
|
3281
|
-
},
|
|
3333
|
+
}, Ca = (e) => e`
|
|
3282
3334
|
SELECT ${e("id")}
|
|
3283
3335
|
FROM ${e("_voltro_migration_plans")}
|
|
3284
3336
|
WHERE ${e("source")} = 'file'
|
|
3285
|
-
`.pipe(w.map((e) => e.map((e) => e.id)), w.catchAll(() => w.succeed([]))),
|
|
3337
|
+
`.pipe(w.map((e) => e.map((e) => e.id)), w.catchAll(() => w.succeed([]))), wa = class extends Error {
|
|
3286
3338
|
migrationId;
|
|
3287
3339
|
file;
|
|
3288
3340
|
cause;
|
|
@@ -3290,7 +3342,7 @@ BEGIN
|
|
|
3290
3342
|
constructor(e, t, n) {
|
|
3291
3343
|
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";
|
|
3292
3344
|
}
|
|
3293
|
-
},
|
|
3345
|
+
}, Ta = (e, t, n, r) => w.gen(function* () {
|
|
3294
3346
|
let i = Date.now(), a = (/* @__PURE__ */ new Date()).toISOString(), o = {
|
|
3295
3347
|
sql: e,
|
|
3296
3348
|
log: {
|
|
@@ -3324,10 +3376,10 @@ BEGIN
|
|
|
3324
3376
|
}])},
|
|
3325
3377
|
${r}, ${n}, ${"file"},
|
|
3326
3378
|
${c}, ${l}, ${t.migration.description})
|
|
3327
|
-
`.pipe(w.mapError((e) => new
|
|
3328
|
-
}),
|
|
3379
|
+
`.pipe(w.mapError((e) => new wa(t.migration.id, t.file, e))), { durationMs: c };
|
|
3380
|
+
}), Ea = (e, t) => w.gen(function* () {
|
|
3329
3381
|
let n = yield* w.tryPromise({
|
|
3330
|
-
try: () =>
|
|
3382
|
+
try: () => xa(ae(t, "migrations")),
|
|
3331
3383
|
catch: (e) => e
|
|
3332
3384
|
});
|
|
3333
3385
|
if (n.length === 0) return {
|
|
@@ -3335,25 +3387,25 @@ BEGIN
|
|
|
3335
3387
|
skipped: []
|
|
3336
3388
|
};
|
|
3337
3389
|
let r = yield* w.tryPromise({
|
|
3338
|
-
try: () =>
|
|
3390
|
+
try: () => Sa(n),
|
|
3339
3391
|
catch: (e) => e
|
|
3340
3392
|
});
|
|
3341
3393
|
if (r.length === 0) return {
|
|
3342
3394
|
pending: [],
|
|
3343
3395
|
skipped: []
|
|
3344
3396
|
};
|
|
3345
|
-
let i = new Set(yield*
|
|
3397
|
+
let i = new Set(yield* Ca(e));
|
|
3346
3398
|
return {
|
|
3347
3399
|
pending: r.filter((e) => !i.has(e.migration.id)),
|
|
3348
3400
|
skipped: r.filter((e) => i.has(e.migration.id)).map((e) => e.migration.id)
|
|
3349
3401
|
};
|
|
3350
|
-
}),
|
|
3351
|
-
let { pending: n, skipped: r } = yield*
|
|
3402
|
+
}), Da = (e, t) => Ea(e, t).pipe(w.map((e) => e.pending.map((e) => e.migration.id))), Oa = (e, t) => w.gen(function* () {
|
|
3403
|
+
let { pending: n, skipped: r } = yield* Ea(e, t.projectRoot);
|
|
3352
3404
|
return n.length === 0 ? {
|
|
3353
3405
|
applied: [],
|
|
3354
3406
|
skipped: r
|
|
3355
3407
|
} : {
|
|
3356
|
-
applied: yield* w.acquireUseRelease(
|
|
3408
|
+
applied: yield* w.acquireUseRelease(Fe(e, { schema: t.lockSchema }), () => w.gen(function* () {
|
|
3357
3409
|
let r = [];
|
|
3358
3410
|
for (let i of n) {
|
|
3359
3411
|
yield* w.logInfo("file-based migration applying").pipe(w.annotateLogs({
|
|
@@ -3361,7 +3413,7 @@ BEGIN
|
|
|
3361
3413
|
id: i.migration.id,
|
|
3362
3414
|
file: i.file
|
|
3363
3415
|
}));
|
|
3364
|
-
let { durationMs: n } = yield*
|
|
3416
|
+
let { durationMs: n } = yield* Ta(e, i, t.env, t.appliedBy);
|
|
3365
3417
|
r.push({
|
|
3366
3418
|
id: i.migration.id,
|
|
3367
3419
|
durationMs: n
|
|
@@ -3375,21 +3427,21 @@ BEGIN
|
|
|
3375
3427
|
}), (e) => e.release.pipe(w.orDie)),
|
|
3376
3428
|
skipped: r
|
|
3377
3429
|
};
|
|
3378
|
-
}),
|
|
3430
|
+
}), ka = (e, t) => e`
|
|
3379
3431
|
SELECT ${e("id")}
|
|
3380
3432
|
FROM ${e("_voltro_migration_plans")}
|
|
3381
3433
|
WHERE ${e("id")} = ${t} AND ${e("source")} = 'file'
|
|
3382
3434
|
LIMIT 1
|
|
3383
|
-
`,
|
|
3384
|
-
if (!(yield*
|
|
3435
|
+
`, Aa = (e, t) => w.gen(function* () {
|
|
3436
|
+
if (!(yield* ka(e, t.id))[0]) return yield* w.fail(/* @__PURE__ */ Error(`rollback: ${t.id} not found in _voltro_migration_plans (file source)`));
|
|
3385
3437
|
let n = yield* w.tryPromise({
|
|
3386
|
-
try: () =>
|
|
3438
|
+
try: () => xa(ae(t.projectRoot, "migrations")),
|
|
3387
3439
|
catch: (e) => e
|
|
3388
3440
|
}), r = (yield* w.tryPromise({
|
|
3389
|
-
try: () =>
|
|
3441
|
+
try: () => Sa(n),
|
|
3390
3442
|
catch: (e) => e
|
|
3391
3443
|
})).find((e) => e.migration.id === t.id);
|
|
3392
|
-
return r ? yield* w.acquireUseRelease(
|
|
3444
|
+
return r ? yield* w.acquireUseRelease(Fe(e, { schema: t.lockSchema }), () => w.gen(function* () {
|
|
3393
3445
|
let n = Date.now(), i = {
|
|
3394
3446
|
sql: e,
|
|
3395
3447
|
log: {
|
|
@@ -3414,8 +3466,8 @@ BEGIN
|
|
|
3414
3466
|
durationMs: o
|
|
3415
3467
|
};
|
|
3416
3468
|
}), (e) => e.release.pipe(w.orDie)) : yield* w.fail(/* @__PURE__ */ Error(`rollback: file for migration ${t.id} not found on disk under ${t.projectRoot}/migrations/`));
|
|
3417
|
-
}),
|
|
3418
|
-
let t = yield*
|
|
3469
|
+
}), ja = (e) => w.gen(function* () {
|
|
3470
|
+
let t = yield* E.SqlClient, n = yield* t`
|
|
3419
3471
|
SELECT id, fingerprint, appliedAt FROM _voltro_migration_plans
|
|
3420
3472
|
WHERE source = 'auto-diff'
|
|
3421
3473
|
AND squashedAt IS NULL
|
|
@@ -3459,7 +3511,7 @@ BEGIN
|
|
|
3459
3511
|
snapshotFingerprint: e.fingerprint,
|
|
3460
3512
|
snapshotId: i
|
|
3461
3513
|
};
|
|
3462
|
-
}),
|
|
3514
|
+
}), Ma = { safe: !0 }, Na = (e) => {
|
|
3463
3515
|
switch (e.kind) {
|
|
3464
3516
|
case "drop-column": return {
|
|
3465
3517
|
safe: !1,
|
|
@@ -3486,7 +3538,7 @@ BEGIN
|
|
|
3486
3538
|
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`,
|
|
3487
3539
|
remedy: "add a new column of the target type + backfill + dual-write, cut code over, then drop the old column in a LATER deploy"
|
|
3488
3540
|
};
|
|
3489
|
-
case "alter-column-nullability": return e.toNullable ?
|
|
3541
|
+
case "alter-column-nullability": return e.toNullable ? Ma : {
|
|
3490
3542
|
safe: !1,
|
|
3491
3543
|
reason: `old instances may INSERT "${e.table}" without (or with NULL in) "${e.column}", which the new NOT NULL rejects`,
|
|
3492
3544
|
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)`
|
|
@@ -3516,12 +3568,12 @@ BEGIN
|
|
|
3516
3568
|
case "drop-unique":
|
|
3517
3569
|
case "drop-unique-composite":
|
|
3518
3570
|
case "drop-foreign-key":
|
|
3519
|
-
case "drop-check": return
|
|
3571
|
+
case "drop-check": return Ma;
|
|
3520
3572
|
}
|
|
3521
|
-
},
|
|
3573
|
+
}, Pa = (e) => {
|
|
3522
3574
|
let t = [];
|
|
3523
3575
|
for (let n of e) {
|
|
3524
|
-
let e =
|
|
3576
|
+
let e = Na(n.op);
|
|
3525
3577
|
e.safe || t.push({
|
|
3526
3578
|
op: n,
|
|
3527
3579
|
reason: e.reason,
|
|
@@ -3529,7 +3581,7 @@ BEGIN
|
|
|
3529
3581
|
});
|
|
3530
3582
|
}
|
|
3531
3583
|
return t;
|
|
3532
|
-
},
|
|
3584
|
+
}, Fa = (e) => {
|
|
3533
3585
|
if (!e.enabled || e.unsafeCount === 0) return {
|
|
3534
3586
|
refuse: !1,
|
|
3535
3587
|
warnForced: !1,
|
|
@@ -3545,18 +3597,18 @@ BEGIN
|
|
|
3545
3597
|
warnForced: !1,
|
|
3546
3598
|
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.`
|
|
3547
3599
|
};
|
|
3548
|
-
},
|
|
3600
|
+
}, Ia = (e) => {
|
|
3549
3601
|
let t = e.table;
|
|
3550
3602
|
if (typeof t == "string") return t;
|
|
3551
3603
|
let n = e.from;
|
|
3552
3604
|
return typeof n == "string" ? n : void 0;
|
|
3553
|
-
},
|
|
3605
|
+
}, La = (e) => ({
|
|
3554
3606
|
kind: e.op.kind,
|
|
3555
|
-
table:
|
|
3607
|
+
table: Ia(e.op),
|
|
3556
3608
|
classification: e.classification,
|
|
3557
3609
|
reason: e.reason,
|
|
3558
3610
|
blockedFix: e.blocked?.fix
|
|
3559
|
-
}),
|
|
3611
|
+
}), Ra = (e) => e.operations.map(La), za = async (e) => {
|
|
3560
3612
|
let t = e.log ?? (() => {}), n = {
|
|
3561
3613
|
branchId: e.branchId,
|
|
3562
3614
|
mechanism: e.mechanism,
|
|
@@ -3575,10 +3627,10 @@ BEGIN
|
|
|
3575
3627
|
applied: !1,
|
|
3576
3628
|
converged: !1,
|
|
3577
3629
|
residual: r,
|
|
3578
|
-
infidelity:
|
|
3630
|
+
infidelity: Ra(o)
|
|
3579
3631
|
};
|
|
3580
3632
|
else {
|
|
3581
|
-
let i = await e.plan(), o =
|
|
3633
|
+
let i = await e.plan(), o = Ra(i), s = o.filter((e) => e.classification === "lossy"), c = ma(i), l = c.operations.filter((e) => e.blocked !== void 0).map(La);
|
|
3582
3634
|
if (l.length > 0) a = {
|
|
3583
3635
|
...n,
|
|
3584
3636
|
outcome: "blocked",
|
|
@@ -3603,7 +3655,7 @@ BEGIN
|
|
|
3603
3655
|
};
|
|
3604
3656
|
else {
|
|
3605
3657
|
await e.apply(c), t(`branch ${e.branchId}: applied ${o.length} operation(s)`);
|
|
3606
|
-
let i =
|
|
3658
|
+
let i = Ra(await e.replan());
|
|
3607
3659
|
a = {
|
|
3608
3660
|
...n,
|
|
3609
3661
|
outcome: i.length > 0 ? "diverged" : s.length > 0 ? "lossy" : "clean",
|
|
@@ -3641,7 +3693,7 @@ BEGIN
|
|
|
3641
3693
|
...a,
|
|
3642
3694
|
tornDown: o
|
|
3643
3695
|
};
|
|
3644
|
-
},
|
|
3696
|
+
}, Ba = (e) => {
|
|
3645
3697
|
switch (e.outcome) {
|
|
3646
3698
|
case "clean": return 0;
|
|
3647
3699
|
case "lossy": return 2;
|
|
@@ -3650,22 +3702,22 @@ BEGIN
|
|
|
3650
3702
|
case "infidelity": return 1;
|
|
3651
3703
|
case "failed": return 1;
|
|
3652
3704
|
}
|
|
3653
|
-
},
|
|
3705
|
+
}, Va = (e) => ` ${e.classification === "lossy" ? "✗" : "•"} ${e.kind}${e.table ? ` ${e.table}` : ""} [${e.classification}]${e.reason ? ` — ${e.reason}` : ""}${e.blockedFix ? `\n ! ${e.blockedFix}` : ""}`, Ha = (e) => {
|
|
3654
3706
|
let t = [];
|
|
3655
3707
|
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"}`);
|
|
3656
3708
|
else if (e.outcome === "infidelity") {
|
|
3657
3709
|
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:");
|
|
3658
|
-
for (let n of e.infidelity) t.push(
|
|
3710
|
+
for (let n of e.infidelity) t.push(Va(n));
|
|
3659
3711
|
} else {
|
|
3660
3712
|
t.push(` plan: ${e.operations.length} operation(s), ${e.lossy.length} lossy, ${e.blocked.length} refused`);
|
|
3661
|
-
for (let n of e.operations) t.push(
|
|
3662
|
-
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(
|
|
3713
|
+
for (let n of e.operations) t.push(Va(n));
|
|
3714
|
+
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(Va(n));
|
|
3663
3715
|
}
|
|
3664
3716
|
return t.push(e.tornDown ? ` branch ${e.branchId} torn down.` : ` branch ${e.branchId} KEPT — drop it when you are done.`), t.join("\n");
|
|
3665
|
-
},
|
|
3717
|
+
}, Ua = (e, ...t) => ({
|
|
3666
3718
|
_tag: "RawSqlFragment",
|
|
3667
3719
|
strings: [...e],
|
|
3668
3720
|
values: [...t]
|
|
3669
|
-
}),
|
|
3721
|
+
}), Wa = (e) => typeof e == "object" && !!e && e._tag === "RawSqlFragment";
|
|
3670
3722
|
//#endregion
|
|
3671
|
-
export {
|
|
3723
|
+
export { A as DEFAULT_CDC_CHANNEL, S as FILE_MIGRATION_PATTERN, wa as FileMigrationLedgerError, Ze as REACTIVE_TRIGGER_PREFIX, he as VOLTRO_MIGRATION_LOCK_KEY, Fe as acquireMigrationLock, U as appliedAtValue, Vt as applyNamespacedSchema, na as applyPlan, jt as applySchema, Fa as assessRollingDeployGate, Ba as branchRehearsalExitCode, Qn as chunkTables, Na as classifyRollingDeploySafety, R as declaredSnapshot, it as defaultArrayClause, rt as defaultClause, N as defaultJsonClause, va as describeOutcome, fa as destructiveScope, dn as detectReactiveTriggerDrift, gi as emitAddIndexMysql, Zr as emitCreateTableMysql, jr as emitDropColumnDdl, Mr as emitDropColumnDdlMysql, At as emitFrameworkBootstrapSql, Ot as emitNamespaceProvisionDdl, kt as emitNamespacedSchemaSql, Dt as emitSchemaSql, pr as engineFromVersion, L as fingerprintSchema, xe as fnv1a64, Ha as formatBranchRehearsal, fn as formatReactiveTriggerDrift, da as ignoreTablesFromEnv, fr as introspectSchema, yr as isAlreadySatisfied, u as isFileMigration, Wa as isRawSqlFragment, Nt as isReRunSafeDdl, Kn as mapPgType, d as migration, Se as migrationLockKeyForSchema, Ce as migrationLockNameForSchema, fi as mysqlIndexPrefixFor, $e as notifyFunctionName, P as numericIdSql, Gn as parseEnumCheck, Da as pendingFileMigrationIds, Wn as planMigrations, Ht as provisionTenantNamespace, Qe as reactiveTriggerName, vt as reactiveTriggerRepairSql, oa as recordUpToDate, za as rehearseMigrationOnBranch, La as rehearsedOperation, Yr as renderColumnMysql, Wr as renderColumnPg, _e as resolveMigrationLockSchema, hr as resolveMysqlEngine, Aa as rollbackFileBasedMigration, Pa as rollingDeployUnsafeOps, Oa as runFileBasedMigrations, Ut as runFrameworkBootstrap, Bt as runMigrate, _a as runPlannedMigrations, an as shortFingerprint, on as snapshotColumn, Ua as sql, M as sqlType, ja as squashMigrationPlans, ma as unblockLossy, Ie as withMigrationLock };
|