@voltro/database 0.2.2 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +49 -0
- package/dist/{fileBased-cc9IzIjU.js → fileBased-CRXgPJkv.js} +24 -0
- package/dist/index.d.ts +45 -0
- package/dist/index.js +1 -1
- package/dist/sql.d.ts +46 -1
- package/dist/sql.js +526 -482
- package/package.json +2 -2
package/dist/sql.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { L as e, R as t, V as n, a as r, c as i, et as a, i as o, n as s, ot as c, r as l, t as u } from "./fileBased-
|
|
1
|
+
import { L as e, R as t, V as n, a as r, c as i, et as a, i as o, n as s, ot as c, r as l, t as u } from "./fileBased-CRXgPJkv.js";
|
|
2
2
|
import { Effect as d } from "effect";
|
|
3
3
|
import { createLogger as f } from "@voltro/logger";
|
|
4
4
|
import { SqlClient as p } from "@effect/sql";
|
|
@@ -39,54 +39,89 @@ var _ = (e, t, n, r = 400) => {
|
|
|
39
39
|
t !== void 0 && s.push(`db.${e}: ${t}`);
|
|
40
40
|
}
|
|
41
41
|
return s.push(""), s.join("\n");
|
|
42
|
-
}, v = (e, t) =>
|
|
42
|
+
}, v = (e) => e.unique === !0 && typeof e.where == "string" && e.where.length > 0, y = (e) => e.replace(/"/g, "`"), te = (e) => typeof e == "string" ? e : e.name ?? String(e), ne = (e, t) => `_ua_${t}_${e}`.slice(0, 64), b = (e, t) => {
|
|
43
|
+
if (t !== "mysql" && t !== "mariadb" || !e.appliedIndexes.some(v)) return e;
|
|
44
|
+
let n = { ...e.fields }, r = [], i = [];
|
|
45
|
+
for (let t of e.appliedIndexes) {
|
|
46
|
+
if (!v(t)) {
|
|
47
|
+
r.push(t);
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
let a = y(t.where), o = [];
|
|
51
|
+
for (let r of t.fields) {
|
|
52
|
+
let i = te(r);
|
|
53
|
+
if (!(i in e.fields)) throw Error(`@voltro/migrate: uniqueActive '${t.name}' on '${e.tableName}' references unknown column '${i}'.`);
|
|
54
|
+
let s = ne(t.name, i);
|
|
55
|
+
o.push(s), n[s] = {
|
|
56
|
+
type: "text",
|
|
57
|
+
nullable: !0,
|
|
58
|
+
unique: !1,
|
|
59
|
+
maxLength: 255,
|
|
60
|
+
generatedAs: {
|
|
61
|
+
expr: `CASE WHEN ${a} THEN CAST(\`${i}\` AS CHAR(255)) ELSE NULL END`,
|
|
62
|
+
stored: !0
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
i.push({
|
|
67
|
+
name: t.name,
|
|
68
|
+
fields: o
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
return {
|
|
72
|
+
...e,
|
|
73
|
+
fields: n,
|
|
74
|
+
appliedIndexes: r,
|
|
75
|
+
appliedUniques: [...e.appliedUniques ?? [], ...i]
|
|
76
|
+
};
|
|
77
|
+
}, x = (e, t) => `${e}::${t}`, S = (e, t) => {
|
|
43
78
|
let n = /* @__PURE__ */ new Set(), r = /* @__PURE__ */ new Set(), i = /* @__PURE__ */ new Set(), a = (e) => {
|
|
44
79
|
n.add(e);
|
|
45
80
|
let o = [...t(e)].filter((t) => t.target !== e).sort((e, t) => e.column.localeCompare(t.column));
|
|
46
|
-
for (let t of o) n.has(t.target) ? i.add(
|
|
81
|
+
for (let t of o) n.has(t.target) ? i.add(x(e, t.column)) : r.has(t.target) || a(t.target);
|
|
47
82
|
n.delete(e), r.add(e);
|
|
48
83
|
};
|
|
49
84
|
for (let t of [...e].sort()) r.has(t) || a(t);
|
|
50
85
|
return i;
|
|
51
|
-
},
|
|
86
|
+
}, C = 6322741009312437n, re = 250, ie = () => {
|
|
52
87
|
let e = Number(process.env.VOLTRO_MIGRATION_LOCK_TIMEOUT_MS);
|
|
53
88
|
return Number.isFinite(e) && e > 0 ? e : 3e4;
|
|
54
|
-
},
|
|
55
|
-
let t =
|
|
89
|
+
}, ae = (e) => d.gen(function* () {
|
|
90
|
+
let t = ie(), n = Date.now();
|
|
56
91
|
for (;;) {
|
|
57
92
|
if ((yield* e`
|
|
58
93
|
SELECT pg_try_advisory_lock(${"6322741009312437"}::bigint) AS got`)[0]?.got) return;
|
|
59
|
-
Date.now() - n >= t && (yield* d.die(/* @__PURE__ */ Error(`could not acquire the postgres migration advisory lock within ${Math.round(t / 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* d.sleep(`${
|
|
94
|
+
Date.now() - n >= t && (yield* d.die(/* @__PURE__ */ Error(`could not acquire the postgres migration advisory lock within ${Math.round(t / 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* d.sleep(`${re} millis`);
|
|
60
95
|
}
|
|
61
|
-
}),
|
|
62
|
-
yield* e`SELECT pg_advisory_unlock(${
|
|
63
|
-
}),
|
|
96
|
+
}), oe = (e) => d.gen(function* () {
|
|
97
|
+
yield* e`SELECT pg_advisory_unlock(${C.toString()}::bigint)`;
|
|
98
|
+
}), se = `voltro_migration_${C.toString(36)}`, ce = 30, le = (e) => d.gen(function* () {
|
|
64
99
|
(yield* e`
|
|
65
|
-
SELECT GET_LOCK(${
|
|
66
|
-
}),
|
|
67
|
-
yield* e`SELECT RELEASE_LOCK(${
|
|
68
|
-
}),
|
|
100
|
+
SELECT GET_LOCK(${se}, ${ce}) AS got`)[0]?.got !== 1 && (yield* d.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${se}' within ${ce}s (another migration is in progress, or a prior one left it held).`)));
|
|
101
|
+
}), ue = (e) => d.gen(function* () {
|
|
102
|
+
yield* e`SELECT RELEASE_LOCK(${se})`;
|
|
103
|
+
}), de = `voltro_migration_${C.toString(36)}`, fe = 3e4, pe = (e) => d.gen(function* () {
|
|
69
104
|
let t = yield* e`
|
|
70
105
|
DECLARE @res int;
|
|
71
|
-
EXEC @res = sp_getapplock @Resource = ${
|
|
72
|
-
@LockOwner = 'Session', @LockTimeout = ${
|
|
106
|
+
EXEC @res = sp_getapplock @Resource = ${de}, @LockMode = 'Exclusive',
|
|
107
|
+
@LockOwner = 'Session', @LockTimeout = ${fe};
|
|
73
108
|
SELECT @res AS res`;
|
|
74
|
-
(t[0]?.res ?? -999) < 0 && (yield* d.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${
|
|
75
|
-
}),
|
|
76
|
-
yield* e`EXEC sp_releaseapplock @Resource = ${
|
|
77
|
-
}),
|
|
78
|
-
mysql: () =>
|
|
79
|
-
mssql: () =>
|
|
80
|
-
sqlite: () =>
|
|
81
|
-
orElse: () =>
|
|
109
|
+
(t[0]?.res ?? -999) < 0 && (yield* d.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${de}' (sp_getapplock returned ${t[0]?.res ?? "no row"}; another migration is in progress).`)));
|
|
110
|
+
}), me = (e) => d.gen(function* () {
|
|
111
|
+
yield* e`EXEC sp_releaseapplock @Resource = ${de}, @LockOwner = 'Session'`;
|
|
112
|
+
}), he = d.void, w = (e) => e.onDialectOrElse({
|
|
113
|
+
mysql: () => le(e),
|
|
114
|
+
mssql: () => pe(e),
|
|
115
|
+
sqlite: () => he,
|
|
116
|
+
orElse: () => ae(e)
|
|
82
117
|
}), T = (e) => e.onDialectOrElse({
|
|
83
|
-
mysql: () =>
|
|
84
|
-
mssql: () =>
|
|
85
|
-
sqlite: () =>
|
|
86
|
-
orElse: () =>
|
|
87
|
-
}),
|
|
88
|
-
|
|
89
|
-
},
|
|
118
|
+
mysql: () => ue(e),
|
|
119
|
+
mssql: () => me(e),
|
|
120
|
+
sqlite: () => he,
|
|
121
|
+
orElse: () => oe(e)
|
|
122
|
+
}), ge = (e, t) => d.acquireUseRelease(w(e), () => t, () => T(e).pipe(d.orDie)), _e = f({ scope: "voltro:migrate" }), E = (e) => {
|
|
123
|
+
_e.warn(e.replace(/^\[voltro:migrate\]\s*/, ""));
|
|
124
|
+
}, D = (t, n) => {
|
|
90
125
|
let r = t.type;
|
|
91
126
|
if (t.spatial) {
|
|
92
127
|
if (n === "postgres") return `${t.spatial.kind}(${t.spatial.geomKind},${t.spatial.srid})`;
|
|
@@ -97,7 +132,7 @@ var _ = (e, t, n, r = 400) => {
|
|
|
97
132
|
return t.rawDdl;
|
|
98
133
|
}
|
|
99
134
|
if (r === "array" && t.arrayElement) {
|
|
100
|
-
if (n === "postgres") return `${
|
|
135
|
+
if (n === "postgres") return `${D({
|
|
101
136
|
...t,
|
|
102
137
|
type: t.arrayElement,
|
|
103
138
|
arrayElement: void 0
|
|
@@ -197,14 +232,14 @@ var _ = (e, t, n, r = 400) => {
|
|
|
197
232
|
case "array": return "TEXT[]";
|
|
198
233
|
case "interval": return "INTERVAL";
|
|
199
234
|
}
|
|
200
|
-
},
|
|
235
|
+
}, ve = (t, n) => {
|
|
201
236
|
if (!t.hasDefault || t.defaultFactory !== void 0) return null;
|
|
202
237
|
let r = t.defaultValue;
|
|
203
|
-
return r === "now" ? e(n) ? "DEFAULT CURRENT_TIMESTAMP" : n === "mssql" ? "DEFAULT SYSUTCDATETIME()" : n === "mysql" || n === "mariadb" ? "DEFAULT CURRENT_TIMESTAMP(6)" : "DEFAULT now()" : typeof r == "boolean" ? n === "postgres" ? `DEFAULT ${r}` : `DEFAULT ${+!!r}` : typeof r == "number" ? `DEFAULT ${r}` : typeof r == "string" ? `DEFAULT '${r.replace(/'/g, "''")}'` : typeof r == "object" && r && !Array.isArray(r) ?
|
|
204
|
-
},
|
|
238
|
+
return r === "now" ? e(n) ? "DEFAULT CURRENT_TIMESTAMP" : n === "mssql" ? "DEFAULT SYSUTCDATETIME()" : n === "mysql" || n === "mariadb" ? "DEFAULT CURRENT_TIMESTAMP(6)" : "DEFAULT now()" : typeof r == "boolean" ? n === "postgres" ? `DEFAULT ${r}` : `DEFAULT ${+!!r}` : typeof r == "number" ? `DEFAULT ${r}` : typeof r == "string" ? `DEFAULT '${r.replace(/'/g, "''")}'` : typeof r == "object" && r && !Array.isArray(r) ? O(r, n) : null;
|
|
239
|
+
}, O = (e, t) => {
|
|
205
240
|
let n = JSON.stringify(e).replace(/'/g, "''");
|
|
206
241
|
return t === "postgres" ? `DEFAULT '${n}'::jsonb` : t === "mysql" || t === "mariadb" ? `DEFAULT (CAST('${n}' AS JSON))` : `DEFAULT '${n}'`;
|
|
207
|
-
},
|
|
242
|
+
}, k = (e, t) => {
|
|
208
243
|
switch (t) {
|
|
209
244
|
case "postgres": return `"${e}" BIGSERIAL PRIMARY KEY`;
|
|
210
245
|
case "mysql":
|
|
@@ -213,7 +248,7 @@ var _ = (e, t, n, r = 400) => {
|
|
|
213
248
|
case "sqlite": return `"${e}" INTEGER PRIMARY KEY AUTOINCREMENT`;
|
|
214
249
|
case "turso": return `"${e}" INTEGER PRIMARY KEY`;
|
|
215
250
|
}
|
|
216
|
-
},
|
|
251
|
+
}, A = (e, t) => {
|
|
217
252
|
if (e === "restrict" && t === "mssql") return "NO ACTION";
|
|
218
253
|
switch (e) {
|
|
219
254
|
case "cascade": return "CASCADE";
|
|
@@ -221,38 +256,38 @@ var _ = (e, t, n, r = 400) => {
|
|
|
221
256
|
case "setNull": return "SET NULL";
|
|
222
257
|
case "noAction": return "NO ACTION";
|
|
223
258
|
}
|
|
224
|
-
},
|
|
259
|
+
}, ye = (e, n, r) => r === null ? t(e, n) : `${t(r, n)}.${t(e, n)}`, be = 191, xe = (e, n, r) => {
|
|
225
260
|
let i = t(e, r);
|
|
226
261
|
if (r !== "mysql" && r !== "mariadb") return i;
|
|
227
262
|
let a = n[e];
|
|
228
263
|
if (!a) return i;
|
|
229
|
-
let o =
|
|
230
|
-
return o.endsWith("TEXT") || o.endsWith("BLOB") ? `${i}(${
|
|
231
|
-
},
|
|
264
|
+
let o = D(a, r).toUpperCase();
|
|
265
|
+
return o.endsWith("TEXT") || o.endsWith("BLOB") ? `${i}(${be})` : i;
|
|
266
|
+
}, Se = (e, t) => {
|
|
232
267
|
if (!e.generatedAs) return null;
|
|
233
268
|
let { expr: n, stored: r } = e.generatedAs;
|
|
234
|
-
if (t === "postgres") return r ||
|
|
269
|
+
if (t === "postgres") return r || E("[voltro:migrate] generated column requested as VIRTUAL but postgres only supports STORED — promoting"), `GENERATED ALWAYS AS (${n}) STORED`;
|
|
235
270
|
if (t === "mysql" || t === "mariadb") return `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
|
|
236
271
|
if (t === "mssql") return `AS (${n})${r ? " PERSISTED" : ""}`;
|
|
237
272
|
if (t === "turso") throw Error("@voltro/sql-turso: generated columns (.generatedAs(...)) are not supported — Turso's MVCC mode (journal_mode=experimental_mvcc) rejects them. Drop the generated column, or use the 'sqlite' / 'postgres' dialect for this table.");
|
|
238
273
|
return `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
|
|
239
|
-
},
|
|
240
|
-
if (r.type === "id" && r.idScheme?.kind === "numeric") return
|
|
241
|
-
let c = i === "mssql" && r.type === "text" && !r.generatedAs && r.maxLength === void 0 && a?.has(n) ? "NVARCHAR(450)" :
|
|
274
|
+
}, Ce = (n, r, i, a, o = !1, s = !1) => {
|
|
275
|
+
if (r.type === "id" && r.idScheme?.kind === "numeric") return k(n, i);
|
|
276
|
+
let c = i === "mssql" && r.type === "text" && !r.generatedAs && r.maxLength === void 0 && a?.has(n) ? "NVARCHAR(450)" : D(r, i), l = [t(n, i), c];
|
|
242
277
|
r.type === "id" && !s && l.push("PRIMARY KEY");
|
|
243
|
-
let u =
|
|
278
|
+
let u = Se(r, i);
|
|
244
279
|
if (u) l.push(u);
|
|
245
280
|
else {
|
|
246
281
|
r.nullable || l.push("NOT NULL"), r.unique && r.type !== "id" && l.push("UNIQUE");
|
|
247
|
-
let e =
|
|
282
|
+
let e = ve(r, i);
|
|
248
283
|
e && l.push(e);
|
|
249
284
|
}
|
|
250
285
|
if (r.type === "reference" && r.references && !o) {
|
|
251
286
|
let e = r.references();
|
|
252
287
|
l.push(`REFERENCES ${t(e.tableName, i)} (${t("id", i)})`);
|
|
253
|
-
let n =
|
|
288
|
+
let n = A(r.onDelete ?? "restrict", i);
|
|
254
289
|
l.push(`ON DELETE ${n}`);
|
|
255
|
-
let a =
|
|
290
|
+
let a = A(r.refOnUpdate ?? "noAction", i);
|
|
256
291
|
a !== "NO ACTION" && l.push(`ON UPDATE ${a}`);
|
|
257
292
|
}
|
|
258
293
|
if (r.oneOf && r.oneOf.length > 0) {
|
|
@@ -269,18 +304,18 @@ var _ = (e, t, n, r = 400) => {
|
|
|
269
304
|
e(i) ? l.push(`CHECK (${r} IS NULL OR json_valid(${r}))`) : i === "mssql" && l.push(`CHECK (${r} IS NULL OR ISJSON(${r}) = 1)`);
|
|
270
305
|
}
|
|
271
306
|
return l.join(" ");
|
|
272
|
-
},
|
|
307
|
+
}, we = (e, n, r = null, i) => {
|
|
273
308
|
let a = /* @__PURE__ */ new Set();
|
|
274
309
|
for (let t of e.appliedIndexes ?? []) for (let e of t.fields) typeof e == "string" && a.add(e);
|
|
275
310
|
for (let t of e.appliedUniques ?? []) for (let e of t.fields) typeof e == "string" && a.add(e);
|
|
276
|
-
let o = e.appliedPrimaryKey ?? [], s = o.length > 0, c = Object.entries(e.fields).map(([e, t]) => ` ${
|
|
277
|
-
let i = r.fields.map((t) =>
|
|
311
|
+
let o = e.appliedPrimaryKey ?? [], s = o.length > 0, c = Object.entries(e.fields).map(([e, t]) => ` ${Ce(e, t, n, a, i?.has(e) ?? !1, s)}`).join(",\n"), l = (e.appliedUniques ?? []).map((r) => {
|
|
312
|
+
let i = r.fields.map((t) => xe(t, e.fields, n)).join(", ");
|
|
278
313
|
return ` CONSTRAINT ${t(r.name, n)} UNIQUE (${i})`;
|
|
279
314
|
}), u = (e.appliedChecks ?? []).map((e) => ` CONSTRAINT ${t(e.name, n)} CHECK (${e.expr})`), d = [
|
|
280
|
-
...s ? [` PRIMARY KEY (${o.map((t) =>
|
|
315
|
+
...s ? [` PRIMARY KEY (${o.map((t) => xe(t, e.fields, n)).join(", ")})`] : [],
|
|
281
316
|
...l,
|
|
282
317
|
...u
|
|
283
|
-
], f = d.length > 0 ? `${c},\n${d.join(",\n")}` : c, p =
|
|
318
|
+
], f = d.length > 0 ? `${c},\n${d.join(",\n")}` : c, p = ye(e.tableName, n, r);
|
|
284
319
|
if (n === "mssql") {
|
|
285
320
|
let t = r === null ? e.tableName : `${r}.${e.tableName}`, n = `CREATE TABLE ${p} (\n${f}\n)`;
|
|
286
321
|
return `IF OBJECT_ID('${t.replace(/'/g, "''")}', 'U') IS NULL EXEC(N'${n.replace(/'/g, "''")}');`;
|
|
@@ -290,10 +325,10 @@ var _ = (e, t, n, r = 400) => {
|
|
|
290
325
|
f,
|
|
291
326
|
");"
|
|
292
327
|
].join("\n");
|
|
293
|
-
},
|
|
328
|
+
}, Te = (e, n, r) => {
|
|
294
329
|
let i = `${e}_${n.name}_fts`, a = (e) => t(e, r), o = n.columns.map(a).join(", "), s = n.columns.map((e) => `new.${a(e)}`).join(", "), c = [];
|
|
295
330
|
return c.push(`CREATE VIRTUAL TABLE IF NOT EXISTS ${a(i)} USING fts5(${o}, row_id UNINDEXED, tokenize='porter');`), c.push(`CREATE TRIGGER IF NOT EXISTS ${a(`${i}_ai`)} AFTER INSERT ON ${a(e)} BEGIN\n INSERT INTO ${a(i)} (${o}, row_id) VALUES (${s}, new.${a("id")});\nEND;`), c.push(`CREATE TRIGGER IF NOT EXISTS ${a(`${i}_ad`)} AFTER DELETE ON ${a(e)} BEGIN\n DELETE FROM ${a(i)} WHERE row_id = old.${a("id")};\nEND;`), c.push(`CREATE TRIGGER IF NOT EXISTS ${a(`${i}_au`)} AFTER UPDATE ON ${a(e)} BEGIN\n DELETE FROM ${a(i)} WHERE row_id = old.${a("id")};\n INSERT INTO ${a(i)} (${o}, row_id) VALUES (${s}, new.${a("id")});\nEND;`), c;
|
|
296
|
-
},
|
|
331
|
+
}, Ee = (e, r, i = null) => {
|
|
297
332
|
let a = [], s = /* @__PURE__ */ new Set(), c = (e) => e.join("\0"), l = (e, t, i, a) => {
|
|
298
333
|
let o = {
|
|
299
334
|
using: "",
|
|
@@ -305,21 +340,21 @@ var _ = (e, t, n, r = 400) => {
|
|
|
305
340
|
using: " USING GIST",
|
|
306
341
|
withSuffix: "",
|
|
307
342
|
skip: !1
|
|
308
|
-
} : (
|
|
343
|
+
} : (E(`[voltro:migrate] index '${e}' on '${t}': ${r} doesn't support GiST — falling back to btree. Spatial queries on this column will fall back to sequential scan.`), o);
|
|
309
344
|
if (i === "gin") return r === "postgres" ? {
|
|
310
345
|
using: " USING GIN",
|
|
311
346
|
withSuffix: "",
|
|
312
347
|
skip: !1
|
|
313
|
-
} : r === "mysql" || r === "mariadb" ? (
|
|
348
|
+
} : r === "mysql" || r === "mariadb" ? (E(`[voltro:migrate] gin index '${e}' on '${t}': ${r} has no GIN access method — skipping (a btree on a JSON/array column can't serve containment/membership queries). Add a generated column for the specific path you query, then index that with .expressionIndex(...).`), {
|
|
314
349
|
using: "",
|
|
315
350
|
withSuffix: "",
|
|
316
351
|
skip: !0
|
|
317
|
-
}) : (
|
|
352
|
+
}) : (E(`[voltro:migrate] gin index '${e}' on '${t}': ${r} has no GIN access method — falling back to btree. Containment/membership queries won't use this index efficiently.`), o);
|
|
318
353
|
if (i === "brin") return r === "postgres" ? {
|
|
319
354
|
using: " USING BRIN",
|
|
320
355
|
withSuffix: "",
|
|
321
356
|
skip: !1
|
|
322
|
-
} : (
|
|
357
|
+
} : (E(`[voltro:migrate] brin index '${e}' on '${t}': ${r} has no BRIN access method — falling back to btree (larger on disk, but the range scan still works).`), o);
|
|
323
358
|
if (i === "hnsw") {
|
|
324
359
|
if (r === "postgres") {
|
|
325
360
|
let e = a?.hnsw?.m ?? 16, t = a?.hnsw?.efConstruction ?? 64, r = a?.hnsw?.opclass ?? n(a?.hnsw?.distance);
|
|
@@ -330,7 +365,7 @@ var _ = (e, t, n, r = 400) => {
|
|
|
330
365
|
skip: !1
|
|
331
366
|
};
|
|
332
367
|
}
|
|
333
|
-
return
|
|
368
|
+
return E(`[voltro:migrate] hnsw index '${e}' on '${t}': ${r} has no pgvector / HNSW access method — skipping. Nearest-neighbour queries on this column fall back to a sequential scan.`), {
|
|
334
369
|
using: "",
|
|
335
370
|
withSuffix: "",
|
|
336
371
|
skip: !0
|
|
@@ -339,7 +374,7 @@ var _ = (e, t, n, r = 400) => {
|
|
|
339
374
|
return o;
|
|
340
375
|
}, u = (t, n) => {
|
|
341
376
|
let i = t.map((t) => {
|
|
342
|
-
if (typeof t == "string") return
|
|
377
|
+
if (typeof t == "string") return xe(t, e.fields, r);
|
|
343
378
|
if ("jsonPath" in t) {
|
|
344
379
|
let { column: e, path: n, numeric: i } = t.jsonPath;
|
|
345
380
|
return `(${o(e, n, r, { numeric: i })})`;
|
|
@@ -347,11 +382,11 @@ var _ = (e, t, n, r = 400) => {
|
|
|
347
382
|
return `(${t.expr})`;
|
|
348
383
|
});
|
|
349
384
|
return n !== void 0 && i.length === 1 ? `${i[0]} ${n}` : i.join(", ");
|
|
350
|
-
}, d = (e, n, a, o, s, c = "") => {
|
|
351
|
-
let
|
|
352
|
-
if (
|
|
353
|
-
let
|
|
354
|
-
return r === "mssql" ? `IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = '${e}') CREATE INDEX ${t(e, r)} ON ${
|
|
385
|
+
}, d = (e, n, a, o, s, c = "", d = !1) => {
|
|
386
|
+
let f = l(e, n, o, s);
|
|
387
|
+
if (f.skip) return "";
|
|
388
|
+
let p = u(a, f.opclass), m = `${f.withSuffix}${c}`, h = ye(n, r, i), g = d ? "UNIQUE " : "";
|
|
389
|
+
return r === "mssql" ? `IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = '${e}') CREATE ${g}INDEX ${t(e, r)} ON ${h}${f.using} (${p})${m};` : r === "mysql" ? `CREATE ${g}INDEX ${t(e, r)} ON ${h}${f.using} (${p})${m};` : `CREATE ${g}INDEX IF NOT EXISTS ${t(e, r)} ON ${h}${f.using} (${p})${m};`;
|
|
355
390
|
};
|
|
356
391
|
for (let n of e.appliedFullText ?? []) if (r === "postgres") {
|
|
357
392
|
let i = n.config ?? "english", o = `${n.name}_tsv`, s = n.columns.map((e) => {
|
|
@@ -363,15 +398,16 @@ var _ = (e, t, n, r = 400) => {
|
|
|
363
398
|
let i = n.columns.map((e) => t(e, r)).join(", ");
|
|
364
399
|
a.push(`CREATE FULLTEXT INDEX ${t(n.name, r)} ON ${t(e.tableName, r)} (${i});`);
|
|
365
400
|
} else if (r === "turso") throw Error(`@voltro/sql-turso: full-text index '${n.name}' on '${e.tableName}' is not supported — Turso's MVCC mode has no FTS5 virtual tables. Drop .fullTextIndex(), or use the 'sqlite' / 'postgres' dialect for this table.`);
|
|
366
|
-
else r === "sqlite" ? a.push(...
|
|
401
|
+
else r === "sqlite" ? a.push(...Te(e.tableName, n, r)) : E(`[voltro:migrate] full-text index '${n.name}' on '${e.tableName}': ${r} uses a ranked LIKE search at query time (no native FTS catalog required).`);
|
|
367
402
|
for (let t of e.appliedIndexes) {
|
|
368
403
|
if ((r === "mariadb" || r === "mssql") && t.fields.some((e) => typeof e != "string" && "jsonPath" in e)) {
|
|
369
|
-
|
|
404
|
+
E(`[voltro:migrate] json-path index '${t.name}' on '${e.tableName}': ${r} cannot index a JSON expression directly — skipping. For an indexed JSON path on ${r}, add a generated column for the path (text().generatedAs(...) / .stored()) and .index([...]) it, then filter on that column instead of jsonField(...).`);
|
|
370
405
|
continue;
|
|
371
406
|
}
|
|
407
|
+
if (t.unique && t.where !== void 0 && t.where.length > 0 && (r === "mysql" || r === "mariadb")) throw Error(`@voltro/migrate: uniqueActive index '${t.name}' on '${e.tableName}' cannot be expressed on ${r} — it has no partial (WHERE) index support, and a full UNIQUE index would forbid re-creating a soft-deleted row. Use a generated STORED column (text().generatedAs("CASE WHEN \`deletedAt\` IS NULL THEN <key> ELSE NULL END", { stored: true })) + .unique([...]) on ${r}, or move this table to postgres/sqlite/mssql.`);
|
|
372
408
|
let n = "";
|
|
373
|
-
t.where !== void 0 && t.where.length > 0 && (r === "mysql" || r === "mariadb" ?
|
|
374
|
-
let i = d(t.name, e.tableName, t.fields, t.kind, t.kindOptions, n);
|
|
409
|
+
t.where !== void 0 && t.where.length > 0 && (r === "mysql" || r === "mariadb" ? E(`[voltro:migrate] partial index '${t.name}' on '${e.tableName}': ${r} does not support WHERE clauses on indexes — emitting a full index`) : n = ` WHERE ${t.where}`);
|
|
410
|
+
let i = d(t.name, e.tableName, t.fields, t.kind, t.kindOptions, n, t.unique === !0);
|
|
375
411
|
i !== "" && a.push(i), t.fields.every((e) => typeof e == "string") && s.add(c(t.fields));
|
|
376
412
|
}
|
|
377
413
|
for (let [t, n] of Object.entries(e.fields)) {
|
|
@@ -380,14 +416,14 @@ var _ = (e, t, n, r = 400) => {
|
|
|
380
416
|
a.push(d(r, e.tableName, [t])), s.add(c([t]));
|
|
381
417
|
}
|
|
382
418
|
return a.join("\n");
|
|
383
|
-
},
|
|
419
|
+
}, De = "CREATE OR REPLACE FUNCTION framework_notify_change() RETURNS trigger AS $$\nDECLARE\n payload TEXT;\nBEGIN\n payload := json_build_object(\n 'table', TG_TABLE_NAME,\n -- The schema the write landed in. Under namespace isolation this is\n -- the tenant schema (tenant_<id>); the CDC consumer uses it so a\n -- write in tenant A namespace does not spuriously wake tenant B\n -- subscriptions on the same-named table. public/absent = shared.\n 'schema', TG_TABLE_SCHEMA,\n 'op', lower(TG_OP),\n 'old', CASE WHEN TG_OP = 'INSERT' THEN NULL ELSE row_to_json(OLD) END,\n 'new', CASE WHEN TG_OP = 'DELETE' THEN NULL ELSE row_to_json(NEW) END\n )::text;\n -- pg_notify hard-caps the payload at 8000 bytes; a wide reactive row\n -- (big text / json column) would otherwise abort the write itself.\n -- Fall back to a body-less notice — the CDC consumer treats absent\n -- old/new as \"all columns changed\" and re-queries, so correctness is\n -- preserved; only the delta-diff fast path is skipped for that write.\n IF octet_length(payload) >= 7999 THEN\n payload := json_build_object(\n 'table', TG_TABLE_NAME,\n 'schema', TG_TABLE_SCHEMA,\n 'op', lower(TG_OP),\n 'old', NULL,\n 'new', NULL,\n 'oversized', true\n )::text;\n END IF;\n PERFORM pg_notify('framework_changes', payload);\n RETURN COALESCE(NEW, OLD);\nEND;\n$$ LANGUAGE plpgsql;", Oe = (e) => `
|
|
384
420
|
ALTER TABLE "${e.tableName}" REPLICA IDENTITY FULL;
|
|
385
421
|
DROP TRIGGER IF EXISTS framework_changes_${e.tableName} ON "${e.tableName}";
|
|
386
422
|
CREATE TRIGGER framework_changes_${e.tableName}
|
|
387
423
|
AFTER INSERT OR UPDATE OR DELETE ON "${e.tableName}"
|
|
388
424
|
FOR EACH ROW EXECUTE FUNCTION framework_notify_change();
|
|
389
|
-
`.trim(),
|
|
390
|
-
let t = new Map(e.map((e) => [e.tableName, e])), n =
|
|
425
|
+
`.trim(), ke = (e) => e.some((e) => Object.values(e.fields).some((e) => e.type === "vector")), Ae = (e) => e.some((e) => Object.values(e.fields).some((e) => e.spatial !== void 0)), je = (e) => {
|
|
426
|
+
let t = new Map(e.map((e) => [e.tableName, e])), n = S(e.map((e) => e.tableName), (e) => {
|
|
391
427
|
let n = t.get(e);
|
|
392
428
|
return n ? Object.entries(n.fields).flatMap(([e, n]) => {
|
|
393
429
|
if (n.type !== "reference" || !n.references) return [];
|
|
@@ -398,7 +434,7 @@ FOR EACH ROW EXECUTE FUNCTION framework_notify_change();
|
|
|
398
434
|
}] : [];
|
|
399
435
|
}) : [];
|
|
400
436
|
}), r = [];
|
|
401
|
-
for (let t of e) for (let [e, i] of Object.entries(t.fields)) i.type !== "reference" || !i.references || n.has(
|
|
437
|
+
for (let t of e) for (let [e, i] of Object.entries(t.fields)) i.type !== "reference" || !i.references || n.has(x(t.tableName, e)) && r.push({
|
|
402
438
|
table: t.tableName,
|
|
403
439
|
column: e,
|
|
404
440
|
targetTable: i.references().tableName,
|
|
@@ -409,7 +445,7 @@ FOR EACH ROW EXECUTE FUNCTION framework_notify_change();
|
|
|
409
445
|
if (!(i.has(e.tableName) || a.has(e.tableName))) {
|
|
410
446
|
a.add(e.tableName);
|
|
411
447
|
for (let [r, i] of Object.entries(e.fields)) {
|
|
412
|
-
if (i.type !== "reference" || !i.references || n.has(
|
|
448
|
+
if (i.type !== "reference" || !i.references || n.has(x(e.tableName, r))) continue;
|
|
413
449
|
let a = i.references();
|
|
414
450
|
if (a.tableName === e.tableName) continue;
|
|
415
451
|
let o = t.get(a.tableName);
|
|
@@ -423,8 +459,8 @@ FOR EACH ROW EXECUTE FUNCTION framework_notify_change();
|
|
|
423
459
|
sorted: o,
|
|
424
460
|
cyclic: r
|
|
425
461
|
};
|
|
426
|
-
},
|
|
427
|
-
let i = (e) => r ? `${t(r, n)}.${t(e, n)}` : t(e, n), a = `${e.table}_${e.column}_fkey`, o =
|
|
462
|
+
}, Me = (e, n, r = null) => {
|
|
463
|
+
let i = (e) => r ? `${t(r, n)}.${t(e, n)}` : t(e, n), a = `${e.table}_${e.column}_fkey`, o = A(e.onDelete, n), s = A(e.onUpdate, n), c = ` ON DELETE ${o}${s === "NO ACTION" ? "" : ` ON UPDATE ${s}`}`, l = (r) => `ADD CONSTRAINT ${t(a, n)} FOREIGN KEY ${r ? "IF NOT EXISTS " : ""}(${t(e.column, n)}) REFERENCES ${i(e.targetTable)} (${t("id", n)})${c}`;
|
|
428
464
|
switch (n) {
|
|
429
465
|
case "postgres": return [
|
|
430
466
|
"DO $$ BEGIN",
|
|
@@ -438,7 +474,7 @@ FOR EACH ROW EXECUTE FUNCTION framework_notify_change();
|
|
|
438
474
|
case "mariadb": return `ALTER TABLE ${i(e.table)} ${l(!0)};`;
|
|
439
475
|
default: return `ALTER TABLE ${i(e.table)} ${l(!1)};`;
|
|
440
476
|
}
|
|
441
|
-
},
|
|
477
|
+
}, Ne = (t, n) => {
|
|
442
478
|
let r = /* @__PURE__ */ new Map();
|
|
443
479
|
if (e(n)) return r;
|
|
444
480
|
for (let e of t) {
|
|
@@ -446,7 +482,7 @@ FOR EACH ROW EXECUTE FUNCTION framework_notify_change();
|
|
|
446
482
|
t.add(e.column), r.set(e.table, t);
|
|
447
483
|
}
|
|
448
484
|
return r;
|
|
449
|
-
},
|
|
485
|
+
}, Pe = (e, t) => {
|
|
450
486
|
if (t !== "postgres") return "";
|
|
451
487
|
let n = /* @__PURE__ */ new Map();
|
|
452
488
|
for (let t of e) for (let e of Object.values(t.fields)) {
|
|
@@ -462,7 +498,7 @@ FOR EACH ROW EXECUTE FUNCTION framework_notify_change();
|
|
|
462
498
|
r.push(`DO $$ BEGIN\n IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = '${e.replace(/'/g, "''")}') THEN\n CREATE TYPE "${e}" AS ENUM (${n});\n END IF;\nEND $$;`);
|
|
463
499
|
}
|
|
464
500
|
return r.join("\n\n");
|
|
465
|
-
},
|
|
501
|
+
}, Fe = (e, t) => {
|
|
466
502
|
if (t !== "postgres") return "";
|
|
467
503
|
let n = /* @__PURE__ */ new Set();
|
|
468
504
|
for (let t of e) for (let e of Object.values(t.fields)) e.type === "enum" && e.enumName && n.add(e.enumName);
|
|
@@ -476,34 +512,34 @@ BEGIN
|
|
|
476
512
|
SELECT oid INTO type_oid FROM pg_type WHERE typname = '${i}';\n IF type_oid IS NOT NULL\n AND EXISTS (SELECT 1 FROM pg_enum WHERE enumtypid = type_oid AND enumlabel = '${a}')\n AND NOT EXISTS (SELECT 1 FROM pg_enum WHERE enumtypid = type_oid AND enumlabel = '${o}') THEN\n IF current_setting('server_version_num')::int >= 140000 THEN\n EXECUTE format('ALTER TYPE %I RENAME VALUE %L TO %L', '${i}', '${a}', '${o}');\n ELSE\n UPDATE pg_enum SET enumlabel = '${o}' WHERE enumtypid = type_oid AND enumlabel = '${a}';\n END IF;\n END IF;\nEND $$;`);
|
|
477
513
|
}
|
|
478
514
|
return r.join("\n\n");
|
|
479
|
-
},
|
|
515
|
+
}, Ie = (e) => {
|
|
480
516
|
let t = [], n = [];
|
|
481
517
|
for (let i of e) r(i) ? n.push(i) : t.push(i);
|
|
482
518
|
return {
|
|
483
519
|
tables: t,
|
|
484
520
|
views: n
|
|
485
521
|
};
|
|
486
|
-
},
|
|
487
|
-
let { tables: r, views: a } =
|
|
488
|
-
n === "postgres" &&
|
|
489
|
-
let u =
|
|
522
|
+
}, j = (t, n) => {
|
|
523
|
+
let { tables: r, views: a } = Ie(t), { sorted: o, cyclic: s } = je(r.map((e) => b(e, n))), c = Ne(s, n), l = [];
|
|
524
|
+
n === "postgres" && ke(o) && l.push("CREATE EXTENSION IF NOT EXISTS vector;"), n === "postgres" && Ae(o) && l.push("CREATE EXTENSION IF NOT EXISTS postgis;");
|
|
525
|
+
let u = Fe(o, n);
|
|
490
526
|
u && l.push(u);
|
|
491
|
-
let d =
|
|
527
|
+
let d = Pe(o, n);
|
|
492
528
|
d && l.push(d);
|
|
493
|
-
for (let e of o) l.push(
|
|
494
|
-
if (!e(n)) for (let e of s) l.push(
|
|
529
|
+
for (let e of o) l.push(we(e, n, null, c.get(e.tableName)));
|
|
530
|
+
if (!e(n)) for (let e of s) l.push(Me(e, n));
|
|
495
531
|
for (let e of o) {
|
|
496
|
-
let t =
|
|
532
|
+
let t = Ee(e, n);
|
|
497
533
|
t && l.push(t);
|
|
498
534
|
}
|
|
499
535
|
let f = o.filter((e) => e.isReactive);
|
|
500
536
|
if (f.length > 0 && n === "postgres") {
|
|
501
|
-
l.push(
|
|
502
|
-
for (let e of f) l.push(
|
|
537
|
+
l.push(De);
|
|
538
|
+
for (let e of f) l.push(Oe(e));
|
|
503
539
|
}
|
|
504
540
|
for (let e of a) l.push(i(e, n));
|
|
505
541
|
return l.join("\n\n") + "\n";
|
|
506
|
-
},
|
|
542
|
+
}, Le = (e, n, r) => {
|
|
507
543
|
let i = t(e, n);
|
|
508
544
|
switch (n) {
|
|
509
545
|
case "postgres": return `CREATE SCHEMA IF NOT EXISTS ${i};`;
|
|
@@ -513,57 +549,57 @@ BEGIN
|
|
|
513
549
|
case "turso":
|
|
514
550
|
case "sqlite": return `ATTACH DATABASE '${(r ?? `${e}.db`).replace(/'/g, "''")}' AS ${i};`;
|
|
515
551
|
}
|
|
516
|
-
},
|
|
517
|
-
let o =
|
|
518
|
-
if (r === "postgres") return `${o}\n\nSET search_path TO ${s};\n\n${
|
|
519
|
-
if (r === "mysql" || r === "mariadb") return `${o}\n\nUSE ${s};\n\n${
|
|
520
|
-
let { sorted: c, cyclic: l } =
|
|
521
|
-
for (let e of c) d.push(
|
|
522
|
-
if (!e(r)) for (let e of l) d.push(
|
|
552
|
+
}, Re = (n, r, i, a) => {
|
|
553
|
+
let o = Le(i, r, a), s = t(i, r);
|
|
554
|
+
if (r === "postgres") return `${o}\n\nSET search_path TO ${s};\n\n${j(n, r)}`;
|
|
555
|
+
if (r === "mysql" || r === "mariadb") return `${o}\n\nUSE ${s};\n\n${j(n, r)}`;
|
|
556
|
+
let { sorted: c, cyclic: l } = je(n), u = Ne(l, r), d = [o];
|
|
557
|
+
for (let e of c) d.push(we(e, r, i, u.get(e.tableName)));
|
|
558
|
+
if (!e(r)) for (let e of l) d.push(Me(e, r, i));
|
|
523
559
|
for (let e of c) {
|
|
524
|
-
let t =
|
|
560
|
+
let t = Ee(e, r, i);
|
|
525
561
|
t && d.push(t);
|
|
526
562
|
}
|
|
527
563
|
return d.join("\n\n") + "\n";
|
|
528
|
-
},
|
|
529
|
-
if (n !== "postgres") return
|
|
530
|
-
let { sorted: r, cyclic: i } =
|
|
564
|
+
}, ze = (e, n) => {
|
|
565
|
+
if (n !== "postgres") return j(e, n);
|
|
566
|
+
let { sorted: r, cyclic: i } = je(e), a = Ne(i, n), o = [], s = Fe(r, n);
|
|
531
567
|
s && o.push(s);
|
|
532
|
-
let c =
|
|
568
|
+
let c = Pe(r, n);
|
|
533
569
|
c && o.push(c);
|
|
534
|
-
for (let e of r) o.push(
|
|
535
|
-
for (let e of i) o.push(
|
|
570
|
+
for (let e of r) o.push(we(e, n, null, a.get(e.tableName)));
|
|
571
|
+
for (let e of i) o.push(Me(e, n));
|
|
536
572
|
for (let e of r) {
|
|
537
573
|
let r = Object.entries(e.fields);
|
|
538
574
|
if (r.length === 0) continue;
|
|
539
575
|
let i = r.map(([r, i]) => {
|
|
540
|
-
let o =
|
|
576
|
+
let o = Ce(r, i, n, void 0, a.get(e.tableName)?.has(r) ?? !1);
|
|
541
577
|
return `ALTER TABLE ${t(e.tableName, n)} ADD COLUMN IF NOT EXISTS ${o};`;
|
|
542
578
|
});
|
|
543
579
|
o.push(i.join("\n"));
|
|
544
580
|
}
|
|
545
581
|
for (let e of r) {
|
|
546
|
-
let t =
|
|
582
|
+
let t = Ee(e, n);
|
|
547
583
|
t && o.push(t);
|
|
548
584
|
}
|
|
549
585
|
let l = r.filter((e) => e.isReactive);
|
|
550
586
|
if (l.length > 0) {
|
|
551
|
-
o.push(
|
|
552
|
-
for (let e of l) o.push(
|
|
587
|
+
o.push(De);
|
|
588
|
+
for (let e of l) o.push(Oe(e));
|
|
553
589
|
}
|
|
554
590
|
return o.join("\n\n") + "\n";
|
|
555
|
-
},
|
|
591
|
+
}, Be = (e, t = "postgres") => d.gen(function* () {
|
|
556
592
|
let n = yield* p.SqlClient;
|
|
557
|
-
yield*
|
|
558
|
-
}),
|
|
593
|
+
yield* ge(n, Ue(n, j(e, t), t)).pipe(d.orDie);
|
|
594
|
+
}), Ve = (e, t) => {
|
|
559
595
|
let n = t.cause ?? {};
|
|
560
596
|
return (n.errno === 1061 || n.code === "ER_DUP_KEYNAME") && /^\s*CREATE\s+(UNIQUE\s+|FULLTEXT\s+)?INDEX\b/i.test(e);
|
|
561
|
-
},
|
|
597
|
+
}, He = (e) => d.gen(function* () {
|
|
562
598
|
let t = yield* p.SqlClient;
|
|
563
|
-
for (let n of
|
|
564
|
-
|
|
599
|
+
for (let n of We(e)) process.env.VOLTRO_MIGRATE_DEBUG === "1" && _e.debug(`EXEC: ${n.replace(/\s+/g, " ").slice(0, 180)}`), yield* t.unsafe(n).pipe(d.catchIf((e) => Ve(n, e), () => d.void), d.tapError((e) => d.sync(() => {
|
|
600
|
+
_e.error(_("migrate: statement failed", n, e, 200));
|
|
565
601
|
})), d.orDieWith((e) => Error(_("migrate: statement failed", n, e, 400).trim())));
|
|
566
|
-
}),
|
|
602
|
+
}), Ue = (e, t, n) => (n === "turso" ? He(t) : e.withTransaction(He(t))).pipe(d.orDie), We = (e) => {
|
|
567
603
|
let t = [], n = "", r = !1;
|
|
568
604
|
for (let i = 0; i < e.length; i++) {
|
|
569
605
|
if (e.slice(i, i + 2) === "$$") {
|
|
@@ -578,40 +614,40 @@ BEGIN
|
|
|
578
614
|
}
|
|
579
615
|
let i = n.trim();
|
|
580
616
|
return i.length > 0 && t.push(i), t;
|
|
581
|
-
},
|
|
582
|
-
await d.runPromise(
|
|
583
|
-
},
|
|
584
|
-
let r =
|
|
585
|
-
yield*
|
|
586
|
-
}),
|
|
587
|
-
await d.runPromise(
|
|
588
|
-
},
|
|
617
|
+
}, Ge = async (e, t, n = "postgres") => {
|
|
618
|
+
await d.runPromise(Be(e, n).pipe(d.provide(t)));
|
|
619
|
+
}, Ke = (e, t, n = "postgres") => d.gen(function* () {
|
|
620
|
+
let r = Re(e, n, t), i = yield* p.SqlClient;
|
|
621
|
+
yield* ge(i, Ue(i, r, n)).pipe(d.orDie);
|
|
622
|
+
}), qe = async (e, t, n, r = "postgres") => {
|
|
623
|
+
await d.runPromise(Ke(e, t, r).pipe(d.provide(n)));
|
|
624
|
+
}, Je = async (e, t, n = "postgres") => {
|
|
589
625
|
await d.runPromise(d.gen(function* () {
|
|
590
|
-
let t =
|
|
591
|
-
yield*
|
|
626
|
+
let t = ze(e, n), r = yield* p.SqlClient;
|
|
627
|
+
yield* ge(r, Ue(r, t, n)).pipe(d.orDie);
|
|
592
628
|
}).pipe(d.provide(t)));
|
|
593
|
-
},
|
|
629
|
+
}, Ye = (e) => {
|
|
594
630
|
if (e == null) return e;
|
|
595
|
-
if (Array.isArray(e)) return e.map(
|
|
631
|
+
if (Array.isArray(e)) return e.map(Ye);
|
|
596
632
|
if (typeof e != "object") return e;
|
|
597
633
|
let t = {};
|
|
598
634
|
for (let n of Object.keys(e).sort()) {
|
|
599
635
|
let r = e[n];
|
|
600
|
-
r !== void 0 && (t[n] =
|
|
636
|
+
r !== void 0 && (t[n] = Ye(r));
|
|
601
637
|
}
|
|
602
638
|
return t;
|
|
603
|
-
},
|
|
639
|
+
}, Xe = (e) => {
|
|
604
640
|
if (!e.idScheme) return e;
|
|
605
641
|
let { idScheme: t, ...n } = e;
|
|
606
642
|
return n;
|
|
607
|
-
},
|
|
643
|
+
}, Ze = (e) => [...e].map(Xe).sort((e, t) => e.name.localeCompare(t.name)), Qe = (e) => [...e].sort((e, t) => e.name.localeCompare(t.name)), $e = (e) => [...e].map((e) => ({
|
|
608
644
|
name: e.name,
|
|
609
|
-
columns:
|
|
610
|
-
indexes:
|
|
611
|
-
})).sort((e, t) => e.name.localeCompare(t.name)),
|
|
612
|
-
let t = { tables:
|
|
645
|
+
columns: Ze(e.columns),
|
|
646
|
+
indexes: Qe(e.indexes)
|
|
647
|
+
})).sort((e, t) => e.name.localeCompare(t.name)), M = (e) => {
|
|
648
|
+
let t = { tables: $e(e.tables) }, n = JSON.stringify(Ye(t));
|
|
613
649
|
return m("sha256").update(n).digest("hex");
|
|
614
|
-
},
|
|
650
|
+
}, N = (e) => e.slice(0, 16), et = (e, t) => {
|
|
615
651
|
let n = t.references ? {
|
|
616
652
|
table: t.references().tableName,
|
|
617
653
|
column: "id",
|
|
@@ -643,7 +679,7 @@ BEGIN
|
|
|
643
679
|
...t.sensitive ? { sensitive: t.sensitive } : t.encrypted && !t.safe ? { sensitive: { class: "secret" } } : {},
|
|
644
680
|
...t.safe ? { safe: !0 } : {}
|
|
645
681
|
};
|
|
646
|
-
},
|
|
682
|
+
}, tt = (e) => {
|
|
647
683
|
let t = [], n = /* @__PURE__ */ new Set(), r = (e) => {
|
|
648
684
|
n.has(e.name) || (n.add(e.name), t.push(e));
|
|
649
685
|
}, i = e.appliedPrimaryKey ?? [];
|
|
@@ -660,6 +696,7 @@ BEGIN
|
|
|
660
696
|
});
|
|
661
697
|
let o = e.appliedIndexes ?? [];
|
|
662
698
|
for (let t of o) {
|
|
699
|
+
if (t.unique && t.where) continue;
|
|
663
700
|
let n = t.fields.map((e) => typeof e == "string" ? e : "jsonPath" in e ? `(json:${e.jsonPath.column}->${e.jsonPath.path.join(".")}${e.jsonPath.numeric ? "::num" : ""})` : `(${e.expr})`), i = t.fields.some((e) => typeof e != "string");
|
|
664
701
|
r({
|
|
665
702
|
name: t.name,
|
|
@@ -690,11 +727,11 @@ BEGIN
|
|
|
690
727
|
});
|
|
691
728
|
}
|
|
692
729
|
return t;
|
|
693
|
-
},
|
|
730
|
+
}, nt = (e) => {
|
|
694
731
|
let t = new Set((e.appliedUniques ?? []).filter((e) => e.fields.length === 1).map((e) => e.fields[0])), n = [];
|
|
695
732
|
for (let [r, i] of Object.entries(e.fields)) {
|
|
696
733
|
if (i.dropped) continue;
|
|
697
|
-
let e =
|
|
734
|
+
let e = et(r, i);
|
|
698
735
|
n.push(t.has(r) ? {
|
|
699
736
|
...e,
|
|
700
737
|
unique: !0
|
|
@@ -704,32 +741,32 @@ BEGIN
|
|
|
704
741
|
return {
|
|
705
742
|
name: e.tableName,
|
|
706
743
|
columns: n,
|
|
707
|
-
indexes:
|
|
744
|
+
indexes: tt(e),
|
|
708
745
|
...r.length > 0 ? { primaryKey: [...r] } : {}
|
|
709
746
|
};
|
|
710
|
-
},
|
|
747
|
+
}, rt = (e) => {
|
|
711
748
|
let t = /* @__PURE__ */ new Map();
|
|
712
749
|
for (let n of e) for (let e of n.indexes) {
|
|
713
750
|
let r = t.get(e.name);
|
|
714
751
|
if (r !== void 0 && r !== n.name) throw Error(`duplicate index name '${e.name}' across tables '${r}' and '${n.name}'. Index names must be unique per SCHEMA, not just per table — the DB creates only one, so the other never applies and 'db plan' re-emits it forever. Give each an explicit, table-prefixed name (e.g. '${n.name}_${e.name}').`);
|
|
715
752
|
t.set(e.name, n.name);
|
|
716
753
|
}
|
|
717
|
-
},
|
|
718
|
-
let
|
|
719
|
-
return
|
|
720
|
-
},
|
|
754
|
+
}, P = (e, t) => {
|
|
755
|
+
let n = e.map((e) => nt(b(e, t)));
|
|
756
|
+
return rt(n), { tables: n };
|
|
757
|
+
}, it = /* @__PURE__ */ new Set(["voltro_isr_cache"]), at = (e) => it.has(e) || e.startsWith("_voltro_") || e.startsWith("_cloud_") || e.startsWith("cluster_"), ot = {
|
|
721
758
|
postgres: !0,
|
|
722
759
|
mysql: !0,
|
|
723
760
|
mariadb: !0,
|
|
724
761
|
mssql: !0,
|
|
725
762
|
sqlite: !0
|
|
726
|
-
},
|
|
763
|
+
}, st = {
|
|
727
764
|
postgres: !0,
|
|
728
765
|
mysql: !1,
|
|
729
766
|
mariadb: !1,
|
|
730
767
|
mssql: !0,
|
|
731
768
|
sqlite: !0
|
|
732
|
-
},
|
|
769
|
+
}, ct = (e) => {
|
|
733
770
|
switch (e) {
|
|
734
771
|
case "add-column":
|
|
735
772
|
case "drop-column":
|
|
@@ -739,43 +776,43 @@ BEGIN
|
|
|
739
776
|
case "add-foreign-key":
|
|
740
777
|
case "add-unique":
|
|
741
778
|
case "add-unique-composite":
|
|
742
|
-
case "add-check": return
|
|
743
|
-
default: return
|
|
779
|
+
case "add-check": return st;
|
|
780
|
+
default: return ot;
|
|
744
781
|
}
|
|
745
|
-
},
|
|
782
|
+
}, lt = (e, t) => {
|
|
746
783
|
let n = new Map(t.tables.map((e) => [e.name, e]));
|
|
747
784
|
return new Map(e.map((e) => [e.tableName, {
|
|
748
785
|
table: e,
|
|
749
786
|
snapshot: n.get(e.tableName),
|
|
750
787
|
columnDefs: e.fields
|
|
751
788
|
}]));
|
|
752
|
-
},
|
|
789
|
+
}, ut = (e) => (t, n) => t.name === e ? -1 : n.name === e ? 1 : t.name.localeCompare(n.name), F = (e) => {
|
|
753
790
|
if (typeof e != "object" || !e) return JSON.stringify(e);
|
|
754
|
-
if (Array.isArray(e)) return `[${e.map(
|
|
791
|
+
if (Array.isArray(e)) return `[${e.map(F).join(",")}]`;
|
|
755
792
|
let t = e;
|
|
756
|
-
return `{${Object.keys(t).sort().map((e) => `${JSON.stringify(e)}:${
|
|
757
|
-
},
|
|
793
|
+
return `{${Object.keys(t).sort().map((e) => `${JSON.stringify(e)}:${F(t[e])}`).join(",")}}`;
|
|
794
|
+
}, dt = (e) => {
|
|
758
795
|
if (!e.hasDefault || e.defaultValue === void 0 || e.defaultValue === null) return null;
|
|
759
796
|
let t = e.defaultValue;
|
|
760
797
|
if (typeof t == "boolean") return t ? "__BOOL_TRUE__" : "__BOOL_FALSE__";
|
|
761
798
|
if (typeof t == "number") return String(t);
|
|
762
|
-
if (typeof t != "string") return
|
|
799
|
+
if (typeof t != "string") return F(t);
|
|
763
800
|
let n = t.trim(), r = n.toLowerCase().replace(/\s+/g, "");
|
|
764
801
|
if (r === "now" || r === "now()" || /^current_timestamp(\(\d*\))?$/.test(r) || r === "sysutcdatetime()" || r === "sysdatetime()" || r === "getutcdate()" || r === "getdate()") return "__NOW__";
|
|
765
802
|
let i = n.replace(/::[a-zA-Z0-9_ "]+$/, "").trim(), a = /^'(.*)'$/.test(i) ? i.slice(1, -1).replace(/''/g, "'") : i, o = /^cast\(\s*(?:_\w+\s*)?\\?'(.*?)\\?'\s+as\s+json\s*\)$/i.exec(a);
|
|
766
803
|
if (o) try {
|
|
767
|
-
return
|
|
804
|
+
return F(JSON.parse(o[1]));
|
|
768
805
|
} catch {}
|
|
769
806
|
if (a.startsWith("{") || a.startsWith("[")) try {
|
|
770
|
-
return
|
|
807
|
+
return F(JSON.parse(a));
|
|
771
808
|
} catch {}
|
|
772
809
|
return /^-?\d+(\.\d+)?$/.test(a) ? String(Number(a)) : a;
|
|
773
|
-
},
|
|
774
|
-
let n =
|
|
810
|
+
}, ft = (e, t) => {
|
|
811
|
+
let n = dt(e), r = dt(t);
|
|
775
812
|
if (n === r) return !0;
|
|
776
813
|
let i = (e) => e === "1" || e === "true" ? "__BOOL_TRUE__" : e === "0" || e === "false" ? "__BOOL_FALSE__" : e;
|
|
777
814
|
return i(n) === i(r);
|
|
778
|
-
},
|
|
815
|
+
}, I = (e) => {
|
|
779
816
|
if (!e) return null;
|
|
780
817
|
let t = (e) => e === "restrict" ? "noAction" : e;
|
|
781
818
|
return {
|
|
@@ -784,18 +821,18 @@ BEGIN
|
|
|
784
821
|
onDelete: t(e.onDelete),
|
|
785
822
|
onUpdate: t(e.onUpdate)
|
|
786
823
|
};
|
|
787
|
-
},
|
|
824
|
+
}, pt = (e, t) => {
|
|
788
825
|
let n = e && e.length > 0 ? e : void 0, r = t && t.length > 0 ? t : void 0;
|
|
789
826
|
if (!n && !r) return !0;
|
|
790
827
|
if (!n || !r || n.length !== r.length) return !1;
|
|
791
828
|
let i = [...n].sort(), a = [...r].sort();
|
|
792
829
|
return i.every((e, t) => e === a[t]);
|
|
793
|
-
},
|
|
830
|
+
}, mt = (e, t) => e.type === t.type && e.nullable === t.nullable && e.unique === t.unique && ft(e, t) && JSON.stringify(I(e.references)) === JSON.stringify(I(t.references)) && pt(e.oneOf, t.oneOf), ht = (e, t) => t.oneOf && t.oneOf.length > 0 ? L({
|
|
794
831
|
kind: "add-check",
|
|
795
832
|
table: e,
|
|
796
833
|
column: t.name,
|
|
797
834
|
values: t.oneOf
|
|
798
|
-
}, "safe", `enum-membership CHECK on ${e}.${t.name}`) : void 0,
|
|
835
|
+
}, "safe", `enum-membership CHECK on ${e}.${t.name}`) : void 0, gt = (e, t) => e.unique === t.unique && (e.expression || t.expression ? !0 : e.columns.length === t.columns.length && e.columns.every((e, n) => e === t.columns[n])), _t = (e, t) => {
|
|
799
836
|
let n = new Map(t.columns.map((e) => [e.name, e])), r = new Map(e.columns.map((e) => [e.name, e])), i = [], a = [], o = [];
|
|
800
837
|
for (let t of e.columns) {
|
|
801
838
|
let e = n.get(t.name);
|
|
@@ -803,7 +840,7 @@ BEGIN
|
|
|
803
840
|
i.push(t);
|
|
804
841
|
continue;
|
|
805
842
|
}
|
|
806
|
-
|
|
843
|
+
mt(t, e) || o.push({
|
|
807
844
|
declared: t,
|
|
808
845
|
live: e
|
|
809
846
|
});
|
|
@@ -814,47 +851,47 @@ BEGIN
|
|
|
814
851
|
removed: a,
|
|
815
852
|
changed: o
|
|
816
853
|
};
|
|
817
|
-
},
|
|
854
|
+
}, vt = (e, t) => {
|
|
818
855
|
let n = new Map(t.indexes.map((e) => [e.name, e])), r = new Map(e.indexes.map((e) => [e.name, e])), i = [], a = [];
|
|
819
856
|
for (let t of e.indexes) {
|
|
820
857
|
let e = n.get(t.name);
|
|
821
|
-
(!e || !
|
|
858
|
+
(!e || !gt(t, e)) && i.push(t);
|
|
822
859
|
}
|
|
823
860
|
for (let e of t.indexes) r.has(e.name) || a.push(e);
|
|
824
861
|
return {
|
|
825
862
|
added: i,
|
|
826
863
|
removed: a
|
|
827
864
|
};
|
|
828
|
-
},
|
|
865
|
+
}, L = (e, t, n, r) => ({
|
|
829
866
|
op: e,
|
|
830
867
|
classification: t,
|
|
831
|
-
atomicByDialect:
|
|
868
|
+
atomicByDialect: ct(e.kind),
|
|
832
869
|
...n ? { reason: n } : {},
|
|
833
870
|
...r ? { blocked: r } : {}
|
|
834
|
-
}),
|
|
871
|
+
}), yt = (e, t, n) => {
|
|
835
872
|
let r = {
|
|
836
873
|
kind: "add-column",
|
|
837
874
|
table: e,
|
|
838
875
|
column: t
|
|
839
876
|
};
|
|
840
|
-
return t.nullable ?
|
|
841
|
-
},
|
|
877
|
+
return t.nullable ? L(r, "safe", "nullable column add — no backfill needed") : t.hasDefault && t.defaultValue !== void 0 ? L(r, "needs-default", "NOT NULL with literal default — DDL DEFAULT will populate existing rows") : n?.backfill ? L(r, "needs-backfill", `backfill declared (kind=${n.backfill.kind}) — applier will run 3-step add/update/set-not-null`) : L(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` });
|
|
878
|
+
}, bt = (e, t, n) => {
|
|
842
879
|
let r = {
|
|
843
880
|
kind: "drop-column",
|
|
844
881
|
table: e,
|
|
845
882
|
column: t.name
|
|
846
883
|
};
|
|
847
|
-
return n?.dropped ?
|
|
848
|
-
},
|
|
884
|
+
return n?.dropped ? L(r, "lossy", `column dropped via \`${t.name}: dropped()\` marker — intentional`) : L(r, "lossy", "column missing from declared schema", { fix: `if intentional, add \`${t.name}: dropped()\` to the schema. If a typo, restore the field` });
|
|
885
|
+
}, xt = (e, t, n, r) => L({
|
|
849
886
|
kind: "create-table",
|
|
850
887
|
table: e,
|
|
851
888
|
columns: t,
|
|
852
889
|
indexes: n,
|
|
853
890
|
...r && r.length > 0 ? { primaryKey: r } : {}
|
|
854
|
-
}, "safe", "new table — no data to preserve"),
|
|
891
|
+
}, "safe", "new table — no data to preserve"), St = (e) => L({
|
|
855
892
|
kind: "drop-table",
|
|
856
893
|
table: e
|
|
857
|
-
}, "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" }),
|
|
894
|
+
}, "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" }), Ct = 5e4, wt = (e, t, n, r) => {
|
|
858
895
|
let i = (n ?? 0) >= r, a;
|
|
859
896
|
return a = t.unique ? t.columns.length === 1 ? {
|
|
860
897
|
kind: "add-unique",
|
|
@@ -869,16 +906,16 @@ BEGIN
|
|
|
869
906
|
kind: "add-index",
|
|
870
907
|
table: e,
|
|
871
908
|
index: t
|
|
872
|
-
}, i ?
|
|
873
|
-
},
|
|
909
|
+
}, i ? L(a, "online-required", `online build on ${n} rows — CONCURRENTLY / INPLACE / WITH(ONLINE=ON) depending on dialect`) : L(a, "safe", t.unique ? t.columns.length === 1 ? "add unique constraint" : "add composite UNIQUE constraint" : "add B-tree index");
|
|
910
|
+
}, Tt = (e, t) => t.unique && t.columns.length > 1 ? L({
|
|
874
911
|
kind: "drop-unique-composite",
|
|
875
912
|
table: e,
|
|
876
913
|
name: t.name
|
|
877
|
-
}, "safe", "drop composite UNIQUE constraint (no data loss — constraint is derived metadata)") :
|
|
914
|
+
}, "safe", "drop composite UNIQUE constraint (no data loss — constraint is derived metadata)") : L({
|
|
878
915
|
kind: "drop-index",
|
|
879
916
|
table: e,
|
|
880
917
|
index: t.name
|
|
881
|
-
}, "safe", "drop index (no data loss — index is derived data)"),
|
|
918
|
+
}, "safe", "drop index (no data loss — index is derived data)"), Et = (e, t) => {
|
|
882
919
|
if (e === "reference") return "text";
|
|
883
920
|
switch (t) {
|
|
884
921
|
case "sqlite":
|
|
@@ -886,7 +923,7 @@ BEGIN
|
|
|
886
923
|
case "mssql": return e === "json" ? "text" : e;
|
|
887
924
|
default: return e;
|
|
888
925
|
}
|
|
889
|
-
},
|
|
926
|
+
}, Dt = (e, t, n, r, i, a) => {
|
|
890
927
|
let o = [];
|
|
891
928
|
if (t.nullable !== n.nullable) {
|
|
892
929
|
let n = {
|
|
@@ -895,7 +932,7 @@ BEGIN
|
|
|
895
932
|
column: t.name,
|
|
896
933
|
toNullable: t.nullable
|
|
897
934
|
};
|
|
898
|
-
o.push(t.nullable ?
|
|
935
|
+
o.push(t.nullable ? L(n, "safe", `loosen ${e}.${t.name} to nullable`) : L(n, "needs-backfill", `tighten ${e}.${t.name} to NOT NULL — existing rows must already be non-null`));
|
|
899
936
|
}
|
|
900
937
|
if (t.unique !== n.unique) if (t.unique) {
|
|
901
938
|
let n = {
|
|
@@ -903,13 +940,13 @@ BEGIN
|
|
|
903
940
|
table: e,
|
|
904
941
|
column: t.name
|
|
905
942
|
}, r = (i ?? 0) >= a;
|
|
906
|
-
o.push(r ?
|
|
907
|
-
} else o.push(
|
|
943
|
+
o.push(r ? L(n, "online-required", `online unique build on ${i} rows — CONCURRENTLY / INPLACE / WITH(ONLINE=ON) depending on dialect`) : L(n, "safe", `add unique constraint on ${e}.${t.name} — existing rows must already be distinct (else the DB rejects at migrate)`));
|
|
944
|
+
} else o.push(L({
|
|
908
945
|
kind: "drop-unique",
|
|
909
946
|
table: e,
|
|
910
947
|
column: t.name
|
|
911
948
|
}, "safe", `drop unique constraint on ${e}.${t.name} — constraint is derived metadata, no data loss`));
|
|
912
|
-
if (
|
|
949
|
+
if (Et(t.type, r) !== Et(n.type, r)) {
|
|
913
950
|
let r = t.narrowedFrom;
|
|
914
951
|
if (r && r.from === n.type) {
|
|
915
952
|
let i = {
|
|
@@ -920,7 +957,7 @@ BEGIN
|
|
|
920
957
|
to: t.type,
|
|
921
958
|
...r.using === void 0 ? {} : { using: r.using }
|
|
922
959
|
};
|
|
923
|
-
o.push(
|
|
960
|
+
o.push(L(i, "needs-backfill", `type change ${n.type} → ${t.type} on ${e}.${t.name} — narrowedFrom('${r.from}') declared` + (r.using ? ` with USING ${r.using}` : " (implicit cast)")));
|
|
924
961
|
} else {
|
|
925
962
|
let r = {
|
|
926
963
|
kind: "alter-column-type",
|
|
@@ -929,10 +966,10 @@ BEGIN
|
|
|
929
966
|
from: n.type,
|
|
930
967
|
to: t.type
|
|
931
968
|
};
|
|
932
|
-
o.push(
|
|
969
|
+
o.push(L(r, "lossy", `type change ${n.type} → ${t.type} on ${e}.${t.name} may not be value-preserving`, { fix: `acknowledge it on the column: \`.narrowedFrom('${n.type}', { using: '${t.name}::${t.type}' })\` (drop \`using\` if the cast is implicit), or use a file-based migration` }));
|
|
933
970
|
}
|
|
934
971
|
}
|
|
935
|
-
if (!
|
|
972
|
+
if (!ft(t, n)) {
|
|
936
973
|
let n = {
|
|
937
974
|
kind: "alter-column-default",
|
|
938
975
|
table: e,
|
|
@@ -940,18 +977,18 @@ BEGIN
|
|
|
940
977
|
hasDefault: t.hasDefault,
|
|
941
978
|
...t.defaultValue === void 0 ? {} : { defaultValue: t.defaultValue }
|
|
942
979
|
};
|
|
943
|
-
o.push(
|
|
980
|
+
o.push(L(n, "safe", `default change on ${e}.${t.name} affects only future inserts`));
|
|
944
981
|
}
|
|
945
|
-
if (!
|
|
946
|
-
n.oneOf && n.oneOf.length > 0 && o.push(
|
|
982
|
+
if (!pt(t.oneOf, n.oneOf)) {
|
|
983
|
+
n.oneOf && n.oneOf.length > 0 && o.push(L({
|
|
947
984
|
kind: "drop-check",
|
|
948
985
|
table: e,
|
|
949
986
|
column: t.name
|
|
950
987
|
}, "safe", `drop stale enum CHECK on ${e}.${t.name}`));
|
|
951
|
-
let r =
|
|
988
|
+
let r = ht(e, t);
|
|
952
989
|
r && o.push(r);
|
|
953
990
|
}
|
|
954
|
-
if (JSON.stringify(
|
|
991
|
+
if (JSON.stringify(I(t.references)) !== JSON.stringify(I(n.references)) && (n.references && o.push(L({
|
|
955
992
|
kind: "drop-foreign-key",
|
|
956
993
|
table: e,
|
|
957
994
|
column: t.name
|
|
@@ -965,17 +1002,17 @@ BEGIN
|
|
|
965
1002
|
...t.references.onDelete ? { onDelete: t.references.onDelete } : {},
|
|
966
1003
|
...t.references.onUpdate ? { onUpdate: t.references.onUpdate } : {}
|
|
967
1004
|
};
|
|
968
|
-
r === "null" && !t.nullable ? o.push(
|
|
1005
|
+
r === "null" && !t.nullable ? o.push(L(i, "lossy", `add FK ${e}.${t.name} → ${n}: 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` })) : r === "null" || r === "delete" ? o.push(L({
|
|
969
1006
|
...i,
|
|
970
1007
|
orphanPolicy: r
|
|
971
|
-
}, "lossy", r === "delete" ? `add FK ${e}.${t.name} → ${n}: orphanPolicy 'delete' first DELETES rows whose ${t.name} points at a missing ${n}` : `add FK ${e}.${t.name} → ${n}: orphanPolicy 'null' first NULLs ${t.name} where it points at a missing ${n}`)) : o.push(
|
|
1008
|
+
}, "lossy", r === "delete" ? `add FK ${e}.${t.name} → ${n}: orphanPolicy 'delete' first DELETES rows whose ${t.name} points at a missing ${n}` : `add FK ${e}.${t.name} → ${n}: orphanPolicy 'null' first NULLs ${t.name} where it points at a missing ${n}`)) : o.push(L(i, "needs-backfill", `add FK ${e}.${t.name} → ${n} — existing rows must already reference a valid ${n} (else set orphanPolicy:'null'/'delete')`));
|
|
972
1009
|
}
|
|
973
1010
|
return o;
|
|
974
|
-
},
|
|
1011
|
+
}, Ot = (e, t, n) => {
|
|
975
1012
|
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));
|
|
976
1013
|
for (let [n, c] of Object.entries(t)) {
|
|
977
1014
|
let t = c.renamedFrom;
|
|
978
|
-
t && o.has(t) && s.has(n) && (i.add(n), a.add(t), r.push(
|
|
1015
|
+
t && o.has(t) && s.has(n) && (i.add(n), a.add(t), r.push(L({
|
|
979
1016
|
kind: "rename-column",
|
|
980
1017
|
table: e.tableName,
|
|
981
1018
|
from: t,
|
|
@@ -987,7 +1024,7 @@ BEGIN
|
|
|
987
1024
|
consumedAddedNames: i,
|
|
988
1025
|
consumedRemovedNames: a
|
|
989
1026
|
};
|
|
990
|
-
},
|
|
1027
|
+
}, kt = (e) => {
|
|
991
1028
|
let t = {
|
|
992
1029
|
safe: 0,
|
|
993
1030
|
needsDefault: 0,
|
|
@@ -1022,37 +1059,37 @@ BEGIN
|
|
|
1022
1059
|
break;
|
|
1023
1060
|
}
|
|
1024
1061
|
return t;
|
|
1025
|
-
},
|
|
1026
|
-
let t =
|
|
1062
|
+
}, At = (e) => {
|
|
1063
|
+
let t = P(e.declared, e.dialect), n = lt(e.declared, t), r = new Map(e.live.tables.map((e) => [e.name, e])), i = e.onlineAfter ?? Ct, a = [];
|
|
1027
1064
|
for (let e of t.tables) if (!r.has(e.name)) {
|
|
1028
|
-
a.push(
|
|
1065
|
+
a.push(xt(e.name, e.columns, e.indexes, e.primaryKey));
|
|
1029
1066
|
for (let t of e.columns) {
|
|
1030
|
-
let n =
|
|
1067
|
+
let n = ht(e.name, t);
|
|
1031
1068
|
n && a.push(n);
|
|
1032
1069
|
}
|
|
1033
1070
|
}
|
|
1034
1071
|
let o = new Set(e.ignoreTables ?? []);
|
|
1035
|
-
for (let t of e.live.tables) n.has(t.name) ||
|
|
1072
|
+
for (let t of e.live.tables) n.has(t.name) || at(t.name) || o.has(t.name) || a.push(St(t.name));
|
|
1036
1073
|
for (let o of t.tables) {
|
|
1037
1074
|
let t = r.get(o.name);
|
|
1038
1075
|
if (!t) continue;
|
|
1039
|
-
let s = n.get(o.name), c =
|
|
1076
|
+
let s = n.get(o.name), c = _t(o, t), l = vt(o, t), u = Ot(s.table, s.columnDefs, c);
|
|
1040
1077
|
a.push(...u.ops);
|
|
1041
1078
|
for (let e of c.removed) {
|
|
1042
1079
|
if (u.consumedRemovedNames.has(e.name)) continue;
|
|
1043
1080
|
let t = s.columnDefs[e.name];
|
|
1044
|
-
a.push(
|
|
1081
|
+
a.push(bt(o.name, e, t));
|
|
1045
1082
|
}
|
|
1046
1083
|
for (let e of c.added) {
|
|
1047
1084
|
if (u.consumedAddedNames.has(e.name)) continue;
|
|
1048
1085
|
let t = s.columnDefs[e.name];
|
|
1049
|
-
a.push(
|
|
1050
|
-
let n =
|
|
1086
|
+
a.push(yt(o.name, e, t));
|
|
1087
|
+
let n = ht(o.name, e);
|
|
1051
1088
|
n && a.push(n);
|
|
1052
1089
|
}
|
|
1053
|
-
for (let e of l.added) a.push(
|
|
1054
|
-
for (let e of l.removed) a.push(
|
|
1055
|
-
for (let { declared: n, live: r } of c.changed) a.push(...
|
|
1090
|
+
for (let e of l.added) a.push(wt(o.name, e, t.rowCount, i));
|
|
1091
|
+
for (let e of l.removed) a.push(Tt(o.name, e));
|
|
1092
|
+
for (let { declared: n, live: r } of c.changed) a.push(...Dt(o.name, n, r, e.dialect, t.rowCount, i));
|
|
1056
1093
|
}
|
|
1057
1094
|
let s = new Set(a.flatMap((e) => e.op.kind === "create-table" ? [e.op.table] : [])), c = new Map(t.tables.map((e) => [e.name, e])), l = (e) => {
|
|
1058
1095
|
let t = c.get(e);
|
|
@@ -1060,8 +1097,8 @@ BEGIN
|
|
|
1060
1097
|
column: e.name,
|
|
1061
1098
|
target: e.references.table
|
|
1062
1099
|
}] : []) : [];
|
|
1063
|
-
}, u =
|
|
1064
|
-
for (let e of t.tables) if (s.has(e.name)) for (let t of e.columns) !t.references || !u.has(
|
|
1100
|
+
}, u = S([...s], l), d = [];
|
|
1101
|
+
for (let e of t.tables) if (s.has(e.name)) for (let t of e.columns) !t.references || !u.has(x(e.name, t.name)) || d.push(L({
|
|
1065
1102
|
kind: "add-foreign-key",
|
|
1066
1103
|
table: e.name,
|
|
1067
1104
|
column: t.name,
|
|
@@ -1076,8 +1113,8 @@ BEGIN
|
|
|
1076
1113
|
let n = a[t];
|
|
1077
1114
|
if (n.op.kind !== "create-table") continue;
|
|
1078
1115
|
let r = n.op;
|
|
1079
|
-
if (!r.columns.some((e) => u.has(
|
|
1080
|
-
let i = r.columns.map((t) => u.has(
|
|
1116
|
+
if (!r.columns.some((e) => u.has(x(r.table, e.name)))) continue;
|
|
1117
|
+
let i = r.columns.map((t) => u.has(x(r.table, t.name)) ? e(t) : t);
|
|
1081
1118
|
a[t] = {
|
|
1082
1119
|
...n,
|
|
1083
1120
|
op: {
|
|
@@ -1097,7 +1134,7 @@ BEGIN
|
|
|
1097
1134
|
let i = new Set(t).add(e), a = 0;
|
|
1098
1135
|
for (let t of r.columns) {
|
|
1099
1136
|
let n = t.references?.table;
|
|
1100
|
-
n && n !== e && !u.has(
|
|
1137
|
+
n && n !== e && !u.has(x(e, t.name)) && (a = Math.max(a, m(n, i) + 1));
|
|
1101
1138
|
}
|
|
1102
1139
|
return p.set(e, a), a;
|
|
1103
1140
|
}, h = (e) => e === "create-table" ? 0 : e === "drop-table" ? 2 : 1, g = (e) => {
|
|
@@ -1120,7 +1157,7 @@ BEGIN
|
|
|
1120
1157
|
"add-unique-composite": 5,
|
|
1121
1158
|
"add-foreign-key": 5,
|
|
1122
1159
|
"add-check": 5
|
|
1123
|
-
}, _ = (e) => ee[e] ?? 9,
|
|
1160
|
+
}, _ = (e) => ee[e] ?? 9, v = [...a].sort((e, t) => {
|
|
1124
1161
|
let n = h(e.op.kind), r = h(t.op.kind);
|
|
1125
1162
|
if (n !== r) return n - r;
|
|
1126
1163
|
let i = g(e.op), a = g(t.op);
|
|
@@ -1131,12 +1168,12 @@ BEGIN
|
|
|
1131
1168
|
return c === l ? e.op.kind.localeCompare(t.op.kind) : c - l;
|
|
1132
1169
|
});
|
|
1133
1170
|
return {
|
|
1134
|
-
operations:
|
|
1135
|
-
fromFingerprint:
|
|
1136
|
-
toFingerprint:
|
|
1137
|
-
summary:
|
|
1171
|
+
operations: v,
|
|
1172
|
+
fromFingerprint: M(e.live),
|
|
1173
|
+
toFingerprint: M(t),
|
|
1174
|
+
summary: kt(v)
|
|
1138
1175
|
};
|
|
1139
|
-
},
|
|
1176
|
+
}, jt = (e) => {
|
|
1140
1177
|
let t = /[`"[]?([A-Za-z_][A-Za-z0-9_]*)[`"\]]?\s*(?:in\b|=)/i.exec(e);
|
|
1141
1178
|
if (!t) return null;
|
|
1142
1179
|
let n = [...e.matchAll(/'((?:[^']|'')*)'/g)].map((e) => e[1].replace(/''/g, "'"));
|
|
@@ -1144,7 +1181,7 @@ BEGIN
|
|
|
1144
1181
|
column: t[1],
|
|
1145
1182
|
values: n
|
|
1146
1183
|
};
|
|
1147
|
-
},
|
|
1184
|
+
}, Mt = (e, t) => {
|
|
1148
1185
|
if (t === "vector") return "vector";
|
|
1149
1186
|
switch (e) {
|
|
1150
1187
|
case "text":
|
|
@@ -1171,7 +1208,7 @@ BEGIN
|
|
|
1171
1208
|
case "USER-DEFINED": return "text";
|
|
1172
1209
|
default: return "text";
|
|
1173
1210
|
}
|
|
1174
|
-
},
|
|
1211
|
+
}, R = (e) => {
|
|
1175
1212
|
switch (e.toUpperCase()) {
|
|
1176
1213
|
case "CASCADE": return "cascade";
|
|
1177
1214
|
case "RESTRICT": return "restrict";
|
|
@@ -1179,25 +1216,25 @@ BEGIN
|
|
|
1179
1216
|
case "SET DEFAULT": return "noAction";
|
|
1180
1217
|
default: return "noAction";
|
|
1181
1218
|
}
|
|
1182
|
-
},
|
|
1219
|
+
}, Nt = (e, t) => {
|
|
1183
1220
|
let n = e !== void 0 && e !== "" ? Number(e) : NaN;
|
|
1184
1221
|
return Number.isInteger(n) && n > 0 ? n : t;
|
|
1185
|
-
},
|
|
1222
|
+
}, Pt = () => Nt(process.env.VOLTRO_INTROSPECT_BATCH, 20), Ft = 300, It = () => {
|
|
1186
1223
|
let e = process.env.VOLTRO_INTROSPECT_TIMEOUT_MS;
|
|
1187
|
-
return e !== void 0 && e.trim() === "0" ? 0 :
|
|
1188
|
-
},
|
|
1224
|
+
return e !== void 0 && e.trim() === "0" ? 0 : Nt(e, 3e4);
|
|
1225
|
+
}, Lt = (e, t) => {
|
|
1189
1226
|
let n = Number.isFinite(t) && t >= 1 ? Math.floor(t) : 1, r = [];
|
|
1190
1227
|
for (let t = 0; t < e.length; t += n) r.push(e.slice(t, t + n));
|
|
1191
1228
|
return r;
|
|
1192
|
-
},
|
|
1193
|
-
let t =
|
|
1229
|
+
}, Rt = (e) => {
|
|
1230
|
+
let t = It(), n = d.gen(function* () {
|
|
1194
1231
|
t > 0 && (yield* e.unsafe(`SET LOCAL statement_timeout = ${t}`));
|
|
1195
|
-
let n = (t) => e.unsafe("(" + t.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ") + ")"), r = (t) => e.unsafe(String(Math.max(0, Math.trunc(t)))), i =
|
|
1232
|
+
let n = (t) => e.unsafe("(" + t.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ") + ")"), r = (t) => e.unsafe(String(Math.max(0, Math.trunc(t)))), i = Pt(), a = (e, t) => d.gen(function* () {
|
|
1196
1233
|
let r = [];
|
|
1197
|
-
for (let a of
|
|
1234
|
+
for (let a of Lt(e, i)) a.length !== 0 && r.push(...yield* t(n(a)));
|
|
1198
1235
|
return r;
|
|
1199
1236
|
}), o = [];
|
|
1200
|
-
for (let t = 0;; t +=
|
|
1237
|
+
for (let t = 0;; t += Ft) {
|
|
1201
1238
|
let n = yield* e`
|
|
1202
1239
|
SELECT c.relname AS table_name,
|
|
1203
1240
|
COALESCE(c.reltuples::bigint, 0) AS row_count
|
|
@@ -1205,9 +1242,9 @@ BEGIN
|
|
|
1205
1242
|
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
1206
1243
|
WHERE n.nspname = current_schema() AND c.relkind = 'r'
|
|
1207
1244
|
ORDER BY c.relname
|
|
1208
|
-
LIMIT ${r(
|
|
1245
|
+
LIMIT ${r(Ft)} OFFSET ${r(t)}
|
|
1209
1246
|
`;
|
|
1210
|
-
if (o.push(...n), n.length <
|
|
1247
|
+
if (o.push(...n), n.length < Ft) break;
|
|
1211
1248
|
}
|
|
1212
1249
|
let s = /* @__PURE__ */ new Set(), c = [];
|
|
1213
1250
|
for (let e of o) s.has(e.table_name) || (s.add(e.table_name), c.push(e));
|
|
@@ -1291,7 +1328,7 @@ BEGIN
|
|
|
1291
1328
|
AND c.relname IN ${t}
|
|
1292
1329
|
)
|
|
1293
1330
|
SELECT * FROM ix ORDER BY table_name, index_name, position
|
|
1294
|
-
`), _ = /* @__PURE__ */ new Map(), v = /* @__PURE__ */ new Map(), y = /* @__PURE__ */ new Map(),
|
|
1331
|
+
`), _ = /* @__PURE__ */ new Map(), v = /* @__PURE__ */ new Map(), y = /* @__PURE__ */ new Map(), te = /* @__PURE__ */ new Map(), ne = /* @__PURE__ */ new Map(), b = /* @__PURE__ */ new Map();
|
|
1295
1332
|
for (let e of u) {
|
|
1296
1333
|
let t = _.get(e.table_name);
|
|
1297
1334
|
t || (t = [], _.set(e.table_name, t)), t.push(e);
|
|
@@ -1300,25 +1337,25 @@ BEGIN
|
|
|
1300
1337
|
let t = v.get(e.table_name);
|
|
1301
1338
|
t || (t = /* @__PURE__ */ new Set(), v.set(e.table_name, t)), t.add(e.column_name);
|
|
1302
1339
|
}
|
|
1303
|
-
let
|
|
1340
|
+
let x = /* @__PURE__ */ new Map();
|
|
1304
1341
|
for (let e of p) {
|
|
1305
|
-
let t = `${e.table_name}${e.constraint_name}`, n =
|
|
1342
|
+
let t = `${e.table_name}${e.constraint_name}`, n = x.get(t);
|
|
1306
1343
|
n || (n = {
|
|
1307
1344
|
table: e.table_name,
|
|
1308
1345
|
columns: []
|
|
1309
|
-
},
|
|
1346
|
+
}, x.set(t, n)), n.columns.push({
|
|
1310
1347
|
name: e.column_name,
|
|
1311
1348
|
position: e.position
|
|
1312
1349
|
});
|
|
1313
1350
|
}
|
|
1314
|
-
for (let [e, t] of
|
|
1351
|
+
for (let [e, t] of x) {
|
|
1315
1352
|
let n = [...t.columns].sort((e, t) => e.position - t.position).map((e) => e.name);
|
|
1316
1353
|
if (n.length === 1) {
|
|
1317
1354
|
let e = y.get(t.table);
|
|
1318
1355
|
e || (e = /* @__PURE__ */ new Set(), y.set(t.table, e)), e.add(n[0]);
|
|
1319
1356
|
} else {
|
|
1320
|
-
let r =
|
|
1321
|
-
r || (r = [],
|
|
1357
|
+
let r = te.get(t.table);
|
|
1358
|
+
r || (r = [], te.set(t.table, r)), r.push({
|
|
1322
1359
|
name: e.slice(e.indexOf("\0") + 1),
|
|
1323
1360
|
table: t.table,
|
|
1324
1361
|
columns: n,
|
|
@@ -1327,23 +1364,23 @@ BEGIN
|
|
|
1327
1364
|
}
|
|
1328
1365
|
}
|
|
1329
1366
|
for (let e of g) {
|
|
1330
|
-
let t =
|
|
1331
|
-
t || (t = [],
|
|
1367
|
+
let t = ne.get(e.source_table);
|
|
1368
|
+
t || (t = [], ne.set(e.source_table, t)), t.push(e);
|
|
1332
1369
|
}
|
|
1333
1370
|
for (let e of ee) {
|
|
1334
|
-
let t =
|
|
1335
|
-
t || (t = /* @__PURE__ */ new Map(),
|
|
1371
|
+
let t = b.get(e.table_name);
|
|
1372
|
+
t || (t = /* @__PURE__ */ new Map(), b.set(e.table_name, t));
|
|
1336
1373
|
let n = t.get(e.index_name);
|
|
1337
1374
|
n || (n = [], t.set(e.index_name, n)), n.push(e);
|
|
1338
1375
|
}
|
|
1339
|
-
let
|
|
1376
|
+
let S = [];
|
|
1340
1377
|
for (let e of c) {
|
|
1341
|
-
let t = /* @__PURE__ */ new Set(), n = (_.get(e.table_name) ?? []).filter((e) => t.has(e.column_name) ? !1 : (t.add(e.column_name), !0)), r = v.get(e.table_name) ?? /* @__PURE__ */ new Set(), i = y.get(e.table_name) ?? /* @__PURE__ */ new Set(), a =
|
|
1342
|
-
let n = r.has(t.column_name) && r.size === 1, a = o.get(t.column_name), s = a ? "reference" : n && t.column_name === "id" ? "id" :
|
|
1378
|
+
let t = /* @__PURE__ */ new Set(), n = (_.get(e.table_name) ?? []).filter((e) => t.has(e.column_name) ? !1 : (t.add(e.column_name), !0)), r = v.get(e.table_name) ?? /* @__PURE__ */ new Set(), i = y.get(e.table_name) ?? /* @__PURE__ */ new Set(), a = ne.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) => {
|
|
1379
|
+
let n = r.has(t.column_name) && r.size === 1, a = o.get(t.column_name), s = a ? "reference" : n && t.column_name === "id" ? "id" : Mt(t.data_type, t.udt_name), c = a ? {
|
|
1343
1380
|
table: a.target_table,
|
|
1344
1381
|
column: a.target_column,
|
|
1345
|
-
onDelete:
|
|
1346
|
-
onUpdate:
|
|
1382
|
+
onDelete: R(a.delete_rule),
|
|
1383
|
+
onUpdate: R(a.update_rule)
|
|
1347
1384
|
} : void 0, l = h.get(`${e.table_name}.${t.column_name}`);
|
|
1348
1385
|
return {
|
|
1349
1386
|
name: t.column_name,
|
|
@@ -1355,7 +1392,7 @@ BEGIN
|
|
|
1355
1392
|
...c ? { references: c } : {},
|
|
1356
1393
|
...l ? { oneOf: l } : {}
|
|
1357
1394
|
};
|
|
1358
|
-
}), l = [], u =
|
|
1395
|
+
}), l = [], u = b.get(e.table_name);
|
|
1359
1396
|
if (u) for (let [t, n] of u) {
|
|
1360
1397
|
let r = /* @__PURE__ */ new Set(), i = [...n].filter((e) => e.column_name !== null && e.position !== null).sort((e, t) => (e.position ?? 0) - (t.position ?? 0)).filter((e) => {
|
|
1361
1398
|
let t = e.position;
|
|
@@ -1371,7 +1408,7 @@ BEGIN
|
|
|
1371
1408
|
...a ? { expression: !0 } : {}
|
|
1372
1409
|
});
|
|
1373
1410
|
}
|
|
1374
|
-
for (let t of
|
|
1411
|
+
for (let t of te.get(e.table_name) ?? []) l.push(t);
|
|
1375
1412
|
r.size > 0 && l.push({
|
|
1376
1413
|
name: `${e.table_name}_pkey`,
|
|
1377
1414
|
table: e.table_name,
|
|
@@ -1379,20 +1416,20 @@ BEGIN
|
|
|
1379
1416
|
unique: !0
|
|
1380
1417
|
});
|
|
1381
1418
|
let d = Number(e.row_count ?? 0);
|
|
1382
|
-
|
|
1419
|
+
S.push({
|
|
1383
1420
|
name: e.table_name,
|
|
1384
1421
|
columns: c,
|
|
1385
1422
|
indexes: l,
|
|
1386
1423
|
...d > 0 ? { rowCount: d } : {}
|
|
1387
1424
|
});
|
|
1388
1425
|
}
|
|
1389
|
-
return { tables:
|
|
1426
|
+
return { tables: S };
|
|
1390
1427
|
});
|
|
1391
1428
|
return (t > 0 ? e.withTransaction(n) : n).pipe(d.catchAll((e) => {
|
|
1392
1429
|
let n = `${String(e)} ${String(e.cause ?? "")}`.toLowerCase();
|
|
1393
1430
|
return n.includes("statement timeout") || n.includes("57014") ? d.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.`)) : d.fail(e);
|
|
1394
1431
|
}));
|
|
1395
|
-
},
|
|
1432
|
+
}, zt = (e, t) => {
|
|
1396
1433
|
switch (e.toLowerCase()) {
|
|
1397
1434
|
case "varchar":
|
|
1398
1435
|
case "char":
|
|
@@ -1424,20 +1461,20 @@ BEGIN
|
|
|
1424
1461
|
case "json": return "json";
|
|
1425
1462
|
default: return "text";
|
|
1426
1463
|
}
|
|
1427
|
-
},
|
|
1464
|
+
}, z = (e) => e.map((e) => {
|
|
1428
1465
|
let t = e, n = {};
|
|
1429
1466
|
for (let e of Object.keys(t)) n[e.toLowerCase()] = t[e];
|
|
1430
1467
|
return n;
|
|
1431
|
-
}),
|
|
1432
|
-
let t =
|
|
1468
|
+
}), Bt = (e) => d.gen(function* () {
|
|
1469
|
+
let t = z(yield* e`
|
|
1433
1470
|
SELECT table_name, COALESCE(table_rows, 0) AS table_rows
|
|
1434
1471
|
FROM information_schema.tables
|
|
1435
1472
|
WHERE table_schema = DATABASE() AND table_type = 'BASE TABLE'
|
|
1436
|
-
ORDER BY table_name`), n =
|
|
1473
|
+
ORDER BY table_name`), n = z(yield* e`
|
|
1437
1474
|
SELECT table_name, column_name, data_type, column_type, is_nullable, column_default, column_key
|
|
1438
1475
|
FROM information_schema.columns
|
|
1439
1476
|
WHERE table_schema = DATABASE()
|
|
1440
|
-
ORDER BY table_name, ordinal_position`), r =
|
|
1477
|
+
ORDER BY table_name, ordinal_position`), r = z(yield* e`
|
|
1441
1478
|
SELECT k.table_name AS source_table,
|
|
1442
1479
|
k.column_name AS source_column,
|
|
1443
1480
|
k.referenced_table_name AS target_table,
|
|
@@ -1447,11 +1484,11 @@ BEGIN
|
|
|
1447
1484
|
JOIN information_schema.referential_constraints r
|
|
1448
1485
|
ON k.constraint_name = r.constraint_name
|
|
1449
1486
|
AND k.table_schema = r.constraint_schema
|
|
1450
|
-
WHERE k.table_schema = DATABASE() AND k.referenced_table_name IS NOT NULL`), i =
|
|
1487
|
+
WHERE k.table_schema = DATABASE() AND k.referenced_table_name IS NOT NULL`), i = z(yield* e`
|
|
1451
1488
|
SELECT table_name, index_name, non_unique, column_name, seq_in_index
|
|
1452
1489
|
FROM information_schema.statistics
|
|
1453
1490
|
WHERE table_schema = DATABASE() AND index_name <> 'PRIMARY'
|
|
1454
|
-
ORDER BY table_name, index_name, seq_in_index`), a =
|
|
1491
|
+
ORDER BY table_name, index_name, seq_in_index`), a = z(yield* e`
|
|
1455
1492
|
SELECT table_name, check_clause
|
|
1456
1493
|
FROM information_schema.check_constraints
|
|
1457
1494
|
WHERE constraint_schema = DATABASE()`.unprepared.pipe(d.orElseSucceed(() => []))), o = /* @__PURE__ */ new Set(), s = /* @__PURE__ */ new Map();
|
|
@@ -1461,7 +1498,7 @@ BEGIN
|
|
|
1461
1498
|
o.add(`${e.table_name}.${t[1]}`);
|
|
1462
1499
|
continue;
|
|
1463
1500
|
}
|
|
1464
|
-
let n =
|
|
1501
|
+
let n = jt(e.check_clause);
|
|
1465
1502
|
n && s.set(`${e.table_name}.${n.column}`, n.values);
|
|
1466
1503
|
}
|
|
1467
1504
|
let c = /* @__PURE__ */ new Map(), l = /* @__PURE__ */ new Map(), u = /* @__PURE__ */ new Map();
|
|
@@ -1484,11 +1521,11 @@ BEGIN
|
|
|
1484
1521
|
let t = c.get(e.table_name) ?? [], n = l.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(), d = u.get(e.table_name);
|
|
1485
1522
|
if (d) for (let e of d.values()) e.length === 1 && e[0].non_unique === 0 && a.add(e[0].column_name);
|
|
1486
1523
|
let p = t.map((t) => {
|
|
1487
|
-
let n = i.includes(t.column_name) && i.length === 1, c = r.get(t.column_name), l = c ? "reference" : n && t.column_name === "id" ? "id" : o.has(`${e.table_name}.${t.column_name}`) ? "json" :
|
|
1524
|
+
let n = i.includes(t.column_name) && i.length === 1, c = r.get(t.column_name), l = c ? "reference" : n && t.column_name === "id" ? "id" : o.has(`${e.table_name}.${t.column_name}`) ? "json" : zt(t.data_type, t.column_type), u = c ? {
|
|
1488
1525
|
table: c.target_table,
|
|
1489
1526
|
column: c.target_column,
|
|
1490
|
-
onDelete:
|
|
1491
|
-
onUpdate:
|
|
1527
|
+
onDelete: R(c.delete_rule),
|
|
1528
|
+
onUpdate: R(c.update_rule)
|
|
1492
1529
|
} : void 0, d = a.has(t.column_name) || n && t.column_name === "id", f = t.column_default === "NULL" ? null : t.column_default, p = s.get(`${e.table_name}.${t.column_name}`);
|
|
1493
1530
|
return {
|
|
1494
1531
|
name: t.column_name,
|
|
@@ -1525,10 +1562,10 @@ BEGIN
|
|
|
1525
1562
|
});
|
|
1526
1563
|
}
|
|
1527
1564
|
return { tables: f };
|
|
1528
|
-
}),
|
|
1565
|
+
}), Vt = (e) => {
|
|
1529
1566
|
let t = e.toUpperCase();
|
|
1530
1567
|
return t.includes("INT") ? "integer" : t.includes("REAL") || t.includes("FLOA") || t.includes("DOUB") ? "real" : t.includes("BLOB") ? "bytes" : "text";
|
|
1531
|
-
},
|
|
1568
|
+
}, Ht = (e) => d.gen(function* () {
|
|
1532
1569
|
let t = yield* e`
|
|
1533
1570
|
SELECT name, sql FROM sqlite_master
|
|
1534
1571
|
WHERE type = 'table' AND name NOT LIKE 'sqlite_%'
|
|
@@ -1545,11 +1582,11 @@ BEGIN
|
|
|
1545
1582
|
d.set(t.name, r), t.unique === 1 && r.length === 1 && f.add(r[0]);
|
|
1546
1583
|
}
|
|
1547
1584
|
let p = o.map((e) => {
|
|
1548
|
-
let n = u.length === 1 && u[0] === e.name, r = l.get(e.name), i = r ? "reference" : n && e.name === "id" ? "id" :
|
|
1585
|
+
let n = u.length === 1 && u[0] === e.name, r = l.get(e.name), i = r ? "reference" : n && e.name === "id" ? "id" : Vt(e.type), a = r ? {
|
|
1549
1586
|
table: r.table,
|
|
1550
1587
|
column: r.to,
|
|
1551
|
-
onDelete:
|
|
1552
|
-
onUpdate:
|
|
1588
|
+
onDelete: R(r.on_delete),
|
|
1589
|
+
onUpdate: R(r.on_update)
|
|
1553
1590
|
} : void 0, o = t.get(e.name);
|
|
1554
1591
|
return {
|
|
1555
1592
|
name: e.name,
|
|
@@ -1584,7 +1621,7 @@ BEGIN
|
|
|
1584
1621
|
});
|
|
1585
1622
|
}
|
|
1586
1623
|
return { tables: r };
|
|
1587
|
-
}),
|
|
1624
|
+
}), Ut = (e) => {
|
|
1588
1625
|
switch (e.toLowerCase()) {
|
|
1589
1626
|
case "int":
|
|
1590
1627
|
case "smallint":
|
|
@@ -1606,7 +1643,7 @@ BEGIN
|
|
|
1606
1643
|
case "image": return "bytes";
|
|
1607
1644
|
default: return "text";
|
|
1608
1645
|
}
|
|
1609
|
-
},
|
|
1646
|
+
}, B = (e) => e === !0 || e === 1, Wt = (e) => d.gen(function* () {
|
|
1610
1647
|
let t = yield* e`
|
|
1611
1648
|
SELECT TABLE_NAME AS table_name FROM INFORMATION_SCHEMA.TABLES
|
|
1612
1649
|
WHERE TABLE_TYPE = 'BASE TABLE' ORDER BY TABLE_NAME`, n = yield* e`
|
|
@@ -1662,16 +1699,16 @@ BEGIN
|
|
|
1662
1699
|
let t = s.get(e) ?? [], n = c.get(e) ?? [], r = new Map(n.map((e) => [e.source_column, e])), i = new Set(n.map((e) => e.source_column)), a = l.get(e), d = [], f = /* @__PURE__ */ new Set();
|
|
1663
1700
|
if (a) for (let [, e] of a) {
|
|
1664
1701
|
let t = [...e].sort((e, t) => e.key_ordinal - t.key_ordinal);
|
|
1665
|
-
if (
|
|
1666
|
-
else
|
|
1702
|
+
if (B(t[0].is_primary)) for (let e of t) d.push(e.column_name);
|
|
1703
|
+
else B(t[0].is_unique) && t.length === 1 && f.add(t[0].column_name);
|
|
1667
1704
|
}
|
|
1668
1705
|
let p = t.map((t) => {
|
|
1669
|
-
let n = d.length === 1 && d[0] === t.column_name, i = r.get(t.column_name), a = i ? "reference" : n && t.column_name === "id" ? "id" :
|
|
1706
|
+
let n = d.length === 1 && d[0] === t.column_name, i = r.get(t.column_name), a = i ? "reference" : n && t.column_name === "id" ? "id" : Ut(t.data_type), s = i ? {
|
|
1670
1707
|
table: i.target_table,
|
|
1671
1708
|
column: i.target_column,
|
|
1672
|
-
onDelete:
|
|
1673
|
-
onUpdate:
|
|
1674
|
-
} : void 0, c = t.column_default === null ? null :
|
|
1709
|
+
onDelete: Gt(i.delete_rule),
|
|
1710
|
+
onUpdate: Gt(i.update_rule)
|
|
1711
|
+
} : void 0, c = t.column_default === null ? null : Kt(t.column_default), l = o.get(`${e}.${t.column_name}`);
|
|
1675
1712
|
return {
|
|
1676
1713
|
name: t.column_name,
|
|
1677
1714
|
type: a,
|
|
@@ -1685,11 +1722,11 @@ BEGIN
|
|
|
1685
1722
|
}), m = [];
|
|
1686
1723
|
if (a) for (let [t, n] of a) {
|
|
1687
1724
|
let r = [...n].sort((e, t) => e.key_ordinal - t.key_ordinal);
|
|
1688
|
-
|
|
1725
|
+
B(r[0].is_primary) || r.length === 1 && B(r[0].is_unique) || r.length === 1 && !B(r[0].is_unique) && i.has(r[0].column_name) && t !== `${e}_${r[0].column_name}_idx` || m.push({
|
|
1689
1726
|
name: t,
|
|
1690
1727
|
table: e,
|
|
1691
1728
|
columns: r.map((e) => e.column_name),
|
|
1692
|
-
unique:
|
|
1729
|
+
unique: B(r[0].is_unique)
|
|
1693
1730
|
});
|
|
1694
1731
|
}
|
|
1695
1732
|
d.length > 0 && m.push({
|
|
@@ -1704,29 +1741,29 @@ BEGIN
|
|
|
1704
1741
|
});
|
|
1705
1742
|
}
|
|
1706
1743
|
return { tables: u };
|
|
1707
|
-
}),
|
|
1744
|
+
}), Gt = (e) => {
|
|
1708
1745
|
switch (e.toUpperCase().replace(/_/g, " ")) {
|
|
1709
1746
|
case "CASCADE": return "cascade";
|
|
1710
1747
|
case "SET NULL": return "setNull";
|
|
1711
1748
|
case "SET DEFAULT": return "noAction";
|
|
1712
1749
|
default: return "noAction";
|
|
1713
1750
|
}
|
|
1714
|
-
},
|
|
1751
|
+
}, Kt = (e) => {
|
|
1715
1752
|
let t = e.trim();
|
|
1716
1753
|
for (; t.startsWith("(") && t.endsWith(")");) t = t.slice(1, -1).trim();
|
|
1717
1754
|
return t.startsWith("N'") && t.endsWith("'") ? t = t.slice(2, -1) : t.startsWith("'") && t.endsWith("'") && (t = t.slice(1, -1)), t;
|
|
1718
|
-
},
|
|
1719
|
-
mysql: () =>
|
|
1720
|
-
mssql: () =>
|
|
1721
|
-
sqlite: () =>
|
|
1722
|
-
orElse: () =>
|
|
1723
|
-
}),
|
|
1755
|
+
}, qt = (e) => e.onDialectOrElse({
|
|
1756
|
+
mysql: () => Bt(e),
|
|
1757
|
+
mssql: () => Wt(e),
|
|
1758
|
+
sqlite: () => Ht(e),
|
|
1759
|
+
orElse: () => Rt(e)
|
|
1760
|
+
}), Jt = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, V = (e) => {
|
|
1724
1761
|
switch (e.type) {
|
|
1725
1762
|
case "id": return "text";
|
|
1726
1763
|
case "text": return "text";
|
|
1727
1764
|
case "integer": return "integer";
|
|
1728
1765
|
case "real": return "double precision";
|
|
1729
|
-
case "decimal": return
|
|
1766
|
+
case "decimal": return Jt(e, "NUMERIC");
|
|
1730
1767
|
case "bigint": return "bigint";
|
|
1731
1768
|
case "boolean": return "boolean";
|
|
1732
1769
|
case "timestamp": return "timestamptz";
|
|
@@ -1740,13 +1777,13 @@ BEGIN
|
|
|
1740
1777
|
case "interval": return "interval";
|
|
1741
1778
|
case "raw": return e.rawDdl ?? "text";
|
|
1742
1779
|
}
|
|
1743
|
-
},
|
|
1780
|
+
}, H = (e) => {
|
|
1744
1781
|
switch (e.type) {
|
|
1745
1782
|
case "id": return "VARCHAR(64)";
|
|
1746
1783
|
case "text": return e.hasDefault && e.defaultValue !== void 0 || e.oneOf && e.oneOf.length > 0 ? "VARCHAR(255)" : "LONGTEXT";
|
|
1747
1784
|
case "integer": return "INT";
|
|
1748
1785
|
case "real": return "DOUBLE";
|
|
1749
|
-
case "decimal": return
|
|
1786
|
+
case "decimal": return Jt(e, "DECIMAL");
|
|
1750
1787
|
case "bigint": return "BIGINT";
|
|
1751
1788
|
case "boolean": return "TINYINT(1)";
|
|
1752
1789
|
case "timestamp": return "DATETIME(6)";
|
|
@@ -1760,74 +1797,74 @@ BEGIN
|
|
|
1760
1797
|
case "interval": return "BIGINT";
|
|
1761
1798
|
case "raw": return e.rawDdl ?? "LONGTEXT";
|
|
1762
1799
|
}
|
|
1763
|
-
},
|
|
1764
|
-
let r = n ?? e.nullable, i =
|
|
1800
|
+
}, U = (e) => `"${e}"`, W = (e) => `\`${e.replace(/`/g, "``")}\``, Yt = (e, t) => `ALTER TABLE ${t(e.table)} DROP COLUMN IF EXISTS ${t(e.column)};`, Xt = (e) => `ALTER TABLE ${W(e.table)} DROP COLUMN IF EXISTS ${W(e.column)}, ALGORITHM=COPY;`, Zt = (e, t) => `ALTER TABLE ${t(e.table)} RENAME COLUMN ${t(e.from)} TO ${t(e.to)};`, Qt = (e, t, n) => `ALTER TABLE ${n(e.table)} RENAME COLUMN ${n(e.column)} TO ${n(`${e.column}${yn(t)}`)};`, $t = (e, t, n) => e.hasDefault && e.defaultValue !== void 0 ? `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} SET ${n(e.defaultValue) ?? "DEFAULT NULL"};` : `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} DROP DEFAULT;`, G = (e, t, n) => e.find((e) => e.tableName === t)?.fields[n], en = (e, t, n) => {
|
|
1801
|
+
let r = n ?? e.nullable, i = ve(e, "mariadb");
|
|
1765
1802
|
return [
|
|
1766
|
-
|
|
1767
|
-
|
|
1803
|
+
W(t),
|
|
1804
|
+
D(e, "mariadb"),
|
|
1768
1805
|
r ? null : "NOT NULL",
|
|
1769
1806
|
i
|
|
1770
1807
|
].filter(Boolean).join(" ");
|
|
1771
|
-
},
|
|
1808
|
+
}, tn = (e) => e == null ? null : 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" && !Array.isArray(e) ? O(e, "mysql") : null, nn = (e) => e == null ? null : 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" && !Array.isArray(e) ? O(e, "postgres") : null, K = (e, t) => {
|
|
1772
1809
|
if (!e.generatedAs) return null;
|
|
1773
1810
|
let { expr: n, stored: r } = e.generatedAs;
|
|
1774
1811
|
return t === "postgres" ? `GENERATED ALWAYS AS (${n}) STORED` : t === "mssql" ? `AS (${n})${r ? " PERSISTED" : ""}` : `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
|
|
1775
|
-
},
|
|
1776
|
-
if (e.type === "id" && e.idScheme?.kind === "numeric") return
|
|
1777
|
-
let t =
|
|
1778
|
-
if (t) return `${
|
|
1779
|
-
let n = [
|
|
1812
|
+
}, rn = (e) => {
|
|
1813
|
+
if (e.type === "id" && e.idScheme?.kind === "numeric") return k(e.name, "postgres");
|
|
1814
|
+
let t = K(e, "postgres");
|
|
1815
|
+
if (t) return `${U(e.name)} ${V(e)} ${t}`;
|
|
1816
|
+
let n = [U(e.name), V(e)];
|
|
1780
1817
|
if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && n.push("UNIQUE"), e.hasDefault) {
|
|
1781
|
-
let t =
|
|
1818
|
+
let t = nn(e.defaultValue);
|
|
1782
1819
|
t && n.push(t);
|
|
1783
1820
|
}
|
|
1784
|
-
return e.references && (n.push(`REFERENCES ${
|
|
1821
|
+
return e.references && (n.push(`REFERENCES ${U(e.references.table)} (${U(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${{
|
|
1785
1822
|
cascade: "CASCADE",
|
|
1786
1823
|
restrict: "RESTRICT",
|
|
1787
1824
|
setNull: "SET NULL",
|
|
1788
1825
|
noAction: "NO ACTION"
|
|
1789
1826
|
}[e.references.onDelete]}`)), n.join(" ");
|
|
1790
|
-
},
|
|
1791
|
-
let t = e.columns.map((e) => ` ${
|
|
1792
|
-
for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${
|
|
1827
|
+
}, q = (e, t) => e.primaryKey && e.primaryKey.length > 0 ? `,\n PRIMARY KEY (${e.primaryKey.map(t).join(", ")})` : "", an = (e) => {
|
|
1828
|
+
let t = e.columns.map((e) => ` ${rn(e)}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${U(e.table)} (\n${t}${q(e, U)}\n)`];
|
|
1829
|
+
for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${U(t.name)} ON ${U(e.table)} (${t.columns.map(wn).join(", ")})`);
|
|
1793
1830
|
return n;
|
|
1794
|
-
},
|
|
1795
|
-
let t =
|
|
1831
|
+
}, on = 191, J = (e) => {
|
|
1832
|
+
let t = H(e).toUpperCase();
|
|
1796
1833
|
return t.endsWith("TEXT") || t.endsWith("BLOB");
|
|
1797
|
-
},
|
|
1798
|
-
if (e.type === "id" && e.idScheme?.kind === "numeric") return
|
|
1799
|
-
let t =
|
|
1800
|
-
if (t) return `${
|
|
1801
|
-
let n = [
|
|
1802
|
-
if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && !
|
|
1803
|
-
let t =
|
|
1834
|
+
}, sn = (e) => {
|
|
1835
|
+
if (e.type === "id" && e.idScheme?.kind === "numeric") return k(e.name, "mariadb");
|
|
1836
|
+
let t = K(e, "mariadb");
|
|
1837
|
+
if (t) return `${W(e.name)} ${H(e)} ${t}`;
|
|
1838
|
+
let n = [W(e.name), H(e)];
|
|
1839
|
+
if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && !J(e) && n.push("UNIQUE"), e.hasDefault) {
|
|
1840
|
+
let t = tn(e.defaultValue);
|
|
1804
1841
|
t && n.push(t);
|
|
1805
1842
|
}
|
|
1806
|
-
return e.references && (n.push(`REFERENCES ${
|
|
1843
|
+
return e.references && (n.push(`REFERENCES ${W(e.references.table)} (${W(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${{
|
|
1807
1844
|
cascade: "CASCADE",
|
|
1808
1845
|
restrict: "RESTRICT",
|
|
1809
1846
|
setNull: "SET NULL",
|
|
1810
1847
|
noAction: "NO ACTION"
|
|
1811
1848
|
}[e.references.onDelete]}`)), n.join(" ");
|
|
1812
|
-
},
|
|
1849
|
+
}, cn = (e) => {
|
|
1813
1850
|
let t = new Map(e.columns.map((e) => [e.name, e])), n = (e) => {
|
|
1814
1851
|
let n = t.get(e);
|
|
1815
|
-
return n &&
|
|
1816
|
-
}, r = e.columns.map((e) => ` ${
|
|
1817
|
-
for (let t of e.columns) t.unique && t.type !== "id" &&
|
|
1818
|
-
for (let t of e.indexes) t.name !== `${e.table}_pkey` && i.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${
|
|
1852
|
+
return n && J(n) ? `${W(e)}(${on})` : W(e);
|
|
1853
|
+
}, r = e.columns.map((e) => ` ${sn(e)}`).join(",\n"), i = [`CREATE TABLE IF NOT EXISTS ${W(e.table)} (\n${r}${q(e, n)}\n)`];
|
|
1854
|
+
for (let t of e.columns) t.unique && t.type !== "id" && J(t) && i.push(`CREATE UNIQUE INDEX IF NOT EXISTS ${W(`${e.table}_${t.name}_key`)} ON ${W(e.table)} (${n(t.name)})`);
|
|
1855
|
+
for (let t of e.indexes) t.name !== `${e.table}_pkey` && i.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${W(t.name)} ON ${W(e.table)} (${t.columns.map(n).join(", ")})`);
|
|
1819
1856
|
return i;
|
|
1820
|
-
},
|
|
1857
|
+
}, ln = {
|
|
1821
1858
|
cascade: "CASCADE",
|
|
1822
1859
|
restrict: "RESTRICT",
|
|
1823
1860
|
setNull: "SET NULL",
|
|
1824
1861
|
noAction: "NO ACTION"
|
|
1825
|
-
},
|
|
1862
|
+
}, un = {
|
|
1826
1863
|
cascade: "CASCADE",
|
|
1827
1864
|
restrict: "NO ACTION",
|
|
1828
1865
|
setNull: "SET NULL",
|
|
1829
1866
|
noAction: "NO ACTION"
|
|
1830
|
-
},
|
|
1867
|
+
}, dn = (e) => {
|
|
1831
1868
|
switch (e.type) {
|
|
1832
1869
|
case "integer":
|
|
1833
1870
|
case "boolean": return "INTEGER";
|
|
@@ -1837,58 +1874,58 @@ BEGIN
|
|
|
1837
1874
|
case "bytes": return "BLOB";
|
|
1838
1875
|
default: return "TEXT";
|
|
1839
1876
|
}
|
|
1840
|
-
}, Y = (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" && !Array.isArray(e) ?
|
|
1841
|
-
if (e.type === "id" && e.idScheme?.kind === "numeric") return
|
|
1842
|
-
let t =
|
|
1843
|
-
if (t) return `${
|
|
1844
|
-
let n = [
|
|
1877
|
+
}, Y = (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" && !Array.isArray(e) ? O(e, "sqlite") : null, fn = (e) => {
|
|
1878
|
+
if (e.type === "id" && e.idScheme?.kind === "numeric") return k(e.name, "sqlite");
|
|
1879
|
+
let t = K(e, "sqlite");
|
|
1880
|
+
if (t) return `${U(e.name)} ${dn(e)} ${t}`;
|
|
1881
|
+
let n = [U(e.name), dn(e)];
|
|
1845
1882
|
if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && n.push("UNIQUE"), e.hasDefault) {
|
|
1846
1883
|
let t = Y(e.defaultValue, "CURRENT_TIMESTAMP");
|
|
1847
1884
|
t && n.push(t);
|
|
1848
1885
|
}
|
|
1849
|
-
if (e.references && (n.push(`REFERENCES ${
|
|
1886
|
+
if (e.references && (n.push(`REFERENCES ${U(e.references.table)} (${U(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${ln[e.references.onDelete]}`)), e.oneOf && e.oneOf.length > 0) {
|
|
1850
1887
|
let t = e.oneOf.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
|
|
1851
|
-
n.push(`CHECK (${
|
|
1888
|
+
n.push(`CHECK (${U(e.name)} IN (${t}))`);
|
|
1852
1889
|
}
|
|
1853
1890
|
return n.join(" ");
|
|
1854
|
-
},
|
|
1855
|
-
let t = e.columns.map((e) => ` ${
|
|
1856
|
-
for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${
|
|
1891
|
+
}, pn = (e) => {
|
|
1892
|
+
let t = e.columns.map((e) => ` ${fn(e)}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${U(e.table)} (\n${t}${q(e, U)}\n)`];
|
|
1893
|
+
for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${U(t.name)} ON ${U(e.table)} (${t.columns.map(U).join(", ")})`);
|
|
1857
1894
|
return n;
|
|
1858
1895
|
}, X = (e, t) => {
|
|
1859
1896
|
let n = t.find((t) => t.tableName === e);
|
|
1860
1897
|
if (!n) return [];
|
|
1861
|
-
let r =
|
|
1862
|
-
...
|
|
1898
|
+
let r = P([n]).tables[0], i = `${e}__voltro_rebuild`, a = r.columns.map((e) => U(e.name)).join(", "), o = [
|
|
1899
|
+
...pn({
|
|
1863
1900
|
kind: "create-table",
|
|
1864
1901
|
table: i,
|
|
1865
1902
|
columns: r.columns,
|
|
1866
1903
|
indexes: [],
|
|
1867
1904
|
...r.primaryKey ? { primaryKey: r.primaryKey } : {}
|
|
1868
1905
|
}),
|
|
1869
|
-
`INSERT INTO ${
|
|
1870
|
-
`DROP TABLE ${
|
|
1871
|
-
`ALTER TABLE ${
|
|
1906
|
+
`INSERT INTO ${U(i)} (${a}) SELECT ${a} FROM ${U(e)}`,
|
|
1907
|
+
`DROP TABLE ${U(e)}`,
|
|
1908
|
+
`ALTER TABLE ${U(i)} RENAME TO ${U(e)}`
|
|
1872
1909
|
];
|
|
1873
|
-
for (let t of r.indexes) t.name !== `${e}_pkey` && o.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${
|
|
1910
|
+
for (let t of r.indexes) t.name !== `${e}_pkey` && o.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${U(t.name)} ON ${U(e)} (${t.columns.map(U).join(", ")})`);
|
|
1874
1911
|
return o;
|
|
1875
|
-
},
|
|
1912
|
+
}, mn = (e, t, n, r) => {
|
|
1876
1913
|
let i = r ?? e.nullable;
|
|
1877
|
-
return `ALTER TABLE ${Z(n)} ALTER COLUMN ${Z(t)} ${
|
|
1878
|
-
},
|
|
1914
|
+
return `ALTER TABLE ${Z(n)} ALTER COLUMN ${Z(t)} ${D(e, "mssql")} ${i ? "NULL" : "NOT NULL"};`;
|
|
1915
|
+
}, hn = (e) => {
|
|
1879
1916
|
let t = `DECLARE @dc sysname; SELECT @dc = dc.name FROM sys.default_constraints dc JOIN sys.columns col ON col.object_id = dc.parent_object_id AND col.column_id = dc.parent_column_id WHERE dc.parent_object_id = OBJECT_ID(N'${e.table.replace(/'/g, "''")}') AND col.name = N'${e.column.replace(/'/g, "''")}'; IF @dc IS NOT NULL EXEC(N'ALTER TABLE ${Z(e.table)} DROP CONSTRAINT [' + @dc + ']');`;
|
|
1880
1917
|
if (!e.hasDefault) return t;
|
|
1881
1918
|
let n = Y(e.defaultValue, "SYSUTCDATETIME()");
|
|
1882
1919
|
if (!n) return t;
|
|
1883
1920
|
let r = n.replace(/^DEFAULT\s+/i, "");
|
|
1884
1921
|
return `${t} ALTER TABLE ${Z(e.table)} ADD DEFAULT ${r} FOR ${Z(e.column)};`;
|
|
1885
|
-
}, Z = (e) => `[${e.replace(/]/g, "]]")}]`,
|
|
1922
|
+
}, Z = (e) => `[${e.replace(/]/g, "]]")}]`, gn = (e) => {
|
|
1886
1923
|
switch (e.type) {
|
|
1887
1924
|
case "id":
|
|
1888
1925
|
case "reference": return "NVARCHAR(64)";
|
|
1889
1926
|
case "integer": return "INT";
|
|
1890
1927
|
case "real": return "FLOAT";
|
|
1891
|
-
case "decimal": return
|
|
1928
|
+
case "decimal": return Jt(e, "DECIMAL");
|
|
1892
1929
|
case "bigint": return "BIGINT";
|
|
1893
1930
|
case "boolean": return "BIT";
|
|
1894
1931
|
case "timestamp": return "DATETIME2(6)";
|
|
@@ -1896,34 +1933,34 @@ BEGIN
|
|
|
1896
1933
|
case "bytes": return "VARBINARY(MAX)";
|
|
1897
1934
|
default: return "NVARCHAR(MAX)";
|
|
1898
1935
|
}
|
|
1899
|
-
},
|
|
1900
|
-
if (e.type === "id" && e.idScheme?.kind === "numeric") return
|
|
1901
|
-
let n = e.type === "text" && t?.has(e.name) ? "NVARCHAR(450)" :
|
|
1936
|
+
}, _n = (e, t) => {
|
|
1937
|
+
if (e.type === "id" && e.idScheme?.kind === "numeric") return k(e.name, "mssql");
|
|
1938
|
+
let n = e.type === "text" && t?.has(e.name) ? "NVARCHAR(450)" : gn(e), r = K(e, "mssql");
|
|
1902
1939
|
if (r) return `${Z(e.name)} ${r}`;
|
|
1903
1940
|
let i = [Z(e.name), n];
|
|
1904
1941
|
if (e.type === "id" && i.push("PRIMARY KEY"), e.nullable || i.push("NOT NULL"), e.unique && e.type !== "id" && i.push("UNIQUE"), e.hasDefault) {
|
|
1905
1942
|
let t = Y(e.defaultValue, "SYSUTCDATETIME()");
|
|
1906
1943
|
t && i.push(t);
|
|
1907
1944
|
}
|
|
1908
|
-
return e.references && (i.push(`REFERENCES ${Z(e.references.table)} (${Z(e.references.column)})`), e.references.onDelete && i.push(`ON DELETE ${
|
|
1909
|
-
},
|
|
1910
|
-
let t = (e) => e.replace(/'/g, "''"), n = new Set(e.indexes.flatMap((e) => e.columns)), r = e.columns.map((e) => ` ${
|
|
1945
|
+
return e.references && (i.push(`REFERENCES ${Z(e.references.table)} (${Z(e.references.column)})`), e.references.onDelete && i.push(`ON DELETE ${un[e.references.onDelete]}`)), i.join(" ");
|
|
1946
|
+
}, vn = (e) => {
|
|
1947
|
+
let t = (e) => e.replace(/'/g, "''"), n = new Set(e.indexes.flatMap((e) => e.columns)), r = e.columns.map((e) => ` ${_n(e, n)}`).join(",\n"), i = `CREATE TABLE ${Z(e.table)} (\n${r}${q(e, Z)}\n)`, a = [`IF OBJECT_ID(N'${t(e.table)}', N'U') IS NULL EXEC(N'${t(i)}')`];
|
|
1911
1948
|
for (let n of e.indexes) {
|
|
1912
1949
|
if (n.name === `${e.table}_pkey`) continue;
|
|
1913
1950
|
let r = `CREATE ${n.unique ? "UNIQUE " : ""}INDEX ${Z(n.name)} ON ${Z(e.table)} (${n.columns.map(Z).join(", ")})`;
|
|
1914
1951
|
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)}')`);
|
|
1915
1952
|
}
|
|
1916
1953
|
return a;
|
|
1917
|
-
},
|
|
1918
|
-
let r = `${e.table}${
|
|
1954
|
+
}, yn = (e) => `__dropped_${e.replace(/[-:T.Z]/g, "").slice(0, 14)}`, bn = (e, t) => `DROP TABLE IF EXISTS ${t(e.table)};`, xn = (e, t, n) => {
|
|
1955
|
+
let r = `${e.table}${yn(t)}`;
|
|
1919
1956
|
return `ALTER TABLE ${n(e.table)} RENAME TO ${n(r)};`;
|
|
1920
|
-
},
|
|
1921
|
-
let r =
|
|
1922
|
-
return r ?
|
|
1923
|
-
},
|
|
1957
|
+
}, Sn = (e, t, n) => {
|
|
1958
|
+
let r = G(e, t, n);
|
|
1959
|
+
return r ? J({ type: r.type }) : !1;
|
|
1960
|
+
}, Cn = (e, t, n) => Sn(e, t, n) ? `${W(n)}(${on})` : W(n), wn = (e) => e.startsWith("(") ? e : U(e), Tn = (e, t) => `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX ${t ? "CONCURRENTLY " : ""}IF NOT EXISTS ${U(e.index.name)} ON ${U(e.table)} (${e.index.columns.map(wn).join(", ")});`, En = (e, t) => `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${W(e.index.name)} ON ${W(e.table)} (${e.index.columns.map((n) => Cn(t, e.table, n)).join(", ")});`, Dn = (e) => `DROP INDEX IF EXISTS ${U(e.index)};`, On = (e) => `DROP INDEX ${W(e.index)} ON ${W(e.table)};`, kn = (e) => `DROP INDEX IF EXISTS ${Z(e.index)} ON ${Z(e.table)};`, An = (e) => {
|
|
1924
1961
|
let t = (e) => e.replace(/'/g, "''"), n = `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX ${Z(e.index.name)} ON ${Z(e.table)} (${e.index.columns.map(Z).join(", ")})`;
|
|
1925
1962
|
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)}');`;
|
|
1926
|
-
},
|
|
1963
|
+
}, jn = (e, t, n) => {
|
|
1927
1964
|
let r = n.find((t) => t.tableName === e);
|
|
1928
1965
|
if (!r) return [];
|
|
1929
1966
|
let i = [];
|
|
@@ -1932,13 +1969,13 @@ BEGIN
|
|
|
1932
1969
|
t && t.type === "text" && !t.generatedAs && i.push(`ALTER TABLE ${Z(e)} ALTER COLUMN ${Z(n)} NVARCHAR(450) ${t.nullable ? "NULL" : "NOT NULL"};`);
|
|
1933
1970
|
}
|
|
1934
1971
|
return i;
|
|
1935
|
-
},
|
|
1936
|
-
let t = e.fields.map((e) =>
|
|
1937
|
-
return `ALTER TABLE ${
|
|
1938
|
-
},
|
|
1939
|
-
let n = e.fields.map((n) =>
|
|
1940
|
-
return `ALTER TABLE ${
|
|
1941
|
-
},
|
|
1972
|
+
}, Mn = (e) => `ALTER TABLE ${U(e.table)} ADD CONSTRAINT ${U(`${e.table}_${e.column}_key`)} UNIQUE (${U(e.column)});`, Nn = (e, t) => `ALTER TABLE ${W(e.table)} ADD CONSTRAINT ${W(`${e.table}_${e.column}_key`)} UNIQUE (${Cn(t, e.table, e.column)});`, Pn = (e) => {
|
|
1973
|
+
let t = e.fields.map((e) => U(e)).join(", ");
|
|
1974
|
+
return `ALTER TABLE ${U(e.table)} ADD CONSTRAINT ${U(e.name)} UNIQUE (${t});`;
|
|
1975
|
+
}, Fn = (e, t) => {
|
|
1976
|
+
let n = e.fields.map((n) => Cn(t, e.table, n)).join(", ");
|
|
1977
|
+
return `ALTER TABLE ${W(e.table)} ADD CONSTRAINT ${W(e.name)} UNIQUE (${n});`;
|
|
1978
|
+
}, In = (e) => `ALTER TABLE ${U(e.table)} DROP CONSTRAINT IF EXISTS ${U(e.name)};`, Ln = (e) => `ALTER TABLE ${W(e.table)} DROP INDEX ${W(e.name)};`, Rn = (e) => `ALTER TABLE ${U(e.table)} DROP CONSTRAINT IF EXISTS ${U(`${e.table}_${e.column}_key`)};`, zn = (e) => `ALTER TABLE ${W(e.table)} DROP INDEX ${W(`${e.table}_${e.column}_key`)};`, Bn = (e, t) => {
|
|
1942
1979
|
let n = [], r = t(e.table), i = t(e.column), a = t(e.targetTable), o = t(e.targetColumn);
|
|
1943
1980
|
if (e.orphanPolicy) {
|
|
1944
1981
|
let t = `${i} IS NOT NULL AND ${i} NOT IN (SELECT ${o} FROM ${a})`;
|
|
@@ -1956,11 +1993,11 @@ BEGIN
|
|
|
1956
1993
|
setNull: "SET NULL",
|
|
1957
1994
|
noAction: "NO ACTION"
|
|
1958
1995
|
}[e.onDelete]}`), n.push(s.join(" ") + ";"), n;
|
|
1959
|
-
},
|
|
1996
|
+
}, Vn = (e) => `ALTER TABLE ${U(e.table)} DROP CONSTRAINT IF EXISTS ${U(`${e.table}_${e.column}_fkey`)};`, Hn = (e) => `ALTER TABLE ${W(e.table)} DROP FOREIGN KEY ${W(`${e.table}_${e.column}_fkey`)};`, Un = (e, t) => {
|
|
1960
1997
|
let n = e.values.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
|
|
1961
1998
|
return `ALTER TABLE ${t(e.table)} ADD CONSTRAINT ${t(`${e.table}_${e.column}_check`)} CHECK (${t(e.column)} IN (${n}));`;
|
|
1962
|
-
},
|
|
1963
|
-
let i = e.column, a = r === "mariadb", o = a ?
|
|
1999
|
+
}, Wn = (e) => `ALTER TABLE ${U(e.table)} DROP CONSTRAINT IF EXISTS ${U(`${e.table}_${e.column}_check`)};`, Gn = (e) => `ALTER TABLE ${W(e.table)} DROP CHECK ${W(`${e.table}_${e.column}_check`)};`, Kn = (e, t, n, r) => {
|
|
2000
|
+
let i = e.column, a = r === "mariadb", o = a ? W : r === "mssql" ? Z : U, s = a ? H(i) : r === "mssql" ? gn(i) : r === "sqlite" ? dn(i) : V(i), c = r === "mssql" ? "ADD" : "ADD COLUMN", l = (e) => a ? tn(e) : r === "mssql" ? Y(e, "SYSUTCDATETIME()") : r === "sqlite" ? Y(e, "CURRENT_TIMESTAMP") : nn(e), u = K(i, r);
|
|
1964
2001
|
if (u) {
|
|
1965
2002
|
let t = r === "mssql" ? `${o(i.name)} ${u}` : `${o(i.name)} ${s} ${u}`;
|
|
1966
2003
|
return {
|
|
@@ -1987,7 +2024,7 @@ BEGIN
|
|
|
1987
2024
|
post: f ? [f] : []
|
|
1988
2025
|
};
|
|
1989
2026
|
return d?.sql && (p.backfillKind = "sql", p.backfillSql = d.sql), d?.js && (p.backfillKind = "js", p.backfillJs = d.js), d?.batchSize !== void 0 && (p.batchSize = d.batchSize), d?.sleepMs !== void 0 && (p.sleepMs = d.sleepMs), p;
|
|
1990
|
-
},
|
|
2027
|
+
}, qn = (e) => {
|
|
1991
2028
|
let t = new Map(e.map((e) => [e.tableName, e]));
|
|
1992
2029
|
return (e, n) => {
|
|
1993
2030
|
let r = t.get(e);
|
|
@@ -2009,95 +2046,95 @@ BEGIN
|
|
|
2009
2046
|
};
|
|
2010
2047
|
}, Q = (e, t, n) => e.unsafe(t).pipe(d.tapError((e) => d.sync(() => {
|
|
2011
2048
|
process.stderr.write(_(`applier: statement failed (op=${n})`, t, e, 400));
|
|
2012
|
-
})), d.map(() => void 0)), $ = (e, t, n) => d.forEach(t, (t) => Q(e, t, n), { discard: !0 }),
|
|
2013
|
-
let r = process.hrtime.bigint(), i =
|
|
2049
|
+
})), d.map(() => void 0)), $ = (e, t, n) => d.forEach(t, (t) => Q(e, t, n), { discard: !0 }), Jn = (e, t, n) => d.gen(function* () {
|
|
2050
|
+
let r = process.hrtime.bigint(), i = qn(n.declared), a = t.op;
|
|
2014
2051
|
switch (a.kind) {
|
|
2015
2052
|
case "create-table": {
|
|
2016
2053
|
let t = yield* e.onDialectOrElse({
|
|
2017
|
-
mysql: () => d.succeed(
|
|
2018
|
-
mssql: () => d.succeed(
|
|
2019
|
-
sqlite: () => d.succeed(
|
|
2020
|
-
orElse: () => d.succeed(
|
|
2054
|
+
mysql: () => d.succeed(cn(a)),
|
|
2055
|
+
mssql: () => d.succeed(vn(a)),
|
|
2056
|
+
sqlite: () => d.succeed(pn(a)),
|
|
2057
|
+
orElse: () => d.succeed(an(a))
|
|
2021
2058
|
});
|
|
2022
2059
|
for (let n of t) yield* Q(e, n, a.kind);
|
|
2023
2060
|
break;
|
|
2024
2061
|
}
|
|
2025
2062
|
case "drop-table": {
|
|
2026
|
-
let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString(), r = (e) => t ?
|
|
2063
|
+
let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString(), r = (e) => t ? xn(a, n, e) : bn(a, e);
|
|
2027
2064
|
yield* e.onDialectOrElse({
|
|
2028
|
-
mysql: () => Q(e, r(
|
|
2029
|
-
orElse: () => Q(e, r(
|
|
2065
|
+
mysql: () => Q(e, r(W), a.kind),
|
|
2066
|
+
orElse: () => Q(e, r(U), a.kind)
|
|
2030
2067
|
});
|
|
2031
2068
|
break;
|
|
2032
2069
|
}
|
|
2033
2070
|
case "drop-column": {
|
|
2034
2071
|
let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString();
|
|
2035
2072
|
yield* e.onDialectOrElse({
|
|
2036
|
-
mysql: () => Q(e, t ?
|
|
2037
|
-
orElse: () => Q(e, t ?
|
|
2073
|
+
mysql: () => Q(e, t ? Qt(a, n, W) : Xt(a), a.kind),
|
|
2074
|
+
orElse: () => Q(e, t ? Qt(a, n, U) : Yt(a, U), a.kind)
|
|
2038
2075
|
});
|
|
2039
2076
|
break;
|
|
2040
2077
|
}
|
|
2041
2078
|
case "rename-column":
|
|
2042
2079
|
yield* e.onDialectOrElse({
|
|
2043
|
-
mysql: () => Q(e,
|
|
2080
|
+
mysql: () => Q(e, Zt(a, W), a.kind),
|
|
2044
2081
|
mssql: () => Q(e, `EXEC sp_rename N'${a.table.replace(/'/g, "''")}.${a.from.replace(/'/g, "''")}', N'${a.to.replace(/'/g, "''")}', 'COLUMN';`, a.kind),
|
|
2045
|
-
orElse: () => Q(e,
|
|
2082
|
+
orElse: () => Q(e, Zt(a, U), a.kind)
|
|
2046
2083
|
});
|
|
2047
2084
|
break;
|
|
2048
2085
|
case "add-index":
|
|
2049
2086
|
yield* e.onDialectOrElse({
|
|
2050
|
-
mysql: () => Q(e,
|
|
2051
|
-
mssql: () => $(e, [...
|
|
2052
|
-
orElse: () => Q(e,
|
|
2087
|
+
mysql: () => Q(e, En(a, n.declared), a.kind),
|
|
2088
|
+
mssql: () => $(e, [...jn(a.table, a.index.columns, n.declared), An(a)], a.kind),
|
|
2089
|
+
orElse: () => Q(e, Tn(a, t.classification === "online-required"), a.kind)
|
|
2053
2090
|
});
|
|
2054
2091
|
break;
|
|
2055
2092
|
case "drop-index":
|
|
2056
2093
|
yield* e.onDialectOrElse({
|
|
2057
|
-
mysql: () => Q(e,
|
|
2058
|
-
mssql: () => Q(e,
|
|
2059
|
-
orElse: () => Q(e,
|
|
2094
|
+
mysql: () => Q(e, On(a), a.kind),
|
|
2095
|
+
mssql: () => Q(e, kn(a), a.kind),
|
|
2096
|
+
orElse: () => Q(e, Dn(a), a.kind)
|
|
2060
2097
|
});
|
|
2061
2098
|
break;
|
|
2062
2099
|
case "add-unique":
|
|
2063
2100
|
yield* e.onDialectOrElse({
|
|
2064
|
-
mysql: () => Q(e,
|
|
2101
|
+
mysql: () => Q(e, Nn(a, n.declared), a.kind),
|
|
2065
2102
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2066
|
-
mssql: () => $(e, [...
|
|
2067
|
-
orElse: () => Q(e,
|
|
2103
|
+
mssql: () => $(e, [...jn(a.table, [a.column], n.declared), Mn(a)], a.kind),
|
|
2104
|
+
orElse: () => Q(e, Mn(a), a.kind)
|
|
2068
2105
|
});
|
|
2069
2106
|
break;
|
|
2070
2107
|
case "drop-unique":
|
|
2071
2108
|
yield* e.onDialectOrElse({
|
|
2072
|
-
mysql: () => Q(e,
|
|
2109
|
+
mysql: () => Q(e, zn(a), a.kind),
|
|
2073
2110
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2074
|
-
orElse: () => Q(e,
|
|
2111
|
+
orElse: () => Q(e, Rn(a), a.kind)
|
|
2075
2112
|
});
|
|
2076
2113
|
break;
|
|
2077
2114
|
case "add-unique-composite":
|
|
2078
2115
|
yield* e.onDialectOrElse({
|
|
2079
|
-
mysql: () => Q(e,
|
|
2116
|
+
mysql: () => Q(e, Fn(a, n.declared), a.kind),
|
|
2080
2117
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2081
|
-
mssql: () => $(e, [...
|
|
2082
|
-
orElse: () => Q(e,
|
|
2118
|
+
mssql: () => $(e, [...jn(a.table, a.fields, n.declared), Pn(a)], a.kind),
|
|
2119
|
+
orElse: () => Q(e, Pn(a), a.kind)
|
|
2083
2120
|
});
|
|
2084
2121
|
break;
|
|
2085
2122
|
case "drop-unique-composite":
|
|
2086
2123
|
yield* e.onDialectOrElse({
|
|
2087
|
-
mysql: () => Q(e,
|
|
2124
|
+
mysql: () => Q(e, Ln(a), a.kind),
|
|
2088
2125
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2089
|
-
orElse: () => Q(e,
|
|
2126
|
+
orElse: () => Q(e, In(a), a.kind)
|
|
2090
2127
|
});
|
|
2091
2128
|
break;
|
|
2092
2129
|
case "add-foreign-key":
|
|
2093
2130
|
yield* e.onDialectOrElse({
|
|
2094
|
-
mysql: () => $(e,
|
|
2131
|
+
mysql: () => $(e, Bn(a, W), a.kind),
|
|
2095
2132
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2096
|
-
orElse: () => $(e,
|
|
2133
|
+
orElse: () => $(e, Bn(a, U), a.kind)
|
|
2097
2134
|
});
|
|
2098
2135
|
break;
|
|
2099
2136
|
case "add-column": {
|
|
2100
|
-
let n =
|
|
2137
|
+
let n = Kn(a, t, i, yield* e.onDialectOrElse({
|
|
2101
2138
|
mysql: () => d.succeed("mariadb"),
|
|
2102
2139
|
mssql: () => d.succeed("mssql"),
|
|
2103
2140
|
sqlite: () => d.succeed("sqlite"),
|
|
@@ -2142,39 +2179,39 @@ BEGIN
|
|
|
2142
2179
|
case "alter-column-nullability":
|
|
2143
2180
|
yield* e.onDialectOrElse({
|
|
2144
2181
|
mysql: () => {
|
|
2145
|
-
let t =
|
|
2146
|
-
return t ? Q(e, `ALTER TABLE ${
|
|
2182
|
+
let t = G(n.declared, a.table, a.column);
|
|
2183
|
+
return t ? Q(e, `ALTER TABLE ${W(a.table)} MODIFY COLUMN ${en(t, a.column, a.toNullable)};`, a.kind) : d.die(/* @__PURE__ */ Error(`alter-column-nullability on mariadb needs the declared column '${a.table}.${a.column}' (to render MODIFY COLUMN); it was not in ctx.declared.`));
|
|
2147
2184
|
},
|
|
2148
2185
|
mssql: () => {
|
|
2149
|
-
let t =
|
|
2150
|
-
return t ? Q(e,
|
|
2186
|
+
let t = G(n.declared, a.table, a.column);
|
|
2187
|
+
return t ? Q(e, mn(t, a.column, a.table, a.toNullable), a.kind) : d.die(/* @__PURE__ */ Error(`alter-column-nullability on mssql needs the declared column '${a.table}.${a.column}'.`));
|
|
2151
2188
|
},
|
|
2152
2189
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2153
|
-
orElse: () => Q(e, `ALTER TABLE ${
|
|
2190
|
+
orElse: () => Q(e, `ALTER TABLE ${U(a.table)} ALTER COLUMN ${U(a.column)} ${a.toNullable ? "DROP NOT NULL" : "SET NOT NULL"};`, a.kind)
|
|
2154
2191
|
});
|
|
2155
2192
|
break;
|
|
2156
2193
|
case "alter-column-default":
|
|
2157
2194
|
yield* e.onDialectOrElse({
|
|
2158
|
-
mysql: () => Q(e,
|
|
2159
|
-
mssql: () => Q(e,
|
|
2195
|
+
mysql: () => Q(e, $t(a, W, tn), a.kind),
|
|
2196
|
+
mssql: () => Q(e, hn(a), a.kind),
|
|
2160
2197
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2161
|
-
orElse: () => Q(e,
|
|
2198
|
+
orElse: () => Q(e, $t(a, U, nn), a.kind)
|
|
2162
2199
|
});
|
|
2163
2200
|
break;
|
|
2164
2201
|
case "alter-column-type": {
|
|
2165
|
-
let r =
|
|
2202
|
+
let r = V({ type: a.to }), i = a.using ? ` USING ${a.using}` : "";
|
|
2166
2203
|
if (t.classification !== "online-required") {
|
|
2167
2204
|
yield* e.onDialectOrElse({
|
|
2168
2205
|
mysql: () => {
|
|
2169
|
-
let t =
|
|
2170
|
-
return t ? Q(e, `ALTER TABLE ${
|
|
2206
|
+
let t = G(n.declared, a.table, a.column);
|
|
2207
|
+
return t ? Q(e, `ALTER TABLE ${W(a.table)} MODIFY COLUMN ${en(t, a.column)};`, a.kind) : d.die(/* @__PURE__ */ Error(`alter-column-type on mariadb needs the declared column '${a.table}.${a.column}' (to render MODIFY COLUMN); it was not in ctx.declared.`));
|
|
2171
2208
|
},
|
|
2172
2209
|
mssql: () => {
|
|
2173
|
-
let t =
|
|
2174
|
-
return t ? Q(e,
|
|
2210
|
+
let t = G(n.declared, a.table, a.column);
|
|
2211
|
+
return t ? Q(e, mn(t, a.column, a.table), a.kind) : d.die(/* @__PURE__ */ Error(`alter-column-type on mssql needs the declared column '${a.table}.${a.column}'.`));
|
|
2175
2212
|
},
|
|
2176
2213
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2177
|
-
orElse: () => Q(e, `ALTER TABLE ${
|
|
2214
|
+
orElse: () => Q(e, `ALTER TABLE ${U(a.table)} ALTER COLUMN ${U(a.column)} TYPE ${r}${i};`, a.kind)
|
|
2178
2215
|
});
|
|
2179
2216
|
break;
|
|
2180
2217
|
}
|
|
@@ -2183,35 +2220,35 @@ BEGIN
|
|
|
2183
2220
|
orElse: () => d.void
|
|
2184
2221
|
});
|
|
2185
2222
|
let o = `${a.column}__shadow`, s = `${a.column}__old`;
|
|
2186
|
-
yield* e.unsafe(`ALTER TABLE ${
|
|
2187
|
-
let c = a.using ??
|
|
2223
|
+
yield* e.unsafe(`ALTER TABLE ${U(a.table)} ADD COLUMN ${U(o)} ${r}`);
|
|
2224
|
+
let c = a.using ?? U(a.column), l;
|
|
2188
2225
|
for (;;) {
|
|
2189
2226
|
let t = l === void 0 ? yield* e`SELECT ${e("id")} FROM ${e(a.table)} WHERE ${e(o)} IS NULL ORDER BY ${e("id")} LIMIT 5000` : yield* e`SELECT ${e("id")} FROM ${e(a.table)} WHERE ${e(o)} IS NULL AND ${e("id")} > ${l} ORDER BY ${e("id")} LIMIT 5000`;
|
|
2190
2227
|
if (t.length === 0) break;
|
|
2191
|
-
yield* e.unsafe(`UPDATE ${
|
|
2228
|
+
yield* e.unsafe(`UPDATE ${U(a.table)} SET ${U(o)} = ${c} WHERE ${U(a.column)} IS NOT NULL AND ${U(o)} IS NULL AND ${U("id")} IN (${t.map((e) => `'${e.id.replace(/'/g, "''")}'`).join(",")})`), l = t[t.length - 1].id;
|
|
2192
2229
|
}
|
|
2193
|
-
yield* d.logInfo(`alter-column-type shadow ${a.table}.${a.column}: shadow populated`).pipe(d.annotateLogs({ scope: "voltro:migrate" })), yield* e.unsafe(`ALTER TABLE ${
|
|
2230
|
+
yield* d.logInfo(`alter-column-type shadow ${a.table}.${a.column}: shadow populated`).pipe(d.annotateLogs({ scope: "voltro:migrate" })), yield* e.unsafe(`ALTER TABLE ${U(a.table)} RENAME COLUMN ${U(a.column)} TO ${U(s)}`), yield* e.unsafe(`ALTER TABLE ${U(a.table)} RENAME COLUMN ${U(o)} TO ${U(a.column)}`), yield* e.unsafe(`ALTER TABLE ${U(a.table)} DROP COLUMN ${U(s)}`);
|
|
2194
2231
|
break;
|
|
2195
2232
|
}
|
|
2196
2233
|
case "drop-foreign-key":
|
|
2197
2234
|
yield* e.onDialectOrElse({
|
|
2198
|
-
mysql: () => Q(e,
|
|
2235
|
+
mysql: () => Q(e, Hn(a), a.kind),
|
|
2199
2236
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2200
|
-
orElse: () => Q(e,
|
|
2237
|
+
orElse: () => Q(e, Vn(a), a.kind)
|
|
2201
2238
|
});
|
|
2202
2239
|
break;
|
|
2203
2240
|
case "add-check":
|
|
2204
2241
|
yield* e.onDialectOrElse({
|
|
2205
|
-
mysql: () => Q(e,
|
|
2242
|
+
mysql: () => Q(e, Un(a, W), a.kind),
|
|
2206
2243
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2207
|
-
orElse: () => Q(e,
|
|
2244
|
+
orElse: () => Q(e, Un(a, U), a.kind)
|
|
2208
2245
|
});
|
|
2209
2246
|
break;
|
|
2210
2247
|
case "drop-check":
|
|
2211
2248
|
yield* e.onDialectOrElse({
|
|
2212
|
-
mysql: () => Q(e,
|
|
2249
|
+
mysql: () => Q(e, Gn(a), a.kind),
|
|
2213
2250
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2214
|
-
orElse: () => Q(e,
|
|
2251
|
+
orElse: () => Q(e, Wn(a), a.kind)
|
|
2215
2252
|
});
|
|
2216
2253
|
break;
|
|
2217
2254
|
}
|
|
@@ -2220,7 +2257,7 @@ BEGIN
|
|
|
2220
2257
|
status: "applied",
|
|
2221
2258
|
durationMs: Number((process.hrtime.bigint() - r) / 1000000n)
|
|
2222
2259
|
};
|
|
2223
|
-
}),
|
|
2260
|
+
}), Yn = (e, t, n) => d.gen(function* () {
|
|
2224
2261
|
let r = t.operations.filter((e) => e.blocked);
|
|
2225
2262
|
if (r.length > 0) return yield* d.die(/* @__PURE__ */ Error(`applyPlan: refusing to execute — ${r.length} blocked operations. Run \`voltro db plan\` to see the fixes.`));
|
|
2226
2263
|
yield* w(e);
|
|
@@ -2233,9 +2270,9 @@ BEGIN
|
|
|
2233
2270
|
}), i = r ? t.operations.filter((e) => e.classification !== "online-required") : [], o = r ? t.operations.filter((e) => e.classification === "online-required") : t.operations;
|
|
2234
2271
|
i.length > 0 && (yield* e.withTransaction(d.gen(function* () {
|
|
2235
2272
|
let e = yield* p.SqlClient;
|
|
2236
|
-
for (let t of i) a.push(yield*
|
|
2273
|
+
for (let t of i) a.push(yield* Jn(e, t, n));
|
|
2237
2274
|
})));
|
|
2238
|
-
for (let t of o) a.push(yield*
|
|
2275
|
+
for (let t of o) a.push(yield* Jn(e, t, n));
|
|
2239
2276
|
} finally {
|
|
2240
2277
|
yield* T(e).pipe(d.orDie);
|
|
2241
2278
|
}
|
|
@@ -2263,13 +2300,19 @@ BEGIN
|
|
|
2263
2300
|
source: n.source,
|
|
2264
2301
|
...n.notes ? { notes: n.notes } : {}
|
|
2265
2302
|
};
|
|
2266
|
-
}),
|
|
2303
|
+
}), Xn = (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"), Zn = (e) => e`
|
|
2267
2304
|
SELECT fingerprint
|
|
2268
2305
|
FROM _voltro_migration_plans
|
|
2269
2306
|
ORDER BY ${e("appliedAt")} DESC
|
|
2270
2307
|
LIMIT 1
|
|
2271
|
-
`.pipe(d.map((e) => e.length > 0 ? e[0].fingerprint : void 0), d.catchAll(() => d.succeed(void 0))),
|
|
2272
|
-
|
|
2308
|
+
`.pipe(d.map((e) => e.length > 0 ? e[0].fingerprint : void 0), d.catchAll(() => d.succeed(void 0))), Qn = (e) => e.onDialectOrElse({
|
|
2309
|
+
pg: () => "postgres",
|
|
2310
|
+
mysql: () => "mysql",
|
|
2311
|
+
mssql: () => "mssql",
|
|
2312
|
+
sqlite: () => "sqlite",
|
|
2313
|
+
orElse: () => "sqlite"
|
|
2314
|
+
}), $n = (e, t) => d.gen(function* () {
|
|
2315
|
+
let n = M(P(t, Qn(e))), r = yield* Zn(e);
|
|
2273
2316
|
return r === n ? {
|
|
2274
2317
|
kind: "up-to-date",
|
|
2275
2318
|
fingerprint: n
|
|
@@ -2278,79 +2321,80 @@ BEGIN
|
|
|
2278
2321
|
expected: n,
|
|
2279
2322
|
...r === void 0 ? {} : { actual: r }
|
|
2280
2323
|
};
|
|
2281
|
-
}),
|
|
2324
|
+
}), er = [
|
|
2282
2325
|
"pgeagertest_",
|
|
2283
2326
|
"mig_e2e_",
|
|
2284
2327
|
"mig_test_",
|
|
2285
2328
|
"mysqleagertest_",
|
|
2286
2329
|
"mssqleagertest_",
|
|
2287
2330
|
"sqliteeagertest_"
|
|
2288
|
-
],
|
|
2331
|
+
], tr = (e) => er.some((t) => e.startsWith(t)), nr = (e, t) => d.gen(function* () {
|
|
2289
2332
|
if (process.env.VOLTRO_TEST_FIXTURE_GC === "off") return [];
|
|
2290
|
-
let n = t.filter((e) =>
|
|
2333
|
+
let n = t.filter((e) => tr(e.name)).map((e) => e.name);
|
|
2291
2334
|
if (n.length === 0) return [];
|
|
2292
2335
|
for (let t of n) yield* e.unsafe(`DROP TABLE IF EXISTS "${t}" CASCADE`).pipe(d.catchAll(() => d.void));
|
|
2293
2336
|
return n;
|
|
2294
|
-
}),
|
|
2337
|
+
}), rr = () => {
|
|
2295
2338
|
let e = (process.env.VOLTRO_DB_IGNORE_TABLES ?? "").split(",").map((e) => e.trim()).filter((e) => e.length > 0);
|
|
2296
2339
|
return e.length > 0 ? { ignoreTables: e } : {};
|
|
2297
|
-
},
|
|
2298
|
-
let r = t.filter((e) =>
|
|
2340
|
+
}, ir = (e, t, n) => d.gen(function* () {
|
|
2341
|
+
let r = Qn(e), i = t.filter((e) => !at(e.tableName));
|
|
2299
2342
|
if (process.env.VOLTRO_MIGRATE_FORCE !== "1") {
|
|
2300
|
-
let t =
|
|
2301
|
-
if ((yield*
|
|
2343
|
+
let t = M(P(i, r));
|
|
2344
|
+
if ((yield* Zn(e)) === t) return {
|
|
2302
2345
|
kind: "up-to-date",
|
|
2303
2346
|
fingerprint: t
|
|
2304
2347
|
};
|
|
2305
2348
|
}
|
|
2306
|
-
let
|
|
2307
|
-
|
|
2349
|
+
let a = yield* qt(e), o = yield* nr(e, a.tables);
|
|
2350
|
+
o.length > 0 && (yield* d.logInfo(`auto-migrate: reaped ${o.length} test-fixture leftover(s)`).pipe(d.annotateLogs({
|
|
2308
2351
|
scope: "voltro:migrate",
|
|
2309
|
-
count:
|
|
2310
|
-
})),
|
|
2311
|
-
let
|
|
2312
|
-
declared:
|
|
2313
|
-
live: { tables:
|
|
2314
|
-
|
|
2352
|
+
count: o.length
|
|
2353
|
+
})), a = yield* qt(e));
|
|
2354
|
+
let s = At({
|
|
2355
|
+
declared: i,
|
|
2356
|
+
live: { tables: a.tables.filter((e) => !at(e.name)) },
|
|
2357
|
+
dialect: r,
|
|
2358
|
+
...rr()
|
|
2315
2359
|
});
|
|
2316
|
-
if (
|
|
2317
|
-
let e =
|
|
2360
|
+
if (s.summary.blocked > 0) {
|
|
2361
|
+
let e = s.operations.filter((e) => e.blocked).every((e) => e.classification === "lossy");
|
|
2318
2362
|
if (process.env.VOLTRO_DESTRUCTIVE_OK !== "1" || !e) return {
|
|
2319
2363
|
kind: "refused-blocked",
|
|
2320
|
-
plan:
|
|
2364
|
+
plan: s
|
|
2321
2365
|
};
|
|
2322
2366
|
}
|
|
2323
|
-
return
|
|
2367
|
+
return s.operations.length === 0 ? {
|
|
2324
2368
|
kind: "up-to-date",
|
|
2325
|
-
fingerprint:
|
|
2369
|
+
fingerprint: s.toFingerprint
|
|
2326
2370
|
} : {
|
|
2327
2371
|
kind: "applied",
|
|
2328
|
-
applied: yield*
|
|
2372
|
+
applied: yield* Yn(e, s, {
|
|
2329
2373
|
declared: t,
|
|
2330
2374
|
appliedBy: n.appliedBy,
|
|
2331
2375
|
environment: n.environment === "prod" ? "dev" : n.environment,
|
|
2332
2376
|
source: "auto-diff"
|
|
2333
2377
|
}),
|
|
2334
|
-
plan:
|
|
2378
|
+
plan: s
|
|
2335
2379
|
};
|
|
2336
|
-
}),
|
|
2380
|
+
}), ar = (e, t, n) => process.env.VOLTRO_AUTO_MIGRATE === "0" ? d.succeed({
|
|
2337
2381
|
kind: "skipped",
|
|
2338
2382
|
reason: "VOLTRO_AUTO_MIGRATE=0"
|
|
2339
|
-
}) : n.environment === "prod" ?
|
|
2383
|
+
}) : n.environment === "prod" ? $n(e, t) : ir(e, t, n), or = (e, t) => {
|
|
2340
2384
|
switch (e.kind) {
|
|
2341
2385
|
case "skipped": return `auto-migrate: skipped (${e.reason})`;
|
|
2342
|
-
case "up-to-date": return `auto-migrate: schema up to date (${t}, fingerprint=${
|
|
2386
|
+
case "up-to-date": return `auto-migrate: schema up to date (${t}, fingerprint=${N(e.fingerprint)})`;
|
|
2343
2387
|
case "applied": {
|
|
2344
2388
|
let t = e.plan.summary;
|
|
2345
|
-
return `auto-migrate: applied ${e.plan.operations.length} op(s) in ${e.applied.durationMs}ms [safe=${t.safe} needs-default=${t.needsDefault} needs-backfill=${t.needsBackfill} rename=${t.needsRenameAnnotation} lossy=${t.lossy}] fingerprint=${
|
|
2389
|
+
return `auto-migrate: applied ${e.plan.operations.length} op(s) in ${e.applied.durationMs}ms [safe=${t.safe} needs-default=${t.needsDefault} needs-backfill=${t.needsBackfill} rename=${t.needsRenameAnnotation} lossy=${t.lossy}] fingerprint=${N(e.applied.fingerprint)}`;
|
|
2346
2390
|
}
|
|
2347
|
-
case "prod-mismatch": return `auto-migrate: SCHEMA FINGERPRINT MISMATCH — declared=${
|
|
2391
|
+
case "prod-mismatch": return `auto-migrate: SCHEMA FINGERPRINT MISMATCH — declared=${N(e.expected)}` + (e.actual ? ` live=${N(e.actual)}` : " live=<no _voltro_migration_plans row>") + ". Run `voltro db apply --plan plan.json` from the deploy pipeline before serving.";
|
|
2348
2392
|
case "refused-blocked": {
|
|
2349
|
-
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 === "add-column").length, i = t.filter((e) => e.op.kind === "drop-column").length, a = t.filter((e) => e.classification === "needs-rename-annotation").length, o = `auto-migrate: REFUSED — ${e.plan.summary.blocked} blocked operation(s):\n` +
|
|
2393
|
+
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 === "add-column").length, i = t.filter((e) => e.op.kind === "drop-column").length, a = t.filter((e) => e.classification === "needs-rename-annotation").length, o = `auto-migrate: REFUSED — ${e.plan.summary.blocked} blocked operation(s):\n` + Xn(e.plan), s = [""];
|
|
2350
2394
|
return n > 0 && s.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=${t.filter((e) => e.op.kind === "drop-table").map((e) => "table" in e.op ? e.op.table : "").filter(Boolean).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.", " → Add it to your declared set + chain `.dropped()` on it, OR", " write a file-based migration in `migrations/` that DROPs it, OR", " set `VOLTRO_DESTRUCTIVE_OK=1` for ONE `voltro dev` run (acknowledges data loss).", " 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`)."), r > 0 && s.push(`${r} 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."), i > 0 && s.push(`${i} column(s) are missing from your declared schema.`, " → If intentional: chain `.dropped()` on the column slot in the table declaration.", " → If a typo: restore the field. Data survives until you drop it."), a > 0 && s.push(`${a} 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."), s.push("", "See `voltro db plan` for the full machine-readable diff."), o + "\n" + s.join("\n");
|
|
2351
2395
|
}
|
|
2352
2396
|
}
|
|
2353
|
-
},
|
|
2397
|
+
}, sr = /* @__PURE__ */ new Set([
|
|
2354
2398
|
"node_modules",
|
|
2355
2399
|
"dist",
|
|
2356
2400
|
"build",
|
|
@@ -2359,11 +2403,11 @@ BEGIN
|
|
|
2359
2403
|
".next",
|
|
2360
2404
|
".git",
|
|
2361
2405
|
".framework"
|
|
2362
|
-
]),
|
|
2406
|
+
]), cr = async (e) => {
|
|
2363
2407
|
let t = [], n = async (e) => {
|
|
2364
2408
|
let r = await h.readdir(e, { withFileTypes: !0 }).catch(() => []);
|
|
2365
2409
|
for (let i of r) {
|
|
2366
|
-
if (
|
|
2410
|
+
if (sr.has(i.name)) continue;
|
|
2367
2411
|
let r = g(e, i.name);
|
|
2368
2412
|
i.isDirectory() ? await n(r) : i.isFile() && u.test(i.name) && t.push(r);
|
|
2369
2413
|
}
|
|
@@ -2372,7 +2416,7 @@ BEGIN
|
|
|
2372
2416
|
let n = e.split("/").pop() ?? e, r = t.split("/").pop() ?? t;
|
|
2373
2417
|
return n.localeCompare(r);
|
|
2374
2418
|
});
|
|
2375
|
-
},
|
|
2419
|
+
}, lr = async (e) => {
|
|
2376
2420
|
let t = [];
|
|
2377
2421
|
for (let n of e) {
|
|
2378
2422
|
let e = (await import(ee(n).href)).default;
|
|
@@ -2386,11 +2430,11 @@ BEGIN
|
|
|
2386
2430
|
});
|
|
2387
2431
|
}
|
|
2388
2432
|
return t;
|
|
2389
|
-
},
|
|
2433
|
+
}, ur = (e) => e`
|
|
2390
2434
|
SELECT ${e("id")}
|
|
2391
2435
|
FROM ${e("_voltro_migration_plans")}
|
|
2392
2436
|
WHERE ${e("source")} = 'file'
|
|
2393
|
-
`.pipe(d.map((e) => e.map((e) => e.id)), d.catchAll(() => d.succeed([]))),
|
|
2437
|
+
`.pipe(d.map((e) => e.map((e) => e.id)), d.catchAll(() => d.succeed([]))), dr = (e, t, n, r) => d.gen(function* () {
|
|
2394
2438
|
let i = Date.now(), a = (/* @__PURE__ */ new Date()).toISOString(), o = {
|
|
2395
2439
|
sql: e,
|
|
2396
2440
|
log: {
|
|
@@ -2423,9 +2467,9 @@ BEGIN
|
|
|
2423
2467
|
${r}, ${n}, ${"file"},
|
|
2424
2468
|
${c}, ${a}, ${t.migration.description})
|
|
2425
2469
|
`, { durationMs: c };
|
|
2426
|
-
}),
|
|
2470
|
+
}), fr = (e, t) => d.gen(function* () {
|
|
2427
2471
|
let n = yield* d.tryPromise({
|
|
2428
|
-
try: () =>
|
|
2472
|
+
try: () => cr(g(t.projectRoot, "migrations")),
|
|
2429
2473
|
catch: (e) => e
|
|
2430
2474
|
});
|
|
2431
2475
|
if (n.length === 0) return {
|
|
@@ -2433,14 +2477,14 @@ BEGIN
|
|
|
2433
2477
|
skipped: []
|
|
2434
2478
|
};
|
|
2435
2479
|
let r = yield* d.tryPromise({
|
|
2436
|
-
try: () =>
|
|
2480
|
+
try: () => lr(n),
|
|
2437
2481
|
catch: (e) => e
|
|
2438
2482
|
});
|
|
2439
2483
|
if (r.length === 0) return {
|
|
2440
2484
|
applied: [],
|
|
2441
2485
|
skipped: []
|
|
2442
2486
|
};
|
|
2443
|
-
let i = new Set(yield*
|
|
2487
|
+
let i = new Set(yield* ur(e)), a = r.filter((e) => !i.has(e.migration.id)), o = r.filter((e) => i.has(e.migration.id)).map((e) => e.migration.id);
|
|
2444
2488
|
if (a.length === 0) return {
|
|
2445
2489
|
applied: [],
|
|
2446
2490
|
skipped: o
|
|
@@ -2454,7 +2498,7 @@ BEGIN
|
|
|
2454
2498
|
id: n.migration.id,
|
|
2455
2499
|
file: n.file
|
|
2456
2500
|
}));
|
|
2457
|
-
let { durationMs: r } = yield*
|
|
2501
|
+
let { durationMs: r } = yield* dr(e, n, t.env, t.appliedBy);
|
|
2458
2502
|
s.push({
|
|
2459
2503
|
id: n.migration.id,
|
|
2460
2504
|
durationMs: r
|
|
@@ -2471,18 +2515,18 @@ BEGIN
|
|
|
2471
2515
|
applied: s,
|
|
2472
2516
|
skipped: o
|
|
2473
2517
|
};
|
|
2474
|
-
}),
|
|
2518
|
+
}), pr = (e, t) => e`
|
|
2475
2519
|
SELECT ${e("id")}
|
|
2476
2520
|
FROM ${e("_voltro_migration_plans")}
|
|
2477
2521
|
WHERE ${e("id")} = ${t} AND ${e("source")} = 'file'
|
|
2478
2522
|
LIMIT 1
|
|
2479
|
-
`,
|
|
2480
|
-
if (!(yield*
|
|
2523
|
+
`, mr = (e, t) => d.gen(function* () {
|
|
2524
|
+
if (!(yield* pr(e, t.id))[0]) return yield* d.fail(/* @__PURE__ */ Error(`rollback: ${t.id} not found in _voltro_migration_plans (file source)`));
|
|
2481
2525
|
let n = yield* d.tryPromise({
|
|
2482
|
-
try: () =>
|
|
2526
|
+
try: () => cr(g(t.projectRoot, "migrations")),
|
|
2483
2527
|
catch: (e) => e
|
|
2484
2528
|
}), r = (yield* d.tryPromise({
|
|
2485
|
-
try: () =>
|
|
2529
|
+
try: () => lr(n),
|
|
2486
2530
|
catch: (e) => e
|
|
2487
2531
|
})).find((e) => e.migration.id === t.id);
|
|
2488
2532
|
if (!r) return yield* d.fail(/* @__PURE__ */ Error(`rollback: file for migration ${t.id} not found on disk under ${t.projectRoot}/migrations/`));
|
|
@@ -2515,7 +2559,7 @@ BEGIN
|
|
|
2515
2559
|
} finally {
|
|
2516
2560
|
yield* T(e).pipe(d.orDie);
|
|
2517
2561
|
}
|
|
2518
|
-
}),
|
|
2562
|
+
}), hr = (e) => d.gen(function* () {
|
|
2519
2563
|
let t = yield* p.SqlClient, n = yield* t`
|
|
2520
2564
|
SELECT id, fingerprint, appliedAt FROM _voltro_migration_plans
|
|
2521
2565
|
WHERE source = 'auto-diff'
|
|
@@ -2560,10 +2604,10 @@ BEGIN
|
|
|
2560
2604
|
snapshotFingerprint: e.fingerprint,
|
|
2561
2605
|
snapshotId: i
|
|
2562
2606
|
};
|
|
2563
|
-
}),
|
|
2607
|
+
}), gr = (e, ...t) => ({
|
|
2564
2608
|
_tag: "RawSqlFragment",
|
|
2565
2609
|
strings: [...e],
|
|
2566
2610
|
values: [...t]
|
|
2567
|
-
}),
|
|
2611
|
+
}), _r = (e) => typeof e == "object" && !!e && e._tag === "RawSqlFragment";
|
|
2568
2612
|
//#endregion
|
|
2569
|
-
export { u as FILE_MIGRATION_PATTERN,
|
|
2613
|
+
export { u as FILE_MIGRATION_PATTERN, C as VOLTRO_MIGRATION_LOCK_KEY, ut as _internalCmp, w as acquireMigrationLock, Ke as applyNamespacedSchema, Yn as applyPlan, Be as applySchema, Lt as chunkTables, P as declaredSnapshot, ve as defaultClause, O as defaultJsonClause, or as describeOutcome, Yt as emitDropColumnDdl, Xt as emitDropColumnDdlMysql, ze as emitFrameworkBootstrapSql, Le as emitNamespaceProvisionDdl, Re as emitNamespacedSchemaSql, j as emitSchemaSql, M as fingerprintSchema, rr as ignoreTablesFromEnv, qt as introspectSchema, s as isFileMigration, _r as isRawSqlFragment, Mt as mapPgType, l as migration, k as numericIdSql, jt as parseEnumCheck, At as planMigrations, qe as provisionTenantNamespace, T as releaseMigrationLock, sn as renderColumnMysql, rn as renderColumnPg, mr as rollbackFileBasedMigration, fr as runFileBasedMigrations, Je as runFrameworkBootstrap, Ge as runMigrate, ar as runPlannedMigrations, N as shortFingerprint, gr as sql, D as sqlType, hr as squashMigrationPlans, ge as withMigrationLock };
|