@voltro/database 0.69.1 → 0.71.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 +1369 -111
- package/dist/{frameworkLiveTables-CWbTSnjk.js → frameworkLiveTables-D53uncZH.js} +3 -3
- package/dist/index.d.ts +85 -18
- package/dist/index.js +812 -791
- package/dist/sql.d.ts +41 -7
- package/dist/sql.js +1144 -955
- package/package.json +2 -2
package/dist/sql.js
CHANGED
|
@@ -1,13 +1,48 @@
|
|
|
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-
|
|
2
|
-
import {
|
|
3
|
-
import { createHash as
|
|
4
|
-
import { createLogger as
|
|
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-D53uncZH.js";
|
|
2
|
+
import { Cause as w, Effect as T, Equal as ee, Exit as te, Schedule as ne, Scope as re } from "effect";
|
|
3
|
+
import { createHash as ie } from "node:crypto";
|
|
4
|
+
import { createLogger as ae } from "@voltro/logger";
|
|
5
5
|
import { SqlClient as E } from "@effect/sql";
|
|
6
|
-
import { promises as
|
|
7
|
-
import { join as
|
|
8
|
-
import { pathToFileURL as
|
|
9
|
-
//#region src/
|
|
10
|
-
var
|
|
6
|
+
import { promises as oe } from "node:fs";
|
|
7
|
+
import { join as se } from "node:path";
|
|
8
|
+
import { pathToFileURL as ce } from "node:url";
|
|
9
|
+
//#region src/indexStorage.ts
|
|
10
|
+
var le = (e, t = "float32") => {
|
|
11
|
+
let n = e?.hnsw, r = n?.m ?? 16, i = n?.efConstruction ?? 64;
|
|
12
|
+
for (let [e, t] of Object.entries({
|
|
13
|
+
m: r,
|
|
14
|
+
efConstruction: i
|
|
15
|
+
})) if (!Number.isSafeInteger(t) || t <= 0) throw Error(`HNSW ${e} must be a positive safe integer`);
|
|
16
|
+
let a = n?.opclass ?? h(n?.distance, t);
|
|
17
|
+
if (!/^[a-z_][a-z0-9_$]*(?:\.[a-z_][a-z0-9_$]*)?$/i.test(a)) throw Error("HNSW opclass must be an unquoted, optionally schema-qualified identifier");
|
|
18
|
+
return {
|
|
19
|
+
m: r,
|
|
20
|
+
efConstruction: i,
|
|
21
|
+
opclass: a.toLowerCase().replace(/^public\./, "")
|
|
22
|
+
};
|
|
23
|
+
}, ue = (e, t) => t === void 0 || t === "postgres" ? e ?? "btree" : e === "hnsw" || e === "gin" && (t === "mysql" || t === "mariadb") ? null : "btree", D = (e, t) => ({
|
|
24
|
+
...e !== void 0 && e !== "btree" ? { kind: e } : {},
|
|
25
|
+
...e === "hnsw" ? { kindOptions: { hnsw: le(t) } } : {}
|
|
26
|
+
}), de = (e, t, n = "float32") => {
|
|
27
|
+
if (e === void 0 || e === "btree") return {
|
|
28
|
+
using: "",
|
|
29
|
+
withSuffix: "",
|
|
30
|
+
skip: !1
|
|
31
|
+
};
|
|
32
|
+
if (!/^[a-z_][a-z0-9_]*$/i.test(e)) throw Error("Index kind must be an SQL access-method identifier");
|
|
33
|
+
if (e !== "hnsw") return {
|
|
34
|
+
using: ` USING ${e.toUpperCase()}`,
|
|
35
|
+
withSuffix: "",
|
|
36
|
+
skip: !1
|
|
37
|
+
};
|
|
38
|
+
let r = le(t, n);
|
|
39
|
+
return {
|
|
40
|
+
using: " USING hnsw",
|
|
41
|
+
withSuffix: ` WITH (m = ${r.m}, ef_construction = ${r.efConstruction})`,
|
|
42
|
+
opclass: r.opclass,
|
|
43
|
+
skip: !1
|
|
44
|
+
};
|
|
45
|
+
}, fe = (e, t, n, r = 400) => {
|
|
11
46
|
let i = n, a = i.cause ?? {}, o = (e) => {
|
|
12
47
|
let t = a[e];
|
|
13
48
|
return t == null || t === "" ? void 0 : String(t);
|
|
@@ -38,21 +73,21 @@ var se = (e, t, n, r = 400) => {
|
|
|
38
73
|
let t = o(e);
|
|
39
74
|
t !== void 0 && s.push(`db.${e}: ${t}`);
|
|
40
75
|
}
|
|
41
|
-
let c =
|
|
76
|
+
let c = pe(o("code"));
|
|
42
77
|
return c !== void 0 && s.push("", c), s.push(""), s.join("\n");
|
|
43
|
-
},
|
|
44
|
-
if (t !== "mysql" && t !== "mariadb" || !e.appliedIndexes.some(
|
|
78
|
+
}, pe = (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, me = (e) => e.unique === !0 && typeof e.where == "string" && e.where.length > 0, he = (e) => e.replace(/"/g, "`"), ge = (e) => typeof e == "string" ? e : e.name ?? String(e), _e = (e, t) => `_ua_${t}_${e}`.slice(0, 64), ve = (e, t) => {
|
|
79
|
+
if (t !== "mysql" && t !== "mariadb" || !e.appliedIndexes.some(me)) return e;
|
|
45
80
|
let n = { ...e.fields }, r = [], i = [];
|
|
46
81
|
for (let t of e.appliedIndexes) {
|
|
47
|
-
if (!
|
|
82
|
+
if (!me(t)) {
|
|
48
83
|
r.push(t);
|
|
49
84
|
continue;
|
|
50
85
|
}
|
|
51
|
-
let a =
|
|
86
|
+
let a = he(t.where), o = [];
|
|
52
87
|
for (let r of t.fields) {
|
|
53
|
-
let i =
|
|
88
|
+
let i = ge(r);
|
|
54
89
|
if (!(i in e.fields)) throw Error(`@voltro/migrate: uniqueActive '${t.name}' on '${e.tableName}' references unknown column '${i}'.`);
|
|
55
|
-
let s =
|
|
90
|
+
let s = _e(t.name, i);
|
|
56
91
|
o.push(s), n[s] = {
|
|
57
92
|
type: "text",
|
|
58
93
|
nullable: !0,
|
|
@@ -75,82 +110,82 @@ var se = (e, t, n, r = 400) => {
|
|
|
75
110
|
appliedIndexes: r,
|
|
76
111
|
appliedUniques: [...e.appliedUniques ?? [], ...i]
|
|
77
112
|
};
|
|
78
|
-
},
|
|
113
|
+
}, O = (e, t) => `${e}::${t}`, ye = (e, t) => {
|
|
79
114
|
let n = /* @__PURE__ */ new Set(), r = /* @__PURE__ */ new Set(), i = /* @__PURE__ */ new Set(), a = (e) => {
|
|
80
115
|
n.add(e);
|
|
81
116
|
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(
|
|
117
|
+
for (let t of o) n.has(t.target) ? i.add(O(e, t.column)) : r.has(t.target) || a(t.target);
|
|
83
118
|
n.delete(e), r.add(e);
|
|
84
119
|
};
|
|
85
120
|
for (let t of [...e].sort()) r.has(t) || a(t);
|
|
86
121
|
return i;
|
|
87
|
-
},
|
|
122
|
+
}, k = (e, t) => e.executeUnprepared(t, [], void 0), be = 6322741009312437n, xe = (e) => {
|
|
88
123
|
let t = e?.trim();
|
|
89
124
|
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 *
|
|
125
|
+
}, Se = (e) => e?.schema === void 0 ? xe(process.env.DB_SCHEMA) : xe(e.schema), Ce = 14695981039346656037n, we = 1099511628211n, Te = 18446744073709551615n, Ee = (e) => {
|
|
126
|
+
let t = Ce;
|
|
127
|
+
for (let n of new TextEncoder().encode(e)) t ^= BigInt(n), t = t * we & Te;
|
|
93
128
|
return t;
|
|
94
|
-
},
|
|
95
|
-
let t =
|
|
96
|
-
return t === void 0 ?
|
|
97
|
-
},
|
|
98
|
-
let t = `voltro_migration_${
|
|
129
|
+
}, De = (e) => {
|
|
130
|
+
let t = xe(e);
|
|
131
|
+
return t === void 0 ? be : Ee(`voltro_migration_lock:${t}`) & 9223372036854775807n;
|
|
132
|
+
}, Oe = (e) => {
|
|
133
|
+
let t = `voltro_migration_${be.toString(36)}`, n = xe(e);
|
|
99
134
|
if (n === void 0) return t;
|
|
100
135
|
let r = `${t}_${n}`;
|
|
101
|
-
return /^[A-Za-z0-9_]+$/.test(n) && r.length <= 64 ? r : `${t}_h${(
|
|
102
|
-
},
|
|
136
|
+
return /^[A-Za-z0-9_]+$/.test(n) && r.length <= 64 ? r : `${t}_h${(Ee(`voltro_migration_lock:${n}`) & Te).toString(16)}`;
|
|
137
|
+
}, ke = 250, Ae = () => {
|
|
103
138
|
let e = Number(process.env.VOLTRO_MIGRATION_LOCK_TIMEOUT_MS);
|
|
104
139
|
return Number.isFinite(e) && e > 0 ? e : 3e4;
|
|
105
|
-
},
|
|
106
|
-
let n =
|
|
140
|
+
}, je = (e, t) => T.gen(function* () {
|
|
141
|
+
let n = Ae(), r = Date.now();
|
|
107
142
|
for (;;) {
|
|
108
|
-
if ((yield*
|
|
109
|
-
Date.now() - r >= n && (yield*
|
|
143
|
+
if ((yield* k(e, `SELECT pg_try_advisory_lock(${t.toString()}::bigint) AS got`))[0]?.got) return;
|
|
144
|
+
Date.now() - r >= n && (yield* T.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* T.sleep(`${ke} millis`);
|
|
110
145
|
}
|
|
111
|
-
}),
|
|
112
|
-
(yield*
|
|
113
|
-
}),
|
|
114
|
-
let n = yield*
|
|
146
|
+
}), Me = (e, t) => T.asVoid(k(e, `SELECT pg_advisory_unlock(${t.toString()}::bigint)`)), Ne = 30, Pe = (e, t) => T.gen(function* () {
|
|
147
|
+
(yield* k(e, `SELECT GET_LOCK('${t}', ${String(Ne)}) AS got`))[0]?.got !== 1 && (yield* T.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${t}' within ${Ne}s (another migration is in progress, or a prior one left it held).`)));
|
|
148
|
+
}), Fe = (e, t) => T.asVoid(k(e, `SELECT RELEASE_LOCK('${t}')`)), Ie = 3e4, Le = (e, t) => T.gen(function* () {
|
|
149
|
+
let n = yield* k(e, `
|
|
115
150
|
DECLARE @res int;
|
|
116
151
|
EXEC @res = sp_getapplock @Resource = '${t}', @LockMode = 'Exclusive',
|
|
117
|
-
@LockOwner = 'Session', @LockTimeout = ${String(
|
|
152
|
+
@LockOwner = 'Session', @LockTimeout = ${String(Ie)};
|
|
118
153
|
SELECT @res AS res`);
|
|
119
|
-
(n[0]?.res ?? -999) < 0 && (yield*
|
|
120
|
-
}),
|
|
121
|
-
let n =
|
|
154
|
+
(n[0]?.res ?? -999) < 0 && (yield* T.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${t}' (sp_getapplock returned ${n[0]?.res ?? "no row"}; another migration is in progress).`)));
|
|
155
|
+
}), Re = (e, t) => T.asVoid(k(e, `EXEC sp_releaseapplock @Resource = '${t}', @LockOwner = 'Session'`)), ze = T.void, Be = (e, t) => T.gen(function* () {
|
|
156
|
+
let n = Se(t), r = Oe(n), i = De(n);
|
|
122
157
|
if (!e.onDialectOrElse({
|
|
123
158
|
mysql: () => !0,
|
|
124
159
|
mssql: () => !0,
|
|
125
160
|
sqlite: () => !1,
|
|
126
161
|
orElse: () => !0
|
|
127
|
-
})) return { release:
|
|
128
|
-
let a = yield*
|
|
162
|
+
})) return { release: ze };
|
|
163
|
+
let a = yield* re.make(), o = yield* T.provideService(e.reserve, re.Scope, a), s = re.close(a, te.void);
|
|
129
164
|
return yield* e.onDialectOrElse({
|
|
130
|
-
mysql: () =>
|
|
131
|
-
mssql: () =>
|
|
132
|
-
sqlite: () =>
|
|
133
|
-
orElse: () =>
|
|
134
|
-
}).pipe(
|
|
135
|
-
mysql: () =>
|
|
136
|
-
mssql: () =>
|
|
137
|
-
sqlite: () =>
|
|
138
|
-
orElse: () =>
|
|
139
|
-
}).pipe(
|
|
140
|
-
}),
|
|
165
|
+
mysql: () => Pe(o, r),
|
|
166
|
+
mssql: () => Le(o, r),
|
|
167
|
+
sqlite: () => ze,
|
|
168
|
+
orElse: () => je(o, i)
|
|
169
|
+
}).pipe(T.onExit((e) => te.isSuccess(e) ? T.void : s)), { release: e.onDialectOrElse({
|
|
170
|
+
mysql: () => Fe(o, r),
|
|
171
|
+
mssql: () => Re(o, r),
|
|
172
|
+
sqlite: () => ze,
|
|
173
|
+
orElse: () => Me(o, i)
|
|
174
|
+
}).pipe(T.ensuring(s)) };
|
|
175
|
+
}), Ve = (e, t, n) => T.acquireUseRelease(Be(e, n), () => t, (e) => e.release.pipe(T.orDie)), He = (e) => e.onDialectOrElse({
|
|
141
176
|
pg: () => "postgres",
|
|
142
177
|
mysql: () => "mysql",
|
|
143
178
|
mssql: () => "mssql",
|
|
144
179
|
sqlite: () => "sqlite",
|
|
145
180
|
orElse: () => "sqlite"
|
|
146
|
-
}),
|
|
181
|
+
}), Ue = {
|
|
147
182
|
postgres: "plan-transactional",
|
|
148
183
|
mssql: "plan-transactional",
|
|
149
184
|
mysql: "per-operation",
|
|
150
185
|
mariadb: "per-operation",
|
|
151
186
|
sqlite: "per-operation",
|
|
152
187
|
turso: "per-operation"
|
|
153
|
-
},
|
|
188
|
+
}, We = (e) => Ue[e], A = "_voltro_migration_ops", Ge = l(A, {
|
|
154
189
|
id: y({ prefix: "mop" }),
|
|
155
190
|
runId: a(),
|
|
156
191
|
planFingerprint: a(),
|
|
@@ -163,7 +198,7 @@ var se = (e, t, n, r = 400) => {
|
|
|
163
198
|
appliedAt: v().nullable(),
|
|
164
199
|
durationMs: t().nullable(),
|
|
165
200
|
createdAt: v().default("now")
|
|
166
|
-
}),
|
|
201
|
+
}), Ke = (e) => {
|
|
167
202
|
switch (e.kind) {
|
|
168
203
|
case "create-table": return /* @__PURE__ */ new Set([
|
|
169
204
|
`table:${e.table}`,
|
|
@@ -183,18 +218,19 @@ var se = (e, t, n, r = 400) => {
|
|
|
183
218
|
case "add-foreign-key":
|
|
184
219
|
case "drop-foreign-key":
|
|
185
220
|
case "add-check":
|
|
186
|
-
case "drop-check":
|
|
221
|
+
case "drop-check":
|
|
222
|
+
case "reconcile-json-check": return /* @__PURE__ */ new Set([`column:${e.table}.${e.column}`]);
|
|
187
223
|
case "add-index": return /* @__PURE__ */ new Set([`index:${e.table}.${e.index.name}`]);
|
|
188
224
|
case "drop-index": return /* @__PURE__ */ new Set([`index:${e.table}.${e.index}`]);
|
|
189
225
|
case "rename-index": return /* @__PURE__ */ new Set([`index:${e.table}.${e.from}`, `index:${e.table}.${e.to}`]);
|
|
190
226
|
case "add-unique-composite":
|
|
191
227
|
case "drop-unique-composite": return /* @__PURE__ */ new Set([`unique:${e.table}.${e.name}`]);
|
|
192
228
|
}
|
|
193
|
-
},
|
|
194
|
-
let n =
|
|
195
|
-
for (let t of
|
|
229
|
+
}, qe = (e) => [...Ke(e)].join(" "), Je = (e, t) => {
|
|
230
|
+
let n = Ke(t);
|
|
231
|
+
for (let t of Ke(e)) if (n.has(t)) return !0;
|
|
196
232
|
return !1;
|
|
197
|
-
},
|
|
233
|
+
}, Ye = (e, t) => e.operations.some((e) => Je(e.op, t)), Xe = "__voltro_rebuild", Ze = "__shadow", Qe = "__old", $e = /* @__PURE__ */ new Set([
|
|
198
234
|
"add-unique",
|
|
199
235
|
"drop-unique",
|
|
200
236
|
"add-unique-composite",
|
|
@@ -206,21 +242,59 @@ var se = (e, t, n, r = 400) => {
|
|
|
206
242
|
"alter-column-nullability",
|
|
207
243
|
"alter-column-type",
|
|
208
244
|
"alter-column-default"
|
|
209
|
-
]),
|
|
245
|
+
]), et = /* @__PURE__ */ new Set(["alter-column-default", "alter-column-nullability"]), tt = (e, t, n) => {
|
|
210
246
|
let r = n === "sqlite" || n === "turso";
|
|
211
|
-
return e.kind === "alter-column-type" && t === "online-required" || r &&
|
|
247
|
+
return e.kind === "alter-column-type" && t === "online-required" || r && $e.has(e.kind) ? "artefact-repair" : et.has(e.kind) ? "idempotent" : "probe-then-replay";
|
|
212
248
|
};
|
|
213
|
-
Object.keys(
|
|
249
|
+
Object.keys(Ue);
|
|
214
250
|
//#endregion
|
|
215
|
-
//#region src/
|
|
216
|
-
var
|
|
251
|
+
//#region src/mssqlJsonValueCheck.ts
|
|
252
|
+
var nt = (e) => {
|
|
253
|
+
let t = `(N'{"v":' + ${e} + N'}')`, n = `ISJSON(${t}) = 1`, r = `JSON_MODIFY(CASE WHEN ${n} THEN ${t} ELSE N'{}' END, '$.v', NULL)`;
|
|
254
|
+
return `(${e} IS NULL OR (${n} AND ${[
|
|
255
|
+
32,
|
|
256
|
+
9,
|
|
257
|
+
10,
|
|
258
|
+
13
|
|
259
|
+
].reduce((e, t) => `REPLACE(${e}, NCHAR(${t}), N'')`, r)} = N'{}'))`;
|
|
260
|
+
}, rt = (e) => {
|
|
261
|
+
let t = [], n = /\s+|N?'(?:''|[^'])*'|\[(?:\]\]|[^\]])*\]|[A-Za-z_][A-Za-z_0-9]*|[0-9]+|[()+,=]/giy, r = 0;
|
|
262
|
+
for (; r < e.length;) {
|
|
263
|
+
n.lastIndex = r;
|
|
264
|
+
let i = n.exec(e);
|
|
265
|
+
if (!i) return;
|
|
266
|
+
let a = i[0];
|
|
267
|
+
/^\s+$/.test(a) || t.push(/^(?:N?')|^\[/i.test(a) ? a.replace(/^n'/, "N'") : a.toLowerCase()), r = n.lastIndex;
|
|
268
|
+
}
|
|
269
|
+
return t;
|
|
270
|
+
}, it = (e, t) => {
|
|
271
|
+
let n = `[${e.replaceAll("]", "]]")}]`, r = `(N'{"v":'+${n})+N'}'`, i = `isjson(${r})=(1)`, a = `json_modify(case when ${i} then ${r} else N'{}' end,'$.v',NULL)`, o = [
|
|
272
|
+
32,
|
|
273
|
+
9,
|
|
274
|
+
10,
|
|
275
|
+
13
|
|
276
|
+
].reduce((e, t) => `replace(${e},nchar((${t})),N'')`, a), s = [
|
|
277
|
+
["value", nt(n)],
|
|
278
|
+
["value", `(${n} IS NULL OR ${i} AND ${o}=N'{}')`],
|
|
279
|
+
["container", `(${n} IS NULL OR ISJSON(${n}) = 1)`],
|
|
280
|
+
["container", `(${n} IS NULL OR isjson(${n})=(1))`]
|
|
281
|
+
], c = rt(t);
|
|
282
|
+
if (c) return s.find(([, e]) => {
|
|
283
|
+
let t = rt(e);
|
|
284
|
+
return t?.length === c.length && t.every((e, t) => e === c[t]);
|
|
285
|
+
})?.[0];
|
|
286
|
+
}, at = (e) => {
|
|
287
|
+
if (e.length === 0) return;
|
|
288
|
+
let t = e.filter((e) => e.enabled);
|
|
289
|
+
return t.some((e) => e.validation === "container") ? t.some((e) => e.validation === "container" && e.trusted) ? "container" : "unverified" : t.some((e) => e.validation === "value" && e.trusted) ? "value" : "unverified";
|
|
290
|
+
}, j = "framework_changes", ot = "framework_changes_", st = (e, t) => t === "framework_changes" ? `${ot}${e}` : `${ot}${t}_${e}`, ct = (e) => e === "framework_changes" ? "framework_notify_change" : `framework_notify_change_${e}`, lt = "voltro:notify:v2", ut = (e, t) => {
|
|
217
291
|
if (e.type === "text" && e.generatedAs === void 0) {
|
|
218
292
|
if (e.maxLength !== void 0) return e.maxLength;
|
|
219
293
|
if (t || e.hasDefault && e.defaultFactory === void 0 || e.oneOf !== void 0 && e.oneOf.length > 0) return 450;
|
|
220
294
|
}
|
|
221
|
-
},
|
|
222
|
-
|
|
223
|
-
},
|
|
295
|
+
}, dt = ae({ scope: "voltro:migrate" }), M = (e) => {
|
|
296
|
+
dt.warn(e.replace(/^\[voltro:migrate\]\s*/, ""));
|
|
297
|
+
}, N = (e, t) => {
|
|
224
298
|
let n = e.type;
|
|
225
299
|
if (e.spatial) {
|
|
226
300
|
if (t === "postgres") return `${e.spatial.kind}(${e.spatial.geomKind},${e.spatial.srid})`;
|
|
@@ -231,7 +305,7 @@ var A = "framework_changes", Ze = "framework_changes_", Qe = (e, t) => t === "fr
|
|
|
231
305
|
return e.rawDdl;
|
|
232
306
|
}
|
|
233
307
|
if (n === "array" && e.arrayElement) {
|
|
234
|
-
if (t === "postgres") return `${
|
|
308
|
+
if (t === "postgres") return `${N({
|
|
235
309
|
...e,
|
|
236
310
|
type: e.arrayElement,
|
|
237
311
|
arrayElement: void 0
|
|
@@ -302,7 +376,7 @@ var A = "framework_changes", Ze = "framework_changes_", Qe = (e, t) => t === "fr
|
|
|
302
376
|
if (t === "mssql") switch (n) {
|
|
303
377
|
case "id": return "NVARCHAR(64)";
|
|
304
378
|
case "text": {
|
|
305
|
-
let t =
|
|
379
|
+
let t = ut(e, !1);
|
|
306
380
|
return t === void 0 ? "NVARCHAR(MAX)" : `NVARCHAR(${t})`;
|
|
307
381
|
}
|
|
308
382
|
case "integer": return "INT";
|
|
@@ -334,22 +408,22 @@ var A = "framework_changes", Ze = "framework_changes_", Qe = (e, t) => t === "fr
|
|
|
334
408
|
case "array": return "TEXT[]";
|
|
335
409
|
case "interval": return "INTERVAL";
|
|
336
410
|
}
|
|
337
|
-
},
|
|
411
|
+
}, ft = (e, t) => {
|
|
338
412
|
if (!e.hasDefault || e.defaultFactory !== void 0) return null;
|
|
339
413
|
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 =
|
|
414
|
+
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) ? pt(n, e, t) : typeof n == "object" && n ? P(n, t) : null;
|
|
415
|
+
}, pt = (e, t, n) => {
|
|
416
|
+
if (n !== "postgres" || t.type !== "array" || t.arrayElement === void 0) return P(e, n);
|
|
417
|
+
let r = N({
|
|
344
418
|
...t,
|
|
345
419
|
type: t.arrayElement,
|
|
346
420
|
arrayElement: void 0
|
|
347
421
|
}, n);
|
|
348
422
|
return `DEFAULT '{${e.map((e) => typeof e == "number" || typeof e == "boolean" ? String(e) : `"${String(e).replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"`).join(",").replace(/'/g, "''")}}'::${r}[]`;
|
|
349
|
-
},
|
|
423
|
+
}, P = (e, t) => {
|
|
350
424
|
let n = JSON.stringify(e).replace(/'/g, "''");
|
|
351
425
|
return t === "postgres" ? `DEFAULT '${n}'::jsonb` : t === "mysql" || t === "mariadb" ? `DEFAULT (CONVERT('${n}' USING utf8mb4))` : `DEFAULT '${n}'`;
|
|
352
|
-
},
|
|
426
|
+
}, F = (e, t) => {
|
|
353
427
|
switch (t) {
|
|
354
428
|
case "postgres": return `"${e}" BIGSERIAL PRIMARY KEY`;
|
|
355
429
|
case "mysql":
|
|
@@ -358,7 +432,7 @@ var A = "framework_changes", Ze = "framework_changes_", Qe = (e, t) => t === "fr
|
|
|
358
432
|
case "sqlite": return `"${e}" INTEGER PRIMARY KEY AUTOINCREMENT`;
|
|
359
433
|
case "turso": return `"${e}" INTEGER PRIMARY KEY`;
|
|
360
434
|
}
|
|
361
|
-
},
|
|
435
|
+
}, I = (e, t) => {
|
|
362
436
|
if (e === "restrict" && t === "mssql") return "NO ACTION";
|
|
363
437
|
switch (e) {
|
|
364
438
|
case "cascade": return "CASCADE";
|
|
@@ -366,42 +440,42 @@ var A = "framework_changes", Ze = "framework_changes_", Qe = (e, t) => t === "fr
|
|
|
366
440
|
case "setNull": return "SET NULL";
|
|
367
441
|
case "noAction": return "NO ACTION";
|
|
368
442
|
}
|
|
369
|
-
},
|
|
443
|
+
}, mt = (e, t, n) => n === null ? o(e, t) : `${o(n, t)}.${o(e, t)}`, ht = 191, gt = (e, t) => {
|
|
370
444
|
if (!e || t !== "mysql" && t !== "mariadb") return !1;
|
|
371
|
-
let n =
|
|
445
|
+
let n = N(e, t).toUpperCase();
|
|
372
446
|
return n.endsWith("TEXT") || n.endsWith("BLOB");
|
|
373
|
-
},
|
|
447
|
+
}, _t = (e, t, n) => {
|
|
374
448
|
let r = o(e, n);
|
|
375
449
|
if (n !== "mysql" && n !== "mariadb") return r;
|
|
376
450
|
let i = t[e];
|
|
377
451
|
if (!i) return r;
|
|
378
|
-
let a =
|
|
379
|
-
return a.endsWith("TEXT") || a.endsWith("BLOB") ? `${r}(${
|
|
380
|
-
},
|
|
452
|
+
let a = N(i, n).toUpperCase();
|
|
453
|
+
return a.endsWith("TEXT") || a.endsWith("BLOB") ? `${r}(${ht})` : r;
|
|
454
|
+
}, vt = (e, t) => {
|
|
381
455
|
if (!e.generatedAs) return null;
|
|
382
456
|
let { expr: n, stored: r } = e.generatedAs;
|
|
383
|
-
if (t === "postgres") return r ||
|
|
457
|
+
if (t === "postgres") return r || M("[voltro:migrate] generated column requested as VIRTUAL but postgres only supports STORED — promoting"), `GENERATED ALWAYS AS (${n}) STORED`;
|
|
384
458
|
if (t === "mysql" || t === "mariadb") return `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
|
|
385
459
|
if (t === "mssql") return `AS (${n})${r ? " PERSISTED" : ""}`;
|
|
386
460
|
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
461
|
return `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
|
|
388
|
-
},
|
|
389
|
-
if (t.type === "id" && t.idScheme?.kind === "numeric") return
|
|
390
|
-
let s = n === "mssql" ?
|
|
462
|
+
}, yt = (e, t, n, r, i = !1, a = !1) => {
|
|
463
|
+
if (t.type === "id" && t.idScheme?.kind === "numeric") return F(e, n);
|
|
464
|
+
let s = n === "mssql" ? ut(t, r?.has(e) ?? !1) : void 0, c = s === void 0 ? N(t, n) : `NVARCHAR(${s})`, l = [o(e, n), c];
|
|
391
465
|
t.type === "id" && !a && l.push("PRIMARY KEY");
|
|
392
|
-
let u =
|
|
466
|
+
let u = vt(t, n);
|
|
393
467
|
if (u) l.push(u);
|
|
394
468
|
else {
|
|
395
|
-
t.nullable || l.push("NOT NULL"), t.unique && t.type !== "id" && !
|
|
396
|
-
let e =
|
|
469
|
+
t.nullable || l.push("NOT NULL"), t.unique && t.type !== "id" && !gt(t, n) && l.push("UNIQUE");
|
|
470
|
+
let e = ft(t, n);
|
|
397
471
|
e && l.push(e);
|
|
398
472
|
}
|
|
399
473
|
if (t.type === "reference" && t.references && !i && !b(n)) {
|
|
400
474
|
let e = t.references();
|
|
401
475
|
l.push(`REFERENCES ${o(e.tableName, n)} (${o(t.referenceColumn ?? "id", n)})`);
|
|
402
|
-
let r =
|
|
476
|
+
let r = I(t.onDelete ?? "restrict", n);
|
|
403
477
|
l.push(`ON DELETE ${r}`);
|
|
404
|
-
let i =
|
|
478
|
+
let i = I(t.refOnUpdate ?? "noAction", n);
|
|
405
479
|
i !== "NO ACTION" && l.push(`ON UPDATE ${i}`);
|
|
406
480
|
}
|
|
407
481
|
if (t.oneOf && t.oneOf.length > 0) {
|
|
@@ -414,30 +488,30 @@ var A = "framework_changes", Ze = "framework_changes_", Qe = (e, t) => t === "fr
|
|
|
414
488
|
l.push(`CHECK (${o(e, n)} IN (${r}))`);
|
|
415
489
|
}
|
|
416
490
|
if (t.type === "json" || t.type === "array") {
|
|
417
|
-
let
|
|
418
|
-
m(n) ? l.push(`CHECK (${
|
|
491
|
+
let r = o(e, n);
|
|
492
|
+
m(n) ? l.push(`CHECK (${r} IS NULL OR json_valid(${r}))`) : n === "mssql" && l.push(t.type === "json" ? `CHECK ${nt(r)}` : `CHECK (${r} IS NULL OR ISJSON(${r}) = 1)`);
|
|
419
493
|
}
|
|
420
494
|
return l.join(" ");
|
|
421
|
-
},
|
|
495
|
+
}, bt = (e, t, n = null, r) => {
|
|
422
496
|
let i = /* @__PURE__ */ new Set();
|
|
423
497
|
for (let t of e.appliedIndexes ?? []) for (let e of t.fields) typeof e == "string" && i.add(e);
|
|
424
498
|
for (let t of e.appliedUniques ?? []) for (let e of t.fields) typeof e == "string" && i.add(e);
|
|
425
499
|
for (let [t, n] of Object.entries(e.fields)) n.unique && i.add(t);
|
|
426
500
|
let a = e.appliedPrimaryKey ?? [];
|
|
427
501
|
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) =>
|
|
502
|
+
let s = a.length > 0, c = Object.entries(e.fields).map(([e, n]) => ` ${yt(e, n, t, i, r?.has(e) ?? !1, s)}`).join(",\n"), l = (e.appliedUniques ?? []).map((n) => {
|
|
503
|
+
let r = n.fields.map((n) => _t(n, e.fields, t)).join(", ");
|
|
430
504
|
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) =>
|
|
505
|
+
}), u = (e.appliedChecks ?? []).map((e) => ` CONSTRAINT ${o(e.name, t)} CHECK (${e.expr})`), d = s ? [` PRIMARY KEY (${a.map((n) => _t(n, e.fields, t)).join(", ")})`] : [], f = b(t) ? Object.entries(e.fields).flatMap(([i, a]) => {
|
|
432
506
|
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 ${
|
|
507
|
+
let s = a.references(), c = I(a.onDelete ?? "restrict", t), l = I(a.refOnUpdate ?? "noAction", t);
|
|
508
|
+
return [` CONSTRAINT ${o(`${e.tableName}_${i}_fkey`, t)} FOREIGN KEY (${o(i, t)}) REFERENCES ${mt(s.tableName, t, n)} (${o(a.referenceColumn ?? "id", t)}) ON DELETE ${c}${l === "NO ACTION" ? "" : ` ON UPDATE ${l}`}`];
|
|
435
509
|
}) : [], p = [
|
|
436
510
|
...d,
|
|
437
511
|
...l,
|
|
438
512
|
...u,
|
|
439
513
|
...f
|
|
440
|
-
], m = p.length > 0 ? `${c},\n${p.join(",\n")}` : c, h =
|
|
514
|
+
], m = p.length > 0 ? `${c},\n${p.join(",\n")}` : c, h = mt(e.tableName, t, n);
|
|
441
515
|
if (t === "mssql") {
|
|
442
516
|
let t = n === null ? e.tableName : `${n}.${e.tableName}`, r = `CREATE TABLE ${h} (\n${m}\n)`;
|
|
443
517
|
return `IF OBJECT_ID('${t.replace(/'/g, "''")}', 'U') IS NULL EXEC(N'${r.replace(/'/g, "''")}');`;
|
|
@@ -447,56 +521,29 @@ var A = "framework_changes", Ze = "framework_changes_", Qe = (e, t) => t === "fr
|
|
|
447
521
|
m,
|
|
448
522
|
");"
|
|
449
523
|
].join("\n");
|
|
450
|
-
},
|
|
524
|
+
}, xt = (e, t, n) => {
|
|
451
525
|
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
526
|
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
|
-
},
|
|
454
|
-
let r = [], i = /* @__PURE__ */ new Set(), a = (e) => e.join("\0"), s = (e, n, r, i) => {
|
|
455
|
-
|
|
527
|
+
}, St = (e, t, n = null) => {
|
|
528
|
+
let r = [], i = /* @__PURE__ */ new Set(), a = (e) => e.join("\0"), s = (e, n, r, i, a) => {
|
|
529
|
+
if (t === "postgres") return de(r, i, a);
|
|
530
|
+
let o = {
|
|
456
531
|
using: "",
|
|
457
532
|
withSuffix: "",
|
|
458
533
|
skip: !1
|
|
459
534
|
};
|
|
460
|
-
|
|
461
|
-
if (r === "gist") return t === "postgres" ? {
|
|
462
|
-
using: " USING GIST",
|
|
463
|
-
withSuffix: "",
|
|
464
|
-
skip: !1
|
|
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
|
-
if (r === "gin") return t === "postgres" ? {
|
|
467
|
-
using: " USING GIN",
|
|
468
|
-
withSuffix: "",
|
|
469
|
-
skip: !1
|
|
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(...).`), {
|
|
535
|
+
return r === void 0 || r === "btree" ? o : r === "gist" ? (M(`[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.`), o) : r === "gin" ? t === "mysql" || t === "mariadb" ? (M(`[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
536
|
using: "",
|
|
472
537
|
withSuffix: "",
|
|
473
538
|
skip: !0
|
|
474
|
-
}) : (
|
|
475
|
-
|
|
476
|
-
using: " USING BRIN",
|
|
539
|
+
}) : (M(`[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.`), o) : r === "brin" ? (M(`[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).`), o) : r === "hnsw" ? (M(`[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.`), {
|
|
540
|
+
using: "",
|
|
477
541
|
withSuffix: "",
|
|
478
|
-
skip: !
|
|
479
|
-
} :
|
|
480
|
-
if (r === "hnsw") {
|
|
481
|
-
if (t === "postgres") {
|
|
482
|
-
let e = i?.hnsw?.m ?? 16, t = i?.hnsw?.efConstruction ?? 64, n = i?.hnsw?.opclass ?? h(i?.hnsw?.distance);
|
|
483
|
-
return {
|
|
484
|
-
using: " USING hnsw",
|
|
485
|
-
withSuffix: ` WITH (m = ${e}, ef_construction = ${t})`,
|
|
486
|
-
opclass: n,
|
|
487
|
-
skip: !1
|
|
488
|
-
};
|
|
489
|
-
}
|
|
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
|
-
using: "",
|
|
492
|
-
withSuffix: "",
|
|
493
|
-
skip: !0
|
|
494
|
-
};
|
|
495
|
-
}
|
|
496
|
-
return a;
|
|
542
|
+
skip: !0
|
|
543
|
+
}) : o;
|
|
497
544
|
}, c = (n, r) => {
|
|
498
545
|
let i = n.map((n) => {
|
|
499
|
-
if (typeof n == "string") return
|
|
546
|
+
if (typeof n == "string") return _t(n, e.fields, t);
|
|
500
547
|
if ("jsonPath" in n) {
|
|
501
548
|
let { column: e, path: r, numeric: i } = n.jsonPath;
|
|
502
549
|
return `(${C(e, r, t, { numeric: i })})`;
|
|
@@ -504,14 +551,14 @@ var A = "framework_changes", Ze = "framework_changes_", Qe = (e, t) => t === "fr
|
|
|
504
551
|
return `(${n.expr})`;
|
|
505
552
|
});
|
|
506
553
|
return r !== void 0 && i.length === 1 ? `${i[0]} ${r}` : i.join(", ");
|
|
507
|
-
}, l = (
|
|
508
|
-
let
|
|
509
|
-
if (
|
|
510
|
-
let
|
|
511
|
-
return t === "mssql" ? `IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = '${
|
|
554
|
+
}, l = (r, i, a, l, u, d = "", f = !1) => {
|
|
555
|
+
let p = a[0], m = typeof p == "string" ? e.fields[p]?.vectorPrecision : void 0, h = s(r, i, l, u, m);
|
|
556
|
+
if (h.skip) return "";
|
|
557
|
+
let g = c(a, h.opclass), _ = `${h.withSuffix}${d}`, v = mt(i, t, n), y = f ? "UNIQUE " : "";
|
|
558
|
+
return t === "mssql" ? `IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = '${r}') CREATE ${y}INDEX ${o(r, t)} ON ${v}${h.using} (${g})${_};` : t === "mysql" ? `CREATE ${y}INDEX ${o(r, t)} ON ${v}${h.using} (${g})${_};` : `CREATE ${y}INDEX IF NOT EXISTS ${o(r, t)} ON ${v}${h.using} (${g})${_};`;
|
|
512
559
|
};
|
|
513
560
|
if (t === "mysql" || t === "mariadb") for (let [n, i] of Object.entries(e.fields)) {
|
|
514
|
-
if (!i.unique || i.type === "id" || !
|
|
561
|
+
if (!i.unique || i.type === "id" || !gt(i, t)) continue;
|
|
515
562
|
let a = l(`${e.tableName}_${n}_key`, e.tableName, [n], void 0, void 0, "", !0);
|
|
516
563
|
a && r.push(a);
|
|
517
564
|
}
|
|
@@ -525,15 +572,15 @@ var A = "framework_changes", Ze = "framework_changes_", Qe = (e, t) => t === "fr
|
|
|
525
572
|
let i = n.columns.map((e) => o(e, t)).join(", ");
|
|
526
573
|
r.push(`CREATE FULLTEXT INDEX ${o(n.name, t)} ON ${o(e.tableName, t)} (${i});`);
|
|
527
574
|
} 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(...
|
|
575
|
+
else t === "sqlite" ? r.push(...xt(e.tableName, n, t)) : M(`[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
576
|
for (let n of e.appliedIndexes) {
|
|
530
577
|
if ((t === "mariadb" || t === "mssql") && n.fields.some((e) => typeof e != "string" && "jsonPath" in e)) {
|
|
531
|
-
|
|
578
|
+
M(`[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
579
|
continue;
|
|
533
580
|
}
|
|
534
581
|
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
582
|
let o = "";
|
|
536
|
-
n.where !== void 0 && n.where.length > 0 && (t === "mysql" || t === "mariadb" ?
|
|
583
|
+
n.where !== void 0 && n.where.length > 0 && (t === "mysql" || t === "mariadb" ? M(`[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
584
|
let s = l(n.name, e.tableName, n.fields, n.kind, n.kindOptions, o, n.unique === !0);
|
|
538
585
|
s !== "" && r.push(s), n.fields.every((e) => typeof e == "string") && i.add(a(n.fields));
|
|
539
586
|
}
|
|
@@ -543,17 +590,17 @@ var A = "framework_changes", Ze = "framework_changes_", Qe = (e, t) => t === "fr
|
|
|
543
590
|
r.push(l(o, e.tableName, [t])), i.add(a([t]));
|
|
544
591
|
}
|
|
545
592
|
return r.join("\n");
|
|
546
|
-
},
|
|
593
|
+
}, Ct = (e, t, n = j) => {
|
|
547
594
|
if (t !== "postgres") return [];
|
|
548
595
|
let r = e.filter((e) => e.isReactive !== !1);
|
|
549
|
-
return r.length === 0 ? [] : [
|
|
550
|
-
},
|
|
551
|
-
CREATE OR REPLACE FUNCTION ${
|
|
596
|
+
return r.length === 0 ? [] : [wt(n), ...r.map((e) => Et(e, n))];
|
|
597
|
+
}, wt = (e) => `
|
|
598
|
+
CREATE OR REPLACE FUNCTION ${ct(e)}() RETURNS trigger AS $$
|
|
552
599
|
DECLARE
|
|
553
600
|
payload TEXT;
|
|
554
601
|
pk JSONB;
|
|
555
602
|
BEGIN
|
|
556
|
-
-- ${
|
|
603
|
+
-- ${lt}
|
|
557
604
|
payload := json_build_object(
|
|
558
605
|
'table', TG_TABLE_NAME,
|
|
559
606
|
-- The schema the write landed in. Under namespace isolation this is
|
|
@@ -607,22 +654,22 @@ BEGIN
|
|
|
607
654
|
RETURN COALESCE(NEW, OLD);
|
|
608
655
|
END;
|
|
609
656
|
$$ LANGUAGE plpgsql;
|
|
610
|
-
`.trim(),
|
|
611
|
-
let n =
|
|
657
|
+
`.trim(), Tt = (e, t) => {
|
|
658
|
+
let n = st(e.tableName, t);
|
|
612
659
|
return [
|
|
613
660
|
`ALTER TABLE "${e.tableName}" REPLICA IDENTITY FULL`,
|
|
614
661
|
`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 ${
|
|
662
|
+
`CREATE TRIGGER ${n}\nAFTER INSERT OR UPDATE OR DELETE ON "${e.tableName}"\nFOR EACH ROW EXECUTE FUNCTION ${ct(t)}()`
|
|
616
663
|
];
|
|
617
|
-
},
|
|
664
|
+
}, Et = (e, t) => Tt(e, t).map((e) => `${e};`).join("\n"), Dt = (e) => {
|
|
618
665
|
if (e.dialect !== "postgres") return [];
|
|
619
666
|
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 ${
|
|
667
|
+
(i.length > 0 || e.functionOutdated === !0) && r.push(wt(t));
|
|
668
|
+
for (let e of i) r.push(...Tt(n.get(e), t));
|
|
669
|
+
for (let n of e.stale) r.push(`DROP TRIGGER IF EXISTS ${st(n, t)} ON "${n}"`), r.push(`ALTER TABLE "${n}" REPLICA IDENTITY DEFAULT`);
|
|
623
670
|
return r;
|
|
624
|
-
},
|
|
625
|
-
let t = new Map(e.map((e) => [e.tableName, e])), n =
|
|
671
|
+
}, Ot = (e) => e.some((e) => Object.values(e.fields).some((e) => e.type === "vector")), kt = (e) => e.some((e) => Object.values(e.fields).some((e) => e.spatial !== void 0)), At = (e) => {
|
|
672
|
+
let t = new Map(e.map((e) => [e.tableName, e])), n = ye(e.map((e) => e.tableName), (e) => {
|
|
626
673
|
let n = t.get(e);
|
|
627
674
|
return n ? Object.entries(n.fields).flatMap(([e, n]) => {
|
|
628
675
|
if (n.type !== "reference" || !n.references) return [];
|
|
@@ -633,7 +680,7 @@ $$ LANGUAGE plpgsql;
|
|
|
633
680
|
}] : [];
|
|
634
681
|
}) : [];
|
|
635
682
|
}), r = [];
|
|
636
|
-
for (let t of e) for (let [e, i] of Object.entries(t.fields)) i.type === "reference" && i.references && n.has(
|
|
683
|
+
for (let t of e) for (let [e, i] of Object.entries(t.fields)) i.type === "reference" && i.references && n.has(O(t.tableName, e)) && r.push({
|
|
637
684
|
table: t.tableName,
|
|
638
685
|
column: e,
|
|
639
686
|
targetTable: i.references().tableName,
|
|
@@ -645,7 +692,7 @@ $$ LANGUAGE plpgsql;
|
|
|
645
692
|
if (!(i.has(e.tableName) || a.has(e.tableName))) {
|
|
646
693
|
a.add(e.tableName);
|
|
647
694
|
for (let [r, i] of Object.entries(e.fields)) {
|
|
648
|
-
if (i.type !== "reference" || !i.references || n.has(
|
|
695
|
+
if (i.type !== "reference" || !i.references || n.has(O(e.tableName, r))) continue;
|
|
649
696
|
let a = i.references();
|
|
650
697
|
if (a.tableName === e.tableName) continue;
|
|
651
698
|
let o = t.get(a.tableName);
|
|
@@ -659,8 +706,8 @@ $$ LANGUAGE plpgsql;
|
|
|
659
706
|
sorted: o,
|
|
660
707
|
cyclic: r
|
|
661
708
|
};
|
|
662
|
-
},
|
|
663
|
-
let r = (e) => n ? `${o(n, t)}.${o(e, t)}` : o(e, t), i = `${e.table}_${e.column}_fkey`, a =
|
|
709
|
+
}, jt = (e, t, n = null) => {
|
|
710
|
+
let r = (e) => n ? `${o(n, t)}.${o(e, t)}` : o(e, t), i = `${e.table}_${e.column}_fkey`, a = I(e.onDelete, t), s = I(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
711
|
switch (t) {
|
|
665
712
|
case "postgres": return [
|
|
666
713
|
"DO $$ BEGIN",
|
|
@@ -674,7 +721,7 @@ $$ LANGUAGE plpgsql;
|
|
|
674
721
|
case "mariadb": return `ALTER TABLE ${r(e.table)} ${l(!0)};`;
|
|
675
722
|
default: return `ALTER TABLE ${r(e.table)} ${l(!1)};`;
|
|
676
723
|
}
|
|
677
|
-
},
|
|
724
|
+
}, Mt = (e, t) => {
|
|
678
725
|
let n = /* @__PURE__ */ new Map();
|
|
679
726
|
if (m(t)) return n;
|
|
680
727
|
for (let t of e) {
|
|
@@ -682,7 +729,7 @@ $$ LANGUAGE plpgsql;
|
|
|
682
729
|
e.add(t.column), n.set(t.table, e);
|
|
683
730
|
}
|
|
684
731
|
return n;
|
|
685
|
-
},
|
|
732
|
+
}, Nt = (e, t) => {
|
|
686
733
|
if (t !== "postgres") return "";
|
|
687
734
|
let n = /* @__PURE__ */ new Map();
|
|
688
735
|
for (let t of e) for (let e of Object.values(t.fields)) {
|
|
@@ -698,7 +745,7 @@ $$ LANGUAGE plpgsql;
|
|
|
698
745
|
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
746
|
}
|
|
700
747
|
return r.join("\n\n");
|
|
701
|
-
},
|
|
748
|
+
}, Pt = (e, t) => {
|
|
702
749
|
if (t !== "postgres") return "";
|
|
703
750
|
let r = /* @__PURE__ */ new Set();
|
|
704
751
|
for (let t of e) for (let e of Object.values(t.fields)) e.type === "enum" && e.enumName && r.add(e.enumName);
|
|
@@ -712,30 +759,30 @@ BEGIN
|
|
|
712
759
|
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
760
|
}
|
|
714
761
|
return i.join("\n\n");
|
|
715
|
-
},
|
|
762
|
+
}, Ft = (e) => {
|
|
716
763
|
let t = [], n = [];
|
|
717
764
|
for (let r of e) s(r) ? n.push(r) : t.push(r);
|
|
718
765
|
return {
|
|
719
766
|
tables: t,
|
|
720
767
|
views: n
|
|
721
768
|
};
|
|
722
|
-
},
|
|
723
|
-
let { tables: i, views: a } =
|
|
724
|
-
n === "postgres" &&
|
|
725
|
-
let u =
|
|
769
|
+
}, It = (t, n, r = j) => {
|
|
770
|
+
let { tables: i, views: a } = Ft(t), { sorted: o, cyclic: s } = At(i.map((e) => ve(e, n))), c = Mt(s, n), l = [];
|
|
771
|
+
n === "postgres" && Ot(o) && l.push("CREATE EXTENSION IF NOT EXISTS vector;"), n === "postgres" && kt(o) && l.push("CREATE EXTENSION IF NOT EXISTS postgis;");
|
|
772
|
+
let u = Pt(o, n);
|
|
726
773
|
u && l.push(u);
|
|
727
|
-
let d =
|
|
774
|
+
let d = Nt(o, n);
|
|
728
775
|
d && l.push(d);
|
|
729
|
-
for (let e of o) l.push(
|
|
730
|
-
if (!m(n)) for (let e of s) l.push(
|
|
776
|
+
for (let e of o) l.push(bt(e, n, null, c.get(e.tableName)));
|
|
777
|
+
if (!m(n)) for (let e of s) l.push(jt(e, n));
|
|
731
778
|
for (let e of o) {
|
|
732
|
-
let t =
|
|
779
|
+
let t = St(e, n);
|
|
733
780
|
t && l.push(t);
|
|
734
781
|
}
|
|
735
|
-
l.push(...
|
|
782
|
+
l.push(...Ct(o, n, r));
|
|
736
783
|
for (let t of a) l.push(e(t, n));
|
|
737
784
|
return l.join("\n\n") + "\n";
|
|
738
|
-
},
|
|
785
|
+
}, Lt = (e, t, n) => {
|
|
739
786
|
let r = o(e, t);
|
|
740
787
|
switch (t) {
|
|
741
788
|
case "postgres": return `CREATE SCHEMA IF NOT EXISTS ${r};`;
|
|
@@ -745,62 +792,62 @@ BEGIN
|
|
|
745
792
|
case "turso":
|
|
746
793
|
case "sqlite": return `ATTACH DATABASE '${(n ?? `${e}.db`).replace(/'/g, "''")}' AS ${r};`;
|
|
747
794
|
}
|
|
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(
|
|
795
|
+
}, Rt = (e, t, n, r) => {
|
|
796
|
+
let i = Lt(n, t, r), a = o(n, t);
|
|
797
|
+
if (t === "postgres") return `${i}\n\nSET search_path TO ${a};\n\n${It(e, t)}`;
|
|
798
|
+
if (t === "mysql" || t === "mariadb") return `${i}\n\nUSE ${a};\n\n${It(e, t)}`;
|
|
799
|
+
let { sorted: s, cyclic: c } = At(e), l = Mt(c, t), u = [i];
|
|
800
|
+
for (let e of s) u.push(bt(e, t, n, l.get(e.tableName)));
|
|
801
|
+
if (!m(t)) for (let e of c) u.push(jt(e, t, n));
|
|
755
802
|
for (let e of s) {
|
|
756
|
-
let r =
|
|
803
|
+
let r = St(e, t, n);
|
|
757
804
|
r && u.push(r);
|
|
758
805
|
}
|
|
759
806
|
return u.join("\n\n") + "\n";
|
|
760
|
-
},
|
|
761
|
-
let { sorted: r, cyclic: i } =
|
|
807
|
+
}, zt = (e, t, n = j) => {
|
|
808
|
+
let { sorted: r, cyclic: i } = At(e), a = Mt(i, t), o = [], s = Pt(r, t);
|
|
762
809
|
s && o.push(s);
|
|
763
|
-
let c =
|
|
810
|
+
let c = Nt(r, t);
|
|
764
811
|
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
|
-
},
|
|
812
|
+
for (let e of r) o.push(bt(e, t, null, a.get(e.tableName)));
|
|
813
|
+
for (let e of i) o.push(jt(e, t));
|
|
814
|
+
return o.push(...Ct(r, t, n)), o.join("\n\n") + "\n";
|
|
815
|
+
}, Bt = (e, t = "postgres", n = j, r = {}) => T.gen(function* () {
|
|
769
816
|
let i = yield* E.SqlClient;
|
|
770
|
-
yield*
|
|
771
|
-
}),
|
|
817
|
+
yield* Ve(i, qt(i, It(e, t, n), t, r.retryFilter), { schema: r.lockSchema }).pipe(T.orDie);
|
|
818
|
+
}), Vt = (e, t) => {
|
|
772
819
|
let n = t.cause ?? {};
|
|
773
820
|
return (n.errno === 1061 || n.code === "ER_DUP_KEYNAME") && /^\s*CREATE\s+(UNIQUE\s+|FULLTEXT\s+)?INDEX\b/i.test(e);
|
|
774
|
-
},
|
|
821
|
+
}, Ht = (e, t) => {
|
|
775
822
|
let n = e.trimStart();
|
|
776
823
|
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
|
-
},
|
|
824
|
+
}, Ut = () => {
|
|
778
825
|
let e = Number(process.env.VOLTRO_MIGRATION_DDL_RETRIES);
|
|
779
826
|
return Number.isInteger(e) && e >= 0 ? e : 4;
|
|
780
|
-
},
|
|
827
|
+
}, Wt = (e) => ({
|
|
781
828
|
while: e,
|
|
782
|
-
times:
|
|
783
|
-
schedule:
|
|
784
|
-
}),
|
|
829
|
+
times: Ut(),
|
|
830
|
+
schedule: ne.jittered(ne.exponential("50 millis"))
|
|
831
|
+
}), Gt = class {
|
|
785
832
|
statement;
|
|
786
833
|
error;
|
|
787
834
|
_tag = "DdlStatementFailed";
|
|
788
835
|
constructor(e, t) {
|
|
789
836
|
this.statement = e, this.error = t;
|
|
790
837
|
}
|
|
791
|
-
},
|
|
792
|
-
let r = yield* E.SqlClient, i = n !== void 0 &&
|
|
793
|
-
for (let a of
|
|
794
|
-
process.env.VOLTRO_MIGRATE_DEBUG === "1" &&
|
|
795
|
-
let e = r.unsafe(a).pipe(
|
|
796
|
-
|
|
838
|
+
}, Kt = (e, t, n) => T.gen(function* () {
|
|
839
|
+
let r = yield* E.SqlClient, i = n !== void 0 && We(t) === "per-operation";
|
|
840
|
+
for (let a of Jt(e)) {
|
|
841
|
+
process.env.VOLTRO_MIGRATE_DEBUG === "1" && dt.debug(`EXEC: ${a.replace(/\s+/g, " ").slice(0, 180)}`);
|
|
842
|
+
let e = r.unsafe(a).pipe(T.catchIf((e) => Vt(a, e), () => T.succeed([])), T.tapError((e) => T.sync(() => {
|
|
843
|
+
dt.error(fe("migrate: statement failed", a, e, 200));
|
|
797
844
|
})));
|
|
798
|
-
yield* (i && n !== void 0 &&
|
|
845
|
+
yield* (i && n !== void 0 && Ht(a, t) ? e.pipe(T.retry(Wt((e) => n(e) === "retry"))) : e).pipe(T.mapError((e) => new Gt(a, e)));
|
|
799
846
|
}
|
|
800
|
-
}),
|
|
801
|
-
let i = n === "turso" ?
|
|
802
|
-
return (r !== void 0 &&
|
|
803
|
-
},
|
|
847
|
+
}), qt = (e, t, n, r) => {
|
|
848
|
+
let i = n === "turso" ? Kt(t, n, r) : e.withTransaction(Kt(t, n, r)), a = (e) => e instanceof Gt ? e.error : e;
|
|
849
|
+
return (r !== void 0 && We(n) === "plan-transactional" ? i.pipe(T.retry(Wt((e) => r(a(e)) === "retry"))) : i).pipe(T.orDieWith((e) => e instanceof Gt ? Error(fe("migrate: statement failed", e.statement, e.error, 400).trim()) : e));
|
|
850
|
+
}, Jt = (e) => {
|
|
804
851
|
let t = [], n = "", r = !1;
|
|
805
852
|
for (let i = 0; i < e.length; i++) {
|
|
806
853
|
if (e.slice(i, i + 2) === "$$") {
|
|
@@ -815,50 +862,50 @@ BEGIN
|
|
|
815
862
|
}
|
|
816
863
|
let i = n.trim();
|
|
817
864
|
return i.length > 0 && t.push(i), t;
|
|
818
|
-
},
|
|
819
|
-
await
|
|
820
|
-
},
|
|
821
|
-
let i =
|
|
822
|
-
yield*
|
|
823
|
-
}),
|
|
824
|
-
await
|
|
865
|
+
}, Yt = async (e, t, n = "postgres", r = {}) => {
|
|
866
|
+
await T.runPromise(Bt(e, n, void 0, r).pipe(T.provide(t)));
|
|
867
|
+
}, Xt = (e, t, n = "postgres", r = {}) => T.gen(function* () {
|
|
868
|
+
let i = Rt(e, n, t), a = yield* E.SqlClient;
|
|
869
|
+
yield* Ve(a, qt(a, i, n, r.retryFilter), { schema: r.lockSchema }).pipe(T.orDie);
|
|
870
|
+
}), Zt = async (e, t, n, r = "postgres", i = {}) => {
|
|
871
|
+
await T.runPromise(Xt(e, t, r, i).pipe(T.provide(n))), await f({
|
|
825
872
|
namespace: t,
|
|
826
873
|
dialect: r
|
|
827
874
|
});
|
|
828
|
-
},
|
|
829
|
-
await
|
|
830
|
-
let t =
|
|
831
|
-
yield*
|
|
832
|
-
}).pipe(
|
|
833
|
-
},
|
|
875
|
+
}, Qt = async (e, t, n = "postgres", r = {}) => {
|
|
876
|
+
await T.runPromise(T.gen(function* () {
|
|
877
|
+
let t = zt(e, n), i = yield* E.SqlClient;
|
|
878
|
+
yield* Ve(i, qt(i, t, n, r.retryFilter), { schema: r.lockSchema }).pipe(T.orDie);
|
|
879
|
+
}).pipe(T.provide(t)));
|
|
880
|
+
}, L = (e) => {
|
|
834
881
|
if (typeof e != "object" || !e) return JSON.stringify(e);
|
|
835
|
-
if (Array.isArray(e)) return `[${e.map(
|
|
882
|
+
if (Array.isArray(e)) return `[${e.map(L).join(",")}]`;
|
|
836
883
|
let t = e;
|
|
837
|
-
return `{${Object.keys(t).sort().map((e) => `${JSON.stringify(e)}:${
|
|
838
|
-
},
|
|
884
|
+
return `{${Object.keys(t).sort().map((e) => `${JSON.stringify(e)}:${L(t[e])}`).join(",")}}`;
|
|
885
|
+
}, $t = (e) => {
|
|
839
886
|
if (!e.hasDefault || e.defaultValue === void 0 || e.defaultValue === null) return null;
|
|
840
887
|
let t = e.defaultValue;
|
|
841
888
|
if (typeof t == "boolean") return t ? "__BOOL_TRUE__" : "__BOOL_FALSE__";
|
|
842
889
|
if (typeof t == "number") return String(t);
|
|
843
|
-
if (typeof t != "string") return
|
|
890
|
+
if (typeof t != "string") return L(t);
|
|
844
891
|
let n = t.trim(), r = n.toLowerCase().replace(/\s+/g, "");
|
|
845
892
|
if (r === "now" || r === "now()" || /^current_timestamp(\(\d*\))?$/.test(r) || r === "sysutcdatetime()" || r === "sysdatetime()" || r === "getutcdate()" || r === "getdate()") return "__NOW__";
|
|
846
893
|
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
894
|
if (o) try {
|
|
848
|
-
return
|
|
895
|
+
return L(JSON.parse(o[1]));
|
|
849
896
|
} catch {}
|
|
850
897
|
let s = /^convert\(\s*(?:_\w+\s*)?\\?'(.*?)\\?'\s+using\s+[\w]+\s*\)$/i.exec(a);
|
|
851
898
|
if (s) try {
|
|
852
|
-
return
|
|
899
|
+
return L(JSON.parse(s[1]));
|
|
853
900
|
} catch {}
|
|
854
901
|
if (a.startsWith("{") || a.startsWith("[")) try {
|
|
855
|
-
return
|
|
902
|
+
return L(JSON.parse(a));
|
|
856
903
|
} catch {}
|
|
857
904
|
return /^-?\d+(\.\d+)?$/.test(a) ? String(Number(a)) : a;
|
|
858
|
-
},
|
|
859
|
-
let t =
|
|
905
|
+
}, en = (e) => {
|
|
906
|
+
let t = $t(e);
|
|
860
907
|
return t === "1" || t === "true" ? "__BOOL_TRUE__" : t === "0" || t === "false" ? "__BOOL_FALSE__" : t;
|
|
861
|
-
},
|
|
908
|
+
}, tn = (e) => typeof e.defaultValue == "string" && /^nextval\(.+::regclass\)$/i.test(e.defaultValue.trim()), nn = (e) => {
|
|
862
909
|
if (!e) return null;
|
|
863
910
|
let t = (e) => e === "restrict" ? "noAction" : e;
|
|
864
911
|
return {
|
|
@@ -867,26 +914,26 @@ BEGIN
|
|
|
867
914
|
onDelete: t(e.onDelete),
|
|
868
915
|
onUpdate: t(e.onUpdate)
|
|
869
916
|
};
|
|
870
|
-
},
|
|
917
|
+
}, rn = (e, t, n) => {
|
|
871
918
|
if (t === "mssql") {
|
|
872
|
-
let t =
|
|
919
|
+
let t = ut(e, n);
|
|
873
920
|
if (t !== void 0) return t;
|
|
874
921
|
}
|
|
875
922
|
try {
|
|
876
|
-
let n = /^N?VARCHAR\((\d+)\)$/i.exec(
|
|
923
|
+
let n = /^N?VARCHAR\((\d+)\)$/i.exec(N(e, t).trim());
|
|
877
924
|
return n ? Number(n[1]) : void 0;
|
|
878
925
|
} catch {
|
|
879
926
|
return;
|
|
880
927
|
}
|
|
881
|
-
},
|
|
928
|
+
}, an = /'(?:''|[^'])*'|"(?:""|[^"])*"|\[(?:\]\]|[^\]])*\]|`(?:``|[^`])*`|[A-Za-z_][A-Za-z_0-9$]*|\d+(?:\.\d+)?|::|<>|!=|<=|>=|\|\||[^\s]/g, on = (e) => {
|
|
882
929
|
let t = 0;
|
|
883
|
-
for (let n of e.matchAll(
|
|
884
|
-
},
|
|
930
|
+
for (let n of e.matchAll(an)) if (n[0] === "(" && t++, n[0] === ")" && t--, t === 0 && n[0].toLowerCase() === "where") return e.slice(n.index + n[0].length).trim().replace(/;$/, "").trim();
|
|
931
|
+
}, sn = (e) => {
|
|
885
932
|
if (e === void 0) return;
|
|
886
|
-
let t = e.match(
|
|
933
|
+
let t = e.match(an) ?? [], n = "(?:'(?:''|[^'])*'(?:\\s*::\\s*text)?|[0-9]+)", r = RegExp(`^\\s*${n}(?:\\s*,\\s*${n})*\\s*$`, "i");
|
|
887
934
|
for (let e = 0; e < t.length - 5; e++) {
|
|
888
935
|
let n = t[e + 4];
|
|
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(
|
|
936
|
+
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(an) ?? [], ")");
|
|
890
937
|
}
|
|
891
938
|
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) => {
|
|
892
939
|
if (e.startsWith("'")) return e;
|
|
@@ -924,22 +971,22 @@ BEGIN
|
|
|
924
971
|
return r;
|
|
925
972
|
};
|
|
926
973
|
return JSON.stringify(a(i));
|
|
927
|
-
},
|
|
974
|
+
}, cn = (e) => {
|
|
928
975
|
if (e == null) return e;
|
|
929
|
-
if (Array.isArray(e)) return e.map(
|
|
976
|
+
if (Array.isArray(e)) return e.map(cn);
|
|
930
977
|
if (typeof e != "object") return e;
|
|
931
978
|
let t = {};
|
|
932
979
|
for (let n of Object.keys(e).sort()) {
|
|
933
980
|
let r = e[n];
|
|
934
|
-
r !== void 0 && (t[n] =
|
|
981
|
+
r !== void 0 && (t[n] = cn(r));
|
|
935
982
|
}
|
|
936
983
|
return t;
|
|
937
|
-
},
|
|
938
|
-
if (!e.idScheme && !e.sensitive && !e.safe && !e.generatedAs) return e;
|
|
939
|
-
let { idScheme: t, sensitive: n, safe: r, generatedAs: i,
|
|
940
|
-
return
|
|
941
|
-
},
|
|
942
|
-
let t =
|
|
984
|
+
}, ln = (e) => {
|
|
985
|
+
if (!e.idScheme && !e.sensitive && !e.safe && !e.generatedAs && !e.jsonChecks) return e;
|
|
986
|
+
let { idScheme: t, sensitive: n, safe: r, generatedAs: i, jsonChecks: a, ...o } = e;
|
|
987
|
+
return o;
|
|
988
|
+
}, un = (e) => {
|
|
989
|
+
let t = ln(e), { references: n, defaultValue: r, hasDefault: i, oneOf: a, ...o } = t, s = t.type === "id" && tn(t) ? null : en(t), c = nn(t.references);
|
|
943
990
|
return {
|
|
944
991
|
...o,
|
|
945
992
|
hasDefault: s !== null,
|
|
@@ -947,17 +994,18 @@ BEGIN
|
|
|
947
994
|
...c === null ? {} : { references: c },
|
|
948
995
|
...t.oneOf !== void 0 && t.oneOf.length > 0 ? { oneOf: [...t.oneOf].sort() } : {}
|
|
949
996
|
};
|
|
950
|
-
},
|
|
951
|
-
...
|
|
952
|
-
|
|
953
|
-
|
|
997
|
+
}, dn = (e) => e.filter((e) => !x(e.name)).map(un).sort((e, t) => e.name.localeCompare(t.name)), fn = (e) => [...e].map(({ kind: e, kindOptions: t, ...n }) => ({
|
|
998
|
+
...n,
|
|
999
|
+
...D(e, t),
|
|
1000
|
+
...n.where === void 0 ? {} : { where: sn(n.where) }
|
|
1001
|
+
})).sort((e, t) => e.name.localeCompare(t.name)), pn = (e) => [...e].map((e) => ({
|
|
954
1002
|
name: e.name,
|
|
955
|
-
columns:
|
|
956
|
-
indexes:
|
|
957
|
-
})).sort((e, t) => e.name.localeCompare(t.name)),
|
|
958
|
-
let t = { tables:
|
|
959
|
-
return
|
|
960
|
-
},
|
|
1003
|
+
columns: dn(e.columns),
|
|
1004
|
+
indexes: fn(e.indexes)
|
|
1005
|
+
})).sort((e, t) => e.name.localeCompare(t.name)), R = (e) => {
|
|
1006
|
+
let t = { tables: pn(e.tables) }, n = JSON.stringify(cn(t));
|
|
1007
|
+
return ie("sha256").update(n).digest("hex");
|
|
1008
|
+
}, mn = (e) => e.slice(0, 16), hn = (e, t) => {
|
|
961
1009
|
let n = t.references ? {
|
|
962
1010
|
table: t.references().tableName,
|
|
963
1011
|
column: t.referenceColumn ?? "id",
|
|
@@ -997,105 +1045,111 @@ BEGIN
|
|
|
997
1045
|
...t.enumValues === void 0 ? {} : { enumValues: t.enumValues },
|
|
998
1046
|
...t.spatial === void 0 ? {} : { spatial: t.spatial }
|
|
999
1047
|
};
|
|
1000
|
-
},
|
|
1001
|
-
let
|
|
1002
|
-
|
|
1003
|
-
},
|
|
1004
|
-
|
|
1048
|
+
}, gn = (e, t) => {
|
|
1049
|
+
let n = [], i = /* @__PURE__ */ new Set(), a = (e) => {
|
|
1050
|
+
i.has(e.name) || (i.add(e.name), n.push(e));
|
|
1051
|
+
}, o = e.appliedPrimaryKey ?? [];
|
|
1052
|
+
o.length > 0 ? a({
|
|
1005
1053
|
name: `${e.tableName}_pkey`,
|
|
1006
1054
|
table: e.tableName,
|
|
1007
|
-
columns: [...
|
|
1055
|
+
columns: [...o],
|
|
1008
1056
|
unique: !0
|
|
1009
|
-
}) : e.fields.id &&
|
|
1057
|
+
}) : e.fields.id && a({
|
|
1010
1058
|
name: `${e.tableName}_pkey`,
|
|
1011
1059
|
table: e.tableName,
|
|
1012
1060
|
columns: ["id"],
|
|
1013
1061
|
unique: !0
|
|
1014
1062
|
});
|
|
1015
|
-
let
|
|
1016
|
-
for (let
|
|
1017
|
-
let
|
|
1018
|
-
|
|
1019
|
-
|
|
1063
|
+
let s = e.appliedIndexes ?? [];
|
|
1064
|
+
for (let n of s) {
|
|
1065
|
+
let r = ue(n.kind, t);
|
|
1066
|
+
if (r === null) continue;
|
|
1067
|
+
let i = n.fields[0], o = typeof i == "string" ? e.fields[i]?.vectorPrecision : void 0, s = r === "hnsw" ? { hnsw: le(n.kindOptions, o) } : void 0, c = n.fields.map((e) => typeof e == "string" ? e : "jsonPath" in e ? `(json:${e.jsonPath.column}->${e.jsonPath.path.join(".")}${e.jsonPath.numeric ? "::num" : ""})` : `(${e.expr})`), l = n.fields.some((e) => typeof e != "string");
|
|
1068
|
+
a({
|
|
1069
|
+
name: n.name,
|
|
1020
1070
|
table: e.tableName,
|
|
1021
|
-
columns:
|
|
1022
|
-
unique:
|
|
1023
|
-
...
|
|
1024
|
-
...
|
|
1071
|
+
columns: c,
|
|
1072
|
+
unique: n.unique ?? !1,
|
|
1073
|
+
...D(r, s),
|
|
1074
|
+
...n.where === void 0 ? {} : { where: n.where },
|
|
1075
|
+
...l ? { expression: !0 } : {}
|
|
1025
1076
|
});
|
|
1026
1077
|
}
|
|
1027
|
-
let
|
|
1028
|
-
for (let t of
|
|
1078
|
+
let c = e.appliedUniques ?? [];
|
|
1079
|
+
for (let t of c) t.fields.length < 2 || a({
|
|
1029
1080
|
name: t.name,
|
|
1030
1081
|
table: e.tableName,
|
|
1031
1082
|
columns: t.fields,
|
|
1032
1083
|
unique: !0
|
|
1033
1084
|
});
|
|
1034
|
-
let
|
|
1035
|
-
for (let e of
|
|
1085
|
+
let l = /* @__PURE__ */ new Set();
|
|
1086
|
+
for (let e of s) e.fields.every((e) => typeof e == "string") && l.add(e.fields.join("\0"));
|
|
1036
1087
|
for (let [t, n] of Object.entries(e.fields)) {
|
|
1037
|
-
let
|
|
1038
|
-
if (
|
|
1088
|
+
let i = n;
|
|
1089
|
+
if (i.dropped || !i.references || i.fkAutoIndex === !1 || l.has(t)) continue;
|
|
1039
1090
|
let o = `${e.tableName}_${t}_idx`;
|
|
1040
|
-
r(e.tableName, o, !0, [t]),
|
|
1091
|
+
r(e.tableName, o, !0, [t]), a({
|
|
1041
1092
|
name: o,
|
|
1042
1093
|
table: e.tableName,
|
|
1043
1094
|
columns: [t],
|
|
1044
1095
|
unique: !1
|
|
1045
1096
|
});
|
|
1046
1097
|
}
|
|
1047
|
-
return
|
|
1048
|
-
},
|
|
1049
|
-
let
|
|
1050
|
-
for (let [
|
|
1098
|
+
return n;
|
|
1099
|
+
}, _n = (e, t) => {
|
|
1100
|
+
let n = new Set((e.appliedUniques ?? []).filter((e) => e.fields.length === 1).map((e) => e.fields[0])), r = [];
|
|
1101
|
+
for (let [t, i] of Object.entries(e.fields)) {
|
|
1051
1102
|
if (i.dropped) continue;
|
|
1052
|
-
let e =
|
|
1053
|
-
|
|
1103
|
+
let e = hn(t, i);
|
|
1104
|
+
r.push(n.has(t) ? {
|
|
1054
1105
|
...e,
|
|
1055
1106
|
unique: !0
|
|
1056
1107
|
} : e);
|
|
1057
1108
|
}
|
|
1058
|
-
let
|
|
1109
|
+
let i = e.appliedPrimaryKey ?? [], a = e.previousTableName;
|
|
1059
1110
|
return {
|
|
1060
1111
|
name: e.tableName,
|
|
1061
|
-
columns:
|
|
1062
|
-
indexes:
|
|
1063
|
-
...
|
|
1064
|
-
...
|
|
1112
|
+
columns: r,
|
|
1113
|
+
indexes: gn(e, t),
|
|
1114
|
+
...i.length > 0 ? { primaryKey: [...i] } : {},
|
|
1115
|
+
...a === void 0 ? {} : { renamedFrom: a }
|
|
1065
1116
|
};
|
|
1066
|
-
},
|
|
1117
|
+
}, vn = (e) => {
|
|
1067
1118
|
let t = /* @__PURE__ */ new Map();
|
|
1068
1119
|
for (let n of e) for (let e of n.indexes) {
|
|
1069
1120
|
let r = t.get(e.name);
|
|
1070
1121
|
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}').`);
|
|
1071
1122
|
t.set(e.name, n.name);
|
|
1072
1123
|
}
|
|
1073
|
-
},
|
|
1074
|
-
let n = e.filter((e) => !c(e.tableName)).map((e) =>
|
|
1124
|
+
}, z = (e, t) => {
|
|
1125
|
+
let n = e.filter((e) => !c(e.tableName)).map((e) => _n(ve(e, t), t));
|
|
1075
1126
|
if (t === "mysql" || t === "mariadb") {
|
|
1076
1127
|
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.`);
|
|
1077
1128
|
}
|
|
1078
|
-
return
|
|
1079
|
-
},
|
|
1129
|
+
return vn(n), { tables: t === void 0 ? n : n.map((e) => yn(e, t)) };
|
|
1130
|
+
}, yn = (e, t) => {
|
|
1080
1131
|
let n = new Set(e.indexes.flatMap((e) => e.columns));
|
|
1081
1132
|
return {
|
|
1082
1133
|
...e,
|
|
1083
1134
|
columns: e.columns.map((e) => {
|
|
1084
|
-
if (e.
|
|
1085
|
-
|
|
1135
|
+
if (t === "mssql" && !e.generatedAs && (e.type === "json" || e.type === "array") && (e = {
|
|
1136
|
+
...e,
|
|
1137
|
+
jsonValidation: e.type === "json" ? "value" : "container"
|
|
1138
|
+
}), e.maxLength !== void 0) return e;
|
|
1139
|
+
let r = rn(e, t, n.has(e.name) || e.unique);
|
|
1086
1140
|
return r === void 0 ? e : {
|
|
1087
1141
|
...e,
|
|
1088
1142
|
maxLength: r
|
|
1089
1143
|
};
|
|
1090
1144
|
})
|
|
1091
1145
|
};
|
|
1092
|
-
},
|
|
1146
|
+
}, bn = (e, t, n = j) => T.gen(function* () {
|
|
1093
1147
|
let r = (yield* e`
|
|
1094
1148
|
SELECT p.prosrc
|
|
1095
1149
|
FROM pg_proc p
|
|
1096
1150
|
JOIN pg_namespace n ON n.oid = p.pronamespace
|
|
1097
1151
|
WHERE n.nspname = current_schema()
|
|
1098
|
-
AND p.proname = ${
|
|
1152
|
+
AND p.proname = ${ct(n)}
|
|
1099
1153
|
`)[0]?.prosrc, i = r !== void 0 && !r.includes("voltro:notify:v2"), a = t.filter((e) => !e.tableName.startsWith("_voltro_"));
|
|
1100
1154
|
if (a.length === 0) return {
|
|
1101
1155
|
missing: [],
|
|
@@ -1109,10 +1163,10 @@ BEGIN
|
|
|
1109
1163
|
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
1110
1164
|
WHERE NOT t.tgisinternal
|
|
1111
1165
|
AND n.nspname = current_schema()
|
|
1112
|
-
AND t.tgname LIKE ${`${
|
|
1166
|
+
AND t.tgname LIKE ${`${ot}%`}
|
|
1113
1167
|
`, s = new Set(o.map((e) => e.tgname)), c = [], l = [];
|
|
1114
1168
|
for (let e of a) {
|
|
1115
|
-
let t = s.has(
|
|
1169
|
+
let t = s.has(st(e.tableName, n)), r = e.isReactive !== !1;
|
|
1116
1170
|
r && !t && c.push(e.tableName), !r && t && l.push(e.tableName);
|
|
1117
1171
|
}
|
|
1118
1172
|
return {
|
|
@@ -1120,7 +1174,7 @@ BEGIN
|
|
|
1120
1174
|
stale: l.sort(),
|
|
1121
1175
|
functionOutdated: i
|
|
1122
1176
|
};
|
|
1123
|
-
}),
|
|
1177
|
+
}), xn = (e) => {
|
|
1124
1178
|
let t = [];
|
|
1125
1179
|
if (e.missing.length > 0) {
|
|
1126
1180
|
let n = e.missing.slice(0, 8).join(", "), r = e.missing.length > 8 ? `, … (+${e.missing.length - 8})` : "";
|
|
@@ -1131,19 +1185,19 @@ BEGIN
|
|
|
1131
1185
|
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.`);
|
|
1132
1186
|
}
|
|
1133
1187
|
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;
|
|
1134
|
-
},
|
|
1188
|
+
}, Sn = {
|
|
1135
1189
|
postgres: !0,
|
|
1136
1190
|
mysql: !0,
|
|
1137
1191
|
mariadb: !0,
|
|
1138
1192
|
mssql: !0,
|
|
1139
1193
|
sqlite: !0
|
|
1140
|
-
},
|
|
1194
|
+
}, Cn = {
|
|
1141
1195
|
postgres: !0,
|
|
1142
1196
|
mysql: !1,
|
|
1143
1197
|
mariadb: !1,
|
|
1144
1198
|
mssql: !0,
|
|
1145
1199
|
sqlite: !0
|
|
1146
|
-
},
|
|
1200
|
+
}, wn = (e) => {
|
|
1147
1201
|
switch (e) {
|
|
1148
1202
|
case "add-column":
|
|
1149
1203
|
case "drop-column":
|
|
@@ -1153,33 +1207,33 @@ BEGIN
|
|
|
1153
1207
|
case "add-foreign-key":
|
|
1154
1208
|
case "add-unique":
|
|
1155
1209
|
case "add-unique-composite":
|
|
1156
|
-
case "add-check": return
|
|
1157
|
-
default: return
|
|
1210
|
+
case "add-check": return Cn;
|
|
1211
|
+
default: return Sn;
|
|
1158
1212
|
}
|
|
1159
|
-
},
|
|
1213
|
+
}, Tn = (e, t) => {
|
|
1160
1214
|
let n = new Map(t.tables.map((e) => [e.name, e]));
|
|
1161
1215
|
return new Map(e.map((e) => [e.tableName, {
|
|
1162
1216
|
table: e,
|
|
1163
1217
|
snapshot: n.get(e.tableName),
|
|
1164
1218
|
columnDefs: e.fields
|
|
1165
1219
|
}]));
|
|
1166
|
-
},
|
|
1167
|
-
let n =
|
|
1220
|
+
}, En = (e, t) => {
|
|
1221
|
+
let n = $t(e), r = $t(t);
|
|
1168
1222
|
if (n === r) return !0;
|
|
1169
|
-
let i =
|
|
1170
|
-
return e.type === "id" && t.type === "id" && (a(e) && n === null && i(t) || a(t) && r === null && i(e)) ? !0 :
|
|
1171
|
-
},
|
|
1223
|
+
let i = tn, a = (e) => e.type === "id" && e.idScheme?.kind === "numeric";
|
|
1224
|
+
return e.type === "id" && t.type === "id" && (a(e) && n === null && i(t) || a(t) && r === null && i(e)) ? !0 : en(e) === en(t);
|
|
1225
|
+
}, Dn = (e, t) => {
|
|
1172
1226
|
let n = e && e.length > 0 ? e : void 0, r = t && t.length > 0 ? t : void 0;
|
|
1173
1227
|
if (!n && !r) return !0;
|
|
1174
1228
|
if (!n || !r || n.length !== r.length) return !1;
|
|
1175
1229
|
let i = [...n].sort(), a = [...r].sort();
|
|
1176
1230
|
return i.every((e, t) => e === a[t]);
|
|
1177
|
-
},
|
|
1231
|
+
}, On = (e, t, n, r) => n === void 0 || m(n) ? !0 : e.type !== "text" || t.type !== "text" || rn(e, n, r) === t.maxLength, kn = (e, t, n, r) => e.type === t.type && e.nullable === t.nullable && e.unique === t.unique && e.jsonValidation === t.jsonValidation && En(e, t) && On(e, t, n, r) && (e.type !== "reference" || (e.referenceStorage ?? "text") === (t.referenceStorage ?? "text")) && JSON.stringify(nn(e.references)) === JSON.stringify(nn(t.references)) && Dn(e.oneOf, t.oneOf), An = (e, t) => t.oneOf && t.oneOf.length > 0 ? B({
|
|
1178
1232
|
kind: "add-check",
|
|
1179
1233
|
table: e,
|
|
1180
1234
|
column: t.name,
|
|
1181
1235
|
values: t.oneOf
|
|
1182
|
-
}, "safe", `enum-membership CHECK on ${e}.${t.name}`) : void 0,
|
|
1236
|
+
}, "safe", `enum-membership CHECK on ${e}.${t.name}`) : void 0, jn = (e, t) => e.unique === t.unique && e.valid !== !1 && t.valid !== !1 && sn(e.where) === sn(t.where) && JSON.stringify(D(e.kind, e.kindOptions)) === JSON.stringify(D(t.kind, t.kindOptions)) && (e.expression || t.expression ? !0 : e.columns.length === t.columns.length && e.columns.every((e, n) => e === t.columns[n])), Mn = (e, t, n) => {
|
|
1183
1237
|
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));
|
|
1184
1238
|
for (let t of e.columns) {
|
|
1185
1239
|
let e = r.get(t.name);
|
|
@@ -1187,7 +1241,7 @@ BEGIN
|
|
|
1187
1241
|
a.push(t);
|
|
1188
1242
|
continue;
|
|
1189
1243
|
}
|
|
1190
|
-
|
|
1244
|
+
kn(t, e, n, c.has(t.name) || t.unique) || s.push({
|
|
1191
1245
|
declared: t,
|
|
1192
1246
|
live: e
|
|
1193
1247
|
});
|
|
@@ -1198,50 +1252,50 @@ BEGIN
|
|
|
1198
1252
|
removed: o,
|
|
1199
1253
|
changed: s
|
|
1200
1254
|
};
|
|
1201
|
-
},
|
|
1255
|
+
}, Nn = (e, t, n) => {
|
|
1202
1256
|
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 = [];
|
|
1203
1257
|
for (let t of e.indexes) {
|
|
1204
1258
|
let e = i.get(r(t.name));
|
|
1205
|
-
(!e || !
|
|
1259
|
+
(!e || !jn(t, e)) && o.push(t);
|
|
1206
1260
|
}
|
|
1207
1261
|
for (let e of t.indexes) {
|
|
1208
1262
|
let t = a.get(r(e.name));
|
|
1209
|
-
(!t ||
|
|
1263
|
+
(!t || !jn(t, e)) && s.push(e);
|
|
1210
1264
|
}
|
|
1211
1265
|
return {
|
|
1212
1266
|
added: o,
|
|
1213
1267
|
removed: s
|
|
1214
1268
|
};
|
|
1215
|
-
},
|
|
1269
|
+
}, B = (e, t, n, r) => ({
|
|
1216
1270
|
op: e,
|
|
1217
1271
|
classification: t,
|
|
1218
|
-
atomicByDialect:
|
|
1272
|
+
atomicByDialect: wn(e.kind),
|
|
1219
1273
|
...n ? { reason: n } : {},
|
|
1220
1274
|
...r ? { blocked: r } : {}
|
|
1221
|
-
}),
|
|
1275
|
+
}), Pn = (e, t, n) => {
|
|
1222
1276
|
let r = {
|
|
1223
1277
|
kind: "add-column",
|
|
1224
1278
|
table: e,
|
|
1225
1279
|
column: t
|
|
1226
1280
|
};
|
|
1227
|
-
return t.nullable ?
|
|
1228
|
-
},
|
|
1281
|
+
return t.nullable ? B(r, "safe", "nullable column add — no backfill needed") : t.hasDefault && t.defaultValue !== void 0 ? B(r, "needs-default", "NOT NULL with literal default — DDL DEFAULT will populate existing rows") : n?.backfill ? B(r, "needs-backfill", `backfill declared (kind=${n.backfill.kind}) — applier will run 3-step add/update/set-not-null`) : B(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` });
|
|
1282
|
+
}, Fn = (e, t, n) => {
|
|
1229
1283
|
let r = {
|
|
1230
1284
|
kind: "drop-column",
|
|
1231
1285
|
table: e,
|
|
1232
1286
|
column: t.name
|
|
1233
1287
|
};
|
|
1234
|
-
return n?.dropped ?
|
|
1235
|
-
},
|
|
1288
|
+
return n?.dropped ? B(r, "lossy", `column dropped via \`${t.name}: dropped()\` marker — intentional`) : B(r, "lossy", "column missing from declared schema", { fix: `if intentional, add \`${t.name}: dropped()\` to the schema. If a typo, restore the field` });
|
|
1289
|
+
}, In = (e, t, n, r, i) => B({
|
|
1236
1290
|
kind: "create-table",
|
|
1237
1291
|
table: e,
|
|
1238
1292
|
columns: t,
|
|
1239
1293
|
indexes: n,
|
|
1240
1294
|
...r && r.length > 0 ? { primaryKey: r } : {}
|
|
1241
|
-
}, "safe", i ?? "new table — no data to preserve"),
|
|
1295
|
+
}, "safe", i ?? "new table — no data to preserve"), Ln = (e) => B({
|
|
1242
1296
|
kind: "drop-table",
|
|
1243
1297
|
table: e
|
|
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" }),
|
|
1298
|
+
}, "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" }), Rn = 5e4, zn = (e, t, n, r) => {
|
|
1245
1299
|
let i = (n ?? 0) >= r, a;
|
|
1246
1300
|
return a = !t.unique || t.where !== void 0 ? {
|
|
1247
1301
|
kind: "add-index",
|
|
@@ -1256,28 +1310,28 @@ BEGIN
|
|
|
1256
1310
|
table: e,
|
|
1257
1311
|
name: t.name,
|
|
1258
1312
|
fields: t.columns
|
|
1259
|
-
}, i ?
|
|
1260
|
-
},
|
|
1313
|
+
}, i ? B(a, "online-required", `online build on ${n} rows — CONCURRENTLY / INPLACE / WITH(ONLINE=ON) depending on dialect`) : B(a, "safe", t.where === void 0 ? t.unique ? t.columns.length === 1 ? "add unique constraint" : "add composite UNIQUE constraint" : `add ${t.kind === void 0 || t.kind === "btree" ? "B-tree" : t.kind.toUpperCase()} index` : `add ${t.unique ? "unique " : ""}partial index`);
|
|
1314
|
+
}, Bn = (e, t) => t.unique && t.where === void 0 && t.columns.length > 1 ? B({
|
|
1261
1315
|
kind: "drop-unique-composite",
|
|
1262
1316
|
table: e,
|
|
1263
1317
|
name: t.name
|
|
1264
|
-
}, "safe", "drop composite UNIQUE constraint (no data loss — constraint is derived metadata)") :
|
|
1318
|
+
}, "safe", "drop composite UNIQUE constraint (no data loss — constraint is derived metadata)") : B({
|
|
1265
1319
|
kind: "drop-index",
|
|
1266
1320
|
table: e,
|
|
1267
1321
|
index: t.name
|
|
1268
|
-
}, "safe", "drop index (no data loss — index is derived data)"),
|
|
1322
|
+
}, "safe", "drop index (no data loss — index is derived data)"), Vn = (e, t) => {
|
|
1269
1323
|
let n = e.type;
|
|
1270
1324
|
if (n === "reference") return e.referenceStorage === "numeric" ? "bigint" : "text";
|
|
1271
1325
|
switch (t) {
|
|
1272
1326
|
case "sqlite":
|
|
1273
1327
|
case "turso": return n === "timestamp" || n === "date" || n === "json" ? "text" : n === "boolean" ? "integer" : n === "decimal" ? "text" : n === "bigint" ? "integer" : n;
|
|
1274
|
-
case "mssql": return n === "json" ? "text" : n;
|
|
1328
|
+
case "mssql": return n === "json" || n === "array" ? "text" : n;
|
|
1275
1329
|
default: return n;
|
|
1276
1330
|
}
|
|
1277
|
-
},
|
|
1331
|
+
}, Hn = (e, t, n) => {
|
|
1278
1332
|
let r = `acknowledge it on the column: \`.narrowedFrom('${e}')\``;
|
|
1279
1333
|
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`;
|
|
1280
|
-
},
|
|
1334
|
+
}, Un = (e, t, n, r, i, a) => {
|
|
1281
1335
|
let o = [];
|
|
1282
1336
|
if (t.nullable !== n.nullable) {
|
|
1283
1337
|
let n = {
|
|
@@ -1286,7 +1340,7 @@ BEGIN
|
|
|
1286
1340
|
column: t.name,
|
|
1287
1341
|
toNullable: t.nullable
|
|
1288
1342
|
};
|
|
1289
|
-
o.push(t.nullable ?
|
|
1343
|
+
o.push(t.nullable ? B(n, "safe", `loosen ${e}.${t.name} to nullable`) : B(n, "needs-backfill", `tighten ${e}.${t.name} to NOT NULL — existing rows must already be non-null`));
|
|
1290
1344
|
}
|
|
1291
1345
|
if (t.unique !== n.unique) {
|
|
1292
1346
|
if (t.unique) {
|
|
@@ -1295,14 +1349,14 @@ BEGIN
|
|
|
1295
1349
|
table: e,
|
|
1296
1350
|
column: t.name
|
|
1297
1351
|
}, r = (i ?? 0) >= a;
|
|
1298
|
-
o.push(r ?
|
|
1299
|
-
} else o.push(
|
|
1352
|
+
o.push(r ? B(n, "online-required", `online unique build on ${i} rows — CONCURRENTLY / INPLACE / WITH(ONLINE=ON) depending on dialect`) : B(n, "safe", `add unique constraint on ${e}.${t.name} — existing rows must already be distinct (else the DB rejects at migrate)`));
|
|
1353
|
+
} else o.push(B({
|
|
1300
1354
|
kind: "drop-unique",
|
|
1301
1355
|
table: e,
|
|
1302
1356
|
column: t.name
|
|
1303
1357
|
}, "safe", `drop unique constraint on ${e}.${t.name} — constraint is derived metadata, no data loss`));
|
|
1304
1358
|
}
|
|
1305
|
-
if (
|
|
1359
|
+
if (Vn(t, r) !== Vn(n, r)) {
|
|
1306
1360
|
let i = t.narrowedFrom;
|
|
1307
1361
|
if (i && i.from === n.type) {
|
|
1308
1362
|
let r = {
|
|
@@ -1313,7 +1367,7 @@ BEGIN
|
|
|
1313
1367
|
to: t.type,
|
|
1314
1368
|
...i.using === void 0 ? {} : { using: i.using }
|
|
1315
1369
|
};
|
|
1316
|
-
o.push(
|
|
1370
|
+
o.push(B(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)")));
|
|
1317
1371
|
} else {
|
|
1318
1372
|
let i = {
|
|
1319
1373
|
kind: "alter-column-type",
|
|
@@ -1322,12 +1376,12 @@ BEGIN
|
|
|
1322
1376
|
from: n.type,
|
|
1323
1377
|
to: t.type
|
|
1324
1378
|
};
|
|
1325
|
-
o.push(
|
|
1379
|
+
o.push(B(i, "lossy", `type change ${n.type} → ${t.type} on ${e}.${t.name} may not be value-preserving`, { fix: Hn(n.type, t, r) }));
|
|
1326
1380
|
}
|
|
1327
1381
|
}
|
|
1328
1382
|
if (t.type === "text" && n.type === "text" && !m(r ?? "postgres") && t.maxLength !== n.maxLength) {
|
|
1329
1383
|
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})`;
|
|
1330
|
-
o.push(
|
|
1384
|
+
o.push(B({
|
|
1331
1385
|
kind: "alter-column-type",
|
|
1332
1386
|
table: e,
|
|
1333
1387
|
column: t.name,
|
|
@@ -1335,7 +1389,7 @@ BEGIN
|
|
|
1335
1389
|
to: "text"
|
|
1336
1390
|
}, 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)}`));
|
|
1337
1391
|
}
|
|
1338
|
-
if (!
|
|
1392
|
+
if (!En(t, n)) {
|
|
1339
1393
|
let n = {
|
|
1340
1394
|
kind: "alter-column-default",
|
|
1341
1395
|
table: e,
|
|
@@ -1343,23 +1397,34 @@ BEGIN
|
|
|
1343
1397
|
hasDefault: t.hasDefault,
|
|
1344
1398
|
...t.defaultValue === void 0 ? {} : { defaultValue: t.defaultValue }
|
|
1345
1399
|
};
|
|
1346
|
-
o.push(
|
|
1400
|
+
o.push(B(n, "safe", `default change on ${e}.${t.name} affects only future inserts`));
|
|
1401
|
+
}
|
|
1402
|
+
if (r === "mssql" && t.jsonValidation !== void 0 && t.jsonValidation !== "unverified" && t.jsonValidation !== n.jsonValidation) {
|
|
1403
|
+
let r = t.jsonValidation === "value" && n.jsonValidation === "container";
|
|
1404
|
+
o.push(B({
|
|
1405
|
+
kind: "reconcile-json-check",
|
|
1406
|
+
table: e,
|
|
1407
|
+
column: t.name,
|
|
1408
|
+
validation: t.jsonValidation,
|
|
1409
|
+
previousValidation: n.jsonValidation ?? "absent",
|
|
1410
|
+
dropConstraints: (n.jsonChecks ?? []).map((e) => e.name).sort()
|
|
1411
|
+
}, r ? "safe" : "needs-backfill", r ? `allow every JSON value on ${e}.${t.name}; preserve existing rows` : `validate existing JSON on ${e}.${t.name}; invalid rows refuse the migration without being rewritten`));
|
|
1347
1412
|
}
|
|
1348
|
-
if (!
|
|
1349
|
-
n.oneOf && n.oneOf.length > 0 && o.push(
|
|
1413
|
+
if (!Dn(t.oneOf, n.oneOf)) {
|
|
1414
|
+
n.oneOf && n.oneOf.length > 0 && o.push(B({
|
|
1350
1415
|
kind: "drop-check",
|
|
1351
1416
|
table: e,
|
|
1352
1417
|
column: t.name
|
|
1353
1418
|
}, "safe", `drop stale enum CHECK on ${e}.${t.name}`));
|
|
1354
|
-
let r =
|
|
1419
|
+
let r = An(e, t);
|
|
1355
1420
|
r && o.push(r);
|
|
1356
1421
|
}
|
|
1357
|
-
return JSON.stringify(
|
|
1422
|
+
return JSON.stringify(nn(t.references)) !== JSON.stringify(nn(n.references)) && (n.references && o.push(B({
|
|
1358
1423
|
kind: "drop-foreign-key",
|
|
1359
1424
|
table: e,
|
|
1360
1425
|
column: t.name
|
|
1361
|
-
}, "safe", `drop FK on ${e}.${t.name} (→ ${n.references.table})`)), o.push(...
|
|
1362
|
-
},
|
|
1426
|
+
}, "safe", `drop FK on ${e}.${t.name} (→ ${n.references.table})`)), o.push(...Wn(e, t))), o;
|
|
1427
|
+
}, Wn = (e, t) => {
|
|
1363
1428
|
let n = [];
|
|
1364
1429
|
if (!t.references) return n;
|
|
1365
1430
|
let r = t.references.table, i = t.references.orphanPolicy ?? "fail", a = {
|
|
@@ -1371,15 +1436,15 @@ BEGIN
|
|
|
1371
1436
|
...t.references.onDelete ? { onDelete: t.references.onDelete } : {},
|
|
1372
1437
|
...t.references.onUpdate ? { onUpdate: t.references.onUpdate } : {}
|
|
1373
1438
|
};
|
|
1374
|
-
return i === "null" && !t.nullable ? n.push(
|
|
1439
|
+
return i === "null" && !t.nullable ? n.push(B(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(B({
|
|
1375
1440
|
...a,
|
|
1376
1441
|
orphanPolicy: i
|
|
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(
|
|
1378
|
-
},
|
|
1442
|
+
}, "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(B(a, "needs-backfill", `add FK ${e}.${t.name} → ${r} — existing rows must already reference a valid ${r} (else set orphanPolicy:'null'/'delete')`)), n;
|
|
1443
|
+
}, Gn = (e, t, n) => {
|
|
1379
1444
|
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));
|
|
1380
1445
|
for (let [n, c] of Object.entries(t)) {
|
|
1381
1446
|
let t = c.renamedFrom;
|
|
1382
|
-
t && o.has(t) && s.has(n) && (i.add(n), a.add(t), r.push(
|
|
1447
|
+
t && o.has(t) && s.has(n) && (i.add(n), a.add(t), r.push(B({
|
|
1383
1448
|
kind: "rename-column",
|
|
1384
1449
|
table: e.tableName,
|
|
1385
1450
|
from: t,
|
|
@@ -1391,30 +1456,30 @@ BEGIN
|
|
|
1391
1456
|
consumedAddedNames: i,
|
|
1392
1457
|
consumedRemovedNames: a
|
|
1393
1458
|
};
|
|
1394
|
-
},
|
|
1459
|
+
}, Kn = /* @__PURE__ */ new Set([
|
|
1395
1460
|
"postgres",
|
|
1396
1461
|
"mysql",
|
|
1397
1462
|
"mariadb",
|
|
1398
1463
|
"mssql"
|
|
1399
|
-
]),
|
|
1464
|
+
]), qn = {
|
|
1400
1465
|
ops: [],
|
|
1401
1466
|
consumedAddedNames: /* @__PURE__ */ new Set(),
|
|
1402
1467
|
consumedRemovedNames: /* @__PURE__ */ new Set()
|
|
1403
|
-
},
|
|
1404
|
-
if (i === void 0 || !
|
|
1405
|
-
let a = t.added.filter((e) =>
|
|
1406
|
-
if (a.length === 0) return
|
|
1468
|
+
}, Jn = (e) => !e.unique && !e.expression && e.where === void 0 && (e.kind === void 0 || e.kind === "btree"), Yn = (e, t, n, r, i) => {
|
|
1469
|
+
if (i === void 0 || !Kn.has(i)) return qn;
|
|
1470
|
+
let a = t.added.filter((e) => Jn(e) && !r.has(e.name));
|
|
1471
|
+
if (a.length === 0) return qn;
|
|
1407
1472
|
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();
|
|
1408
1473
|
for (let n of t.removed) {
|
|
1409
|
-
if (!
|
|
1410
|
-
let
|
|
1411
|
-
if (
|
|
1412
|
-
let
|
|
1413
|
-
|
|
1474
|
+
if (!Jn(n) || t.added.some((e) => e.name === n.name)) continue;
|
|
1475
|
+
let r = o(n), i = a.filter((e) => !l.has(e.name) && s(e) === r);
|
|
1476
|
+
if (i.length !== 1) continue;
|
|
1477
|
+
let d = i[0];
|
|
1478
|
+
d.name !== n.name && (l.add(d.name), u.add(n.name), c.push(B({
|
|
1414
1479
|
kind: "rename-index",
|
|
1415
1480
|
table: e,
|
|
1416
1481
|
from: n.name,
|
|
1417
|
-
to:
|
|
1482
|
+
to: d.name
|
|
1418
1483
|
}, "safe", "rename index in place — catalog-only, no rebuild")));
|
|
1419
1484
|
}
|
|
1420
1485
|
return {
|
|
@@ -1422,7 +1487,7 @@ BEGIN
|
|
|
1422
1487
|
consumedAddedNames: l,
|
|
1423
1488
|
consumedRemovedNames: u
|
|
1424
1489
|
};
|
|
1425
|
-
},
|
|
1490
|
+
}, Xn = (e, t, n) => {
|
|
1426
1491
|
let r = [], i = /* @__PURE__ */ new Map(), a = /* @__PURE__ */ new Set(), o = /* @__PURE__ */ new Map(), s = /* @__PURE__ */ new Map(), c = /* @__PURE__ */ new Set();
|
|
1427
1492
|
for (let t of e.tables) t.renamedFrom !== void 0 && (s.set(t.renamedFrom, (s.get(t.renamedFrom) ?? 0) + 1), c.add(t.renamedFrom));
|
|
1428
1493
|
for (let c of e.tables) {
|
|
@@ -1433,7 +1498,7 @@ BEGIN
|
|
|
1433
1498
|
continue;
|
|
1434
1499
|
}
|
|
1435
1500
|
if (t.has(c.name)) {
|
|
1436
|
-
r.push(
|
|
1501
|
+
r.push(B({
|
|
1437
1502
|
kind: "rename-table",
|
|
1438
1503
|
from: e,
|
|
1439
1504
|
to: c.name
|
|
@@ -1441,14 +1506,14 @@ BEGIN
|
|
|
1441
1506
|
continue;
|
|
1442
1507
|
}
|
|
1443
1508
|
if ((s.get(e) ?? 0) !== 1) {
|
|
1444
|
-
r.push(
|
|
1509
|
+
r.push(B({
|
|
1445
1510
|
kind: "rename-table",
|
|
1446
1511
|
from: e,
|
|
1447
1512
|
to: c.name
|
|
1448
1513
|
}, "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.` }));
|
|
1449
1514
|
continue;
|
|
1450
1515
|
}
|
|
1451
|
-
i.set(c.name, e), a.add(e), r.push(
|
|
1516
|
+
i.set(c.name, e), a.add(e), r.push(B({
|
|
1452
1517
|
kind: "rename-table",
|
|
1453
1518
|
from: e,
|
|
1454
1519
|
to: c.name
|
|
@@ -1462,19 +1527,19 @@ BEGIN
|
|
|
1462
1527
|
claimedOldNames: c,
|
|
1463
1528
|
refusals: o
|
|
1464
1529
|
};
|
|
1465
|
-
},
|
|
1530
|
+
}, Zn = (e, t, n, r) => {
|
|
1466
1531
|
if (t === void 0) return {
|
|
1467
1532
|
live: e,
|
|
1468
1533
|
ops: []
|
|
1469
1534
|
};
|
|
1470
|
-
let i = r !== void 0 &&
|
|
1535
|
+
let i = r !== void 0 && Kn.has(r), a = [], o = e.indexes.map((e) => {
|
|
1471
1536
|
if (!e.name.startsWith(t)) return e;
|
|
1472
1537
|
let r = `${n}${e.name.slice(t.length)}`;
|
|
1473
1538
|
return r === e.name ? e : e.name === `${t}_pkey` ? {
|
|
1474
1539
|
...e,
|
|
1475
1540
|
name: r,
|
|
1476
1541
|
table: n
|
|
1477
|
-
} : i ? (a.push(
|
|
1542
|
+
} : i ? (a.push(B({
|
|
1478
1543
|
kind: "rename-index",
|
|
1479
1544
|
table: n,
|
|
1480
1545
|
from: e.name,
|
|
@@ -1493,7 +1558,7 @@ BEGIN
|
|
|
1493
1558
|
},
|
|
1494
1559
|
ops: a
|
|
1495
1560
|
};
|
|
1496
|
-
},
|
|
1561
|
+
}, Qn = (e) => {
|
|
1497
1562
|
let t = {
|
|
1498
1563
|
safe: 0,
|
|
1499
1564
|
needsDefault: 0,
|
|
@@ -1526,13 +1591,13 @@ BEGIN
|
|
|
1526
1591
|
case "multi-step": t.multiStep++;
|
|
1527
1592
|
}
|
|
1528
1593
|
return t;
|
|
1529
|
-
},
|
|
1530
|
-
let t =
|
|
1594
|
+
}, $n = (e) => {
|
|
1595
|
+
let t = z(e.declared, e.dialect), n = Tn(e.declared, t), r = new Map(e.live.tables.map((e) => [e.name, e])), i = e.onlineAfter ?? Rn, a = [], o = Xn(t, r, n);
|
|
1531
1596
|
a.push(...o.ops);
|
|
1532
1597
|
for (let e of t.tables) if (!o.renamedInto.has(e.name) && !r.has(e.name)) {
|
|
1533
|
-
a.push(
|
|
1598
|
+
a.push(In(e.name, e.columns, e.indexes, e.primaryKey, o.refusals.get(e.name)));
|
|
1534
1599
|
for (let t of e.columns) {
|
|
1535
|
-
let n =
|
|
1600
|
+
let n = An(e.name, t);
|
|
1536
1601
|
n && a.push(n);
|
|
1537
1602
|
}
|
|
1538
1603
|
}
|
|
@@ -1554,32 +1619,40 @@ BEGIN
|
|
|
1554
1619
|
c.push(t.name);
|
|
1555
1620
|
continue;
|
|
1556
1621
|
}
|
|
1557
|
-
a.push(
|
|
1622
|
+
a.push(Ln(t.name));
|
|
1558
1623
|
}
|
|
1559
1624
|
for (let s of t.tables) {
|
|
1560
1625
|
let t = o.renamedInto.get(s.name), c = r.get(s.name) ?? (t === void 0 ? void 0 : r.get(t));
|
|
1561
1626
|
if (!c) continue;
|
|
1562
|
-
let l =
|
|
1627
|
+
let l = Zn(c, t, s.name, e.dialect);
|
|
1563
1628
|
a.push(...l.ops);
|
|
1564
|
-
let u = l.live, d = n.get(s.name), f =
|
|
1629
|
+
let u = l.live, d = n.get(s.name), f = Mn(s, u, e.dialect), p = Nn(s, u, e.dialect), m = Gn(d.table, d.columnDefs, f);
|
|
1565
1630
|
a.push(...m.ops);
|
|
1631
|
+
for (let { op: t } of m.ops) {
|
|
1632
|
+
if (t.kind !== "rename-column") continue;
|
|
1633
|
+
let n = s.columns.find((e) => e.name === t.to), r = u.columns.find((e) => e.name === t.from);
|
|
1634
|
+
n && r && a.push(...Un(s.name, n, {
|
|
1635
|
+
...r,
|
|
1636
|
+
name: t.to
|
|
1637
|
+
}, e.dialect, u.rowCount, i));
|
|
1638
|
+
}
|
|
1566
1639
|
for (let e of f.removed) {
|
|
1567
1640
|
if (m.consumedRemovedNames.has(e.name) || x(e.name)) continue;
|
|
1568
1641
|
let t = d.columnDefs[e.name];
|
|
1569
|
-
a.push(
|
|
1642
|
+
a.push(Fn(s.name, e, t));
|
|
1570
1643
|
}
|
|
1571
1644
|
for (let e of f.added) {
|
|
1572
1645
|
if (m.consumedAddedNames.has(e.name)) continue;
|
|
1573
1646
|
let t = d.columnDefs[e.name];
|
|
1574
|
-
a.push(
|
|
1575
|
-
let n =
|
|
1576
|
-
n && a.push(n), a.push(...
|
|
1647
|
+
a.push(Pn(s.name, e, t));
|
|
1648
|
+
let n = An(s.name, e);
|
|
1649
|
+
n && a.push(n), a.push(...Wn(s.name, e));
|
|
1577
1650
|
}
|
|
1578
|
-
let h = new Map(m.ops.flatMap((e) => e.op.kind === "rename-column" ? [[e.op.from, e.op.to]] : [])), g =
|
|
1651
|
+
let h = new Map(m.ops.flatMap((e) => e.op.kind === "rename-column" ? [[e.op.from, e.op.to]] : [])), g = Yn(s.name, p, h, new Set(u.indexes.map((e) => e.name)), e.dialect);
|
|
1579
1652
|
a.push(...g.ops);
|
|
1580
|
-
for (let e of p.added) g.consumedAddedNames.has(e.name) || a.push(
|
|
1581
|
-
for (let e of p.removed) g.consumedRemovedNames.has(e.name) || a.push(
|
|
1582
|
-
for (let { declared: t, live: n } of f.changed) a.push(...
|
|
1653
|
+
for (let e of p.added) g.consumedAddedNames.has(e.name) || a.push(zn(s.name, e, u.rowCount, i));
|
|
1654
|
+
for (let e of p.removed) g.consumedRemovedNames.has(e.name) || a.push(Bn(s.name, e));
|
|
1655
|
+
for (let { declared: t, live: n } of f.changed) a.push(...Un(s.name, t, n, e.dialect, u.rowCount, i));
|
|
1583
1656
|
}
|
|
1584
1657
|
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
1658
|
let t = u.get(e);
|
|
@@ -1587,8 +1660,8 @@ BEGIN
|
|
|
1587
1660
|
column: e.name,
|
|
1588
1661
|
target: e.references.table
|
|
1589
1662
|
}] : []) : [];
|
|
1590
|
-
}, f =
|
|
1591
|
-
for (let e of t.tables) if (l.has(e.name)) for (let t of e.columns) t.references && f.has(
|
|
1663
|
+
}, f = ye([...l], d), p = [];
|
|
1664
|
+
for (let e of t.tables) if (l.has(e.name)) for (let t of e.columns) t.references && f.has(O(e.name, t.name)) && p.push(B({
|
|
1592
1665
|
kind: "add-foreign-key",
|
|
1593
1666
|
table: e.name,
|
|
1594
1667
|
column: t.name,
|
|
@@ -1603,8 +1676,8 @@ BEGIN
|
|
|
1603
1676
|
let n = a[t];
|
|
1604
1677
|
if (n.op.kind !== "create-table") continue;
|
|
1605
1678
|
let r = n.op;
|
|
1606
|
-
if (!r.columns.some((e) => f.has(
|
|
1607
|
-
let i = r.columns.map((t) => f.has(
|
|
1679
|
+
if (!r.columns.some((e) => f.has(O(r.table, e.name)))) continue;
|
|
1680
|
+
let i = r.columns.map((t) => f.has(O(r.table, t.name)) ? e(t) : t);
|
|
1608
1681
|
a[t] = {
|
|
1609
1682
|
...n,
|
|
1610
1683
|
op: {
|
|
@@ -1624,7 +1697,7 @@ BEGIN
|
|
|
1624
1697
|
let i = new Set(t).add(e), a = 0;
|
|
1625
1698
|
for (let t of r.columns) {
|
|
1626
1699
|
let n = t.references?.table;
|
|
1627
|
-
n && n !== e && !f.has(
|
|
1700
|
+
n && n !== e && !f.has(O(e, t.name)) && (a = Math.max(a, g(n, i) + 1));
|
|
1628
1701
|
}
|
|
1629
1702
|
return h.set(e, a), a;
|
|
1630
1703
|
}, v = (e) => e === "rename-table" ? -1 : e === "create-table" ? 0 : e === "drop-table" ? 2 : 1, y = (e) => {
|
|
@@ -1647,7 +1720,8 @@ BEGIN
|
|
|
1647
1720
|
"add-unique": 5,
|
|
1648
1721
|
"add-unique-composite": 5,
|
|
1649
1722
|
"add-foreign-key": 5,
|
|
1650
|
-
"add-check": 5
|
|
1723
|
+
"add-check": 5,
|
|
1724
|
+
"reconcile-json-check": 5
|
|
1651
1725
|
}, S = (e) => b[e] ?? 9, C = [...a].sort((e, t) => {
|
|
1652
1726
|
let n = v(e.op.kind), r = v(t.op.kind);
|
|
1653
1727
|
if (n !== r) return n - r;
|
|
@@ -1663,19 +1737,34 @@ BEGIN
|
|
|
1663
1737
|
for (let e of t.tables) {
|
|
1664
1738
|
if (w.has(e.name) || o.renamedInto.has(e.name)) continue;
|
|
1665
1739
|
let t = r.get(e.name);
|
|
1666
|
-
t !== void 0 &&
|
|
1740
|
+
t !== void 0 && R({ tables: [t] }) !== R({ tables: [e] }) && T.push(e.name);
|
|
1667
1741
|
}
|
|
1668
1742
|
return {
|
|
1669
1743
|
operations: C,
|
|
1670
|
-
fromFingerprint:
|
|
1671
|
-
toFingerprint:
|
|
1672
|
-
summary:
|
|
1744
|
+
fromFingerprint: R(e.live),
|
|
1745
|
+
toFingerprint: R(t),
|
|
1746
|
+
summary: Qn(C),
|
|
1673
1747
|
fingerprintDivergence: {
|
|
1674
1748
|
outsideDiff: c,
|
|
1675
1749
|
diffEquivalent: T
|
|
1676
1750
|
}
|
|
1677
1751
|
};
|
|
1678
|
-
},
|
|
1752
|
+
}, er = (e, t) => {
|
|
1753
|
+
let n = (e.match(/'(?:''|[^'])*'|"(?:""|[^"])*"|::|[A-Za-z_][A-Za-z_0-9$]*|[^\s]/g) ?? []).filter((e) => e !== "(" && e !== ")"), r = 0, i = (e) => n[r]?.toLowerCase() === e && (r++, !0);
|
|
1754
|
+
if (!i("check")) return null;
|
|
1755
|
+
let a = n[r++];
|
|
1756
|
+
if (a === void 0 || (a.startsWith("\"") ? a.slice(1, -1).replace(/""/g, "\"") : a.toLowerCase()) !== t) return null;
|
|
1757
|
+
let o = () => !i("::") || i("text") || i("character") && i("varying");
|
|
1758
|
+
if (!o() || !i("=")) return null;
|
|
1759
|
+
let s = i("any");
|
|
1760
|
+
if (s && (!i("array") || !i("["))) return null;
|
|
1761
|
+
let c = [];
|
|
1762
|
+
do {
|
|
1763
|
+
let e = n[r++];
|
|
1764
|
+
if (e === void 0 || !/^'(?:''|[^'])*'$/.test(e) || (c.push(e.slice(1, -1).replace(/''/g, "'")), !o())) return null;
|
|
1765
|
+
} while (s && i(","));
|
|
1766
|
+
return s && (!i("]") || i("::") && (!i("text") || !i("[") || !i("]"))) ? null : r === n.length ? c : null;
|
|
1767
|
+
}, tr = (e) => {
|
|
1679
1768
|
let t = /[`"[]?([A-Za-z_][A-Za-z0-9_]*)[`"\]]?\s*(?:in\b|=)/i.exec(e);
|
|
1680
1769
|
if (!t) return null;
|
|
1681
1770
|
let n = [...e.replace(/\\'/g, "'").matchAll(/'((?:[^']|'')*)'/g)].map((e) => e[1].replace(/''/g, "'")).filter((e) => e.length > 0);
|
|
@@ -1683,8 +1772,8 @@ BEGIN
|
|
|
1683
1772
|
column: t[1],
|
|
1684
1773
|
values: n
|
|
1685
1774
|
};
|
|
1686
|
-
},
|
|
1687
|
-
if (t === "vector") return "vector";
|
|
1775
|
+
}, nr = (e, t) => {
|
|
1776
|
+
if (t === "vector" || t === "halfvec") return "vector";
|
|
1688
1777
|
switch (e) {
|
|
1689
1778
|
case "text":
|
|
1690
1779
|
case "character varying":
|
|
@@ -1710,10 +1799,10 @@ BEGIN
|
|
|
1710
1799
|
case "USER-DEFINED": return "text";
|
|
1711
1800
|
default: return "text";
|
|
1712
1801
|
}
|
|
1713
|
-
},
|
|
1802
|
+
}, rr = (e, t) => e == null || e === "" ? void 0 : { generatedAs: {
|
|
1714
1803
|
expr: e,
|
|
1715
1804
|
stored: t
|
|
1716
|
-
} },
|
|
1805
|
+
} }, V = (e) => {
|
|
1717
1806
|
switch (e.toUpperCase()) {
|
|
1718
1807
|
case "CASCADE": return "cascade";
|
|
1719
1808
|
case "RESTRICT": return "restrict";
|
|
@@ -1721,25 +1810,25 @@ BEGIN
|
|
|
1721
1810
|
case "SET DEFAULT": return "noAction";
|
|
1722
1811
|
default: return "noAction";
|
|
1723
1812
|
}
|
|
1724
|
-
},
|
|
1813
|
+
}, ir = (e, t) => {
|
|
1725
1814
|
let n = e !== void 0 && e !== "" ? Number(e) : NaN;
|
|
1726
1815
|
return Number.isInteger(n) && n > 0 ? n : t;
|
|
1727
|
-
},
|
|
1816
|
+
}, ar = () => ir(process.env.VOLTRO_INTROSPECT_BATCH, 20), or = 300, sr = () => {
|
|
1728
1817
|
let e = process.env.VOLTRO_INTROSPECT_TIMEOUT_MS;
|
|
1729
|
-
return e !== void 0 && e.trim() === "0" ? 0 :
|
|
1730
|
-
},
|
|
1818
|
+
return e !== void 0 && e.trim() === "0" ? 0 : ir(e, 3e4);
|
|
1819
|
+
}, cr = (e, t) => {
|
|
1731
1820
|
let n = Number.isFinite(t) && t >= 1 ? Math.floor(t) : 1, r = [];
|
|
1732
1821
|
for (let t = 0; t < e.length; t += n) r.push(e.slice(t, t + n));
|
|
1733
1822
|
return r;
|
|
1734
|
-
},
|
|
1735
|
-
let t =
|
|
1823
|
+
}, lr = (e) => {
|
|
1824
|
+
let t = sr(), n = T.gen(function* () {
|
|
1736
1825
|
t > 0 && (yield* e.unsafe(`SET LOCAL statement_timeout = ${t}`));
|
|
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 =
|
|
1826
|
+
let n = (t) => e.unsafe("(" + t.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ") + ")"), r = (t) => e.unsafe(String(Math.max(0, Math.trunc(t)))), i = ar(), a = (e, t) => T.gen(function* () {
|
|
1738
1827
|
let r = [];
|
|
1739
|
-
for (let a of
|
|
1828
|
+
for (let a of cr(e, i)) a.length !== 0 && r.push(...yield* t(n(a)));
|
|
1740
1829
|
return r;
|
|
1741
1830
|
}), o = [];
|
|
1742
|
-
for (let t = 0;; t +=
|
|
1831
|
+
for (let t = 0;; t += or) {
|
|
1743
1832
|
let n = yield* e`
|
|
1744
1833
|
SELECT c.relname AS table_name,
|
|
1745
1834
|
COALESCE(c.reltuples::bigint, 0) AS row_count
|
|
@@ -1747,16 +1836,21 @@ BEGIN
|
|
|
1747
1836
|
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
1748
1837
|
WHERE n.nspname = current_schema() AND c.relkind = 'r'
|
|
1749
1838
|
ORDER BY c.relname
|
|
1750
|
-
LIMIT ${r(
|
|
1839
|
+
LIMIT ${r(or)} OFFSET ${r(t)}
|
|
1751
1840
|
`;
|
|
1752
|
-
if (o.push(...n), n.length <
|
|
1841
|
+
if (o.push(...n), n.length < or) break;
|
|
1753
1842
|
}
|
|
1754
1843
|
let s = /* @__PURE__ */ new Set(), c = [];
|
|
1755
1844
|
for (let e of o) s.has(e.table_name) || (s.add(e.table_name), c.push(e));
|
|
1756
1845
|
let l = c.map((e) => e.table_name), u = yield* a(l, (t) => e`
|
|
1757
1846
|
SELECT table_name, column_name, data_type, udt_name, is_nullable, column_default,
|
|
1758
|
-
character_maximum_length, is_generated, generation_expression
|
|
1759
|
-
|
|
1847
|
+
character_maximum_length, is_generated, generation_expression,
|
|
1848
|
+
(SELECT a.atttypmod FROM pg_attribute a
|
|
1849
|
+
JOIN pg_class c ON c.oid = a.attrelid
|
|
1850
|
+
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
1851
|
+
WHERE n.nspname = col.table_schema AND c.relname = col.table_name
|
|
1852
|
+
AND a.attname = col.column_name) AS type_modifier
|
|
1853
|
+
FROM information_schema.columns col
|
|
1760
1854
|
WHERE table_schema = current_schema() AND table_name IN ${t}
|
|
1761
1855
|
ORDER BY table_name, ordinal_position
|
|
1762
1856
|
`), d = yield* a(l, (t) => e`
|
|
@@ -1786,8 +1880,8 @@ BEGIN
|
|
|
1786
1880
|
AND rel.relname IN ${t}
|
|
1787
1881
|
`), m = /* @__PURE__ */ new Map();
|
|
1788
1882
|
for (let e of p) {
|
|
1789
|
-
let t =
|
|
1790
|
-
t
|
|
1883
|
+
let t = er(e.def, e.column_name);
|
|
1884
|
+
t !== null && m.set(`${e.table_name}.${e.column_name}`, t);
|
|
1791
1885
|
}
|
|
1792
1886
|
let h = yield* a(l, (t) => e`
|
|
1793
1887
|
SELECT
|
|
@@ -1820,6 +1914,10 @@ BEGIN
|
|
|
1820
1914
|
c.relname AS table_name,
|
|
1821
1915
|
i.relname AS index_name,
|
|
1822
1916
|
ix2.indisunique AS is_unique,
|
|
1917
|
+
am.amname AS access_method,
|
|
1918
|
+
CASE WHEN opn.nspname IN ('public', 'pg_catalog') THEN opc.opcname
|
|
1919
|
+
ELSE opn.nspname || '.' || opc.opcname END AS operator_class,
|
|
1920
|
+
i.reloptions AS reloptions,
|
|
1823
1921
|
pg_get_expr(ix2.indpred, ix2.indrelid) AS predicate,
|
|
1824
1922
|
ix2.indisvalid AS is_valid,
|
|
1825
1923
|
(0 = ANY (ix2.indkey::int[])) AS has_expression,
|
|
@@ -1827,6 +1925,9 @@ BEGIN
|
|
|
1827
1925
|
array_position(ix2.indkey::int[], a.attnum) + 1 AS position
|
|
1828
1926
|
FROM pg_index ix2
|
|
1829
1927
|
JOIN pg_class i ON i.oid = ix2.indexrelid
|
|
1928
|
+
JOIN pg_am am ON am.oid = i.relam
|
|
1929
|
+
LEFT JOIN pg_opclass opc ON opc.oid = ix2.indclass[0]
|
|
1930
|
+
LEFT JOIN pg_namespace opn ON opn.oid = opc.opcnamespace
|
|
1830
1931
|
JOIN pg_class c ON c.oid = ix2.indrelid
|
|
1831
1932
|
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
1832
1933
|
LEFT JOIN pg_attribute a ON a.attrelid = c.oid AND a.attnum = ANY (ix2.indkey)
|
|
@@ -1882,27 +1983,31 @@ BEGIN
|
|
|
1882
1983
|
let n = t.get(e.index_name);
|
|
1883
1984
|
n || (n = [], t.set(e.index_name, n)), n.push(e);
|
|
1884
1985
|
}
|
|
1885
|
-
let
|
|
1986
|
+
let w = [];
|
|
1886
1987
|
for (let e of c) {
|
|
1887
1988
|
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) => {
|
|
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" :
|
|
1989
|
+
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" : nr(t.data_type, t.udt_name), c = a ? {
|
|
1889
1990
|
table: a.target_table,
|
|
1890
1991
|
column: a.target_column,
|
|
1891
|
-
onDelete:
|
|
1892
|
-
onUpdate:
|
|
1992
|
+
onDelete: V(a.delete_rule),
|
|
1993
|
+
onUpdate: V(a.update_rule)
|
|
1893
1994
|
} : void 0, l = m.get(`${e.table_name}.${t.column_name}`);
|
|
1894
1995
|
return {
|
|
1895
1996
|
name: t.column_name,
|
|
1896
1997
|
type: s,
|
|
1897
|
-
...
|
|
1998
|
+
...s === "vector" ? {
|
|
1999
|
+
vectorPrecision: t.udt_name === "halfvec" ? "half" : "float32",
|
|
2000
|
+
...t.type_modifier !== void 0 && t.type_modifier > 0 ? { vectorDim: t.type_modifier } : {}
|
|
2001
|
+
} : {},
|
|
2002
|
+
...U(t.data_type, t.character_maximum_length) === void 0 ? {} : { maxLength: U(t.data_type, t.character_maximum_length) },
|
|
1898
2003
|
nullable: t.is_nullable === "YES",
|
|
1899
2004
|
unique: i.has(t.column_name) || n && t.column_name === "id",
|
|
1900
2005
|
hasDefault: t.column_default !== null,
|
|
1901
2006
|
...t.column_default === null ? {} : { defaultValue: t.column_default },
|
|
1902
2007
|
...c ? { references: c } : {},
|
|
1903
|
-
...a ? { referenceStorage: ["integer", "bigint"].includes(
|
|
2008
|
+
...a ? { referenceStorage: ["integer", "bigint"].includes(nr(t.data_type, t.udt_name)) ? "numeric" : "text" } : {},
|
|
1904
2009
|
...l ? { oneOf: l } : {},
|
|
1905
|
-
...
|
|
2010
|
+
...rr(t.is_generated === "ALWAYS" ? t.generation_expression ?? "generated" : null, !0) ?? {}
|
|
1906
2011
|
};
|
|
1907
2012
|
}), l = [], u = S.get(e.table_name);
|
|
1908
2013
|
if (u) for (let [t, n] of u) {
|
|
@@ -1911,12 +2016,21 @@ BEGIN
|
|
|
1911
2016
|
return !r.has(t) && (r.add(t), !0);
|
|
1912
2017
|
});
|
|
1913
2018
|
if (i.some((e) => s.has(e.column_name))) continue;
|
|
1914
|
-
let a = n.some((e) => e.has_expression)
|
|
2019
|
+
let a = n.some((e) => e.has_expression), o = n[0], c = new Map((o?.reloptions ?? []).map((e) => {
|
|
2020
|
+
let [t, n] = e.split("=");
|
|
2021
|
+
return [t, Number(n)];
|
|
2022
|
+
}));
|
|
2023
|
+
if (o?.access_method === "hnsw" && !o.operator_class) throw Error(`Cannot read HNSW operator class for index ${t}`);
|
|
1915
2024
|
l.push({
|
|
1916
2025
|
name: t,
|
|
1917
2026
|
table: e.table_name,
|
|
1918
2027
|
columns: i.map((e) => e.column_name),
|
|
1919
2028
|
unique: n[0]?.is_unique ?? !1,
|
|
2029
|
+
...D(o?.access_method, o?.access_method === "hnsw" ? { hnsw: {
|
|
2030
|
+
opclass: o.operator_class,
|
|
2031
|
+
m: c.get("m") ?? 16,
|
|
2032
|
+
efConstruction: c.get("ef_construction") ?? 64
|
|
2033
|
+
} } : void 0),
|
|
1920
2034
|
...n[0]?.predicate == null ? {} : { where: n[0].predicate },
|
|
1921
2035
|
...n[0]?.is_valid === !1 ? { valid: !1 } : {},
|
|
1922
2036
|
...a ? { expression: !0 } : {}
|
|
@@ -1930,20 +2044,20 @@ BEGIN
|
|
|
1930
2044
|
unique: !0
|
|
1931
2045
|
});
|
|
1932
2046
|
let d = Number(e.row_count ?? 0);
|
|
1933
|
-
|
|
2047
|
+
w.push({
|
|
1934
2048
|
name: e.table_name,
|
|
1935
2049
|
columns: c,
|
|
1936
2050
|
indexes: l,
|
|
1937
2051
|
...d > 0 ? { rowCount: d } : {}
|
|
1938
2052
|
});
|
|
1939
2053
|
}
|
|
1940
|
-
return { tables:
|
|
2054
|
+
return { tables: w };
|
|
1941
2055
|
});
|
|
1942
|
-
return (t > 0 ? e.withTransaction(n) : n).pipe(
|
|
2056
|
+
return (t > 0 ? e.withTransaction(n) : n).pipe(T.catchAll((e) => {
|
|
1943
2057
|
let n = `${String(e)} ${String(e.cause ?? "")}`.toLowerCase();
|
|
1944
|
-
return n.includes("statement timeout") || n.includes("57014") ?
|
|
2058
|
+
return n.includes("statement timeout") || n.includes("57014") ? T.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.`)) : T.fail(e);
|
|
1945
2059
|
}));
|
|
1946
|
-
},
|
|
2060
|
+
}, ur = (e, t) => {
|
|
1947
2061
|
switch (e.toLowerCase()) {
|
|
1948
2062
|
case "varchar":
|
|
1949
2063
|
case "char":
|
|
@@ -1975,21 +2089,21 @@ BEGIN
|
|
|
1975
2089
|
case "json": return "json";
|
|
1976
2090
|
default: return "text";
|
|
1977
2091
|
}
|
|
1978
|
-
},
|
|
2092
|
+
}, dr = (e) => e.map((e) => {
|
|
1979
2093
|
let t = e, n = {};
|
|
1980
2094
|
for (let e of Object.keys(t)) n[e.toLowerCase()] = t[e];
|
|
1981
2095
|
return n;
|
|
1982
|
-
}),
|
|
1983
|
-
let t =
|
|
2096
|
+
}), fr = (e) => T.gen(function* () {
|
|
2097
|
+
let t = dr(yield* e`
|
|
1984
2098
|
SELECT table_name, COALESCE(table_rows, 0) AS table_rows
|
|
1985
2099
|
FROM information_schema.tables
|
|
1986
2100
|
WHERE table_schema = DATABASE() AND table_type = 'BASE TABLE'
|
|
1987
|
-
ORDER BY table_name`), n =
|
|
2101
|
+
ORDER BY table_name`), n = dr(yield* e`
|
|
1988
2102
|
SELECT table_name, column_name, data_type, column_type, is_nullable, column_default, column_key,
|
|
1989
2103
|
character_maximum_length, generation_expression, extra
|
|
1990
2104
|
FROM information_schema.columns
|
|
1991
2105
|
WHERE table_schema = DATABASE()
|
|
1992
|
-
ORDER BY table_name, ordinal_position`), r =
|
|
2106
|
+
ORDER BY table_name, ordinal_position`), r = dr(yield* e`
|
|
1993
2107
|
SELECT k.table_name AS source_table,
|
|
1994
2108
|
k.column_name AS source_column,
|
|
1995
2109
|
k.referenced_table_name AS target_table,
|
|
@@ -1999,7 +2113,7 @@ BEGIN
|
|
|
1999
2113
|
JOIN information_schema.referential_constraints r
|
|
2000
2114
|
ON k.constraint_name = r.constraint_name
|
|
2001
2115
|
AND k.table_schema = r.constraint_schema
|
|
2002
|
-
WHERE k.table_schema = DATABASE() AND k.referenced_table_name IS NOT NULL`), i =
|
|
2116
|
+
WHERE k.table_schema = DATABASE() AND k.referenced_table_name IS NOT NULL`), i = dr(yield* e`
|
|
2003
2117
|
SELECT table_name, index_name, non_unique, column_name, seq_in_index
|
|
2004
2118
|
FROM information_schema.statistics
|
|
2005
2119
|
WHERE table_schema = DATABASE() AND index_name <> 'PRIMARY'
|
|
@@ -2012,14 +2126,14 @@ BEGIN
|
|
|
2012
2126
|
JOIN information_schema.table_constraints tc
|
|
2013
2127
|
ON tc.constraint_schema = cc.constraint_schema
|
|
2014
2128
|
AND tc.constraint_name = cc.constraint_name
|
|
2015
|
-
WHERE cc.constraint_schema = DATABASE()`.unprepared, s =
|
|
2129
|
+
WHERE cc.constraint_schema = DATABASE()`.unprepared, s = dr(yield* a.pipe(T.orElse(() => o), T.orElseSucceed(() => []))), c = /* @__PURE__ */ new Set(), l = /* @__PURE__ */ new Map();
|
|
2016
2130
|
for (let e of s) {
|
|
2017
2131
|
let t = /json_valid\(`?([^`)]+)`?\)/i.exec(e.check_clause);
|
|
2018
2132
|
if (t) {
|
|
2019
2133
|
c.add(`${e.table_name}.${t[1]}`);
|
|
2020
2134
|
continue;
|
|
2021
2135
|
}
|
|
2022
|
-
let n =
|
|
2136
|
+
let n = tr(e.check_clause);
|
|
2023
2137
|
n && l.set(`${e.table_name}.${n.column}`, n.values);
|
|
2024
2138
|
}
|
|
2025
2139
|
let u = /* @__PURE__ */ new Map(), d = /* @__PURE__ */ new Map(), f = /* @__PURE__ */ new Map();
|
|
@@ -2042,24 +2156,24 @@ BEGIN
|
|
|
2042
2156
|
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);
|
|
2043
2157
|
if (o) for (let e of o.values()) e.length === 1 && e[0].non_unique === 0 && a.add(e[0].column_name);
|
|
2044
2158
|
let s = t.map((t) => {
|
|
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" :
|
|
2159
|
+
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" : ur(t.data_type, t.column_type), u = o ? {
|
|
2046
2160
|
table: o.target_table,
|
|
2047
2161
|
column: o.target_column,
|
|
2048
|
-
onDelete:
|
|
2049
|
-
onUpdate:
|
|
2162
|
+
onDelete: V(o.delete_rule),
|
|
2163
|
+
onUpdate: V(o.update_rule)
|
|
2050
2164
|
} : 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}`);
|
|
2051
2165
|
return {
|
|
2052
2166
|
name: t.column_name,
|
|
2053
2167
|
type: s,
|
|
2054
2168
|
nullable: t.is_nullable === "YES",
|
|
2055
|
-
...
|
|
2169
|
+
...U(t.data_type, t.character_maximum_length) === void 0 ? {} : { maxLength: U(t.data_type, t.character_maximum_length) },
|
|
2056
2170
|
unique: d,
|
|
2057
2171
|
hasDefault: f !== null,
|
|
2058
2172
|
...f === null ? {} : { defaultValue: f },
|
|
2059
2173
|
...u ? { references: u } : {},
|
|
2060
|
-
...o ? { referenceStorage: ["integer", "bigint"].includes(
|
|
2174
|
+
...o ? { referenceStorage: ["integer", "bigint"].includes(ur(t.data_type, t.column_type)) ? "numeric" : "text" } : {},
|
|
2061
2175
|
...p ? { oneOf: p } : {},
|
|
2062
|
-
...
|
|
2176
|
+
...rr(t.generation_expression, /STORED/i.test(t.extra ?? "")) ?? {}
|
|
2063
2177
|
};
|
|
2064
2178
|
}), m = new Set(n.map((e) => e.source_column)), h = [];
|
|
2065
2179
|
if (o) for (let [t, n] of o) {
|
|
@@ -2086,10 +2200,10 @@ BEGIN
|
|
|
2086
2200
|
});
|
|
2087
2201
|
}
|
|
2088
2202
|
return { tables: p };
|
|
2089
|
-
}),
|
|
2203
|
+
}), pr = (e) => {
|
|
2090
2204
|
let t = e.toUpperCase();
|
|
2091
2205
|
return t.includes("INT") ? "integer" : t.includes("REAL") || t.includes("FLOA") || t.includes("DOUB") ? "real" : t.includes("BLOB") ? "bytes" : "text";
|
|
2092
|
-
},
|
|
2206
|
+
}, mr = (e) => e === 1 || e === !0, hr = (e) => T.gen(function* () {
|
|
2093
2207
|
let t = yield* e`
|
|
2094
2208
|
SELECT name, sql FROM sqlite_master
|
|
2095
2209
|
WHERE type = 'table' AND name NOT LIKE 'sqlite_%'
|
|
@@ -2103,18 +2217,18 @@ BEGIN
|
|
|
2103
2217
|
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();
|
|
2104
2218
|
for (let t of c) {
|
|
2105
2219
|
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);
|
|
2106
|
-
if (f.set(t.name, r), t.partial !== void 0 &&
|
|
2107
|
-
let n =
|
|
2220
|
+
if (f.set(t.name, r), t.partial !== void 0 && mr(t.partial)) {
|
|
2221
|
+
let n = on((yield* e`SELECT sql FROM sqlite_master WHERE type = 'index' AND name = ${t.name}`)[0]?.sql ?? "");
|
|
2108
2222
|
n !== void 0 && p.set(t.name, n);
|
|
2109
2223
|
}
|
|
2110
|
-
!p.has(t.name) &&
|
|
2224
|
+
!p.has(t.name) && mr(t.unique) && r.length === 1 && m.add(r[0]);
|
|
2111
2225
|
}
|
|
2112
2226
|
let h = o.map((e) => {
|
|
2113
|
-
let n = u.length === 1 && u[0] === e.name, r = l.get(e.name), i = r ? "reference" : n && e.name === "id" ? "id" :
|
|
2227
|
+
let n = u.length === 1 && u[0] === e.name, r = l.get(e.name), i = r ? "reference" : n && e.name === "id" ? "id" : pr(e.type), a = r ? {
|
|
2114
2228
|
table: r.table,
|
|
2115
2229
|
column: r.to,
|
|
2116
|
-
onDelete:
|
|
2117
|
-
onUpdate:
|
|
2230
|
+
onDelete: V(r.on_delete),
|
|
2231
|
+
onUpdate: V(r.on_update)
|
|
2118
2232
|
} : void 0, o = t.get(e.name);
|
|
2119
2233
|
return {
|
|
2120
2234
|
name: e.name,
|
|
@@ -2124,19 +2238,19 @@ BEGIN
|
|
|
2124
2238
|
hasDefault: e.dflt_value !== null,
|
|
2125
2239
|
...e.dflt_value === null ? {} : { defaultValue: e.dflt_value },
|
|
2126
2240
|
...a ? { references: a } : {},
|
|
2127
|
-
...r ? { referenceStorage: ["integer", "bigint"].includes(
|
|
2241
|
+
...r ? { referenceStorage: ["integer", "bigint"].includes(pr(e.type)) ? "numeric" : "text" } : {},
|
|
2128
2242
|
...o ? { oneOf: o } : {},
|
|
2129
|
-
...
|
|
2243
|
+
...rr(e.hidden === 2 || e.hidden === 3 ? "generated" : null, e.hidden === 3) ?? {}
|
|
2130
2244
|
};
|
|
2131
2245
|
}), g = new Set(s.map((e) => e.from)), _ = [];
|
|
2132
2246
|
for (let e of c) {
|
|
2133
2247
|
if (e.origin === "pk") continue;
|
|
2134
2248
|
let t = f.get(e.name) ?? [], n = p.get(e.name);
|
|
2135
|
-
n === void 0 && t.length === 1 &&
|
|
2249
|
+
n === void 0 && t.length === 1 && mr(e.unique) || (n !== void 0 || t.length !== 1 || mr(e.unique) || !g.has(t[0]) || e.name === `${i}_${t[0]}_idx`) && _.push({
|
|
2136
2250
|
name: e.name,
|
|
2137
2251
|
table: i,
|
|
2138
2252
|
columns: t,
|
|
2139
|
-
unique:
|
|
2253
|
+
unique: mr(e.unique),
|
|
2140
2254
|
...n === void 0 ? {} : { where: n }
|
|
2141
2255
|
});
|
|
2142
2256
|
}
|
|
@@ -2152,7 +2266,7 @@ BEGIN
|
|
|
2152
2266
|
});
|
|
2153
2267
|
}
|
|
2154
2268
|
return { tables: r };
|
|
2155
|
-
}),
|
|
2269
|
+
}), gr = (e) => {
|
|
2156
2270
|
switch (e.toLowerCase()) {
|
|
2157
2271
|
case "int":
|
|
2158
2272
|
case "smallint":
|
|
@@ -2174,14 +2288,14 @@ BEGIN
|
|
|
2174
2288
|
case "image": return "bytes";
|
|
2175
2289
|
default: return "text";
|
|
2176
2290
|
}
|
|
2177
|
-
},
|
|
2291
|
+
}, H = (e) => e === !0 || e === 1, _r = (e) => T.gen(function* () {
|
|
2178
2292
|
let t = yield* e`
|
|
2179
2293
|
SELECT TABLE_NAME AS table_name FROM INFORMATION_SCHEMA.TABLES
|
|
2180
2294
|
WHERE TABLE_TYPE = 'BASE TABLE' ORDER BY TABLE_NAME`, n = yield* e`
|
|
2181
2295
|
SELECT TABLE_NAME AS table_name, COLUMN_NAME AS column_name, DATA_TYPE AS data_type,
|
|
2182
2296
|
IS_NULLABLE AS is_nullable, COLUMN_DEFAULT AS column_default,
|
|
2183
2297
|
CHARACTER_MAXIMUM_LENGTH AS character_maximum_length
|
|
2184
|
-
FROM INFORMATION_SCHEMA.COLUMNS ORDER BY TABLE_NAME, ORDINAL_POSITION`, r = yield*
|
|
2298
|
+
FROM INFORMATION_SCHEMA.COLUMNS ORDER BY TABLE_NAME, ORDINAL_POSITION`, r = yield* T.orElseSucceed(e`
|
|
2185
2299
|
SELECT t.name AS table_name, c.name AS column_name, cc.definition AS definition,
|
|
2186
2300
|
cc.is_persisted AS is_persisted
|
|
2187
2301
|
FROM sys.computed_columns cc
|
|
@@ -2206,14 +2320,14 @@ BEGIN
|
|
|
2206
2320
|
JOIN sys.columns c ON c.object_id = ic.object_id AND c.column_id = ic.column_id
|
|
2207
2321
|
WHERE i.type > 0 AND ic.is_included_column = 0
|
|
2208
2322
|
ORDER BY t.name, i.name, ic.key_ordinal`, s = yield* e`
|
|
2209
|
-
SELECT t.name AS table_name, c.name AS column_name, cc.definition AS def
|
|
2323
|
+
SELECT t.name AS table_name, c.name AS column_name, cc.definition AS def,
|
|
2324
|
+
cc.name AS constraint_name, cc.is_disabled, cc.is_not_trusted
|
|
2210
2325
|
FROM sys.check_constraints cc
|
|
2211
2326
|
JOIN sys.tables t ON t.object_id = cc.parent_object_id
|
|
2212
|
-
JOIN sys.columns c ON c.object_id = cc.parent_object_id AND c.column_id = cc.parent_column_id
|
|
2213
|
-
WHERE cc.parent_column_id <> 0`, c = /* @__PURE__ */ new Map();
|
|
2327
|
+
LEFT JOIN sys.columns c ON c.object_id = cc.parent_object_id AND c.column_id = cc.parent_column_id`, c = /* @__PURE__ */ new Map();
|
|
2214
2328
|
for (let e of s) {
|
|
2215
|
-
let t =
|
|
2216
|
-
t
|
|
2329
|
+
let t = tr(e.def);
|
|
2330
|
+
t?.column === e.column_name && c.set(`${e.table_name}.${e.column_name}`, t.values);
|
|
2217
2331
|
}
|
|
2218
2332
|
let l = /* @__PURE__ */ new Map();
|
|
2219
2333
|
for (let e of n) {
|
|
@@ -2234,141 +2348,173 @@ BEGIN
|
|
|
2234
2348
|
}
|
|
2235
2349
|
let f = [];
|
|
2236
2350
|
for (let { table_name: e } of t) {
|
|
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),
|
|
2351
|
+
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), p = [], m = /* @__PURE__ */ new Set();
|
|
2238
2352
|
if (o) for (let [, e] of o) {
|
|
2239
2353
|
let t = [...e].sort((e, t) => e.key_ordinal - t.key_ordinal);
|
|
2240
|
-
if (
|
|
2241
|
-
else t[0].predicate == null &&
|
|
2354
|
+
if (H(t[0].is_primary)) for (let e of t) p.push(e.column_name);
|
|
2355
|
+
else t[0].predicate == null && H(t[0].is_unique) && t.length === 1 && m.add(t[0].column_name);
|
|
2242
2356
|
}
|
|
2243
|
-
let
|
|
2244
|
-
let n =
|
|
2357
|
+
let h = t.map((t) => {
|
|
2358
|
+
let n = p.length === 1 && p[0] === t.column_name, a = r.get(t.column_name), o = a ? "reference" : n && t.column_name === "id" ? "id" : gr(t.data_type), l = a ? {
|
|
2245
2359
|
table: a.target_table,
|
|
2246
2360
|
column: a.target_column,
|
|
2247
|
-
onDelete:
|
|
2248
|
-
onUpdate:
|
|
2249
|
-
} : void 0, u = t.column_default === null ? null :
|
|
2361
|
+
onDelete: vr(a.delete_rule),
|
|
2362
|
+
onUpdate: vr(a.update_rule)
|
|
2363
|
+
} : void 0, u = t.column_default === null ? null : yr(t.column_default), d = c.get(`${e}.${t.column_name}`), f = s.flatMap((n) => {
|
|
2364
|
+
if (n.table_name !== e || n.column_name !== null && n.column_name !== t.column_name) return [];
|
|
2365
|
+
let r = it(t.column_name, n.def);
|
|
2366
|
+
return r ? [{
|
|
2367
|
+
name: n.constraint_name,
|
|
2368
|
+
validation: r,
|
|
2369
|
+
enabled: !H(n.is_disabled),
|
|
2370
|
+
trusted: !H(n.is_not_trusted)
|
|
2371
|
+
}] : [];
|
|
2372
|
+
}).sort((e, t) => e.name.localeCompare(t.name)), h = at(f);
|
|
2250
2373
|
return {
|
|
2251
2374
|
name: t.column_name,
|
|
2252
2375
|
type: o,
|
|
2253
2376
|
nullable: t.is_nullable === "YES",
|
|
2254
|
-
...
|
|
2255
|
-
unique:
|
|
2377
|
+
...U(t.data_type, t.character_maximum_length) === void 0 ? {} : { maxLength: U(t.data_type, t.character_maximum_length) },
|
|
2378
|
+
unique: m.has(t.column_name) || n && t.column_name === "id",
|
|
2256
2379
|
hasDefault: u !== null,
|
|
2257
2380
|
...u === null ? {} : { defaultValue: u },
|
|
2258
2381
|
...l ? { references: l } : {},
|
|
2259
|
-
...a ? { referenceStorage: ["integer", "bigint"].includes(
|
|
2382
|
+
...a ? { referenceStorage: ["integer", "bigint"].includes(gr(t.data_type)) ? "numeric" : "text" } : {},
|
|
2260
2383
|
...d ? { oneOf: d } : {},
|
|
2261
|
-
...
|
|
2384
|
+
...f.length > 0 ? { jsonChecks: f } : {},
|
|
2385
|
+
...h ? { jsonValidation: h } : {},
|
|
2386
|
+
...rr(i.get(`${e}.${t.column_name}`)?.definition ?? null, H(i.get(`${e}.${t.column_name}`)?.is_persisted ?? !1)) ?? {}
|
|
2262
2387
|
};
|
|
2263
|
-
}),
|
|
2388
|
+
}), g = [];
|
|
2264
2389
|
if (o) for (let [t, n] of o) {
|
|
2265
2390
|
let r = [...n].sort((e, t) => e.key_ordinal - t.key_ordinal);
|
|
2266
|
-
if (
|
|
2391
|
+
if (H(r[0].is_primary)) continue;
|
|
2267
2392
|
let i = r[0].predicate ?? void 0;
|
|
2268
|
-
i === void 0 && r.length === 1 &&
|
|
2393
|
+
i === void 0 && r.length === 1 && H(r[0].is_unique) || (i !== void 0 || r.length !== 1 || H(r[0].is_unique) || !a.has(r[0].column_name) || t === `${e}_${r[0].column_name}_idx`) && g.push({
|
|
2269
2394
|
name: t,
|
|
2270
2395
|
table: e,
|
|
2271
2396
|
columns: r.map((e) => e.column_name),
|
|
2272
|
-
unique:
|
|
2397
|
+
unique: H(r[0].is_unique),
|
|
2273
2398
|
...i === void 0 ? {} : { where: i }
|
|
2274
2399
|
});
|
|
2275
2400
|
}
|
|
2276
|
-
|
|
2401
|
+
p.length > 0 && g.push({
|
|
2277
2402
|
name: `${e}_pkey`,
|
|
2278
2403
|
table: e,
|
|
2279
|
-
columns:
|
|
2404
|
+
columns: p,
|
|
2280
2405
|
unique: !0
|
|
2281
2406
|
}), f.push({
|
|
2282
2407
|
name: e,
|
|
2283
|
-
columns:
|
|
2284
|
-
indexes:
|
|
2408
|
+
columns: h,
|
|
2409
|
+
indexes: g
|
|
2285
2410
|
});
|
|
2286
2411
|
}
|
|
2287
2412
|
return { tables: f };
|
|
2288
|
-
}),
|
|
2413
|
+
}), vr = (e) => {
|
|
2289
2414
|
switch (e.toUpperCase().replace(/_/g, " ")) {
|
|
2290
2415
|
case "CASCADE": return "cascade";
|
|
2291
2416
|
case "SET NULL": return "setNull";
|
|
2292
2417
|
case "SET DEFAULT": return "noAction";
|
|
2293
2418
|
default: return "noAction";
|
|
2294
2419
|
}
|
|
2295
|
-
},
|
|
2420
|
+
}, yr = (e) => {
|
|
2296
2421
|
let t = e.trim();
|
|
2297
2422
|
for (; t.startsWith("(") && t.endsWith(")");) t = t.slice(1, -1).trim();
|
|
2298
2423
|
return t.startsWith("N'") && t.endsWith("'") ? t = t.slice(2, -1) : t.startsWith("'") && t.endsWith("'") && (t = t.slice(1, -1)), t;
|
|
2299
|
-
},
|
|
2424
|
+
}, br = /* @__PURE__ */ new Set([
|
|
2300
2425
|
"character varying",
|
|
2301
2426
|
"varchar",
|
|
2302
2427
|
"nvarchar",
|
|
2303
2428
|
"char",
|
|
2304
2429
|
"character",
|
|
2305
2430
|
"nchar"
|
|
2306
|
-
]),
|
|
2307
|
-
if (!
|
|
2431
|
+
]), U = (e, t) => {
|
|
2432
|
+
if (!br.has(e.toLowerCase())) return;
|
|
2308
2433
|
let n = Number(t);
|
|
2309
2434
|
if (!(!Number.isFinite(n) || n <= 0)) return n;
|
|
2310
|
-
},
|
|
2311
|
-
mysql: () =>
|
|
2312
|
-
mssql: () =>
|
|
2313
|
-
sqlite: () =>
|
|
2314
|
-
orElse: () =>
|
|
2315
|
-
}).pipe(
|
|
2435
|
+
}, xr = /* @__PURE__ */ new Set([A]), Sr = (e) => e.onDialectOrElse({
|
|
2436
|
+
mysql: () => fr(e),
|
|
2437
|
+
mssql: () => _r(e),
|
|
2438
|
+
sqlite: () => hr(e),
|
|
2439
|
+
orElse: () => lr(e)
|
|
2440
|
+
}).pipe(T.map((e) => ({
|
|
2316
2441
|
...e,
|
|
2317
|
-
tables: e.tables.filter((e) => !
|
|
2318
|
-
}))),
|
|
2319
|
-
let t =
|
|
2320
|
-
return t === void 0 ?
|
|
2321
|
-
}),
|
|
2442
|
+
tables: e.tables.filter((e) => !xr.has(e.name))
|
|
2443
|
+
}))), Cr = (e) => /mariadb/i.test(e) ? "mariadb" : "mysql", wr = /* @__PURE__ */ new WeakMap(), Tr = (e) => T.suspend(() => {
|
|
2444
|
+
let t = wr.get(e);
|
|
2445
|
+
return t === void 0 ? Er(e).pipe(T.tap((t) => T.sync(() => wr.set(e, t)))) : T.succeed(t);
|
|
2446
|
+
}), Er = (e) => e.unsafe("SELECT VERSION() AS v").pipe(T.map((e) => {
|
|
2322
2447
|
let t = e[0]?.v;
|
|
2323
|
-
return typeof t == "string" ?
|
|
2324
|
-
}),
|
|
2448
|
+
return typeof t == "string" ? Cr(t) : "mysql";
|
|
2449
|
+
}), T.catchAll(() => T.succeed("mysql"))), Dr = (e) => {
|
|
2325
2450
|
let t = e;
|
|
2326
2451
|
for (let e = 0; e < 6 && typeof t == "object" && t; e++) {
|
|
2327
2452
|
let e = t;
|
|
2328
2453
|
if (typeof e.errno == "number") return e.errno;
|
|
2329
2454
|
t = e.cause;
|
|
2330
2455
|
}
|
|
2331
|
-
},
|
|
2456
|
+
}, Or = (e) => {
|
|
2332
2457
|
let t = [], n = e;
|
|
2333
2458
|
for (let e = 0; e < 6 && typeof n == "object" && n; e++) {
|
|
2334
2459
|
let e = n;
|
|
2335
2460
|
typeof e.message == "string" && t.push(e.message), n = e.cause;
|
|
2336
2461
|
}
|
|
2337
2462
|
return t.join(" | ");
|
|
2338
|
-
},
|
|
2463
|
+
}, kr = (e, t) => {
|
|
2339
2464
|
if (t.length === 0) return !1;
|
|
2340
|
-
let n =
|
|
2465
|
+
let n = Dr(e), r = Or(e);
|
|
2341
2466
|
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)));
|
|
2342
|
-
},
|
|
2467
|
+
}, Ar = {
|
|
2343
2468
|
why: "mysql has no CREATE INDEX IF NOT EXISTS; 1061 is exactly that condition",
|
|
2344
2469
|
errno: [1061]
|
|
2345
|
-
},
|
|
2470
|
+
}, jr = {
|
|
2346
2471
|
why: "mysql has no DROP COLUMN IF EXISTS; 1091 is exactly that condition",
|
|
2347
2472
|
errno: [1091]
|
|
2348
|
-
},
|
|
2473
|
+
}, Mr = {
|
|
2349
2474
|
why: "sqlite has no DROP COLUMN IF EXISTS, and reports the absent column only in the message",
|
|
2350
2475
|
messageIncludes: ["no such column"]
|
|
2351
|
-
},
|
|
2476
|
+
}, Nr = {
|
|
2352
2477
|
why: "mysql/mariadb DROP CONSTRAINT has no portable IF EXISTS; 1091 / 3940 are exactly \"already gone\"",
|
|
2353
2478
|
errno: [1091, 3940]
|
|
2354
|
-
},
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2479
|
+
}, Pr = (e, t) => T.suspend(() => {
|
|
2480
|
+
let n;
|
|
2481
|
+
return e.withTransaction(t.pipe(T.tapErrorCause((e) => T.sync(() => {
|
|
2482
|
+
n = e;
|
|
2483
|
+
})))).pipe(T.catchAllCause((e) => T.failCause(n !== void 0 && !ee.equals(n, e) ? w.sequential(n, e) : e)));
|
|
2484
|
+
}), Fr = (e, t, n) => {
|
|
2485
|
+
let r = e.match(/'(?:''|[^'])*'|\[(?:\]\]|[^\]])*\]|\s+|[^'\[\s]+/g) ?? [];
|
|
2486
|
+
if (r.join("") !== e || r.some((e) => !e.startsWith("'") && !e.startsWith("[") && /"|\/\*|--/.test(e))) throw Error("Cannot safely rename CHECK: unsupported catalog SQL; use an explicit migration");
|
|
2487
|
+
let i = r.map((e, t) => ({
|
|
2488
|
+
value: e,
|
|
2489
|
+
index: t
|
|
2490
|
+
})).filter((e) => e.value.trim() !== ""), a = 0;
|
|
2491
|
+
for (let e = 0; e < i.length; e++) {
|
|
2492
|
+
let s = i[e];
|
|
2493
|
+
if (s.value !== o(t, "mssql")) continue;
|
|
2494
|
+
let c = i[e - 1]?.value ?? "", l = i[e + 1]?.value ?? "";
|
|
2495
|
+
if (c.endsWith(".") || l.startsWith(".") || l.startsWith("(")) throw Error(`Cannot safely rename CHECK reference '${t}': qualified or callable identifier; use an explicit migration`);
|
|
2496
|
+
r[s.index] = o(n, "mssql"), a++;
|
|
2497
|
+
}
|
|
2498
|
+
if (a === 0 || r.join("").length === 0) throw Error(`Cannot safely rename CHECK reference '${t}': no exact catalog column token; use an explicit migration`);
|
|
2499
|
+
return r.join("");
|
|
2500
|
+
}, W = (e, t) => e.onDialectOrElse({
|
|
2501
|
+
mysql: () => T.succeed(t.replace("T", " ").replace("Z", "")),
|
|
2502
|
+
orElse: () => T.succeed(t)
|
|
2503
|
+
}), Ir = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, Lr = (e) => e.type === "text" && (e.hasDefault && e.defaultValue !== void 0 || e.oneOf !== void 0 && e.oneOf.length > 0), Rr = (e, t) => {
|
|
2504
|
+
if ((e.type !== "text" || e.maxLength === void 0) && !Lr(e) && !e.spatial && e.type !== "vector" && e.type !== "array" && e.type !== "enum") return;
|
|
2359
2505
|
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;
|
|
2360
2506
|
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.`);
|
|
2361
|
-
return
|
|
2362
|
-
},
|
|
2363
|
-
let t =
|
|
2364
|
-
return t === void 0 ?
|
|
2365
|
-
},
|
|
2507
|
+
return N(e, t);
|
|
2508
|
+
}, zr = (e) => {
|
|
2509
|
+
let t = Rr(e, "postgres");
|
|
2510
|
+
return t === void 0 ? Br(e) : t;
|
|
2511
|
+
}, Br = (e) => {
|
|
2366
2512
|
switch (e.type) {
|
|
2367
2513
|
case "id": return "text";
|
|
2368
2514
|
case "text": return "text";
|
|
2369
2515
|
case "integer": return "integer";
|
|
2370
2516
|
case "real": return "double precision";
|
|
2371
|
-
case "decimal": return
|
|
2517
|
+
case "decimal": return Ir(e, "NUMERIC");
|
|
2372
2518
|
case "bigint": return "bigint";
|
|
2373
2519
|
case "boolean": return "boolean";
|
|
2374
2520
|
case "timestamp": return "timestamptz";
|
|
@@ -2382,15 +2528,15 @@ BEGIN
|
|
|
2382
2528
|
case "interval": return "interval";
|
|
2383
2529
|
case "raw": return e.rawDdl ?? "text";
|
|
2384
2530
|
}
|
|
2385
|
-
},
|
|
2386
|
-
let t =
|
|
2531
|
+
}, Vr = (e) => {
|
|
2532
|
+
let t = Rr(e, "mariadb");
|
|
2387
2533
|
if (t !== void 0) return t;
|
|
2388
2534
|
switch (e.type) {
|
|
2389
2535
|
case "id": return "VARCHAR(64)";
|
|
2390
2536
|
case "text": return "LONGTEXT";
|
|
2391
2537
|
case "integer": return "INT";
|
|
2392
2538
|
case "real": return "DOUBLE";
|
|
2393
|
-
case "decimal": return
|
|
2539
|
+
case "decimal": return Ir(e, "DECIMAL");
|
|
2394
2540
|
case "bigint": return "BIGINT";
|
|
2395
2541
|
case "boolean": return "TINYINT(1)";
|
|
2396
2542
|
case "timestamp": return "DATETIME(6)";
|
|
@@ -2404,64 +2550,68 @@ BEGIN
|
|
|
2404
2550
|
case "interval": return "BIGINT";
|
|
2405
2551
|
case "raw": return e.rawDdl ?? "LONGTEXT";
|
|
2406
2552
|
}
|
|
2407
|
-
},
|
|
2553
|
+
}, G = (e) => `"${e}"`, K = (e) => `\`${e.replace(/`/g, "``")}\``, Hr = (e) => e === "mariadb" ? "IF NOT EXISTS " : "", Ur = (e, t, n = !0) => `ALTER TABLE ${t(e.table)} DROP COLUMN ${n ? "IF EXISTS " : ""}${t(e.column)};`, Wr = (e, t = "mariadb") => `ALTER TABLE ${K(e.table)} DROP COLUMN ${t === "mariadb" ? "IF EXISTS " : ""}${K(e.column)}, ALGORITHM=COPY;`, Gr = (e, t) => `ALTER TABLE ${t(e.table)} RENAME COLUMN ${t(e.from)} TO ${t(e.to)};`, Kr = (e, t, n) => `ALTER TABLE ${n(e.table)} RENAME COLUMN ${n(e.column)} TO ${n(`${e.column}${Si(t)}`)};`, qr = (e, t, n) => e.hasDefault && e.defaultValue !== void 0 ? `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} SET ${Yr(e, n)};` : `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} DROP DEFAULT;`, Jr = (e, t) => {
|
|
2408
2554
|
let { defaultFactory: n, ...r } = e;
|
|
2409
|
-
return
|
|
2555
|
+
return N(e, t) !== N({
|
|
2410
2556
|
...r,
|
|
2411
2557
|
hasDefault: !1
|
|
2412
2558
|
}, t);
|
|
2413
|
-
},
|
|
2559
|
+
}, Yr = (e, t) => {
|
|
2414
2560
|
let n = t(e.defaultValue);
|
|
2415
2561
|
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.`);
|
|
2416
2562
|
return n;
|
|
2417
|
-
},
|
|
2418
|
-
let r =
|
|
2419
|
-
return r ?
|
|
2420
|
-
},
|
|
2421
|
-
let r = n ?? e.nullable, i =
|
|
2563
|
+
}, q = (e, t, n) => e.find((e) => e.tableName === t)?.fields[n], Xr = (e, t, n) => {
|
|
2564
|
+
let r = q(e, t, n);
|
|
2565
|
+
return r ? hn(n, r) : void 0;
|
|
2566
|
+
}, Zr = (e, t, n) => {
|
|
2567
|
+
let r = n ?? e.nullable, i = ft(e, "mariadb");
|
|
2422
2568
|
return [
|
|
2423
|
-
|
|
2424
|
-
|
|
2569
|
+
K(t),
|
|
2570
|
+
N(e, "mariadb"),
|
|
2425
2571
|
r ? null : "NOT NULL",
|
|
2426
2572
|
i
|
|
2427
2573
|
].filter(Boolean).join(" ");
|
|
2428
|
-
},
|
|
2574
|
+
}, Qr = (e, t) => e == null ? null : Array.isArray(e) ? $r(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" ? P(e, "mariadb") : null, $r = (e, t, n) => pt(e, t ?? { type: "json" }, n), ei = (e, t) => e == null ? null : Array.isArray(e) ? $r(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" ? P(e, "postgres") : null, ti = (e, t) => {
|
|
2429
2575
|
if (!e.generatedAs) return null;
|
|
2430
2576
|
let { expr: n, stored: r } = e.generatedAs;
|
|
2431
2577
|
return t === "postgres" ? `GENERATED ALWAYS AS (${n}) STORED` : t === "mssql" ? `AS (${n})${r ? " PERSISTED" : ""}` : `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
|
|
2432
|
-
},
|
|
2433
|
-
if (e.type === "id" && e.idScheme?.kind === "numeric") return
|
|
2434
|
-
let
|
|
2435
|
-
if (
|
|
2436
|
-
let
|
|
2437
|
-
if (e.type === "id" &&
|
|
2438
|
-
let t =
|
|
2439
|
-
t &&
|
|
2440
|
-
}
|
|
2441
|
-
return e.references && (
|
|
2578
|
+
}, ni = (e, t = !1) => {
|
|
2579
|
+
if (e.type === "id" && e.idScheme?.kind === "numeric") return F(e.name, "postgres");
|
|
2580
|
+
let n = ti(e, "postgres");
|
|
2581
|
+
if (n) return `${G(e.name)} ${zr(e)} ${n}`;
|
|
2582
|
+
let r = [G(e.name), zr(e)];
|
|
2583
|
+
if (e.type === "id" && !t && r.push("PRIMARY KEY"), e.nullable || r.push("NOT NULL"), e.unique && e.type !== "id" && r.push("UNIQUE"), e.hasDefault) {
|
|
2584
|
+
let t = ei(e.defaultValue, e);
|
|
2585
|
+
t && r.push(t);
|
|
2586
|
+
}
|
|
2587
|
+
return e.references && (r.push(`REFERENCES ${G(e.references.table)} (${G(e.references.column)})`), e.references.onDelete && r.push(`ON DELETE ${{
|
|
2442
2588
|
cascade: "CASCADE",
|
|
2443
2589
|
restrict: "RESTRICT",
|
|
2444
2590
|
setNull: "SET NULL",
|
|
2445
2591
|
noAction: "NO ACTION"
|
|
2446
|
-
}[e.references.onDelete]}`)),
|
|
2447
|
-
},
|
|
2448
|
-
let t = e.columns.map((
|
|
2449
|
-
for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(
|
|
2592
|
+
}[e.references.onDelete]}`)), r.join(" ");
|
|
2593
|
+
}, ri = (e) => (e.primaryKey?.length ?? 0) > 0, ii = (e, t) => e.primaryKey && e.primaryKey.length > 0 ? `,\n PRIMARY KEY (${e.primaryKey.map(t).join(", ")})` : "", ai = (e) => {
|
|
2594
|
+
let t = e.columns.map((t) => ` ${ni(t, ri(e))}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${G(e.table)} (\n${t}${ii(e, G)}\n)`];
|
|
2595
|
+
for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(ki({
|
|
2596
|
+
kind: "add-index",
|
|
2597
|
+
table: e.table,
|
|
2598
|
+
index: t
|
|
2599
|
+
}, !1));
|
|
2450
2600
|
return n;
|
|
2451
|
-
},
|
|
2452
|
-
let t =
|
|
2601
|
+
}, oi = 191, si = (e) => {
|
|
2602
|
+
let t = Vr(e).toUpperCase();
|
|
2453
2603
|
return t.endsWith("TEXT") || t.endsWith("BLOB");
|
|
2454
|
-
},
|
|
2455
|
-
if (e.type === "id" && e.idScheme?.kind === "numeric") return
|
|
2456
|
-
let
|
|
2457
|
-
if (
|
|
2458
|
-
let
|
|
2459
|
-
if (e.type === "id" &&
|
|
2460
|
-
let t =
|
|
2461
|
-
t &&
|
|
2462
|
-
}
|
|
2463
|
-
return
|
|
2464
|
-
},
|
|
2604
|
+
}, ci = (e, t = !1) => {
|
|
2605
|
+
if (e.type === "id" && e.idScheme?.kind === "numeric") return F(e.name, "mariadb");
|
|
2606
|
+
let n = ti(e, "mariadb");
|
|
2607
|
+
if (n) return `${K(e.name)} ${Vr(e)} ${n}`;
|
|
2608
|
+
let r = [K(e.name), Vr(e)];
|
|
2609
|
+
if (e.type === "id" && !t && r.push("PRIMARY KEY"), e.nullable || r.push("NOT NULL"), e.unique && e.type !== "id" && !si(e) && r.push("UNIQUE"), e.hasDefault) {
|
|
2610
|
+
let t = Qr(e.defaultValue, e);
|
|
2611
|
+
t && r.push(t);
|
|
2612
|
+
}
|
|
2613
|
+
return r.join(" ");
|
|
2614
|
+
}, li = (e) => e.columns.flatMap((t) => {
|
|
2465
2615
|
if (!t.references) return [];
|
|
2466
2616
|
let n = t.references.onDelete ? ` ON DELETE ${{
|
|
2467
2617
|
cascade: "CASCADE",
|
|
@@ -2469,28 +2619,28 @@ BEGIN
|
|
|
2469
2619
|
setNull: "SET NULL",
|
|
2470
2620
|
noAction: "NO ACTION"
|
|
2471
2621
|
}[t.references.onDelete]}` : "";
|
|
2472
|
-
return [` CONSTRAINT ${
|
|
2473
|
-
}),
|
|
2474
|
-
for (let n of e.indexes)
|
|
2622
|
+
return [` CONSTRAINT ${K(`${e.table}_${t.name}_fkey`)} FOREIGN KEY (${K(t.name)}) REFERENCES ${K(t.references.table)} (${K(t.references.column)})${n}`];
|
|
2623
|
+
}), ui = (e, t = "mariadb") => {
|
|
2624
|
+
for (let n of e.indexes) ji(n, t);
|
|
2475
2625
|
let n = new Map(e.columns.map((e) => [e.name, e])), r = (e) => {
|
|
2476
|
-
let t =
|
|
2477
|
-
return t === void 0 ?
|
|
2478
|
-
}, i = e.columns.map((
|
|
2479
|
-
for (let n of e.columns) n.unique && n.type !== "id" &&
|
|
2480
|
-
for (let n of e.indexes) n.name !== `${e.table}_pkey` && s.push(`CREATE ${n.unique ? "UNIQUE " : ""}INDEX ${
|
|
2626
|
+
let t = Ti(n.get(e));
|
|
2627
|
+
return t === void 0 ? K(e) : `${K(e)}(${t})`;
|
|
2628
|
+
}, i = e.columns.map((t) => ` ${ci(t, ri(e))}`).join(",\n"), a = li(e), o = a.length > 0 ? `${i},\n${a.join(",\n")}` : i, s = [`CREATE TABLE IF NOT EXISTS ${K(e.table)} (\n${o}${ii(e, r)}\n)`];
|
|
2629
|
+
for (let n of e.columns) n.unique && n.type !== "id" && si(n) && s.push(`CREATE UNIQUE INDEX ${Hr(t)}${K(`${e.table}_${n.name}_key`)} ON ${K(e.table)} (${r(n.name)})`);
|
|
2630
|
+
for (let n of e.indexes) n.name !== `${e.table}_pkey` && s.push(`CREATE ${n.unique ? "UNIQUE " : ""}INDEX ${Hr(t)}${K(n.name)} ON ${K(e.table)} (${n.columns.map(r).join(", ")})`);
|
|
2481
2631
|
return s;
|
|
2482
|
-
},
|
|
2632
|
+
}, di = {
|
|
2483
2633
|
cascade: "CASCADE",
|
|
2484
2634
|
restrict: "RESTRICT",
|
|
2485
2635
|
setNull: "SET NULL",
|
|
2486
2636
|
noAction: "NO ACTION"
|
|
2487
|
-
},
|
|
2637
|
+
}, fi = {
|
|
2488
2638
|
cascade: "CASCADE",
|
|
2489
2639
|
restrict: "NO ACTION",
|
|
2490
2640
|
setNull: "SET NULL",
|
|
2491
2641
|
noAction: "NO ACTION"
|
|
2492
|
-
},
|
|
2493
|
-
let t =
|
|
2642
|
+
}, pi = (e) => {
|
|
2643
|
+
let t = Rr(e, "sqlite");
|
|
2494
2644
|
if (t !== void 0) return t;
|
|
2495
2645
|
switch (e.type) {
|
|
2496
2646
|
case "integer":
|
|
@@ -2502,60 +2652,60 @@ BEGIN
|
|
|
2502
2652
|
case "bytes": return "BLOB";
|
|
2503
2653
|
default: return "TEXT";
|
|
2504
2654
|
}
|
|
2505
|
-
},
|
|
2506
|
-
if (e.type === "id" && e.idScheme?.kind === "numeric") return
|
|
2507
|
-
let
|
|
2508
|
-
if (
|
|
2509
|
-
let
|
|
2510
|
-
if (e.type === "id" &&
|
|
2511
|
-
let t =
|
|
2512
|
-
t &&
|
|
2655
|
+
}, mi = (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" ? P(e, "sqlite") : null, hi = (e, t = !1) => {
|
|
2656
|
+
if (e.type === "id" && e.idScheme?.kind === "numeric") return F(e.name, "sqlite");
|
|
2657
|
+
let n = ti(e, "sqlite");
|
|
2658
|
+
if (n) return `${G(e.name)} ${pi(e)} ${n}`;
|
|
2659
|
+
let r = [G(e.name), pi(e)];
|
|
2660
|
+
if (e.type === "id" && !t && r.push("PRIMARY KEY"), e.nullable || r.push("NOT NULL"), e.unique && e.type !== "id" && r.push("UNIQUE"), e.hasDefault) {
|
|
2661
|
+
let t = mi(e.defaultValue, "CURRENT_TIMESTAMP");
|
|
2662
|
+
t && r.push(t);
|
|
2513
2663
|
}
|
|
2514
|
-
if (e.references && (
|
|
2664
|
+
if (e.references && (r.push(`REFERENCES ${G(e.references.table)} (${G(e.references.column)})`), e.references.onDelete && r.push(`ON DELETE ${di[e.references.onDelete]}`)), e.oneOf && e.oneOf.length > 0) {
|
|
2515
2665
|
let t = e.oneOf.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
|
|
2516
|
-
|
|
2666
|
+
r.push(`CHECK (${G(e.name)} IN (${t}))`);
|
|
2517
2667
|
}
|
|
2518
|
-
return
|
|
2519
|
-
},
|
|
2520
|
-
let t = e.columns.map((
|
|
2521
|
-
for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${
|
|
2668
|
+
return r.join(" ");
|
|
2669
|
+
}, gi = (e) => {
|
|
2670
|
+
let t = e.columns.map((t) => ` ${hi(t, ri(e))}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${G(e.table)} (\n${t}${ii(e, G)}\n)`];
|
|
2671
|
+
for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${G(t.name)} ON ${G(e.table)} (${t.columns.map(G).join(", ")})${Oi(t)}`);
|
|
2522
2672
|
return n;
|
|
2523
|
-
},
|
|
2673
|
+
}, J = (e, t) => {
|
|
2524
2674
|
let n = t.find((t) => t.tableName === e);
|
|
2525
2675
|
if (!n) return [];
|
|
2526
|
-
let r =
|
|
2527
|
-
...
|
|
2676
|
+
let r = z([n]).tables[0], i = `${e}__voltro_rebuild`, a = r.columns.map((e) => G(e.name)).join(", "), o = [
|
|
2677
|
+
...gi({
|
|
2528
2678
|
kind: "create-table",
|
|
2529
2679
|
table: i,
|
|
2530
2680
|
columns: r.columns,
|
|
2531
2681
|
indexes: [],
|
|
2532
2682
|
...r.primaryKey ? { primaryKey: r.primaryKey } : {}
|
|
2533
2683
|
}),
|
|
2534
|
-
`INSERT INTO ${
|
|
2535
|
-
`DROP TABLE ${
|
|
2536
|
-
`ALTER TABLE ${
|
|
2684
|
+
`INSERT INTO ${G(i)} (${a}) SELECT ${a} FROM ${G(e)}`,
|
|
2685
|
+
`DROP TABLE ${G(e)}`,
|
|
2686
|
+
`ALTER TABLE ${G(i)} RENAME TO ${G(e)}`
|
|
2537
2687
|
];
|
|
2538
|
-
for (let t of r.indexes) t.name !== `${e}_pkey` && o.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${
|
|
2688
|
+
for (let t of r.indexes) t.name !== `${e}_pkey` && o.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${G(t.name)} ON ${G(e)} (${t.columns.map(G).join(", ")})${Oi(t)}`);
|
|
2539
2689
|
return o;
|
|
2540
|
-
},
|
|
2690
|
+
}, _i = (e, t, n, r) => {
|
|
2541
2691
|
let i = r ?? e.nullable;
|
|
2542
|
-
return `ALTER TABLE ${
|
|
2543
|
-
},
|
|
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 ${
|
|
2692
|
+
return `ALTER TABLE ${Y(n)} ALTER COLUMN ${Y(t)} ${N(e, "mssql")} ${i ? "NULL" : "NOT NULL"};`;
|
|
2693
|
+
}, vi = (e, t) => {
|
|
2694
|
+
let n = `DECLARE @dc sysname; SELECT @dc = dc.name FROM sys.default_constraints dc JOIN sys.columns col ON col.object_id = dc.parent_object_id AND col.column_id = dc.parent_column_id WHERE dc.parent_object_id = OBJECT_ID(N'${e.table.replace(/'/g, "''")}') AND col.name = N'${e.column.replace(/'/g, "''")}'; IF @dc IS NOT NULL EXEC(N'ALTER TABLE ${Y(e.table)} DROP CONSTRAINT [' + @dc + ']');` + (t ? ` ${t}` : "");
|
|
2545
2695
|
if (!e.hasDefault) return n;
|
|
2546
|
-
let r =
|
|
2696
|
+
let r = mi(e.defaultValue, "SYSUTCDATETIME()");
|
|
2547
2697
|
if (!r) return n;
|
|
2548
2698
|
let i = r.replace(/^DEFAULT\s+/i, "");
|
|
2549
|
-
return `${n} ALTER TABLE ${
|
|
2550
|
-
},
|
|
2551
|
-
let t =
|
|
2699
|
+
return `${n} ALTER TABLE ${Y(e.table)} ADD DEFAULT ${i} FOR ${Y(e.column)};`;
|
|
2700
|
+
}, Y = (e) => `[${e.replace(/]/g, "]]")}]`, yi = (e) => {
|
|
2701
|
+
let t = Rr(e, "mssql");
|
|
2552
2702
|
if (t !== void 0) return t;
|
|
2553
2703
|
switch (e.type) {
|
|
2554
2704
|
case "id": return "NVARCHAR(64)";
|
|
2555
2705
|
case "reference": return e.referenceStorage === "numeric" ? "BIGINT" : "NVARCHAR(64)";
|
|
2556
2706
|
case "integer": return "INT";
|
|
2557
2707
|
case "real": return "FLOAT";
|
|
2558
|
-
case "decimal": return
|
|
2708
|
+
case "decimal": return Ir(e, "DECIMAL");
|
|
2559
2709
|
case "bigint": return "BIGINT";
|
|
2560
2710
|
case "boolean": return "BIT";
|
|
2561
2711
|
case "timestamp": return "DATETIME2(6)";
|
|
@@ -2563,61 +2713,68 @@ BEGIN
|
|
|
2563
2713
|
case "bytes": return "VARBINARY(MAX)";
|
|
2564
2714
|
default: return "NVARCHAR(MAX)";
|
|
2565
2715
|
}
|
|
2566
|
-
},
|
|
2567
|
-
if (e.type === "id" && e.idScheme?.kind === "numeric") return
|
|
2568
|
-
let
|
|
2569
|
-
if (
|
|
2570
|
-
let
|
|
2571
|
-
if (e.type === "id" &&
|
|
2572
|
-
let t =
|
|
2573
|
-
t &&
|
|
2574
|
-
}
|
|
2575
|
-
return e.references && (
|
|
2576
|
-
},
|
|
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((
|
|
2716
|
+
}, bi = (e, t, n = !1) => {
|
|
2717
|
+
if (e.type === "id" && e.idScheme?.kind === "numeric") return F(e.name, "mssql");
|
|
2718
|
+
let r = e.type === "text" && t?.has(e.name) ? "NVARCHAR(450)" : yi(e), i = ti(e, "mssql");
|
|
2719
|
+
if (i) return `${Y(e.name)} ${i}`;
|
|
2720
|
+
let a = [Y(e.name), r];
|
|
2721
|
+
if (e.type === "json" && a.push(`CHECK ${nt(Y(e.name))}`), e.type === "array" && a.push(`CHECK (${Y(e.name)} IS NULL OR ISJSON(${Y(e.name)}) = 1)`), e.type === "id" && !n && a.push("PRIMARY KEY"), e.nullable || a.push("NOT NULL"), e.unique && e.type !== "id" && a.push("UNIQUE"), e.hasDefault) {
|
|
2722
|
+
let t = mi(e.defaultValue, "SYSUTCDATETIME()");
|
|
2723
|
+
t && a.push(t);
|
|
2724
|
+
}
|
|
2725
|
+
return e.references && (a.push(`REFERENCES ${Y(e.references.table)} (${Y(e.references.column)})`), e.references.onDelete && a.push(`ON DELETE ${fi[e.references.onDelete]}`)), a.join(" ");
|
|
2726
|
+
}, xi = (e) => {
|
|
2727
|
+
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((t) => ` ${bi(t, n, ri(e))}`).join(",\n"), i = `CREATE TABLE ${Y(e.table)} (\n${r}${ii(e, Y)}\n)`, a = [`IF OBJECT_ID(N'${t(e.table)}', N'U') IS NULL EXEC(N'${t(i)}')`];
|
|
2578
2728
|
for (let n of e.indexes) {
|
|
2579
2729
|
if (n.name === `${e.table}_pkey`) continue;
|
|
2580
|
-
let r = `CREATE ${n.unique ? "UNIQUE " : ""}INDEX ${
|
|
2730
|
+
let r = `CREATE ${n.unique ? "UNIQUE " : ""}INDEX ${Y(n.name)} ON ${Y(e.table)} (${n.columns.map(Y).join(", ")})${Oi(n)}`;
|
|
2581
2731
|
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)}')`);
|
|
2582
2732
|
}
|
|
2583
2733
|
return a;
|
|
2584
|
-
},
|
|
2585
|
-
let r = `${e.table}${
|
|
2734
|
+
}, Si = (e) => `__dropped_${e.replace(/[-:T.Z]/g, "").slice(0, 14)}`, Ci = (e, t) => `DROP TABLE IF EXISTS ${t(e.table)};`, wi = (e, t, n) => {
|
|
2735
|
+
let r = `${e.table}${Si(t)}`;
|
|
2586
2736
|
return `ALTER TABLE ${n(e.table)} RENAME TO ${n(r)};`;
|
|
2587
|
-
},
|
|
2588
|
-
if (e === void 0 || !
|
|
2737
|
+
}, Ti = (e) => {
|
|
2738
|
+
if (e === void 0 || !si(e)) return;
|
|
2589
2739
|
let t = typeof e.maxLength == "number" && e.maxLength > 0 ? e.maxLength : void 0;
|
|
2590
|
-
return t === void 0 ?
|
|
2591
|
-
},
|
|
2592
|
-
let r =
|
|
2593
|
-
return r === void 0 ?
|
|
2594
|
-
},
|
|
2740
|
+
return t === void 0 ? oi : Math.min(oi, t);
|
|
2741
|
+
}, Ei = (e, t, n) => {
|
|
2742
|
+
let r = Ti(Xr(e, t, n));
|
|
2743
|
+
return r === void 0 ? K(n) : `${K(n)}(${r})`;
|
|
2744
|
+
}, Di = (e) => e.startsWith("(") ? e : G(e), Oi = (e) => e.where === void 0 ? "" : ` WHERE ${e.where}`, ki = (e, t) => {
|
|
2745
|
+
let n = de(e.index.kind, e.index.kindOptions), r = e.index.columns.map(Di);
|
|
2746
|
+
if (n.opclass !== void 0) {
|
|
2747
|
+
if (r.length !== 1) throw Error("HNSW index requires exactly one column");
|
|
2748
|
+
r[0] = `${r[0]} ${n.opclass}`;
|
|
2749
|
+
}
|
|
2750
|
+
return `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX ${t ? "CONCURRENTLY " : ""}IF NOT EXISTS ${G(e.index.name)} ON ${G(e.table)}${n.using} (${r.join(", ")})${n.withSuffix}${Oi(e.index)};`;
|
|
2751
|
+
}, Ai = (e, t, n = "mariadb") => (ji(e.index, n), `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX ${Hr(n)}${K(e.index.name)} ON ${K(e.table)} (${e.index.columns.map((n) => Ei(t, e.table, n)).join(", ")});`), ji = (e, t) => {
|
|
2595
2752
|
if (e.where !== void 0) throw Error(`Partial index '${e.name}' is not supported by ${t}; uniqueActive must be lowered before applying the plan.`);
|
|
2596
|
-
},
|
|
2753
|
+
}, Mi = (e) => `DROP INDEX IF EXISTS ${G(e.index)};`, Ni = (e) => `DROP INDEX ${K(e.index)} ON ${K(e.table)};`, Pi = (e) => `DROP INDEX IF EXISTS ${Y(e.index)} ON ${Y(e.table)};`, Fi = (e, t) => `ALTER TABLE ${t(e.from)} RENAME TO ${t(e.to)};`, Ii = (e) => {
|
|
2597
2754
|
let t = (e) => e.replace(/'/g, "''");
|
|
2598
2755
|
return `EXEC sp_rename N'${t(e.from)}', N'${t(e.to)}';`;
|
|
2599
|
-
},
|
|
2756
|
+
}, Li = (e) => `ALTER INDEX ${G(e.from)} RENAME TO ${G(e.to)};`, Ri = (e) => `ALTER TABLE ${K(e.table)} RENAME INDEX ${K(e.from)} TO ${K(e.to)};`, zi = (e) => {
|
|
2600
2757
|
let t = (e) => e.replace(/'/g, "''");
|
|
2601
2758
|
return `EXEC sp_rename N'${t(e.table)}.${t(e.from)}', N'${t(e.to)}', N'INDEX';`;
|
|
2602
|
-
},
|
|
2603
|
-
let t = (e) => e.replace(/'/g, "''"), n = `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX ${
|
|
2759
|
+
}, Bi = (e) => {
|
|
2760
|
+
let t = (e) => e.replace(/'/g, "''"), n = `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX ${Y(e.index.name)} ON ${Y(e.table)} (${e.index.columns.map(Y).join(", ")})${Oi(e.index)}`;
|
|
2604
2761
|
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)}');`;
|
|
2605
|
-
},
|
|
2762
|
+
}, Vi = (e, t, n) => {
|
|
2606
2763
|
let r = n.find((t) => t.tableName === e);
|
|
2607
2764
|
if (!r) return [];
|
|
2608
2765
|
let i = [];
|
|
2609
2766
|
for (let n of t) {
|
|
2610
2767
|
let t = r.fields[n];
|
|
2611
|
-
t && t.type === "text" && !t.generatedAs && i.push(`ALTER TABLE ${
|
|
2768
|
+
t && t.type === "text" && !t.generatedAs && i.push(`ALTER TABLE ${Y(e)} ALTER COLUMN ${Y(n)} NVARCHAR(450) ${t.nullable ? "NULL" : "NOT NULL"};`);
|
|
2612
2769
|
}
|
|
2613
2770
|
return i;
|
|
2614
|
-
},
|
|
2615
|
-
let t = e.fields.map((e) =>
|
|
2616
|
-
return `ALTER TABLE ${
|
|
2617
|
-
},
|
|
2618
|
-
let n = e.fields.map((n) =>
|
|
2619
|
-
return `ALTER TABLE ${
|
|
2620
|
-
},
|
|
2771
|
+
}, Hi = (e) => `ALTER TABLE ${G(e.table)} ADD CONSTRAINT ${G(`${e.table}_${e.column}_key`)} UNIQUE (${G(e.column)});`, Ui = (e, t) => `ALTER TABLE ${K(e.table)} ADD CONSTRAINT ${K(`${e.table}_${e.column}_key`)} UNIQUE (${Ei(t, e.table, e.column)});`, Wi = (e) => {
|
|
2772
|
+
let t = e.fields.map((e) => G(e)).join(", ");
|
|
2773
|
+
return `ALTER TABLE ${G(e.table)} ADD CONSTRAINT ${G(e.name)} UNIQUE (${t});`;
|
|
2774
|
+
}, Gi = (e, t) => {
|
|
2775
|
+
let n = e.fields.map((n) => Ei(t, e.table, n)).join(", ");
|
|
2776
|
+
return `ALTER TABLE ${K(e.table)} ADD CONSTRAINT ${K(e.name)} UNIQUE (${n});`;
|
|
2777
|
+
}, Ki = (e) => `ALTER TABLE ${G(e.table)} DROP CONSTRAINT IF EXISTS ${G(e.name)};`, qi = (e) => `ALTER TABLE ${K(e.table)} DROP INDEX ${K(e.name)};`, Ji = (e) => `ALTER TABLE ${G(e.table)} DROP CONSTRAINT IF EXISTS ${G(`${e.table}_${e.column}_key`)};`, Yi = (e) => `ALTER TABLE ${K(e.table)} DROP INDEX ${K(`${e.table}_${e.column}_key`)};`, Xi = (e, t) => {
|
|
2621
2778
|
let n = [], r = t(e.table), i = t(e.column), a = t(e.targetTable), o = t(e.targetColumn);
|
|
2622
2779
|
if (e.orphanPolicy) {
|
|
2623
2780
|
let t = `${i} IS NOT NULL AND ${i} NOT IN (SELECT ${o} FROM ${a})`;
|
|
@@ -2635,36 +2792,36 @@ BEGIN
|
|
|
2635
2792
|
setNull: "SET NULL",
|
|
2636
2793
|
noAction: "NO ACTION"
|
|
2637
2794
|
}[e.onDelete]}`), n.push(s.join(" ") + ";"), n;
|
|
2638
|
-
},
|
|
2795
|
+
}, Zi = (e) => `ALTER TABLE ${G(e.table)} DROP CONSTRAINT IF EXISTS ${G(`${e.table}_${e.column}_fkey`)};`, Qi = (e) => `ALTER TABLE ${K(e.table)} DROP FOREIGN KEY ${K(`${e.table}_${e.column}_fkey`)};`, $i = (e, t) => {
|
|
2639
2796
|
let n = e.values.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
|
|
2640
2797
|
return `ALTER TABLE ${t(e.table)} ADD CONSTRAINT ${t(`${e.table}_${e.column}_check`)} CHECK (${t(e.column)} IN (${n}));`;
|
|
2641
|
-
},
|
|
2798
|
+
}, ea = (e) => `ALTER TABLE ${G(e.table)} DROP CONSTRAINT IF EXISTS ${G(`${e.table}_${e.column}_check`)};`, ta = (e, t) => T.gen(function* () {
|
|
2642
2799
|
let n = yield* e`
|
|
2643
2800
|
SELECT cc.constraint_name AS n, cc.check_clause AS c
|
|
2644
2801
|
FROM information_schema.check_constraints cc
|
|
2645
|
-
WHERE cc.constraint_schema = DATABASE() AND cc.table_name = ${t.table}`.pipe(
|
|
2802
|
+
WHERE cc.constraint_schema = DATABASE() AND cc.table_name = ${t.table}`.pipe(T.orElse(() => e`
|
|
2646
2803
|
SELECT cc.constraint_name AS n, cc.check_clause AS c
|
|
2647
2804
|
FROM information_schema.check_constraints cc
|
|
2648
2805
|
JOIN information_schema.table_constraints tc
|
|
2649
2806
|
ON tc.constraint_schema = cc.constraint_schema
|
|
2650
2807
|
AND tc.constraint_name = cc.constraint_name
|
|
2651
|
-
WHERE tc.table_schema = DATABASE() AND tc.table_name = ${t.table}`),
|
|
2808
|
+
WHERE tc.table_schema = DATABASE() AND tc.table_name = ${t.table}`), T.orElseSucceed(() => []));
|
|
2652
2809
|
for (let e of n) {
|
|
2653
2810
|
let n = String(e.n ?? "");
|
|
2654
|
-
if (n !== "" &&
|
|
2811
|
+
if (n !== "" && tr(String(e.c ?? ""))?.column === t.column) return n;
|
|
2655
2812
|
}
|
|
2656
|
-
}),
|
|
2657
|
-
let r = yield*
|
|
2658
|
-
r !== void 0 && (yield* X(e, `ALTER TABLE ${
|
|
2659
|
-
let i = yield*
|
|
2813
|
+
}), na = (e, t, n) => T.gen(function* () {
|
|
2814
|
+
let r = yield* ta(e, t);
|
|
2815
|
+
r !== void 0 && (yield* X(e, `ALTER TABLE ${K(t.table)} DROP CONSTRAINT ${K(r)};`, t.kind, [Nr]));
|
|
2816
|
+
let i = yield* ta(e, t);
|
|
2660
2817
|
if (i === void 0) return;
|
|
2661
|
-
let a =
|
|
2662
|
-
if (!a) return yield*
|
|
2663
|
-
yield* X(e, `ALTER TABLE ${
|
|
2664
|
-
}),
|
|
2665
|
-
let i = e.column, a = r === "mariadb", o = a ?
|
|
2666
|
-
if (
|
|
2667
|
-
let t = r === "mssql" ? `${o(i.name)} ${
|
|
2818
|
+
let a = q(n, t.table, t.column);
|
|
2819
|
+
if (!a) return yield* T.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.`));
|
|
2820
|
+
yield* X(e, `ALTER TABLE ${K(t.table)} MODIFY COLUMN ${Zr(a, t.column)};`, t.kind);
|
|
2821
|
+
}), ra = (e, t, n, r) => {
|
|
2822
|
+
let i = e.column, a = r === "mariadb", o = a ? K : r === "mssql" ? Y : G, s = a ? Vr(i) : r === "mssql" ? yi(i) : r === "sqlite" ? pi(i) : zr(i), c = r === "mssql" ? "ADD" : "ADD COLUMN", l = r === "mssql" ? i.type === "json" ? ` CHECK ${nt(o(i.name))}` : i.type === "array" ? ` CHECK (${o(i.name)} IS NULL OR ISJSON(${o(i.name)}) = 1)` : "" : "", u = (e) => a ? Qr(e, i) : r === "mssql" ? mi(e, "SYSUTCDATETIME()") : r === "sqlite" ? mi(e, "CURRENT_TIMESTAMP") : ei(e, i), d = ti(i, r);
|
|
2823
|
+
if (d) {
|
|
2824
|
+
let t = r === "mssql" ? `${o(i.name)} ${d}` : `${o(i.name)} ${s} ${d}`;
|
|
2668
2825
|
return {
|
|
2669
2826
|
pre: [`ALTER TABLE ${o(e.table)} ${c} ${t};`],
|
|
2670
2827
|
post: []
|
|
@@ -2673,24 +2830,24 @@ BEGIN
|
|
|
2673
2830
|
if (t.classification === "safe") {
|
|
2674
2831
|
let t = [`ALTER TABLE ${o(e.table)} ${c} ${o(i.name)} ${s}`];
|
|
2675
2832
|
return i.unique && t.push("UNIQUE"), {
|
|
2676
|
-
pre: [`${t.join(" ")};`],
|
|
2833
|
+
pre: [`${t.join(" ")}${l};`],
|
|
2677
2834
|
post: []
|
|
2678
2835
|
};
|
|
2679
2836
|
}
|
|
2680
2837
|
if (t.classification === "needs-default") {
|
|
2681
|
-
let t =
|
|
2838
|
+
let t = u(i.defaultValue);
|
|
2682
2839
|
if (t === null) throw Error(`migration applier: cannot render the declared default for '${e.table}.${i.name}' (${JSON.stringify(i.defaultValue)}) while adding it NOT NULL to a populated table. This is a framework bug — report the column type + default.`);
|
|
2683
2840
|
return {
|
|
2684
|
-
pre: [`ALTER TABLE ${o(e.table)} ${c} ${o(i.name)} ${s} NOT NULL ${t};`],
|
|
2841
|
+
pre: [`ALTER TABLE ${o(e.table)} ${c} ${o(i.name)} ${s} NOT NULL ${t}${l};`],
|
|
2685
2842
|
post: []
|
|
2686
2843
|
};
|
|
2687
2844
|
}
|
|
2688
|
-
let
|
|
2689
|
-
pre: [`ALTER TABLE ${o(e.table)} ${c} ${o(i.name)} ${s};`],
|
|
2690
|
-
post:
|
|
2845
|
+
let f = n(e.table, i.name), p = a ? `ALTER TABLE ${o(e.table)} MODIFY COLUMN ${o(i.name)} ${s} NOT NULL;` : r === "mssql" ? `ALTER TABLE ${o(e.table)} ALTER COLUMN ${o(i.name)} ${s} NOT NULL;` : r === "sqlite" ? null : `ALTER TABLE ${o(e.table)} ALTER COLUMN ${o(i.name)} SET NOT NULL;`, m = {
|
|
2846
|
+
pre: [`ALTER TABLE ${o(e.table)} ${c} ${o(i.name)} ${s}${l};`],
|
|
2847
|
+
post: p ? [p] : []
|
|
2691
2848
|
};
|
|
2692
|
-
return
|
|
2693
|
-
},
|
|
2849
|
+
return f?.sql && (m.backfillKind = "sql", m.backfillSql = f.sql), f?.js && (m.backfillKind = "js", m.backfillJs = f.js), f?.batchSize !== void 0 && (m.batchSize = f.batchSize), f?.sleepMs !== void 0 && (m.sleepMs = f.sleepMs), m;
|
|
2850
|
+
}, ia = (e) => {
|
|
2694
2851
|
let t = new Map(e.map((e) => [e.tableName, e]));
|
|
2695
2852
|
return (e, n) => {
|
|
2696
2853
|
let r = t.get(e);
|
|
@@ -2710,47 +2867,47 @@ BEGIN
|
|
|
2710
2867
|
...o
|
|
2711
2868
|
};
|
|
2712
2869
|
};
|
|
2713
|
-
}, X = (e, t, n, r = []) => e.unsafe(t).pipe(
|
|
2714
|
-
process.stderr.write(
|
|
2715
|
-
})),
|
|
2716
|
-
let r =
|
|
2870
|
+
}, X = (e, t, n, r = []) => e.unsafe(t).pipe(T.catchIf((e) => kr(e, r), () => T.void), T.tapError((e) => T.sync(() => {
|
|
2871
|
+
process.stderr.write(fe(`applier: statement failed (op=${n})`, t, e, 400));
|
|
2872
|
+
})), T.mapError((e) => {
|
|
2873
|
+
let r = fe(`applier: statement failed (op=${n})`, t, e, 400).trim();
|
|
2717
2874
|
return Object.assign(e, { message: r });
|
|
2718
|
-
}),
|
|
2719
|
-
let n =
|
|
2720
|
-
if (!n) return yield*
|
|
2875
|
+
}), T.map(() => void 0)), Z = (e, t, n) => T.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(T.as(!0), T.catchAll(() => T.succeed(!1))), aa = (e, t) => T.gen(function* () {
|
|
2876
|
+
let n = z([Ge], t).tables[0];
|
|
2877
|
+
if (!n) return yield* T.die(/* @__PURE__ */ Error("migration applier: the resume-ledger table descriptor produced no snapshot. This is a framework bug."));
|
|
2721
2878
|
let r = {
|
|
2722
2879
|
kind: "create-table",
|
|
2723
|
-
table:
|
|
2880
|
+
table: A,
|
|
2724
2881
|
columns: n.columns,
|
|
2725
2882
|
indexes: []
|
|
2726
2883
|
}, i = yield* e.onDialectOrElse({
|
|
2727
|
-
mysql: () =>
|
|
2728
|
-
mssql: () =>
|
|
2729
|
-
sqlite: () =>
|
|
2730
|
-
orElse: () =>
|
|
2884
|
+
mysql: () => Tr(e).pipe(T.map((e) => ui(r, e))),
|
|
2885
|
+
mssql: () => T.succeed(xi(r)),
|
|
2886
|
+
sqlite: () => T.succeed(gi(r)),
|
|
2887
|
+
orElse: () => T.succeed(ai(r))
|
|
2731
2888
|
});
|
|
2732
|
-
yield*
|
|
2733
|
-
}),
|
|
2889
|
+
yield* T.forEach(i, (t) => X(e, t, "resume-ledger-bootstrap"), { discard: !0 });
|
|
2890
|
+
}), oa = (e) => e`
|
|
2734
2891
|
SELECT ${e("runId")}, ${e("planFingerprint")}, ${e("opIndex")},
|
|
2735
2892
|
${e("status")}, ${e("payload")}
|
|
2736
|
-
FROM ${e(
|
|
2737
|
-
`,
|
|
2738
|
-
let i = yield*
|
|
2739
|
-
yield*
|
|
2740
|
-
INSERT INTO ${e(
|
|
2893
|
+
FROM ${e(A)}
|
|
2894
|
+
`, sa = (e, t, n, r) => T.gen(function* () {
|
|
2895
|
+
let i = yield* W(e, (/* @__PURE__ */ new Date()).toISOString());
|
|
2896
|
+
yield* T.forEach(r, ({ index: r, planned: a }) => e`
|
|
2897
|
+
INSERT INTO ${e(A)}
|
|
2741
2898
|
(${e("id")}, ${e("runId")}, ${e("planFingerprint")}, ${e("opIndex")},
|
|
2742
2899
|
${e("opKind")}, ${e("opTarget")}, ${e("status")}, ${e("payload")},
|
|
2743
2900
|
${e("createdAt")})
|
|
2744
2901
|
VALUES
|
|
2745
2902
|
(${`mop_${t}_${r}`}, ${t}, ${n}, ${r},
|
|
2746
|
-
${a.op.kind}, ${
|
|
2903
|
+
${a.op.kind}, ${qe(a.op)}, ${"pending"},
|
|
2747
2904
|
${JSON.stringify(a)}, ${i})
|
|
2748
2905
|
`, { discard: !0 });
|
|
2749
|
-
}),
|
|
2750
|
-
let a = yield*
|
|
2906
|
+
}), ca = (e, t, n, r, i) => T.gen(function* () {
|
|
2907
|
+
let a = yield* W(e, (/* @__PURE__ */ new Date()).toISOString());
|
|
2751
2908
|
if (r === "applied") {
|
|
2752
2909
|
yield* e`
|
|
2753
|
-
UPDATE ${e(
|
|
2910
|
+
UPDATE ${e(A)}
|
|
2754
2911
|
SET ${e("status")} = ${r}, ${e("appliedAt")} = ${a},
|
|
2755
2912
|
${e("durationMs")} = ${i ?? null}
|
|
2756
2913
|
WHERE ${e("runId")} = ${t} AND ${e("opIndex")} = ${n}
|
|
@@ -2758,295 +2915,322 @@ BEGIN
|
|
|
2758
2915
|
return;
|
|
2759
2916
|
}
|
|
2760
2917
|
yield* e`
|
|
2761
|
-
UPDATE ${e(
|
|
2918
|
+
UPDATE ${e(A)}
|
|
2762
2919
|
SET ${e("status")} = ${r}, ${e("startedAt")} = ${a}
|
|
2763
2920
|
WHERE ${e("runId")} = ${t} AND ${e("opIndex")} = ${n}
|
|
2764
2921
|
`;
|
|
2765
|
-
}),
|
|
2766
|
-
let i = yield*
|
|
2922
|
+
}), la = (e, t, n, r) => T.gen(function* () {
|
|
2923
|
+
let i = yield* W(e, (/* @__PURE__ */ new Date()).toISOString());
|
|
2767
2924
|
r.length > 0 && (yield* e`
|
|
2768
|
-
UPDATE ${e(
|
|
2925
|
+
UPDATE ${e(A)}
|
|
2769
2926
|
SET ${e("status")} = ${"applied"}, ${e("appliedAt")} = ${i}
|
|
2770
2927
|
WHERE ${e("runId")} = ${t} AND ${e("opIndex")} IN ${e.in(r)}
|
|
2771
2928
|
`), n.length > 0 && (yield* e`
|
|
2772
|
-
UPDATE ${e(
|
|
2929
|
+
UPDATE ${e(A)}
|
|
2773
2930
|
SET ${e("status")} = ${"pending"}
|
|
2774
2931
|
WHERE ${e("runId")} = ${t} AND ${e("opIndex")} IN ${e.in(n)}
|
|
2775
2932
|
`);
|
|
2776
|
-
}),
|
|
2777
|
-
if (
|
|
2933
|
+
}), ua = (e, t) => t === void 0 ? e`DELETE FROM ${e(A)}`.pipe(T.asVoid) : e`DELETE FROM ${e(A)} WHERE ${e("runId")} = ${t}`.pipe(T.asVoid), da = (e, t, n) => T.gen(function* () {
|
|
2934
|
+
if (tt(n.op, n.classification, t) !== "artefact-repair") return "clean";
|
|
2778
2935
|
let r = n.op, i = (e) => o(e, t);
|
|
2779
2936
|
if (t === "sqlite" || t === "turso") {
|
|
2780
2937
|
if (!("table" in r)) return "clean";
|
|
2781
|
-
let n = `${r.table}${
|
|
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*
|
|
2938
|
+
let n = `${r.table}${Xe}`;
|
|
2939
|
+
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* T.logWarning(`migration resume: reconciled an interrupted sqlite table rebuild on '${r.table}' — replaying the operation`).pipe(T.annotateLogs({ scope: "voltro:migrate" })), "outstanding") : "clean";
|
|
2783
2940
|
}
|
|
2784
2941
|
if (r.kind !== "alter-column-type") return "clean";
|
|
2785
|
-
let a = `${r.column}${
|
|
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*
|
|
2787
|
-
}),
|
|
2788
|
-
let i = process.hrtime.bigint(), a =
|
|
2789
|
-
switch (
|
|
2942
|
+
let a = `${r.column}${Ze}`, 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) => T.logWarning(`migration resume: ${e}`).pipe(T.annotateLogs({ scope: "voltro:migrate" }));
|
|
2943
|
+
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* T.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.`));
|
|
2944
|
+
}), fa = (e, t, n, r = "fresh") => T.gen(function* () {
|
|
2945
|
+
let i = process.hrtime.bigint(), a = ia(n.declared), s = t.op;
|
|
2946
|
+
switch (s.kind) {
|
|
2790
2947
|
case "create-table": {
|
|
2791
2948
|
let t = yield* e.onDialectOrElse({
|
|
2792
|
-
mysql: () =>
|
|
2793
|
-
mssql: () =>
|
|
2794
|
-
sqlite: () =>
|
|
2795
|
-
orElse: () =>
|
|
2949
|
+
mysql: () => Tr(e).pipe(T.map((e) => ui(s, e))),
|
|
2950
|
+
mssql: () => T.succeed(xi(s)),
|
|
2951
|
+
sqlite: () => T.succeed(gi(s)),
|
|
2952
|
+
orElse: () => T.succeed(ai(s))
|
|
2796
2953
|
}), n = yield* e.onDialectOrElse({
|
|
2797
|
-
mysql: () =>
|
|
2798
|
-
orElse: () =>
|
|
2954
|
+
mysql: () => T.succeed([Ar]),
|
|
2955
|
+
orElse: () => T.succeed([])
|
|
2799
2956
|
});
|
|
2800
|
-
for (let r of t) yield* X(e, r,
|
|
2957
|
+
for (let r of t) yield* X(e, r, s.kind, n);
|
|
2801
2958
|
break;
|
|
2802
2959
|
}
|
|
2803
2960
|
case "drop-table": {
|
|
2804
|
-
let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString(), r = (e) => t ?
|
|
2961
|
+
let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString(), r = (e) => t ? wi(s, n, e) : Ci(s, e);
|
|
2805
2962
|
yield* e.onDialectOrElse({
|
|
2806
|
-
mysql: () => X(e, r(
|
|
2807
|
-
orElse: () => X(e, r(
|
|
2963
|
+
mysql: () => X(e, r(K), s.kind),
|
|
2964
|
+
orElse: () => X(e, r(G), s.kind)
|
|
2808
2965
|
});
|
|
2809
2966
|
break;
|
|
2810
2967
|
}
|
|
2811
2968
|
case "drop-column": {
|
|
2812
2969
|
let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString();
|
|
2813
2970
|
yield* e.onDialectOrElse({
|
|
2814
|
-
mysql: () =>
|
|
2815
|
-
sqlite: () => X(e, t ?
|
|
2816
|
-
orElse: () => X(e, t ?
|
|
2971
|
+
mysql: () => Tr(e).pipe(T.flatMap((r) => X(e, t ? Kr(s, n, K) : Wr(s, r), s.kind, t ? [] : [jr]))),
|
|
2972
|
+
sqlite: () => X(e, t ? Kr(s, n, G) : Ur(s, G, !1), s.kind, t ? [] : [Mr]),
|
|
2973
|
+
orElse: () => X(e, t ? Kr(s, n, G) : Ur(s, G), s.kind)
|
|
2817
2974
|
});
|
|
2818
2975
|
break;
|
|
2819
2976
|
}
|
|
2820
2977
|
case "rename-column":
|
|
2821
2978
|
yield* e.onDialectOrElse({
|
|
2822
|
-
mysql: () => X(e,
|
|
2823
|
-
mssql: () =>
|
|
2824
|
-
|
|
2979
|
+
mysql: () => X(e, Gr(s, K), s.kind),
|
|
2980
|
+
mssql: () => T.gen(function* () {
|
|
2981
|
+
let t = (yield* e`
|
|
2982
|
+
SELECT ck.name, ck.definition, ck.is_disabled AS disabled,
|
|
2983
|
+
ck.is_not_trusted AS untrusted, ck.is_not_for_replication AS notForReplication
|
|
2984
|
+
FROM sys.check_constraints ck
|
|
2985
|
+
WHERE ck.parent_object_id = OBJECT_ID(${s.table}) AND EXISTS (
|
|
2986
|
+
SELECT 1 FROM sys.sql_expression_dependencies dep
|
|
2987
|
+
JOIN sys.columns col ON col.object_id = dep.referenced_id AND col.column_id = dep.referenced_minor_id
|
|
2988
|
+
WHERE dep.referencing_id = ck.object_id AND col.object_id = ck.parent_object_id AND col.name = ${s.from}
|
|
2989
|
+
) ORDER BY ck.name
|
|
2990
|
+
`).map((e) => ({
|
|
2991
|
+
...e,
|
|
2992
|
+
definition: Fr(e.definition, s.from, s.to)
|
|
2993
|
+
})), n = (e) => o(e, "mssql"), r = (e) => e.replace(/'/g, "''");
|
|
2994
|
+
return yield* Z(e, [
|
|
2995
|
+
...t.map((e) => `ALTER TABLE ${n(s.table)} DROP CONSTRAINT ${n(e.name)}`),
|
|
2996
|
+
`EXEC sp_rename N'${r(`${n(s.table)}.${n(s.from)}`)}', N'${r(s.to)}', 'COLUMN';`,
|
|
2997
|
+
...t.flatMap((e) => [`ALTER TABLE ${n(s.table)} WITH ${e.untrusted ? "NOCHECK" : "CHECK"} ADD CONSTRAINT ${n(e.name)} CHECK ${e.notForReplication ? "NOT FOR REPLICATION " : ""}${e.definition}`, ...e.disabled ? [`ALTER TABLE ${n(s.table)} NOCHECK CONSTRAINT ${n(e.name)}`] : []])
|
|
2998
|
+
], s.kind);
|
|
2999
|
+
}),
|
|
3000
|
+
orElse: () => X(e, Gr(s, G), s.kind)
|
|
2825
3001
|
});
|
|
2826
3002
|
break;
|
|
2827
3003
|
case "add-index":
|
|
2828
3004
|
yield* e.onDialectOrElse({
|
|
2829
|
-
sqlite: () => X(e,
|
|
2830
|
-
mysql: () =>
|
|
2831
|
-
mssql: () => Z(e, [...
|
|
2832
|
-
orElse: () => X(e,
|
|
3005
|
+
sqlite: () => X(e, ki(s, !1), s.kind),
|
|
3006
|
+
mysql: () => Tr(e).pipe(T.flatMap((t) => X(e, Ai(s, n.declared, t), s.kind, [Ar]))),
|
|
3007
|
+
mssql: () => Z(e, [...Vi(s.table, s.index.columns, n.declared), Bi(s)], s.kind),
|
|
3008
|
+
orElse: () => X(e, ki(s, t.classification === "online-required"), s.kind)
|
|
2833
3009
|
});
|
|
2834
3010
|
break;
|
|
2835
3011
|
case "drop-index":
|
|
2836
3012
|
yield* e.onDialectOrElse({
|
|
2837
|
-
mysql: () => X(e,
|
|
2838
|
-
mssql: () => X(e,
|
|
2839
|
-
orElse: () => X(e,
|
|
3013
|
+
mysql: () => X(e, Ni(s), s.kind),
|
|
3014
|
+
mssql: () => X(e, Pi(s), s.kind),
|
|
3015
|
+
orElse: () => X(e, Mi(s), s.kind)
|
|
2840
3016
|
});
|
|
2841
3017
|
break;
|
|
2842
3018
|
case "rename-table":
|
|
2843
3019
|
yield* e.onDialectOrElse({
|
|
2844
|
-
mysql: () => X(e,
|
|
2845
|
-
mssql: () => X(e,
|
|
2846
|
-
orElse: () => X(e,
|
|
3020
|
+
mysql: () => X(e, Fi(s, K), s.kind),
|
|
3021
|
+
mssql: () => X(e, Ii(s), s.kind),
|
|
3022
|
+
orElse: () => X(e, Fi(s, G), s.kind)
|
|
2847
3023
|
});
|
|
2848
3024
|
break;
|
|
2849
3025
|
case "rename-index":
|
|
2850
3026
|
yield* e.onDialectOrElse({
|
|
2851
|
-
mysql: () => X(e,
|
|
2852
|
-
mssql: () => X(e,
|
|
2853
|
-
orElse: () => X(e,
|
|
3027
|
+
mysql: () => X(e, Ri(s), s.kind),
|
|
3028
|
+
mssql: () => X(e, zi(s), s.kind),
|
|
3029
|
+
orElse: () => X(e, Li(s), s.kind)
|
|
2854
3030
|
});
|
|
2855
3031
|
break;
|
|
2856
3032
|
case "add-unique":
|
|
2857
3033
|
yield* e.onDialectOrElse({
|
|
2858
|
-
mysql: () => X(e,
|
|
2859
|
-
sqlite: () => Z(e,
|
|
2860
|
-
mssql: () => Z(e, [...
|
|
2861
|
-
orElse: () => X(e,
|
|
3034
|
+
mysql: () => X(e, Ui(s, n.declared), s.kind),
|
|
3035
|
+
sqlite: () => Z(e, J(s.table, n.declared), s.kind),
|
|
3036
|
+
mssql: () => Z(e, [...Vi(s.table, [s.column], n.declared), Hi(s)], s.kind),
|
|
3037
|
+
orElse: () => X(e, Hi(s), s.kind)
|
|
2862
3038
|
});
|
|
2863
3039
|
break;
|
|
2864
3040
|
case "drop-unique":
|
|
2865
3041
|
yield* e.onDialectOrElse({
|
|
2866
|
-
mysql: () => X(e,
|
|
2867
|
-
sqlite: () => Z(e,
|
|
2868
|
-
orElse: () => X(e,
|
|
3042
|
+
mysql: () => X(e, Yi(s), s.kind),
|
|
3043
|
+
sqlite: () => Z(e, J(s.table, n.declared), s.kind),
|
|
3044
|
+
orElse: () => X(e, Ji(s), s.kind)
|
|
2869
3045
|
});
|
|
2870
3046
|
break;
|
|
2871
3047
|
case "add-unique-composite":
|
|
2872
3048
|
yield* e.onDialectOrElse({
|
|
2873
|
-
mysql: () => X(e,
|
|
2874
|
-
sqlite: () => Z(e,
|
|
2875
|
-
mssql: () => Z(e, [...
|
|
2876
|
-
orElse: () => X(e,
|
|
3049
|
+
mysql: () => X(e, Gi(s, n.declared), s.kind),
|
|
3050
|
+
sqlite: () => Z(e, J(s.table, n.declared), s.kind),
|
|
3051
|
+
mssql: () => Z(e, [...Vi(s.table, s.fields, n.declared), Wi(s)], s.kind),
|
|
3052
|
+
orElse: () => X(e, Wi(s), s.kind)
|
|
2877
3053
|
});
|
|
2878
3054
|
break;
|
|
2879
3055
|
case "drop-unique-composite":
|
|
2880
3056
|
yield* e.onDialectOrElse({
|
|
2881
|
-
mysql: () => X(e,
|
|
2882
|
-
sqlite: () => Z(e,
|
|
2883
|
-
orElse: () => X(e,
|
|
3057
|
+
mysql: () => X(e, qi(s), s.kind),
|
|
3058
|
+
sqlite: () => Z(e, J(s.table, n.declared), s.kind),
|
|
3059
|
+
orElse: () => X(e, Ki(s), s.kind)
|
|
2884
3060
|
});
|
|
2885
3061
|
break;
|
|
2886
3062
|
case "add-foreign-key":
|
|
2887
3063
|
yield* e.onDialectOrElse({
|
|
2888
|
-
mysql: () => Z(e,
|
|
2889
|
-
sqlite: () => Z(e,
|
|
2890
|
-
orElse: () => Z(e,
|
|
3064
|
+
mysql: () => Z(e, Xi(s, K), s.kind),
|
|
3065
|
+
sqlite: () => Z(e, J(s.table, n.declared), s.kind),
|
|
3066
|
+
orElse: () => Z(e, Xi(s, G), s.kind)
|
|
2891
3067
|
});
|
|
2892
3068
|
break;
|
|
2893
3069
|
case "add-column": {
|
|
2894
|
-
let n =
|
|
2895
|
-
mysql: () =>
|
|
2896
|
-
mssql: () =>
|
|
2897
|
-
sqlite: () =>
|
|
2898
|
-
orElse: () =>
|
|
3070
|
+
let n = ra(s, t, a, yield* e.onDialectOrElse({
|
|
3071
|
+
mysql: () => T.succeed("mariadb"),
|
|
3072
|
+
mssql: () => T.succeed("mssql"),
|
|
3073
|
+
sqlite: () => T.succeed("sqlite"),
|
|
3074
|
+
orElse: () => T.succeed("postgres")
|
|
2899
3075
|
}));
|
|
2900
|
-
if (!(r === "resume" && (yield* $(e,
|
|
3076
|
+
if (!(r === "resume" && (yield* $(e, He(e), s.table, s.column.name)))) for (let t of n.pre) yield* X(e, t, s.kind);
|
|
2901
3077
|
if (n.backfillKind === "sql" && n.backfillSql) {
|
|
2902
|
-
if (t.classification !== "online-required" && n.batchSize === void 0) yield* e`UPDATE ${e(
|
|
3078
|
+
if (t.classification !== "online-required" && n.batchSize === void 0) yield* e`UPDATE ${e(s.table)} SET ${e(s.column.name)} = ${n.backfillSql}`;
|
|
2903
3079
|
else {
|
|
2904
3080
|
let t = n.batchSize ?? 5e3, r = n.sleepMs ?? 0, i, a = 0;
|
|
2905
3081
|
for (;;) {
|
|
2906
|
-
let
|
|
2907
|
-
if (
|
|
2908
|
-
let c =
|
|
2909
|
-
yield* e`UPDATE ${e(
|
|
3082
|
+
let o = i === void 0 ? yield* e`SELECT ${e("id")} FROM ${e(s.table)} WHERE ${e(s.column.name)} IS NULL ORDER BY ${e("id")} ${Q(e, t)}` : yield* e`SELECT ${e("id")} FROM ${e(s.table)} WHERE ${e(s.column.name)} IS NULL AND ${e("id")} > ${i} ORDER BY ${e("id")} ${Q(e, t)}`;
|
|
3083
|
+
if (o.length === 0) break;
|
|
3084
|
+
let c = o.map((e) => e.id);
|
|
3085
|
+
yield* e`UPDATE ${e(s.table)} SET ${e(s.column.name)} = ${n.backfillSql} WHERE ${e("id")} IN ${e.in(c)}`, a += o.length, yield* T.logInfo(`backfill ${s.table}.${s.column.name}: ${a} rows`).pipe(T.annotateLogs({
|
|
2910
3086
|
scope: "voltro:migrate",
|
|
2911
3087
|
mode: "sql-batched"
|
|
2912
|
-
})), i =
|
|
3088
|
+
})), i = o[o.length - 1].id, r > 0 && (yield* T.sleep(`${r} millis`));
|
|
2913
3089
|
}
|
|
2914
3090
|
}
|
|
2915
3091
|
} else if (n.backfillKind === "js" && n.backfillJs) {
|
|
2916
3092
|
let t = n.batchSize ?? 1e3, r = n.sleepMs ?? 0, i, a = 0;
|
|
2917
3093
|
for (;;) {
|
|
2918
|
-
let
|
|
2919
|
-
if (
|
|
2920
|
-
for (let t of
|
|
2921
|
-
let r = yield*
|
|
3094
|
+
let o = i === void 0 ? yield* e`SELECT ${e("id")} FROM ${e(s.table)} WHERE ${e(s.column.name)} IS NULL ORDER BY ${e("id")} ${Q(e, t)}` : yield* e`SELECT ${e("id")} FROM ${e(s.table)} WHERE ${e(s.column.name)} IS NULL AND ${e("id")} > ${i} ORDER BY ${e("id")} ${Q(e, t)}`;
|
|
3095
|
+
if (o.length === 0) break;
|
|
3096
|
+
for (let t of o) {
|
|
3097
|
+
let r = yield* T.tryPromise({
|
|
2922
3098
|
try: () => Promise.resolve(n.backfillJs({ id: t.id })),
|
|
2923
3099
|
catch: (e) => e
|
|
2924
|
-
}).pipe(
|
|
2925
|
-
yield* e`UPDATE ${e(
|
|
3100
|
+
}).pipe(T.orDie);
|
|
3101
|
+
yield* e`UPDATE ${e(s.table)} SET ${e(s.column.name)} = ${r} WHERE ${e("id")} = ${t.id}`;
|
|
2926
3102
|
}
|
|
2927
|
-
a +=
|
|
3103
|
+
a += o.length, yield* T.logInfo(`backfill ${s.table}.${s.column.name}: ${a} rows processed`).pipe(T.annotateLogs({
|
|
2928
3104
|
scope: "voltro:migrate",
|
|
2929
|
-
table:
|
|
2930
|
-
column:
|
|
2931
|
-
})), i =
|
|
3105
|
+
table: s.table,
|
|
3106
|
+
column: s.column.name
|
|
3107
|
+
})), i = o[o.length - 1].id, r > 0 && (yield* T.sleep(`${r} millis`));
|
|
2932
3108
|
}
|
|
2933
3109
|
}
|
|
2934
|
-
for (let t of n.post) yield* X(e, t,
|
|
3110
|
+
for (let t of n.post) yield* X(e, t, s.kind);
|
|
2935
3111
|
break;
|
|
2936
3112
|
}
|
|
2937
3113
|
case "alter-column-nullability":
|
|
2938
3114
|
yield* e.onDialectOrElse({
|
|
2939
3115
|
mysql: () => {
|
|
2940
|
-
let t =
|
|
2941
|
-
return t ? X(e, `ALTER TABLE ${
|
|
3116
|
+
let t = q(n.declared, s.table, s.column);
|
|
3117
|
+
return t ? X(e, `ALTER TABLE ${K(s.table)} MODIFY COLUMN ${Zr(t, s.column, s.toNullable)};`, s.kind) : T.die(/* @__PURE__ */ Error(`alter-column-nullability on mariadb needs the declared column '${s.table}.${s.column}' (to render MODIFY COLUMN); it was not in ctx.declared.`));
|
|
2942
3118
|
},
|
|
2943
3119
|
mssql: () => {
|
|
2944
|
-
let t =
|
|
2945
|
-
return t ? X(e,
|
|
3120
|
+
let t = q(n.declared, s.table, s.column);
|
|
3121
|
+
return t ? X(e, _i(t, s.column, s.table, s.toNullable), s.kind) : T.die(/* @__PURE__ */ Error(`alter-column-nullability on mssql needs the declared column '${s.table}.${s.column}'.`));
|
|
2946
3122
|
},
|
|
2947
|
-
sqlite: () => Z(e,
|
|
2948
|
-
orElse: () => X(e, `ALTER TABLE ${
|
|
3123
|
+
sqlite: () => Z(e, J(s.table, n.declared), s.kind),
|
|
3124
|
+
orElse: () => X(e, `ALTER TABLE ${G(s.table)} ALTER COLUMN ${G(s.column)} ${s.toNullable ? "DROP NOT NULL" : "SET NOT NULL"};`, s.kind)
|
|
2949
3125
|
});
|
|
2950
3126
|
break;
|
|
2951
3127
|
case "alter-column-default": {
|
|
2952
|
-
let t =
|
|
3128
|
+
let t = Xr(n.declared, s.table, s.column), r = q(n.declared, s.table, s.column), i = (e) => s.hasDefault && r !== void 0 && Jr(r, e) ? r : void 0;
|
|
2953
3129
|
yield* e.onDialectOrElse({
|
|
2954
3130
|
mysql: () => {
|
|
2955
3131
|
let n = i("mariadb");
|
|
2956
|
-
return X(e, n ? `ALTER TABLE ${
|
|
3132
|
+
return X(e, n ? `ALTER TABLE ${K(s.table)} MODIFY COLUMN ${Zr(n, s.column)};` : qr(s, K, (e) => Qr(e, t)), s.kind);
|
|
2957
3133
|
},
|
|
2958
3134
|
mssql: () => {
|
|
2959
3135
|
let t = i("mssql");
|
|
2960
|
-
return X(e,
|
|
3136
|
+
return X(e, vi(s, t ? _i(t, s.column, s.table) : void 0), s.kind);
|
|
2961
3137
|
},
|
|
2962
|
-
sqlite: () => Z(e,
|
|
2963
|
-
orElse: () => X(e,
|
|
3138
|
+
sqlite: () => Z(e, J(s.table, n.declared), s.kind),
|
|
3139
|
+
orElse: () => X(e, qr(s, G, (e) => ei(e, t)), s.kind)
|
|
2964
3140
|
});
|
|
2965
3141
|
break;
|
|
2966
3142
|
}
|
|
2967
3143
|
case "alter-column-type": {
|
|
2968
|
-
let r =
|
|
3144
|
+
let r = zr(Xr(n.declared, s.table, s.column) ?? { type: s.to }), i = s.using ? ` USING ${s.using}` : "";
|
|
2969
3145
|
if (t.classification !== "online-required") {
|
|
2970
3146
|
yield* e.onDialectOrElse({
|
|
2971
3147
|
mysql: () => {
|
|
2972
|
-
let t =
|
|
2973
|
-
return t ? X(e, `ALTER TABLE ${
|
|
3148
|
+
let t = q(n.declared, s.table, s.column);
|
|
3149
|
+
return t ? X(e, `ALTER TABLE ${K(s.table)} MODIFY COLUMN ${Zr(t, s.column)};`, s.kind) : T.die(/* @__PURE__ */ Error(`alter-column-type on mariadb needs the declared column '${s.table}.${s.column}' (to render MODIFY COLUMN); it was not in ctx.declared.`));
|
|
2974
3150
|
},
|
|
2975
3151
|
mssql: () => {
|
|
2976
|
-
let t =
|
|
2977
|
-
return t ? X(e,
|
|
3152
|
+
let t = q(n.declared, s.table, s.column);
|
|
3153
|
+
return t ? X(e, _i(t, s.column, s.table), s.kind) : T.die(/* @__PURE__ */ Error(`alter-column-type on mssql needs the declared column '${s.table}.${s.column}'.`));
|
|
2978
3154
|
},
|
|
2979
|
-
sqlite: () => Z(e,
|
|
2980
|
-
orElse: () => X(e, `ALTER TABLE ${
|
|
3155
|
+
sqlite: () => Z(e, J(s.table, n.declared), s.kind),
|
|
3156
|
+
orElse: () => X(e, `ALTER TABLE ${G(s.table)} ALTER COLUMN ${G(s.column)} TYPE ${r}${i};`, s.kind)
|
|
2981
3157
|
});
|
|
2982
3158
|
break;
|
|
2983
3159
|
}
|
|
2984
3160
|
yield* e.onDialectOrElse({
|
|
2985
|
-
mysql: () =>
|
|
2986
|
-
orElse: () =>
|
|
3161
|
+
mysql: () => T.die(/* @__PURE__ */ Error(`online-required alter-column-type on ${s.table}.${s.column} is not supported on mariadb (the shadow-swap path is postgres-only). Use a smaller-table window or an external online-DDL tool.`)),
|
|
3162
|
+
orElse: () => T.void
|
|
2987
3163
|
});
|
|
2988
|
-
let a = `${
|
|
2989
|
-
yield* e.unsafe(`ALTER TABLE ${
|
|
2990
|
-
let c =
|
|
3164
|
+
let a = `${s.column}__shadow`, o = `${s.column}__old`;
|
|
3165
|
+
yield* e.unsafe(`ALTER TABLE ${G(s.table)} ADD COLUMN ${G(a)} ${r}`);
|
|
3166
|
+
let c = s.using ?? G(s.column), l;
|
|
2991
3167
|
for (;;) {
|
|
2992
|
-
let t = l === void 0 ? yield* e`SELECT ${e("id")} FROM ${e(
|
|
3168
|
+
let t = l === void 0 ? yield* e`SELECT ${e("id")} FROM ${e(s.table)} WHERE ${e(a)} IS NULL ORDER BY ${e("id")} ${Q(e, 5e3)}` : yield* e`SELECT ${e("id")} FROM ${e(s.table)} WHERE ${e(a)} IS NULL AND ${e("id")} > ${l} ORDER BY ${e("id")} ${Q(e, 5e3)}`;
|
|
2993
3169
|
if (t.length === 0) break;
|
|
2994
|
-
yield* e.unsafe(`UPDATE ${
|
|
3170
|
+
yield* e.unsafe(`UPDATE ${G(s.table)} SET ${G(a)} = ${c} WHERE ${G(s.column)} IS NOT NULL AND ${G(a)} IS NULL AND ${G("id")} IN (${t.map((e) => `'${e.id.replace(/'/g, "''")}'`).join(",")})`), l = t[t.length - 1].id;
|
|
2995
3171
|
}
|
|
2996
|
-
yield*
|
|
3172
|
+
yield* T.logInfo(`alter-column-type shadow ${s.table}.${s.column}: shadow populated`).pipe(T.annotateLogs({ scope: "voltro:migrate" })), yield* e.unsafe(`ALTER TABLE ${G(s.table)} RENAME COLUMN ${G(s.column)} TO ${G(o)}`), yield* e.unsafe(`ALTER TABLE ${G(s.table)} RENAME COLUMN ${G(a)} TO ${G(s.column)}`), yield* e.unsafe(`ALTER TABLE ${G(s.table)} DROP COLUMN ${G(o)}`);
|
|
2997
3173
|
break;
|
|
2998
3174
|
}
|
|
2999
3175
|
case "drop-foreign-key":
|
|
3000
3176
|
yield* e.onDialectOrElse({
|
|
3001
|
-
mysql: () => X(e,
|
|
3002
|
-
sqlite: () => Z(e,
|
|
3003
|
-
orElse: () => X(e,
|
|
3177
|
+
mysql: () => X(e, Qi(s), s.kind),
|
|
3178
|
+
sqlite: () => Z(e, J(s.table, n.declared), s.kind),
|
|
3179
|
+
orElse: () => X(e, Zi(s), s.kind)
|
|
3004
3180
|
});
|
|
3005
3181
|
break;
|
|
3006
3182
|
case "add-check":
|
|
3007
3183
|
yield* e.onDialectOrElse({
|
|
3008
|
-
mysql: () => X(e,
|
|
3009
|
-
sqlite: () => Z(e,
|
|
3010
|
-
orElse: () => X(e,
|
|
3184
|
+
mysql: () => X(e, $i(s, K), s.kind),
|
|
3185
|
+
sqlite: () => Z(e, J(s.table, n.declared), s.kind),
|
|
3186
|
+
orElse: () => X(e, $i(s, G), s.kind)
|
|
3011
3187
|
});
|
|
3012
3188
|
break;
|
|
3189
|
+
case "reconcile-json-check": {
|
|
3190
|
+
let t = Y(s.column), n = s.validation === "value" ? nt(t) : `(${t} IS NULL OR ISJSON(${t}) = 1)`;
|
|
3191
|
+
yield* e.onDialectOrElse({
|
|
3192
|
+
mssql: () => Z(e, [...s.dropConstraints.map((e) => `ALTER TABLE ${Y(s.table)} DROP CONSTRAINT ${Y(e)}`), `ALTER TABLE ${Y(s.table)} WITH CHECK ADD CHECK ${n}`], s.kind),
|
|
3193
|
+
orElse: () => T.dieMessage("reconcile-json-check requires SQL Server")
|
|
3194
|
+
});
|
|
3195
|
+
break;
|
|
3196
|
+
}
|
|
3013
3197
|
case "drop-check": yield* e.onDialectOrElse({
|
|
3014
|
-
mysql: () =>
|
|
3015
|
-
sqlite: () => Z(e,
|
|
3016
|
-
orElse: () => X(e,
|
|
3198
|
+
mysql: () => na(e, s, n.declared),
|
|
3199
|
+
sqlite: () => Z(e, J(s.table, n.declared), s.kind),
|
|
3200
|
+
orElse: () => X(e, ea(s), s.kind)
|
|
3017
3201
|
});
|
|
3018
3202
|
}
|
|
3019
3203
|
return {
|
|
3020
|
-
op:
|
|
3204
|
+
op: s,
|
|
3021
3205
|
status: "applied",
|
|
3022
3206
|
durationMs: Number((process.hrtime.bigint() - i) / 1000000n)
|
|
3023
3207
|
};
|
|
3024
|
-
}),
|
|
3208
|
+
}), pa = (e, t, n, r) => T.gen(function* () {
|
|
3025
3209
|
let i = [...new Set(r.map((e) => e.runId))];
|
|
3026
|
-
if (i.length > 1) return yield*
|
|
3210
|
+
if (i.length > 1) return yield* T.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 \`${A}\`, reconcile the schema by hand, and delete the rows of the run you have finished.`));
|
|
3027
3211
|
let a = i[0], o = [...r].map((e) => ({
|
|
3028
3212
|
index: Number(e.opIndex),
|
|
3029
3213
|
status: e.status,
|
|
3030
3214
|
planned: JSON.parse(e.payload)
|
|
3031
3215
|
})).sort((e, t) => e.index - t.index), s = o.find((e) => e.status === "started"), c = o.filter((e) => e.status === "started").length;
|
|
3032
|
-
if (c > 1) return yield*
|
|
3033
|
-
if (yield*
|
|
3216
|
+
if (c > 1) return yield* T.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 \`${A}\` by hand before re-running.`));
|
|
3217
|
+
if (yield* T.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} ${qe(s.planned.op)}` : ""}`).pipe(T.annotateLogs({ scope: "voltro:migrate" })), o.every((e) => e.status === "pending")) return {
|
|
3034
3218
|
kind: "discard",
|
|
3035
3219
|
runId: a,
|
|
3036
3220
|
why: "no operation had started — no DDL ran"
|
|
3037
3221
|
};
|
|
3038
|
-
let l = s ? yield*
|
|
3222
|
+
let l = s ? yield* da(e, t, s.planned) : "clean", u = r[0].planFingerprint;
|
|
3039
3223
|
if (u !== n.toFingerprint) return {
|
|
3040
3224
|
kind: "discard",
|
|
3041
3225
|
runId: a,
|
|
3042
3226
|
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`
|
|
3043
3227
|
};
|
|
3044
|
-
let d = (e) => e.status === "applied" ? !1 : s && e.index === s.index && l !== "clean" ? l === "outstanding" :
|
|
3228
|
+
let d = (e) => e.status === "applied" ? !1 : s && e.index === s.index && l !== "clean" ? l === "outstanding" : Ye(n, e.planned.op), f = o.filter(d), p = o.filter((e) => e.status !== "applied" && !d(e));
|
|
3045
3229
|
return f.length === 0 ? {
|
|
3046
3230
|
kind: "discard",
|
|
3047
3231
|
runId: a,
|
|
3048
3232
|
why: "every recorded operation had already taken effect"
|
|
3049
|
-
} : (yield*
|
|
3233
|
+
} : (yield* la(e, a, f.map((e) => e.index), p.map((e) => e.index)), yield* T.logWarning(`migration resume: continuing run ${a} — replaying ${f.length} operation(s), ${o.length - f.length} already applied`).pipe(T.annotateLogs({ scope: "voltro:migrate" })), {
|
|
3050
3234
|
kind: "resume",
|
|
3051
3235
|
runId: a,
|
|
3052
3236
|
ops: f.map((e) => ({
|
|
@@ -3054,7 +3238,7 @@ BEGIN
|
|
|
3054
3238
|
planned: e.planned
|
|
3055
3239
|
}))
|
|
3056
3240
|
});
|
|
3057
|
-
}),
|
|
3241
|
+
}), ma = (e, t, n) => T.gen(function* () {
|
|
3058
3242
|
for (let r of t.operations) {
|
|
3059
3243
|
let i = r.op;
|
|
3060
3244
|
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 && [
|
|
@@ -3063,9 +3247,9 @@ BEGIN
|
|
|
3063
3247
|
"rename-column"
|
|
3064
3248
|
].includes(e.op.kind))) continue;
|
|
3065
3249
|
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";
|
|
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*
|
|
3250
|
+
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* T.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.`));
|
|
3067
3251
|
}
|
|
3068
|
-
}),
|
|
3252
|
+
}), ha = (e) => {
|
|
3069
3253
|
let t = e.op, n = (e) => typeof t[e] == "string" ? t[e] : "";
|
|
3070
3254
|
return [
|
|
3071
3255
|
t.kind,
|
|
@@ -3074,45 +3258,45 @@ BEGIN
|
|
|
3074
3258
|
n("name"),
|
|
3075
3259
|
n("to")
|
|
3076
3260
|
].join("\0");
|
|
3077
|
-
},
|
|
3261
|
+
}, ga = (e, t, n) => T.acquireUseRelease(Be(e, { schema: n.lockSchema }), () => _a(e, t, n), (e) => e.release.pipe(T.orDie)), _a = (e, t, n) => T.gen(function* () {
|
|
3078
3262
|
let r = t.operations.filter((e) => e.blocked);
|
|
3079
|
-
if (r.length > 0) return yield*
|
|
3080
|
-
let i = Date.now(), a = [], o =
|
|
3263
|
+
if (r.length > 0) return yield* T.die(/* @__PURE__ */ Error(`applyPlan: refusing to execute — ${r.length} blocked operations. Run \`voltro db plan\` to see the fixes.`));
|
|
3264
|
+
let i = Date.now(), a = [], o = He(e), s = yield* n.replan(e), c = new Set(t.operations.filter((e) => !e.blocked).map((e) => ha(e))), l = {
|
|
3081
3265
|
...s,
|
|
3082
3266
|
operations: s.operations.map((e) => {
|
|
3083
|
-
if (!e.blocked || !c.has(
|
|
3267
|
+
if (!e.blocked || !c.has(ha(e))) return e;
|
|
3084
3268
|
let { blocked: t, ...n } = e;
|
|
3085
3269
|
return n;
|
|
3086
3270
|
})
|
|
3087
3271
|
};
|
|
3088
|
-
(l.operations.length !== t.operations.length || l.toFingerprint !== t.toFingerprint) && (yield*
|
|
3272
|
+
(l.operations.length !== t.operations.length || l.toFingerprint !== t.toFingerprint) && (yield* T.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(T.annotateLogs({ scope: "voltro:migrate" })));
|
|
3089
3273
|
let u = l.operations.filter((e) => e.blocked);
|
|
3090
|
-
if (u.length > 0) return yield*
|
|
3091
|
-
let d =
|
|
3274
|
+
if (u.length > 0) return yield* T.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.`));
|
|
3275
|
+
let d = We(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) => ({
|
|
3092
3276
|
index: t,
|
|
3093
3277
|
planned: e
|
|
3094
3278
|
})), _ = "fresh";
|
|
3095
|
-
yield*
|
|
3096
|
-
let v = yield*
|
|
3279
|
+
yield* ma(e, l, o), yield* aa(e, o);
|
|
3280
|
+
let v = yield* oa(e);
|
|
3097
3281
|
if (v.length > 0) {
|
|
3098
|
-
let t = yield*
|
|
3099
|
-
t.kind === "resume" ? (m = t.runId, h = t.ops, _ = "resume") : (yield*
|
|
3282
|
+
let t = yield* pa(e, o, l, v);
|
|
3283
|
+
t.kind === "resume" ? (m = t.runId, h = t.ops, _ = "resume") : (yield* T.logWarning(`migration resume: discarding the ledger of run ${t.runId} — ${t.why}`).pipe(T.annotateLogs({ scope: "voltro:migrate" })), yield* ua(e, t.runId));
|
|
3100
3284
|
}
|
|
3101
|
-
_ === "fresh" && h.length > 0 && (yield*
|
|
3285
|
+
_ === "fresh" && h.length > 0 && (yield* sa(e, m, l.toFingerprint, h)), f.length > 0 && (yield* Pr(e, T.gen(function* () {
|
|
3102
3286
|
let e = yield* E.SqlClient;
|
|
3103
|
-
for (let t of f) a.push(yield*
|
|
3287
|
+
for (let t of f) a.push(yield* fa(e, t, n));
|
|
3104
3288
|
})));
|
|
3105
3289
|
for (let { index: t, planned: r } of h) {
|
|
3106
|
-
yield*
|
|
3107
|
-
let i = a.length, o = yield*
|
|
3108
|
-
a.push(o), yield*
|
|
3290
|
+
yield* ca(e, m, t, "started");
|
|
3291
|
+
let i = a.length, o = yield* fa(e, r, n, _).pipe(T.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`) })));
|
|
3292
|
+
a.push(o), yield* ca(e, m, t, "applied", o.durationMs);
|
|
3109
3293
|
}
|
|
3110
3294
|
let y = yield* n.replan(e);
|
|
3111
3295
|
if (y.operations.length > 0) {
|
|
3112
3296
|
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");
|
|
3113
|
-
return yield*
|
|
3297
|
+
return yield* T.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.`));
|
|
3114
3298
|
}
|
|
3115
|
-
let b = a.filter((e) => e.status === "applied").length, x = Date.now() - i, S = m, C = (/* @__PURE__ */ new Date()).toISOString(),
|
|
3299
|
+
let b = a.filter((e) => e.status === "applied").length, x = Date.now() - i, S = m, C = (/* @__PURE__ */ new Date()).toISOString(), w = yield* W(e, C), ee = [...f, ...h.map((e) => e.planned)];
|
|
3116
3300
|
yield* e`
|
|
3117
3301
|
INSERT INTO ${e("_voltro_migration_plans")}
|
|
3118
3302
|
(${e("id")}, ${e("fingerprint")}, ${e("liveFingerprint")}, ${e("operations")},
|
|
@@ -3121,10 +3305,10 @@ BEGIN
|
|
|
3121
3305
|
VALUES
|
|
3122
3306
|
(${S}, ${l.toFingerprint}, ${y.fromFingerprint}, ${JSON.stringify(ee)},
|
|
3123
3307
|
${n.appliedBy}, ${n.environment}, ${n.source},
|
|
3124
|
-
${x}, ${
|
|
3125
|
-
`, yield*
|
|
3308
|
+
${x}, ${w}, ${n.notes ?? null})
|
|
3309
|
+
`, yield* ua(e, m);
|
|
3126
3310
|
let te = [...new Set(ee.flatMap((e) => e.op.kind === "rename-table" ? [e.op.to] : [e.op.table]))];
|
|
3127
|
-
return yield*
|
|
3311
|
+
return yield* T.promise(() => g({ changedTables: te }).catch(() => {})), {
|
|
3128
3312
|
id: S,
|
|
3129
3313
|
appliedAt: C,
|
|
3130
3314
|
fingerprint: l.toFingerprint,
|
|
@@ -3136,14 +3320,14 @@ BEGIN
|
|
|
3136
3320
|
source: n.source,
|
|
3137
3321
|
...n.notes ? { notes: n.notes } : {}
|
|
3138
3322
|
};
|
|
3139
|
-
}),
|
|
3323
|
+
}), va = (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"), ya = (e) => e`
|
|
3140
3324
|
SELECT fingerprint
|
|
3141
3325
|
FROM _voltro_migration_plans
|
|
3142
3326
|
ORDER BY ${e("appliedAt")} DESC
|
|
3143
3327
|
LIMIT 1
|
|
3144
|
-
`.pipe(
|
|
3145
|
-
if ((yield*
|
|
3146
|
-
let r = `plan_${Date.now().toString(36)}`, i = yield*
|
|
3328
|
+
`.pipe(T.map((e) => e.length > 0 ? e[0].fingerprint : void 0), T.catchAll(() => T.succeed(void 0))), ba = (e, t, n) => T.gen(function* () {
|
|
3329
|
+
if ((yield* ya(e)) === t.toFingerprint) return "already-current";
|
|
3330
|
+
let r = `plan_${Date.now().toString(36)}`, i = yield* W(e, (/* @__PURE__ */ new Date()).toISOString());
|
|
3147
3331
|
return yield* e`
|
|
3148
3332
|
INSERT INTO ${e("_voltro_migration_plans")}
|
|
3149
3333
|
(${e("id")}, ${e("fingerprint")}, ${e("liveFingerprint")}, ${e("operations")},
|
|
@@ -3154,8 +3338,8 @@ BEGIN
|
|
|
3154
3338
|
${n.appliedBy}, ${n.environment}, ${n.source},
|
|
3155
3339
|
${0}, ${i}, ${"no DDL — the declared schema already matched the database"})
|
|
3156
3340
|
`, "recorded";
|
|
3157
|
-
}).pipe(
|
|
3158
|
-
let n =
|
|
3341
|
+
}).pipe(T.catchAll(() => T.succeed("already-current"))), xa = (e, t) => T.gen(function* () {
|
|
3342
|
+
let n = R(z(t, He(e))), r = yield* ya(e);
|
|
3159
3343
|
return r === n ? {
|
|
3160
3344
|
kind: "up-to-date",
|
|
3161
3345
|
fingerprint: n
|
|
@@ -3164,23 +3348,23 @@ BEGIN
|
|
|
3164
3348
|
expected: n,
|
|
3165
3349
|
...r === void 0 ? {} : { actual: r }
|
|
3166
3350
|
};
|
|
3167
|
-
}),
|
|
3351
|
+
}), Sa = [
|
|
3168
3352
|
"pgeagertest_",
|
|
3169
3353
|
"mig_e2e_",
|
|
3170
3354
|
"mig_test_",
|
|
3171
3355
|
"mysqleagertest_",
|
|
3172
3356
|
"mssqleagertest_",
|
|
3173
3357
|
"sqliteeagertest_"
|
|
3174
|
-
],
|
|
3358
|
+
], Ca = (e) => Sa.some((t) => e.startsWith(t)), wa = (e, t) => T.gen(function* () {
|
|
3175
3359
|
if (process.env.VOLTRO_TEST_FIXTURE_GC === "off") return [];
|
|
3176
|
-
let n = t.filter((e) =>
|
|
3360
|
+
let n = t.filter((e) => Ca(e.name)).map((e) => e.name);
|
|
3177
3361
|
if (n.length === 0) return [];
|
|
3178
|
-
for (let t of n) yield* e.unsafe(`DROP TABLE IF EXISTS "${t}" CASCADE`).pipe(
|
|
3362
|
+
for (let t of n) yield* e.unsafe(`DROP TABLE IF EXISTS "${t}" CASCADE`).pipe(T.catchAll(() => T.void));
|
|
3179
3363
|
return n;
|
|
3180
|
-
}),
|
|
3364
|
+
}), Ta = () => {
|
|
3181
3365
|
let e = (process.env.VOLTRO_DB_IGNORE_TABLES ?? "").split(",").map((e) => e.trim()).filter((e) => e.length > 0);
|
|
3182
3366
|
return e.length > 0 ? { ignoreTables: e } : {};
|
|
3183
|
-
},
|
|
3367
|
+
}, Ea = (e) => {
|
|
3184
3368
|
if (e === void 0) return;
|
|
3185
3369
|
let t = e.trim();
|
|
3186
3370
|
if (t === "") return;
|
|
@@ -3190,55 +3374,55 @@ BEGIN
|
|
|
3190
3374
|
kind: "tables",
|
|
3191
3375
|
tables: new Set(n)
|
|
3192
3376
|
} : void 0;
|
|
3193
|
-
},
|
|
3377
|
+
}, Da = (e) => typeof e.table == "string" ? e.table : void 0, Oa = (e, t = { kind: "all" }) => ({
|
|
3194
3378
|
...e,
|
|
3195
3379
|
operations: e.operations.map((e) => {
|
|
3196
3380
|
if (!e.blocked || e.classification !== "lossy") return e;
|
|
3197
3381
|
if (t?.kind === "tables") {
|
|
3198
|
-
let n =
|
|
3382
|
+
let n = Da(e.op);
|
|
3199
3383
|
if (n === void 0 || !t.tables.has(n)) return e;
|
|
3200
3384
|
}
|
|
3201
3385
|
let { blocked: n, ...r } = e;
|
|
3202
3386
|
return r;
|
|
3203
3387
|
})
|
|
3204
|
-
}),
|
|
3205
|
-
let t =
|
|
3206
|
-
return t === void 0 ?
|
|
3207
|
-
}),
|
|
3208
|
-
let r =
|
|
3388
|
+
}), ka = (e, t, n) => t === "postgres" ? bn(e, n).pipe(T.flatMap((e) => {
|
|
3389
|
+
let t = xn(e);
|
|
3390
|
+
return t === void 0 ? T.void : T.logWarning(`auto-migrate: ${t}`).pipe(T.annotateLogs({ scope: "voltro:migrate" }));
|
|
3391
|
+
}), T.catchAll(() => T.void)) : T.void, Aa = (e, t, n) => T.gen(function* () {
|
|
3392
|
+
let r = He(e), a = t;
|
|
3209
3393
|
if (process.env.VOLTRO_MIGRATE_FORCE !== "1") {
|
|
3210
|
-
let t =
|
|
3211
|
-
if ((yield*
|
|
3394
|
+
let t = R(z(a, r));
|
|
3395
|
+
if ((yield* ya(e)) === t) return yield* ka(e, r, a), {
|
|
3212
3396
|
kind: "up-to-date",
|
|
3213
3397
|
fingerprint: t
|
|
3214
3398
|
};
|
|
3215
3399
|
}
|
|
3216
|
-
let o = yield*
|
|
3217
|
-
s.length > 0 && (yield*
|
|
3400
|
+
let o = yield* Sr(e), s = yield* wa(e, o.tables);
|
|
3401
|
+
s.length > 0 && (yield* T.logInfo(`auto-migrate: reaped ${s.length} test-fixture leftover(s)`).pipe(T.annotateLogs({
|
|
3218
3402
|
scope: "voltro:migrate",
|
|
3219
3403
|
count: s.length
|
|
3220
|
-
})), o = yield*
|
|
3404
|
+
})), o = yield* Sr(e));
|
|
3221
3405
|
{
|
|
3222
3406
|
let e = n.softDropRetentionDays ?? 7, t = p(o, { retentionDays: e });
|
|
3223
|
-
t.length > 0 && (yield*
|
|
3407
|
+
t.length > 0 && (yield* T.logWarning(`auto-migrate: ${i(t, e)}`).pipe(T.annotateLogs({
|
|
3224
3408
|
scope: "voltro:migrate",
|
|
3225
3409
|
snapshots: t.map((e) => e.name)
|
|
3226
3410
|
})));
|
|
3227
3411
|
}
|
|
3228
|
-
let c = new Set(t.map((e) => e.tableName)), l = (e) => e.filter((e) => !_(e.name) || c.has(e.name)), u =
|
|
3412
|
+
let c = new Set(t.map((e) => e.tableName)), l = (e) => e.filter((e) => !_(e.name) || c.has(e.name)), u = $n({
|
|
3229
3413
|
declared: a,
|
|
3230
3414
|
live: { tables: l(o.tables) },
|
|
3231
3415
|
dialect: r,
|
|
3232
|
-
...
|
|
3416
|
+
...Ta()
|
|
3233
3417
|
});
|
|
3234
3418
|
if (u.summary.blocked > 0) {
|
|
3235
|
-
let e = u.operations.filter((e) => e.blocked).every((e) => e.classification === "lossy"), t =
|
|
3236
|
-
if (t === void 0 || !e || (u =
|
|
3419
|
+
let e = u.operations.filter((e) => e.blocked).every((e) => e.classification === "lossy"), t = Ea(process.env.VOLTRO_DESTRUCTIVE_OK);
|
|
3420
|
+
if (t === void 0 || !e || (u = Oa(u, t), u.operations.some((e) => e.blocked))) return {
|
|
3237
3421
|
kind: "refused-blocked",
|
|
3238
3422
|
plan: u
|
|
3239
3423
|
};
|
|
3240
3424
|
}
|
|
3241
|
-
return u.operations.length === 0 ? (yield*
|
|
3425
|
+
return u.operations.length === 0 ? (yield* ba(e, u, {
|
|
3242
3426
|
appliedBy: n.appliedBy,
|
|
3243
3427
|
environment: n.environment === "prod" ? "dev" : n.environment,
|
|
3244
3428
|
source: "auto-diff"
|
|
@@ -3247,37 +3431,37 @@ BEGIN
|
|
|
3247
3431
|
fingerprint: u.toFingerprint
|
|
3248
3432
|
}) : {
|
|
3249
3433
|
kind: "applied",
|
|
3250
|
-
applied: yield*
|
|
3434
|
+
applied: yield* ga(e, u, {
|
|
3251
3435
|
declared: t,
|
|
3252
3436
|
appliedBy: n.appliedBy,
|
|
3253
3437
|
environment: n.environment === "prod" ? "dev" : n.environment,
|
|
3254
3438
|
source: "auto-diff",
|
|
3255
|
-
replan: (e) =>
|
|
3256
|
-
let t = yield*
|
|
3257
|
-
return
|
|
3439
|
+
replan: (e) => T.gen(function* () {
|
|
3440
|
+
let t = yield* Sr(e);
|
|
3441
|
+
return $n({
|
|
3258
3442
|
declared: a,
|
|
3259
3443
|
live: { tables: l(t.tables) },
|
|
3260
3444
|
dialect: r,
|
|
3261
|
-
...
|
|
3445
|
+
...Ta()
|
|
3262
3446
|
});
|
|
3263
3447
|
})
|
|
3264
3448
|
}),
|
|
3265
3449
|
plan: u
|
|
3266
3450
|
};
|
|
3267
|
-
}),
|
|
3451
|
+
}), ja = (e, t, n) => process.env.VOLTRO_AUTO_MIGRATE === "0" ? T.succeed({
|
|
3268
3452
|
kind: "skipped",
|
|
3269
3453
|
reason: "VOLTRO_AUTO_MIGRATE=0"
|
|
3270
|
-
}) : n.environment === "prod" ?
|
|
3454
|
+
}) : n.environment === "prod" ? xa(e, t) : Aa(e, t, n), Ma = (e, t) => {
|
|
3271
3455
|
switch (e.kind) {
|
|
3272
3456
|
case "skipped": return `auto-migrate: skipped (${e.reason})`;
|
|
3273
|
-
case "up-to-date": return `auto-migrate: schema up to date (${t}, fingerprint=${
|
|
3457
|
+
case "up-to-date": return `auto-migrate: schema up to date (${t}, fingerprint=${mn(e.fingerprint)})`;
|
|
3274
3458
|
case "applied": {
|
|
3275
3459
|
let t = e.plan.summary;
|
|
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=${
|
|
3460
|
+
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=${mn(e.applied.fingerprint)}`;
|
|
3277
3461
|
}
|
|
3278
|
-
case "prod-mismatch": return `auto-migrate: SCHEMA FINGERPRINT MISMATCH — declared=${
|
|
3462
|
+
case "prod-mismatch": return `auto-migrate: SCHEMA FINGERPRINT MISMATCH — declared=${mn(e.expected)}` + (e.actual ? ` live=${mn(e.actual)}` : " live=<no _voltro_migration_plans row>") + ". Run `voltro db apply --plan plan.json` from the deploy pipeline before serving.";
|
|
3279
3463
|
case "refused-blocked": {
|
|
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` +
|
|
3464
|
+
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` + va(e.plan), c = [""];
|
|
3281
3465
|
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) {
|
|
3282
3466
|
let t = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map();
|
|
3283
3467
|
for (let r of e.plan.operations) {
|
|
@@ -3294,7 +3478,7 @@ BEGIN
|
|
|
3294
3478
|
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");
|
|
3295
3479
|
}
|
|
3296
3480
|
}
|
|
3297
|
-
},
|
|
3481
|
+
}, Na = ae({ scope: "voltro:migrate" }), Pa = /* @__PURE__ */ new Set([
|
|
3298
3482
|
"node_modules",
|
|
3299
3483
|
"dist",
|
|
3300
3484
|
"build",
|
|
@@ -3303,12 +3487,12 @@ BEGIN
|
|
|
3303
3487
|
".next",
|
|
3304
3488
|
".git",
|
|
3305
3489
|
".framework"
|
|
3306
|
-
]),
|
|
3490
|
+
]), Fa = async (e) => {
|
|
3307
3491
|
let t = [], n = async (e) => {
|
|
3308
|
-
let r = await
|
|
3492
|
+
let r = await oe.readdir(e, { withFileTypes: !0 }).catch(() => []);
|
|
3309
3493
|
for (let i of r) {
|
|
3310
|
-
if (
|
|
3311
|
-
let r =
|
|
3494
|
+
if (Pa.has(i.name)) continue;
|
|
3495
|
+
let r = se(e, i.name);
|
|
3312
3496
|
i.isDirectory() ? await n(r) : i.isFile() && S.test(i.name) && t.push(r);
|
|
3313
3497
|
}
|
|
3314
3498
|
};
|
|
@@ -3316,12 +3500,12 @@ BEGIN
|
|
|
3316
3500
|
let n = e.split("/").pop() ?? e, r = t.split("/").pop() ?? t;
|
|
3317
3501
|
return n.localeCompare(r);
|
|
3318
3502
|
});
|
|
3319
|
-
},
|
|
3503
|
+
}, Ia = async (e) => {
|
|
3320
3504
|
let t = [];
|
|
3321
3505
|
for (let n of e) {
|
|
3322
|
-
let e = (await import(
|
|
3506
|
+
let e = (await import(ce(n).href)).default;
|
|
3323
3507
|
if (!u(e)) {
|
|
3324
|
-
|
|
3508
|
+
Na.warn("migration file has no default-exported `migration(...)` — skipped", { file: n });
|
|
3325
3509
|
continue;
|
|
3326
3510
|
}
|
|
3327
3511
|
t.push({
|
|
@@ -3330,11 +3514,11 @@ BEGIN
|
|
|
3330
3514
|
});
|
|
3331
3515
|
}
|
|
3332
3516
|
return t;
|
|
3333
|
-
},
|
|
3517
|
+
}, La = (e) => e`
|
|
3334
3518
|
SELECT ${e("id")}
|
|
3335
3519
|
FROM ${e("_voltro_migration_plans")}
|
|
3336
3520
|
WHERE ${e("source")} = 'file'
|
|
3337
|
-
`.pipe(
|
|
3521
|
+
`.pipe(T.map((e) => e.map((e) => e.id)), T.catchAll(() => T.succeed([]))), Ra = class extends Error {
|
|
3338
3522
|
migrationId;
|
|
3339
3523
|
file;
|
|
3340
3524
|
cause;
|
|
@@ -3342,28 +3526,28 @@ BEGIN
|
|
|
3342
3526
|
constructor(e, t, n) {
|
|
3343
3527
|
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";
|
|
3344
3528
|
}
|
|
3345
|
-
},
|
|
3529
|
+
}, za = (e, t, n, r) => T.gen(function* () {
|
|
3346
3530
|
let i = Date.now(), a = (/* @__PURE__ */ new Date()).toISOString(), o = {
|
|
3347
3531
|
sql: e,
|
|
3348
3532
|
log: {
|
|
3349
|
-
info: (e, n) =>
|
|
3533
|
+
info: (e, n) => T.logInfo(e).pipe(T.annotateLogs({
|
|
3350
3534
|
scope: `migrations:file:${t.migration.id}`,
|
|
3351
3535
|
...n ?? {}
|
|
3352
3536
|
})),
|
|
3353
|
-
warn: (e, n) =>
|
|
3537
|
+
warn: (e, n) => T.logWarning(e).pipe(T.annotateLogs({
|
|
3354
3538
|
scope: `migrations:file:${t.migration.id}`,
|
|
3355
3539
|
...n ?? {}
|
|
3356
3540
|
}))
|
|
3357
3541
|
},
|
|
3358
3542
|
appliedAt: a
|
|
3359
3543
|
}, s = t.migration.up(o);
|
|
3360
|
-
|
|
3544
|
+
T.isEffect(s) ? yield* s : yield* T.tryPromise({
|
|
3361
3545
|
try: () => s,
|
|
3362
3546
|
catch: (e) => e
|
|
3363
3547
|
});
|
|
3364
3548
|
let c = Date.now() - i;
|
|
3365
|
-
!
|
|
3366
|
-
let l = yield*
|
|
3549
|
+
!T.isEffect(s) && c < 2 && (yield* T.logWarning(`migration ${t.migration.id}: up() resolved in ${c}ms — did the body \`await\` an \`@effect/sql\` Effect by accident? \`sql.unsafe(...)\` returns an Effect, not a Promise; \`await\` on it is a silent no-op. Switch the body to \`Effect.gen(function* () { yield* sql.unsafe(...) })\` form.`).pipe(T.annotateLogs({ scope: `migrations:file:${t.migration.id}` })));
|
|
3550
|
+
let l = yield* W(e, a);
|
|
3367
3551
|
return yield* e`
|
|
3368
3552
|
INSERT INTO ${e("_voltro_migration_plans")}
|
|
3369
3553
|
(${e("id")}, ${e("fingerprint")}, ${e("operations")},
|
|
@@ -3376,87 +3560,87 @@ BEGIN
|
|
|
3376
3560
|
}])},
|
|
3377
3561
|
${r}, ${n}, ${"file"},
|
|
3378
3562
|
${c}, ${l}, ${t.migration.description})
|
|
3379
|
-
`.pipe(
|
|
3380
|
-
}),
|
|
3381
|
-
let n = yield*
|
|
3382
|
-
try: () =>
|
|
3563
|
+
`.pipe(T.mapError((e) => new Ra(t.migration.id, t.file, e))), { durationMs: c };
|
|
3564
|
+
}), Ba = (e, t) => T.gen(function* () {
|
|
3565
|
+
let n = yield* T.tryPromise({
|
|
3566
|
+
try: () => Fa(se(t, "migrations")),
|
|
3383
3567
|
catch: (e) => e
|
|
3384
3568
|
});
|
|
3385
3569
|
if (n.length === 0) return {
|
|
3386
3570
|
pending: [],
|
|
3387
3571
|
skipped: []
|
|
3388
3572
|
};
|
|
3389
|
-
let r = yield*
|
|
3390
|
-
try: () =>
|
|
3573
|
+
let r = yield* T.tryPromise({
|
|
3574
|
+
try: () => Ia(n),
|
|
3391
3575
|
catch: (e) => e
|
|
3392
3576
|
});
|
|
3393
3577
|
if (r.length === 0) return {
|
|
3394
3578
|
pending: [],
|
|
3395
3579
|
skipped: []
|
|
3396
3580
|
};
|
|
3397
|
-
let i = new Set(yield*
|
|
3581
|
+
let i = new Set(yield* La(e));
|
|
3398
3582
|
return {
|
|
3399
3583
|
pending: r.filter((e) => !i.has(e.migration.id)),
|
|
3400
3584
|
skipped: r.filter((e) => i.has(e.migration.id)).map((e) => e.migration.id)
|
|
3401
3585
|
};
|
|
3402
|
-
}),
|
|
3403
|
-
let { pending: n, skipped: r } = yield*
|
|
3586
|
+
}), Va = (e, t) => Ba(e, t).pipe(T.map((e) => e.pending.map((e) => e.migration.id))), Ha = (e, t) => T.gen(function* () {
|
|
3587
|
+
let { pending: n, skipped: r } = yield* Ba(e, t.projectRoot);
|
|
3404
3588
|
return n.length === 0 ? {
|
|
3405
3589
|
applied: [],
|
|
3406
3590
|
skipped: r
|
|
3407
3591
|
} : {
|
|
3408
|
-
applied: yield*
|
|
3592
|
+
applied: yield* T.acquireUseRelease(Be(e, { schema: t.lockSchema }), () => T.gen(function* () {
|
|
3409
3593
|
let r = [];
|
|
3410
3594
|
for (let i of n) {
|
|
3411
|
-
yield*
|
|
3595
|
+
yield* T.logInfo("file-based migration applying").pipe(T.annotateLogs({
|
|
3412
3596
|
scope: "voltro:migrate",
|
|
3413
3597
|
id: i.migration.id,
|
|
3414
3598
|
file: i.file
|
|
3415
3599
|
}));
|
|
3416
|
-
let { durationMs: n } = yield*
|
|
3600
|
+
let { durationMs: n } = yield* za(e, i, t.env, t.appliedBy);
|
|
3417
3601
|
r.push({
|
|
3418
3602
|
id: i.migration.id,
|
|
3419
3603
|
durationMs: n
|
|
3420
|
-
}), yield*
|
|
3604
|
+
}), yield* T.logInfo("file-based migration applied").pipe(T.annotateLogs({
|
|
3421
3605
|
scope: "voltro:migrate",
|
|
3422
3606
|
id: i.migration.id,
|
|
3423
3607
|
durationMs: n
|
|
3424
3608
|
}));
|
|
3425
3609
|
}
|
|
3426
3610
|
return r;
|
|
3427
|
-
}), (e) => e.release.pipe(
|
|
3611
|
+
}), (e) => e.release.pipe(T.orDie)),
|
|
3428
3612
|
skipped: r
|
|
3429
3613
|
};
|
|
3430
|
-
}),
|
|
3614
|
+
}), Ua = (e, t) => e`
|
|
3431
3615
|
SELECT ${e("id")}
|
|
3432
3616
|
FROM ${e("_voltro_migration_plans")}
|
|
3433
3617
|
WHERE ${e("id")} = ${t} AND ${e("source")} = 'file'
|
|
3434
3618
|
LIMIT 1
|
|
3435
|
-
`,
|
|
3436
|
-
if (!(yield*
|
|
3437
|
-
let n = yield*
|
|
3438
|
-
try: () =>
|
|
3619
|
+
`, Wa = (e, t) => T.gen(function* () {
|
|
3620
|
+
if (!(yield* Ua(e, t.id))[0]) return yield* T.fail(/* @__PURE__ */ Error(`rollback: ${t.id} not found in _voltro_migration_plans (file source)`));
|
|
3621
|
+
let n = yield* T.tryPromise({
|
|
3622
|
+
try: () => Fa(se(t.projectRoot, "migrations")),
|
|
3439
3623
|
catch: (e) => e
|
|
3440
|
-
}), r = (yield*
|
|
3441
|
-
try: () =>
|
|
3624
|
+
}), r = (yield* T.tryPromise({
|
|
3625
|
+
try: () => Ia(n),
|
|
3442
3626
|
catch: (e) => e
|
|
3443
3627
|
})).find((e) => e.migration.id === t.id);
|
|
3444
|
-
return r ? yield*
|
|
3628
|
+
return r ? yield* T.acquireUseRelease(Be(e, { schema: t.lockSchema }), () => T.gen(function* () {
|
|
3445
3629
|
let n = Date.now(), i = {
|
|
3446
3630
|
sql: e,
|
|
3447
3631
|
log: {
|
|
3448
|
-
info: (e, n) =>
|
|
3632
|
+
info: (e, n) => T.logInfo(e).pipe(T.annotateLogs({
|
|
3449
3633
|
scope: `migrations:file:${t.id}`,
|
|
3450
3634
|
...n ?? {}
|
|
3451
3635
|
})),
|
|
3452
|
-
warn: (e, n) =>
|
|
3636
|
+
warn: (e, n) => T.logWarning(e).pipe(T.annotateLogs({
|
|
3453
3637
|
scope: `migrations:file:${t.id}`,
|
|
3454
3638
|
...n ?? {}
|
|
3455
3639
|
}))
|
|
3456
3640
|
},
|
|
3457
3641
|
appliedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
3458
3642
|
}, a = r.migration.down(i);
|
|
3459
|
-
|
|
3643
|
+
T.isEffect(a) ? yield* a : yield* T.tryPromise({
|
|
3460
3644
|
try: () => a,
|
|
3461
3645
|
catch: (e) => e
|
|
3462
3646
|
});
|
|
@@ -3465,8 +3649,8 @@ BEGIN
|
|
|
3465
3649
|
id: t.id,
|
|
3466
3650
|
durationMs: o
|
|
3467
3651
|
};
|
|
3468
|
-
}), (e) => e.release.pipe(
|
|
3469
|
-
}),
|
|
3652
|
+
}), (e) => e.release.pipe(T.orDie)) : yield* T.fail(/* @__PURE__ */ Error(`rollback: file for migration ${t.id} not found on disk under ${t.projectRoot}/migrations/`));
|
|
3653
|
+
}), Ga = (e) => T.gen(function* () {
|
|
3470
3654
|
let t = yield* E.SqlClient, n = yield* t`
|
|
3471
3655
|
SELECT id, fingerprint, appliedAt FROM _voltro_migration_plans
|
|
3472
3656
|
WHERE source = 'auto-diff'
|
|
@@ -3474,9 +3658,9 @@ BEGIN
|
|
|
3474
3658
|
AND appliedAt < ${e.before}
|
|
3475
3659
|
ORDER BY appliedAt DESC
|
|
3476
3660
|
`;
|
|
3477
|
-
if (n.length === 0) return yield*
|
|
3661
|
+
if (n.length === 0) return yield* T.fail(/* @__PURE__ */ Error(`squash: no rows applied before ${e.before}`));
|
|
3478
3662
|
let r = n[0];
|
|
3479
|
-
if (r.fingerprint !== e.fingerprint) return yield*
|
|
3663
|
+
if (r.fingerprint !== e.fingerprint) return yield* T.fail(/* @__PURE__ */ Error(`squash: latest pre-squash fingerprint (${r.fingerprint.slice(0, 12)}…) differs from current declared-schema fingerprint (${e.fingerprint.slice(0, 12)}…). This means the working tree carries un-applied changes — squashing now would lock the drift in.\n\nFix: run \`voltro db apply\` first to align the live schema with the working tree, then re-squash.`));
|
|
3480
3664
|
yield* t`
|
|
3481
3665
|
UPDATE _voltro_migration_plans
|
|
3482
3666
|
SET squashedAt = CURRENT_TIMESTAMP
|
|
@@ -3511,7 +3695,7 @@ BEGIN
|
|
|
3511
3695
|
snapshotFingerprint: e.fingerprint,
|
|
3512
3696
|
snapshotId: i
|
|
3513
3697
|
};
|
|
3514
|
-
}),
|
|
3698
|
+
}), Ka = { safe: !0 }, qa = (e) => {
|
|
3515
3699
|
switch (e.kind) {
|
|
3516
3700
|
case "drop-column": return {
|
|
3517
3701
|
safe: !1,
|
|
@@ -3538,7 +3722,7 @@ BEGIN
|
|
|
3538
3722
|
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`,
|
|
3539
3723
|
remedy: "add a new column of the target type + backfill + dual-write, cut code over, then drop the old column in a LATER deploy"
|
|
3540
3724
|
};
|
|
3541
|
-
case "alter-column-nullability": return e.toNullable ?
|
|
3725
|
+
case "alter-column-nullability": return e.toNullable ? Ka : {
|
|
3542
3726
|
safe: !1,
|
|
3543
3727
|
reason: `old instances may INSERT "${e.table}" without (or with NULL in) "${e.column}", which the new NOT NULL rejects`,
|
|
3544
3728
|
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)`
|
|
@@ -3549,6 +3733,11 @@ BEGIN
|
|
|
3549
3733
|
reason: `old instances still write "${e.table}" without honouring the new uniqueness; a colliding insert now fails mid-rollout`,
|
|
3550
3734
|
remedy: "make code enforce uniqueness first and deploy that; add the constraint in a LATER deploy once no old writer remains"
|
|
3551
3735
|
};
|
|
3736
|
+
case "reconcile-json-check": return e.previousValidation === "container" && e.validation === "value" ? Ka : {
|
|
3737
|
+
safe: !1,
|
|
3738
|
+
reason: `writes to "${e.table}"."${e.column}" must satisfy the new JSON validation`,
|
|
3739
|
+
remedy: "ensure all writers supply valid JSON in the required domain before enabling this check"
|
|
3740
|
+
};
|
|
3552
3741
|
case "add-check": return {
|
|
3553
3742
|
safe: !1,
|
|
3554
3743
|
reason: `old instances may write values to "${e.table}" the new CHECK rejects`,
|
|
@@ -3568,12 +3757,12 @@ BEGIN
|
|
|
3568
3757
|
case "drop-unique":
|
|
3569
3758
|
case "drop-unique-composite":
|
|
3570
3759
|
case "drop-foreign-key":
|
|
3571
|
-
case "drop-check": return
|
|
3760
|
+
case "drop-check": return Ka;
|
|
3572
3761
|
}
|
|
3573
|
-
},
|
|
3762
|
+
}, Ja = (e) => {
|
|
3574
3763
|
let t = [];
|
|
3575
3764
|
for (let n of e) {
|
|
3576
|
-
let e =
|
|
3765
|
+
let e = qa(n.op);
|
|
3577
3766
|
e.safe || t.push({
|
|
3578
3767
|
op: n,
|
|
3579
3768
|
reason: e.reason,
|
|
@@ -3581,7 +3770,7 @@ BEGIN
|
|
|
3581
3770
|
});
|
|
3582
3771
|
}
|
|
3583
3772
|
return t;
|
|
3584
|
-
},
|
|
3773
|
+
}, Ya = (e) => {
|
|
3585
3774
|
if (!e.enabled || e.unsafeCount === 0) return {
|
|
3586
3775
|
refuse: !1,
|
|
3587
3776
|
warnForced: !1,
|
|
@@ -3597,18 +3786,18 @@ BEGIN
|
|
|
3597
3786
|
warnForced: !1,
|
|
3598
3787
|
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.`
|
|
3599
3788
|
};
|
|
3600
|
-
},
|
|
3789
|
+
}, Xa = (e) => {
|
|
3601
3790
|
let t = e.table;
|
|
3602
3791
|
if (typeof t == "string") return t;
|
|
3603
3792
|
let n = e.from;
|
|
3604
3793
|
return typeof n == "string" ? n : void 0;
|
|
3605
|
-
},
|
|
3794
|
+
}, Za = (e) => ({
|
|
3606
3795
|
kind: e.op.kind,
|
|
3607
|
-
table:
|
|
3796
|
+
table: Xa(e.op),
|
|
3608
3797
|
classification: e.classification,
|
|
3609
3798
|
reason: e.reason,
|
|
3610
3799
|
blockedFix: e.blocked?.fix
|
|
3611
|
-
}),
|
|
3800
|
+
}), Qa = (e) => e.operations.map(Za), $a = async (e) => {
|
|
3612
3801
|
let t = e.log ?? (() => {}), n = {
|
|
3613
3802
|
branchId: e.branchId,
|
|
3614
3803
|
mechanism: e.mechanism,
|
|
@@ -3627,10 +3816,10 @@ BEGIN
|
|
|
3627
3816
|
applied: !1,
|
|
3628
3817
|
converged: !1,
|
|
3629
3818
|
residual: r,
|
|
3630
|
-
infidelity:
|
|
3819
|
+
infidelity: Qa(o)
|
|
3631
3820
|
};
|
|
3632
3821
|
else {
|
|
3633
|
-
let i = await e.plan(), o =
|
|
3822
|
+
let i = await e.plan(), o = Qa(i), s = o.filter((e) => e.classification === "lossy"), c = Oa(i), l = c.operations.filter((e) => e.blocked !== void 0).map(Za);
|
|
3634
3823
|
if (l.length > 0) a = {
|
|
3635
3824
|
...n,
|
|
3636
3825
|
outcome: "blocked",
|
|
@@ -3655,7 +3844,7 @@ BEGIN
|
|
|
3655
3844
|
};
|
|
3656
3845
|
else {
|
|
3657
3846
|
await e.apply(c), t(`branch ${e.branchId}: applied ${o.length} operation(s)`);
|
|
3658
|
-
let i =
|
|
3847
|
+
let i = Qa(await e.replan());
|
|
3659
3848
|
a = {
|
|
3660
3849
|
...n,
|
|
3661
3850
|
outcome: i.length > 0 ? "diverged" : s.length > 0 ? "lossy" : "clean",
|
|
@@ -3693,7 +3882,7 @@ BEGIN
|
|
|
3693
3882
|
...a,
|
|
3694
3883
|
tornDown: o
|
|
3695
3884
|
};
|
|
3696
|
-
},
|
|
3885
|
+
}, eo = (e) => {
|
|
3697
3886
|
switch (e.outcome) {
|
|
3698
3887
|
case "clean": return 0;
|
|
3699
3888
|
case "lossy": return 2;
|
|
@@ -3702,22 +3891,22 @@ BEGIN
|
|
|
3702
3891
|
case "infidelity": return 1;
|
|
3703
3892
|
case "failed": return 1;
|
|
3704
3893
|
}
|
|
3705
|
-
},
|
|
3894
|
+
}, to = (e) => ` ${e.classification === "lossy" ? "✗" : "•"} ${e.kind}${e.table ? ` ${e.table}` : ""} [${e.classification}]${e.reason ? ` — ${e.reason}` : ""}${e.blockedFix ? `\n ! ${e.blockedFix}` : ""}`, no = (e) => {
|
|
3706
3895
|
let t = [];
|
|
3707
3896
|
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"}`);
|
|
3708
3897
|
else if (e.outcome === "infidelity") {
|
|
3709
3898
|
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:");
|
|
3710
|
-
for (let n of e.infidelity) t.push(
|
|
3899
|
+
for (let n of e.infidelity) t.push(to(n));
|
|
3711
3900
|
} else {
|
|
3712
3901
|
t.push(` plan: ${e.operations.length} operation(s), ${e.lossy.length} lossy, ${e.blocked.length} refused`);
|
|
3713
|
-
for (let n of e.operations) t.push(
|
|
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(
|
|
3902
|
+
for (let n of e.operations) t.push(to(n));
|
|
3903
|
+
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(to(n));
|
|
3715
3904
|
}
|
|
3716
3905
|
return t.push(e.tornDown ? ` branch ${e.branchId} torn down.` : ` branch ${e.branchId} KEPT — drop it when you are done.`), t.join("\n");
|
|
3717
|
-
},
|
|
3906
|
+
}, ro = (e, ...t) => ({
|
|
3718
3907
|
_tag: "RawSqlFragment",
|
|
3719
3908
|
strings: [...e],
|
|
3720
3909
|
values: [...t]
|
|
3721
|
-
}),
|
|
3910
|
+
}), io = (e) => typeof e == "object" && !!e && e._tag === "RawSqlFragment";
|
|
3722
3911
|
//#endregion
|
|
3723
|
-
export {
|
|
3912
|
+
export { j as DEFAULT_CDC_CHANNEL, S as FILE_MIGRATION_PATTERN, Ra as FileMigrationLedgerError, ot as REACTIVE_TRIGGER_PREFIX, be as VOLTRO_MIGRATION_LOCK_KEY, Be as acquireMigrationLock, W as appliedAtValue, Xt as applyNamespacedSchema, ga as applyPlan, Bt as applySchema, Ya as assessRollingDeployGate, eo as branchRehearsalExitCode, cr as chunkTables, qa as classifyRollingDeploySafety, z as declaredSnapshot, pt as defaultArrayClause, ft as defaultClause, P as defaultJsonClause, Ma as describeOutcome, Ea as destructiveScope, bn as detectReactiveTriggerDrift, Ai as emitAddIndexMysql, xi as emitCreateTableMssql, ui as emitCreateTableMysql, ai as emitCreateTablePg, gi as emitCreateTableSqlite, Ur as emitDropColumnDdl, Wr as emitDropColumnDdlMysql, zt as emitFrameworkBootstrapSql, Lt as emitNamespaceProvisionDdl, Rt as emitNamespacedSchemaSql, It as emitSchemaSql, Cr as engineFromVersion, R as fingerprintSchema, Ee as fnv1a64, no as formatBranchRehearsal, xn as formatReactiveTriggerDrift, Ta as ignoreTablesFromEnv, Sr as introspectSchema, kr as isAlreadySatisfied, u as isFileMigration, io as isRawSqlFragment, Ht as isReRunSafeDdl, nr as mapPgType, d as migration, De as migrationLockKeyForSchema, Oe as migrationLockNameForSchema, Ti as mysqlIndexPrefixFor, ct as notifyFunctionName, F as numericIdSql, tr as parseEnumCheck, Va as pendingFileMigrationIds, $n as planMigrations, Zt as provisionTenantNamespace, st as reactiveTriggerName, Dt as reactiveTriggerRepairSql, ba as recordUpToDate, $a as rehearseMigrationOnBranch, Za as rehearsedOperation, ci as renderColumnMysql, ni as renderColumnPg, Se as resolveMigrationLockSchema, Tr as resolveMysqlEngine, Wa as rollbackFileBasedMigration, Ja as rollingDeployUnsafeOps, Ha as runFileBasedMigrations, Qt as runFrameworkBootstrap, Yt as runMigrate, ja as runPlannedMigrations, mn as shortFingerprint, hn as snapshotColumn, ro as sql, N as sqlType, Ga as squashMigrationPlans, Oa as unblockLossy, Ve as withMigrationLock };
|