@voltro/database 0.79.0 → 0.79.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 +55 -0
- package/dist/sql.d.ts +27 -3
- package/dist/sql.js +778 -753
- package/package.json +2 -2
package/dist/sql.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { A as e, B as t, Bn as n, C as r, Cn as i, Cr as a, D as o, Dn as s, E as c, En as l, Er as u, F as d, Fr as f, Ft as p, Gn as m, H as h, I as g, It as _, J as v, Kn as y, L as b, M as x, N as S, Nt as C,
|
|
2
|
-
import { Cause as
|
|
3
|
-
import { createHash as
|
|
4
|
-
import { createLogger as
|
|
1
|
+
import { A as e, B as t, Bn as n, C as r, Cn as i, Cr as a, D as o, Dn as s, E as c, En as l, Er as u, F as d, Fr as f, Ft as p, Gn as m, H as h, I as g, It as _, J as v, Kn as y, L as b, M as x, N as S, Nt as C, O as w, P as T, Pr as E, R as D, Rt as O, S as ee, Sn as k, Sr as te, T as ne, U as re, Vt as ie, Xn as ae, ct as oe, et as se, hn as ce, j as le, k as ue, p as de, r as fe, rr as pe, rt as me, t as he, w as ge, wt as _e, xn as ve, z as ye } from "./replaceInProgress-BmSjNTp0.js";
|
|
2
|
+
import { Cause as be, Effect as A, Equal as xe, Exit as Se, Schedule as Ce, Scope as we } from "effect";
|
|
3
|
+
import { createHash as Te } from "node:crypto";
|
|
4
|
+
import { createLogger as Ee } from "@voltro/logger";
|
|
5
5
|
import { SqlClient as j } from "@effect/sql";
|
|
6
|
-
import { promises as
|
|
7
|
-
import { join as
|
|
8
|
-
import { pathToFileURL as
|
|
6
|
+
import { promises as De } from "node:fs";
|
|
7
|
+
import { join as Oe } from "node:path";
|
|
8
|
+
import { pathToFileURL as ke } from "node:url";
|
|
9
9
|
//#region src/indexStorage.ts
|
|
10
|
-
var
|
|
10
|
+
var Ae = (e, t = "float32") => {
|
|
11
11
|
let n = e?.hnsw, r = n?.m ?? 16, i = n?.efConstruction ?? 64;
|
|
12
12
|
for (let [e, t] of Object.entries({
|
|
13
13
|
m: r,
|
|
@@ -20,10 +20,10 @@ var ke = (e, t = "float32") => {
|
|
|
20
20
|
efConstruction: i,
|
|
21
21
|
opclass: a.toLowerCase().replace(/^public\./, "")
|
|
22
22
|
};
|
|
23
|
-
},
|
|
23
|
+
}, je = (e, t) => t === void 0 || t === "postgres" ? e ?? "btree" : e === "hnsw" || e === "gin" && (t === "mysql" || t === "mariadb") ? null : "btree", Me = (e, t) => ({
|
|
24
24
|
...e !== void 0 && e !== "btree" ? { kind: e } : {},
|
|
25
|
-
...e === "hnsw" ? { kindOptions: { hnsw:
|
|
26
|
-
}),
|
|
25
|
+
...e === "hnsw" ? { kindOptions: { hnsw: Ae(t) } } : {}
|
|
26
|
+
}), Ne = (e, t, n = "float32") => {
|
|
27
27
|
if (e === void 0 || e === "btree") return {
|
|
28
28
|
using: "",
|
|
29
29
|
withSuffix: "",
|
|
@@ -35,14 +35,14 @@ var ke = (e, t = "float32") => {
|
|
|
35
35
|
withSuffix: "",
|
|
36
36
|
skip: !1
|
|
37
37
|
};
|
|
38
|
-
let r =
|
|
38
|
+
let r = Ae(t, n);
|
|
39
39
|
return {
|
|
40
40
|
using: " USING hnsw",
|
|
41
41
|
withSuffix: ` WITH (m = ${r.m}, ef_construction = ${r.efConstruction})`,
|
|
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 ke = (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 = Fe(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
|
+
}, Fe = (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, Ie = (e) => e.unique === !0 && typeof e.where == "string" && e.where.length > 0, Le = (e) => e.replace(/"/g, "`"), Re = (e) => typeof e == "string" ? e : e.name ?? String(e), ze = (e, t) => `_ua_${t}_${e}`.slice(0, 64), Be = (e, t) => {
|
|
79
|
+
if (t !== "mysql" && t !== "mariadb" || !e.appliedIndexes.some(Ie)) return e;
|
|
80
80
|
let n = { ...e.fields }, r = [], i = [];
|
|
81
81
|
for (let t of e.appliedIndexes) {
|
|
82
|
-
if (!
|
|
82
|
+
if (!Ie(t)) {
|
|
83
83
|
r.push(t);
|
|
84
84
|
continue;
|
|
85
85
|
}
|
|
86
|
-
let a =
|
|
86
|
+
let a = Le(t.where), o = [];
|
|
87
87
|
for (let r of t.fields) {
|
|
88
|
-
let i =
|
|
88
|
+
let i = Re(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 = ze(t.name, i);
|
|
91
91
|
o.push(s), n[s] = {
|
|
92
92
|
type: "text",
|
|
93
93
|
nullable: !0,
|
|
@@ -110,7 +110,7 @@ var ke = (e, t = "float32") => {
|
|
|
110
110
|
appliedIndexes: r,
|
|
111
111
|
appliedUniques: [...e.appliedUniques ?? [], ...i]
|
|
112
112
|
};
|
|
113
|
-
}, M = (e, t) => `${e}::${t}`,
|
|
113
|
+
}, M = (e, t) => `${e}::${t}`, Ve = (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));
|
|
@@ -119,96 +119,96 @@ var ke = (e, t = "float32") => {
|
|
|
119
119
|
};
|
|
120
120
|
for (let t of [...e].sort()) r.has(t) || a(t);
|
|
121
121
|
return i;
|
|
122
|
-
},
|
|
123
|
-
t !== void 0 && Number.isInteger(t) && t > 0 &&
|
|
124
|
-
},
|
|
125
|
-
let t =
|
|
122
|
+
}, He = /* @__PURE__ */ new WeakMap(), Ue = (e, t) => {
|
|
123
|
+
t !== void 0 && Number.isInteger(t) && t > 0 && He.set(e, t);
|
|
124
|
+
}, We = (e) => {
|
|
125
|
+
let t = He.get(e);
|
|
126
126
|
if (t !== void 0) return t;
|
|
127
127
|
if (!("config" in e) || typeof e.config != "object" || e.config === null || !("maxConnections" in e.config)) return;
|
|
128
128
|
let n = e.config.maxConnections;
|
|
129
129
|
return typeof n == "number" && Number.isInteger(n) && n > 0 ? n : void 0;
|
|
130
|
-
},
|
|
130
|
+
}, Ge = (e, t) => e.executeUnprepared(t, [], void 0), Ke = 6322741009312437n, qe = (e) => {
|
|
131
131
|
let t = e?.trim();
|
|
132
132
|
return t === void 0 || t === "" || t === "public" ? void 0 : t;
|
|
133
|
-
},
|
|
134
|
-
let t =
|
|
135
|
-
for (let n of new TextEncoder().encode(e)) t ^= BigInt(n), t = t *
|
|
133
|
+
}, Je = (e) => e?.schema === void 0 ? qe(process.env.DB_SCHEMA) : qe(e.schema), Ye = 14695981039346656037n, Xe = 1099511628211n, Ze = 18446744073709551615n, Qe = (e) => {
|
|
134
|
+
let t = Ye;
|
|
135
|
+
for (let n of new TextEncoder().encode(e)) t ^= BigInt(n), t = t * Xe & Ze;
|
|
136
136
|
return t;
|
|
137
|
-
}, Qe = (e) => {
|
|
138
|
-
let t = Ke(e);
|
|
139
|
-
return t === void 0 ? Ge : Ze(`voltro_migration_lock:${t}`) & 9223372036854775807n;
|
|
140
137
|
}, $e = (e) => {
|
|
141
|
-
let t =
|
|
138
|
+
let t = qe(e);
|
|
139
|
+
return t === void 0 ? Ke : Qe(`voltro_migration_lock:${t}`) & 9223372036854775807n;
|
|
140
|
+
}, et = (e) => {
|
|
141
|
+
let t = `voltro_migration_${Ke.toString(36)}`, n = qe(e);
|
|
142
142
|
if (n === void 0) return t;
|
|
143
143
|
let r = `${t}_${n}`;
|
|
144
|
-
return /^[A-Za-z0-9_]+$/.test(n) && r.length <= 64 ? r : `${t}_h${(
|
|
145
|
-
},
|
|
144
|
+
return /^[A-Za-z0-9_]+$/.test(n) && r.length <= 64 ? r : `${t}_h${(Qe(`voltro_migration_lock:${n}`) & Ze).toString(16)}`;
|
|
145
|
+
}, tt = 250, nt = () => {
|
|
146
146
|
let e = Number(process.env.VOLTRO_MIGRATION_LOCK_TIMEOUT_MS);
|
|
147
147
|
return Number.isFinite(e) && e > 0 ? e : 3e4;
|
|
148
|
-
},
|
|
149
|
-
let n =
|
|
148
|
+
}, rt = (e, t) => A.gen(function* () {
|
|
149
|
+
let n = nt(), r = Date.now();
|
|
150
150
|
for (;;) {
|
|
151
|
-
if ((yield*
|
|
152
|
-
Date.now() - r >= n && (yield* A.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* A.sleep(`${
|
|
151
|
+
if ((yield* Ge(e, `SELECT pg_try_advisory_lock(${t.toString()}::bigint) AS got`))[0]?.got) return;
|
|
152
|
+
Date.now() - r >= n && (yield* A.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* A.sleep(`${tt} millis`);
|
|
153
153
|
}
|
|
154
|
-
}),
|
|
155
|
-
(yield*
|
|
156
|
-
}),
|
|
157
|
-
let n = yield*
|
|
154
|
+
}), it = (e, t) => A.asVoid(Ge(e, `SELECT pg_advisory_unlock(${t.toString()}::bigint)`)), at = 30, ot = (e, t) => A.gen(function* () {
|
|
155
|
+
(yield* Ge(e, `SELECT GET_LOCK('${t}', ${String(at)}) AS got`))[0]?.got !== 1 && (yield* A.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${t}' within ${at}s (another migration is in progress, or a prior one left it held).`)));
|
|
156
|
+
}), st = (e, t) => A.asVoid(Ge(e, `SELECT RELEASE_LOCK('${t}')`)), ct = 3e4, lt = (e, t) => A.gen(function* () {
|
|
157
|
+
let n = yield* Ge(e, `
|
|
158
158
|
DECLARE @res int;
|
|
159
159
|
EXEC @res = sp_getapplock @Resource = '${t}', @LockMode = 'Exclusive',
|
|
160
|
-
@LockOwner = 'Session', @LockTimeout = ${String(
|
|
160
|
+
@LockOwner = 'Session', @LockTimeout = ${String(ct)};
|
|
161
161
|
SELECT @res AS res`);
|
|
162
162
|
(n[0]?.res ?? -999) < 0 && (yield* A.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${t}' (sp_getapplock returned ${n[0]?.res ?? "no row"}; another migration is in progress).`)));
|
|
163
|
-
}),
|
|
164
|
-
let n =
|
|
163
|
+
}), ut = (e, t) => A.asVoid(Ge(e, `EXEC sp_releaseapplock @Resource = '${t}', @LockOwner = 'Session'`)), dt = A.void, ft = (e, t) => A.gen(function* () {
|
|
164
|
+
let n = Je(t), r = et(n), i = $e(n);
|
|
165
165
|
if (!e.onDialectOrElse({
|
|
166
166
|
mysql: () => !0,
|
|
167
167
|
mssql: () => !0,
|
|
168
168
|
sqlite: () => !1,
|
|
169
169
|
orElse: () => !0
|
|
170
|
-
})) return { release:
|
|
171
|
-
let a =
|
|
170
|
+
})) return { release: dt };
|
|
171
|
+
let a = We(e);
|
|
172
172
|
if (a !== void 0 && a < 2) return yield* A.dieMessage(`migrate needs at least 2 connections, pool has ${a}: one holds the migration lock and another runs the statements. Configure maxConnections >= 2 for the migrating process.`);
|
|
173
|
-
let o = yield*
|
|
173
|
+
let o = yield* we.make(), s = yield* A.provideService(e.reserve, we.Scope, o), c = we.close(o, Se.void);
|
|
174
174
|
return yield* e.onDialectOrElse({
|
|
175
|
-
mysql: () => at(s, r),
|
|
176
|
-
mssql: () => ct(s, r),
|
|
177
|
-
sqlite: () => ut,
|
|
178
|
-
orElse: () => nt(s, i)
|
|
179
|
-
}).pipe(A.onExit((e) => xe.isSuccess(e) ? A.void : c)), { release: e.onDialectOrElse({
|
|
180
175
|
mysql: () => ot(s, r),
|
|
181
176
|
mssql: () => lt(s, r),
|
|
182
|
-
sqlite: () =>
|
|
177
|
+
sqlite: () => dt,
|
|
183
178
|
orElse: () => rt(s, i)
|
|
179
|
+
}).pipe(A.onExit((e) => Se.isSuccess(e) ? A.void : c)), { release: e.onDialectOrElse({
|
|
180
|
+
mysql: () => st(s, r),
|
|
181
|
+
mssql: () => ut(s, r),
|
|
182
|
+
sqlite: () => dt,
|
|
183
|
+
orElse: () => it(s, i)
|
|
184
184
|
}).pipe(A.ensuring(c)) };
|
|
185
|
-
}),
|
|
185
|
+
}), pt = "a migration needs 2 connections: one holds the migration lock for the whole apply, the other runs the statements. The pool could not hand out the second one — raise its size (DB_MAX_CONNECTIONS / PG_MAX_CONNECTIONS, or the driver's own `maxConnections`) to at least 2 for the migrating process; behind a pooler (PgBouncer, Supavisor) point the migration at the database directly (DB_DIRECT_URL / DB_MIGRATE_URL).", mt = (e) => /acquire connection/i.test(String(e?.message ?? e)), ht = (e, t, n) => A.acquireUseRelease(ft(e, n), () => t.pipe(A.tapError((e) => mt(e) ? A.logError(`migrate: ${pt}`).pipe(A.annotateLogs({ scope: "voltro:migrate" })) : A.void)), (e) => e.release.pipe(A.orDie)), N = (e) => e.onDialectOrElse({
|
|
186
186
|
pg: () => "postgres",
|
|
187
187
|
mysql: () => "mysql",
|
|
188
188
|
mssql: () => "mssql",
|
|
189
189
|
sqlite: () => "sqlite",
|
|
190
190
|
orElse: () => "sqlite"
|
|
191
|
-
}),
|
|
191
|
+
}), gt = {
|
|
192
192
|
postgres: "plan-transactional",
|
|
193
193
|
mssql: "plan-transactional",
|
|
194
194
|
mysql: "per-operation",
|
|
195
195
|
mariadb: "per-operation",
|
|
196
196
|
sqlite: "per-operation",
|
|
197
197
|
turso: "per-operation"
|
|
198
|
-
},
|
|
198
|
+
}, _t = (e) => gt[e], P = "_voltro_migration_ops", vt = l(P, {
|
|
199
199
|
id: te({ prefix: "mop" }),
|
|
200
|
-
runId:
|
|
201
|
-
planFingerprint:
|
|
200
|
+
runId: E(),
|
|
201
|
+
planFingerprint: E(),
|
|
202
202
|
opIndex: a(),
|
|
203
|
-
opKind:
|
|
204
|
-
opTarget:
|
|
205
|
-
status:
|
|
206
|
-
payload:
|
|
203
|
+
opKind: E(),
|
|
204
|
+
opTarget: E(),
|
|
205
|
+
status: E(),
|
|
206
|
+
payload: E(),
|
|
207
207
|
startedAt: f().nullable(),
|
|
208
208
|
appliedAt: f().nullable(),
|
|
209
209
|
durationMs: a().nullable(),
|
|
210
210
|
createdAt: f().default("now")
|
|
211
|
-
}),
|
|
211
|
+
}), yt = (e) => {
|
|
212
212
|
switch (e.kind) {
|
|
213
213
|
case "create-table": return /* @__PURE__ */ new Set([
|
|
214
214
|
`table:${e.table}`,
|
|
@@ -242,11 +242,11 @@ var ke = (e, t = "float32") => {
|
|
|
242
242
|
...e.foreignKeys.map((e) => `column:${e.table}.${e.column}`)
|
|
243
243
|
]);
|
|
244
244
|
}
|
|
245
|
-
},
|
|
246
|
-
let n =
|
|
247
|
-
for (let t of
|
|
245
|
+
}, bt = (e) => [...yt(e)].join(" "), xt = (e, t) => {
|
|
246
|
+
let n = yt(t);
|
|
247
|
+
for (let t of yt(e)) if (n.has(t)) return !0;
|
|
248
248
|
return !1;
|
|
249
|
-
},
|
|
249
|
+
}, St = (e, t) => e.operations.some((e) => xt(e.op, t)), Ct = "__voltro_rebuild", wt = "__shadow", Tt = "__old", Et = /* @__PURE__ */ new Set([
|
|
250
250
|
"add-unique",
|
|
251
251
|
"drop-unique",
|
|
252
252
|
"add-unique-composite",
|
|
@@ -258,14 +258,14 @@ var ke = (e, t = "float32") => {
|
|
|
258
258
|
"alter-column-nullability",
|
|
259
259
|
"alter-column-type",
|
|
260
260
|
"alter-column-default"
|
|
261
|
-
]),
|
|
261
|
+
]), Dt = /* @__PURE__ */ new Set(["alter-column-default", "alter-column-nullability"]), Ot = (e, t, n) => {
|
|
262
262
|
let r = n === "sqlite" || n === "turso";
|
|
263
|
-
return e.kind === "alter-column-type" && t === "online-required" || r &&
|
|
263
|
+
return e.kind === "alter-column-type" && t === "online-required" || r && Et.has(e.kind) ? "artefact-repair" : Dt.has(e.kind) ? "idempotent" : "probe-then-replay";
|
|
264
264
|
};
|
|
265
|
-
Object.keys(
|
|
265
|
+
Object.keys(gt);
|
|
266
266
|
//#endregion
|
|
267
267
|
//#region src/mssqlJsonValueCheck.ts
|
|
268
|
-
var
|
|
268
|
+
var kt = (e) => {
|
|
269
269
|
let t = `(N'{"v":' + ${e} + N'}')`, n = `ISJSON(${t}) = 1`, r = `JSON_MODIFY(CASE WHEN ${n} THEN ${t} ELSE N'{}' END, '$.v', NULL)`;
|
|
270
270
|
return `(${e} IS NULL OR (${n} AND ${[
|
|
271
271
|
32,
|
|
@@ -273,7 +273,7 @@ var Ot = (e) => {
|
|
|
273
273
|
10,
|
|
274
274
|
13
|
|
275
275
|
].reduce((e, t) => `REPLACE(${e}, NCHAR(${t}), N'')`, r)} = N'{}'))`;
|
|
276
|
-
},
|
|
276
|
+
}, At = (e) => {
|
|
277
277
|
let t = [], n = /\s+|N?'(?:''|[^'])*'|\[(?:\]\]|[^\]])*\]|[A-Za-z_][A-Za-z_0-9]*|[0-9]+|[()+,=]/giy, r = 0;
|
|
278
278
|
for (; r < e.length;) {
|
|
279
279
|
n.lastIndex = r;
|
|
@@ -283,36 +283,36 @@ var Ot = (e) => {
|
|
|
283
283
|
/^\s+$/.test(a) || t.push(/^(?:N?')|^\[/i.test(a) ? a.replace(/^n'/, "N'") : a.toLowerCase()), r = n.lastIndex;
|
|
284
284
|
}
|
|
285
285
|
return t;
|
|
286
|
-
},
|
|
286
|
+
}, jt = (e, t) => {
|
|
287
287
|
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 = [
|
|
288
288
|
32,
|
|
289
289
|
9,
|
|
290
290
|
10,
|
|
291
291
|
13
|
|
292
292
|
].reduce((e, t) => `replace(${e},nchar((${t})),N'')`, a), s = [
|
|
293
|
-
["value",
|
|
293
|
+
["value", kt(n)],
|
|
294
294
|
["value", `(${n} IS NULL OR ${i} AND ${o}=N'{}')`],
|
|
295
295
|
["container", `(${n} IS NULL OR ISJSON(${n}) = 1)`],
|
|
296
296
|
["container", `(${n} IS NULL OR isjson(${n})=(1))`]
|
|
297
|
-
], c =
|
|
297
|
+
], c = At(t);
|
|
298
298
|
if (c) return s.find(([, e]) => {
|
|
299
|
-
let t =
|
|
299
|
+
let t = At(e);
|
|
300
300
|
return t?.length === c.length && t.every((e, t) => e === c[t]);
|
|
301
301
|
})?.[0];
|
|
302
|
-
},
|
|
302
|
+
}, Mt = (e) => {
|
|
303
303
|
if (e.length === 0) return;
|
|
304
304
|
let t = e.filter((e) => e.enabled);
|
|
305
305
|
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";
|
|
306
|
-
},
|
|
306
|
+
}, Nt = "framework_changes", Pt = "framework_changes_", Ft = (e, t) => t === "framework_changes" ? `${Pt}${e}` : `${Pt}${t}_${e}`, It = (e, t) => Rt(Ft(e, t).replace(/[A-Z]/g, (e) => e.toLowerCase())), Lt = 63, Rt = (e) => {
|
|
307
307
|
let t = new TextEncoder().encode(e);
|
|
308
|
-
return t.length <=
|
|
309
|
-
},
|
|
308
|
+
return t.length <= Lt ? e : new TextDecoder().decode(t.subarray(0, Lt)).replace(/�+$/u, "");
|
|
309
|
+
}, zt = (e) => e === "framework_changes" ? "framework_notify_change" : `framework_notify_change_${e}`, Bt = "voltro:notify:v2", Vt = (e, t) => {
|
|
310
310
|
if (e.type === "text" && e.generatedAs === void 0) {
|
|
311
311
|
if (e.maxLength !== void 0) return e.maxLength;
|
|
312
312
|
if (t || e.hasDefault && e.defaultFactory === void 0 || e.oneOf !== void 0 && e.oneOf.length > 0) return 450;
|
|
313
313
|
}
|
|
314
|
-
},
|
|
315
|
-
|
|
314
|
+
}, Ht = Ee({ scope: "voltro:migrate" }), F = (e) => {
|
|
315
|
+
Ht.warn(e.replace(/^\[voltro:migrate\]\s*/, ""));
|
|
316
316
|
}, I = (e, t) => {
|
|
317
317
|
let n = e.type;
|
|
318
318
|
if (e.spatial) {
|
|
@@ -331,7 +331,7 @@ var Ot = (e) => {
|
|
|
331
331
|
}, t)}[]`;
|
|
332
332
|
if (t === "mysql" || t === "mariadb") return "JSON";
|
|
333
333
|
if (t === "mssql") return "NVARCHAR(MAX)";
|
|
334
|
-
if (
|
|
334
|
+
if (k(t)) return "TEXT";
|
|
335
335
|
}
|
|
336
336
|
if (n === "vector") {
|
|
337
337
|
let n = e.vectorDim;
|
|
@@ -340,27 +340,27 @@ var Ot = (e) => {
|
|
|
340
340
|
if (t === "postgres") return r ? `HALFVEC(${n})` : `VECTOR(${n})`;
|
|
341
341
|
if (t === "mysql" || t === "mariadb") return `VECTOR(${n})`;
|
|
342
342
|
if (t === "mssql") return "VARBINARY(MAX)";
|
|
343
|
-
if (
|
|
343
|
+
if (k(t)) return "BLOB";
|
|
344
344
|
}
|
|
345
345
|
if (n === "interval") {
|
|
346
346
|
if (t === "postgres") return "INTERVAL";
|
|
347
347
|
if (t === "mysql" || t === "mariadb" || t === "mssql") return "BIGINT";
|
|
348
|
-
if (
|
|
348
|
+
if (k(t)) return "INTEGER";
|
|
349
349
|
}
|
|
350
350
|
if (n === "decimal") {
|
|
351
351
|
let n = e.precision, r = e.scale ?? 0;
|
|
352
352
|
if (n === void 0) throw Error("decimal column is missing its precision — this is a framework bug.");
|
|
353
|
-
return
|
|
353
|
+
return k(t) ? "NUMERIC" : t === "postgres" ? `NUMERIC(${n}, ${r})` : `DECIMAL(${n}, ${r})`;
|
|
354
354
|
}
|
|
355
|
-
if (n === "bigint") return
|
|
355
|
+
if (n === "bigint") return k(t) ? "INTEGER" : "BIGINT";
|
|
356
356
|
if (n === "enum") {
|
|
357
357
|
if (t === "postgres") return e.enumName ?? "TEXT";
|
|
358
358
|
if (t === "mysql" || t === "mariadb") return `ENUM(${(e.enumValues ?? []).map((e) => `'${e.replace(/'/g, "''")}'`).join(", ")})`;
|
|
359
359
|
if (t === "mssql") return "NVARCHAR(255)";
|
|
360
|
-
if (
|
|
360
|
+
if (k(t)) return "TEXT";
|
|
361
361
|
}
|
|
362
|
-
if (n === "text" && e.maxLength !== void 0 && e.generatedAs === void 0) return t === "mssql" ? `NVARCHAR(${e.maxLength})` :
|
|
363
|
-
if (
|
|
362
|
+
if (n === "text" && e.maxLength !== void 0 && e.generatedAs === void 0) return t === "mssql" ? `NVARCHAR(${e.maxLength})` : k(t) ? "TEXT" : `VARCHAR(${e.maxLength})`;
|
|
363
|
+
if (k(t)) switch (n) {
|
|
364
364
|
case "id": return "TEXT";
|
|
365
365
|
case "text": return "TEXT";
|
|
366
366
|
case "integer": return "INTEGER";
|
|
@@ -395,7 +395,7 @@ var Ot = (e) => {
|
|
|
395
395
|
if (t === "mssql") switch (n) {
|
|
396
396
|
case "id": return "NVARCHAR(64)";
|
|
397
397
|
case "text": {
|
|
398
|
-
let t =
|
|
398
|
+
let t = Vt(e, !1);
|
|
399
399
|
return t === void 0 ? "NVARCHAR(MAX)" : `NVARCHAR(${t})`;
|
|
400
400
|
}
|
|
401
401
|
case "integer": return "INT";
|
|
@@ -427,19 +427,19 @@ var Ot = (e) => {
|
|
|
427
427
|
case "array": return "TEXT[]";
|
|
428
428
|
case "interval": return "INTERVAL";
|
|
429
429
|
}
|
|
430
|
-
},
|
|
430
|
+
}, Ut = (e, t) => {
|
|
431
431
|
if (!e.hasDefault || e.defaultFactory !== void 0) return null;
|
|
432
432
|
let n = e.defaultValue;
|
|
433
|
-
return n === "now" ?
|
|
434
|
-
},
|
|
435
|
-
if (n !== "postgres" || t.type !== "array" || t.arrayElement === void 0) return
|
|
433
|
+
return n === "now" ? k(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) ? Wt(n, e, t) : typeof n == "object" && n ? L(n, t) : null;
|
|
434
|
+
}, Wt = (e, t, n) => {
|
|
435
|
+
if (n !== "postgres" || t.type !== "array" || t.arrayElement === void 0) return L(e, n);
|
|
436
436
|
let r = I({
|
|
437
437
|
...t,
|
|
438
438
|
type: t.arrayElement,
|
|
439
439
|
arrayElement: void 0
|
|
440
440
|
}, n);
|
|
441
441
|
return `DEFAULT '{${e.map((e) => typeof e == "number" || typeof e == "boolean" ? String(e) : `"${String(e).replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"`).join(",").replace(/'/g, "''")}}'::${r}[]`;
|
|
442
|
-
},
|
|
442
|
+
}, L = (e, t) => {
|
|
443
443
|
let n = JSON.stringify(e).replace(/'/g, "''");
|
|
444
444
|
return t === "postgres" ? `DEFAULT '${n}'::jsonb` : t === "mysql" || t === "mariadb" ? `DEFAULT (CONVERT('${n}' USING utf8mb4))` : `DEFAULT '${n}'`;
|
|
445
445
|
}, Gt = (e, t) => {
|
|
@@ -480,16 +480,16 @@ var Ot = (e) => {
|
|
|
480
480
|
return `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
|
|
481
481
|
}, Qt = (e, t, n, r, a = !1, o = !1) => {
|
|
482
482
|
if (t.type === "id" && t.idScheme?.kind === "numeric") return Gt(e, n);
|
|
483
|
-
let s = n === "mssql" ?
|
|
483
|
+
let s = n === "mssql" ? Vt(t, r?.has(e) ?? !1) : void 0, c = s === void 0 ? I(t, n) : `NVARCHAR(${s})`, l = [i(e, n), c];
|
|
484
484
|
t.type === "id" && !o && l.push("PRIMARY KEY");
|
|
485
485
|
let u = Zt(t, n);
|
|
486
486
|
if (u) l.push(u);
|
|
487
487
|
else {
|
|
488
488
|
t.nullable || l.push("NOT NULL"), t.unique && t.type !== "id" && !Yt(t, n) && l.push("UNIQUE");
|
|
489
|
-
let e =
|
|
489
|
+
let e = Ut(t, n);
|
|
490
490
|
e && l.push(e);
|
|
491
491
|
}
|
|
492
|
-
if (t.type === "reference" && t.references && !a && !
|
|
492
|
+
if (t.type === "reference" && t.references && !a && !ve(n)) {
|
|
493
493
|
let e = t.references();
|
|
494
494
|
l.push(`REFERENCES ${i(e.tableName, n)} (${i(t.referenceColumn ?? "id", n)})`);
|
|
495
495
|
let r = Kt(t.onDelete ?? "restrict", n);
|
|
@@ -502,18 +502,18 @@ var Ot = (e) => {
|
|
|
502
502
|
l.push(`CHECK (${i(e, n)} IN (${r}))`);
|
|
503
503
|
}
|
|
504
504
|
if (t.checks && t.checks.length > 0) for (let e of t.checks) l.push(`CHECK (${e})`);
|
|
505
|
-
if (t.type === "enum" && t.enumValues && t.enumValues.length > 0 && (n === "mssql" ||
|
|
505
|
+
if (t.type === "enum" && t.enumValues && t.enumValues.length > 0 && (n === "mssql" || k(n))) {
|
|
506
506
|
let r = t.enumValues.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
|
|
507
507
|
l.push(`CHECK (${i(e, n)} IN (${r}))`);
|
|
508
508
|
}
|
|
509
509
|
if (t.type === "json" || t.type === "array") {
|
|
510
510
|
let r = i(e, n);
|
|
511
|
-
|
|
511
|
+
k(n) ? l.push(`CHECK (${r} IS NULL OR json_valid(${r}))`) : n === "mssql" && l.push(t.type === "json" ? `CHECK ${kt(r)}` : `CHECK (${r} IS NULL OR ISJSON(${r}) = 1)`);
|
|
512
512
|
}
|
|
513
513
|
return l.join(" ");
|
|
514
514
|
}, $t = (e, t) => {
|
|
515
515
|
if (t.charset !== void 0) {
|
|
516
|
-
if (!
|
|
516
|
+
if (!ve(e)) throw Error(`store charset '${t.charset}' is declared for a ${e} store — a character set is a MySQL / MariaDB setting. Remove \`charset\` from \`store\` in app.config.ts, or declare \`store: { dialect: 'mysql' | 'mariadb', charset }\`.`);
|
|
517
517
|
return t.charset;
|
|
518
518
|
}
|
|
519
519
|
}, en = (e, t, n = null, r, a) => {
|
|
@@ -526,7 +526,7 @@ var Ot = (e) => {
|
|
|
526
526
|
let c = s.length > 0, l = Object.entries(e.fields).map(([e, n]) => ` ${Qt(e, n, t, o, r?.has(e) ?? !1, c)}`).join(",\n"), u = (e.appliedUniques ?? []).map((n) => {
|
|
527
527
|
let r = n.fields.map((n) => Xt(n, e.fields, t)).join(", ");
|
|
528
528
|
return ` CONSTRAINT ${i(n.name, t)} UNIQUE (${r})`;
|
|
529
|
-
}), d = (e.appliedChecks ?? []).map((e) => ` CONSTRAINT ${i(e.name, t)} CHECK (${e.expr})`), f = c ? [` PRIMARY KEY (${s.map((n) => Xt(n, e.fields, t)).join(", ")})`] : [], p =
|
|
529
|
+
}), d = (e.appliedChecks ?? []).map((e) => ` CONSTRAINT ${i(e.name, t)} CHECK (${e.expr})`), f = c ? [` PRIMARY KEY (${s.map((n) => Xt(n, e.fields, t)).join(", ")})`] : [], p = ve(t) ? Object.entries(e.fields).flatMap(([a, o]) => {
|
|
530
530
|
if (o.type !== "reference" || !o.references || (r?.has(a) ?? !1)) return [];
|
|
531
531
|
let s = o.references(), c = Kt(o.onDelete ?? "restrict", t), l = Kt(o.refOnUpdate ?? "noAction", t);
|
|
532
532
|
return [` CONSTRAINT ${i(`${e.tableName}_${a}_fkey`, t)} FOREIGN KEY (${i(a, t)}) REFERENCES ${qt(s.tableName, t, n)} (${i(o.referenceColumn ?? "id", t)}) ON DELETE ${c}${l === "NO ACTION" ? "" : ` ON UPDATE ${l}`}`];
|
|
@@ -543,14 +543,14 @@ var Ot = (e) => {
|
|
|
543
543
|
return [
|
|
544
544
|
`CREATE TABLE IF NOT EXISTS ${g} (`,
|
|
545
545
|
h,
|
|
546
|
-
`)${a !== void 0 &&
|
|
546
|
+
`)${a !== void 0 && ve(t) ? ` DEFAULT CHARACTER SET ${a}` : ""};`
|
|
547
547
|
].join("\n");
|
|
548
548
|
}, tn = (e, t, n) => {
|
|
549
549
|
let r = `${e}_${t.name}_fts`, a = (e) => i(e, n), o = t.columns.map(a).join(", "), s = t.columns.map((e) => `new.${a(e)}`).join(", "), c = [];
|
|
550
550
|
return c.push(`CREATE VIRTUAL TABLE IF NOT EXISTS ${a(r)} USING fts5(${o}, row_id UNINDEXED, tokenize='porter');`), c.push(`CREATE TRIGGER IF NOT EXISTS ${a(`${r}_ai`)} AFTER INSERT ON ${a(e)} BEGIN\n INSERT INTO ${a(r)} (${o}, row_id) VALUES (${s}, new.${a("id")});\nEND;`), c.push(`CREATE TRIGGER IF NOT EXISTS ${a(`${r}_ad`)} AFTER DELETE ON ${a(e)} BEGIN\n DELETE FROM ${a(r)} WHERE row_id = old.${a("id")};\nEND;`), c.push(`CREATE TRIGGER IF NOT EXISTS ${a(`${r}_au`)} AFTER UPDATE ON ${a(e)} BEGIN\n DELETE FROM ${a(r)} WHERE row_id = old.${a("id")};\n INSERT INTO ${a(r)} (${o}, row_id) VALUES (${s}, new.${a("id")});\nEND;`), c;
|
|
551
551
|
}, nn = (e, t, n = null) => {
|
|
552
552
|
let r = [], a = /* @__PURE__ */ new Set(), o = (e) => e.join("\0"), s = (e, n, r, i, a) => {
|
|
553
|
-
if (t === "postgres") return
|
|
553
|
+
if (t === "postgres") return Ne(r, i, a);
|
|
554
554
|
let o = {
|
|
555
555
|
using: "",
|
|
556
556
|
withSuffix: "",
|
|
@@ -614,17 +614,17 @@ var Ot = (e) => {
|
|
|
614
614
|
r.push(l(i, e.tableName, [t])), a.add(o([t]));
|
|
615
615
|
}
|
|
616
616
|
return r.join("\n");
|
|
617
|
-
}, rn = (e, t, n =
|
|
617
|
+
}, rn = (e, t, n = Nt) => {
|
|
618
618
|
if (t !== "postgres") return [];
|
|
619
619
|
let r = e.filter((e) => e.isReactive !== !1);
|
|
620
620
|
return r.length === 0 ? [] : [an(n), ...r.map((e) => sn(e, n))];
|
|
621
621
|
}, an = (e) => `
|
|
622
|
-
CREATE OR REPLACE FUNCTION ${
|
|
622
|
+
CREATE OR REPLACE FUNCTION ${zt(e)}() RETURNS trigger AS $$
|
|
623
623
|
DECLARE
|
|
624
624
|
payload TEXT;
|
|
625
625
|
pk JSONB;
|
|
626
626
|
BEGIN
|
|
627
|
-
-- ${
|
|
627
|
+
-- ${Bt}
|
|
628
628
|
payload := json_build_object(
|
|
629
629
|
'table', TG_TABLE_NAME,
|
|
630
630
|
-- The schema the write landed in. Under namespace isolation this is
|
|
@@ -679,25 +679,25 @@ BEGIN
|
|
|
679
679
|
END;
|
|
680
680
|
$$ LANGUAGE plpgsql;
|
|
681
681
|
`.trim(), on = (e, t) => {
|
|
682
|
-
let n =
|
|
682
|
+
let n = Ft(e.tableName, t);
|
|
683
683
|
return [
|
|
684
684
|
`ALTER TABLE "${e.tableName}" REPLICA IDENTITY FULL`,
|
|
685
685
|
`DROP TRIGGER IF EXISTS ${n} ON "${e.tableName}"`,
|
|
686
|
-
`CREATE TRIGGER ${n}\nAFTER INSERT OR UPDATE OR DELETE ON "${e.tableName}"\nFOR EACH ROW EXECUTE FUNCTION ${
|
|
686
|
+
`CREATE TRIGGER ${n}\nAFTER INSERT OR UPDATE OR DELETE ON "${e.tableName}"\nFOR EACH ROW EXECUTE FUNCTION ${zt(t)}()`
|
|
687
687
|
];
|
|
688
688
|
}, sn = (e, t) => on(e, t).map((e) => `${e};`).join("\n"), cn = (e) => {
|
|
689
689
|
if (e.dialect !== "postgres") return [];
|
|
690
690
|
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));
|
|
691
691
|
(i.length > 0 || e.functionOutdated === !0) && r.push(an(t));
|
|
692
692
|
for (let e of i) r.push(...on(n.get(e), t));
|
|
693
|
-
for (let n of e.stale) r.push(`DROP TRIGGER IF EXISTS ${
|
|
693
|
+
for (let n of e.stale) r.push(`DROP TRIGGER IF EXISTS ${Ft(n, t)} ON "${n}"`), r.push(`ALTER TABLE "${n}" REPLICA IDENTITY DEFAULT`);
|
|
694
694
|
return r;
|
|
695
695
|
}, ln = (e, t) => {
|
|
696
696
|
if (t !== "postgres") return;
|
|
697
697
|
let n = [];
|
|
698
698
|
return un(e) && n.push("CREATE EXTENSION IF NOT EXISTS vector;"), dn(e) && n.push("CREATE EXTENSION IF NOT EXISTS postgis;"), n.length === 0 ? void 0 : n.join("\n");
|
|
699
699
|
}, un = (e) => e.some((e) => Object.values(e.fields).some((e) => e.type === "vector")), dn = (e) => e.some((e) => Object.values(e.fields).some((e) => e.spatial !== void 0)), fn = (e) => {
|
|
700
|
-
let t = new Map(e.map((e) => [e.tableName, e])), n =
|
|
700
|
+
let t = new Map(e.map((e) => [e.tableName, e])), n = Ve(e.map((e) => e.tableName), (e) => {
|
|
701
701
|
let n = t.get(e);
|
|
702
702
|
return n ? Object.entries(n.fields).flatMap(([e, n]) => {
|
|
703
703
|
if (n.type !== "reference" || !n.references) return [];
|
|
@@ -751,7 +751,7 @@ $$ LANGUAGE plpgsql;
|
|
|
751
751
|
}
|
|
752
752
|
}, mn = (e, t) => {
|
|
753
753
|
let n = /* @__PURE__ */ new Map();
|
|
754
|
-
if (
|
|
754
|
+
if (k(t)) return n;
|
|
755
755
|
for (let t of e) {
|
|
756
756
|
let e = n.get(t.table) ?? /* @__PURE__ */ new Set();
|
|
757
757
|
e.add(t.column), n.set(t.table, e);
|
|
@@ -778,7 +778,7 @@ $$ LANGUAGE plpgsql;
|
|
|
778
778
|
let n = /* @__PURE__ */ new Set();
|
|
779
779
|
for (let t of e) for (let e of Object.values(t.fields)) e.type === "enum" && e.enumName && n.add(e.enumName);
|
|
780
780
|
let r = [];
|
|
781
|
-
for (let e of n) for (let { from: t, to: n } of
|
|
781
|
+
for (let e of n) for (let { from: t, to: n } of pe(e)) {
|
|
782
782
|
let i = e.replace(/'/g, "''"), a = t.replace(/'/g, "''"), o = n.replace(/'/g, "''");
|
|
783
783
|
r.push(`DO \$\$
|
|
784
784
|
DECLARE
|
|
@@ -789,26 +789,26 @@ BEGIN
|
|
|
789
789
|
return r.join("\n\n");
|
|
790
790
|
}, _n = (e) => {
|
|
791
791
|
let t = [], n = [];
|
|
792
|
-
for (let r of e)
|
|
792
|
+
for (let r of e) O(r) ? n.push(r) : t.push(r);
|
|
793
793
|
return {
|
|
794
794
|
tables: t,
|
|
795
795
|
views: n
|
|
796
796
|
};
|
|
797
|
-
}, vn = (e, t, n =
|
|
798
|
-
let i = $t(t, r), { tables: a, views: o } = _n(e), { sorted: s, cyclic: c } = fn(a.map((e) =>
|
|
797
|
+
}, vn = (e, t, n = Nt, r = {}) => {
|
|
798
|
+
let i = $t(t, r), { tables: a, views: o } = _n(e), { sorted: s, cyclic: c } = fn(a.map((e) => Be(e, t))), l = mn(c, t), u = [], d = ln(s, t);
|
|
799
799
|
d && u.push(d);
|
|
800
800
|
let f = gn(s, t);
|
|
801
801
|
f && u.push(f);
|
|
802
802
|
let p = hn(s, t);
|
|
803
803
|
p && u.push(p);
|
|
804
804
|
for (let e of s) u.push(en(e, t, null, l.get(e.tableName), i));
|
|
805
|
-
if (!
|
|
805
|
+
if (!k(t)) for (let e of c) u.push(pn(e, t));
|
|
806
806
|
for (let e of s) {
|
|
807
807
|
let n = nn(e, t);
|
|
808
808
|
n && u.push(n);
|
|
809
809
|
}
|
|
810
810
|
u.push(...rn(s, t, n));
|
|
811
|
-
for (let e of o) u.push(
|
|
811
|
+
for (let e of o) u.push(ie(e, t));
|
|
812
812
|
return u.join("\n\n") + "\n";
|
|
813
813
|
}, yn = (e, t, n, r) => {
|
|
814
814
|
let a = i(e, t);
|
|
@@ -825,13 +825,13 @@ BEGIN
|
|
|
825
825
|
if (t === "postgres") return `${s}\n\nSET search_path TO ${c};\n\n${vn(e, t)}`;
|
|
826
826
|
let { sorted: l, cyclic: u } = fn(e), d = mn(u, t), f = [s];
|
|
827
827
|
for (let e of l) f.push(en(e, t, n, d.get(e.tableName), o));
|
|
828
|
-
if (!
|
|
828
|
+
if (!k(t)) for (let e of u) f.push(pn(e, t, n));
|
|
829
829
|
for (let e of l) {
|
|
830
830
|
let r = nn(e, t, n);
|
|
831
831
|
r && f.push(r);
|
|
832
832
|
}
|
|
833
833
|
return f.join("\n\n") + "\n";
|
|
834
|
-
}, xn = (e, t, n =
|
|
834
|
+
}, xn = (e, t, n = Nt) => {
|
|
835
835
|
let { sorted: r, cyclic: i } = fn(e), a = mn(i, t), o = [], s = gn(r, t);
|
|
836
836
|
s && o.push(s);
|
|
837
837
|
let c = hn(r, t);
|
|
@@ -839,9 +839,9 @@ BEGIN
|
|
|
839
839
|
for (let e of r) o.push(en(e, t, null, a.get(e.tableName)));
|
|
840
840
|
for (let e of i) o.push(pn(e, t));
|
|
841
841
|
return o.push(...rn(r, t, n)), o.join("\n\n") + "\n";
|
|
842
|
-
}, Sn = (e, t = "postgres", n =
|
|
842
|
+
}, Sn = (e, t = "postgres", n = Nt, r = {}) => A.gen(function* () {
|
|
843
843
|
let i = yield* j.SqlClient;
|
|
844
|
-
yield*
|
|
844
|
+
yield* ht(i, kn(i, vn(e, t, n, { charset: r.charset }), t, r.retryFilter), { schema: r.lockSchema }).pipe(A.orDie);
|
|
845
845
|
}), Cn = (e, t) => {
|
|
846
846
|
let n = t.cause ?? {};
|
|
847
847
|
return (n.errno === 1061 || n.code === "ER_DUP_KEYNAME") && /^\s*CREATE\s+(UNIQUE\s+|FULLTEXT\s+)?INDEX\b/i.test(e);
|
|
@@ -854,7 +854,7 @@ BEGIN
|
|
|
854
854
|
}, En = (e) => ({
|
|
855
855
|
while: e,
|
|
856
856
|
times: Tn(),
|
|
857
|
-
schedule:
|
|
857
|
+
schedule: Ce.jittered(Ce.exponential("50 millis"))
|
|
858
858
|
}), Dn = class {
|
|
859
859
|
statement;
|
|
860
860
|
error;
|
|
@@ -863,17 +863,17 @@ BEGIN
|
|
|
863
863
|
this.statement = e, this.error = t;
|
|
864
864
|
}
|
|
865
865
|
}, On = (e, t, n) => A.gen(function* () {
|
|
866
|
-
let r = yield* j.SqlClient, i = n !== void 0 &&
|
|
866
|
+
let r = yield* j.SqlClient, i = n !== void 0 && _t(t) === "per-operation";
|
|
867
867
|
for (let a of An(e)) {
|
|
868
|
-
process.env.VOLTRO_MIGRATE_DEBUG === "1" &&
|
|
868
|
+
process.env.VOLTRO_MIGRATE_DEBUG === "1" && Ht.debug(`EXEC: ${a.replace(/\s+/g, " ").slice(0, 180)}`);
|
|
869
869
|
let e = r.unsafe(a).pipe(A.catchIf((e) => Cn(a, e), () => A.succeed([])), A.tapError((e) => A.sync(() => {
|
|
870
|
-
|
|
870
|
+
Ht.error(Pe("migrate: statement failed", a, e, 200));
|
|
871
871
|
})));
|
|
872
872
|
yield* (i && n !== void 0 && wn(a, t) ? e.pipe(A.retry(En((e) => n(e) === "retry"))) : e).pipe(A.mapError((e) => new Dn(a, e)));
|
|
873
873
|
}
|
|
874
874
|
}), kn = (e, t, n, r) => {
|
|
875
875
|
let i = n === "turso" ? On(t, n, r) : e.withTransaction(On(t, n, r)), a = (e) => e instanceof Dn ? e.error : e;
|
|
876
|
-
return (r !== void 0 &&
|
|
876
|
+
return (r !== void 0 && _t(n) === "plan-transactional" ? i.pipe(A.retry(En((e) => r(a(e)) === "retry"))) : i).pipe(A.orDieWith((e) => e instanceof Dn ? Error(Pe("migrate: statement failed", e.statement, e.error, 400).trim()) : e));
|
|
877
877
|
}, An = (e) => {
|
|
878
878
|
let t = [], n = "", r = !1;
|
|
879
879
|
for (let i = 0; i < e.length; i++) {
|
|
@@ -893,16 +893,16 @@ BEGIN
|
|
|
893
893
|
await A.runPromise(Sn(e, n, void 0, r).pipe(A.provide(t)));
|
|
894
894
|
}, Mn = (e, t, n = "postgres", r = {}) => A.gen(function* () {
|
|
895
895
|
let i = bn(e, n, t, void 0, { charset: r.charset }), a = yield* j.SqlClient;
|
|
896
|
-
yield*
|
|
896
|
+
yield* ht(a, kn(a, i, n, r.retryFilter), { schema: r.lockSchema }).pipe(A.orDie);
|
|
897
897
|
}), Nn = async (e, t, n, r = "postgres", i = {}) => {
|
|
898
|
-
await A.runPromise(Mn(e, t, r, i).pipe(A.provide(n))), await
|
|
898
|
+
await A.runPromise(Mn(e, t, r, i).pipe(A.provide(n))), await re({
|
|
899
899
|
namespace: t,
|
|
900
900
|
dialect: r
|
|
901
901
|
});
|
|
902
902
|
}, Pn = async (e, t, n = "postgres", r = {}) => {
|
|
903
903
|
await A.runPromise(A.gen(function* () {
|
|
904
904
|
let t = xn(e, n), i = yield* j.SqlClient;
|
|
905
|
-
yield*
|
|
905
|
+
yield* ht(i, kn(i, t, n, r.retryFilter), { schema: r.lockSchema }).pipe(A.orDie);
|
|
906
906
|
}).pipe(A.provide(t)));
|
|
907
907
|
}, Fn = /'(?:''|[^'])*'|"(?:""|[^"])*"|\[(?:\]\]|[^\]])*\]|`(?:``|[^`])*`|[A-Za-z_][A-Za-z_0-9$]*|\d+(?:\.\d+)?|::|<>|!=|<=|>=|\|\||[^\s]/g, In = (e) => {
|
|
908
908
|
let t = 0;
|
|
@@ -972,7 +972,7 @@ BEGIN
|
|
|
972
972
|
}, Xn = (e) => {
|
|
973
973
|
let { kind: t, kindOptions: n, ...r } = e, i = {
|
|
974
974
|
...r,
|
|
975
|
-
...
|
|
975
|
+
...Me(t, n),
|
|
976
976
|
...e.where === void 0 ? {} : { where: Ln(e.where) }
|
|
977
977
|
};
|
|
978
978
|
return e.expression ? {
|
|
@@ -1018,7 +1018,7 @@ BEGIN
|
|
|
1018
1018
|
};
|
|
1019
1019
|
}, nr = (e, t, n) => {
|
|
1020
1020
|
if (t === "mssql") {
|
|
1021
|
-
let t =
|
|
1021
|
+
let t = Vt(e, n);
|
|
1022
1022
|
if (t !== void 0) return t;
|
|
1023
1023
|
}
|
|
1024
1024
|
try {
|
|
@@ -1059,13 +1059,13 @@ BEGIN
|
|
|
1059
1059
|
...t.spatial === void 0 ? {} : { spatial: Jn(t.spatial) },
|
|
1060
1060
|
...t.enumValues === void 0 ? {} : { enumValues: [...t.enumValues].sort() }
|
|
1061
1061
|
};
|
|
1062
|
-
}, or = (e) => e.columns.filter((e) => !
|
|
1062
|
+
}, or = (e) => e.columns.filter((e) => !ne(e.name)).map((t) => ar(Gn(t, Rn(e, t)))).sort((e, t) => e.name.localeCompare(t.name)), sr = (e) => [...e].map(Xn).sort((e, t) => e.name.localeCompare(t.name)), cr = (e) => [...e].filter((e) => !ne(e.name)).map((e) => ({
|
|
1063
1063
|
name: e.name,
|
|
1064
1064
|
columns: or(e),
|
|
1065
1065
|
indexes: sr(e.indexes)
|
|
1066
|
-
})).sort((e, t) => e.name.localeCompare(t.name)),
|
|
1066
|
+
})).sort((e, t) => e.name.localeCompare(t.name)), R = (e) => {
|
|
1067
1067
|
let t = { tables: cr(e.tables) }, n = JSON.stringify(rr(t));
|
|
1068
|
-
return
|
|
1068
|
+
return Te("sha256").update(n).digest("hex");
|
|
1069
1069
|
}, lr = (e) => e.slice(0, 16), ur = ["utf8mb3", "utf8mb4"], dr = (e) => e === "utf8mb3" || e === "utf8mb4", fr = (e) => {
|
|
1070
1070
|
switch (e.type) {
|
|
1071
1071
|
case "text":
|
|
@@ -1084,10 +1084,10 @@ BEGIN
|
|
|
1084
1084
|
column: e.name,
|
|
1085
1085
|
charset: e.charset
|
|
1086
1086
|
}]), hr = "utf8mb4", gr = (e) => e.columns.some((e) => e.type === "json" || e.type === "array" || e.storageType === "json"), _r = (e) => {
|
|
1087
|
-
if (!
|
|
1087
|
+
if (!ve(e.dialect)) return [];
|
|
1088
1088
|
let t = [];
|
|
1089
1089
|
for (let n of [...e.live.tables].sort((e, t) => e.name.localeCompare(t.name))) {
|
|
1090
|
-
if (
|
|
1090
|
+
if (ne(n.name)) continue;
|
|
1091
1091
|
let r = mr(n);
|
|
1092
1092
|
if (r.length === 0) continue;
|
|
1093
1093
|
if (e.charset !== void 0) {
|
|
@@ -1186,15 +1186,15 @@ BEGIN
|
|
|
1186
1186
|
});
|
|
1187
1187
|
let s = e.appliedIndexes ?? [];
|
|
1188
1188
|
for (let n of s) {
|
|
1189
|
-
let r =
|
|
1189
|
+
let r = je(n.kind, t);
|
|
1190
1190
|
if (r === null) continue;
|
|
1191
|
-
let i = n.fields[0], o = typeof i == "string" ? e.fields[i]?.vectorPrecision : void 0, s = r === "hnsw" ? { hnsw:
|
|
1191
|
+
let i = n.fields[0], o = typeof i == "string" ? e.fields[i]?.vectorPrecision : void 0, s = r === "hnsw" ? { hnsw: Ae(n.kindOptions, o) } : void 0, c = n.fields.map((e) => typeof e == "string" ? e : "jsonPath" in e ? `(json:${e.jsonPath.column}->${e.jsonPath.path.join(".")}${e.jsonPath.numeric ? "::num" : ""})` : `(${e.expr})`), l = n.fields.some((e) => typeof e != "string");
|
|
1192
1192
|
a({
|
|
1193
1193
|
name: n.name,
|
|
1194
1194
|
table: e.tableName,
|
|
1195
1195
|
columns: c,
|
|
1196
1196
|
unique: n.unique ?? !1,
|
|
1197
|
-
...
|
|
1197
|
+
...Me(r, s),
|
|
1198
1198
|
...n.where === void 0 ? {} : { where: n.where },
|
|
1199
1199
|
...l ? { expression: !0 } : {}
|
|
1200
1200
|
});
|
|
@@ -1247,7 +1247,7 @@ BEGIN
|
|
|
1247
1247
|
}
|
|
1248
1248
|
}, wr = (e, t, n = {}) => {
|
|
1249
1249
|
if (n.charset !== void 0 && t !== "mysql" && t !== "mariadb") throw Error(`store charset '${n.charset}' is declared for a ${t ?? "dialect-less"} store — a character set is a MySQL / MariaDB setting. Remove \`charset\` from \`store\` in app.config.ts, or declare \`store: { dialect: 'mysql' | 'mariadb', charset }\`.`);
|
|
1250
|
-
let r = e.filter((e) => !c(e.tableName)).map((e) => Sr(
|
|
1250
|
+
let r = e.filter((e) => !c(e.tableName)).map((e) => Sr(Be(e, t), t));
|
|
1251
1251
|
if (t === "mysql" || t === "mariadb") {
|
|
1252
1252
|
for (let e of r) 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.`);
|
|
1253
1253
|
}
|
|
@@ -1262,7 +1262,7 @@ BEGIN
|
|
|
1262
1262
|
if (t === "mssql" && !e.generatedAs && (e.type === "json" || e.type === "array") && (e = {
|
|
1263
1263
|
...e,
|
|
1264
1264
|
jsonValidation: e.type === "json" ? "value" : "container"
|
|
1265
|
-
}),
|
|
1265
|
+
}), k(t)) {
|
|
1266
1266
|
if (e.maxLength === void 0) return e;
|
|
1267
1267
|
let { maxLength: t, ...n } = e;
|
|
1268
1268
|
return n;
|
|
@@ -1275,13 +1275,13 @@ BEGIN
|
|
|
1275
1275
|
};
|
|
1276
1276
|
})
|
|
1277
1277
|
};
|
|
1278
|
-
}, Er = (e, t, n =
|
|
1278
|
+
}, Er = (e, t, n = Nt) => A.gen(function* () {
|
|
1279
1279
|
let r = (yield* e`
|
|
1280
1280
|
SELECT p.prosrc
|
|
1281
1281
|
FROM pg_proc p
|
|
1282
1282
|
JOIN pg_namespace n ON n.oid = p.pronamespace
|
|
1283
1283
|
WHERE n.nspname = current_schema()
|
|
1284
|
-
AND p.proname = ${
|
|
1284
|
+
AND p.proname = ${zt(n)}
|
|
1285
1285
|
`)[0]?.prosrc, i = r !== void 0 && !r.includes("voltro:notify:v2"), a = (yield* e`SELECT current_schema() AS schema`)[0]?.schema ?? "", o = t.filter((e) => !e.tableName.startsWith("_voltro_"));
|
|
1286
1286
|
if (o.length === 0) return {
|
|
1287
1287
|
missing: [],
|
|
@@ -1300,10 +1300,10 @@ BEGIN
|
|
|
1300
1300
|
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
1301
1301
|
WHERE NOT t.tgisinternal
|
|
1302
1302
|
AND n.nspname = current_schema()
|
|
1303
|
-
AND t.tgname LIKE ${`${
|
|
1303
|
+
AND t.tgname LIKE ${`${Pt}%`}
|
|
1304
1304
|
`, c = (e, t) => `${e}\u0000${t}`, l = new Set(s.map((e) => c(e.relname, e.tgname))), u = [], d = [];
|
|
1305
1305
|
for (let e of o) {
|
|
1306
|
-
let t = l.has(c(e.tableName,
|
|
1306
|
+
let t = l.has(c(e.tableName, It(e.tableName, n))), r = e.isReactive !== !1;
|
|
1307
1307
|
r && !t && u.push(e.tableName), !r && t && d.push(e.tableName);
|
|
1308
1308
|
}
|
|
1309
1309
|
return {
|
|
@@ -1320,7 +1320,7 @@ BEGIN
|
|
|
1320
1320
|
let t = [];
|
|
1321
1321
|
if (e.missing.length > 0) {
|
|
1322
1322
|
let n = e.missing.slice(0, 8).join(", "), r = e.missing.length > 8 ? `, … (+${e.missing.length - 8})` : "";
|
|
1323
|
-
t.push(`${e.missing.length} reactive table(s) have NO change trigger in the database — ${n}${r}. Writes to them will not reach another instance's subscribers; a single instance is unaffected, which is why this stays invisible until you scale out. Run \`voltro db apply\` to install them.` + (e.compared === void 0 ? "" : ` (compared against ${e.compared.present} \`${
|
|
1323
|
+
t.push(`${e.missing.length} reactive table(s) have NO change trigger in the database — ${n}${r}. Writes to them will not reach another instance's subscribers; a single instance is unaffected, which is why this stays invisible until you scale out. Run \`voltro db apply\` to install them.` + (e.compared === void 0 ? "" : ` (compared against ${e.compared.present} \`${Pt}*\` trigger(s) present in schema "${e.compared.schema}", channel "${e.compared.channel}")`));
|
|
1324
1324
|
}
|
|
1325
1325
|
if (e.stale.length > 0) {
|
|
1326
1326
|
let n = e.stale.slice(0, 8).join(", ");
|
|
@@ -1371,12 +1371,12 @@ BEGIN
|
|
|
1371
1371
|
if (!n || !r || n.length !== r.length) return !1;
|
|
1372
1372
|
let i = [...n].sort(), a = [...r].sort();
|
|
1373
1373
|
return i.every((e, t) => e === a[t]);
|
|
1374
|
-
}, Pr = (e, t, n, r) => n === void 0 ||
|
|
1374
|
+
}, Pr = (e, t, n, r) => n === void 0 || k(n) ? !0 : e.type !== "text" || !Wn(t) || nr(e, n, r) === t.maxLength, Fr = (e, t, n, r, i = !1) => (!qn(e) || e.type === t.type || Kn(e, t, i)) && Gn(e, i).idStorage === Gn(t, !1).idStorage && e.nullable === t.nullable && (e.unique === t.unique || Kn(e, t, i)) && e.jsonValidation === t.jsonValidation && (t.enumValues === void 0 || e.enumValues === void 0 || e.enumValues.length === t.enumValues.length && e.enumValues.every((e) => t.enumValues.includes(e))) && (t.precision === void 0 || e.precision === t.precision && (e.scale ?? 0) === (t.scale ?? 0)) && Yn(e.spatial, t.spatial) && (e.storageType !== void 0 || t.storageType !== void 0 || t.arrayElement === void 0 || e.arrayElement === void 0 || e.arrayElement === t.arrayElement) && (t.vectorDim === void 0 || e.vectorDim === t.vectorDim) && (e.vectorPrecision ?? "float32") === (t.vectorPrecision ?? "float32") && Mr(e, t) && Pr(e, t, n, r) && (e.type !== "reference" || (e.referenceStorage ?? "text") === (t.referenceStorage ?? "text")) && JSON.stringify(tr(e.references)) === JSON.stringify(tr(t.references)) && Nr(e.oneOf, t.oneOf), Ir = (e, t) => t.oneOf && t.oneOf.length > 0 ? z({
|
|
1375
1375
|
kind: "add-check",
|
|
1376
1376
|
table: e,
|
|
1377
1377
|
column: t.name,
|
|
1378
1378
|
values: t.oneOf
|
|
1379
|
-
}, "safe", `enum-membership CHECK on ${e}.${t.name}`) : void 0, Lr = (e, t) => e.unique === t.unique && e.valid !== !1 && t.valid !== !1 && Ln(e.where) === Ln(t.where) && JSON.stringify(
|
|
1379
|
+
}, "safe", `enum-membership CHECK on ${e}.${t.name}`) : void 0, Lr = (e, t) => e.unique === t.unique && e.valid !== !1 && t.valid !== !1 && Ln(e.where) === Ln(t.where) && JSON.stringify(Me(e.kind, e.kindOptions)) === JSON.stringify(Me(t.kind, t.kindOptions)) && (e.expression ?? !1) === (t.expression ?? !1) && (e.expression === !0 && t.expression === !0 || e.columns.length === t.columns.length && e.columns.every((e, n) => e === t.columns[n])), Rr = (e, t, n) => {
|
|
1380
1380
|
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));
|
|
1381
1381
|
for (let t of e.columns) {
|
|
1382
1382
|
let i = r.get(t.name);
|
|
@@ -1409,7 +1409,7 @@ BEGIN
|
|
|
1409
1409
|
added: o,
|
|
1410
1410
|
removed: s
|
|
1411
1411
|
};
|
|
1412
|
-
},
|
|
1412
|
+
}, z = (e, t, n, r) => ({
|
|
1413
1413
|
op: e,
|
|
1414
1414
|
classification: t,
|
|
1415
1415
|
atomicByDialect: Ar(e.kind),
|
|
@@ -1421,21 +1421,21 @@ BEGIN
|
|
|
1421
1421
|
table: e,
|
|
1422
1422
|
column: t
|
|
1423
1423
|
};
|
|
1424
|
-
return t.nullable ?
|
|
1424
|
+
return t.nullable ? z(r, "safe", "nullable column add — no backfill needed") : t.hasDefault && t.defaultValue !== void 0 ? z(r, "needs-default", "NOT NULL with literal default — DDL DEFAULT will populate existing rows") : n?.backfill ? z(r, "needs-backfill", `backfill declared (kind=${n.backfill.kind}) — applier will run 3-step add/update/set-not-null`) : z(r, "needs-backfill", "NOT NULL column on a table whose row count is unknown", { fix: `declare \`${t.name}: <type>().backfill(sql\`...\`)\` OR \`.default(value)\` so existing rows survive the migration` });
|
|
1425
1425
|
}, Vr = (e, t, n) => {
|
|
1426
1426
|
let r = {
|
|
1427
1427
|
kind: "drop-column",
|
|
1428
1428
|
table: e,
|
|
1429
1429
|
column: t.name
|
|
1430
1430
|
};
|
|
1431
|
-
return n?.dropped ?
|
|
1432
|
-
}, Hr = (e, t, n, r, i) =>
|
|
1431
|
+
return n?.dropped ? z(r, "lossy", `column dropped via \`${t.name}: dropped()\` marker — intentional`) : z(r, "lossy", "column missing from declared schema", { fix: `if intentional, add \`${t.name}: dropped()\` to the schema. If a typo, restore the field` });
|
|
1432
|
+
}, Hr = (e, t, n, r, i) => z({
|
|
1433
1433
|
kind: "create-table",
|
|
1434
1434
|
table: e,
|
|
1435
1435
|
columns: t,
|
|
1436
1436
|
indexes: n,
|
|
1437
1437
|
...r && r.length > 0 ? { primaryKey: r } : {}
|
|
1438
|
-
}, "safe", i ?? "new table — no data to preserve"), Ur = (e) =>
|
|
1438
|
+
}, "safe", i ?? "new table — no data to preserve"), Ur = (e) => z({
|
|
1439
1439
|
kind: "drop-table",
|
|
1440
1440
|
table: e
|
|
1441
1441
|
}, "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" }), Wr = 5e4, Gr = (e, t, n, r) => {
|
|
@@ -1453,12 +1453,12 @@ BEGIN
|
|
|
1453
1453
|
table: e,
|
|
1454
1454
|
name: t.name,
|
|
1455
1455
|
fields: t.columns
|
|
1456
|
-
}, i ?
|
|
1457
|
-
}, Kr = (e, t) => t.unique && t.where === void 0 && t.columns.length > 1 ?
|
|
1456
|
+
}, i ? z(a, "online-required", `online build on ${n} rows — CONCURRENTLY / INPLACE / WITH(ONLINE=ON) depending on dialect`) : z(a, "safe", t.where === void 0 ? t.unique ? t.columns.length === 1 ? "add unique constraint" : "add composite UNIQUE constraint" : `add ${t.kind === void 0 || t.kind === "btree" ? "B-tree" : t.kind.toUpperCase()} index` : `add ${t.unique ? "unique " : ""}partial index`);
|
|
1457
|
+
}, Kr = (e, t) => t.unique && t.where === void 0 && t.columns.length > 1 ? z({
|
|
1458
1458
|
kind: "drop-unique-composite",
|
|
1459
1459
|
table: e,
|
|
1460
1460
|
name: t.name
|
|
1461
|
-
}, "safe", "drop composite UNIQUE constraint (no data loss — constraint is derived metadata)") :
|
|
1461
|
+
}, "safe", "drop composite UNIQUE constraint (no data loss — constraint is derived metadata)") : z({
|
|
1462
1462
|
kind: "drop-index",
|
|
1463
1463
|
table: e,
|
|
1464
1464
|
index: t.name
|
|
@@ -1466,7 +1466,7 @@ BEGIN
|
|
|
1466
1466
|
let n = e.type;
|
|
1467
1467
|
if (n === "id") return Un(e) === "numeric" ? "bigint" : "text";
|
|
1468
1468
|
if (n === "array") return t === void 0 || t === "postgres" ? "array" : t === "mysql" || t === "mariadb" ? "json" : "text";
|
|
1469
|
-
if (n === "enum") return t === "mssql" ||
|
|
1469
|
+
if (n === "enum") return t === "mssql" || k(t ?? "postgres") ? "text" : "enum";
|
|
1470
1470
|
if (n === "reference") return e.referenceStorage === "numeric" ? "bigint" : "text";
|
|
1471
1471
|
switch (t) {
|
|
1472
1472
|
case "sqlite":
|
|
@@ -1486,7 +1486,7 @@ BEGIN
|
|
|
1486
1486
|
column: t.name,
|
|
1487
1487
|
toNullable: t.nullable
|
|
1488
1488
|
};
|
|
1489
|
-
o.push(t.nullable ?
|
|
1489
|
+
o.push(t.nullable ? z(n, "safe", `loosen ${e}.${t.name} to nullable`) : z(n, "needs-backfill", `tighten ${e}.${t.name} to NOT NULL — existing rows must already be non-null`));
|
|
1490
1490
|
}
|
|
1491
1491
|
if (t.unique !== n.unique) {
|
|
1492
1492
|
if (t.unique) {
|
|
@@ -1495,8 +1495,8 @@ BEGIN
|
|
|
1495
1495
|
table: e,
|
|
1496
1496
|
column: t.name
|
|
1497
1497
|
}, r = (i ?? 0) >= a;
|
|
1498
|
-
o.push(r ?
|
|
1499
|
-
} else o.push(
|
|
1498
|
+
o.push(r ? z(n, "online-required", `online unique build on ${i} rows — CONCURRENTLY / INPLACE / WITH(ONLINE=ON) depending on dialect`) : z(n, "safe", `add unique constraint on ${e}.${t.name} — existing rows must already be distinct (else the DB rejects at migrate)`));
|
|
1499
|
+
} else o.push(z({
|
|
1500
1500
|
kind: "drop-unique",
|
|
1501
1501
|
table: e,
|
|
1502
1502
|
column: t.name
|
|
@@ -1513,7 +1513,7 @@ BEGIN
|
|
|
1513
1513
|
to: t.type,
|
|
1514
1514
|
...i.using === void 0 ? {} : { using: i.using }
|
|
1515
1515
|
};
|
|
1516
|
-
o.push(
|
|
1516
|
+
o.push(z(r, "needs-backfill", `type change ${n.type} → ${t.type} on ${e}.${t.name} — narrowedFrom('${i.from}') declared` + (i.using ? ` with USING ${i.using}` : " (implicit cast)")));
|
|
1517
1517
|
} else {
|
|
1518
1518
|
let i = {
|
|
1519
1519
|
kind: "alter-column-type",
|
|
@@ -1522,12 +1522,12 @@ BEGIN
|
|
|
1522
1522
|
from: n.type,
|
|
1523
1523
|
to: t.type
|
|
1524
1524
|
};
|
|
1525
|
-
o.push(
|
|
1525
|
+
o.push(z(i, "lossy", `type change ${n.type} → ${t.type} on ${e}.${t.name} may not be value-preserving`, { fix: Jr(n.type, t, r) }));
|
|
1526
1526
|
}
|
|
1527
1527
|
}
|
|
1528
|
-
if (t.type === "text" && Wn(n) && !
|
|
1528
|
+
if (t.type === "text" && Wn(n) && !k(r ?? "postgres") && t.maxLength !== n.maxLength) {
|
|
1529
1529
|
let r = t.maxLength === void 0 || n.maxLength !== void 0 && t.maxLength > n.maxLength, i = n.maxLength === void 0 ? "unbounded" : `varchar(${n.maxLength})`, a = t.maxLength === void 0 ? "unbounded" : `varchar(${t.maxLength})`;
|
|
1530
|
-
o.push(
|
|
1530
|
+
o.push(z({
|
|
1531
1531
|
kind: "alter-column-type",
|
|
1532
1532
|
table: e,
|
|
1533
1533
|
column: t.name,
|
|
@@ -1538,7 +1538,7 @@ BEGIN
|
|
|
1538
1538
|
if (t.type === "enum" && n.type === "enum" && n.enumValues !== void 0 && t.enumValues !== void 0) {
|
|
1539
1539
|
let r = new Set(n.enumValues);
|
|
1540
1540
|
new Set(t.enumValues);
|
|
1541
|
-
for (let n of t.enumValues) r.has(n) || o.push(
|
|
1541
|
+
for (let n of t.enumValues) r.has(n) || o.push(z({
|
|
1542
1542
|
kind: "add-enum-value",
|
|
1543
1543
|
table: e,
|
|
1544
1544
|
column: t.name,
|
|
@@ -1548,7 +1548,7 @@ BEGIN
|
|
|
1548
1548
|
}
|
|
1549
1549
|
if (!Yn(t.spatial, n.spatial)) {
|
|
1550
1550
|
let r = t.spatial, i = n.spatial, a = (e) => e === void 0 ? "plain text" : `${e.kind}(${e.geomKind},${String(e.srid)})`, s = r !== void 0 && i !== void 0 && r.kind === i.kind && r.geomKind.toUpperCase() === i.geomKind.toUpperCase() && r.srid !== i.srid, c = r === void 0 ? void 0 : r.kind === "geography" ? `ST_Transform("${t.name}"::geometry, ${String(r.srid)})::geography` : `ST_Transform("${t.name}", ${String(r.srid)})`, l = t.narrowedFrom, u = l !== void 0 && l.from === n.type, d = s ? c : u ? l.using : void 0;
|
|
1551
|
-
o.push(
|
|
1551
|
+
o.push(z({
|
|
1552
1552
|
kind: "alter-column-type",
|
|
1553
1553
|
table: e,
|
|
1554
1554
|
column: t.name,
|
|
@@ -1559,7 +1559,7 @@ BEGIN
|
|
|
1559
1559
|
}
|
|
1560
1560
|
if (t.type === "array" && n.type === "array" && n.arrayElement !== void 0 && t.arrayElement !== void 0 && t.arrayElement !== n.arrayElement) {
|
|
1561
1561
|
let r = t.narrowedFrom, i = r !== void 0 && r.from === n.type;
|
|
1562
|
-
o.push(
|
|
1562
|
+
o.push(z({
|
|
1563
1563
|
kind: "alter-column-type",
|
|
1564
1564
|
table: e,
|
|
1565
1565
|
column: t.name,
|
|
@@ -1570,7 +1570,7 @@ BEGIN
|
|
|
1570
1570
|
}
|
|
1571
1571
|
if (t.type === "vector" && n.type === "vector" && (n.vectorDim !== void 0 && t.vectorDim !== n.vectorDim || (t.vectorPrecision ?? "float32") !== (n.vectorPrecision ?? "float32"))) {
|
|
1572
1572
|
let r = (e) => `${e.vectorPrecision === "half" ? "halfvec" : "vector"}(${String(e.vectorDim ?? "?")})`, i = t.narrowedFrom, a = i !== void 0 && i.from === n.type;
|
|
1573
|
-
o.push(
|
|
1573
|
+
o.push(z({
|
|
1574
1574
|
kind: "alter-column-type",
|
|
1575
1575
|
table: e,
|
|
1576
1576
|
column: t.name,
|
|
@@ -1581,7 +1581,7 @@ BEGIN
|
|
|
1581
1581
|
}
|
|
1582
1582
|
if (t.type === "decimal" && n.type === "decimal" && n.precision !== void 0 && (t.precision !== n.precision || (t.scale ?? 0) !== (n.scale ?? 0))) {
|
|
1583
1583
|
let r = (e) => `${String(e.precision)},${String(e.scale ?? 0)}`, i = t.precision !== void 0 && n.precision !== void 0 && t.precision - (t.scale ?? 0) >= n.precision - (n.scale ?? 0) && (t.scale ?? 0) >= (n.scale ?? 0);
|
|
1584
|
-
o.push(
|
|
1584
|
+
o.push(z({
|
|
1585
1585
|
kind: "alter-column-type",
|
|
1586
1586
|
table: e,
|
|
1587
1587
|
column: t.name,
|
|
@@ -1597,11 +1597,11 @@ BEGIN
|
|
|
1597
1597
|
hasDefault: t.hasDefault,
|
|
1598
1598
|
...t.defaultValue === void 0 ? {} : { defaultValue: t.defaultValue }
|
|
1599
1599
|
};
|
|
1600
|
-
o.push(
|
|
1600
|
+
o.push(z(n, "safe", `default change on ${e}.${t.name} affects only future inserts`));
|
|
1601
1601
|
}
|
|
1602
1602
|
if (r === "mssql" && t.jsonValidation !== void 0 && t.jsonValidation !== "unverified" && t.jsonValidation !== n.jsonValidation) {
|
|
1603
1603
|
let r = t.jsonValidation === "value" && n.jsonValidation === "container";
|
|
1604
|
-
o.push(
|
|
1604
|
+
o.push(z({
|
|
1605
1605
|
kind: "reconcile-json-check",
|
|
1606
1606
|
table: e,
|
|
1607
1607
|
column: t.name,
|
|
@@ -1611,7 +1611,7 @@ BEGIN
|
|
|
1611
1611
|
}, 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`));
|
|
1612
1612
|
}
|
|
1613
1613
|
if (!Nr(t.oneOf, n.oneOf)) {
|
|
1614
|
-
n.oneOf && n.oneOf.length > 0 && o.push(
|
|
1614
|
+
n.oneOf && n.oneOf.length > 0 && o.push(z({
|
|
1615
1615
|
kind: "drop-check",
|
|
1616
1616
|
table: e,
|
|
1617
1617
|
column: t.name
|
|
@@ -1619,7 +1619,7 @@ BEGIN
|
|
|
1619
1619
|
let r = Ir(e, t);
|
|
1620
1620
|
r && o.push(r);
|
|
1621
1621
|
}
|
|
1622
|
-
return JSON.stringify(tr(t.references)) !== JSON.stringify(tr(n.references)) && (n.references && o.push(
|
|
1622
|
+
return JSON.stringify(tr(t.references)) !== JSON.stringify(tr(n.references)) && (n.references && o.push(z({
|
|
1623
1623
|
kind: "drop-foreign-key",
|
|
1624
1624
|
table: e,
|
|
1625
1625
|
column: t.name
|
|
@@ -1636,15 +1636,15 @@ BEGIN
|
|
|
1636
1636
|
...t.references.onDelete ? { onDelete: t.references.onDelete } : {},
|
|
1637
1637
|
...t.references.onUpdate ? { onUpdate: t.references.onUpdate } : {}
|
|
1638
1638
|
};
|
|
1639
|
-
return i === "null" && !t.nullable ? n.push(
|
|
1639
|
+
return i === "null" && !t.nullable ? n.push(z(a, "lossy", `add FK ${e}.${t.name} → ${r}: orphanPolicy 'null' needs a nullable column (the NULL-out would violate NOT NULL)`, { fix: `make ${t.name} \`.nullable()\`, OR use \`orphanPolicy: 'delete'\`, OR clean the orphans and drop the policy` })) : i === "null" || i === "delete" ? n.push(z({
|
|
1640
1640
|
...a,
|
|
1641
1641
|
orphanPolicy: i
|
|
1642
|
-
}, "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(
|
|
1642
|
+
}, "lossy", i === "delete" ? `add FK ${e}.${t.name} → ${r}: orphanPolicy 'delete' first DELETES rows whose ${t.name} points at a missing ${r}` : `add FK ${e}.${t.name} → ${r}: orphanPolicy 'null' first NULLs ${t.name} where it points at a missing ${r}`)) : n.push(z(a, "needs-backfill", `add FK ${e}.${t.name} → ${r} — existing rows must already reference a valid ${r} (else set orphanPolicy:'null'/'delete')`)), n;
|
|
1643
1643
|
}, Zr = (e, t, n) => {
|
|
1644
1644
|
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));
|
|
1645
1645
|
for (let [n, c] of Object.entries(t)) {
|
|
1646
1646
|
let t = c.renamedFrom;
|
|
1647
|
-
t && o.has(t) && s.has(n) && (i.add(n), a.add(t), r.push(
|
|
1647
|
+
t && o.has(t) && s.has(n) && (i.add(n), a.add(t), r.push(z({
|
|
1648
1648
|
kind: "rename-column",
|
|
1649
1649
|
table: e.tableName,
|
|
1650
1650
|
from: t,
|
|
@@ -1675,7 +1675,7 @@ BEGIN
|
|
|
1675
1675
|
let r = o(n), i = a.filter((e) => !l.has(e.name) && s(e) === r);
|
|
1676
1676
|
if (i.length !== 1) continue;
|
|
1677
1677
|
let d = i[0];
|
|
1678
|
-
d.name !== n.name && (l.add(d.name), u.add(n.name), c.push(
|
|
1678
|
+
d.name !== n.name && (l.add(d.name), u.add(n.name), c.push(z({
|
|
1679
1679
|
kind: "rename-index",
|
|
1680
1680
|
table: e,
|
|
1681
1681
|
from: n.name,
|
|
@@ -1698,7 +1698,7 @@ BEGIN
|
|
|
1698
1698
|
continue;
|
|
1699
1699
|
}
|
|
1700
1700
|
if (t.has(c.name)) {
|
|
1701
|
-
r.push(
|
|
1701
|
+
r.push(z({
|
|
1702
1702
|
kind: "rename-table",
|
|
1703
1703
|
from: e,
|
|
1704
1704
|
to: c.name
|
|
@@ -1706,14 +1706,14 @@ BEGIN
|
|
|
1706
1706
|
continue;
|
|
1707
1707
|
}
|
|
1708
1708
|
if ((s.get(e) ?? 0) !== 1) {
|
|
1709
|
-
r.push(
|
|
1709
|
+
r.push(z({
|
|
1710
1710
|
kind: "rename-table",
|
|
1711
1711
|
from: e,
|
|
1712
1712
|
to: c.name
|
|
1713
1713
|
}, "needs-rename-annotation", `.renamedFrom('${e}') is claimed by ${s.get(e)} tables — nothing says which receives its rows`, { fix: `remove the \`.renamedFrom('${e}')\` marker from all but one of them.` }));
|
|
1714
1714
|
continue;
|
|
1715
1715
|
}
|
|
1716
|
-
i.set(c.name, e), a.add(e), r.push(
|
|
1716
|
+
i.set(c.name, e), a.add(e), r.push(z({
|
|
1717
1717
|
kind: "rename-table",
|
|
1718
1718
|
from: e,
|
|
1719
1719
|
to: c.name
|
|
@@ -1739,7 +1739,7 @@ BEGIN
|
|
|
1739
1739
|
...e,
|
|
1740
1740
|
name: r,
|
|
1741
1741
|
table: n
|
|
1742
|
-
} : i ? (a.push(
|
|
1742
|
+
} : i ? (a.push(z({
|
|
1743
1743
|
kind: "rename-index",
|
|
1744
1744
|
table: n,
|
|
1745
1745
|
from: e.name,
|
|
@@ -1791,7 +1791,13 @@ BEGIN
|
|
|
1791
1791
|
case "multi-step": t.multiStep++;
|
|
1792
1792
|
}
|
|
1793
1793
|
return t;
|
|
1794
|
-
}, ai = (e, t
|
|
1794
|
+
}, ai = (e, t) => {
|
|
1795
|
+
let n = t.flatMap((e) => [e.table, e.targetTable]).flatMap((e) => {
|
|
1796
|
+
let t = w(e);
|
|
1797
|
+
return t === void 0 ? [] : [t.getTime()];
|
|
1798
|
+
}), r = new Date(Math.max(...n)), i = new Date(Date.UTC(r.getUTCFullYear(), r.getUTCMonth(), r.getUTCDate() + 1)).toISOString().slice(0, 10);
|
|
1799
|
+
return `${e.join("; ")}. Reclaim the snapshots first — \`voltro db gc-snapshots --before ${i}\` drops every snapshot older than that date, so run it with --dry-run to see the list — or, if a snapshot's data is still wanted, bring it back with \`voltro db restore-snapshot <plan-id>\` and declare it, so it converts in the same plan.`;
|
|
1800
|
+
}, oi = (e, t, n, r) => {
|
|
1795
1801
|
let i = /* @__PURE__ */ new Map();
|
|
1796
1802
|
for (let a of e.tables) {
|
|
1797
1803
|
let e = t.get(a.name) ?? (n.has(a.name) ? t.get(n.get(a.name)) : void 0);
|
|
@@ -1825,30 +1831,34 @@ BEGIN
|
|
|
1825
1831
|
let s = t.columns.filter(fr).map((e) => e.name), c = new Map(n.columns.map((e) => [e.name, e])), l = [...new Set(s.flatMap((e) => {
|
|
1826
1832
|
let t = c.get(e);
|
|
1827
1833
|
return t?.charset === void 0 ? [] : [t.charset];
|
|
1828
|
-
}))].sort(), u = s.filter((e) => c.has(e)), d = a.filter((t) => t.table === e || t.targetTable === e), f = [], p = d.map((t) => {
|
|
1834
|
+
}))].sort(), u = s.filter((e) => c.has(e)), d = a.filter((t) => t.table === e || t.targetTable === e), f = [], p = [], m = d.map((t) => {
|
|
1829
1835
|
let n = t.table === e ? t.targetTable : t.table, a = n === e || i.has(n), o = t.table === e ? t.targetCharset : t.sourceCharset;
|
|
1830
|
-
!a && o !== void 0 && o !== r
|
|
1836
|
+
if (!a && o !== void 0 && o !== r) {
|
|
1837
|
+
let e = `${t.name} (${t.table}.${t.column} → ${t.targetTable}.${t.targetColumn})`;
|
|
1838
|
+
ne(n) ? p.push(`${e}: "${n}" is a soft-drop snapshot, stored ${o}`) : f.push(`${e}: "${n}" stays ${o} — it is not a declared table, so the plan does not convert it`);
|
|
1839
|
+
}
|
|
1831
1840
|
let { sourceCharset: s, targetCharset: c, ...l } = t, u = a && n !== e && n.localeCompare(e) > 0 ? "peer" : "here";
|
|
1832
1841
|
return {
|
|
1833
1842
|
...l,
|
|
1834
1843
|
restore: u
|
|
1835
1844
|
};
|
|
1836
|
-
}),
|
|
1845
|
+
}), h = r === "utf8mb4", g = `table rewrite: ${u.length} string column${u.length === 1 ? "" : "s"} ${l.join("/")} → ${r}` + (m.length > 0 ? `; ${m.length} foreign key${m.length === 1 ? "" : "s"} dropped and re-created around it` : ""), _ = {
|
|
1837
1846
|
kind: "convert-charset",
|
|
1838
1847
|
table: e,
|
|
1839
1848
|
charset: r,
|
|
1840
1849
|
columns: u,
|
|
1841
1850
|
from: l,
|
|
1842
|
-
foreignKeys:
|
|
1851
|
+
foreignKeys: m
|
|
1843
1852
|
};
|
|
1844
|
-
if (f.length > 0) {
|
|
1845
|
-
|
|
1853
|
+
if (f.length > 0 || p.length > 0) {
|
|
1854
|
+
let t = [...f.length > 0 ? [`${f.join("; ")}. Declare that table so it converts in the same plan, convert it by hand first, or leave the store charset undeclared.`] : [], ...p.length > 0 ? [ai(p, d)] : []];
|
|
1855
|
+
o.push(z(_, "lossy", g, { fix: `converting "${e}" to ${r} would break a foreign key the plan cannot carry: ${t.join(" ")}` }));
|
|
1846
1856
|
continue;
|
|
1847
1857
|
}
|
|
1848
|
-
o.push(
|
|
1858
|
+
o.push(h ? z(_, "safe", g) : z(_, "lossy", g, { fix: `${e}: narrowing to ${r} can refuse or truncate 4-byte characters the columns already hold. Declare charset: 'utf8mb4' instead, or — after checking the data — allow it with the destructive opt-in (VOLTRO_DESTRUCTIVE_OK=1).` }));
|
|
1849
1859
|
}
|
|
1850
1860
|
return o;
|
|
1851
|
-
},
|
|
1861
|
+
}, si = (e) => {
|
|
1852
1862
|
let t = wr(e.declared, e.dialect, { charset: e.charset }), n = jr(e.declared, t), r = new Map(e.live.tables.map((e) => [e.name, e])), i = e.onlineAfter ?? Wr, a = [], o = ni(t, r, n);
|
|
1853
1863
|
a.push(...o.ops);
|
|
1854
1864
|
for (let e of t.tables) if (!o.renamedInto.has(e.name) && !r.has(e.name)) {
|
|
@@ -1864,11 +1874,11 @@ BEGIN
|
|
|
1864
1874
|
c.push(t.name);
|
|
1865
1875
|
continue;
|
|
1866
1876
|
}
|
|
1867
|
-
if (
|
|
1877
|
+
if (ge(t.name)) {
|
|
1868
1878
|
c.push(t.name);
|
|
1869
1879
|
continue;
|
|
1870
1880
|
}
|
|
1871
|
-
if (
|
|
1881
|
+
if (ne(t.name)) {
|
|
1872
1882
|
c.push(t.name);
|
|
1873
1883
|
continue;
|
|
1874
1884
|
}
|
|
@@ -1894,10 +1904,10 @@ BEGIN
|
|
|
1894
1904
|
}, e.dialect, u.rowCount, i));
|
|
1895
1905
|
}
|
|
1896
1906
|
for (let e of f.removed) {
|
|
1897
|
-
if (m.consumedRemovedNames.has(e.name) ||
|
|
1907
|
+
if (m.consumedRemovedNames.has(e.name) || ne(e.name)) continue;
|
|
1898
1908
|
let t = d.columnDefs[e.name], n = Vr(s.name, e, t);
|
|
1899
1909
|
e.references !== void 0 && a.push({
|
|
1900
|
-
...
|
|
1910
|
+
...z({
|
|
1901
1911
|
kind: "drop-foreign-key",
|
|
1902
1912
|
table: s.name,
|
|
1903
1913
|
column: e.name,
|
|
@@ -1919,15 +1929,15 @@ BEGIN
|
|
|
1919
1929
|
for (let e of p.removed) g.consumedRemovedNames.has(e.name) || a.push(Kr(s.name, e));
|
|
1920
1930
|
for (let { declared: t, live: n } of f.changed) a.push(...Yr(s.name, t, n, e.dialect, u.rowCount, i));
|
|
1921
1931
|
}
|
|
1922
|
-
e.charset !== void 0 && a.push(...
|
|
1932
|
+
e.charset !== void 0 && a.push(...oi(t, r, o.renamedInto, e.charset));
|
|
1923
1933
|
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) => {
|
|
1924
1934
|
let t = u.get(e);
|
|
1925
1935
|
return t ? t.columns.flatMap((e) => e.references && l.has(e.references.table) ? [{
|
|
1926
1936
|
column: e.name,
|
|
1927
1937
|
target: e.references.table
|
|
1928
1938
|
}] : []) : [];
|
|
1929
|
-
}, f =
|
|
1930
|
-
for (let e of t.tables) if (l.has(e.name)) for (let t of e.columns) t.references && f.has(M(e.name, t.name)) && p.push(
|
|
1939
|
+
}, f = Ve([...l], d), p = [];
|
|
1940
|
+
for (let e of t.tables) if (l.has(e.name)) for (let t of e.columns) t.references && f.has(M(e.name, t.name)) && p.push(z({
|
|
1931
1941
|
kind: "add-foreign-key",
|
|
1932
1942
|
table: e.name,
|
|
1933
1943
|
column: t.name,
|
|
@@ -2004,31 +2014,31 @@ BEGIN
|
|
|
2004
2014
|
for (let e of t.tables) {
|
|
2005
2015
|
if (S.has(e.name) || o.renamedInto.has(e.name)) continue;
|
|
2006
2016
|
let t = r.get(e.name);
|
|
2007
|
-
t !== void 0 &&
|
|
2017
|
+
t !== void 0 && R({ tables: [t] }) !== R({ tables: [e] }) && C.push(e.name);
|
|
2008
2018
|
}
|
|
2009
2019
|
return {
|
|
2010
2020
|
operations: x,
|
|
2011
|
-
fromFingerprint:
|
|
2012
|
-
toFingerprint:
|
|
2021
|
+
fromFingerprint: R(e.live),
|
|
2022
|
+
toFingerprint: R(t),
|
|
2013
2023
|
summary: ii(x),
|
|
2014
2024
|
fingerprintDivergence: {
|
|
2015
2025
|
outsideDiff: c,
|
|
2016
2026
|
diffEquivalent: C
|
|
2017
2027
|
}
|
|
2018
2028
|
};
|
|
2019
|
-
},
|
|
2029
|
+
}, B = "_voltro_deploys", ci = l(B, {
|
|
2020
2030
|
id: te({ prefix: "dpl" }),
|
|
2021
|
-
status:
|
|
2022
|
-
dialect:
|
|
2023
|
-
appliedBy:
|
|
2024
|
-
startedAt:
|
|
2025
|
-
baseline:
|
|
2026
|
-
report:
|
|
2027
|
-
}),
|
|
2028
|
-
VALUES (${t.id}, ${"running"}, ${t.dialect}, ${t.appliedBy}, ${(/* @__PURE__ */ new Date()).toISOString()}, ${t.baseline}, ${null})`.pipe(A.asVoid),
|
|
2031
|
+
status: E(),
|
|
2032
|
+
dialect: E(),
|
|
2033
|
+
appliedBy: E(),
|
|
2034
|
+
startedAt: E(),
|
|
2035
|
+
baseline: E(),
|
|
2036
|
+
report: E().nullable()
|
|
2037
|
+
}), li = (e, t) => e`INSERT INTO ${e(B)} (${e("id")}, ${e("status")}, ${e("dialect")}, ${e("appliedBy")}, ${e("startedAt")}, ${e("baseline")}, ${e("report")})
|
|
2038
|
+
VALUES (${t.id}, ${"running"}, ${t.dialect}, ${t.appliedBy}, ${(/* @__PURE__ */ new Date()).toISOString()}, ${t.baseline}, ${null})`.pipe(A.asVoid), ui = (e, t) => e`DELETE FROM ${e(B)} WHERE ${e("id")} = ${t}`.pipe(A.asVoid), di = (e, t, n) => e`UPDATE ${e(B)} SET ${e("status")} = ${"failed"}, ${e("report")} = ${n} WHERE ${e("id")} = ${t}`.pipe(A.asVoid), fi = (e) => e`SELECT ${e("id")}, ${e("status")}, ${e("dialect")}, ${e("appliedBy")}, ${e("startedAt")}, ${e("baseline")}, ${e("report")} FROM ${e(B)}`.pipe(A.map((e) => e.map((e) => ({
|
|
2029
2039
|
...e,
|
|
2030
2040
|
startedAt: String(e.startedAt)
|
|
2031
|
-
}))), A.catchAll(() => A.succeed([]))),
|
|
2041
|
+
}))), A.catchAll(() => A.succeed([]))), pi = (e, t) => {
|
|
2032
2042
|
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);
|
|
2033
2043
|
if (!i("check")) return null;
|
|
2034
2044
|
let a = n[r++];
|
|
@@ -2043,7 +2053,7 @@ BEGIN
|
|
|
2043
2053
|
if (e === void 0 || !/^'(?:''|[^'])*'$/.test(e) || (c.push(e.slice(1, -1).replace(/''/g, "'")), !o())) return null;
|
|
2044
2054
|
} while (s && i(","));
|
|
2045
2055
|
return s && (!i("]") || i("::") && (!i("text") || !i("[") || !i("]"))) ? null : r === n.length ? c : null;
|
|
2046
|
-
},
|
|
2056
|
+
}, mi = (e) => {
|
|
2047
2057
|
let t = /[`"[]?([A-Za-z_][A-Za-z0-9_]*)[`"\]]?\s*(?:in\b|=)/i.exec(e);
|
|
2048
2058
|
if (!t) return null;
|
|
2049
2059
|
let n = [...e.replace(/\\'/g, "'").matchAll(/'((?:[^']|'')*)'/g)].map((e) => e[1].replace(/''/g, "'")).filter((e) => e.length > 0);
|
|
@@ -2051,7 +2061,7 @@ BEGIN
|
|
|
2051
2061
|
column: t[1],
|
|
2052
2062
|
values: n
|
|
2053
2063
|
};
|
|
2054
|
-
},
|
|
2064
|
+
}, hi = (e, t) => {
|
|
2055
2065
|
if (t === "vector" || t === "halfvec") return "vector";
|
|
2056
2066
|
switch (e) {
|
|
2057
2067
|
case "text":
|
|
@@ -2079,7 +2089,7 @@ BEGIN
|
|
|
2079
2089
|
case "USER-DEFINED": return "text";
|
|
2080
2090
|
default: return "text";
|
|
2081
2091
|
}
|
|
2082
|
-
},
|
|
2092
|
+
}, gi = {
|
|
2083
2093
|
_text: "text",
|
|
2084
2094
|
_varchar: "text",
|
|
2085
2095
|
_uuid: "text",
|
|
@@ -2095,10 +2105,10 @@ BEGIN
|
|
|
2095
2105
|
_date: "date",
|
|
2096
2106
|
_jsonb: "json",
|
|
2097
2107
|
_json: "json"
|
|
2098
|
-
},
|
|
2108
|
+
}, _i = (e) => e === void 0 ? void 0 : gi[e], vi = (e, t) => e == null || e === "" ? void 0 : { generatedAs: {
|
|
2099
2109
|
expr: e,
|
|
2100
2110
|
stored: t
|
|
2101
|
-
} },
|
|
2111
|
+
} }, yi = (e) => {
|
|
2102
2112
|
switch (e.toUpperCase()) {
|
|
2103
2113
|
case "CASCADE": return "cascade";
|
|
2104
2114
|
case "RESTRICT": return "restrict";
|
|
@@ -2106,25 +2116,25 @@ BEGIN
|
|
|
2106
2116
|
case "SET DEFAULT": return "noAction";
|
|
2107
2117
|
default: return "noAction";
|
|
2108
2118
|
}
|
|
2109
|
-
},
|
|
2119
|
+
}, bi = (e, t) => {
|
|
2110
2120
|
let n = e !== void 0 && e !== "" ? Number(e) : NaN;
|
|
2111
2121
|
return Number.isInteger(n) && n > 0 ? n : t;
|
|
2112
|
-
},
|
|
2122
|
+
}, xi = () => bi(process.env.VOLTRO_INTROSPECT_BATCH, 20), Si = 300, Ci = () => {
|
|
2113
2123
|
let e = process.env.VOLTRO_INTROSPECT_TIMEOUT_MS;
|
|
2114
|
-
return e !== void 0 && e.trim() === "0" ? 0 :
|
|
2115
|
-
},
|
|
2124
|
+
return e !== void 0 && e.trim() === "0" ? 0 : bi(e, 3e4);
|
|
2125
|
+
}, wi = (e, t) => {
|
|
2116
2126
|
let n = Number.isFinite(t) && t >= 1 ? Math.floor(t) : 1, r = [];
|
|
2117
2127
|
for (let t = 0; t < e.length; t += n) r.push(e.slice(t, t + n));
|
|
2118
2128
|
return r;
|
|
2119
|
-
},
|
|
2120
|
-
let t =
|
|
2129
|
+
}, Ti = (e) => {
|
|
2130
|
+
let t = Ci(), n = A.gen(function* () {
|
|
2121
2131
|
t > 0 && (yield* e.unsafe(`SET LOCAL statement_timeout = ${t}`));
|
|
2122
|
-
let n = (t) => e.unsafe("(" + t.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ") + ")"), r = (t) => e.unsafe(String(Math.max(0, Math.trunc(t)))), i =
|
|
2132
|
+
let n = (t) => e.unsafe("(" + t.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ") + ")"), r = (t) => e.unsafe(String(Math.max(0, Math.trunc(t)))), i = xi(), a = (e, t) => A.gen(function* () {
|
|
2123
2133
|
let r = [];
|
|
2124
|
-
for (let a of
|
|
2134
|
+
for (let a of wi(e, i)) a.length !== 0 && r.push(...yield* t(n(a)));
|
|
2125
2135
|
return r;
|
|
2126
2136
|
}), o = [];
|
|
2127
|
-
for (let t = 0;; t +=
|
|
2137
|
+
for (let t = 0;; t += Si) {
|
|
2128
2138
|
let n = yield* e`
|
|
2129
2139
|
SELECT c.relname AS table_name,
|
|
2130
2140
|
COALESCE(c.reltuples::bigint, 0) AS row_count
|
|
@@ -2132,9 +2142,9 @@ BEGIN
|
|
|
2132
2142
|
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
2133
2143
|
WHERE n.nspname = current_schema() AND c.relkind = 'r'
|
|
2134
2144
|
ORDER BY c.relname
|
|
2135
|
-
LIMIT ${r(
|
|
2145
|
+
LIMIT ${r(Si)} OFFSET ${r(t)}
|
|
2136
2146
|
`;
|
|
2137
|
-
if (o.push(...n), n.length <
|
|
2147
|
+
if (o.push(...n), n.length < Si) break;
|
|
2138
2148
|
}
|
|
2139
2149
|
let s = /* @__PURE__ */ new Set(), c = [];
|
|
2140
2150
|
for (let e of o) s.has(e.table_name) || (s.add(e.table_name), c.push(e));
|
|
@@ -2197,7 +2207,7 @@ BEGIN
|
|
|
2197
2207
|
srid: e.srid
|
|
2198
2208
|
}])), y = /* @__PURE__ */ new Map();
|
|
2199
2209
|
for (let e of p) {
|
|
2200
|
-
let t =
|
|
2210
|
+
let t = pi(e.def, e.column_name);
|
|
2201
2211
|
t !== null && y.set(`${e.table_name}.${e.column_name}`, t);
|
|
2202
2212
|
}
|
|
2203
2213
|
let b = yield* a(l, (t) => e`
|
|
@@ -2276,18 +2286,18 @@ BEGIN
|
|
|
2276
2286
|
let t = C.get(e.table_name);
|
|
2277
2287
|
t || (t = /* @__PURE__ */ new Set(), C.set(e.table_name, t)), t.add(e.column_name);
|
|
2278
2288
|
}
|
|
2279
|
-
let
|
|
2289
|
+
let O = /* @__PURE__ */ new Map();
|
|
2280
2290
|
for (let e of f) {
|
|
2281
|
-
let t = `${e.table_name}\u0000${e.constraint_name}`, n =
|
|
2291
|
+
let t = `${e.table_name}\u0000${e.constraint_name}`, n = O.get(t);
|
|
2282
2292
|
n || (n = {
|
|
2283
2293
|
table: e.table_name,
|
|
2284
2294
|
columns: []
|
|
2285
|
-
},
|
|
2295
|
+
}, O.set(t, n)), n.columns.push({
|
|
2286
2296
|
name: e.column_name,
|
|
2287
2297
|
position: e.position
|
|
2288
2298
|
});
|
|
2289
2299
|
}
|
|
2290
|
-
for (let [e, t] of
|
|
2300
|
+
for (let [e, t] of O) {
|
|
2291
2301
|
let n = [...t.columns].sort((e, t) => e.position - t.position).map((e) => e.name);
|
|
2292
2302
|
if (n.length === 1) {
|
|
2293
2303
|
let e = w.get(t.table);
|
|
@@ -2312,14 +2322,14 @@ BEGIN
|
|
|
2312
2322
|
let n = t.get(e.index_name);
|
|
2313
2323
|
n || (n = [], t.set(e.index_name, n)), n.push(e);
|
|
2314
2324
|
}
|
|
2315
|
-
let
|
|
2325
|
+
let ee = [];
|
|
2316
2326
|
for (let e of c) {
|
|
2317
2327
|
let t = /* @__PURE__ */ new Set(), n = (S.get(e.table_name) ?? []).filter((e) => !t.has(e.column_name) && (t.add(e.column_name), !0)), r = C.get(e.table_name) ?? /* @__PURE__ */ new Set(), i = w.get(e.table_name) ?? /* @__PURE__ */ new Set(), a = E.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) => {
|
|
2318
|
-
let n = r.has(t.column_name) && r.size === 1, a = o.get(t.column_name), s = t.data_type === "USER-DEFINED" && t.udt_name !== void 0 && g.has(t.udt_name), c = s ? "enum" :
|
|
2328
|
+
let n = r.has(t.column_name) && r.size === 1, a = o.get(t.column_name), s = t.data_type === "USER-DEFINED" && t.udt_name !== void 0 && g.has(t.udt_name), c = s ? "enum" : hi(t.data_type, t.udt_name), l = !a && n && t.column_name === "id", u = a ? "reference" : l ? "id" : c, d = a ? {
|
|
2319
2329
|
table: a.target_table,
|
|
2320
2330
|
column: a.target_column,
|
|
2321
|
-
onDelete:
|
|
2322
|
-
onUpdate:
|
|
2331
|
+
onDelete: yi(a.delete_rule),
|
|
2332
|
+
onUpdate: yi(a.update_rule),
|
|
2323
2333
|
constraintName: a.constraint_name
|
|
2324
2334
|
} : void 0, f = y.get(`${e.table_name}.${t.column_name}`);
|
|
2325
2335
|
return {
|
|
@@ -2329,14 +2339,14 @@ BEGIN
|
|
|
2329
2339
|
enumName: t.udt_name,
|
|
2330
2340
|
enumValues: h.get(t.udt_name) ?? []
|
|
2331
2341
|
} : {},
|
|
2332
|
-
...u === "array" &&
|
|
2342
|
+
...u === "array" && _i(t.udt_name) !== void 0 ? { arrayElement: _i(t.udt_name) } : {},
|
|
2333
2343
|
...v.has(`${e.table_name}.${t.column_name}`) ? { spatial: v.get(`${e.table_name}.${t.column_name}`) } : {},
|
|
2334
2344
|
...l ? { idStorage: Bn(c) } : {},
|
|
2335
2345
|
...u === "vector" ? {
|
|
2336
2346
|
vectorPrecision: t.udt_name === "halfvec" ? "half" : "float32",
|
|
2337
2347
|
...t.type_modifier !== void 0 && t.type_modifier > 0 ? { vectorDim: t.type_modifier } : {}
|
|
2338
2348
|
} : {},
|
|
2339
|
-
...
|
|
2349
|
+
...Li(t.data_type, t.character_maximum_length) === void 0 ? {} : { maxLength: Li(t.data_type, t.character_maximum_length) },
|
|
2340
2350
|
...c === "decimal" && typeof t.numeric_precision == "number" ? {
|
|
2341
2351
|
precision: t.numeric_precision,
|
|
2342
2352
|
...typeof t.numeric_scale == "number" ? { scale: t.numeric_scale } : {}
|
|
@@ -2346,9 +2356,9 @@ BEGIN
|
|
|
2346
2356
|
hasDefault: t.column_default !== null,
|
|
2347
2357
|
...t.column_default === null ? {} : { defaultValue: t.column_default },
|
|
2348
2358
|
...d ? { references: d } : {},
|
|
2349
|
-
...a ? { referenceStorage: ["integer", "bigint"].includes(
|
|
2359
|
+
...a ? { referenceStorage: ["integer", "bigint"].includes(hi(t.data_type, t.udt_name)) ? "numeric" : "text" } : {},
|
|
2350
2360
|
...f ? { oneOf: f } : {},
|
|
2351
|
-
...
|
|
2361
|
+
...vi(t.is_generated === "ALWAYS" ? t.generation_expression ?? "generated" : null, !0) ?? {}
|
|
2352
2362
|
};
|
|
2353
2363
|
}), l = [], u = D.get(e.table_name);
|
|
2354
2364
|
if (u) for (let [t, n] of u) {
|
|
@@ -2367,7 +2377,7 @@ BEGIN
|
|
|
2367
2377
|
table: e.table_name,
|
|
2368
2378
|
columns: i.map((e) => e.column_name),
|
|
2369
2379
|
unique: n[0]?.is_unique ?? !1,
|
|
2370
|
-
...
|
|
2380
|
+
...Me(o?.access_method, o?.access_method === "hnsw" ? { hnsw: {
|
|
2371
2381
|
opclass: o.operator_class,
|
|
2372
2382
|
m: c.get("m") ?? 16,
|
|
2373
2383
|
efConstruction: c.get("ef_construction") ?? 64
|
|
@@ -2385,20 +2395,20 @@ BEGIN
|
|
|
2385
2395
|
unique: !0
|
|
2386
2396
|
});
|
|
2387
2397
|
let d = Number(e.row_count ?? 0);
|
|
2388
|
-
|
|
2398
|
+
ee.push({
|
|
2389
2399
|
name: e.table_name,
|
|
2390
2400
|
columns: c,
|
|
2391
2401
|
indexes: l,
|
|
2392
2402
|
...d > 0 ? { rowCount: d } : {}
|
|
2393
2403
|
});
|
|
2394
2404
|
}
|
|
2395
|
-
return { tables:
|
|
2405
|
+
return { tables: ee };
|
|
2396
2406
|
});
|
|
2397
2407
|
return (t > 0 ? e.withTransaction(n) : n).pipe(A.catchAll((e) => {
|
|
2398
2408
|
let n = `${String(e)} ${String(e.cause ?? "")}`.toLowerCase();
|
|
2399
2409
|
return n.includes("statement timeout") || n.includes("57014") ? A.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.`)) : A.fail(e);
|
|
2400
2410
|
}));
|
|
2401
|
-
},
|
|
2411
|
+
}, Ei = (e, t) => {
|
|
2402
2412
|
switch (e.toLowerCase()) {
|
|
2403
2413
|
case "varchar":
|
|
2404
2414
|
case "char":
|
|
@@ -2430,22 +2440,22 @@ BEGIN
|
|
|
2430
2440
|
case "json": return "json";
|
|
2431
2441
|
default: return "text";
|
|
2432
2442
|
}
|
|
2433
|
-
},
|
|
2443
|
+
}, Di = (e) => e.map((e) => {
|
|
2434
2444
|
let t = e, n = {};
|
|
2435
2445
|
for (let e of Object.keys(t)) n[e.toLowerCase()] = t[e];
|
|
2436
2446
|
return n;
|
|
2437
|
-
}),
|
|
2438
|
-
let t =
|
|
2447
|
+
}), Oi = (e) => A.gen(function* () {
|
|
2448
|
+
let t = Di(yield* e`
|
|
2439
2449
|
SELECT table_name, COALESCE(table_rows, 0) AS table_rows
|
|
2440
2450
|
FROM information_schema.tables
|
|
2441
2451
|
WHERE table_schema = DATABASE() AND table_type = 'BASE TABLE'
|
|
2442
|
-
ORDER BY table_name`), n =
|
|
2452
|
+
ORDER BY table_name`), n = Di(yield* e`
|
|
2443
2453
|
SELECT table_name, column_name, data_type, column_type, is_nullable, column_default, column_key,
|
|
2444
2454
|
character_maximum_length, numeric_precision, numeric_scale,
|
|
2445
2455
|
generation_expression, extra, character_set_name
|
|
2446
2456
|
FROM information_schema.columns
|
|
2447
2457
|
WHERE table_schema = DATABASE()
|
|
2448
|
-
ORDER BY table_name, ordinal_position`), r =
|
|
2458
|
+
ORDER BY table_name, ordinal_position`), r = Di(yield* e`
|
|
2449
2459
|
SELECT k.table_name AS source_table,
|
|
2450
2460
|
k.column_name AS source_column,
|
|
2451
2461
|
k.referenced_table_name AS target_table,
|
|
@@ -2456,7 +2466,7 @@ BEGIN
|
|
|
2456
2466
|
JOIN information_schema.referential_constraints r
|
|
2457
2467
|
ON k.constraint_name = r.constraint_name
|
|
2458
2468
|
AND k.table_schema = r.constraint_schema
|
|
2459
|
-
WHERE k.table_schema = DATABASE() AND k.referenced_table_name IS NOT NULL`), i =
|
|
2469
|
+
WHERE k.table_schema = DATABASE() AND k.referenced_table_name IS NOT NULL`), i = Di(yield* e`
|
|
2460
2470
|
SELECT table_name, index_name, non_unique, column_name, seq_in_index
|
|
2461
2471
|
FROM information_schema.statistics
|
|
2462
2472
|
WHERE table_schema = DATABASE() AND index_name <> 'PRIMARY'
|
|
@@ -2469,14 +2479,14 @@ BEGIN
|
|
|
2469
2479
|
JOIN information_schema.table_constraints tc
|
|
2470
2480
|
ON tc.constraint_schema = cc.constraint_schema
|
|
2471
2481
|
AND tc.constraint_name = cc.constraint_name
|
|
2472
|
-
WHERE cc.constraint_schema = DATABASE()`.unprepared, s =
|
|
2482
|
+
WHERE cc.constraint_schema = DATABASE()`.unprepared, s = Di(yield* a.pipe(A.orElse(() => o), A.orElseSucceed(() => []))), c = /* @__PURE__ */ new Set(), l = /* @__PURE__ */ new Map();
|
|
2473
2483
|
for (let e of s) {
|
|
2474
2484
|
let t = /json_valid\(`?([^`)]+)`?\)/i.exec(e.check_clause);
|
|
2475
2485
|
if (t) {
|
|
2476
2486
|
c.add(`${e.table_name}.${t[1]}`);
|
|
2477
2487
|
continue;
|
|
2478
2488
|
}
|
|
2479
|
-
let n =
|
|
2489
|
+
let n = mi(e.check_clause);
|
|
2480
2490
|
n && l.set(`${e.table_name}.${n.column}`, n.values);
|
|
2481
2491
|
}
|
|
2482
2492
|
let u = /* @__PURE__ */ new Map(), d = /* @__PURE__ */ new Map(), f = /* @__PURE__ */ new Map();
|
|
@@ -2499,11 +2509,11 @@ BEGIN
|
|
|
2499
2509
|
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);
|
|
2500
2510
|
if (o) for (let e of o.values()) e.length === 1 && e[0].non_unique === 0 && a.add(e[0].column_name);
|
|
2501
2511
|
let s = t.map((t) => {
|
|
2502
|
-
let n = i.includes(t.column_name) && i.length === 1, o = r.get(t.column_name), s = c.has(`${e.table_name}.${t.column_name}`) ? "json" :
|
|
2512
|
+
let n = i.includes(t.column_name) && i.length === 1, o = r.get(t.column_name), s = c.has(`${e.table_name}.${t.column_name}`) ? "json" : Ei(t.data_type, t.column_type), u = !o && n && t.column_name === "id", d = o ? "reference" : u ? "id" : s, f = o ? {
|
|
2503
2513
|
table: o.target_table,
|
|
2504
2514
|
column: o.target_column,
|
|
2505
|
-
onDelete:
|
|
2506
|
-
onUpdate:
|
|
2515
|
+
onDelete: yi(o.delete_rule),
|
|
2516
|
+
onUpdate: yi(o.update_rule),
|
|
2507
2517
|
constraintName: o.constraint_name
|
|
2508
2518
|
} : void 0, p = a.has(t.column_name) || n && t.column_name === "id", m = t.column_default === "NULL" ? null : t.column_default, h = l.get(`${e.table_name}.${t.column_name}`), g = t.data_type.toLowerCase() === "enum" ? [...t.column_type.matchAll(/'((?:[^']|'')*)'/g)].map((e) => e[1].replace(/''/g, "'")) : void 0;
|
|
2509
2519
|
return {
|
|
@@ -2512,7 +2522,7 @@ BEGIN
|
|
|
2512
2522
|
...u ? { idStorage: Bn(s) } : {},
|
|
2513
2523
|
...d === "enum" && g !== void 0 ? { enumValues: g } : {},
|
|
2514
2524
|
nullable: t.is_nullable === "YES",
|
|
2515
|
-
...
|
|
2525
|
+
...Li(t.data_type, t.character_maximum_length) === void 0 ? {} : { maxLength: Li(t.data_type, t.character_maximum_length) },
|
|
2516
2526
|
...s === "decimal" && typeof t.numeric_precision == "number" ? {
|
|
2517
2527
|
precision: t.numeric_precision,
|
|
2518
2528
|
...typeof t.numeric_scale == "number" ? { scale: t.numeric_scale } : {}
|
|
@@ -2521,9 +2531,9 @@ BEGIN
|
|
|
2521
2531
|
hasDefault: m !== null,
|
|
2522
2532
|
...m === null ? {} : { defaultValue: m },
|
|
2523
2533
|
...f ? { references: f } : {},
|
|
2524
|
-
...o ? { referenceStorage: ["integer", "bigint"].includes(
|
|
2534
|
+
...o ? { referenceStorage: ["integer", "bigint"].includes(Ei(t.data_type, t.column_type)) ? "numeric" : "text" } : {},
|
|
2525
2535
|
...h ? { oneOf: h } : {},
|
|
2526
|
-
...
|
|
2536
|
+
...vi(t.generation_expression, /STORED/i.test(t.extra ?? "")) ?? {},
|
|
2527
2537
|
...t.character_set_name !== null && t.character_set_name !== void 0 && d !== "json" ? { charset: t.character_set_name } : {}
|
|
2528
2538
|
};
|
|
2529
2539
|
}), m = new Set(n.map((e) => e.source_column)), h = [];
|
|
@@ -2551,10 +2561,10 @@ BEGIN
|
|
|
2551
2561
|
});
|
|
2552
2562
|
}
|
|
2553
2563
|
return { tables: p };
|
|
2554
|
-
}),
|
|
2564
|
+
}), ki = (e) => {
|
|
2555
2565
|
let t = e.toUpperCase();
|
|
2556
2566
|
return t.includes("INT") ? "integer" : t.includes("REAL") || t.includes("FLOA") || t.includes("DOUB") ? "real" : t.includes("BLOB") ? "bytes" : "text";
|
|
2557
|
-
},
|
|
2567
|
+
}, Ai = (e) => e === 1 || e === !0, ji = (e) => A.gen(function* () {
|
|
2558
2568
|
let t = yield* e`
|
|
2559
2569
|
SELECT name, sql FROM sqlite_master
|
|
2560
2570
|
WHERE type = 'table' AND name NOT LIKE 'sqlite_%'
|
|
@@ -2568,18 +2578,18 @@ BEGIN
|
|
|
2568
2578
|
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();
|
|
2569
2579
|
for (let t of c) {
|
|
2570
2580
|
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);
|
|
2571
|
-
if (f.set(t.name, r), t.partial !== void 0 &&
|
|
2581
|
+
if (f.set(t.name, r), t.partial !== void 0 && Ai(t.partial)) {
|
|
2572
2582
|
let n = In((yield* e`SELECT sql FROM sqlite_master WHERE type = 'index' AND name = ${t.name}`)[0]?.sql ?? "");
|
|
2573
2583
|
n !== void 0 && p.set(t.name, n);
|
|
2574
2584
|
}
|
|
2575
|
-
!p.has(t.name) &&
|
|
2585
|
+
!p.has(t.name) && Ai(t.unique) && r.length === 1 && m.add(r[0]);
|
|
2576
2586
|
}
|
|
2577
2587
|
let h = o.map((e) => {
|
|
2578
|
-
let n = u.length === 1 && u[0] === e.name, r = l.get(e.name), i =
|
|
2588
|
+
let n = u.length === 1 && u[0] === e.name, r = l.get(e.name), i = ki(e.type), a = !r && n && e.name === "id", o = r ? "reference" : a ? "id" : i, s = r ? {
|
|
2579
2589
|
table: r.table,
|
|
2580
2590
|
column: r.to,
|
|
2581
|
-
onDelete:
|
|
2582
|
-
onUpdate:
|
|
2591
|
+
onDelete: yi(r.on_delete),
|
|
2592
|
+
onUpdate: yi(r.on_update)
|
|
2583
2593
|
} : void 0, c = t.get(e.name);
|
|
2584
2594
|
return {
|
|
2585
2595
|
name: e.name,
|
|
@@ -2590,19 +2600,19 @@ BEGIN
|
|
|
2590
2600
|
hasDefault: e.dflt_value !== null,
|
|
2591
2601
|
...e.dflt_value === null ? {} : { defaultValue: e.dflt_value },
|
|
2592
2602
|
...s ? { references: s } : {},
|
|
2593
|
-
...r ? { referenceStorage: ["integer", "bigint"].includes(
|
|
2603
|
+
...r ? { referenceStorage: ["integer", "bigint"].includes(ki(e.type)) ? "numeric" : "text" } : {},
|
|
2594
2604
|
...c ? { oneOf: c } : {},
|
|
2595
|
-
...
|
|
2605
|
+
...vi(e.hidden === 2 || e.hidden === 3 ? "generated" : null, e.hidden === 3) ?? {}
|
|
2596
2606
|
};
|
|
2597
2607
|
}), g = new Set(s.map((e) => e.from)), _ = [];
|
|
2598
2608
|
for (let e of c) {
|
|
2599
2609
|
if (e.origin === "pk") continue;
|
|
2600
2610
|
let t = f.get(e.name) ?? [], n = p.get(e.name);
|
|
2601
|
-
n === void 0 && t.length === 1 &&
|
|
2611
|
+
n === void 0 && t.length === 1 && Ai(e.unique) || (n !== void 0 || t.length !== 1 || Ai(e.unique) || !g.has(t[0]) || e.name.toLowerCase() === `${i}_${t[0]}_idx`.toLowerCase()) && _.push({
|
|
2602
2612
|
name: e.name,
|
|
2603
2613
|
table: i,
|
|
2604
2614
|
columns: t,
|
|
2605
|
-
unique:
|
|
2615
|
+
unique: Ai(e.unique),
|
|
2606
2616
|
...n === void 0 ? {} : { where: n }
|
|
2607
2617
|
});
|
|
2608
2618
|
}
|
|
@@ -2618,7 +2628,7 @@ BEGIN
|
|
|
2618
2628
|
});
|
|
2619
2629
|
}
|
|
2620
2630
|
return { tables: r };
|
|
2621
|
-
}),
|
|
2631
|
+
}), Mi = (e) => {
|
|
2622
2632
|
switch (e.toLowerCase()) {
|
|
2623
2633
|
case "int":
|
|
2624
2634
|
case "smallint":
|
|
@@ -2640,7 +2650,7 @@ BEGIN
|
|
|
2640
2650
|
case "image": return "bytes";
|
|
2641
2651
|
default: return "text";
|
|
2642
2652
|
}
|
|
2643
|
-
}, V = (e) => e === !0 || e === 1,
|
|
2653
|
+
}, V = (e) => e === !0 || e === 1, Ni = (e) => A.gen(function* () {
|
|
2644
2654
|
let t = yield* e`
|
|
2645
2655
|
SELECT TABLE_NAME AS table_name FROM INFORMATION_SCHEMA.TABLES
|
|
2646
2656
|
WHERE TABLE_TYPE = 'BASE TABLE' ORDER BY TABLE_NAME`, n = yield* e`
|
|
@@ -2680,7 +2690,7 @@ BEGIN
|
|
|
2680
2690
|
JOIN sys.tables t ON t.object_id = cc.parent_object_id
|
|
2681
2691
|
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();
|
|
2682
2692
|
for (let e of s) {
|
|
2683
|
-
let t =
|
|
2693
|
+
let t = mi(e.def);
|
|
2684
2694
|
t?.column === e.column_name && c.set(`${e.table_name}.${e.column_name}`, t.values);
|
|
2685
2695
|
}
|
|
2686
2696
|
let l = /* @__PURE__ */ new Map();
|
|
@@ -2709,28 +2719,28 @@ BEGIN
|
|
|
2709
2719
|
else t[0].predicate == null && V(t[0].is_unique) && t.length === 1 && m.add(t[0].column_name);
|
|
2710
2720
|
}
|
|
2711
2721
|
let h = t.map((t) => {
|
|
2712
|
-
let n = p.length === 1 && p[0] === t.column_name, a = r.get(t.column_name), o =
|
|
2722
|
+
let n = p.length === 1 && p[0] === t.column_name, a = r.get(t.column_name), o = Mi(t.data_type), l = !a && n && t.column_name === "id", u = a ? "reference" : l ? "id" : o, d = a ? {
|
|
2713
2723
|
table: a.target_table,
|
|
2714
2724
|
column: a.target_column,
|
|
2715
|
-
onDelete:
|
|
2716
|
-
onUpdate:
|
|
2725
|
+
onDelete: Pi(a.delete_rule),
|
|
2726
|
+
onUpdate: Pi(a.update_rule),
|
|
2717
2727
|
constraintName: a.constraint_name
|
|
2718
|
-
} : void 0, f = t.column_default === null ? null :
|
|
2728
|
+
} : void 0, f = t.column_default === null ? null : Fi(t.column_default), h = c.get(`${e}.${t.column_name}`), g = s.flatMap((n) => {
|
|
2719
2729
|
if (n.table_name !== e || n.column_name !== null && n.column_name !== t.column_name) return [];
|
|
2720
|
-
let r =
|
|
2730
|
+
let r = jt(t.column_name, n.def);
|
|
2721
2731
|
return r ? [{
|
|
2722
2732
|
name: n.constraint_name,
|
|
2723
2733
|
validation: r,
|
|
2724
2734
|
enabled: !V(n.is_disabled),
|
|
2725
2735
|
trusted: !V(n.is_not_trusted)
|
|
2726
2736
|
}] : [];
|
|
2727
|
-
}).sort((e, t) => e.name.localeCompare(t.name)), _ =
|
|
2737
|
+
}).sort((e, t) => e.name.localeCompare(t.name)), _ = Mt(g);
|
|
2728
2738
|
return {
|
|
2729
2739
|
name: t.column_name,
|
|
2730
2740
|
type: u,
|
|
2731
2741
|
...l ? { idStorage: Bn(o) } : {},
|
|
2732
2742
|
nullable: t.is_nullable === "YES",
|
|
2733
|
-
...
|
|
2743
|
+
...Li(t.data_type, t.character_maximum_length) === void 0 ? {} : { maxLength: Li(t.data_type, t.character_maximum_length) },
|
|
2734
2744
|
...o === "decimal" && typeof t.numeric_precision == "number" ? {
|
|
2735
2745
|
precision: t.numeric_precision,
|
|
2736
2746
|
...typeof t.numeric_scale == "number" ? { scale: t.numeric_scale } : {}
|
|
@@ -2739,11 +2749,11 @@ BEGIN
|
|
|
2739
2749
|
hasDefault: f !== null,
|
|
2740
2750
|
...f === null ? {} : { defaultValue: f },
|
|
2741
2751
|
...d ? { references: d } : {},
|
|
2742
|
-
...a ? { referenceStorage: ["integer", "bigint"].includes(
|
|
2752
|
+
...a ? { referenceStorage: ["integer", "bigint"].includes(Mi(t.data_type)) ? "numeric" : "text" } : {},
|
|
2743
2753
|
...h ? { oneOf: h } : {},
|
|
2744
2754
|
...g.length > 0 ? { jsonChecks: g } : {},
|
|
2745
2755
|
..._ ? { jsonValidation: _ } : {},
|
|
2746
|
-
...
|
|
2756
|
+
...vi(i.get(`${e}.${t.column_name}`)?.definition ?? null, V(i.get(`${e}.${t.column_name}`)?.is_persisted ?? !1)) ?? {}
|
|
2747
2757
|
};
|
|
2748
2758
|
}), g = [];
|
|
2749
2759
|
if (o) for (let [t, n] of o) {
|
|
@@ -2770,81 +2780,81 @@ BEGIN
|
|
|
2770
2780
|
});
|
|
2771
2781
|
}
|
|
2772
2782
|
return { tables: f };
|
|
2773
|
-
}),
|
|
2783
|
+
}), Pi = (e) => {
|
|
2774
2784
|
switch (e.toUpperCase().replace(/_/g, " ")) {
|
|
2775
2785
|
case "CASCADE": return "cascade";
|
|
2776
2786
|
case "SET NULL": return "setNull";
|
|
2777
2787
|
case "SET DEFAULT": return "noAction";
|
|
2778
2788
|
default: return "noAction";
|
|
2779
2789
|
}
|
|
2780
|
-
},
|
|
2790
|
+
}, Fi = (e) => {
|
|
2781
2791
|
let t = e.trim();
|
|
2782
2792
|
for (; t.startsWith("(") && t.endsWith(")");) t = t.slice(1, -1).trim();
|
|
2783
2793
|
return t.startsWith("N'") && t.endsWith("'") ? t = t.slice(2, -1) : t.startsWith("'") && t.endsWith("'") && (t = t.slice(1, -1)), t;
|
|
2784
|
-
},
|
|
2794
|
+
}, Ii = /* @__PURE__ */ new Set([
|
|
2785
2795
|
"character varying",
|
|
2786
2796
|
"varchar",
|
|
2787
2797
|
"nvarchar",
|
|
2788
2798
|
"char",
|
|
2789
2799
|
"character",
|
|
2790
2800
|
"nchar"
|
|
2791
|
-
]),
|
|
2792
|
-
if (!
|
|
2801
|
+
]), Li = (e, t) => {
|
|
2802
|
+
if (!Ii.has(e.toLowerCase())) return;
|
|
2793
2803
|
let n = Number(t);
|
|
2794
2804
|
if (!(!Number.isFinite(n) || n <= 0)) return n;
|
|
2795
|
-
},
|
|
2796
|
-
mysql: () =>
|
|
2797
|
-
mssql: () =>
|
|
2798
|
-
sqlite: () =>
|
|
2799
|
-
orElse: () =>
|
|
2805
|
+
}, Ri = /* @__PURE__ */ new Set([P, B]), zi = (e) => e.onDialectOrElse({
|
|
2806
|
+
mysql: () => Oi(e),
|
|
2807
|
+
mssql: () => Ni(e),
|
|
2808
|
+
sqlite: () => ji(e),
|
|
2809
|
+
orElse: () => Ti(e)
|
|
2800
2810
|
}).pipe(A.map((e) => ({
|
|
2801
2811
|
...e,
|
|
2802
|
-
tables: e.tables.filter((e) => !
|
|
2803
|
-
}))),
|
|
2804
|
-
let t =
|
|
2805
|
-
return t === void 0 ?
|
|
2806
|
-
}),
|
|
2812
|
+
tables: e.tables.filter((e) => !Ri.has(e.name))
|
|
2813
|
+
}))), Bi = (e) => /mariadb/i.test(e) ? "mariadb" : "mysql", Vi = /* @__PURE__ */ new WeakMap(), H = (e) => A.suspend(() => {
|
|
2814
|
+
let t = Vi.get(e);
|
|
2815
|
+
return t === void 0 ? Hi(e).pipe(A.tap((t) => A.sync(() => Vi.set(e, t)))) : A.succeed(t);
|
|
2816
|
+
}), Hi = (e) => e.unsafe("SELECT VERSION() AS v").pipe(A.map((e) => {
|
|
2807
2817
|
let t = e[0]?.v;
|
|
2808
|
-
return typeof t == "string" ?
|
|
2809
|
-
}), A.catchAll(() => A.succeed("mysql"))),
|
|
2818
|
+
return typeof t == "string" ? Bi(t) : "mysql";
|
|
2819
|
+
}), A.catchAll(() => A.succeed("mysql"))), Ui = (e) => {
|
|
2810
2820
|
let t = e;
|
|
2811
2821
|
for (let e = 0; e < 6 && typeof t == "object" && t; e++) {
|
|
2812
2822
|
let e = t;
|
|
2813
2823
|
if (typeof e.errno == "number") return e.errno;
|
|
2814
2824
|
t = e.cause;
|
|
2815
2825
|
}
|
|
2816
|
-
},
|
|
2826
|
+
}, Wi = (e) => {
|
|
2817
2827
|
let t = [], n = e;
|
|
2818
2828
|
for (let e = 0; e < 6 && typeof n == "object" && n; e++) {
|
|
2819
2829
|
let e = n;
|
|
2820
2830
|
typeof e.message == "string" && t.push(e.message), n = e.cause;
|
|
2821
2831
|
}
|
|
2822
2832
|
return t.join(" | ");
|
|
2823
|
-
},
|
|
2833
|
+
}, Gi = (e, t) => {
|
|
2824
2834
|
if (t.length === 0) return !1;
|
|
2825
|
-
let n =
|
|
2835
|
+
let n = Ui(e), r = Wi(e);
|
|
2826
2836
|
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)));
|
|
2827
|
-
},
|
|
2837
|
+
}, Ki = {
|
|
2828
2838
|
why: "mysql has no CREATE INDEX IF NOT EXISTS; 1061 is exactly that condition",
|
|
2829
2839
|
errno: [1061]
|
|
2830
|
-
},
|
|
2840
|
+
}, qi = {
|
|
2831
2841
|
why: "mysql has no DROP COLUMN IF EXISTS; 1091 is exactly that condition",
|
|
2832
2842
|
errno: [1091]
|
|
2833
|
-
},
|
|
2843
|
+
}, Ji = {
|
|
2834
2844
|
why: "sqlite has no DROP COLUMN IF EXISTS, and reports the absent column only in the message",
|
|
2835
2845
|
messageIncludes: ["no such column"]
|
|
2836
|
-
},
|
|
2846
|
+
}, Yi = {
|
|
2837
2847
|
why: "mysql/mariadb DROP CONSTRAINT has no portable IF EXISTS; 1091 / 3940 are exactly \"already gone\"",
|
|
2838
2848
|
errno: [1091, 3940]
|
|
2839
|
-
},
|
|
2849
|
+
}, Xi = {
|
|
2840
2850
|
why: "mysql/mariadb ADD CONSTRAINT has no IF NOT EXISTS; 1826 is exactly \"already there\"",
|
|
2841
2851
|
errno: [1826]
|
|
2842
|
-
},
|
|
2852
|
+
}, Zi = (e, t) => A.suspend(() => {
|
|
2843
2853
|
let n;
|
|
2844
2854
|
return e.withTransaction(t.pipe(A.tapErrorCause((e) => A.sync(() => {
|
|
2845
2855
|
n = e;
|
|
2846
|
-
})))).pipe(A.catchAllCause((e) => A.failCause(n !== void 0 && !
|
|
2847
|
-
}),
|
|
2856
|
+
})))).pipe(A.catchAllCause((e) => A.failCause(n !== void 0 && !xe.equals(n, e) ? be.sequential(n, e) : e)));
|
|
2857
|
+
}), Qi = (e, t, n) => {
|
|
2848
2858
|
let r = e.match(/'(?:''|[^'])*'|\[(?:\]\]|[^\]])*\]|\s+|[^'\[\s]+/g) ?? [];
|
|
2849
2859
|
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");
|
|
2850
2860
|
let a = r.map((e, t) => ({
|
|
@@ -2863,21 +2873,21 @@ BEGIN
|
|
|
2863
2873
|
}, U = (e, t) => e.onDialectOrElse({
|
|
2864
2874
|
mysql: () => A.succeed(t.replace("T", " ").replace("Z", "")),
|
|
2865
2875
|
orElse: () => A.succeed(t)
|
|
2866
|
-
}),
|
|
2867
|
-
if ((e.type !== "text" || e.maxLength === void 0) && !
|
|
2876
|
+
}), $i = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, ea = (e) => e.type === "text" && (e.hasDefault && e.defaultValue !== void 0 || e.oneOf !== void 0 && e.oneOf.length > 0), ta = (e, t) => {
|
|
2877
|
+
if ((e.type !== "text" || e.maxLength === void 0) && !ea(e) && !e.spatial && e.type !== "vector" && e.type !== "array" && e.type !== "enum") return;
|
|
2868
2878
|
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;
|
|
2869
2879
|
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.`);
|
|
2870
2880
|
return I(e, t);
|
|
2871
|
-
},
|
|
2872
|
-
let t =
|
|
2873
|
-
return t === void 0 ?
|
|
2874
|
-
},
|
|
2881
|
+
}, na = (e) => {
|
|
2882
|
+
let t = ta(e, "postgres");
|
|
2883
|
+
return t === void 0 ? ra(e) : t;
|
|
2884
|
+
}, ra = (e) => {
|
|
2875
2885
|
switch (e.type) {
|
|
2876
2886
|
case "id": return "text";
|
|
2877
2887
|
case "text": return "text";
|
|
2878
2888
|
case "integer": return "integer";
|
|
2879
2889
|
case "real": return "double precision";
|
|
2880
|
-
case "decimal": return
|
|
2890
|
+
case "decimal": return $i(e, "NUMERIC");
|
|
2881
2891
|
case "bigint": return "bigint";
|
|
2882
2892
|
case "boolean": return "boolean";
|
|
2883
2893
|
case "timestamp": return "timestamptz";
|
|
@@ -2891,15 +2901,15 @@ BEGIN
|
|
|
2891
2901
|
case "interval": return "interval";
|
|
2892
2902
|
case "raw": return e.rawDdl ?? "text";
|
|
2893
2903
|
}
|
|
2894
|
-
},
|
|
2895
|
-
let t =
|
|
2904
|
+
}, ia = (e) => {
|
|
2905
|
+
let t = ta(e, "mariadb");
|
|
2896
2906
|
if (t !== void 0) return t;
|
|
2897
2907
|
switch (e.type) {
|
|
2898
2908
|
case "id": return "VARCHAR(64)";
|
|
2899
2909
|
case "text": return "LONGTEXT";
|
|
2900
2910
|
case "integer": return "INT";
|
|
2901
2911
|
case "real": return "DOUBLE";
|
|
2902
|
-
case "decimal": return
|
|
2912
|
+
case "decimal": return $i(e, "DECIMAL");
|
|
2903
2913
|
case "bigint": return "BIGINT";
|
|
2904
2914
|
case "boolean": return "TINYINT(1)";
|
|
2905
2915
|
case "timestamp": return "DATETIME(6)";
|
|
@@ -2913,38 +2923,42 @@ BEGIN
|
|
|
2913
2923
|
case "interval": return "BIGINT";
|
|
2914
2924
|
case "raw": return e.rawDdl ?? "LONGTEXT";
|
|
2915
2925
|
}
|
|
2916
|
-
}, W = (e) => `"${e}"`, G = (e) => `\`${e.replace(/`/g, "``")}\``,
|
|
2926
|
+
}, W = (e) => `"${e}"`, G = (e) => `\`${e.replace(/`/g, "``")}\``, aa = (e) => e === "mariadb" ? "IF NOT EXISTS " : "", oa = (e, t, n = !0) => `ALTER TABLE ${t(e.table)} DROP COLUMN ${n ? "IF EXISTS " : ""}${t(e.column)};`, sa = (e, t = "mariadb") => `ALTER TABLE ${G(e.table)} DROP COLUMN ${t === "mariadb" ? "IF EXISTS " : ""}${G(e.column)}, ALGORITHM=COPY;`, ca = (e, t) => `ALTER TABLE ${t(e.table)} RENAME COLUMN ${t(e.from)} TO ${t(e.to)};`, la = (e, t, n) => `ALTER TABLE ${n(e.table)} RENAME COLUMN ${n(e.column)} TO ${n(`${e.column}${Ka(t)}`)};`, ua = (e, t, n) => e.hasDefault && e.defaultValue !== void 0 ? `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} SET ${fa(e, n)};` : `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} DROP DEFAULT;`, da = (e, t) => {
|
|
2917
2927
|
let { defaultFactory: n, ...r } = e;
|
|
2918
2928
|
return I(e, t) !== I({
|
|
2919
2929
|
...r,
|
|
2920
2930
|
hasDefault: !1
|
|
2921
2931
|
}, t);
|
|
2922
|
-
},
|
|
2932
|
+
}, fa = (e, t) => {
|
|
2923
2933
|
let n = t(e.defaultValue);
|
|
2924
2934
|
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.`);
|
|
2925
2935
|
return n;
|
|
2926
|
-
}, K = (e, t, n) => e.find((e) => e.tableName === t)?.fields[n],
|
|
2936
|
+
}, K = (e, t, n) => e.find((e) => e.tableName === t)?.fields[n], pa = (e, t, n) => {
|
|
2927
2937
|
let r = K(e, t, n);
|
|
2928
2938
|
return r ? br(n, r) : void 0;
|
|
2929
|
-
},
|
|
2930
|
-
let
|
|
2939
|
+
}, ma = (e, t, n, r) => {
|
|
2940
|
+
let i = n ?? e.nullable, a = Ut(e, "mariadb");
|
|
2931
2941
|
return [
|
|
2932
2942
|
G(t),
|
|
2933
2943
|
I(e, "mariadb"),
|
|
2934
|
-
|
|
2935
|
-
|
|
2944
|
+
i ? null : "NOT NULL",
|
|
2945
|
+
a,
|
|
2946
|
+
r === void 0 ? null : `CHECK (${r})`
|
|
2936
2947
|
].filter(Boolean).join(" ");
|
|
2937
|
-
},
|
|
2948
|
+
}, ha = /^json_valid\(`[^`]+`\)$/i, ga = (e, t) => H(e).pipe(A.flatMap((n) => n === "mariadb" ? e`
|
|
2949
|
+
SELECT constraint_name AS n, check_clause AS c
|
|
2950
|
+
FROM information_schema.check_constraints
|
|
2951
|
+
WHERE constraint_schema = DATABASE() AND table_name = ${t} AND level = 'Column'`.pipe(A.map((e) => new Map(e.map((e) => [String(e.n ?? ""), String(e.c ?? "")]).filter(([e, t]) => e !== "" && t !== "" && !ha.test(t.trim()))))) : A.succeed(/* @__PURE__ */ new Map()))), _a = (e, t, n, r, i) => A.map(ga(e, t), (e) => `ALTER TABLE ${G(t)} MODIFY COLUMN ${ma(n, r, i, e.get(r))};`), va = (e, t) => e == null ? null : Array.isArray(e) ? ya(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" ? L(e, "mariadb") : null, ya = (e, t, n) => Wt(e, t ?? { type: "json" }, n), ba = (e, t) => e == null ? null : Array.isArray(e) ? ya(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" ? L(e, "postgres") : null, xa = (e, t) => {
|
|
2938
2952
|
if (!e.generatedAs) return null;
|
|
2939
2953
|
let { expr: n, stored: r } = e.generatedAs;
|
|
2940
2954
|
return t === "postgres" ? `GENERATED ALWAYS AS (${n}) STORED` : t === "mssql" ? `AS (${n})${r ? " PERSISTED" : ""}` : `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
|
|
2941
|
-
},
|
|
2955
|
+
}, Sa = (e, t = !1) => {
|
|
2942
2956
|
if (e.type === "id" && e.idScheme?.kind === "numeric") return Gt(e.name, "postgres");
|
|
2943
|
-
let n =
|
|
2944
|
-
if (n) return `${W(e.name)} ${
|
|
2945
|
-
let r = [W(e.name),
|
|
2957
|
+
let n = xa(e, "postgres");
|
|
2958
|
+
if (n) return `${W(e.name)} ${na(e)} ${n}`;
|
|
2959
|
+
let r = [W(e.name), na(e)];
|
|
2946
2960
|
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) {
|
|
2947
|
-
let t =
|
|
2961
|
+
let t = ba(e.defaultValue, e);
|
|
2948
2962
|
t && r.push(t);
|
|
2949
2963
|
}
|
|
2950
2964
|
return e.references && (r.push(`REFERENCES ${W(e.references.table)} (${W(e.references.column)})`), e.references.onDelete && r.push(`ON DELETE ${{
|
|
@@ -2953,28 +2967,28 @@ BEGIN
|
|
|
2953
2967
|
setNull: "SET NULL",
|
|
2954
2968
|
noAction: "NO ACTION"
|
|
2955
2969
|
}[e.references.onDelete]}`)), r.join(" ");
|
|
2956
|
-
},
|
|
2957
|
-
let t = e.columns.map((t) => ` ${
|
|
2958
|
-
for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(
|
|
2970
|
+
}, Ca = (e) => (e.primaryKey?.length ?? 0) > 0, wa = (e, t) => e.primaryKey && e.primaryKey.length > 0 ? `,\n PRIMARY KEY (${e.primaryKey.map(t).join(", ")})` : "", Ta = (e) => {
|
|
2971
|
+
let t = e.columns.map((t) => ` ${Sa(t, Ca(e))}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${W(e.table)} (\n${t}${wa(e, W)}\n)`];
|
|
2972
|
+
for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push($a({
|
|
2959
2973
|
kind: "add-index",
|
|
2960
2974
|
table: e.table,
|
|
2961
2975
|
index: t
|
|
2962
2976
|
}, !1));
|
|
2963
2977
|
return n;
|
|
2964
|
-
},
|
|
2965
|
-
let t =
|
|
2978
|
+
}, Ea = 191, Da = (e) => {
|
|
2979
|
+
let t = ia(e).toUpperCase();
|
|
2966
2980
|
return t.endsWith("TEXT") || t.endsWith("BLOB");
|
|
2967
|
-
},
|
|
2981
|
+
}, Oa = (e, t = !1) => {
|
|
2968
2982
|
if (e.type === "id" && e.idScheme?.kind === "numeric") return Gt(e.name, "mariadb");
|
|
2969
|
-
let n = e.charset === void 0 ?
|
|
2983
|
+
let n = e.charset === void 0 ? ia(e) : `${ia(e)} CHARACTER SET ${e.charset}`, r = xa(e, "mariadb");
|
|
2970
2984
|
if (r) return `${G(e.name)} ${n} ${r}`;
|
|
2971
2985
|
let i = [G(e.name), n];
|
|
2972
|
-
if (e.type === "id" && !t && i.push("PRIMARY KEY"), e.nullable || i.push("NOT NULL"), e.unique && e.type !== "id" && !
|
|
2973
|
-
let t =
|
|
2986
|
+
if (e.type === "id" && !t && i.push("PRIMARY KEY"), e.nullable || i.push("NOT NULL"), e.unique && e.type !== "id" && !Da(e) && i.push("UNIQUE"), e.hasDefault) {
|
|
2987
|
+
let t = va(e.defaultValue, e);
|
|
2974
2988
|
t && i.push(t);
|
|
2975
2989
|
}
|
|
2976
2990
|
return i.join(" ");
|
|
2977
|
-
},
|
|
2991
|
+
}, ka = (e) => e.columns.flatMap((t) => {
|
|
2978
2992
|
if (!t.references) return [];
|
|
2979
2993
|
let n = t.references.onDelete ? ` ON DELETE ${{
|
|
2980
2994
|
cascade: "CASCADE",
|
|
@@ -2983,48 +2997,53 @@ BEGIN
|
|
|
2983
2997
|
noAction: "NO ACTION"
|
|
2984
2998
|
}[t.references.onDelete]}` : "";
|
|
2985
2999
|
return [` CONSTRAINT ${G(`${e.table}_${t.name}_fkey`)} FOREIGN KEY (${G(t.name)}) REFERENCES ${G(t.references.table)} (${G(t.references.column)})${n}`];
|
|
2986
|
-
}),
|
|
3000
|
+
}), Aa = (e) => {
|
|
2987
3001
|
let t = e.find((e) => e.charset !== void 0)?.charset;
|
|
2988
3002
|
return t === void 0 ? "" : ` DEFAULT CHARACTER SET ${t}`;
|
|
2989
|
-
},
|
|
2990
|
-
let
|
|
2991
|
-
let
|
|
2992
|
-
if (
|
|
2993
|
-
let
|
|
2994
|
-
if (
|
|
2995
|
-
|
|
2996
|
-
return `MODIFY COLUMN ${[
|
|
3003
|
+
}, ja = (e, t, n = /* @__PURE__ */ new Map()) => {
|
|
3004
|
+
let r = e.foreignKeys.map((e) => `ALTER TABLE ${G(e.table)} DROP FOREIGN KEY ${G(e.name)}`), i = e.columns.map((r) => {
|
|
3005
|
+
let i = K(t, e.table, r), a = pa(t, e.table, r);
|
|
3006
|
+
if (i === void 0 || a === void 0) throw Error(`convert-charset: no declared column '${e.table}.${r}' to render MODIFY COLUMN from; it was not in ctx.declared.`);
|
|
3007
|
+
let o = xa(a, "mariadb"), s = `${G(r)} ${I(i, "mariadb")} CHARACTER SET ${e.charset}`, c = n.get(r), l = c === void 0 ? null : `CHECK (${c})`;
|
|
3008
|
+
if (o) return `MODIFY COLUMN ${[
|
|
3009
|
+
s,
|
|
2997
3010
|
o,
|
|
2998
|
-
|
|
2999
|
-
|
|
3011
|
+
l
|
|
3012
|
+
].filter(Boolean).join(" ")}`;
|
|
3013
|
+
let u = Ut(i, "mariadb");
|
|
3014
|
+
return `MODIFY COLUMN ${[
|
|
3015
|
+
s,
|
|
3016
|
+
i.nullable ? null : "NOT NULL",
|
|
3017
|
+
u,
|
|
3018
|
+
l
|
|
3000
3019
|
].filter(Boolean).join(" ")}`;
|
|
3001
3020
|
});
|
|
3002
3021
|
return {
|
|
3003
|
-
drops:
|
|
3004
|
-
rewrite: `ALTER TABLE ${G(e.table)} ${[...
|
|
3005
|
-
restores: e.foreignKeys.filter((e) => e.restore === "here").map((e) => `ALTER TABLE ${G(e.table)} ADD CONSTRAINT ${G(e.name)} FOREIGN KEY (${G(e.column)}) REFERENCES ${G(e.targetTable)} (${G(e.targetColumn)})` + (e.onDelete ? ` ON DELETE ${
|
|
3022
|
+
drops: r,
|
|
3023
|
+
rewrite: `ALTER TABLE ${G(e.table)} ${[...i, `DEFAULT CHARACTER SET ${e.charset}`].join(", ")}`,
|
|
3024
|
+
restores: e.foreignKeys.filter((e) => e.restore === "here").map((e) => `ALTER TABLE ${G(e.table)} ADD CONSTRAINT ${G(e.name)} FOREIGN KEY (${G(e.column)}) REFERENCES ${G(e.targetTable)} (${G(e.targetColumn)})` + (e.onDelete ? ` ON DELETE ${Na[e.onDelete]}` : "") + (e.onUpdate && e.onUpdate !== "noAction" ? ` ON UPDATE ${Na[e.onUpdate]}` : ""))
|
|
3006
3025
|
};
|
|
3007
|
-
},
|
|
3008
|
-
for (let n of e.indexes)
|
|
3026
|
+
}, Ma = (e, t = "mariadb") => {
|
|
3027
|
+
for (let n of e.indexes) to(n, t);
|
|
3009
3028
|
let n = new Map(e.columns.map((e) => [e.name, e])), r = (e) => {
|
|
3010
|
-
let t =
|
|
3029
|
+
let t = Ya(n.get(e));
|
|
3011
3030
|
return t === void 0 ? G(e) : `${G(e)}(${t})`;
|
|
3012
|
-
}, i = e.columns.map((t) => ` ${
|
|
3013
|
-
for (let n of e.columns) n.unique && n.type !== "id" &&
|
|
3014
|
-
for (let n of e.indexes) n.name !== `${e.table}_pkey` && s.push(`CREATE ${n.unique ? "UNIQUE " : ""}INDEX ${
|
|
3031
|
+
}, i = e.columns.map((t) => ` ${Oa(t, Ca(e))}`).join(",\n"), a = ka(e), o = a.length > 0 ? `${i},\n${a.join(",\n")}` : i, s = [`CREATE TABLE IF NOT EXISTS ${G(e.table)} (\n${o}${wa(e, r)}\n)${Aa(e.columns)}`];
|
|
3032
|
+
for (let n of e.columns) n.unique && n.type !== "id" && Da(n) && s.push(`CREATE UNIQUE INDEX ${aa(t)}${G(`${e.table}_${n.name}_key`)} ON ${G(e.table)} (${r(n.name)})`);
|
|
3033
|
+
for (let n of e.indexes) n.name !== `${e.table}_pkey` && s.push(`CREATE ${n.unique ? "UNIQUE " : ""}INDEX ${aa(t)}${G(n.name)} ON ${G(e.table)} (${n.columns.map(r).join(", ")})`);
|
|
3015
3034
|
return s;
|
|
3016
|
-
},
|
|
3035
|
+
}, Na = {
|
|
3017
3036
|
cascade: "CASCADE",
|
|
3018
3037
|
restrict: "RESTRICT",
|
|
3019
3038
|
setNull: "SET NULL",
|
|
3020
3039
|
noAction: "NO ACTION"
|
|
3021
|
-
},
|
|
3040
|
+
}, Pa = {
|
|
3022
3041
|
cascade: "CASCADE",
|
|
3023
3042
|
restrict: "NO ACTION",
|
|
3024
3043
|
setNull: "SET NULL",
|
|
3025
3044
|
noAction: "NO ACTION"
|
|
3026
|
-
},
|
|
3027
|
-
let t =
|
|
3045
|
+
}, Fa = (e) => {
|
|
3046
|
+
let t = ta(e, "sqlite");
|
|
3028
3047
|
if (t !== void 0) return t;
|
|
3029
3048
|
switch (e.type) {
|
|
3030
3049
|
case "integer":
|
|
@@ -3036,30 +3055,30 @@ BEGIN
|
|
|
3036
3055
|
case "bytes": return "BLOB";
|
|
3037
3056
|
default: return "TEXT";
|
|
3038
3057
|
}
|
|
3039
|
-
},
|
|
3058
|
+
}, Ia = (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" ? L(e, "sqlite") : null, La = (e, t = !1) => {
|
|
3040
3059
|
if (e.type === "id" && e.idScheme?.kind === "numeric") return Gt(e.name, "sqlite");
|
|
3041
|
-
let n =
|
|
3042
|
-
if (n) return `${W(e.name)} ${
|
|
3043
|
-
let r = [W(e.name),
|
|
3060
|
+
let n = xa(e, "sqlite");
|
|
3061
|
+
if (n) return `${W(e.name)} ${Fa(e)} ${n}`;
|
|
3062
|
+
let r = [W(e.name), Fa(e)];
|
|
3044
3063
|
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) {
|
|
3045
|
-
let t =
|
|
3064
|
+
let t = Ia(e.defaultValue, "CURRENT_TIMESTAMP");
|
|
3046
3065
|
t && r.push(t);
|
|
3047
3066
|
}
|
|
3048
|
-
if (e.references && (r.push(`REFERENCES ${W(e.references.table)} (${W(e.references.column)})`), e.references.onDelete && r.push(`ON DELETE ${
|
|
3067
|
+
if (e.references && (r.push(`REFERENCES ${W(e.references.table)} (${W(e.references.column)})`), e.references.onDelete && r.push(`ON DELETE ${Na[e.references.onDelete]}`)), e.oneOf && e.oneOf.length > 0) {
|
|
3049
3068
|
let t = e.oneOf.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
|
|
3050
3069
|
r.push(`CHECK (${W(e.name)} IN (${t}))`);
|
|
3051
3070
|
}
|
|
3052
3071
|
return r.join(" ");
|
|
3053
|
-
},
|
|
3054
|
-
let t = e.columns.map((t) => ` ${
|
|
3055
|
-
for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${W(t.name)} ON ${W(e.table)} (${t.columns.map(W).join(", ")})${
|
|
3072
|
+
}, Ra = (e) => {
|
|
3073
|
+
let t = e.columns.map((t) => ` ${La(t, Ca(e))}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${W(e.table)} (\n${t}${wa(e, W)}\n)`];
|
|
3074
|
+
for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${W(t.name)} ON ${W(e.table)} (${t.columns.map(W).join(", ")})${Qa(t)}`);
|
|
3056
3075
|
return n;
|
|
3057
|
-
},
|
|
3076
|
+
}, za = (e, t) => {
|
|
3058
3077
|
let n = t.find((t) => t.tableName === e);
|
|
3059
|
-
return n ?
|
|
3060
|
-
},
|
|
3078
|
+
return n ? Ba(wr([n], "sqlite").tables[0]) : [];
|
|
3079
|
+
}, Ba = (e) => {
|
|
3061
3080
|
let t = e.name, n = `${t}__voltro_rebuild`, r = e.columns.map((e) => W(e.name)).join(", "), i = [
|
|
3062
|
-
...
|
|
3081
|
+
...Ra({
|
|
3063
3082
|
kind: "create-table",
|
|
3064
3083
|
table: n,
|
|
3065
3084
|
columns: e.columns,
|
|
@@ -3070,27 +3089,27 @@ BEGIN
|
|
|
3070
3089
|
`DROP TABLE ${W(t)}`,
|
|
3071
3090
|
`ALTER TABLE ${W(n)} RENAME TO ${W(t)}`
|
|
3072
3091
|
];
|
|
3073
|
-
for (let n of e.indexes) n.name !== `${t}_pkey` && i.push(`CREATE ${n.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${W(n.name)} ON ${W(t)} (${n.columns.map(W).join(", ")})${
|
|
3092
|
+
for (let n of e.indexes) n.name !== `${t}_pkey` && i.push(`CREATE ${n.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${W(n.name)} ON ${W(t)} (${n.columns.map(W).join(", ")})${Qa(n)}`);
|
|
3074
3093
|
return i;
|
|
3075
|
-
},
|
|
3094
|
+
}, Va = (e, t, n, r) => {
|
|
3076
3095
|
let i = r ?? e.nullable;
|
|
3077
3096
|
return `ALTER TABLE ${q(n)} ALTER COLUMN ${q(t)} ${I(e, "mssql")} ${i ? "NULL" : "NOT NULL"};`;
|
|
3078
|
-
},
|
|
3097
|
+
}, Ha = (e, t) => {
|
|
3079
3098
|
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 ${q(e.table)} DROP CONSTRAINT [' + @dc + ']');` + (t ? ` ${t}` : "");
|
|
3080
3099
|
if (!e.hasDefault) return n;
|
|
3081
|
-
let r =
|
|
3100
|
+
let r = Ia(e.defaultValue, "SYSUTCDATETIME()");
|
|
3082
3101
|
if (!r) return n;
|
|
3083
3102
|
let i = r.replace(/^DEFAULT\s+/i, "");
|
|
3084
3103
|
return `${n} ALTER TABLE ${q(e.table)} ADD DEFAULT ${i} FOR ${q(e.column)};`;
|
|
3085
|
-
}, q = (e) => `[${e.replace(/]/g, "]]")}]`,
|
|
3086
|
-
let t =
|
|
3104
|
+
}, q = (e) => `[${e.replace(/]/g, "]]")}]`, Ua = (e) => {
|
|
3105
|
+
let t = ta(e, "mssql");
|
|
3087
3106
|
if (t !== void 0) return t;
|
|
3088
3107
|
switch (e.type) {
|
|
3089
3108
|
case "id": return "NVARCHAR(64)";
|
|
3090
3109
|
case "reference": return e.referenceStorage === "numeric" ? "BIGINT" : "NVARCHAR(64)";
|
|
3091
3110
|
case "integer": return "INT";
|
|
3092
3111
|
case "real": return "FLOAT";
|
|
3093
|
-
case "decimal": return
|
|
3112
|
+
case "decimal": return $i(e, "DECIMAL");
|
|
3094
3113
|
case "bigint": return "BIGINT";
|
|
3095
3114
|
case "boolean": return "BIT";
|
|
3096
3115
|
case "timestamp": return "DATETIME2(6)";
|
|
@@ -3098,53 +3117,53 @@ BEGIN
|
|
|
3098
3117
|
case "bytes": return "VARBINARY(MAX)";
|
|
3099
3118
|
default: return "NVARCHAR(MAX)";
|
|
3100
3119
|
}
|
|
3101
|
-
},
|
|
3120
|
+
}, Wa = (e, t, n = !1) => {
|
|
3102
3121
|
if (e.type === "id" && e.idScheme?.kind === "numeric") return Gt(e.name, "mssql");
|
|
3103
|
-
let r = e.type === "text" && t?.has(e.name) ? `NVARCHAR(${Math.min(e.maxLength ?? 450, 450)})` :
|
|
3122
|
+
let r = e.type === "text" && t?.has(e.name) ? `NVARCHAR(${Math.min(e.maxLength ?? 450, 450)})` : Ua(e), i = xa(e, "mssql");
|
|
3104
3123
|
if (i) return `${q(e.name)} ${i}`;
|
|
3105
3124
|
let a = [q(e.name), r];
|
|
3106
|
-
if (e.type === "json" && a.push(`CHECK ${
|
|
3107
|
-
let t =
|
|
3125
|
+
if (e.type === "json" && a.push(`CHECK ${kt(q(e.name))}`), e.type === "array" && a.push(`CHECK (${q(e.name)} IS NULL OR ISJSON(${q(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) {
|
|
3126
|
+
let t = Ia(e.defaultValue, "SYSUTCDATETIME()");
|
|
3108
3127
|
t && a.push(t);
|
|
3109
3128
|
}
|
|
3110
|
-
return e.references && (a.push(`REFERENCES ${q(e.references.table)} (${q(e.references.column)})`), e.references.onDelete && a.push(`ON DELETE ${
|
|
3111
|
-
},
|
|
3112
|
-
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) => ` ${
|
|
3129
|
+
return e.references && (a.push(`REFERENCES ${q(e.references.table)} (${q(e.references.column)})`), e.references.onDelete && a.push(`ON DELETE ${Pa[e.references.onDelete]}`)), a.join(" ");
|
|
3130
|
+
}, Ga = (e) => {
|
|
3131
|
+
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) => ` ${Wa(t, n, Ca(e))}`).join(",\n"), i = `CREATE TABLE ${q(e.table)} (\n${r}${wa(e, q)}\n)`, a = [`IF OBJECT_ID(N'${t(e.table)}', N'U') IS NULL EXEC(N'${t(i)}')`];
|
|
3113
3132
|
for (let n of e.indexes) {
|
|
3114
3133
|
if (n.name === `${e.table}_pkey`) continue;
|
|
3115
|
-
let r = `CREATE ${n.unique ? "UNIQUE " : ""}INDEX ${q(n.name)} ON ${q(e.table)} (${n.columns.map(q).join(", ")})${
|
|
3134
|
+
let r = `CREATE ${n.unique ? "UNIQUE " : ""}INDEX ${q(n.name)} ON ${q(e.table)} (${n.columns.map(q).join(", ")})${Qa(n)}`;
|
|
3116
3135
|
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)}')`);
|
|
3117
3136
|
}
|
|
3118
3137
|
return a;
|
|
3119
|
-
},
|
|
3120
|
-
let r = `${e.table}${
|
|
3138
|
+
}, Ka = (e) => `__dropped_${e.replace(/[-:T.Z]/g, "").slice(0, 14)}`, qa = (e, t) => `DROP TABLE IF EXISTS ${t(e.table)};`, Ja = (e, t, n) => {
|
|
3139
|
+
let r = `${e.table}${Ka(t)}`;
|
|
3121
3140
|
return `ALTER TABLE ${n(e.table)} RENAME TO ${n(r)};`;
|
|
3122
|
-
},
|
|
3123
|
-
if (e === void 0 || !
|
|
3141
|
+
}, Ya = (e) => {
|
|
3142
|
+
if (e === void 0 || !Da(e)) return;
|
|
3124
3143
|
let t = typeof e.maxLength == "number" && e.maxLength > 0 ? e.maxLength : void 0;
|
|
3125
|
-
return t === void 0 ?
|
|
3126
|
-
},
|
|
3127
|
-
let r =
|
|
3144
|
+
return t === void 0 ? Ea : Math.min(Ea, t);
|
|
3145
|
+
}, Xa = (e, t, n) => {
|
|
3146
|
+
let r = Ya(pa(e, t, n));
|
|
3128
3147
|
return r === void 0 ? G(n) : `${G(n)}(${r})`;
|
|
3129
|
-
},
|
|
3130
|
-
let n =
|
|
3148
|
+
}, Za = (e) => e.startsWith("(") ? e : W(e), Qa = (e) => e.where === void 0 ? "" : ` WHERE ${e.where}`, $a = (e, t) => {
|
|
3149
|
+
let n = Ne(e.index.kind, e.index.kindOptions), r = e.index.columns.map(Za);
|
|
3131
3150
|
if (n.opclass !== void 0) {
|
|
3132
3151
|
if (r.length !== 1) throw Error("HNSW index requires exactly one column");
|
|
3133
3152
|
r[0] = `${r[0]} ${n.opclass}`;
|
|
3134
3153
|
}
|
|
3135
|
-
return `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX ${t ? "CONCURRENTLY " : ""}IF NOT EXISTS ${W(e.index.name)} ON ${W(e.table)}${n.using} (${r.join(", ")})${n.withSuffix}${
|
|
3136
|
-
},
|
|
3154
|
+
return `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX ${t ? "CONCURRENTLY " : ""}IF NOT EXISTS ${W(e.index.name)} ON ${W(e.table)}${n.using} (${r.join(", ")})${n.withSuffix}${Qa(e.index)};`;
|
|
3155
|
+
}, eo = (e, t, n = "mariadb") => (to(e.index, n), `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX ${aa(n)}${G(e.index.name)} ON ${G(e.table)} (${e.index.columns.map((n) => Xa(t, e.table, n)).join(", ")});`), to = (e, t) => {
|
|
3137
3156
|
if (e.where !== void 0) throw Error(`Partial index '${e.name}' is not supported by ${t}; uniqueActive must be lowered before applying the plan.`);
|
|
3138
|
-
},
|
|
3157
|
+
}, no = (e) => `DROP INDEX IF EXISTS ${W(e.index)};`, ro = (e) => `DROP INDEX ${G(e.index)} ON ${G(e.table)};`, io = (e) => `DROP INDEX IF EXISTS ${q(e.index)} ON ${q(e.table)};`, ao = (e, t) => `ALTER TABLE ${t(e.from)} RENAME TO ${t(e.to)};`, oo = (e) => {
|
|
3139
3158
|
let t = (e) => e.replace(/'/g, "''");
|
|
3140
3159
|
return `EXEC sp_rename N'${t(e.from)}', N'${t(e.to)}';`;
|
|
3141
|
-
},
|
|
3160
|
+
}, so = (e) => `ALTER INDEX ${W(e.from)} RENAME TO ${W(e.to)};`, co = (e) => `ALTER TABLE ${G(e.table)} RENAME INDEX ${G(e.from)} TO ${G(e.to)};`, lo = (e) => {
|
|
3142
3161
|
let t = (e) => e.replace(/'/g, "''");
|
|
3143
3162
|
return `EXEC sp_rename N'${t(e.table)}.${t(e.from)}', N'${t(e.to)}', N'INDEX';`;
|
|
3144
|
-
},
|
|
3145
|
-
let t = (e) => e.replace(/'/g, "''"), n = `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX ${q(e.index.name)} ON ${q(e.table)} (${e.index.columns.map(q).join(", ")})${
|
|
3163
|
+
}, uo = (e) => {
|
|
3164
|
+
let t = (e) => e.replace(/'/g, "''"), n = `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX ${q(e.index.name)} ON ${q(e.table)} (${e.index.columns.map(q).join(", ")})${Qa(e.index)}`;
|
|
3146
3165
|
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)}');`;
|
|
3147
|
-
},
|
|
3166
|
+
}, fo = (e, t, n) => {
|
|
3148
3167
|
let r = n.find((t) => t.tableName === e);
|
|
3149
3168
|
if (!r) return [];
|
|
3150
3169
|
let i = [];
|
|
@@ -3156,13 +3175,13 @@ BEGIN
|
|
|
3156
3175
|
}
|
|
3157
3176
|
}
|
|
3158
3177
|
return i;
|
|
3159
|
-
},
|
|
3178
|
+
}, po = (e) => `ALTER TABLE ${W(e.table)} ADD CONSTRAINT ${W(`${e.table}_${e.column}_key`)} UNIQUE (${W(e.column)});`, mo = (e, t) => `ALTER TABLE ${G(e.table)} ADD CONSTRAINT ${G(`${e.table}_${e.column}_key`)} UNIQUE (${Xa(t, e.table, e.column)});`, ho = (e) => {
|
|
3160
3179
|
let t = e.fields.map((e) => W(e)).join(", ");
|
|
3161
3180
|
return `ALTER TABLE ${W(e.table)} ADD CONSTRAINT ${W(e.name)} UNIQUE (${t});`;
|
|
3162
|
-
},
|
|
3163
|
-
let n = e.fields.map((n) =>
|
|
3181
|
+
}, go = (e, t) => {
|
|
3182
|
+
let n = e.fields.map((n) => Xa(t, e.table, n)).join(", ");
|
|
3164
3183
|
return `ALTER TABLE ${G(e.table)} ADD CONSTRAINT ${G(e.name)} UNIQUE (${n});`;
|
|
3165
|
-
},
|
|
3184
|
+
}, _o = (e) => `ALTER TABLE ${W(e.table)} DROP CONSTRAINT IF EXISTS ${W(e.name)};`, vo = (e) => `ALTER TABLE ${G(e.table)} DROP INDEX ${G(e.name)};`, yo = (e) => `ALTER TABLE ${W(e.table)} DROP CONSTRAINT IF EXISTS ${W(`${e.table}_${e.column}_key`)};`, bo = (e) => `ALTER TABLE ${G(e.table)} DROP INDEX ${G(`${e.table}_${e.column}_key`)};`, xo = (e, t, n = Na) => {
|
|
3166
3185
|
let r = [], i = t(e.table), a = t(e.column), o = t(e.targetTable), s = t(e.targetColumn);
|
|
3167
3186
|
if (e.orphanPolicy) {
|
|
3168
3187
|
let t = `${a} IS NOT NULL AND ${a} NOT IN (SELECT ${s} FROM ${o})`;
|
|
@@ -3175,10 +3194,10 @@ BEGIN
|
|
|
3175
3194
|
`REFERENCES ${o} (${s})`
|
|
3176
3195
|
];
|
|
3177
3196
|
return e.onDelete && c.push(`ON DELETE ${n[e.onDelete]}`), r.push(c.join(" ") + ";"), r;
|
|
3178
|
-
},
|
|
3197
|
+
}, So = (e) => e.name ?? `${e.table}_${e.column}_fkey`, Co = (e) => `ALTER TABLE ${W(e.table)} DROP CONSTRAINT IF EXISTS ${W(So(e))};`, wo = (e) => `ALTER TABLE ${G(e.table)} DROP FOREIGN KEY ${G(So(e))};`, To = (e, t) => {
|
|
3179
3198
|
let n = e.values.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
|
|
3180
3199
|
return `ALTER TABLE ${t(e.table)} ADD CONSTRAINT ${t(`${e.table}_${e.column}_check`)} CHECK (${t(e.column)} IN (${n}));`;
|
|
3181
|
-
},
|
|
3200
|
+
}, Eo = (e) => `ALTER TABLE ${W(e.table)} DROP CONSTRAINT IF EXISTS ${W(`${e.table}_${e.column}_check`)};`, Do = (e, t) => A.gen(function* () {
|
|
3182
3201
|
let n = yield* e`
|
|
3183
3202
|
SELECT cc.constraint_name AS n, cc.check_clause AS c
|
|
3184
3203
|
FROM information_schema.check_constraints cc
|
|
@@ -3191,18 +3210,18 @@ BEGIN
|
|
|
3191
3210
|
WHERE tc.table_schema = DATABASE() AND tc.table_name = ${t.table}`), A.orElseSucceed(() => []));
|
|
3192
3211
|
for (let e of n) {
|
|
3193
3212
|
let n = String(e.n ?? "");
|
|
3194
|
-
if (n !== "" &&
|
|
3213
|
+
if (n !== "" && mi(String(e.c ?? ""))?.column === t.column) return n;
|
|
3195
3214
|
}
|
|
3196
|
-
}),
|
|
3197
|
-
let r = yield*
|
|
3198
|
-
r !== void 0 && (yield* J(e, `ALTER TABLE ${G(t.table)} DROP CONSTRAINT ${G(r)};`, t.kind, [
|
|
3199
|
-
let i = yield*
|
|
3215
|
+
}), Oo = (e, t, n) => A.gen(function* () {
|
|
3216
|
+
let r = yield* Do(e, t);
|
|
3217
|
+
r !== void 0 && (yield* J(e, `ALTER TABLE ${G(t.table)} DROP CONSTRAINT ${G(r)};`, t.kind, [Yi]));
|
|
3218
|
+
let i = yield* Do(e, t);
|
|
3200
3219
|
if (i === void 0) return;
|
|
3201
3220
|
let a = K(n, t.table, t.column);
|
|
3202
3221
|
if (!a) return yield* A.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.`));
|
|
3203
|
-
yield* J(e, `ALTER TABLE ${G(t.table)} MODIFY COLUMN ${
|
|
3204
|
-
}),
|
|
3205
|
-
let i = e.column, a = r === "mariadb", o = a ? G : r === "mssql" ? q : W, s = a ?
|
|
3222
|
+
yield* J(e, `ALTER TABLE ${G(t.table)} MODIFY COLUMN ${ma(a, t.column)};`, t.kind);
|
|
3223
|
+
}), ko = (e, t, n, r) => {
|
|
3224
|
+
let i = e.column, a = r === "mariadb", o = a ? G : r === "mssql" ? q : W, s = a ? ia(i) : r === "mssql" ? Ua(i) : r === "sqlite" ? Fa(i) : na(i), c = r === "mssql" ? "ADD" : "ADD COLUMN", l = r === "mssql" ? i.type === "json" ? ` CHECK ${kt(o(i.name))}` : i.type === "array" ? ` CHECK (${o(i.name)} IS NULL OR ISJSON(${o(i.name)}) = 1)` : "" : "", u = (e) => a ? va(e, i) : r === "mssql" ? Ia(e, "SYSUTCDATETIME()") : r === "sqlite" ? Ia(e, "CURRENT_TIMESTAMP") : ba(e, i), d = xa(i, r);
|
|
3206
3225
|
if (d) {
|
|
3207
3226
|
let t = r === "mssql" ? `${o(i.name)} ${d}` : `${o(i.name)} ${s} ${d}`;
|
|
3208
3227
|
return {
|
|
@@ -3231,7 +3250,7 @@ BEGIN
|
|
|
3231
3250
|
post: p ? [p] : []
|
|
3232
3251
|
};
|
|
3233
3252
|
return i.unique && i.type !== "id" && (m.uniquePending = !0), 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;
|
|
3234
|
-
},
|
|
3253
|
+
}, Ao = /* @__PURE__ */ new Set([
|
|
3235
3254
|
"drop-index",
|
|
3236
3255
|
"drop-check",
|
|
3237
3256
|
"drop-unique",
|
|
@@ -3239,7 +3258,7 @@ BEGIN
|
|
|
3239
3258
|
"drop-foreign-key",
|
|
3240
3259
|
"drop-column",
|
|
3241
3260
|
"drop-table"
|
|
3242
|
-
]),
|
|
3261
|
+
]), jo = (e) => {
|
|
3243
3262
|
let t = new Map(e.map((e) => [e.tableName, e]));
|
|
3244
3263
|
return (e, n) => {
|
|
3245
3264
|
let r = t.get(e);
|
|
@@ -3259,15 +3278,15 @@ BEGIN
|
|
|
3259
3278
|
...o
|
|
3260
3279
|
};
|
|
3261
3280
|
};
|
|
3262
|
-
}, J = (e, t, n, r = []) => e.unsafe(t).pipe(A.catchIf((e) =>
|
|
3263
|
-
process.stderr.write(
|
|
3281
|
+
}, J = (e, t, n, r = []) => e.unsafe(t).pipe(A.catchIf((e) => Gi(e, r), () => A.void), A.tapError((e) => A.sync(() => {
|
|
3282
|
+
process.stderr.write(Pe(`applier: statement failed (op=${n})`, t, e, 400));
|
|
3264
3283
|
})), A.mapError((e) => {
|
|
3265
|
-
let r =
|
|
3284
|
+
let r = Pe(`applier: statement failed (op=${n})`, t, e, 400).trim();
|
|
3266
3285
|
return Object.assign(e, { message: r });
|
|
3267
|
-
}), A.map(() => void 0)), Y = (e, t, n, r) =>
|
|
3286
|
+
}), A.map(() => void 0)), Y = (e, t, n, r) => Mo(e, t, za(t, n), r), Mo = (e, t, n, r) => {
|
|
3268
3287
|
if (n.length === 0) return A.void;
|
|
3269
3288
|
let i = (e) => (n) => {
|
|
3270
|
-
let i =
|
|
3289
|
+
let i = Pe(`applier: statement failed (op=${r}, sqlite rebuild of ${t})`, e, n, 400).trim();
|
|
3271
3290
|
return process.stderr.write(`${i}\n`), Object.assign(n, { message: i });
|
|
3272
3291
|
};
|
|
3273
3292
|
return A.scoped(A.gen(function* () {
|
|
@@ -3281,7 +3300,7 @@ BEGIN
|
|
|
3281
3300
|
}
|
|
3282
3301
|
}), A.ignore(a("PRAGMA foreign_keys = ON")));
|
|
3283
3302
|
}));
|
|
3284
|
-
},
|
|
3303
|
+
}, No = (e, t) => A.gen(function* () {
|
|
3285
3304
|
let n = (yield* e`
|
|
3286
3305
|
SELECT ck.name, ck.definition, ck.is_disabled AS disabled,
|
|
3287
3306
|
ck.is_not_trusted AS untrusted, ck.is_not_for_replication AS notForReplication
|
|
@@ -3293,17 +3312,17 @@ BEGIN
|
|
|
3293
3312
|
) ORDER BY ck.name
|
|
3294
3313
|
`).map((e) => ({
|
|
3295
3314
|
...e,
|
|
3296
|
-
definition:
|
|
3315
|
+
definition: Qi(e.definition, t.from, t.to)
|
|
3297
3316
|
})), r = (e) => i(e, "mssql"), a = (e) => e.replace(/'/g, "''");
|
|
3298
3317
|
return yield* X(e, [
|
|
3299
3318
|
...n.map((e) => `ALTER TABLE ${r(t.table)} DROP CONSTRAINT ${r(e.name)}`),
|
|
3300
3319
|
`EXEC sp_rename N'${a(`${r(t.table)}.${r(t.from)}`)}', N'${a(t.to)}', 'COLUMN';`,
|
|
3301
3320
|
...n.flatMap((e) => [`ALTER TABLE ${r(t.table)} WITH ${e.untrusted ? "NOCHECK" : "CHECK"} ADD CONSTRAINT ${r(e.name)} CHECK ${e.notForReplication ? "NOT FOR REPLICATION " : ""}${e.definition}`, ...e.disabled ? [`ALTER TABLE ${r(t.table)} NOCHECK CONSTRAINT ${r(e.name)}`] : []])
|
|
3302
3321
|
], t.kind);
|
|
3303
|
-
}),
|
|
3322
|
+
}), Po = (e, t, n) => e == null ? e : t.type === "json" ? JSON.stringify(e) : (t.type === "array" || t.type === "vector") && n !== "postgres" ? typeof e == "string" ? e : JSON.stringify(e) : e, X = (e, t, n) => A.forEach(t, (t) => J(e, t, n), { discard: !0 }), Fo = (e, t) => {
|
|
3304
3323
|
let n = Math.max(1, Math.floor(Number.isFinite(t) ? t : 1));
|
|
3305
3324
|
return e.literal(N(e) === "mssql" ? `OFFSET 0 ROWS FETCH NEXT ${n} ROWS ONLY` : `LIMIT ${n}`);
|
|
3306
|
-
},
|
|
3325
|
+
}, Io = (e, t, n, r) => e.unsafe(`SELECT ${r === void 0 ? "*" : i(r, t)} FROM ${i(n, t)} WHERE 1=0`).pipe(A.as(!0), A.catchAll(() => A.succeed(!1))), Lo = (e, t) => Vo(e, t, vt, P), Ro = (e, t) => Vo(e, t, de, "_voltro_migration_plans"), zo = (e, t) => Vo(e, t, ci, B), Bo = (e, t) => Vo(e, t, fe, he), Vo = (e, t, n, r) => A.gen(function* () {
|
|
3307
3326
|
let i = wr([n], t).tables[0];
|
|
3308
3327
|
if (!i) return yield* A.die(/* @__PURE__ */ Error(`migration applier: the ${r} table descriptor produced no snapshot. This is a framework bug.`));
|
|
3309
3328
|
let a = {
|
|
@@ -3312,17 +3331,17 @@ BEGIN
|
|
|
3312
3331
|
columns: i.columns,
|
|
3313
3332
|
indexes: []
|
|
3314
3333
|
}, o = yield* e.onDialectOrElse({
|
|
3315
|
-
mysql: () =>
|
|
3316
|
-
mssql: () => A.succeed(
|
|
3317
|
-
sqlite: () => A.succeed(
|
|
3318
|
-
orElse: () => A.succeed(
|
|
3334
|
+
mysql: () => H(e).pipe(A.map((e) => Ma(a, e))),
|
|
3335
|
+
mssql: () => A.succeed(Ga(a)),
|
|
3336
|
+
sqlite: () => A.succeed(Ra(a)),
|
|
3337
|
+
orElse: () => A.succeed(Ta(a))
|
|
3319
3338
|
});
|
|
3320
3339
|
yield* A.forEach(o, (t) => J(e, t, "resume-ledger-bootstrap"), { discard: !0 });
|
|
3321
|
-
}),
|
|
3340
|
+
}), Ho = (e) => e`
|
|
3322
3341
|
SELECT ${e("runId")}, ${e("planFingerprint")}, ${e("opIndex")},
|
|
3323
3342
|
${e("status")}, ${e("payload")}
|
|
3324
3343
|
FROM ${e(P)}
|
|
3325
|
-
`,
|
|
3344
|
+
`, Uo = (e, t, n, r) => A.gen(function* () {
|
|
3326
3345
|
let i = yield* U(e, (/* @__PURE__ */ new Date()).toISOString());
|
|
3327
3346
|
yield* A.forEach(r, ({ index: r, planned: a }) => e`
|
|
3328
3347
|
INSERT INTO ${e(P)}
|
|
@@ -3331,10 +3350,10 @@ BEGIN
|
|
|
3331
3350
|
${e("createdAt")})
|
|
3332
3351
|
VALUES
|
|
3333
3352
|
(${`mop_${t}_${r}`}, ${t}, ${n}, ${r},
|
|
3334
|
-
${a.op.kind}, ${
|
|
3353
|
+
${a.op.kind}, ${bt(a.op)}, ${"pending"},
|
|
3335
3354
|
${JSON.stringify(a)}, ${i})
|
|
3336
3355
|
`, { discard: !0 });
|
|
3337
|
-
}),
|
|
3356
|
+
}), Wo = (e, t, n, r, i) => A.gen(function* () {
|
|
3338
3357
|
let a = yield* U(e, (/* @__PURE__ */ new Date()).toISOString());
|
|
3339
3358
|
if (r === "applied") {
|
|
3340
3359
|
yield* e`
|
|
@@ -3350,7 +3369,7 @@ BEGIN
|
|
|
3350
3369
|
SET ${e("status")} = ${r}, ${e("startedAt")} = ${a}
|
|
3351
3370
|
WHERE ${e("runId")} = ${t} AND ${e("opIndex")} = ${n}
|
|
3352
3371
|
`;
|
|
3353
|
-
}),
|
|
3372
|
+
}), Go = (e, t, n, r) => A.gen(function* () {
|
|
3354
3373
|
let i = yield* U(e, (/* @__PURE__ */ new Date()).toISOString());
|
|
3355
3374
|
r.length > 0 && (yield* e`
|
|
3356
3375
|
UPDATE ${e(P)}
|
|
@@ -3361,35 +3380,35 @@ BEGIN
|
|
|
3361
3380
|
SET ${e("status")} = ${"pending"}
|
|
3362
3381
|
WHERE ${e("runId")} = ${t} AND ${e("opIndex")} IN ${e.in(n)}
|
|
3363
3382
|
`);
|
|
3364
|
-
}),
|
|
3365
|
-
if (
|
|
3383
|
+
}), Ko = (e, t) => t === void 0 ? e`DELETE FROM ${e(P)}`.pipe(A.asVoid) : e`DELETE FROM ${e(P)} WHERE ${e("runId")} = ${t}`.pipe(A.asVoid), qo = (e) => Ho(e).pipe(A.map((e) => e.filter((e) => e.status === "started" || e.status === "added" || e.status === "applied").map((e) => JSON.parse(e.payload))), A.catchAll(() => A.succeed([]))), Jo = (e) => Ko(e).pipe(A.catchAll(() => A.void)), Yo = (e, t, n) => A.gen(function* () {
|
|
3384
|
+
if (Ot(n.op, n.classification, t) !== "artefact-repair") return "clean";
|
|
3366
3385
|
let r = n.op, a = (e) => i(e, t);
|
|
3367
3386
|
if (t === "sqlite" || t === "turso") {
|
|
3368
3387
|
if (!("table" in r)) return "clean";
|
|
3369
|
-
let n = `${r.table}${
|
|
3370
|
-
return (yield*
|
|
3388
|
+
let n = `${r.table}${Ct}`;
|
|
3389
|
+
return (yield* Io(e, t, n)) ? ((yield* Io(e, t, r.table)) ? yield* J(e, `DROP TABLE ${a(n)}`, "resume-repair") : yield* J(e, `ALTER TABLE ${a(n)} RENAME TO ${a(r.table)}`, "resume-repair"), yield* A.logWarning(`migration resume: reconciled an interrupted sqlite table rebuild on '${r.table}' — replaying the operation`).pipe(A.annotateLogs({ scope: "voltro:migrate" })), "outstanding") : "clean";
|
|
3371
3390
|
}
|
|
3372
3391
|
if (r.kind !== "alter-column-type") return "clean";
|
|
3373
|
-
let o = `${r.column}${
|
|
3392
|
+
let o = `${r.column}${wt}`, s = `${r.column}${Tt}`, c = yield* Io(e, t, r.table, r.column), l = yield* Io(e, t, r.table, o), u = yield* Io(e, t, r.table, s), d = (e) => A.logWarning(`migration resume: ${e}`).pipe(A.annotateLogs({ scope: "voltro:migrate" }));
|
|
3374
3393
|
return !l && !u ? "clean" : c && l && !u ? (yield* J(e, `ALTER TABLE ${a(r.table)} DROP COLUMN ${a(o)}`, "resume-repair"), yield* d(`dropped a half-populated shadow column '${r.table}.${o}' — replaying the type change`), "outstanding") : !c && l && u ? (yield* J(e, `ALTER TABLE ${a(r.table)} RENAME COLUMN ${a(o)} TO ${a(r.column)}`, "resume-repair"), yield* J(e, `ALTER TABLE ${a(r.table)} DROP COLUMN ${a(s)}`, "resume-repair"), yield* d(`completed an interrupted shadow swap on '${r.table}.${r.column}'`), "applied") : c && !l && u ? (yield* J(e, `ALTER TABLE ${a(r.table)} DROP COLUMN ${a(s)}`, "resume-repair"), yield* d(`dropped the leftover pre-swap column '${r.table}.${s}'`), "applied") : yield* A.die(/* @__PURE__ */ Error(`applyPlan: an interrupted online type change on '${r.table}.${r.column}' left a shadow-swap state this resume cannot classify (column=${c}, ${o}=${l}, ${s}=${u}).\nNothing was changed. Inspect those three columns and reconcile them by hand — the data is in whichever of them is populated — then re-run the migration.`));
|
|
3375
|
-
}),
|
|
3376
|
-
let o = process.hrtime.bigint(), s =
|
|
3394
|
+
}), Xo = (e, t, n, r = "fresh", a) => A.gen(function* () {
|
|
3395
|
+
let o = process.hrtime.bigint(), s = jo(n.declared), c = t.op, l = N(e);
|
|
3377
3396
|
switch (c.kind) {
|
|
3378
3397
|
case "create-table": {
|
|
3379
3398
|
let t = yield* e.onDialectOrElse({
|
|
3380
|
-
mysql: () =>
|
|
3381
|
-
mssql: () => A.succeed(
|
|
3382
|
-
sqlite: () => A.succeed(
|
|
3383
|
-
orElse: () => A.succeed(
|
|
3399
|
+
mysql: () => H(e).pipe(A.map((e) => Ma(c, e))),
|
|
3400
|
+
mssql: () => A.succeed(Ga(c)),
|
|
3401
|
+
sqlite: () => A.succeed(Ra(c)),
|
|
3402
|
+
orElse: () => A.succeed(Ta(c))
|
|
3384
3403
|
}), n = yield* e.onDialectOrElse({
|
|
3385
|
-
mysql: () => A.succeed([
|
|
3404
|
+
mysql: () => A.succeed([Ki]),
|
|
3386
3405
|
orElse: () => A.succeed([])
|
|
3387
3406
|
});
|
|
3388
3407
|
for (let r of t) yield* J(e, r, c.kind, n);
|
|
3389
3408
|
break;
|
|
3390
3409
|
}
|
|
3391
3410
|
case "drop-table": {
|
|
3392
|
-
let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString(), r = (e) => t ?
|
|
3411
|
+
let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString(), r = (e) => t ? Ja(c, n, e) : qa(c, e);
|
|
3393
3412
|
yield* e.onDialectOrElse({
|
|
3394
3413
|
mysql: () => J(e, r(G), c.kind),
|
|
3395
3414
|
orElse: () => J(e, r(W), c.kind)
|
|
@@ -3399,61 +3418,61 @@ BEGIN
|
|
|
3399
3418
|
case "drop-column": {
|
|
3400
3419
|
let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString();
|
|
3401
3420
|
yield* e.onDialectOrElse({
|
|
3402
|
-
mysql: () =>
|
|
3403
|
-
sqlite: () => J(e, t ?
|
|
3404
|
-
orElse: () => J(e, t ?
|
|
3421
|
+
mysql: () => H(e).pipe(A.flatMap((r) => J(e, t ? la(c, n, G) : sa(c, r), c.kind, t ? [] : [qi]))),
|
|
3422
|
+
sqlite: () => J(e, t ? la(c, n, W) : oa(c, W, !1), c.kind, t ? [] : [Ji]),
|
|
3423
|
+
orElse: () => J(e, t ? la(c, n, W) : oa(c, W), c.kind)
|
|
3405
3424
|
});
|
|
3406
3425
|
break;
|
|
3407
3426
|
}
|
|
3408
3427
|
case "rename-column":
|
|
3409
3428
|
yield* e.onDialectOrElse({
|
|
3410
|
-
mysql: () => J(e,
|
|
3411
|
-
mssql: () =>
|
|
3412
|
-
orElse: () => J(e,
|
|
3429
|
+
mysql: () => J(e, ca(c, G), c.kind),
|
|
3430
|
+
mssql: () => No(e, c),
|
|
3431
|
+
orElse: () => J(e, ca(c, W), c.kind)
|
|
3413
3432
|
});
|
|
3414
3433
|
break;
|
|
3415
3434
|
case "add-index":
|
|
3416
3435
|
yield* e.onDialectOrElse({
|
|
3417
|
-
sqlite: () => J(e,
|
|
3418
|
-
mysql: () =>
|
|
3419
|
-
mssql: () => X(e, [...
|
|
3420
|
-
orElse: () => J(e,
|
|
3436
|
+
sqlite: () => J(e, $a(c, !1), c.kind),
|
|
3437
|
+
mysql: () => H(e).pipe(A.flatMap((t) => J(e, eo(c, n.declared, t), c.kind, [Ki]))),
|
|
3438
|
+
mssql: () => X(e, [...fo(c.table, c.index.columns, n.declared), uo(c)], c.kind),
|
|
3439
|
+
orElse: () => J(e, $a(c, t.classification === "online-required"), c.kind)
|
|
3421
3440
|
});
|
|
3422
3441
|
break;
|
|
3423
3442
|
case "drop-index":
|
|
3424
3443
|
yield* e.onDialectOrElse({
|
|
3425
|
-
mysql: () => J(e,
|
|
3426
|
-
mssql: () => J(e,
|
|
3427
|
-
orElse: () => J(e,
|
|
3444
|
+
mysql: () => J(e, ro(c), c.kind),
|
|
3445
|
+
mssql: () => J(e, io(c), c.kind),
|
|
3446
|
+
orElse: () => J(e, no(c), c.kind)
|
|
3428
3447
|
});
|
|
3429
3448
|
break;
|
|
3430
3449
|
case "rename-table":
|
|
3431
3450
|
yield* e.onDialectOrElse({
|
|
3432
|
-
mysql: () => J(e,
|
|
3433
|
-
mssql: () => J(e,
|
|
3434
|
-
orElse: () => J(e,
|
|
3451
|
+
mysql: () => J(e, ao(c, G), c.kind),
|
|
3452
|
+
mssql: () => J(e, oo(c), c.kind),
|
|
3453
|
+
orElse: () => J(e, ao(c, W), c.kind)
|
|
3435
3454
|
});
|
|
3436
3455
|
break;
|
|
3437
3456
|
case "rename-index":
|
|
3438
3457
|
yield* e.onDialectOrElse({
|
|
3439
|
-
mysql: () => J(e,
|
|
3440
|
-
mssql: () => J(e,
|
|
3441
|
-
orElse: () => J(e,
|
|
3458
|
+
mysql: () => J(e, co(c), c.kind),
|
|
3459
|
+
mssql: () => J(e, lo(c), c.kind),
|
|
3460
|
+
orElse: () => J(e, so(c), c.kind)
|
|
3442
3461
|
});
|
|
3443
3462
|
break;
|
|
3444
3463
|
case "add-unique":
|
|
3445
3464
|
yield* e.onDialectOrElse({
|
|
3446
|
-
mysql: () => J(e,
|
|
3465
|
+
mysql: () => J(e, mo(c, n.declared), c.kind),
|
|
3447
3466
|
sqlite: () => Y(e, c.table, n.declared, c.kind),
|
|
3448
|
-
mssql: () => X(e, [...
|
|
3449
|
-
orElse: () => J(e,
|
|
3467
|
+
mssql: () => X(e, [...fo(c.table, [c.column], n.declared), po(c)], c.kind),
|
|
3468
|
+
orElse: () => J(e, po(c), c.kind)
|
|
3450
3469
|
});
|
|
3451
3470
|
break;
|
|
3452
3471
|
case "drop-unique":
|
|
3453
3472
|
yield* e.onDialectOrElse({
|
|
3454
|
-
mysql: () => J(e,
|
|
3473
|
+
mysql: () => J(e, bo(c), c.kind),
|
|
3455
3474
|
sqlite: () => Y(e, c.table, n.declared, c.kind),
|
|
3456
|
-
orElse: () => J(e,
|
|
3475
|
+
orElse: () => J(e, yo(c), c.kind)
|
|
3457
3476
|
});
|
|
3458
3477
|
break;
|
|
3459
3478
|
case "add-enum-value":
|
|
@@ -3461,49 +3480,49 @@ BEGIN
|
|
|
3461
3480
|
pg: () => c.enumName === void 0 ? A.die(/* @__PURE__ */ Error(`add-enum-value on postgres needs the type name for ${c.table}.${c.column}; the plan carries none.`)) : J(e, `ALTER TYPE ${i(c.enumName, "postgres")} ADD VALUE IF NOT EXISTS '${c.value.replace(/'/g, "''")}'`, c.kind),
|
|
3462
3481
|
mysql: () => {
|
|
3463
3482
|
let t = K(n.declared, c.table, c.column);
|
|
3464
|
-
return t === void 0 || t.enumValues === void 0 || t.enumValues.length === 0 ? A.die(/* @__PURE__ */ Error(`add-enum-value on the mysql family needs the declared column ${c.table}.${c.column} and its labels; the declaration carries none.`)) :
|
|
3483
|
+
return t === void 0 || t.enumValues === void 0 || t.enumValues.length === 0 ? A.die(/* @__PURE__ */ Error(`add-enum-value on the mysql family needs the declared column ${c.table}.${c.column} and its labels; the declaration carries none.`)) : A.flatMap(_a(e, c.table, t, c.column), (t) => J(e, t, c.kind));
|
|
3465
3484
|
},
|
|
3466
3485
|
orElse: () => A.void
|
|
3467
3486
|
});
|
|
3468
3487
|
break;
|
|
3469
3488
|
case "add-unique-composite":
|
|
3470
3489
|
yield* e.onDialectOrElse({
|
|
3471
|
-
mysql: () => J(e,
|
|
3490
|
+
mysql: () => J(e, go(c, n.declared), c.kind),
|
|
3472
3491
|
sqlite: () => Y(e, c.table, n.declared, c.kind),
|
|
3473
|
-
mssql: () => X(e, [...
|
|
3474
|
-
orElse: () => J(e,
|
|
3492
|
+
mssql: () => X(e, [...fo(c.table, c.fields, n.declared), ho(c)], c.kind),
|
|
3493
|
+
orElse: () => J(e, ho(c), c.kind)
|
|
3475
3494
|
});
|
|
3476
3495
|
break;
|
|
3477
3496
|
case "drop-unique-composite":
|
|
3478
3497
|
yield* e.onDialectOrElse({
|
|
3479
|
-
mysql: () => J(e,
|
|
3498
|
+
mysql: () => J(e, vo(c), c.kind),
|
|
3480
3499
|
sqlite: () => Y(e, c.table, n.declared, c.kind),
|
|
3481
|
-
orElse: () => J(e,
|
|
3500
|
+
orElse: () => J(e, _o(c), c.kind)
|
|
3482
3501
|
});
|
|
3483
3502
|
break;
|
|
3484
3503
|
case "add-foreign-key":
|
|
3485
3504
|
yield* e.onDialectOrElse({
|
|
3486
|
-
mysql: () => X(e,
|
|
3505
|
+
mysql: () => X(e, xo(c, G), c.kind),
|
|
3487
3506
|
sqlite: () => Y(e, c.table, n.declared, c.kind),
|
|
3488
|
-
mssql: () => X(e,
|
|
3489
|
-
orElse: () => X(e,
|
|
3507
|
+
mssql: () => X(e, xo(c, q, Pa), c.kind),
|
|
3508
|
+
orElse: () => X(e, xo(c, W), c.kind)
|
|
3490
3509
|
});
|
|
3491
3510
|
break;
|
|
3492
3511
|
case "add-column": {
|
|
3493
|
-
let i =
|
|
3512
|
+
let i = ko(c, t, s, yield* e.onDialectOrElse({
|
|
3494
3513
|
mysql: () => A.succeed("mariadb"),
|
|
3495
3514
|
mssql: () => A.succeed("mssql"),
|
|
3496
3515
|
sqlite: () => A.succeed("sqlite"),
|
|
3497
3516
|
orElse: () => A.succeed("postgres")
|
|
3498
3517
|
}));
|
|
3499
|
-
if (!(r === "resume" && (yield*
|
|
3518
|
+
if (!(r === "resume" && (yield* Io(e, N(e), c.table, c.column.name)))) for (let t of i.pre) yield* J(e, t, c.kind);
|
|
3500
3519
|
let u = t.classification === "online-required" || i.batchSize !== void 0 || i.sleepMs !== void 0, d = A.gen(function* () {
|
|
3501
3520
|
if (i.backfillKind === "sql" && i.backfillSql) {
|
|
3502
3521
|
if (t.classification !== "online-required" && i.batchSize === void 0) yield* e`UPDATE ${e(c.table)} SET ${e(c.column.name)} = ${i.backfillSql}`;
|
|
3503
3522
|
else {
|
|
3504
3523
|
let t = i.batchSize ?? 5e3, n = i.sleepMs ?? 0, r, a = 0;
|
|
3505
3524
|
for (;;) {
|
|
3506
|
-
let o = r === void 0 ? yield* e`SELECT ${e("id")} FROM ${e(c.table)} WHERE ${e(c.column.name)} IS NULL ORDER BY ${e("id")} ${
|
|
3525
|
+
let o = r === void 0 ? yield* e`SELECT ${e("id")} FROM ${e(c.table)} WHERE ${e(c.column.name)} IS NULL ORDER BY ${e("id")} ${Fo(e, t)}` : yield* e`SELECT ${e("id")} FROM ${e(c.table)} WHERE ${e(c.column.name)} IS NULL AND ${e("id")} > ${r} ORDER BY ${e("id")} ${Fo(e, t)}`;
|
|
3507
3526
|
if (o.length === 0) break;
|
|
3508
3527
|
let s = o.map((e) => e.id);
|
|
3509
3528
|
yield* e`UPDATE ${e(c.table)} SET ${e(c.column.name)} = ${i.backfillSql} WHERE ${e("id")} IN ${e.in(s)}`, a += o.length, yield* A.logInfo(`backfill ${c.table}.${c.column.name}: ${a} rows`).pipe(A.annotateLogs({
|
|
@@ -3515,7 +3534,7 @@ BEGIN
|
|
|
3515
3534
|
} else if (i.backfillKind === "js" && i.backfillJs) {
|
|
3516
3535
|
let t = i.batchSize ?? 1e3, r = i.sleepMs ?? 0, a = n.declared.find((e) => e.tableName === c.table), o, s = 0;
|
|
3517
3536
|
for (;;) {
|
|
3518
|
-
let n = o === void 0 ? yield* e`SELECT * FROM ${e(c.table)} WHERE ${e(c.column.name)} IS NULL ORDER BY ${e("id")} ${
|
|
3537
|
+
let n = o === void 0 ? yield* e`SELECT * FROM ${e(c.table)} WHERE ${e(c.column.name)} IS NULL ORDER BY ${e("id")} ${Fo(e, t)}` : yield* e`SELECT * FROM ${e(c.table)} WHERE ${e(c.column.name)} IS NULL AND ${e("id")} > ${o} ORDER BY ${e("id")} ${Fo(e, t)}`;
|
|
3519
3538
|
if (n.length === 0) break;
|
|
3520
3539
|
let u = a === void 0 ? n : p(n, a, l);
|
|
3521
3540
|
for (let t of u) {
|
|
@@ -3523,7 +3542,7 @@ BEGIN
|
|
|
3523
3542
|
try: () => Promise.resolve(i.backfillJs(t)),
|
|
3524
3543
|
catch: (e) => e
|
|
3525
3544
|
}).pipe(A.orDie);
|
|
3526
|
-
yield* e`UPDATE ${e(c.table)} SET ${e(c.column.name)} = ${
|
|
3545
|
+
yield* e`UPDATE ${e(c.table)} SET ${e(c.column.name)} = ${Po(n, c.column, l)} WHERE ${e("id")} = ${t.id}`;
|
|
3527
3546
|
}
|
|
3528
3547
|
s += u.length, yield* A.logInfo(`backfill ${c.table}.${c.column.name}: ${s} rows processed`).pipe(A.annotateLogs({
|
|
3529
3548
|
scope: "voltro:migrate",
|
|
@@ -3534,7 +3553,7 @@ BEGIN
|
|
|
3534
3553
|
}
|
|
3535
3554
|
}), f = A.gen(function* () {
|
|
3536
3555
|
for (let t of i.post) yield* J(e, t, c.kind);
|
|
3537
|
-
if (
|
|
3556
|
+
if (k(l) && (i.uniquePending === !0 || i.backfillKind !== void 0 && !c.column.nullable)) yield* Y(e, c.table, n.declared, c.kind);
|
|
3538
3557
|
else if (i.uniquePending === !0) {
|
|
3539
3558
|
let t = {
|
|
3540
3559
|
kind: "add-unique",
|
|
@@ -3542,9 +3561,9 @@ BEGIN
|
|
|
3542
3561
|
column: c.column.name
|
|
3543
3562
|
};
|
|
3544
3563
|
yield* e.onDialectOrElse({
|
|
3545
|
-
mysql: () => J(e,
|
|
3546
|
-
mssql: () => X(e, [...
|
|
3547
|
-
orElse: () => J(e,
|
|
3564
|
+
mysql: () => J(e, mo(t, n.declared), c.kind),
|
|
3565
|
+
mssql: () => X(e, [...fo(c.table, [c.column.name], n.declared), po(t)], c.kind),
|
|
3566
|
+
orElse: () => J(e, po(t), c.kind)
|
|
3548
3567
|
});
|
|
3549
3568
|
}
|
|
3550
3569
|
});
|
|
@@ -3566,43 +3585,43 @@ BEGIN
|
|
|
3566
3585
|
yield* e.onDialectOrElse({
|
|
3567
3586
|
mysql: () => {
|
|
3568
3587
|
let t = K(n.declared, c.table, c.column);
|
|
3569
|
-
return t ?
|
|
3588
|
+
return t ? A.flatMap(_a(e, c.table, t, c.column, c.toNullable), (t) => J(e, t, c.kind)) : A.die(/* @__PURE__ */ Error(`alter-column-nullability on mariadb needs the declared column '${c.table}.${c.column}' (to render MODIFY COLUMN); it was not in ctx.declared.`));
|
|
3570
3589
|
},
|
|
3571
3590
|
mssql: () => {
|
|
3572
3591
|
let t = K(n.declared, c.table, c.column);
|
|
3573
|
-
return t ? J(e,
|
|
3592
|
+
return t ? J(e, Va(t, c.column, c.table, c.toNullable), c.kind) : A.die(/* @__PURE__ */ Error(`alter-column-nullability on mssql needs the declared column '${c.table}.${c.column}'.`));
|
|
3574
3593
|
},
|
|
3575
3594
|
sqlite: () => Y(e, c.table, n.declared, c.kind),
|
|
3576
3595
|
orElse: () => J(e, `ALTER TABLE ${W(c.table)} ALTER COLUMN ${W(c.column)} ${c.toNullable ? "DROP NOT NULL" : "SET NOT NULL"};`, c.kind)
|
|
3577
3596
|
});
|
|
3578
3597
|
break;
|
|
3579
3598
|
case "alter-column-default": {
|
|
3580
|
-
let t =
|
|
3599
|
+
let t = pa(n.declared, c.table, c.column), r = K(n.declared, c.table, c.column), i = (e) => c.hasDefault && r !== void 0 && da(r, e) ? r : void 0;
|
|
3581
3600
|
yield* e.onDialectOrElse({
|
|
3582
3601
|
mysql: () => {
|
|
3583
3602
|
let n = i("mariadb");
|
|
3584
|
-
return
|
|
3603
|
+
return A.flatMap(n ? _a(e, c.table, n, c.column) : A.succeed(ua(c, G, (e) => va(e, t))), (t) => J(e, t, c.kind));
|
|
3585
3604
|
},
|
|
3586
3605
|
mssql: () => {
|
|
3587
3606
|
let t = i("mssql");
|
|
3588
|
-
return J(e,
|
|
3607
|
+
return J(e, Ha(c, t ? Va(t, c.column, c.table) : void 0), c.kind);
|
|
3589
3608
|
},
|
|
3590
3609
|
sqlite: () => Y(e, c.table, n.declared, c.kind),
|
|
3591
|
-
orElse: () => J(e,
|
|
3610
|
+
orElse: () => J(e, ua(c, W, (e) => ba(e, t)), c.kind)
|
|
3592
3611
|
});
|
|
3593
3612
|
break;
|
|
3594
3613
|
}
|
|
3595
3614
|
case "alter-column-type": {
|
|
3596
|
-
let r =
|
|
3615
|
+
let r = na(pa(n.declared, c.table, c.column) ?? { type: c.to }), i = c.using ? ` USING ${c.using}` : "";
|
|
3597
3616
|
if (t.classification !== "online-required") {
|
|
3598
3617
|
yield* e.onDialectOrElse({
|
|
3599
3618
|
mysql: () => {
|
|
3600
3619
|
let t = K(n.declared, c.table, c.column);
|
|
3601
|
-
return t ?
|
|
3620
|
+
return t ? A.flatMap(_a(e, c.table, t, c.column), (t) => J(e, t, c.kind)) : A.die(/* @__PURE__ */ Error(`alter-column-type on mariadb needs the declared column '${c.table}.${c.column}' (to render MODIFY COLUMN); it was not in ctx.declared.`));
|
|
3602
3621
|
},
|
|
3603
3622
|
mssql: () => {
|
|
3604
3623
|
let t = K(n.declared, c.table, c.column);
|
|
3605
|
-
return t ? J(e,
|
|
3624
|
+
return t ? J(e, Va(t, c.column, c.table), c.kind) : A.die(/* @__PURE__ */ Error(`alter-column-type on mssql needs the declared column '${c.table}.${c.column}'.`));
|
|
3606
3625
|
},
|
|
3607
3626
|
sqlite: () => Y(e, c.table, n.declared, c.kind),
|
|
3608
3627
|
orElse: () => J(e, `ALTER TABLE ${W(c.table)} ALTER COLUMN ${W(c.column)} TYPE ${r}${i};`, c.kind)
|
|
@@ -3617,7 +3636,7 @@ BEGIN
|
|
|
3617
3636
|
yield* e.unsafe(`ALTER TABLE ${W(c.table)} ADD COLUMN ${W(a)} ${r}`);
|
|
3618
3637
|
let s = c.using ?? W(c.column), l;
|
|
3619
3638
|
for (;;) {
|
|
3620
|
-
let t = l === void 0 ? yield* e`SELECT ${e("id")} FROM ${e(c.table)} WHERE ${e(a)} IS NULL ORDER BY ${e("id")} ${
|
|
3639
|
+
let t = l === void 0 ? yield* e`SELECT ${e("id")} FROM ${e(c.table)} WHERE ${e(a)} IS NULL ORDER BY ${e("id")} ${Fo(e, 5e3)}` : yield* e`SELECT ${e("id")} FROM ${e(c.table)} WHERE ${e(a)} IS NULL AND ${e("id")} > ${l} ORDER BY ${e("id")} ${Fo(e, 5e3)}`;
|
|
3621
3640
|
if (t.length === 0) break;
|
|
3622
3641
|
yield* e.unsafe(`UPDATE ${W(c.table)} SET ${W(a)} = ${s} WHERE ${W(c.column)} IS NOT NULL AND ${W(a)} IS NULL AND ${W("id")} IN (${t.map((e) => `'${e.id.replace(/'/g, "''")}'`).join(",")})`), l = t[t.length - 1].id;
|
|
3623
3642
|
}
|
|
@@ -3626,31 +3645,31 @@ BEGIN
|
|
|
3626
3645
|
}
|
|
3627
3646
|
case "drop-foreign-key":
|
|
3628
3647
|
yield* e.onDialectOrElse({
|
|
3629
|
-
mysql: () => J(e,
|
|
3648
|
+
mysql: () => J(e, wo(c), c.kind),
|
|
3630
3649
|
sqlite: () => Y(e, c.table, n.declared, c.kind),
|
|
3631
|
-
orElse: () => J(e,
|
|
3650
|
+
orElse: () => J(e, Co(c), c.kind)
|
|
3632
3651
|
});
|
|
3633
3652
|
break;
|
|
3634
3653
|
case "add-check":
|
|
3635
3654
|
yield* e.onDialectOrElse({
|
|
3636
|
-
mysql: () => J(e,
|
|
3655
|
+
mysql: () => J(e, To(c, G), c.kind),
|
|
3637
3656
|
sqlite: () => Y(e, c.table, n.declared, c.kind),
|
|
3638
|
-
orElse: () => J(e,
|
|
3657
|
+
orElse: () => J(e, To(c, W), c.kind)
|
|
3639
3658
|
});
|
|
3640
3659
|
break;
|
|
3641
3660
|
case "convert-charset":
|
|
3642
3661
|
yield* e.onDialectOrElse({
|
|
3643
3662
|
mysql: () => A.gen(function* () {
|
|
3644
|
-
let { drops: t, rewrite: r, restores: i } =
|
|
3645
|
-
for (let n of t) yield* J(e, n, c.kind, [
|
|
3663
|
+
let { drops: t, rewrite: r, restores: i } = ja(c, n.declared, yield* ga(e, c.table));
|
|
3664
|
+
for (let n of t) yield* J(e, n, c.kind, [Yi]);
|
|
3646
3665
|
yield* J(e, r, c.kind);
|
|
3647
|
-
for (let t of i) yield* J(e, t, c.kind, [
|
|
3666
|
+
for (let t of i) yield* J(e, t, c.kind, [Xi]);
|
|
3648
3667
|
}),
|
|
3649
3668
|
orElse: () => A.dieMessage("convert-charset requires MySQL or MariaDB")
|
|
3650
3669
|
});
|
|
3651
3670
|
break;
|
|
3652
3671
|
case "reconcile-json-check": {
|
|
3653
|
-
let t = q(c.column), n = c.validation === "value" ?
|
|
3672
|
+
let t = q(c.column), n = c.validation === "value" ? kt(t) : `(${t} IS NULL OR ISJSON(${t}) = 1)`;
|
|
3654
3673
|
yield* e.onDialectOrElse({
|
|
3655
3674
|
mssql: () => X(e, [...c.dropConstraints.map((e) => `ALTER TABLE ${q(c.table)} DROP CONSTRAINT ${q(e)}`), `ALTER TABLE ${q(c.table)} WITH CHECK ADD CHECK ${n}`], c.kind),
|
|
3656
3675
|
orElse: () => A.dieMessage("reconcile-json-check requires SQL Server")
|
|
@@ -3658,9 +3677,9 @@ BEGIN
|
|
|
3658
3677
|
break;
|
|
3659
3678
|
}
|
|
3660
3679
|
case "drop-check": yield* e.onDialectOrElse({
|
|
3661
|
-
mysql: () =>
|
|
3680
|
+
mysql: () => Oo(e, c, n.declared),
|
|
3662
3681
|
sqlite: () => Y(e, c.table, n.declared, c.kind),
|
|
3663
|
-
orElse: () => J(e,
|
|
3682
|
+
orElse: () => J(e, Eo(c), c.kind)
|
|
3664
3683
|
});
|
|
3665
3684
|
}
|
|
3666
3685
|
return {
|
|
@@ -3668,7 +3687,7 @@ BEGIN
|
|
|
3668
3687
|
status: "applied",
|
|
3669
3688
|
durationMs: Number((process.hrtime.bigint() - o) / 1000000n)
|
|
3670
3689
|
};
|
|
3671
|
-
}),
|
|
3690
|
+
}), Zo = (e, t, n, r) => A.gen(function* () {
|
|
3672
3691
|
let i = [...new Set(r.map((e) => e.runId))];
|
|
3673
3692
|
if (i.length > 1) return yield* A.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 \`${P}\`, reconcile the schema by hand, and delete the rows of the run you have finished.`));
|
|
3674
3693
|
let a = i[0], o = [...r].map((e) => ({
|
|
@@ -3678,23 +3697,23 @@ BEGIN
|
|
|
3678
3697
|
})).sort((e, t) => e.index - t.index), s = o.find((e) => e.status === "started"), c = o.filter((e) => e.status === "started").length;
|
|
3679
3698
|
if (c > 1) return yield* A.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 \`${P}\` by hand before re-running.`));
|
|
3680
3699
|
let l = o.filter((e) => e.status === "added");
|
|
3681
|
-
if (yield* A.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} ${
|
|
3700
|
+
if (yield* A.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} ${bt(s.planned.op)}` : ""}${l.length > 0 ? `, ${l.length} column(s) added with the backfill still owed` : ""}`).pipe(A.annotateLogs({ scope: "voltro:migrate" })), o.every((e) => e.status === "pending")) return {
|
|
3682
3701
|
kind: "discard",
|
|
3683
3702
|
runId: a,
|
|
3684
3703
|
why: "no operation had started — no DDL ran"
|
|
3685
3704
|
};
|
|
3686
|
-
let u = s ? yield*
|
|
3705
|
+
let u = s ? yield* Yo(e, t, s.planned) : "clean", d = r[0].planFingerprint;
|
|
3687
3706
|
if (d !== n.toFingerprint) return {
|
|
3688
3707
|
kind: "discard",
|
|
3689
3708
|
runId: a,
|
|
3690
3709
|
why: `the declared schema changed since the interruption (recorded target ${d.slice(0, 12)}…, current ${n.toFingerprint.slice(0, 12)}…) — applying the freshly-diffed plan instead`
|
|
3691
3710
|
};
|
|
3692
|
-
let f = (e) => e.status === "applied" ? !1 : s && e.index === s.index && u !== "clean" ? u === "outstanding" :
|
|
3711
|
+
let f = (e) => e.status === "applied" ? !1 : s && e.index === s.index && u !== "clean" ? u === "outstanding" : St(n, e.planned.op), p = o.filter(f), m = o.filter((e) => e.status !== "applied" && !f(e));
|
|
3693
3712
|
return p.length === 0 ? {
|
|
3694
3713
|
kind: "discard",
|
|
3695
3714
|
runId: a,
|
|
3696
3715
|
why: "every recorded operation had already taken effect"
|
|
3697
|
-
} : (yield*
|
|
3716
|
+
} : (yield* Go(e, a, p.map((e) => e.index), m.map((e) => e.index)), yield* A.logWarning(`migration resume: continuing run ${a} — replaying ${p.length} operation(s), ${o.length - p.length} already applied`).pipe(A.annotateLogs({ scope: "voltro:migrate" })), {
|
|
3698
3717
|
kind: "resume",
|
|
3699
3718
|
runId: a,
|
|
3700
3719
|
ops: p.map((e) => ({
|
|
@@ -3702,7 +3721,7 @@ BEGIN
|
|
|
3702
3721
|
planned: e.planned
|
|
3703
3722
|
}))
|
|
3704
3723
|
});
|
|
3705
|
-
}),
|
|
3724
|
+
}), Qo = (e, t, n) => A.gen(function* () {
|
|
3706
3725
|
for (let r of t.operations) {
|
|
3707
3726
|
let a = r.op;
|
|
3708
3727
|
if (a.kind !== "add-index" || !a.index.unique || a.index.where === void 0 || t.operations.some((e) => e.op.kind === "rename-table" ? e.op.to === a.table : e.op.table === a.table && [
|
|
@@ -3713,7 +3732,7 @@ BEGIN
|
|
|
3713
3732
|
let o = a.index.columns.map((e) => e.startsWith("(") ? e : i(e, n)), s = n === "mssql" ? "" : o.map((e) => ` AND ${e} IS NOT NULL`).join(""), c = n === "mssql" ? "SELECT TOP (1) 1" : "SELECT 1", l = n === "mssql" ? "" : " LIMIT 1";
|
|
3714
3733
|
if ((yield* e.unsafe(`${c} FROM ${i(a.table, n)} WHERE (${a.index.where})${s} GROUP BY ${o.join(", ")} HAVING COUNT(*) > 1${l}`)).length > 0) return yield* A.die(/* @__PURE__ */ Error(`applyPlan: partial unique index '${a.index.name}' on '${a.table}' conflicts with existing qualifying rows. No schema or row changes were applied. Resolve the conflicting data explicitly before retrying.`));
|
|
3715
3734
|
}
|
|
3716
|
-
}),
|
|
3735
|
+
}), $o = (e) => {
|
|
3717
3736
|
let t = e.op, n = (e) => typeof t[e] == "string" ? t[e] : "";
|
|
3718
3737
|
return [
|
|
3719
3738
|
t.kind,
|
|
@@ -3722,13 +3741,13 @@ BEGIN
|
|
|
3722
3741
|
n("name"),
|
|
3723
3742
|
n("to")
|
|
3724
3743
|
].join("\0");
|
|
3725
|
-
},
|
|
3744
|
+
}, es = (e, t, n) => A.acquireUseRelease(ft(e, { schema: n.lockSchema }), () => ts(e, t, n), (e) => e.release.pipe(A.orDie)), ts = (e, t, n) => A.gen(function* () {
|
|
3726
3745
|
let r = t.operations.filter((e) => e.blocked);
|
|
3727
3746
|
if (r.length > 0) return yield* A.die(/* @__PURE__ */ Error(`applyPlan: refusing to execute — ${r.length} blocked operations. Run \`voltro db plan\` to see the fixes.`));
|
|
3728
|
-
let i = Date.now(), a = [], o = N(e), s = yield* n.replan(e), c = new Set(t.operations.filter((e) => !e.blocked).map((e) =>
|
|
3747
|
+
let i = Date.now(), a = [], o = N(e), s = yield* n.replan(e), c = new Set(t.operations.filter((e) => !e.blocked).map((e) => $o(e))), l = {
|
|
3729
3748
|
...s,
|
|
3730
3749
|
operations: s.operations.map((e) => {
|
|
3731
|
-
if (!e.blocked || !c.has(
|
|
3750
|
+
if (!e.blocked || !c.has($o(e))) return e;
|
|
3732
3751
|
let { blocked: t, ...n } = e;
|
|
3733
3752
|
return n;
|
|
3734
3753
|
})
|
|
@@ -3742,48 +3761,48 @@ BEGIN
|
|
|
3742
3761
|
f && (yield* J(e, f, "enum-types"));
|
|
3743
3762
|
let p = hn(n.declared, o);
|
|
3744
3763
|
p && (yield* J(e, p, "enum-types"));
|
|
3745
|
-
let m =
|
|
3764
|
+
let m = _t(o) === "plan-transactional", g = m ? l.operations.filter((e) => e.classification !== "online-required") : [], _ = m ? l.operations.filter((e) => e.classification === "online-required") : l.operations, v = `plan_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`, y = _.map((e, t) => ({
|
|
3746
3765
|
index: t,
|
|
3747
3766
|
planned: e
|
|
3748
3767
|
})), b = "fresh";
|
|
3749
|
-
yield*
|
|
3750
|
-
let x = yield*
|
|
3768
|
+
yield* Qo(e, l, o), yield* Lo(e, o);
|
|
3769
|
+
let x = yield* Ho(e);
|
|
3751
3770
|
if (x.length > 0) {
|
|
3752
|
-
let t = yield*
|
|
3753
|
-
t.kind === "resume" ? (v = t.runId, y = t.ops, b = "resume") : (yield* A.logWarning(`migration resume: discarding the ledger of run ${t.runId} — ${t.why}`).pipe(A.annotateLogs({ scope: "voltro:migrate" })), yield*
|
|
3771
|
+
let t = yield* Zo(e, o, l, x);
|
|
3772
|
+
t.kind === "resume" ? (v = t.runId, y = t.ops, b = "resume") : (yield* A.logWarning(`migration resume: discarding the ledger of run ${t.runId} — ${t.why}`).pipe(A.annotateLogs({ scope: "voltro:migrate" })), yield* Ko(e, t.runId));
|
|
3754
3773
|
}
|
|
3755
|
-
b === "fresh" && y.length > 0 && (yield*
|
|
3774
|
+
b === "fresh" && y.length > 0 && (yield* Uo(e, v, l.toFingerprint, y)), g.length > 0 && (yield* Zi(e, A.gen(function* () {
|
|
3756
3775
|
let e = yield* j.SqlClient, t = [], r = () => A.gen(function* () {
|
|
3757
3776
|
for (let e of t.splice(0)) yield* e.data, yield* e.after;
|
|
3758
3777
|
});
|
|
3759
|
-
for (let i of g)
|
|
3778
|
+
for (let i of g) Ao.has(i.op.kind) && t.length > 0 && (yield* r()), a.push(yield* Xo(e, i, n, "fresh", (e) => t.push(e)));
|
|
3760
3779
|
yield* r();
|
|
3761
3780
|
})));
|
|
3762
3781
|
let S = [], C = () => A.gen(function* () {
|
|
3763
3782
|
let t = S.splice(0);
|
|
3764
3783
|
if (t.length !== 0) {
|
|
3765
|
-
yield*
|
|
3784
|
+
yield* Zi(e, A.gen(function* () {
|
|
3766
3785
|
for (let e of t) yield* e.data;
|
|
3767
3786
|
}));
|
|
3768
3787
|
for (let n of t) yield* n.after, a.push({
|
|
3769
3788
|
op: n.op,
|
|
3770
3789
|
status: "applied",
|
|
3771
3790
|
durationMs: Number(process.hrtime.bigint() - n.startedAt) / 1e6
|
|
3772
|
-
}), yield*
|
|
3791
|
+
}), yield* Wo(e, v, n.index, "applied", Number(process.hrtime.bigint() - n.startedAt) / 1e6);
|
|
3773
3792
|
}
|
|
3774
3793
|
});
|
|
3775
3794
|
for (let { index: t, planned: r } of y) {
|
|
3776
|
-
|
|
3777
|
-
let i = a.length, o = process.hrtime.bigint(), s = yield*
|
|
3795
|
+
Ao.has(r.op.kind) && S.length > 0 && (yield* C()), yield* Wo(e, v, t, "started");
|
|
3796
|
+
let i = a.length, o = process.hrtime.bigint(), s = yield* Xo(e, r, n, b, (e) => S.push({
|
|
3778
3797
|
...e,
|
|
3779
3798
|
index: t,
|
|
3780
3799
|
startedAt: o
|
|
3781
3800
|
})).pipe(A.mapError((e) => Object.assign(e, { message: `${String(e?.message ?? e)}\n\n progress: ${i} of ${y.length + g.length} operation(s) applied before this one${g.length > 0 ? ` (${g.length} of them in a transaction)` : ""}.\n` + (m ? " 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 ledger records how far it got (operation ${t} was in flight).\n`) })));
|
|
3782
3801
|
if (s.deferred === !0) {
|
|
3783
|
-
yield*
|
|
3802
|
+
yield* Wo(e, v, t, "added");
|
|
3784
3803
|
continue;
|
|
3785
3804
|
}
|
|
3786
|
-
a.push(s), yield*
|
|
3805
|
+
a.push(s), yield* Wo(e, v, t, "applied", s.durationMs);
|
|
3787
3806
|
}
|
|
3788
3807
|
yield* C();
|
|
3789
3808
|
let w = yield* n.replan(e);
|
|
@@ -3791,23 +3810,23 @@ BEGIN
|
|
|
3791
3810
|
let e = (e) => "column" in e ? typeof e.column == "string" ? `.${e.column}` : `.${String(e.column.name ?? "")}` : "", t = w.operations.slice(0, 10).map((t) => ` - ${t.op.kind} ${"table" in t.op ? t.op.table : ""}${e(t.op)}`).join("\n"), n = a.filter((e) => e.status === "applied"), r = n.slice(0, 10).map((t) => ` - ${t.op.kind} ${"table" in t.op ? t.op.table : ""}${e(t.op)}`).join("\n") + (n.length > 10 ? `\n … and ${n.length - 10} more` : "");
|
|
3792
3811
|
return yield* A.die(/* @__PURE__ */ Error(`applyPlan: the migration did not converge. ${l.operations.length} operation(s) were executed without error, but re-planning against the live schema still finds ${w.operations.length}:\n${t}${w.operations.length > 10 ? `\n … and ${w.operations.length - 10} more` : ""}\nNo fingerprint was recorded — recording one would make the next boot report "schema up to date" for a schema that was never applied. This is a framework bug.\n` + (m ? " This dialect applies a plan atomically, so the run is rolled back and the schema IS unchanged.\n" : ` This dialect does NOT apply a plan atomically. The ${n.length} operation(s) below are COMMITTED\n and there is no rollback — the schema is PART-APPLIED, not unchanged:\n${r}\n Re-running plans from where the database now is, which is a different plan from the one that failed.\n`) + "Two causes look identical from here, so read the list before assuming either:\n - the DDL for those operations is a no-op (it succeeded and changed nothing), or\n - the planner cannot see what the DDL did, so it proposes the same work again — which is what an\n operation naming an object a PREVIOUS operation created or renamed usually means.\nReport the operation kinds above with the column types involved."));
|
|
3793
3812
|
}
|
|
3794
|
-
let T = a.filter((e) => e.status === "applied").length, E = Date.now() - i, D = v,
|
|
3813
|
+
let T = a.filter((e) => e.status === "applied").length, E = Date.now() - i, D = v, O = (/* @__PURE__ */ new Date()).toISOString(), ee = yield* U(e, O), k = [...g, ...y.map((e) => e.planned)];
|
|
3795
3814
|
yield* e`
|
|
3796
3815
|
INSERT INTO ${e("_voltro_migration_plans")}
|
|
3797
3816
|
(${e("id")}, ${e("fingerprint")}, ${e("liveFingerprint")}, ${e("operations")},
|
|
3798
3817
|
${e("appliedBy")}, ${e("environment")}, ${e("source")},
|
|
3799
3818
|
${e("durationMs")}, ${e("appliedAt")}, ${e("notes")})
|
|
3800
3819
|
VALUES
|
|
3801
|
-
(${D}, ${l.toFingerprint}, ${w.fromFingerprint}, ${JSON.stringify(
|
|
3820
|
+
(${D}, ${l.toFingerprint}, ${w.fromFingerprint}, ${JSON.stringify(k)},
|
|
3802
3821
|
${n.appliedBy}, ${n.environment}, ${n.source},
|
|
3803
|
-
${E}, ${
|
|
3804
|
-
`, yield*
|
|
3805
|
-
let
|
|
3806
|
-
return yield* A.promise(() => h({ changedTables:
|
|
3822
|
+
${E}, ${ee}, ${n.notes ?? null})
|
|
3823
|
+
`, yield* Ko(e, v);
|
|
3824
|
+
let te = [...new Set(k.flatMap((e) => e.op.kind === "rename-table" ? [e.op.to] : [e.op.table]))];
|
|
3825
|
+
return yield* A.promise(() => h({ changedTables: te }).catch(() => {})), {
|
|
3807
3826
|
id: D,
|
|
3808
|
-
appliedAt:
|
|
3827
|
+
appliedAt: O,
|
|
3809
3828
|
fingerprint: l.toFingerprint,
|
|
3810
|
-
operations:
|
|
3829
|
+
operations: k,
|
|
3811
3830
|
appliedBy: n.appliedBy,
|
|
3812
3831
|
environment: n.environment,
|
|
3813
3832
|
durationMs: E,
|
|
@@ -3815,7 +3834,7 @@ BEGIN
|
|
|
3815
3834
|
source: n.source,
|
|
3816
3835
|
...n.notes ? { notes: n.notes } : {}
|
|
3817
3836
|
};
|
|
3818
|
-
}),
|
|
3837
|
+
}), ns = (e, t) => {
|
|
3819
3838
|
switch (t.kind) {
|
|
3820
3839
|
case "drop-foreign-key": return {
|
|
3821
3840
|
...e,
|
|
@@ -3848,36 +3867,36 @@ BEGIN
|
|
|
3848
3867
|
};
|
|
3849
3868
|
}
|
|
3850
3869
|
}, Z = (e, t, n) => {
|
|
3851
|
-
let r = n.tables.find((e) => e.name === t.table), i = () => r === void 0 ? A.void :
|
|
3870
|
+
let r = n.tables.find((e) => e.name === t.table), i = () => r === void 0 ? A.void : Mo(e, t.table, Ba(ns(r, t)), t.kind);
|
|
3852
3871
|
switch (t.kind) {
|
|
3853
3872
|
case "drop-foreign-key": return e.onDialectOrElse({
|
|
3854
|
-
mysql: () => J(e,
|
|
3873
|
+
mysql: () => J(e, wo(t), t.kind),
|
|
3855
3874
|
sqlite: i,
|
|
3856
|
-
orElse: () => J(e,
|
|
3875
|
+
orElse: () => J(e, Co(t), t.kind)
|
|
3857
3876
|
});
|
|
3858
3877
|
case "drop-index": return e.onDialectOrElse({
|
|
3859
|
-
mysql: () => J(e,
|
|
3860
|
-
mssql: () => J(e,
|
|
3861
|
-
orElse: () => J(e,
|
|
3878
|
+
mysql: () => J(e, ro(t), t.kind),
|
|
3879
|
+
mssql: () => J(e, io(t), t.kind),
|
|
3880
|
+
orElse: () => J(e, no(t), t.kind)
|
|
3862
3881
|
});
|
|
3863
3882
|
case "drop-column": return e.onDialectOrElse({
|
|
3864
|
-
mysql: () =>
|
|
3883
|
+
mysql: () => H(e).pipe(A.flatMap((n) => J(e, sa(t, n), t.kind, [qi]))),
|
|
3865
3884
|
sqlite: i,
|
|
3866
|
-
orElse: () => J(e,
|
|
3885
|
+
orElse: () => J(e, oa(t, W), t.kind)
|
|
3867
3886
|
});
|
|
3868
3887
|
case "rename-column": return e.onDialectOrElse({
|
|
3869
|
-
mysql: () => J(e,
|
|
3870
|
-
mssql: () =>
|
|
3871
|
-
orElse: () => J(e,
|
|
3888
|
+
mysql: () => J(e, ca(t, G), t.kind),
|
|
3889
|
+
mssql: () => No(e, t),
|
|
3890
|
+
orElse: () => J(e, ca(t, W), t.kind)
|
|
3872
3891
|
});
|
|
3873
3892
|
}
|
|
3874
|
-
},
|
|
3893
|
+
}, rs = (e, t, n) => Xo(e, t, { declared: n }), is = (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"), as = (e) => e`
|
|
3875
3894
|
SELECT fingerprint
|
|
3876
3895
|
FROM _voltro_migration_plans
|
|
3877
3896
|
ORDER BY ${e("appliedAt")} DESC
|
|
3878
3897
|
LIMIT 1
|
|
3879
|
-
`.pipe(A.map((e) => e.length > 0 ? e[0].fingerprint : void 0), A.catchAll(() => A.succeed(void 0))),
|
|
3880
|
-
if ((yield*
|
|
3898
|
+
`.pipe(A.map((e) => e.length > 0 ? e[0].fingerprint : void 0), A.catchAll(() => A.succeed(void 0))), os = (e, t, n) => A.gen(function* () {
|
|
3899
|
+
if ((yield* as(e)) === t.toFingerprint) return "already-current";
|
|
3881
3900
|
let r = `plan_${Date.now().toString(36)}`, i = yield* U(e, (/* @__PURE__ */ new Date()).toISOString());
|
|
3882
3901
|
return yield* e`
|
|
3883
3902
|
INSERT INTO ${e("_voltro_migration_plans")}
|
|
@@ -3889,8 +3908,8 @@ BEGIN
|
|
|
3889
3908
|
${n.appliedBy}, ${n.environment}, ${n.source},
|
|
3890
3909
|
${0}, ${i}, ${"no DDL — the declared schema already matched the database"})
|
|
3891
3910
|
`, "recorded";
|
|
3892
|
-
}).pipe(A.catchAll(() => A.succeed("already-current"))),
|
|
3893
|
-
let r =
|
|
3911
|
+
}).pipe(A.catchAll(() => A.succeed("already-current"))), ss = (e, t, n) => A.gen(function* () {
|
|
3912
|
+
let r = R(wr(t, N(e), { charset: n.charset })), i = yield* as(e);
|
|
3894
3913
|
return i === r ? {
|
|
3895
3914
|
kind: "up-to-date",
|
|
3896
3915
|
fingerprint: r
|
|
@@ -3899,23 +3918,23 @@ BEGIN
|
|
|
3899
3918
|
expected: r,
|
|
3900
3919
|
...i === void 0 ? {} : { actual: i }
|
|
3901
3920
|
};
|
|
3902
|
-
}),
|
|
3921
|
+
}), cs = [
|
|
3903
3922
|
"pgeagertest_",
|
|
3904
3923
|
"mig_e2e_",
|
|
3905
3924
|
"mig_test_",
|
|
3906
3925
|
"mysqleagertest_",
|
|
3907
3926
|
"mssqleagertest_",
|
|
3908
3927
|
"sqliteeagertest_"
|
|
3909
|
-
],
|
|
3928
|
+
], ls = (e) => cs.some((t) => e.startsWith(t)), us = (e, t) => A.gen(function* () {
|
|
3910
3929
|
if (process.env.VOLTRO_TEST_FIXTURE_GC === "off") return [];
|
|
3911
|
-
let n = t.filter((e) =>
|
|
3930
|
+
let n = t.filter((e) => ls(e.name)).map((e) => e.name);
|
|
3912
3931
|
if (n.length === 0) return [];
|
|
3913
3932
|
for (let t of n) yield* e.unsafe(`DROP TABLE IF EXISTS "${t}" CASCADE`).pipe(A.catchAll(() => A.void));
|
|
3914
3933
|
return n;
|
|
3915
|
-
}),
|
|
3934
|
+
}), ds = () => {
|
|
3916
3935
|
let e = (process.env.VOLTRO_DB_IGNORE_TABLES ?? "").split(",").map((e) => e.trim()).filter((e) => e.length > 0);
|
|
3917
3936
|
return e.length > 0 ? { ignoreTables: e } : {};
|
|
3918
|
-
},
|
|
3937
|
+
}, fs = (e) => {
|
|
3919
3938
|
if (e === void 0) return;
|
|
3920
3939
|
let t = e.trim();
|
|
3921
3940
|
if (t === "") return;
|
|
@@ -3925,34 +3944,34 @@ BEGIN
|
|
|
3925
3944
|
kind: "tables",
|
|
3926
3945
|
tables: new Set(n)
|
|
3927
3946
|
} : void 0;
|
|
3928
|
-
},
|
|
3947
|
+
}, ps = (e) => typeof e.table == "string" ? e.table : void 0, ms = (e, t = { kind: "all" }) => ({
|
|
3929
3948
|
...e,
|
|
3930
3949
|
operations: e.operations.map((e) => {
|
|
3931
3950
|
if (!e.blocked || e.classification !== "lossy") return e;
|
|
3932
3951
|
if (t?.kind === "tables") {
|
|
3933
|
-
let n =
|
|
3952
|
+
let n = ps(e.op);
|
|
3934
3953
|
if (n === void 0 || !t.tables.has(n)) return e;
|
|
3935
3954
|
}
|
|
3936
3955
|
let { blocked: n, ...r } = e;
|
|
3937
3956
|
return r;
|
|
3938
3957
|
})
|
|
3939
|
-
}),
|
|
3958
|
+
}), hs = (e, t, n) => t === "postgres" ? Er(e, n).pipe(A.flatMap((e) => {
|
|
3940
3959
|
let t = Dr(e);
|
|
3941
3960
|
return t === void 0 ? A.void : A.logWarning(`auto-migrate: ${t}`).pipe(A.annotateLogs({ scope: "voltro:migrate" }));
|
|
3942
|
-
}), A.catchAll(() => A.void)) : A.void,
|
|
3961
|
+
}), A.catchAll(() => A.void)) : A.void, gs = (e, t, n) => A.gen(function* () {
|
|
3943
3962
|
let i = N(e), a = t;
|
|
3944
3963
|
if (process.env.VOLTRO_MIGRATE_FORCE !== "1") {
|
|
3945
|
-
let t =
|
|
3946
|
-
if ((yield*
|
|
3964
|
+
let t = R(wr(a, i, { charset: n.charset }));
|
|
3965
|
+
if ((yield* as(e)) === t) return yield* hs(e, i, a), {
|
|
3947
3966
|
kind: "up-to-date",
|
|
3948
3967
|
fingerprint: t
|
|
3949
3968
|
};
|
|
3950
3969
|
}
|
|
3951
|
-
let s = yield*
|
|
3970
|
+
let s = yield* zi(e), c = yield* us(e, s.tables);
|
|
3952
3971
|
c.length > 0 && (yield* A.logInfo(`auto-migrate: reaped ${c.length} test-fixture leftover(s)`).pipe(A.annotateLogs({
|
|
3953
3972
|
scope: "voltro:migrate",
|
|
3954
3973
|
count: c.length
|
|
3955
|
-
})), s = yield*
|
|
3974
|
+
})), s = yield* zi(e));
|
|
3956
3975
|
{
|
|
3957
3976
|
let e = n.softDropRetentionDays ?? 7, t = ee(s, { retentionDays: e });
|
|
3958
3977
|
t.length > 0 && (yield* A.logWarning(`auto-migrate: ${r(t, e)}`).pipe(A.annotateLogs({
|
|
@@ -3960,21 +3979,21 @@ BEGIN
|
|
|
3960
3979
|
snapshots: t.map((e) => e.name)
|
|
3961
3980
|
})));
|
|
3962
3981
|
}
|
|
3963
|
-
let l = new Set(t.map((e) => e.tableName)), u = (e) => o(e, l), d =
|
|
3982
|
+
let l = new Set(t.map((e) => e.tableName)), u = (e) => o(e, l), d = si({
|
|
3964
3983
|
declared: a,
|
|
3965
3984
|
live: { tables: u(s.tables) },
|
|
3966
3985
|
dialect: i,
|
|
3967
3986
|
charset: n.charset,
|
|
3968
|
-
...
|
|
3987
|
+
...ds()
|
|
3969
3988
|
});
|
|
3970
3989
|
if (d.summary.blocked > 0) {
|
|
3971
|
-
let e = d.operations.filter((e) => e.blocked).every((e) => e.classification === "lossy"), t =
|
|
3972
|
-
if (t === void 0 || !e || (d =
|
|
3990
|
+
let e = d.operations.filter((e) => e.blocked).every((e) => e.classification === "lossy"), t = fs(process.env.VOLTRO_DESTRUCTIVE_OK);
|
|
3991
|
+
if (t === void 0 || !e || (d = ms(d, t), d.operations.some((e) => e.blocked))) return {
|
|
3973
3992
|
kind: "refused-blocked",
|
|
3974
3993
|
plan: d
|
|
3975
3994
|
};
|
|
3976
3995
|
}
|
|
3977
|
-
return d.operations.length === 0 ? (yield*
|
|
3996
|
+
return d.operations.length === 0 ? (yield* os(e, d, {
|
|
3978
3997
|
appliedBy: n.appliedBy,
|
|
3979
3998
|
environment: n.environment === "prod" ? "dev" : n.environment,
|
|
3980
3999
|
source: "auto-diff"
|
|
@@ -3983,28 +4002,28 @@ BEGIN
|
|
|
3983
4002
|
fingerprint: d.toFingerprint
|
|
3984
4003
|
}) : {
|
|
3985
4004
|
kind: "applied",
|
|
3986
|
-
applied: yield*
|
|
4005
|
+
applied: yield* es(e, d, {
|
|
3987
4006
|
declared: t,
|
|
3988
4007
|
appliedBy: n.appliedBy,
|
|
3989
4008
|
environment: n.environment === "prod" ? "dev" : n.environment,
|
|
3990
4009
|
source: "auto-diff",
|
|
3991
4010
|
replan: (e) => A.gen(function* () {
|
|
3992
|
-
let t = yield*
|
|
3993
|
-
return
|
|
4011
|
+
let t = yield* zi(e);
|
|
4012
|
+
return si({
|
|
3994
4013
|
declared: a,
|
|
3995
4014
|
live: { tables: u(t.tables) },
|
|
3996
4015
|
dialect: i,
|
|
3997
4016
|
charset: n.charset,
|
|
3998
|
-
...
|
|
4017
|
+
...ds()
|
|
3999
4018
|
});
|
|
4000
4019
|
})
|
|
4001
4020
|
}),
|
|
4002
4021
|
plan: d
|
|
4003
4022
|
};
|
|
4004
|
-
}),
|
|
4023
|
+
}), _s = (e, t, n) => process.env.VOLTRO_AUTO_MIGRATE === "0" ? A.succeed({
|
|
4005
4024
|
kind: "skipped",
|
|
4006
4025
|
reason: "VOLTRO_AUTO_MIGRATE=0"
|
|
4007
|
-
}) : n.environment === "prod" ?
|
|
4026
|
+
}) : n.environment === "prod" ? ss(e, t, n) : gs(e, t, n), vs = (e, t) => {
|
|
4008
4027
|
switch (e.kind) {
|
|
4009
4028
|
case "skipped": return `auto-migrate: skipped (${e.reason})`;
|
|
4010
4029
|
case "up-to-date": return `auto-migrate: schema up to date (${t}, fingerprint=${lr(e.fingerprint)})`;
|
|
@@ -4014,7 +4033,7 @@ BEGIN
|
|
|
4014
4033
|
}
|
|
4015
4034
|
case "prod-mismatch": return `auto-migrate: SCHEMA FINGERPRINT MISMATCH — declared=${lr(e.expected)}` + (e.actual ? ` live=${lr(e.actual)}` : " live=<no _voltro_migration_plans row>") + ". Run `voltro db apply --plan plan.json` from the deploy pipeline before serving.";
|
|
4016
4035
|
case "refused-blocked": {
|
|
4017
|
-
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` +
|
|
4036
|
+
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` + is(e.plan), c = [""];
|
|
4018
4037
|
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) {
|
|
4019
4038
|
let t = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map();
|
|
4020
4039
|
for (let r of e.plan.operations) {
|
|
@@ -4031,7 +4050,13 @@ BEGIN
|
|
|
4031
4050
|
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");
|
|
4032
4051
|
}
|
|
4033
4052
|
}
|
|
4034
|
-
},
|
|
4053
|
+
}, ys = (e) => typeof e.__definition == "function" ? u({ c: e }).c : e, bs = (e) => {
|
|
4054
|
+
if (typeof e != "string") return e;
|
|
4055
|
+
let t = e.trim().replace(/::[a-zA-Z0-9_ "]+$/, "").trim();
|
|
4056
|
+
if (/^current_timestamp(\(\d*\))?$/i.test(t) || /^now\(\)$/i.test(t)) return "now";
|
|
4057
|
+
let n = /^'(.*)'$/s.exec(t);
|
|
4058
|
+
return n === null ? e : n[1].replace(/''/g, "'");
|
|
4059
|
+
}, Q = (e, t = /* @__PURE__ */ new Map()) => {
|
|
4035
4060
|
let n = {};
|
|
4036
4061
|
for (let r of e.columns) {
|
|
4037
4062
|
let e = r.references, i = e === void 0 ? void 0 : t.get(e.table);
|
|
@@ -4040,7 +4065,7 @@ BEGIN
|
|
|
4040
4065
|
nullable: r.nullable,
|
|
4041
4066
|
unique: r.unique,
|
|
4042
4067
|
hasDefault: r.hasDefault,
|
|
4043
|
-
...r.hasDefault ? { defaultValue: r.defaultValue } : {},
|
|
4068
|
+
...r.hasDefault ? { defaultValue: bs(r.defaultValue) } : {},
|
|
4044
4069
|
...r.maxLength === void 0 ? {} : { maxLength: r.maxLength },
|
|
4045
4070
|
...r.precision === void 0 ? {} : { precision: r.precision },
|
|
4046
4071
|
...r.scale === void 0 ? {} : { scale: r.scale },
|
|
@@ -4082,14 +4107,14 @@ BEGIN
|
|
|
4082
4107
|
})),
|
|
4083
4108
|
...e.primaryKey === void 0 ? {} : { appliedPrimaryKey: e.primaryKey }
|
|
4084
4109
|
};
|
|
4085
|
-
},
|
|
4110
|
+
}, xs = (e) => {
|
|
4086
4111
|
let t = new Map(e.tables.map((e) => [e.name, e]));
|
|
4087
4112
|
return e.tables.map((e) => Q(e, t));
|
|
4088
|
-
},
|
|
4113
|
+
}, Ss = (e, t = "safe") => ({
|
|
4089
4114
|
op: e,
|
|
4090
4115
|
classification: t,
|
|
4091
4116
|
reason: "file migration schema operation"
|
|
4092
|
-
}), $ = "this context was built over an in-memory store without a `sql` client, and this needs a live connection. Run the migration against a database (the runner supplies the client), or keep a database-free test to `each`, `rewrite`, `expect`, `skipUnless`, `store`, `log`, `schema.tableExists`, `schema.columnExists` and a Promise body under `transactional`.",
|
|
4117
|
+
}), $ = "this context was built over an in-memory store without a `sql` client, and this needs a live connection. Run the migration against a database (the runner supplies the client), or keep a database-free test to `each`, `rewrite`, `expect`, `skipUnless`, `store`, `log`, `schema.tableExists`, `schema.columnExists` and a Promise body under `transactional`.", Cs = {
|
|
4093
4118
|
snapshot: "the in-memory store holds rows, not a catalog — it has no column types, defaults, indexes or constraints to report. `schema.tableExists` and `schema.columnExists` answer from the rows it holds; a body that needs the whole shape needs a database.",
|
|
4094
4119
|
indexExists: "the in-memory store has no indexes — every read of it is a scan — so there is no honest answer to give, and `false` would claim an index is absent from a store that could never have had one. Run this migration against a database, or guard on `schema.tableExists` / `schema.columnExists`, which the store can answer.",
|
|
4095
4120
|
foreignKeyExists: "the in-memory store has no constraints, so there is no honest answer to give, and `false` would claim a foreign key is absent from a store that could never have had one. Run this migration against a database, or guard on `schema.tableExists` / `schema.columnExists`, which the store can answer.",
|
|
@@ -4106,7 +4131,7 @@ BEGIN
|
|
|
4106
4131
|
dropColumn: $,
|
|
4107
4132
|
renameColumn: $,
|
|
4108
4133
|
truncate: $
|
|
4109
|
-
},
|
|
4134
|
+
}, ws = "this context was built over a store that cannot report the tables it holds (`DataStore.storedTables` is not implemented), so the question has no honest answer here. Use the in-memory store `@voltro/runtime` ships, or run the migration against a database.", Ts = (e, t) => {
|
|
4110
4135
|
let n = () => {
|
|
4111
4136
|
let e = t.storedTables;
|
|
4112
4137
|
if (e !== void 0) return new Map(e.call(t).map((e) => [e.table, e]));
|
|
@@ -4114,23 +4139,23 @@ BEGIN
|
|
|
4114
4139
|
return {
|
|
4115
4140
|
tableExists: (e) => A.suspend(() => {
|
|
4116
4141
|
let t = n();
|
|
4117
|
-
return t === void 0 ? r("schema.tableExists()",
|
|
4142
|
+
return t === void 0 ? r("schema.tableExists()", ws) : A.succeed(t.has(e));
|
|
4118
4143
|
}),
|
|
4119
4144
|
columnExists: (e, t) => A.suspend(() => {
|
|
4120
4145
|
let i = n();
|
|
4121
|
-
if (i === void 0) return r("schema.columnExists()",
|
|
4146
|
+
if (i === void 0) return r("schema.columnExists()", ws);
|
|
4122
4147
|
let a = i.get(e);
|
|
4123
4148
|
return a === void 0 ? A.succeed(!1) : a.rowCount === 0 ? r(`schema.columnExists(${JSON.stringify(e)}, ${JSON.stringify(t)})`, `${e} is in this store and holds no rows, and a column exists in a store without a catalog only as a key on a row — so "no such column" and "no row has said yet" are the same observation, and answering either would be a guess. Seed ${e} with a row carrying the columns this migration guards on, or run the migration against a database.`) : A.succeed(a.columns.includes(t));
|
|
4124
4149
|
})
|
|
4125
4150
|
};
|
|
4126
|
-
},
|
|
4127
|
-
let n = { ...
|
|
4128
|
-
for (let [t, r] of Object.entries(
|
|
4151
|
+
}, Es = (e, t) => {
|
|
4152
|
+
let n = { ...Ts(e, t) };
|
|
4153
|
+
for (let [t, r] of Object.entries(Cs)) n[t] = () => A.fail(new S(e, `schema.${t}()`, r));
|
|
4129
4154
|
return n;
|
|
4130
|
-
},
|
|
4155
|
+
}, Ds = (e) => typeof e == "function" && typeof e.onDialectOrElse == "function", Os = (e) => A.isEffect(e) ? e : A.tryPromise({
|
|
4131
4156
|
try: () => e,
|
|
4132
4157
|
catch: (e) => e
|
|
4133
|
-
}),
|
|
4158
|
+
}), ks = (e, t, n) => t.run === void 0 ? Promise.reject(new S(e, "transactional() with an Effect body", "an Effect returned from `transactional` runs ON the transaction's connection, and this store has none. Return a Promise body that uses the transaction's `store`, or run the migration against a database.")) : t.run(n), As = (e, t) => {
|
|
4134
4159
|
let n = e.run;
|
|
4135
4160
|
if (n === void 0) return t;
|
|
4136
4161
|
let r = {};
|
|
@@ -4142,20 +4167,20 @@ BEGIN
|
|
|
4142
4167
|
});
|
|
4143
4168
|
}
|
|
4144
4169
|
return r;
|
|
4145
|
-
},
|
|
4146
|
-
let r = () =>
|
|
4170
|
+
}, js = (e, t, n) => {
|
|
4171
|
+
let r = () => zi(e), i = (e, t) => e.tables.find((e) => e.name === t), a = (e, t, n) => i(e, t)?.columns.find((e) => e.name === n), o = (e) => A.succeed(e), s = (e) => new Map(e.tables.map((e) => [e.name, e])), c = (e, t) => {
|
|
4147
4172
|
let n = i(e, t);
|
|
4148
4173
|
if (n === void 0) throw Error(`schema: table ${t} does not exist`);
|
|
4149
4174
|
return n;
|
|
4150
4175
|
}, l = (n) => A.gen(function* () {
|
|
4151
|
-
let i = () => r().pipe(A.map((e) => ({ tables: e.tables.filter((e) => e.name === n.tableName) }))), a =
|
|
4176
|
+
let i = () => r().pipe(A.map((e) => ({ tables: e.tables.filter((e) => e.name === n.tableName) }))), a = ms(si({
|
|
4152
4177
|
declared: [n],
|
|
4153
4178
|
live: yield* i(),
|
|
4154
4179
|
dialect: t
|
|
4155
4180
|
})), o = a.operations.filter((e) => e.blocked !== void 0);
|
|
4156
4181
|
if (o.length > 0) return yield* A.fail(/* @__PURE__ */ Error(`evolve(${n.tableName}): ${o.length} operation(s) cannot be planned:\n` + o.map((e) => ` - ${e.op.kind}: ${e.blocked?.fix ?? e.reason}`).join("\n")));
|
|
4157
|
-
for (let t of a.operations) yield*
|
|
4158
|
-
let s =
|
|
4182
|
+
for (let t of a.operations) yield* rs(e, t, [n]);
|
|
4183
|
+
let s = si({
|
|
4159
4184
|
declared: [n],
|
|
4160
4185
|
live: yield* i(),
|
|
4161
4186
|
dialect: t
|
|
@@ -4169,14 +4194,14 @@ BEGIN
|
|
|
4169
4194
|
return (yield* r()).tables.some((t) => t.name === e.tableName) ? yield* o("already-present") : (yield* l(e), "applied");
|
|
4170
4195
|
}),
|
|
4171
4196
|
dropTable: (t) => A.gen(function* () {
|
|
4172
|
-
return (yield* r()).tables.some((e) => e.name === t) ? (yield*
|
|
4197
|
+
return (yield* r()).tables.some((e) => e.name === t) ? (yield* rs(e, Ss({
|
|
4173
4198
|
kind: "drop-table",
|
|
4174
4199
|
table: t
|
|
4175
4200
|
}, "lossy"), []), "applied") : yield* o("already-absent");
|
|
4176
4201
|
}),
|
|
4177
4202
|
renameTable: (t, n) => A.gen(function* () {
|
|
4178
4203
|
let a = yield* r(), s = i(a, t) !== void 0, l = i(a, n) !== void 0;
|
|
4179
|
-
return !s && l ? yield* o("already-present") : s ? l ? yield* A.fail(/* @__PURE__ */ Error(`renameTable: ${n} already exists beside ${t}`)) : (yield*
|
|
4204
|
+
return !s && l ? yield* o("already-present") : s ? l ? yield* A.fail(/* @__PURE__ */ Error(`renameTable: ${n} already exists beside ${t}`)) : (yield* rs(e, Ss({
|
|
4180
4205
|
kind: "rename-table",
|
|
4181
4206
|
from: t,
|
|
4182
4207
|
to: n
|
|
@@ -4185,7 +4210,7 @@ BEGIN
|
|
|
4185
4210
|
addColumn: (t, n, i) => A.gen(function* () {
|
|
4186
4211
|
let a = yield* r(), u = c(a, t);
|
|
4187
4212
|
if (u.columns.some((e) => e.name === n)) return yield* o("already-present");
|
|
4188
|
-
let d =
|
|
4213
|
+
let d = ys(i);
|
|
4189
4214
|
if (!d.nullable && !d.hasDefault && d.backfill === void 0) {
|
|
4190
4215
|
let r = yield* e`SELECT COUNT(*) AS n FROM ${e(t)}`;
|
|
4191
4216
|
if (Number(r[0]?.n ?? 0) > 0) return yield* A.fail(/* @__PURE__ */ Error(`addColumn(${t}.${n}): a NOT NULL column without a default cannot be added to a table with rows on any dialect. Add it nullable or with a default, fill it (rewrite), then alterColumn(${JSON.stringify(t)}, ${JSON.stringify(n)}, { nullable: false }).`));
|
|
@@ -4321,11 +4346,11 @@ BEGIN
|
|
|
4321
4346
|
}, s), "applied") : yield* A.fail(/* @__PURE__ */ Error(`renameColumn: ${t}.${n} does not exist`));
|
|
4322
4347
|
})
|
|
4323
4348
|
};
|
|
4324
|
-
},
|
|
4349
|
+
}, Ms = (e, t, n, r) => {
|
|
4325
4350
|
let i;
|
|
4326
4351
|
return (async function* () {
|
|
4327
4352
|
for (;;) {
|
|
4328
|
-
let a = [i === void 0 ? void 0 :
|
|
4353
|
+
let a = [i === void 0 ? void 0 : me("id", i), r].filter((e) => e !== void 0), o = await e.query({
|
|
4329
4354
|
table: t,
|
|
4330
4355
|
predicate: a.length === 0 ? void 0 : a.length === 1 ? a[0] : v(...a),
|
|
4331
4356
|
order: [{
|
|
@@ -4343,8 +4368,8 @@ BEGIN
|
|
|
4343
4368
|
if (i = s, yield o, o.length < n) return;
|
|
4344
4369
|
}
|
|
4345
4370
|
})();
|
|
4346
|
-
},
|
|
4347
|
-
let i = r.batchSize ?? 1e3, a = 0, o = 0, s =
|
|
4371
|
+
}, Ns = (e) => e > 0 ? A.sleep(`${e} millis`) : A.void, Ps = (e) => (t, n, r = {}) => A.gen(function* () {
|
|
4372
|
+
let i = r.batchSize ?? 1e3, a = 0, o = 0, s = Ms(e, t, i);
|
|
4348
4373
|
for (;;) {
|
|
4349
4374
|
let e = yield* A.tryPromise({
|
|
4350
4375
|
try: () => s.next(),
|
|
@@ -4352,16 +4377,16 @@ BEGIN
|
|
|
4352
4377
|
});
|
|
4353
4378
|
if (e.done) break;
|
|
4354
4379
|
o++;
|
|
4355
|
-
for (let t of e.value) yield*
|
|
4356
|
-
yield*
|
|
4380
|
+
for (let t of e.value) yield* Os(n(t)), a++;
|
|
4381
|
+
yield* Ns(r.sleepMs ?? 0);
|
|
4357
4382
|
}
|
|
4358
4383
|
return {
|
|
4359
4384
|
scanned: a,
|
|
4360
4385
|
pages: o
|
|
4361
4386
|
};
|
|
4362
|
-
}),
|
|
4387
|
+
}), Fs = (e, t) => t == null ? oe(e) : se(e, t), Is = (e) => typeof e != "object" || !e || e instanceof Date, Ls = (e, t) => A.gen(function* () {
|
|
4363
4388
|
if (e === void 0) return [];
|
|
4364
|
-
let n = (yield*
|
|
4389
|
+
let n = (yield* zi(e)).tables.find((e) => e.name === t)?.columns ?? [], r = new Set(n.map((e) => e.name)), i = ce(t)?.fields;
|
|
4365
4390
|
return n.filter((e) => e.type === "timestamp" || e.type === "date" || i?.[e.name]?.type === "timestamp" || i?.[e.name]?.type === "date").map((e, t) => {
|
|
4366
4391
|
let n = `__voltro_rewrite_guard_${t}`;
|
|
4367
4392
|
for (; r.has(n);) n += "_";
|
|
@@ -4370,14 +4395,14 @@ BEGIN
|
|
|
4370
4395
|
alias: n
|
|
4371
4396
|
};
|
|
4372
4397
|
});
|
|
4373
|
-
}),
|
|
4374
|
-
let s = o.batchSize ?? 1e3, c = o.maxPasses ?? 10, l = o.guard ?? [], u = yield*
|
|
4375
|
-
let o =
|
|
4398
|
+
}), Rs = (e, t, n, r) => (i, a, o = {}) => A.gen(function* () {
|
|
4399
|
+
let s = o.batchSize ?? 1e3, c = o.maxPasses ?? 10, l = o.guard ?? [], u = yield* Ls(n, i), f = /* @__PURE__ */ new WeakMap(), p = u.length === 0 || n === void 0 ? t : { query: async (a) => {
|
|
4400
|
+
let o = _e(a, n), s = u.map(({ column: e, alias: t }) => n`${n.onDialectOrElse({
|
|
4376
4401
|
mysql: () => n`CAST(${n(e)} AS CHAR)`,
|
|
4377
4402
|
mssql: () => n`CONVERT(VARCHAR(40), ${n(e)}, 127)`,
|
|
4378
4403
|
orElse: () => n`CAST(${n(e)} AS TEXT)`
|
|
4379
4404
|
})} AS ${n(t)}`);
|
|
4380
|
-
return (await
|
|
4405
|
+
return (await ks(e, t, n`SELECT *, ${n.csv(s)} FROM (${o}) AS ${n("__voltro_rewrite_rows")} ORDER BY ${n("id")} ASC`)).map((e) => {
|
|
4381
4406
|
let t = { ...e }, n = /* @__PURE__ */ new Map();
|
|
4382
4407
|
for (let { column: e, alias: r } of u) n.set(e, t[r]), delete t[r];
|
|
4383
4408
|
let a = _([t], i, r)[0];
|
|
@@ -4390,7 +4415,7 @@ BEGIN
|
|
|
4390
4415
|
contended: 0
|
|
4391
4416
|
}, h = m;
|
|
4392
4417
|
for (let e = 1; e <= c; e++) {
|
|
4393
|
-
let n = 0, r = 0, c = 0, u =
|
|
4418
|
+
let n = 0, r = 0, c = 0, u = Ms(p, i, s);
|
|
4394
4419
|
for (;;) {
|
|
4395
4420
|
let e = yield* A.tryPromise({
|
|
4396
4421
|
try: () => u.next(),
|
|
@@ -4406,15 +4431,15 @@ BEGIN
|
|
|
4406
4431
|
if (e === void 0) continue;
|
|
4407
4432
|
let s = Object.entries(e).filter(([e, t]) => !Object.is(o[e], t));
|
|
4408
4433
|
if (s.length === 0) continue;
|
|
4409
|
-
let u = [
|
|
4410
|
-
for (let [e] of s)
|
|
4411
|
-
for (let e of l) u.push(
|
|
4434
|
+
let u = [se("id", o.id)], d = (e) => f.get(o)?.has(e) ? f.get(o).get(e) : o[e];
|
|
4435
|
+
for (let [e] of s) Is(o[e]) && u.push(Fs(e, d(e)));
|
|
4436
|
+
for (let e of l) u.push(Fs(e, d(e)));
|
|
4412
4437
|
(yield* A.tryPromise({
|
|
4413
4438
|
try: () => t.updateMany(i, Object.fromEntries(s), { where: v(...u) }),
|
|
4414
4439
|
catch: (e) => e
|
|
4415
4440
|
})) === 1 ? r++ : c++;
|
|
4416
4441
|
}
|
|
4417
|
-
yield*
|
|
4442
|
+
yield* Ns(o.sleepMs ?? 0);
|
|
4418
4443
|
}
|
|
4419
4444
|
if (h = {
|
|
4420
4445
|
passes: e,
|
|
@@ -4429,9 +4454,9 @@ BEGIN
|
|
|
4429
4454
|
}, r === 0 && c === 0) return m;
|
|
4430
4455
|
}
|
|
4431
4456
|
return yield* A.fail(new d(i, h));
|
|
4432
|
-
}),
|
|
4457
|
+
}), zs = (e) => {
|
|
4433
4458
|
let { migrationId: t } = e, n = `migrations:file:${t}`;
|
|
4434
|
-
if (e.sql !== void 0 && !
|
|
4459
|
+
if (e.sql !== void 0 && !Ds(e.sql)) throw new S(t, "makeFileMigrationContext()", `\`sql\` is not an @effect/sql client (got ${typeof e.sql}). Pass the client the store executes on, or omit \`sql\` to drive the body over an in-memory store.`);
|
|
4435
4460
|
if (e.sql === void 0 && e.store.run !== void 0) throw new S(t, "makeFileMigrationContext()", "a SQL-backed store was given without `sql`. Its migration context runs `raw()`, `schema` and the guarded rewrite on the client the store executes on; pass that client, or use an in-memory store for a database-free test.");
|
|
4436
4461
|
let r = e.sql, i = [], a = (e) => {
|
|
4437
4462
|
if (typeof e != "string" || e.trim().length < 12) throw Error(`raw(reason): say why this migration needs raw SQL — the reason is what a reviewer and \`voltro doctor\` read (got ${JSON.stringify(e)})`);
|
|
@@ -4455,9 +4480,9 @@ BEGIN
|
|
|
4455
4480
|
...t ?? {}
|
|
4456
4481
|
}))
|
|
4457
4482
|
},
|
|
4458
|
-
schema: r === void 0 ?
|
|
4459
|
-
each:
|
|
4460
|
-
rewrite:
|
|
4483
|
+
schema: r === void 0 ? Es(t, o) : As(o, js(r, e.dialect, o)),
|
|
4484
|
+
each: Ps(o),
|
|
4485
|
+
rewrite: Rs(t, o, r, e.dialect),
|
|
4461
4486
|
expect: (e, t) => {
|
|
4462
4487
|
i.push({
|
|
4463
4488
|
description: e,
|
|
@@ -4465,7 +4490,7 @@ BEGIN
|
|
|
4465
4490
|
});
|
|
4466
4491
|
},
|
|
4467
4492
|
skipUnless: (e, t) => A.gen(function* () {
|
|
4468
|
-
if (!(typeof e == "boolean" ? e : yield*
|
|
4493
|
+
if (!(typeof e == "boolean" ? e : yield* Os(e))) return yield* A.fail(new T(t));
|
|
4469
4494
|
})
|
|
4470
4495
|
}))(e.store),
|
|
4471
4496
|
transactional: (n) => A.tryPromise({
|
|
@@ -4474,19 +4499,19 @@ BEGIN
|
|
|
4474
4499
|
store: e,
|
|
4475
4500
|
raw: a
|
|
4476
4501
|
});
|
|
4477
|
-
return A.isEffect(r) ?
|
|
4502
|
+
return A.isEffect(r) ? ks(t, e, r) : r;
|
|
4478
4503
|
}),
|
|
4479
4504
|
catch: (e) => e
|
|
4480
4505
|
})
|
|
4481
4506
|
},
|
|
4482
4507
|
expectations: i
|
|
4483
4508
|
};
|
|
4484
|
-
},
|
|
4509
|
+
}, Bs = (e) => A.gen(function* () {
|
|
4485
4510
|
let t = [];
|
|
4486
|
-
for (let { description: n, check: r } of e) (yield*
|
|
4511
|
+
for (let { description: n, check: r } of e) (yield* Os(r())) || t.push(n);
|
|
4487
4512
|
return t;
|
|
4488
|
-
}),
|
|
4489
|
-
let t = [], n = (e) => (n) => (!n && !t.some((t) =>
|
|
4513
|
+
}), Vs = (e) => e.kind === "table" ? e.table : `${e.table}.${e.name}`, Hs = (e, t) => e.kind === t.kind && e.table === t.table && Vs(e) === Vs(t), Us = (e) => {
|
|
4514
|
+
let t = [], n = (e) => (n) => (!n && !t.some((t) => Hs(t, e)) && t.push(e), n), r = (e, t) => (...r) => e(...r).pipe(A.map(n(t(...r)))), i = {
|
|
4490
4515
|
tableExists: r(e.schema.tableExists, (e) => ({
|
|
4491
4516
|
kind: "table",
|
|
4492
4517
|
table: e
|
|
@@ -4517,9 +4542,9 @@ BEGIN
|
|
|
4517
4542
|
},
|
|
4518
4543
|
absent: () => t.slice()
|
|
4519
4544
|
};
|
|
4520
|
-
},
|
|
4545
|
+
}, Ws = (e) => {
|
|
4521
4546
|
let t = [], n = (e) => {
|
|
4522
|
-
t.some((t) =>
|
|
4547
|
+
t.some((t) => Hs(t, e)) || t.push(e);
|
|
4523
4548
|
};
|
|
4524
4549
|
for (let t of e.operations) {
|
|
4525
4550
|
let e = t.op;
|
|
@@ -4562,17 +4587,17 @@ BEGIN
|
|
|
4562
4587
|
}
|
|
4563
4588
|
}
|
|
4564
4589
|
return t;
|
|
4565
|
-
},
|
|
4566
|
-
let n =
|
|
4590
|
+
}, Gs = (e, t) => {
|
|
4591
|
+
let n = Ws(t);
|
|
4567
4592
|
return n.length === 0 ? [] : e.flatMap((e) => {
|
|
4568
|
-
let t = e.absent.filter((e) => n.some((t) =>
|
|
4593
|
+
let t = e.absent.filter((e) => n.some((t) => Hs(t, e)));
|
|
4569
4594
|
return t.length === 0 ? [] : [{
|
|
4570
4595
|
id: e.id,
|
|
4571
4596
|
reason: e.reason,
|
|
4572
4597
|
created: t
|
|
4573
4598
|
}];
|
|
4574
4599
|
});
|
|
4575
|
-
},
|
|
4600
|
+
}, Ks = Ee({ scope: "voltro:migrate" }), qs = (e) => Te("sha256").update(e).digest("hex").slice(0, 16), Js = /* @__PURE__ */ new Set([
|
|
4576
4601
|
"node_modules",
|
|
4577
4602
|
"dist",
|
|
4578
4603
|
"build",
|
|
@@ -4581,57 +4606,57 @@ BEGIN
|
|
|
4581
4606
|
".next",
|
|
4582
4607
|
".git",
|
|
4583
4608
|
".framework"
|
|
4584
|
-
]),
|
|
4609
|
+
]), Ys = async (e) => {
|
|
4585
4610
|
let t = [], n = async (e) => {
|
|
4586
|
-
let r = await
|
|
4611
|
+
let r = await De.readdir(e, { withFileTypes: !0 }).catch(() => []);
|
|
4587
4612
|
for (let i of r) {
|
|
4588
|
-
if (
|
|
4589
|
-
let r =
|
|
4590
|
-
i.isDirectory() ? await n(r) : i.isFile() &&
|
|
4613
|
+
if (Js.has(i.name)) continue;
|
|
4614
|
+
let r = Oe(e, i.name);
|
|
4615
|
+
i.isDirectory() ? await n(r) : i.isFile() && ue.test(i.name) && t.push(r);
|
|
4591
4616
|
}
|
|
4592
4617
|
};
|
|
4593
4618
|
return await n(e), t.sort((e, t) => {
|
|
4594
4619
|
let n = e.split("/").pop() ?? e, r = t.split("/").pop() ?? t;
|
|
4595
4620
|
return n.localeCompare(r);
|
|
4596
4621
|
});
|
|
4597
|
-
},
|
|
4598
|
-
let
|
|
4599
|
-
for (let
|
|
4600
|
-
let e = (await
|
|
4601
|
-
if (!
|
|
4602
|
-
|
|
4622
|
+
}, Xs = async (e) => await import(ke(e).href), Zs = async (e, t = Xs) => {
|
|
4623
|
+
let n = [];
|
|
4624
|
+
for (let r of e) {
|
|
4625
|
+
let e = (await t(r)).default;
|
|
4626
|
+
if (!ye(e)) {
|
|
4627
|
+
Ks.warn("migration file has no default-exported `migration(...)` — skipped", { file: r });
|
|
4603
4628
|
continue;
|
|
4604
4629
|
}
|
|
4605
|
-
let
|
|
4606
|
-
|
|
4607
|
-
file:
|
|
4630
|
+
let i = await De.readFile(r, "utf8").catch(() => "");
|
|
4631
|
+
n.push({
|
|
4632
|
+
file: r,
|
|
4608
4633
|
migration: e,
|
|
4609
|
-
hash:
|
|
4634
|
+
hash: qs(i)
|
|
4610
4635
|
});
|
|
4611
4636
|
}
|
|
4612
|
-
return
|
|
4613
|
-
},
|
|
4637
|
+
return n;
|
|
4638
|
+
}, Qs = "_voltro_migration_plans", $s = (e) => {
|
|
4614
4639
|
let t = N(e);
|
|
4615
|
-
return (t === "sqlite" ? e`SELECT COUNT(*) AS n FROM sqlite_master WHERE type = 'table' AND name = ${
|
|
4616
|
-
},
|
|
4640
|
+
return (t === "sqlite" ? e`SELECT COUNT(*) AS n FROM sqlite_master WHERE type = 'table' AND name = ${Qs}` : t === "mysql" ? e`SELECT COUNT(*) AS n FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = ${Qs}` : t === "mssql" ? e`SELECT COUNT(*) AS n FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME = ${Qs}` : e`SELECT COUNT(*) AS n FROM information_schema.tables WHERE table_schema = current_schema() AND table_name = ${Qs}`).pipe(A.map((e) => Number(e[0]?.n ?? 0) > 0));
|
|
4641
|
+
}, ec = (e) => tc(e).pipe(A.map((e) => e.map((e) => e.id))), tc = (e) => $s(e).pipe(A.flatMap((t) => t ? e`
|
|
4617
4642
|
SELECT ${e("id")}, ${e("fingerprint")}
|
|
4618
|
-
FROM ${e(
|
|
4643
|
+
FROM ${e(Qs)}
|
|
4619
4644
|
WHERE ${e("source")} = 'file'
|
|
4620
4645
|
`.pipe(A.map((e) => e.map((e) => ({
|
|
4621
4646
|
id: e.id,
|
|
4622
4647
|
hash: e.fingerprint ?? ""
|
|
4623
|
-
})))) : A.succeed([]))),
|
|
4648
|
+
})))) : A.succeed([]))), nc = (e, t) => t.filter((t) => {
|
|
4624
4649
|
let n = e.get(t.migration.id);
|
|
4625
4650
|
return n !== void 0 && n !== "" && n !== t.hash;
|
|
4626
|
-
}).map((e) => e.migration.id),
|
|
4651
|
+
}).map((e) => e.migration.id), rc = (e) => y(ae(e))?.kind === "unique", ic = class extends Error {
|
|
4627
4652
|
migrationId;
|
|
4628
4653
|
file;
|
|
4629
4654
|
cause;
|
|
4630
4655
|
_tag = "FileMigrationLedgerError";
|
|
4631
4656
|
constructor(e, t, n) {
|
|
4632
|
-
super(
|
|
4657
|
+
super(rc(n) ? `migration ${e}: up() SUCCEEDED here, and ANOTHER process had already recorded the same migration.\n The body has run TWICE. The ledger row is correct — do not delete it; the next run will not apply ${t} again.\n Two processes applied it without being serialised by the migration lock: check that both reach the same database and lock schema.\n Cause: ${n instanceof Error ? n.message : String(n)}` : `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";
|
|
4633
4658
|
}
|
|
4634
|
-
},
|
|
4659
|
+
}, ac = (e, t, n) => A.gen(function* () {
|
|
4635
4660
|
let r = yield* U(e, n.appliedAtIso);
|
|
4636
4661
|
yield* e`
|
|
4637
4662
|
INSERT INTO ${e("_voltro_migration_plans")}
|
|
@@ -4646,19 +4671,19 @@ BEGIN
|
|
|
4646
4671
|
}])},
|
|
4647
4672
|
${n.appliedBy}, ${n.env}, ${"file"},
|
|
4648
4673
|
${n.durationMs}, ${r}, ${n.notes})
|
|
4649
|
-
`.pipe(A.mapError((e) => new
|
|
4650
|
-
}),
|
|
4651
|
-
for (let t of m(e)) if (t instanceof
|
|
4652
|
-
},
|
|
4653
|
-
let r =
|
|
4674
|
+
`.pipe(A.mapError((e) => new ic(t.migration.id, t.file, e)));
|
|
4675
|
+
}), oc = (e) => {
|
|
4676
|
+
for (let t of m(e)) if (t instanceof T) return t.reason;
|
|
4677
|
+
}, sc = (e, t, n) => A.gen(function* () {
|
|
4678
|
+
let r = Us(t), i = r.ctx, a = e.migration.up(i), o = !A.isEffect(a), s = yield* (A.isEffect(a) ? a : A.tryPromise({
|
|
4654
4679
|
try: () => a,
|
|
4655
4680
|
catch: (e) => e
|
|
4656
4681
|
})).pipe(A.as(void 0), A.catchAll((e) => {
|
|
4657
|
-
let t =
|
|
4682
|
+
let t = oc(e);
|
|
4658
4683
|
return t === void 0 ? A.fail(e) : A.succeed(t);
|
|
4659
4684
|
}));
|
|
4660
4685
|
if (s === void 0) {
|
|
4661
|
-
let t = yield*
|
|
4686
|
+
let t = yield* Bs(n);
|
|
4662
4687
|
if (t.length > 0) return yield* A.fail(new x(e.migration.id, t));
|
|
4663
4688
|
}
|
|
4664
4689
|
return {
|
|
@@ -4666,7 +4691,7 @@ BEGIN
|
|
|
4666
4691
|
promiseForm: o,
|
|
4667
4692
|
absent: r.absent()
|
|
4668
4693
|
};
|
|
4669
|
-
}),
|
|
4694
|
+
}), cc = (e, t, n, r, i, a) => A.gen(function* () {
|
|
4670
4695
|
let o = Date.now(), s = (/* @__PURE__ */ new Date()).toISOString(), c = N(e), l = `migrations:file:${n.migration.id}`, u = (e) => ({
|
|
4671
4696
|
durationMs: Date.now() - o,
|
|
4672
4697
|
notes: e.skipped === void 0 ? n.migration.description : `skipped: ${e.skipped}`
|
|
@@ -4674,19 +4699,19 @@ BEGIN
|
|
|
4674
4699
|
if (n.migration.transactional !== !1 && !a) {
|
|
4675
4700
|
if (t.run === void 0) return yield* A.fail(/* @__PURE__ */ Error(`migration ${n.migration.id}: transactional: true needs a SQL-backed store`));
|
|
4676
4701
|
let a = c === "mysql" || c === "mariadb", o = `probe_${n.migration.id}_${Date.now().toString(36)}`;
|
|
4677
|
-
a && (yield*
|
|
4702
|
+
a && (yield* Lo(e, c));
|
|
4678
4703
|
let d = () => e`SELECT COUNT(*) AS n FROM ${e(P)} WHERE ${e("runId")} = ${o}`.pipe(A.map((e) => Number(e[0]?.n ?? 0) > 0)), f = yield* A.tryPromise({
|
|
4679
4704
|
try: () => t.transactional(async (t) => {
|
|
4680
4705
|
a && await t.run(e`INSERT INTO ${e(P)} (${e("id")}, ${e("runId")}, ${e("planFingerprint")}, ${e("opIndex")}, ${e("status")}, ${e("opKind")}, ${e("opTarget")}, ${e("payload")})
|
|
4681
4706
|
VALUES (${`mop_${o}`}, ${o}, ${""}, ${0}, ${"pending"}, ${"probe"}, ${""}, ${"{}"})`);
|
|
4682
|
-
let { ctx: l, expectations: f } =
|
|
4707
|
+
let { ctx: l, expectations: f } = zs({
|
|
4683
4708
|
sql: e,
|
|
4684
4709
|
store: t,
|
|
4685
4710
|
dialect: c,
|
|
4686
4711
|
migrationId: n.migration.id,
|
|
4687
4712
|
appliedAt: s
|
|
4688
|
-
}), p = await t.run(
|
|
4689
|
-
return await t.run(
|
|
4713
|
+
}), p = await t.run(sc(n, l, f)), m = a && await A.runPromise(d().pipe(A.provideService(j.SqlClient, e))), { durationMs: h, notes: g } = u(p);
|
|
4714
|
+
return await t.run(ac(e, n, {
|
|
4690
4715
|
env: r,
|
|
4691
4716
|
appliedBy: i,
|
|
4692
4717
|
durationMs: h,
|
|
@@ -4709,14 +4734,14 @@ BEGIN
|
|
|
4709
4734
|
}
|
|
4710
4735
|
});
|
|
4711
4736
|
}
|
|
4712
|
-
let { ctx: d, expectations: f } =
|
|
4737
|
+
let { ctx: d, expectations: f } = zs({
|
|
4713
4738
|
sql: e,
|
|
4714
4739
|
store: t,
|
|
4715
4740
|
dialect: c,
|
|
4716
4741
|
migrationId: n.migration.id,
|
|
4717
4742
|
appliedAt: s
|
|
4718
|
-
}), p = yield*
|
|
4719
|
-
return p.promiseForm && p.skipped === void 0 && m < 2 && (yield* A.logWarning(`migration ${n.migration.id}: up() resolved in ${m}ms — did the body \`await\` an \`@effect/sql\` Effect by accident? \`sql.unsafe(...)\` returns an Effect, not a Promise; \`await\` on it is a silent no-op. Switch the body to \`Effect.gen(function* () { yield* sql.unsafe(...) })\` form.`).pipe(A.annotateLogs({ scope: l }))), p.skipped !== void 0 && (yield* A.logInfo(`migration ${n.migration.id} skipped: ${p.skipped}`).pipe(A.annotateLogs({ scope: l }))), yield*
|
|
4743
|
+
}), p = yield* sc(n, d, f), { durationMs: m, notes: h } = u(p);
|
|
4744
|
+
return p.promiseForm && p.skipped === void 0 && m < 2 && (yield* A.logWarning(`migration ${n.migration.id}: up() resolved in ${m}ms — did the body \`await\` an \`@effect/sql\` Effect by accident? \`sql.unsafe(...)\` returns an Effect, not a Promise; \`await\` on it is a silent no-op. Switch the body to \`Effect.gen(function* () { yield* sql.unsafe(...) })\` form.`).pipe(A.annotateLogs({ scope: l }))), p.skipped !== void 0 && (yield* A.logInfo(`migration ${n.migration.id} skipped: ${p.skipped}`).pipe(A.annotateLogs({ scope: l }))), yield* ac(e, n, {
|
|
4720
4745
|
env: r,
|
|
4721
4746
|
appliedBy: i,
|
|
4722
4747
|
durationMs: m,
|
|
@@ -4730,41 +4755,41 @@ BEGIN
|
|
|
4730
4755
|
absent: p.absent
|
|
4731
4756
|
}
|
|
4732
4757
|
};
|
|
4733
|
-
}),
|
|
4734
|
-
let
|
|
4735
|
-
try: () =>
|
|
4758
|
+
}), lc = (e, t, n, r) => A.gen(function* () {
|
|
4759
|
+
let i = yield* A.tryPromise({
|
|
4760
|
+
try: () => Ys(Oe(t, "migrations")),
|
|
4736
4761
|
catch: (e) => e
|
|
4737
4762
|
});
|
|
4738
|
-
if (
|
|
4763
|
+
if (i.length === 0) return {
|
|
4739
4764
|
pending: [],
|
|
4740
4765
|
alreadyApplied: [],
|
|
4741
4766
|
drifted: []
|
|
4742
4767
|
};
|
|
4743
|
-
let
|
|
4744
|
-
try: () =>
|
|
4768
|
+
let a = yield* A.tryPromise({
|
|
4769
|
+
try: () => Zs(i, r),
|
|
4745
4770
|
catch: (e) => e
|
|
4746
4771
|
});
|
|
4747
|
-
if (
|
|
4772
|
+
if (a.length === 0) return {
|
|
4748
4773
|
pending: [],
|
|
4749
4774
|
alreadyApplied: [],
|
|
4750
4775
|
drifted: []
|
|
4751
4776
|
};
|
|
4752
|
-
let
|
|
4753
|
-
for (let e of
|
|
4777
|
+
let o = new Map((yield* tc(e)).map((e) => [e.id, e.hash])), s = nc(o, a);
|
|
4778
|
+
for (let e of s) Ks.warn("file migration: the body on disk is not the one that was applied — the file no longer describes this database", {
|
|
4754
4779
|
id: e,
|
|
4755
|
-
file:
|
|
4780
|
+
file: a.find((t) => t.migration.id === e)?.file
|
|
4756
4781
|
});
|
|
4757
|
-
let
|
|
4782
|
+
let c = n === void 0 ? a : a.filter((e) => e.migration.phase === n);
|
|
4758
4783
|
return {
|
|
4759
|
-
pending:
|
|
4760
|
-
alreadyApplied:
|
|
4761
|
-
drifted:
|
|
4784
|
+
pending: c.filter((e) => !o.has(e.migration.id)),
|
|
4785
|
+
alreadyApplied: c.filter((e) => o.has(e.migration.id)),
|
|
4786
|
+
drifted: s
|
|
4762
4787
|
};
|
|
4763
|
-
}),
|
|
4788
|
+
}), uc = (e, t, n, r) => lc(e, t, n, r).pipe(A.map((e) => e.pending.map((e) => e.migration.id))), dc = (e, t, n) => lc(e, t, n).pipe(A.map((e) => e.pending.map((e) => ({
|
|
4764
4789
|
id: e.migration.id,
|
|
4765
4790
|
phase: e.migration.phase,
|
|
4766
|
-
irreversible:
|
|
4767
|
-
})))),
|
|
4791
|
+
irreversible: D(e.migration.down)
|
|
4792
|
+
})))), fc = (e, t) => lc(e, t).pipe(A.map((e) => {
|
|
4768
4793
|
let t = new Set(e.drifted);
|
|
4769
4794
|
return [...e.alreadyApplied.map((e) => ({
|
|
4770
4795
|
id: e.migration.id,
|
|
@@ -4777,16 +4802,16 @@ BEGIN
|
|
|
4777
4802
|
applied: !1,
|
|
4778
4803
|
bodyChanged: !1
|
|
4779
4804
|
}))].sort((e, t) => e.id < t.id ? -1 : 1);
|
|
4780
|
-
})),
|
|
4781
|
-
let { pending: n, alreadyApplied: r } = yield*
|
|
4805
|
+
})), pc = (e, t) => A.gen(function* () {
|
|
4806
|
+
let { pending: n, alreadyApplied: r } = yield* lc(e, t.projectRoot, t.phase), i = r.map((e) => e.migration.id);
|
|
4782
4807
|
if (n.length === 0) return {
|
|
4783
4808
|
applied: [],
|
|
4784
4809
|
skipped: i,
|
|
4785
4810
|
skips: []
|
|
4786
4811
|
};
|
|
4787
|
-
yield*
|
|
4788
|
-
let a = yield* A.acquireUseRelease(
|
|
4789
|
-
let r = new Set((yield*
|
|
4812
|
+
yield* Ro(e, N(e));
|
|
4813
|
+
let a = yield* A.acquireUseRelease(ft(e, { schema: t.lockSchema }), () => A.gen(function* () {
|
|
4814
|
+
let r = new Set((yield* tc(e)).map((e) => e.id)), i = n.filter((e) => !r.has(e.migration.id));
|
|
4790
4815
|
i.length < n.length && (yield* A.logInfo("file-based migrations applied by another process while this one waited for the migration lock").pipe(A.annotateLogs({
|
|
4791
4816
|
scope: "voltro:migrate",
|
|
4792
4817
|
ids: n.filter((e) => r.has(e.migration.id)).map((e) => e.migration.id).join(",")
|
|
@@ -4799,7 +4824,7 @@ BEGIN
|
|
|
4799
4824
|
file: n.file,
|
|
4800
4825
|
phase: n.migration.phase
|
|
4801
4826
|
}));
|
|
4802
|
-
let { durationMs: r, skip: i } = yield*
|
|
4827
|
+
let { durationMs: r, skip: i } = yield* cc(e, t.store, n, t.env, t.appliedBy, t.enclosed === !0);
|
|
4803
4828
|
a.push({
|
|
4804
4829
|
id: n.migration.id,
|
|
4805
4830
|
durationMs: r
|
|
@@ -4820,24 +4845,24 @@ BEGIN
|
|
|
4820
4845
|
skipped: i,
|
|
4821
4846
|
skips: a.skips
|
|
4822
4847
|
};
|
|
4823
|
-
}),
|
|
4848
|
+
}), mc = (e, t) => e`
|
|
4824
4849
|
SELECT ${e("id")}
|
|
4825
4850
|
FROM ${e("_voltro_migration_plans")}
|
|
4826
4851
|
WHERE ${e("id")} = ${t} AND ${e("source")} = 'file'
|
|
4827
|
-
`,
|
|
4828
|
-
if (!(yield*
|
|
4852
|
+
`, hc = (t, n) => A.gen(function* () {
|
|
4853
|
+
if (!(yield* mc(t, n.id))[0]) return yield* A.fail(/* @__PURE__ */ Error(`rollback: ${n.id} not found in _voltro_migration_plans (file source)`));
|
|
4829
4854
|
let r = yield* A.tryPromise({
|
|
4830
|
-
try: () =>
|
|
4855
|
+
try: () => Ys(Oe(n.projectRoot, "migrations")),
|
|
4831
4856
|
catch: (e) => e
|
|
4832
4857
|
}), i = (yield* A.tryPromise({
|
|
4833
|
-
try: () =>
|
|
4858
|
+
try: () => Zs(r),
|
|
4834
4859
|
catch: (e) => e
|
|
4835
4860
|
})).find((e) => e.migration.id === n.id);
|
|
4836
4861
|
if (!i) return yield* A.fail(/* @__PURE__ */ Error(`rollback: file for migration ${n.id} not found on disk under ${n.projectRoot}/migrations/`));
|
|
4837
|
-
let a =
|
|
4838
|
-
return a === void 0 ? yield* A.acquireUseRelease(
|
|
4839
|
-
if ((yield*
|
|
4840
|
-
let e = Date.now(), { ctx: r } =
|
|
4862
|
+
let a = D(i.migration.down);
|
|
4863
|
+
return a === void 0 ? yield* A.acquireUseRelease(ft(t, { schema: n.lockSchema }), () => A.gen(function* () {
|
|
4864
|
+
if ((yield* mc(t, n.id))[0] === void 0) return yield* A.fail(/* @__PURE__ */ Error(`rollback: ${n.id} was rolled back by another process while this one waited for the migration lock — nothing to do`));
|
|
4865
|
+
let e = Date.now(), { ctx: r } = zs({
|
|
4841
4866
|
sql: t,
|
|
4842
4867
|
store: n.store,
|
|
4843
4868
|
dialect: N(t),
|
|
@@ -4854,7 +4879,7 @@ BEGIN
|
|
|
4854
4879
|
durationMs: o
|
|
4855
4880
|
};
|
|
4856
4881
|
}), (e) => e.release.pipe(A.orDie)) : yield* A.fail(new e(n.id, a));
|
|
4857
|
-
}),
|
|
4882
|
+
}), gc = (e) => A.gen(function* () {
|
|
4858
4883
|
let t = yield* j.SqlClient, n = yield* t`
|
|
4859
4884
|
SELECT id, fingerprint, appliedAt FROM _voltro_migration_plans
|
|
4860
4885
|
WHERE source = 'auto-diff'
|
|
@@ -4899,8 +4924,8 @@ BEGIN
|
|
|
4899
4924
|
snapshotFingerprint: e.fingerprint,
|
|
4900
4925
|
snapshotId: i
|
|
4901
4926
|
};
|
|
4902
|
-
}),
|
|
4903
|
-
if (
|
|
4927
|
+
}), _c = (e) => new Set(e.flatMap((e) => e.op.kind === "create-table" ? [e.op.table] : [])), vc = (e, t) => t !== void 0 && "table" in e && t.createdTables.has(e.table), yc = { safe: !0 }, bc = (e, t) => {
|
|
4928
|
+
if (vc(e, t)) return yc;
|
|
4904
4929
|
switch (e.kind) {
|
|
4905
4930
|
case "add-enum-value": return { safe: !0 };
|
|
4906
4931
|
case "drop-column": return {
|
|
@@ -4932,7 +4957,7 @@ BEGIN
|
|
|
4932
4957
|
reason: `instances on the previous release read/write "${e.table}"."${e.column}" as ${e.from}; the new ${e.to} type can reject their writes or fail to decode their reads`,
|
|
4933
4958
|
remedy: "add a new column of the target type + backfill + dual-write, cut code over, then drop the old column in a LATER deploy"
|
|
4934
4959
|
};
|
|
4935
|
-
case "alter-column-nullability": return e.toNullable ?
|
|
4960
|
+
case "alter-column-nullability": return e.toNullable ? yc : {
|
|
4936
4961
|
safe: !1,
|
|
4937
4962
|
reason: `instances on the previous release may INSERT "${e.table}" without (or with NULL in) "${e.column}", which the new NOT NULL rejects`,
|
|
4938
4963
|
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)`
|
|
@@ -4943,12 +4968,12 @@ BEGIN
|
|
|
4943
4968
|
reason: `instances on the previous release still write "${e.table}" without honouring the new uniqueness; a colliding insert now fails mid-rollout`,
|
|
4944
4969
|
remedy: "make code enforce uniqueness first and deploy that; add the constraint in a LATER deploy once no old writer remains"
|
|
4945
4970
|
};
|
|
4946
|
-
case "reconcile-json-check": return e.previousValidation === "container" && e.validation === "value" ?
|
|
4971
|
+
case "reconcile-json-check": return e.previousValidation === "container" && e.validation === "value" ? yc : {
|
|
4947
4972
|
safe: !1,
|
|
4948
4973
|
reason: `instances on the previous release write "${e.table}"."${e.column}" without the new JSON validation, which now rejects them`,
|
|
4949
4974
|
remedy: "ensure all writers supply valid JSON in the required domain before enabling this check"
|
|
4950
4975
|
};
|
|
4951
|
-
case "add-check": return e.table.startsWith("_voltro_") ?
|
|
4976
|
+
case "add-check": return e.table.startsWith("_voltro_") ? yc : {
|
|
4952
4977
|
safe: !1,
|
|
4953
4978
|
reason: `instances on the previous release may write values to "${e.table}" the new CHECK rejects`,
|
|
4954
4979
|
remedy: "make code satisfy the constraint first and deploy that; add the CHECK in a LATER deploy"
|
|
@@ -4958,7 +4983,7 @@ BEGIN
|
|
|
4958
4983
|
reason: `instances on the previous release may write "${e.table}"."${e.column}" values with no matching parent row, which the new FK rejects`,
|
|
4959
4984
|
remedy: "make code guarantee the referent first and deploy that; add the FK in a LATER deploy"
|
|
4960
4985
|
};
|
|
4961
|
-
case "convert-charset": return e.charset === "utf8mb4" ?
|
|
4986
|
+
case "convert-charset": return e.charset === "utf8mb4" ? yc : {
|
|
4962
4987
|
safe: !1,
|
|
4963
4988
|
reason: `instances on the previous release may write 4-byte characters into "${e.table}", which utf8mb3 rejects with errno 1366`,
|
|
4964
4989
|
remedy: "keep utf8mb4 while any writer on the previous release remains; narrow in a LATER deploy, after every writer refuses such input itself"
|
|
@@ -4972,12 +4997,12 @@ BEGIN
|
|
|
4972
4997
|
case "drop-unique":
|
|
4973
4998
|
case "drop-unique-composite":
|
|
4974
4999
|
case "drop-foreign-key":
|
|
4975
|
-
case "drop-check": return
|
|
5000
|
+
case "drop-check": return yc;
|
|
4976
5001
|
}
|
|
4977
|
-
},
|
|
4978
|
-
let t = [], n = { createdTables:
|
|
5002
|
+
}, xc = (e) => {
|
|
5003
|
+
let t = [], n = { createdTables: _c(e) };
|
|
4979
5004
|
for (let r of e) {
|
|
4980
|
-
let e =
|
|
5005
|
+
let e = bc(r.op, n);
|
|
4981
5006
|
e.safe || t.push({
|
|
4982
5007
|
op: r,
|
|
4983
5008
|
reason: e.reason,
|
|
@@ -4985,7 +5010,7 @@ BEGIN
|
|
|
4985
5010
|
});
|
|
4986
5011
|
}
|
|
4987
5012
|
return t;
|
|
4988
|
-
},
|
|
5013
|
+
}, Sc = (e) => {
|
|
4989
5014
|
if (!e.enabled || e.unsafeCount === 0) return {
|
|
4990
5015
|
refuse: !1,
|
|
4991
5016
|
warnForced: !1,
|
|
@@ -5001,18 +5026,18 @@ BEGIN
|
|
|
5001
5026
|
warnForced: !1,
|
|
5002
5027
|
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.`
|
|
5003
5028
|
};
|
|
5004
|
-
},
|
|
5029
|
+
}, Cc = (e) => {
|
|
5005
5030
|
let t = e.table;
|
|
5006
5031
|
if (typeof t == "string") return t;
|
|
5007
5032
|
let n = e.from;
|
|
5008
5033
|
return typeof n == "string" ? n : void 0;
|
|
5009
|
-
},
|
|
5034
|
+
}, wc = (e) => ({
|
|
5010
5035
|
kind: e.op.kind,
|
|
5011
|
-
table:
|
|
5036
|
+
table: Cc(e.op),
|
|
5012
5037
|
classification: e.classification,
|
|
5013
5038
|
reason: e.reason,
|
|
5014
5039
|
blockedFix: e.blocked?.fix
|
|
5015
|
-
}),
|
|
5040
|
+
}), Tc = (e) => e.operations.map(wc), Ec = async (e) => {
|
|
5016
5041
|
let t = e.log ?? (() => {}), n = {
|
|
5017
5042
|
branchId: e.branchId,
|
|
5018
5043
|
mechanism: e.mechanism,
|
|
@@ -5031,10 +5056,10 @@ BEGIN
|
|
|
5031
5056
|
applied: !1,
|
|
5032
5057
|
converged: !1,
|
|
5033
5058
|
residual: r,
|
|
5034
|
-
infidelity:
|
|
5059
|
+
infidelity: Tc(o)
|
|
5035
5060
|
};
|
|
5036
5061
|
else {
|
|
5037
|
-
let i = await e.plan(), o =
|
|
5062
|
+
let i = await e.plan(), o = Tc(i), s = o.filter((e) => e.classification === "lossy"), c = ms(i), l = c.operations.filter((e) => e.blocked !== void 0).map(wc);
|
|
5038
5063
|
if (l.length > 0) a = {
|
|
5039
5064
|
...n,
|
|
5040
5065
|
outcome: "blocked",
|
|
@@ -5059,7 +5084,7 @@ BEGIN
|
|
|
5059
5084
|
};
|
|
5060
5085
|
else {
|
|
5061
5086
|
await e.apply(c), t(`branch ${e.branchId}: applied ${o.length} operation(s)`);
|
|
5062
|
-
let i =
|
|
5087
|
+
let i = Tc(await e.replan());
|
|
5063
5088
|
a = {
|
|
5064
5089
|
...n,
|
|
5065
5090
|
outcome: i.length > 0 ? "diverged" : s.length > 0 ? "lossy" : "clean",
|
|
@@ -5097,7 +5122,7 @@ BEGIN
|
|
|
5097
5122
|
...a,
|
|
5098
5123
|
tornDown: o
|
|
5099
5124
|
};
|
|
5100
|
-
},
|
|
5125
|
+
}, Dc = (e) => {
|
|
5101
5126
|
switch (e.outcome) {
|
|
5102
5127
|
case "clean": return 0;
|
|
5103
5128
|
case "lossy": return 2;
|
|
@@ -5106,28 +5131,28 @@ BEGIN
|
|
|
5106
5131
|
case "infidelity": return 1;
|
|
5107
5132
|
case "failed": return 1;
|
|
5108
5133
|
}
|
|
5109
|
-
},
|
|
5134
|
+
}, Oc = (e) => ` ${e.classification === "lossy" ? "✗" : "•"} ${e.kind}${e.table ? ` ${e.table}` : ""} [${e.classification}]${e.reason ? ` — ${e.reason}` : ""}${e.blockedFix ? `\n ! ${e.blockedFix}` : ""}`, kc = (e) => {
|
|
5110
5135
|
let t = [];
|
|
5111
5136
|
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"}`);
|
|
5112
5137
|
else if (e.outcome === "infidelity") {
|
|
5113
5138
|
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:");
|
|
5114
|
-
for (let n of e.infidelity) t.push(
|
|
5139
|
+
for (let n of e.infidelity) t.push(Oc(n));
|
|
5115
5140
|
} else {
|
|
5116
5141
|
t.push(` plan: ${e.operations.length} operation(s), ${e.lossy.length} lossy, ${e.blocked.length} refused`);
|
|
5117
|
-
for (let n of e.operations) t.push(
|
|
5118
|
-
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(
|
|
5142
|
+
for (let n of e.operations) t.push(Oc(n));
|
|
5143
|
+
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(Oc(n));
|
|
5119
5144
|
}
|
|
5120
5145
|
return t.push(e.tornDown ? ` branch ${e.branchId} torn down.` : ` branch ${e.branchId} KEPT — drop it when you are done.`), t.join("\n");
|
|
5121
|
-
},
|
|
5122
|
-
let e = yield* j.SqlClient, n =
|
|
5146
|
+
}, Ac = "tenant_", jc = (e) => e.map((e) => Object.fromEntries(Object.entries(e).map(([e, t]) => [e.toLowerCase(), t]))), Mc = async (e, t) => e(A.gen(function* () {
|
|
5147
|
+
let e = yield* j.SqlClient, n = jc(yield* e`
|
|
5123
5148
|
SELECT schema_name FROM information_schema.schemata
|
|
5124
|
-
WHERE schema_name LIKE ${`${
|
|
5149
|
+
WHERE schema_name LIKE ${`${Ac}%`} ORDER BY schema_name`), r = [];
|
|
5125
5150
|
for (let { schema_name: i } of n) {
|
|
5126
|
-
let n =
|
|
5151
|
+
let n = jc(yield* e`
|
|
5127
5152
|
SELECT table_name, column_name, data_type, character_set_name
|
|
5128
5153
|
FROM information_schema.columns
|
|
5129
5154
|
WHERE table_schema = ${i}
|
|
5130
|
-
ORDER BY table_name, ordinal_position`), a =
|
|
5155
|
+
ORDER BY table_name, ordinal_position`), a = jc(yield* e`
|
|
5131
5156
|
SELECT cc.table_name AS table_name, cc.check_clause AS check_clause
|
|
5132
5157
|
FROM information_schema.check_constraints cc
|
|
5133
5158
|
WHERE cc.constraint_schema = ${i}`.pipe(A.orElseSucceed(() => []))), o = /* @__PURE__ */ new Set();
|
|
@@ -5162,10 +5187,10 @@ BEGIN
|
|
|
5162
5187
|
});
|
|
5163
5188
|
}
|
|
5164
5189
|
return r;
|
|
5165
|
-
})),
|
|
5190
|
+
})), Nc = (e, ...t) => ({
|
|
5166
5191
|
_tag: "RawSqlFragment",
|
|
5167
5192
|
strings: [...e],
|
|
5168
5193
|
values: [...t]
|
|
5169
|
-
}),
|
|
5194
|
+
}), Pc = (e) => typeof e == "object" && !!e && e._tag === "RawSqlFragment";
|
|
5170
5195
|
//#endregion
|
|
5171
|
-
export {
|
|
5196
|
+
export { Nt as DEFAULT_CDC_CHANNEL, B as DEPLOY_LEDGER_TABLE, ue as FILE_MIGRATION_PATTERN, ic as FileMigrationLedgerError, e as IrreversibleMigrationError, gt as MIGRATION_ATOMICITY, pt as MIGRATION_NEEDS_TWO_CONNECTIONS, le as MIGRATION_PHASES, ur as MYSQL_CHARSETS, x as MigrationExpectationFailed, S as MigrationNeedsSqlClient, T as MigrationSkipped, Pt as REACTIVE_TRIGGER_PREFIX, d as RewriteUnstableError, yr as STORE_CHARSET_REMEDY, g as TransactionBrokenByBodyError, Ke as VOLTRO_MIGRATION_LOCK_KEY, ci as _voltroDeploysTable, ft as acquireMigrationLock, ko as addColumnDdl, U as appliedAtValue, ec as appliedFileMigrationIds, tc as appliedFileMigrations, qo as appliedLedgerOperations, Mn as applyNamespacedSchema, es as applyPlan, Sn as applySchema, Sc as assessRollingDeployGate, Dc as branchRehearsalExitCode, mr as charsetColumnsOf, wi as chunkTables, bc as classifyRollingDeploySafety, Jo as clearResumeLedger, ui as closeDeploy, fr as columnTakesCharset, _c as createdTablesOf, wr as declaredSnapshot, Wt as defaultArrayClause, Ut as defaultClause, L as defaultJsonClause, vs as describeOutcome, Vs as describeProbe, vr as describeStoreCharsetFinding, fs as destructiveScope, Er as detectReactiveTriggerDrift, eo as emitAddIndexMysql, ja as emitConvertCharsetMysql, Ga as emitCreateTableMssql, Ma as emitCreateTableMysql, Ta as emitCreateTablePg, Ra as emitCreateTableSqlite, oa as emitDropColumnDdl, sa as emitDropColumnDdlMysql, xn as emitFrameworkBootstrapSql, yn as emitNamespaceProvisionDdl, bn as emitNamespacedSchemaSql, vn as emitSchemaSql, Bi as engineFromVersion, zo as ensureDeployLedgerTable, Lo as ensureLedgerTable, Ro as ensurePlanLedgerTable, Bo as ensureReplaceMarkerTable, gn as enumRenameBlocks, hn as enumTypeBlocks, ln as extensionBlocks, di as failDeploy, Bs as failedExpectations, fc as fileMigrationStatus, R as fingerprintSchema, Qe as fnv1a64, kc as formatBranchRehearsal, Dr as formatReactiveTriggerDrift, ds as ignoreTablesFromEnv, zi as introspectSchema, b as irreversible, D as irreversibleReason, Gi as isAlreadySatisfied, ye as isFileMigration, dr as isMysqlCharset, Pc as isRawSqlFragment, wn as isReRunSafeDdl, zs as makeFileMigrationContext, hi as mapPgType, xs as materialiseSnapshot, t as migration, _t as migrationAtomicityFor, qs as migrationBodyHash, $e as migrationLockKeyForSchema, et as migrationLockNameForSchema, Ya as mysqlIndexPrefixFor, zt as notifyFunctionName, Gt as numericIdSql, li as openDeploy, mi as parseEnumCheck, uc as pendingFileMigrationIds, dc as pendingFileMigrationSummary, Gs as permanentSkips, si as planMigrations, o as plannableLiveTables, Ws as plannedCreations, Nn as provisionTenantNamespace, Ft as reactiveTriggerName, cn as reactiveTriggerRepairSql, os as recordUpToDate, Ue as registerSqlPoolCapacity, Ec as rehearseMigrationOnBranch, wc as rehearsedOperation, Oa as renderColumnMysql, Sa as renderColumnPg, Je as resolveMigrationLockSchema, H as resolveMysqlEngine, hc as rollbackFileBasedMigration, xc as rollingDeployUnsafeOps, pc as runFileBasedMigrations, Pn as runFrameworkBootstrap, jn as runMigrate, rs as runMigrationOp, _s as runPlannedMigrations, Z as runSchemaOp, lr as shortFingerprint, br as snapshotColumn, Nc as sql, I as sqlType, gc as squashMigrationPlans, pr as stampDeclaredCharset, _r as storeCharsetFindings, Mc as tenantNamespaceCharsetFindings, ms as unblockLossy, fi as unfinishedDeploys, Ys as walkMigrationFiles, ht as withMigrationLock, Us as withSchemaProbeRecorder };
|