@voltro/database 0.71.0 → 0.71.1
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 +52 -0
- package/dist/index.js +2 -2
- package/dist/sql.js +676 -672
- package/package.json +2 -2
package/dist/sql.js
CHANGED
|
@@ -20,10 +20,10 @@ var le = (e, t = "float32") => {
|
|
|
20
20
|
efConstruction: i,
|
|
21
21
|
opclass: a.toLowerCase().replace(/^public\./, "")
|
|
22
22
|
};
|
|
23
|
-
}, ue = (e, t) => t === void 0 || t === "postgres" ? e ?? "btree" : e === "hnsw" || e === "gin" && (t === "mysql" || t === "mariadb") ? null : "btree",
|
|
23
|
+
}, ue = (e, t) => t === void 0 || t === "postgres" ? e ?? "btree" : e === "hnsw" || e === "gin" && (t === "mysql" || t === "mariadb") ? null : "btree", de = (e, t) => ({
|
|
24
24
|
...e !== void 0 && e !== "btree" ? { kind: e } : {},
|
|
25
25
|
...e === "hnsw" ? { kindOptions: { hnsw: le(t) } } : {}
|
|
26
|
-
}),
|
|
26
|
+
}), fe = (e, t, n = "float32") => {
|
|
27
27
|
if (e === void 0 || e === "btree") return {
|
|
28
28
|
using: "",
|
|
29
29
|
withSuffix: "",
|
|
@@ -42,7 +42,7 @@ var le = (e, t = "float32") => {
|
|
|
42
42
|
opclass: r.opclass,
|
|
43
43
|
skip: !1
|
|
44
44
|
};
|
|
45
|
-
},
|
|
45
|
+
}, pe = (e, t, n, r = 400) => {
|
|
46
46
|
let i = n, a = i.cause ?? {}, o = (e) => {
|
|
47
47
|
let t = a[e];
|
|
48
48
|
return t == null || t === "" ? void 0 : String(t);
|
|
@@ -73,21 +73,21 @@ var le = (e, t = "float32") => {
|
|
|
73
73
|
let t = o(e);
|
|
74
74
|
t !== void 0 && s.push(`db.${e}: ${t}`);
|
|
75
75
|
}
|
|
76
|
-
let c =
|
|
76
|
+
let c = me(o("code"));
|
|
77
77
|
return c !== void 0 && s.push("", c), s.push(""), s.join("\n");
|
|
78
|
-
},
|
|
79
|
-
if (t !== "mysql" && t !== "mariadb" || !e.appliedIndexes.some(
|
|
78
|
+
}, me = (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, he = (e) => e.unique === !0 && typeof e.where == "string" && e.where.length > 0, ge = (e) => e.replace(/"/g, "`"), _e = (e) => typeof e == "string" ? e : e.name ?? String(e), ve = (e, t) => `_ua_${t}_${e}`.slice(0, 64), ye = (e, t) => {
|
|
79
|
+
if (t !== "mysql" && t !== "mariadb" || !e.appliedIndexes.some(he)) return e;
|
|
80
80
|
let n = { ...e.fields }, r = [], i = [];
|
|
81
81
|
for (let t of e.appliedIndexes) {
|
|
82
|
-
if (!
|
|
82
|
+
if (!he(t)) {
|
|
83
83
|
r.push(t);
|
|
84
84
|
continue;
|
|
85
85
|
}
|
|
86
|
-
let a =
|
|
86
|
+
let a = ge(t.where), o = [];
|
|
87
87
|
for (let r of t.fields) {
|
|
88
|
-
let i =
|
|
88
|
+
let i = _e(r);
|
|
89
89
|
if (!(i in e.fields)) throw Error(`@voltro/migrate: uniqueActive '${t.name}' on '${e.tableName}' references unknown column '${i}'.`);
|
|
90
|
-
let s =
|
|
90
|
+
let s = ve(t.name, i);
|
|
91
91
|
o.push(s), n[s] = {
|
|
92
92
|
type: "text",
|
|
93
93
|
nullable: !0,
|
|
@@ -110,82 +110,82 @@ var le = (e, t = "float32") => {
|
|
|
110
110
|
appliedIndexes: r,
|
|
111
111
|
appliedUniques: [...e.appliedUniques ?? [], ...i]
|
|
112
112
|
};
|
|
113
|
-
},
|
|
113
|
+
}, D = (e, t) => `${e}::${t}`, be = (e, t) => {
|
|
114
114
|
let n = /* @__PURE__ */ new Set(), r = /* @__PURE__ */ new Set(), i = /* @__PURE__ */ new Set(), a = (e) => {
|
|
115
115
|
n.add(e);
|
|
116
116
|
let o = [...t(e)].filter((t) => t.target !== e).sort((e, t) => e.column.localeCompare(t.column));
|
|
117
|
-
for (let t of o) n.has(t.target) ? i.add(
|
|
117
|
+
for (let t of o) n.has(t.target) ? i.add(D(e, t.column)) : r.has(t.target) || a(t.target);
|
|
118
118
|
n.delete(e), r.add(e);
|
|
119
119
|
};
|
|
120
120
|
for (let t of [...e].sort()) r.has(t) || a(t);
|
|
121
121
|
return i;
|
|
122
|
-
},
|
|
122
|
+
}, O = (e, t) => e.executeUnprepared(t, [], void 0), xe = 6322741009312437n, Se = (e) => {
|
|
123
123
|
let t = e?.trim();
|
|
124
124
|
return t === void 0 || t === "" || t === "public" ? void 0 : t;
|
|
125
|
-
},
|
|
126
|
-
let t =
|
|
127
|
-
for (let n of new TextEncoder().encode(e)) t ^= BigInt(n), t = t *
|
|
125
|
+
}, Ce = (e) => e?.schema === void 0 ? Se(process.env.DB_SCHEMA) : Se(e.schema), we = 14695981039346656037n, Te = 1099511628211n, Ee = 18446744073709551615n, De = (e) => {
|
|
126
|
+
let t = we;
|
|
127
|
+
for (let n of new TextEncoder().encode(e)) t ^= BigInt(n), t = t * Te & Ee;
|
|
128
128
|
return t;
|
|
129
|
-
}, De = (e) => {
|
|
130
|
-
let t = xe(e);
|
|
131
|
-
return t === void 0 ? be : Ee(`voltro_migration_lock:${t}`) & 9223372036854775807n;
|
|
132
129
|
}, Oe = (e) => {
|
|
133
|
-
let t =
|
|
130
|
+
let t = Se(e);
|
|
131
|
+
return t === void 0 ? xe : De(`voltro_migration_lock:${t}`) & 9223372036854775807n;
|
|
132
|
+
}, ke = (e) => {
|
|
133
|
+
let t = `voltro_migration_${xe.toString(36)}`, n = Se(e);
|
|
134
134
|
if (n === void 0) return t;
|
|
135
135
|
let r = `${t}_${n}`;
|
|
136
|
-
return /^[A-Za-z0-9_]+$/.test(n) && r.length <= 64 ? r : `${t}_h${(
|
|
137
|
-
},
|
|
136
|
+
return /^[A-Za-z0-9_]+$/.test(n) && r.length <= 64 ? r : `${t}_h${(De(`voltro_migration_lock:${n}`) & Ee).toString(16)}`;
|
|
137
|
+
}, Ae = 250, je = () => {
|
|
138
138
|
let e = Number(process.env.VOLTRO_MIGRATION_LOCK_TIMEOUT_MS);
|
|
139
139
|
return Number.isFinite(e) && e > 0 ? e : 3e4;
|
|
140
|
-
},
|
|
141
|
-
let n =
|
|
140
|
+
}, Me = (e, t) => T.gen(function* () {
|
|
141
|
+
let n = je(), r = Date.now();
|
|
142
142
|
for (;;) {
|
|
143
|
-
if ((yield*
|
|
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(`${
|
|
143
|
+
if ((yield* O(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(`${Ae} millis`);
|
|
145
145
|
}
|
|
146
|
-
}),
|
|
147
|
-
(yield*
|
|
148
|
-
}),
|
|
149
|
-
let n = yield*
|
|
146
|
+
}), Ne = (e, t) => T.asVoid(O(e, `SELECT pg_advisory_unlock(${t.toString()}::bigint)`)), Pe = 30, Fe = (e, t) => T.gen(function* () {
|
|
147
|
+
(yield* O(e, `SELECT GET_LOCK('${t}', ${String(Pe)}) AS got`))[0]?.got !== 1 && (yield* T.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${t}' within ${Pe}s (another migration is in progress, or a prior one left it held).`)));
|
|
148
|
+
}), Ie = (e, t) => T.asVoid(O(e, `SELECT RELEASE_LOCK('${t}')`)), Le = 3e4, Re = (e, t) => T.gen(function* () {
|
|
149
|
+
let n = yield* O(e, `
|
|
150
150
|
DECLARE @res int;
|
|
151
151
|
EXEC @res = sp_getapplock @Resource = '${t}', @LockMode = 'Exclusive',
|
|
152
|
-
@LockOwner = 'Session', @LockTimeout = ${String(
|
|
152
|
+
@LockOwner = 'Session', @LockTimeout = ${String(Le)};
|
|
153
153
|
SELECT @res AS res`);
|
|
154
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
|
-
}),
|
|
156
|
-
let n =
|
|
155
|
+
}), ze = (e, t) => T.asVoid(O(e, `EXEC sp_releaseapplock @Resource = '${t}', @LockOwner = 'Session'`)), Be = T.void, Ve = (e, t) => T.gen(function* () {
|
|
156
|
+
let n = Ce(t), r = ke(n), i = Oe(n);
|
|
157
157
|
if (!e.onDialectOrElse({
|
|
158
158
|
mysql: () => !0,
|
|
159
159
|
mssql: () => !0,
|
|
160
160
|
sqlite: () => !1,
|
|
161
161
|
orElse: () => !0
|
|
162
|
-
})) return { release:
|
|
162
|
+
})) return { release: Be };
|
|
163
163
|
let a = yield* re.make(), o = yield* T.provideService(e.reserve, re.Scope, a), s = re.close(a, te.void);
|
|
164
164
|
return yield* e.onDialectOrElse({
|
|
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
165
|
mysql: () => Fe(o, r),
|
|
171
166
|
mssql: () => Re(o, r),
|
|
172
|
-
sqlite: () =>
|
|
167
|
+
sqlite: () => Be,
|
|
173
168
|
orElse: () => Me(o, i)
|
|
169
|
+
}).pipe(T.onExit((e) => te.isSuccess(e) ? T.void : s)), { release: e.onDialectOrElse({
|
|
170
|
+
mysql: () => Ie(o, r),
|
|
171
|
+
mssql: () => ze(o, r),
|
|
172
|
+
sqlite: () => Be,
|
|
173
|
+
orElse: () => Ne(o, i)
|
|
174
174
|
}).pipe(T.ensuring(s)) };
|
|
175
|
-
}),
|
|
175
|
+
}), He = (e, t, n) => T.acquireUseRelease(Ve(e, n), () => t, (e) => e.release.pipe(T.orDie)), Ue = (e) => e.onDialectOrElse({
|
|
176
176
|
pg: () => "postgres",
|
|
177
177
|
mysql: () => "mysql",
|
|
178
178
|
mssql: () => "mssql",
|
|
179
179
|
sqlite: () => "sqlite",
|
|
180
180
|
orElse: () => "sqlite"
|
|
181
|
-
}),
|
|
181
|
+
}), We = {
|
|
182
182
|
postgres: "plan-transactional",
|
|
183
183
|
mssql: "plan-transactional",
|
|
184
184
|
mysql: "per-operation",
|
|
185
185
|
mariadb: "per-operation",
|
|
186
186
|
sqlite: "per-operation",
|
|
187
187
|
turso: "per-operation"
|
|
188
|
-
},
|
|
188
|
+
}, Ge = (e) => We[e], k = "_voltro_migration_ops", Ke = l(k, {
|
|
189
189
|
id: y({ prefix: "mop" }),
|
|
190
190
|
runId: a(),
|
|
191
191
|
planFingerprint: a(),
|
|
@@ -198,7 +198,7 @@ var le = (e, t = "float32") => {
|
|
|
198
198
|
appliedAt: v().nullable(),
|
|
199
199
|
durationMs: t().nullable(),
|
|
200
200
|
createdAt: v().default("now")
|
|
201
|
-
}),
|
|
201
|
+
}), qe = (e) => {
|
|
202
202
|
switch (e.kind) {
|
|
203
203
|
case "create-table": return /* @__PURE__ */ new Set([
|
|
204
204
|
`table:${e.table}`,
|
|
@@ -226,11 +226,11 @@ var le = (e, t = "float32") => {
|
|
|
226
226
|
case "add-unique-composite":
|
|
227
227
|
case "drop-unique-composite": return /* @__PURE__ */ new Set([`unique:${e.table}.${e.name}`]);
|
|
228
228
|
}
|
|
229
|
-
},
|
|
230
|
-
let n =
|
|
231
|
-
for (let t of
|
|
229
|
+
}, Je = (e) => [...qe(e)].join(" "), Ye = (e, t) => {
|
|
230
|
+
let n = qe(t);
|
|
231
|
+
for (let t of qe(e)) if (n.has(t)) return !0;
|
|
232
232
|
return !1;
|
|
233
|
-
},
|
|
233
|
+
}, Xe = (e, t) => e.operations.some((e) => Ye(e.op, t)), Ze = "__voltro_rebuild", Qe = "__shadow", $e = "__old", et = /* @__PURE__ */ new Set([
|
|
234
234
|
"add-unique",
|
|
235
235
|
"drop-unique",
|
|
236
236
|
"add-unique-composite",
|
|
@@ -242,14 +242,14 @@ var le = (e, t = "float32") => {
|
|
|
242
242
|
"alter-column-nullability",
|
|
243
243
|
"alter-column-type",
|
|
244
244
|
"alter-column-default"
|
|
245
|
-
]),
|
|
245
|
+
]), tt = /* @__PURE__ */ new Set(["alter-column-default", "alter-column-nullability"]), nt = (e, t, n) => {
|
|
246
246
|
let r = n === "sqlite" || n === "turso";
|
|
247
|
-
return e.kind === "alter-column-type" && t === "online-required" || r &&
|
|
247
|
+
return e.kind === "alter-column-type" && t === "online-required" || r && et.has(e.kind) ? "artefact-repair" : tt.has(e.kind) ? "idempotent" : "probe-then-replay";
|
|
248
248
|
};
|
|
249
|
-
Object.keys(
|
|
249
|
+
Object.keys(We);
|
|
250
250
|
//#endregion
|
|
251
251
|
//#region src/mssqlJsonValueCheck.ts
|
|
252
|
-
var
|
|
252
|
+
var rt = (e) => {
|
|
253
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
254
|
return `(${e} IS NULL OR (${n} AND ${[
|
|
255
255
|
32,
|
|
@@ -257,7 +257,7 @@ var nt = (e) => {
|
|
|
257
257
|
10,
|
|
258
258
|
13
|
|
259
259
|
].reduce((e, t) => `REPLACE(${e}, NCHAR(${t}), N'')`, r)} = N'{}'))`;
|
|
260
|
-
},
|
|
260
|
+
}, it = (e) => {
|
|
261
261
|
let t = [], n = /\s+|N?'(?:''|[^'])*'|\[(?:\]\]|[^\]])*\]|[A-Za-z_][A-Za-z_0-9]*|[0-9]+|[()+,=]/giy, r = 0;
|
|
262
262
|
for (; r < e.length;) {
|
|
263
263
|
n.lastIndex = r;
|
|
@@ -267,34 +267,34 @@ var nt = (e) => {
|
|
|
267
267
|
/^\s+$/.test(a) || t.push(/^(?:N?')|^\[/i.test(a) ? a.replace(/^n'/, "N'") : a.toLowerCase()), r = n.lastIndex;
|
|
268
268
|
}
|
|
269
269
|
return t;
|
|
270
|
-
},
|
|
270
|
+
}, at = (e, t) => {
|
|
271
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
272
|
32,
|
|
273
273
|
9,
|
|
274
274
|
10,
|
|
275
275
|
13
|
|
276
276
|
].reduce((e, t) => `replace(${e},nchar((${t})),N'')`, a), s = [
|
|
277
|
-
["value",
|
|
277
|
+
["value", rt(n)],
|
|
278
278
|
["value", `(${n} IS NULL OR ${i} AND ${o}=N'{}')`],
|
|
279
279
|
["container", `(${n} IS NULL OR ISJSON(${n}) = 1)`],
|
|
280
280
|
["container", `(${n} IS NULL OR isjson(${n})=(1))`]
|
|
281
|
-
], c =
|
|
281
|
+
], c = it(t);
|
|
282
282
|
if (c) return s.find(([, e]) => {
|
|
283
|
-
let t =
|
|
283
|
+
let t = it(e);
|
|
284
284
|
return t?.length === c.length && t.every((e, t) => e === c[t]);
|
|
285
285
|
})?.[0];
|
|
286
|
-
},
|
|
286
|
+
}, ot = (e) => {
|
|
287
287
|
if (e.length === 0) return;
|
|
288
288
|
let t = e.filter((e) => e.enabled);
|
|
289
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
|
-
},
|
|
290
|
+
}, A = "framework_changes", st = "framework_changes_", ct = (e, t) => t === "framework_changes" ? `${st}${e}` : `${st}${t}_${e}`, lt = (e) => e === "framework_changes" ? "framework_notify_change" : `framework_notify_change_${e}`, ut = "voltro:notify:v2", dt = (e, t) => {
|
|
291
291
|
if (e.type === "text" && e.generatedAs === void 0) {
|
|
292
292
|
if (e.maxLength !== void 0) return e.maxLength;
|
|
293
293
|
if (t || e.hasDefault && e.defaultFactory === void 0 || e.oneOf !== void 0 && e.oneOf.length > 0) return 450;
|
|
294
294
|
}
|
|
295
|
-
},
|
|
296
|
-
|
|
297
|
-
},
|
|
295
|
+
}, ft = ae({ scope: "voltro:migrate" }), j = (e) => {
|
|
296
|
+
ft.warn(e.replace(/^\[voltro:migrate\]\s*/, ""));
|
|
297
|
+
}, M = (e, t) => {
|
|
298
298
|
let n = e.type;
|
|
299
299
|
if (e.spatial) {
|
|
300
300
|
if (t === "postgres") return `${e.spatial.kind}(${e.spatial.geomKind},${e.spatial.srid})`;
|
|
@@ -305,7 +305,7 @@ var nt = (e) => {
|
|
|
305
305
|
return e.rawDdl;
|
|
306
306
|
}
|
|
307
307
|
if (n === "array" && e.arrayElement) {
|
|
308
|
-
if (t === "postgres") return `${
|
|
308
|
+
if (t === "postgres") return `${M({
|
|
309
309
|
...e,
|
|
310
310
|
type: e.arrayElement,
|
|
311
311
|
arrayElement: void 0
|
|
@@ -376,7 +376,7 @@ var nt = (e) => {
|
|
|
376
376
|
if (t === "mssql") switch (n) {
|
|
377
377
|
case "id": return "NVARCHAR(64)";
|
|
378
378
|
case "text": {
|
|
379
|
-
let t =
|
|
379
|
+
let t = dt(e, !1);
|
|
380
380
|
return t === void 0 ? "NVARCHAR(MAX)" : `NVARCHAR(${t})`;
|
|
381
381
|
}
|
|
382
382
|
case "integer": return "INT";
|
|
@@ -408,22 +408,22 @@ var nt = (e) => {
|
|
|
408
408
|
case "array": return "TEXT[]";
|
|
409
409
|
case "interval": return "INTERVAL";
|
|
410
410
|
}
|
|
411
|
-
},
|
|
411
|
+
}, pt = (e, t) => {
|
|
412
412
|
if (!e.hasDefault || e.defaultFactory !== void 0) return null;
|
|
413
413
|
let n = e.defaultValue;
|
|
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) ?
|
|
415
|
-
},
|
|
416
|
-
if (n !== "postgres" || t.type !== "array" || t.arrayElement === void 0) return
|
|
417
|
-
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) ? mt(n, e, t) : typeof n == "object" && n ? N(n, t) : null;
|
|
415
|
+
}, mt = (e, t, n) => {
|
|
416
|
+
if (n !== "postgres" || t.type !== "array" || t.arrayElement === void 0) return N(e, n);
|
|
417
|
+
let r = M({
|
|
418
418
|
...t,
|
|
419
419
|
type: t.arrayElement,
|
|
420
420
|
arrayElement: void 0
|
|
421
421
|
}, n);
|
|
422
422
|
return `DEFAULT '{${e.map((e) => typeof e == "number" || typeof e == "boolean" ? String(e) : `"${String(e).replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"`).join(",").replace(/'/g, "''")}}'::${r}[]`;
|
|
423
|
-
},
|
|
423
|
+
}, N = (e, t) => {
|
|
424
424
|
let n = JSON.stringify(e).replace(/'/g, "''");
|
|
425
425
|
return t === "postgres" ? `DEFAULT '${n}'::jsonb` : t === "mysql" || t === "mariadb" ? `DEFAULT (CONVERT('${n}' USING utf8mb4))` : `DEFAULT '${n}'`;
|
|
426
|
-
},
|
|
426
|
+
}, P = (e, t) => {
|
|
427
427
|
switch (t) {
|
|
428
428
|
case "postgres": return `"${e}" BIGSERIAL PRIMARY KEY`;
|
|
429
429
|
case "mysql":
|
|
@@ -432,7 +432,7 @@ var nt = (e) => {
|
|
|
432
432
|
case "sqlite": return `"${e}" INTEGER PRIMARY KEY AUTOINCREMENT`;
|
|
433
433
|
case "turso": return `"${e}" INTEGER PRIMARY KEY`;
|
|
434
434
|
}
|
|
435
|
-
},
|
|
435
|
+
}, F = (e, t) => {
|
|
436
436
|
if (e === "restrict" && t === "mssql") return "NO ACTION";
|
|
437
437
|
switch (e) {
|
|
438
438
|
case "cascade": return "CASCADE";
|
|
@@ -440,42 +440,42 @@ var nt = (e) => {
|
|
|
440
440
|
case "setNull": return "SET NULL";
|
|
441
441
|
case "noAction": return "NO ACTION";
|
|
442
442
|
}
|
|
443
|
-
},
|
|
443
|
+
}, ht = (e, t, n) => n === null ? o(e, t) : `${o(n, t)}.${o(e, t)}`, gt = 191, _t = (e, t) => {
|
|
444
444
|
if (!e || t !== "mysql" && t !== "mariadb") return !1;
|
|
445
|
-
let n =
|
|
445
|
+
let n = M(e, t).toUpperCase();
|
|
446
446
|
return n.endsWith("TEXT") || n.endsWith("BLOB");
|
|
447
|
-
},
|
|
447
|
+
}, vt = (e, t, n) => {
|
|
448
448
|
let r = o(e, n);
|
|
449
449
|
if (n !== "mysql" && n !== "mariadb") return r;
|
|
450
450
|
let i = t[e];
|
|
451
451
|
if (!i) return r;
|
|
452
|
-
let a =
|
|
453
|
-
return a.endsWith("TEXT") || a.endsWith("BLOB") ? `${r}(${
|
|
454
|
-
},
|
|
452
|
+
let a = M(i, n).toUpperCase();
|
|
453
|
+
return a.endsWith("TEXT") || a.endsWith("BLOB") ? `${r}(${gt})` : r;
|
|
454
|
+
}, yt = (e, t) => {
|
|
455
455
|
if (!e.generatedAs) return null;
|
|
456
456
|
let { expr: n, stored: r } = e.generatedAs;
|
|
457
|
-
if (t === "postgres") return r ||
|
|
457
|
+
if (t === "postgres") return r || j("[voltro:migrate] generated column requested as VIRTUAL but postgres only supports STORED — promoting"), `GENERATED ALWAYS AS (${n}) STORED`;
|
|
458
458
|
if (t === "mysql" || t === "mariadb") return `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
|
|
459
459
|
if (t === "mssql") return `AS (${n})${r ? " PERSISTED" : ""}`;
|
|
460
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.");
|
|
461
461
|
return `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
|
|
462
|
-
},
|
|
463
|
-
if (t.type === "id" && t.idScheme?.kind === "numeric") return
|
|
464
|
-
let s = n === "mssql" ?
|
|
462
|
+
}, bt = (e, t, n, r, i = !1, a = !1) => {
|
|
463
|
+
if (t.type === "id" && t.idScheme?.kind === "numeric") return P(e, n);
|
|
464
|
+
let s = n === "mssql" ? dt(t, r?.has(e) ?? !1) : void 0, c = s === void 0 ? M(t, n) : `NVARCHAR(${s})`, l = [o(e, n), c];
|
|
465
465
|
t.type === "id" && !a && l.push("PRIMARY KEY");
|
|
466
|
-
let u =
|
|
466
|
+
let u = yt(t, n);
|
|
467
467
|
if (u) l.push(u);
|
|
468
468
|
else {
|
|
469
|
-
t.nullable || l.push("NOT NULL"), t.unique && t.type !== "id" && !
|
|
470
|
-
let e =
|
|
469
|
+
t.nullable || l.push("NOT NULL"), t.unique && t.type !== "id" && !_t(t, n) && l.push("UNIQUE");
|
|
470
|
+
let e = pt(t, n);
|
|
471
471
|
e && l.push(e);
|
|
472
472
|
}
|
|
473
473
|
if (t.type === "reference" && t.references && !i && !b(n)) {
|
|
474
474
|
let e = t.references();
|
|
475
475
|
l.push(`REFERENCES ${o(e.tableName, n)} (${o(t.referenceColumn ?? "id", n)})`);
|
|
476
|
-
let r =
|
|
476
|
+
let r = F(t.onDelete ?? "restrict", n);
|
|
477
477
|
l.push(`ON DELETE ${r}`);
|
|
478
|
-
let i =
|
|
478
|
+
let i = F(t.refOnUpdate ?? "noAction", n);
|
|
479
479
|
i !== "NO ACTION" && l.push(`ON UPDATE ${i}`);
|
|
480
480
|
}
|
|
481
481
|
if (t.oneOf && t.oneOf.length > 0) {
|
|
@@ -489,29 +489,29 @@ var nt = (e) => {
|
|
|
489
489
|
}
|
|
490
490
|
if (t.type === "json" || t.type === "array") {
|
|
491
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 ${
|
|
492
|
+
m(n) ? l.push(`CHECK (${r} IS NULL OR json_valid(${r}))`) : n === "mssql" && l.push(t.type === "json" ? `CHECK ${rt(r)}` : `CHECK (${r} IS NULL OR ISJSON(${r}) = 1)`);
|
|
493
493
|
}
|
|
494
494
|
return l.join(" ");
|
|
495
|
-
},
|
|
495
|
+
}, xt = (e, t, n = null, r) => {
|
|
496
496
|
let i = /* @__PURE__ */ new Set();
|
|
497
497
|
for (let t of e.appliedIndexes ?? []) for (let e of t.fields) typeof e == "string" && i.add(e);
|
|
498
498
|
for (let t of e.appliedUniques ?? []) for (let e of t.fields) typeof e == "string" && i.add(e);
|
|
499
499
|
for (let [t, n] of Object.entries(e.fields)) n.unique && i.add(t);
|
|
500
500
|
let a = e.appliedPrimaryKey ?? [];
|
|
501
501
|
for (let e of a) i.add(e);
|
|
502
|
-
let s = a.length > 0, c = Object.entries(e.fields).map(([e, n]) => ` ${
|
|
503
|
-
let r = n.fields.map((n) =>
|
|
502
|
+
let s = a.length > 0, c = Object.entries(e.fields).map(([e, n]) => ` ${bt(e, n, t, i, r?.has(e) ?? !1, s)}`).join(",\n"), l = (e.appliedUniques ?? []).map((n) => {
|
|
503
|
+
let r = n.fields.map((n) => vt(n, e.fields, t)).join(", ");
|
|
504
504
|
return ` CONSTRAINT ${o(n.name, t)} UNIQUE (${r})`;
|
|
505
|
-
}), 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) => vt(n, e.fields, t)).join(", ")})`] : [], f = b(t) ? Object.entries(e.fields).flatMap(([i, a]) => {
|
|
506
506
|
if (a.type !== "reference" || !a.references || (r?.has(i) ?? !1)) return [];
|
|
507
|
-
let s = a.references(), c =
|
|
508
|
-
return [` CONSTRAINT ${o(`${e.tableName}_${i}_fkey`, t)} FOREIGN KEY (${o(i, t)}) REFERENCES ${
|
|
507
|
+
let s = a.references(), c = F(a.onDelete ?? "restrict", t), l = F(a.refOnUpdate ?? "noAction", t);
|
|
508
|
+
return [` CONSTRAINT ${o(`${e.tableName}_${i}_fkey`, t)} FOREIGN KEY (${o(i, t)}) REFERENCES ${ht(s.tableName, t, n)} (${o(a.referenceColumn ?? "id", t)}) ON DELETE ${c}${l === "NO ACTION" ? "" : ` ON UPDATE ${l}`}`];
|
|
509
509
|
}) : [], p = [
|
|
510
510
|
...d,
|
|
511
511
|
...l,
|
|
512
512
|
...u,
|
|
513
513
|
...f
|
|
514
|
-
], m = p.length > 0 ? `${c},\n${p.join(",\n")}` : c, h =
|
|
514
|
+
], m = p.length > 0 ? `${c},\n${p.join(",\n")}` : c, h = ht(e.tableName, t, n);
|
|
515
515
|
if (t === "mssql") {
|
|
516
516
|
let t = n === null ? e.tableName : `${n}.${e.tableName}`, r = `CREATE TABLE ${h} (\n${m}\n)`;
|
|
517
517
|
return `IF OBJECT_ID('${t.replace(/'/g, "''")}', 'U') IS NULL EXEC(N'${r.replace(/'/g, "''")}');`;
|
|
@@ -521,29 +521,29 @@ var nt = (e) => {
|
|
|
521
521
|
m,
|
|
522
522
|
");"
|
|
523
523
|
].join("\n");
|
|
524
|
-
},
|
|
524
|
+
}, St = (e, t, n) => {
|
|
525
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 = [];
|
|
526
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;
|
|
527
|
-
},
|
|
527
|
+
}, Ct = (e, t, n = null) => {
|
|
528
528
|
let r = [], i = /* @__PURE__ */ new Set(), a = (e) => e.join("\0"), s = (e, n, r, i, a) => {
|
|
529
|
-
if (t === "postgres") return
|
|
529
|
+
if (t === "postgres") return fe(r, i, a);
|
|
530
530
|
let o = {
|
|
531
531
|
using: "",
|
|
532
532
|
withSuffix: "",
|
|
533
533
|
skip: !1
|
|
534
534
|
};
|
|
535
|
-
return r === void 0 || r === "btree" ? o : r === "gist" ? (
|
|
535
|
+
return r === void 0 || r === "btree" ? o : r === "gist" ? (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.`), o) : r === "gin" ? 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(...).`), {
|
|
536
536
|
using: "",
|
|
537
537
|
withSuffix: "",
|
|
538
538
|
skip: !0
|
|
539
|
-
}) : (
|
|
539
|
+
}) : (j(`[voltro:migrate] gin index '${e}' on '${n}': ${t} has no GIN access method — falling back to btree. Containment/membership queries won't use this index efficiently.`), o) : r === "brin" ? (j(`[voltro:migrate] brin index '${e}' on '${n}': ${t} has no BRIN access method — falling back to btree (larger on disk, but the range scan still works).`), o) : r === "hnsw" ? (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.`), {
|
|
540
540
|
using: "",
|
|
541
541
|
withSuffix: "",
|
|
542
542
|
skip: !0
|
|
543
543
|
}) : o;
|
|
544
544
|
}, c = (n, r) => {
|
|
545
545
|
let i = n.map((n) => {
|
|
546
|
-
if (typeof n == "string") return
|
|
546
|
+
if (typeof n == "string") return vt(n, e.fields, t);
|
|
547
547
|
if ("jsonPath" in n) {
|
|
548
548
|
let { column: e, path: r, numeric: i } = n.jsonPath;
|
|
549
549
|
return `(${C(e, r, t, { numeric: i })})`;
|
|
@@ -554,11 +554,11 @@ var nt = (e) => {
|
|
|
554
554
|
}, l = (r, i, a, l, u, d = "", f = !1) => {
|
|
555
555
|
let p = a[0], m = typeof p == "string" ? e.fields[p]?.vectorPrecision : void 0, h = s(r, i, l, u, m);
|
|
556
556
|
if (h.skip) return "";
|
|
557
|
-
let g = c(a, h.opclass), _ = `${h.withSuffix}${d}`, v =
|
|
557
|
+
let g = c(a, h.opclass), _ = `${h.withSuffix}${d}`, v = ht(i, t, n), y = f ? "UNIQUE " : "";
|
|
558
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})${_};`;
|
|
559
559
|
};
|
|
560
560
|
if (t === "mysql" || t === "mariadb") for (let [n, i] of Object.entries(e.fields)) {
|
|
561
|
-
if (!i.unique || i.type === "id" || !
|
|
561
|
+
if (!i.unique || i.type === "id" || !_t(i, t)) continue;
|
|
562
562
|
let a = l(`${e.tableName}_${n}_key`, e.tableName, [n], void 0, void 0, "", !0);
|
|
563
563
|
a && r.push(a);
|
|
564
564
|
}
|
|
@@ -572,15 +572,15 @@ var nt = (e) => {
|
|
|
572
572
|
let i = n.columns.map((e) => o(e, t)).join(", ");
|
|
573
573
|
r.push(`CREATE FULLTEXT INDEX ${o(n.name, t)} ON ${o(e.tableName, t)} (${i});`);
|
|
574
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.`);
|
|
575
|
-
else t === "sqlite" ? r.push(...
|
|
575
|
+
else t === "sqlite" ? r.push(...St(e.tableName, n, t)) : j(`[voltro:migrate] full-text index '${n.name}' on '${e.tableName}': ${t} uses a ranked LIKE search at query time (no native FTS catalog required).`);
|
|
576
576
|
for (let n of e.appliedIndexes) {
|
|
577
577
|
if ((t === "mariadb" || t === "mssql") && n.fields.some((e) => typeof e != "string" && "jsonPath" in e)) {
|
|
578
|
-
|
|
578
|
+
j(`[voltro:migrate] json-path index '${n.name}' on '${e.tableName}': ${t} cannot index a JSON expression directly — skipping. For an indexed JSON path on ${t}, add a generated column for the path (text().generatedAs(...) / .stored()) and .index([...]) it, then filter on that column instead of jsonField(...).`);
|
|
579
579
|
continue;
|
|
580
580
|
}
|
|
581
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.`);
|
|
582
582
|
let o = "";
|
|
583
|
-
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" ? j(`[voltro:migrate] partial index '${n.name}' on '${e.tableName}': ${t} does not support WHERE clauses on indexes — emitting a full index`) : o = ` WHERE ${n.where}`);
|
|
584
584
|
let s = l(n.name, e.tableName, n.fields, n.kind, n.kindOptions, o, n.unique === !0);
|
|
585
585
|
s !== "" && r.push(s), n.fields.every((e) => typeof e == "string") && i.add(a(n.fields));
|
|
586
586
|
}
|
|
@@ -590,17 +590,17 @@ var nt = (e) => {
|
|
|
590
590
|
r.push(l(o, e.tableName, [t])), i.add(a([t]));
|
|
591
591
|
}
|
|
592
592
|
return r.join("\n");
|
|
593
|
-
},
|
|
593
|
+
}, wt = (e, t, n = A) => {
|
|
594
594
|
if (t !== "postgres") return [];
|
|
595
595
|
let r = e.filter((e) => e.isReactive !== !1);
|
|
596
|
-
return r.length === 0 ? [] : [
|
|
597
|
-
},
|
|
598
|
-
CREATE OR REPLACE FUNCTION ${
|
|
596
|
+
return r.length === 0 ? [] : [Tt(n), ...r.map((e) => Dt(e, n))];
|
|
597
|
+
}, Tt = (e) => `
|
|
598
|
+
CREATE OR REPLACE FUNCTION ${lt(e)}() RETURNS trigger AS $$
|
|
599
599
|
DECLARE
|
|
600
600
|
payload TEXT;
|
|
601
601
|
pk JSONB;
|
|
602
602
|
BEGIN
|
|
603
|
-
-- ${
|
|
603
|
+
-- ${ut}
|
|
604
604
|
payload := json_build_object(
|
|
605
605
|
'table', TG_TABLE_NAME,
|
|
606
606
|
-- The schema the write landed in. Under namespace isolation this is
|
|
@@ -654,22 +654,22 @@ BEGIN
|
|
|
654
654
|
RETURN COALESCE(NEW, OLD);
|
|
655
655
|
END;
|
|
656
656
|
$$ LANGUAGE plpgsql;
|
|
657
|
-
`.trim(),
|
|
658
|
-
let n =
|
|
657
|
+
`.trim(), Et = (e, t) => {
|
|
658
|
+
let n = ct(e.tableName, t);
|
|
659
659
|
return [
|
|
660
660
|
`ALTER TABLE "${e.tableName}" REPLICA IDENTITY FULL`,
|
|
661
661
|
`DROP TRIGGER IF EXISTS ${n} ON "${e.tableName}"`,
|
|
662
|
-
`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 ${lt(t)}()`
|
|
663
663
|
];
|
|
664
|
-
},
|
|
664
|
+
}, Dt = (e, t) => Et(e, t).map((e) => `${e};`).join("\n"), Ot = (e) => {
|
|
665
665
|
if (e.dialect !== "postgres") return [];
|
|
666
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));
|
|
667
|
-
(i.length > 0 || e.functionOutdated === !0) && r.push(
|
|
668
|
-
for (let e of i) r.push(...
|
|
669
|
-
for (let n of e.stale) r.push(`DROP TRIGGER IF EXISTS ${
|
|
667
|
+
(i.length > 0 || e.functionOutdated === !0) && r.push(Tt(t));
|
|
668
|
+
for (let e of i) r.push(...Et(n.get(e), t));
|
|
669
|
+
for (let n of e.stale) r.push(`DROP TRIGGER IF EXISTS ${ct(n, t)} ON "${n}"`), r.push(`ALTER TABLE "${n}" REPLICA IDENTITY DEFAULT`);
|
|
670
670
|
return r;
|
|
671
|
-
},
|
|
672
|
-
let t = new Map(e.map((e) => [e.tableName, e])), n =
|
|
671
|
+
}, kt = (e) => e.some((e) => Object.values(e.fields).some((e) => e.type === "vector")), At = (e) => e.some((e) => Object.values(e.fields).some((e) => e.spatial !== void 0)), jt = (e) => {
|
|
672
|
+
let t = new Map(e.map((e) => [e.tableName, e])), n = be(e.map((e) => e.tableName), (e) => {
|
|
673
673
|
let n = t.get(e);
|
|
674
674
|
return n ? Object.entries(n.fields).flatMap(([e, n]) => {
|
|
675
675
|
if (n.type !== "reference" || !n.references) return [];
|
|
@@ -680,7 +680,7 @@ $$ LANGUAGE plpgsql;
|
|
|
680
680
|
}] : [];
|
|
681
681
|
}) : [];
|
|
682
682
|
}), r = [];
|
|
683
|
-
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(D(t.tableName, e)) && r.push({
|
|
684
684
|
table: t.tableName,
|
|
685
685
|
column: e,
|
|
686
686
|
targetTable: i.references().tableName,
|
|
@@ -692,7 +692,7 @@ $$ LANGUAGE plpgsql;
|
|
|
692
692
|
if (!(i.has(e.tableName) || a.has(e.tableName))) {
|
|
693
693
|
a.add(e.tableName);
|
|
694
694
|
for (let [r, i] of Object.entries(e.fields)) {
|
|
695
|
-
if (i.type !== "reference" || !i.references || n.has(
|
|
695
|
+
if (i.type !== "reference" || !i.references || n.has(D(e.tableName, r))) continue;
|
|
696
696
|
let a = i.references();
|
|
697
697
|
if (a.tableName === e.tableName) continue;
|
|
698
698
|
let o = t.get(a.tableName);
|
|
@@ -706,8 +706,8 @@ $$ LANGUAGE plpgsql;
|
|
|
706
706
|
sorted: o,
|
|
707
707
|
cyclic: r
|
|
708
708
|
};
|
|
709
|
-
},
|
|
710
|
-
let r = (e) => n ? `${o(n, t)}.${o(e, t)}` : o(e, t), i = `${e.table}_${e.column}_fkey`, a =
|
|
709
|
+
}, Mt = (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 = F(e.onDelete, t), s = F(e.onUpdate, t), c = ` ON DELETE ${a}${s === "NO ACTION" ? "" : ` ON UPDATE ${s}`}`, l = (n) => `ADD CONSTRAINT ${o(i, t)} FOREIGN KEY ${n ? "IF NOT EXISTS " : ""}(${o(e.column, t)}) REFERENCES ${r(e.targetTable)} (${o(e.targetColumn, t)})${c}`;
|
|
711
711
|
switch (t) {
|
|
712
712
|
case "postgres": return [
|
|
713
713
|
"DO $$ BEGIN",
|
|
@@ -721,7 +721,7 @@ $$ LANGUAGE plpgsql;
|
|
|
721
721
|
case "mariadb": return `ALTER TABLE ${r(e.table)} ${l(!0)};`;
|
|
722
722
|
default: return `ALTER TABLE ${r(e.table)} ${l(!1)};`;
|
|
723
723
|
}
|
|
724
|
-
},
|
|
724
|
+
}, Nt = (e, t) => {
|
|
725
725
|
let n = /* @__PURE__ */ new Map();
|
|
726
726
|
if (m(t)) return n;
|
|
727
727
|
for (let t of e) {
|
|
@@ -729,7 +729,7 @@ $$ LANGUAGE plpgsql;
|
|
|
729
729
|
e.add(t.column), n.set(t.table, e);
|
|
730
730
|
}
|
|
731
731
|
return n;
|
|
732
|
-
},
|
|
732
|
+
}, Pt = (e, t) => {
|
|
733
733
|
if (t !== "postgres") return "";
|
|
734
734
|
let n = /* @__PURE__ */ new Map();
|
|
735
735
|
for (let t of e) for (let e of Object.values(t.fields)) {
|
|
@@ -745,7 +745,7 @@ $$ LANGUAGE plpgsql;
|
|
|
745
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 $$;`);
|
|
746
746
|
}
|
|
747
747
|
return r.join("\n\n");
|
|
748
|
-
},
|
|
748
|
+
}, Ft = (e, t) => {
|
|
749
749
|
if (t !== "postgres") return "";
|
|
750
750
|
let r = /* @__PURE__ */ new Set();
|
|
751
751
|
for (let t of e) for (let e of Object.values(t.fields)) e.type === "enum" && e.enumName && r.add(e.enumName);
|
|
@@ -759,30 +759,30 @@ BEGIN
|
|
|
759
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 $$;`);
|
|
760
760
|
}
|
|
761
761
|
return i.join("\n\n");
|
|
762
|
-
},
|
|
762
|
+
}, It = (e) => {
|
|
763
763
|
let t = [], n = [];
|
|
764
764
|
for (let r of e) s(r) ? n.push(r) : t.push(r);
|
|
765
765
|
return {
|
|
766
766
|
tables: t,
|
|
767
767
|
views: n
|
|
768
768
|
};
|
|
769
|
-
},
|
|
770
|
-
let { tables: i, views: a } =
|
|
771
|
-
n === "postgres" &&
|
|
772
|
-
let u =
|
|
769
|
+
}, Lt = (t, n, r = A) => {
|
|
770
|
+
let { tables: i, views: a } = It(t), { sorted: o, cyclic: s } = jt(i.map((e) => ye(e, n))), c = Nt(s, n), l = [];
|
|
771
|
+
n === "postgres" && kt(o) && l.push("CREATE EXTENSION IF NOT EXISTS vector;"), n === "postgres" && At(o) && l.push("CREATE EXTENSION IF NOT EXISTS postgis;");
|
|
772
|
+
let u = Ft(o, n);
|
|
773
773
|
u && l.push(u);
|
|
774
|
-
let d =
|
|
774
|
+
let d = Pt(o, n);
|
|
775
775
|
d && l.push(d);
|
|
776
|
-
for (let e of o) l.push(
|
|
777
|
-
if (!m(n)) for (let e of s) l.push(
|
|
776
|
+
for (let e of o) l.push(xt(e, n, null, c.get(e.tableName)));
|
|
777
|
+
if (!m(n)) for (let e of s) l.push(Mt(e, n));
|
|
778
778
|
for (let e of o) {
|
|
779
|
-
let t =
|
|
779
|
+
let t = Ct(e, n);
|
|
780
780
|
t && l.push(t);
|
|
781
781
|
}
|
|
782
|
-
l.push(...
|
|
782
|
+
l.push(...wt(o, n, r));
|
|
783
783
|
for (let t of a) l.push(e(t, n));
|
|
784
784
|
return l.join("\n\n") + "\n";
|
|
785
|
-
},
|
|
785
|
+
}, Rt = (e, t, n) => {
|
|
786
786
|
let r = o(e, t);
|
|
787
787
|
switch (t) {
|
|
788
788
|
case "postgres": return `CREATE SCHEMA IF NOT EXISTS ${r};`;
|
|
@@ -792,62 +792,62 @@ BEGIN
|
|
|
792
792
|
case "turso":
|
|
793
793
|
case "sqlite": return `ATTACH DATABASE '${(n ?? `${e}.db`).replace(/'/g, "''")}' AS ${r};`;
|
|
794
794
|
}
|
|
795
|
-
},
|
|
796
|
-
let i =
|
|
797
|
-
if (t === "postgres") return `${i}\n\nSET search_path TO ${a};\n\n${
|
|
798
|
-
if (t === "mysql" || t === "mariadb") return `${i}\n\nUSE ${a};\n\n${
|
|
799
|
-
let { sorted: s, cyclic: c } =
|
|
800
|
-
for (let e of s) u.push(
|
|
801
|
-
if (!m(t)) for (let e of c) u.push(
|
|
795
|
+
}, zt = (e, t, n, r) => {
|
|
796
|
+
let i = Rt(n, t, r), a = o(n, t);
|
|
797
|
+
if (t === "postgres") return `${i}\n\nSET search_path TO ${a};\n\n${Lt(e, t)}`;
|
|
798
|
+
if (t === "mysql" || t === "mariadb") return `${i}\n\nUSE ${a};\n\n${Lt(e, t)}`;
|
|
799
|
+
let { sorted: s, cyclic: c } = jt(e), l = Nt(c, t), u = [i];
|
|
800
|
+
for (let e of s) u.push(xt(e, t, n, l.get(e.tableName)));
|
|
801
|
+
if (!m(t)) for (let e of c) u.push(Mt(e, t, n));
|
|
802
802
|
for (let e of s) {
|
|
803
|
-
let r =
|
|
803
|
+
let r = Ct(e, t, n);
|
|
804
804
|
r && u.push(r);
|
|
805
805
|
}
|
|
806
806
|
return u.join("\n\n") + "\n";
|
|
807
|
-
},
|
|
808
|
-
let { sorted: r, cyclic: i } =
|
|
807
|
+
}, Bt = (e, t, n = A) => {
|
|
808
|
+
let { sorted: r, cyclic: i } = jt(e), a = Nt(i, t), o = [], s = Ft(r, t);
|
|
809
809
|
s && o.push(s);
|
|
810
|
-
let c =
|
|
810
|
+
let c = Pt(r, t);
|
|
811
811
|
c && o.push(c);
|
|
812
|
-
for (let e of r) o.push(
|
|
813
|
-
for (let e of i) o.push(
|
|
814
|
-
return o.push(...
|
|
815
|
-
},
|
|
812
|
+
for (let e of r) o.push(xt(e, t, null, a.get(e.tableName)));
|
|
813
|
+
for (let e of i) o.push(Mt(e, t));
|
|
814
|
+
return o.push(...wt(r, t, n)), o.join("\n\n") + "\n";
|
|
815
|
+
}, Vt = (e, t = "postgres", n = A, r = {}) => T.gen(function* () {
|
|
816
816
|
let i = yield* E.SqlClient;
|
|
817
|
-
yield*
|
|
818
|
-
}),
|
|
817
|
+
yield* He(i, Jt(i, Lt(e, t, n), t, r.retryFilter), { schema: r.lockSchema }).pipe(T.orDie);
|
|
818
|
+
}), Ht = (e, t) => {
|
|
819
819
|
let n = t.cause ?? {};
|
|
820
820
|
return (n.errno === 1061 || n.code === "ER_DUP_KEYNAME") && /^\s*CREATE\s+(UNIQUE\s+|FULLTEXT\s+)?INDEX\b/i.test(e);
|
|
821
|
-
},
|
|
821
|
+
}, Ut = (e, t) => {
|
|
822
822
|
let n = e.trimStart();
|
|
823
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));
|
|
824
|
-
},
|
|
824
|
+
}, Wt = () => {
|
|
825
825
|
let e = Number(process.env.VOLTRO_MIGRATION_DDL_RETRIES);
|
|
826
826
|
return Number.isInteger(e) && e >= 0 ? e : 4;
|
|
827
|
-
},
|
|
827
|
+
}, Gt = (e) => ({
|
|
828
828
|
while: e,
|
|
829
|
-
times:
|
|
829
|
+
times: Wt(),
|
|
830
830
|
schedule: ne.jittered(ne.exponential("50 millis"))
|
|
831
|
-
}),
|
|
831
|
+
}), Kt = class {
|
|
832
832
|
statement;
|
|
833
833
|
error;
|
|
834
834
|
_tag = "DdlStatementFailed";
|
|
835
835
|
constructor(e, t) {
|
|
836
836
|
this.statement = e, this.error = t;
|
|
837
837
|
}
|
|
838
|
-
},
|
|
839
|
-
let r = yield* E.SqlClient, i = n !== void 0 &&
|
|
840
|
-
for (let a of
|
|
841
|
-
process.env.VOLTRO_MIGRATE_DEBUG === "1" &&
|
|
842
|
-
let e = r.unsafe(a).pipe(T.catchIf((e) =>
|
|
843
|
-
|
|
838
|
+
}, qt = (e, t, n) => T.gen(function* () {
|
|
839
|
+
let r = yield* E.SqlClient, i = n !== void 0 && Ge(t) === "per-operation";
|
|
840
|
+
for (let a of Yt(e)) {
|
|
841
|
+
process.env.VOLTRO_MIGRATE_DEBUG === "1" && ft.debug(`EXEC: ${a.replace(/\s+/g, " ").slice(0, 180)}`);
|
|
842
|
+
let e = r.unsafe(a).pipe(T.catchIf((e) => Ht(a, e), () => T.succeed([])), T.tapError((e) => T.sync(() => {
|
|
843
|
+
ft.error(pe("migrate: statement failed", a, e, 200));
|
|
844
844
|
})));
|
|
845
|
-
yield* (i && n !== void 0 &&
|
|
845
|
+
yield* (i && n !== void 0 && Ut(a, t) ? e.pipe(T.retry(Gt((e) => n(e) === "retry"))) : e).pipe(T.mapError((e) => new Kt(a, e)));
|
|
846
846
|
}
|
|
847
|
-
}),
|
|
848
|
-
let i = n === "turso" ?
|
|
849
|
-
return (r !== void 0 &&
|
|
850
|
-
},
|
|
847
|
+
}), Jt = (e, t, n, r) => {
|
|
848
|
+
let i = n === "turso" ? qt(t, n, r) : e.withTransaction(qt(t, n, r)), a = (e) => e instanceof Kt ? e.error : e;
|
|
849
|
+
return (r !== void 0 && Ge(n) === "plan-transactional" ? i.pipe(T.retry(Gt((e) => r(a(e)) === "retry"))) : i).pipe(T.orDieWith((e) => e instanceof Kt ? Error(pe("migrate: statement failed", e.statement, e.error, 400).trim()) : e));
|
|
850
|
+
}, Yt = (e) => {
|
|
851
851
|
let t = [], n = "", r = !1;
|
|
852
852
|
for (let i = 0; i < e.length; i++) {
|
|
853
853
|
if (e.slice(i, i + 2) === "$$") {
|
|
@@ -862,50 +862,50 @@ BEGIN
|
|
|
862
862
|
}
|
|
863
863
|
let i = n.trim();
|
|
864
864
|
return i.length > 0 && t.push(i), t;
|
|
865
|
-
},
|
|
866
|
-
await T.runPromise(
|
|
867
|
-
},
|
|
868
|
-
let i =
|
|
869
|
-
yield*
|
|
870
|
-
}),
|
|
871
|
-
await T.runPromise(
|
|
865
|
+
}, Xt = async (e, t, n = "postgres", r = {}) => {
|
|
866
|
+
await T.runPromise(Vt(e, n, void 0, r).pipe(T.provide(t)));
|
|
867
|
+
}, Zt = (e, t, n = "postgres", r = {}) => T.gen(function* () {
|
|
868
|
+
let i = zt(e, n, t), a = yield* E.SqlClient;
|
|
869
|
+
yield* He(a, Jt(a, i, n, r.retryFilter), { schema: r.lockSchema }).pipe(T.orDie);
|
|
870
|
+
}), Qt = async (e, t, n, r = "postgres", i = {}) => {
|
|
871
|
+
await T.runPromise(Zt(e, t, r, i).pipe(T.provide(n))), await f({
|
|
872
872
|
namespace: t,
|
|
873
873
|
dialect: r
|
|
874
874
|
});
|
|
875
|
-
},
|
|
875
|
+
}, $t = async (e, t, n = "postgres", r = {}) => {
|
|
876
876
|
await T.runPromise(T.gen(function* () {
|
|
877
|
-
let t =
|
|
878
|
-
yield*
|
|
877
|
+
let t = Bt(e, n), i = yield* E.SqlClient;
|
|
878
|
+
yield* He(i, Jt(i, t, n, r.retryFilter), { schema: r.lockSchema }).pipe(T.orDie);
|
|
879
879
|
}).pipe(T.provide(t)));
|
|
880
|
-
},
|
|
880
|
+
}, en = (e, t) => t.name === "id" && e.primaryKey?.length === 1 && e.primaryKey[0] === "id", tn = (e, t, n) => n && t.type === "id" && (e.type === "text" || e.type === "id"), I = (e) => {
|
|
881
881
|
if (typeof e != "object" || !e) return JSON.stringify(e);
|
|
882
|
-
if (Array.isArray(e)) return `[${e.map(
|
|
882
|
+
if (Array.isArray(e)) return `[${e.map(I).join(",")}]`;
|
|
883
883
|
let t = e;
|
|
884
|
-
return `{${Object.keys(t).sort().map((e) => `${JSON.stringify(e)}:${
|
|
885
|
-
},
|
|
884
|
+
return `{${Object.keys(t).sort().map((e) => `${JSON.stringify(e)}:${I(t[e])}`).join(",")}}`;
|
|
885
|
+
}, nn = (e) => {
|
|
886
886
|
if (!e.hasDefault || e.defaultValue === void 0 || e.defaultValue === null) return null;
|
|
887
887
|
let t = e.defaultValue;
|
|
888
888
|
if (typeof t == "boolean") return t ? "__BOOL_TRUE__" : "__BOOL_FALSE__";
|
|
889
889
|
if (typeof t == "number") return String(t);
|
|
890
|
-
if (typeof t != "string") return
|
|
890
|
+
if (typeof t != "string") return I(t);
|
|
891
891
|
let n = t.trim(), r = n.toLowerCase().replace(/\s+/g, "");
|
|
892
892
|
if (r === "now" || r === "now()" || /^current_timestamp(\(\d*\))?$/.test(r) || r === "sysutcdatetime()" || r === "sysdatetime()" || r === "getutcdate()" || r === "getdate()") return "__NOW__";
|
|
893
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);
|
|
894
894
|
if (o) try {
|
|
895
|
-
return
|
|
895
|
+
return I(JSON.parse(o[1]));
|
|
896
896
|
} catch {}
|
|
897
897
|
let s = /^convert\(\s*(?:_\w+\s*)?\\?'(.*?)\\?'\s+using\s+[\w]+\s*\)$/i.exec(a);
|
|
898
898
|
if (s) try {
|
|
899
|
-
return
|
|
899
|
+
return I(JSON.parse(s[1]));
|
|
900
900
|
} catch {}
|
|
901
901
|
if (a.startsWith("{") || a.startsWith("[")) try {
|
|
902
|
-
return
|
|
902
|
+
return I(JSON.parse(a));
|
|
903
903
|
} catch {}
|
|
904
904
|
return /^-?\d+(\.\d+)?$/.test(a) ? String(Number(a)) : a;
|
|
905
|
-
},
|
|
906
|
-
let t =
|
|
905
|
+
}, rn = (e) => {
|
|
906
|
+
let t = nn(e);
|
|
907
907
|
return t === "1" || t === "true" ? "__BOOL_TRUE__" : t === "0" || t === "false" ? "__BOOL_FALSE__" : t;
|
|
908
|
-
},
|
|
908
|
+
}, an = (e) => typeof e.defaultValue == "string" && /^nextval\(.+::regclass\)$/i.test(e.defaultValue.trim()), L = (e) => {
|
|
909
909
|
if (!e) return null;
|
|
910
910
|
let t = (e) => e === "restrict" ? "noAction" : e;
|
|
911
911
|
return {
|
|
@@ -914,26 +914,26 @@ BEGIN
|
|
|
914
914
|
onDelete: t(e.onDelete),
|
|
915
915
|
onUpdate: t(e.onUpdate)
|
|
916
916
|
};
|
|
917
|
-
},
|
|
917
|
+
}, on = (e, t, n) => {
|
|
918
918
|
if (t === "mssql") {
|
|
919
|
-
let t =
|
|
919
|
+
let t = dt(e, n);
|
|
920
920
|
if (t !== void 0) return t;
|
|
921
921
|
}
|
|
922
922
|
try {
|
|
923
|
-
let n = /^N?VARCHAR\((\d+)\)$/i.exec(
|
|
923
|
+
let n = /^N?VARCHAR\((\d+)\)$/i.exec(M(e, t).trim());
|
|
924
924
|
return n ? Number(n[1]) : void 0;
|
|
925
925
|
} catch {
|
|
926
926
|
return;
|
|
927
927
|
}
|
|
928
|
-
},
|
|
928
|
+
}, sn = /'(?:''|[^'])*'|"(?:""|[^"])*"|\[(?:\]\]|[^\]])*\]|`(?:``|[^`])*`|[A-Za-z_][A-Za-z_0-9$]*|\d+(?:\.\d+)?|::|<>|!=|<=|>=|\|\||[^\s]/g, cn = (e) => {
|
|
929
929
|
let t = 0;
|
|
930
|
-
for (let n of e.matchAll(
|
|
931
|
-
},
|
|
930
|
+
for (let n of e.matchAll(sn)) 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
|
+
}, ln = (e) => {
|
|
932
932
|
if (e === void 0) return;
|
|
933
|
-
let t = e.match(
|
|
933
|
+
let t = e.match(sn) ?? [], n = "(?:'(?:''|[^'])*'(?:\\s*::\\s*text)?|[0-9]+)", r = RegExp(`^\\s*${n}(?:\\s*,\\s*${n})*\\s*$`, "i");
|
|
934
934
|
for (let e = 0; e < t.length - 5; e++) {
|
|
935
935
|
let n = t[e + 4];
|
|
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(
|
|
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(sn) ?? [], ")");
|
|
937
937
|
}
|
|
938
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) => {
|
|
939
939
|
if (e.startsWith("'")) return e;
|
|
@@ -971,22 +971,22 @@ BEGIN
|
|
|
971
971
|
return r;
|
|
972
972
|
};
|
|
973
973
|
return JSON.stringify(a(i));
|
|
974
|
-
},
|
|
974
|
+
}, un = (e) => {
|
|
975
975
|
if (e == null) return e;
|
|
976
|
-
if (Array.isArray(e)) return e.map(
|
|
976
|
+
if (Array.isArray(e)) return e.map(un);
|
|
977
977
|
if (typeof e != "object") return e;
|
|
978
978
|
let t = {};
|
|
979
979
|
for (let n of Object.keys(e).sort()) {
|
|
980
980
|
let r = e[n];
|
|
981
|
-
r !== void 0 && (t[n] =
|
|
981
|
+
r !== void 0 && (t[n] = un(r));
|
|
982
982
|
}
|
|
983
983
|
return t;
|
|
984
|
-
},
|
|
984
|
+
}, dn = (e) => {
|
|
985
985
|
if (!e.idScheme && !e.sensitive && !e.safe && !e.generatedAs && !e.jsonChecks) return e;
|
|
986
986
|
let { idScheme: t, sensitive: n, safe: r, generatedAs: i, jsonChecks: a, ...o } = e;
|
|
987
987
|
return o;
|
|
988
|
-
},
|
|
989
|
-
let t =
|
|
988
|
+
}, fn = (e) => {
|
|
989
|
+
let t = dn(e), { references: n, defaultValue: r, hasDefault: i, oneOf: a, ...o } = t, s = t.type === "id" && an(t) ? null : rn(t), c = L(t.references);
|
|
990
990
|
return {
|
|
991
991
|
...o,
|
|
992
992
|
hasDefault: s !== null,
|
|
@@ -994,18 +994,22 @@ BEGIN
|
|
|
994
994
|
...c === null ? {} : { references: c },
|
|
995
995
|
...t.oneOf !== void 0 && t.oneOf.length > 0 ? { oneOf: [...t.oneOf].sort() } : {}
|
|
996
996
|
};
|
|
997
|
-
},
|
|
997
|
+
}, pn = (e, t) => en(e, t) && (t.type === "text" || t.type === "id") ? {
|
|
998
|
+
...t,
|
|
999
|
+
type: "id",
|
|
1000
|
+
unique: !0
|
|
1001
|
+
} : t, mn = (e) => e.columns.filter((e) => !x(e.name)).map((t) => fn(pn(e, t))).sort((e, t) => e.name.localeCompare(t.name)), hn = (e) => [...e].map(({ kind: e, kindOptions: t, ...n }) => ({
|
|
998
1002
|
...n,
|
|
999
|
-
...
|
|
1000
|
-
...n.where === void 0 ? {} : { where:
|
|
1001
|
-
})).sort((e, t) => e.name.localeCompare(t.name)),
|
|
1003
|
+
...de(e, t),
|
|
1004
|
+
...n.where === void 0 ? {} : { where: ln(n.where) }
|
|
1005
|
+
})).sort((e, t) => e.name.localeCompare(t.name)), gn = (e) => [...e].map((e) => ({
|
|
1002
1006
|
name: e.name,
|
|
1003
|
-
columns:
|
|
1004
|
-
indexes:
|
|
1007
|
+
columns: mn(e),
|
|
1008
|
+
indexes: hn(e.indexes)
|
|
1005
1009
|
})).sort((e, t) => e.name.localeCompare(t.name)), R = (e) => {
|
|
1006
|
-
let t = { tables:
|
|
1010
|
+
let t = { tables: gn(e.tables) }, n = JSON.stringify(un(t));
|
|
1007
1011
|
return ie("sha256").update(n).digest("hex");
|
|
1008
|
-
},
|
|
1012
|
+
}, _n = (e) => e.slice(0, 16), vn = (e, t) => {
|
|
1009
1013
|
let n = t.references ? {
|
|
1010
1014
|
table: t.references().tableName,
|
|
1011
1015
|
column: t.referenceColumn ?? "id",
|
|
@@ -1045,7 +1049,7 @@ BEGIN
|
|
|
1045
1049
|
...t.enumValues === void 0 ? {} : { enumValues: t.enumValues },
|
|
1046
1050
|
...t.spatial === void 0 ? {} : { spatial: t.spatial }
|
|
1047
1051
|
};
|
|
1048
|
-
},
|
|
1052
|
+
}, yn = (e, t) => {
|
|
1049
1053
|
let n = [], i = /* @__PURE__ */ new Set(), a = (e) => {
|
|
1050
1054
|
i.has(e.name) || (i.add(e.name), n.push(e));
|
|
1051
1055
|
}, o = e.appliedPrimaryKey ?? [];
|
|
@@ -1070,7 +1074,7 @@ BEGIN
|
|
|
1070
1074
|
table: e.tableName,
|
|
1071
1075
|
columns: c,
|
|
1072
1076
|
unique: n.unique ?? !1,
|
|
1073
|
-
...
|
|
1077
|
+
...de(r, s),
|
|
1074
1078
|
...n.where === void 0 ? {} : { where: n.where },
|
|
1075
1079
|
...l ? { expression: !0 } : {}
|
|
1076
1080
|
});
|
|
@@ -1096,11 +1100,11 @@ BEGIN
|
|
|
1096
1100
|
});
|
|
1097
1101
|
}
|
|
1098
1102
|
return n;
|
|
1099
|
-
},
|
|
1103
|
+
}, bn = (e, t) => {
|
|
1100
1104
|
let n = new Set((e.appliedUniques ?? []).filter((e) => e.fields.length === 1).map((e) => e.fields[0])), r = [];
|
|
1101
1105
|
for (let [t, i] of Object.entries(e.fields)) {
|
|
1102
1106
|
if (i.dropped) continue;
|
|
1103
|
-
let e =
|
|
1107
|
+
let e = vn(t, i);
|
|
1104
1108
|
r.push(n.has(t) ? {
|
|
1105
1109
|
...e,
|
|
1106
1110
|
unique: !0
|
|
@@ -1110,11 +1114,11 @@ BEGIN
|
|
|
1110
1114
|
return {
|
|
1111
1115
|
name: e.tableName,
|
|
1112
1116
|
columns: r,
|
|
1113
|
-
indexes:
|
|
1117
|
+
indexes: yn(e, t),
|
|
1114
1118
|
...i.length > 0 ? { primaryKey: [...i] } : {},
|
|
1115
1119
|
...a === void 0 ? {} : { renamedFrom: a }
|
|
1116
1120
|
};
|
|
1117
|
-
},
|
|
1121
|
+
}, xn = (e) => {
|
|
1118
1122
|
let t = /* @__PURE__ */ new Map();
|
|
1119
1123
|
for (let n of e) for (let e of n.indexes) {
|
|
1120
1124
|
let r = t.get(e.name);
|
|
@@ -1122,12 +1126,12 @@ BEGIN
|
|
|
1122
1126
|
t.set(e.name, n.name);
|
|
1123
1127
|
}
|
|
1124
1128
|
}, z = (e, t) => {
|
|
1125
|
-
let n = e.filter((e) => !c(e.tableName)).map((e) =>
|
|
1129
|
+
let n = e.filter((e) => !c(e.tableName)).map((e) => bn(ye(e, t), t));
|
|
1126
1130
|
if (t === "mysql" || t === "mariadb") {
|
|
1127
1131
|
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.`);
|
|
1128
1132
|
}
|
|
1129
|
-
return
|
|
1130
|
-
},
|
|
1133
|
+
return xn(n), { tables: t === void 0 ? n : n.map((e) => Sn(e, t)) };
|
|
1134
|
+
}, Sn = (e, t) => {
|
|
1131
1135
|
let n = new Set(e.indexes.flatMap((e) => e.columns));
|
|
1132
1136
|
return {
|
|
1133
1137
|
...e,
|
|
@@ -1136,20 +1140,20 @@ BEGIN
|
|
|
1136
1140
|
...e,
|
|
1137
1141
|
jsonValidation: e.type === "json" ? "value" : "container"
|
|
1138
1142
|
}), e.maxLength !== void 0) return e;
|
|
1139
|
-
let r =
|
|
1143
|
+
let r = on(e, t, n.has(e.name) || e.unique);
|
|
1140
1144
|
return r === void 0 ? e : {
|
|
1141
1145
|
...e,
|
|
1142
1146
|
maxLength: r
|
|
1143
1147
|
};
|
|
1144
1148
|
})
|
|
1145
1149
|
};
|
|
1146
|
-
},
|
|
1150
|
+
}, Cn = (e, t, n = A) => T.gen(function* () {
|
|
1147
1151
|
let r = (yield* e`
|
|
1148
1152
|
SELECT p.prosrc
|
|
1149
1153
|
FROM pg_proc p
|
|
1150
1154
|
JOIN pg_namespace n ON n.oid = p.pronamespace
|
|
1151
1155
|
WHERE n.nspname = current_schema()
|
|
1152
|
-
AND p.proname = ${
|
|
1156
|
+
AND p.proname = ${lt(n)}
|
|
1153
1157
|
`)[0]?.prosrc, i = r !== void 0 && !r.includes("voltro:notify:v2"), a = t.filter((e) => !e.tableName.startsWith("_voltro_"));
|
|
1154
1158
|
if (a.length === 0) return {
|
|
1155
1159
|
missing: [],
|
|
@@ -1163,10 +1167,10 @@ BEGIN
|
|
|
1163
1167
|
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
1164
1168
|
WHERE NOT t.tgisinternal
|
|
1165
1169
|
AND n.nspname = current_schema()
|
|
1166
|
-
AND t.tgname LIKE ${`${
|
|
1170
|
+
AND t.tgname LIKE ${`${st}%`}
|
|
1167
1171
|
`, s = new Set(o.map((e) => e.tgname)), c = [], l = [];
|
|
1168
1172
|
for (let e of a) {
|
|
1169
|
-
let t = s.has(
|
|
1173
|
+
let t = s.has(ct(e.tableName, n)), r = e.isReactive !== !1;
|
|
1170
1174
|
r && !t && c.push(e.tableName), !r && t && l.push(e.tableName);
|
|
1171
1175
|
}
|
|
1172
1176
|
return {
|
|
@@ -1174,7 +1178,7 @@ BEGIN
|
|
|
1174
1178
|
stale: l.sort(),
|
|
1175
1179
|
functionOutdated: i
|
|
1176
1180
|
};
|
|
1177
|
-
}),
|
|
1181
|
+
}), wn = (e) => {
|
|
1178
1182
|
let t = [];
|
|
1179
1183
|
if (e.missing.length > 0) {
|
|
1180
1184
|
let n = e.missing.slice(0, 8).join(", "), r = e.missing.length > 8 ? `, … (+${e.missing.length - 8})` : "";
|
|
@@ -1185,19 +1189,19 @@ BEGIN
|
|
|
1185
1189
|
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.`);
|
|
1186
1190
|
}
|
|
1187
1191
|
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;
|
|
1188
|
-
},
|
|
1192
|
+
}, Tn = {
|
|
1189
1193
|
postgres: !0,
|
|
1190
1194
|
mysql: !0,
|
|
1191
1195
|
mariadb: !0,
|
|
1192
1196
|
mssql: !0,
|
|
1193
1197
|
sqlite: !0
|
|
1194
|
-
},
|
|
1198
|
+
}, En = {
|
|
1195
1199
|
postgres: !0,
|
|
1196
1200
|
mysql: !1,
|
|
1197
1201
|
mariadb: !1,
|
|
1198
1202
|
mssql: !0,
|
|
1199
1203
|
sqlite: !0
|
|
1200
|
-
},
|
|
1204
|
+
}, Dn = (e) => {
|
|
1201
1205
|
switch (e) {
|
|
1202
1206
|
case "add-column":
|
|
1203
1207
|
case "drop-column":
|
|
@@ -1207,43 +1211,43 @@ BEGIN
|
|
|
1207
1211
|
case "add-foreign-key":
|
|
1208
1212
|
case "add-unique":
|
|
1209
1213
|
case "add-unique-composite":
|
|
1210
|
-
case "add-check": return
|
|
1211
|
-
default: return
|
|
1214
|
+
case "add-check": return En;
|
|
1215
|
+
default: return Tn;
|
|
1212
1216
|
}
|
|
1213
|
-
},
|
|
1217
|
+
}, On = (e, t) => {
|
|
1214
1218
|
let n = new Map(t.tables.map((e) => [e.name, e]));
|
|
1215
1219
|
return new Map(e.map((e) => [e.tableName, {
|
|
1216
1220
|
table: e,
|
|
1217
1221
|
snapshot: n.get(e.tableName),
|
|
1218
1222
|
columnDefs: e.fields
|
|
1219
1223
|
}]));
|
|
1220
|
-
},
|
|
1221
|
-
let n =
|
|
1224
|
+
}, kn = (e, t) => {
|
|
1225
|
+
let n = nn(e), r = nn(t);
|
|
1222
1226
|
if (n === r) return !0;
|
|
1223
|
-
let i =
|
|
1224
|
-
return e.type === "id" && t.type === "id" && (a(e) && n === null && i(t) || a(t) && r === null && i(e)) ? !0 :
|
|
1225
|
-
},
|
|
1227
|
+
let i = an, a = (e) => e.type === "id" && e.idScheme?.kind === "numeric";
|
|
1228
|
+
return e.type === "id" && t.type === "id" && (a(e) && n === null && i(t) || a(t) && r === null && i(e)) ? !0 : rn(e) === rn(t);
|
|
1229
|
+
}, An = (e, t) => {
|
|
1226
1230
|
let n = e && e.length > 0 ? e : void 0, r = t && t.length > 0 ? t : void 0;
|
|
1227
1231
|
if (!n && !r) return !0;
|
|
1228
1232
|
if (!n || !r || n.length !== r.length) return !1;
|
|
1229
1233
|
let i = [...n].sort(), a = [...r].sort();
|
|
1230
1234
|
return i.every((e, t) => e === a[t]);
|
|
1231
|
-
},
|
|
1235
|
+
}, jn = (e, t, n, r) => n === void 0 || m(n) ? !0 : e.type !== "text" || t.type !== "text" || on(e, n, r) === t.maxLength, Mn = (e, t, n, r, i = !1) => (e.type === t.type || tn(e, t, i)) && e.nullable === t.nullable && (e.unique === t.unique || tn(e, t, i)) && e.jsonValidation === t.jsonValidation && kn(e, t) && jn(e, t, n, r) && (e.type !== "reference" || (e.referenceStorage ?? "text") === (t.referenceStorage ?? "text")) && JSON.stringify(L(e.references)) === JSON.stringify(L(t.references)) && An(e.oneOf, t.oneOf), Nn = (e, t) => t.oneOf && t.oneOf.length > 0 ? B({
|
|
1232
1236
|
kind: "add-check",
|
|
1233
1237
|
table: e,
|
|
1234
1238
|
column: t.name,
|
|
1235
1239
|
values: t.oneOf
|
|
1236
|
-
}, "safe", `enum-membership CHECK on ${e}.${t.name}`) : void 0,
|
|
1240
|
+
}, "safe", `enum-membership CHECK on ${e}.${t.name}`) : void 0, Pn = (e, t) => e.unique === t.unique && e.valid !== !1 && t.valid !== !1 && ln(e.where) === ln(t.where) && JSON.stringify(de(e.kind, e.kindOptions)) === JSON.stringify(de(t.kind, t.kindOptions)) && (e.expression || t.expression ? !0 : e.columns.length === t.columns.length && e.columns.every((e, n) => e === t.columns[n])), Fn = (e, t, n) => {
|
|
1237
1241
|
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));
|
|
1238
1242
|
for (let t of e.columns) {
|
|
1239
|
-
let
|
|
1240
|
-
if (!
|
|
1243
|
+
let i = r.get(t.name);
|
|
1244
|
+
if (!i) {
|
|
1241
1245
|
a.push(t);
|
|
1242
1246
|
continue;
|
|
1243
1247
|
}
|
|
1244
|
-
|
|
1248
|
+
Mn(t, i, n, c.has(t.name) || t.unique, en(e, t)) || s.push({
|
|
1245
1249
|
declared: t,
|
|
1246
|
-
live:
|
|
1250
|
+
live: i
|
|
1247
1251
|
});
|
|
1248
1252
|
}
|
|
1249
1253
|
for (let e of t.columns) i.has(e.name) || o.push(e);
|
|
@@ -1252,15 +1256,15 @@ BEGIN
|
|
|
1252
1256
|
removed: o,
|
|
1253
1257
|
changed: s
|
|
1254
1258
|
};
|
|
1255
|
-
},
|
|
1259
|
+
}, In = (e, t, n) => {
|
|
1256
1260
|
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 = [];
|
|
1257
1261
|
for (let t of e.indexes) {
|
|
1258
1262
|
let e = i.get(r(t.name));
|
|
1259
|
-
(!e || !
|
|
1263
|
+
(!e || !Pn(t, e)) && o.push(t);
|
|
1260
1264
|
}
|
|
1261
1265
|
for (let e of t.indexes) {
|
|
1262
1266
|
let t = a.get(r(e.name));
|
|
1263
|
-
(!t || !
|
|
1267
|
+
(!t || !Pn(t, e)) && s.push(e);
|
|
1264
1268
|
}
|
|
1265
1269
|
return {
|
|
1266
1270
|
added: o,
|
|
@@ -1269,33 +1273,33 @@ BEGIN
|
|
|
1269
1273
|
}, B = (e, t, n, r) => ({
|
|
1270
1274
|
op: e,
|
|
1271
1275
|
classification: t,
|
|
1272
|
-
atomicByDialect:
|
|
1276
|
+
atomicByDialect: Dn(e.kind),
|
|
1273
1277
|
...n ? { reason: n } : {},
|
|
1274
1278
|
...r ? { blocked: r } : {}
|
|
1275
|
-
}),
|
|
1279
|
+
}), Ln = (e, t, n) => {
|
|
1276
1280
|
let r = {
|
|
1277
1281
|
kind: "add-column",
|
|
1278
1282
|
table: e,
|
|
1279
1283
|
column: t
|
|
1280
1284
|
};
|
|
1281
1285
|
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
|
-
},
|
|
1286
|
+
}, Rn = (e, t, n) => {
|
|
1283
1287
|
let r = {
|
|
1284
1288
|
kind: "drop-column",
|
|
1285
1289
|
table: e,
|
|
1286
1290
|
column: t.name
|
|
1287
1291
|
};
|
|
1288
1292
|
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
|
-
},
|
|
1293
|
+
}, zn = (e, t, n, r, i) => B({
|
|
1290
1294
|
kind: "create-table",
|
|
1291
1295
|
table: e,
|
|
1292
1296
|
columns: t,
|
|
1293
1297
|
indexes: n,
|
|
1294
1298
|
...r && r.length > 0 ? { primaryKey: r } : {}
|
|
1295
|
-
}, "safe", i ?? "new table — no data to preserve"),
|
|
1299
|
+
}, "safe", i ?? "new table — no data to preserve"), Bn = (e) => B({
|
|
1296
1300
|
kind: "drop-table",
|
|
1297
1301
|
table: e
|
|
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" }),
|
|
1302
|
+
}, "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" }), Vn = 5e4, Hn = (e, t, n, r) => {
|
|
1299
1303
|
let i = (n ?? 0) >= r, a;
|
|
1300
1304
|
return a = !t.unique || t.where !== void 0 ? {
|
|
1301
1305
|
kind: "add-index",
|
|
@@ -1311,7 +1315,7 @@ BEGIN
|
|
|
1311
1315
|
name: t.name,
|
|
1312
1316
|
fields: t.columns
|
|
1313
1317
|
}, 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
|
-
},
|
|
1318
|
+
}, Un = (e, t) => t.unique && t.where === void 0 && t.columns.length > 1 ? B({
|
|
1315
1319
|
kind: "drop-unique-composite",
|
|
1316
1320
|
table: e,
|
|
1317
1321
|
name: t.name
|
|
@@ -1319,7 +1323,7 @@ BEGIN
|
|
|
1319
1323
|
kind: "drop-index",
|
|
1320
1324
|
table: e,
|
|
1321
1325
|
index: t.name
|
|
1322
|
-
}, "safe", "drop index (no data loss — index is derived data)"),
|
|
1326
|
+
}, "safe", "drop index (no data loss — index is derived data)"), Wn = (e, t) => {
|
|
1323
1327
|
let n = e.type;
|
|
1324
1328
|
if (n === "reference") return e.referenceStorage === "numeric" ? "bigint" : "text";
|
|
1325
1329
|
switch (t) {
|
|
@@ -1328,10 +1332,10 @@ BEGIN
|
|
|
1328
1332
|
case "mssql": return n === "json" || n === "array" ? "text" : n;
|
|
1329
1333
|
default: return n;
|
|
1330
1334
|
}
|
|
1331
|
-
},
|
|
1335
|
+
}, Gn = (e, t, n) => {
|
|
1332
1336
|
let r = `acknowledge it on the column: \`.narrowedFrom('${e}')\``;
|
|
1333
1337
|
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`;
|
|
1334
|
-
},
|
|
1338
|
+
}, Kn = (e, t, n, r, i, a) => {
|
|
1335
1339
|
let o = [];
|
|
1336
1340
|
if (t.nullable !== n.nullable) {
|
|
1337
1341
|
let n = {
|
|
@@ -1356,7 +1360,7 @@ BEGIN
|
|
|
1356
1360
|
column: t.name
|
|
1357
1361
|
}, "safe", `drop unique constraint on ${e}.${t.name} — constraint is derived metadata, no data loss`));
|
|
1358
1362
|
}
|
|
1359
|
-
if (
|
|
1363
|
+
if (Wn(t, r) !== Wn(n, r)) {
|
|
1360
1364
|
let i = t.narrowedFrom;
|
|
1361
1365
|
if (i && i.from === n.type) {
|
|
1362
1366
|
let r = {
|
|
@@ -1376,7 +1380,7 @@ BEGIN
|
|
|
1376
1380
|
from: n.type,
|
|
1377
1381
|
to: t.type
|
|
1378
1382
|
};
|
|
1379
|
-
o.push(B(i, "lossy", `type change ${n.type} → ${t.type} on ${e}.${t.name} may not be value-preserving`, { fix:
|
|
1383
|
+
o.push(B(i, "lossy", `type change ${n.type} → ${t.type} on ${e}.${t.name} may not be value-preserving`, { fix: Gn(n.type, t, r) }));
|
|
1380
1384
|
}
|
|
1381
1385
|
}
|
|
1382
1386
|
if (t.type === "text" && n.type === "text" && !m(r ?? "postgres") && t.maxLength !== n.maxLength) {
|
|
@@ -1389,7 +1393,7 @@ BEGIN
|
|
|
1389
1393
|
to: "text"
|
|
1390
1394
|
}, 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)}`));
|
|
1391
1395
|
}
|
|
1392
|
-
if (!
|
|
1396
|
+
if (!kn(t, n)) {
|
|
1393
1397
|
let n = {
|
|
1394
1398
|
kind: "alter-column-default",
|
|
1395
1399
|
table: e,
|
|
@@ -1410,21 +1414,21 @@ BEGIN
|
|
|
1410
1414
|
dropConstraints: (n.jsonChecks ?? []).map((e) => e.name).sort()
|
|
1411
1415
|
}, 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`));
|
|
1412
1416
|
}
|
|
1413
|
-
if (!
|
|
1417
|
+
if (!An(t.oneOf, n.oneOf)) {
|
|
1414
1418
|
n.oneOf && n.oneOf.length > 0 && o.push(B({
|
|
1415
1419
|
kind: "drop-check",
|
|
1416
1420
|
table: e,
|
|
1417
1421
|
column: t.name
|
|
1418
1422
|
}, "safe", `drop stale enum CHECK on ${e}.${t.name}`));
|
|
1419
|
-
let r =
|
|
1423
|
+
let r = Nn(e, t);
|
|
1420
1424
|
r && o.push(r);
|
|
1421
1425
|
}
|
|
1422
|
-
return JSON.stringify(
|
|
1426
|
+
return JSON.stringify(L(t.references)) !== JSON.stringify(L(n.references)) && (n.references && o.push(B({
|
|
1423
1427
|
kind: "drop-foreign-key",
|
|
1424
1428
|
table: e,
|
|
1425
1429
|
column: t.name
|
|
1426
|
-
}, "safe", `drop FK on ${e}.${t.name} (→ ${n.references.table})`)), o.push(...
|
|
1427
|
-
},
|
|
1430
|
+
}, "safe", `drop FK on ${e}.${t.name} (→ ${n.references.table})`)), o.push(...qn(e, t))), o;
|
|
1431
|
+
}, qn = (e, t) => {
|
|
1428
1432
|
let n = [];
|
|
1429
1433
|
if (!t.references) return n;
|
|
1430
1434
|
let r = t.references.table, i = t.references.orphanPolicy ?? "fail", a = {
|
|
@@ -1440,7 +1444,7 @@ BEGIN
|
|
|
1440
1444
|
...a,
|
|
1441
1445
|
orphanPolicy: i
|
|
1442
1446
|
}, "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
|
-
},
|
|
1447
|
+
}, Jn = (e, t, n) => {
|
|
1444
1448
|
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));
|
|
1445
1449
|
for (let [n, c] of Object.entries(t)) {
|
|
1446
1450
|
let t = c.renamedFrom;
|
|
@@ -1456,22 +1460,22 @@ BEGIN
|
|
|
1456
1460
|
consumedAddedNames: i,
|
|
1457
1461
|
consumedRemovedNames: a
|
|
1458
1462
|
};
|
|
1459
|
-
},
|
|
1463
|
+
}, Yn = /* @__PURE__ */ new Set([
|
|
1460
1464
|
"postgres",
|
|
1461
1465
|
"mysql",
|
|
1462
1466
|
"mariadb",
|
|
1463
1467
|
"mssql"
|
|
1464
|
-
]),
|
|
1468
|
+
]), Xn = {
|
|
1465
1469
|
ops: [],
|
|
1466
1470
|
consumedAddedNames: /* @__PURE__ */ new Set(),
|
|
1467
1471
|
consumedRemovedNames: /* @__PURE__ */ new Set()
|
|
1468
|
-
},
|
|
1469
|
-
if (i === void 0 || !
|
|
1470
|
-
let a = t.added.filter((e) =>
|
|
1471
|
-
if (a.length === 0) return
|
|
1472
|
+
}, Zn = (e) => !e.unique && !e.expression && e.where === void 0 && (e.kind === void 0 || e.kind === "btree"), Qn = (e, t, n, r, i) => {
|
|
1473
|
+
if (i === void 0 || !Yn.has(i)) return Xn;
|
|
1474
|
+
let a = t.added.filter((e) => Zn(e) && !r.has(e.name));
|
|
1475
|
+
if (a.length === 0) return Xn;
|
|
1472
1476
|
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();
|
|
1473
1477
|
for (let n of t.removed) {
|
|
1474
|
-
if (!
|
|
1478
|
+
if (!Zn(n) || t.added.some((e) => e.name === n.name)) continue;
|
|
1475
1479
|
let r = o(n), i = a.filter((e) => !l.has(e.name) && s(e) === r);
|
|
1476
1480
|
if (i.length !== 1) continue;
|
|
1477
1481
|
let d = i[0];
|
|
@@ -1487,7 +1491,7 @@ BEGIN
|
|
|
1487
1491
|
consumedAddedNames: l,
|
|
1488
1492
|
consumedRemovedNames: u
|
|
1489
1493
|
};
|
|
1490
|
-
},
|
|
1494
|
+
}, $n = (e, t, n) => {
|
|
1491
1495
|
let r = [], i = /* @__PURE__ */ new Map(), a = /* @__PURE__ */ new Set(), o = /* @__PURE__ */ new Map(), s = /* @__PURE__ */ new Map(), c = /* @__PURE__ */ new Set();
|
|
1492
1496
|
for (let t of e.tables) t.renamedFrom !== void 0 && (s.set(t.renamedFrom, (s.get(t.renamedFrom) ?? 0) + 1), c.add(t.renamedFrom));
|
|
1493
1497
|
for (let c of e.tables) {
|
|
@@ -1527,12 +1531,12 @@ BEGIN
|
|
|
1527
1531
|
claimedOldNames: c,
|
|
1528
1532
|
refusals: o
|
|
1529
1533
|
};
|
|
1530
|
-
},
|
|
1534
|
+
}, er = (e, t, n, r) => {
|
|
1531
1535
|
if (t === void 0) return {
|
|
1532
1536
|
live: e,
|
|
1533
1537
|
ops: []
|
|
1534
1538
|
};
|
|
1535
|
-
let i = r !== void 0 &&
|
|
1539
|
+
let i = r !== void 0 && Yn.has(r), a = [], o = e.indexes.map((e) => {
|
|
1536
1540
|
if (!e.name.startsWith(t)) return e;
|
|
1537
1541
|
let r = `${n}${e.name.slice(t.length)}`;
|
|
1538
1542
|
return r === e.name ? e : e.name === `${t}_pkey` ? {
|
|
@@ -1558,7 +1562,7 @@ BEGIN
|
|
|
1558
1562
|
},
|
|
1559
1563
|
ops: a
|
|
1560
1564
|
};
|
|
1561
|
-
},
|
|
1565
|
+
}, tr = (e) => {
|
|
1562
1566
|
let t = {
|
|
1563
1567
|
safe: 0,
|
|
1564
1568
|
needsDefault: 0,
|
|
@@ -1591,13 +1595,13 @@ BEGIN
|
|
|
1591
1595
|
case "multi-step": t.multiStep++;
|
|
1592
1596
|
}
|
|
1593
1597
|
return t;
|
|
1594
|
-
},
|
|
1595
|
-
let t = z(e.declared, e.dialect), n =
|
|
1598
|
+
}, nr = (e) => {
|
|
1599
|
+
let t = z(e.declared, e.dialect), n = On(e.declared, t), r = new Map(e.live.tables.map((e) => [e.name, e])), i = e.onlineAfter ?? Vn, a = [], o = $n(t, r, n);
|
|
1596
1600
|
a.push(...o.ops);
|
|
1597
1601
|
for (let e of t.tables) if (!o.renamedInto.has(e.name) && !r.has(e.name)) {
|
|
1598
|
-
a.push(
|
|
1602
|
+
a.push(zn(e.name, e.columns, e.indexes, e.primaryKey, o.refusals.get(e.name)));
|
|
1599
1603
|
for (let t of e.columns) {
|
|
1600
|
-
let n =
|
|
1604
|
+
let n = Nn(e.name, t);
|
|
1601
1605
|
n && a.push(n);
|
|
1602
1606
|
}
|
|
1603
1607
|
}
|
|
@@ -1619,19 +1623,19 @@ BEGIN
|
|
|
1619
1623
|
c.push(t.name);
|
|
1620
1624
|
continue;
|
|
1621
1625
|
}
|
|
1622
|
-
a.push(
|
|
1626
|
+
a.push(Bn(t.name));
|
|
1623
1627
|
}
|
|
1624
1628
|
for (let s of t.tables) {
|
|
1625
1629
|
let t = o.renamedInto.get(s.name), c = r.get(s.name) ?? (t === void 0 ? void 0 : r.get(t));
|
|
1626
1630
|
if (!c) continue;
|
|
1627
|
-
let l =
|
|
1631
|
+
let l = er(c, t, s.name, e.dialect);
|
|
1628
1632
|
a.push(...l.ops);
|
|
1629
|
-
let u = l.live, d = n.get(s.name), f =
|
|
1633
|
+
let u = l.live, d = n.get(s.name), f = Fn(s, u, e.dialect), p = In(s, u, e.dialect), m = Jn(d.table, d.columnDefs, f);
|
|
1630
1634
|
a.push(...m.ops);
|
|
1631
1635
|
for (let { op: t } of m.ops) {
|
|
1632
1636
|
if (t.kind !== "rename-column") continue;
|
|
1633
1637
|
let n = s.columns.find((e) => e.name === t.to), r = u.columns.find((e) => e.name === t.from);
|
|
1634
|
-
n && r && a.push(...
|
|
1638
|
+
n && r && a.push(...Kn(s.name, n, {
|
|
1635
1639
|
...r,
|
|
1636
1640
|
name: t.to
|
|
1637
1641
|
}, e.dialect, u.rowCount, i));
|
|
@@ -1639,20 +1643,20 @@ BEGIN
|
|
|
1639
1643
|
for (let e of f.removed) {
|
|
1640
1644
|
if (m.consumedRemovedNames.has(e.name) || x(e.name)) continue;
|
|
1641
1645
|
let t = d.columnDefs[e.name];
|
|
1642
|
-
a.push(
|
|
1646
|
+
a.push(Rn(s.name, e, t));
|
|
1643
1647
|
}
|
|
1644
1648
|
for (let e of f.added) {
|
|
1645
1649
|
if (m.consumedAddedNames.has(e.name)) continue;
|
|
1646
1650
|
let t = d.columnDefs[e.name];
|
|
1647
|
-
a.push(
|
|
1648
|
-
let n =
|
|
1649
|
-
n && a.push(n), a.push(...
|
|
1651
|
+
a.push(Ln(s.name, e, t));
|
|
1652
|
+
let n = Nn(s.name, e);
|
|
1653
|
+
n && a.push(n), a.push(...qn(s.name, e));
|
|
1650
1654
|
}
|
|
1651
|
-
let h = new Map(m.ops.flatMap((e) => e.op.kind === "rename-column" ? [[e.op.from, e.op.to]] : [])), g =
|
|
1655
|
+
let h = new Map(m.ops.flatMap((e) => e.op.kind === "rename-column" ? [[e.op.from, e.op.to]] : [])), g = Qn(s.name, p, h, new Set(u.indexes.map((e) => e.name)), e.dialect);
|
|
1652
1656
|
a.push(...g.ops);
|
|
1653
|
-
for (let e of p.added) g.consumedAddedNames.has(e.name) || a.push(
|
|
1654
|
-
for (let e of p.removed) g.consumedRemovedNames.has(e.name) || a.push(
|
|
1655
|
-
for (let { declared: t, live: n } of f.changed) a.push(...
|
|
1657
|
+
for (let e of p.added) g.consumedAddedNames.has(e.name) || a.push(Hn(s.name, e, u.rowCount, i));
|
|
1658
|
+
for (let e of p.removed) g.consumedRemovedNames.has(e.name) || a.push(Un(s.name, e));
|
|
1659
|
+
for (let { declared: t, live: n } of f.changed) a.push(...Kn(s.name, t, n, e.dialect, u.rowCount, i));
|
|
1656
1660
|
}
|
|
1657
1661
|
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) => {
|
|
1658
1662
|
let t = u.get(e);
|
|
@@ -1660,8 +1664,8 @@ BEGIN
|
|
|
1660
1664
|
column: e.name,
|
|
1661
1665
|
target: e.references.table
|
|
1662
1666
|
}] : []) : [];
|
|
1663
|
-
}, f =
|
|
1664
|
-
for (let e of t.tables) if (l.has(e.name)) for (let t of e.columns) t.references && f.has(
|
|
1667
|
+
}, f = be([...l], d), p = [];
|
|
1668
|
+
for (let e of t.tables) if (l.has(e.name)) for (let t of e.columns) t.references && f.has(D(e.name, t.name)) && p.push(B({
|
|
1665
1669
|
kind: "add-foreign-key",
|
|
1666
1670
|
table: e.name,
|
|
1667
1671
|
column: t.name,
|
|
@@ -1676,8 +1680,8 @@ BEGIN
|
|
|
1676
1680
|
let n = a[t];
|
|
1677
1681
|
if (n.op.kind !== "create-table") continue;
|
|
1678
1682
|
let r = n.op;
|
|
1679
|
-
if (!r.columns.some((e) => f.has(
|
|
1680
|
-
let i = r.columns.map((t) => f.has(
|
|
1683
|
+
if (!r.columns.some((e) => f.has(D(r.table, e.name)))) continue;
|
|
1684
|
+
let i = r.columns.map((t) => f.has(D(r.table, t.name)) ? e(t) : t);
|
|
1681
1685
|
a[t] = {
|
|
1682
1686
|
...n,
|
|
1683
1687
|
op: {
|
|
@@ -1697,7 +1701,7 @@ BEGIN
|
|
|
1697
1701
|
let i = new Set(t).add(e), a = 0;
|
|
1698
1702
|
for (let t of r.columns) {
|
|
1699
1703
|
let n = t.references?.table;
|
|
1700
|
-
n && n !== e && !f.has(
|
|
1704
|
+
n && n !== e && !f.has(D(e, t.name)) && (a = Math.max(a, g(n, i) + 1));
|
|
1701
1705
|
}
|
|
1702
1706
|
return h.set(e, a), a;
|
|
1703
1707
|
}, v = (e) => e === "rename-table" ? -1 : e === "create-table" ? 0 : e === "drop-table" ? 2 : 1, y = (e) => {
|
|
@@ -1743,13 +1747,13 @@ BEGIN
|
|
|
1743
1747
|
operations: C,
|
|
1744
1748
|
fromFingerprint: R(e.live),
|
|
1745
1749
|
toFingerprint: R(t),
|
|
1746
|
-
summary:
|
|
1750
|
+
summary: tr(C),
|
|
1747
1751
|
fingerprintDivergence: {
|
|
1748
1752
|
outsideDiff: c,
|
|
1749
1753
|
diffEquivalent: T
|
|
1750
1754
|
}
|
|
1751
1755
|
};
|
|
1752
|
-
},
|
|
1756
|
+
}, rr = (e, t) => {
|
|
1753
1757
|
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
1758
|
if (!i("check")) return null;
|
|
1755
1759
|
let a = n[r++];
|
|
@@ -1764,7 +1768,7 @@ BEGIN
|
|
|
1764
1768
|
if (e === void 0 || !/^'(?:''|[^'])*'$/.test(e) || (c.push(e.slice(1, -1).replace(/''/g, "'")), !o())) return null;
|
|
1765
1769
|
} while (s && i(","));
|
|
1766
1770
|
return s && (!i("]") || i("::") && (!i("text") || !i("[") || !i("]"))) ? null : r === n.length ? c : null;
|
|
1767
|
-
},
|
|
1771
|
+
}, ir = (e) => {
|
|
1768
1772
|
let t = /[`"[]?([A-Za-z_][A-Za-z0-9_]*)[`"\]]?\s*(?:in\b|=)/i.exec(e);
|
|
1769
1773
|
if (!t) return null;
|
|
1770
1774
|
let n = [...e.replace(/\\'/g, "'").matchAll(/'((?:[^']|'')*)'/g)].map((e) => e[1].replace(/''/g, "'")).filter((e) => e.length > 0);
|
|
@@ -1772,7 +1776,7 @@ BEGIN
|
|
|
1772
1776
|
column: t[1],
|
|
1773
1777
|
values: n
|
|
1774
1778
|
};
|
|
1775
|
-
},
|
|
1779
|
+
}, ar = (e, t) => {
|
|
1776
1780
|
if (t === "vector" || t === "halfvec") return "vector";
|
|
1777
1781
|
switch (e) {
|
|
1778
1782
|
case "text":
|
|
@@ -1799,7 +1803,7 @@ BEGIN
|
|
|
1799
1803
|
case "USER-DEFINED": return "text";
|
|
1800
1804
|
default: return "text";
|
|
1801
1805
|
}
|
|
1802
|
-
},
|
|
1806
|
+
}, or = (e, t) => e == null || e === "" ? void 0 : { generatedAs: {
|
|
1803
1807
|
expr: e,
|
|
1804
1808
|
stored: t
|
|
1805
1809
|
} }, V = (e) => {
|
|
@@ -1810,25 +1814,25 @@ BEGIN
|
|
|
1810
1814
|
case "SET DEFAULT": return "noAction";
|
|
1811
1815
|
default: return "noAction";
|
|
1812
1816
|
}
|
|
1813
|
-
},
|
|
1817
|
+
}, sr = (e, t) => {
|
|
1814
1818
|
let n = e !== void 0 && e !== "" ? Number(e) : NaN;
|
|
1815
1819
|
return Number.isInteger(n) && n > 0 ? n : t;
|
|
1816
|
-
},
|
|
1820
|
+
}, cr = () => sr(process.env.VOLTRO_INTROSPECT_BATCH, 20), lr = 300, ur = () => {
|
|
1817
1821
|
let e = process.env.VOLTRO_INTROSPECT_TIMEOUT_MS;
|
|
1818
|
-
return e !== void 0 && e.trim() === "0" ? 0 :
|
|
1819
|
-
},
|
|
1822
|
+
return e !== void 0 && e.trim() === "0" ? 0 : sr(e, 3e4);
|
|
1823
|
+
}, dr = (e, t) => {
|
|
1820
1824
|
let n = Number.isFinite(t) && t >= 1 ? Math.floor(t) : 1, r = [];
|
|
1821
1825
|
for (let t = 0; t < e.length; t += n) r.push(e.slice(t, t + n));
|
|
1822
1826
|
return r;
|
|
1823
|
-
},
|
|
1824
|
-
let t =
|
|
1827
|
+
}, fr = (e) => {
|
|
1828
|
+
let t = ur(), n = T.gen(function* () {
|
|
1825
1829
|
t > 0 && (yield* e.unsafe(`SET LOCAL statement_timeout = ${t}`));
|
|
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 =
|
|
1830
|
+
let n = (t) => e.unsafe("(" + t.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ") + ")"), r = (t) => e.unsafe(String(Math.max(0, Math.trunc(t)))), i = cr(), a = (e, t) => T.gen(function* () {
|
|
1827
1831
|
let r = [];
|
|
1828
|
-
for (let a of
|
|
1832
|
+
for (let a of dr(e, i)) a.length !== 0 && r.push(...yield* t(n(a)));
|
|
1829
1833
|
return r;
|
|
1830
1834
|
}), o = [];
|
|
1831
|
-
for (let t = 0;; t +=
|
|
1835
|
+
for (let t = 0;; t += lr) {
|
|
1832
1836
|
let n = yield* e`
|
|
1833
1837
|
SELECT c.relname AS table_name,
|
|
1834
1838
|
COALESCE(c.reltuples::bigint, 0) AS row_count
|
|
@@ -1836,9 +1840,9 @@ BEGIN
|
|
|
1836
1840
|
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
1837
1841
|
WHERE n.nspname = current_schema() AND c.relkind = 'r'
|
|
1838
1842
|
ORDER BY c.relname
|
|
1839
|
-
LIMIT ${r(
|
|
1843
|
+
LIMIT ${r(lr)} OFFSET ${r(t)}
|
|
1840
1844
|
`;
|
|
1841
|
-
if (o.push(...n), n.length <
|
|
1845
|
+
if (o.push(...n), n.length < lr) break;
|
|
1842
1846
|
}
|
|
1843
1847
|
let s = /* @__PURE__ */ new Set(), c = [];
|
|
1844
1848
|
for (let e of o) s.has(e.table_name) || (s.add(e.table_name), c.push(e));
|
|
@@ -1880,7 +1884,7 @@ BEGIN
|
|
|
1880
1884
|
AND rel.relname IN ${t}
|
|
1881
1885
|
`), m = /* @__PURE__ */ new Map();
|
|
1882
1886
|
for (let e of p) {
|
|
1883
|
-
let t =
|
|
1887
|
+
let t = rr(e.def, e.column_name);
|
|
1884
1888
|
t !== null && m.set(`${e.table_name}.${e.column_name}`, t);
|
|
1885
1889
|
}
|
|
1886
1890
|
let h = yield* a(l, (t) => e`
|
|
@@ -1986,7 +1990,7 @@ BEGIN
|
|
|
1986
1990
|
let w = [];
|
|
1987
1991
|
for (let e of c) {
|
|
1988
1992
|
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) => {
|
|
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" :
|
|
1993
|
+
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" : ar(t.data_type, t.udt_name), c = a ? {
|
|
1990
1994
|
table: a.target_table,
|
|
1991
1995
|
column: a.target_column,
|
|
1992
1996
|
onDelete: V(a.delete_rule),
|
|
@@ -2005,9 +2009,9 @@ BEGIN
|
|
|
2005
2009
|
hasDefault: t.column_default !== null,
|
|
2006
2010
|
...t.column_default === null ? {} : { defaultValue: t.column_default },
|
|
2007
2011
|
...c ? { references: c } : {},
|
|
2008
|
-
...a ? { referenceStorage: ["integer", "bigint"].includes(
|
|
2012
|
+
...a ? { referenceStorage: ["integer", "bigint"].includes(ar(t.data_type, t.udt_name)) ? "numeric" : "text" } : {},
|
|
2009
2013
|
...l ? { oneOf: l } : {},
|
|
2010
|
-
...
|
|
2014
|
+
...or(t.is_generated === "ALWAYS" ? t.generation_expression ?? "generated" : null, !0) ?? {}
|
|
2011
2015
|
};
|
|
2012
2016
|
}), l = [], u = S.get(e.table_name);
|
|
2013
2017
|
if (u) for (let [t, n] of u) {
|
|
@@ -2026,7 +2030,7 @@ BEGIN
|
|
|
2026
2030
|
table: e.table_name,
|
|
2027
2031
|
columns: i.map((e) => e.column_name),
|
|
2028
2032
|
unique: n[0]?.is_unique ?? !1,
|
|
2029
|
-
...
|
|
2033
|
+
...de(o?.access_method, o?.access_method === "hnsw" ? { hnsw: {
|
|
2030
2034
|
opclass: o.operator_class,
|
|
2031
2035
|
m: c.get("m") ?? 16,
|
|
2032
2036
|
efConstruction: c.get("ef_construction") ?? 64
|
|
@@ -2057,7 +2061,7 @@ BEGIN
|
|
|
2057
2061
|
let n = `${String(e)} ${String(e.cause ?? "")}`.toLowerCase();
|
|
2058
2062
|
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);
|
|
2059
2063
|
}));
|
|
2060
|
-
},
|
|
2064
|
+
}, pr = (e, t) => {
|
|
2061
2065
|
switch (e.toLowerCase()) {
|
|
2062
2066
|
case "varchar":
|
|
2063
2067
|
case "char":
|
|
@@ -2089,21 +2093,21 @@ BEGIN
|
|
|
2089
2093
|
case "json": return "json";
|
|
2090
2094
|
default: return "text";
|
|
2091
2095
|
}
|
|
2092
|
-
},
|
|
2096
|
+
}, mr = (e) => e.map((e) => {
|
|
2093
2097
|
let t = e, n = {};
|
|
2094
2098
|
for (let e of Object.keys(t)) n[e.toLowerCase()] = t[e];
|
|
2095
2099
|
return n;
|
|
2096
|
-
}),
|
|
2097
|
-
let t =
|
|
2100
|
+
}), hr = (e) => T.gen(function* () {
|
|
2101
|
+
let t = mr(yield* e`
|
|
2098
2102
|
SELECT table_name, COALESCE(table_rows, 0) AS table_rows
|
|
2099
2103
|
FROM information_schema.tables
|
|
2100
2104
|
WHERE table_schema = DATABASE() AND table_type = 'BASE TABLE'
|
|
2101
|
-
ORDER BY table_name`), n =
|
|
2105
|
+
ORDER BY table_name`), n = mr(yield* e`
|
|
2102
2106
|
SELECT table_name, column_name, data_type, column_type, is_nullable, column_default, column_key,
|
|
2103
2107
|
character_maximum_length, generation_expression, extra
|
|
2104
2108
|
FROM information_schema.columns
|
|
2105
2109
|
WHERE table_schema = DATABASE()
|
|
2106
|
-
ORDER BY table_name, ordinal_position`), r =
|
|
2110
|
+
ORDER BY table_name, ordinal_position`), r = mr(yield* e`
|
|
2107
2111
|
SELECT k.table_name AS source_table,
|
|
2108
2112
|
k.column_name AS source_column,
|
|
2109
2113
|
k.referenced_table_name AS target_table,
|
|
@@ -2113,7 +2117,7 @@ BEGIN
|
|
|
2113
2117
|
JOIN information_schema.referential_constraints r
|
|
2114
2118
|
ON k.constraint_name = r.constraint_name
|
|
2115
2119
|
AND k.table_schema = r.constraint_schema
|
|
2116
|
-
WHERE k.table_schema = DATABASE() AND k.referenced_table_name IS NOT NULL`), i =
|
|
2120
|
+
WHERE k.table_schema = DATABASE() AND k.referenced_table_name IS NOT NULL`), i = mr(yield* e`
|
|
2117
2121
|
SELECT table_name, index_name, non_unique, column_name, seq_in_index
|
|
2118
2122
|
FROM information_schema.statistics
|
|
2119
2123
|
WHERE table_schema = DATABASE() AND index_name <> 'PRIMARY'
|
|
@@ -2126,14 +2130,14 @@ BEGIN
|
|
|
2126
2130
|
JOIN information_schema.table_constraints tc
|
|
2127
2131
|
ON tc.constraint_schema = cc.constraint_schema
|
|
2128
2132
|
AND tc.constraint_name = cc.constraint_name
|
|
2129
|
-
WHERE cc.constraint_schema = DATABASE()`.unprepared, s =
|
|
2133
|
+
WHERE cc.constraint_schema = DATABASE()`.unprepared, s = mr(yield* a.pipe(T.orElse(() => o), T.orElseSucceed(() => []))), c = /* @__PURE__ */ new Set(), l = /* @__PURE__ */ new Map();
|
|
2130
2134
|
for (let e of s) {
|
|
2131
2135
|
let t = /json_valid\(`?([^`)]+)`?\)/i.exec(e.check_clause);
|
|
2132
2136
|
if (t) {
|
|
2133
2137
|
c.add(`${e.table_name}.${t[1]}`);
|
|
2134
2138
|
continue;
|
|
2135
2139
|
}
|
|
2136
|
-
let n =
|
|
2140
|
+
let n = ir(e.check_clause);
|
|
2137
2141
|
n && l.set(`${e.table_name}.${n.column}`, n.values);
|
|
2138
2142
|
}
|
|
2139
2143
|
let u = /* @__PURE__ */ new Map(), d = /* @__PURE__ */ new Map(), f = /* @__PURE__ */ new Map();
|
|
@@ -2156,7 +2160,7 @@ BEGIN
|
|
|
2156
2160
|
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);
|
|
2157
2161
|
if (o) for (let e of o.values()) e.length === 1 && e[0].non_unique === 0 && a.add(e[0].column_name);
|
|
2158
2162
|
let s = t.map((t) => {
|
|
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" :
|
|
2163
|
+
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" : pr(t.data_type, t.column_type), u = o ? {
|
|
2160
2164
|
table: o.target_table,
|
|
2161
2165
|
column: o.target_column,
|
|
2162
2166
|
onDelete: V(o.delete_rule),
|
|
@@ -2171,9 +2175,9 @@ BEGIN
|
|
|
2171
2175
|
hasDefault: f !== null,
|
|
2172
2176
|
...f === null ? {} : { defaultValue: f },
|
|
2173
2177
|
...u ? { references: u } : {},
|
|
2174
|
-
...o ? { referenceStorage: ["integer", "bigint"].includes(
|
|
2178
|
+
...o ? { referenceStorage: ["integer", "bigint"].includes(pr(t.data_type, t.column_type)) ? "numeric" : "text" } : {},
|
|
2175
2179
|
...p ? { oneOf: p } : {},
|
|
2176
|
-
...
|
|
2180
|
+
...or(t.generation_expression, /STORED/i.test(t.extra ?? "")) ?? {}
|
|
2177
2181
|
};
|
|
2178
2182
|
}), m = new Set(n.map((e) => e.source_column)), h = [];
|
|
2179
2183
|
if (o) for (let [t, n] of o) {
|
|
@@ -2200,10 +2204,10 @@ BEGIN
|
|
|
2200
2204
|
});
|
|
2201
2205
|
}
|
|
2202
2206
|
return { tables: p };
|
|
2203
|
-
}),
|
|
2207
|
+
}), gr = (e) => {
|
|
2204
2208
|
let t = e.toUpperCase();
|
|
2205
2209
|
return t.includes("INT") ? "integer" : t.includes("REAL") || t.includes("FLOA") || t.includes("DOUB") ? "real" : t.includes("BLOB") ? "bytes" : "text";
|
|
2206
|
-
},
|
|
2210
|
+
}, _r = (e) => e === 1 || e === !0, vr = (e) => T.gen(function* () {
|
|
2207
2211
|
let t = yield* e`
|
|
2208
2212
|
SELECT name, sql FROM sqlite_master
|
|
2209
2213
|
WHERE type = 'table' AND name NOT LIKE 'sqlite_%'
|
|
@@ -2217,14 +2221,14 @@ BEGIN
|
|
|
2217
2221
|
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();
|
|
2218
2222
|
for (let t of c) {
|
|
2219
2223
|
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);
|
|
2220
|
-
if (f.set(t.name, r), t.partial !== void 0 &&
|
|
2221
|
-
let n =
|
|
2224
|
+
if (f.set(t.name, r), t.partial !== void 0 && _r(t.partial)) {
|
|
2225
|
+
let n = cn((yield* e`SELECT sql FROM sqlite_master WHERE type = 'index' AND name = ${t.name}`)[0]?.sql ?? "");
|
|
2222
2226
|
n !== void 0 && p.set(t.name, n);
|
|
2223
2227
|
}
|
|
2224
|
-
!p.has(t.name) &&
|
|
2228
|
+
!p.has(t.name) && _r(t.unique) && r.length === 1 && m.add(r[0]);
|
|
2225
2229
|
}
|
|
2226
2230
|
let h = o.map((e) => {
|
|
2227
|
-
let n = u.length === 1 && u[0] === e.name, r = l.get(e.name), i = r ? "reference" : n && e.name === "id" ? "id" :
|
|
2231
|
+
let n = u.length === 1 && u[0] === e.name, r = l.get(e.name), i = r ? "reference" : n && e.name === "id" ? "id" : gr(e.type), a = r ? {
|
|
2228
2232
|
table: r.table,
|
|
2229
2233
|
column: r.to,
|
|
2230
2234
|
onDelete: V(r.on_delete),
|
|
@@ -2238,19 +2242,19 @@ BEGIN
|
|
|
2238
2242
|
hasDefault: e.dflt_value !== null,
|
|
2239
2243
|
...e.dflt_value === null ? {} : { defaultValue: e.dflt_value },
|
|
2240
2244
|
...a ? { references: a } : {},
|
|
2241
|
-
...r ? { referenceStorage: ["integer", "bigint"].includes(
|
|
2245
|
+
...r ? { referenceStorage: ["integer", "bigint"].includes(gr(e.type)) ? "numeric" : "text" } : {},
|
|
2242
2246
|
...o ? { oneOf: o } : {},
|
|
2243
|
-
...
|
|
2247
|
+
...or(e.hidden === 2 || e.hidden === 3 ? "generated" : null, e.hidden === 3) ?? {}
|
|
2244
2248
|
};
|
|
2245
2249
|
}), g = new Set(s.map((e) => e.from)), _ = [];
|
|
2246
2250
|
for (let e of c) {
|
|
2247
2251
|
if (e.origin === "pk") continue;
|
|
2248
2252
|
let t = f.get(e.name) ?? [], n = p.get(e.name);
|
|
2249
|
-
n === void 0 && t.length === 1 &&
|
|
2253
|
+
n === void 0 && t.length === 1 && _r(e.unique) || (n !== void 0 || t.length !== 1 || _r(e.unique) || !g.has(t[0]) || e.name === `${i}_${t[0]}_idx`) && _.push({
|
|
2250
2254
|
name: e.name,
|
|
2251
2255
|
table: i,
|
|
2252
2256
|
columns: t,
|
|
2253
|
-
unique:
|
|
2257
|
+
unique: _r(e.unique),
|
|
2254
2258
|
...n === void 0 ? {} : { where: n }
|
|
2255
2259
|
});
|
|
2256
2260
|
}
|
|
@@ -2266,7 +2270,7 @@ BEGIN
|
|
|
2266
2270
|
});
|
|
2267
2271
|
}
|
|
2268
2272
|
return { tables: r };
|
|
2269
|
-
}),
|
|
2273
|
+
}), yr = (e) => {
|
|
2270
2274
|
switch (e.toLowerCase()) {
|
|
2271
2275
|
case "int":
|
|
2272
2276
|
case "smallint":
|
|
@@ -2288,7 +2292,7 @@ BEGIN
|
|
|
2288
2292
|
case "image": return "bytes";
|
|
2289
2293
|
default: return "text";
|
|
2290
2294
|
}
|
|
2291
|
-
}, H = (e) => e === !0 || e === 1,
|
|
2295
|
+
}, H = (e) => e === !0 || e === 1, br = (e) => T.gen(function* () {
|
|
2292
2296
|
let t = yield* e`
|
|
2293
2297
|
SELECT TABLE_NAME AS table_name FROM INFORMATION_SCHEMA.TABLES
|
|
2294
2298
|
WHERE TABLE_TYPE = 'BASE TABLE' ORDER BY TABLE_NAME`, n = yield* e`
|
|
@@ -2326,7 +2330,7 @@ BEGIN
|
|
|
2326
2330
|
JOIN sys.tables t ON t.object_id = cc.parent_object_id
|
|
2327
2331
|
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();
|
|
2328
2332
|
for (let e of s) {
|
|
2329
|
-
let t =
|
|
2333
|
+
let t = ir(e.def);
|
|
2330
2334
|
t?.column === e.column_name && c.set(`${e.table_name}.${e.column_name}`, t.values);
|
|
2331
2335
|
}
|
|
2332
2336
|
let l = /* @__PURE__ */ new Map();
|
|
@@ -2355,21 +2359,21 @@ BEGIN
|
|
|
2355
2359
|
else t[0].predicate == null && H(t[0].is_unique) && t.length === 1 && m.add(t[0].column_name);
|
|
2356
2360
|
}
|
|
2357
2361
|
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" :
|
|
2362
|
+
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" : yr(t.data_type), l = a ? {
|
|
2359
2363
|
table: a.target_table,
|
|
2360
2364
|
column: a.target_column,
|
|
2361
|
-
onDelete:
|
|
2362
|
-
onUpdate:
|
|
2363
|
-
} : void 0, u = t.column_default === null ? null :
|
|
2365
|
+
onDelete: xr(a.delete_rule),
|
|
2366
|
+
onUpdate: xr(a.update_rule)
|
|
2367
|
+
} : void 0, u = t.column_default === null ? null : Sr(t.column_default), d = c.get(`${e}.${t.column_name}`), f = s.flatMap((n) => {
|
|
2364
2368
|
if (n.table_name !== e || n.column_name !== null && n.column_name !== t.column_name) return [];
|
|
2365
|
-
let r =
|
|
2369
|
+
let r = at(t.column_name, n.def);
|
|
2366
2370
|
return r ? [{
|
|
2367
2371
|
name: n.constraint_name,
|
|
2368
2372
|
validation: r,
|
|
2369
2373
|
enabled: !H(n.is_disabled),
|
|
2370
2374
|
trusted: !H(n.is_not_trusted)
|
|
2371
2375
|
}] : [];
|
|
2372
|
-
}).sort((e, t) => e.name.localeCompare(t.name)), h =
|
|
2376
|
+
}).sort((e, t) => e.name.localeCompare(t.name)), h = ot(f);
|
|
2373
2377
|
return {
|
|
2374
2378
|
name: t.column_name,
|
|
2375
2379
|
type: o,
|
|
@@ -2379,11 +2383,11 @@ BEGIN
|
|
|
2379
2383
|
hasDefault: u !== null,
|
|
2380
2384
|
...u === null ? {} : { defaultValue: u },
|
|
2381
2385
|
...l ? { references: l } : {},
|
|
2382
|
-
...a ? { referenceStorage: ["integer", "bigint"].includes(
|
|
2386
|
+
...a ? { referenceStorage: ["integer", "bigint"].includes(yr(t.data_type)) ? "numeric" : "text" } : {},
|
|
2383
2387
|
...d ? { oneOf: d } : {},
|
|
2384
2388
|
...f.length > 0 ? { jsonChecks: f } : {},
|
|
2385
2389
|
...h ? { jsonValidation: h } : {},
|
|
2386
|
-
...
|
|
2390
|
+
...or(i.get(`${e}.${t.column_name}`)?.definition ?? null, H(i.get(`${e}.${t.column_name}`)?.is_persisted ?? !1)) ?? {}
|
|
2387
2391
|
};
|
|
2388
2392
|
}), g = [];
|
|
2389
2393
|
if (o) for (let [t, n] of o) {
|
|
@@ -2410,18 +2414,18 @@ BEGIN
|
|
|
2410
2414
|
});
|
|
2411
2415
|
}
|
|
2412
2416
|
return { tables: f };
|
|
2413
|
-
}),
|
|
2417
|
+
}), xr = (e) => {
|
|
2414
2418
|
switch (e.toUpperCase().replace(/_/g, " ")) {
|
|
2415
2419
|
case "CASCADE": return "cascade";
|
|
2416
2420
|
case "SET NULL": return "setNull";
|
|
2417
2421
|
case "SET DEFAULT": return "noAction";
|
|
2418
2422
|
default: return "noAction";
|
|
2419
2423
|
}
|
|
2420
|
-
},
|
|
2424
|
+
}, Sr = (e) => {
|
|
2421
2425
|
let t = e.trim();
|
|
2422
2426
|
for (; t.startsWith("(") && t.endsWith(")");) t = t.slice(1, -1).trim();
|
|
2423
2427
|
return t.startsWith("N'") && t.endsWith("'") ? t = t.slice(2, -1) : t.startsWith("'") && t.endsWith("'") && (t = t.slice(1, -1)), t;
|
|
2424
|
-
},
|
|
2428
|
+
}, Cr = /* @__PURE__ */ new Set([
|
|
2425
2429
|
"character varying",
|
|
2426
2430
|
"varchar",
|
|
2427
2431
|
"nvarchar",
|
|
@@ -2429,59 +2433,59 @@ BEGIN
|
|
|
2429
2433
|
"character",
|
|
2430
2434
|
"nchar"
|
|
2431
2435
|
]), U = (e, t) => {
|
|
2432
|
-
if (!
|
|
2436
|
+
if (!Cr.has(e.toLowerCase())) return;
|
|
2433
2437
|
let n = Number(t);
|
|
2434
2438
|
if (!(!Number.isFinite(n) || n <= 0)) return n;
|
|
2435
|
-
},
|
|
2436
|
-
mysql: () =>
|
|
2437
|
-
mssql: () =>
|
|
2438
|
-
sqlite: () =>
|
|
2439
|
-
orElse: () =>
|
|
2439
|
+
}, wr = /* @__PURE__ */ new Set([k]), Tr = (e) => e.onDialectOrElse({
|
|
2440
|
+
mysql: () => hr(e),
|
|
2441
|
+
mssql: () => br(e),
|
|
2442
|
+
sqlite: () => vr(e),
|
|
2443
|
+
orElse: () => fr(e)
|
|
2440
2444
|
}).pipe(T.map((e) => ({
|
|
2441
2445
|
...e,
|
|
2442
|
-
tables: e.tables.filter((e) => !
|
|
2443
|
-
}))),
|
|
2444
|
-
let t =
|
|
2445
|
-
return t === void 0 ?
|
|
2446
|
-
}),
|
|
2446
|
+
tables: e.tables.filter((e) => !wr.has(e.name))
|
|
2447
|
+
}))), Er = (e) => /mariadb/i.test(e) ? "mariadb" : "mysql", Dr = /* @__PURE__ */ new WeakMap(), Or = (e) => T.suspend(() => {
|
|
2448
|
+
let t = Dr.get(e);
|
|
2449
|
+
return t === void 0 ? kr(e).pipe(T.tap((t) => T.sync(() => Dr.set(e, t)))) : T.succeed(t);
|
|
2450
|
+
}), kr = (e) => e.unsafe("SELECT VERSION() AS v").pipe(T.map((e) => {
|
|
2447
2451
|
let t = e[0]?.v;
|
|
2448
|
-
return typeof t == "string" ?
|
|
2449
|
-
}), T.catchAll(() => T.succeed("mysql"))),
|
|
2452
|
+
return typeof t == "string" ? Er(t) : "mysql";
|
|
2453
|
+
}), T.catchAll(() => T.succeed("mysql"))), Ar = (e) => {
|
|
2450
2454
|
let t = e;
|
|
2451
2455
|
for (let e = 0; e < 6 && typeof t == "object" && t; e++) {
|
|
2452
2456
|
let e = t;
|
|
2453
2457
|
if (typeof e.errno == "number") return e.errno;
|
|
2454
2458
|
t = e.cause;
|
|
2455
2459
|
}
|
|
2456
|
-
},
|
|
2460
|
+
}, jr = (e) => {
|
|
2457
2461
|
let t = [], n = e;
|
|
2458
2462
|
for (let e = 0; e < 6 && typeof n == "object" && n; e++) {
|
|
2459
2463
|
let e = n;
|
|
2460
2464
|
typeof e.message == "string" && t.push(e.message), n = e.cause;
|
|
2461
2465
|
}
|
|
2462
2466
|
return t.join(" | ");
|
|
2463
|
-
},
|
|
2467
|
+
}, Mr = (e, t) => {
|
|
2464
2468
|
if (t.length === 0) return !1;
|
|
2465
|
-
let n =
|
|
2469
|
+
let n = Ar(e), r = jr(e);
|
|
2466
2470
|
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)));
|
|
2467
|
-
},
|
|
2471
|
+
}, Nr = {
|
|
2468
2472
|
why: "mysql has no CREATE INDEX IF NOT EXISTS; 1061 is exactly that condition",
|
|
2469
2473
|
errno: [1061]
|
|
2470
|
-
},
|
|
2474
|
+
}, Pr = {
|
|
2471
2475
|
why: "mysql has no DROP COLUMN IF EXISTS; 1091 is exactly that condition",
|
|
2472
2476
|
errno: [1091]
|
|
2473
|
-
},
|
|
2477
|
+
}, Fr = {
|
|
2474
2478
|
why: "sqlite has no DROP COLUMN IF EXISTS, and reports the absent column only in the message",
|
|
2475
2479
|
messageIncludes: ["no such column"]
|
|
2476
|
-
},
|
|
2480
|
+
}, Ir = {
|
|
2477
2481
|
why: "mysql/mariadb DROP CONSTRAINT has no portable IF EXISTS; 1091 / 3940 are exactly \"already gone\"",
|
|
2478
2482
|
errno: [1091, 3940]
|
|
2479
|
-
},
|
|
2483
|
+
}, Lr = (e, t) => T.suspend(() => {
|
|
2480
2484
|
let n;
|
|
2481
2485
|
return e.withTransaction(t.pipe(T.tapErrorCause((e) => T.sync(() => {
|
|
2482
2486
|
n = e;
|
|
2483
2487
|
})))).pipe(T.catchAllCause((e) => T.failCause(n !== void 0 && !ee.equals(n, e) ? w.sequential(n, e) : e)));
|
|
2484
|
-
}),
|
|
2488
|
+
}), Rr = (e, t, n) => {
|
|
2485
2489
|
let r = e.match(/'(?:''|[^'])*'|\[(?:\]\]|[^\]])*\]|\s+|[^'\[\s]+/g) ?? [];
|
|
2486
2490
|
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
2491
|
let i = r.map((e, t) => ({
|
|
@@ -2500,21 +2504,21 @@ BEGIN
|
|
|
2500
2504
|
}, W = (e, t) => e.onDialectOrElse({
|
|
2501
2505
|
mysql: () => T.succeed(t.replace("T", " ").replace("Z", "")),
|
|
2502
2506
|
orElse: () => T.succeed(t)
|
|
2503
|
-
}),
|
|
2504
|
-
if ((e.type !== "text" || e.maxLength === void 0) && !
|
|
2507
|
+
}), zr = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, Br = (e) => e.type === "text" && (e.hasDefault && e.defaultValue !== void 0 || e.oneOf !== void 0 && e.oneOf.length > 0), Vr = (e, t) => {
|
|
2508
|
+
if ((e.type !== "text" || e.maxLength === void 0) && !Br(e) && !e.spatial && e.type !== "vector" && e.type !== "array" && e.type !== "enum") return;
|
|
2505
2509
|
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;
|
|
2506
2510
|
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.`);
|
|
2507
|
-
return
|
|
2508
|
-
},
|
|
2509
|
-
let t =
|
|
2510
|
-
return t === void 0 ?
|
|
2511
|
-
},
|
|
2511
|
+
return M(e, t);
|
|
2512
|
+
}, Hr = (e) => {
|
|
2513
|
+
let t = Vr(e, "postgres");
|
|
2514
|
+
return t === void 0 ? Ur(e) : t;
|
|
2515
|
+
}, Ur = (e) => {
|
|
2512
2516
|
switch (e.type) {
|
|
2513
2517
|
case "id": return "text";
|
|
2514
2518
|
case "text": return "text";
|
|
2515
2519
|
case "integer": return "integer";
|
|
2516
2520
|
case "real": return "double precision";
|
|
2517
|
-
case "decimal": return
|
|
2521
|
+
case "decimal": return zr(e, "NUMERIC");
|
|
2518
2522
|
case "bigint": return "bigint";
|
|
2519
2523
|
case "boolean": return "boolean";
|
|
2520
2524
|
case "timestamp": return "timestamptz";
|
|
@@ -2528,15 +2532,15 @@ BEGIN
|
|
|
2528
2532
|
case "interval": return "interval";
|
|
2529
2533
|
case "raw": return e.rawDdl ?? "text";
|
|
2530
2534
|
}
|
|
2531
|
-
},
|
|
2532
|
-
let t =
|
|
2535
|
+
}, Wr = (e) => {
|
|
2536
|
+
let t = Vr(e, "mariadb");
|
|
2533
2537
|
if (t !== void 0) return t;
|
|
2534
2538
|
switch (e.type) {
|
|
2535
2539
|
case "id": return "VARCHAR(64)";
|
|
2536
2540
|
case "text": return "LONGTEXT";
|
|
2537
2541
|
case "integer": return "INT";
|
|
2538
2542
|
case "real": return "DOUBLE";
|
|
2539
|
-
case "decimal": return
|
|
2543
|
+
case "decimal": return zr(e, "DECIMAL");
|
|
2540
2544
|
case "bigint": return "BIGINT";
|
|
2541
2545
|
case "boolean": return "TINYINT(1)";
|
|
2542
2546
|
case "timestamp": return "DATETIME(6)";
|
|
@@ -2550,38 +2554,38 @@ BEGIN
|
|
|
2550
2554
|
case "interval": return "BIGINT";
|
|
2551
2555
|
case "raw": return e.rawDdl ?? "LONGTEXT";
|
|
2552
2556
|
}
|
|
2553
|
-
}, G = (e) => `"${e}"`, K = (e) => `\`${e.replace(/`/g, "``")}\``,
|
|
2557
|
+
}, G = (e) => `"${e}"`, K = (e) => `\`${e.replace(/`/g, "``")}\``, Gr = (e) => e === "mariadb" ? "IF NOT EXISTS " : "", Kr = (e, t, n = !0) => `ALTER TABLE ${t(e.table)} DROP COLUMN ${n ? "IF EXISTS " : ""}${t(e.column)};`, qr = (e, t = "mariadb") => `ALTER TABLE ${K(e.table)} DROP COLUMN ${t === "mariadb" ? "IF EXISTS " : ""}${K(e.column)}, ALGORITHM=COPY;`, Jr = (e, t) => `ALTER TABLE ${t(e.table)} RENAME COLUMN ${t(e.from)} TO ${t(e.to)};`, Yr = (e, t, n) => `ALTER TABLE ${n(e.table)} RENAME COLUMN ${n(e.column)} TO ${n(`${e.column}${Ti(t)}`)};`, Xr = (e, t, n) => e.hasDefault && e.defaultValue !== void 0 ? `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} SET ${Qr(e, n)};` : `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} DROP DEFAULT;`, Zr = (e, t) => {
|
|
2554
2558
|
let { defaultFactory: n, ...r } = e;
|
|
2555
|
-
return
|
|
2559
|
+
return M(e, t) !== M({
|
|
2556
2560
|
...r,
|
|
2557
2561
|
hasDefault: !1
|
|
2558
2562
|
}, t);
|
|
2559
|
-
},
|
|
2563
|
+
}, Qr = (e, t) => {
|
|
2560
2564
|
let n = t(e.defaultValue);
|
|
2561
2565
|
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.`);
|
|
2562
2566
|
return n;
|
|
2563
|
-
}, q = (e, t, n) => e.find((e) => e.tableName === t)?.fields[n],
|
|
2567
|
+
}, q = (e, t, n) => e.find((e) => e.tableName === t)?.fields[n], $r = (e, t, n) => {
|
|
2564
2568
|
let r = q(e, t, n);
|
|
2565
|
-
return r ?
|
|
2566
|
-
},
|
|
2567
|
-
let r = n ?? e.nullable, i =
|
|
2569
|
+
return r ? vn(n, r) : void 0;
|
|
2570
|
+
}, ei = (e, t, n) => {
|
|
2571
|
+
let r = n ?? e.nullable, i = pt(e, "mariadb");
|
|
2568
2572
|
return [
|
|
2569
2573
|
K(t),
|
|
2570
|
-
|
|
2574
|
+
M(e, "mariadb"),
|
|
2571
2575
|
r ? null : "NOT NULL",
|
|
2572
2576
|
i
|
|
2573
2577
|
].filter(Boolean).join(" ");
|
|
2574
|
-
},
|
|
2578
|
+
}, ti = (e, t) => e == null ? null : Array.isArray(e) ? ni(e, t, "mariadb") : e === "now" ? "DEFAULT CURRENT_TIMESTAMP(6)" : typeof e == "boolean" ? `DEFAULT ${+!!e}` : typeof e == "number" ? `DEFAULT ${e}` : typeof e == "string" ? /[()]|^'/.test(e) ? `DEFAULT ${e}` : `DEFAULT '${e.replace(/'/g, "''")}'` : typeof e == "object" ? N(e, "mariadb") : null, ni = (e, t, n) => mt(e, t ?? { type: "json" }, n), ri = (e, t) => e == null ? null : Array.isArray(e) ? ni(e, t, "postgres") : e === "now" ? "DEFAULT now()" : typeof e == "boolean" || typeof e == "number" ? `DEFAULT ${e}` : typeof e == "string" ? /[()]|::|^'/.test(e) ? `DEFAULT ${e}` : `DEFAULT '${e.replace(/'/g, "''")}'` : typeof e == "object" ? N(e, "postgres") : null, ii = (e, t) => {
|
|
2575
2579
|
if (!e.generatedAs) return null;
|
|
2576
2580
|
let { expr: n, stored: r } = e.generatedAs;
|
|
2577
2581
|
return t === "postgres" ? `GENERATED ALWAYS AS (${n}) STORED` : t === "mssql" ? `AS (${n})${r ? " PERSISTED" : ""}` : `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
|
|
2578
|
-
},
|
|
2579
|
-
if (e.type === "id" && e.idScheme?.kind === "numeric") return
|
|
2580
|
-
let n =
|
|
2581
|
-
if (n) return `${G(e.name)} ${
|
|
2582
|
-
let r = [G(e.name),
|
|
2582
|
+
}, ai = (e, t = !1) => {
|
|
2583
|
+
if (e.type === "id" && e.idScheme?.kind === "numeric") return P(e.name, "postgres");
|
|
2584
|
+
let n = ii(e, "postgres");
|
|
2585
|
+
if (n) return `${G(e.name)} ${Hr(e)} ${n}`;
|
|
2586
|
+
let r = [G(e.name), Hr(e)];
|
|
2583
2587
|
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 =
|
|
2588
|
+
let t = ri(e.defaultValue, e);
|
|
2585
2589
|
t && r.push(t);
|
|
2586
2590
|
}
|
|
2587
2591
|
return e.references && (r.push(`REFERENCES ${G(e.references.table)} (${G(e.references.column)})`), e.references.onDelete && r.push(`ON DELETE ${{
|
|
@@ -2590,28 +2594,28 @@ BEGIN
|
|
|
2590
2594
|
setNull: "SET NULL",
|
|
2591
2595
|
noAction: "NO ACTION"
|
|
2592
2596
|
}[e.references.onDelete]}`)), r.join(" ");
|
|
2593
|
-
},
|
|
2594
|
-
let t = e.columns.map((t) => ` ${
|
|
2595
|
-
for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(
|
|
2597
|
+
}, oi = (e) => (e.primaryKey?.length ?? 0) > 0, si = (e, t) => e.primaryKey && e.primaryKey.length > 0 ? `,\n PRIMARY KEY (${e.primaryKey.map(t).join(", ")})` : "", ci = (e) => {
|
|
2598
|
+
let t = e.columns.map((t) => ` ${ai(t, oi(e))}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${G(e.table)} (\n${t}${si(e, G)}\n)`];
|
|
2599
|
+
for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(Mi({
|
|
2596
2600
|
kind: "add-index",
|
|
2597
2601
|
table: e.table,
|
|
2598
2602
|
index: t
|
|
2599
2603
|
}, !1));
|
|
2600
2604
|
return n;
|
|
2601
|
-
},
|
|
2602
|
-
let t =
|
|
2605
|
+
}, li = 191, ui = (e) => {
|
|
2606
|
+
let t = Wr(e).toUpperCase();
|
|
2603
2607
|
return t.endsWith("TEXT") || t.endsWith("BLOB");
|
|
2604
|
-
},
|
|
2605
|
-
if (e.type === "id" && e.idScheme?.kind === "numeric") return
|
|
2606
|
-
let n =
|
|
2607
|
-
if (n) return `${K(e.name)} ${
|
|
2608
|
-
let r = [K(e.name),
|
|
2609
|
-
if (e.type === "id" && !t && r.push("PRIMARY KEY"), e.nullable || r.push("NOT NULL"), e.unique && e.type !== "id" && !
|
|
2610
|
-
let t =
|
|
2608
|
+
}, di = (e, t = !1) => {
|
|
2609
|
+
if (e.type === "id" && e.idScheme?.kind === "numeric") return P(e.name, "mariadb");
|
|
2610
|
+
let n = ii(e, "mariadb");
|
|
2611
|
+
if (n) return `${K(e.name)} ${Wr(e)} ${n}`;
|
|
2612
|
+
let r = [K(e.name), Wr(e)];
|
|
2613
|
+
if (e.type === "id" && !t && r.push("PRIMARY KEY"), e.nullable || r.push("NOT NULL"), e.unique && e.type !== "id" && !ui(e) && r.push("UNIQUE"), e.hasDefault) {
|
|
2614
|
+
let t = ti(e.defaultValue, e);
|
|
2611
2615
|
t && r.push(t);
|
|
2612
2616
|
}
|
|
2613
2617
|
return r.join(" ");
|
|
2614
|
-
},
|
|
2618
|
+
}, fi = (e) => e.columns.flatMap((t) => {
|
|
2615
2619
|
if (!t.references) return [];
|
|
2616
2620
|
let n = t.references.onDelete ? ` ON DELETE ${{
|
|
2617
2621
|
cascade: "CASCADE",
|
|
@@ -2620,27 +2624,27 @@ BEGIN
|
|
|
2620
2624
|
noAction: "NO ACTION"
|
|
2621
2625
|
}[t.references.onDelete]}` : "";
|
|
2622
2626
|
return [` CONSTRAINT ${K(`${e.table}_${t.name}_fkey`)} FOREIGN KEY (${K(t.name)}) REFERENCES ${K(t.references.table)} (${K(t.references.column)})${n}`];
|
|
2623
|
-
}),
|
|
2624
|
-
for (let n of e.indexes)
|
|
2627
|
+
}), pi = (e, t = "mariadb") => {
|
|
2628
|
+
for (let n of e.indexes) Pi(n, t);
|
|
2625
2629
|
let n = new Map(e.columns.map((e) => [e.name, e])), r = (e) => {
|
|
2626
|
-
let t =
|
|
2630
|
+
let t = Oi(n.get(e));
|
|
2627
2631
|
return t === void 0 ? K(e) : `${K(e)}(${t})`;
|
|
2628
|
-
}, i = e.columns.map((t) => ` ${
|
|
2629
|
-
for (let n of e.columns) n.unique && n.type !== "id" &&
|
|
2630
|
-
for (let n of e.indexes) n.name !== `${e.table}_pkey` && s.push(`CREATE ${n.unique ? "UNIQUE " : ""}INDEX ${
|
|
2632
|
+
}, i = e.columns.map((t) => ` ${di(t, oi(e))}`).join(",\n"), a = fi(e), o = a.length > 0 ? `${i},\n${a.join(",\n")}` : i, s = [`CREATE TABLE IF NOT EXISTS ${K(e.table)} (\n${o}${si(e, r)}\n)`];
|
|
2633
|
+
for (let n of e.columns) n.unique && n.type !== "id" && ui(n) && s.push(`CREATE UNIQUE INDEX ${Gr(t)}${K(`${e.table}_${n.name}_key`)} ON ${K(e.table)} (${r(n.name)})`);
|
|
2634
|
+
for (let n of e.indexes) n.name !== `${e.table}_pkey` && s.push(`CREATE ${n.unique ? "UNIQUE " : ""}INDEX ${Gr(t)}${K(n.name)} ON ${K(e.table)} (${n.columns.map(r).join(", ")})`);
|
|
2631
2635
|
return s;
|
|
2632
|
-
},
|
|
2636
|
+
}, mi = {
|
|
2633
2637
|
cascade: "CASCADE",
|
|
2634
2638
|
restrict: "RESTRICT",
|
|
2635
2639
|
setNull: "SET NULL",
|
|
2636
2640
|
noAction: "NO ACTION"
|
|
2637
|
-
},
|
|
2641
|
+
}, hi = {
|
|
2638
2642
|
cascade: "CASCADE",
|
|
2639
2643
|
restrict: "NO ACTION",
|
|
2640
2644
|
setNull: "SET NULL",
|
|
2641
2645
|
noAction: "NO ACTION"
|
|
2642
|
-
},
|
|
2643
|
-
let t =
|
|
2646
|
+
}, gi = (e) => {
|
|
2647
|
+
let t = Vr(e, "sqlite");
|
|
2644
2648
|
if (t !== void 0) return t;
|
|
2645
2649
|
switch (e.type) {
|
|
2646
2650
|
case "integer":
|
|
@@ -2652,29 +2656,29 @@ BEGIN
|
|
|
2652
2656
|
case "bytes": return "BLOB";
|
|
2653
2657
|
default: return "TEXT";
|
|
2654
2658
|
}
|
|
2655
|
-
},
|
|
2656
|
-
if (e.type === "id" && e.idScheme?.kind === "numeric") return
|
|
2657
|
-
let n =
|
|
2658
|
-
if (n) return `${G(e.name)} ${
|
|
2659
|
-
let r = [G(e.name),
|
|
2659
|
+
}, _i = (e, t) => e == null ? null : e === "now" ? `DEFAULT ${t}` : typeof e == "boolean" ? `DEFAULT ${+!!e}` : typeof e == "number" ? `DEFAULT ${e}` : typeof e == "string" ? /[()]|^'/.test(e) ? `DEFAULT ${e}` : `DEFAULT '${e.replace(/'/g, "''")}'` : typeof e == "object" ? N(e, "sqlite") : null, vi = (e, t = !1) => {
|
|
2660
|
+
if (e.type === "id" && e.idScheme?.kind === "numeric") return P(e.name, "sqlite");
|
|
2661
|
+
let n = ii(e, "sqlite");
|
|
2662
|
+
if (n) return `${G(e.name)} ${gi(e)} ${n}`;
|
|
2663
|
+
let r = [G(e.name), gi(e)];
|
|
2660
2664
|
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 =
|
|
2665
|
+
let t = _i(e.defaultValue, "CURRENT_TIMESTAMP");
|
|
2662
2666
|
t && r.push(t);
|
|
2663
2667
|
}
|
|
2664
|
-
if (e.references && (r.push(`REFERENCES ${G(e.references.table)} (${G(e.references.column)})`), e.references.onDelete && r.push(`ON DELETE ${
|
|
2668
|
+
if (e.references && (r.push(`REFERENCES ${G(e.references.table)} (${G(e.references.column)})`), e.references.onDelete && r.push(`ON DELETE ${mi[e.references.onDelete]}`)), e.oneOf && e.oneOf.length > 0) {
|
|
2665
2669
|
let t = e.oneOf.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
|
|
2666
2670
|
r.push(`CHECK (${G(e.name)} IN (${t}))`);
|
|
2667
2671
|
}
|
|
2668
2672
|
return r.join(" ");
|
|
2669
|
-
},
|
|
2670
|
-
let t = e.columns.map((t) => ` ${
|
|
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(", ")})${
|
|
2673
|
+
}, yi = (e) => {
|
|
2674
|
+
let t = e.columns.map((t) => ` ${vi(t, oi(e))}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${G(e.table)} (\n${t}${si(e, G)}\n)`];
|
|
2675
|
+
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(", ")})${ji(t)}`);
|
|
2672
2676
|
return n;
|
|
2673
2677
|
}, J = (e, t) => {
|
|
2674
2678
|
let n = t.find((t) => t.tableName === e);
|
|
2675
2679
|
if (!n) return [];
|
|
2676
2680
|
let r = z([n]).tables[0], i = `${e}__voltro_rebuild`, a = r.columns.map((e) => G(e.name)).join(", "), o = [
|
|
2677
|
-
...
|
|
2681
|
+
...yi({
|
|
2678
2682
|
kind: "create-table",
|
|
2679
2683
|
table: i,
|
|
2680
2684
|
columns: r.columns,
|
|
@@ -2685,27 +2689,27 @@ BEGIN
|
|
|
2685
2689
|
`DROP TABLE ${G(e)}`,
|
|
2686
2690
|
`ALTER TABLE ${G(i)} RENAME TO ${G(e)}`
|
|
2687
2691
|
];
|
|
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(", ")})${
|
|
2692
|
+
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(", ")})${ji(t)}`);
|
|
2689
2693
|
return o;
|
|
2690
|
-
},
|
|
2694
|
+
}, bi = (e, t, n, r) => {
|
|
2691
2695
|
let i = r ?? e.nullable;
|
|
2692
|
-
return `ALTER TABLE ${Y(n)} ALTER COLUMN ${Y(t)} ${
|
|
2693
|
-
},
|
|
2696
|
+
return `ALTER TABLE ${Y(n)} ALTER COLUMN ${Y(t)} ${M(e, "mssql")} ${i ? "NULL" : "NOT NULL"};`;
|
|
2697
|
+
}, xi = (e, t) => {
|
|
2694
2698
|
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}` : "");
|
|
2695
2699
|
if (!e.hasDefault) return n;
|
|
2696
|
-
let r =
|
|
2700
|
+
let r = _i(e.defaultValue, "SYSUTCDATETIME()");
|
|
2697
2701
|
if (!r) return n;
|
|
2698
2702
|
let i = r.replace(/^DEFAULT\s+/i, "");
|
|
2699
2703
|
return `${n} ALTER TABLE ${Y(e.table)} ADD DEFAULT ${i} FOR ${Y(e.column)};`;
|
|
2700
|
-
}, Y = (e) => `[${e.replace(/]/g, "]]")}]`,
|
|
2701
|
-
let t =
|
|
2704
|
+
}, Y = (e) => `[${e.replace(/]/g, "]]")}]`, Si = (e) => {
|
|
2705
|
+
let t = Vr(e, "mssql");
|
|
2702
2706
|
if (t !== void 0) return t;
|
|
2703
2707
|
switch (e.type) {
|
|
2704
2708
|
case "id": return "NVARCHAR(64)";
|
|
2705
2709
|
case "reference": return e.referenceStorage === "numeric" ? "BIGINT" : "NVARCHAR(64)";
|
|
2706
2710
|
case "integer": return "INT";
|
|
2707
2711
|
case "real": return "FLOAT";
|
|
2708
|
-
case "decimal": return
|
|
2712
|
+
case "decimal": return zr(e, "DECIMAL");
|
|
2709
2713
|
case "bigint": return "BIGINT";
|
|
2710
2714
|
case "boolean": return "BIT";
|
|
2711
2715
|
case "timestamp": return "DATETIME2(6)";
|
|
@@ -2713,53 +2717,53 @@ BEGIN
|
|
|
2713
2717
|
case "bytes": return "VARBINARY(MAX)";
|
|
2714
2718
|
default: return "NVARCHAR(MAX)";
|
|
2715
2719
|
}
|
|
2716
|
-
},
|
|
2717
|
-
if (e.type === "id" && e.idScheme?.kind === "numeric") return
|
|
2718
|
-
let r = e.type === "text" && t?.has(e.name) ? "NVARCHAR(450)" :
|
|
2720
|
+
}, Ci = (e, t, n = !1) => {
|
|
2721
|
+
if (e.type === "id" && e.idScheme?.kind === "numeric") return P(e.name, "mssql");
|
|
2722
|
+
let r = e.type === "text" && t?.has(e.name) ? "NVARCHAR(450)" : Si(e), i = ii(e, "mssql");
|
|
2719
2723
|
if (i) return `${Y(e.name)} ${i}`;
|
|
2720
2724
|
let a = [Y(e.name), r];
|
|
2721
|
-
if (e.type === "json" && a.push(`CHECK ${
|
|
2722
|
-
let t =
|
|
2725
|
+
if (e.type === "json" && a.push(`CHECK ${rt(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) {
|
|
2726
|
+
let t = _i(e.defaultValue, "SYSUTCDATETIME()");
|
|
2723
2727
|
t && a.push(t);
|
|
2724
2728
|
}
|
|
2725
|
-
return e.references && (a.push(`REFERENCES ${Y(e.references.table)} (${Y(e.references.column)})`), e.references.onDelete && a.push(`ON DELETE ${
|
|
2726
|
-
},
|
|
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) => ` ${
|
|
2729
|
+
return e.references && (a.push(`REFERENCES ${Y(e.references.table)} (${Y(e.references.column)})`), e.references.onDelete && a.push(`ON DELETE ${hi[e.references.onDelete]}`)), a.join(" ");
|
|
2730
|
+
}, wi = (e) => {
|
|
2731
|
+
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) => ` ${Ci(t, n, oi(e))}`).join(",\n"), i = `CREATE TABLE ${Y(e.table)} (\n${r}${si(e, Y)}\n)`, a = [`IF OBJECT_ID(N'${t(e.table)}', N'U') IS NULL EXEC(N'${t(i)}')`];
|
|
2728
2732
|
for (let n of e.indexes) {
|
|
2729
2733
|
if (n.name === `${e.table}_pkey`) continue;
|
|
2730
|
-
let r = `CREATE ${n.unique ? "UNIQUE " : ""}INDEX ${Y(n.name)} ON ${Y(e.table)} (${n.columns.map(Y).join(", ")})${
|
|
2734
|
+
let r = `CREATE ${n.unique ? "UNIQUE " : ""}INDEX ${Y(n.name)} ON ${Y(e.table)} (${n.columns.map(Y).join(", ")})${ji(n)}`;
|
|
2731
2735
|
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)}')`);
|
|
2732
2736
|
}
|
|
2733
2737
|
return a;
|
|
2734
|
-
},
|
|
2735
|
-
let r = `${e.table}${
|
|
2738
|
+
}, Ti = (e) => `__dropped_${e.replace(/[-:T.Z]/g, "").slice(0, 14)}`, Ei = (e, t) => `DROP TABLE IF EXISTS ${t(e.table)};`, Di = (e, t, n) => {
|
|
2739
|
+
let r = `${e.table}${Ti(t)}`;
|
|
2736
2740
|
return `ALTER TABLE ${n(e.table)} RENAME TO ${n(r)};`;
|
|
2737
|
-
},
|
|
2738
|
-
if (e === void 0 || !
|
|
2741
|
+
}, Oi = (e) => {
|
|
2742
|
+
if (e === void 0 || !ui(e)) return;
|
|
2739
2743
|
let t = typeof e.maxLength == "number" && e.maxLength > 0 ? e.maxLength : void 0;
|
|
2740
|
-
return t === void 0 ?
|
|
2741
|
-
},
|
|
2742
|
-
let r =
|
|
2744
|
+
return t === void 0 ? li : Math.min(li, t);
|
|
2745
|
+
}, ki = (e, t, n) => {
|
|
2746
|
+
let r = Oi($r(e, t, n));
|
|
2743
2747
|
return r === void 0 ? K(n) : `${K(n)}(${r})`;
|
|
2744
|
-
},
|
|
2745
|
-
let n =
|
|
2748
|
+
}, Ai = (e) => e.startsWith("(") ? e : G(e), ji = (e) => e.where === void 0 ? "" : ` WHERE ${e.where}`, Mi = (e, t) => {
|
|
2749
|
+
let n = fe(e.index.kind, e.index.kindOptions), r = e.index.columns.map(Ai);
|
|
2746
2750
|
if (n.opclass !== void 0) {
|
|
2747
2751
|
if (r.length !== 1) throw Error("HNSW index requires exactly one column");
|
|
2748
2752
|
r[0] = `${r[0]} ${n.opclass}`;
|
|
2749
2753
|
}
|
|
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}${
|
|
2751
|
-
},
|
|
2754
|
+
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}${ji(e.index)};`;
|
|
2755
|
+
}, Ni = (e, t, n = "mariadb") => (Pi(e.index, n), `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX ${Gr(n)}${K(e.index.name)} ON ${K(e.table)} (${e.index.columns.map((n) => ki(t, e.table, n)).join(", ")});`), Pi = (e, t) => {
|
|
2752
2756
|
if (e.where !== void 0) throw Error(`Partial index '${e.name}' is not supported by ${t}; uniqueActive must be lowered before applying the plan.`);
|
|
2753
|
-
},
|
|
2757
|
+
}, Fi = (e) => `DROP INDEX IF EXISTS ${G(e.index)};`, Ii = (e) => `DROP INDEX ${K(e.index)} ON ${K(e.table)};`, Li = (e) => `DROP INDEX IF EXISTS ${Y(e.index)} ON ${Y(e.table)};`, Ri = (e, t) => `ALTER TABLE ${t(e.from)} RENAME TO ${t(e.to)};`, zi = (e) => {
|
|
2754
2758
|
let t = (e) => e.replace(/'/g, "''");
|
|
2755
2759
|
return `EXEC sp_rename N'${t(e.from)}', N'${t(e.to)}';`;
|
|
2756
|
-
},
|
|
2760
|
+
}, Bi = (e) => `ALTER INDEX ${G(e.from)} RENAME TO ${G(e.to)};`, Vi = (e) => `ALTER TABLE ${K(e.table)} RENAME INDEX ${K(e.from)} TO ${K(e.to)};`, Hi = (e) => {
|
|
2757
2761
|
let t = (e) => e.replace(/'/g, "''");
|
|
2758
2762
|
return `EXEC sp_rename N'${t(e.table)}.${t(e.from)}', N'${t(e.to)}', N'INDEX';`;
|
|
2759
|
-
},
|
|
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(", ")})${
|
|
2763
|
+
}, Ui = (e) => {
|
|
2764
|
+
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(", ")})${ji(e.index)}`;
|
|
2761
2765
|
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)}');`;
|
|
2762
|
-
},
|
|
2766
|
+
}, Wi = (e, t, n) => {
|
|
2763
2767
|
let r = n.find((t) => t.tableName === e);
|
|
2764
2768
|
if (!r) return [];
|
|
2765
2769
|
let i = [];
|
|
@@ -2768,13 +2772,13 @@ BEGIN
|
|
|
2768
2772
|
t && t.type === "text" && !t.generatedAs && i.push(`ALTER TABLE ${Y(e)} ALTER COLUMN ${Y(n)} NVARCHAR(450) ${t.nullable ? "NULL" : "NOT NULL"};`);
|
|
2769
2773
|
}
|
|
2770
2774
|
return i;
|
|
2771
|
-
},
|
|
2775
|
+
}, Gi = (e) => `ALTER TABLE ${G(e.table)} ADD CONSTRAINT ${G(`${e.table}_${e.column}_key`)} UNIQUE (${G(e.column)});`, Ki = (e, t) => `ALTER TABLE ${K(e.table)} ADD CONSTRAINT ${K(`${e.table}_${e.column}_key`)} UNIQUE (${ki(t, e.table, e.column)});`, qi = (e) => {
|
|
2772
2776
|
let t = e.fields.map((e) => G(e)).join(", ");
|
|
2773
2777
|
return `ALTER TABLE ${G(e.table)} ADD CONSTRAINT ${G(e.name)} UNIQUE (${t});`;
|
|
2774
|
-
},
|
|
2775
|
-
let n = e.fields.map((n) =>
|
|
2778
|
+
}, Ji = (e, t) => {
|
|
2779
|
+
let n = e.fields.map((n) => ki(t, e.table, n)).join(", ");
|
|
2776
2780
|
return `ALTER TABLE ${K(e.table)} ADD CONSTRAINT ${K(e.name)} UNIQUE (${n});`;
|
|
2777
|
-
},
|
|
2781
|
+
}, Yi = (e) => `ALTER TABLE ${G(e.table)} DROP CONSTRAINT IF EXISTS ${G(e.name)};`, Xi = (e) => `ALTER TABLE ${K(e.table)} DROP INDEX ${K(e.name)};`, Zi = (e) => `ALTER TABLE ${G(e.table)} DROP CONSTRAINT IF EXISTS ${G(`${e.table}_${e.column}_key`)};`, Qi = (e) => `ALTER TABLE ${K(e.table)} DROP INDEX ${K(`${e.table}_${e.column}_key`)};`, $i = (e, t) => {
|
|
2778
2782
|
let n = [], r = t(e.table), i = t(e.column), a = t(e.targetTable), o = t(e.targetColumn);
|
|
2779
2783
|
if (e.orphanPolicy) {
|
|
2780
2784
|
let t = `${i} IS NOT NULL AND ${i} NOT IN (SELECT ${o} FROM ${a})`;
|
|
@@ -2792,10 +2796,10 @@ BEGIN
|
|
|
2792
2796
|
setNull: "SET NULL",
|
|
2793
2797
|
noAction: "NO ACTION"
|
|
2794
2798
|
}[e.onDelete]}`), n.push(s.join(" ") + ";"), n;
|
|
2795
|
-
},
|
|
2799
|
+
}, ea = (e) => `ALTER TABLE ${G(e.table)} DROP CONSTRAINT IF EXISTS ${G(`${e.table}_${e.column}_fkey`)};`, ta = (e) => `ALTER TABLE ${K(e.table)} DROP FOREIGN KEY ${K(`${e.table}_${e.column}_fkey`)};`, na = (e, t) => {
|
|
2796
2800
|
let n = e.values.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
|
|
2797
2801
|
return `ALTER TABLE ${t(e.table)} ADD CONSTRAINT ${t(`${e.table}_${e.column}_check`)} CHECK (${t(e.column)} IN (${n}));`;
|
|
2798
|
-
},
|
|
2802
|
+
}, ra = (e) => `ALTER TABLE ${G(e.table)} DROP CONSTRAINT IF EXISTS ${G(`${e.table}_${e.column}_check`)};`, ia = (e, t) => T.gen(function* () {
|
|
2799
2803
|
let n = yield* e`
|
|
2800
2804
|
SELECT cc.constraint_name AS n, cc.check_clause AS c
|
|
2801
2805
|
FROM information_schema.check_constraints cc
|
|
@@ -2808,18 +2812,18 @@ BEGIN
|
|
|
2808
2812
|
WHERE tc.table_schema = DATABASE() AND tc.table_name = ${t.table}`), T.orElseSucceed(() => []));
|
|
2809
2813
|
for (let e of n) {
|
|
2810
2814
|
let n = String(e.n ?? "");
|
|
2811
|
-
if (n !== "" &&
|
|
2815
|
+
if (n !== "" && ir(String(e.c ?? ""))?.column === t.column) return n;
|
|
2812
2816
|
}
|
|
2813
|
-
}),
|
|
2814
|
-
let r = yield*
|
|
2815
|
-
r !== void 0 && (yield* X(e, `ALTER TABLE ${K(t.table)} DROP CONSTRAINT ${K(r)};`, t.kind, [
|
|
2816
|
-
let i = yield*
|
|
2817
|
+
}), aa = (e, t, n) => T.gen(function* () {
|
|
2818
|
+
let r = yield* ia(e, t);
|
|
2819
|
+
r !== void 0 && (yield* X(e, `ALTER TABLE ${K(t.table)} DROP CONSTRAINT ${K(r)};`, t.kind, [Ir]));
|
|
2820
|
+
let i = yield* ia(e, t);
|
|
2817
2821
|
if (i === void 0) return;
|
|
2818
2822
|
let a = q(n, t.table, t.column);
|
|
2819
2823
|
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 ${
|
|
2821
|
-
}),
|
|
2822
|
-
let i = e.column, a = r === "mariadb", o = a ? K : r === "mssql" ? Y : G, s = a ?
|
|
2824
|
+
yield* X(e, `ALTER TABLE ${K(t.table)} MODIFY COLUMN ${ei(a, t.column)};`, t.kind);
|
|
2825
|
+
}), oa = (e, t, n, r) => {
|
|
2826
|
+
let i = e.column, a = r === "mariadb", o = a ? K : r === "mssql" ? Y : G, s = a ? Wr(i) : r === "mssql" ? Si(i) : r === "sqlite" ? gi(i) : Hr(i), c = r === "mssql" ? "ADD" : "ADD COLUMN", l = r === "mssql" ? i.type === "json" ? ` CHECK ${rt(o(i.name))}` : i.type === "array" ? ` CHECK (${o(i.name)} IS NULL OR ISJSON(${o(i.name)}) = 1)` : "" : "", u = (e) => a ? ti(e, i) : r === "mssql" ? _i(e, "SYSUTCDATETIME()") : r === "sqlite" ? _i(e, "CURRENT_TIMESTAMP") : ri(e, i), d = ii(i, r);
|
|
2823
2827
|
if (d) {
|
|
2824
2828
|
let t = r === "mssql" ? `${o(i.name)} ${d}` : `${o(i.name)} ${s} ${d}`;
|
|
2825
2829
|
return {
|
|
@@ -2847,7 +2851,7 @@ BEGIN
|
|
|
2847
2851
|
post: p ? [p] : []
|
|
2848
2852
|
};
|
|
2849
2853
|
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
|
-
},
|
|
2854
|
+
}, sa = (e) => {
|
|
2851
2855
|
let t = new Map(e.map((e) => [e.tableName, e]));
|
|
2852
2856
|
return (e, n) => {
|
|
2853
2857
|
let r = t.get(e);
|
|
@@ -2867,47 +2871,47 @@ BEGIN
|
|
|
2867
2871
|
...o
|
|
2868
2872
|
};
|
|
2869
2873
|
};
|
|
2870
|
-
}, X = (e, t, n, r = []) => e.unsafe(t).pipe(T.catchIf((e) =>
|
|
2871
|
-
process.stderr.write(
|
|
2874
|
+
}, X = (e, t, n, r = []) => e.unsafe(t).pipe(T.catchIf((e) => Mr(e, r), () => T.void), T.tapError((e) => T.sync(() => {
|
|
2875
|
+
process.stderr.write(pe(`applier: statement failed (op=${n})`, t, e, 400));
|
|
2872
2876
|
})), T.mapError((e) => {
|
|
2873
|
-
let r =
|
|
2877
|
+
let r = pe(`applier: statement failed (op=${n})`, t, e, 400).trim();
|
|
2874
2878
|
return Object.assign(e, { message: r });
|
|
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))),
|
|
2876
|
-
let n = z([
|
|
2879
|
+
}), 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))), ca = (e, t) => T.gen(function* () {
|
|
2880
|
+
let n = z([Ke], t).tables[0];
|
|
2877
2881
|
if (!n) return yield* T.die(/* @__PURE__ */ Error("migration applier: the resume-ledger table descriptor produced no snapshot. This is a framework bug."));
|
|
2878
2882
|
let r = {
|
|
2879
2883
|
kind: "create-table",
|
|
2880
|
-
table:
|
|
2884
|
+
table: k,
|
|
2881
2885
|
columns: n.columns,
|
|
2882
2886
|
indexes: []
|
|
2883
2887
|
}, i = yield* e.onDialectOrElse({
|
|
2884
|
-
mysql: () =>
|
|
2885
|
-
mssql: () => T.succeed(
|
|
2886
|
-
sqlite: () => T.succeed(
|
|
2887
|
-
orElse: () => T.succeed(
|
|
2888
|
+
mysql: () => Or(e).pipe(T.map((e) => pi(r, e))),
|
|
2889
|
+
mssql: () => T.succeed(wi(r)),
|
|
2890
|
+
sqlite: () => T.succeed(yi(r)),
|
|
2891
|
+
orElse: () => T.succeed(ci(r))
|
|
2888
2892
|
});
|
|
2889
2893
|
yield* T.forEach(i, (t) => X(e, t, "resume-ledger-bootstrap"), { discard: !0 });
|
|
2890
|
-
}),
|
|
2894
|
+
}), la = (e) => e`
|
|
2891
2895
|
SELECT ${e("runId")}, ${e("planFingerprint")}, ${e("opIndex")},
|
|
2892
2896
|
${e("status")}, ${e("payload")}
|
|
2893
|
-
FROM ${e(
|
|
2894
|
-
`,
|
|
2897
|
+
FROM ${e(k)}
|
|
2898
|
+
`, ua = (e, t, n, r) => T.gen(function* () {
|
|
2895
2899
|
let i = yield* W(e, (/* @__PURE__ */ new Date()).toISOString());
|
|
2896
2900
|
yield* T.forEach(r, ({ index: r, planned: a }) => e`
|
|
2897
|
-
INSERT INTO ${e(
|
|
2901
|
+
INSERT INTO ${e(k)}
|
|
2898
2902
|
(${e("id")}, ${e("runId")}, ${e("planFingerprint")}, ${e("opIndex")},
|
|
2899
2903
|
${e("opKind")}, ${e("opTarget")}, ${e("status")}, ${e("payload")},
|
|
2900
2904
|
${e("createdAt")})
|
|
2901
2905
|
VALUES
|
|
2902
2906
|
(${`mop_${t}_${r}`}, ${t}, ${n}, ${r},
|
|
2903
|
-
${a.op.kind}, ${
|
|
2907
|
+
${a.op.kind}, ${Je(a.op)}, ${"pending"},
|
|
2904
2908
|
${JSON.stringify(a)}, ${i})
|
|
2905
2909
|
`, { discard: !0 });
|
|
2906
|
-
}),
|
|
2910
|
+
}), da = (e, t, n, r, i) => T.gen(function* () {
|
|
2907
2911
|
let a = yield* W(e, (/* @__PURE__ */ new Date()).toISOString());
|
|
2908
2912
|
if (r === "applied") {
|
|
2909
2913
|
yield* e`
|
|
2910
|
-
UPDATE ${e(
|
|
2914
|
+
UPDATE ${e(k)}
|
|
2911
2915
|
SET ${e("status")} = ${r}, ${e("appliedAt")} = ${a},
|
|
2912
2916
|
${e("durationMs")} = ${i ?? null}
|
|
2913
2917
|
WHERE ${e("runId")} = ${t} AND ${e("opIndex")} = ${n}
|
|
@@ -2915,50 +2919,50 @@ BEGIN
|
|
|
2915
2919
|
return;
|
|
2916
2920
|
}
|
|
2917
2921
|
yield* e`
|
|
2918
|
-
UPDATE ${e(
|
|
2922
|
+
UPDATE ${e(k)}
|
|
2919
2923
|
SET ${e("status")} = ${r}, ${e("startedAt")} = ${a}
|
|
2920
2924
|
WHERE ${e("runId")} = ${t} AND ${e("opIndex")} = ${n}
|
|
2921
2925
|
`;
|
|
2922
|
-
}),
|
|
2926
|
+
}), fa = (e, t, n, r) => T.gen(function* () {
|
|
2923
2927
|
let i = yield* W(e, (/* @__PURE__ */ new Date()).toISOString());
|
|
2924
2928
|
r.length > 0 && (yield* e`
|
|
2925
|
-
UPDATE ${e(
|
|
2929
|
+
UPDATE ${e(k)}
|
|
2926
2930
|
SET ${e("status")} = ${"applied"}, ${e("appliedAt")} = ${i}
|
|
2927
2931
|
WHERE ${e("runId")} = ${t} AND ${e("opIndex")} IN ${e.in(r)}
|
|
2928
2932
|
`), n.length > 0 && (yield* e`
|
|
2929
|
-
UPDATE ${e(
|
|
2933
|
+
UPDATE ${e(k)}
|
|
2930
2934
|
SET ${e("status")} = ${"pending"}
|
|
2931
2935
|
WHERE ${e("runId")} = ${t} AND ${e("opIndex")} IN ${e.in(n)}
|
|
2932
2936
|
`);
|
|
2933
|
-
}),
|
|
2934
|
-
if (
|
|
2937
|
+
}), pa = (e, t) => t === void 0 ? e`DELETE FROM ${e(k)}`.pipe(T.asVoid) : e`DELETE FROM ${e(k)} WHERE ${e("runId")} = ${t}`.pipe(T.asVoid), ma = (e, t, n) => T.gen(function* () {
|
|
2938
|
+
if (nt(n.op, n.classification, t) !== "artefact-repair") return "clean";
|
|
2935
2939
|
let r = n.op, i = (e) => o(e, t);
|
|
2936
2940
|
if (t === "sqlite" || t === "turso") {
|
|
2937
2941
|
if (!("table" in r)) return "clean";
|
|
2938
|
-
let n = `${r.table}${
|
|
2942
|
+
let n = `${r.table}${Ze}`;
|
|
2939
2943
|
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";
|
|
2940
2944
|
}
|
|
2941
2945
|
if (r.kind !== "alter-column-type") return "clean";
|
|
2942
|
-
let a = `${r.column}${
|
|
2946
|
+
let a = `${r.column}${Qe}`, s = `${r.column}${$e}`, 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
2947
|
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
|
-
}),
|
|
2945
|
-
let i = process.hrtime.bigint(), a =
|
|
2948
|
+
}), ha = (e, t, n, r = "fresh") => T.gen(function* () {
|
|
2949
|
+
let i = process.hrtime.bigint(), a = sa(n.declared), s = t.op;
|
|
2946
2950
|
switch (s.kind) {
|
|
2947
2951
|
case "create-table": {
|
|
2948
2952
|
let t = yield* e.onDialectOrElse({
|
|
2949
|
-
mysql: () =>
|
|
2950
|
-
mssql: () => T.succeed(
|
|
2951
|
-
sqlite: () => T.succeed(
|
|
2952
|
-
orElse: () => T.succeed(
|
|
2953
|
+
mysql: () => Or(e).pipe(T.map((e) => pi(s, e))),
|
|
2954
|
+
mssql: () => T.succeed(wi(s)),
|
|
2955
|
+
sqlite: () => T.succeed(yi(s)),
|
|
2956
|
+
orElse: () => T.succeed(ci(s))
|
|
2953
2957
|
}), n = yield* e.onDialectOrElse({
|
|
2954
|
-
mysql: () => T.succeed([
|
|
2958
|
+
mysql: () => T.succeed([Nr]),
|
|
2955
2959
|
orElse: () => T.succeed([])
|
|
2956
2960
|
});
|
|
2957
2961
|
for (let r of t) yield* X(e, r, s.kind, n);
|
|
2958
2962
|
break;
|
|
2959
2963
|
}
|
|
2960
2964
|
case "drop-table": {
|
|
2961
|
-
let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString(), r = (e) => t ?
|
|
2965
|
+
let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString(), r = (e) => t ? Di(s, n, e) : Ei(s, e);
|
|
2962
2966
|
yield* e.onDialectOrElse({
|
|
2963
2967
|
mysql: () => X(e, r(K), s.kind),
|
|
2964
2968
|
orElse: () => X(e, r(G), s.kind)
|
|
@@ -2968,15 +2972,15 @@ BEGIN
|
|
|
2968
2972
|
case "drop-column": {
|
|
2969
2973
|
let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString();
|
|
2970
2974
|
yield* e.onDialectOrElse({
|
|
2971
|
-
mysql: () =>
|
|
2972
|
-
sqlite: () => X(e, t ?
|
|
2973
|
-
orElse: () => X(e, t ?
|
|
2975
|
+
mysql: () => Or(e).pipe(T.flatMap((r) => X(e, t ? Yr(s, n, K) : qr(s, r), s.kind, t ? [] : [Pr]))),
|
|
2976
|
+
sqlite: () => X(e, t ? Yr(s, n, G) : Kr(s, G, !1), s.kind, t ? [] : [Fr]),
|
|
2977
|
+
orElse: () => X(e, t ? Yr(s, n, G) : Kr(s, G), s.kind)
|
|
2974
2978
|
});
|
|
2975
2979
|
break;
|
|
2976
2980
|
}
|
|
2977
2981
|
case "rename-column":
|
|
2978
2982
|
yield* e.onDialectOrElse({
|
|
2979
|
-
mysql: () => X(e,
|
|
2983
|
+
mysql: () => X(e, Jr(s, K), s.kind),
|
|
2980
2984
|
mssql: () => T.gen(function* () {
|
|
2981
2985
|
let t = (yield* e`
|
|
2982
2986
|
SELECT ck.name, ck.definition, ck.is_disabled AS disabled,
|
|
@@ -2989,7 +2993,7 @@ BEGIN
|
|
|
2989
2993
|
) ORDER BY ck.name
|
|
2990
2994
|
`).map((e) => ({
|
|
2991
2995
|
...e,
|
|
2992
|
-
definition:
|
|
2996
|
+
definition: Rr(e.definition, s.from, s.to)
|
|
2993
2997
|
})), n = (e) => o(e, "mssql"), r = (e) => e.replace(/'/g, "''");
|
|
2994
2998
|
return yield* Z(e, [
|
|
2995
2999
|
...t.map((e) => `ALTER TABLE ${n(s.table)} DROP CONSTRAINT ${n(e.name)}`),
|
|
@@ -2997,83 +3001,83 @@ BEGIN
|
|
|
2997
3001
|
...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
3002
|
], s.kind);
|
|
2999
3003
|
}),
|
|
3000
|
-
orElse: () => X(e,
|
|
3004
|
+
orElse: () => X(e, Jr(s, G), s.kind)
|
|
3001
3005
|
});
|
|
3002
3006
|
break;
|
|
3003
3007
|
case "add-index":
|
|
3004
3008
|
yield* e.onDialectOrElse({
|
|
3005
|
-
sqlite: () => X(e,
|
|
3006
|
-
mysql: () =>
|
|
3007
|
-
mssql: () => Z(e, [...
|
|
3008
|
-
orElse: () => X(e,
|
|
3009
|
+
sqlite: () => X(e, Mi(s, !1), s.kind),
|
|
3010
|
+
mysql: () => Or(e).pipe(T.flatMap((t) => X(e, Ni(s, n.declared, t), s.kind, [Nr]))),
|
|
3011
|
+
mssql: () => Z(e, [...Wi(s.table, s.index.columns, n.declared), Ui(s)], s.kind),
|
|
3012
|
+
orElse: () => X(e, Mi(s, t.classification === "online-required"), s.kind)
|
|
3009
3013
|
});
|
|
3010
3014
|
break;
|
|
3011
3015
|
case "drop-index":
|
|
3012
3016
|
yield* e.onDialectOrElse({
|
|
3013
|
-
mysql: () => X(e,
|
|
3014
|
-
mssql: () => X(e,
|
|
3015
|
-
orElse: () => X(e,
|
|
3017
|
+
mysql: () => X(e, Ii(s), s.kind),
|
|
3018
|
+
mssql: () => X(e, Li(s), s.kind),
|
|
3019
|
+
orElse: () => X(e, Fi(s), s.kind)
|
|
3016
3020
|
});
|
|
3017
3021
|
break;
|
|
3018
3022
|
case "rename-table":
|
|
3019
3023
|
yield* e.onDialectOrElse({
|
|
3020
|
-
mysql: () => X(e,
|
|
3021
|
-
mssql: () => X(e,
|
|
3022
|
-
orElse: () => X(e,
|
|
3024
|
+
mysql: () => X(e, Ri(s, K), s.kind),
|
|
3025
|
+
mssql: () => X(e, zi(s), s.kind),
|
|
3026
|
+
orElse: () => X(e, Ri(s, G), s.kind)
|
|
3023
3027
|
});
|
|
3024
3028
|
break;
|
|
3025
3029
|
case "rename-index":
|
|
3026
3030
|
yield* e.onDialectOrElse({
|
|
3027
|
-
mysql: () => X(e,
|
|
3028
|
-
mssql: () => X(e,
|
|
3029
|
-
orElse: () => X(e,
|
|
3031
|
+
mysql: () => X(e, Vi(s), s.kind),
|
|
3032
|
+
mssql: () => X(e, Hi(s), s.kind),
|
|
3033
|
+
orElse: () => X(e, Bi(s), s.kind)
|
|
3030
3034
|
});
|
|
3031
3035
|
break;
|
|
3032
3036
|
case "add-unique":
|
|
3033
3037
|
yield* e.onDialectOrElse({
|
|
3034
|
-
mysql: () => X(e,
|
|
3038
|
+
mysql: () => X(e, Ki(s, n.declared), s.kind),
|
|
3035
3039
|
sqlite: () => Z(e, J(s.table, n.declared), s.kind),
|
|
3036
|
-
mssql: () => Z(e, [...
|
|
3037
|
-
orElse: () => X(e,
|
|
3040
|
+
mssql: () => Z(e, [...Wi(s.table, [s.column], n.declared), Gi(s)], s.kind),
|
|
3041
|
+
orElse: () => X(e, Gi(s), s.kind)
|
|
3038
3042
|
});
|
|
3039
3043
|
break;
|
|
3040
3044
|
case "drop-unique":
|
|
3041
3045
|
yield* e.onDialectOrElse({
|
|
3042
|
-
mysql: () => X(e,
|
|
3046
|
+
mysql: () => X(e, Qi(s), s.kind),
|
|
3043
3047
|
sqlite: () => Z(e, J(s.table, n.declared), s.kind),
|
|
3044
|
-
orElse: () => X(e,
|
|
3048
|
+
orElse: () => X(e, Zi(s), s.kind)
|
|
3045
3049
|
});
|
|
3046
3050
|
break;
|
|
3047
3051
|
case "add-unique-composite":
|
|
3048
3052
|
yield* e.onDialectOrElse({
|
|
3049
|
-
mysql: () => X(e,
|
|
3053
|
+
mysql: () => X(e, Ji(s, n.declared), s.kind),
|
|
3050
3054
|
sqlite: () => Z(e, J(s.table, n.declared), s.kind),
|
|
3051
|
-
mssql: () => Z(e, [...
|
|
3052
|
-
orElse: () => X(e,
|
|
3055
|
+
mssql: () => Z(e, [...Wi(s.table, s.fields, n.declared), qi(s)], s.kind),
|
|
3056
|
+
orElse: () => X(e, qi(s), s.kind)
|
|
3053
3057
|
});
|
|
3054
3058
|
break;
|
|
3055
3059
|
case "drop-unique-composite":
|
|
3056
3060
|
yield* e.onDialectOrElse({
|
|
3057
|
-
mysql: () => X(e,
|
|
3061
|
+
mysql: () => X(e, Xi(s), s.kind),
|
|
3058
3062
|
sqlite: () => Z(e, J(s.table, n.declared), s.kind),
|
|
3059
|
-
orElse: () => X(e,
|
|
3063
|
+
orElse: () => X(e, Yi(s), s.kind)
|
|
3060
3064
|
});
|
|
3061
3065
|
break;
|
|
3062
3066
|
case "add-foreign-key":
|
|
3063
3067
|
yield* e.onDialectOrElse({
|
|
3064
|
-
mysql: () => Z(e,
|
|
3068
|
+
mysql: () => Z(e, $i(s, K), s.kind),
|
|
3065
3069
|
sqlite: () => Z(e, J(s.table, n.declared), s.kind),
|
|
3066
|
-
orElse: () => Z(e,
|
|
3070
|
+
orElse: () => Z(e, $i(s, G), s.kind)
|
|
3067
3071
|
});
|
|
3068
3072
|
break;
|
|
3069
3073
|
case "add-column": {
|
|
3070
|
-
let n =
|
|
3074
|
+
let n = oa(s, t, a, yield* e.onDialectOrElse({
|
|
3071
3075
|
mysql: () => T.succeed("mariadb"),
|
|
3072
3076
|
mssql: () => T.succeed("mssql"),
|
|
3073
3077
|
sqlite: () => T.succeed("sqlite"),
|
|
3074
3078
|
orElse: () => T.succeed("postgres")
|
|
3075
3079
|
}));
|
|
3076
|
-
if (!(r === "resume" && (yield* $(e,
|
|
3080
|
+
if (!(r === "resume" && (yield* $(e, Ue(e), s.table, s.column.name)))) for (let t of n.pre) yield* X(e, t, s.kind);
|
|
3077
3081
|
if (n.backfillKind === "sql" && n.backfillSql) {
|
|
3078
3082
|
if (t.classification !== "online-required" && n.batchSize === void 0) yield* e`UPDATE ${e(s.table)} SET ${e(s.column.name)} = ${n.backfillSql}`;
|
|
3079
3083
|
else {
|
|
@@ -3114,43 +3118,43 @@ BEGIN
|
|
|
3114
3118
|
yield* e.onDialectOrElse({
|
|
3115
3119
|
mysql: () => {
|
|
3116
3120
|
let t = q(n.declared, s.table, s.column);
|
|
3117
|
-
return t ? X(e, `ALTER TABLE ${K(s.table)} MODIFY COLUMN ${
|
|
3121
|
+
return t ? X(e, `ALTER TABLE ${K(s.table)} MODIFY COLUMN ${ei(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.`));
|
|
3118
3122
|
},
|
|
3119
3123
|
mssql: () => {
|
|
3120
3124
|
let t = q(n.declared, s.table, s.column);
|
|
3121
|
-
return t ? X(e,
|
|
3125
|
+
return t ? X(e, bi(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}'.`));
|
|
3122
3126
|
},
|
|
3123
3127
|
sqlite: () => Z(e, J(s.table, n.declared), s.kind),
|
|
3124
3128
|
orElse: () => X(e, `ALTER TABLE ${G(s.table)} ALTER COLUMN ${G(s.column)} ${s.toNullable ? "DROP NOT NULL" : "SET NOT NULL"};`, s.kind)
|
|
3125
3129
|
});
|
|
3126
3130
|
break;
|
|
3127
3131
|
case "alter-column-default": {
|
|
3128
|
-
let t =
|
|
3132
|
+
let t = $r(n.declared, s.table, s.column), r = q(n.declared, s.table, s.column), i = (e) => s.hasDefault && r !== void 0 && Zr(r, e) ? r : void 0;
|
|
3129
3133
|
yield* e.onDialectOrElse({
|
|
3130
3134
|
mysql: () => {
|
|
3131
3135
|
let n = i("mariadb");
|
|
3132
|
-
return X(e, n ? `ALTER TABLE ${K(s.table)} MODIFY COLUMN ${
|
|
3136
|
+
return X(e, n ? `ALTER TABLE ${K(s.table)} MODIFY COLUMN ${ei(n, s.column)};` : Xr(s, K, (e) => ti(e, t)), s.kind);
|
|
3133
3137
|
},
|
|
3134
3138
|
mssql: () => {
|
|
3135
3139
|
let t = i("mssql");
|
|
3136
|
-
return X(e,
|
|
3140
|
+
return X(e, xi(s, t ? bi(t, s.column, s.table) : void 0), s.kind);
|
|
3137
3141
|
},
|
|
3138
3142
|
sqlite: () => Z(e, J(s.table, n.declared), s.kind),
|
|
3139
|
-
orElse: () => X(e,
|
|
3143
|
+
orElse: () => X(e, Xr(s, G, (e) => ri(e, t)), s.kind)
|
|
3140
3144
|
});
|
|
3141
3145
|
break;
|
|
3142
3146
|
}
|
|
3143
3147
|
case "alter-column-type": {
|
|
3144
|
-
let r =
|
|
3148
|
+
let r = Hr($r(n.declared, s.table, s.column) ?? { type: s.to }), i = s.using ? ` USING ${s.using}` : "";
|
|
3145
3149
|
if (t.classification !== "online-required") {
|
|
3146
3150
|
yield* e.onDialectOrElse({
|
|
3147
3151
|
mysql: () => {
|
|
3148
3152
|
let t = q(n.declared, s.table, s.column);
|
|
3149
|
-
return t ? X(e, `ALTER TABLE ${K(s.table)} MODIFY COLUMN ${
|
|
3153
|
+
return t ? X(e, `ALTER TABLE ${K(s.table)} MODIFY COLUMN ${ei(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.`));
|
|
3150
3154
|
},
|
|
3151
3155
|
mssql: () => {
|
|
3152
3156
|
let t = q(n.declared, s.table, s.column);
|
|
3153
|
-
return t ? X(e,
|
|
3157
|
+
return t ? X(e, bi(t, s.column, s.table), s.kind) : T.die(/* @__PURE__ */ Error(`alter-column-type on mssql needs the declared column '${s.table}.${s.column}'.`));
|
|
3154
3158
|
},
|
|
3155
3159
|
sqlite: () => Z(e, J(s.table, n.declared), s.kind),
|
|
3156
3160
|
orElse: () => X(e, `ALTER TABLE ${G(s.table)} ALTER COLUMN ${G(s.column)} TYPE ${r}${i};`, s.kind)
|
|
@@ -3174,20 +3178,20 @@ BEGIN
|
|
|
3174
3178
|
}
|
|
3175
3179
|
case "drop-foreign-key":
|
|
3176
3180
|
yield* e.onDialectOrElse({
|
|
3177
|
-
mysql: () => X(e,
|
|
3181
|
+
mysql: () => X(e, ta(s), s.kind),
|
|
3178
3182
|
sqlite: () => Z(e, J(s.table, n.declared), s.kind),
|
|
3179
|
-
orElse: () => X(e,
|
|
3183
|
+
orElse: () => X(e, ea(s), s.kind)
|
|
3180
3184
|
});
|
|
3181
3185
|
break;
|
|
3182
3186
|
case "add-check":
|
|
3183
3187
|
yield* e.onDialectOrElse({
|
|
3184
|
-
mysql: () => X(e,
|
|
3188
|
+
mysql: () => X(e, na(s, K), s.kind),
|
|
3185
3189
|
sqlite: () => Z(e, J(s.table, n.declared), s.kind),
|
|
3186
|
-
orElse: () => X(e,
|
|
3190
|
+
orElse: () => X(e, na(s, G), s.kind)
|
|
3187
3191
|
});
|
|
3188
3192
|
break;
|
|
3189
3193
|
case "reconcile-json-check": {
|
|
3190
|
-
let t = Y(s.column), n = s.validation === "value" ?
|
|
3194
|
+
let t = Y(s.column), n = s.validation === "value" ? rt(t) : `(${t} IS NULL OR ISJSON(${t}) = 1)`;
|
|
3191
3195
|
yield* e.onDialectOrElse({
|
|
3192
3196
|
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
3197
|
orElse: () => T.dieMessage("reconcile-json-check requires SQL Server")
|
|
@@ -3195,9 +3199,9 @@ BEGIN
|
|
|
3195
3199
|
break;
|
|
3196
3200
|
}
|
|
3197
3201
|
case "drop-check": yield* e.onDialectOrElse({
|
|
3198
|
-
mysql: () =>
|
|
3202
|
+
mysql: () => aa(e, s, n.declared),
|
|
3199
3203
|
sqlite: () => Z(e, J(s.table, n.declared), s.kind),
|
|
3200
|
-
orElse: () => X(e,
|
|
3204
|
+
orElse: () => X(e, ra(s), s.kind)
|
|
3201
3205
|
});
|
|
3202
3206
|
}
|
|
3203
3207
|
return {
|
|
@@ -3205,32 +3209,32 @@ BEGIN
|
|
|
3205
3209
|
status: "applied",
|
|
3206
3210
|
durationMs: Number((process.hrtime.bigint() - i) / 1000000n)
|
|
3207
3211
|
};
|
|
3208
|
-
}),
|
|
3212
|
+
}), ga = (e, t, n, r) => T.gen(function* () {
|
|
3209
3213
|
let i = [...new Set(r.map((e) => e.runId))];
|
|
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 \`${
|
|
3214
|
+
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 \`${k}\`, reconcile the schema by hand, and delete the rows of the run you have finished.`));
|
|
3211
3215
|
let a = i[0], o = [...r].map((e) => ({
|
|
3212
3216
|
index: Number(e.opIndex),
|
|
3213
3217
|
status: e.status,
|
|
3214
3218
|
planned: JSON.parse(e.payload)
|
|
3215
3219
|
})).sort((e, t) => e.index - t.index), s = o.find((e) => e.status === "started"), c = o.filter((e) => e.status === "started").length;
|
|
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 \`${
|
|
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} ${
|
|
3220
|
+
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 \`${k}\` by hand before re-running.`));
|
|
3221
|
+
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} ${Je(s.planned.op)}` : ""}`).pipe(T.annotateLogs({ scope: "voltro:migrate" })), o.every((e) => e.status === "pending")) return {
|
|
3218
3222
|
kind: "discard",
|
|
3219
3223
|
runId: a,
|
|
3220
3224
|
why: "no operation had started — no DDL ran"
|
|
3221
3225
|
};
|
|
3222
|
-
let l = s ? yield*
|
|
3226
|
+
let l = s ? yield* ma(e, t, s.planned) : "clean", u = r[0].planFingerprint;
|
|
3223
3227
|
if (u !== n.toFingerprint) return {
|
|
3224
3228
|
kind: "discard",
|
|
3225
3229
|
runId: a,
|
|
3226
3230
|
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`
|
|
3227
3231
|
};
|
|
3228
|
-
let d = (e) => e.status === "applied" ? !1 : s && e.index === s.index && l !== "clean" ? l === "outstanding" :
|
|
3232
|
+
let d = (e) => e.status === "applied" ? !1 : s && e.index === s.index && l !== "clean" ? l === "outstanding" : Xe(n, e.planned.op), f = o.filter(d), p = o.filter((e) => e.status !== "applied" && !d(e));
|
|
3229
3233
|
return f.length === 0 ? {
|
|
3230
3234
|
kind: "discard",
|
|
3231
3235
|
runId: a,
|
|
3232
3236
|
why: "every recorded operation had already taken effect"
|
|
3233
|
-
} : (yield*
|
|
3237
|
+
} : (yield* fa(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" })), {
|
|
3234
3238
|
kind: "resume",
|
|
3235
3239
|
runId: a,
|
|
3236
3240
|
ops: f.map((e) => ({
|
|
@@ -3238,7 +3242,7 @@ BEGIN
|
|
|
3238
3242
|
planned: e.planned
|
|
3239
3243
|
}))
|
|
3240
3244
|
});
|
|
3241
|
-
}),
|
|
3245
|
+
}), _a = (e, t, n) => T.gen(function* () {
|
|
3242
3246
|
for (let r of t.operations) {
|
|
3243
3247
|
let i = r.op;
|
|
3244
3248
|
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 && [
|
|
@@ -3249,7 +3253,7 @@ BEGIN
|
|
|
3249
3253
|
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";
|
|
3250
3254
|
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.`));
|
|
3251
3255
|
}
|
|
3252
|
-
}),
|
|
3256
|
+
}), va = (e) => {
|
|
3253
3257
|
let t = e.op, n = (e) => typeof t[e] == "string" ? t[e] : "";
|
|
3254
3258
|
return [
|
|
3255
3259
|
t.kind,
|
|
@@ -3258,13 +3262,13 @@ BEGIN
|
|
|
3258
3262
|
n("name"),
|
|
3259
3263
|
n("to")
|
|
3260
3264
|
].join("\0");
|
|
3261
|
-
},
|
|
3265
|
+
}, ya = (e, t, n) => T.acquireUseRelease(Ve(e, { schema: n.lockSchema }), () => ba(e, t, n), (e) => e.release.pipe(T.orDie)), ba = (e, t, n) => T.gen(function* () {
|
|
3262
3266
|
let r = t.operations.filter((e) => e.blocked);
|
|
3263
3267
|
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 =
|
|
3268
|
+
let i = Date.now(), a = [], o = Ue(e), s = yield* n.replan(e), c = new Set(t.operations.filter((e) => !e.blocked).map((e) => va(e))), l = {
|
|
3265
3269
|
...s,
|
|
3266
3270
|
operations: s.operations.map((e) => {
|
|
3267
|
-
if (!e.blocked || !c.has(
|
|
3271
|
+
if (!e.blocked || !c.has(va(e))) return e;
|
|
3268
3272
|
let { blocked: t, ...n } = e;
|
|
3269
3273
|
return n;
|
|
3270
3274
|
})
|
|
@@ -3272,24 +3276,24 @@ BEGIN
|
|
|
3272
3276
|
(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" })));
|
|
3273
3277
|
let u = l.operations.filter((e) => e.blocked);
|
|
3274
3278
|
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 =
|
|
3279
|
+
let d = Ge(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) => ({
|
|
3276
3280
|
index: t,
|
|
3277
3281
|
planned: e
|
|
3278
3282
|
})), _ = "fresh";
|
|
3279
|
-
yield*
|
|
3280
|
-
let v = yield*
|
|
3283
|
+
yield* _a(e, l, o), yield* ca(e, o);
|
|
3284
|
+
let v = yield* la(e);
|
|
3281
3285
|
if (v.length > 0) {
|
|
3282
|
-
let t = yield*
|
|
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*
|
|
3286
|
+
let t = yield* ga(e, o, l, v);
|
|
3287
|
+
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* pa(e, t.runId));
|
|
3284
3288
|
}
|
|
3285
|
-
_ === "fresh" && h.length > 0 && (yield*
|
|
3289
|
+
_ === "fresh" && h.length > 0 && (yield* ua(e, m, l.toFingerprint, h)), f.length > 0 && (yield* Lr(e, T.gen(function* () {
|
|
3286
3290
|
let e = yield* E.SqlClient;
|
|
3287
|
-
for (let t of f) a.push(yield*
|
|
3291
|
+
for (let t of f) a.push(yield* ha(e, t, n));
|
|
3288
3292
|
})));
|
|
3289
3293
|
for (let { index: t, planned: r } of h) {
|
|
3290
|
-
yield*
|
|
3291
|
-
let i = a.length, o = yield*
|
|
3292
|
-
a.push(o), yield*
|
|
3294
|
+
yield* da(e, m, t, "started");
|
|
3295
|
+
let i = a.length, o = yield* ha(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`) })));
|
|
3296
|
+
a.push(o), yield* da(e, m, t, "applied", o.durationMs);
|
|
3293
3297
|
}
|
|
3294
3298
|
let y = yield* n.replan(e);
|
|
3295
3299
|
if (y.operations.length > 0) {
|
|
@@ -3306,7 +3310,7 @@ BEGIN
|
|
|
3306
3310
|
(${S}, ${l.toFingerprint}, ${y.fromFingerprint}, ${JSON.stringify(ee)},
|
|
3307
3311
|
${n.appliedBy}, ${n.environment}, ${n.source},
|
|
3308
3312
|
${x}, ${w}, ${n.notes ?? null})
|
|
3309
|
-
`, yield*
|
|
3313
|
+
`, yield* pa(e, m);
|
|
3310
3314
|
let te = [...new Set(ee.flatMap((e) => e.op.kind === "rename-table" ? [e.op.to] : [e.op.table]))];
|
|
3311
3315
|
return yield* T.promise(() => g({ changedTables: te }).catch(() => {})), {
|
|
3312
3316
|
id: S,
|
|
@@ -3320,13 +3324,13 @@ BEGIN
|
|
|
3320
3324
|
source: n.source,
|
|
3321
3325
|
...n.notes ? { notes: n.notes } : {}
|
|
3322
3326
|
};
|
|
3323
|
-
}),
|
|
3327
|
+
}), xa = (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"), Sa = (e) => e`
|
|
3324
3328
|
SELECT fingerprint
|
|
3325
3329
|
FROM _voltro_migration_plans
|
|
3326
3330
|
ORDER BY ${e("appliedAt")} DESC
|
|
3327
3331
|
LIMIT 1
|
|
3328
|
-
`.pipe(T.map((e) => e.length > 0 ? e[0].fingerprint : void 0), T.catchAll(() => T.succeed(void 0))),
|
|
3329
|
-
if ((yield*
|
|
3332
|
+
`.pipe(T.map((e) => e.length > 0 ? e[0].fingerprint : void 0), T.catchAll(() => T.succeed(void 0))), Ca = (e, t, n) => T.gen(function* () {
|
|
3333
|
+
if ((yield* Sa(e)) === t.toFingerprint) return "already-current";
|
|
3330
3334
|
let r = `plan_${Date.now().toString(36)}`, i = yield* W(e, (/* @__PURE__ */ new Date()).toISOString());
|
|
3331
3335
|
return yield* e`
|
|
3332
3336
|
INSERT INTO ${e("_voltro_migration_plans")}
|
|
@@ -3338,8 +3342,8 @@ BEGIN
|
|
|
3338
3342
|
${n.appliedBy}, ${n.environment}, ${n.source},
|
|
3339
3343
|
${0}, ${i}, ${"no DDL — the declared schema already matched the database"})
|
|
3340
3344
|
`, "recorded";
|
|
3341
|
-
}).pipe(T.catchAll(() => T.succeed("already-current"))),
|
|
3342
|
-
let n = R(z(t,
|
|
3345
|
+
}).pipe(T.catchAll(() => T.succeed("already-current"))), wa = (e, t) => T.gen(function* () {
|
|
3346
|
+
let n = R(z(t, Ue(e))), r = yield* Sa(e);
|
|
3343
3347
|
return r === n ? {
|
|
3344
3348
|
kind: "up-to-date",
|
|
3345
3349
|
fingerprint: n
|
|
@@ -3348,23 +3352,23 @@ BEGIN
|
|
|
3348
3352
|
expected: n,
|
|
3349
3353
|
...r === void 0 ? {} : { actual: r }
|
|
3350
3354
|
};
|
|
3351
|
-
}),
|
|
3355
|
+
}), Ta = [
|
|
3352
3356
|
"pgeagertest_",
|
|
3353
3357
|
"mig_e2e_",
|
|
3354
3358
|
"mig_test_",
|
|
3355
3359
|
"mysqleagertest_",
|
|
3356
3360
|
"mssqleagertest_",
|
|
3357
3361
|
"sqliteeagertest_"
|
|
3358
|
-
],
|
|
3362
|
+
], Ea = (e) => Ta.some((t) => e.startsWith(t)), Da = (e, t) => T.gen(function* () {
|
|
3359
3363
|
if (process.env.VOLTRO_TEST_FIXTURE_GC === "off") return [];
|
|
3360
|
-
let n = t.filter((e) =>
|
|
3364
|
+
let n = t.filter((e) => Ea(e.name)).map((e) => e.name);
|
|
3361
3365
|
if (n.length === 0) return [];
|
|
3362
3366
|
for (let t of n) yield* e.unsafe(`DROP TABLE IF EXISTS "${t}" CASCADE`).pipe(T.catchAll(() => T.void));
|
|
3363
3367
|
return n;
|
|
3364
|
-
}),
|
|
3368
|
+
}), Oa = () => {
|
|
3365
3369
|
let e = (process.env.VOLTRO_DB_IGNORE_TABLES ?? "").split(",").map((e) => e.trim()).filter((e) => e.length > 0);
|
|
3366
3370
|
return e.length > 0 ? { ignoreTables: e } : {};
|
|
3367
|
-
},
|
|
3371
|
+
}, ka = (e) => {
|
|
3368
3372
|
if (e === void 0) return;
|
|
3369
3373
|
let t = e.trim();
|
|
3370
3374
|
if (t === "") return;
|
|
@@ -3374,34 +3378,34 @@ BEGIN
|
|
|
3374
3378
|
kind: "tables",
|
|
3375
3379
|
tables: new Set(n)
|
|
3376
3380
|
} : void 0;
|
|
3377
|
-
},
|
|
3381
|
+
}, Aa = (e) => typeof e.table == "string" ? e.table : void 0, ja = (e, t = { kind: "all" }) => ({
|
|
3378
3382
|
...e,
|
|
3379
3383
|
operations: e.operations.map((e) => {
|
|
3380
3384
|
if (!e.blocked || e.classification !== "lossy") return e;
|
|
3381
3385
|
if (t?.kind === "tables") {
|
|
3382
|
-
let n =
|
|
3386
|
+
let n = Aa(e.op);
|
|
3383
3387
|
if (n === void 0 || !t.tables.has(n)) return e;
|
|
3384
3388
|
}
|
|
3385
3389
|
let { blocked: n, ...r } = e;
|
|
3386
3390
|
return r;
|
|
3387
3391
|
})
|
|
3388
|
-
}),
|
|
3389
|
-
let t =
|
|
3392
|
+
}), Ma = (e, t, n) => t === "postgres" ? Cn(e, n).pipe(T.flatMap((e) => {
|
|
3393
|
+
let t = wn(e);
|
|
3390
3394
|
return t === void 0 ? T.void : T.logWarning(`auto-migrate: ${t}`).pipe(T.annotateLogs({ scope: "voltro:migrate" }));
|
|
3391
|
-
}), T.catchAll(() => T.void)) : T.void,
|
|
3392
|
-
let r =
|
|
3395
|
+
}), T.catchAll(() => T.void)) : T.void, Na = (e, t, n) => T.gen(function* () {
|
|
3396
|
+
let r = Ue(e), a = t;
|
|
3393
3397
|
if (process.env.VOLTRO_MIGRATE_FORCE !== "1") {
|
|
3394
3398
|
let t = R(z(a, r));
|
|
3395
|
-
if ((yield*
|
|
3399
|
+
if ((yield* Sa(e)) === t) return yield* Ma(e, r, a), {
|
|
3396
3400
|
kind: "up-to-date",
|
|
3397
3401
|
fingerprint: t
|
|
3398
3402
|
};
|
|
3399
3403
|
}
|
|
3400
|
-
let o = yield*
|
|
3404
|
+
let o = yield* Tr(e), s = yield* Da(e, o.tables);
|
|
3401
3405
|
s.length > 0 && (yield* T.logInfo(`auto-migrate: reaped ${s.length} test-fixture leftover(s)`).pipe(T.annotateLogs({
|
|
3402
3406
|
scope: "voltro:migrate",
|
|
3403
3407
|
count: s.length
|
|
3404
|
-
})), o = yield*
|
|
3408
|
+
})), o = yield* Tr(e));
|
|
3405
3409
|
{
|
|
3406
3410
|
let e = n.softDropRetentionDays ?? 7, t = p(o, { retentionDays: e });
|
|
3407
3411
|
t.length > 0 && (yield* T.logWarning(`auto-migrate: ${i(t, e)}`).pipe(T.annotateLogs({
|
|
@@ -3409,20 +3413,20 @@ BEGIN
|
|
|
3409
3413
|
snapshots: t.map((e) => e.name)
|
|
3410
3414
|
})));
|
|
3411
3415
|
}
|
|
3412
|
-
let c = new Set(t.map((e) => e.tableName)), l = (e) => e.filter((e) => !_(e.name) || c.has(e.name)), u =
|
|
3416
|
+
let c = new Set(t.map((e) => e.tableName)), l = (e) => e.filter((e) => !_(e.name) || c.has(e.name)), u = nr({
|
|
3413
3417
|
declared: a,
|
|
3414
3418
|
live: { tables: l(o.tables) },
|
|
3415
3419
|
dialect: r,
|
|
3416
|
-
...
|
|
3420
|
+
...Oa()
|
|
3417
3421
|
});
|
|
3418
3422
|
if (u.summary.blocked > 0) {
|
|
3419
|
-
let e = u.operations.filter((e) => e.blocked).every((e) => e.classification === "lossy"), t =
|
|
3420
|
-
if (t === void 0 || !e || (u =
|
|
3423
|
+
let e = u.operations.filter((e) => e.blocked).every((e) => e.classification === "lossy"), t = ka(process.env.VOLTRO_DESTRUCTIVE_OK);
|
|
3424
|
+
if (t === void 0 || !e || (u = ja(u, t), u.operations.some((e) => e.blocked))) return {
|
|
3421
3425
|
kind: "refused-blocked",
|
|
3422
3426
|
plan: u
|
|
3423
3427
|
};
|
|
3424
3428
|
}
|
|
3425
|
-
return u.operations.length === 0 ? (yield*
|
|
3429
|
+
return u.operations.length === 0 ? (yield* Ca(e, u, {
|
|
3426
3430
|
appliedBy: n.appliedBy,
|
|
3427
3431
|
environment: n.environment === "prod" ? "dev" : n.environment,
|
|
3428
3432
|
source: "auto-diff"
|
|
@@ -3431,37 +3435,37 @@ BEGIN
|
|
|
3431
3435
|
fingerprint: u.toFingerprint
|
|
3432
3436
|
}) : {
|
|
3433
3437
|
kind: "applied",
|
|
3434
|
-
applied: yield*
|
|
3438
|
+
applied: yield* ya(e, u, {
|
|
3435
3439
|
declared: t,
|
|
3436
3440
|
appliedBy: n.appliedBy,
|
|
3437
3441
|
environment: n.environment === "prod" ? "dev" : n.environment,
|
|
3438
3442
|
source: "auto-diff",
|
|
3439
3443
|
replan: (e) => T.gen(function* () {
|
|
3440
|
-
let t = yield*
|
|
3441
|
-
return
|
|
3444
|
+
let t = yield* Tr(e);
|
|
3445
|
+
return nr({
|
|
3442
3446
|
declared: a,
|
|
3443
3447
|
live: { tables: l(t.tables) },
|
|
3444
3448
|
dialect: r,
|
|
3445
|
-
...
|
|
3449
|
+
...Oa()
|
|
3446
3450
|
});
|
|
3447
3451
|
})
|
|
3448
3452
|
}),
|
|
3449
3453
|
plan: u
|
|
3450
3454
|
};
|
|
3451
|
-
}),
|
|
3455
|
+
}), Pa = (e, t, n) => process.env.VOLTRO_AUTO_MIGRATE === "0" ? T.succeed({
|
|
3452
3456
|
kind: "skipped",
|
|
3453
3457
|
reason: "VOLTRO_AUTO_MIGRATE=0"
|
|
3454
|
-
}) : n.environment === "prod" ?
|
|
3458
|
+
}) : n.environment === "prod" ? wa(e, t) : Na(e, t, n), Fa = (e, t) => {
|
|
3455
3459
|
switch (e.kind) {
|
|
3456
3460
|
case "skipped": return `auto-migrate: skipped (${e.reason})`;
|
|
3457
|
-
case "up-to-date": return `auto-migrate: schema up to date (${t}, fingerprint=${
|
|
3461
|
+
case "up-to-date": return `auto-migrate: schema up to date (${t}, fingerprint=${_n(e.fingerprint)})`;
|
|
3458
3462
|
case "applied": {
|
|
3459
3463
|
let t = e.plan.summary;
|
|
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=${
|
|
3464
|
+
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=${_n(e.applied.fingerprint)}`;
|
|
3461
3465
|
}
|
|
3462
|
-
case "prod-mismatch": return `auto-migrate: SCHEMA FINGERPRINT MISMATCH — declared=${
|
|
3466
|
+
case "prod-mismatch": return `auto-migrate: SCHEMA FINGERPRINT MISMATCH — declared=${_n(e.expected)}` + (e.actual ? ` live=${_n(e.actual)}` : " live=<no _voltro_migration_plans row>") + ". Run `voltro db apply --plan plan.json` from the deploy pipeline before serving.";
|
|
3463
3467
|
case "refused-blocked": {
|
|
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` +
|
|
3468
|
+
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` + xa(e.plan), c = [""];
|
|
3465
3469
|
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) {
|
|
3466
3470
|
let t = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map();
|
|
3467
3471
|
for (let r of e.plan.operations) {
|
|
@@ -3478,7 +3482,7 @@ BEGIN
|
|
|
3478
3482
|
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");
|
|
3479
3483
|
}
|
|
3480
3484
|
}
|
|
3481
|
-
},
|
|
3485
|
+
}, Ia = ae({ scope: "voltro:migrate" }), La = /* @__PURE__ */ new Set([
|
|
3482
3486
|
"node_modules",
|
|
3483
3487
|
"dist",
|
|
3484
3488
|
"build",
|
|
@@ -3487,11 +3491,11 @@ BEGIN
|
|
|
3487
3491
|
".next",
|
|
3488
3492
|
".git",
|
|
3489
3493
|
".framework"
|
|
3490
|
-
]),
|
|
3494
|
+
]), Ra = async (e) => {
|
|
3491
3495
|
let t = [], n = async (e) => {
|
|
3492
3496
|
let r = await oe.readdir(e, { withFileTypes: !0 }).catch(() => []);
|
|
3493
3497
|
for (let i of r) {
|
|
3494
|
-
if (
|
|
3498
|
+
if (La.has(i.name)) continue;
|
|
3495
3499
|
let r = se(e, i.name);
|
|
3496
3500
|
i.isDirectory() ? await n(r) : i.isFile() && S.test(i.name) && t.push(r);
|
|
3497
3501
|
}
|
|
@@ -3500,12 +3504,12 @@ BEGIN
|
|
|
3500
3504
|
let n = e.split("/").pop() ?? e, r = t.split("/").pop() ?? t;
|
|
3501
3505
|
return n.localeCompare(r);
|
|
3502
3506
|
});
|
|
3503
|
-
},
|
|
3507
|
+
}, za = async (e) => {
|
|
3504
3508
|
let t = [];
|
|
3505
3509
|
for (let n of e) {
|
|
3506
3510
|
let e = (await import(ce(n).href)).default;
|
|
3507
3511
|
if (!u(e)) {
|
|
3508
|
-
|
|
3512
|
+
Ia.warn("migration file has no default-exported `migration(...)` — skipped", { file: n });
|
|
3509
3513
|
continue;
|
|
3510
3514
|
}
|
|
3511
3515
|
t.push({
|
|
@@ -3514,11 +3518,11 @@ BEGIN
|
|
|
3514
3518
|
});
|
|
3515
3519
|
}
|
|
3516
3520
|
return t;
|
|
3517
|
-
},
|
|
3521
|
+
}, Ba = (e) => e`
|
|
3518
3522
|
SELECT ${e("id")}
|
|
3519
3523
|
FROM ${e("_voltro_migration_plans")}
|
|
3520
3524
|
WHERE ${e("source")} = 'file'
|
|
3521
|
-
`.pipe(T.map((e) => e.map((e) => e.id)), T.catchAll(() => T.succeed([]))),
|
|
3525
|
+
`.pipe(T.map((e) => e.map((e) => e.id)), T.catchAll(() => T.succeed([]))), Va = class extends Error {
|
|
3522
3526
|
migrationId;
|
|
3523
3527
|
file;
|
|
3524
3528
|
cause;
|
|
@@ -3526,7 +3530,7 @@ BEGIN
|
|
|
3526
3530
|
constructor(e, t, n) {
|
|
3527
3531
|
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";
|
|
3528
3532
|
}
|
|
3529
|
-
},
|
|
3533
|
+
}, Ha = (e, t, n, r) => T.gen(function* () {
|
|
3530
3534
|
let i = Date.now(), a = (/* @__PURE__ */ new Date()).toISOString(), o = {
|
|
3531
3535
|
sql: e,
|
|
3532
3536
|
log: {
|
|
@@ -3560,10 +3564,10 @@ BEGIN
|
|
|
3560
3564
|
}])},
|
|
3561
3565
|
${r}, ${n}, ${"file"},
|
|
3562
3566
|
${c}, ${l}, ${t.migration.description})
|
|
3563
|
-
`.pipe(T.mapError((e) => new
|
|
3564
|
-
}),
|
|
3567
|
+
`.pipe(T.mapError((e) => new Va(t.migration.id, t.file, e))), { durationMs: c };
|
|
3568
|
+
}), Ua = (e, t) => T.gen(function* () {
|
|
3565
3569
|
let n = yield* T.tryPromise({
|
|
3566
|
-
try: () =>
|
|
3570
|
+
try: () => Ra(se(t, "migrations")),
|
|
3567
3571
|
catch: (e) => e
|
|
3568
3572
|
});
|
|
3569
3573
|
if (n.length === 0) return {
|
|
@@ -3571,25 +3575,25 @@ BEGIN
|
|
|
3571
3575
|
skipped: []
|
|
3572
3576
|
};
|
|
3573
3577
|
let r = yield* T.tryPromise({
|
|
3574
|
-
try: () =>
|
|
3578
|
+
try: () => za(n),
|
|
3575
3579
|
catch: (e) => e
|
|
3576
3580
|
});
|
|
3577
3581
|
if (r.length === 0) return {
|
|
3578
3582
|
pending: [],
|
|
3579
3583
|
skipped: []
|
|
3580
3584
|
};
|
|
3581
|
-
let i = new Set(yield*
|
|
3585
|
+
let i = new Set(yield* Ba(e));
|
|
3582
3586
|
return {
|
|
3583
3587
|
pending: r.filter((e) => !i.has(e.migration.id)),
|
|
3584
3588
|
skipped: r.filter((e) => i.has(e.migration.id)).map((e) => e.migration.id)
|
|
3585
3589
|
};
|
|
3586
|
-
}),
|
|
3587
|
-
let { pending: n, skipped: r } = yield*
|
|
3590
|
+
}), Wa = (e, t) => Ua(e, t).pipe(T.map((e) => e.pending.map((e) => e.migration.id))), Ga = (e, t) => T.gen(function* () {
|
|
3591
|
+
let { pending: n, skipped: r } = yield* Ua(e, t.projectRoot);
|
|
3588
3592
|
return n.length === 0 ? {
|
|
3589
3593
|
applied: [],
|
|
3590
3594
|
skipped: r
|
|
3591
3595
|
} : {
|
|
3592
|
-
applied: yield* T.acquireUseRelease(
|
|
3596
|
+
applied: yield* T.acquireUseRelease(Ve(e, { schema: t.lockSchema }), () => T.gen(function* () {
|
|
3593
3597
|
let r = [];
|
|
3594
3598
|
for (let i of n) {
|
|
3595
3599
|
yield* T.logInfo("file-based migration applying").pipe(T.annotateLogs({
|
|
@@ -3597,7 +3601,7 @@ BEGIN
|
|
|
3597
3601
|
id: i.migration.id,
|
|
3598
3602
|
file: i.file
|
|
3599
3603
|
}));
|
|
3600
|
-
let { durationMs: n } = yield*
|
|
3604
|
+
let { durationMs: n } = yield* Ha(e, i, t.env, t.appliedBy);
|
|
3601
3605
|
r.push({
|
|
3602
3606
|
id: i.migration.id,
|
|
3603
3607
|
durationMs: n
|
|
@@ -3611,21 +3615,21 @@ BEGIN
|
|
|
3611
3615
|
}), (e) => e.release.pipe(T.orDie)),
|
|
3612
3616
|
skipped: r
|
|
3613
3617
|
};
|
|
3614
|
-
}),
|
|
3618
|
+
}), Ka = (e, t) => e`
|
|
3615
3619
|
SELECT ${e("id")}
|
|
3616
3620
|
FROM ${e("_voltro_migration_plans")}
|
|
3617
3621
|
WHERE ${e("id")} = ${t} AND ${e("source")} = 'file'
|
|
3618
3622
|
LIMIT 1
|
|
3619
|
-
`,
|
|
3620
|
-
if (!(yield*
|
|
3623
|
+
`, qa = (e, t) => T.gen(function* () {
|
|
3624
|
+
if (!(yield* Ka(e, t.id))[0]) return yield* T.fail(/* @__PURE__ */ Error(`rollback: ${t.id} not found in _voltro_migration_plans (file source)`));
|
|
3621
3625
|
let n = yield* T.tryPromise({
|
|
3622
|
-
try: () =>
|
|
3626
|
+
try: () => Ra(se(t.projectRoot, "migrations")),
|
|
3623
3627
|
catch: (e) => e
|
|
3624
3628
|
}), r = (yield* T.tryPromise({
|
|
3625
|
-
try: () =>
|
|
3629
|
+
try: () => za(n),
|
|
3626
3630
|
catch: (e) => e
|
|
3627
3631
|
})).find((e) => e.migration.id === t.id);
|
|
3628
|
-
return r ? yield* T.acquireUseRelease(
|
|
3632
|
+
return r ? yield* T.acquireUseRelease(Ve(e, { schema: t.lockSchema }), () => T.gen(function* () {
|
|
3629
3633
|
let n = Date.now(), i = {
|
|
3630
3634
|
sql: e,
|
|
3631
3635
|
log: {
|
|
@@ -3650,7 +3654,7 @@ BEGIN
|
|
|
3650
3654
|
durationMs: o
|
|
3651
3655
|
};
|
|
3652
3656
|
}), (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
|
-
}),
|
|
3657
|
+
}), Ja = (e) => T.gen(function* () {
|
|
3654
3658
|
let t = yield* E.SqlClient, n = yield* t`
|
|
3655
3659
|
SELECT id, fingerprint, appliedAt FROM _voltro_migration_plans
|
|
3656
3660
|
WHERE source = 'auto-diff'
|
|
@@ -3695,7 +3699,7 @@ BEGIN
|
|
|
3695
3699
|
snapshotFingerprint: e.fingerprint,
|
|
3696
3700
|
snapshotId: i
|
|
3697
3701
|
};
|
|
3698
|
-
}),
|
|
3702
|
+
}), Ya = { safe: !0 }, Xa = (e) => {
|
|
3699
3703
|
switch (e.kind) {
|
|
3700
3704
|
case "drop-column": return {
|
|
3701
3705
|
safe: !1,
|
|
@@ -3722,7 +3726,7 @@ BEGIN
|
|
|
3722
3726
|
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`,
|
|
3723
3727
|
remedy: "add a new column of the target type + backfill + dual-write, cut code over, then drop the old column in a LATER deploy"
|
|
3724
3728
|
};
|
|
3725
|
-
case "alter-column-nullability": return e.toNullable ?
|
|
3729
|
+
case "alter-column-nullability": return e.toNullable ? Ya : {
|
|
3726
3730
|
safe: !1,
|
|
3727
3731
|
reason: `old instances may INSERT "${e.table}" without (or with NULL in) "${e.column}", which the new NOT NULL rejects`,
|
|
3728
3732
|
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)`
|
|
@@ -3733,7 +3737,7 @@ BEGIN
|
|
|
3733
3737
|
reason: `old instances still write "${e.table}" without honouring the new uniqueness; a colliding insert now fails mid-rollout`,
|
|
3734
3738
|
remedy: "make code enforce uniqueness first and deploy that; add the constraint in a LATER deploy once no old writer remains"
|
|
3735
3739
|
};
|
|
3736
|
-
case "reconcile-json-check": return e.previousValidation === "container" && e.validation === "value" ?
|
|
3740
|
+
case "reconcile-json-check": return e.previousValidation === "container" && e.validation === "value" ? Ya : {
|
|
3737
3741
|
safe: !1,
|
|
3738
3742
|
reason: `writes to "${e.table}"."${e.column}" must satisfy the new JSON validation`,
|
|
3739
3743
|
remedy: "ensure all writers supply valid JSON in the required domain before enabling this check"
|
|
@@ -3757,12 +3761,12 @@ BEGIN
|
|
|
3757
3761
|
case "drop-unique":
|
|
3758
3762
|
case "drop-unique-composite":
|
|
3759
3763
|
case "drop-foreign-key":
|
|
3760
|
-
case "drop-check": return
|
|
3764
|
+
case "drop-check": return Ya;
|
|
3761
3765
|
}
|
|
3762
|
-
},
|
|
3766
|
+
}, Za = (e) => {
|
|
3763
3767
|
let t = [];
|
|
3764
3768
|
for (let n of e) {
|
|
3765
|
-
let e =
|
|
3769
|
+
let e = Xa(n.op);
|
|
3766
3770
|
e.safe || t.push({
|
|
3767
3771
|
op: n,
|
|
3768
3772
|
reason: e.reason,
|
|
@@ -3770,7 +3774,7 @@ BEGIN
|
|
|
3770
3774
|
});
|
|
3771
3775
|
}
|
|
3772
3776
|
return t;
|
|
3773
|
-
},
|
|
3777
|
+
}, Qa = (e) => {
|
|
3774
3778
|
if (!e.enabled || e.unsafeCount === 0) return {
|
|
3775
3779
|
refuse: !1,
|
|
3776
3780
|
warnForced: !1,
|
|
@@ -3786,18 +3790,18 @@ BEGIN
|
|
|
3786
3790
|
warnForced: !1,
|
|
3787
3791
|
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.`
|
|
3788
3792
|
};
|
|
3789
|
-
},
|
|
3793
|
+
}, $a = (e) => {
|
|
3790
3794
|
let t = e.table;
|
|
3791
3795
|
if (typeof t == "string") return t;
|
|
3792
3796
|
let n = e.from;
|
|
3793
3797
|
return typeof n == "string" ? n : void 0;
|
|
3794
|
-
},
|
|
3798
|
+
}, eo = (e) => ({
|
|
3795
3799
|
kind: e.op.kind,
|
|
3796
|
-
table:
|
|
3800
|
+
table: $a(e.op),
|
|
3797
3801
|
classification: e.classification,
|
|
3798
3802
|
reason: e.reason,
|
|
3799
3803
|
blockedFix: e.blocked?.fix
|
|
3800
|
-
}),
|
|
3804
|
+
}), to = (e) => e.operations.map(eo), no = async (e) => {
|
|
3801
3805
|
let t = e.log ?? (() => {}), n = {
|
|
3802
3806
|
branchId: e.branchId,
|
|
3803
3807
|
mechanism: e.mechanism,
|
|
@@ -3816,10 +3820,10 @@ BEGIN
|
|
|
3816
3820
|
applied: !1,
|
|
3817
3821
|
converged: !1,
|
|
3818
3822
|
residual: r,
|
|
3819
|
-
infidelity:
|
|
3823
|
+
infidelity: to(o)
|
|
3820
3824
|
};
|
|
3821
3825
|
else {
|
|
3822
|
-
let i = await e.plan(), o =
|
|
3826
|
+
let i = await e.plan(), o = to(i), s = o.filter((e) => e.classification === "lossy"), c = ja(i), l = c.operations.filter((e) => e.blocked !== void 0).map(eo);
|
|
3823
3827
|
if (l.length > 0) a = {
|
|
3824
3828
|
...n,
|
|
3825
3829
|
outcome: "blocked",
|
|
@@ -3844,7 +3848,7 @@ BEGIN
|
|
|
3844
3848
|
};
|
|
3845
3849
|
else {
|
|
3846
3850
|
await e.apply(c), t(`branch ${e.branchId}: applied ${o.length} operation(s)`);
|
|
3847
|
-
let i =
|
|
3851
|
+
let i = to(await e.replan());
|
|
3848
3852
|
a = {
|
|
3849
3853
|
...n,
|
|
3850
3854
|
outcome: i.length > 0 ? "diverged" : s.length > 0 ? "lossy" : "clean",
|
|
@@ -3882,7 +3886,7 @@ BEGIN
|
|
|
3882
3886
|
...a,
|
|
3883
3887
|
tornDown: o
|
|
3884
3888
|
};
|
|
3885
|
-
},
|
|
3889
|
+
}, ro = (e) => {
|
|
3886
3890
|
switch (e.outcome) {
|
|
3887
3891
|
case "clean": return 0;
|
|
3888
3892
|
case "lossy": return 2;
|
|
@@ -3891,22 +3895,22 @@ BEGIN
|
|
|
3891
3895
|
case "infidelity": return 1;
|
|
3892
3896
|
case "failed": return 1;
|
|
3893
3897
|
}
|
|
3894
|
-
},
|
|
3898
|
+
}, io = (e) => ` ${e.classification === "lossy" ? "✗" : "•"} ${e.kind}${e.table ? ` ${e.table}` : ""} [${e.classification}]${e.reason ? ` — ${e.reason}` : ""}${e.blockedFix ? `\n ! ${e.blockedFix}` : ""}`, ao = (e) => {
|
|
3895
3899
|
let t = [];
|
|
3896
3900
|
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"}`);
|
|
3897
3901
|
else if (e.outcome === "infidelity") {
|
|
3898
3902
|
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:");
|
|
3899
|
-
for (let n of e.infidelity) t.push(
|
|
3903
|
+
for (let n of e.infidelity) t.push(io(n));
|
|
3900
3904
|
} else {
|
|
3901
3905
|
t.push(` plan: ${e.operations.length} operation(s), ${e.lossy.length} lossy, ${e.blocked.length} refused`);
|
|
3902
|
-
for (let n of e.operations) t.push(
|
|
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(
|
|
3906
|
+
for (let n of e.operations) t.push(io(n));
|
|
3907
|
+
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(io(n));
|
|
3904
3908
|
}
|
|
3905
3909
|
return t.push(e.tornDown ? ` branch ${e.branchId} torn down.` : ` branch ${e.branchId} KEPT — drop it when you are done.`), t.join("\n");
|
|
3906
|
-
},
|
|
3910
|
+
}, oo = (e, ...t) => ({
|
|
3907
3911
|
_tag: "RawSqlFragment",
|
|
3908
3912
|
strings: [...e],
|
|
3909
3913
|
values: [...t]
|
|
3910
|
-
}),
|
|
3914
|
+
}), so = (e) => typeof e == "object" && !!e && e._tag === "RawSqlFragment";
|
|
3911
3915
|
//#endregion
|
|
3912
|
-
export {
|
|
3916
|
+
export { A as DEFAULT_CDC_CHANNEL, S as FILE_MIGRATION_PATTERN, Va as FileMigrationLedgerError, st as REACTIVE_TRIGGER_PREFIX, xe as VOLTRO_MIGRATION_LOCK_KEY, Ve as acquireMigrationLock, W as appliedAtValue, Zt as applyNamespacedSchema, ya as applyPlan, Vt as applySchema, Qa as assessRollingDeployGate, ro as branchRehearsalExitCode, dr as chunkTables, Xa as classifyRollingDeploySafety, z as declaredSnapshot, mt as defaultArrayClause, pt as defaultClause, N as defaultJsonClause, Fa as describeOutcome, ka as destructiveScope, Cn as detectReactiveTriggerDrift, Ni as emitAddIndexMysql, wi as emitCreateTableMssql, pi as emitCreateTableMysql, ci as emitCreateTablePg, yi as emitCreateTableSqlite, Kr as emitDropColumnDdl, qr as emitDropColumnDdlMysql, Bt as emitFrameworkBootstrapSql, Rt as emitNamespaceProvisionDdl, zt as emitNamespacedSchemaSql, Lt as emitSchemaSql, Er as engineFromVersion, R as fingerprintSchema, De as fnv1a64, ao as formatBranchRehearsal, wn as formatReactiveTriggerDrift, Oa as ignoreTablesFromEnv, Tr as introspectSchema, Mr as isAlreadySatisfied, u as isFileMigration, so as isRawSqlFragment, Ut as isReRunSafeDdl, ar as mapPgType, d as migration, Oe as migrationLockKeyForSchema, ke as migrationLockNameForSchema, Oi as mysqlIndexPrefixFor, lt as notifyFunctionName, P as numericIdSql, ir as parseEnumCheck, Wa as pendingFileMigrationIds, nr as planMigrations, Qt as provisionTenantNamespace, ct as reactiveTriggerName, Ot as reactiveTriggerRepairSql, Ca as recordUpToDate, no as rehearseMigrationOnBranch, eo as rehearsedOperation, di as renderColumnMysql, ai as renderColumnPg, Ce as resolveMigrationLockSchema, Or as resolveMysqlEngine, qa as rollbackFileBasedMigration, Za as rollingDeployUnsafeOps, Ga as runFileBasedMigrations, $t as runFrameworkBootstrap, Xt as runMigrate, Pa as runPlannedMigrations, _n as shortFingerprint, vn as snapshotColumn, oo as sql, M as sqlType, Ja as squashMigrationPlans, ja as unblockLossy, He as withMigrationLock };
|