@voltro/database 0.20.2 → 0.22.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 +398 -0
- package/THIRD-PARTY-NOTICES.md +1 -1
- package/dist/{fileBased-Dfuv6JWP.js → fileBased-CDnutVVk.js} +19 -0
- package/dist/index.d.ts +121 -1
- package/dist/index.js +488 -444
- package/dist/sql.d.ts +96 -30
- package/dist/sql.js +600 -450
- package/package.json +4 -4
package/dist/sql.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { B as e, W as t, a as n, c as r, i, lt as a, n as o, r as s, rt as c, t as l, z as u } from "./fileBased-
|
|
1
|
+
import { B as e, W as t, a as n, c as r, i, lt as a, n as o, r as s, rt as c, t as l, z as u } from "./fileBased-CDnutVVk.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,7 +39,7 @@ 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) => e.unique === !0 && typeof e.where == "string" && e.where.length > 0,
|
|
42
|
+
}, v = (e) => e.unique === !0 && typeof e.where == "string" && e.where.length > 0, y = (e) => e.replace(/"/g, "`"), b = (e) => typeof e == "string" ? e : e.name ?? String(e), te = (e, t) => `_ua_${t}_${e}`.slice(0, 64), x = (e, t) => {
|
|
43
43
|
if (t !== "mysql" && t !== "mariadb" || !e.appliedIndexes.some(v)) return e;
|
|
44
44
|
let n = { ...e.fields }, r = [], i = [];
|
|
45
45
|
for (let t of e.appliedIndexes) {
|
|
@@ -47,11 +47,11 @@ var _ = (e, t, n, r = 400) => {
|
|
|
47
47
|
r.push(t);
|
|
48
48
|
continue;
|
|
49
49
|
}
|
|
50
|
-
let a =
|
|
50
|
+
let a = y(t.where), o = [];
|
|
51
51
|
for (let r of t.fields) {
|
|
52
|
-
let i =
|
|
52
|
+
let i = b(r);
|
|
53
53
|
if (!(i in e.fields)) throw Error(`@voltro/migrate: uniqueActive '${t.name}' on '${e.tableName}' references unknown column '${i}'.`);
|
|
54
|
-
let s =
|
|
54
|
+
let s = te(t.name, i);
|
|
55
55
|
o.push(s), n[s] = {
|
|
56
56
|
type: "text",
|
|
57
57
|
nullable: !0,
|
|
@@ -74,54 +74,54 @@ var _ = (e, t, n, r = 400) => {
|
|
|
74
74
|
appliedIndexes: r,
|
|
75
75
|
appliedUniques: [...e.appliedUniques ?? [], ...i]
|
|
76
76
|
};
|
|
77
|
-
},
|
|
77
|
+
}, S = (e, t) => `${e}::${t}`, ne = (e, t) => {
|
|
78
78
|
let n = /* @__PURE__ */ new Set(), r = /* @__PURE__ */ new Set(), i = /* @__PURE__ */ new Set(), a = (e) => {
|
|
79
79
|
n.add(e);
|
|
80
80
|
let o = [...t(e)].filter((t) => t.target !== e).sort((e, t) => e.column.localeCompare(t.column));
|
|
81
|
-
for (let t of o) n.has(t.target) ? i.add(
|
|
81
|
+
for (let t of o) n.has(t.target) ? i.add(S(e, t.column)) : r.has(t.target) || a(t.target);
|
|
82
82
|
n.delete(e), r.add(e);
|
|
83
83
|
};
|
|
84
84
|
for (let t of [...e].sort()) r.has(t) || a(t);
|
|
85
85
|
return i;
|
|
86
|
-
},
|
|
86
|
+
}, re = 6322741009312437n, ie = 250, ae = () => {
|
|
87
87
|
let e = Number(process.env.VOLTRO_MIGRATION_LOCK_TIMEOUT_MS);
|
|
88
88
|
return Number.isFinite(e) && e > 0 ? e : 3e4;
|
|
89
|
-
},
|
|
90
|
-
let t =
|
|
89
|
+
}, oe = (e) => d.gen(function* () {
|
|
90
|
+
let t = ae(), n = Date.now();
|
|
91
91
|
for (;;) {
|
|
92
92
|
if ((yield* e`
|
|
93
93
|
SELECT pg_try_advisory_lock(${"6322741009312437"}::bigint) AS got`)[0]?.got) return;
|
|
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(`${
|
|
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(`${ie} millis`);
|
|
95
95
|
}
|
|
96
|
-
}),
|
|
97
|
-
yield* e`SELECT pg_advisory_unlock(${
|
|
98
|
-
}),
|
|
96
|
+
}), se = (e) => d.gen(function* () {
|
|
97
|
+
yield* e`SELECT pg_advisory_unlock(${re.toString()}::bigint)`;
|
|
98
|
+
}), ce = `voltro_migration_${re.toString(36)}`, le = 30, ue = (e) => d.gen(function* () {
|
|
99
99
|
(yield* e`
|
|
100
|
-
SELECT GET_LOCK(${
|
|
101
|
-
}),
|
|
102
|
-
yield* e`SELECT RELEASE_LOCK(${
|
|
103
|
-
}),
|
|
100
|
+
SELECT GET_LOCK(${ce}, ${le}) AS got`)[0]?.got !== 1 && (yield* d.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${ce}' within ${le}s (another migration is in progress, or a prior one left it held).`)));
|
|
101
|
+
}), de = (e) => d.gen(function* () {
|
|
102
|
+
yield* e`SELECT RELEASE_LOCK(${ce})`;
|
|
103
|
+
}), fe = `voltro_migration_${re.toString(36)}`, pe = 3e4, me = (e) => d.gen(function* () {
|
|
104
104
|
let t = yield* e`
|
|
105
105
|
DECLARE @res int;
|
|
106
|
-
EXEC @res = sp_getapplock @Resource = ${
|
|
107
|
-
@LockOwner = 'Session', @LockTimeout = ${
|
|
106
|
+
EXEC @res = sp_getapplock @Resource = ${fe}, @LockMode = 'Exclusive',
|
|
107
|
+
@LockOwner = 'Session', @LockTimeout = ${pe};
|
|
108
108
|
SELECT @res AS res`;
|
|
109
|
-
(t[0]?.res ?? -999) < 0 && (yield* d.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${
|
|
110
|
-
}),
|
|
111
|
-
yield* e`EXEC sp_releaseapplock @Resource = ${
|
|
112
|
-
}),
|
|
113
|
-
mysql: () => le(e),
|
|
114
|
-
mssql: () => pe(e),
|
|
115
|
-
sqlite: () => he,
|
|
116
|
-
orElse: () => ae(e)
|
|
117
|
-
}), T = (e) => e.onDialectOrElse({
|
|
109
|
+
(t[0]?.res ?? -999) < 0 && (yield* d.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${fe}' (sp_getapplock returned ${t[0]?.res ?? "no row"}; another migration is in progress).`)));
|
|
110
|
+
}), he = (e) => d.gen(function* () {
|
|
111
|
+
yield* e`EXEC sp_releaseapplock @Resource = ${fe}, @LockOwner = 'Session'`;
|
|
112
|
+
}), ge = d.void, C = (e) => e.onDialectOrElse({
|
|
118
113
|
mysql: () => ue(e),
|
|
119
114
|
mssql: () => me(e),
|
|
120
|
-
sqlite: () =>
|
|
115
|
+
sqlite: () => ge,
|
|
121
116
|
orElse: () => oe(e)
|
|
122
|
-
}),
|
|
123
|
-
|
|
124
|
-
|
|
117
|
+
}), w = (e) => e.onDialectOrElse({
|
|
118
|
+
mysql: () => de(e),
|
|
119
|
+
mssql: () => he(e),
|
|
120
|
+
sqlite: () => ge,
|
|
121
|
+
orElse: () => se(e)
|
|
122
|
+
}), _e = (e, t) => d.acquireUseRelease(C(e), () => t, () => w(e).pipe(d.orDie)), ve = f({ scope: "voltro:migrate" }), T = (e) => {
|
|
123
|
+
ve.warn(e.replace(/^\[voltro:migrate\]\s*/, ""));
|
|
124
|
+
}, E = (e, t) => {
|
|
125
125
|
let n = e.type;
|
|
126
126
|
if (e.spatial) {
|
|
127
127
|
if (t === "postgres") return `${e.spatial.kind}(${e.spatial.geomKind},${e.spatial.srid})`;
|
|
@@ -132,7 +132,7 @@ var _ = (e, t, n, r = 400) => {
|
|
|
132
132
|
return e.rawDdl;
|
|
133
133
|
}
|
|
134
134
|
if (n === "array" && e.arrayElement) {
|
|
135
|
-
if (t === "postgres") return `${
|
|
135
|
+
if (t === "postgres") return `${E({
|
|
136
136
|
...e,
|
|
137
137
|
type: e.arrayElement,
|
|
138
138
|
arrayElement: void 0
|
|
@@ -232,22 +232,22 @@ var _ = (e, t, n, r = 400) => {
|
|
|
232
232
|
case "array": return "TEXT[]";
|
|
233
233
|
case "interval": return "INTERVAL";
|
|
234
234
|
}
|
|
235
|
-
},
|
|
235
|
+
}, ye = (e, t) => {
|
|
236
236
|
if (!e.hasDefault || e.defaultFactory !== void 0) return null;
|
|
237
237
|
let n = e.defaultValue;
|
|
238
|
-
return n === "now" ? u(t) ? "DEFAULT CURRENT_TIMESTAMP" : t === "mssql" ? "DEFAULT SYSUTCDATETIME()" : t === "mysql" || t === "mariadb" ? "DEFAULT CURRENT_TIMESTAMP(6)" : "DEFAULT now()" : typeof n == "boolean" ? t === "postgres" ? `DEFAULT ${n}` : `DEFAULT ${+!!n}` : typeof n == "number" ? `DEFAULT ${n}` : typeof n == "string" ? `DEFAULT '${n.replace(/'/g, "''")}'` : Array.isArray(n) ?
|
|
239
|
-
},
|
|
240
|
-
if (n !== "postgres" || t.type !== "array" || t.arrayElement === void 0) return
|
|
241
|
-
let r =
|
|
238
|
+
return n === "now" ? u(t) ? "DEFAULT CURRENT_TIMESTAMP" : t === "mssql" ? "DEFAULT SYSUTCDATETIME()" : t === "mysql" || t === "mariadb" ? "DEFAULT CURRENT_TIMESTAMP(6)" : "DEFAULT now()" : typeof n == "boolean" ? t === "postgres" ? `DEFAULT ${n}` : `DEFAULT ${+!!n}` : typeof n == "number" ? `DEFAULT ${n}` : typeof n == "string" ? `DEFAULT '${n.replace(/'/g, "''")}'` : Array.isArray(n) ? be(n, e, t) : typeof n == "object" && n ? D(n, t) : null;
|
|
239
|
+
}, be = (e, t, n) => {
|
|
240
|
+
if (n !== "postgres" || t.type !== "array" || t.arrayElement === void 0) return D(e, n);
|
|
241
|
+
let r = E({
|
|
242
242
|
...t,
|
|
243
243
|
type: t.arrayElement,
|
|
244
244
|
arrayElement: void 0
|
|
245
245
|
}, n);
|
|
246
246
|
return `DEFAULT '{${e.map((e) => typeof e == "number" || typeof e == "boolean" ? String(e) : `"${String(e).replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"`).join(",").replace(/'/g, "''")}}'::${r}[]`;
|
|
247
|
-
},
|
|
247
|
+
}, D = (e, t) => {
|
|
248
248
|
let n = JSON.stringify(e).replace(/'/g, "''");
|
|
249
249
|
return t === "postgres" ? `DEFAULT '${n}'::jsonb` : t === "mysql" || t === "mariadb" ? `DEFAULT (CAST('${n}' AS JSON))` : `DEFAULT '${n}'`;
|
|
250
|
-
},
|
|
250
|
+
}, O = (e, t) => {
|
|
251
251
|
switch (t) {
|
|
252
252
|
case "postgres": return `"${e}" BIGSERIAL PRIMARY KEY`;
|
|
253
253
|
case "mysql":
|
|
@@ -256,7 +256,7 @@ var _ = (e, t, n, r = 400) => {
|
|
|
256
256
|
case "sqlite": return `"${e}" INTEGER PRIMARY KEY AUTOINCREMENT`;
|
|
257
257
|
case "turso": return `"${e}" INTEGER PRIMARY KEY`;
|
|
258
258
|
}
|
|
259
|
-
},
|
|
259
|
+
}, k = (e, t) => {
|
|
260
260
|
if (e === "restrict" && t === "mssql") return "NO ACTION";
|
|
261
261
|
switch (e) {
|
|
262
262
|
case "cascade": return "CASCADE";
|
|
@@ -269,33 +269,33 @@ var _ = (e, t, n, r = 400) => {
|
|
|
269
269
|
if (r !== "mysql" && r !== "mariadb") return i;
|
|
270
270
|
let a = n[t];
|
|
271
271
|
if (!a) return i;
|
|
272
|
-
let o =
|
|
272
|
+
let o = E(a, r).toUpperCase();
|
|
273
273
|
return o.endsWith("TEXT") || o.endsWith("BLOB") ? `${i}(${Se})` : i;
|
|
274
274
|
}, we = (e, t) => {
|
|
275
275
|
if (!e.generatedAs) return null;
|
|
276
276
|
let { expr: n, stored: r } = e.generatedAs;
|
|
277
|
-
if (t === "postgres") return r ||
|
|
277
|
+
if (t === "postgres") return r || T("[voltro:migrate] generated column requested as VIRTUAL but postgres only supports STORED — promoting"), `GENERATED ALWAYS AS (${n}) STORED`;
|
|
278
278
|
if (t === "mysql" || t === "mariadb") return `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
|
|
279
279
|
if (t === "mssql") return `AS (${n})${r ? " PERSISTED" : ""}`;
|
|
280
280
|
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.");
|
|
281
281
|
return `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
|
|
282
282
|
}, Te = (t, n, r, i, a = !1, o = !1) => {
|
|
283
|
-
if (n.type === "id" && n.idScheme?.kind === "numeric") return
|
|
284
|
-
let s = r === "mssql" && n.type === "text" && !n.generatedAs && n.maxLength === void 0 && i?.has(t) ? "NVARCHAR(450)" :
|
|
283
|
+
if (n.type === "id" && n.idScheme?.kind === "numeric") return O(t, r);
|
|
284
|
+
let s = r === "mssql" && n.type === "text" && !n.generatedAs && n.maxLength === void 0 && i?.has(t) ? "NVARCHAR(450)" : E(n, r), c = [e(t, r), s];
|
|
285
285
|
n.type === "id" && !o && c.push("PRIMARY KEY");
|
|
286
286
|
let l = we(n, r);
|
|
287
287
|
if (l) c.push(l);
|
|
288
288
|
else {
|
|
289
289
|
n.nullable || c.push("NOT NULL"), n.unique && n.type !== "id" && c.push("UNIQUE");
|
|
290
|
-
let e =
|
|
290
|
+
let e = ye(n, r);
|
|
291
291
|
e && c.push(e);
|
|
292
292
|
}
|
|
293
293
|
if (n.type === "reference" && n.references && !a) {
|
|
294
294
|
let t = n.references();
|
|
295
295
|
c.push(`REFERENCES ${e(t.tableName, r)} (${e("id", r)})`);
|
|
296
|
-
let i =
|
|
296
|
+
let i = k(n.onDelete ?? "restrict", r);
|
|
297
297
|
c.push(`ON DELETE ${i}`);
|
|
298
|
-
let a =
|
|
298
|
+
let a = k(n.refOnUpdate ?? "noAction", r);
|
|
299
299
|
a !== "NO ACTION" && c.push(`ON UPDATE ${a}`);
|
|
300
300
|
}
|
|
301
301
|
if (n.oneOf && n.oneOf.length > 0) {
|
|
@@ -348,21 +348,21 @@ var _ = (e, t, n, r = 400) => {
|
|
|
348
348
|
using: " USING GIST",
|
|
349
349
|
withSuffix: "",
|
|
350
350
|
skip: !1
|
|
351
|
-
} : (
|
|
351
|
+
} : (T(`[voltro:migrate] index '${e}' on '${n}': ${r} doesn't support GiST — falling back to btree. Spatial queries on this column will fall back to sequential scan.`), o);
|
|
352
352
|
if (i === "gin") return r === "postgres" ? {
|
|
353
353
|
using: " USING GIN",
|
|
354
354
|
withSuffix: "",
|
|
355
355
|
skip: !1
|
|
356
|
-
} : r === "mysql" || r === "mariadb" ? (
|
|
356
|
+
} : r === "mysql" || r === "mariadb" ? (T(`[voltro:migrate] gin index '${e}' on '${n}': ${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(...).`), {
|
|
357
357
|
using: "",
|
|
358
358
|
withSuffix: "",
|
|
359
359
|
skip: !0
|
|
360
|
-
}) : (
|
|
360
|
+
}) : (T(`[voltro:migrate] gin index '${e}' on '${n}': ${r} has no GIN access method — falling back to btree. Containment/membership queries won't use this index efficiently.`), o);
|
|
361
361
|
if (i === "brin") return r === "postgres" ? {
|
|
362
362
|
using: " USING BRIN",
|
|
363
363
|
withSuffix: "",
|
|
364
364
|
skip: !1
|
|
365
|
-
} : (
|
|
365
|
+
} : (T(`[voltro:migrate] brin index '${e}' on '${n}': ${r} has no BRIN access method — falling back to btree (larger on disk, but the range scan still works).`), o);
|
|
366
366
|
if (i === "hnsw") {
|
|
367
367
|
if (r === "postgres") {
|
|
368
368
|
let e = a?.hnsw?.m ?? 16, n = a?.hnsw?.efConstruction ?? 64, r = a?.hnsw?.opclass ?? t(a?.hnsw?.distance);
|
|
@@ -373,7 +373,7 @@ var _ = (e, t, n, r = 400) => {
|
|
|
373
373
|
skip: !1
|
|
374
374
|
};
|
|
375
375
|
}
|
|
376
|
-
return
|
|
376
|
+
return T(`[voltro:migrate] hnsw index '${e}' on '${n}': ${r} has no pgvector / HNSW access method — skipping. Nearest-neighbour queries on this column fall back to a sequential scan.`), {
|
|
377
377
|
using: "",
|
|
378
378
|
withSuffix: "",
|
|
379
379
|
skip: !0
|
|
@@ -406,15 +406,15 @@ var _ = (e, t, n, r = 400) => {
|
|
|
406
406
|
let i = t.columns.map((t) => e(t, r)).join(", ");
|
|
407
407
|
o.push(`CREATE FULLTEXT INDEX ${e(t.name, r)} ON ${e(n.tableName, r)} (${i});`);
|
|
408
408
|
} else if (r === "turso") throw Error(`@voltro/sql-turso: full-text index '${t.name}' on '${n.tableName}' is not supported — Turso's MVCC mode has no FTS5 virtual tables. Drop .fullTextIndex(), or use the 'sqlite' / 'postgres' dialect for this table.`);
|
|
409
|
-
else r === "sqlite" ? o.push(...De(n.tableName, t, r)) :
|
|
409
|
+
else r === "sqlite" ? o.push(...De(n.tableName, t, r)) : T(`[voltro:migrate] full-text index '${t.name}' on '${n.tableName}': ${r} uses a ranked LIKE search at query time (no native FTS catalog required).`);
|
|
410
410
|
for (let e of n.appliedIndexes) {
|
|
411
411
|
if ((r === "mariadb" || r === "mssql") && e.fields.some((e) => typeof e != "string" && "jsonPath" in e)) {
|
|
412
|
-
|
|
412
|
+
T(`[voltro:migrate] json-path index '${e.name}' on '${n.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(...).`);
|
|
413
413
|
continue;
|
|
414
414
|
}
|
|
415
415
|
if (e.unique && e.where !== void 0 && e.where.length > 0 && (r === "mysql" || r === "mariadb")) throw Error(`@voltro/migrate: uniqueActive index '${e.name}' on '${n.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.`);
|
|
416
416
|
let t = "";
|
|
417
|
-
e.where !== void 0 && e.where.length > 0 && (r === "mysql" || r === "mariadb" ?
|
|
417
|
+
e.where !== void 0 && e.where.length > 0 && (r === "mysql" || r === "mariadb" ? T(`[voltro:migrate] partial index '${e.name}' on '${n.tableName}': ${r} does not support WHERE clauses on indexes — emitting a full index`) : t = ` WHERE ${e.where}`);
|
|
418
418
|
let i = d(e.name, n.tableName, e.fields, e.kind, e.kindOptions, t, e.unique === !0);
|
|
419
419
|
i !== "" && o.push(i), e.fields.every((e) => typeof e == "string") && s.add(c(e.fields));
|
|
420
420
|
}
|
|
@@ -431,7 +431,7 @@ CREATE TRIGGER framework_changes_${e.tableName}
|
|
|
431
431
|
AFTER INSERT OR UPDATE OR DELETE ON "${e.tableName}"
|
|
432
432
|
FOR EACH ROW EXECUTE FUNCTION framework_notify_change();
|
|
433
433
|
`.trim(), je = (e) => e.some((e) => Object.values(e.fields).some((e) => e.type === "vector")), Me = (e) => e.some((e) => Object.values(e.fields).some((e) => e.spatial !== void 0)), Ne = (e) => {
|
|
434
|
-
let t = new Map(e.map((e) => [e.tableName, e])), n =
|
|
434
|
+
let t = new Map(e.map((e) => [e.tableName, e])), n = ne(e.map((e) => e.tableName), (e) => {
|
|
435
435
|
let n = t.get(e);
|
|
436
436
|
return n ? Object.entries(n.fields).flatMap(([e, n]) => {
|
|
437
437
|
if (n.type !== "reference" || !n.references) return [];
|
|
@@ -442,7 +442,7 @@ FOR EACH ROW EXECUTE FUNCTION framework_notify_change();
|
|
|
442
442
|
}] : [];
|
|
443
443
|
}) : [];
|
|
444
444
|
}), r = [];
|
|
445
|
-
for (let t of e) for (let [e, i] of Object.entries(t.fields)) i.type !== "reference" || !i.references || n.has(
|
|
445
|
+
for (let t of e) for (let [e, i] of Object.entries(t.fields)) i.type !== "reference" || !i.references || n.has(S(t.tableName, e)) && r.push({
|
|
446
446
|
table: t.tableName,
|
|
447
447
|
column: e,
|
|
448
448
|
targetTable: i.references().tableName,
|
|
@@ -453,7 +453,7 @@ FOR EACH ROW EXECUTE FUNCTION framework_notify_change();
|
|
|
453
453
|
if (!(i.has(e.tableName) || a.has(e.tableName))) {
|
|
454
454
|
a.add(e.tableName);
|
|
455
455
|
for (let [r, i] of Object.entries(e.fields)) {
|
|
456
|
-
if (i.type !== "reference" || !i.references || n.has(
|
|
456
|
+
if (i.type !== "reference" || !i.references || n.has(S(e.tableName, r))) continue;
|
|
457
457
|
let a = i.references();
|
|
458
458
|
if (a.tableName === e.tableName) continue;
|
|
459
459
|
let o = t.get(a.tableName);
|
|
@@ -468,7 +468,7 @@ FOR EACH ROW EXECUTE FUNCTION framework_notify_change();
|
|
|
468
468
|
cyclic: r
|
|
469
469
|
};
|
|
470
470
|
}, Pe = (t, n, r = null) => {
|
|
471
|
-
let i = (t) => r ? `${e(r, n)}.${e(t, n)}` : e(t, n), a = `${t.table}_${t.column}_fkey`, o =
|
|
471
|
+
let i = (t) => r ? `${e(r, n)}.${e(t, n)}` : e(t, n), a = `${t.table}_${t.column}_fkey`, o = k(t.onDelete, n), s = k(t.onUpdate, n), c = ` ON DELETE ${o}${s === "NO ACTION" ? "" : ` ON UPDATE ${s}`}`, l = (r) => `ADD CONSTRAINT ${e(a, n)} FOREIGN KEY ${r ? "IF NOT EXISTS " : ""}(${e(t.column, n)}) REFERENCES ${i(t.targetTable)} (${e("id", n)})${c}`;
|
|
472
472
|
switch (n) {
|
|
473
473
|
case "postgres": return [
|
|
474
474
|
"DO $$ BEGIN",
|
|
@@ -528,7 +528,7 @@ BEGIN
|
|
|
528
528
|
views: r
|
|
529
529
|
};
|
|
530
530
|
}, A = (e, t) => {
|
|
531
|
-
let { tables: n, views: i } = Re(e), { sorted: a, cyclic: o } = Ne(n.map((e) =>
|
|
531
|
+
let { tables: n, views: i } = Re(e), { sorted: a, cyclic: o } = Ne(n.map((e) => x(e, t))), s = Fe(o, t), c = [];
|
|
532
532
|
t === "postgres" && je(a) && c.push("CREATE EXTENSION IF NOT EXISTS vector;"), t === "postgres" && Me(a) && c.push("CREATE EXTENSION IF NOT EXISTS postgis;");
|
|
533
533
|
let l = Le(a, t);
|
|
534
534
|
l && c.push(l);
|
|
@@ -569,43 +569,29 @@ BEGIN
|
|
|
569
569
|
t && d.push(t);
|
|
570
570
|
}
|
|
571
571
|
return d.join("\n\n") + "\n";
|
|
572
|
-
}, Ve = (
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
s
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
for (let e of r)
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
return `ALTER TABLE ${e(t.tableName, n)} ADD COLUMN IF NOT EXISTS ${o};`;
|
|
586
|
-
});
|
|
587
|
-
o.push(i.join("\n"));
|
|
588
|
-
}
|
|
589
|
-
for (let e of r) {
|
|
590
|
-
let t = Oe(e, n);
|
|
591
|
-
t && o.push(t);
|
|
592
|
-
}
|
|
593
|
-
let l = r.filter((e) => e.isReactive);
|
|
594
|
-
if (l.length > 0) {
|
|
595
|
-
o.push(ke);
|
|
596
|
-
for (let e of l) o.push(Ae(e));
|
|
597
|
-
}
|
|
598
|
-
return o.join("\n\n") + "\n";
|
|
572
|
+
}, Ve = (e, t) => {
|
|
573
|
+
let { sorted: n, cyclic: r } = Ne(e), i = Fe(r, t), a = [], o = Le(n, t);
|
|
574
|
+
o && a.push(o);
|
|
575
|
+
let s = Ie(n, t);
|
|
576
|
+
s && a.push(s);
|
|
577
|
+
for (let e of n) a.push(Ee(e, t, null, i.get(e.tableName)));
|
|
578
|
+
for (let e of r) a.push(Pe(e, t));
|
|
579
|
+
let c = n.filter((e) => e.isReactive);
|
|
580
|
+
if (c.length > 0) {
|
|
581
|
+
a.push(ke);
|
|
582
|
+
for (let e of c) a.push(Ae(e));
|
|
583
|
+
}
|
|
584
|
+
return a.join("\n\n") + "\n";
|
|
599
585
|
}, He = (e, t = "postgres") => d.gen(function* () {
|
|
600
586
|
let n = yield* p.SqlClient;
|
|
601
|
-
yield*
|
|
587
|
+
yield* _e(n, Ge(n, A(e, t), t)).pipe(d.orDie);
|
|
602
588
|
}), Ue = (e, t) => {
|
|
603
589
|
let n = t.cause ?? {};
|
|
604
590
|
return (n.errno === 1061 || n.code === "ER_DUP_KEYNAME") && /^\s*CREATE\s+(UNIQUE\s+|FULLTEXT\s+)?INDEX\b/i.test(e);
|
|
605
591
|
}, We = (e) => d.gen(function* () {
|
|
606
592
|
let t = yield* p.SqlClient;
|
|
607
|
-
for (let n of Ke(e)) process.env.VOLTRO_MIGRATE_DEBUG === "1" &&
|
|
608
|
-
|
|
593
|
+
for (let n of Ke(e)) process.env.VOLTRO_MIGRATE_DEBUG === "1" && ve.debug(`EXEC: ${n.replace(/\s+/g, " ").slice(0, 180)}`), yield* t.unsafe(n).pipe(d.catchIf((e) => Ue(n, e), () => d.void), d.tapError((e) => d.sync(() => {
|
|
594
|
+
ve.error(_("migrate: statement failed", n, e, 200));
|
|
609
595
|
})), d.orDieWith((e) => Error(_("migrate: statement failed", n, e, 400).trim())));
|
|
610
596
|
}), Ge = (e, t, n) => (n === "turso" ? We(t) : e.withTransaction(We(t))).pipe(d.orDie), Ke = (e) => {
|
|
611
597
|
let t = [], n = "", r = !1;
|
|
@@ -626,13 +612,13 @@ BEGIN
|
|
|
626
612
|
await d.runPromise(He(e, n).pipe(d.provide(t)));
|
|
627
613
|
}, Je = (e, t, n = "postgres") => d.gen(function* () {
|
|
628
614
|
let r = Be(e, n, t), i = yield* p.SqlClient;
|
|
629
|
-
yield*
|
|
615
|
+
yield* _e(i, Ge(i, r, n)).pipe(d.orDie);
|
|
630
616
|
}), Ye = async (e, t, n, r = "postgres") => {
|
|
631
617
|
await d.runPromise(Je(e, t, r).pipe(d.provide(n)));
|
|
632
618
|
}, Xe = async (e, t, n = "postgres") => {
|
|
633
619
|
await d.runPromise(d.gen(function* () {
|
|
634
620
|
let t = Ve(e, n), r = yield* p.SqlClient;
|
|
635
|
-
yield*
|
|
621
|
+
yield* _e(r, Ge(r, t, n)).pipe(d.orDie);
|
|
636
622
|
}).pipe(d.provide(t)));
|
|
637
623
|
}, Ze = (e) => {
|
|
638
624
|
if (e == null) return e;
|
|
@@ -674,6 +660,7 @@ BEGIN
|
|
|
674
660
|
...t.oneOf && t.oneOf.length > 0 ? { oneOf: t.oneOf } : {},
|
|
675
661
|
...t.idScheme ? { idScheme: { kind: t.idScheme.kind } } : {},
|
|
676
662
|
...t.rawDdl === void 0 ? {} : { rawDdl: t.rawDdl },
|
|
663
|
+
...t.maxLength === void 0 ? {} : { maxLength: t.maxLength },
|
|
677
664
|
...t.precision === void 0 ? {} : { precision: t.precision },
|
|
678
665
|
...t.scale === void 0 ? {} : { scale: t.scale },
|
|
679
666
|
...t.generatedAs ? { generatedAs: {
|
|
@@ -751,12 +738,13 @@ BEGIN
|
|
|
751
738
|
unique: !0
|
|
752
739
|
} : e);
|
|
753
740
|
}
|
|
754
|
-
let r = e.appliedPrimaryKey ?? [];
|
|
741
|
+
let r = e.appliedPrimaryKey ?? [], i = e.previousTableName;
|
|
755
742
|
return {
|
|
756
743
|
name: e.tableName,
|
|
757
744
|
columns: n,
|
|
758
745
|
indexes: rt(e),
|
|
759
|
-
...r.length > 0 ? { primaryKey: [...r] } : {}
|
|
746
|
+
...r.length > 0 ? { primaryKey: [...r] } : {},
|
|
747
|
+
...i === void 0 ? {} : { renamedFrom: i }
|
|
760
748
|
};
|
|
761
749
|
}, at = (e) => {
|
|
762
750
|
let t = /* @__PURE__ */ new Map();
|
|
@@ -766,7 +754,7 @@ BEGIN
|
|
|
766
754
|
t.set(e.name, n.name);
|
|
767
755
|
}
|
|
768
756
|
}, N = (e, t) => {
|
|
769
|
-
let n = e.map((e) => it(
|
|
757
|
+
let n = e.map((e) => it(x(e, t)));
|
|
770
758
|
return at(n), { tables: n };
|
|
771
759
|
}, ot = "framework_changes_", st = (e, t) => d.gen(function* () {
|
|
772
760
|
let n = t.filter((e) => !e.tableName.startsWith("_voltro_"));
|
|
@@ -802,19 +790,19 @@ BEGIN
|
|
|
802
790
|
t.push(`${e.stale.length} .nonReactive() table(s) still carry a change trigger — ${n}. They keep paying REPLICA IDENTITY FULL and a NOTIFY on every write for a subscription nobody receives. \`voltro db apply\` removes them.`);
|
|
803
791
|
}
|
|
804
792
|
return t.length > 0 ? t.join("\n") : void 0;
|
|
805
|
-
}, lt = /* @__PURE__ */ new Set(["voltro_isr_cache"]),
|
|
793
|
+
}, lt = /* @__PURE__ */ new Set(["voltro_isr_cache"]), ut = (e) => lt.has(e) || e.startsWith("_voltro_") || e.startsWith("_cloud_") || e.startsWith("cluster_"), dt = /__dropped_\d{14}$/, ft = (e) => dt.test(e), pt = {
|
|
806
794
|
postgres: !0,
|
|
807
795
|
mysql: !0,
|
|
808
796
|
mariadb: !0,
|
|
809
797
|
mssql: !0,
|
|
810
798
|
sqlite: !0
|
|
811
|
-
},
|
|
799
|
+
}, mt = {
|
|
812
800
|
postgres: !0,
|
|
813
801
|
mysql: !1,
|
|
814
802
|
mariadb: !1,
|
|
815
803
|
mssql: !0,
|
|
816
804
|
sqlite: !0
|
|
817
|
-
},
|
|
805
|
+
}, ht = (e) => {
|
|
818
806
|
switch (e) {
|
|
819
807
|
case "add-column":
|
|
820
808
|
case "drop-column":
|
|
@@ -824,43 +812,43 @@ BEGIN
|
|
|
824
812
|
case "add-foreign-key":
|
|
825
813
|
case "add-unique":
|
|
826
814
|
case "add-unique-composite":
|
|
827
|
-
case "add-check": return
|
|
828
|
-
default: return
|
|
815
|
+
case "add-check": return mt;
|
|
816
|
+
default: return pt;
|
|
829
817
|
}
|
|
830
|
-
},
|
|
818
|
+
}, gt = (e, t) => {
|
|
831
819
|
let n = new Map(t.tables.map((e) => [e.name, e]));
|
|
832
820
|
return new Map(e.map((e) => [e.tableName, {
|
|
833
821
|
table: e,
|
|
834
822
|
snapshot: n.get(e.tableName),
|
|
835
823
|
columnDefs: e.fields
|
|
836
824
|
}]));
|
|
837
|
-
},
|
|
825
|
+
}, P = (e) => {
|
|
838
826
|
if (typeof e != "object" || !e) return JSON.stringify(e);
|
|
839
|
-
if (Array.isArray(e)) return `[${e.map(
|
|
827
|
+
if (Array.isArray(e)) return `[${e.map(P).join(",")}]`;
|
|
840
828
|
let t = e;
|
|
841
|
-
return `{${Object.keys(t).sort().map((e) => `${JSON.stringify(e)}:${
|
|
842
|
-
},
|
|
829
|
+
return `{${Object.keys(t).sort().map((e) => `${JSON.stringify(e)}:${P(t[e])}`).join(",")}}`;
|
|
830
|
+
}, _t = (e) => {
|
|
843
831
|
if (!e.hasDefault || e.defaultValue === void 0 || e.defaultValue === null) return null;
|
|
844
832
|
let t = e.defaultValue;
|
|
845
833
|
if (typeof t == "boolean") return t ? "__BOOL_TRUE__" : "__BOOL_FALSE__";
|
|
846
834
|
if (typeof t == "number") return String(t);
|
|
847
|
-
if (typeof t != "string") return
|
|
835
|
+
if (typeof t != "string") return P(t);
|
|
848
836
|
let n = t.trim(), r = n.toLowerCase().replace(/\s+/g, "");
|
|
849
837
|
if (r === "now" || r === "now()" || /^current_timestamp(\(\d*\))?$/.test(r) || r === "sysutcdatetime()" || r === "sysdatetime()" || r === "getutcdate()" || r === "getdate()") return "__NOW__";
|
|
850
838
|
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);
|
|
851
839
|
if (o) try {
|
|
852
|
-
return
|
|
840
|
+
return P(JSON.parse(o[1]));
|
|
853
841
|
} catch {}
|
|
854
842
|
if (a.startsWith("{") || a.startsWith("[")) try {
|
|
855
|
-
return
|
|
843
|
+
return P(JSON.parse(a));
|
|
856
844
|
} catch {}
|
|
857
845
|
return /^-?\d+(\.\d+)?$/.test(a) ? String(Number(a)) : a;
|
|
858
|
-
},
|
|
859
|
-
let n =
|
|
846
|
+
}, vt = (e, t) => {
|
|
847
|
+
let n = _t(e), r = _t(t);
|
|
860
848
|
if (n === r) return !0;
|
|
861
849
|
let i = (e) => e === "1" || e === "true" ? "__BOOL_TRUE__" : e === "0" || e === "false" ? "__BOOL_FALSE__" : e;
|
|
862
850
|
return i(n) === i(r);
|
|
863
|
-
},
|
|
851
|
+
}, F = (e) => {
|
|
864
852
|
if (!e) return null;
|
|
865
853
|
let t = (e) => e === "restrict" ? "noAction" : e;
|
|
866
854
|
return {
|
|
@@ -869,77 +857,84 @@ BEGIN
|
|
|
869
857
|
onDelete: t(e.onDelete),
|
|
870
858
|
onUpdate: t(e.onUpdate)
|
|
871
859
|
};
|
|
872
|
-
},
|
|
860
|
+
}, yt = (e, t) => {
|
|
873
861
|
let n = e && e.length > 0 ? e : void 0, r = t && t.length > 0 ? t : void 0;
|
|
874
862
|
if (!n && !r) return !0;
|
|
875
863
|
if (!n || !r || n.length !== r.length) return !1;
|
|
876
864
|
let i = [...n].sort(), a = [...r].sort();
|
|
877
865
|
return i.every((e, t) => e === a[t]);
|
|
878
|
-
},
|
|
866
|
+
}, bt = (e, t) => {
|
|
867
|
+
try {
|
|
868
|
+
let n = /\((\d+)\)/.exec(E(e, t));
|
|
869
|
+
return n ? Number(n[1]) : void 0;
|
|
870
|
+
} catch {
|
|
871
|
+
return;
|
|
872
|
+
}
|
|
873
|
+
}, xt = (e, t, n) => n === void 0 || u(n) ? !0 : e.type !== "text" || t.type !== "text" || bt(e, n) === t.maxLength, St = (e, t, n) => e.type === t.type && e.nullable === t.nullable && e.unique === t.unique && vt(e, t) && xt(e, t, n) && JSON.stringify(F(e.references)) === JSON.stringify(F(t.references)) && yt(e.oneOf, t.oneOf), Ct = (e, t) => t.oneOf && t.oneOf.length > 0 ? I({
|
|
879
874
|
kind: "add-check",
|
|
880
875
|
table: e,
|
|
881
876
|
column: t.name,
|
|
882
877
|
values: t.oneOf
|
|
883
|
-
}, "safe", `enum-membership CHECK on ${e}.${t.name}`) : void 0,
|
|
884
|
-
let
|
|
878
|
+
}, "safe", `enum-membership CHECK on ${e}.${t.name}`) : void 0, wt = (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])), Tt = (e, t, n) => {
|
|
879
|
+
let r = new Map(t.columns.map((e) => [e.name, e])), i = new Map(e.columns.map((e) => [e.name, e])), a = [], o = [], s = [];
|
|
885
880
|
for (let t of e.columns) {
|
|
886
|
-
let e =
|
|
881
|
+
let e = r.get(t.name);
|
|
887
882
|
if (!e) {
|
|
888
|
-
|
|
883
|
+
a.push(t);
|
|
889
884
|
continue;
|
|
890
885
|
}
|
|
891
|
-
|
|
886
|
+
St(t, e, n) || s.push({
|
|
892
887
|
declared: t,
|
|
893
888
|
live: e
|
|
894
889
|
});
|
|
895
890
|
}
|
|
896
|
-
for (let e of t.columns)
|
|
891
|
+
for (let e of t.columns) i.has(e.name) || o.push(e);
|
|
897
892
|
return {
|
|
898
|
-
added:
|
|
899
|
-
removed:
|
|
900
|
-
changed:
|
|
893
|
+
added: a,
|
|
894
|
+
removed: o,
|
|
895
|
+
changed: s
|
|
901
896
|
};
|
|
902
|
-
},
|
|
897
|
+
}, Et = (e, t) => {
|
|
903
898
|
let n = new Map(t.indexes.map((e) => [e.name, e])), r = new Map(e.indexes.map((e) => [e.name, e])), i = [], a = [];
|
|
904
899
|
for (let t of e.indexes) {
|
|
905
900
|
let e = n.get(t.name);
|
|
906
|
-
(!e || !
|
|
901
|
+
(!e || !wt(t, e)) && i.push(t);
|
|
907
902
|
}
|
|
908
903
|
for (let e of t.indexes) r.has(e.name) || a.push(e);
|
|
909
904
|
return {
|
|
910
905
|
added: i,
|
|
911
906
|
removed: a
|
|
912
907
|
};
|
|
913
|
-
},
|
|
908
|
+
}, I = (e, t, n, r) => ({
|
|
914
909
|
op: e,
|
|
915
910
|
classification: t,
|
|
916
|
-
atomicByDialect:
|
|
911
|
+
atomicByDialect: ht(e.kind),
|
|
917
912
|
...n ? { reason: n } : {},
|
|
918
913
|
...r ? { blocked: r } : {}
|
|
919
|
-
}),
|
|
914
|
+
}), Dt = (e, t, n) => {
|
|
920
915
|
let r = {
|
|
921
916
|
kind: "add-column",
|
|
922
917
|
table: e,
|
|
923
918
|
column: t
|
|
924
919
|
};
|
|
925
|
-
return t.nullable ?
|
|
926
|
-
},
|
|
920
|
+
return t.nullable ? I(r, "safe", "nullable column add — no backfill needed") : t.hasDefault && t.defaultValue !== void 0 ? I(r, "needs-default", "NOT NULL with literal default — DDL DEFAULT will populate existing rows") : n?.backfill ? I(r, "needs-backfill", `backfill declared (kind=${n.backfill.kind}) — applier will run 3-step add/update/set-not-null`) : I(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` });
|
|
921
|
+
}, Ot = (e, t, n) => {
|
|
927
922
|
let r = {
|
|
928
923
|
kind: "drop-column",
|
|
929
924
|
table: e,
|
|
930
925
|
column: t.name
|
|
931
926
|
};
|
|
932
|
-
return n?.dropped ?
|
|
933
|
-
},
|
|
927
|
+
return n?.dropped ? I(r, "lossy", `column dropped via \`${t.name}: dropped()\` marker — intentional`) : I(r, "lossy", "column missing from declared schema", { fix: `if intentional, add \`${t.name}: dropped()\` to the schema. If a typo, restore the field` });
|
|
928
|
+
}, kt = (e, t, n, r, i) => I({
|
|
934
929
|
kind: "create-table",
|
|
935
930
|
table: e,
|
|
936
931
|
columns: t,
|
|
937
932
|
indexes: n,
|
|
938
933
|
...r && r.length > 0 ? { primaryKey: r } : {}
|
|
939
|
-
}, "safe", "new table — no data to preserve"),
|
|
934
|
+
}, "safe", i ?? "new table — no data to preserve"), At = (e) => I({
|
|
940
935
|
kind: "drop-table",
|
|
941
936
|
table: e
|
|
942
|
-
}, "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" }),
|
|
937
|
+
}, "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" }), jt = 5e4, Mt = (e, t, n, r) => {
|
|
943
938
|
let i = (n ?? 0) >= r, a;
|
|
944
939
|
return a = t.unique ? t.columns.length === 1 ? {
|
|
945
940
|
kind: "add-unique",
|
|
@@ -954,16 +949,16 @@ BEGIN
|
|
|
954
949
|
kind: "add-index",
|
|
955
950
|
table: e,
|
|
956
951
|
index: t
|
|
957
|
-
}, i ?
|
|
958
|
-
},
|
|
952
|
+
}, i ? I(a, "online-required", `online build on ${n} rows — CONCURRENTLY / INPLACE / WITH(ONLINE=ON) depending on dialect`) : I(a, "safe", t.unique ? t.columns.length === 1 ? "add unique constraint" : "add composite UNIQUE constraint" : "add B-tree index");
|
|
953
|
+
}, Nt = (e, t) => t.unique && t.columns.length > 1 ? I({
|
|
959
954
|
kind: "drop-unique-composite",
|
|
960
955
|
table: e,
|
|
961
956
|
name: t.name
|
|
962
|
-
}, "safe", "drop composite UNIQUE constraint (no data loss — constraint is derived metadata)") :
|
|
957
|
+
}, "safe", "drop composite UNIQUE constraint (no data loss — constraint is derived metadata)") : I({
|
|
963
958
|
kind: "drop-index",
|
|
964
959
|
table: e,
|
|
965
960
|
index: t.name
|
|
966
|
-
}, "safe", "drop index (no data loss — index is derived data)"),
|
|
961
|
+
}, "safe", "drop index (no data loss — index is derived data)"), Pt = (e, t) => {
|
|
967
962
|
if (e === "reference") return "text";
|
|
968
963
|
switch (t) {
|
|
969
964
|
case "sqlite":
|
|
@@ -971,7 +966,7 @@ BEGIN
|
|
|
971
966
|
case "mssql": return e === "json" ? "text" : e;
|
|
972
967
|
default: return e;
|
|
973
968
|
}
|
|
974
|
-
},
|
|
969
|
+
}, Ft = (e, t, n, r, i, a) => {
|
|
975
970
|
let o = [];
|
|
976
971
|
if (t.nullable !== n.nullable) {
|
|
977
972
|
let n = {
|
|
@@ -980,7 +975,7 @@ BEGIN
|
|
|
980
975
|
column: t.name,
|
|
981
976
|
toNullable: t.nullable
|
|
982
977
|
};
|
|
983
|
-
o.push(t.nullable ?
|
|
978
|
+
o.push(t.nullable ? I(n, "safe", `loosen ${e}.${t.name} to nullable`) : I(n, "needs-backfill", `tighten ${e}.${t.name} to NOT NULL — existing rows must already be non-null`));
|
|
984
979
|
}
|
|
985
980
|
if (t.unique !== n.unique) if (t.unique) {
|
|
986
981
|
let n = {
|
|
@@ -988,13 +983,13 @@ BEGIN
|
|
|
988
983
|
table: e,
|
|
989
984
|
column: t.name
|
|
990
985
|
}, r = (i ?? 0) >= a;
|
|
991
|
-
o.push(r ?
|
|
992
|
-
} else o.push(
|
|
986
|
+
o.push(r ? I(n, "online-required", `online unique build on ${i} rows — CONCURRENTLY / INPLACE / WITH(ONLINE=ON) depending on dialect`) : I(n, "safe", `add unique constraint on ${e}.${t.name} — existing rows must already be distinct (else the DB rejects at migrate)`));
|
|
987
|
+
} else o.push(I({
|
|
993
988
|
kind: "drop-unique",
|
|
994
989
|
table: e,
|
|
995
990
|
column: t.name
|
|
996
991
|
}, "safe", `drop unique constraint on ${e}.${t.name} — constraint is derived metadata, no data loss`));
|
|
997
|
-
if (
|
|
992
|
+
if (Pt(t.type, r) !== Pt(n.type, r)) {
|
|
998
993
|
let r = t.narrowedFrom;
|
|
999
994
|
if (r && r.from === n.type) {
|
|
1000
995
|
let i = {
|
|
@@ -1005,7 +1000,7 @@ BEGIN
|
|
|
1005
1000
|
to: t.type,
|
|
1006
1001
|
...r.using === void 0 ? {} : { using: r.using }
|
|
1007
1002
|
};
|
|
1008
|
-
o.push(
|
|
1003
|
+
o.push(I(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)")));
|
|
1009
1004
|
} else {
|
|
1010
1005
|
let r = {
|
|
1011
1006
|
kind: "alter-column-type",
|
|
@@ -1014,10 +1009,20 @@ BEGIN
|
|
|
1014
1009
|
from: n.type,
|
|
1015
1010
|
to: t.type
|
|
1016
1011
|
};
|
|
1017
|
-
o.push(
|
|
1012
|
+
o.push(I(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` }));
|
|
1018
1013
|
}
|
|
1019
1014
|
}
|
|
1020
|
-
if (!
|
|
1015
|
+
if (t.type === "text" && n.type === "text" && !u(r ?? "postgres") && t.maxLength !== n.maxLength) {
|
|
1016
|
+
let r = t.maxLength === void 0 || n.maxLength !== void 0 && t.maxLength > n.maxLength, i = n.maxLength === void 0 ? "unbounded" : `varchar(${n.maxLength})`, a = t.maxLength === void 0 ? "unbounded" : `varchar(${t.maxLength})`;
|
|
1017
|
+
o.push(I({
|
|
1018
|
+
kind: "alter-column-type",
|
|
1019
|
+
table: e,
|
|
1020
|
+
column: t.name,
|
|
1021
|
+
from: "text",
|
|
1022
|
+
to: "text"
|
|
1023
|
+
}, r ? "safe" : "needs-backfill", r ? `text length ${i} → ${a} on ${e}.${t.name} — widening, no data can be lost` : `text length ${i} → ${a} on ${e}.${t.name} — NARROWING; the ALTER fails if any existing value is longer than ${String(t.maxLength)}. Check first: SELECT COUNT(*) FROM ${e} WHERE LENGTH(${t.name}) > ${String(t.maxLength)}`));
|
|
1024
|
+
}
|
|
1025
|
+
if (!vt(t, n)) {
|
|
1021
1026
|
let n = {
|
|
1022
1027
|
kind: "alter-column-default",
|
|
1023
1028
|
table: e,
|
|
@@ -1025,18 +1030,18 @@ BEGIN
|
|
|
1025
1030
|
hasDefault: t.hasDefault,
|
|
1026
1031
|
...t.defaultValue === void 0 ? {} : { defaultValue: t.defaultValue }
|
|
1027
1032
|
};
|
|
1028
|
-
o.push(
|
|
1033
|
+
o.push(I(n, "safe", `default change on ${e}.${t.name} affects only future inserts`));
|
|
1029
1034
|
}
|
|
1030
|
-
if (!
|
|
1031
|
-
n.oneOf && n.oneOf.length > 0 && o.push(
|
|
1035
|
+
if (!yt(t.oneOf, n.oneOf)) {
|
|
1036
|
+
n.oneOf && n.oneOf.length > 0 && o.push(I({
|
|
1032
1037
|
kind: "drop-check",
|
|
1033
1038
|
table: e,
|
|
1034
1039
|
column: t.name
|
|
1035
1040
|
}, "safe", `drop stale enum CHECK on ${e}.${t.name}`));
|
|
1036
|
-
let r =
|
|
1041
|
+
let r = Ct(e, t);
|
|
1037
1042
|
r && o.push(r);
|
|
1038
1043
|
}
|
|
1039
|
-
if (JSON.stringify(
|
|
1044
|
+
if (JSON.stringify(F(t.references)) !== JSON.stringify(F(n.references)) && (n.references && o.push(I({
|
|
1040
1045
|
kind: "drop-foreign-key",
|
|
1041
1046
|
table: e,
|
|
1042
1047
|
column: t.name
|
|
@@ -1050,17 +1055,17 @@ BEGIN
|
|
|
1050
1055
|
...t.references.onDelete ? { onDelete: t.references.onDelete } : {},
|
|
1051
1056
|
...t.references.onUpdate ? { onUpdate: t.references.onUpdate } : {}
|
|
1052
1057
|
};
|
|
1053
|
-
r === "null" && !t.nullable ? o.push(
|
|
1058
|
+
r === "null" && !t.nullable ? o.push(I(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(I({
|
|
1054
1059
|
...i,
|
|
1055
1060
|
orphanPolicy: r
|
|
1056
|
-
}, "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(
|
|
1061
|
+
}, "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(I(i, "needs-backfill", `add FK ${e}.${t.name} → ${n} — existing rows must already reference a valid ${n} (else set orphanPolicy:'null'/'delete')`));
|
|
1057
1062
|
}
|
|
1058
1063
|
return o;
|
|
1059
|
-
},
|
|
1064
|
+
}, It = (e, t, n) => {
|
|
1060
1065
|
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));
|
|
1061
1066
|
for (let [n, c] of Object.entries(t)) {
|
|
1062
1067
|
let t = c.renamedFrom;
|
|
1063
|
-
t && o.has(t) && s.has(n) && (i.add(n), a.add(t), r.push(
|
|
1068
|
+
t && o.has(t) && s.has(n) && (i.add(n), a.add(t), r.push(I({
|
|
1064
1069
|
kind: "rename-column",
|
|
1065
1070
|
table: e.tableName,
|
|
1066
1071
|
from: t,
|
|
@@ -1072,7 +1077,109 @@ BEGIN
|
|
|
1072
1077
|
consumedAddedNames: i,
|
|
1073
1078
|
consumedRemovedNames: a
|
|
1074
1079
|
};
|
|
1075
|
-
},
|
|
1080
|
+
}, Lt = /* @__PURE__ */ new Set([
|
|
1081
|
+
"postgres",
|
|
1082
|
+
"mysql",
|
|
1083
|
+
"mariadb",
|
|
1084
|
+
"mssql"
|
|
1085
|
+
]), Rt = {
|
|
1086
|
+
ops: [],
|
|
1087
|
+
consumedAddedNames: /* @__PURE__ */ new Set(),
|
|
1088
|
+
consumedRemovedNames: /* @__PURE__ */ new Set()
|
|
1089
|
+
}, zt = (e) => !e.unique && !e.expression, Bt = (e, t, n, r, i) => {
|
|
1090
|
+
if (i === void 0 || !Lt.has(i)) return Rt;
|
|
1091
|
+
let a = t.added.filter((e) => zt(e) && !r.has(e.name));
|
|
1092
|
+
if (a.length === 0) return Rt;
|
|
1093
|
+
let o = (e) => e.columns.map((e) => n.get(e) ?? e).join("\0"), s = (e) => e.columns.join("\0"), c = [], l = /* @__PURE__ */ new Set(), u = /* @__PURE__ */ new Set();
|
|
1094
|
+
for (let n of t.removed) {
|
|
1095
|
+
if (!zt(n)) continue;
|
|
1096
|
+
let t = o(n), r = a.filter((e) => !l.has(e.name) && s(e) === t);
|
|
1097
|
+
if (r.length !== 1) continue;
|
|
1098
|
+
let i = r[0];
|
|
1099
|
+
i.name !== n.name && (l.add(i.name), u.add(n.name), c.push(I({
|
|
1100
|
+
kind: "rename-index",
|
|
1101
|
+
table: e,
|
|
1102
|
+
from: n.name,
|
|
1103
|
+
to: i.name
|
|
1104
|
+
}, "safe", "rename index in place — catalog-only, no rebuild")));
|
|
1105
|
+
}
|
|
1106
|
+
return {
|
|
1107
|
+
ops: c,
|
|
1108
|
+
consumedAddedNames: l,
|
|
1109
|
+
consumedRemovedNames: u
|
|
1110
|
+
};
|
|
1111
|
+
}, Vt = (e, t, n) => {
|
|
1112
|
+
let r = [], i = /* @__PURE__ */ new Map(), a = /* @__PURE__ */ new Set(), o = /* @__PURE__ */ new Map(), s = /* @__PURE__ */ new Map(), c = /* @__PURE__ */ new Set();
|
|
1113
|
+
for (let t of e.tables) t.renamedFrom !== void 0 && (s.set(t.renamedFrom, (s.get(t.renamedFrom) ?? 0) + 1), c.add(t.renamedFrom));
|
|
1114
|
+
for (let c of e.tables) {
|
|
1115
|
+
let e = c.renamedFrom;
|
|
1116
|
+
if (e !== void 0 && e !== c.name && t.has(e)) {
|
|
1117
|
+
if (t.has(c.name)) {
|
|
1118
|
+
r.push(I({
|
|
1119
|
+
kind: "rename-table",
|
|
1120
|
+
from: e,
|
|
1121
|
+
to: c.name
|
|
1122
|
+
}, "needs-rename-annotation", `.renamedFrom('${e}') cannot be applied — both '${e}' and '${c.name}' exist in the database`, { fix: `decide which holds the real rows: move them into '${c.name}' and drop '${e}', or drop the empty '${c.name}' so the rename can run. '${e}' is left untouched until you do.` }));
|
|
1123
|
+
continue;
|
|
1124
|
+
}
|
|
1125
|
+
if (n.has(e)) {
|
|
1126
|
+
o.set(c.name, `.renamedFrom('${e}') NOT applied — '${e}' is still declared by this schema, so it belongs to that declaration. This table is created empty; that is the intended outcome when an app owns a table of the same name.`);
|
|
1127
|
+
continue;
|
|
1128
|
+
}
|
|
1129
|
+
if ((s.get(e) ?? 0) !== 1) {
|
|
1130
|
+
r.push(I({
|
|
1131
|
+
kind: "rename-table",
|
|
1132
|
+
from: e,
|
|
1133
|
+
to: c.name
|
|
1134
|
+
}, "needs-rename-annotation", `.renamedFrom('${e}') is claimed by ${s.get(e)} tables — nothing says which receives its rows`, { fix: `remove the \`.renamedFrom('${e}')\` marker from all but one of them.` }));
|
|
1135
|
+
continue;
|
|
1136
|
+
}
|
|
1137
|
+
i.set(c.name, e), a.add(e), r.push(I({
|
|
1138
|
+
kind: "rename-table",
|
|
1139
|
+
from: e,
|
|
1140
|
+
to: c.name
|
|
1141
|
+
}, "safe", `rename via \`.renamedFrom('${e}')\` — catalog-only, the rows stay put`));
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
return {
|
|
1145
|
+
ops: r,
|
|
1146
|
+
renamedInto: i,
|
|
1147
|
+
renamedFromNames: a,
|
|
1148
|
+
claimedOldNames: c,
|
|
1149
|
+
refusals: o
|
|
1150
|
+
};
|
|
1151
|
+
}, Ht = (e, t, n, r) => {
|
|
1152
|
+
if (t === void 0) return {
|
|
1153
|
+
live: e,
|
|
1154
|
+
ops: []
|
|
1155
|
+
};
|
|
1156
|
+
let i = r !== void 0 && Lt.has(r), a = [], o = e.indexes.map((e) => {
|
|
1157
|
+
if (!e.name.startsWith(t)) return e;
|
|
1158
|
+
let r = `${n}${e.name.slice(t.length)}`;
|
|
1159
|
+
return r === e.name ? e : e.name === `${t}_pkey` ? {
|
|
1160
|
+
...e,
|
|
1161
|
+
name: r,
|
|
1162
|
+
table: n
|
|
1163
|
+
} : i ? (a.push(I({
|
|
1164
|
+
kind: "rename-index",
|
|
1165
|
+
table: n,
|
|
1166
|
+
from: e.name,
|
|
1167
|
+
to: r
|
|
1168
|
+
}, "safe", "auto-named index follows its renamed table — catalog-only, no rebuild")), {
|
|
1169
|
+
...e,
|
|
1170
|
+
name: r,
|
|
1171
|
+
table: n
|
|
1172
|
+
}) : e;
|
|
1173
|
+
});
|
|
1174
|
+
return {
|
|
1175
|
+
live: {
|
|
1176
|
+
...e,
|
|
1177
|
+
indexes: o,
|
|
1178
|
+
name: n
|
|
1179
|
+
},
|
|
1180
|
+
ops: a
|
|
1181
|
+
};
|
|
1182
|
+
}, Ut = (e) => {
|
|
1076
1183
|
let t = {
|
|
1077
1184
|
safe: 0,
|
|
1078
1185
|
needsDefault: 0,
|
|
@@ -1107,46 +1214,51 @@ BEGIN
|
|
|
1107
1214
|
break;
|
|
1108
1215
|
}
|
|
1109
1216
|
return t;
|
|
1110
|
-
},
|
|
1111
|
-
let t = N(e.declared, e.dialect), n =
|
|
1112
|
-
|
|
1113
|
-
|
|
1217
|
+
}, Wt = (e) => {
|
|
1218
|
+
let t = N(e.declared, e.dialect), n = gt(e.declared, t), r = new Map(e.live.tables.map((e) => [e.name, e])), i = e.onlineAfter ?? jt, a = [], o = Vt(t, r, n);
|
|
1219
|
+
a.push(...o.ops);
|
|
1220
|
+
for (let e of t.tables) if (!o.renamedInto.has(e.name) && !r.has(e.name)) {
|
|
1221
|
+
a.push(kt(e.name, e.columns, e.indexes, e.primaryKey, o.refusals.get(e.name)));
|
|
1114
1222
|
for (let t of e.columns) {
|
|
1115
|
-
let n =
|
|
1223
|
+
let n = Ct(e.name, t);
|
|
1116
1224
|
n && a.push(n);
|
|
1117
1225
|
}
|
|
1118
1226
|
}
|
|
1119
|
-
let
|
|
1120
|
-
for (let t of e.live.tables) n.has(t.name) ||
|
|
1121
|
-
for (let
|
|
1122
|
-
let t = r.get(
|
|
1123
|
-
if (!
|
|
1124
|
-
let
|
|
1125
|
-
a.push(...
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1227
|
+
let s = new Set(e.ignoreTables ?? []);
|
|
1228
|
+
for (let t of e.live.tables) n.has(t.name) || o.claimedOldNames.has(t.name) || ut(t.name) || ft(t.name) || s.has(t.name) || a.push(At(t.name));
|
|
1229
|
+
for (let s of t.tables) {
|
|
1230
|
+
let t = o.renamedInto.get(s.name), c = r.get(s.name) ?? (t === void 0 ? void 0 : r.get(t));
|
|
1231
|
+
if (!c) continue;
|
|
1232
|
+
let l = Ht(c, t, s.name, e.dialect);
|
|
1233
|
+
a.push(...l.ops);
|
|
1234
|
+
let u = l.live, d = n.get(s.name), f = Tt(s, u, e.dialect), p = Et(s, u), m = It(d.table, d.columnDefs, f);
|
|
1235
|
+
a.push(...m.ops);
|
|
1236
|
+
for (let e of f.removed) {
|
|
1237
|
+
if (m.consumedRemovedNames.has(e.name) || ft(e.name)) continue;
|
|
1238
|
+
let t = d.columnDefs[e.name];
|
|
1239
|
+
a.push(Ot(s.name, e, t));
|
|
1130
1240
|
}
|
|
1131
|
-
for (let e of
|
|
1132
|
-
if (
|
|
1133
|
-
let t =
|
|
1134
|
-
a.push(
|
|
1135
|
-
let n =
|
|
1241
|
+
for (let e of f.added) {
|
|
1242
|
+
if (m.consumedAddedNames.has(e.name)) continue;
|
|
1243
|
+
let t = d.columnDefs[e.name];
|
|
1244
|
+
a.push(Dt(s.name, e, t));
|
|
1245
|
+
let n = Ct(s.name, e);
|
|
1136
1246
|
n && a.push(n);
|
|
1137
1247
|
}
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
for (let
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1248
|
+
let h = new Map(m.ops.flatMap((e) => e.op.kind === "rename-column" ? [[e.op.from, e.op.to]] : [])), g = Bt(s.name, p, h, new Set(u.indexes.map((e) => e.name)), e.dialect);
|
|
1249
|
+
a.push(...g.ops);
|
|
1250
|
+
for (let e of p.added) g.consumedAddedNames.has(e.name) || a.push(Mt(s.name, e, u.rowCount, i));
|
|
1251
|
+
for (let e of p.removed) g.consumedRemovedNames.has(e.name) || a.push(Nt(s.name, e));
|
|
1252
|
+
for (let { declared: t, live: n } of f.changed) a.push(...Ft(s.name, t, n, e.dialect, u.rowCount, i));
|
|
1253
|
+
}
|
|
1254
|
+
let c = new Set(a.flatMap((e) => e.op.kind === "create-table" ? [e.op.table] : [])), l = new Map(t.tables.map((e) => [e.name, e])), u = (e) => {
|
|
1255
|
+
let t = l.get(e);
|
|
1256
|
+
return t ? t.columns.flatMap((e) => e.references && c.has(e.references.table) ? [{
|
|
1145
1257
|
column: e.name,
|
|
1146
1258
|
target: e.references.table
|
|
1147
1259
|
}] : []) : [];
|
|
1148
|
-
},
|
|
1149
|
-
for (let e of t.tables) if (
|
|
1260
|
+
}, d = ne([...c], u), f = [];
|
|
1261
|
+
for (let e of t.tables) if (c.has(e.name)) for (let t of e.columns) !t.references || !d.has(S(e.name, t.name)) || f.push(I({
|
|
1150
1262
|
kind: "add-foreign-key",
|
|
1151
1263
|
table: e.name,
|
|
1152
1264
|
column: t.name,
|
|
@@ -1155,14 +1267,14 @@ BEGIN
|
|
|
1155
1267
|
...t.references.onDelete ? { onDelete: t.references.onDelete } : {},
|
|
1156
1268
|
...t.references.onUpdate ? { onUpdate: t.references.onUpdate } : {}
|
|
1157
1269
|
}, "safe", `deferred FK ${e.name}.${t.name} → ${t.references.table} — breaks a create-time table cycle`));
|
|
1158
|
-
if (
|
|
1270
|
+
if (d.size > 0) {
|
|
1159
1271
|
let e = (e) => e.references ? Object.fromEntries(Object.entries(e).filter(([e]) => e !== "references")) : e;
|
|
1160
1272
|
for (let t = 0; t < a.length; t += 1) {
|
|
1161
1273
|
let n = a[t];
|
|
1162
1274
|
if (n.op.kind !== "create-table") continue;
|
|
1163
1275
|
let r = n.op;
|
|
1164
|
-
if (!r.columns.some((e) =>
|
|
1165
|
-
let i = r.columns.map((t) =>
|
|
1276
|
+
if (!r.columns.some((e) => d.has(S(r.table, e.name)))) continue;
|
|
1277
|
+
let i = r.columns.map((t) => d.has(S(r.table, t.name)) ? e(t) : t);
|
|
1166
1278
|
a[t] = {
|
|
1167
1279
|
...n,
|
|
1168
1280
|
op: {
|
|
@@ -1171,26 +1283,27 @@ BEGIN
|
|
|
1171
1283
|
}
|
|
1172
1284
|
};
|
|
1173
1285
|
}
|
|
1174
|
-
a.push(...
|
|
1286
|
+
a.push(...f);
|
|
1175
1287
|
}
|
|
1176
|
-
let
|
|
1177
|
-
let n =
|
|
1288
|
+
let p = new Map(t.tables.map((e) => [e.name, e])), m = /* @__PURE__ */ new Map(), h = (e, t = /* @__PURE__ */ new Set()) => {
|
|
1289
|
+
let n = m.get(e);
|
|
1178
1290
|
if (n !== void 0) return n;
|
|
1179
1291
|
if (t.has(e)) return 0;
|
|
1180
|
-
let r =
|
|
1292
|
+
let r = p.get(e);
|
|
1181
1293
|
if (!r) return 0;
|
|
1182
1294
|
let i = new Set(t).add(e), a = 0;
|
|
1183
1295
|
for (let t of r.columns) {
|
|
1184
1296
|
let n = t.references?.table;
|
|
1185
|
-
n && n !== e && !
|
|
1297
|
+
n && n !== e && !d.has(S(e, t.name)) && (a = Math.max(a, h(n, i) + 1));
|
|
1186
1298
|
}
|
|
1187
|
-
return
|
|
1188
|
-
},
|
|
1299
|
+
return m.set(e, a), a;
|
|
1300
|
+
}, g = (e) => e === "rename-table" ? -1 : e === "create-table" ? 0 : e === "drop-table" ? 2 : 1, ee = (e) => {
|
|
1189
1301
|
let t = "table" in e ? e.table : "";
|
|
1190
|
-
return e.kind === "create-table" ?
|
|
1191
|
-
},
|
|
1302
|
+
return e.kind === "create-table" ? h(t) : e.kind === "drop-table" ? -h(t) : 0;
|
|
1303
|
+
}, _ = {
|
|
1192
1304
|
"add-column": 0,
|
|
1193
1305
|
"rename-column": 1,
|
|
1306
|
+
"rename-index": 1,
|
|
1194
1307
|
"alter-column-nullability": 2,
|
|
1195
1308
|
"alter-column-type": 2,
|
|
1196
1309
|
"alter-column-default": 2,
|
|
@@ -1205,23 +1318,23 @@ BEGIN
|
|
|
1205
1318
|
"add-unique-composite": 5,
|
|
1206
1319
|
"add-foreign-key": 5,
|
|
1207
1320
|
"add-check": 5
|
|
1208
|
-
},
|
|
1209
|
-
let n =
|
|
1321
|
+
}, v = (e) => _[e] ?? 9, y = [...a].sort((e, t) => {
|
|
1322
|
+
let n = g(e.op.kind), r = g(t.op.kind);
|
|
1210
1323
|
if (n !== r) return n - r;
|
|
1211
|
-
let i =
|
|
1324
|
+
let i = ee(e.op), a = ee(t.op);
|
|
1212
1325
|
if (i !== a) return i - a;
|
|
1213
1326
|
let o = "table" in e.op ? e.op.table : "", s = "table" in t.op ? t.op.table : "";
|
|
1214
1327
|
if (o !== s) return o.localeCompare(s);
|
|
1215
|
-
let c =
|
|
1328
|
+
let c = v(e.op.kind), l = v(t.op.kind);
|
|
1216
1329
|
return c === l ? e.op.kind.localeCompare(t.op.kind) : c - l;
|
|
1217
1330
|
});
|
|
1218
1331
|
return {
|
|
1219
|
-
operations:
|
|
1332
|
+
operations: y,
|
|
1220
1333
|
fromFingerprint: j(e.live),
|
|
1221
1334
|
toFingerprint: j(t),
|
|
1222
|
-
summary:
|
|
1335
|
+
summary: Ut(y)
|
|
1223
1336
|
};
|
|
1224
|
-
},
|
|
1337
|
+
}, Gt = (e) => {
|
|
1225
1338
|
let t = /[`"[]?([A-Za-z_][A-Za-z0-9_]*)[`"\]]?\s*(?:in\b|=)/i.exec(e);
|
|
1226
1339
|
if (!t) return null;
|
|
1227
1340
|
let n = [...e.matchAll(/'((?:[^']|'')*)'/g)].map((e) => e[1].replace(/''/g, "'"));
|
|
@@ -1229,7 +1342,7 @@ BEGIN
|
|
|
1229
1342
|
column: t[1],
|
|
1230
1343
|
values: n
|
|
1231
1344
|
};
|
|
1232
|
-
},
|
|
1345
|
+
}, Kt = (e, t) => {
|
|
1233
1346
|
if (t === "vector") return "vector";
|
|
1234
1347
|
switch (e) {
|
|
1235
1348
|
case "text":
|
|
@@ -1256,7 +1369,7 @@ BEGIN
|
|
|
1256
1369
|
case "USER-DEFINED": return "text";
|
|
1257
1370
|
default: return "text";
|
|
1258
1371
|
}
|
|
1259
|
-
},
|
|
1372
|
+
}, L = (e) => {
|
|
1260
1373
|
switch (e.toUpperCase()) {
|
|
1261
1374
|
case "CASCADE": return "cascade";
|
|
1262
1375
|
case "RESTRICT": return "restrict";
|
|
@@ -1264,25 +1377,25 @@ BEGIN
|
|
|
1264
1377
|
case "SET DEFAULT": return "noAction";
|
|
1265
1378
|
default: return "noAction";
|
|
1266
1379
|
}
|
|
1267
|
-
},
|
|
1380
|
+
}, qt = (e, t) => {
|
|
1268
1381
|
let n = e !== void 0 && e !== "" ? Number(e) : NaN;
|
|
1269
1382
|
return Number.isInteger(n) && n > 0 ? n : t;
|
|
1270
|
-
},
|
|
1383
|
+
}, Jt = () => qt(process.env.VOLTRO_INTROSPECT_BATCH, 20), Yt = 300, Xt = () => {
|
|
1271
1384
|
let e = process.env.VOLTRO_INTROSPECT_TIMEOUT_MS;
|
|
1272
|
-
return e !== void 0 && e.trim() === "0" ? 0 :
|
|
1273
|
-
},
|
|
1385
|
+
return e !== void 0 && e.trim() === "0" ? 0 : qt(e, 3e4);
|
|
1386
|
+
}, Zt = (e, t) => {
|
|
1274
1387
|
let n = Number.isFinite(t) && t >= 1 ? Math.floor(t) : 1, r = [];
|
|
1275
1388
|
for (let t = 0; t < e.length; t += n) r.push(e.slice(t, t + n));
|
|
1276
1389
|
return r;
|
|
1277
|
-
},
|
|
1278
|
-
let t =
|
|
1390
|
+
}, Qt = (e) => {
|
|
1391
|
+
let t = Xt(), n = d.gen(function* () {
|
|
1279
1392
|
t > 0 && (yield* e.unsafe(`SET LOCAL statement_timeout = ${t}`));
|
|
1280
|
-
let n = (t) => e.unsafe("(" + t.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ") + ")"), r = (t) => e.unsafe(String(Math.max(0, Math.trunc(t)))), i =
|
|
1393
|
+
let n = (t) => e.unsafe("(" + t.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ") + ")"), r = (t) => e.unsafe(String(Math.max(0, Math.trunc(t)))), i = Jt(), a = (e, t) => d.gen(function* () {
|
|
1281
1394
|
let r = [];
|
|
1282
|
-
for (let a of
|
|
1395
|
+
for (let a of Zt(e, i)) a.length !== 0 && r.push(...yield* t(n(a)));
|
|
1283
1396
|
return r;
|
|
1284
1397
|
}), o = [];
|
|
1285
|
-
for (let t = 0;; t +=
|
|
1398
|
+
for (let t = 0;; t += Yt) {
|
|
1286
1399
|
let n = yield* e`
|
|
1287
1400
|
SELECT c.relname AS table_name,
|
|
1288
1401
|
COALESCE(c.reltuples::bigint, 0) AS row_count
|
|
@@ -1290,14 +1403,15 @@ BEGIN
|
|
|
1290
1403
|
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
1291
1404
|
WHERE n.nspname = current_schema() AND c.relkind = 'r'
|
|
1292
1405
|
ORDER BY c.relname
|
|
1293
|
-
LIMIT ${r(
|
|
1406
|
+
LIMIT ${r(Yt)} OFFSET ${r(t)}
|
|
1294
1407
|
`;
|
|
1295
|
-
if (o.push(...n), n.length <
|
|
1408
|
+
if (o.push(...n), n.length < Yt) break;
|
|
1296
1409
|
}
|
|
1297
1410
|
let s = /* @__PURE__ */ new Set(), c = [];
|
|
1298
1411
|
for (let e of o) s.has(e.table_name) || (s.add(e.table_name), c.push(e));
|
|
1299
1412
|
let l = c.map((e) => e.table_name), u = yield* a(l, (t) => e`
|
|
1300
|
-
SELECT table_name, column_name, data_type, udt_name, is_nullable, column_default
|
|
1413
|
+
SELECT table_name, column_name, data_type, udt_name, is_nullable, column_default,
|
|
1414
|
+
character_maximum_length
|
|
1301
1415
|
FROM information_schema.columns
|
|
1302
1416
|
WHERE table_schema = current_schema() AND table_name IN ${t}
|
|
1303
1417
|
ORDER BY table_name, ordinal_position
|
|
@@ -1377,7 +1491,7 @@ BEGIN
|
|
|
1377
1491
|
AND c.relname IN ${t}
|
|
1378
1492
|
)
|
|
1379
1493
|
SELECT * FROM ix ORDER BY table_name, index_name, position
|
|
1380
|
-
`), _ = /* @__PURE__ */ new Map(), v = /* @__PURE__ */ new Map(),
|
|
1494
|
+
`), _ = /* @__PURE__ */ new Map(), v = /* @__PURE__ */ new Map(), y = /* @__PURE__ */ new Map(), b = /* @__PURE__ */ new Map(), te = /* @__PURE__ */ new Map(), x = /* @__PURE__ */ new Map();
|
|
1381
1495
|
for (let e of u) {
|
|
1382
1496
|
let t = _.get(e.table_name);
|
|
1383
1497
|
t || (t = [], _.set(e.table_name, t)), t.push(e);
|
|
@@ -1386,25 +1500,25 @@ BEGIN
|
|
|
1386
1500
|
let t = v.get(e.table_name);
|
|
1387
1501
|
t || (t = /* @__PURE__ */ new Set(), v.set(e.table_name, t)), t.add(e.column_name);
|
|
1388
1502
|
}
|
|
1389
|
-
let
|
|
1503
|
+
let S = /* @__PURE__ */ new Map();
|
|
1390
1504
|
for (let e of p) {
|
|
1391
|
-
let t = `${e.table_name}\u0000${e.constraint_name}`, n =
|
|
1505
|
+
let t = `${e.table_name}\u0000${e.constraint_name}`, n = S.get(t);
|
|
1392
1506
|
n || (n = {
|
|
1393
1507
|
table: e.table_name,
|
|
1394
1508
|
columns: []
|
|
1395
|
-
},
|
|
1509
|
+
}, S.set(t, n)), n.columns.push({
|
|
1396
1510
|
name: e.column_name,
|
|
1397
1511
|
position: e.position
|
|
1398
1512
|
});
|
|
1399
1513
|
}
|
|
1400
|
-
for (let [e, t] of
|
|
1514
|
+
for (let [e, t] of S) {
|
|
1401
1515
|
let n = [...t.columns].sort((e, t) => e.position - t.position).map((e) => e.name);
|
|
1402
1516
|
if (n.length === 1) {
|
|
1403
|
-
let e =
|
|
1404
|
-
e || (e = /* @__PURE__ */ new Set(),
|
|
1517
|
+
let e = y.get(t.table);
|
|
1518
|
+
e || (e = /* @__PURE__ */ new Set(), y.set(t.table, e)), e.add(n[0]);
|
|
1405
1519
|
} else {
|
|
1406
|
-
let r =
|
|
1407
|
-
r || (r = [],
|
|
1520
|
+
let r = b.get(t.table);
|
|
1521
|
+
r || (r = [], b.set(t.table, r)), r.push({
|
|
1408
1522
|
name: e.slice(e.indexOf("\0") + 1),
|
|
1409
1523
|
table: t.table,
|
|
1410
1524
|
columns: n,
|
|
@@ -1413,27 +1527,28 @@ BEGIN
|
|
|
1413
1527
|
}
|
|
1414
1528
|
}
|
|
1415
1529
|
for (let e of g) {
|
|
1416
|
-
let t =
|
|
1417
|
-
t || (t = [],
|
|
1530
|
+
let t = te.get(e.source_table);
|
|
1531
|
+
t || (t = [], te.set(e.source_table, t)), t.push(e);
|
|
1418
1532
|
}
|
|
1419
1533
|
for (let e of ee) {
|
|
1420
|
-
let t =
|
|
1421
|
-
t || (t = /* @__PURE__ */ new Map(),
|
|
1534
|
+
let t = x.get(e.table_name);
|
|
1535
|
+
t || (t = /* @__PURE__ */ new Map(), x.set(e.table_name, t));
|
|
1422
1536
|
let n = t.get(e.index_name);
|
|
1423
1537
|
n || (n = [], t.set(e.index_name, n)), n.push(e);
|
|
1424
1538
|
}
|
|
1425
|
-
let
|
|
1539
|
+
let ne = [];
|
|
1426
1540
|
for (let e of c) {
|
|
1427
|
-
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 =
|
|
1428
|
-
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" :
|
|
1541
|
+
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 = te.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) => {
|
|
1542
|
+
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" : Kt(t.data_type, t.udt_name), c = a ? {
|
|
1429
1543
|
table: a.target_table,
|
|
1430
1544
|
column: a.target_column,
|
|
1431
|
-
onDelete:
|
|
1432
|
-
onUpdate:
|
|
1545
|
+
onDelete: L(a.delete_rule),
|
|
1546
|
+
onUpdate: L(a.update_rule)
|
|
1433
1547
|
} : void 0, l = h.get(`${e.table_name}.${t.column_name}`);
|
|
1434
1548
|
return {
|
|
1435
1549
|
name: t.column_name,
|
|
1436
1550
|
type: s,
|
|
1551
|
+
...B(t.data_type, t.character_maximum_length) === void 0 ? {} : { maxLength: B(t.data_type, t.character_maximum_length) },
|
|
1437
1552
|
nullable: t.is_nullable === "YES",
|
|
1438
1553
|
unique: i.has(t.column_name) || n && t.column_name === "id",
|
|
1439
1554
|
hasDefault: t.column_default !== null,
|
|
@@ -1441,7 +1556,7 @@ BEGIN
|
|
|
1441
1556
|
...c ? { references: c } : {},
|
|
1442
1557
|
...l ? { oneOf: l } : {}
|
|
1443
1558
|
};
|
|
1444
|
-
}), l = [], u =
|
|
1559
|
+
}), l = [], u = x.get(e.table_name);
|
|
1445
1560
|
if (u) for (let [t, n] of u) {
|
|
1446
1561
|
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) => {
|
|
1447
1562
|
let t = e.position;
|
|
@@ -1457,7 +1572,7 @@ BEGIN
|
|
|
1457
1572
|
...a ? { expression: !0 } : {}
|
|
1458
1573
|
});
|
|
1459
1574
|
}
|
|
1460
|
-
for (let t of
|
|
1575
|
+
for (let t of b.get(e.table_name) ?? []) l.push(t);
|
|
1461
1576
|
r.size > 0 && l.push({
|
|
1462
1577
|
name: `${e.table_name}_pkey`,
|
|
1463
1578
|
table: e.table_name,
|
|
@@ -1465,20 +1580,20 @@ BEGIN
|
|
|
1465
1580
|
unique: !0
|
|
1466
1581
|
});
|
|
1467
1582
|
let d = Number(e.row_count ?? 0);
|
|
1468
|
-
|
|
1583
|
+
ne.push({
|
|
1469
1584
|
name: e.table_name,
|
|
1470
1585
|
columns: c,
|
|
1471
1586
|
indexes: l,
|
|
1472
1587
|
...d > 0 ? { rowCount: d } : {}
|
|
1473
1588
|
});
|
|
1474
1589
|
}
|
|
1475
|
-
return { tables:
|
|
1590
|
+
return { tables: ne };
|
|
1476
1591
|
});
|
|
1477
1592
|
return (t > 0 ? e.withTransaction(n) : n).pipe(d.catchAll((e) => {
|
|
1478
1593
|
let n = `${String(e)} ${String(e.cause ?? "")}`.toLowerCase();
|
|
1479
1594
|
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);
|
|
1480
1595
|
}));
|
|
1481
|
-
},
|
|
1596
|
+
}, $t = (e, t) => {
|
|
1482
1597
|
switch (e.toLowerCase()) {
|
|
1483
1598
|
case "varchar":
|
|
1484
1599
|
case "char":
|
|
@@ -1510,20 +1625,21 @@ BEGIN
|
|
|
1510
1625
|
case "json": return "json";
|
|
1511
1626
|
default: return "text";
|
|
1512
1627
|
}
|
|
1513
|
-
},
|
|
1628
|
+
}, R = (e) => e.map((e) => {
|
|
1514
1629
|
let t = e, n = {};
|
|
1515
1630
|
for (let e of Object.keys(t)) n[e.toLowerCase()] = t[e];
|
|
1516
1631
|
return n;
|
|
1517
|
-
}),
|
|
1518
|
-
let t =
|
|
1632
|
+
}), en = (e) => d.gen(function* () {
|
|
1633
|
+
let t = R(yield* e`
|
|
1519
1634
|
SELECT table_name, COALESCE(table_rows, 0) AS table_rows
|
|
1520
1635
|
FROM information_schema.tables
|
|
1521
1636
|
WHERE table_schema = DATABASE() AND table_type = 'BASE TABLE'
|
|
1522
|
-
ORDER BY table_name`), n =
|
|
1523
|
-
SELECT table_name, column_name, data_type, column_type, is_nullable, column_default, column_key
|
|
1637
|
+
ORDER BY table_name`), n = R(yield* e`
|
|
1638
|
+
SELECT table_name, column_name, data_type, column_type, is_nullable, column_default, column_key,
|
|
1639
|
+
character_maximum_length
|
|
1524
1640
|
FROM information_schema.columns
|
|
1525
1641
|
WHERE table_schema = DATABASE()
|
|
1526
|
-
ORDER BY table_name, ordinal_position`), r =
|
|
1642
|
+
ORDER BY table_name, ordinal_position`), r = R(yield* e`
|
|
1527
1643
|
SELECT k.table_name AS source_table,
|
|
1528
1644
|
k.column_name AS source_column,
|
|
1529
1645
|
k.referenced_table_name AS target_table,
|
|
@@ -1533,11 +1649,11 @@ BEGIN
|
|
|
1533
1649
|
JOIN information_schema.referential_constraints r
|
|
1534
1650
|
ON k.constraint_name = r.constraint_name
|
|
1535
1651
|
AND k.table_schema = r.constraint_schema
|
|
1536
|
-
WHERE k.table_schema = DATABASE() AND k.referenced_table_name IS NOT NULL`), i =
|
|
1652
|
+
WHERE k.table_schema = DATABASE() AND k.referenced_table_name IS NOT NULL`), i = R(yield* e`
|
|
1537
1653
|
SELECT table_name, index_name, non_unique, column_name, seq_in_index
|
|
1538
1654
|
FROM information_schema.statistics
|
|
1539
1655
|
WHERE table_schema = DATABASE() AND index_name <> 'PRIMARY'
|
|
1540
|
-
ORDER BY table_name, index_name, seq_in_index`), a =
|
|
1656
|
+
ORDER BY table_name, index_name, seq_in_index`), a = R(yield* e`
|
|
1541
1657
|
SELECT table_name, check_clause
|
|
1542
1658
|
FROM information_schema.check_constraints
|
|
1543
1659
|
WHERE constraint_schema = DATABASE()`.unprepared.pipe(d.orElseSucceed(() => []))), o = /* @__PURE__ */ new Set(), s = /* @__PURE__ */ new Map();
|
|
@@ -1547,7 +1663,7 @@ BEGIN
|
|
|
1547
1663
|
o.add(`${e.table_name}.${t[1]}`);
|
|
1548
1664
|
continue;
|
|
1549
1665
|
}
|
|
1550
|
-
let n =
|
|
1666
|
+
let n = Gt(e.check_clause);
|
|
1551
1667
|
n && s.set(`${e.table_name}.${n.column}`, n.values);
|
|
1552
1668
|
}
|
|
1553
1669
|
let c = /* @__PURE__ */ new Map(), l = /* @__PURE__ */ new Map(), u = /* @__PURE__ */ new Map();
|
|
@@ -1570,16 +1686,17 @@ BEGIN
|
|
|
1570
1686
|
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);
|
|
1571
1687
|
if (d) for (let e of d.values()) e.length === 1 && e[0].non_unique === 0 && a.add(e[0].column_name);
|
|
1572
1688
|
let p = t.map((t) => {
|
|
1573
|
-
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" :
|
|
1689
|
+
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" : $t(t.data_type, t.column_type), u = c ? {
|
|
1574
1690
|
table: c.target_table,
|
|
1575
1691
|
column: c.target_column,
|
|
1576
|
-
onDelete:
|
|
1577
|
-
onUpdate:
|
|
1692
|
+
onDelete: L(c.delete_rule),
|
|
1693
|
+
onUpdate: L(c.update_rule)
|
|
1578
1694
|
} : 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}`);
|
|
1579
1695
|
return {
|
|
1580
1696
|
name: t.column_name,
|
|
1581
1697
|
type: l,
|
|
1582
1698
|
nullable: t.is_nullable === "YES",
|
|
1699
|
+
...B(t.data_type, t.character_maximum_length) === void 0 ? {} : { maxLength: B(t.data_type, t.character_maximum_length) },
|
|
1583
1700
|
unique: d,
|
|
1584
1701
|
hasDefault: f !== null,
|
|
1585
1702
|
...f === null ? {} : { defaultValue: f },
|
|
@@ -1611,10 +1728,10 @@ BEGIN
|
|
|
1611
1728
|
});
|
|
1612
1729
|
}
|
|
1613
1730
|
return { tables: f };
|
|
1614
|
-
}),
|
|
1731
|
+
}), tn = (e) => {
|
|
1615
1732
|
let t = e.toUpperCase();
|
|
1616
1733
|
return t.includes("INT") ? "integer" : t.includes("REAL") || t.includes("FLOA") || t.includes("DOUB") ? "real" : t.includes("BLOB") ? "bytes" : "text";
|
|
1617
|
-
},
|
|
1734
|
+
}, nn = (e) => d.gen(function* () {
|
|
1618
1735
|
let t = yield* e`
|
|
1619
1736
|
SELECT name, sql FROM sqlite_master
|
|
1620
1737
|
WHERE type = 'table' AND name NOT LIKE 'sqlite_%'
|
|
@@ -1631,11 +1748,11 @@ BEGIN
|
|
|
1631
1748
|
d.set(t.name, r), t.unique === 1 && r.length === 1 && f.add(r[0]);
|
|
1632
1749
|
}
|
|
1633
1750
|
let p = o.map((e) => {
|
|
1634
|
-
let n = u.length === 1 && u[0] === e.name, r = l.get(e.name), i = r ? "reference" : n && e.name === "id" ? "id" :
|
|
1751
|
+
let n = u.length === 1 && u[0] === e.name, r = l.get(e.name), i = r ? "reference" : n && e.name === "id" ? "id" : tn(e.type), a = r ? {
|
|
1635
1752
|
table: r.table,
|
|
1636
1753
|
column: r.to,
|
|
1637
|
-
onDelete:
|
|
1638
|
-
onUpdate:
|
|
1754
|
+
onDelete: L(r.on_delete),
|
|
1755
|
+
onUpdate: L(r.on_update)
|
|
1639
1756
|
} : void 0, o = t.get(e.name);
|
|
1640
1757
|
return {
|
|
1641
1758
|
name: e.name,
|
|
@@ -1670,7 +1787,7 @@ BEGIN
|
|
|
1670
1787
|
});
|
|
1671
1788
|
}
|
|
1672
1789
|
return { tables: r };
|
|
1673
|
-
}),
|
|
1790
|
+
}), rn = (e) => {
|
|
1674
1791
|
switch (e.toLowerCase()) {
|
|
1675
1792
|
case "int":
|
|
1676
1793
|
case "smallint":
|
|
@@ -1692,12 +1809,13 @@ BEGIN
|
|
|
1692
1809
|
case "image": return "bytes";
|
|
1693
1810
|
default: return "text";
|
|
1694
1811
|
}
|
|
1695
|
-
},
|
|
1812
|
+
}, z = (e) => e === !0 || e === 1, an = (e) => d.gen(function* () {
|
|
1696
1813
|
let t = yield* e`
|
|
1697
1814
|
SELECT TABLE_NAME AS table_name FROM INFORMATION_SCHEMA.TABLES
|
|
1698
1815
|
WHERE TABLE_TYPE = 'BASE TABLE' ORDER BY TABLE_NAME`, n = yield* e`
|
|
1699
1816
|
SELECT TABLE_NAME AS table_name, COLUMN_NAME AS column_name, DATA_TYPE AS data_type,
|
|
1700
|
-
IS_NULLABLE AS is_nullable, COLUMN_DEFAULT AS column_default
|
|
1817
|
+
IS_NULLABLE AS is_nullable, COLUMN_DEFAULT AS column_default,
|
|
1818
|
+
CHARACTER_MAXIMUM_LENGTH AS character_maximum_length
|
|
1701
1819
|
FROM INFORMATION_SCHEMA.COLUMNS ORDER BY TABLE_NAME, ORDINAL_POSITION`, r = yield* e`
|
|
1702
1820
|
SELECT st.name AS source_table, sc.name AS source_column,
|
|
1703
1821
|
tt.name AS target_table, tc.name AS target_column,
|
|
@@ -1748,20 +1866,21 @@ BEGIN
|
|
|
1748
1866
|
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();
|
|
1749
1867
|
if (a) for (let [, e] of a) {
|
|
1750
1868
|
let t = [...e].sort((e, t) => e.key_ordinal - t.key_ordinal);
|
|
1751
|
-
if (
|
|
1752
|
-
else
|
|
1869
|
+
if (z(t[0].is_primary)) for (let e of t) d.push(e.column_name);
|
|
1870
|
+
else z(t[0].is_unique) && t.length === 1 && f.add(t[0].column_name);
|
|
1753
1871
|
}
|
|
1754
1872
|
let p = t.map((t) => {
|
|
1755
|
-
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" :
|
|
1873
|
+
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" : rn(t.data_type), s = i ? {
|
|
1756
1874
|
table: i.target_table,
|
|
1757
1875
|
column: i.target_column,
|
|
1758
|
-
onDelete:
|
|
1759
|
-
onUpdate:
|
|
1760
|
-
} : void 0, c = t.column_default === null ? null :
|
|
1876
|
+
onDelete: on(i.delete_rule),
|
|
1877
|
+
onUpdate: on(i.update_rule)
|
|
1878
|
+
} : void 0, c = t.column_default === null ? null : sn(t.column_default), l = o.get(`${e}.${t.column_name}`);
|
|
1761
1879
|
return {
|
|
1762
1880
|
name: t.column_name,
|
|
1763
1881
|
type: a,
|
|
1764
1882
|
nullable: t.is_nullable === "YES",
|
|
1883
|
+
...B(t.data_type, t.character_maximum_length) === void 0 ? {} : { maxLength: B(t.data_type, t.character_maximum_length) },
|
|
1765
1884
|
unique: f.has(t.column_name) || n && t.column_name === "id",
|
|
1766
1885
|
hasDefault: c !== null,
|
|
1767
1886
|
...c === null ? {} : { defaultValue: c },
|
|
@@ -1771,11 +1890,11 @@ BEGIN
|
|
|
1771
1890
|
}), m = [];
|
|
1772
1891
|
if (a) for (let [t, n] of a) {
|
|
1773
1892
|
let r = [...n].sort((e, t) => e.key_ordinal - t.key_ordinal);
|
|
1774
|
-
|
|
1893
|
+
z(r[0].is_primary) || r.length === 1 && z(r[0].is_unique) || r.length === 1 && !z(r[0].is_unique) && i.has(r[0].column_name) && t !== `${e}_${r[0].column_name}_idx` || m.push({
|
|
1775
1894
|
name: t,
|
|
1776
1895
|
table: e,
|
|
1777
1896
|
columns: r.map((e) => e.column_name),
|
|
1778
|
-
unique:
|
|
1897
|
+
unique: z(r[0].is_unique)
|
|
1779
1898
|
});
|
|
1780
1899
|
}
|
|
1781
1900
|
d.length > 0 && m.push({
|
|
@@ -1790,37 +1909,48 @@ BEGIN
|
|
|
1790
1909
|
});
|
|
1791
1910
|
}
|
|
1792
1911
|
return { tables: u };
|
|
1793
|
-
}),
|
|
1912
|
+
}), on = (e) => {
|
|
1794
1913
|
switch (e.toUpperCase().replace(/_/g, " ")) {
|
|
1795
1914
|
case "CASCADE": return "cascade";
|
|
1796
1915
|
case "SET NULL": return "setNull";
|
|
1797
1916
|
case "SET DEFAULT": return "noAction";
|
|
1798
1917
|
default: return "noAction";
|
|
1799
1918
|
}
|
|
1800
|
-
},
|
|
1919
|
+
}, sn = (e) => {
|
|
1801
1920
|
let t = e.trim();
|
|
1802
1921
|
for (; t.startsWith("(") && t.endsWith(")");) t = t.slice(1, -1).trim();
|
|
1803
1922
|
return t.startsWith("N'") && t.endsWith("'") ? t = t.slice(2, -1) : t.startsWith("'") && t.endsWith("'") && (t = t.slice(1, -1)), t;
|
|
1923
|
+
}, cn = /* @__PURE__ */ new Set([
|
|
1924
|
+
"character varying",
|
|
1925
|
+
"varchar",
|
|
1926
|
+
"nvarchar",
|
|
1927
|
+
"char",
|
|
1928
|
+
"character",
|
|
1929
|
+
"nchar"
|
|
1930
|
+
]), B = (e, t) => {
|
|
1931
|
+
if (!cn.has(e.toLowerCase())) return;
|
|
1932
|
+
let n = Number(t);
|
|
1933
|
+
if (!(!Number.isFinite(n) || n <= 0)) return n;
|
|
1804
1934
|
}, V = (e) => e.onDialectOrElse({
|
|
1805
|
-
mysql: () =>
|
|
1806
|
-
mssql: () =>
|
|
1807
|
-
sqlite: () =>
|
|
1808
|
-
orElse: () =>
|
|
1809
|
-
}),
|
|
1810
|
-
if (!e.spatial && e.type !== "vector" && e.type !== "array" && e.type !== "enum") return;
|
|
1935
|
+
mysql: () => en(e),
|
|
1936
|
+
mssql: () => an(e),
|
|
1937
|
+
sqlite: () => nn(e),
|
|
1938
|
+
orElse: () => Qt(e)
|
|
1939
|
+
}), ln = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, H = (e, t) => {
|
|
1940
|
+
if (!(e.type === "text" && e.maxLength !== void 0) && !e.spatial && e.type !== "vector" && e.type !== "array" && e.type !== "enum") return;
|
|
1811
1941
|
let n = e.type === "vector" && e.vectorDim === void 0 ? "vector dimension" : e.type === "array" && e.arrayElement === void 0 ? "array element type" : e.type === "enum" && e.enumName === void 0 && e.enumValues === void 0 ? "enum name/values" : void 0;
|
|
1812
1942
|
if (n !== void 0) throw Error(`migration applier: cannot render '${e.name}' (${e.type}) — the schema snapshot carries no ${n}. Rendering it as 'text' would emit DDL that applies successfully and changes nothing, so this fails instead. This is a framework bug: declaredSchema.ts must carry the parameter into the ColumnSnapshot.`);
|
|
1813
|
-
return
|
|
1943
|
+
return E(e, t);
|
|
1814
1944
|
}, U = (e) => {
|
|
1815
1945
|
let t = H(e, "postgres");
|
|
1816
|
-
return t === void 0 ?
|
|
1817
|
-
},
|
|
1946
|
+
return t === void 0 ? un(e) : t;
|
|
1947
|
+
}, un = (e) => {
|
|
1818
1948
|
switch (e.type) {
|
|
1819
1949
|
case "id": return "text";
|
|
1820
1950
|
case "text": return "text";
|
|
1821
1951
|
case "integer": return "integer";
|
|
1822
1952
|
case "real": return "double precision";
|
|
1823
|
-
case "decimal": return
|
|
1953
|
+
case "decimal": return ln(e, "NUMERIC");
|
|
1824
1954
|
case "bigint": return "bigint";
|
|
1825
1955
|
case "boolean": return "boolean";
|
|
1826
1956
|
case "timestamp": return "timestamptz";
|
|
@@ -1842,7 +1972,7 @@ BEGIN
|
|
|
1842
1972
|
case "text": return e.hasDefault && e.defaultValue !== void 0 || e.oneOf && e.oneOf.length > 0 ? "VARCHAR(255)" : "LONGTEXT";
|
|
1843
1973
|
case "integer": return "INT";
|
|
1844
1974
|
case "real": return "DOUBLE";
|
|
1845
|
-
case "decimal": return
|
|
1975
|
+
case "decimal": return ln(e, "DECIMAL");
|
|
1846
1976
|
case "bigint": return "BIGINT";
|
|
1847
1977
|
case "boolean": return "TINYINT(1)";
|
|
1848
1978
|
case "timestamp": return "DATETIME(6)";
|
|
@@ -1856,32 +1986,32 @@ BEGIN
|
|
|
1856
1986
|
case "interval": return "BIGINT";
|
|
1857
1987
|
case "raw": return e.rawDdl ?? "LONGTEXT";
|
|
1858
1988
|
}
|
|
1859
|
-
}, G = (e) => `"${e}"`, K = (e) => `\`${e.replace(/`/g, "``")}\``,
|
|
1989
|
+
}, G = (e) => `"${e}"`, K = (e) => `\`${e.replace(/`/g, "``")}\``, dn = (e, t) => `ALTER TABLE ${t(e.table)} DROP COLUMN IF EXISTS ${t(e.column)};`, fn = (e) => `ALTER TABLE ${K(e.table)} DROP COLUMN IF EXISTS ${K(e.column)}, ALGORITHM=COPY;`, pn = (e, t) => `ALTER TABLE ${t(e.table)} RENAME COLUMN ${t(e.from)} TO ${t(e.to)};`, mn = (e, t, n) => `ALTER TABLE ${n(e.table)} RENAME COLUMN ${n(e.column)} TO ${n(`${e.column}${zn(t)}`)};`, hn = (e, t, n) => e.hasDefault && e.defaultValue !== void 0 ? `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} SET ${gn(e, n)};` : `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} DROP DEFAULT;`, gn = (e, t) => {
|
|
1860
1990
|
let n = t(e.defaultValue);
|
|
1861
1991
|
if (n === null) throw Error(`migration applier: cannot render the declared default for '${e.table}.${e.column}' (${JSON.stringify(e.defaultValue)}). Emitting 'DEFAULT NULL' would apply cleanly and drop the default silently, so this fails instead. This is a framework bug — report the column type + default.`);
|
|
1862
1992
|
return n;
|
|
1863
|
-
}, q = (e, t, n) => e.find((e) => e.tableName === t)?.fields[n],
|
|
1993
|
+
}, q = (e, t, n) => e.find((e) => e.tableName === t)?.fields[n], _n = (e, t, n) => {
|
|
1864
1994
|
let r = q(e, t, n);
|
|
1865
1995
|
return r ? nt(n, r) : void 0;
|
|
1866
|
-
},
|
|
1867
|
-
let r = n ?? e.nullable, i =
|
|
1996
|
+
}, vn = (e, t, n) => {
|
|
1997
|
+
let r = n ?? e.nullable, i = ye(e, "mariadb");
|
|
1868
1998
|
return [
|
|
1869
1999
|
K(t),
|
|
1870
|
-
|
|
2000
|
+
E(e, "mariadb"),
|
|
1871
2001
|
r ? null : "NOT NULL",
|
|
1872
2002
|
i
|
|
1873
2003
|
].filter(Boolean).join(" ");
|
|
1874
|
-
},
|
|
2004
|
+
}, yn = (e, t) => e == null ? null : Array.isArray(e) ? bn(e, t, "mariadb") : e === "now" ? "DEFAULT CURRENT_TIMESTAMP(6)" : typeof e == "boolean" ? `DEFAULT ${+!!e}` : typeof e == "number" ? `DEFAULT ${e}` : typeof e == "string" ? /[()]|^'/.test(e) ? `DEFAULT ${e}` : `DEFAULT '${e.replace(/'/g, "''")}'` : typeof e == "object" ? D(e, "mysql") : null, bn = (e, t, n) => be(e, t ?? { type: "json" }, n), xn = (e, t) => e == null ? null : Array.isArray(e) ? bn(e, t, "postgres") : e === "now" ? "DEFAULT now()" : typeof e == "boolean" || typeof e == "number" ? `DEFAULT ${e}` : typeof e == "string" ? /[()]|::|^'/.test(e) ? `DEFAULT ${e}` : `DEFAULT '${e.replace(/'/g, "''")}'` : typeof e == "object" ? D(e, "postgres") : null, J = (e, t) => {
|
|
1875
2005
|
if (!e.generatedAs) return null;
|
|
1876
2006
|
let { expr: n, stored: r } = e.generatedAs;
|
|
1877
2007
|
return t === "postgres" ? `GENERATED ALWAYS AS (${n}) STORED` : t === "mssql" ? `AS (${n})${r ? " PERSISTED" : ""}` : `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
|
|
1878
|
-
},
|
|
1879
|
-
if (e.type === "id" && e.idScheme?.kind === "numeric") return
|
|
2008
|
+
}, Sn = (e) => {
|
|
2009
|
+
if (e.type === "id" && e.idScheme?.kind === "numeric") return O(e.name, "postgres");
|
|
1880
2010
|
let t = J(e, "postgres");
|
|
1881
2011
|
if (t) return `${G(e.name)} ${U(e)} ${t}`;
|
|
1882
2012
|
let n = [G(e.name), U(e)];
|
|
1883
2013
|
if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && n.push("UNIQUE"), e.hasDefault) {
|
|
1884
|
-
let t =
|
|
2014
|
+
let t = xn(e.defaultValue, e);
|
|
1885
2015
|
t && n.push(t);
|
|
1886
2016
|
}
|
|
1887
2017
|
return e.references && (n.push(`REFERENCES ${G(e.references.table)} (${G(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${{
|
|
@@ -1890,20 +2020,20 @@ BEGIN
|
|
|
1890
2020
|
setNull: "SET NULL",
|
|
1891
2021
|
noAction: "NO ACTION"
|
|
1892
2022
|
}[e.references.onDelete]}`)), n.join(" ");
|
|
1893
|
-
},
|
|
1894
|
-
let t = e.columns.map((e) => ` ${
|
|
1895
|
-
for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${G(t.name)} ON ${G(e.table)} (${t.columns.map(
|
|
2023
|
+
}, Cn = (e, t) => e.primaryKey && e.primaryKey.length > 0 ? `,\n PRIMARY KEY (${e.primaryKey.map(t).join(", ")})` : "", wn = (e) => {
|
|
2024
|
+
let t = e.columns.map((e) => ` ${Sn(e)}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${G(e.table)} (\n${t}${Cn(e, G)}\n)`];
|
|
2025
|
+
for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${G(t.name)} ON ${G(e.table)} (${t.columns.map(Wn).join(", ")})`);
|
|
1896
2026
|
return n;
|
|
1897
|
-
},
|
|
2027
|
+
}, Tn = 191, En = (e) => {
|
|
1898
2028
|
let t = W(e).toUpperCase();
|
|
1899
2029
|
return t.endsWith("TEXT") || t.endsWith("BLOB");
|
|
1900
|
-
},
|
|
1901
|
-
if (e.type === "id" && e.idScheme?.kind === "numeric") return
|
|
2030
|
+
}, Dn = (e) => {
|
|
2031
|
+
if (e.type === "id" && e.idScheme?.kind === "numeric") return O(e.name, "mariadb");
|
|
1902
2032
|
let t = J(e, "mariadb");
|
|
1903
2033
|
if (t) return `${K(e.name)} ${W(e)} ${t}`;
|
|
1904
2034
|
let n = [K(e.name), W(e)];
|
|
1905
|
-
if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && !
|
|
1906
|
-
let t =
|
|
2035
|
+
if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && !En(e) && n.push("UNIQUE"), e.hasDefault) {
|
|
2036
|
+
let t = yn(e.defaultValue, e);
|
|
1907
2037
|
t && n.push(t);
|
|
1908
2038
|
}
|
|
1909
2039
|
return e.references && (n.push(`REFERENCES ${K(e.references.table)} (${K(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${{
|
|
@@ -1912,25 +2042,25 @@ BEGIN
|
|
|
1912
2042
|
setNull: "SET NULL",
|
|
1913
2043
|
noAction: "NO ACTION"
|
|
1914
2044
|
}[e.references.onDelete]}`)), n.join(" ");
|
|
1915
|
-
},
|
|
2045
|
+
}, On = (e) => {
|
|
1916
2046
|
let t = new Map(e.columns.map((e) => [e.name, e])), n = (e) => {
|
|
1917
2047
|
let n = t.get(e);
|
|
1918
|
-
return n &&
|
|
1919
|
-
}, r = e.columns.map((e) => ` ${
|
|
1920
|
-
for (let t of e.columns) t.unique && t.type !== "id" &&
|
|
2048
|
+
return n && En(n) ? `${K(e)}(${Tn})` : K(e);
|
|
2049
|
+
}, r = e.columns.map((e) => ` ${Dn(e)}`).join(",\n"), i = [`CREATE TABLE IF NOT EXISTS ${K(e.table)} (\n${r}${Cn(e, n)}\n)`];
|
|
2050
|
+
for (let t of e.columns) t.unique && t.type !== "id" && En(t) && i.push(`CREATE UNIQUE INDEX IF NOT EXISTS ${K(`${e.table}_${t.name}_key`)} ON ${K(e.table)} (${n(t.name)})`);
|
|
1921
2051
|
for (let t of e.indexes) t.name !== `${e.table}_pkey` && i.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${K(t.name)} ON ${K(e.table)} (${t.columns.map(n).join(", ")})`);
|
|
1922
2052
|
return i;
|
|
1923
|
-
},
|
|
2053
|
+
}, kn = {
|
|
1924
2054
|
cascade: "CASCADE",
|
|
1925
2055
|
restrict: "RESTRICT",
|
|
1926
2056
|
setNull: "SET NULL",
|
|
1927
2057
|
noAction: "NO ACTION"
|
|
1928
|
-
},
|
|
2058
|
+
}, An = {
|
|
1929
2059
|
cascade: "CASCADE",
|
|
1930
2060
|
restrict: "NO ACTION",
|
|
1931
2061
|
setNull: "SET NULL",
|
|
1932
2062
|
noAction: "NO ACTION"
|
|
1933
|
-
},
|
|
2063
|
+
}, jn = (e) => {
|
|
1934
2064
|
let t = H(e, "sqlite");
|
|
1935
2065
|
if (t !== void 0) return t;
|
|
1936
2066
|
switch (e.type) {
|
|
@@ -1942,29 +2072,29 @@ BEGIN
|
|
|
1942
2072
|
case "bytes": return "BLOB";
|
|
1943
2073
|
default: return "TEXT";
|
|
1944
2074
|
}
|
|
1945
|
-
}, 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" ?
|
|
1946
|
-
if (e.type === "id" && e.idScheme?.kind === "numeric") return
|
|
2075
|
+
}, 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" ? D(e, "sqlite") : null, Mn = (e) => {
|
|
2076
|
+
if (e.type === "id" && e.idScheme?.kind === "numeric") return O(e.name, "sqlite");
|
|
1947
2077
|
let t = J(e, "sqlite");
|
|
1948
|
-
if (t) return `${G(e.name)} ${
|
|
1949
|
-
let n = [G(e.name),
|
|
2078
|
+
if (t) return `${G(e.name)} ${jn(e)} ${t}`;
|
|
2079
|
+
let n = [G(e.name), jn(e)];
|
|
1950
2080
|
if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && n.push("UNIQUE"), e.hasDefault) {
|
|
1951
2081
|
let t = Y(e.defaultValue, "CURRENT_TIMESTAMP");
|
|
1952
2082
|
t && n.push(t);
|
|
1953
2083
|
}
|
|
1954
|
-
if (e.references && (n.push(`REFERENCES ${G(e.references.table)} (${G(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${
|
|
2084
|
+
if (e.references && (n.push(`REFERENCES ${G(e.references.table)} (${G(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${kn[e.references.onDelete]}`)), e.oneOf && e.oneOf.length > 0) {
|
|
1955
2085
|
let t = e.oneOf.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
|
|
1956
2086
|
n.push(`CHECK (${G(e.name)} IN (${t}))`);
|
|
1957
2087
|
}
|
|
1958
2088
|
return n.join(" ");
|
|
1959
|
-
},
|
|
1960
|
-
let t = e.columns.map((e) => ` ${
|
|
2089
|
+
}, Nn = (e) => {
|
|
2090
|
+
let t = e.columns.map((e) => ` ${Mn(e)}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${G(e.table)} (\n${t}${Cn(e, G)}\n)`];
|
|
1961
2091
|
for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${G(t.name)} ON ${G(e.table)} (${t.columns.map(G).join(", ")})`);
|
|
1962
2092
|
return n;
|
|
1963
2093
|
}, X = (e, t) => {
|
|
1964
2094
|
let n = t.find((t) => t.tableName === e);
|
|
1965
2095
|
if (!n) return [];
|
|
1966
2096
|
let r = N([n]).tables[0], i = `${e}__voltro_rebuild`, a = r.columns.map((e) => G(e.name)).join(", "), o = [
|
|
1967
|
-
...
|
|
2097
|
+
...Nn({
|
|
1968
2098
|
kind: "create-table",
|
|
1969
2099
|
table: i,
|
|
1970
2100
|
columns: r.columns,
|
|
@@ -1977,17 +2107,17 @@ BEGIN
|
|
|
1977
2107
|
];
|
|
1978
2108
|
for (let t of r.indexes) t.name !== `${e}_pkey` && o.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${G(t.name)} ON ${G(e)} (${t.columns.map(G).join(", ")})`);
|
|
1979
2109
|
return o;
|
|
1980
|
-
},
|
|
2110
|
+
}, Pn = (e, t, n, r) => {
|
|
1981
2111
|
let i = r ?? e.nullable;
|
|
1982
|
-
return `ALTER TABLE ${Z(n)} ALTER COLUMN ${Z(t)} ${
|
|
1983
|
-
},
|
|
2112
|
+
return `ALTER TABLE ${Z(n)} ALTER COLUMN ${Z(t)} ${E(e, "mssql")} ${i ? "NULL" : "NOT NULL"};`;
|
|
2113
|
+
}, Fn = (e) => {
|
|
1984
2114
|
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 + ']');`;
|
|
1985
2115
|
if (!e.hasDefault) return t;
|
|
1986
2116
|
let n = Y(e.defaultValue, "SYSUTCDATETIME()");
|
|
1987
2117
|
if (!n) return t;
|
|
1988
2118
|
let r = n.replace(/^DEFAULT\s+/i, "");
|
|
1989
2119
|
return `${t} ALTER TABLE ${Z(e.table)} ADD DEFAULT ${r} FOR ${Z(e.column)};`;
|
|
1990
|
-
}, Z = (e) => `[${e.replace(/]/g, "]]")}]`,
|
|
2120
|
+
}, Z = (e) => `[${e.replace(/]/g, "]]")}]`, In = (e) => {
|
|
1991
2121
|
let t = H(e, "mssql");
|
|
1992
2122
|
if (t !== void 0) return t;
|
|
1993
2123
|
switch (e.type) {
|
|
@@ -1995,7 +2125,7 @@ BEGIN
|
|
|
1995
2125
|
case "reference": return "NVARCHAR(64)";
|
|
1996
2126
|
case "integer": return "INT";
|
|
1997
2127
|
case "real": return "FLOAT";
|
|
1998
|
-
case "decimal": return
|
|
2128
|
+
case "decimal": return ln(e, "DECIMAL");
|
|
1999
2129
|
case "bigint": return "BIGINT";
|
|
2000
2130
|
case "boolean": return "BIT";
|
|
2001
2131
|
case "timestamp": return "DATETIME2(6)";
|
|
@@ -2003,34 +2133,40 @@ BEGIN
|
|
|
2003
2133
|
case "bytes": return "VARBINARY(MAX)";
|
|
2004
2134
|
default: return "NVARCHAR(MAX)";
|
|
2005
2135
|
}
|
|
2006
|
-
},
|
|
2007
|
-
if (e.type === "id" && e.idScheme?.kind === "numeric") return
|
|
2008
|
-
let n = e.type === "text" && t?.has(e.name) ? "NVARCHAR(450)" :
|
|
2136
|
+
}, Ln = (e, t) => {
|
|
2137
|
+
if (e.type === "id" && e.idScheme?.kind === "numeric") return O(e.name, "mssql");
|
|
2138
|
+
let n = e.type === "text" && t?.has(e.name) ? "NVARCHAR(450)" : In(e), r = J(e, "mssql");
|
|
2009
2139
|
if (r) return `${Z(e.name)} ${r}`;
|
|
2010
2140
|
let i = [Z(e.name), n];
|
|
2011
2141
|
if (e.type === "id" && i.push("PRIMARY KEY"), e.nullable || i.push("NOT NULL"), e.unique && e.type !== "id" && i.push("UNIQUE"), e.hasDefault) {
|
|
2012
2142
|
let t = Y(e.defaultValue, "SYSUTCDATETIME()");
|
|
2013
2143
|
t && i.push(t);
|
|
2014
2144
|
}
|
|
2015
|
-
return e.references && (i.push(`REFERENCES ${Z(e.references.table)} (${Z(e.references.column)})`), e.references.onDelete && i.push(`ON DELETE ${
|
|
2016
|
-
},
|
|
2017
|
-
let t = (e) => e.replace(/'/g, "''"), n = new Set(e.indexes.flatMap((e) => e.columns)), r = e.columns.map((e) => ` ${
|
|
2145
|
+
return e.references && (i.push(`REFERENCES ${Z(e.references.table)} (${Z(e.references.column)})`), e.references.onDelete && i.push(`ON DELETE ${An[e.references.onDelete]}`)), i.join(" ");
|
|
2146
|
+
}, Rn = (e) => {
|
|
2147
|
+
let t = (e) => e.replace(/'/g, "''"), n = new Set(e.indexes.flatMap((e) => e.columns)), r = e.columns.map((e) => ` ${Ln(e, n)}`).join(",\n"), i = `CREATE TABLE ${Z(e.table)} (\n${r}${Cn(e, Z)}\n)`, a = [`IF OBJECT_ID(N'${t(e.table)}', N'U') IS NULL EXEC(N'${t(i)}')`];
|
|
2018
2148
|
for (let n of e.indexes) {
|
|
2019
2149
|
if (n.name === `${e.table}_pkey`) continue;
|
|
2020
2150
|
let r = `CREATE ${n.unique ? "UNIQUE " : ""}INDEX ${Z(n.name)} ON ${Z(e.table)} (${n.columns.map(Z).join(", ")})`;
|
|
2021
2151
|
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)}')`);
|
|
2022
2152
|
}
|
|
2023
2153
|
return a;
|
|
2024
|
-
},
|
|
2025
|
-
let r = `${e.table}${
|
|
2154
|
+
}, zn = (e) => `__dropped_${e.replace(/[-:T.Z]/g, "").slice(0, 14)}`, Bn = (e, t) => `DROP TABLE IF EXISTS ${t(e.table)};`, Vn = (e, t, n) => {
|
|
2155
|
+
let r = `${e.table}${zn(t)}`;
|
|
2026
2156
|
return `ALTER TABLE ${n(e.table)} RENAME TO ${n(r)};`;
|
|
2027
|
-
},
|
|
2157
|
+
}, Hn = (e, t, n) => {
|
|
2028
2158
|
let r = q(e, t, n);
|
|
2029
|
-
return r ?
|
|
2030
|
-
},
|
|
2159
|
+
return r ? En({ type: r.type }) : !1;
|
|
2160
|
+
}, Un = (e, t, n) => Hn(e, t, n) ? `${K(n)}(${Tn})` : K(n), Wn = (e) => e.startsWith("(") ? e : G(e), Gn = (e, t) => `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX ${t ? "CONCURRENTLY " : ""}IF NOT EXISTS ${G(e.index.name)} ON ${G(e.table)} (${e.index.columns.map(Wn).join(", ")});`, Kn = (e, t) => `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${K(e.index.name)} ON ${K(e.table)} (${e.index.columns.map((n) => Un(t, e.table, n)).join(", ")});`, qn = (e) => `DROP INDEX IF EXISTS ${G(e.index)};`, Jn = (e) => `DROP INDEX ${K(e.index)} ON ${K(e.table)};`, Yn = (e) => `DROP INDEX IF EXISTS ${Z(e.index)} ON ${Z(e.table)};`, Xn = (e, t) => `ALTER TABLE ${t(e.from)} RENAME TO ${t(e.to)};`, Zn = (e) => {
|
|
2161
|
+
let t = (e) => e.replace(/'/g, "''");
|
|
2162
|
+
return `EXEC sp_rename N'${t(e.from)}', N'${t(e.to)}';`;
|
|
2163
|
+
}, Qn = (e) => `ALTER INDEX ${G(e.from)} RENAME TO ${G(e.to)};`, $n = (e) => `ALTER TABLE ${K(e.table)} RENAME INDEX ${K(e.from)} TO ${K(e.to)};`, er = (e) => {
|
|
2164
|
+
let t = (e) => e.replace(/'/g, "''");
|
|
2165
|
+
return `EXEC sp_rename N'${t(e.table)}.${t(e.from)}', N'${t(e.to)}', N'INDEX';`;
|
|
2166
|
+
}, tr = (e) => {
|
|
2031
2167
|
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(", ")})`;
|
|
2032
2168
|
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)}');`;
|
|
2033
|
-
},
|
|
2169
|
+
}, nr = (e, t, n) => {
|
|
2034
2170
|
let r = n.find((t) => t.tableName === e);
|
|
2035
2171
|
if (!r) return [];
|
|
2036
2172
|
let i = [];
|
|
@@ -2039,13 +2175,13 @@ BEGIN
|
|
|
2039
2175
|
t && t.type === "text" && !t.generatedAs && i.push(`ALTER TABLE ${Z(e)} ALTER COLUMN ${Z(n)} NVARCHAR(450) ${t.nullable ? "NULL" : "NOT NULL"};`);
|
|
2040
2176
|
}
|
|
2041
2177
|
return i;
|
|
2042
|
-
},
|
|
2178
|
+
}, rr = (e) => `ALTER TABLE ${G(e.table)} ADD CONSTRAINT ${G(`${e.table}_${e.column}_key`)} UNIQUE (${G(e.column)});`, ir = (e, t) => `ALTER TABLE ${K(e.table)} ADD CONSTRAINT ${K(`${e.table}_${e.column}_key`)} UNIQUE (${Un(t, e.table, e.column)});`, ar = (e) => {
|
|
2043
2179
|
let t = e.fields.map((e) => G(e)).join(", ");
|
|
2044
2180
|
return `ALTER TABLE ${G(e.table)} ADD CONSTRAINT ${G(e.name)} UNIQUE (${t});`;
|
|
2045
|
-
},
|
|
2046
|
-
let n = e.fields.map((n) =>
|
|
2181
|
+
}, or = (e, t) => {
|
|
2182
|
+
let n = e.fields.map((n) => Un(t, e.table, n)).join(", ");
|
|
2047
2183
|
return `ALTER TABLE ${K(e.table)} ADD CONSTRAINT ${K(e.name)} UNIQUE (${n});`;
|
|
2048
|
-
},
|
|
2184
|
+
}, sr = (e) => `ALTER TABLE ${G(e.table)} DROP CONSTRAINT IF EXISTS ${G(e.name)};`, cr = (e) => `ALTER TABLE ${K(e.table)} DROP INDEX ${K(e.name)};`, lr = (e) => `ALTER TABLE ${G(e.table)} DROP CONSTRAINT IF EXISTS ${G(`${e.table}_${e.column}_key`)};`, ur = (e) => `ALTER TABLE ${K(e.table)} DROP INDEX ${K(`${e.table}_${e.column}_key`)};`, dr = (e, t) => {
|
|
2049
2185
|
let n = [], r = t(e.table), i = t(e.column), a = t(e.targetTable), o = t(e.targetColumn);
|
|
2050
2186
|
if (e.orphanPolicy) {
|
|
2051
2187
|
let t = `${i} IS NOT NULL AND ${i} NOT IN (SELECT ${o} FROM ${a})`;
|
|
@@ -2063,11 +2199,11 @@ BEGIN
|
|
|
2063
2199
|
setNull: "SET NULL",
|
|
2064
2200
|
noAction: "NO ACTION"
|
|
2065
2201
|
}[e.onDelete]}`), n.push(s.join(" ") + ";"), n;
|
|
2066
|
-
},
|
|
2202
|
+
}, fr = (e) => `ALTER TABLE ${G(e.table)} DROP CONSTRAINT IF EXISTS ${G(`${e.table}_${e.column}_fkey`)};`, pr = (e) => `ALTER TABLE ${K(e.table)} DROP FOREIGN KEY ${K(`${e.table}_${e.column}_fkey`)};`, mr = (e, t) => {
|
|
2067
2203
|
let n = e.values.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
|
|
2068
2204
|
return `ALTER TABLE ${t(e.table)} ADD CONSTRAINT ${t(`${e.table}_${e.column}_check`)} CHECK (${t(e.column)} IN (${n}));`;
|
|
2069
|
-
},
|
|
2070
|
-
let i = e.column, a = r === "mariadb", o = a ? K : r === "mssql" ? Z : G, s = a ? W(i) : r === "mssql" ?
|
|
2205
|
+
}, hr = (e) => `ALTER TABLE ${G(e.table)} DROP CONSTRAINT IF EXISTS ${G(`${e.table}_${e.column}_check`)};`, gr = (e) => `ALTER TABLE ${K(e.table)} DROP CHECK ${K(`${e.table}_${e.column}_check`)};`, _r = (e, t, n, r) => {
|
|
2206
|
+
let i = e.column, a = r === "mariadb", o = a ? K : r === "mssql" ? Z : G, s = a ? W(i) : r === "mssql" ? In(i) : r === "sqlite" ? jn(i) : U(i), c = r === "mssql" ? "ADD" : "ADD COLUMN", l = (e) => a ? yn(e, i) : r === "mssql" ? Y(e, "SYSUTCDATETIME()") : r === "sqlite" ? Y(e, "CURRENT_TIMESTAMP") : xn(e, i), u = J(i, r);
|
|
2071
2207
|
if (u) {
|
|
2072
2208
|
let t = r === "mssql" ? `${o(i.name)} ${u}` : `${o(i.name)} ${s} ${u}`;
|
|
2073
2209
|
return {
|
|
@@ -2095,7 +2231,7 @@ BEGIN
|
|
|
2095
2231
|
post: f ? [f] : []
|
|
2096
2232
|
};
|
|
2097
2233
|
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;
|
|
2098
|
-
},
|
|
2234
|
+
}, vr = (e) => {
|
|
2099
2235
|
let t = new Map(e.map((e) => [e.tableName, e]));
|
|
2100
2236
|
return (e, n) => {
|
|
2101
2237
|
let r = t.get(e);
|
|
@@ -2120,21 +2256,21 @@ BEGIN
|
|
|
2120
2256
|
})), d.mapError((e) => {
|
|
2121
2257
|
let r = _(`applier: statement failed (op=${n})`, t, e, 400).trim();
|
|
2122
2258
|
return Object.assign(e, { message: r });
|
|
2123
|
-
}), d.map(() => void 0)), $ = (e, t, n) => d.forEach(t, (t) => Q(e, t, n), { discard: !0 }),
|
|
2124
|
-
let r = process.hrtime.bigint(), i =
|
|
2259
|
+
}), d.map(() => void 0)), $ = (e, t, n) => d.forEach(t, (t) => Q(e, t, n), { discard: !0 }), yr = (e, t, n) => d.gen(function* () {
|
|
2260
|
+
let r = process.hrtime.bigint(), i = vr(n.declared), a = t.op;
|
|
2125
2261
|
switch (a.kind) {
|
|
2126
2262
|
case "create-table": {
|
|
2127
2263
|
let t = yield* e.onDialectOrElse({
|
|
2128
|
-
mysql: () => d.succeed(
|
|
2129
|
-
mssql: () => d.succeed(
|
|
2130
|
-
sqlite: () => d.succeed(
|
|
2131
|
-
orElse: () => d.succeed(
|
|
2264
|
+
mysql: () => d.succeed(On(a)),
|
|
2265
|
+
mssql: () => d.succeed(Rn(a)),
|
|
2266
|
+
sqlite: () => d.succeed(Nn(a)),
|
|
2267
|
+
orElse: () => d.succeed(wn(a))
|
|
2132
2268
|
});
|
|
2133
2269
|
for (let n of t) yield* Q(e, n, a.kind);
|
|
2134
2270
|
break;
|
|
2135
2271
|
}
|
|
2136
2272
|
case "drop-table": {
|
|
2137
|
-
let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString(), r = (e) => t ?
|
|
2273
|
+
let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString(), r = (e) => t ? Vn(a, n, e) : Bn(a, e);
|
|
2138
2274
|
yield* e.onDialectOrElse({
|
|
2139
2275
|
mysql: () => Q(e, r(K), a.kind),
|
|
2140
2276
|
orElse: () => Q(e, r(G), a.kind)
|
|
@@ -2144,71 +2280,85 @@ BEGIN
|
|
|
2144
2280
|
case "drop-column": {
|
|
2145
2281
|
let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString();
|
|
2146
2282
|
yield* e.onDialectOrElse({
|
|
2147
|
-
mysql: () => Q(e, t ?
|
|
2148
|
-
orElse: () => Q(e, t ?
|
|
2283
|
+
mysql: () => Q(e, t ? mn(a, n, K) : fn(a), a.kind),
|
|
2284
|
+
orElse: () => Q(e, t ? mn(a, n, G) : dn(a, G), a.kind)
|
|
2149
2285
|
});
|
|
2150
2286
|
break;
|
|
2151
2287
|
}
|
|
2152
2288
|
case "rename-column":
|
|
2153
2289
|
yield* e.onDialectOrElse({
|
|
2154
|
-
mysql: () => Q(e,
|
|
2290
|
+
mysql: () => Q(e, pn(a, K), a.kind),
|
|
2155
2291
|
mssql: () => Q(e, `EXEC sp_rename N'${a.table.replace(/'/g, "''")}.${a.from.replace(/'/g, "''")}', N'${a.to.replace(/'/g, "''")}', 'COLUMN';`, a.kind),
|
|
2156
|
-
orElse: () => Q(e,
|
|
2292
|
+
orElse: () => Q(e, pn(a, G), a.kind)
|
|
2157
2293
|
});
|
|
2158
2294
|
break;
|
|
2159
2295
|
case "add-index":
|
|
2160
2296
|
yield* e.onDialectOrElse({
|
|
2161
|
-
mysql: () => Q(e,
|
|
2162
|
-
mssql: () => $(e, [...
|
|
2163
|
-
orElse: () => Q(e,
|
|
2297
|
+
mysql: () => Q(e, Kn(a, n.declared), a.kind),
|
|
2298
|
+
mssql: () => $(e, [...nr(a.table, a.index.columns, n.declared), tr(a)], a.kind),
|
|
2299
|
+
orElse: () => Q(e, Gn(a, t.classification === "online-required"), a.kind)
|
|
2164
2300
|
});
|
|
2165
2301
|
break;
|
|
2166
2302
|
case "drop-index":
|
|
2167
2303
|
yield* e.onDialectOrElse({
|
|
2168
|
-
mysql: () => Q(e,
|
|
2169
|
-
mssql: () => Q(e,
|
|
2170
|
-
orElse: () => Q(e,
|
|
2304
|
+
mysql: () => Q(e, Jn(a), a.kind),
|
|
2305
|
+
mssql: () => Q(e, Yn(a), a.kind),
|
|
2306
|
+
orElse: () => Q(e, qn(a), a.kind)
|
|
2307
|
+
});
|
|
2308
|
+
break;
|
|
2309
|
+
case "rename-table":
|
|
2310
|
+
yield* e.onDialectOrElse({
|
|
2311
|
+
mysql: () => Q(e, Xn(a, K), a.kind),
|
|
2312
|
+
mssql: () => Q(e, Zn(a), a.kind),
|
|
2313
|
+
orElse: () => Q(e, Xn(a, G), a.kind)
|
|
2314
|
+
});
|
|
2315
|
+
break;
|
|
2316
|
+
case "rename-index":
|
|
2317
|
+
yield* e.onDialectOrElse({
|
|
2318
|
+
mysql: () => Q(e, $n(a), a.kind),
|
|
2319
|
+
mssql: () => Q(e, er(a), a.kind),
|
|
2320
|
+
orElse: () => Q(e, Qn(a), a.kind)
|
|
2171
2321
|
});
|
|
2172
2322
|
break;
|
|
2173
2323
|
case "add-unique":
|
|
2174
2324
|
yield* e.onDialectOrElse({
|
|
2175
|
-
mysql: () => Q(e,
|
|
2325
|
+
mysql: () => Q(e, ir(a, n.declared), a.kind),
|
|
2176
2326
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2177
|
-
mssql: () => $(e, [...
|
|
2178
|
-
orElse: () => Q(e,
|
|
2327
|
+
mssql: () => $(e, [...nr(a.table, [a.column], n.declared), rr(a)], a.kind),
|
|
2328
|
+
orElse: () => Q(e, rr(a), a.kind)
|
|
2179
2329
|
});
|
|
2180
2330
|
break;
|
|
2181
2331
|
case "drop-unique":
|
|
2182
2332
|
yield* e.onDialectOrElse({
|
|
2183
|
-
mysql: () => Q(e,
|
|
2333
|
+
mysql: () => Q(e, ur(a), a.kind),
|
|
2184
2334
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2185
|
-
orElse: () => Q(e,
|
|
2335
|
+
orElse: () => Q(e, lr(a), a.kind)
|
|
2186
2336
|
});
|
|
2187
2337
|
break;
|
|
2188
2338
|
case "add-unique-composite":
|
|
2189
2339
|
yield* e.onDialectOrElse({
|
|
2190
|
-
mysql: () => Q(e,
|
|
2340
|
+
mysql: () => Q(e, or(a, n.declared), a.kind),
|
|
2191
2341
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2192
|
-
mssql: () => $(e, [...
|
|
2193
|
-
orElse: () => Q(e,
|
|
2342
|
+
mssql: () => $(e, [...nr(a.table, a.fields, n.declared), ar(a)], a.kind),
|
|
2343
|
+
orElse: () => Q(e, ar(a), a.kind)
|
|
2194
2344
|
});
|
|
2195
2345
|
break;
|
|
2196
2346
|
case "drop-unique-composite":
|
|
2197
2347
|
yield* e.onDialectOrElse({
|
|
2198
|
-
mysql: () => Q(e,
|
|
2348
|
+
mysql: () => Q(e, cr(a), a.kind),
|
|
2199
2349
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2200
|
-
orElse: () => Q(e,
|
|
2350
|
+
orElse: () => Q(e, sr(a), a.kind)
|
|
2201
2351
|
});
|
|
2202
2352
|
break;
|
|
2203
2353
|
case "add-foreign-key":
|
|
2204
2354
|
yield* e.onDialectOrElse({
|
|
2205
|
-
mysql: () => $(e,
|
|
2355
|
+
mysql: () => $(e, dr(a, K), a.kind),
|
|
2206
2356
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2207
|
-
orElse: () => $(e,
|
|
2357
|
+
orElse: () => $(e, dr(a, G), a.kind)
|
|
2208
2358
|
});
|
|
2209
2359
|
break;
|
|
2210
2360
|
case "add-column": {
|
|
2211
|
-
let n =
|
|
2361
|
+
let n = _r(a, t, i, yield* e.onDialectOrElse({
|
|
2212
2362
|
mysql: () => d.succeed("mariadb"),
|
|
2213
2363
|
mssql: () => d.succeed("mssql"),
|
|
2214
2364
|
sqlite: () => d.succeed("sqlite"),
|
|
@@ -2254,37 +2404,37 @@ BEGIN
|
|
|
2254
2404
|
yield* e.onDialectOrElse({
|
|
2255
2405
|
mysql: () => {
|
|
2256
2406
|
let t = q(n.declared, a.table, a.column);
|
|
2257
|
-
return t ? Q(e, `ALTER TABLE ${K(a.table)} MODIFY COLUMN ${
|
|
2407
|
+
return t ? Q(e, `ALTER TABLE ${K(a.table)} MODIFY COLUMN ${vn(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.`));
|
|
2258
2408
|
},
|
|
2259
2409
|
mssql: () => {
|
|
2260
2410
|
let t = q(n.declared, a.table, a.column);
|
|
2261
|
-
return t ? Q(e,
|
|
2411
|
+
return t ? Q(e, Pn(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}'.`));
|
|
2262
2412
|
},
|
|
2263
2413
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2264
2414
|
orElse: () => Q(e, `ALTER TABLE ${G(a.table)} ALTER COLUMN ${G(a.column)} ${a.toNullable ? "DROP NOT NULL" : "SET NOT NULL"};`, a.kind)
|
|
2265
2415
|
});
|
|
2266
2416
|
break;
|
|
2267
2417
|
case "alter-column-default": {
|
|
2268
|
-
let t =
|
|
2418
|
+
let t = _n(n.declared, a.table, a.column);
|
|
2269
2419
|
yield* e.onDialectOrElse({
|
|
2270
|
-
mysql: () => Q(e,
|
|
2271
|
-
mssql: () => Q(e,
|
|
2420
|
+
mysql: () => Q(e, hn(a, K, (e) => yn(e, t)), a.kind),
|
|
2421
|
+
mssql: () => Q(e, Fn(a), a.kind),
|
|
2272
2422
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2273
|
-
orElse: () => Q(e,
|
|
2423
|
+
orElse: () => Q(e, hn(a, G, (e) => xn(e, t)), a.kind)
|
|
2274
2424
|
});
|
|
2275
2425
|
break;
|
|
2276
2426
|
}
|
|
2277
2427
|
case "alter-column-type": {
|
|
2278
|
-
let r = U(
|
|
2428
|
+
let r = U(_n(n.declared, a.table, a.column) ?? { type: a.to }), i = a.using ? ` USING ${a.using}` : "";
|
|
2279
2429
|
if (t.classification !== "online-required") {
|
|
2280
2430
|
yield* e.onDialectOrElse({
|
|
2281
2431
|
mysql: () => {
|
|
2282
2432
|
let t = q(n.declared, a.table, a.column);
|
|
2283
|
-
return t ? Q(e, `ALTER TABLE ${K(a.table)} MODIFY COLUMN ${
|
|
2433
|
+
return t ? Q(e, `ALTER TABLE ${K(a.table)} MODIFY COLUMN ${vn(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.`));
|
|
2284
2434
|
},
|
|
2285
2435
|
mssql: () => {
|
|
2286
2436
|
let t = q(n.declared, a.table, a.column);
|
|
2287
|
-
return t ? Q(e,
|
|
2437
|
+
return t ? Q(e, Pn(t, a.column, a.table), a.kind) : d.die(/* @__PURE__ */ Error(`alter-column-type on mssql needs the declared column '${a.table}.${a.column}'.`));
|
|
2288
2438
|
},
|
|
2289
2439
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2290
2440
|
orElse: () => Q(e, `ALTER TABLE ${G(a.table)} ALTER COLUMN ${G(a.column)} TYPE ${r}${i};`, a.kind)
|
|
@@ -2308,23 +2458,23 @@ BEGIN
|
|
|
2308
2458
|
}
|
|
2309
2459
|
case "drop-foreign-key":
|
|
2310
2460
|
yield* e.onDialectOrElse({
|
|
2311
|
-
mysql: () => Q(e,
|
|
2461
|
+
mysql: () => Q(e, pr(a), a.kind),
|
|
2312
2462
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2313
|
-
orElse: () => Q(e,
|
|
2463
|
+
orElse: () => Q(e, fr(a), a.kind)
|
|
2314
2464
|
});
|
|
2315
2465
|
break;
|
|
2316
2466
|
case "add-check":
|
|
2317
2467
|
yield* e.onDialectOrElse({
|
|
2318
|
-
mysql: () => Q(e,
|
|
2468
|
+
mysql: () => Q(e, mr(a, K), a.kind),
|
|
2319
2469
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2320
|
-
orElse: () => Q(e,
|
|
2470
|
+
orElse: () => Q(e, mr(a, G), a.kind)
|
|
2321
2471
|
});
|
|
2322
2472
|
break;
|
|
2323
2473
|
case "drop-check":
|
|
2324
2474
|
yield* e.onDialectOrElse({
|
|
2325
|
-
mysql: () => Q(e,
|
|
2475
|
+
mysql: () => Q(e, gr(a), a.kind),
|
|
2326
2476
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2327
|
-
orElse: () => Q(e,
|
|
2477
|
+
orElse: () => Q(e, hr(a), a.kind)
|
|
2328
2478
|
});
|
|
2329
2479
|
break;
|
|
2330
2480
|
}
|
|
@@ -2333,10 +2483,10 @@ BEGIN
|
|
|
2333
2483
|
status: "applied",
|
|
2334
2484
|
durationMs: Number((process.hrtime.bigint() - r) / 1000000n)
|
|
2335
2485
|
};
|
|
2336
|
-
}),
|
|
2486
|
+
}), br = (e, t, n) => d.gen(function* () {
|
|
2337
2487
|
let r = t.operations.filter((e) => e.blocked);
|
|
2338
2488
|
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.`));
|
|
2339
|
-
yield*
|
|
2489
|
+
yield* C(e);
|
|
2340
2490
|
let i = Date.now(), a = [];
|
|
2341
2491
|
try {
|
|
2342
2492
|
let r = yield* e.onDialectOrElse({
|
|
@@ -2346,11 +2496,11 @@ BEGIN
|
|
|
2346
2496
|
}), i = r ? t.operations.filter((e) => e.classification !== "online-required") : [], o = r ? t.operations.filter((e) => e.classification === "online-required") : t.operations;
|
|
2347
2497
|
i.length > 0 && (yield* e.withTransaction(d.gen(function* () {
|
|
2348
2498
|
let e = yield* p.SqlClient;
|
|
2349
|
-
for (let t of i) a.push(yield*
|
|
2499
|
+
for (let t of i) a.push(yield* yr(e, t, n));
|
|
2350
2500
|
})));
|
|
2351
|
-
for (let t of o) a.push(yield*
|
|
2501
|
+
for (let t of o) a.push(yield* yr(e, t, n));
|
|
2352
2502
|
} finally {
|
|
2353
|
-
yield*
|
|
2503
|
+
yield* w(e).pipe(d.orDie);
|
|
2354
2504
|
}
|
|
2355
2505
|
let o = yield* n.replan(e);
|
|
2356
2506
|
if (o.operations.length > 0) {
|
|
@@ -2382,19 +2532,19 @@ BEGIN
|
|
|
2382
2532
|
source: n.source,
|
|
2383
2533
|
...n.notes ? { notes: n.notes } : {}
|
|
2384
2534
|
};
|
|
2385
|
-
}),
|
|
2535
|
+
}), xr = (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"), Sr = (e) => e`
|
|
2386
2536
|
SELECT fingerprint
|
|
2387
2537
|
FROM _voltro_migration_plans
|
|
2388
2538
|
ORDER BY ${e("appliedAt")} DESC
|
|
2389
2539
|
LIMIT 1
|
|
2390
|
-
`.pipe(d.map((e) => e.length > 0 ? e[0].fingerprint : void 0), d.catchAll(() => d.succeed(void 0))),
|
|
2540
|
+
`.pipe(d.map((e) => e.length > 0 ? e[0].fingerprint : void 0), d.catchAll(() => d.succeed(void 0))), Cr = (e) => e.onDialectOrElse({
|
|
2391
2541
|
pg: () => "postgres",
|
|
2392
2542
|
mysql: () => "mysql",
|
|
2393
2543
|
mssql: () => "mssql",
|
|
2394
2544
|
sqlite: () => "sqlite",
|
|
2395
2545
|
orElse: () => "sqlite"
|
|
2396
|
-
}),
|
|
2397
|
-
let n = j(N(t,
|
|
2546
|
+
}), wr = (e, t) => d.gen(function* () {
|
|
2547
|
+
let n = j(N(t, Cr(e))), r = yield* Sr(e);
|
|
2398
2548
|
return r === n ? {
|
|
2399
2549
|
kind: "up-to-date",
|
|
2400
2550
|
fingerprint: n
|
|
@@ -2403,23 +2553,23 @@ BEGIN
|
|
|
2403
2553
|
expected: n,
|
|
2404
2554
|
...r === void 0 ? {} : { actual: r }
|
|
2405
2555
|
};
|
|
2406
|
-
}),
|
|
2556
|
+
}), Tr = [
|
|
2407
2557
|
"pgeagertest_",
|
|
2408
2558
|
"mig_e2e_",
|
|
2409
2559
|
"mig_test_",
|
|
2410
2560
|
"mysqleagertest_",
|
|
2411
2561
|
"mssqleagertest_",
|
|
2412
2562
|
"sqliteeagertest_"
|
|
2413
|
-
],
|
|
2563
|
+
], Er = (e) => Tr.some((t) => e.startsWith(t)), Dr = (e, t) => d.gen(function* () {
|
|
2414
2564
|
if (process.env.VOLTRO_TEST_FIXTURE_GC === "off") return [];
|
|
2415
|
-
let n = t.filter((e) =>
|
|
2565
|
+
let n = t.filter((e) => Er(e.name)).map((e) => e.name);
|
|
2416
2566
|
if (n.length === 0) return [];
|
|
2417
2567
|
for (let t of n) yield* e.unsafe(`DROP TABLE IF EXISTS "${t}" CASCADE`).pipe(d.catchAll(() => d.void));
|
|
2418
2568
|
return n;
|
|
2419
|
-
}),
|
|
2569
|
+
}), Or = () => {
|
|
2420
2570
|
let e = (process.env.VOLTRO_DB_IGNORE_TABLES ?? "").split(",").map((e) => e.trim()).filter((e) => e.length > 0);
|
|
2421
2571
|
return e.length > 0 ? { ignoreTables: e } : {};
|
|
2422
|
-
},
|
|
2572
|
+
}, kr = (e) => {
|
|
2423
2573
|
if (e === void 0) return;
|
|
2424
2574
|
let t = e.trim();
|
|
2425
2575
|
if (t === "") return;
|
|
@@ -2429,73 +2579,73 @@ BEGIN
|
|
|
2429
2579
|
kind: "tables",
|
|
2430
2580
|
tables: new Set(n)
|
|
2431
2581
|
} : void 0;
|
|
2432
|
-
},
|
|
2582
|
+
}, Ar = (e) => typeof e.table == "string" ? e.table : void 0, jr = (e, t = { kind: "all" }) => ({
|
|
2433
2583
|
...e,
|
|
2434
2584
|
operations: e.operations.map((e) => {
|
|
2435
2585
|
if (!e.blocked || e.classification !== "lossy") return e;
|
|
2436
2586
|
if (t?.kind === "tables") {
|
|
2437
|
-
let n =
|
|
2587
|
+
let n = Ar(e.op);
|
|
2438
2588
|
if (n === void 0 || !t.tables.has(n)) return e;
|
|
2439
2589
|
}
|
|
2440
2590
|
let { blocked: n, ...r } = e;
|
|
2441
2591
|
return r;
|
|
2442
2592
|
})
|
|
2443
|
-
}),
|
|
2593
|
+
}), Mr = (e, t, n) => t === "postgres" ? st(e, n).pipe(d.flatMap((e) => {
|
|
2444
2594
|
let t = ct(e);
|
|
2445
2595
|
return t === void 0 ? d.void : d.logWarning(`auto-migrate: ${t}`).pipe(d.annotateLogs({ scope: "voltro:migrate" }));
|
|
2446
|
-
}), d.catchAll(() => d.void)) : d.void,
|
|
2447
|
-
let r =
|
|
2596
|
+
}), d.catchAll(() => d.void)) : d.void, Nr = (e, t, n) => d.gen(function* () {
|
|
2597
|
+
let r = Cr(e), i = t;
|
|
2448
2598
|
if (process.env.VOLTRO_MIGRATE_FORCE !== "1") {
|
|
2449
2599
|
let t = j(N(i, r));
|
|
2450
|
-
if ((yield*
|
|
2600
|
+
if ((yield* Sr(e)) === t) return yield* Mr(e, r, i), {
|
|
2451
2601
|
kind: "up-to-date",
|
|
2452
2602
|
fingerprint: t
|
|
2453
2603
|
};
|
|
2454
2604
|
}
|
|
2455
|
-
let a = yield* V(e), o = yield*
|
|
2605
|
+
let a = yield* V(e), o = yield* Dr(e, a.tables);
|
|
2456
2606
|
o.length > 0 && (yield* d.logInfo(`auto-migrate: reaped ${o.length} test-fixture leftover(s)`).pipe(d.annotateLogs({
|
|
2457
2607
|
scope: "voltro:migrate",
|
|
2458
2608
|
count: o.length
|
|
2459
2609
|
})), a = yield* V(e));
|
|
2460
|
-
let s =
|
|
2610
|
+
let s = new Set(t.map((e) => e.tableName)), c = (e) => e.filter((e) => !ut(e.name) || s.has(e.name)), l = Wt({
|
|
2461
2611
|
declared: i,
|
|
2462
|
-
live: { tables: a.tables
|
|
2612
|
+
live: { tables: c(a.tables) },
|
|
2463
2613
|
dialect: r,
|
|
2464
|
-
...
|
|
2614
|
+
...Or()
|
|
2465
2615
|
});
|
|
2466
|
-
if (
|
|
2467
|
-
let e =
|
|
2468
|
-
if (t === void 0 || !e || (
|
|
2616
|
+
if (l.summary.blocked > 0) {
|
|
2617
|
+
let e = l.operations.filter((e) => e.blocked).every((e) => e.classification === "lossy"), t = kr(process.env.VOLTRO_DESTRUCTIVE_OK);
|
|
2618
|
+
if (t === void 0 || !e || (l = jr(l, t), l.operations.some((e) => e.blocked))) return {
|
|
2469
2619
|
kind: "refused-blocked",
|
|
2470
|
-
plan:
|
|
2620
|
+
plan: l
|
|
2471
2621
|
};
|
|
2472
2622
|
}
|
|
2473
|
-
return
|
|
2623
|
+
return l.operations.length === 0 ? {
|
|
2474
2624
|
kind: "up-to-date",
|
|
2475
|
-
fingerprint:
|
|
2625
|
+
fingerprint: l.toFingerprint
|
|
2476
2626
|
} : {
|
|
2477
2627
|
kind: "applied",
|
|
2478
|
-
applied: yield*
|
|
2628
|
+
applied: yield* br(e, l, {
|
|
2479
2629
|
declared: t,
|
|
2480
2630
|
appliedBy: n.appliedBy,
|
|
2481
2631
|
environment: n.environment === "prod" ? "dev" : n.environment,
|
|
2482
2632
|
source: "auto-diff",
|
|
2483
2633
|
replan: (e) => d.gen(function* () {
|
|
2484
2634
|
let t = yield* V(e);
|
|
2485
|
-
return
|
|
2635
|
+
return Wt({
|
|
2486
2636
|
declared: i,
|
|
2487
|
-
live: { tables: t.tables
|
|
2637
|
+
live: { tables: c(t.tables) },
|
|
2488
2638
|
dialect: r,
|
|
2489
|
-
...
|
|
2639
|
+
...Or()
|
|
2490
2640
|
});
|
|
2491
2641
|
})
|
|
2492
2642
|
}),
|
|
2493
|
-
plan:
|
|
2643
|
+
plan: l
|
|
2494
2644
|
};
|
|
2495
|
-
}),
|
|
2645
|
+
}), Pr = (e, t, n) => process.env.VOLTRO_AUTO_MIGRATE === "0" ? d.succeed({
|
|
2496
2646
|
kind: "skipped",
|
|
2497
2647
|
reason: "VOLTRO_AUTO_MIGRATE=0"
|
|
2498
|
-
}) : n.environment === "prod" ?
|
|
2648
|
+
}) : n.environment === "prod" ? wr(e, t) : Nr(e, t, n), Fr = (e, t) => {
|
|
2499
2649
|
switch (e.kind) {
|
|
2500
2650
|
case "skipped": return `auto-migrate: skipped (${e.reason})`;
|
|
2501
2651
|
case "up-to-date": return `auto-migrate: schema up to date (${t}, fingerprint=${M(e.fingerprint)})`;
|
|
@@ -2505,7 +2655,7 @@ BEGIN
|
|
|
2505
2655
|
}
|
|
2506
2656
|
case "prod-mismatch": return `auto-migrate: SCHEMA FINGERPRINT MISMATCH — declared=${M(e.expected)}` + (e.actual ? ` live=${M(e.actual)}` : " live=<no _voltro_migration_plans row>") + ". Run `voltro db apply --plan plan.json` from the deploy pipeline before serving.";
|
|
2507
2657
|
case "refused-blocked": {
|
|
2508
|
-
let t = e.plan.operations.filter((e) => e.blocked), n = t.filter((e) => e.op.kind === "drop-table").length, r = t.filter((e) => e.op.kind === "drop-table").map((e) => "table" in e.op ? e.op.table : "").filter(Boolean), i = t.filter((e) => e.op.kind === "add-column").length, a = t.filter((e) => e.op.kind === "drop-column").length, o = t.filter((e) => e.classification === "needs-rename-annotation").length, s = `auto-migrate: REFUSED — ${e.plan.summary.blocked} blocked operation(s):\n` +
|
|
2658
|
+
let t = e.plan.operations.filter((e) => e.blocked), n = t.filter((e) => e.op.kind === "drop-table").length, r = t.filter((e) => e.op.kind === "drop-table").map((e) => "table" in e.op ? e.op.table : "").filter(Boolean), i = t.filter((e) => e.op.kind === "add-column").length, a = t.filter((e) => e.op.kind === "drop-column").length, o = t.filter((e) => e.classification === "needs-rename-annotation").length, s = `auto-migrate: REFUSED — ${e.plan.summary.blocked} blocked operation(s):\n` + xr(e.plan), c = [""];
|
|
2509
2659
|
if (n > 0 && c.push(`${n} table(s) exist in the live DB but aren't in your declared schema.`, "This is usually one of three things:", " (a) You're iterating on the schema — the table file got renamed, moved, or temporarily commented out.", " → Restore the declaration. Your data stays intact.", " (b) You want to KEEP the table but NOT manage it with Voltro (a leftover from another tool —", " a Strapi/Rails/legacy migration artifact, or an externally-owned table).", ` → Set \`VOLTRO_DB_IGNORE_TABLES=${r.join(",")}\` (comma-separated).`, " The planner excludes those tables from the diff entirely — it never drops them, and they", " stop blocking your OTHER (additive) changes. This is the fix when a leftover freezes your schema.", " (c) You actually want to drop the table.", ` → Set \`VOLTRO_DESTRUCTIVE_OK=${r.join(",")}\` for ONE run — it acknowledges`, " the data loss for THOSE tables only; every other lossy op in this plan stays blocked.", " (`VOLTRO_DESTRUCTIVE_OK=1` acknowledges all of them, which is rarely what you mean.)", " There is deliberately no `dropped()` marker for a TABLE, unlike for a column: a", " dropped column leaves a slot worth documenting in the declaration, a dropped table", " leaves nothing — the marker would be a dead entry you must remember to delete.", " Soft-drop: set `VOLTRO_SOFT_DROP=1` alongside DESTRUCTIVE_OK to RENAME instead of DROP", " (data survives as `<name>__dropped_<ts>` for ~7d; restorable via `voltro db restore-snapshot`)."), i > 0 && c.push(`${i} required column(s) need a backfill strategy before adding to a populated table.`, " → Annotate the column: `.backfill(sql`<expr>`)` or `.backfill(row => <fn>)` or `.default(<value>)`.", " Existing rows get the backfill value; the column then lands as NOT NULL."), a > 0) {
|
|
2510
2660
|
let t = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map();
|
|
2511
2661
|
for (let r of e.plan.operations) {
|
|
@@ -2522,7 +2672,7 @@ BEGIN
|
|
|
2522
2672
|
return o > 0 && c.push(`${o} column(s) look like renames (one column gone + a new one of same shape appeared).`, " → On the NEW column add `.renamedFrom('<oldName>')` so the planner emits RENAME instead of DROP+ADD."), c.push("", "See `voltro db plan` for the full machine-readable diff."), s + "\n" + c.join("\n");
|
|
2523
2673
|
}
|
|
2524
2674
|
}
|
|
2525
|
-
},
|
|
2675
|
+
}, Ir = /* @__PURE__ */ new Set([
|
|
2526
2676
|
"node_modules",
|
|
2527
2677
|
"dist",
|
|
2528
2678
|
"build",
|
|
@@ -2531,11 +2681,11 @@ BEGIN
|
|
|
2531
2681
|
".next",
|
|
2532
2682
|
".git",
|
|
2533
2683
|
".framework"
|
|
2534
|
-
]),
|
|
2684
|
+
]), Lr = async (e) => {
|
|
2535
2685
|
let t = [], n = async (e) => {
|
|
2536
2686
|
let r = await h.readdir(e, { withFileTypes: !0 }).catch(() => []);
|
|
2537
2687
|
for (let i of r) {
|
|
2538
|
-
if (
|
|
2688
|
+
if (Ir.has(i.name)) continue;
|
|
2539
2689
|
let r = g(e, i.name);
|
|
2540
2690
|
i.isDirectory() ? await n(r) : i.isFile() && l.test(i.name) && t.push(r);
|
|
2541
2691
|
}
|
|
@@ -2544,7 +2694,7 @@ BEGIN
|
|
|
2544
2694
|
let n = e.split("/").pop() ?? e, r = t.split("/").pop() ?? t;
|
|
2545
2695
|
return n.localeCompare(r);
|
|
2546
2696
|
});
|
|
2547
|
-
},
|
|
2697
|
+
}, Rr = async (e) => {
|
|
2548
2698
|
let t = [];
|
|
2549
2699
|
for (let n of e) {
|
|
2550
2700
|
let e = (await import(ee(n).href)).default;
|
|
@@ -2558,11 +2708,11 @@ BEGIN
|
|
|
2558
2708
|
});
|
|
2559
2709
|
}
|
|
2560
2710
|
return t;
|
|
2561
|
-
},
|
|
2711
|
+
}, zr = (e) => e`
|
|
2562
2712
|
SELECT ${e("id")}
|
|
2563
2713
|
FROM ${e("_voltro_migration_plans")}
|
|
2564
2714
|
WHERE ${e("source")} = 'file'
|
|
2565
|
-
`.pipe(d.map((e) => e.map((e) => e.id)), d.catchAll(() => d.succeed([]))),
|
|
2715
|
+
`.pipe(d.map((e) => e.map((e) => e.id)), d.catchAll(() => d.succeed([]))), Br = (e, t, n, r) => d.gen(function* () {
|
|
2566
2716
|
let i = Date.now(), a = (/* @__PURE__ */ new Date()).toISOString(), o = {
|
|
2567
2717
|
sql: e,
|
|
2568
2718
|
log: {
|
|
@@ -2595,9 +2745,9 @@ BEGIN
|
|
|
2595
2745
|
${r}, ${n}, ${"file"},
|
|
2596
2746
|
${c}, ${a}, ${t.migration.description})
|
|
2597
2747
|
`, { durationMs: c };
|
|
2598
|
-
}),
|
|
2748
|
+
}), Vr = (e, t) => d.gen(function* () {
|
|
2599
2749
|
let n = yield* d.tryPromise({
|
|
2600
|
-
try: () =>
|
|
2750
|
+
try: () => Lr(g(t, "migrations")),
|
|
2601
2751
|
catch: (e) => e
|
|
2602
2752
|
});
|
|
2603
2753
|
if (n.length === 0) return {
|
|
@@ -2605,25 +2755,25 @@ BEGIN
|
|
|
2605
2755
|
skipped: []
|
|
2606
2756
|
};
|
|
2607
2757
|
let r = yield* d.tryPromise({
|
|
2608
|
-
try: () =>
|
|
2758
|
+
try: () => Rr(n),
|
|
2609
2759
|
catch: (e) => e
|
|
2610
2760
|
});
|
|
2611
2761
|
if (r.length === 0) return {
|
|
2612
2762
|
pending: [],
|
|
2613
2763
|
skipped: []
|
|
2614
2764
|
};
|
|
2615
|
-
let i = new Set(yield*
|
|
2765
|
+
let i = new Set(yield* zr(e));
|
|
2616
2766
|
return {
|
|
2617
2767
|
pending: r.filter((e) => !i.has(e.migration.id)),
|
|
2618
2768
|
skipped: r.filter((e) => i.has(e.migration.id)).map((e) => e.migration.id)
|
|
2619
2769
|
};
|
|
2620
|
-
}),
|
|
2621
|
-
let { pending: n, skipped: r } = yield*
|
|
2770
|
+
}), Hr = (e, t) => Vr(e, t).pipe(d.map((e) => e.pending.map((e) => e.migration.id))), Ur = (e, t) => d.gen(function* () {
|
|
2771
|
+
let { pending: n, skipped: r } = yield* Vr(e, t.projectRoot);
|
|
2622
2772
|
if (n.length === 0) return {
|
|
2623
2773
|
applied: [],
|
|
2624
2774
|
skipped: r
|
|
2625
2775
|
};
|
|
2626
|
-
yield*
|
|
2776
|
+
yield* C(e);
|
|
2627
2777
|
let i = [];
|
|
2628
2778
|
try {
|
|
2629
2779
|
for (let r of n) {
|
|
@@ -2632,7 +2782,7 @@ BEGIN
|
|
|
2632
2782
|
id: r.migration.id,
|
|
2633
2783
|
file: r.file
|
|
2634
2784
|
}));
|
|
2635
|
-
let { durationMs: n } = yield*
|
|
2785
|
+
let { durationMs: n } = yield* Br(e, r, t.env, t.appliedBy);
|
|
2636
2786
|
i.push({
|
|
2637
2787
|
id: r.migration.id,
|
|
2638
2788
|
durationMs: n
|
|
@@ -2643,28 +2793,28 @@ BEGIN
|
|
|
2643
2793
|
}));
|
|
2644
2794
|
}
|
|
2645
2795
|
} finally {
|
|
2646
|
-
yield*
|
|
2796
|
+
yield* w(e).pipe(d.orDie);
|
|
2647
2797
|
}
|
|
2648
2798
|
return {
|
|
2649
2799
|
applied: i,
|
|
2650
2800
|
skipped: r
|
|
2651
2801
|
};
|
|
2652
|
-
}),
|
|
2802
|
+
}), Wr = (e, t) => e`
|
|
2653
2803
|
SELECT ${e("id")}
|
|
2654
2804
|
FROM ${e("_voltro_migration_plans")}
|
|
2655
2805
|
WHERE ${e("id")} = ${t} AND ${e("source")} = 'file'
|
|
2656
2806
|
LIMIT 1
|
|
2657
|
-
`,
|
|
2658
|
-
if (!(yield*
|
|
2807
|
+
`, Gr = (e, t) => d.gen(function* () {
|
|
2808
|
+
if (!(yield* Wr(e, t.id))[0]) return yield* d.fail(/* @__PURE__ */ Error(`rollback: ${t.id} not found in _voltro_migration_plans (file source)`));
|
|
2659
2809
|
let n = yield* d.tryPromise({
|
|
2660
|
-
try: () =>
|
|
2810
|
+
try: () => Lr(g(t.projectRoot, "migrations")),
|
|
2661
2811
|
catch: (e) => e
|
|
2662
2812
|
}), r = (yield* d.tryPromise({
|
|
2663
|
-
try: () =>
|
|
2813
|
+
try: () => Rr(n),
|
|
2664
2814
|
catch: (e) => e
|
|
2665
2815
|
})).find((e) => e.migration.id === t.id);
|
|
2666
2816
|
if (!r) return yield* d.fail(/* @__PURE__ */ Error(`rollback: file for migration ${t.id} not found on disk under ${t.projectRoot}/migrations/`));
|
|
2667
|
-
yield*
|
|
2817
|
+
yield* C(e);
|
|
2668
2818
|
let i = Date.now();
|
|
2669
2819
|
try {
|
|
2670
2820
|
let n = {
|
|
@@ -2691,9 +2841,9 @@ BEGIN
|
|
|
2691
2841
|
durationMs: o
|
|
2692
2842
|
};
|
|
2693
2843
|
} finally {
|
|
2694
|
-
yield*
|
|
2844
|
+
yield* w(e).pipe(d.orDie);
|
|
2695
2845
|
}
|
|
2696
|
-
}),
|
|
2846
|
+
}), Kr = (e) => d.gen(function* () {
|
|
2697
2847
|
let t = yield* p.SqlClient, n = yield* t`
|
|
2698
2848
|
SELECT id, fingerprint, appliedAt FROM _voltro_migration_plans
|
|
2699
2849
|
WHERE source = 'auto-diff'
|
|
@@ -2738,10 +2888,10 @@ BEGIN
|
|
|
2738
2888
|
snapshotFingerprint: e.fingerprint,
|
|
2739
2889
|
snapshotId: i
|
|
2740
2890
|
};
|
|
2741
|
-
}),
|
|
2891
|
+
}), qr = (e, ...t) => ({
|
|
2742
2892
|
_tag: "RawSqlFragment",
|
|
2743
2893
|
strings: [...e],
|
|
2744
2894
|
values: [...t]
|
|
2745
|
-
}),
|
|
2895
|
+
}), Jr = (e) => typeof e == "object" && !!e && e._tag === "RawSqlFragment";
|
|
2746
2896
|
//#endregion
|
|
2747
|
-
export { l as FILE_MIGRATION_PATTERN, ot as REACTIVE_TRIGGER_PREFIX,
|
|
2897
|
+
export { l as FILE_MIGRATION_PATTERN, ot as REACTIVE_TRIGGER_PREFIX, re as VOLTRO_MIGRATION_LOCK_KEY, C as acquireMigrationLock, Je as applyNamespacedSchema, br as applyPlan, He as applySchema, Zt as chunkTables, N as declaredSnapshot, be as defaultArrayClause, ye as defaultClause, D as defaultJsonClause, Fr as describeOutcome, kr as destructiveScope, st as detectReactiveTriggerDrift, dn as emitDropColumnDdl, fn as emitDropColumnDdlMysql, Ve as emitFrameworkBootstrapSql, ze as emitNamespaceProvisionDdl, Be as emitNamespacedSchemaSql, A as emitSchemaSql, j as fingerprintSchema, ct as formatReactiveTriggerDrift, Or as ignoreTablesFromEnv, V as introspectSchema, o as isFileMigration, Jr as isRawSqlFragment, Kt as mapPgType, s as migration, O as numericIdSql, Gt as parseEnumCheck, Hr as pendingFileMigrationIds, Wt as planMigrations, Ye as provisionTenantNamespace, w as releaseMigrationLock, Dn as renderColumnMysql, Sn as renderColumnPg, Gr as rollbackFileBasedMigration, Ur as runFileBasedMigrations, Xe as runFrameworkBootstrap, qe as runMigrate, Pr as runPlannedMigrations, M as shortFingerprint, nt as snapshotColumn, qr as sql, E as sqlType, Kr as squashMigrationPlans, jr as unblockLossy, _e as withMigrationLock };
|