@voltro/database 0.14.0 → 0.16.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 +190 -0
- package/dist/sql.d.ts +20 -17
- package/dist/sql.js +480 -451
- package/package.json +2 -2
package/dist/sql.js
CHANGED
|
@@ -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, te = (e) => e.replace(/"/g, "`"), y = (e) => typeof e == "string" ? e : e.name ?? String(e), b = (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 = te(t.where), o = [];
|
|
51
51
|
for (let r of t.fields) {
|
|
52
|
-
let i =
|
|
52
|
+
let i = y(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 = b(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: () =>
|
|
114
|
-
mssql: () =>
|
|
115
|
-
sqlite: () =>
|
|
116
|
-
orElse: () =>
|
|
117
|
-
}),
|
|
118
|
-
mysql: () =>
|
|
119
|
-
mssql: () =>
|
|
120
|
-
sqlite: () =>
|
|
121
|
-
orElse: () =>
|
|
122
|
-
}),
|
|
123
|
-
|
|
124
|
-
},
|
|
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({
|
|
113
|
+
mysql: () => ue(e),
|
|
114
|
+
mssql: () => me(e),
|
|
115
|
+
sqlite: () => ge,
|
|
116
|
+
orElse: () => oe(e)
|
|
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";
|
|
@@ -264,38 +264,38 @@ var _ = (e, t, n, r = 400) => {
|
|
|
264
264
|
case "setNull": return "SET NULL";
|
|
265
265
|
case "noAction": return "NO ACTION";
|
|
266
266
|
}
|
|
267
|
-
},
|
|
267
|
+
}, xe = (t, n, r) => r === null ? e(t, n) : `${e(r, n)}.${e(t, n)}`, Se = 191, Ce = (t, n, r) => {
|
|
268
268
|
let i = e(t, r);
|
|
269
269
|
if (r !== "mysql" && r !== "mariadb") return i;
|
|
270
270
|
let a = n[t];
|
|
271
271
|
if (!a) return i;
|
|
272
|
-
let o =
|
|
273
|
-
return o.endsWith("TEXT") || o.endsWith("BLOB") ? `${i}(${
|
|
274
|
-
},
|
|
272
|
+
let o = E(a, r).toUpperCase();
|
|
273
|
+
return o.endsWith("TEXT") || o.endsWith("BLOB") ? `${i}(${Se})` : i;
|
|
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
|
-
},
|
|
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)" :
|
|
282
|
+
}, Te = (t, n, r, i, a = !1, o = !1) => {
|
|
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
|
-
let l =
|
|
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) {
|
|
@@ -312,18 +312,18 @@ var _ = (e, t, n, r = 400) => {
|
|
|
312
312
|
u(r) ? c.push(`CHECK (${n} IS NULL OR json_valid(${n}))`) : r === "mssql" && c.push(`CHECK (${n} IS NULL OR ISJSON(${n}) = 1)`);
|
|
313
313
|
}
|
|
314
314
|
return c.join(" ");
|
|
315
|
-
},
|
|
315
|
+
}, Ee = (t, n, r = null, i) => {
|
|
316
316
|
let a = /* @__PURE__ */ new Set();
|
|
317
317
|
for (let e of t.appliedIndexes ?? []) for (let t of e.fields) typeof t == "string" && a.add(t);
|
|
318
318
|
for (let e of t.appliedUniques ?? []) for (let t of e.fields) typeof t == "string" && a.add(t);
|
|
319
|
-
let o = t.appliedPrimaryKey ?? [], s = o.length > 0, c = Object.entries(t.fields).map(([e, t]) => ` ${
|
|
320
|
-
let i = r.fields.map((e) =>
|
|
319
|
+
let o = t.appliedPrimaryKey ?? [], s = o.length > 0, c = Object.entries(t.fields).map(([e, t]) => ` ${Te(e, t, n, a, i?.has(e) ?? !1, s)}`).join(",\n"), l = (t.appliedUniques ?? []).map((r) => {
|
|
320
|
+
let i = r.fields.map((e) => Ce(e, t.fields, n)).join(", ");
|
|
321
321
|
return ` CONSTRAINT ${e(r.name, n)} UNIQUE (${i})`;
|
|
322
322
|
}), u = (t.appliedChecks ?? []).map((t) => ` CONSTRAINT ${e(t.name, n)} CHECK (${t.expr})`), d = [
|
|
323
|
-
...s ? [` PRIMARY KEY (${o.map((e) =>
|
|
323
|
+
...s ? [` PRIMARY KEY (${o.map((e) => Ce(e, t.fields, n)).join(", ")})`] : [],
|
|
324
324
|
...l,
|
|
325
325
|
...u
|
|
326
|
-
], f = d.length > 0 ? `${c},\n${d.join(",\n")}` : c, p =
|
|
326
|
+
], f = d.length > 0 ? `${c},\n${d.join(",\n")}` : c, p = xe(t.tableName, n, r);
|
|
327
327
|
if (n === "mssql") {
|
|
328
328
|
let e = r === null ? t.tableName : `${r}.${t.tableName}`, n = `CREATE TABLE ${p} (\n${f}\n)`;
|
|
329
329
|
return `IF OBJECT_ID('${e.replace(/'/g, "''")}', 'U') IS NULL EXEC(N'${n.replace(/'/g, "''")}');`;
|
|
@@ -333,10 +333,10 @@ var _ = (e, t, n, r = 400) => {
|
|
|
333
333
|
f,
|
|
334
334
|
");"
|
|
335
335
|
].join("\n");
|
|
336
|
-
},
|
|
336
|
+
}, De = (t, n, r) => {
|
|
337
337
|
let i = `${t}_${n.name}_fts`, a = (t) => e(t, r), o = n.columns.map(a).join(", "), s = n.columns.map((e) => `new.${a(e)}`).join(", "), c = [];
|
|
338
338
|
return c.push(`CREATE VIRTUAL TABLE IF NOT EXISTS ${a(i)} USING fts5(${o}, row_id UNINDEXED, tokenize='porter');`), c.push(`CREATE TRIGGER IF NOT EXISTS ${a(`${i}_ai`)} AFTER INSERT ON ${a(t)} BEGIN\n INSERT INTO ${a(i)} (${o}, row_id) VALUES (${s}, new.${a("id")});\nEND;`), c.push(`CREATE TRIGGER IF NOT EXISTS ${a(`${i}_ad`)} AFTER DELETE ON ${a(t)} BEGIN\n DELETE FROM ${a(i)} WHERE row_id = old.${a("id")};\nEND;`), c.push(`CREATE TRIGGER IF NOT EXISTS ${a(`${i}_au`)} AFTER UPDATE ON ${a(t)} BEGIN\n DELETE FROM ${a(i)} WHERE row_id = old.${a("id")};\n INSERT INTO ${a(i)} (${o}, row_id) VALUES (${s}, new.${a("id")});\nEND;`), c;
|
|
339
|
-
},
|
|
339
|
+
}, Oe = (n, r, a = null) => {
|
|
340
340
|
let o = [], s = /* @__PURE__ */ new Set(), c = (e) => e.join("\0"), l = (e, n, i, a) => {
|
|
341
341
|
let o = {
|
|
342
342
|
using: "",
|
|
@@ -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
|
|
@@ -382,7 +382,7 @@ var _ = (e, t, n, r = 400) => {
|
|
|
382
382
|
return o;
|
|
383
383
|
}, u = (e, t) => {
|
|
384
384
|
let a = e.map((e) => {
|
|
385
|
-
if (typeof e == "string") return
|
|
385
|
+
if (typeof e == "string") return Ce(e, n.fields, r);
|
|
386
386
|
if ("jsonPath" in e) {
|
|
387
387
|
let { column: t, path: n, numeric: a } = e.jsonPath;
|
|
388
388
|
return `(${i(t, n, r, { numeric: a })})`;
|
|
@@ -393,7 +393,7 @@ var _ = (e, t, n, r = 400) => {
|
|
|
393
393
|
}, d = (t, n, i, o, s, c = "", d = !1) => {
|
|
394
394
|
let f = l(t, n, o, s);
|
|
395
395
|
if (f.skip) return "";
|
|
396
|
-
let p = u(i, f.opclass), m = `${f.withSuffix}${c}`, h =
|
|
396
|
+
let p = u(i, f.opclass), m = `${f.withSuffix}${c}`, h = xe(n, r, a), g = d ? "UNIQUE " : "";
|
|
397
397
|
return r === "mssql" ? `IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = '${t}') CREATE ${g}INDEX ${e(t, r)} ON ${h}${f.using} (${p})${m};` : r === "mysql" ? `CREATE ${g}INDEX ${e(t, r)} ON ${h}${f.using} (${p})${m};` : `CREATE ${g}INDEX IF NOT EXISTS ${e(t, r)} ON ${h}${f.using} (${p})${m};`;
|
|
398
398
|
};
|
|
399
399
|
for (let t of n.appliedFullText ?? []) if (r === "postgres") {
|
|
@@ -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(...
|
|
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
|
}
|
|
@@ -424,14 +424,14 @@ var _ = (e, t, n, r = 400) => {
|
|
|
424
424
|
o.push(d(r, n.tableName, [e])), s.add(c([e]));
|
|
425
425
|
}
|
|
426
426
|
return o.join("\n");
|
|
427
|
-
},
|
|
427
|
+
}, ke = "CREATE OR REPLACE FUNCTION framework_notify_change() RETURNS trigger AS $$\nDECLARE\n payload TEXT;\nBEGIN\n payload := json_build_object(\n 'table', TG_TABLE_NAME,\n -- The schema the write landed in. Under namespace isolation this is\n -- the tenant schema (tenant_<id>); the CDC consumer uses it so a\n -- write in tenant A namespace does not spuriously wake tenant B\n -- subscriptions on the same-named table. public/absent = shared.\n 'schema', TG_TABLE_SCHEMA,\n 'op', lower(TG_OP),\n 'old', CASE WHEN TG_OP = 'INSERT' THEN NULL ELSE row_to_json(OLD) END,\n 'new', CASE WHEN TG_OP = 'DELETE' THEN NULL ELSE row_to_json(NEW) END\n )::text;\n -- pg_notify hard-caps the payload at 8000 bytes; a wide reactive row\n -- (big text / json column) would otherwise abort the write itself.\n -- Fall back to a body-less notice — the CDC consumer treats absent\n -- old/new as \"all columns changed\" and re-queries, so correctness is\n -- preserved; only the delta-diff fast path is skipped for that write.\n IF octet_length(payload) >= 7999 THEN\n payload := json_build_object(\n 'table', TG_TABLE_NAME,\n 'schema', TG_TABLE_SCHEMA,\n 'op', lower(TG_OP),\n 'old', NULL,\n 'new', NULL,\n 'oversized', true\n )::text;\n END IF;\n PERFORM pg_notify('framework_changes', payload);\n RETURN COALESCE(NEW, OLD);\nEND;\n$$ LANGUAGE plpgsql;", Ae = (e) => `
|
|
428
428
|
ALTER TABLE "${e.tableName}" REPLICA IDENTITY FULL;
|
|
429
429
|
DROP TRIGGER IF EXISTS framework_changes_${e.tableName} ON "${e.tableName}";
|
|
430
430
|
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
|
-
`.trim(),
|
|
434
|
-
let t = new Map(e.map((e) => [e.tableName, e])), n =
|
|
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 = 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);
|
|
@@ -467,8 +467,8 @@ FOR EACH ROW EXECUTE FUNCTION framework_notify_change();
|
|
|
467
467
|
sorted: o,
|
|
468
468
|
cyclic: r
|
|
469
469
|
};
|
|
470
|
-
},
|
|
471
|
-
let i = (t) => r ? `${e(r, n)}.${e(t, n)}` : e(t, n), a = `${t.table}_${t.column}_fkey`, o =
|
|
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 = 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",
|
|
@@ -482,7 +482,7 @@ FOR EACH ROW EXECUTE FUNCTION framework_notify_change();
|
|
|
482
482
|
case "mariadb": return `ALTER TABLE ${i(t.table)} ${l(!0)};`;
|
|
483
483
|
default: return `ALTER TABLE ${i(t.table)} ${l(!1)};`;
|
|
484
484
|
}
|
|
485
|
-
},
|
|
485
|
+
}, Fe = (e, t) => {
|
|
486
486
|
let n = /* @__PURE__ */ new Map();
|
|
487
487
|
if (u(t)) return n;
|
|
488
488
|
for (let t of e) {
|
|
@@ -490,7 +490,7 @@ FOR EACH ROW EXECUTE FUNCTION framework_notify_change();
|
|
|
490
490
|
e.add(t.column), n.set(t.table, e);
|
|
491
491
|
}
|
|
492
492
|
return n;
|
|
493
|
-
},
|
|
493
|
+
}, Ie = (e, t) => {
|
|
494
494
|
if (t !== "postgres") return "";
|
|
495
495
|
let n = /* @__PURE__ */ new Map();
|
|
496
496
|
for (let t of e) for (let e of Object.values(t.fields)) {
|
|
@@ -506,7 +506,7 @@ FOR EACH ROW EXECUTE FUNCTION framework_notify_change();
|
|
|
506
506
|
r.push(`DO $$ BEGIN\n IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = '${e.replace(/'/g, "''")}') THEN\n CREATE TYPE "${e}" AS ENUM (${n});\n END IF;\nEND $$;`);
|
|
507
507
|
}
|
|
508
508
|
return r.join("\n\n");
|
|
509
|
-
},
|
|
509
|
+
}, Le = (e, t) => {
|
|
510
510
|
if (t !== "postgres") return "";
|
|
511
511
|
let n = /* @__PURE__ */ new Set();
|
|
512
512
|
for (let t of e) for (let e of Object.values(t.fields)) e.type === "enum" && e.enumName && n.add(e.enumName);
|
|
@@ -520,34 +520,34 @@ BEGIN
|
|
|
520
520
|
SELECT oid INTO type_oid FROM pg_type WHERE typname = '${i}';\n IF type_oid IS NOT NULL\n AND EXISTS (SELECT 1 FROM pg_enum WHERE enumtypid = type_oid AND enumlabel = '${a}')\n AND NOT EXISTS (SELECT 1 FROM pg_enum WHERE enumtypid = type_oid AND enumlabel = '${o}') THEN\n IF current_setting('server_version_num')::int >= 140000 THEN\n EXECUTE format('ALTER TYPE %I RENAME VALUE %L TO %L', '${i}', '${a}', '${o}');\n ELSE\n UPDATE pg_enum SET enumlabel = '${o}' WHERE enumtypid = type_oid AND enumlabel = '${a}';\n END IF;\n END IF;\nEND $$;`);
|
|
521
521
|
}
|
|
522
522
|
return r.join("\n\n");
|
|
523
|
-
},
|
|
523
|
+
}, Re = (e) => {
|
|
524
524
|
let t = [], r = [];
|
|
525
525
|
for (let i of e) n(i) ? r.push(i) : t.push(i);
|
|
526
526
|
return {
|
|
527
527
|
tables: t,
|
|
528
528
|
views: r
|
|
529
529
|
};
|
|
530
|
-
},
|
|
531
|
-
let { tables: n, views: i } =
|
|
532
|
-
t === "postgres" &&
|
|
533
|
-
let l =
|
|
530
|
+
}, A = (e, t) => {
|
|
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
|
+
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
|
+
let l = Le(a, t);
|
|
534
534
|
l && c.push(l);
|
|
535
|
-
let d =
|
|
535
|
+
let d = Ie(a, t);
|
|
536
536
|
d && c.push(d);
|
|
537
|
-
for (let e of a) c.push(
|
|
538
|
-
if (!u(t)) for (let e of o) c.push(
|
|
537
|
+
for (let e of a) c.push(Ee(e, t, null, s.get(e.tableName)));
|
|
538
|
+
if (!u(t)) for (let e of o) c.push(Pe(e, t));
|
|
539
539
|
for (let e of a) {
|
|
540
|
-
let n =
|
|
540
|
+
let n = Oe(e, t);
|
|
541
541
|
n && c.push(n);
|
|
542
542
|
}
|
|
543
543
|
let f = a.filter((e) => e.isReactive !== !1);
|
|
544
544
|
if (f.length > 0 && t === "postgres") {
|
|
545
|
-
c.push(
|
|
546
|
-
for (let e of f) c.push(
|
|
545
|
+
c.push(ke);
|
|
546
|
+
for (let e of f) c.push(Ae(e));
|
|
547
547
|
}
|
|
548
548
|
for (let e of i) c.push(r(e, t));
|
|
549
549
|
return c.join("\n\n") + "\n";
|
|
550
|
-
},
|
|
550
|
+
}, ze = (t, n, r) => {
|
|
551
551
|
let i = e(t, n);
|
|
552
552
|
switch (n) {
|
|
553
553
|
case "postgres": return `CREATE SCHEMA IF NOT EXISTS ${i};`;
|
|
@@ -557,57 +557,57 @@ BEGIN
|
|
|
557
557
|
case "turso":
|
|
558
558
|
case "sqlite": return `ATTACH DATABASE '${(r ?? `${t}.db`).replace(/'/g, "''")}' AS ${i};`;
|
|
559
559
|
}
|
|
560
|
-
},
|
|
561
|
-
let a =
|
|
562
|
-
if (n === "postgres") return `${a}\n\nSET search_path TO ${o};\n\n${
|
|
563
|
-
if (n === "mysql" || n === "mariadb") return `${a}\n\nUSE ${o};\n\n${
|
|
564
|
-
let { sorted: s, cyclic: c } =
|
|
565
|
-
for (let e of s) d.push(
|
|
566
|
-
if (!u(n)) for (let e of c) d.push(
|
|
560
|
+
}, Be = (t, n, r, i) => {
|
|
561
|
+
let a = ze(r, n, i), o = e(r, n);
|
|
562
|
+
if (n === "postgres") return `${a}\n\nSET search_path TO ${o};\n\n${A(t, n)}`;
|
|
563
|
+
if (n === "mysql" || n === "mariadb") return `${a}\n\nUSE ${o};\n\n${A(t, n)}`;
|
|
564
|
+
let { sorted: s, cyclic: c } = Ne(t), l = Fe(c, n), d = [a];
|
|
565
|
+
for (let e of s) d.push(Ee(e, n, r, l.get(e.tableName)));
|
|
566
|
+
if (!u(n)) for (let e of c) d.push(Pe(e, n, r));
|
|
567
567
|
for (let e of s) {
|
|
568
|
-
let t =
|
|
568
|
+
let t = Oe(e, n, r);
|
|
569
569
|
t && d.push(t);
|
|
570
570
|
}
|
|
571
571
|
return d.join("\n\n") + "\n";
|
|
572
|
-
},
|
|
573
|
-
if (n !== "postgres") return
|
|
574
|
-
let { sorted: r, cyclic: i } =
|
|
572
|
+
}, Ve = (t, n) => {
|
|
573
|
+
if (n !== "postgres") return A(t, n);
|
|
574
|
+
let { sorted: r, cyclic: i } = Ne(t), a = Fe(i, n), o = [], s = Le(r, n);
|
|
575
575
|
s && o.push(s);
|
|
576
|
-
let c =
|
|
576
|
+
let c = Ie(r, n);
|
|
577
577
|
c && o.push(c);
|
|
578
|
-
for (let e of r) o.push(
|
|
579
|
-
for (let e of i) o.push(
|
|
578
|
+
for (let e of r) o.push(Ee(e, n, null, a.get(e.tableName)));
|
|
579
|
+
for (let e of i) o.push(Pe(e, n));
|
|
580
580
|
for (let t of r) {
|
|
581
581
|
let r = Object.entries(t.fields);
|
|
582
582
|
if (r.length === 0) continue;
|
|
583
583
|
let i = r.map(([r, i]) => {
|
|
584
|
-
let o =
|
|
584
|
+
let o = Te(r, i, n, void 0, a.get(t.tableName)?.has(r) ?? !1);
|
|
585
585
|
return `ALTER TABLE ${e(t.tableName, n)} ADD COLUMN IF NOT EXISTS ${o};`;
|
|
586
586
|
});
|
|
587
587
|
o.push(i.join("\n"));
|
|
588
588
|
}
|
|
589
589
|
for (let e of r) {
|
|
590
|
-
let t =
|
|
590
|
+
let t = Oe(e, n);
|
|
591
591
|
t && o.push(t);
|
|
592
592
|
}
|
|
593
593
|
let l = r.filter((e) => e.isReactive);
|
|
594
594
|
if (l.length > 0) {
|
|
595
|
-
o.push(
|
|
596
|
-
for (let e of l) o.push(
|
|
595
|
+
o.push(ke);
|
|
596
|
+
for (let e of l) o.push(Ae(e));
|
|
597
597
|
}
|
|
598
598
|
return o.join("\n\n") + "\n";
|
|
599
|
-
},
|
|
599
|
+
}, He = (e, t = "postgres") => d.gen(function* () {
|
|
600
600
|
let n = yield* p.SqlClient;
|
|
601
|
-
yield*
|
|
602
|
-
}),
|
|
601
|
+
yield* _e(n, Ge(n, A(e, t), t)).pipe(d.orDie);
|
|
602
|
+
}), Ue = (e, t) => {
|
|
603
603
|
let n = t.cause ?? {};
|
|
604
604
|
return (n.errno === 1061 || n.code === "ER_DUP_KEYNAME") && /^\s*CREATE\s+(UNIQUE\s+|FULLTEXT\s+)?INDEX\b/i.test(e);
|
|
605
|
-
},
|
|
605
|
+
}, We = (e) => d.gen(function* () {
|
|
606
606
|
let t = yield* p.SqlClient;
|
|
607
|
-
for (let n of
|
|
608
|
-
|
|
607
|
+
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(() => {
|
|
608
|
+
ve.error(_("migrate: statement failed", n, e, 200));
|
|
609
609
|
})), d.orDieWith((e) => Error(_("migrate: statement failed", n, e, 400).trim())));
|
|
610
|
-
}),
|
|
610
|
+
}), Ge = (e, t, n) => (n === "turso" ? We(t) : e.withTransaction(We(t))).pipe(d.orDie), Ke = (e) => {
|
|
611
611
|
let t = [], n = "", r = !1;
|
|
612
612
|
for (let i = 0; i < e.length; i++) {
|
|
613
613
|
if (e.slice(i, i + 2) === "$$") {
|
|
@@ -622,40 +622,40 @@ BEGIN
|
|
|
622
622
|
}
|
|
623
623
|
let i = n.trim();
|
|
624
624
|
return i.length > 0 && t.push(i), t;
|
|
625
|
-
},
|
|
626
|
-
await d.runPromise(
|
|
627
|
-
},
|
|
628
|
-
let r =
|
|
629
|
-
yield*
|
|
630
|
-
}),
|
|
631
|
-
await d.runPromise(
|
|
632
|
-
},
|
|
625
|
+
}, qe = async (e, t, n = "postgres") => {
|
|
626
|
+
await d.runPromise(He(e, n).pipe(d.provide(t)));
|
|
627
|
+
}, Je = (e, t, n = "postgres") => d.gen(function* () {
|
|
628
|
+
let r = Be(e, n, t), i = yield* p.SqlClient;
|
|
629
|
+
yield* _e(i, Ge(i, r, n)).pipe(d.orDie);
|
|
630
|
+
}), Ye = async (e, t, n, r = "postgres") => {
|
|
631
|
+
await d.runPromise(Je(e, t, r).pipe(d.provide(n)));
|
|
632
|
+
}, Xe = async (e, t, n = "postgres") => {
|
|
633
633
|
await d.runPromise(d.gen(function* () {
|
|
634
|
-
let t =
|
|
635
|
-
yield*
|
|
634
|
+
let t = Ve(e, n), r = yield* p.SqlClient;
|
|
635
|
+
yield* _e(r, Ge(r, t, n)).pipe(d.orDie);
|
|
636
636
|
}).pipe(d.provide(t)));
|
|
637
|
-
},
|
|
637
|
+
}, Ze = (e) => {
|
|
638
638
|
if (e == null) return e;
|
|
639
|
-
if (Array.isArray(e)) return e.map(
|
|
639
|
+
if (Array.isArray(e)) return e.map(Ze);
|
|
640
640
|
if (typeof e != "object") return e;
|
|
641
641
|
let t = {};
|
|
642
642
|
for (let n of Object.keys(e).sort()) {
|
|
643
643
|
let r = e[n];
|
|
644
|
-
r !== void 0 && (t[n] =
|
|
644
|
+
r !== void 0 && (t[n] = Ze(r));
|
|
645
645
|
}
|
|
646
646
|
return t;
|
|
647
|
-
},
|
|
647
|
+
}, Qe = (e) => {
|
|
648
648
|
if (!e.idScheme && !e.sensitive && !e.safe) return e;
|
|
649
649
|
let { idScheme: t, sensitive: n, safe: r, ...i } = e;
|
|
650
650
|
return i;
|
|
651
|
-
},
|
|
651
|
+
}, $e = (e) => [...e].map(Qe).sort((e, t) => e.name.localeCompare(t.name)), et = (e) => [...e].sort((e, t) => e.name.localeCompare(t.name)), tt = (e) => [...e].map((e) => ({
|
|
652
652
|
name: e.name,
|
|
653
|
-
columns:
|
|
654
|
-
indexes:
|
|
655
|
-
})).sort((e, t) => e.name.localeCompare(t.name)),
|
|
656
|
-
let t = { tables:
|
|
653
|
+
columns: $e(e.columns),
|
|
654
|
+
indexes: et(e.indexes)
|
|
655
|
+
})).sort((e, t) => e.name.localeCompare(t.name)), j = (e) => {
|
|
656
|
+
let t = { tables: tt(e.tables) }, n = JSON.stringify(Ze(t));
|
|
657
657
|
return m("sha256").update(n).digest("hex");
|
|
658
|
-
},
|
|
658
|
+
}, M = (e) => e.slice(0, 16), nt = (e, t) => {
|
|
659
659
|
let n = t.references ? {
|
|
660
660
|
table: t.references().tableName,
|
|
661
661
|
column: "id",
|
|
@@ -693,7 +693,7 @@ BEGIN
|
|
|
693
693
|
...t.enumValues === void 0 ? {} : { enumValues: t.enumValues },
|
|
694
694
|
...t.spatial === void 0 ? {} : { spatial: t.spatial }
|
|
695
695
|
};
|
|
696
|
-
},
|
|
696
|
+
}, rt = (e) => {
|
|
697
697
|
let t = [], n = /* @__PURE__ */ new Set(), r = (e) => {
|
|
698
698
|
n.has(e.name) || (n.add(e.name), t.push(e));
|
|
699
699
|
}, i = e.appliedPrimaryKey ?? [];
|
|
@@ -741,11 +741,11 @@ BEGIN
|
|
|
741
741
|
});
|
|
742
742
|
}
|
|
743
743
|
return t;
|
|
744
|
-
},
|
|
744
|
+
}, it = (e) => {
|
|
745
745
|
let t = new Set((e.appliedUniques ?? []).filter((e) => e.fields.length === 1).map((e) => e.fields[0])), n = [];
|
|
746
746
|
for (let [r, i] of Object.entries(e.fields)) {
|
|
747
747
|
if (i.dropped) continue;
|
|
748
|
-
let e =
|
|
748
|
+
let e = nt(r, i);
|
|
749
749
|
n.push(t.has(r) ? {
|
|
750
750
|
...e,
|
|
751
751
|
unique: !0
|
|
@@ -755,20 +755,20 @@ BEGIN
|
|
|
755
755
|
return {
|
|
756
756
|
name: e.tableName,
|
|
757
757
|
columns: n,
|
|
758
|
-
indexes:
|
|
758
|
+
indexes: rt(e),
|
|
759
759
|
...r.length > 0 ? { primaryKey: [...r] } : {}
|
|
760
760
|
};
|
|
761
|
-
},
|
|
761
|
+
}, at = (e) => {
|
|
762
762
|
let t = /* @__PURE__ */ new Map();
|
|
763
763
|
for (let n of e) for (let e of n.indexes) {
|
|
764
764
|
let r = t.get(e.name);
|
|
765
765
|
if (r !== void 0 && r !== n.name) throw Error(`duplicate index name '${e.name}' across tables '${r}' and '${n.name}'. Index names must be unique per SCHEMA, not just per table — the DB creates only one, so the other never applies and 'db plan' re-emits it forever. Give each an explicit, table-prefixed name (e.g. '${n.name}_${e.name}').`);
|
|
766
766
|
t.set(e.name, n.name);
|
|
767
767
|
}
|
|
768
|
-
},
|
|
769
|
-
let n = e.map((e) =>
|
|
770
|
-
return
|
|
771
|
-
},
|
|
768
|
+
}, N = (e, t) => {
|
|
769
|
+
let n = e.map((e) => it(x(e, t)));
|
|
770
|
+
return at(n), { tables: n };
|
|
771
|
+
}, ot = "framework_changes_", st = (e, t) => d.gen(function* () {
|
|
772
772
|
let n = t.filter((e) => !e.tableName.startsWith("_voltro_"));
|
|
773
773
|
if (n.length === 0) return {
|
|
774
774
|
missing: [],
|
|
@@ -781,17 +781,17 @@ BEGIN
|
|
|
781
781
|
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
782
782
|
WHERE NOT t.tgisinternal
|
|
783
783
|
AND n.nspname = current_schema()
|
|
784
|
-
AND t.tgname LIKE ${`${
|
|
784
|
+
AND t.tgname LIKE ${`${ot}%`}
|
|
785
785
|
`, i = new Set(r.map((e) => e.tgname)), a = [], o = [];
|
|
786
786
|
for (let e of n) {
|
|
787
|
-
let t = i.has(`${
|
|
787
|
+
let t = i.has(`${ot}${e.tableName}`), n = e.isReactive !== !1;
|
|
788
788
|
n && !t && a.push(e.tableName), !n && t && o.push(e.tableName);
|
|
789
789
|
}
|
|
790
790
|
return {
|
|
791
791
|
missing: a.sort(),
|
|
792
792
|
stale: o.sort()
|
|
793
793
|
};
|
|
794
|
-
}),
|
|
794
|
+
}), ct = (e) => {
|
|
795
795
|
let t = [];
|
|
796
796
|
if (e.missing.length > 0) {
|
|
797
797
|
let n = e.missing.slice(0, 8).join(", "), r = e.missing.length > 8 ? `, … (+${e.missing.length - 8})` : "";
|
|
@@ -802,19 +802,19 @@ BEGIN
|
|
|
802
802
|
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
803
|
}
|
|
804
804
|
return t.length > 0 ? t.join("\n") : void 0;
|
|
805
|
-
},
|
|
805
|
+
}, lt = /* @__PURE__ */ new Set(["voltro_isr_cache"]), P = (e) => lt.has(e) || e.startsWith("_voltro_") || e.startsWith("_cloud_") || e.startsWith("cluster_"), ut = {
|
|
806
806
|
postgres: !0,
|
|
807
807
|
mysql: !0,
|
|
808
808
|
mariadb: !0,
|
|
809
809
|
mssql: !0,
|
|
810
810
|
sqlite: !0
|
|
811
|
-
},
|
|
811
|
+
}, dt = {
|
|
812
812
|
postgres: !0,
|
|
813
813
|
mysql: !1,
|
|
814
814
|
mariadb: !1,
|
|
815
815
|
mssql: !0,
|
|
816
816
|
sqlite: !0
|
|
817
|
-
},
|
|
817
|
+
}, ft = (e) => {
|
|
818
818
|
switch (e) {
|
|
819
819
|
case "add-column":
|
|
820
820
|
case "drop-column":
|
|
@@ -824,43 +824,43 @@ BEGIN
|
|
|
824
824
|
case "add-foreign-key":
|
|
825
825
|
case "add-unique":
|
|
826
826
|
case "add-unique-composite":
|
|
827
|
-
case "add-check": return
|
|
828
|
-
default: return
|
|
827
|
+
case "add-check": return dt;
|
|
828
|
+
default: return ut;
|
|
829
829
|
}
|
|
830
|
-
},
|
|
830
|
+
}, pt = (e, t) => {
|
|
831
831
|
let n = new Map(t.tables.map((e) => [e.name, e]));
|
|
832
832
|
return new Map(e.map((e) => [e.tableName, {
|
|
833
833
|
table: e,
|
|
834
834
|
snapshot: n.get(e.tableName),
|
|
835
835
|
columnDefs: e.fields
|
|
836
836
|
}]));
|
|
837
|
-
},
|
|
837
|
+
}, mt = (e) => (t, n) => t.name === e ? -1 : n.name === e ? 1 : t.name.localeCompare(n.name), F = (e) => {
|
|
838
838
|
if (typeof e != "object" || !e) return JSON.stringify(e);
|
|
839
|
-
if (Array.isArray(e)) return `[${e.map(
|
|
839
|
+
if (Array.isArray(e)) return `[${e.map(F).join(",")}]`;
|
|
840
840
|
let t = e;
|
|
841
|
-
return `{${Object.keys(t).sort().map((e) => `${JSON.stringify(e)}:${
|
|
842
|
-
},
|
|
841
|
+
return `{${Object.keys(t).sort().map((e) => `${JSON.stringify(e)}:${F(t[e])}`).join(",")}}`;
|
|
842
|
+
}, ht = (e) => {
|
|
843
843
|
if (!e.hasDefault || e.defaultValue === void 0 || e.defaultValue === null) return null;
|
|
844
844
|
let t = e.defaultValue;
|
|
845
845
|
if (typeof t == "boolean") return t ? "__BOOL_TRUE__" : "__BOOL_FALSE__";
|
|
846
846
|
if (typeof t == "number") return String(t);
|
|
847
|
-
if (typeof t != "string") return
|
|
847
|
+
if (typeof t != "string") return F(t);
|
|
848
848
|
let n = t.trim(), r = n.toLowerCase().replace(/\s+/g, "");
|
|
849
849
|
if (r === "now" || r === "now()" || /^current_timestamp(\(\d*\))?$/.test(r) || r === "sysutcdatetime()" || r === "sysdatetime()" || r === "getutcdate()" || r === "getdate()") return "__NOW__";
|
|
850
850
|
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
851
|
if (o) try {
|
|
852
|
-
return
|
|
852
|
+
return F(JSON.parse(o[1]));
|
|
853
853
|
} catch {}
|
|
854
854
|
if (a.startsWith("{") || a.startsWith("[")) try {
|
|
855
|
-
return
|
|
855
|
+
return F(JSON.parse(a));
|
|
856
856
|
} catch {}
|
|
857
857
|
return /^-?\d+(\.\d+)?$/.test(a) ? String(Number(a)) : a;
|
|
858
|
-
},
|
|
859
|
-
let n =
|
|
858
|
+
}, gt = (e, t) => {
|
|
859
|
+
let n = ht(e), r = ht(t);
|
|
860
860
|
if (n === r) return !0;
|
|
861
861
|
let i = (e) => e === "1" || e === "true" ? "__BOOL_TRUE__" : e === "0" || e === "false" ? "__BOOL_FALSE__" : e;
|
|
862
862
|
return i(n) === i(r);
|
|
863
|
-
},
|
|
863
|
+
}, I = (e) => {
|
|
864
864
|
if (!e) return null;
|
|
865
865
|
let t = (e) => e === "restrict" ? "noAction" : e;
|
|
866
866
|
return {
|
|
@@ -869,18 +869,18 @@ BEGIN
|
|
|
869
869
|
onDelete: t(e.onDelete),
|
|
870
870
|
onUpdate: t(e.onUpdate)
|
|
871
871
|
};
|
|
872
|
-
},
|
|
872
|
+
}, _t = (e, t) => {
|
|
873
873
|
let n = e && e.length > 0 ? e : void 0, r = t && t.length > 0 ? t : void 0;
|
|
874
874
|
if (!n && !r) return !0;
|
|
875
875
|
if (!n || !r || n.length !== r.length) return !1;
|
|
876
876
|
let i = [...n].sort(), a = [...r].sort();
|
|
877
877
|
return i.every((e, t) => e === a[t]);
|
|
878
|
-
},
|
|
878
|
+
}, vt = (e, t) => e.type === t.type && e.nullable === t.nullable && e.unique === t.unique && gt(e, t) && JSON.stringify(I(e.references)) === JSON.stringify(I(t.references)) && _t(e.oneOf, t.oneOf), yt = (e, t) => t.oneOf && t.oneOf.length > 0 ? L({
|
|
879
879
|
kind: "add-check",
|
|
880
880
|
table: e,
|
|
881
881
|
column: t.name,
|
|
882
882
|
values: t.oneOf
|
|
883
|
-
}, "safe", `enum-membership CHECK on ${e}.${t.name}`) : void 0,
|
|
883
|
+
}, "safe", `enum-membership CHECK on ${e}.${t.name}`) : void 0, bt = (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])), xt = (e, t) => {
|
|
884
884
|
let n = new Map(t.columns.map((e) => [e.name, e])), r = new Map(e.columns.map((e) => [e.name, e])), i = [], a = [], o = [];
|
|
885
885
|
for (let t of e.columns) {
|
|
886
886
|
let e = n.get(t.name);
|
|
@@ -888,7 +888,7 @@ BEGIN
|
|
|
888
888
|
i.push(t);
|
|
889
889
|
continue;
|
|
890
890
|
}
|
|
891
|
-
|
|
891
|
+
vt(t, e) || o.push({
|
|
892
892
|
declared: t,
|
|
893
893
|
live: e
|
|
894
894
|
});
|
|
@@ -899,47 +899,47 @@ BEGIN
|
|
|
899
899
|
removed: a,
|
|
900
900
|
changed: o
|
|
901
901
|
};
|
|
902
|
-
},
|
|
902
|
+
}, St = (e, t) => {
|
|
903
903
|
let n = new Map(t.indexes.map((e) => [e.name, e])), r = new Map(e.indexes.map((e) => [e.name, e])), i = [], a = [];
|
|
904
904
|
for (let t of e.indexes) {
|
|
905
905
|
let e = n.get(t.name);
|
|
906
|
-
(!e || !
|
|
906
|
+
(!e || !bt(t, e)) && i.push(t);
|
|
907
907
|
}
|
|
908
908
|
for (let e of t.indexes) r.has(e.name) || a.push(e);
|
|
909
909
|
return {
|
|
910
910
|
added: i,
|
|
911
911
|
removed: a
|
|
912
912
|
};
|
|
913
|
-
},
|
|
913
|
+
}, L = (e, t, n, r) => ({
|
|
914
914
|
op: e,
|
|
915
915
|
classification: t,
|
|
916
|
-
atomicByDialect:
|
|
916
|
+
atomicByDialect: ft(e.kind),
|
|
917
917
|
...n ? { reason: n } : {},
|
|
918
918
|
...r ? { blocked: r } : {}
|
|
919
|
-
}),
|
|
919
|
+
}), Ct = (e, t, n) => {
|
|
920
920
|
let r = {
|
|
921
921
|
kind: "add-column",
|
|
922
922
|
table: e,
|
|
923
923
|
column: t
|
|
924
924
|
};
|
|
925
|
-
return t.nullable ?
|
|
926
|
-
},
|
|
925
|
+
return t.nullable ? L(r, "safe", "nullable column add — no backfill needed") : t.hasDefault && t.defaultValue !== void 0 ? L(r, "needs-default", "NOT NULL with literal default — DDL DEFAULT will populate existing rows") : n?.backfill ? L(r, "needs-backfill", `backfill declared (kind=${n.backfill.kind}) — applier will run 3-step add/update/set-not-null`) : L(r, "needs-backfill", "NOT NULL column on a table whose row count is unknown", { fix: `declare \`${t.name}: <type>().backfill(sql\`...\`)\` OR \`.default(value)\` so existing rows survive the migration` });
|
|
926
|
+
}, wt = (e, t, n) => {
|
|
927
927
|
let r = {
|
|
928
928
|
kind: "drop-column",
|
|
929
929
|
table: e,
|
|
930
930
|
column: t.name
|
|
931
931
|
};
|
|
932
|
-
return n?.dropped ?
|
|
933
|
-
},
|
|
932
|
+
return n?.dropped ? L(r, "lossy", `column dropped via \`${t.name}: dropped()\` marker — intentional`) : L(r, "lossy", "column missing from declared schema", { fix: `if intentional, add \`${t.name}: dropped()\` to the schema. If a typo, restore the field` });
|
|
933
|
+
}, Tt = (e, t, n, r) => L({
|
|
934
934
|
kind: "create-table",
|
|
935
935
|
table: e,
|
|
936
936
|
columns: t,
|
|
937
937
|
indexes: n,
|
|
938
938
|
...r && r.length > 0 ? { primaryKey: r } : {}
|
|
939
|
-
}, "safe", "new table — no data to preserve"),
|
|
939
|
+
}, "safe", "new table — no data to preserve"), Et = (e) => L({
|
|
940
940
|
kind: "drop-table",
|
|
941
941
|
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" }),
|
|
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" }), Dt = 5e4, Ot = (e, t, n, r) => {
|
|
943
943
|
let i = (n ?? 0) >= r, a;
|
|
944
944
|
return a = t.unique ? t.columns.length === 1 ? {
|
|
945
945
|
kind: "add-unique",
|
|
@@ -954,16 +954,16 @@ BEGIN
|
|
|
954
954
|
kind: "add-index",
|
|
955
955
|
table: e,
|
|
956
956
|
index: t
|
|
957
|
-
}, i ?
|
|
958
|
-
},
|
|
957
|
+
}, i ? L(a, "online-required", `online build on ${n} rows — CONCURRENTLY / INPLACE / WITH(ONLINE=ON) depending on dialect`) : L(a, "safe", t.unique ? t.columns.length === 1 ? "add unique constraint" : "add composite UNIQUE constraint" : "add B-tree index");
|
|
958
|
+
}, kt = (e, t) => t.unique && t.columns.length > 1 ? L({
|
|
959
959
|
kind: "drop-unique-composite",
|
|
960
960
|
table: e,
|
|
961
961
|
name: t.name
|
|
962
|
-
}, "safe", "drop composite UNIQUE constraint (no data loss — constraint is derived metadata)") :
|
|
962
|
+
}, "safe", "drop composite UNIQUE constraint (no data loss — constraint is derived metadata)") : L({
|
|
963
963
|
kind: "drop-index",
|
|
964
964
|
table: e,
|
|
965
965
|
index: t.name
|
|
966
|
-
}, "safe", "drop index (no data loss — index is derived data)"),
|
|
966
|
+
}, "safe", "drop index (no data loss — index is derived data)"), At = (e, t) => {
|
|
967
967
|
if (e === "reference") return "text";
|
|
968
968
|
switch (t) {
|
|
969
969
|
case "sqlite":
|
|
@@ -971,7 +971,7 @@ BEGIN
|
|
|
971
971
|
case "mssql": return e === "json" ? "text" : e;
|
|
972
972
|
default: return e;
|
|
973
973
|
}
|
|
974
|
-
},
|
|
974
|
+
}, jt = (e, t, n, r, i, a) => {
|
|
975
975
|
let o = [];
|
|
976
976
|
if (t.nullable !== n.nullable) {
|
|
977
977
|
let n = {
|
|
@@ -980,7 +980,7 @@ BEGIN
|
|
|
980
980
|
column: t.name,
|
|
981
981
|
toNullable: t.nullable
|
|
982
982
|
};
|
|
983
|
-
o.push(t.nullable ?
|
|
983
|
+
o.push(t.nullable ? L(n, "safe", `loosen ${e}.${t.name} to nullable`) : L(n, "needs-backfill", `tighten ${e}.${t.name} to NOT NULL — existing rows must already be non-null`));
|
|
984
984
|
}
|
|
985
985
|
if (t.unique !== n.unique) if (t.unique) {
|
|
986
986
|
let n = {
|
|
@@ -988,13 +988,13 @@ BEGIN
|
|
|
988
988
|
table: e,
|
|
989
989
|
column: t.name
|
|
990
990
|
}, r = (i ?? 0) >= a;
|
|
991
|
-
o.push(r ?
|
|
992
|
-
} else o.push(
|
|
991
|
+
o.push(r ? L(n, "online-required", `online unique build on ${i} rows — CONCURRENTLY / INPLACE / WITH(ONLINE=ON) depending on dialect`) : L(n, "safe", `add unique constraint on ${e}.${t.name} — existing rows must already be distinct (else the DB rejects at migrate)`));
|
|
992
|
+
} else o.push(L({
|
|
993
993
|
kind: "drop-unique",
|
|
994
994
|
table: e,
|
|
995
995
|
column: t.name
|
|
996
996
|
}, "safe", `drop unique constraint on ${e}.${t.name} — constraint is derived metadata, no data loss`));
|
|
997
|
-
if (
|
|
997
|
+
if (At(t.type, r) !== At(n.type, r)) {
|
|
998
998
|
let r = t.narrowedFrom;
|
|
999
999
|
if (r && r.from === n.type) {
|
|
1000
1000
|
let i = {
|
|
@@ -1005,7 +1005,7 @@ BEGIN
|
|
|
1005
1005
|
to: t.type,
|
|
1006
1006
|
...r.using === void 0 ? {} : { using: r.using }
|
|
1007
1007
|
};
|
|
1008
|
-
o.push(
|
|
1008
|
+
o.push(L(i, "needs-backfill", `type change ${n.type} → ${t.type} on ${e}.${t.name} — narrowedFrom('${r.from}') declared` + (r.using ? ` with USING ${r.using}` : " (implicit cast)")));
|
|
1009
1009
|
} else {
|
|
1010
1010
|
let r = {
|
|
1011
1011
|
kind: "alter-column-type",
|
|
@@ -1014,10 +1014,10 @@ BEGIN
|
|
|
1014
1014
|
from: n.type,
|
|
1015
1015
|
to: t.type
|
|
1016
1016
|
};
|
|
1017
|
-
o.push(
|
|
1017
|
+
o.push(L(r, "lossy", `type change ${n.type} → ${t.type} on ${e}.${t.name} may not be value-preserving`, { fix: `acknowledge it on the column: \`.narrowedFrom('${n.type}', { using: '${t.name}::${t.type}' })\` (drop \`using\` if the cast is implicit), or use a file-based migration` }));
|
|
1018
1018
|
}
|
|
1019
1019
|
}
|
|
1020
|
-
if (!
|
|
1020
|
+
if (!gt(t, n)) {
|
|
1021
1021
|
let n = {
|
|
1022
1022
|
kind: "alter-column-default",
|
|
1023
1023
|
table: e,
|
|
@@ -1025,18 +1025,18 @@ BEGIN
|
|
|
1025
1025
|
hasDefault: t.hasDefault,
|
|
1026
1026
|
...t.defaultValue === void 0 ? {} : { defaultValue: t.defaultValue }
|
|
1027
1027
|
};
|
|
1028
|
-
o.push(
|
|
1028
|
+
o.push(L(n, "safe", `default change on ${e}.${t.name} affects only future inserts`));
|
|
1029
1029
|
}
|
|
1030
|
-
if (!
|
|
1031
|
-
n.oneOf && n.oneOf.length > 0 && o.push(
|
|
1030
|
+
if (!_t(t.oneOf, n.oneOf)) {
|
|
1031
|
+
n.oneOf && n.oneOf.length > 0 && o.push(L({
|
|
1032
1032
|
kind: "drop-check",
|
|
1033
1033
|
table: e,
|
|
1034
1034
|
column: t.name
|
|
1035
1035
|
}, "safe", `drop stale enum CHECK on ${e}.${t.name}`));
|
|
1036
|
-
let r =
|
|
1036
|
+
let r = yt(e, t);
|
|
1037
1037
|
r && o.push(r);
|
|
1038
1038
|
}
|
|
1039
|
-
if (JSON.stringify(
|
|
1039
|
+
if (JSON.stringify(I(t.references)) !== JSON.stringify(I(n.references)) && (n.references && o.push(L({
|
|
1040
1040
|
kind: "drop-foreign-key",
|
|
1041
1041
|
table: e,
|
|
1042
1042
|
column: t.name
|
|
@@ -1050,17 +1050,17 @@ BEGIN
|
|
|
1050
1050
|
...t.references.onDelete ? { onDelete: t.references.onDelete } : {},
|
|
1051
1051
|
...t.references.onUpdate ? { onUpdate: t.references.onUpdate } : {}
|
|
1052
1052
|
};
|
|
1053
|
-
r === "null" && !t.nullable ? o.push(
|
|
1053
|
+
r === "null" && !t.nullable ? o.push(L(i, "lossy", `add FK ${e}.${t.name} → ${n}: orphanPolicy 'null' needs a nullable column (the NULL-out would violate NOT NULL)`, { fix: `make ${t.name} \`.nullable()\`, OR use \`orphanPolicy: 'delete'\`, OR clean the orphans and drop the policy` })) : r === "null" || r === "delete" ? o.push(L({
|
|
1054
1054
|
...i,
|
|
1055
1055
|
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(
|
|
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(L(i, "needs-backfill", `add FK ${e}.${t.name} → ${n} — existing rows must already reference a valid ${n} (else set orphanPolicy:'null'/'delete')`));
|
|
1057
1057
|
}
|
|
1058
1058
|
return o;
|
|
1059
|
-
},
|
|
1059
|
+
}, Mt = (e, t, n) => {
|
|
1060
1060
|
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
1061
|
for (let [n, c] of Object.entries(t)) {
|
|
1062
1062
|
let t = c.renamedFrom;
|
|
1063
|
-
t && o.has(t) && s.has(n) && (i.add(n), a.add(t), r.push(
|
|
1063
|
+
t && o.has(t) && s.has(n) && (i.add(n), a.add(t), r.push(L({
|
|
1064
1064
|
kind: "rename-column",
|
|
1065
1065
|
table: e.tableName,
|
|
1066
1066
|
from: t,
|
|
@@ -1072,7 +1072,7 @@ BEGIN
|
|
|
1072
1072
|
consumedAddedNames: i,
|
|
1073
1073
|
consumedRemovedNames: a
|
|
1074
1074
|
};
|
|
1075
|
-
},
|
|
1075
|
+
}, Nt = (e) => {
|
|
1076
1076
|
let t = {
|
|
1077
1077
|
safe: 0,
|
|
1078
1078
|
needsDefault: 0,
|
|
@@ -1107,37 +1107,37 @@ BEGIN
|
|
|
1107
1107
|
break;
|
|
1108
1108
|
}
|
|
1109
1109
|
return t;
|
|
1110
|
-
},
|
|
1111
|
-
let t =
|
|
1110
|
+
}, Pt = (e) => {
|
|
1111
|
+
let t = N(e.declared, e.dialect), n = pt(e.declared, t), r = new Map(e.live.tables.map((e) => [e.name, e])), i = e.onlineAfter ?? Dt, a = [];
|
|
1112
1112
|
for (let e of t.tables) if (!r.has(e.name)) {
|
|
1113
|
-
a.push(
|
|
1113
|
+
a.push(Tt(e.name, e.columns, e.indexes, e.primaryKey));
|
|
1114
1114
|
for (let t of e.columns) {
|
|
1115
|
-
let n =
|
|
1115
|
+
let n = yt(e.name, t);
|
|
1116
1116
|
n && a.push(n);
|
|
1117
1117
|
}
|
|
1118
1118
|
}
|
|
1119
1119
|
let o = new Set(e.ignoreTables ?? []);
|
|
1120
|
-
for (let t of e.live.tables) n.has(t.name) ||
|
|
1120
|
+
for (let t of e.live.tables) n.has(t.name) || P(t.name) || o.has(t.name) || a.push(Et(t.name));
|
|
1121
1121
|
for (let o of t.tables) {
|
|
1122
1122
|
let t = r.get(o.name);
|
|
1123
1123
|
if (!t) continue;
|
|
1124
|
-
let s = n.get(o.name), c =
|
|
1124
|
+
let s = n.get(o.name), c = xt(o, t), l = St(o, t), u = Mt(s.table, s.columnDefs, c);
|
|
1125
1125
|
a.push(...u.ops);
|
|
1126
1126
|
for (let e of c.removed) {
|
|
1127
1127
|
if (u.consumedRemovedNames.has(e.name)) continue;
|
|
1128
1128
|
let t = s.columnDefs[e.name];
|
|
1129
|
-
a.push(
|
|
1129
|
+
a.push(wt(o.name, e, t));
|
|
1130
1130
|
}
|
|
1131
1131
|
for (let e of c.added) {
|
|
1132
1132
|
if (u.consumedAddedNames.has(e.name)) continue;
|
|
1133
1133
|
let t = s.columnDefs[e.name];
|
|
1134
|
-
a.push(
|
|
1135
|
-
let n =
|
|
1134
|
+
a.push(Ct(o.name, e, t));
|
|
1135
|
+
let n = yt(o.name, e);
|
|
1136
1136
|
n && a.push(n);
|
|
1137
1137
|
}
|
|
1138
|
-
for (let e of l.added) a.push(
|
|
1139
|
-
for (let e of l.removed) a.push(
|
|
1140
|
-
for (let { declared: n, live: r } of c.changed) a.push(...
|
|
1138
|
+
for (let e of l.added) a.push(Ot(o.name, e, t.rowCount, i));
|
|
1139
|
+
for (let e of l.removed) a.push(kt(o.name, e));
|
|
1140
|
+
for (let { declared: n, live: r } of c.changed) a.push(...jt(o.name, n, r, e.dialect, t.rowCount, i));
|
|
1141
1141
|
}
|
|
1142
1142
|
let s = new Set(a.flatMap((e) => e.op.kind === "create-table" ? [e.op.table] : [])), c = new Map(t.tables.map((e) => [e.name, e])), l = (e) => {
|
|
1143
1143
|
let t = c.get(e);
|
|
@@ -1145,8 +1145,8 @@ BEGIN
|
|
|
1145
1145
|
column: e.name,
|
|
1146
1146
|
target: e.references.table
|
|
1147
1147
|
}] : []) : [];
|
|
1148
|
-
}, u =
|
|
1149
|
-
for (let e of t.tables) if (s.has(e.name)) for (let t of e.columns) !t.references || !u.has(
|
|
1148
|
+
}, u = ne([...s], l), d = [];
|
|
1149
|
+
for (let e of t.tables) if (s.has(e.name)) for (let t of e.columns) !t.references || !u.has(S(e.name, t.name)) || d.push(L({
|
|
1150
1150
|
kind: "add-foreign-key",
|
|
1151
1151
|
table: e.name,
|
|
1152
1152
|
column: t.name,
|
|
@@ -1161,8 +1161,8 @@ BEGIN
|
|
|
1161
1161
|
let n = a[t];
|
|
1162
1162
|
if (n.op.kind !== "create-table") continue;
|
|
1163
1163
|
let r = n.op;
|
|
1164
|
-
if (!r.columns.some((e) => u.has(
|
|
1165
|
-
let i = r.columns.map((t) => u.has(
|
|
1164
|
+
if (!r.columns.some((e) => u.has(S(r.table, e.name)))) continue;
|
|
1165
|
+
let i = r.columns.map((t) => u.has(S(r.table, t.name)) ? e(t) : t);
|
|
1166
1166
|
a[t] = {
|
|
1167
1167
|
...n,
|
|
1168
1168
|
op: {
|
|
@@ -1182,7 +1182,7 @@ BEGIN
|
|
|
1182
1182
|
let i = new Set(t).add(e), a = 0;
|
|
1183
1183
|
for (let t of r.columns) {
|
|
1184
1184
|
let n = t.references?.table;
|
|
1185
|
-
n && n !== e && !u.has(
|
|
1185
|
+
n && n !== e && !u.has(S(e, t.name)) && (a = Math.max(a, m(n, i) + 1));
|
|
1186
1186
|
}
|
|
1187
1187
|
return p.set(e, a), a;
|
|
1188
1188
|
}, h = (e) => e === "create-table" ? 0 : e === "drop-table" ? 2 : 1, g = (e) => {
|
|
@@ -1217,11 +1217,11 @@ BEGIN
|
|
|
1217
1217
|
});
|
|
1218
1218
|
return {
|
|
1219
1219
|
operations: v,
|
|
1220
|
-
fromFingerprint:
|
|
1221
|
-
toFingerprint:
|
|
1222
|
-
summary:
|
|
1220
|
+
fromFingerprint: j(e.live),
|
|
1221
|
+
toFingerprint: j(t),
|
|
1222
|
+
summary: Nt(v)
|
|
1223
1223
|
};
|
|
1224
|
-
},
|
|
1224
|
+
}, Ft = (e) => {
|
|
1225
1225
|
let t = /[`"[]?([A-Za-z_][A-Za-z0-9_]*)[`"\]]?\s*(?:in\b|=)/i.exec(e);
|
|
1226
1226
|
if (!t) return null;
|
|
1227
1227
|
let n = [...e.matchAll(/'((?:[^']|'')*)'/g)].map((e) => e[1].replace(/''/g, "'"));
|
|
@@ -1229,7 +1229,7 @@ BEGIN
|
|
|
1229
1229
|
column: t[1],
|
|
1230
1230
|
values: n
|
|
1231
1231
|
};
|
|
1232
|
-
},
|
|
1232
|
+
}, It = (e, t) => {
|
|
1233
1233
|
if (t === "vector") return "vector";
|
|
1234
1234
|
switch (e) {
|
|
1235
1235
|
case "text":
|
|
@@ -1256,7 +1256,7 @@ BEGIN
|
|
|
1256
1256
|
case "USER-DEFINED": return "text";
|
|
1257
1257
|
default: return "text";
|
|
1258
1258
|
}
|
|
1259
|
-
},
|
|
1259
|
+
}, R = (e) => {
|
|
1260
1260
|
switch (e.toUpperCase()) {
|
|
1261
1261
|
case "CASCADE": return "cascade";
|
|
1262
1262
|
case "RESTRICT": return "restrict";
|
|
@@ -1264,25 +1264,25 @@ BEGIN
|
|
|
1264
1264
|
case "SET DEFAULT": return "noAction";
|
|
1265
1265
|
default: return "noAction";
|
|
1266
1266
|
}
|
|
1267
|
-
},
|
|
1267
|
+
}, Lt = (e, t) => {
|
|
1268
1268
|
let n = e !== void 0 && e !== "" ? Number(e) : NaN;
|
|
1269
1269
|
return Number.isInteger(n) && n > 0 ? n : t;
|
|
1270
|
-
},
|
|
1270
|
+
}, Rt = () => Lt(process.env.VOLTRO_INTROSPECT_BATCH, 20), zt = 300, Bt = () => {
|
|
1271
1271
|
let e = process.env.VOLTRO_INTROSPECT_TIMEOUT_MS;
|
|
1272
|
-
return e !== void 0 && e.trim() === "0" ? 0 :
|
|
1273
|
-
},
|
|
1272
|
+
return e !== void 0 && e.trim() === "0" ? 0 : Lt(e, 3e4);
|
|
1273
|
+
}, Vt = (e, t) => {
|
|
1274
1274
|
let n = Number.isFinite(t) && t >= 1 ? Math.floor(t) : 1, r = [];
|
|
1275
1275
|
for (let t = 0; t < e.length; t += n) r.push(e.slice(t, t + n));
|
|
1276
1276
|
return r;
|
|
1277
|
-
},
|
|
1278
|
-
let t =
|
|
1277
|
+
}, Ht = (e) => {
|
|
1278
|
+
let t = Bt(), n = d.gen(function* () {
|
|
1279
1279
|
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 =
|
|
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 = Rt(), a = (e, t) => d.gen(function* () {
|
|
1281
1281
|
let r = [];
|
|
1282
|
-
for (let a of
|
|
1282
|
+
for (let a of Vt(e, i)) a.length !== 0 && r.push(...yield* t(n(a)));
|
|
1283
1283
|
return r;
|
|
1284
1284
|
}), o = [];
|
|
1285
|
-
for (let t = 0;; t +=
|
|
1285
|
+
for (let t = 0;; t += zt) {
|
|
1286
1286
|
let n = yield* e`
|
|
1287
1287
|
SELECT c.relname AS table_name,
|
|
1288
1288
|
COALESCE(c.reltuples::bigint, 0) AS row_count
|
|
@@ -1290,9 +1290,9 @@ BEGIN
|
|
|
1290
1290
|
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
1291
1291
|
WHERE n.nspname = current_schema() AND c.relkind = 'r'
|
|
1292
1292
|
ORDER BY c.relname
|
|
1293
|
-
LIMIT ${r(
|
|
1293
|
+
LIMIT ${r(zt)} OFFSET ${r(t)}
|
|
1294
1294
|
`;
|
|
1295
|
-
if (o.push(...n), n.length <
|
|
1295
|
+
if (o.push(...n), n.length < zt) break;
|
|
1296
1296
|
}
|
|
1297
1297
|
let s = /* @__PURE__ */ new Set(), c = [];
|
|
1298
1298
|
for (let e of o) s.has(e.table_name) || (s.add(e.table_name), c.push(e));
|
|
@@ -1377,7 +1377,7 @@ BEGIN
|
|
|
1377
1377
|
AND c.relname IN ${t}
|
|
1378
1378
|
)
|
|
1379
1379
|
SELECT * FROM ix ORDER BY table_name, index_name, position
|
|
1380
|
-
`), _ = /* @__PURE__ */ new Map(), v = /* @__PURE__ */ new Map(),
|
|
1380
|
+
`), _ = /* @__PURE__ */ new Map(), v = /* @__PURE__ */ new Map(), te = /* @__PURE__ */ new Map(), y = /* @__PURE__ */ new Map(), b = /* @__PURE__ */ new Map(), x = /* @__PURE__ */ new Map();
|
|
1381
1381
|
for (let e of u) {
|
|
1382
1382
|
let t = _.get(e.table_name);
|
|
1383
1383
|
t || (t = [], _.set(e.table_name, t)), t.push(e);
|
|
@@ -1386,25 +1386,25 @@ BEGIN
|
|
|
1386
1386
|
let t = v.get(e.table_name);
|
|
1387
1387
|
t || (t = /* @__PURE__ */ new Set(), v.set(e.table_name, t)), t.add(e.column_name);
|
|
1388
1388
|
}
|
|
1389
|
-
let
|
|
1389
|
+
let S = /* @__PURE__ */ new Map();
|
|
1390
1390
|
for (let e of p) {
|
|
1391
|
-
let t = `${e.table_name}${e.constraint_name}`, n =
|
|
1391
|
+
let t = `${e.table_name}${e.constraint_name}`, n = S.get(t);
|
|
1392
1392
|
n || (n = {
|
|
1393
1393
|
table: e.table_name,
|
|
1394
1394
|
columns: []
|
|
1395
|
-
},
|
|
1395
|
+
}, S.set(t, n)), n.columns.push({
|
|
1396
1396
|
name: e.column_name,
|
|
1397
1397
|
position: e.position
|
|
1398
1398
|
});
|
|
1399
1399
|
}
|
|
1400
|
-
for (let [e, t] of
|
|
1400
|
+
for (let [e, t] of S) {
|
|
1401
1401
|
let n = [...t.columns].sort((e, t) => e.position - t.position).map((e) => e.name);
|
|
1402
1402
|
if (n.length === 1) {
|
|
1403
|
-
let e =
|
|
1404
|
-
e || (e = /* @__PURE__ */ new Set(),
|
|
1403
|
+
let e = te.get(t.table);
|
|
1404
|
+
e || (e = /* @__PURE__ */ new Set(), te.set(t.table, e)), e.add(n[0]);
|
|
1405
1405
|
} else {
|
|
1406
|
-
let r =
|
|
1407
|
-
r || (r = [],
|
|
1406
|
+
let r = y.get(t.table);
|
|
1407
|
+
r || (r = [], y.set(t.table, r)), r.push({
|
|
1408
1408
|
name: e.slice(e.indexOf("\0") + 1),
|
|
1409
1409
|
table: t.table,
|
|
1410
1410
|
columns: n,
|
|
@@ -1413,23 +1413,23 @@ BEGIN
|
|
|
1413
1413
|
}
|
|
1414
1414
|
}
|
|
1415
1415
|
for (let e of g) {
|
|
1416
|
-
let t =
|
|
1417
|
-
t || (t = [],
|
|
1416
|
+
let t = b.get(e.source_table);
|
|
1417
|
+
t || (t = [], b.set(e.source_table, t)), t.push(e);
|
|
1418
1418
|
}
|
|
1419
1419
|
for (let e of ee) {
|
|
1420
|
-
let t =
|
|
1421
|
-
t || (t = /* @__PURE__ */ new Map(),
|
|
1420
|
+
let t = x.get(e.table_name);
|
|
1421
|
+
t || (t = /* @__PURE__ */ new Map(), x.set(e.table_name, t));
|
|
1422
1422
|
let n = t.get(e.index_name);
|
|
1423
1423
|
n || (n = [], t.set(e.index_name, n)), n.push(e);
|
|
1424
1424
|
}
|
|
1425
|
-
let
|
|
1425
|
+
let ne = [];
|
|
1426
1426
|
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" :
|
|
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 = te.get(e.table_name) ?? /* @__PURE__ */ new Set(), a = b.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) => {
|
|
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" : It(t.data_type, t.udt_name), c = a ? {
|
|
1429
1429
|
table: a.target_table,
|
|
1430
1430
|
column: a.target_column,
|
|
1431
|
-
onDelete:
|
|
1432
|
-
onUpdate:
|
|
1431
|
+
onDelete: R(a.delete_rule),
|
|
1432
|
+
onUpdate: R(a.update_rule)
|
|
1433
1433
|
} : void 0, l = h.get(`${e.table_name}.${t.column_name}`);
|
|
1434
1434
|
return {
|
|
1435
1435
|
name: t.column_name,
|
|
@@ -1441,7 +1441,7 @@ BEGIN
|
|
|
1441
1441
|
...c ? { references: c } : {},
|
|
1442
1442
|
...l ? { oneOf: l } : {}
|
|
1443
1443
|
};
|
|
1444
|
-
}), l = [], u =
|
|
1444
|
+
}), l = [], u = x.get(e.table_name);
|
|
1445
1445
|
if (u) for (let [t, n] of u) {
|
|
1446
1446
|
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
1447
|
let t = e.position;
|
|
@@ -1457,7 +1457,7 @@ BEGIN
|
|
|
1457
1457
|
...a ? { expression: !0 } : {}
|
|
1458
1458
|
});
|
|
1459
1459
|
}
|
|
1460
|
-
for (let t of
|
|
1460
|
+
for (let t of y.get(e.table_name) ?? []) l.push(t);
|
|
1461
1461
|
r.size > 0 && l.push({
|
|
1462
1462
|
name: `${e.table_name}_pkey`,
|
|
1463
1463
|
table: e.table_name,
|
|
@@ -1465,20 +1465,20 @@ BEGIN
|
|
|
1465
1465
|
unique: !0
|
|
1466
1466
|
});
|
|
1467
1467
|
let d = Number(e.row_count ?? 0);
|
|
1468
|
-
|
|
1468
|
+
ne.push({
|
|
1469
1469
|
name: e.table_name,
|
|
1470
1470
|
columns: c,
|
|
1471
1471
|
indexes: l,
|
|
1472
1472
|
...d > 0 ? { rowCount: d } : {}
|
|
1473
1473
|
});
|
|
1474
1474
|
}
|
|
1475
|
-
return { tables:
|
|
1475
|
+
return { tables: ne };
|
|
1476
1476
|
});
|
|
1477
1477
|
return (t > 0 ? e.withTransaction(n) : n).pipe(d.catchAll((e) => {
|
|
1478
1478
|
let n = `${String(e)} ${String(e.cause ?? "")}`.toLowerCase();
|
|
1479
1479
|
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
1480
|
}));
|
|
1481
|
-
},
|
|
1481
|
+
}, Ut = (e, t) => {
|
|
1482
1482
|
switch (e.toLowerCase()) {
|
|
1483
1483
|
case "varchar":
|
|
1484
1484
|
case "char":
|
|
@@ -1510,20 +1510,20 @@ BEGIN
|
|
|
1510
1510
|
case "json": return "json";
|
|
1511
1511
|
default: return "text";
|
|
1512
1512
|
}
|
|
1513
|
-
},
|
|
1513
|
+
}, z = (e) => e.map((e) => {
|
|
1514
1514
|
let t = e, n = {};
|
|
1515
1515
|
for (let e of Object.keys(t)) n[e.toLowerCase()] = t[e];
|
|
1516
1516
|
return n;
|
|
1517
|
-
}),
|
|
1518
|
-
let t =
|
|
1517
|
+
}), Wt = (e) => d.gen(function* () {
|
|
1518
|
+
let t = z(yield* e`
|
|
1519
1519
|
SELECT table_name, COALESCE(table_rows, 0) AS table_rows
|
|
1520
1520
|
FROM information_schema.tables
|
|
1521
1521
|
WHERE table_schema = DATABASE() AND table_type = 'BASE TABLE'
|
|
1522
|
-
ORDER BY table_name`), n =
|
|
1522
|
+
ORDER BY table_name`), n = z(yield* e`
|
|
1523
1523
|
SELECT table_name, column_name, data_type, column_type, is_nullable, column_default, column_key
|
|
1524
1524
|
FROM information_schema.columns
|
|
1525
1525
|
WHERE table_schema = DATABASE()
|
|
1526
|
-
ORDER BY table_name, ordinal_position`), r =
|
|
1526
|
+
ORDER BY table_name, ordinal_position`), r = z(yield* e`
|
|
1527
1527
|
SELECT k.table_name AS source_table,
|
|
1528
1528
|
k.column_name AS source_column,
|
|
1529
1529
|
k.referenced_table_name AS target_table,
|
|
@@ -1533,11 +1533,11 @@ BEGIN
|
|
|
1533
1533
|
JOIN information_schema.referential_constraints r
|
|
1534
1534
|
ON k.constraint_name = r.constraint_name
|
|
1535
1535
|
AND k.table_schema = r.constraint_schema
|
|
1536
|
-
WHERE k.table_schema = DATABASE() AND k.referenced_table_name IS NOT NULL`), i =
|
|
1536
|
+
WHERE k.table_schema = DATABASE() AND k.referenced_table_name IS NOT NULL`), i = z(yield* e`
|
|
1537
1537
|
SELECT table_name, index_name, non_unique, column_name, seq_in_index
|
|
1538
1538
|
FROM information_schema.statistics
|
|
1539
1539
|
WHERE table_schema = DATABASE() AND index_name <> 'PRIMARY'
|
|
1540
|
-
ORDER BY table_name, index_name, seq_in_index`), a =
|
|
1540
|
+
ORDER BY table_name, index_name, seq_in_index`), a = z(yield* e`
|
|
1541
1541
|
SELECT table_name, check_clause
|
|
1542
1542
|
FROM information_schema.check_constraints
|
|
1543
1543
|
WHERE constraint_schema = DATABASE()`.unprepared.pipe(d.orElseSucceed(() => []))), o = /* @__PURE__ */ new Set(), s = /* @__PURE__ */ new Map();
|
|
@@ -1547,7 +1547,7 @@ BEGIN
|
|
|
1547
1547
|
o.add(`${e.table_name}.${t[1]}`);
|
|
1548
1548
|
continue;
|
|
1549
1549
|
}
|
|
1550
|
-
let n =
|
|
1550
|
+
let n = Ft(e.check_clause);
|
|
1551
1551
|
n && s.set(`${e.table_name}.${n.column}`, n.values);
|
|
1552
1552
|
}
|
|
1553
1553
|
let c = /* @__PURE__ */ new Map(), l = /* @__PURE__ */ new Map(), u = /* @__PURE__ */ new Map();
|
|
@@ -1570,11 +1570,11 @@ BEGIN
|
|
|
1570
1570
|
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
1571
|
if (d) for (let e of d.values()) e.length === 1 && e[0].non_unique === 0 && a.add(e[0].column_name);
|
|
1572
1572
|
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" :
|
|
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" : Ut(t.data_type, t.column_type), u = c ? {
|
|
1574
1574
|
table: c.target_table,
|
|
1575
1575
|
column: c.target_column,
|
|
1576
|
-
onDelete:
|
|
1577
|
-
onUpdate:
|
|
1576
|
+
onDelete: R(c.delete_rule),
|
|
1577
|
+
onUpdate: R(c.update_rule)
|
|
1578
1578
|
} : 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
1579
|
return {
|
|
1580
1580
|
name: t.column_name,
|
|
@@ -1611,10 +1611,10 @@ BEGIN
|
|
|
1611
1611
|
});
|
|
1612
1612
|
}
|
|
1613
1613
|
return { tables: f };
|
|
1614
|
-
}),
|
|
1614
|
+
}), Gt = (e) => {
|
|
1615
1615
|
let t = e.toUpperCase();
|
|
1616
1616
|
return t.includes("INT") ? "integer" : t.includes("REAL") || t.includes("FLOA") || t.includes("DOUB") ? "real" : t.includes("BLOB") ? "bytes" : "text";
|
|
1617
|
-
},
|
|
1617
|
+
}, Kt = (e) => d.gen(function* () {
|
|
1618
1618
|
let t = yield* e`
|
|
1619
1619
|
SELECT name, sql FROM sqlite_master
|
|
1620
1620
|
WHERE type = 'table' AND name NOT LIKE 'sqlite_%'
|
|
@@ -1631,11 +1631,11 @@ BEGIN
|
|
|
1631
1631
|
d.set(t.name, r), t.unique === 1 && r.length === 1 && f.add(r[0]);
|
|
1632
1632
|
}
|
|
1633
1633
|
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" :
|
|
1634
|
+
let n = u.length === 1 && u[0] === e.name, r = l.get(e.name), i = r ? "reference" : n && e.name === "id" ? "id" : Gt(e.type), a = r ? {
|
|
1635
1635
|
table: r.table,
|
|
1636
1636
|
column: r.to,
|
|
1637
|
-
onDelete:
|
|
1638
|
-
onUpdate:
|
|
1637
|
+
onDelete: R(r.on_delete),
|
|
1638
|
+
onUpdate: R(r.on_update)
|
|
1639
1639
|
} : void 0, o = t.get(e.name);
|
|
1640
1640
|
return {
|
|
1641
1641
|
name: e.name,
|
|
@@ -1670,7 +1670,7 @@ BEGIN
|
|
|
1670
1670
|
});
|
|
1671
1671
|
}
|
|
1672
1672
|
return { tables: r };
|
|
1673
|
-
}),
|
|
1673
|
+
}), qt = (e) => {
|
|
1674
1674
|
switch (e.toLowerCase()) {
|
|
1675
1675
|
case "int":
|
|
1676
1676
|
case "smallint":
|
|
@@ -1692,7 +1692,7 @@ BEGIN
|
|
|
1692
1692
|
case "image": return "bytes";
|
|
1693
1693
|
default: return "text";
|
|
1694
1694
|
}
|
|
1695
|
-
},
|
|
1695
|
+
}, B = (e) => e === !0 || e === 1, Jt = (e) => d.gen(function* () {
|
|
1696
1696
|
let t = yield* e`
|
|
1697
1697
|
SELECT TABLE_NAME AS table_name FROM INFORMATION_SCHEMA.TABLES
|
|
1698
1698
|
WHERE TABLE_TYPE = 'BASE TABLE' ORDER BY TABLE_NAME`, n = yield* e`
|
|
@@ -1748,16 +1748,16 @@ BEGIN
|
|
|
1748
1748
|
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
1749
|
if (a) for (let [, e] of a) {
|
|
1750
1750
|
let t = [...e].sort((e, t) => e.key_ordinal - t.key_ordinal);
|
|
1751
|
-
if (
|
|
1752
|
-
else
|
|
1751
|
+
if (B(t[0].is_primary)) for (let e of t) d.push(e.column_name);
|
|
1752
|
+
else B(t[0].is_unique) && t.length === 1 && f.add(t[0].column_name);
|
|
1753
1753
|
}
|
|
1754
1754
|
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" :
|
|
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" : qt(t.data_type), s = i ? {
|
|
1756
1756
|
table: i.target_table,
|
|
1757
1757
|
column: i.target_column,
|
|
1758
|
-
onDelete:
|
|
1759
|
-
onUpdate:
|
|
1760
|
-
} : void 0, c = t.column_default === null ? null :
|
|
1758
|
+
onDelete: Yt(i.delete_rule),
|
|
1759
|
+
onUpdate: Yt(i.update_rule)
|
|
1760
|
+
} : void 0, c = t.column_default === null ? null : Xt(t.column_default), l = o.get(`${e}.${t.column_name}`);
|
|
1761
1761
|
return {
|
|
1762
1762
|
name: t.column_name,
|
|
1763
1763
|
type: a,
|
|
@@ -1771,11 +1771,11 @@ BEGIN
|
|
|
1771
1771
|
}), m = [];
|
|
1772
1772
|
if (a) for (let [t, n] of a) {
|
|
1773
1773
|
let r = [...n].sort((e, t) => e.key_ordinal - t.key_ordinal);
|
|
1774
|
-
|
|
1774
|
+
B(r[0].is_primary) || r.length === 1 && B(r[0].is_unique) || r.length === 1 && !B(r[0].is_unique) && i.has(r[0].column_name) && t !== `${e}_${r[0].column_name}_idx` || m.push({
|
|
1775
1775
|
name: t,
|
|
1776
1776
|
table: e,
|
|
1777
1777
|
columns: r.map((e) => e.column_name),
|
|
1778
|
-
unique:
|
|
1778
|
+
unique: B(r[0].is_unique)
|
|
1779
1779
|
});
|
|
1780
1780
|
}
|
|
1781
1781
|
d.length > 0 && m.push({
|
|
@@ -1790,37 +1790,37 @@ BEGIN
|
|
|
1790
1790
|
});
|
|
1791
1791
|
}
|
|
1792
1792
|
return { tables: u };
|
|
1793
|
-
}),
|
|
1793
|
+
}), Yt = (e) => {
|
|
1794
1794
|
switch (e.toUpperCase().replace(/_/g, " ")) {
|
|
1795
1795
|
case "CASCADE": return "cascade";
|
|
1796
1796
|
case "SET NULL": return "setNull";
|
|
1797
1797
|
case "SET DEFAULT": return "noAction";
|
|
1798
1798
|
default: return "noAction";
|
|
1799
1799
|
}
|
|
1800
|
-
},
|
|
1800
|
+
}, Xt = (e) => {
|
|
1801
1801
|
let t = e.trim();
|
|
1802
1802
|
for (; t.startsWith("(") && t.endsWith(")");) t = t.slice(1, -1).trim();
|
|
1803
1803
|
return t.startsWith("N'") && t.endsWith("'") ? t = t.slice(2, -1) : t.startsWith("'") && t.endsWith("'") && (t = t.slice(1, -1)), t;
|
|
1804
|
-
},
|
|
1805
|
-
mysql: () =>
|
|
1806
|
-
mssql: () =>
|
|
1807
|
-
sqlite: () =>
|
|
1808
|
-
orElse: () =>
|
|
1809
|
-
}),
|
|
1804
|
+
}, V = (e) => e.onDialectOrElse({
|
|
1805
|
+
mysql: () => Wt(e),
|
|
1806
|
+
mssql: () => Jt(e),
|
|
1807
|
+
sqlite: () => Kt(e),
|
|
1808
|
+
orElse: () => Ht(e)
|
|
1809
|
+
}), Zt = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, H = (e, t) => {
|
|
1810
1810
|
if (!e.spatial && e.type !== "vector" && e.type !== "array" && e.type !== "enum") return;
|
|
1811
1811
|
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
1812
|
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
|
|
1813
|
+
return E(e, t);
|
|
1814
|
+
}, U = (e) => {
|
|
1815
|
+
let t = H(e, "postgres");
|
|
1816
|
+
return t === void 0 ? Qt(e) : t;
|
|
1814
1817
|
}, Qt = (e) => {
|
|
1815
|
-
let t = Zt(e, "postgres");
|
|
1816
|
-
return t === void 0 ? $t(e) : t;
|
|
1817
|
-
}, $t = (e) => {
|
|
1818
1818
|
switch (e.type) {
|
|
1819
1819
|
case "id": return "text";
|
|
1820
1820
|
case "text": return "text";
|
|
1821
1821
|
case "integer": return "integer";
|
|
1822
1822
|
case "real": return "double precision";
|
|
1823
|
-
case "decimal": return
|
|
1823
|
+
case "decimal": return Zt(e, "NUMERIC");
|
|
1824
1824
|
case "bigint": return "bigint";
|
|
1825
1825
|
case "boolean": return "boolean";
|
|
1826
1826
|
case "timestamp": return "timestamptz";
|
|
@@ -1834,15 +1834,15 @@ BEGIN
|
|
|
1834
1834
|
case "interval": return "interval";
|
|
1835
1835
|
case "raw": return e.rawDdl ?? "text";
|
|
1836
1836
|
}
|
|
1837
|
-
},
|
|
1838
|
-
let t =
|
|
1837
|
+
}, W = (e) => {
|
|
1838
|
+
let t = H(e, "mariadb");
|
|
1839
1839
|
if (t !== void 0) return t;
|
|
1840
1840
|
switch (e.type) {
|
|
1841
1841
|
case "id": return "VARCHAR(64)";
|
|
1842
1842
|
case "text": return e.hasDefault && e.defaultValue !== void 0 || e.oneOf && e.oneOf.length > 0 ? "VARCHAR(255)" : "LONGTEXT";
|
|
1843
1843
|
case "integer": return "INT";
|
|
1844
1844
|
case "real": return "DOUBLE";
|
|
1845
|
-
case "decimal": return
|
|
1845
|
+
case "decimal": return Zt(e, "DECIMAL");
|
|
1846
1846
|
case "bigint": return "BIGINT";
|
|
1847
1847
|
case "boolean": return "TINYINT(1)";
|
|
1848
1848
|
case "timestamp": return "DATETIME(6)";
|
|
@@ -1856,57 +1856,57 @@ BEGIN
|
|
|
1856
1856
|
case "interval": return "BIGINT";
|
|
1857
1857
|
case "raw": return e.rawDdl ?? "LONGTEXT";
|
|
1858
1858
|
}
|
|
1859
|
-
},
|
|
1859
|
+
}, G = (e) => `"${e}"`, K = (e) => `\`${e.replace(/`/g, "``")}\``, $t = (e, t) => `ALTER TABLE ${t(e.table)} DROP COLUMN IF EXISTS ${t(e.column)};`, en = (e) => `ALTER TABLE ${K(e.table)} DROP COLUMN IF EXISTS ${K(e.column)}, ALGORITHM=COPY;`, tn = (e, t) => `ALTER TABLE ${t(e.table)} RENAME COLUMN ${t(e.from)} TO ${t(e.to)};`, nn = (e, t, n) => `ALTER TABLE ${n(e.table)} RENAME COLUMN ${n(e.column)} TO ${n(`${e.column}${On(t)}`)};`, rn = (e, t, n) => e.hasDefault && e.defaultValue !== void 0 ? `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} SET ${an(e, n)};` : `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} DROP DEFAULT;`, an = (e, t) => {
|
|
1860
1860
|
let n = t(e.defaultValue);
|
|
1861
1861
|
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
1862
|
return n;
|
|
1863
|
-
},
|
|
1864
|
-
let r =
|
|
1865
|
-
return r ?
|
|
1866
|
-
},
|
|
1867
|
-
let r = n ?? e.nullable, i =
|
|
1863
|
+
}, q = (e, t, n) => e.find((e) => e.tableName === t)?.fields[n], on = (e, t, n) => {
|
|
1864
|
+
let r = q(e, t, n);
|
|
1865
|
+
return r ? nt(n, r) : void 0;
|
|
1866
|
+
}, sn = (e, t, n) => {
|
|
1867
|
+
let r = n ?? e.nullable, i = ye(e, "mariadb");
|
|
1868
1868
|
return [
|
|
1869
|
-
|
|
1870
|
-
|
|
1869
|
+
K(t),
|
|
1870
|
+
E(e, "mariadb"),
|
|
1871
1871
|
r ? null : "NOT NULL",
|
|
1872
1872
|
i
|
|
1873
1873
|
].filter(Boolean).join(" ");
|
|
1874
|
-
},
|
|
1874
|
+
}, cn = (e, t) => e == null ? null : Array.isArray(e) ? ln(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, ln = (e, t, n) => be(e, t ?? { type: "json" }, n), un = (e, t) => e == null ? null : Array.isArray(e) ? ln(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
1875
|
if (!e.generatedAs) return null;
|
|
1876
1876
|
let { expr: n, stored: r } = e.generatedAs;
|
|
1877
1877
|
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
|
|
1880
|
-
let t =
|
|
1881
|
-
if (t) return `${
|
|
1882
|
-
let n = [
|
|
1878
|
+
}, dn = (e) => {
|
|
1879
|
+
if (e.type === "id" && e.idScheme?.kind === "numeric") return O(e.name, "postgres");
|
|
1880
|
+
let t = J(e, "postgres");
|
|
1881
|
+
if (t) return `${G(e.name)} ${U(e)} ${t}`;
|
|
1882
|
+
let n = [G(e.name), U(e)];
|
|
1883
1883
|
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 =
|
|
1884
|
+
let t = un(e.defaultValue, e);
|
|
1885
1885
|
t && n.push(t);
|
|
1886
1886
|
}
|
|
1887
|
-
return e.references && (n.push(`REFERENCES ${
|
|
1887
|
+
return e.references && (n.push(`REFERENCES ${G(e.references.table)} (${G(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${{
|
|
1888
1888
|
cascade: "CASCADE",
|
|
1889
1889
|
restrict: "RESTRICT",
|
|
1890
1890
|
setNull: "SET NULL",
|
|
1891
1891
|
noAction: "NO ACTION"
|
|
1892
1892
|
}[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 ${
|
|
1893
|
+
}, fn = (e, t) => e.primaryKey && e.primaryKey.length > 0 ? `,\n PRIMARY KEY (${e.primaryKey.map(t).join(", ")})` : "", pn = (e) => {
|
|
1894
|
+
let t = e.columns.map((e) => ` ${dn(e)}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${G(e.table)} (\n${t}${fn(e, G)}\n)`];
|
|
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(Nn).join(", ")})`);
|
|
1896
1896
|
return n;
|
|
1897
|
-
},
|
|
1898
|
-
let t =
|
|
1897
|
+
}, mn = 191, hn = (e) => {
|
|
1898
|
+
let t = W(e).toUpperCase();
|
|
1899
1899
|
return t.endsWith("TEXT") || t.endsWith("BLOB");
|
|
1900
1900
|
}, gn = (e) => {
|
|
1901
|
-
if (e.type === "id" && e.idScheme?.kind === "numeric") return
|
|
1902
|
-
let t =
|
|
1903
|
-
if (t) return `${
|
|
1904
|
-
let n = [
|
|
1905
|
-
if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && !
|
|
1906
|
-
let t =
|
|
1901
|
+
if (e.type === "id" && e.idScheme?.kind === "numeric") return O(e.name, "mariadb");
|
|
1902
|
+
let t = J(e, "mariadb");
|
|
1903
|
+
if (t) return `${K(e.name)} ${W(e)} ${t}`;
|
|
1904
|
+
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" && !hn(e) && n.push("UNIQUE"), e.hasDefault) {
|
|
1906
|
+
let t = cn(e.defaultValue, e);
|
|
1907
1907
|
t && n.push(t);
|
|
1908
1908
|
}
|
|
1909
|
-
return e.references && (n.push(`REFERENCES ${
|
|
1909
|
+
return e.references && (n.push(`REFERENCES ${K(e.references.table)} (${K(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${{
|
|
1910
1910
|
cascade: "CASCADE",
|
|
1911
1911
|
restrict: "RESTRICT",
|
|
1912
1912
|
setNull: "SET NULL",
|
|
@@ -1915,10 +1915,10 @@ BEGIN
|
|
|
1915
1915
|
}, _n = (e) => {
|
|
1916
1916
|
let t = new Map(e.columns.map((e) => [e.name, e])), n = (e) => {
|
|
1917
1917
|
let n = t.get(e);
|
|
1918
|
-
return n &&
|
|
1919
|
-
}, r = e.columns.map((e) => ` ${gn(e)}`).join(",\n"), i = [`CREATE TABLE IF NOT EXISTS ${
|
|
1920
|
-
for (let t of e.columns) t.unique && t.type !== "id" &&
|
|
1921
|
-
for (let t of e.indexes) t.name !== `${e.table}_pkey` && i.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${
|
|
1918
|
+
return n && hn(n) ? `${K(e)}(${mn})` : K(e);
|
|
1919
|
+
}, r = e.columns.map((e) => ` ${gn(e)}`).join(",\n"), i = [`CREATE TABLE IF NOT EXISTS ${K(e.table)} (\n${r}${fn(e, n)}\n)`];
|
|
1920
|
+
for (let t of e.columns) t.unique && t.type !== "id" && hn(t) && i.push(`CREATE UNIQUE INDEX IF NOT EXISTS ${K(`${e.table}_${t.name}_key`)} ON ${K(e.table)} (${n(t.name)})`);
|
|
1921
|
+
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
1922
|
return i;
|
|
1923
1923
|
}, vn = {
|
|
1924
1924
|
cascade: "CASCADE",
|
|
@@ -1931,7 +1931,7 @@ BEGIN
|
|
|
1931
1931
|
setNull: "SET NULL",
|
|
1932
1932
|
noAction: "NO ACTION"
|
|
1933
1933
|
}, bn = (e) => {
|
|
1934
|
-
let t =
|
|
1934
|
+
let t = H(e, "sqlite");
|
|
1935
1935
|
if (t !== void 0) return t;
|
|
1936
1936
|
switch (e.type) {
|
|
1937
1937
|
case "integer":
|
|
@@ -1942,28 +1942,28 @@ BEGIN
|
|
|
1942
1942
|
case "bytes": return "BLOB";
|
|
1943
1943
|
default: return "TEXT";
|
|
1944
1944
|
}
|
|
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
|
|
1947
|
-
let t =
|
|
1948
|
-
if (t) return `${
|
|
1949
|
-
let n = [
|
|
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" ? D(e, "sqlite") : null, xn = (e) => {
|
|
1946
|
+
if (e.type === "id" && e.idScheme?.kind === "numeric") return O(e.name, "sqlite");
|
|
1947
|
+
let t = J(e, "sqlite");
|
|
1948
|
+
if (t) return `${G(e.name)} ${bn(e)} ${t}`;
|
|
1949
|
+
let n = [G(e.name), bn(e)];
|
|
1950
1950
|
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
1951
|
let t = Y(e.defaultValue, "CURRENT_TIMESTAMP");
|
|
1952
1952
|
t && n.push(t);
|
|
1953
1953
|
}
|
|
1954
|
-
if (e.references && (n.push(`REFERENCES ${
|
|
1954
|
+
if (e.references && (n.push(`REFERENCES ${G(e.references.table)} (${G(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${vn[e.references.onDelete]}`)), e.oneOf && e.oneOf.length > 0) {
|
|
1955
1955
|
let t = e.oneOf.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
|
|
1956
|
-
n.push(`CHECK (${
|
|
1956
|
+
n.push(`CHECK (${G(e.name)} IN (${t}))`);
|
|
1957
1957
|
}
|
|
1958
1958
|
return n.join(" ");
|
|
1959
1959
|
}, Sn = (e) => {
|
|
1960
|
-
let t = e.columns.map((e) => ` ${xn(e)}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${
|
|
1961
|
-
for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${
|
|
1960
|
+
let t = e.columns.map((e) => ` ${xn(e)}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${G(e.table)} (\n${t}${fn(e, G)}\n)`];
|
|
1961
|
+
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
1962
|
return n;
|
|
1963
1963
|
}, X = (e, t) => {
|
|
1964
1964
|
let n = t.find((t) => t.tableName === e);
|
|
1965
1965
|
if (!n) return [];
|
|
1966
|
-
let r =
|
|
1966
|
+
let r = N([n]).tables[0], i = `${e}__voltro_rebuild`, a = r.columns.map((e) => G(e.name)).join(", "), o = [
|
|
1967
1967
|
...Sn({
|
|
1968
1968
|
kind: "create-table",
|
|
1969
1969
|
table: i,
|
|
@@ -1971,15 +1971,15 @@ BEGIN
|
|
|
1971
1971
|
indexes: [],
|
|
1972
1972
|
...r.primaryKey ? { primaryKey: r.primaryKey } : {}
|
|
1973
1973
|
}),
|
|
1974
|
-
`INSERT INTO ${
|
|
1975
|
-
`DROP TABLE ${
|
|
1976
|
-
`ALTER TABLE ${
|
|
1974
|
+
`INSERT INTO ${G(i)} (${a}) SELECT ${a} FROM ${G(e)}`,
|
|
1975
|
+
`DROP TABLE ${G(e)}`,
|
|
1976
|
+
`ALTER TABLE ${G(i)} RENAME TO ${G(e)}`
|
|
1977
1977
|
];
|
|
1978
|
-
for (let t of r.indexes) t.name !== `${e}_pkey` && o.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${
|
|
1978
|
+
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
1979
|
return o;
|
|
1980
1980
|
}, Cn = (e, t, n, r) => {
|
|
1981
1981
|
let i = r ?? e.nullable;
|
|
1982
|
-
return `ALTER TABLE ${Z(n)} ALTER COLUMN ${Z(t)} ${
|
|
1982
|
+
return `ALTER TABLE ${Z(n)} ALTER COLUMN ${Z(t)} ${E(e, "mssql")} ${i ? "NULL" : "NOT NULL"};`;
|
|
1983
1983
|
}, wn = (e) => {
|
|
1984
1984
|
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
1985
|
if (!e.hasDefault) return t;
|
|
@@ -1988,14 +1988,14 @@ BEGIN
|
|
|
1988
1988
|
let r = n.replace(/^DEFAULT\s+/i, "");
|
|
1989
1989
|
return `${t} ALTER TABLE ${Z(e.table)} ADD DEFAULT ${r} FOR ${Z(e.column)};`;
|
|
1990
1990
|
}, Z = (e) => `[${e.replace(/]/g, "]]")}]`, Tn = (e) => {
|
|
1991
|
-
let t =
|
|
1991
|
+
let t = H(e, "mssql");
|
|
1992
1992
|
if (t !== void 0) return t;
|
|
1993
1993
|
switch (e.type) {
|
|
1994
1994
|
case "id":
|
|
1995
1995
|
case "reference": return "NVARCHAR(64)";
|
|
1996
1996
|
case "integer": return "INT";
|
|
1997
1997
|
case "real": return "FLOAT";
|
|
1998
|
-
case "decimal": return
|
|
1998
|
+
case "decimal": return Zt(e, "DECIMAL");
|
|
1999
1999
|
case "bigint": return "BIGINT";
|
|
2000
2000
|
case "boolean": return "BIT";
|
|
2001
2001
|
case "timestamp": return "DATETIME2(6)";
|
|
@@ -2004,8 +2004,8 @@ BEGIN
|
|
|
2004
2004
|
default: return "NVARCHAR(MAX)";
|
|
2005
2005
|
}
|
|
2006
2006
|
}, En = (e, t) => {
|
|
2007
|
-
if (e.type === "id" && e.idScheme?.kind === "numeric") return
|
|
2008
|
-
let n = e.type === "text" && t?.has(e.name) ? "NVARCHAR(450)" : Tn(e), r =
|
|
2007
|
+
if (e.type === "id" && e.idScheme?.kind === "numeric") return O(e.name, "mssql");
|
|
2008
|
+
let n = e.type === "text" && t?.has(e.name) ? "NVARCHAR(450)" : Tn(e), r = J(e, "mssql");
|
|
2009
2009
|
if (r) return `${Z(e.name)} ${r}`;
|
|
2010
2010
|
let i = [Z(e.name), n];
|
|
2011
2011
|
if (e.type === "id" && i.push("PRIMARY KEY"), e.nullable || i.push("NOT NULL"), e.unique && e.type !== "id" && i.push("UNIQUE"), e.hasDefault) {
|
|
@@ -2014,7 +2014,7 @@ BEGIN
|
|
|
2014
2014
|
}
|
|
2015
2015
|
return e.references && (i.push(`REFERENCES ${Z(e.references.table)} (${Z(e.references.column)})`), e.references.onDelete && i.push(`ON DELETE ${yn[e.references.onDelete]}`)), i.join(" ");
|
|
2016
2016
|
}, Dn = (e) => {
|
|
2017
|
-
let t = (e) => e.replace(/'/g, "''"), n = new Set(e.indexes.flatMap((e) => e.columns)), r = e.columns.map((e) => ` ${En(e, n)}`).join(",\n"), i = `CREATE TABLE ${Z(e.table)} (\n${r}${
|
|
2017
|
+
let t = (e) => e.replace(/'/g, "''"), n = new Set(e.indexes.flatMap((e) => e.columns)), r = e.columns.map((e) => ` ${En(e, n)}`).join(",\n"), i = `CREATE TABLE ${Z(e.table)} (\n${r}${fn(e, Z)}\n)`, a = [`IF OBJECT_ID(N'${t(e.table)}', N'U') IS NULL EXEC(N'${t(i)}')`];
|
|
2018
2018
|
for (let n of e.indexes) {
|
|
2019
2019
|
if (n.name === `${e.table}_pkey`) continue;
|
|
2020
2020
|
let r = `CREATE ${n.unique ? "UNIQUE " : ""}INDEX ${Z(n.name)} ON ${Z(e.table)} (${n.columns.map(Z).join(", ")})`;
|
|
@@ -2025,9 +2025,9 @@ BEGIN
|
|
|
2025
2025
|
let r = `${e.table}${On(t)}`;
|
|
2026
2026
|
return `ALTER TABLE ${n(e.table)} RENAME TO ${n(r)};`;
|
|
2027
2027
|
}, jn = (e, t, n) => {
|
|
2028
|
-
let r =
|
|
2029
|
-
return r ?
|
|
2030
|
-
}, Mn = (e, t, n) => jn(e, t, n) ? `${
|
|
2028
|
+
let r = q(e, t, n);
|
|
2029
|
+
return r ? hn({ type: r.type }) : !1;
|
|
2030
|
+
}, Mn = (e, t, n) => jn(e, t, n) ? `${K(n)}(${mn})` : K(n), Nn = (e) => e.startsWith("(") ? e : G(e), Pn = (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(Nn).join(", ")});`, Fn = (e, t) => `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${K(e.index.name)} ON ${K(e.table)} (${e.index.columns.map((n) => Mn(t, e.table, n)).join(", ")});`, In = (e) => `DROP INDEX IF EXISTS ${G(e.index)};`, Ln = (e) => `DROP INDEX ${K(e.index)} ON ${K(e.table)};`, Rn = (e) => `DROP INDEX IF EXISTS ${Z(e.index)} ON ${Z(e.table)};`, zn = (e) => {
|
|
2031
2031
|
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
2032
|
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
2033
|
}, Bn = (e, t, n) => {
|
|
@@ -2039,13 +2039,13 @@ BEGIN
|
|
|
2039
2039
|
t && t.type === "text" && !t.generatedAs && i.push(`ALTER TABLE ${Z(e)} ALTER COLUMN ${Z(n)} NVARCHAR(450) ${t.nullable ? "NULL" : "NOT NULL"};`);
|
|
2040
2040
|
}
|
|
2041
2041
|
return i;
|
|
2042
|
-
}, Vn = (e) => `ALTER TABLE ${
|
|
2043
|
-
let t = e.fields.map((e) =>
|
|
2044
|
-
return `ALTER TABLE ${
|
|
2042
|
+
}, Vn = (e) => `ALTER TABLE ${G(e.table)} ADD CONSTRAINT ${G(`${e.table}_${e.column}_key`)} UNIQUE (${G(e.column)});`, Hn = (e, t) => `ALTER TABLE ${K(e.table)} ADD CONSTRAINT ${K(`${e.table}_${e.column}_key`)} UNIQUE (${Mn(t, e.table, e.column)});`, Un = (e) => {
|
|
2043
|
+
let t = e.fields.map((e) => G(e)).join(", ");
|
|
2044
|
+
return `ALTER TABLE ${G(e.table)} ADD CONSTRAINT ${G(e.name)} UNIQUE (${t});`;
|
|
2045
2045
|
}, Wn = (e, t) => {
|
|
2046
2046
|
let n = e.fields.map((n) => Mn(t, e.table, n)).join(", ");
|
|
2047
|
-
return `ALTER TABLE ${
|
|
2048
|
-
}, Gn = (e) => `ALTER TABLE ${
|
|
2047
|
+
return `ALTER TABLE ${K(e.table)} ADD CONSTRAINT ${K(e.name)} UNIQUE (${n});`;
|
|
2048
|
+
}, Gn = (e) => `ALTER TABLE ${G(e.table)} DROP CONSTRAINT IF EXISTS ${G(e.name)};`, Kn = (e) => `ALTER TABLE ${K(e.table)} DROP INDEX ${K(e.name)};`, qn = (e) => `ALTER TABLE ${G(e.table)} DROP CONSTRAINT IF EXISTS ${G(`${e.table}_${e.column}_key`)};`, Jn = (e) => `ALTER TABLE ${K(e.table)} DROP INDEX ${K(`${e.table}_${e.column}_key`)};`, Yn = (e, t) => {
|
|
2049
2049
|
let n = [], r = t(e.table), i = t(e.column), a = t(e.targetTable), o = t(e.targetColumn);
|
|
2050
2050
|
if (e.orphanPolicy) {
|
|
2051
2051
|
let t = `${i} IS NOT NULL AND ${i} NOT IN (SELECT ${o} FROM ${a})`;
|
|
@@ -2063,11 +2063,11 @@ BEGIN
|
|
|
2063
2063
|
setNull: "SET NULL",
|
|
2064
2064
|
noAction: "NO ACTION"
|
|
2065
2065
|
}[e.onDelete]}`), n.push(s.join(" ") + ";"), n;
|
|
2066
|
-
}, Xn = (e) => `ALTER TABLE ${
|
|
2066
|
+
}, Xn = (e) => `ALTER TABLE ${G(e.table)} DROP CONSTRAINT IF EXISTS ${G(`${e.table}_${e.column}_fkey`)};`, Zn = (e) => `ALTER TABLE ${K(e.table)} DROP FOREIGN KEY ${K(`${e.table}_${e.column}_fkey`)};`, Qn = (e, t) => {
|
|
2067
2067
|
let n = e.values.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
|
|
2068
2068
|
return `ALTER TABLE ${t(e.table)} ADD CONSTRAINT ${t(`${e.table}_${e.column}_check`)} CHECK (${t(e.column)} IN (${n}));`;
|
|
2069
|
-
}, $n = (e) => `ALTER TABLE ${
|
|
2070
|
-
let i = e.column, a = r === "mariadb", o = a ?
|
|
2069
|
+
}, $n = (e) => `ALTER TABLE ${G(e.table)} DROP CONSTRAINT IF EXISTS ${G(`${e.table}_${e.column}_check`)};`, er = (e) => `ALTER TABLE ${K(e.table)} DROP CHECK ${K(`${e.table}_${e.column}_check`)};`, tr = (e, t, n, r) => {
|
|
2070
|
+
let i = e.column, a = r === "mariadb", o = a ? K : r === "mssql" ? Z : G, s = a ? W(i) : r === "mssql" ? Tn(i) : r === "sqlite" ? bn(i) : U(i), c = r === "mssql" ? "ADD" : "ADD COLUMN", l = (e) => a ? cn(e, i) : r === "mssql" ? Y(e, "SYSUTCDATETIME()") : r === "sqlite" ? Y(e, "CURRENT_TIMESTAMP") : un(e, i), u = J(i, r);
|
|
2071
2071
|
if (u) {
|
|
2072
2072
|
let t = r === "mssql" ? `${o(i.name)} ${u}` : `${o(i.name)} ${s} ${u}`;
|
|
2073
2073
|
return {
|
|
@@ -2117,7 +2117,10 @@ BEGIN
|
|
|
2117
2117
|
};
|
|
2118
2118
|
}, Q = (e, t, n) => e.unsafe(t).pipe(d.tapError((e) => d.sync(() => {
|
|
2119
2119
|
process.stderr.write(_(`applier: statement failed (op=${n})`, t, e, 400));
|
|
2120
|
-
})), d.
|
|
2120
|
+
})), d.mapError((e) => {
|
|
2121
|
+
let r = _(`applier: statement failed (op=${n})`, t, e, 400).trim();
|
|
2122
|
+
return Object.assign(e, { message: r });
|
|
2123
|
+
}), d.map(() => void 0)), $ = (e, t, n) => d.forEach(t, (t) => Q(e, t, n), { discard: !0 }), rr = (e, t, n) => d.gen(function* () {
|
|
2121
2124
|
let r = process.hrtime.bigint(), i = nr(n.declared), a = t.op;
|
|
2122
2125
|
switch (a.kind) {
|
|
2123
2126
|
case "create-table": {
|
|
@@ -2125,7 +2128,7 @@ BEGIN
|
|
|
2125
2128
|
mysql: () => d.succeed(_n(a)),
|
|
2126
2129
|
mssql: () => d.succeed(Dn(a)),
|
|
2127
2130
|
sqlite: () => d.succeed(Sn(a)),
|
|
2128
|
-
orElse: () => d.succeed(
|
|
2131
|
+
orElse: () => d.succeed(pn(a))
|
|
2129
2132
|
});
|
|
2130
2133
|
for (let n of t) yield* Q(e, n, a.kind);
|
|
2131
2134
|
break;
|
|
@@ -2133,24 +2136,24 @@ BEGIN
|
|
|
2133
2136
|
case "drop-table": {
|
|
2134
2137
|
let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString(), r = (e) => t ? An(a, n, e) : kn(a, e);
|
|
2135
2138
|
yield* e.onDialectOrElse({
|
|
2136
|
-
mysql: () => Q(e, r(
|
|
2137
|
-
orElse: () => Q(e, r(
|
|
2139
|
+
mysql: () => Q(e, r(K), a.kind),
|
|
2140
|
+
orElse: () => Q(e, r(G), a.kind)
|
|
2138
2141
|
});
|
|
2139
2142
|
break;
|
|
2140
2143
|
}
|
|
2141
2144
|
case "drop-column": {
|
|
2142
2145
|
let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString();
|
|
2143
2146
|
yield* e.onDialectOrElse({
|
|
2144
|
-
mysql: () => Q(e, t ?
|
|
2145
|
-
orElse: () => Q(e, t ?
|
|
2147
|
+
mysql: () => Q(e, t ? nn(a, n, K) : en(a), a.kind),
|
|
2148
|
+
orElse: () => Q(e, t ? nn(a, n, G) : $t(a, G), a.kind)
|
|
2146
2149
|
});
|
|
2147
2150
|
break;
|
|
2148
2151
|
}
|
|
2149
2152
|
case "rename-column":
|
|
2150
2153
|
yield* e.onDialectOrElse({
|
|
2151
|
-
mysql: () => Q(e,
|
|
2154
|
+
mysql: () => Q(e, tn(a, K), a.kind),
|
|
2152
2155
|
mssql: () => Q(e, `EXEC sp_rename N'${a.table.replace(/'/g, "''")}.${a.from.replace(/'/g, "''")}', N'${a.to.replace(/'/g, "''")}', 'COLUMN';`, a.kind),
|
|
2153
|
-
orElse: () => Q(e,
|
|
2156
|
+
orElse: () => Q(e, tn(a, G), a.kind)
|
|
2154
2157
|
});
|
|
2155
2158
|
break;
|
|
2156
2159
|
case "add-index":
|
|
@@ -2199,9 +2202,9 @@ BEGIN
|
|
|
2199
2202
|
break;
|
|
2200
2203
|
case "add-foreign-key":
|
|
2201
2204
|
yield* e.onDialectOrElse({
|
|
2202
|
-
mysql: () => $(e, Yn(a,
|
|
2205
|
+
mysql: () => $(e, Yn(a, K), a.kind),
|
|
2203
2206
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2204
|
-
orElse: () => $(e, Yn(a,
|
|
2207
|
+
orElse: () => $(e, Yn(a, G), a.kind)
|
|
2205
2208
|
});
|
|
2206
2209
|
break;
|
|
2207
2210
|
case "add-column": {
|
|
@@ -2250,41 +2253,41 @@ BEGIN
|
|
|
2250
2253
|
case "alter-column-nullability":
|
|
2251
2254
|
yield* e.onDialectOrElse({
|
|
2252
2255
|
mysql: () => {
|
|
2253
|
-
let t =
|
|
2254
|
-
return t ? Q(e, `ALTER TABLE ${
|
|
2256
|
+
let t = q(n.declared, a.table, a.column);
|
|
2257
|
+
return t ? Q(e, `ALTER TABLE ${K(a.table)} MODIFY COLUMN ${sn(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.`));
|
|
2255
2258
|
},
|
|
2256
2259
|
mssql: () => {
|
|
2257
|
-
let t =
|
|
2260
|
+
let t = q(n.declared, a.table, a.column);
|
|
2258
2261
|
return t ? Q(e, Cn(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}'.`));
|
|
2259
2262
|
},
|
|
2260
2263
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2261
|
-
orElse: () => Q(e, `ALTER TABLE ${
|
|
2264
|
+
orElse: () => Q(e, `ALTER TABLE ${G(a.table)} ALTER COLUMN ${G(a.column)} ${a.toNullable ? "DROP NOT NULL" : "SET NOT NULL"};`, a.kind)
|
|
2262
2265
|
});
|
|
2263
2266
|
break;
|
|
2264
2267
|
case "alter-column-default": {
|
|
2265
|
-
let t =
|
|
2268
|
+
let t = on(n.declared, a.table, a.column);
|
|
2266
2269
|
yield* e.onDialectOrElse({
|
|
2267
|
-
mysql: () => Q(e,
|
|
2270
|
+
mysql: () => Q(e, rn(a, K, (e) => cn(e, t)), a.kind),
|
|
2268
2271
|
mssql: () => Q(e, wn(a), a.kind),
|
|
2269
2272
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2270
|
-
orElse: () => Q(e,
|
|
2273
|
+
orElse: () => Q(e, rn(a, G, (e) => un(e, t)), a.kind)
|
|
2271
2274
|
});
|
|
2272
2275
|
break;
|
|
2273
2276
|
}
|
|
2274
2277
|
case "alter-column-type": {
|
|
2275
|
-
let r =
|
|
2278
|
+
let r = U(on(n.declared, a.table, a.column) ?? { type: a.to }), i = a.using ? ` USING ${a.using}` : "";
|
|
2276
2279
|
if (t.classification !== "online-required") {
|
|
2277
2280
|
yield* e.onDialectOrElse({
|
|
2278
2281
|
mysql: () => {
|
|
2279
|
-
let t =
|
|
2280
|
-
return t ? Q(e, `ALTER TABLE ${
|
|
2282
|
+
let t = q(n.declared, a.table, a.column);
|
|
2283
|
+
return t ? Q(e, `ALTER TABLE ${K(a.table)} MODIFY COLUMN ${sn(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.`));
|
|
2281
2284
|
},
|
|
2282
2285
|
mssql: () => {
|
|
2283
|
-
let t =
|
|
2286
|
+
let t = q(n.declared, a.table, a.column);
|
|
2284
2287
|
return t ? Q(e, Cn(t, a.column, a.table), a.kind) : d.die(/* @__PURE__ */ Error(`alter-column-type on mssql needs the declared column '${a.table}.${a.column}'.`));
|
|
2285
2288
|
},
|
|
2286
2289
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2287
|
-
orElse: () => Q(e, `ALTER TABLE ${
|
|
2290
|
+
orElse: () => Q(e, `ALTER TABLE ${G(a.table)} ALTER COLUMN ${G(a.column)} TYPE ${r}${i};`, a.kind)
|
|
2288
2291
|
});
|
|
2289
2292
|
break;
|
|
2290
2293
|
}
|
|
@@ -2293,14 +2296,14 @@ BEGIN
|
|
|
2293
2296
|
orElse: () => d.void
|
|
2294
2297
|
});
|
|
2295
2298
|
let o = `${a.column}__shadow`, s = `${a.column}__old`;
|
|
2296
|
-
yield* e.unsafe(`ALTER TABLE ${
|
|
2297
|
-
let c = a.using ??
|
|
2299
|
+
yield* e.unsafe(`ALTER TABLE ${G(a.table)} ADD COLUMN ${G(o)} ${r}`);
|
|
2300
|
+
let c = a.using ?? G(a.column), l;
|
|
2298
2301
|
for (;;) {
|
|
2299
2302
|
let t = l === void 0 ? yield* e`SELECT ${e("id")} FROM ${e(a.table)} WHERE ${e(o)} IS NULL ORDER BY ${e("id")} LIMIT 5000` : yield* e`SELECT ${e("id")} FROM ${e(a.table)} WHERE ${e(o)} IS NULL AND ${e("id")} > ${l} ORDER BY ${e("id")} LIMIT 5000`;
|
|
2300
2303
|
if (t.length === 0) break;
|
|
2301
|
-
yield* e.unsafe(`UPDATE ${
|
|
2304
|
+
yield* e.unsafe(`UPDATE ${G(a.table)} SET ${G(o)} = ${c} WHERE ${G(a.column)} IS NOT NULL AND ${G(o)} IS NULL AND ${G("id")} IN (${t.map((e) => `'${e.id.replace(/'/g, "''")}'`).join(",")})`), l = t[t.length - 1].id;
|
|
2302
2305
|
}
|
|
2303
|
-
yield* d.logInfo(`alter-column-type shadow ${a.table}.${a.column}: shadow populated`).pipe(d.annotateLogs({ scope: "voltro:migrate" })), yield* e.unsafe(`ALTER TABLE ${
|
|
2306
|
+
yield* d.logInfo(`alter-column-type shadow ${a.table}.${a.column}: shadow populated`).pipe(d.annotateLogs({ scope: "voltro:migrate" })), yield* e.unsafe(`ALTER TABLE ${G(a.table)} RENAME COLUMN ${G(a.column)} TO ${G(s)}`), yield* e.unsafe(`ALTER TABLE ${G(a.table)} RENAME COLUMN ${G(o)} TO ${G(a.column)}`), yield* e.unsafe(`ALTER TABLE ${G(a.table)} DROP COLUMN ${G(s)}`);
|
|
2304
2307
|
break;
|
|
2305
2308
|
}
|
|
2306
2309
|
case "drop-foreign-key":
|
|
@@ -2312,9 +2315,9 @@ BEGIN
|
|
|
2312
2315
|
break;
|
|
2313
2316
|
case "add-check":
|
|
2314
2317
|
yield* e.onDialectOrElse({
|
|
2315
|
-
mysql: () => Q(e, Qn(a,
|
|
2318
|
+
mysql: () => Q(e, Qn(a, K), a.kind),
|
|
2316
2319
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2317
|
-
orElse: () => Q(e, Qn(a,
|
|
2320
|
+
orElse: () => Q(e, Qn(a, G), a.kind)
|
|
2318
2321
|
});
|
|
2319
2322
|
break;
|
|
2320
2323
|
case "drop-check":
|
|
@@ -2333,7 +2336,7 @@ BEGIN
|
|
|
2333
2336
|
}), ir = (e, t, n) => d.gen(function* () {
|
|
2334
2337
|
let r = t.operations.filter((e) => e.blocked);
|
|
2335
2338
|
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.`));
|
|
2336
|
-
yield*
|
|
2339
|
+
yield* C(e);
|
|
2337
2340
|
let i = Date.now(), a = [];
|
|
2338
2341
|
try {
|
|
2339
2342
|
let r = yield* e.onDialectOrElse({
|
|
@@ -2347,7 +2350,7 @@ BEGIN
|
|
|
2347
2350
|
})));
|
|
2348
2351
|
for (let t of o) a.push(yield* rr(e, t, n));
|
|
2349
2352
|
} finally {
|
|
2350
|
-
yield*
|
|
2353
|
+
yield* w(e).pipe(d.orDie);
|
|
2351
2354
|
}
|
|
2352
2355
|
let o = yield* n.replan(e);
|
|
2353
2356
|
if (o.operations.length > 0) {
|
|
@@ -2391,7 +2394,7 @@ BEGIN
|
|
|
2391
2394
|
sqlite: () => "sqlite",
|
|
2392
2395
|
orElse: () => "sqlite"
|
|
2393
2396
|
}), cr = (e, t) => d.gen(function* () {
|
|
2394
|
-
let n = N(
|
|
2397
|
+
let n = j(N(t, sr(e))), r = yield* or(e);
|
|
2395
2398
|
return r === n ? {
|
|
2396
2399
|
kind: "up-to-date",
|
|
2397
2400
|
fingerprint: n
|
|
@@ -2416,43 +2419,56 @@ BEGIN
|
|
|
2416
2419
|
}), fr = () => {
|
|
2417
2420
|
let e = (process.env.VOLTRO_DB_IGNORE_TABLES ?? "").split(",").map((e) => e.trim()).filter((e) => e.length > 0);
|
|
2418
2421
|
return e.length > 0 ? { ignoreTables: e } : {};
|
|
2419
|
-
}, pr = (e) =>
|
|
2422
|
+
}, pr = (e) => {
|
|
2423
|
+
if (e === void 0) return;
|
|
2424
|
+
let t = e.trim();
|
|
2425
|
+
if (t === "") return;
|
|
2426
|
+
if (t === "1" || t.toLowerCase() === "true") return { kind: "all" };
|
|
2427
|
+
let n = t.split(",").map((e) => e.trim()).filter((e) => e.length > 0);
|
|
2428
|
+
return n.length > 0 ? {
|
|
2429
|
+
kind: "tables",
|
|
2430
|
+
tables: new Set(n)
|
|
2431
|
+
} : void 0;
|
|
2432
|
+
}, mr = (e) => typeof e.table == "string" ? e.table : void 0, hr = (e, t = { kind: "all" }) => ({
|
|
2420
2433
|
...e,
|
|
2421
2434
|
operations: e.operations.map((e) => {
|
|
2422
2435
|
if (!e.blocked || e.classification !== "lossy") return e;
|
|
2423
|
-
|
|
2424
|
-
|
|
2436
|
+
if (t?.kind === "tables") {
|
|
2437
|
+
let n = mr(e.op);
|
|
2438
|
+
if (n === void 0 || !t.tables.has(n)) return e;
|
|
2439
|
+
}
|
|
2440
|
+
let { blocked: n, ...r } = e;
|
|
2441
|
+
return r;
|
|
2425
2442
|
})
|
|
2426
|
-
}),
|
|
2427
|
-
let t =
|
|
2443
|
+
}), gr = (e, t, n) => t === "postgres" ? st(e, n).pipe(d.flatMap((e) => {
|
|
2444
|
+
let t = ct(e);
|
|
2428
2445
|
return t === void 0 ? d.void : d.logWarning(`auto-migrate: ${t}`).pipe(d.annotateLogs({ scope: "voltro:migrate" }));
|
|
2429
|
-
}), d.catchAll(() => d.void)) : d.void,
|
|
2430
|
-
let r = sr(e), i = t.filter((e) => !
|
|
2446
|
+
}), d.catchAll(() => d.void)) : d.void, _r = (e, t, n) => d.gen(function* () {
|
|
2447
|
+
let r = sr(e), i = t.filter((e) => !P(e.tableName));
|
|
2431
2448
|
if (process.env.VOLTRO_MIGRATE_FORCE !== "1") {
|
|
2432
|
-
let t = N(
|
|
2433
|
-
if ((yield* or(e)) === t) return yield*
|
|
2449
|
+
let t = j(N(i, r));
|
|
2450
|
+
if ((yield* or(e)) === t) return yield* gr(e, r, i), {
|
|
2434
2451
|
kind: "up-to-date",
|
|
2435
2452
|
fingerprint: t
|
|
2436
2453
|
};
|
|
2437
2454
|
}
|
|
2438
|
-
let a = yield*
|
|
2455
|
+
let a = yield* V(e), o = yield* dr(e, a.tables);
|
|
2439
2456
|
o.length > 0 && (yield* d.logInfo(`auto-migrate: reaped ${o.length} test-fixture leftover(s)`).pipe(d.annotateLogs({
|
|
2440
2457
|
scope: "voltro:migrate",
|
|
2441
2458
|
count: o.length
|
|
2442
|
-
})), a = yield*
|
|
2443
|
-
let s =
|
|
2459
|
+
})), a = yield* V(e));
|
|
2460
|
+
let s = Pt({
|
|
2444
2461
|
declared: i,
|
|
2445
|
-
live: { tables: a.tables.filter((e) => !
|
|
2462
|
+
live: { tables: a.tables.filter((e) => !P(e.name)) },
|
|
2446
2463
|
dialect: r,
|
|
2447
2464
|
...fr()
|
|
2448
2465
|
});
|
|
2449
2466
|
if (s.summary.blocked > 0) {
|
|
2450
|
-
let e = s.operations.filter((e) => e.blocked).every((e) => e.classification === "lossy");
|
|
2451
|
-
if (
|
|
2467
|
+
let e = s.operations.filter((e) => e.blocked).every((e) => e.classification === "lossy"), t = pr(process.env.VOLTRO_DESTRUCTIVE_OK);
|
|
2468
|
+
if (t === void 0 || !e || (s = hr(s, t), s.operations.some((e) => e.blocked))) return {
|
|
2452
2469
|
kind: "refused-blocked",
|
|
2453
2470
|
plan: s
|
|
2454
2471
|
};
|
|
2455
|
-
s = pr(s);
|
|
2456
2472
|
}
|
|
2457
2473
|
return s.operations.length === 0 ? {
|
|
2458
2474
|
kind: "up-to-date",
|
|
@@ -2465,10 +2481,10 @@ BEGIN
|
|
|
2465
2481
|
environment: n.environment === "prod" ? "dev" : n.environment,
|
|
2466
2482
|
source: "auto-diff",
|
|
2467
2483
|
replan: (e) => d.gen(function* () {
|
|
2468
|
-
let t = yield*
|
|
2469
|
-
return
|
|
2484
|
+
let t = yield* V(e);
|
|
2485
|
+
return Pt({
|
|
2470
2486
|
declared: i,
|
|
2471
|
-
live: { tables: t.tables.filter((e) => !
|
|
2487
|
+
live: { tables: t.tables.filter((e) => !P(e.name)) },
|
|
2472
2488
|
dialect: r,
|
|
2473
2489
|
...fr()
|
|
2474
2490
|
});
|
|
@@ -2476,24 +2492,37 @@ BEGIN
|
|
|
2476
2492
|
}),
|
|
2477
2493
|
plan: s
|
|
2478
2494
|
};
|
|
2479
|
-
}),
|
|
2495
|
+
}), vr = (e, t, n) => process.env.VOLTRO_AUTO_MIGRATE === "0" ? d.succeed({
|
|
2480
2496
|
kind: "skipped",
|
|
2481
2497
|
reason: "VOLTRO_AUTO_MIGRATE=0"
|
|
2482
|
-
}) : n.environment === "prod" ? cr(e, t) :
|
|
2498
|
+
}) : n.environment === "prod" ? cr(e, t) : _r(e, t, n), yr = (e, t) => {
|
|
2483
2499
|
switch (e.kind) {
|
|
2484
2500
|
case "skipped": return `auto-migrate: skipped (${e.reason})`;
|
|
2485
|
-
case "up-to-date": return `auto-migrate: schema up to date (${t}, fingerprint=${
|
|
2501
|
+
case "up-to-date": return `auto-migrate: schema up to date (${t}, fingerprint=${M(e.fingerprint)})`;
|
|
2486
2502
|
case "applied": {
|
|
2487
2503
|
let t = e.plan.summary;
|
|
2488
|
-
return `auto-migrate: applied ${e.applied.appliedOps} op(s) in ${e.applied.durationMs}ms [safe=${t.safe} needs-default=${t.needsDefault} needs-backfill=${t.needsBackfill} rename=${t.needsRenameAnnotation} lossy=${t.lossy}] fingerprint=${
|
|
2504
|
+
return `auto-migrate: applied ${e.applied.appliedOps} op(s) in ${e.applied.durationMs}ms [safe=${t.safe} needs-default=${t.needsDefault} needs-backfill=${t.needsBackfill} rename=${t.needsRenameAnnotation} lossy=${t.lossy}] fingerprint=${M(e.applied.fingerprint)}`;
|
|
2489
2505
|
}
|
|
2490
|
-
case "prod-mismatch": return `auto-migrate: SCHEMA FINGERPRINT MISMATCH — declared=${
|
|
2506
|
+
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.";
|
|
2491
2507
|
case "refused-blocked": {
|
|
2492
|
-
let t = e.plan.operations.filter((e) => e.blocked), n = t.filter((e) => e.op.kind === "drop-table").length, r = t.filter((e) => e.op.kind === "add-column").length,
|
|
2493
|
-
|
|
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` + ar(e.plan), c = [""];
|
|
2509
|
+
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
|
+
let t = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map();
|
|
2511
|
+
for (let r of e.plan.operations) {
|
|
2512
|
+
let e = "table" in r.op ? r.op.table : void 0;
|
|
2513
|
+
if (e === void 0) continue;
|
|
2514
|
+
let i = "column" in r.op ? String(r.op.column) : void 0;
|
|
2515
|
+
if (i === void 0) continue;
|
|
2516
|
+
let a = r.op.kind === "drop-column" ? t : r.op.kind === "add-column" ? n : void 0;
|
|
2517
|
+
a !== void 0 && a.set(e, [...a.get(e) ?? [], i]);
|
|
2518
|
+
}
|
|
2519
|
+
let r = [...t.entries()].filter(([e]) => (n.get(e)?.length ?? 0) > 0).map(([e, t]) => `${e}: ${t.join(", ")} gone, ${n.get(e).join(", ")} new`);
|
|
2520
|
+
c.push(`${a} column(s) are missing from your declared schema.`), r.length > 0 && c.push(" → DID YOU RENAME ONE? This plan drops AND adds columns on the same table:", ...r.map((e) => ` ${e}`), " If so, add `.renamedFrom('<oldName>')` to the NEW column — the planner then emits a", " RENAME and the data moves with it. Dropping and re-adding loses every value."), c.push(" → If intentional: give the field the `dropped()` marker as its VALUE —", " `<column>: dropped()` (import it from `@voltro/database`). It is not a method", " chained onto the column; the slot stays, documenting the hole.", " → If a typo: restore the field. Data survives until you drop it.");
|
|
2521
|
+
}
|
|
2522
|
+
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");
|
|
2494
2523
|
}
|
|
2495
2524
|
}
|
|
2496
|
-
},
|
|
2525
|
+
}, br = /* @__PURE__ */ new Set([
|
|
2497
2526
|
"node_modules",
|
|
2498
2527
|
"dist",
|
|
2499
2528
|
"build",
|
|
@@ -2502,11 +2531,11 @@ BEGIN
|
|
|
2502
2531
|
".next",
|
|
2503
2532
|
".git",
|
|
2504
2533
|
".framework"
|
|
2505
|
-
]),
|
|
2534
|
+
]), xr = async (e) => {
|
|
2506
2535
|
let t = [], n = async (e) => {
|
|
2507
2536
|
let r = await h.readdir(e, { withFileTypes: !0 }).catch(() => []);
|
|
2508
2537
|
for (let i of r) {
|
|
2509
|
-
if (
|
|
2538
|
+
if (br.has(i.name)) continue;
|
|
2510
2539
|
let r = g(e, i.name);
|
|
2511
2540
|
i.isDirectory() ? await n(r) : i.isFile() && l.test(i.name) && t.push(r);
|
|
2512
2541
|
}
|
|
@@ -2515,7 +2544,7 @@ BEGIN
|
|
|
2515
2544
|
let n = e.split("/").pop() ?? e, r = t.split("/").pop() ?? t;
|
|
2516
2545
|
return n.localeCompare(r);
|
|
2517
2546
|
});
|
|
2518
|
-
},
|
|
2547
|
+
}, Sr = async (e) => {
|
|
2519
2548
|
let t = [];
|
|
2520
2549
|
for (let n of e) {
|
|
2521
2550
|
let e = (await import(ee(n).href)).default;
|
|
@@ -2529,11 +2558,11 @@ BEGIN
|
|
|
2529
2558
|
});
|
|
2530
2559
|
}
|
|
2531
2560
|
return t;
|
|
2532
|
-
},
|
|
2561
|
+
}, Cr = (e) => e`
|
|
2533
2562
|
SELECT ${e("id")}
|
|
2534
2563
|
FROM ${e("_voltro_migration_plans")}
|
|
2535
2564
|
WHERE ${e("source")} = 'file'
|
|
2536
|
-
`.pipe(d.map((e) => e.map((e) => e.id)), d.catchAll(() => d.succeed([]))),
|
|
2565
|
+
`.pipe(d.map((e) => e.map((e) => e.id)), d.catchAll(() => d.succeed([]))), wr = (e, t, n, r) => d.gen(function* () {
|
|
2537
2566
|
let i = Date.now(), a = (/* @__PURE__ */ new Date()).toISOString(), o = {
|
|
2538
2567
|
sql: e,
|
|
2539
2568
|
log: {
|
|
@@ -2566,9 +2595,9 @@ BEGIN
|
|
|
2566
2595
|
${r}, ${n}, ${"file"},
|
|
2567
2596
|
${c}, ${a}, ${t.migration.description})
|
|
2568
2597
|
`, { durationMs: c };
|
|
2569
|
-
}),
|
|
2598
|
+
}), Tr = (e, t) => d.gen(function* () {
|
|
2570
2599
|
let n = yield* d.tryPromise({
|
|
2571
|
-
try: () =>
|
|
2600
|
+
try: () => xr(g(t, "migrations")),
|
|
2572
2601
|
catch: (e) => e
|
|
2573
2602
|
});
|
|
2574
2603
|
if (n.length === 0) return {
|
|
@@ -2576,25 +2605,25 @@ BEGIN
|
|
|
2576
2605
|
skipped: []
|
|
2577
2606
|
};
|
|
2578
2607
|
let r = yield* d.tryPromise({
|
|
2579
|
-
try: () =>
|
|
2608
|
+
try: () => Sr(n),
|
|
2580
2609
|
catch: (e) => e
|
|
2581
2610
|
});
|
|
2582
2611
|
if (r.length === 0) return {
|
|
2583
2612
|
pending: [],
|
|
2584
2613
|
skipped: []
|
|
2585
2614
|
};
|
|
2586
|
-
let i = new Set(yield*
|
|
2615
|
+
let i = new Set(yield* Cr(e));
|
|
2587
2616
|
return {
|
|
2588
2617
|
pending: r.filter((e) => !i.has(e.migration.id)),
|
|
2589
2618
|
skipped: r.filter((e) => i.has(e.migration.id)).map((e) => e.migration.id)
|
|
2590
2619
|
};
|
|
2591
|
-
}),
|
|
2592
|
-
let { pending: n, skipped: r } = yield*
|
|
2620
|
+
}), Er = (e, t) => Tr(e, t).pipe(d.map((e) => e.pending.map((e) => e.migration.id))), Dr = (e, t) => d.gen(function* () {
|
|
2621
|
+
let { pending: n, skipped: r } = yield* Tr(e, t.projectRoot);
|
|
2593
2622
|
if (n.length === 0) return {
|
|
2594
2623
|
applied: [],
|
|
2595
2624
|
skipped: r
|
|
2596
2625
|
};
|
|
2597
|
-
yield*
|
|
2626
|
+
yield* C(e);
|
|
2598
2627
|
let i = [];
|
|
2599
2628
|
try {
|
|
2600
2629
|
for (let r of n) {
|
|
@@ -2603,7 +2632,7 @@ BEGIN
|
|
|
2603
2632
|
id: r.migration.id,
|
|
2604
2633
|
file: r.file
|
|
2605
2634
|
}));
|
|
2606
|
-
let { durationMs: n } = yield*
|
|
2635
|
+
let { durationMs: n } = yield* wr(e, r, t.env, t.appliedBy);
|
|
2607
2636
|
i.push({
|
|
2608
2637
|
id: r.migration.id,
|
|
2609
2638
|
durationMs: n
|
|
@@ -2614,28 +2643,28 @@ BEGIN
|
|
|
2614
2643
|
}));
|
|
2615
2644
|
}
|
|
2616
2645
|
} finally {
|
|
2617
|
-
yield*
|
|
2646
|
+
yield* w(e).pipe(d.orDie);
|
|
2618
2647
|
}
|
|
2619
2648
|
return {
|
|
2620
2649
|
applied: i,
|
|
2621
2650
|
skipped: r
|
|
2622
2651
|
};
|
|
2623
|
-
}),
|
|
2652
|
+
}), Or = (e, t) => e`
|
|
2624
2653
|
SELECT ${e("id")}
|
|
2625
2654
|
FROM ${e("_voltro_migration_plans")}
|
|
2626
2655
|
WHERE ${e("id")} = ${t} AND ${e("source")} = 'file'
|
|
2627
2656
|
LIMIT 1
|
|
2628
|
-
`,
|
|
2629
|
-
if (!(yield*
|
|
2657
|
+
`, kr = (e, t) => d.gen(function* () {
|
|
2658
|
+
if (!(yield* Or(e, t.id))[0]) return yield* d.fail(/* @__PURE__ */ Error(`rollback: ${t.id} not found in _voltro_migration_plans (file source)`));
|
|
2630
2659
|
let n = yield* d.tryPromise({
|
|
2631
|
-
try: () =>
|
|
2660
|
+
try: () => xr(g(t.projectRoot, "migrations")),
|
|
2632
2661
|
catch: (e) => e
|
|
2633
2662
|
}), r = (yield* d.tryPromise({
|
|
2634
|
-
try: () =>
|
|
2663
|
+
try: () => Sr(n),
|
|
2635
2664
|
catch: (e) => e
|
|
2636
2665
|
})).find((e) => e.migration.id === t.id);
|
|
2637
2666
|
if (!r) return yield* d.fail(/* @__PURE__ */ Error(`rollback: file for migration ${t.id} not found on disk under ${t.projectRoot}/migrations/`));
|
|
2638
|
-
yield*
|
|
2667
|
+
yield* C(e);
|
|
2639
2668
|
let i = Date.now();
|
|
2640
2669
|
try {
|
|
2641
2670
|
let n = {
|
|
@@ -2662,9 +2691,9 @@ BEGIN
|
|
|
2662
2691
|
durationMs: o
|
|
2663
2692
|
};
|
|
2664
2693
|
} finally {
|
|
2665
|
-
yield*
|
|
2694
|
+
yield* w(e).pipe(d.orDie);
|
|
2666
2695
|
}
|
|
2667
|
-
}),
|
|
2696
|
+
}), Ar = (e) => d.gen(function* () {
|
|
2668
2697
|
let t = yield* p.SqlClient, n = yield* t`
|
|
2669
2698
|
SELECT id, fingerprint, appliedAt FROM _voltro_migration_plans
|
|
2670
2699
|
WHERE source = 'auto-diff'
|
|
@@ -2709,10 +2738,10 @@ BEGIN
|
|
|
2709
2738
|
snapshotFingerprint: e.fingerprint,
|
|
2710
2739
|
snapshotId: i
|
|
2711
2740
|
};
|
|
2712
|
-
}),
|
|
2741
|
+
}), jr = (e, ...t) => ({
|
|
2713
2742
|
_tag: "RawSqlFragment",
|
|
2714
2743
|
strings: [...e],
|
|
2715
2744
|
values: [...t]
|
|
2716
|
-
}),
|
|
2745
|
+
}), Mr = (e) => typeof e == "object" && !!e && e._tag === "RawSqlFragment";
|
|
2717
2746
|
//#endregion
|
|
2718
|
-
export { l as FILE_MIGRATION_PATTERN,
|
|
2747
|
+
export { l as FILE_MIGRATION_PATTERN, ot as REACTIVE_TRIGGER_PREFIX, re as VOLTRO_MIGRATION_LOCK_KEY, mt as _internalCmp, C as acquireMigrationLock, Je as applyNamespacedSchema, ir as applyPlan, He as applySchema, Vt as chunkTables, N as declaredSnapshot, be as defaultArrayClause, ye as defaultClause, D as defaultJsonClause, yr as describeOutcome, pr as destructiveScope, st as detectReactiveTriggerDrift, $t as emitDropColumnDdl, en as emitDropColumnDdlMysql, Ve as emitFrameworkBootstrapSql, ze as emitNamespaceProvisionDdl, Be as emitNamespacedSchemaSql, A as emitSchemaSql, j as fingerprintSchema, ct as formatReactiveTriggerDrift, fr as ignoreTablesFromEnv, V as introspectSchema, o as isFileMigration, Mr as isRawSqlFragment, It as mapPgType, s as migration, O as numericIdSql, Ft as parseEnumCheck, Er as pendingFileMigrationIds, Pt as planMigrations, Ye as provisionTenantNamespace, w as releaseMigrationLock, gn as renderColumnMysql, dn as renderColumnPg, kr as rollbackFileBasedMigration, Dr as runFileBasedMigrations, Xe as runFrameworkBootstrap, qe as runMigrate, vr as runPlannedMigrations, M as shortFingerprint, nt as snapshotColumn, jr as sql, E as sqlType, Ar as squashMigrationPlans, hr as unblockLossy, _e as withMigrationLock };
|