@voltro/database 0.12.0 → 0.14.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 +378 -0
- package/dist/{fileBased-DEW2BvnP.js → fileBased-Dfuv6JWP.js} +67 -67
- package/dist/index.d.ts +85 -7
- package/dist/index.js +516 -515
- package/dist/sql.d.ts +158 -15
- package/dist/sql.js +698 -602
- package/package.json +2 -2
package/dist/sql.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { B as e, W as t, a as n, c as r, i, lt as a, n as o, r as s, rt as c, t as l, z as u } from "./fileBased-Dfuv6JWP.js";
|
|
2
2
|
import { Effect as d } from "effect";
|
|
3
3
|
import { createLogger as f } from "@voltro/logger";
|
|
4
4
|
import { SqlClient as p } from "@effect/sql";
|
|
@@ -39,7 +39,7 @@ var _ = (e, t, n, r = 400) => {
|
|
|
39
39
|
t !== void 0 && s.push(`db.${e}: ${t}`);
|
|
40
40
|
}
|
|
41
41
|
return s.push(""), s.join("\n");
|
|
42
|
-
}, v = (e) => e.unique === !0 && typeof e.where == "string" && e.where.length > 0, y = (e) => e.replace(/"/g, "`"),
|
|
42
|
+
}, v = (e) => e.unique === !0 && typeof e.where == "string" && e.where.length > 0, y = (e) => e.replace(/"/g, "`"), b = (e) => typeof e == "string" ? e : e.name ?? String(e), x = (e, t) => `_ua_${t}_${e}`.slice(0, 64), S = (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) {
|
|
@@ -49,9 +49,9 @@ var _ = (e, t, n, r = 400) => {
|
|
|
49
49
|
}
|
|
50
50
|
let a = y(t.where), o = [];
|
|
51
51
|
for (let r of t.fields) {
|
|
52
|
-
let i =
|
|
52
|
+
let i = b(r);
|
|
53
53
|
if (!(i in e.fields)) throw Error(`@voltro/migrate: uniqueActive '${t.name}' on '${e.tableName}' references unknown column '${i}'.`);
|
|
54
|
-
let s =
|
|
54
|
+
let s = x(t.name, i);
|
|
55
55
|
o.push(s), n[s] = {
|
|
56
56
|
type: "text",
|
|
57
57
|
nullable: !0,
|
|
@@ -74,101 +74,101 @@ var _ = (e, t, n, r = 400) => {
|
|
|
74
74
|
appliedIndexes: r,
|
|
75
75
|
appliedUniques: [...e.appliedUniques ?? [], ...i]
|
|
76
76
|
};
|
|
77
|
-
},
|
|
77
|
+
}, C = (e, t) => `${e}::${t}`, w = (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(C(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
|
+
}, te = 6322741009312437n, ne = 250, re = () => {
|
|
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
|
+
}, ie = (e) => d.gen(function* () {
|
|
90
|
+
let t = re(), 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(`${ne} millis`);
|
|
95
95
|
}
|
|
96
|
-
}),
|
|
97
|
-
yield* e`SELECT pg_advisory_unlock(${
|
|
98
|
-
}),
|
|
96
|
+
}), ae = (e) => d.gen(function* () {
|
|
97
|
+
yield* e`SELECT pg_advisory_unlock(${te.toString()}::bigint)`;
|
|
98
|
+
}), oe = `voltro_migration_${te.toString(36)}`, se = 30, ce = (e) => d.gen(function* () {
|
|
99
99
|
(yield* e`
|
|
100
|
-
SELECT GET_LOCK(${
|
|
101
|
-
}),
|
|
102
|
-
yield* e`SELECT RELEASE_LOCK(${
|
|
103
|
-
}),
|
|
100
|
+
SELECT GET_LOCK(${oe}, ${se}) AS got`)[0]?.got !== 1 && (yield* d.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${oe}' within ${se}s (another migration is in progress, or a prior one left it held).`)));
|
|
101
|
+
}), le = (e) => d.gen(function* () {
|
|
102
|
+
yield* e`SELECT RELEASE_LOCK(${oe})`;
|
|
103
|
+
}), ue = `voltro_migration_${te.toString(36)}`, de = 3e4, fe = (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 = ${ue}, @LockMode = 'Exclusive',
|
|
107
|
+
@LockOwner = 'Session', @LockTimeout = ${de};
|
|
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
|
-
}),
|
|
109
|
+
(t[0]?.res ?? -999) < 0 && (yield* d.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${ue}' (sp_getapplock returned ${t[0]?.res ?? "no row"}; another migration is in progress).`)));
|
|
110
|
+
}), pe = (e) => d.gen(function* () {
|
|
111
|
+
yield* e`EXEC sp_releaseapplock @Resource = ${ue}, @LockOwner = 'Session'`;
|
|
112
|
+
}), me = d.void, T = (e) => e.onDialectOrElse({
|
|
113
|
+
mysql: () => ce(e),
|
|
114
|
+
mssql: () => fe(e),
|
|
115
|
+
sqlite: () => me,
|
|
116
|
+
orElse: () => ie(e)
|
|
117
|
+
}), E = (e) => e.onDialectOrElse({
|
|
113
118
|
mysql: () => le(e),
|
|
114
119
|
mssql: () => pe(e),
|
|
115
|
-
sqlite: () =>
|
|
120
|
+
sqlite: () => me,
|
|
116
121
|
orElse: () => ae(e)
|
|
117
|
-
}),
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
}
|
|
134
|
-
if (r === "array" && t.arrayElement) {
|
|
135
|
-
if (n === "postgres") return `${D({
|
|
136
|
-
...t,
|
|
137
|
-
type: t.arrayElement,
|
|
122
|
+
}), he = (e, t) => d.acquireUseRelease(T(e), () => t, () => E(e).pipe(d.orDie)), ge = f({ scope: "voltro:migrate" }), D = (e) => {
|
|
123
|
+
ge.warn(e.replace(/^\[voltro:migrate\]\s*/, ""));
|
|
124
|
+
}, O = (e, t) => {
|
|
125
|
+
let n = e.type;
|
|
126
|
+
if (e.spatial) {
|
|
127
|
+
if (t === "postgres") return `${e.spatial.kind}(${e.spatial.geomKind},${e.spatial.srid})`;
|
|
128
|
+
throw Error(`@voltro/plugin-postgis: ${e.spatial.kind}('${e.spatial.geomKind}', ${e.spatial.srid}) is postgres-only — the active dialect is '${t}'. PostGIS has no portable equivalent; use store: 'postgres' (or DB_DIALECT=postgres) for spatial columns, or model the value as plain text/json.`);
|
|
129
|
+
}
|
|
130
|
+
if (n === "raw") {
|
|
131
|
+
if (e.rawDdl === void 0) throw Error("raw() column is missing its DDL fragment — this is a framework bug.");
|
|
132
|
+
return e.rawDdl;
|
|
133
|
+
}
|
|
134
|
+
if (n === "array" && e.arrayElement) {
|
|
135
|
+
if (t === "postgres") return `${O({
|
|
136
|
+
...e,
|
|
137
|
+
type: e.arrayElement,
|
|
138
138
|
arrayElement: void 0
|
|
139
|
-
},
|
|
140
|
-
if (
|
|
141
|
-
if (
|
|
142
|
-
if (
|
|
143
|
-
}
|
|
144
|
-
if (
|
|
145
|
-
let
|
|
146
|
-
if (
|
|
147
|
-
let
|
|
148
|
-
if (
|
|
149
|
-
if (
|
|
150
|
-
if (
|
|
151
|
-
if (
|
|
152
|
-
}
|
|
153
|
-
if (
|
|
154
|
-
if (
|
|
155
|
-
if (
|
|
156
|
-
if (
|
|
157
|
-
}
|
|
158
|
-
if (
|
|
159
|
-
let
|
|
160
|
-
if (
|
|
161
|
-
return
|
|
162
|
-
}
|
|
163
|
-
if (
|
|
164
|
-
if (
|
|
165
|
-
if (
|
|
166
|
-
if (
|
|
167
|
-
if (
|
|
168
|
-
if (
|
|
169
|
-
}
|
|
170
|
-
if (
|
|
171
|
-
if (
|
|
139
|
+
}, t)}[]`;
|
|
140
|
+
if (t === "mysql" || t === "mariadb") return "JSON";
|
|
141
|
+
if (t === "mssql") return "NVARCHAR(MAX)";
|
|
142
|
+
if (u(t)) return "TEXT";
|
|
143
|
+
}
|
|
144
|
+
if (n === "vector") {
|
|
145
|
+
let n = e.vectorDim;
|
|
146
|
+
if (n === void 0) throw Error("vector column is missing its dimension — this is a framework bug.");
|
|
147
|
+
let r = e.vectorPrecision === "half";
|
|
148
|
+
if (t === "postgres") return r ? `HALFVEC(${n})` : `VECTOR(${n})`;
|
|
149
|
+
if (t === "mysql" || t === "mariadb") return `VECTOR(${n})`;
|
|
150
|
+
if (t === "mssql") return "VARBINARY(MAX)";
|
|
151
|
+
if (u(t)) return "BLOB";
|
|
152
|
+
}
|
|
153
|
+
if (n === "interval") {
|
|
154
|
+
if (t === "postgres") return "INTERVAL";
|
|
155
|
+
if (t === "mysql" || t === "mariadb" || t === "mssql") return "BIGINT";
|
|
156
|
+
if (u(t)) return "INTEGER";
|
|
157
|
+
}
|
|
158
|
+
if (n === "decimal") {
|
|
159
|
+
let n = e.precision, r = e.scale ?? 0;
|
|
160
|
+
if (n === void 0) throw Error("decimal column is missing its precision — this is a framework bug.");
|
|
161
|
+
return u(t) ? "NUMERIC" : t === "postgres" ? `NUMERIC(${n}, ${r})` : `DECIMAL(${n}, ${r})`;
|
|
162
|
+
}
|
|
163
|
+
if (n === "bigint") return u(t) ? "INTEGER" : "BIGINT";
|
|
164
|
+
if (n === "enum") {
|
|
165
|
+
if (t === "postgres") return e.enumName ?? "TEXT";
|
|
166
|
+
if (t === "mysql" || t === "mariadb") return `ENUM(${(e.enumValues ?? []).map((e) => `'${e.replace(/'/g, "''")}'`).join(", ")})`;
|
|
167
|
+
if (t === "mssql") return "NVARCHAR(255)";
|
|
168
|
+
if (u(t)) return "TEXT";
|
|
169
|
+
}
|
|
170
|
+
if (n === "text" && e.maxLength !== void 0 && e.generatedAs === void 0) return t === "mssql" ? `NVARCHAR(${e.maxLength})` : u(t) ? "TEXT" : `VARCHAR(${e.maxLength})`;
|
|
171
|
+
if (u(t)) switch (n) {
|
|
172
172
|
case "id": return "TEXT";
|
|
173
173
|
case "text": return "TEXT";
|
|
174
174
|
case "integer": return "INTEGER";
|
|
@@ -184,9 +184,9 @@ var _ = (e, t, n, r = 400) => {
|
|
|
184
184
|
case "array": return "TEXT";
|
|
185
185
|
case "interval": return "INTEGER";
|
|
186
186
|
}
|
|
187
|
-
if (
|
|
187
|
+
if (t === "mysql" || t === "mariadb") switch (n) {
|
|
188
188
|
case "id": return "VARCHAR(64)";
|
|
189
|
-
case "text": return
|
|
189
|
+
case "text": return e.hasDefault && e.defaultFactory === void 0 || e.oneOf && e.oneOf.length > 0 ? "VARCHAR(255)" : e.generatedAs ? "TEXT" : "LONGTEXT";
|
|
190
190
|
case "integer": return "INT";
|
|
191
191
|
case "real": return "DOUBLE";
|
|
192
192
|
case "boolean": return "TINYINT(1)";
|
|
@@ -200,9 +200,9 @@ var _ = (e, t, n, r = 400) => {
|
|
|
200
200
|
case "array": return "JSON";
|
|
201
201
|
case "interval": return "BIGINT";
|
|
202
202
|
}
|
|
203
|
-
if (
|
|
203
|
+
if (t === "mssql") switch (n) {
|
|
204
204
|
case "id": return "NVARCHAR(64)";
|
|
205
|
-
case "text": return
|
|
205
|
+
case "text": return e.hasDefault && e.defaultFactory === void 0 || e.oneOf && e.oneOf.length > 0 ? "NVARCHAR(450)" : "NVARCHAR(MAX)";
|
|
206
206
|
case "integer": return "INT";
|
|
207
207
|
case "real": return "FLOAT";
|
|
208
208
|
case "boolean": return "BIT";
|
|
@@ -216,7 +216,7 @@ var _ = (e, t, n, r = 400) => {
|
|
|
216
216
|
case "array": return "NVARCHAR(MAX)";
|
|
217
217
|
case "interval": return "BIGINT";
|
|
218
218
|
}
|
|
219
|
-
switch (
|
|
219
|
+
switch (n) {
|
|
220
220
|
case "id": return "TEXT";
|
|
221
221
|
case "text": return "TEXT";
|
|
222
222
|
case "integer": return "INTEGER";
|
|
@@ -228,18 +228,26 @@ var _ = (e, t, n, r = 400) => {
|
|
|
228
228
|
case "bytes": return "BYTEA";
|
|
229
229
|
case "reference": return "TEXT";
|
|
230
230
|
case "vector": return "VECTOR";
|
|
231
|
-
case "enum": return
|
|
231
|
+
case "enum": return e.enumName ?? "TEXT";
|
|
232
232
|
case "array": return "TEXT[]";
|
|
233
233
|
case "interval": return "INTERVAL";
|
|
234
234
|
}
|
|
235
|
-
},
|
|
236
|
-
if (!
|
|
237
|
-
let
|
|
238
|
-
return
|
|
239
|
-
},
|
|
235
|
+
}, _e = (e, t) => {
|
|
236
|
+
if (!e.hasDefault || e.defaultFactory !== void 0) return null;
|
|
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) ? ve(n, e, t) : typeof n == "object" && n ? k(n, t) : null;
|
|
239
|
+
}, ve = (e, t, n) => {
|
|
240
|
+
if (n !== "postgres" || t.type !== "array" || t.arrayElement === void 0) return k(e, n);
|
|
241
|
+
let r = O({
|
|
242
|
+
...t,
|
|
243
|
+
type: t.arrayElement,
|
|
244
|
+
arrayElement: void 0
|
|
245
|
+
}, n);
|
|
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
|
+
}, k = (e, t) => {
|
|
240
248
|
let n = JSON.stringify(e).replace(/'/g, "''");
|
|
241
249
|
return t === "postgres" ? `DEFAULT '${n}'::jsonb` : t === "mysql" || t === "mariadb" ? `DEFAULT (CAST('${n}' AS JSON))` : `DEFAULT '${n}'`;
|
|
242
|
-
},
|
|
250
|
+
}, A = (e, t) => {
|
|
243
251
|
switch (t) {
|
|
244
252
|
case "postgres": return `"${e}" BIGSERIAL PRIMARY KEY`;
|
|
245
253
|
case "mysql":
|
|
@@ -248,7 +256,7 @@ var _ = (e, t, n, r = 400) => {
|
|
|
248
256
|
case "sqlite": return `"${e}" INTEGER PRIMARY KEY AUTOINCREMENT`;
|
|
249
257
|
case "turso": return `"${e}" INTEGER PRIMARY KEY`;
|
|
250
258
|
}
|
|
251
|
-
},
|
|
259
|
+
}, j = (e, t) => {
|
|
252
260
|
if (e === "restrict" && t === "mssql") return "NO ACTION";
|
|
253
261
|
switch (e) {
|
|
254
262
|
case "cascade": return "CASCADE";
|
|
@@ -256,107 +264,107 @@ var _ = (e, t, n, r = 400) => {
|
|
|
256
264
|
case "setNull": return "SET NULL";
|
|
257
265
|
case "noAction": return "NO ACTION";
|
|
258
266
|
}
|
|
259
|
-
}, ye = (
|
|
260
|
-
let
|
|
261
|
-
if (
|
|
262
|
-
let
|
|
263
|
-
if (!
|
|
264
|
-
let
|
|
265
|
-
return
|
|
267
|
+
}, ye = (t, n, r) => r === null ? e(t, n) : `${e(r, n)}.${e(t, n)}`, be = 191, xe = (t, n, r) => {
|
|
268
|
+
let i = e(t, r);
|
|
269
|
+
if (r !== "mysql" && r !== "mariadb") return i;
|
|
270
|
+
let a = n[t];
|
|
271
|
+
if (!a) return i;
|
|
272
|
+
let o = O(a, r).toUpperCase();
|
|
273
|
+
return o.endsWith("TEXT") || o.endsWith("BLOB") ? `${i}(${be})` : i;
|
|
266
274
|
}, Se = (e, t) => {
|
|
267
275
|
if (!e.generatedAs) return null;
|
|
268
276
|
let { expr: n, stored: r } = e.generatedAs;
|
|
269
|
-
if (t === "postgres") return r ||
|
|
277
|
+
if (t === "postgres") return r || D("[voltro:migrate] generated column requested as VIRTUAL but postgres only supports STORED — promoting"), `GENERATED ALWAYS AS (${n}) STORED`;
|
|
270
278
|
if (t === "mysql" || t === "mariadb") return `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
|
|
271
279
|
if (t === "mssql") return `AS (${n})${r ? " PERSISTED" : ""}`;
|
|
272
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.");
|
|
273
281
|
return `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
|
|
274
282
|
}, Ce = (t, n, r, i, a = !1, o = !1) => {
|
|
275
|
-
if (n.type === "id" && n.idScheme?.kind === "numeric") return
|
|
276
|
-
let s = r === "mssql" && n.type === "text" && !n.generatedAs && n.maxLength === void 0 && i?.has(t) ? "NVARCHAR(450)" :
|
|
283
|
+
if (n.type === "id" && n.idScheme?.kind === "numeric") return A(t, r);
|
|
284
|
+
let s = r === "mssql" && n.type === "text" && !n.generatedAs && n.maxLength === void 0 && i?.has(t) ? "NVARCHAR(450)" : O(n, r), c = [e(t, r), s];
|
|
277
285
|
n.type === "id" && !o && c.push("PRIMARY KEY");
|
|
278
286
|
let l = Se(n, r);
|
|
279
287
|
if (l) c.push(l);
|
|
280
288
|
else {
|
|
281
289
|
n.nullable || c.push("NOT NULL"), n.unique && n.type !== "id" && c.push("UNIQUE");
|
|
282
|
-
let e =
|
|
290
|
+
let e = _e(n, r);
|
|
283
291
|
e && c.push(e);
|
|
284
292
|
}
|
|
285
293
|
if (n.type === "reference" && n.references && !a) {
|
|
286
|
-
let
|
|
287
|
-
c.push(`REFERENCES ${
|
|
288
|
-
let
|
|
289
|
-
c.push(`ON DELETE ${
|
|
290
|
-
let
|
|
291
|
-
|
|
294
|
+
let t = n.references();
|
|
295
|
+
c.push(`REFERENCES ${e(t.tableName, r)} (${e("id", r)})`);
|
|
296
|
+
let i = j(n.onDelete ?? "restrict", r);
|
|
297
|
+
c.push(`ON DELETE ${i}`);
|
|
298
|
+
let a = j(n.refOnUpdate ?? "noAction", r);
|
|
299
|
+
a !== "NO ACTION" && c.push(`ON UPDATE ${a}`);
|
|
292
300
|
}
|
|
293
301
|
if (n.oneOf && n.oneOf.length > 0) {
|
|
294
|
-
let
|
|
295
|
-
c.push(`CHECK (${
|
|
302
|
+
let i = n.oneOf.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
|
|
303
|
+
c.push(`CHECK (${e(t, r)} IN (${i}))`);
|
|
296
304
|
}
|
|
297
305
|
if (n.checks && n.checks.length > 0) for (let e of n.checks) c.push(`CHECK (${e})`);
|
|
298
|
-
if (n.type === "enum" && n.enumValues && n.enumValues.length > 0 && (r === "mssql" ||
|
|
299
|
-
let
|
|
300
|
-
c.push(`CHECK (${
|
|
306
|
+
if (n.type === "enum" && n.enumValues && n.enumValues.length > 0 && (r === "mssql" || u(r))) {
|
|
307
|
+
let i = n.enumValues.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
|
|
308
|
+
c.push(`CHECK (${e(t, r)} IN (${i}))`);
|
|
301
309
|
}
|
|
302
310
|
if (n.type === "json" || n.type === "array") {
|
|
303
|
-
let n =
|
|
304
|
-
|
|
311
|
+
let n = e(t, r);
|
|
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)`);
|
|
305
313
|
}
|
|
306
314
|
return c.join(" ");
|
|
307
|
-
}, we = (
|
|
308
|
-
let
|
|
309
|
-
for (let
|
|
310
|
-
for (let
|
|
311
|
-
let
|
|
312
|
-
let
|
|
313
|
-
return ` CONSTRAINT ${
|
|
314
|
-
}),
|
|
315
|
-
...
|
|
316
|
-
...
|
|
317
|
-
...
|
|
318
|
-
], f = d.length > 0 ? `${
|
|
319
|
-
if (
|
|
320
|
-
let
|
|
321
|
-
return `IF OBJECT_ID('${
|
|
315
|
+
}, we = (t, n, r = null, i) => {
|
|
316
|
+
let a = /* @__PURE__ */ new Set();
|
|
317
|
+
for (let e of t.appliedIndexes ?? []) for (let t of e.fields) typeof t == "string" && a.add(t);
|
|
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]) => ` ${Ce(e, t, n, a, i?.has(e) ?? !1, s)}`).join(",\n"), l = (t.appliedUniques ?? []).map((r) => {
|
|
320
|
+
let i = r.fields.map((e) => xe(e, t.fields, n)).join(", ");
|
|
321
|
+
return ` CONSTRAINT ${e(r.name, n)} UNIQUE (${i})`;
|
|
322
|
+
}), u = (t.appliedChecks ?? []).map((t) => ` CONSTRAINT ${e(t.name, n)} CHECK (${t.expr})`), d = [
|
|
323
|
+
...s ? [` PRIMARY KEY (${o.map((e) => xe(e, t.fields, n)).join(", ")})`] : [],
|
|
324
|
+
...l,
|
|
325
|
+
...u
|
|
326
|
+
], f = d.length > 0 ? `${c},\n${d.join(",\n")}` : c, p = ye(t.tableName, n, r);
|
|
327
|
+
if (n === "mssql") {
|
|
328
|
+
let e = r === null ? t.tableName : `${r}.${t.tableName}`, n = `CREATE TABLE ${p} (\n${f}\n)`;
|
|
329
|
+
return `IF OBJECT_ID('${e.replace(/'/g, "''")}', 'U') IS NULL EXEC(N'${n.replace(/'/g, "''")}');`;
|
|
322
330
|
}
|
|
323
331
|
return [
|
|
324
332
|
`CREATE TABLE IF NOT EXISTS ${p} (`,
|
|
325
333
|
f,
|
|
326
334
|
");"
|
|
327
335
|
].join("\n");
|
|
328
|
-
}, Te = (
|
|
329
|
-
let
|
|
330
|
-
return
|
|
331
|
-
}, Ee = (
|
|
332
|
-
let
|
|
336
|
+
}, Te = (t, n, r) => {
|
|
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
|
+
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
|
+
}, Ee = (n, r, a = null) => {
|
|
340
|
+
let o = [], s = /* @__PURE__ */ new Set(), c = (e) => e.join("\0"), l = (e, n, i, a) => {
|
|
333
341
|
let o = {
|
|
334
342
|
using: "",
|
|
335
343
|
withSuffix: "",
|
|
336
344
|
skip: !1
|
|
337
345
|
};
|
|
338
346
|
if (i === void 0 || i === "btree") return o;
|
|
339
|
-
if (i === "gist") return
|
|
347
|
+
if (i === "gist") return r === "postgres" ? {
|
|
340
348
|
using: " USING GIST",
|
|
341
349
|
withSuffix: "",
|
|
342
350
|
skip: !1
|
|
343
|
-
} : (
|
|
344
|
-
if (i === "gin") return
|
|
351
|
+
} : (D(`[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
|
+
if (i === "gin") return r === "postgres" ? {
|
|
345
353
|
using: " USING GIN",
|
|
346
354
|
withSuffix: "",
|
|
347
355
|
skip: !1
|
|
348
|
-
} :
|
|
356
|
+
} : r === "mysql" || r === "mariadb" ? (D(`[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(...).`), {
|
|
349
357
|
using: "",
|
|
350
358
|
withSuffix: "",
|
|
351
359
|
skip: !0
|
|
352
|
-
}) : (
|
|
353
|
-
if (i === "brin") return
|
|
360
|
+
}) : (D(`[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
|
+
if (i === "brin") return r === "postgres" ? {
|
|
354
362
|
using: " USING BRIN",
|
|
355
363
|
withSuffix: "",
|
|
356
364
|
skip: !1
|
|
357
|
-
} : (
|
|
365
|
+
} : (D(`[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);
|
|
358
366
|
if (i === "hnsw") {
|
|
359
|
-
if (
|
|
367
|
+
if (r === "postgres") {
|
|
360
368
|
let e = a?.hnsw?.m ?? 16, n = a?.hnsw?.efConstruction ?? 64, r = a?.hnsw?.opclass ?? t(a?.hnsw?.distance);
|
|
361
369
|
return {
|
|
362
370
|
using: " USING hnsw",
|
|
@@ -365,57 +373,57 @@ var _ = (e, t, n, r = 400) => {
|
|
|
365
373
|
skip: !1
|
|
366
374
|
};
|
|
367
375
|
}
|
|
368
|
-
return
|
|
376
|
+
return D(`[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.`), {
|
|
369
377
|
using: "",
|
|
370
378
|
withSuffix: "",
|
|
371
379
|
skip: !0
|
|
372
380
|
};
|
|
373
381
|
}
|
|
374
382
|
return o;
|
|
375
|
-
},
|
|
376
|
-
let
|
|
377
|
-
if (typeof
|
|
378
|
-
if ("jsonPath" in
|
|
379
|
-
let { column:
|
|
380
|
-
return `(${
|
|
383
|
+
}, u = (e, t) => {
|
|
384
|
+
let a = e.map((e) => {
|
|
385
|
+
if (typeof e == "string") return xe(e, n.fields, r);
|
|
386
|
+
if ("jsonPath" in e) {
|
|
387
|
+
let { column: t, path: n, numeric: a } = e.jsonPath;
|
|
388
|
+
return `(${i(t, n, r, { numeric: a })})`;
|
|
381
389
|
}
|
|
382
|
-
return `(${
|
|
390
|
+
return `(${e.expr})`;
|
|
383
391
|
});
|
|
384
|
-
return
|
|
385
|
-
}, d = (
|
|
386
|
-
let f =
|
|
392
|
+
return t !== void 0 && a.length === 1 ? `${a[0]} ${t}` : a.join(", ");
|
|
393
|
+
}, d = (t, n, i, o, s, c = "", d = !1) => {
|
|
394
|
+
let f = l(t, n, o, s);
|
|
387
395
|
if (f.skip) return "";
|
|
388
|
-
let p =
|
|
389
|
-
return
|
|
396
|
+
let p = u(i, f.opclass), m = `${f.withSuffix}${c}`, h = ye(n, r, a), g = d ? "UNIQUE " : "";
|
|
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};`;
|
|
390
398
|
};
|
|
391
|
-
for (let t of
|
|
392
|
-
let
|
|
393
|
-
let
|
|
394
|
-
return `setweight(to_tsvector('${
|
|
399
|
+
for (let t of n.appliedFullText ?? []) if (r === "postgres") {
|
|
400
|
+
let i = t.config ?? "english", a = `${t.name}_tsv`, s = t.columns.map((n) => {
|
|
401
|
+
let a = t.weights?.[n] ?? "A";
|
|
402
|
+
return `setweight(to_tsvector('${i}', coalesce(${e(n, r)}, '')), '${a}')`;
|
|
395
403
|
}).join(" || ");
|
|
396
|
-
|
|
397
|
-
} else if (
|
|
398
|
-
let
|
|
399
|
-
|
|
400
|
-
} else if (
|
|
401
|
-
else
|
|
402
|
-
for (let
|
|
403
|
-
if ((
|
|
404
|
-
|
|
404
|
+
o.push(`ALTER TABLE ${e(n.tableName, r)} ADD COLUMN IF NOT EXISTS ${e(a, r)} tsvector GENERATED ALWAYS AS (${s}) STORED;`), o.push(`CREATE INDEX IF NOT EXISTS ${e(t.name, r)} ON ${e(n.tableName, r)} USING GIN (${e(a, r)});`);
|
|
405
|
+
} else if (r === "mysql" || r === "mariadb") {
|
|
406
|
+
let i = t.columns.map((t) => e(t, r)).join(", ");
|
|
407
|
+
o.push(`CREATE FULLTEXT INDEX ${e(t.name, r)} ON ${e(n.tableName, r)} (${i});`);
|
|
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(...Te(n.tableName, t, r)) : D(`[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
|
+
for (let e of n.appliedIndexes) {
|
|
411
|
+
if ((r === "mariadb" || r === "mssql") && e.fields.some((e) => typeof e != "string" && "jsonPath" in e)) {
|
|
412
|
+
D(`[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(...).`);
|
|
405
413
|
continue;
|
|
406
414
|
}
|
|
407
|
-
if (
|
|
408
|
-
let
|
|
409
|
-
|
|
410
|
-
let
|
|
411
|
-
|
|
412
|
-
}
|
|
413
|
-
for (let [
|
|
414
|
-
if (
|
|
415
|
-
let r = `${
|
|
416
|
-
|
|
417
|
-
}
|
|
418
|
-
return
|
|
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
|
+
let t = "";
|
|
417
|
+
e.where !== void 0 && e.where.length > 0 && (r === "mysql" || r === "mariadb" ? D(`[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
|
+
let i = d(e.name, n.tableName, e.fields, e.kind, e.kindOptions, t, e.unique === !0);
|
|
419
|
+
i !== "" && o.push(i), e.fields.every((e) => typeof e == "string") && s.add(c(e.fields));
|
|
420
|
+
}
|
|
421
|
+
for (let [e, t] of Object.entries(n.fields)) {
|
|
422
|
+
if (t.type !== "reference" || t.fkAutoIndex === !1 || s.has(c([e]))) continue;
|
|
423
|
+
let r = `${n.tableName}_${e}_idx`;
|
|
424
|
+
o.push(d(r, n.tableName, [e])), s.add(c([e]));
|
|
425
|
+
}
|
|
426
|
+
return o.join("\n");
|
|
419
427
|
}, De = "CREATE OR REPLACE FUNCTION framework_notify_change() RETURNS trigger AS $$\nDECLARE\n payload TEXT;\nBEGIN\n payload := json_build_object(\n 'table', TG_TABLE_NAME,\n -- The schema the write landed in. Under namespace isolation this is\n -- the tenant schema (tenant_<id>); the CDC consumer uses it so a\n -- write in tenant A namespace does not spuriously wake tenant B\n -- subscriptions on the same-named table. public/absent = shared.\n 'schema', TG_TABLE_SCHEMA,\n 'op', lower(TG_OP),\n 'old', CASE WHEN TG_OP = 'INSERT' THEN NULL ELSE row_to_json(OLD) END,\n 'new', CASE WHEN TG_OP = 'DELETE' THEN NULL ELSE row_to_json(NEW) END\n )::text;\n -- pg_notify hard-caps the payload at 8000 bytes; a wide reactive row\n -- (big text / json column) would otherwise abort the write itself.\n -- Fall back to a body-less notice — the CDC consumer treats absent\n -- old/new as \"all columns changed\" and re-queries, so correctness is\n -- preserved; only the delta-diff fast path is skipped for that write.\n IF octet_length(payload) >= 7999 THEN\n payload := json_build_object(\n 'table', TG_TABLE_NAME,\n 'schema', TG_TABLE_SCHEMA,\n 'op', lower(TG_OP),\n 'old', NULL,\n 'new', NULL,\n 'oversized', true\n )::text;\n END IF;\n PERFORM pg_notify('framework_changes', payload);\n RETURN COALESCE(NEW, OLD);\nEND;\n$$ LANGUAGE plpgsql;", Oe = (e) => `
|
|
420
428
|
ALTER TABLE "${e.tableName}" REPLICA IDENTITY FULL;
|
|
421
429
|
DROP TRIGGER IF EXISTS framework_changes_${e.tableName} ON "${e.tableName}";
|
|
@@ -423,7 +431,7 @@ CREATE TRIGGER framework_changes_${e.tableName}
|
|
|
423
431
|
AFTER INSERT OR UPDATE OR DELETE ON "${e.tableName}"
|
|
424
432
|
FOR EACH ROW EXECUTE FUNCTION framework_notify_change();
|
|
425
433
|
`.trim(), ke = (e) => e.some((e) => Object.values(e.fields).some((e) => e.type === "vector")), Ae = (e) => e.some((e) => Object.values(e.fields).some((e) => e.spatial !== void 0)), je = (e) => {
|
|
426
|
-
let t = new Map(e.map((e) => [e.tableName, e])), n =
|
|
434
|
+
let t = new Map(e.map((e) => [e.tableName, e])), n = w(e.map((e) => e.tableName), (e) => {
|
|
427
435
|
let n = t.get(e);
|
|
428
436
|
return n ? Object.entries(n.fields).flatMap(([e, n]) => {
|
|
429
437
|
if (n.type !== "reference" || !n.references) return [];
|
|
@@ -434,7 +442,7 @@ FOR EACH ROW EXECUTE FUNCTION framework_notify_change();
|
|
|
434
442
|
}] : [];
|
|
435
443
|
}) : [];
|
|
436
444
|
}), r = [];
|
|
437
|
-
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(C(t.tableName, e)) && r.push({
|
|
438
446
|
table: t.tableName,
|
|
439
447
|
column: e,
|
|
440
448
|
targetTable: i.references().tableName,
|
|
@@ -445,7 +453,7 @@ FOR EACH ROW EXECUTE FUNCTION framework_notify_change();
|
|
|
445
453
|
if (!(i.has(e.tableName) || a.has(e.tableName))) {
|
|
446
454
|
a.add(e.tableName);
|
|
447
455
|
for (let [r, i] of Object.entries(e.fields)) {
|
|
448
|
-
if (i.type !== "reference" || !i.references || n.has(
|
|
456
|
+
if (i.type !== "reference" || !i.references || n.has(C(e.tableName, r))) continue;
|
|
449
457
|
let a = i.references();
|
|
450
458
|
if (a.tableName === e.tableName) continue;
|
|
451
459
|
let o = t.get(a.tableName);
|
|
@@ -459,29 +467,29 @@ FOR EACH ROW EXECUTE FUNCTION framework_notify_change();
|
|
|
459
467
|
sorted: o,
|
|
460
468
|
cyclic: r
|
|
461
469
|
};
|
|
462
|
-
}, Me = (
|
|
463
|
-
let
|
|
464
|
-
switch (
|
|
470
|
+
}, Me = (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 = j(t.onDelete, n), s = j(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
|
+
switch (n) {
|
|
465
473
|
case "postgres": return [
|
|
466
474
|
"DO $$ BEGIN",
|
|
467
475
|
" IF NOT EXISTS (SELECT 1 FROM pg_constraint",
|
|
468
|
-
` WHERE conname = '${
|
|
469
|
-
` ALTER TABLE ${
|
|
476
|
+
` WHERE conname = '${a}' AND conrelid = '${r ? `${r}.` : ""}${t.table}'::regclass) THEN`,
|
|
477
|
+
` ALTER TABLE ${i(t.table)} ${l(!1)};`,
|
|
470
478
|
" END IF;",
|
|
471
479
|
"END $$;"
|
|
472
480
|
].join("\n");
|
|
473
|
-
case "mssql": return `IF NOT EXISTS (SELECT 1 FROM sys.foreign_keys WHERE name = '${
|
|
474
|
-
case "mariadb": return `ALTER TABLE ${
|
|
475
|
-
default: return `ALTER TABLE ${
|
|
481
|
+
case "mssql": return `IF NOT EXISTS (SELECT 1 FROM sys.foreign_keys WHERE name = '${a}') ALTER TABLE ${i(t.table)} ${l(!1)};`;
|
|
482
|
+
case "mariadb": return `ALTER TABLE ${i(t.table)} ${l(!0)};`;
|
|
483
|
+
default: return `ALTER TABLE ${i(t.table)} ${l(!1)};`;
|
|
476
484
|
}
|
|
477
|
-
}, Ne = (
|
|
478
|
-
let
|
|
479
|
-
if (
|
|
480
|
-
for (let
|
|
481
|
-
let
|
|
482
|
-
|
|
485
|
+
}, Ne = (e, t) => {
|
|
486
|
+
let n = /* @__PURE__ */ new Map();
|
|
487
|
+
if (u(t)) return n;
|
|
488
|
+
for (let t of e) {
|
|
489
|
+
let e = n.get(t.table) ?? /* @__PURE__ */ new Set();
|
|
490
|
+
e.add(t.column), n.set(t.table, e);
|
|
483
491
|
}
|
|
484
|
-
return
|
|
492
|
+
return n;
|
|
485
493
|
}, Pe = (e, t) => {
|
|
486
494
|
if (t !== "postgres") return "";
|
|
487
495
|
let n = /* @__PURE__ */ new Map();
|
|
@@ -503,7 +511,7 @@ FOR EACH ROW EXECUTE FUNCTION framework_notify_change();
|
|
|
503
511
|
let n = /* @__PURE__ */ new Set();
|
|
504
512
|
for (let t of e) for (let e of Object.values(t.fields)) e.type === "enum" && e.enumName && n.add(e.enumName);
|
|
505
513
|
let r = [];
|
|
506
|
-
for (let e of n) for (let { from: t, to: n } of
|
|
514
|
+
for (let e of n) for (let { from: t, to: n } of a(e)) {
|
|
507
515
|
let i = e.replace(/'/g, "''"), a = t.replace(/'/g, "''"), o = n.replace(/'/g, "''");
|
|
508
516
|
r.push(`DO \$\$
|
|
509
517
|
DECLARE
|
|
@@ -519,85 +527,85 @@ BEGIN
|
|
|
519
527
|
tables: t,
|
|
520
528
|
views: r
|
|
521
529
|
};
|
|
522
|
-
},
|
|
523
|
-
let { tables:
|
|
524
|
-
|
|
525
|
-
let
|
|
526
|
-
|
|
527
|
-
let d = Pe(
|
|
528
|
-
d &&
|
|
529
|
-
for (let e of
|
|
530
|
-
if (!
|
|
531
|
-
for (let e of
|
|
532
|
-
let
|
|
533
|
-
|
|
534
|
-
}
|
|
535
|
-
let f =
|
|
536
|
-
if (f.length > 0 &&
|
|
537
|
-
|
|
538
|
-
for (let e of f)
|
|
539
|
-
}
|
|
540
|
-
for (let e of
|
|
541
|
-
return
|
|
542
|
-
}, Le = (
|
|
543
|
-
let
|
|
544
|
-
switch (
|
|
545
|
-
case "postgres": return `CREATE SCHEMA IF NOT EXISTS ${
|
|
530
|
+
}, M = (e, t) => {
|
|
531
|
+
let { tables: n, views: i } = Ie(e), { sorted: a, cyclic: o } = je(n.map((e) => S(e, t))), s = Ne(o, t), c = [];
|
|
532
|
+
t === "postgres" && ke(a) && c.push("CREATE EXTENSION IF NOT EXISTS vector;"), t === "postgres" && Ae(a) && c.push("CREATE EXTENSION IF NOT EXISTS postgis;");
|
|
533
|
+
let l = Fe(a, t);
|
|
534
|
+
l && c.push(l);
|
|
535
|
+
let d = Pe(a, t);
|
|
536
|
+
d && c.push(d);
|
|
537
|
+
for (let e of a) c.push(we(e, t, null, s.get(e.tableName)));
|
|
538
|
+
if (!u(t)) for (let e of o) c.push(Me(e, t));
|
|
539
|
+
for (let e of a) {
|
|
540
|
+
let n = Ee(e, t);
|
|
541
|
+
n && c.push(n);
|
|
542
|
+
}
|
|
543
|
+
let f = a.filter((e) => e.isReactive !== !1);
|
|
544
|
+
if (f.length > 0 && t === "postgres") {
|
|
545
|
+
c.push(De);
|
|
546
|
+
for (let e of f) c.push(Oe(e));
|
|
547
|
+
}
|
|
548
|
+
for (let e of i) c.push(r(e, t));
|
|
549
|
+
return c.join("\n\n") + "\n";
|
|
550
|
+
}, Le = (t, n, r) => {
|
|
551
|
+
let i = e(t, n);
|
|
552
|
+
switch (n) {
|
|
553
|
+
case "postgres": return `CREATE SCHEMA IF NOT EXISTS ${i};`;
|
|
546
554
|
case "mysql":
|
|
547
|
-
case "mariadb": return `CREATE DATABASE IF NOT EXISTS ${
|
|
548
|
-
case "mssql": return `IF SCHEMA_ID('${
|
|
555
|
+
case "mariadb": return `CREATE DATABASE IF NOT EXISTS ${i};`;
|
|
556
|
+
case "mssql": return `IF SCHEMA_ID('${t.replace(/'/g, "''")}') IS NULL EXEC(N'CREATE SCHEMA ${i.replace(/'/g, "''")}');`;
|
|
549
557
|
case "turso":
|
|
550
|
-
case "sqlite": return `ATTACH DATABASE '${(
|
|
558
|
+
case "sqlite": return `ATTACH DATABASE '${(r ?? `${t}.db`).replace(/'/g, "''")}' AS ${i};`;
|
|
551
559
|
}
|
|
552
560
|
}, Re = (t, n, r, i) => {
|
|
553
|
-
let a = Le(r, n, i), o =
|
|
554
|
-
if (n === "postgres") return `${a}\n\nSET search_path TO ${o};\n\n${
|
|
555
|
-
if (n === "mysql" || n === "mariadb") return `${a}\n\nUSE ${o};\n\n${
|
|
561
|
+
let a = Le(r, n, i), o = e(r, n);
|
|
562
|
+
if (n === "postgres") return `${a}\n\nSET search_path TO ${o};\n\n${M(t, n)}`;
|
|
563
|
+
if (n === "mysql" || n === "mariadb") return `${a}\n\nUSE ${o};\n\n${M(t, n)}`;
|
|
556
564
|
let { sorted: s, cyclic: c } = je(t), l = Ne(c, n), d = [a];
|
|
557
565
|
for (let e of s) d.push(we(e, n, r, l.get(e.tableName)));
|
|
558
|
-
if (!
|
|
566
|
+
if (!u(n)) for (let e of c) d.push(Me(e, n, r));
|
|
559
567
|
for (let e of s) {
|
|
560
568
|
let t = Ee(e, n, r);
|
|
561
569
|
t && d.push(t);
|
|
562
570
|
}
|
|
563
571
|
return d.join("\n\n") + "\n";
|
|
564
|
-
}, ze = (
|
|
565
|
-
if (
|
|
566
|
-
let { sorted:
|
|
567
|
-
|
|
568
|
-
let
|
|
569
|
-
|
|
570
|
-
for (let e of
|
|
571
|
-
for (let e of
|
|
572
|
-
for (let
|
|
573
|
-
let
|
|
574
|
-
if (
|
|
575
|
-
let
|
|
576
|
-
let
|
|
577
|
-
return `ALTER TABLE ${
|
|
572
|
+
}, ze = (t, n) => {
|
|
573
|
+
if (n !== "postgres") return M(t, n);
|
|
574
|
+
let { sorted: r, cyclic: i } = je(t), a = Ne(i, n), o = [], s = Fe(r, n);
|
|
575
|
+
s && o.push(s);
|
|
576
|
+
let c = Pe(r, n);
|
|
577
|
+
c && o.push(c);
|
|
578
|
+
for (let e of r) o.push(we(e, n, null, a.get(e.tableName)));
|
|
579
|
+
for (let e of i) o.push(Me(e, n));
|
|
580
|
+
for (let t of r) {
|
|
581
|
+
let r = Object.entries(t.fields);
|
|
582
|
+
if (r.length === 0) continue;
|
|
583
|
+
let i = r.map(([r, i]) => {
|
|
584
|
+
let o = Ce(r, i, n, void 0, a.get(t.tableName)?.has(r) ?? !1);
|
|
585
|
+
return `ALTER TABLE ${e(t.tableName, n)} ADD COLUMN IF NOT EXISTS ${o};`;
|
|
578
586
|
});
|
|
579
|
-
|
|
587
|
+
o.push(i.join("\n"));
|
|
580
588
|
}
|
|
581
|
-
for (let e of
|
|
582
|
-
let
|
|
583
|
-
|
|
589
|
+
for (let e of r) {
|
|
590
|
+
let t = Ee(e, n);
|
|
591
|
+
t && o.push(t);
|
|
584
592
|
}
|
|
585
|
-
let
|
|
586
|
-
if (
|
|
587
|
-
|
|
588
|
-
for (let e of
|
|
593
|
+
let l = r.filter((e) => e.isReactive);
|
|
594
|
+
if (l.length > 0) {
|
|
595
|
+
o.push(De);
|
|
596
|
+
for (let e of l) o.push(Oe(e));
|
|
589
597
|
}
|
|
590
|
-
return
|
|
598
|
+
return o.join("\n\n") + "\n";
|
|
591
599
|
}, Be = (e, t = "postgres") => d.gen(function* () {
|
|
592
600
|
let n = yield* p.SqlClient;
|
|
593
|
-
yield*
|
|
601
|
+
yield* he(n, Ue(n, M(e, t), t)).pipe(d.orDie);
|
|
594
602
|
}), Ve = (e, t) => {
|
|
595
603
|
let n = t.cause ?? {};
|
|
596
604
|
return (n.errno === 1061 || n.code === "ER_DUP_KEYNAME") && /^\s*CREATE\s+(UNIQUE\s+|FULLTEXT\s+)?INDEX\b/i.test(e);
|
|
597
605
|
}, He = (e) => d.gen(function* () {
|
|
598
606
|
let t = yield* p.SqlClient;
|
|
599
|
-
for (let n of We(e)) process.env.VOLTRO_MIGRATE_DEBUG === "1" &&
|
|
600
|
-
|
|
607
|
+
for (let n of We(e)) process.env.VOLTRO_MIGRATE_DEBUG === "1" && ge.debug(`EXEC: ${n.replace(/\s+/g, " ").slice(0, 180)}`), yield* t.unsafe(n).pipe(d.catchIf((e) => Ve(n, e), () => d.void), d.tapError((e) => d.sync(() => {
|
|
608
|
+
ge.error(_("migrate: statement failed", n, e, 200));
|
|
601
609
|
})), d.orDieWith((e) => Error(_("migrate: statement failed", n, e, 400).trim())));
|
|
602
610
|
}), Ue = (e, t, n) => (n === "turso" ? He(t) : e.withTransaction(He(t))).pipe(d.orDie), We = (e) => {
|
|
603
611
|
let t = [], n = "", r = !1;
|
|
@@ -618,13 +626,13 @@ BEGIN
|
|
|
618
626
|
await d.runPromise(Be(e, n).pipe(d.provide(t)));
|
|
619
627
|
}, Ke = (e, t, n = "postgres") => d.gen(function* () {
|
|
620
628
|
let r = Re(e, n, t), i = yield* p.SqlClient;
|
|
621
|
-
yield*
|
|
629
|
+
yield* he(i, Ue(i, r, n)).pipe(d.orDie);
|
|
622
630
|
}), qe = async (e, t, n, r = "postgres") => {
|
|
623
631
|
await d.runPromise(Ke(e, t, r).pipe(d.provide(n)));
|
|
624
632
|
}, Je = async (e, t, n = "postgres") => {
|
|
625
633
|
await d.runPromise(d.gen(function* () {
|
|
626
634
|
let t = ze(e, n), r = yield* p.SqlClient;
|
|
627
|
-
yield*
|
|
635
|
+
yield* he(r, Ue(r, t, n)).pipe(d.orDie);
|
|
628
636
|
}).pipe(d.provide(t)));
|
|
629
637
|
}, Ye = (e) => {
|
|
630
638
|
if (e == null) return e;
|
|
@@ -644,10 +652,10 @@ BEGIN
|
|
|
644
652
|
name: e.name,
|
|
645
653
|
columns: Ze(e.columns),
|
|
646
654
|
indexes: Qe(e.indexes)
|
|
647
|
-
})).sort((e, t) => e.name.localeCompare(t.name)),
|
|
655
|
+
})).sort((e, t) => e.name.localeCompare(t.name)), N = (e) => {
|
|
648
656
|
let t = { tables: $e(e.tables) }, n = JSON.stringify(Ye(t));
|
|
649
657
|
return m("sha256").update(n).digest("hex");
|
|
650
|
-
},
|
|
658
|
+
}, P = (e) => e.slice(0, 16), et = (e, t) => {
|
|
651
659
|
let n = t.references ? {
|
|
652
660
|
table: t.references().tableName,
|
|
653
661
|
column: "id",
|
|
@@ -677,7 +685,13 @@ BEGIN
|
|
|
677
685
|
...t.narrowedFrom.using === void 0 ? {} : { using: t.narrowedFrom.using }
|
|
678
686
|
} } : {},
|
|
679
687
|
...t.sensitive ? { sensitive: t.sensitive } : t.encrypted && !t.safe ? { sensitive: { class: "secret" } } : {},
|
|
680
|
-
...t.safe ? { safe: !0 } : {}
|
|
688
|
+
...t.safe ? { safe: !0 } : {},
|
|
689
|
+
...t.vectorDim === void 0 ? {} : { vectorDim: t.vectorDim },
|
|
690
|
+
...t.vectorPrecision === void 0 ? {} : { vectorPrecision: t.vectorPrecision },
|
|
691
|
+
...t.arrayElement === void 0 ? {} : { arrayElement: t.arrayElement },
|
|
692
|
+
...t.enumName === void 0 ? {} : { enumName: t.enumName },
|
|
693
|
+
...t.enumValues === void 0 ? {} : { enumValues: t.enumValues },
|
|
694
|
+
...t.spatial === void 0 ? {} : { spatial: t.spatial }
|
|
681
695
|
};
|
|
682
696
|
}, tt = (e) => {
|
|
683
697
|
let t = [], n = /* @__PURE__ */ new Set(), r = (e) => {
|
|
@@ -713,13 +727,13 @@ BEGIN
|
|
|
713
727
|
columns: t.fields,
|
|
714
728
|
unique: !0
|
|
715
729
|
});
|
|
716
|
-
let
|
|
717
|
-
for (let e of a) e.fields.every((e) => typeof e == "string") &&
|
|
730
|
+
let s = /* @__PURE__ */ new Set();
|
|
731
|
+
for (let e of a) e.fields.every((e) => typeof e == "string") && s.add(e.fields.join("\0"));
|
|
718
732
|
for (let [t, n] of Object.entries(e.fields)) {
|
|
719
733
|
let i = n;
|
|
720
|
-
if (i.dropped || !i.references || i.fkAutoIndex === !1 ||
|
|
734
|
+
if (i.dropped || !i.references || i.fkAutoIndex === !1 || s.has(t)) continue;
|
|
721
735
|
let a = `${e.tableName}_${t}_idx`;
|
|
722
|
-
|
|
736
|
+
c(e.tableName, a, !0, [t]), r({
|
|
723
737
|
name: a,
|
|
724
738
|
table: e.tableName,
|
|
725
739
|
columns: [t],
|
|
@@ -751,22 +765,56 @@ BEGIN
|
|
|
751
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}').`);
|
|
752
766
|
t.set(e.name, n.name);
|
|
753
767
|
}
|
|
754
|
-
},
|
|
755
|
-
let n = e.map((e) => nt(
|
|
768
|
+
}, F = (e, t) => {
|
|
769
|
+
let n = e.map((e) => nt(S(e, t)));
|
|
756
770
|
return rt(n), { tables: n };
|
|
757
|
-
}, it =
|
|
771
|
+
}, it = "framework_changes_", at = (e, t) => d.gen(function* () {
|
|
772
|
+
let n = t.filter((e) => !e.tableName.startsWith("_voltro_"));
|
|
773
|
+
if (n.length === 0) return {
|
|
774
|
+
missing: [],
|
|
775
|
+
stale: []
|
|
776
|
+
};
|
|
777
|
+
let r = yield* e`
|
|
778
|
+
SELECT t.tgname
|
|
779
|
+
FROM pg_trigger t
|
|
780
|
+
JOIN pg_class c ON c.oid = t.tgrelid
|
|
781
|
+
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
782
|
+
WHERE NOT t.tgisinternal
|
|
783
|
+
AND n.nspname = current_schema()
|
|
784
|
+
AND t.tgname LIKE ${`${it}%`}
|
|
785
|
+
`, i = new Set(r.map((e) => e.tgname)), a = [], o = [];
|
|
786
|
+
for (let e of n) {
|
|
787
|
+
let t = i.has(`${it}${e.tableName}`), n = e.isReactive !== !1;
|
|
788
|
+
n && !t && a.push(e.tableName), !n && t && o.push(e.tableName);
|
|
789
|
+
}
|
|
790
|
+
return {
|
|
791
|
+
missing: a.sort(),
|
|
792
|
+
stale: o.sort()
|
|
793
|
+
};
|
|
794
|
+
}), ot = (e) => {
|
|
795
|
+
let t = [];
|
|
796
|
+
if (e.missing.length > 0) {
|
|
797
|
+
let n = e.missing.slice(0, 8).join(", "), r = e.missing.length > 8 ? `, … (+${e.missing.length - 8})` : "";
|
|
798
|
+
t.push(`${e.missing.length} reactive table(s) have NO change trigger in the database — ${n}${r}. Writes to them will not reach another instance's subscribers; a single instance is unaffected, which is why this stays invisible until you scale out. Run \`voltro db apply\` to install them.`);
|
|
799
|
+
}
|
|
800
|
+
if (e.stale.length > 0) {
|
|
801
|
+
let n = e.stale.slice(0, 8).join(", ");
|
|
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
|
+
}
|
|
804
|
+
return t.length > 0 ? t.join("\n") : void 0;
|
|
805
|
+
}, st = /* @__PURE__ */ new Set(["voltro_isr_cache"]), I = (e) => st.has(e) || e.startsWith("_voltro_") || e.startsWith("_cloud_") || e.startsWith("cluster_"), ct = {
|
|
758
806
|
postgres: !0,
|
|
759
807
|
mysql: !0,
|
|
760
808
|
mariadb: !0,
|
|
761
809
|
mssql: !0,
|
|
762
810
|
sqlite: !0
|
|
763
|
-
},
|
|
811
|
+
}, lt = {
|
|
764
812
|
postgres: !0,
|
|
765
813
|
mysql: !1,
|
|
766
814
|
mariadb: !1,
|
|
767
815
|
mssql: !0,
|
|
768
816
|
sqlite: !0
|
|
769
|
-
},
|
|
817
|
+
}, ut = (e) => {
|
|
770
818
|
switch (e) {
|
|
771
819
|
case "add-column":
|
|
772
820
|
case "drop-column":
|
|
@@ -776,43 +824,43 @@ BEGIN
|
|
|
776
824
|
case "add-foreign-key":
|
|
777
825
|
case "add-unique":
|
|
778
826
|
case "add-unique-composite":
|
|
779
|
-
case "add-check": return
|
|
780
|
-
default: return
|
|
827
|
+
case "add-check": return lt;
|
|
828
|
+
default: return ct;
|
|
781
829
|
}
|
|
782
|
-
},
|
|
830
|
+
}, dt = (e, t) => {
|
|
783
831
|
let n = new Map(t.tables.map((e) => [e.name, e]));
|
|
784
832
|
return new Map(e.map((e) => [e.tableName, {
|
|
785
833
|
table: e,
|
|
786
834
|
snapshot: n.get(e.tableName),
|
|
787
835
|
columnDefs: e.fields
|
|
788
836
|
}]));
|
|
789
|
-
},
|
|
837
|
+
}, ft = (e) => (t, n) => t.name === e ? -1 : n.name === e ? 1 : t.name.localeCompare(n.name), L = (e) => {
|
|
790
838
|
if (typeof e != "object" || !e) return JSON.stringify(e);
|
|
791
|
-
if (Array.isArray(e)) return `[${e.map(
|
|
839
|
+
if (Array.isArray(e)) return `[${e.map(L).join(",")}]`;
|
|
792
840
|
let t = e;
|
|
793
|
-
return `{${Object.keys(t).sort().map((e) => `${JSON.stringify(e)}:${
|
|
794
|
-
},
|
|
841
|
+
return `{${Object.keys(t).sort().map((e) => `${JSON.stringify(e)}:${L(t[e])}`).join(",")}}`;
|
|
842
|
+
}, pt = (e) => {
|
|
795
843
|
if (!e.hasDefault || e.defaultValue === void 0 || e.defaultValue === null) return null;
|
|
796
844
|
let t = e.defaultValue;
|
|
797
845
|
if (typeof t == "boolean") return t ? "__BOOL_TRUE__" : "__BOOL_FALSE__";
|
|
798
846
|
if (typeof t == "number") return String(t);
|
|
799
|
-
if (typeof t != "string") return
|
|
847
|
+
if (typeof t != "string") return L(t);
|
|
800
848
|
let n = t.trim(), r = n.toLowerCase().replace(/\s+/g, "");
|
|
801
849
|
if (r === "now" || r === "now()" || /^current_timestamp(\(\d*\))?$/.test(r) || r === "sysutcdatetime()" || r === "sysdatetime()" || r === "getutcdate()" || r === "getdate()") return "__NOW__";
|
|
802
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);
|
|
803
851
|
if (o) try {
|
|
804
|
-
return
|
|
852
|
+
return L(JSON.parse(o[1]));
|
|
805
853
|
} catch {}
|
|
806
854
|
if (a.startsWith("{") || a.startsWith("[")) try {
|
|
807
|
-
return
|
|
855
|
+
return L(JSON.parse(a));
|
|
808
856
|
} catch {}
|
|
809
857
|
return /^-?\d+(\.\d+)?$/.test(a) ? String(Number(a)) : a;
|
|
810
|
-
},
|
|
811
|
-
let n =
|
|
858
|
+
}, mt = (e, t) => {
|
|
859
|
+
let n = pt(e), r = pt(t);
|
|
812
860
|
if (n === r) return !0;
|
|
813
861
|
let i = (e) => e === "1" || e === "true" ? "__BOOL_TRUE__" : e === "0" || e === "false" ? "__BOOL_FALSE__" : e;
|
|
814
862
|
return i(n) === i(r);
|
|
815
|
-
},
|
|
863
|
+
}, R = (e) => {
|
|
816
864
|
if (!e) return null;
|
|
817
865
|
let t = (e) => e === "restrict" ? "noAction" : e;
|
|
818
866
|
return {
|
|
@@ -821,18 +869,18 @@ BEGIN
|
|
|
821
869
|
onDelete: t(e.onDelete),
|
|
822
870
|
onUpdate: t(e.onUpdate)
|
|
823
871
|
};
|
|
824
|
-
},
|
|
872
|
+
}, ht = (e, t) => {
|
|
825
873
|
let n = e && e.length > 0 ? e : void 0, r = t && t.length > 0 ? t : void 0;
|
|
826
874
|
if (!n && !r) return !0;
|
|
827
875
|
if (!n || !r || n.length !== r.length) return !1;
|
|
828
876
|
let i = [...n].sort(), a = [...r].sort();
|
|
829
877
|
return i.every((e, t) => e === a[t]);
|
|
830
|
-
},
|
|
878
|
+
}, gt = (e, t) => e.type === t.type && e.nullable === t.nullable && e.unique === t.unique && mt(e, t) && JSON.stringify(R(e.references)) === JSON.stringify(R(t.references)) && ht(e.oneOf, t.oneOf), _t = (e, t) => t.oneOf && t.oneOf.length > 0 ? z({
|
|
831
879
|
kind: "add-check",
|
|
832
880
|
table: e,
|
|
833
881
|
column: t.name,
|
|
834
882
|
values: t.oneOf
|
|
835
|
-
}, "safe", `enum-membership CHECK on ${e}.${t.name}`) : void 0,
|
|
883
|
+
}, "safe", `enum-membership CHECK on ${e}.${t.name}`) : void 0, vt = (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])), yt = (e, t) => {
|
|
836
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 = [];
|
|
837
885
|
for (let t of e.columns) {
|
|
838
886
|
let e = n.get(t.name);
|
|
@@ -840,7 +888,7 @@ BEGIN
|
|
|
840
888
|
i.push(t);
|
|
841
889
|
continue;
|
|
842
890
|
}
|
|
843
|
-
|
|
891
|
+
gt(t, e) || o.push({
|
|
844
892
|
declared: t,
|
|
845
893
|
live: e
|
|
846
894
|
});
|
|
@@ -851,47 +899,47 @@ BEGIN
|
|
|
851
899
|
removed: a,
|
|
852
900
|
changed: o
|
|
853
901
|
};
|
|
854
|
-
},
|
|
902
|
+
}, bt = (e, t) => {
|
|
855
903
|
let n = new Map(t.indexes.map((e) => [e.name, e])), r = new Map(e.indexes.map((e) => [e.name, e])), i = [], a = [];
|
|
856
904
|
for (let t of e.indexes) {
|
|
857
905
|
let e = n.get(t.name);
|
|
858
|
-
(!e || !
|
|
906
|
+
(!e || !vt(t, e)) && i.push(t);
|
|
859
907
|
}
|
|
860
908
|
for (let e of t.indexes) r.has(e.name) || a.push(e);
|
|
861
909
|
return {
|
|
862
910
|
added: i,
|
|
863
911
|
removed: a
|
|
864
912
|
};
|
|
865
|
-
},
|
|
913
|
+
}, z = (e, t, n, r) => ({
|
|
866
914
|
op: e,
|
|
867
915
|
classification: t,
|
|
868
|
-
atomicByDialect:
|
|
916
|
+
atomicByDialect: ut(e.kind),
|
|
869
917
|
...n ? { reason: n } : {},
|
|
870
918
|
...r ? { blocked: r } : {}
|
|
871
|
-
}),
|
|
919
|
+
}), xt = (e, t, n) => {
|
|
872
920
|
let r = {
|
|
873
921
|
kind: "add-column",
|
|
874
922
|
table: e,
|
|
875
923
|
column: t
|
|
876
924
|
};
|
|
877
|
-
return t.nullable ?
|
|
878
|
-
},
|
|
925
|
+
return t.nullable ? z(r, "safe", "nullable column add — no backfill needed") : t.hasDefault && t.defaultValue !== void 0 ? z(r, "needs-default", "NOT NULL with literal default — DDL DEFAULT will populate existing rows") : n?.backfill ? z(r, "needs-backfill", `backfill declared (kind=${n.backfill.kind}) — applier will run 3-step add/update/set-not-null`) : z(r, "needs-backfill", "NOT NULL column on a table whose row count is unknown", { fix: `declare \`${t.name}: <type>().backfill(sql\`...\`)\` OR \`.default(value)\` so existing rows survive the migration` });
|
|
926
|
+
}, St = (e, t, n) => {
|
|
879
927
|
let r = {
|
|
880
928
|
kind: "drop-column",
|
|
881
929
|
table: e,
|
|
882
930
|
column: t.name
|
|
883
931
|
};
|
|
884
|
-
return n?.dropped ?
|
|
885
|
-
},
|
|
932
|
+
return n?.dropped ? z(r, "lossy", `column dropped via \`${t.name}: dropped()\` marker — intentional`) : z(r, "lossy", "column missing from declared schema", { fix: `if intentional, add \`${t.name}: dropped()\` to the schema. If a typo, restore the field` });
|
|
933
|
+
}, Ct = (e, t, n, r) => z({
|
|
886
934
|
kind: "create-table",
|
|
887
935
|
table: e,
|
|
888
936
|
columns: t,
|
|
889
937
|
indexes: n,
|
|
890
938
|
...r && r.length > 0 ? { primaryKey: r } : {}
|
|
891
|
-
}, "safe", "new table — no data to preserve"),
|
|
939
|
+
}, "safe", "new table — no data to preserve"), wt = (e) => z({
|
|
892
940
|
kind: "drop-table",
|
|
893
941
|
table: e
|
|
894
|
-
}, "lossy", "table missing from declared schema", { fix: "if intentional, set VOLTRO_DESTRUCTIVE_OK=1 OR add a file-based migration. If a typo, restore the table declaration" }),
|
|
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" }), Tt = 5e4, Et = (e, t, n, r) => {
|
|
895
943
|
let i = (n ?? 0) >= r, a;
|
|
896
944
|
return a = t.unique ? t.columns.length === 1 ? {
|
|
897
945
|
kind: "add-unique",
|
|
@@ -906,16 +954,16 @@ BEGIN
|
|
|
906
954
|
kind: "add-index",
|
|
907
955
|
table: e,
|
|
908
956
|
index: t
|
|
909
|
-
}, i ?
|
|
910
|
-
},
|
|
957
|
+
}, i ? z(a, "online-required", `online build on ${n} rows — CONCURRENTLY / INPLACE / WITH(ONLINE=ON) depending on dialect`) : z(a, "safe", t.unique ? t.columns.length === 1 ? "add unique constraint" : "add composite UNIQUE constraint" : "add B-tree index");
|
|
958
|
+
}, Dt = (e, t) => t.unique && t.columns.length > 1 ? z({
|
|
911
959
|
kind: "drop-unique-composite",
|
|
912
960
|
table: e,
|
|
913
961
|
name: t.name
|
|
914
|
-
}, "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)") : z({
|
|
915
963
|
kind: "drop-index",
|
|
916
964
|
table: e,
|
|
917
965
|
index: t.name
|
|
918
|
-
}, "safe", "drop index (no data loss — index is derived data)"),
|
|
966
|
+
}, "safe", "drop index (no data loss — index is derived data)"), Ot = (e, t) => {
|
|
919
967
|
if (e === "reference") return "text";
|
|
920
968
|
switch (t) {
|
|
921
969
|
case "sqlite":
|
|
@@ -923,7 +971,7 @@ BEGIN
|
|
|
923
971
|
case "mssql": return e === "json" ? "text" : e;
|
|
924
972
|
default: return e;
|
|
925
973
|
}
|
|
926
|
-
},
|
|
974
|
+
}, kt = (e, t, n, r, i, a) => {
|
|
927
975
|
let o = [];
|
|
928
976
|
if (t.nullable !== n.nullable) {
|
|
929
977
|
let n = {
|
|
@@ -932,7 +980,7 @@ BEGIN
|
|
|
932
980
|
column: t.name,
|
|
933
981
|
toNullable: t.nullable
|
|
934
982
|
};
|
|
935
|
-
o.push(t.nullable ?
|
|
983
|
+
o.push(t.nullable ? z(n, "safe", `loosen ${e}.${t.name} to nullable`) : z(n, "needs-backfill", `tighten ${e}.${t.name} to NOT NULL — existing rows must already be non-null`));
|
|
936
984
|
}
|
|
937
985
|
if (t.unique !== n.unique) if (t.unique) {
|
|
938
986
|
let n = {
|
|
@@ -940,13 +988,13 @@ BEGIN
|
|
|
940
988
|
table: e,
|
|
941
989
|
column: t.name
|
|
942
990
|
}, r = (i ?? 0) >= a;
|
|
943
|
-
o.push(r ?
|
|
944
|
-
} else o.push(
|
|
991
|
+
o.push(r ? z(n, "online-required", `online unique build on ${i} rows — CONCURRENTLY / INPLACE / WITH(ONLINE=ON) depending on dialect`) : z(n, "safe", `add unique constraint on ${e}.${t.name} — existing rows must already be distinct (else the DB rejects at migrate)`));
|
|
992
|
+
} else o.push(z({
|
|
945
993
|
kind: "drop-unique",
|
|
946
994
|
table: e,
|
|
947
995
|
column: t.name
|
|
948
996
|
}, "safe", `drop unique constraint on ${e}.${t.name} — constraint is derived metadata, no data loss`));
|
|
949
|
-
if (
|
|
997
|
+
if (Ot(t.type, r) !== Ot(n.type, r)) {
|
|
950
998
|
let r = t.narrowedFrom;
|
|
951
999
|
if (r && r.from === n.type) {
|
|
952
1000
|
let i = {
|
|
@@ -957,7 +1005,7 @@ BEGIN
|
|
|
957
1005
|
to: t.type,
|
|
958
1006
|
...r.using === void 0 ? {} : { using: r.using }
|
|
959
1007
|
};
|
|
960
|
-
o.push(
|
|
1008
|
+
o.push(z(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)")));
|
|
961
1009
|
} else {
|
|
962
1010
|
let r = {
|
|
963
1011
|
kind: "alter-column-type",
|
|
@@ -966,10 +1014,10 @@ BEGIN
|
|
|
966
1014
|
from: n.type,
|
|
967
1015
|
to: t.type
|
|
968
1016
|
};
|
|
969
|
-
o.push(
|
|
1017
|
+
o.push(z(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` }));
|
|
970
1018
|
}
|
|
971
1019
|
}
|
|
972
|
-
if (!
|
|
1020
|
+
if (!mt(t, n)) {
|
|
973
1021
|
let n = {
|
|
974
1022
|
kind: "alter-column-default",
|
|
975
1023
|
table: e,
|
|
@@ -977,18 +1025,18 @@ BEGIN
|
|
|
977
1025
|
hasDefault: t.hasDefault,
|
|
978
1026
|
...t.defaultValue === void 0 ? {} : { defaultValue: t.defaultValue }
|
|
979
1027
|
};
|
|
980
|
-
o.push(
|
|
1028
|
+
o.push(z(n, "safe", `default change on ${e}.${t.name} affects only future inserts`));
|
|
981
1029
|
}
|
|
982
|
-
if (!
|
|
983
|
-
n.oneOf && n.oneOf.length > 0 && o.push(
|
|
1030
|
+
if (!ht(t.oneOf, n.oneOf)) {
|
|
1031
|
+
n.oneOf && n.oneOf.length > 0 && o.push(z({
|
|
984
1032
|
kind: "drop-check",
|
|
985
1033
|
table: e,
|
|
986
1034
|
column: t.name
|
|
987
1035
|
}, "safe", `drop stale enum CHECK on ${e}.${t.name}`));
|
|
988
|
-
let r =
|
|
1036
|
+
let r = _t(e, t);
|
|
989
1037
|
r && o.push(r);
|
|
990
1038
|
}
|
|
991
|
-
if (JSON.stringify(
|
|
1039
|
+
if (JSON.stringify(R(t.references)) !== JSON.stringify(R(n.references)) && (n.references && o.push(z({
|
|
992
1040
|
kind: "drop-foreign-key",
|
|
993
1041
|
table: e,
|
|
994
1042
|
column: t.name
|
|
@@ -1002,17 +1050,17 @@ BEGIN
|
|
|
1002
1050
|
...t.references.onDelete ? { onDelete: t.references.onDelete } : {},
|
|
1003
1051
|
...t.references.onUpdate ? { onUpdate: t.references.onUpdate } : {}
|
|
1004
1052
|
};
|
|
1005
|
-
r === "null" && !t.nullable ? o.push(
|
|
1053
|
+
r === "null" && !t.nullable ? o.push(z(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(z({
|
|
1006
1054
|
...i,
|
|
1007
1055
|
orphanPolicy: r
|
|
1008
|
-
}, "lossy", r === "delete" ? `add FK ${e}.${t.name} → ${n}: orphanPolicy 'delete' first DELETES rows whose ${t.name} points at a missing ${n}` : `add FK ${e}.${t.name} → ${n}: orphanPolicy 'null' first NULLs ${t.name} where it points at a missing ${n}`)) : o.push(
|
|
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(z(i, "needs-backfill", `add FK ${e}.${t.name} → ${n} — existing rows must already reference a valid ${n} (else set orphanPolicy:'null'/'delete')`));
|
|
1009
1057
|
}
|
|
1010
1058
|
return o;
|
|
1011
|
-
},
|
|
1059
|
+
}, At = (e, t, n) => {
|
|
1012
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));
|
|
1013
1061
|
for (let [n, c] of Object.entries(t)) {
|
|
1014
1062
|
let t = c.renamedFrom;
|
|
1015
|
-
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(z({
|
|
1016
1064
|
kind: "rename-column",
|
|
1017
1065
|
table: e.tableName,
|
|
1018
1066
|
from: t,
|
|
@@ -1024,7 +1072,7 @@ BEGIN
|
|
|
1024
1072
|
consumedAddedNames: i,
|
|
1025
1073
|
consumedRemovedNames: a
|
|
1026
1074
|
};
|
|
1027
|
-
},
|
|
1075
|
+
}, jt = (e) => {
|
|
1028
1076
|
let t = {
|
|
1029
1077
|
safe: 0,
|
|
1030
1078
|
needsDefault: 0,
|
|
@@ -1059,37 +1107,37 @@ BEGIN
|
|
|
1059
1107
|
break;
|
|
1060
1108
|
}
|
|
1061
1109
|
return t;
|
|
1062
|
-
},
|
|
1063
|
-
let t =
|
|
1110
|
+
}, Mt = (e) => {
|
|
1111
|
+
let t = F(e.declared, e.dialect), n = dt(e.declared, t), r = new Map(e.live.tables.map((e) => [e.name, e])), i = e.onlineAfter ?? Tt, a = [];
|
|
1064
1112
|
for (let e of t.tables) if (!r.has(e.name)) {
|
|
1065
|
-
a.push(
|
|
1113
|
+
a.push(Ct(e.name, e.columns, e.indexes, e.primaryKey));
|
|
1066
1114
|
for (let t of e.columns) {
|
|
1067
|
-
let n =
|
|
1115
|
+
let n = _t(e.name, t);
|
|
1068
1116
|
n && a.push(n);
|
|
1069
1117
|
}
|
|
1070
1118
|
}
|
|
1071
1119
|
let o = new Set(e.ignoreTables ?? []);
|
|
1072
|
-
for (let t of e.live.tables) n.has(t.name) ||
|
|
1120
|
+
for (let t of e.live.tables) n.has(t.name) || I(t.name) || o.has(t.name) || a.push(wt(t.name));
|
|
1073
1121
|
for (let o of t.tables) {
|
|
1074
1122
|
let t = r.get(o.name);
|
|
1075
1123
|
if (!t) continue;
|
|
1076
|
-
let s = n.get(o.name), c =
|
|
1124
|
+
let s = n.get(o.name), c = yt(o, t), l = bt(o, t), u = At(s.table, s.columnDefs, c);
|
|
1077
1125
|
a.push(...u.ops);
|
|
1078
1126
|
for (let e of c.removed) {
|
|
1079
1127
|
if (u.consumedRemovedNames.has(e.name)) continue;
|
|
1080
1128
|
let t = s.columnDefs[e.name];
|
|
1081
|
-
a.push(
|
|
1129
|
+
a.push(St(o.name, e, t));
|
|
1082
1130
|
}
|
|
1083
1131
|
for (let e of c.added) {
|
|
1084
1132
|
if (u.consumedAddedNames.has(e.name)) continue;
|
|
1085
1133
|
let t = s.columnDefs[e.name];
|
|
1086
|
-
a.push(
|
|
1087
|
-
let n =
|
|
1134
|
+
a.push(xt(o.name, e, t));
|
|
1135
|
+
let n = _t(o.name, e);
|
|
1088
1136
|
n && a.push(n);
|
|
1089
1137
|
}
|
|
1090
|
-
for (let e of l.added) a.push(
|
|
1091
|
-
for (let e of l.removed) a.push(
|
|
1092
|
-
for (let { declared: n, live: r } of c.changed) a.push(...
|
|
1138
|
+
for (let e of l.added) a.push(Et(o.name, e, t.rowCount, i));
|
|
1139
|
+
for (let e of l.removed) a.push(Dt(o.name, e));
|
|
1140
|
+
for (let { declared: n, live: r } of c.changed) a.push(...kt(o.name, n, r, e.dialect, t.rowCount, i));
|
|
1093
1141
|
}
|
|
1094
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) => {
|
|
1095
1143
|
let t = c.get(e);
|
|
@@ -1097,8 +1145,8 @@ BEGIN
|
|
|
1097
1145
|
column: e.name,
|
|
1098
1146
|
target: e.references.table
|
|
1099
1147
|
}] : []) : [];
|
|
1100
|
-
}, u =
|
|
1101
|
-
for (let e of t.tables) if (s.has(e.name)) for (let t of e.columns) !t.references || !u.has(
|
|
1148
|
+
}, u = w([...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(C(e.name, t.name)) || d.push(z({
|
|
1102
1150
|
kind: "add-foreign-key",
|
|
1103
1151
|
table: e.name,
|
|
1104
1152
|
column: t.name,
|
|
@@ -1113,8 +1161,8 @@ BEGIN
|
|
|
1113
1161
|
let n = a[t];
|
|
1114
1162
|
if (n.op.kind !== "create-table") continue;
|
|
1115
1163
|
let r = n.op;
|
|
1116
|
-
if (!r.columns.some((e) => u.has(
|
|
1117
|
-
let i = r.columns.map((t) => u.has(
|
|
1164
|
+
if (!r.columns.some((e) => u.has(C(r.table, e.name)))) continue;
|
|
1165
|
+
let i = r.columns.map((t) => u.has(C(r.table, t.name)) ? e(t) : t);
|
|
1118
1166
|
a[t] = {
|
|
1119
1167
|
...n,
|
|
1120
1168
|
op: {
|
|
@@ -1134,7 +1182,7 @@ BEGIN
|
|
|
1134
1182
|
let i = new Set(t).add(e), a = 0;
|
|
1135
1183
|
for (let t of r.columns) {
|
|
1136
1184
|
let n = t.references?.table;
|
|
1137
|
-
n && n !== e && !u.has(
|
|
1185
|
+
n && n !== e && !u.has(C(e, t.name)) && (a = Math.max(a, m(n, i) + 1));
|
|
1138
1186
|
}
|
|
1139
1187
|
return p.set(e, a), a;
|
|
1140
1188
|
}, h = (e) => e === "create-table" ? 0 : e === "drop-table" ? 2 : 1, g = (e) => {
|
|
@@ -1169,11 +1217,11 @@ BEGIN
|
|
|
1169
1217
|
});
|
|
1170
1218
|
return {
|
|
1171
1219
|
operations: v,
|
|
1172
|
-
fromFingerprint:
|
|
1173
|
-
toFingerprint:
|
|
1174
|
-
summary:
|
|
1220
|
+
fromFingerprint: N(e.live),
|
|
1221
|
+
toFingerprint: N(t),
|
|
1222
|
+
summary: jt(v)
|
|
1175
1223
|
};
|
|
1176
|
-
},
|
|
1224
|
+
}, Nt = (e) => {
|
|
1177
1225
|
let t = /[`"[]?([A-Za-z_][A-Za-z0-9_]*)[`"\]]?\s*(?:in\b|=)/i.exec(e);
|
|
1178
1226
|
if (!t) return null;
|
|
1179
1227
|
let n = [...e.matchAll(/'((?:[^']|'')*)'/g)].map((e) => e[1].replace(/''/g, "'"));
|
|
@@ -1181,7 +1229,7 @@ BEGIN
|
|
|
1181
1229
|
column: t[1],
|
|
1182
1230
|
values: n
|
|
1183
1231
|
};
|
|
1184
|
-
},
|
|
1232
|
+
}, Pt = (e, t) => {
|
|
1185
1233
|
if (t === "vector") return "vector";
|
|
1186
1234
|
switch (e) {
|
|
1187
1235
|
case "text":
|
|
@@ -1208,7 +1256,7 @@ BEGIN
|
|
|
1208
1256
|
case "USER-DEFINED": return "text";
|
|
1209
1257
|
default: return "text";
|
|
1210
1258
|
}
|
|
1211
|
-
},
|
|
1259
|
+
}, B = (e) => {
|
|
1212
1260
|
switch (e.toUpperCase()) {
|
|
1213
1261
|
case "CASCADE": return "cascade";
|
|
1214
1262
|
case "RESTRICT": return "restrict";
|
|
@@ -1216,25 +1264,25 @@ BEGIN
|
|
|
1216
1264
|
case "SET DEFAULT": return "noAction";
|
|
1217
1265
|
default: return "noAction";
|
|
1218
1266
|
}
|
|
1219
|
-
},
|
|
1267
|
+
}, Ft = (e, t) => {
|
|
1220
1268
|
let n = e !== void 0 && e !== "" ? Number(e) : NaN;
|
|
1221
1269
|
return Number.isInteger(n) && n > 0 ? n : t;
|
|
1222
|
-
},
|
|
1270
|
+
}, It = () => Ft(process.env.VOLTRO_INTROSPECT_BATCH, 20), Lt = 300, Rt = () => {
|
|
1223
1271
|
let e = process.env.VOLTRO_INTROSPECT_TIMEOUT_MS;
|
|
1224
|
-
return e !== void 0 && e.trim() === "0" ? 0 :
|
|
1225
|
-
},
|
|
1272
|
+
return e !== void 0 && e.trim() === "0" ? 0 : Ft(e, 3e4);
|
|
1273
|
+
}, zt = (e, t) => {
|
|
1226
1274
|
let n = Number.isFinite(t) && t >= 1 ? Math.floor(t) : 1, r = [];
|
|
1227
1275
|
for (let t = 0; t < e.length; t += n) r.push(e.slice(t, t + n));
|
|
1228
1276
|
return r;
|
|
1229
|
-
},
|
|
1230
|
-
let t =
|
|
1277
|
+
}, Bt = (e) => {
|
|
1278
|
+
let t = Rt(), n = d.gen(function* () {
|
|
1231
1279
|
t > 0 && (yield* e.unsafe(`SET LOCAL statement_timeout = ${t}`));
|
|
1232
|
-
let n = (t) => e.unsafe("(" + t.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ") + ")"), r = (t) => e.unsafe(String(Math.max(0, Math.trunc(t)))), i =
|
|
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 = It(), a = (e, t) => d.gen(function* () {
|
|
1233
1281
|
let r = [];
|
|
1234
|
-
for (let a of
|
|
1282
|
+
for (let a of zt(e, i)) a.length !== 0 && r.push(...yield* t(n(a)));
|
|
1235
1283
|
return r;
|
|
1236
1284
|
}), o = [];
|
|
1237
|
-
for (let t = 0;; t +=
|
|
1285
|
+
for (let t = 0;; t += Lt) {
|
|
1238
1286
|
let n = yield* e`
|
|
1239
1287
|
SELECT c.relname AS table_name,
|
|
1240
1288
|
COALESCE(c.reltuples::bigint, 0) AS row_count
|
|
@@ -1242,9 +1290,9 @@ BEGIN
|
|
|
1242
1290
|
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
1243
1291
|
WHERE n.nspname = current_schema() AND c.relkind = 'r'
|
|
1244
1292
|
ORDER BY c.relname
|
|
1245
|
-
LIMIT ${r(
|
|
1293
|
+
LIMIT ${r(Lt)} OFFSET ${r(t)}
|
|
1246
1294
|
`;
|
|
1247
|
-
if (o.push(...n), n.length <
|
|
1295
|
+
if (o.push(...n), n.length < Lt) break;
|
|
1248
1296
|
}
|
|
1249
1297
|
let s = /* @__PURE__ */ new Set(), c = [];
|
|
1250
1298
|
for (let e of o) s.has(e.table_name) || (s.add(e.table_name), c.push(e));
|
|
@@ -1329,7 +1377,7 @@ BEGIN
|
|
|
1329
1377
|
AND c.relname IN ${t}
|
|
1330
1378
|
)
|
|
1331
1379
|
SELECT * FROM ix ORDER BY table_name, index_name, position
|
|
1332
|
-
`), _ = /* @__PURE__ */ new Map(), v = /* @__PURE__ */ new Map(), y = /* @__PURE__ */ new Map(),
|
|
1380
|
+
`), _ = /* @__PURE__ */ new Map(), v = /* @__PURE__ */ new Map(), y = /* @__PURE__ */ new Map(), b = /* @__PURE__ */ new Map(), x = /* @__PURE__ */ new Map(), S = /* @__PURE__ */ new Map();
|
|
1333
1381
|
for (let e of u) {
|
|
1334
1382
|
let t = _.get(e.table_name);
|
|
1335
1383
|
t || (t = [], _.set(e.table_name, t)), t.push(e);
|
|
@@ -1338,25 +1386,25 @@ BEGIN
|
|
|
1338
1386
|
let t = v.get(e.table_name);
|
|
1339
1387
|
t || (t = /* @__PURE__ */ new Set(), v.set(e.table_name, t)), t.add(e.column_name);
|
|
1340
1388
|
}
|
|
1341
|
-
let
|
|
1389
|
+
let C = /* @__PURE__ */ new Map();
|
|
1342
1390
|
for (let e of p) {
|
|
1343
|
-
let t = `${e.table_name}${e.constraint_name}`, n =
|
|
1391
|
+
let t = `${e.table_name}${e.constraint_name}`, n = C.get(t);
|
|
1344
1392
|
n || (n = {
|
|
1345
1393
|
table: e.table_name,
|
|
1346
1394
|
columns: []
|
|
1347
|
-
},
|
|
1395
|
+
}, C.set(t, n)), n.columns.push({
|
|
1348
1396
|
name: e.column_name,
|
|
1349
1397
|
position: e.position
|
|
1350
1398
|
});
|
|
1351
1399
|
}
|
|
1352
|
-
for (let [e, t] of
|
|
1400
|
+
for (let [e, t] of C) {
|
|
1353
1401
|
let n = [...t.columns].sort((e, t) => e.position - t.position).map((e) => e.name);
|
|
1354
1402
|
if (n.length === 1) {
|
|
1355
1403
|
let e = y.get(t.table);
|
|
1356
1404
|
e || (e = /* @__PURE__ */ new Set(), y.set(t.table, e)), e.add(n[0]);
|
|
1357
1405
|
} else {
|
|
1358
|
-
let r =
|
|
1359
|
-
r || (r = [],
|
|
1406
|
+
let r = b.get(t.table);
|
|
1407
|
+
r || (r = [], b.set(t.table, r)), r.push({
|
|
1360
1408
|
name: e.slice(e.indexOf("\0") + 1),
|
|
1361
1409
|
table: t.table,
|
|
1362
1410
|
columns: n,
|
|
@@ -1365,23 +1413,23 @@ BEGIN
|
|
|
1365
1413
|
}
|
|
1366
1414
|
}
|
|
1367
1415
|
for (let e of g) {
|
|
1368
|
-
let t =
|
|
1369
|
-
t || (t = [],
|
|
1416
|
+
let t = x.get(e.source_table);
|
|
1417
|
+
t || (t = [], x.set(e.source_table, t)), t.push(e);
|
|
1370
1418
|
}
|
|
1371
1419
|
for (let e of ee) {
|
|
1372
|
-
let t =
|
|
1373
|
-
t || (t = /* @__PURE__ */ new Map(),
|
|
1420
|
+
let t = S.get(e.table_name);
|
|
1421
|
+
t || (t = /* @__PURE__ */ new Map(), S.set(e.table_name, t));
|
|
1374
1422
|
let n = t.get(e.index_name);
|
|
1375
1423
|
n || (n = [], t.set(e.index_name, n)), n.push(e);
|
|
1376
1424
|
}
|
|
1377
|
-
let
|
|
1425
|
+
let w = [];
|
|
1378
1426
|
for (let e of c) {
|
|
1379
|
-
let t = /* @__PURE__ */ new Set(), n = (_.get(e.table_name) ?? []).filter((e) => t.has(e.column_name) ? !1 : (t.add(e.column_name), !0)), r = v.get(e.table_name) ?? /* @__PURE__ */ new Set(), i = y.get(e.table_name) ?? /* @__PURE__ */ new Set(), a =
|
|
1380
|
-
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 = y.get(e.table_name) ?? /* @__PURE__ */ new Set(), a = x.get(e.table_name) ?? [], o = new Map(a.map((e) => [e.source_column, e])), s = new Set(n.filter((e) => e.udt_name === "tsvector").map((e) => e.column_name)), c = n.filter((e) => !s.has(e.column_name)).map((t) => {
|
|
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" : Pt(t.data_type, t.udt_name), c = a ? {
|
|
1381
1429
|
table: a.target_table,
|
|
1382
1430
|
column: a.target_column,
|
|
1383
|
-
onDelete:
|
|
1384
|
-
onUpdate:
|
|
1431
|
+
onDelete: B(a.delete_rule),
|
|
1432
|
+
onUpdate: B(a.update_rule)
|
|
1385
1433
|
} : void 0, l = h.get(`${e.table_name}.${t.column_name}`);
|
|
1386
1434
|
return {
|
|
1387
1435
|
name: t.column_name,
|
|
@@ -1393,7 +1441,7 @@ BEGIN
|
|
|
1393
1441
|
...c ? { references: c } : {},
|
|
1394
1442
|
...l ? { oneOf: l } : {}
|
|
1395
1443
|
};
|
|
1396
|
-
}), l = [], u =
|
|
1444
|
+
}), l = [], u = S.get(e.table_name);
|
|
1397
1445
|
if (u) for (let [t, n] of u) {
|
|
1398
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) => {
|
|
1399
1447
|
let t = e.position;
|
|
@@ -1409,7 +1457,7 @@ BEGIN
|
|
|
1409
1457
|
...a ? { expression: !0 } : {}
|
|
1410
1458
|
});
|
|
1411
1459
|
}
|
|
1412
|
-
for (let t of
|
|
1460
|
+
for (let t of b.get(e.table_name) ?? []) l.push(t);
|
|
1413
1461
|
r.size > 0 && l.push({
|
|
1414
1462
|
name: `${e.table_name}_pkey`,
|
|
1415
1463
|
table: e.table_name,
|
|
@@ -1417,20 +1465,20 @@ BEGIN
|
|
|
1417
1465
|
unique: !0
|
|
1418
1466
|
});
|
|
1419
1467
|
let d = Number(e.row_count ?? 0);
|
|
1420
|
-
|
|
1468
|
+
w.push({
|
|
1421
1469
|
name: e.table_name,
|
|
1422
1470
|
columns: c,
|
|
1423
1471
|
indexes: l,
|
|
1424
1472
|
...d > 0 ? { rowCount: d } : {}
|
|
1425
1473
|
});
|
|
1426
1474
|
}
|
|
1427
|
-
return { tables:
|
|
1475
|
+
return { tables: w };
|
|
1428
1476
|
});
|
|
1429
1477
|
return (t > 0 ? e.withTransaction(n) : n).pipe(d.catchAll((e) => {
|
|
1430
1478
|
let n = `${String(e)} ${String(e.cause ?? "")}`.toLowerCase();
|
|
1431
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);
|
|
1432
1480
|
}));
|
|
1433
|
-
},
|
|
1481
|
+
}, Vt = (e, t) => {
|
|
1434
1482
|
switch (e.toLowerCase()) {
|
|
1435
1483
|
case "varchar":
|
|
1436
1484
|
case "char":
|
|
@@ -1462,20 +1510,20 @@ BEGIN
|
|
|
1462
1510
|
case "json": return "json";
|
|
1463
1511
|
default: return "text";
|
|
1464
1512
|
}
|
|
1465
|
-
},
|
|
1513
|
+
}, V = (e) => e.map((e) => {
|
|
1466
1514
|
let t = e, n = {};
|
|
1467
1515
|
for (let e of Object.keys(t)) n[e.toLowerCase()] = t[e];
|
|
1468
1516
|
return n;
|
|
1469
|
-
}),
|
|
1470
|
-
let t =
|
|
1517
|
+
}), Ht = (e) => d.gen(function* () {
|
|
1518
|
+
let t = V(yield* e`
|
|
1471
1519
|
SELECT table_name, COALESCE(table_rows, 0) AS table_rows
|
|
1472
1520
|
FROM information_schema.tables
|
|
1473
1521
|
WHERE table_schema = DATABASE() AND table_type = 'BASE TABLE'
|
|
1474
|
-
ORDER BY table_name`), n =
|
|
1522
|
+
ORDER BY table_name`), n = V(yield* e`
|
|
1475
1523
|
SELECT table_name, column_name, data_type, column_type, is_nullable, column_default, column_key
|
|
1476
1524
|
FROM information_schema.columns
|
|
1477
1525
|
WHERE table_schema = DATABASE()
|
|
1478
|
-
ORDER BY table_name, ordinal_position`), r =
|
|
1526
|
+
ORDER BY table_name, ordinal_position`), r = V(yield* e`
|
|
1479
1527
|
SELECT k.table_name AS source_table,
|
|
1480
1528
|
k.column_name AS source_column,
|
|
1481
1529
|
k.referenced_table_name AS target_table,
|
|
@@ -1485,11 +1533,11 @@ BEGIN
|
|
|
1485
1533
|
JOIN information_schema.referential_constraints r
|
|
1486
1534
|
ON k.constraint_name = r.constraint_name
|
|
1487
1535
|
AND k.table_schema = r.constraint_schema
|
|
1488
|
-
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 = V(yield* e`
|
|
1489
1537
|
SELECT table_name, index_name, non_unique, column_name, seq_in_index
|
|
1490
1538
|
FROM information_schema.statistics
|
|
1491
1539
|
WHERE table_schema = DATABASE() AND index_name <> 'PRIMARY'
|
|
1492
|
-
ORDER BY table_name, index_name, seq_in_index`), a =
|
|
1540
|
+
ORDER BY table_name, index_name, seq_in_index`), a = V(yield* e`
|
|
1493
1541
|
SELECT table_name, check_clause
|
|
1494
1542
|
FROM information_schema.check_constraints
|
|
1495
1543
|
WHERE constraint_schema = DATABASE()`.unprepared.pipe(d.orElseSucceed(() => []))), o = /* @__PURE__ */ new Set(), s = /* @__PURE__ */ new Map();
|
|
@@ -1499,7 +1547,7 @@ BEGIN
|
|
|
1499
1547
|
o.add(`${e.table_name}.${t[1]}`);
|
|
1500
1548
|
continue;
|
|
1501
1549
|
}
|
|
1502
|
-
let n =
|
|
1550
|
+
let n = Nt(e.check_clause);
|
|
1503
1551
|
n && s.set(`${e.table_name}.${n.column}`, n.values);
|
|
1504
1552
|
}
|
|
1505
1553
|
let c = /* @__PURE__ */ new Map(), l = /* @__PURE__ */ new Map(), u = /* @__PURE__ */ new Map();
|
|
@@ -1522,11 +1570,11 @@ BEGIN
|
|
|
1522
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);
|
|
1523
1571
|
if (d) for (let e of d.values()) e.length === 1 && e[0].non_unique === 0 && a.add(e[0].column_name);
|
|
1524
1572
|
let p = t.map((t) => {
|
|
1525
|
-
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" : Vt(t.data_type, t.column_type), u = c ? {
|
|
1526
1574
|
table: c.target_table,
|
|
1527
1575
|
column: c.target_column,
|
|
1528
|
-
onDelete:
|
|
1529
|
-
onUpdate:
|
|
1576
|
+
onDelete: B(c.delete_rule),
|
|
1577
|
+
onUpdate: B(c.update_rule)
|
|
1530
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}`);
|
|
1531
1579
|
return {
|
|
1532
1580
|
name: t.column_name,
|
|
@@ -1563,10 +1611,10 @@ BEGIN
|
|
|
1563
1611
|
});
|
|
1564
1612
|
}
|
|
1565
1613
|
return { tables: f };
|
|
1566
|
-
}),
|
|
1614
|
+
}), Ut = (e) => {
|
|
1567
1615
|
let t = e.toUpperCase();
|
|
1568
1616
|
return t.includes("INT") ? "integer" : t.includes("REAL") || t.includes("FLOA") || t.includes("DOUB") ? "real" : t.includes("BLOB") ? "bytes" : "text";
|
|
1569
|
-
},
|
|
1617
|
+
}, Wt = (e) => d.gen(function* () {
|
|
1570
1618
|
let t = yield* e`
|
|
1571
1619
|
SELECT name, sql FROM sqlite_master
|
|
1572
1620
|
WHERE type = 'table' AND name NOT LIKE 'sqlite_%'
|
|
@@ -1583,11 +1631,11 @@ BEGIN
|
|
|
1583
1631
|
d.set(t.name, r), t.unique === 1 && r.length === 1 && f.add(r[0]);
|
|
1584
1632
|
}
|
|
1585
1633
|
let p = o.map((e) => {
|
|
1586
|
-
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" : Ut(e.type), a = r ? {
|
|
1587
1635
|
table: r.table,
|
|
1588
1636
|
column: r.to,
|
|
1589
|
-
onDelete:
|
|
1590
|
-
onUpdate:
|
|
1637
|
+
onDelete: B(r.on_delete),
|
|
1638
|
+
onUpdate: B(r.on_update)
|
|
1591
1639
|
} : void 0, o = t.get(e.name);
|
|
1592
1640
|
return {
|
|
1593
1641
|
name: e.name,
|
|
@@ -1622,7 +1670,7 @@ BEGIN
|
|
|
1622
1670
|
});
|
|
1623
1671
|
}
|
|
1624
1672
|
return { tables: r };
|
|
1625
|
-
}),
|
|
1673
|
+
}), Gt = (e) => {
|
|
1626
1674
|
switch (e.toLowerCase()) {
|
|
1627
1675
|
case "int":
|
|
1628
1676
|
case "smallint":
|
|
@@ -1644,7 +1692,7 @@ BEGIN
|
|
|
1644
1692
|
case "image": return "bytes";
|
|
1645
1693
|
default: return "text";
|
|
1646
1694
|
}
|
|
1647
|
-
},
|
|
1695
|
+
}, H = (e) => e === !0 || e === 1, Kt = (e) => d.gen(function* () {
|
|
1648
1696
|
let t = yield* e`
|
|
1649
1697
|
SELECT TABLE_NAME AS table_name FROM INFORMATION_SCHEMA.TABLES
|
|
1650
1698
|
WHERE TABLE_TYPE = 'BASE TABLE' ORDER BY TABLE_NAME`, n = yield* e`
|
|
@@ -1700,16 +1748,16 @@ BEGIN
|
|
|
1700
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();
|
|
1701
1749
|
if (a) for (let [, e] of a) {
|
|
1702
1750
|
let t = [...e].sort((e, t) => e.key_ordinal - t.key_ordinal);
|
|
1703
|
-
if (
|
|
1704
|
-
else
|
|
1751
|
+
if (H(t[0].is_primary)) for (let e of t) d.push(e.column_name);
|
|
1752
|
+
else H(t[0].is_unique) && t.length === 1 && f.add(t[0].column_name);
|
|
1705
1753
|
}
|
|
1706
1754
|
let p = t.map((t) => {
|
|
1707
|
-
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" : Gt(t.data_type), s = i ? {
|
|
1708
1756
|
table: i.target_table,
|
|
1709
1757
|
column: i.target_column,
|
|
1710
|
-
onDelete:
|
|
1711
|
-
onUpdate:
|
|
1712
|
-
} : void 0, c = t.column_default === null ? null :
|
|
1758
|
+
onDelete: qt(i.delete_rule),
|
|
1759
|
+
onUpdate: qt(i.update_rule)
|
|
1760
|
+
} : void 0, c = t.column_default === null ? null : Jt(t.column_default), l = o.get(`${e}.${t.column_name}`);
|
|
1713
1761
|
return {
|
|
1714
1762
|
name: t.column_name,
|
|
1715
1763
|
type: a,
|
|
@@ -1723,11 +1771,11 @@ BEGIN
|
|
|
1723
1771
|
}), m = [];
|
|
1724
1772
|
if (a) for (let [t, n] of a) {
|
|
1725
1773
|
let r = [...n].sort((e, t) => e.key_ordinal - t.key_ordinal);
|
|
1726
|
-
|
|
1774
|
+
H(r[0].is_primary) || r.length === 1 && H(r[0].is_unique) || r.length === 1 && !H(r[0].is_unique) && i.has(r[0].column_name) && t !== `${e}_${r[0].column_name}_idx` || m.push({
|
|
1727
1775
|
name: t,
|
|
1728
1776
|
table: e,
|
|
1729
1777
|
columns: r.map((e) => e.column_name),
|
|
1730
|
-
unique:
|
|
1778
|
+
unique: H(r[0].is_unique)
|
|
1731
1779
|
});
|
|
1732
1780
|
}
|
|
1733
1781
|
d.length > 0 && m.push({
|
|
@@ -1742,29 +1790,37 @@ BEGIN
|
|
|
1742
1790
|
});
|
|
1743
1791
|
}
|
|
1744
1792
|
return { tables: u };
|
|
1745
|
-
}),
|
|
1793
|
+
}), qt = (e) => {
|
|
1746
1794
|
switch (e.toUpperCase().replace(/_/g, " ")) {
|
|
1747
1795
|
case "CASCADE": return "cascade";
|
|
1748
1796
|
case "SET NULL": return "setNull";
|
|
1749
1797
|
case "SET DEFAULT": return "noAction";
|
|
1750
1798
|
default: return "noAction";
|
|
1751
1799
|
}
|
|
1752
|
-
},
|
|
1800
|
+
}, Jt = (e) => {
|
|
1753
1801
|
let t = e.trim();
|
|
1754
1802
|
for (; t.startsWith("(") && t.endsWith(")");) t = t.slice(1, -1).trim();
|
|
1755
1803
|
return t.startsWith("N'") && t.endsWith("'") ? t = t.slice(2, -1) : t.startsWith("'") && t.endsWith("'") && (t = t.slice(1, -1)), t;
|
|
1756
|
-
},
|
|
1757
|
-
mysql: () =>
|
|
1758
|
-
mssql: () =>
|
|
1759
|
-
sqlite: () =>
|
|
1760
|
-
orElse: () =>
|
|
1761
|
-
}),
|
|
1804
|
+
}, Yt = (e) => e.onDialectOrElse({
|
|
1805
|
+
mysql: () => Ht(e),
|
|
1806
|
+
mssql: () => Kt(e),
|
|
1807
|
+
sqlite: () => Wt(e),
|
|
1808
|
+
orElse: () => Bt(e)
|
|
1809
|
+
}), Xt = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, Zt = (e, t) => {
|
|
1810
|
+
if (!e.spatial && e.type !== "vector" && e.type !== "array" && e.type !== "enum") return;
|
|
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
|
+
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 O(e, t);
|
|
1814
|
+
}, Qt = (e) => {
|
|
1815
|
+
let t = Zt(e, "postgres");
|
|
1816
|
+
return t === void 0 ? $t(e) : t;
|
|
1817
|
+
}, $t = (e) => {
|
|
1762
1818
|
switch (e.type) {
|
|
1763
1819
|
case "id": return "text";
|
|
1764
1820
|
case "text": return "text";
|
|
1765
1821
|
case "integer": return "integer";
|
|
1766
1822
|
case "real": return "double precision";
|
|
1767
|
-
case "decimal": return
|
|
1823
|
+
case "decimal": return Xt(e, "NUMERIC");
|
|
1768
1824
|
case "bigint": return "bigint";
|
|
1769
1825
|
case "boolean": return "boolean";
|
|
1770
1826
|
case "timestamp": return "timestamptz";
|
|
@@ -1772,19 +1828,21 @@ BEGIN
|
|
|
1772
1828
|
case "json": return "jsonb";
|
|
1773
1829
|
case "bytes": return "bytea";
|
|
1774
1830
|
case "reference": return "text";
|
|
1775
|
-
case "vector":
|
|
1776
|
-
case "enum":
|
|
1777
|
-
case "array":
|
|
1831
|
+
case "vector":
|
|
1832
|
+
case "enum":
|
|
1833
|
+
case "array": throw Error(`snapshotPgType: '${e.type}' must go through parameterisedSqlType`);
|
|
1778
1834
|
case "interval": return "interval";
|
|
1779
1835
|
case "raw": return e.rawDdl ?? "text";
|
|
1780
1836
|
}
|
|
1781
|
-
},
|
|
1837
|
+
}, en = (e) => {
|
|
1838
|
+
let t = Zt(e, "mariadb");
|
|
1839
|
+
if (t !== void 0) return t;
|
|
1782
1840
|
switch (e.type) {
|
|
1783
1841
|
case "id": return "VARCHAR(64)";
|
|
1784
1842
|
case "text": return e.hasDefault && e.defaultValue !== void 0 || e.oneOf && e.oneOf.length > 0 ? "VARCHAR(255)" : "LONGTEXT";
|
|
1785
1843
|
case "integer": return "INT";
|
|
1786
1844
|
case "real": return "DOUBLE";
|
|
1787
|
-
case "decimal": return
|
|
1845
|
+
case "decimal": return Xt(e, "DECIMAL");
|
|
1788
1846
|
case "bigint": return "BIGINT";
|
|
1789
1847
|
case "boolean": return "TINYINT(1)";
|
|
1790
1848
|
case "timestamp": return "DATETIME(6)";
|
|
@@ -1792,31 +1850,38 @@ BEGIN
|
|
|
1792
1850
|
case "json": return "JSON";
|
|
1793
1851
|
case "bytes": return "LONGBLOB";
|
|
1794
1852
|
case "reference": return "VARCHAR(64)";
|
|
1795
|
-
case "vector":
|
|
1796
|
-
case "enum":
|
|
1797
|
-
case "array":
|
|
1853
|
+
case "vector":
|
|
1854
|
+
case "enum":
|
|
1855
|
+
case "array": throw Error(`snapshotMysqlType: '${e.type}' must go through parameterisedSqlType`);
|
|
1798
1856
|
case "interval": return "BIGINT";
|
|
1799
1857
|
case "raw": return e.rawDdl ?? "LONGTEXT";
|
|
1800
1858
|
}
|
|
1801
|
-
}, U = (e) => `"${e}"`, W = (e) => `\`${e.replace(/`/g, "``")}\``,
|
|
1802
|
-
let
|
|
1859
|
+
}, U = (e) => `"${e}"`, W = (e) => `\`${e.replace(/`/g, "``")}\``, tn = (e, t) => `ALTER TABLE ${t(e.table)} DROP COLUMN IF EXISTS ${t(e.column)};`, nn = (e) => `ALTER TABLE ${W(e.table)} DROP COLUMN IF EXISTS ${W(e.column)}, ALGORITHM=COPY;`, rn = (e, t) => `ALTER TABLE ${t(e.table)} RENAME COLUMN ${t(e.from)} TO ${t(e.to)};`, an = (e, t, n) => `ALTER TABLE ${n(e.table)} RENAME COLUMN ${n(e.column)} TO ${n(`${e.column}${On(t)}`)};`, on = (e, t, n) => e.hasDefault && e.defaultValue !== void 0 ? `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} SET ${sn(e, n)};` : `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} DROP DEFAULT;`, sn = (e, t) => {
|
|
1860
|
+
let n = t(e.defaultValue);
|
|
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
|
+
return n;
|
|
1863
|
+
}, G = (e, t, n) => e.find((e) => e.tableName === t)?.fields[n], cn = (e, t, n) => {
|
|
1864
|
+
let r = G(e, t, n);
|
|
1865
|
+
return r ? et(n, r) : void 0;
|
|
1866
|
+
}, ln = (e, t, n) => {
|
|
1867
|
+
let r = n ?? e.nullable, i = _e(e, "mariadb");
|
|
1803
1868
|
return [
|
|
1804
1869
|
W(t),
|
|
1805
|
-
|
|
1870
|
+
O(e, "mariadb"),
|
|
1806
1871
|
r ? null : "NOT NULL",
|
|
1807
1872
|
i
|
|
1808
1873
|
].filter(Boolean).join(" ");
|
|
1809
|
-
},
|
|
1874
|
+
}, un = (e, t) => e == null ? null : Array.isArray(e) ? dn(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" ? k(e, "mysql") : null, dn = (e, t, n) => ve(e, t ?? { type: "json" }, n), fn = (e, t) => e == null ? null : Array.isArray(e) ? dn(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" ? k(e, "postgres") : null, K = (e, t) => {
|
|
1810
1875
|
if (!e.generatedAs) return null;
|
|
1811
1876
|
let { expr: n, stored: r } = e.generatedAs;
|
|
1812
1877
|
return t === "postgres" ? `GENERATED ALWAYS AS (${n}) STORED` : t === "mssql" ? `AS (${n})${r ? " PERSISTED" : ""}` : `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
|
|
1813
|
-
},
|
|
1814
|
-
if (e.type === "id" && e.idScheme?.kind === "numeric") return
|
|
1878
|
+
}, pn = (e) => {
|
|
1879
|
+
if (e.type === "id" && e.idScheme?.kind === "numeric") return A(e.name, "postgres");
|
|
1815
1880
|
let t = K(e, "postgres");
|
|
1816
|
-
if (t) return `${U(e.name)} ${
|
|
1817
|
-
let n = [U(e.name),
|
|
1881
|
+
if (t) return `${U(e.name)} ${Qt(e)} ${t}`;
|
|
1882
|
+
let n = [U(e.name), Qt(e)];
|
|
1818
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) {
|
|
1819
|
-
let t =
|
|
1884
|
+
let t = fn(e.defaultValue, e);
|
|
1820
1885
|
t && n.push(t);
|
|
1821
1886
|
}
|
|
1822
1887
|
return e.references && (n.push(`REFERENCES ${U(e.references.table)} (${U(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${{
|
|
@@ -1825,20 +1890,20 @@ BEGIN
|
|
|
1825
1890
|
setNull: "SET NULL",
|
|
1826
1891
|
noAction: "NO ACTION"
|
|
1827
1892
|
}[e.references.onDelete]}`)), n.join(" ");
|
|
1828
|
-
}, q = (e, t) => e.primaryKey && e.primaryKey.length > 0 ? `,\n PRIMARY KEY (${e.primaryKey.map(t).join(", ")})` : "",
|
|
1829
|
-
let t = e.columns.map((e) => ` ${
|
|
1830
|
-
for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${U(t.name)} ON ${U(e.table)} (${t.columns.map(
|
|
1893
|
+
}, q = (e, t) => e.primaryKey && e.primaryKey.length > 0 ? `,\n PRIMARY KEY (${e.primaryKey.map(t).join(", ")})` : "", mn = (e) => {
|
|
1894
|
+
let t = e.columns.map((e) => ` ${pn(e)}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${U(e.table)} (\n${t}${q(e, U)}\n)`];
|
|
1895
|
+
for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${U(t.name)} ON ${U(e.table)} (${t.columns.map(Nn).join(", ")})`);
|
|
1831
1896
|
return n;
|
|
1832
|
-
},
|
|
1833
|
-
let t =
|
|
1897
|
+
}, hn = 191, J = (e) => {
|
|
1898
|
+
let t = en(e).toUpperCase();
|
|
1834
1899
|
return t.endsWith("TEXT") || t.endsWith("BLOB");
|
|
1835
|
-
},
|
|
1836
|
-
if (e.type === "id" && e.idScheme?.kind === "numeric") return
|
|
1900
|
+
}, gn = (e) => {
|
|
1901
|
+
if (e.type === "id" && e.idScheme?.kind === "numeric") return A(e.name, "mariadb");
|
|
1837
1902
|
let t = K(e, "mariadb");
|
|
1838
|
-
if (t) return `${W(e.name)} ${
|
|
1839
|
-
let n = [W(e.name),
|
|
1903
|
+
if (t) return `${W(e.name)} ${en(e)} ${t}`;
|
|
1904
|
+
let n = [W(e.name), en(e)];
|
|
1840
1905
|
if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && !J(e) && n.push("UNIQUE"), e.hasDefault) {
|
|
1841
|
-
let t =
|
|
1906
|
+
let t = un(e.defaultValue, e);
|
|
1842
1907
|
t && n.push(t);
|
|
1843
1908
|
}
|
|
1844
1909
|
return e.references && (n.push(`REFERENCES ${W(e.references.table)} (${W(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${{
|
|
@@ -1847,25 +1912,27 @@ BEGIN
|
|
|
1847
1912
|
setNull: "SET NULL",
|
|
1848
1913
|
noAction: "NO ACTION"
|
|
1849
1914
|
}[e.references.onDelete]}`)), n.join(" ");
|
|
1850
|
-
},
|
|
1915
|
+
}, _n = (e) => {
|
|
1851
1916
|
let t = new Map(e.columns.map((e) => [e.name, e])), n = (e) => {
|
|
1852
1917
|
let n = t.get(e);
|
|
1853
|
-
return n && J(n) ? `${W(e)}(${
|
|
1854
|
-
}, r = e.columns.map((e) => ` ${
|
|
1918
|
+
return n && J(n) ? `${W(e)}(${hn})` : W(e);
|
|
1919
|
+
}, r = e.columns.map((e) => ` ${gn(e)}`).join(",\n"), i = [`CREATE TABLE IF NOT EXISTS ${W(e.table)} (\n${r}${q(e, n)}\n)`];
|
|
1855
1920
|
for (let t of e.columns) t.unique && t.type !== "id" && J(t) && i.push(`CREATE UNIQUE INDEX IF NOT EXISTS ${W(`${e.table}_${t.name}_key`)} ON ${W(e.table)} (${n(t.name)})`);
|
|
1856
1921
|
for (let t of e.indexes) t.name !== `${e.table}_pkey` && i.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${W(t.name)} ON ${W(e.table)} (${t.columns.map(n).join(", ")})`);
|
|
1857
1922
|
return i;
|
|
1858
|
-
},
|
|
1923
|
+
}, vn = {
|
|
1859
1924
|
cascade: "CASCADE",
|
|
1860
1925
|
restrict: "RESTRICT",
|
|
1861
1926
|
setNull: "SET NULL",
|
|
1862
1927
|
noAction: "NO ACTION"
|
|
1863
|
-
},
|
|
1928
|
+
}, yn = {
|
|
1864
1929
|
cascade: "CASCADE",
|
|
1865
1930
|
restrict: "NO ACTION",
|
|
1866
1931
|
setNull: "SET NULL",
|
|
1867
1932
|
noAction: "NO ACTION"
|
|
1868
|
-
},
|
|
1933
|
+
}, bn = (e) => {
|
|
1934
|
+
let t = Zt(e, "sqlite");
|
|
1935
|
+
if (t !== void 0) return t;
|
|
1869
1936
|
switch (e.type) {
|
|
1870
1937
|
case "integer":
|
|
1871
1938
|
case "boolean": return "INTEGER";
|
|
@@ -1875,29 +1942,29 @@ BEGIN
|
|
|
1875
1942
|
case "bytes": return "BLOB";
|
|
1876
1943
|
default: return "TEXT";
|
|
1877
1944
|
}
|
|
1878
|
-
}, 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"
|
|
1879
|
-
if (e.type === "id" && e.idScheme?.kind === "numeric") return
|
|
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" ? k(e, "sqlite") : null, xn = (e) => {
|
|
1946
|
+
if (e.type === "id" && e.idScheme?.kind === "numeric") return A(e.name, "sqlite");
|
|
1880
1947
|
let t = K(e, "sqlite");
|
|
1881
|
-
if (t) return `${U(e.name)} ${
|
|
1882
|
-
let n = [U(e.name),
|
|
1948
|
+
if (t) return `${U(e.name)} ${bn(e)} ${t}`;
|
|
1949
|
+
let n = [U(e.name), bn(e)];
|
|
1883
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) {
|
|
1884
1951
|
let t = Y(e.defaultValue, "CURRENT_TIMESTAMP");
|
|
1885
1952
|
t && n.push(t);
|
|
1886
1953
|
}
|
|
1887
|
-
if (e.references && (n.push(`REFERENCES ${U(e.references.table)} (${U(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${
|
|
1954
|
+
if (e.references && (n.push(`REFERENCES ${U(e.references.table)} (${U(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${vn[e.references.onDelete]}`)), e.oneOf && e.oneOf.length > 0) {
|
|
1888
1955
|
let t = e.oneOf.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
|
|
1889
1956
|
n.push(`CHECK (${U(e.name)} IN (${t}))`);
|
|
1890
1957
|
}
|
|
1891
1958
|
return n.join(" ");
|
|
1892
|
-
},
|
|
1893
|
-
let t = e.columns.map((e) => ` ${
|
|
1959
|
+
}, Sn = (e) => {
|
|
1960
|
+
let t = e.columns.map((e) => ` ${xn(e)}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${U(e.table)} (\n${t}${q(e, U)}\n)`];
|
|
1894
1961
|
for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${U(t.name)} ON ${U(e.table)} (${t.columns.map(U).join(", ")})`);
|
|
1895
1962
|
return n;
|
|
1896
1963
|
}, X = (e, t) => {
|
|
1897
1964
|
let n = t.find((t) => t.tableName === e);
|
|
1898
1965
|
if (!n) return [];
|
|
1899
|
-
let r =
|
|
1900
|
-
...
|
|
1966
|
+
let r = F([n]).tables[0], i = `${e}__voltro_rebuild`, a = r.columns.map((e) => U(e.name)).join(", "), o = [
|
|
1967
|
+
...Sn({
|
|
1901
1968
|
kind: "create-table",
|
|
1902
1969
|
table: i,
|
|
1903
1970
|
columns: r.columns,
|
|
@@ -1910,23 +1977,25 @@ BEGIN
|
|
|
1910
1977
|
];
|
|
1911
1978
|
for (let t of r.indexes) t.name !== `${e}_pkey` && o.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${U(t.name)} ON ${U(e)} (${t.columns.map(U).join(", ")})`);
|
|
1912
1979
|
return o;
|
|
1913
|
-
},
|
|
1980
|
+
}, Cn = (e, t, n, r) => {
|
|
1914
1981
|
let i = r ?? e.nullable;
|
|
1915
|
-
return `ALTER TABLE ${Z(n)} ALTER COLUMN ${Z(t)} ${
|
|
1916
|
-
},
|
|
1982
|
+
return `ALTER TABLE ${Z(n)} ALTER COLUMN ${Z(t)} ${O(e, "mssql")} ${i ? "NULL" : "NOT NULL"};`;
|
|
1983
|
+
}, wn = (e) => {
|
|
1917
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 + ']');`;
|
|
1918
1985
|
if (!e.hasDefault) return t;
|
|
1919
1986
|
let n = Y(e.defaultValue, "SYSUTCDATETIME()");
|
|
1920
1987
|
if (!n) return t;
|
|
1921
1988
|
let r = n.replace(/^DEFAULT\s+/i, "");
|
|
1922
1989
|
return `${t} ALTER TABLE ${Z(e.table)} ADD DEFAULT ${r} FOR ${Z(e.column)};`;
|
|
1923
|
-
}, Z = (e) => `[${e.replace(/]/g, "]]")}]`,
|
|
1990
|
+
}, Z = (e) => `[${e.replace(/]/g, "]]")}]`, Tn = (e) => {
|
|
1991
|
+
let t = Zt(e, "mssql");
|
|
1992
|
+
if (t !== void 0) return t;
|
|
1924
1993
|
switch (e.type) {
|
|
1925
1994
|
case "id":
|
|
1926
1995
|
case "reference": return "NVARCHAR(64)";
|
|
1927
1996
|
case "integer": return "INT";
|
|
1928
1997
|
case "real": return "FLOAT";
|
|
1929
|
-
case "decimal": return
|
|
1998
|
+
case "decimal": return Xt(e, "DECIMAL");
|
|
1930
1999
|
case "bigint": return "BIGINT";
|
|
1931
2000
|
case "boolean": return "BIT";
|
|
1932
2001
|
case "timestamp": return "DATETIME2(6)";
|
|
@@ -1934,34 +2003,34 @@ BEGIN
|
|
|
1934
2003
|
case "bytes": return "VARBINARY(MAX)";
|
|
1935
2004
|
default: return "NVARCHAR(MAX)";
|
|
1936
2005
|
}
|
|
1937
|
-
},
|
|
1938
|
-
if (e.type === "id" && e.idScheme?.kind === "numeric") return
|
|
1939
|
-
let n = e.type === "text" && t?.has(e.name) ? "NVARCHAR(450)" :
|
|
2006
|
+
}, En = (e, t) => {
|
|
2007
|
+
if (e.type === "id" && e.idScheme?.kind === "numeric") return A(e.name, "mssql");
|
|
2008
|
+
let n = e.type === "text" && t?.has(e.name) ? "NVARCHAR(450)" : Tn(e), r = K(e, "mssql");
|
|
1940
2009
|
if (r) return `${Z(e.name)} ${r}`;
|
|
1941
2010
|
let i = [Z(e.name), n];
|
|
1942
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) {
|
|
1943
2012
|
let t = Y(e.defaultValue, "SYSUTCDATETIME()");
|
|
1944
2013
|
t && i.push(t);
|
|
1945
2014
|
}
|
|
1946
|
-
return e.references && (i.push(`REFERENCES ${Z(e.references.table)} (${Z(e.references.column)})`), e.references.onDelete && i.push(`ON DELETE ${
|
|
1947
|
-
},
|
|
1948
|
-
let t = (e) => e.replace(/'/g, "''"), n = new Set(e.indexes.flatMap((e) => e.columns)), r = e.columns.map((e) => ` ${
|
|
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
|
+
}, 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}${q(e, Z)}\n)`, a = [`IF OBJECT_ID(N'${t(e.table)}', N'U') IS NULL EXEC(N'${t(i)}')`];
|
|
1949
2018
|
for (let n of e.indexes) {
|
|
1950
2019
|
if (n.name === `${e.table}_pkey`) continue;
|
|
1951
2020
|
let r = `CREATE ${n.unique ? "UNIQUE " : ""}INDEX ${Z(n.name)} ON ${Z(e.table)} (${n.columns.map(Z).join(", ")})`;
|
|
1952
2021
|
a.push(`IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = N'${t(n.name)}' AND object_id = OBJECT_ID(N'${t(e.table)}')) EXEC(N'${t(r)}')`);
|
|
1953
2022
|
}
|
|
1954
2023
|
return a;
|
|
1955
|
-
},
|
|
1956
|
-
let r = `${e.table}${
|
|
2024
|
+
}, On = (e) => `__dropped_${e.replace(/[-:T.Z]/g, "").slice(0, 14)}`, kn = (e, t) => `DROP TABLE IF EXISTS ${t(e.table)};`, An = (e, t, n) => {
|
|
2025
|
+
let r = `${e.table}${On(t)}`;
|
|
1957
2026
|
return `ALTER TABLE ${n(e.table)} RENAME TO ${n(r)};`;
|
|
1958
|
-
},
|
|
2027
|
+
}, jn = (e, t, n) => {
|
|
1959
2028
|
let r = G(e, t, n);
|
|
1960
2029
|
return r ? J({ type: r.type }) : !1;
|
|
1961
|
-
},
|
|
2030
|
+
}, Mn = (e, t, n) => jn(e, t, n) ? `${W(n)}(${hn})` : W(n), Nn = (e) => e.startsWith("(") ? e : U(e), Pn = (e, t) => `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX ${t ? "CONCURRENTLY " : ""}IF NOT EXISTS ${U(e.index.name)} ON ${U(e.table)} (${e.index.columns.map(Nn).join(", ")});`, Fn = (e, t) => `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${W(e.index.name)} ON ${W(e.table)} (${e.index.columns.map((n) => Mn(t, e.table, n)).join(", ")});`, In = (e) => `DROP INDEX IF EXISTS ${U(e.index)};`, Ln = (e) => `DROP INDEX ${W(e.index)} ON ${W(e.table)};`, Rn = (e) => `DROP INDEX IF EXISTS ${Z(e.index)} ON ${Z(e.table)};`, zn = (e) => {
|
|
1962
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(", ")})`;
|
|
1963
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)}');`;
|
|
1964
|
-
},
|
|
2033
|
+
}, Bn = (e, t, n) => {
|
|
1965
2034
|
let r = n.find((t) => t.tableName === e);
|
|
1966
2035
|
if (!r) return [];
|
|
1967
2036
|
let i = [];
|
|
@@ -1970,13 +2039,13 @@ BEGIN
|
|
|
1970
2039
|
t && t.type === "text" && !t.generatedAs && i.push(`ALTER TABLE ${Z(e)} ALTER COLUMN ${Z(n)} NVARCHAR(450) ${t.nullable ? "NULL" : "NOT NULL"};`);
|
|
1971
2040
|
}
|
|
1972
2041
|
return i;
|
|
1973
|
-
},
|
|
2042
|
+
}, Vn = (e) => `ALTER TABLE ${U(e.table)} ADD CONSTRAINT ${U(`${e.table}_${e.column}_key`)} UNIQUE (${U(e.column)});`, Hn = (e, t) => `ALTER TABLE ${W(e.table)} ADD CONSTRAINT ${W(`${e.table}_${e.column}_key`)} UNIQUE (${Mn(t, e.table, e.column)});`, Un = (e) => {
|
|
1974
2043
|
let t = e.fields.map((e) => U(e)).join(", ");
|
|
1975
2044
|
return `ALTER TABLE ${U(e.table)} ADD CONSTRAINT ${U(e.name)} UNIQUE (${t});`;
|
|
1976
|
-
},
|
|
1977
|
-
let n = e.fields.map((n) =>
|
|
2045
|
+
}, Wn = (e, t) => {
|
|
2046
|
+
let n = e.fields.map((n) => Mn(t, e.table, n)).join(", ");
|
|
1978
2047
|
return `ALTER TABLE ${W(e.table)} ADD CONSTRAINT ${W(e.name)} UNIQUE (${n});`;
|
|
1979
|
-
},
|
|
2048
|
+
}, Gn = (e) => `ALTER TABLE ${U(e.table)} DROP CONSTRAINT IF EXISTS ${U(e.name)};`, Kn = (e) => `ALTER TABLE ${W(e.table)} DROP INDEX ${W(e.name)};`, qn = (e) => `ALTER TABLE ${U(e.table)} DROP CONSTRAINT IF EXISTS ${U(`${e.table}_${e.column}_key`)};`, Jn = (e) => `ALTER TABLE ${W(e.table)} DROP INDEX ${W(`${e.table}_${e.column}_key`)};`, Yn = (e, t) => {
|
|
1980
2049
|
let n = [], r = t(e.table), i = t(e.column), a = t(e.targetTable), o = t(e.targetColumn);
|
|
1981
2050
|
if (e.orphanPolicy) {
|
|
1982
2051
|
let t = `${i} IS NOT NULL AND ${i} NOT IN (SELECT ${o} FROM ${a})`;
|
|
@@ -1994,11 +2063,11 @@ BEGIN
|
|
|
1994
2063
|
setNull: "SET NULL",
|
|
1995
2064
|
noAction: "NO ACTION"
|
|
1996
2065
|
}[e.onDelete]}`), n.push(s.join(" ") + ";"), n;
|
|
1997
|
-
},
|
|
2066
|
+
}, Xn = (e) => `ALTER TABLE ${U(e.table)} DROP CONSTRAINT IF EXISTS ${U(`${e.table}_${e.column}_fkey`)};`, Zn = (e) => `ALTER TABLE ${W(e.table)} DROP FOREIGN KEY ${W(`${e.table}_${e.column}_fkey`)};`, Qn = (e, t) => {
|
|
1998
2067
|
let n = e.values.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
|
|
1999
2068
|
return `ALTER TABLE ${t(e.table)} ADD CONSTRAINT ${t(`${e.table}_${e.column}_check`)} CHECK (${t(e.column)} IN (${n}));`;
|
|
2000
|
-
},
|
|
2001
|
-
let i = e.column, a = r === "mariadb", o = a ? W : r === "mssql" ? Z : U, s = a ?
|
|
2069
|
+
}, $n = (e) => `ALTER TABLE ${U(e.table)} DROP CONSTRAINT IF EXISTS ${U(`${e.table}_${e.column}_check`)};`, er = (e) => `ALTER TABLE ${W(e.table)} DROP CHECK ${W(`${e.table}_${e.column}_check`)};`, tr = (e, t, n, r) => {
|
|
2070
|
+
let i = e.column, a = r === "mariadb", o = a ? W : r === "mssql" ? Z : U, s = a ? en(i) : r === "mssql" ? Tn(i) : r === "sqlite" ? bn(i) : Qt(i), c = r === "mssql" ? "ADD" : "ADD COLUMN", l = (e) => a ? un(e, i) : r === "mssql" ? Y(e, "SYSUTCDATETIME()") : r === "sqlite" ? Y(e, "CURRENT_TIMESTAMP") : fn(e, i), u = K(i, r);
|
|
2002
2071
|
if (u) {
|
|
2003
2072
|
let t = r === "mssql" ? `${o(i.name)} ${u}` : `${o(i.name)} ${s} ${u}`;
|
|
2004
2073
|
return {
|
|
@@ -2014,7 +2083,8 @@ BEGIN
|
|
|
2014
2083
|
};
|
|
2015
2084
|
}
|
|
2016
2085
|
if (t.classification === "needs-default") {
|
|
2017
|
-
let t = l(i.defaultValue)
|
|
2086
|
+
let t = l(i.defaultValue);
|
|
2087
|
+
if (t === null) throw Error(`migration applier: cannot render the declared default for '${e.table}.${i.name}' (${JSON.stringify(i.defaultValue)}) while adding it NOT NULL to a populated table. This is a framework bug — report the column type + default.`);
|
|
2018
2088
|
return {
|
|
2019
2089
|
pre: [`ALTER TABLE ${o(e.table)} ${c} ${o(i.name)} ${s} NOT NULL ${t};`],
|
|
2020
2090
|
post: []
|
|
@@ -2025,7 +2095,7 @@ BEGIN
|
|
|
2025
2095
|
post: f ? [f] : []
|
|
2026
2096
|
};
|
|
2027
2097
|
return d?.sql && (p.backfillKind = "sql", p.backfillSql = d.sql), d?.js && (p.backfillKind = "js", p.backfillJs = d.js), d?.batchSize !== void 0 && (p.batchSize = d.batchSize), d?.sleepMs !== void 0 && (p.sleepMs = d.sleepMs), p;
|
|
2028
|
-
},
|
|
2098
|
+
}, nr = (e) => {
|
|
2029
2099
|
let t = new Map(e.map((e) => [e.tableName, e]));
|
|
2030
2100
|
return (e, n) => {
|
|
2031
2101
|
let r = t.get(e);
|
|
@@ -2047,21 +2117,21 @@ BEGIN
|
|
|
2047
2117
|
};
|
|
2048
2118
|
}, Q = (e, t, n) => e.unsafe(t).pipe(d.tapError((e) => d.sync(() => {
|
|
2049
2119
|
process.stderr.write(_(`applier: statement failed (op=${n})`, t, e, 400));
|
|
2050
|
-
})), d.map(() => void 0)), $ = (e, t, n) => d.forEach(t, (t) => Q(e, t, n), { discard: !0 }),
|
|
2051
|
-
let r = process.hrtime.bigint(), i =
|
|
2120
|
+
})), 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
|
+
let r = process.hrtime.bigint(), i = nr(n.declared), a = t.op;
|
|
2052
2122
|
switch (a.kind) {
|
|
2053
2123
|
case "create-table": {
|
|
2054
2124
|
let t = yield* e.onDialectOrElse({
|
|
2055
|
-
mysql: () => d.succeed(
|
|
2056
|
-
mssql: () => d.succeed(
|
|
2057
|
-
sqlite: () => d.succeed(
|
|
2058
|
-
orElse: () => d.succeed(
|
|
2125
|
+
mysql: () => d.succeed(_n(a)),
|
|
2126
|
+
mssql: () => d.succeed(Dn(a)),
|
|
2127
|
+
sqlite: () => d.succeed(Sn(a)),
|
|
2128
|
+
orElse: () => d.succeed(mn(a))
|
|
2059
2129
|
});
|
|
2060
2130
|
for (let n of t) yield* Q(e, n, a.kind);
|
|
2061
2131
|
break;
|
|
2062
2132
|
}
|
|
2063
2133
|
case "drop-table": {
|
|
2064
|
-
let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString(), r = (e) => t ?
|
|
2134
|
+
let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString(), r = (e) => t ? An(a, n, e) : kn(a, e);
|
|
2065
2135
|
yield* e.onDialectOrElse({
|
|
2066
2136
|
mysql: () => Q(e, r(W), a.kind),
|
|
2067
2137
|
orElse: () => Q(e, r(U), a.kind)
|
|
@@ -2071,71 +2141,71 @@ BEGIN
|
|
|
2071
2141
|
case "drop-column": {
|
|
2072
2142
|
let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString();
|
|
2073
2143
|
yield* e.onDialectOrElse({
|
|
2074
|
-
mysql: () => Q(e, t ?
|
|
2075
|
-
orElse: () => Q(e, t ?
|
|
2144
|
+
mysql: () => Q(e, t ? an(a, n, W) : nn(a), a.kind),
|
|
2145
|
+
orElse: () => Q(e, t ? an(a, n, U) : tn(a, U), a.kind)
|
|
2076
2146
|
});
|
|
2077
2147
|
break;
|
|
2078
2148
|
}
|
|
2079
2149
|
case "rename-column":
|
|
2080
2150
|
yield* e.onDialectOrElse({
|
|
2081
|
-
mysql: () => Q(e,
|
|
2151
|
+
mysql: () => Q(e, rn(a, W), a.kind),
|
|
2082
2152
|
mssql: () => Q(e, `EXEC sp_rename N'${a.table.replace(/'/g, "''")}.${a.from.replace(/'/g, "''")}', N'${a.to.replace(/'/g, "''")}', 'COLUMN';`, a.kind),
|
|
2083
|
-
orElse: () => Q(e,
|
|
2153
|
+
orElse: () => Q(e, rn(a, U), a.kind)
|
|
2084
2154
|
});
|
|
2085
2155
|
break;
|
|
2086
2156
|
case "add-index":
|
|
2087
2157
|
yield* e.onDialectOrElse({
|
|
2088
|
-
mysql: () => Q(e,
|
|
2089
|
-
mssql: () => $(e, [...
|
|
2090
|
-
orElse: () => Q(e,
|
|
2158
|
+
mysql: () => Q(e, Fn(a, n.declared), a.kind),
|
|
2159
|
+
mssql: () => $(e, [...Bn(a.table, a.index.columns, n.declared), zn(a)], a.kind),
|
|
2160
|
+
orElse: () => Q(e, Pn(a, t.classification === "online-required"), a.kind)
|
|
2091
2161
|
});
|
|
2092
2162
|
break;
|
|
2093
2163
|
case "drop-index":
|
|
2094
2164
|
yield* e.onDialectOrElse({
|
|
2095
|
-
mysql: () => Q(e,
|
|
2096
|
-
mssql: () => Q(e,
|
|
2097
|
-
orElse: () => Q(e,
|
|
2165
|
+
mysql: () => Q(e, Ln(a), a.kind),
|
|
2166
|
+
mssql: () => Q(e, Rn(a), a.kind),
|
|
2167
|
+
orElse: () => Q(e, In(a), a.kind)
|
|
2098
2168
|
});
|
|
2099
2169
|
break;
|
|
2100
2170
|
case "add-unique":
|
|
2101
2171
|
yield* e.onDialectOrElse({
|
|
2102
|
-
mysql: () => Q(e,
|
|
2172
|
+
mysql: () => Q(e, Hn(a, n.declared), a.kind),
|
|
2103
2173
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2104
|
-
mssql: () => $(e, [...
|
|
2105
|
-
orElse: () => Q(e,
|
|
2174
|
+
mssql: () => $(e, [...Bn(a.table, [a.column], n.declared), Vn(a)], a.kind),
|
|
2175
|
+
orElse: () => Q(e, Vn(a), a.kind)
|
|
2106
2176
|
});
|
|
2107
2177
|
break;
|
|
2108
2178
|
case "drop-unique":
|
|
2109
2179
|
yield* e.onDialectOrElse({
|
|
2110
|
-
mysql: () => Q(e,
|
|
2180
|
+
mysql: () => Q(e, Jn(a), a.kind),
|
|
2111
2181
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2112
|
-
orElse: () => Q(e,
|
|
2182
|
+
orElse: () => Q(e, qn(a), a.kind)
|
|
2113
2183
|
});
|
|
2114
2184
|
break;
|
|
2115
2185
|
case "add-unique-composite":
|
|
2116
2186
|
yield* e.onDialectOrElse({
|
|
2117
|
-
mysql: () => Q(e,
|
|
2187
|
+
mysql: () => Q(e, Wn(a, n.declared), a.kind),
|
|
2118
2188
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2119
|
-
mssql: () => $(e, [...
|
|
2120
|
-
orElse: () => Q(e,
|
|
2189
|
+
mssql: () => $(e, [...Bn(a.table, a.fields, n.declared), Un(a)], a.kind),
|
|
2190
|
+
orElse: () => Q(e, Un(a), a.kind)
|
|
2121
2191
|
});
|
|
2122
2192
|
break;
|
|
2123
2193
|
case "drop-unique-composite":
|
|
2124
2194
|
yield* e.onDialectOrElse({
|
|
2125
|
-
mysql: () => Q(e,
|
|
2195
|
+
mysql: () => Q(e, Kn(a), a.kind),
|
|
2126
2196
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2127
|
-
orElse: () => Q(e,
|
|
2197
|
+
orElse: () => Q(e, Gn(a), a.kind)
|
|
2128
2198
|
});
|
|
2129
2199
|
break;
|
|
2130
2200
|
case "add-foreign-key":
|
|
2131
2201
|
yield* e.onDialectOrElse({
|
|
2132
|
-
mysql: () => $(e,
|
|
2202
|
+
mysql: () => $(e, Yn(a, W), a.kind),
|
|
2133
2203
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2134
|
-
orElse: () => $(e,
|
|
2204
|
+
orElse: () => $(e, Yn(a, U), a.kind)
|
|
2135
2205
|
});
|
|
2136
2206
|
break;
|
|
2137
2207
|
case "add-column": {
|
|
2138
|
-
let n =
|
|
2208
|
+
let n = tr(a, t, i, yield* e.onDialectOrElse({
|
|
2139
2209
|
mysql: () => d.succeed("mariadb"),
|
|
2140
2210
|
mssql: () => d.succeed("mssql"),
|
|
2141
2211
|
sqlite: () => d.succeed("sqlite"),
|
|
@@ -2181,35 +2251,37 @@ BEGIN
|
|
|
2181
2251
|
yield* e.onDialectOrElse({
|
|
2182
2252
|
mysql: () => {
|
|
2183
2253
|
let t = G(n.declared, a.table, a.column);
|
|
2184
|
-
return t ? Q(e, `ALTER TABLE ${W(a.table)} MODIFY COLUMN ${
|
|
2254
|
+
return t ? Q(e, `ALTER TABLE ${W(a.table)} MODIFY COLUMN ${ln(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.`));
|
|
2185
2255
|
},
|
|
2186
2256
|
mssql: () => {
|
|
2187
2257
|
let t = G(n.declared, a.table, a.column);
|
|
2188
|
-
return t ? Q(e,
|
|
2258
|
+
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}'.`));
|
|
2189
2259
|
},
|
|
2190
2260
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2191
2261
|
orElse: () => Q(e, `ALTER TABLE ${U(a.table)} ALTER COLUMN ${U(a.column)} ${a.toNullable ? "DROP NOT NULL" : "SET NOT NULL"};`, a.kind)
|
|
2192
2262
|
});
|
|
2193
2263
|
break;
|
|
2194
|
-
case "alter-column-default":
|
|
2264
|
+
case "alter-column-default": {
|
|
2265
|
+
let t = cn(n.declared, a.table, a.column);
|
|
2195
2266
|
yield* e.onDialectOrElse({
|
|
2196
|
-
mysql: () => Q(e,
|
|
2197
|
-
mssql: () => Q(e,
|
|
2267
|
+
mysql: () => Q(e, on(a, W, (e) => un(e, t)), a.kind),
|
|
2268
|
+
mssql: () => Q(e, wn(a), a.kind),
|
|
2198
2269
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2199
|
-
orElse: () => Q(e,
|
|
2270
|
+
orElse: () => Q(e, on(a, U, (e) => fn(e, t)), a.kind)
|
|
2200
2271
|
});
|
|
2201
2272
|
break;
|
|
2273
|
+
}
|
|
2202
2274
|
case "alter-column-type": {
|
|
2203
|
-
let r =
|
|
2275
|
+
let r = Qt(cn(n.declared, a.table, a.column) ?? { type: a.to }), i = a.using ? ` USING ${a.using}` : "";
|
|
2204
2276
|
if (t.classification !== "online-required") {
|
|
2205
2277
|
yield* e.onDialectOrElse({
|
|
2206
2278
|
mysql: () => {
|
|
2207
2279
|
let t = G(n.declared, a.table, a.column);
|
|
2208
|
-
return t ? Q(e, `ALTER TABLE ${W(a.table)} MODIFY COLUMN ${
|
|
2280
|
+
return t ? Q(e, `ALTER TABLE ${W(a.table)} MODIFY COLUMN ${ln(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.`));
|
|
2209
2281
|
},
|
|
2210
2282
|
mssql: () => {
|
|
2211
2283
|
let t = G(n.declared, a.table, a.column);
|
|
2212
|
-
return t ? Q(e,
|
|
2284
|
+
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}'.`));
|
|
2213
2285
|
},
|
|
2214
2286
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2215
2287
|
orElse: () => Q(e, `ALTER TABLE ${U(a.table)} ALTER COLUMN ${U(a.column)} TYPE ${r}${i};`, a.kind)
|
|
@@ -2233,23 +2305,23 @@ BEGIN
|
|
|
2233
2305
|
}
|
|
2234
2306
|
case "drop-foreign-key":
|
|
2235
2307
|
yield* e.onDialectOrElse({
|
|
2236
|
-
mysql: () => Q(e,
|
|
2308
|
+
mysql: () => Q(e, Zn(a), a.kind),
|
|
2237
2309
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2238
|
-
orElse: () => Q(e,
|
|
2310
|
+
orElse: () => Q(e, Xn(a), a.kind)
|
|
2239
2311
|
});
|
|
2240
2312
|
break;
|
|
2241
2313
|
case "add-check":
|
|
2242
2314
|
yield* e.onDialectOrElse({
|
|
2243
|
-
mysql: () => Q(e,
|
|
2315
|
+
mysql: () => Q(e, Qn(a, W), a.kind),
|
|
2244
2316
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2245
|
-
orElse: () => Q(e,
|
|
2317
|
+
orElse: () => Q(e, Qn(a, U), a.kind)
|
|
2246
2318
|
});
|
|
2247
2319
|
break;
|
|
2248
2320
|
case "drop-check":
|
|
2249
2321
|
yield* e.onDialectOrElse({
|
|
2250
|
-
mysql: () => Q(e,
|
|
2322
|
+
mysql: () => Q(e, er(a), a.kind),
|
|
2251
2323
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2252
|
-
orElse: () => Q(e,
|
|
2324
|
+
orElse: () => Q(e, $n(a), a.kind)
|
|
2253
2325
|
});
|
|
2254
2326
|
break;
|
|
2255
2327
|
}
|
|
@@ -2258,10 +2330,10 @@ BEGIN
|
|
|
2258
2330
|
status: "applied",
|
|
2259
2331
|
durationMs: Number((process.hrtime.bigint() - r) / 1000000n)
|
|
2260
2332
|
};
|
|
2261
|
-
}),
|
|
2333
|
+
}), ir = (e, t, n) => d.gen(function* () {
|
|
2262
2334
|
let r = t.operations.filter((e) => e.blocked);
|
|
2263
2335
|
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.`));
|
|
2264
|
-
yield*
|
|
2336
|
+
yield* T(e);
|
|
2265
2337
|
let i = Date.now(), a = [];
|
|
2266
2338
|
try {
|
|
2267
2339
|
let r = yield* e.onDialectOrElse({
|
|
@@ -2271,15 +2343,20 @@ BEGIN
|
|
|
2271
2343
|
}), i = r ? t.operations.filter((e) => e.classification !== "online-required") : [], o = r ? t.operations.filter((e) => e.classification === "online-required") : t.operations;
|
|
2272
2344
|
i.length > 0 && (yield* e.withTransaction(d.gen(function* () {
|
|
2273
2345
|
let e = yield* p.SqlClient;
|
|
2274
|
-
for (let t of i) a.push(yield*
|
|
2346
|
+
for (let t of i) a.push(yield* rr(e, t, n));
|
|
2275
2347
|
})));
|
|
2276
|
-
for (let t of o) a.push(yield*
|
|
2348
|
+
for (let t of o) a.push(yield* rr(e, t, n));
|
|
2277
2349
|
} finally {
|
|
2278
|
-
yield*
|
|
2350
|
+
yield* E(e).pipe(d.orDie);
|
|
2351
|
+
}
|
|
2352
|
+
let o = yield* n.replan(e);
|
|
2353
|
+
if (o.operations.length > 0) {
|
|
2354
|
+
let e = o.operations.slice(0, 10).map((e) => ` - ${e.op.kind} ${"table" in e.op ? e.op.table : ""}${"column" in e.op ? `.${String(e.op.column)}` : ""}`).join("\n");
|
|
2355
|
+
return yield* d.die(/* @__PURE__ */ Error(`applyPlan: the migration did not converge. ${t.operations.length} operation(s) were executed without error, but re-planning against the live schema still finds ${o.operations.length}:\n${e}${o.operations.length > 10 ? `\n … and ${o.operations.length - 10} more` : ""}\nNo fingerprint was recorded — recording one would make the next boot report "schema up to date" for a schema that was never applied. This is a framework bug: the DDL for these operations is a no-op. Report the operation kinds above with the column types involved.`));
|
|
2279
2356
|
}
|
|
2280
|
-
let
|
|
2281
|
-
mysql: () => d.succeed(
|
|
2282
|
-
orElse: () => d.succeed(
|
|
2357
|
+
let s = a.filter((e) => e.status === "applied").length, c = Date.now() - i, l = `plan_${Date.now().toString(36)}`, u = (/* @__PURE__ */ new Date()).toISOString(), f = yield* e.onDialectOrElse({
|
|
2358
|
+
mysql: () => d.succeed(u.replace("T", " ").replace("Z", "")),
|
|
2359
|
+
orElse: () => d.succeed(u)
|
|
2283
2360
|
});
|
|
2284
2361
|
return yield* e`
|
|
2285
2362
|
INSERT INTO ${e("_voltro_migration_plans")}
|
|
@@ -2287,33 +2364,34 @@ BEGIN
|
|
|
2287
2364
|
${e("appliedBy")}, ${e("environment")}, ${e("source")},
|
|
2288
2365
|
${e("durationMs")}, ${e("appliedAt")}, ${e("notes")})
|
|
2289
2366
|
VALUES
|
|
2290
|
-
(${
|
|
2367
|
+
(${l}, ${t.toFingerprint}, ${JSON.stringify(t.operations)},
|
|
2291
2368
|
${n.appliedBy}, ${n.environment}, ${n.source},
|
|
2292
|
-
${
|
|
2369
|
+
${c}, ${f}, ${n.notes ?? null})
|
|
2293
2370
|
`, {
|
|
2294
|
-
id:
|
|
2295
|
-
appliedAt:
|
|
2371
|
+
id: l,
|
|
2372
|
+
appliedAt: u,
|
|
2296
2373
|
fingerprint: t.toFingerprint,
|
|
2297
2374
|
operations: t.operations,
|
|
2298
2375
|
appliedBy: n.appliedBy,
|
|
2299
2376
|
environment: n.environment,
|
|
2300
|
-
durationMs:
|
|
2377
|
+
durationMs: c,
|
|
2378
|
+
appliedOps: s,
|
|
2301
2379
|
source: n.source,
|
|
2302
2380
|
...n.notes ? { notes: n.notes } : {}
|
|
2303
2381
|
};
|
|
2304
|
-
}),
|
|
2382
|
+
}), ar = (e) => e.operations.filter((e) => e.blocked).map((e) => ` - ${e.op.kind} ${"table" in e.op ? `[${e.op.table}]` : ""}: ${e.reason ?? "<no reason>"}\n fix: ${e.blocked?.fix ?? "<no fix>"}`).join("\n"), or = (e) => e`
|
|
2305
2383
|
SELECT fingerprint
|
|
2306
2384
|
FROM _voltro_migration_plans
|
|
2307
2385
|
ORDER BY ${e("appliedAt")} DESC
|
|
2308
2386
|
LIMIT 1
|
|
2309
|
-
`.pipe(d.map((e) => e.length > 0 ? e[0].fingerprint : void 0), d.catchAll(() => d.succeed(void 0))),
|
|
2387
|
+
`.pipe(d.map((e) => e.length > 0 ? e[0].fingerprint : void 0), d.catchAll(() => d.succeed(void 0))), sr = (e) => e.onDialectOrElse({
|
|
2310
2388
|
pg: () => "postgres",
|
|
2311
2389
|
mysql: () => "mysql",
|
|
2312
2390
|
mssql: () => "mssql",
|
|
2313
2391
|
sqlite: () => "sqlite",
|
|
2314
2392
|
orElse: () => "sqlite"
|
|
2315
|
-
}),
|
|
2316
|
-
let n =
|
|
2393
|
+
}), cr = (e, t) => d.gen(function* () {
|
|
2394
|
+
let n = N(F(t, sr(e))), r = yield* or(e);
|
|
2317
2395
|
return r === n ? {
|
|
2318
2396
|
kind: "up-to-date",
|
|
2319
2397
|
fingerprint: n
|
|
@@ -2322,48 +2400,51 @@ BEGIN
|
|
|
2322
2400
|
expected: n,
|
|
2323
2401
|
...r === void 0 ? {} : { actual: r }
|
|
2324
2402
|
};
|
|
2325
|
-
}),
|
|
2403
|
+
}), lr = [
|
|
2326
2404
|
"pgeagertest_",
|
|
2327
2405
|
"mig_e2e_",
|
|
2328
2406
|
"mig_test_",
|
|
2329
2407
|
"mysqleagertest_",
|
|
2330
2408
|
"mssqleagertest_",
|
|
2331
2409
|
"sqliteeagertest_"
|
|
2332
|
-
],
|
|
2410
|
+
], ur = (e) => lr.some((t) => e.startsWith(t)), dr = (e, t) => d.gen(function* () {
|
|
2333
2411
|
if (process.env.VOLTRO_TEST_FIXTURE_GC === "off") return [];
|
|
2334
|
-
let n = t.filter((e) =>
|
|
2412
|
+
let n = t.filter((e) => ur(e.name)).map((e) => e.name);
|
|
2335
2413
|
if (n.length === 0) return [];
|
|
2336
2414
|
for (let t of n) yield* e.unsafe(`DROP TABLE IF EXISTS "${t}" CASCADE`).pipe(d.catchAll(() => d.void));
|
|
2337
2415
|
return n;
|
|
2338
|
-
}),
|
|
2416
|
+
}), fr = () => {
|
|
2339
2417
|
let e = (process.env.VOLTRO_DB_IGNORE_TABLES ?? "").split(",").map((e) => e.trim()).filter((e) => e.length > 0);
|
|
2340
2418
|
return e.length > 0 ? { ignoreTables: e } : {};
|
|
2341
|
-
},
|
|
2419
|
+
}, pr = (e) => ({
|
|
2342
2420
|
...e,
|
|
2343
2421
|
operations: e.operations.map((e) => {
|
|
2344
2422
|
if (!e.blocked || e.classification !== "lossy") return e;
|
|
2345
2423
|
let { blocked: t, ...n } = e;
|
|
2346
2424
|
return n;
|
|
2347
2425
|
})
|
|
2348
|
-
}),
|
|
2349
|
-
let
|
|
2426
|
+
}), mr = (e, t, n) => t === "postgres" ? at(e, n).pipe(d.flatMap((e) => {
|
|
2427
|
+
let t = ot(e);
|
|
2428
|
+
return t === void 0 ? d.void : d.logWarning(`auto-migrate: ${t}`).pipe(d.annotateLogs({ scope: "voltro:migrate" }));
|
|
2429
|
+
}), d.catchAll(() => d.void)) : d.void, hr = (e, t, n) => d.gen(function* () {
|
|
2430
|
+
let r = sr(e), i = t.filter((e) => !I(e.tableName));
|
|
2350
2431
|
if (process.env.VOLTRO_MIGRATE_FORCE !== "1") {
|
|
2351
|
-
let t =
|
|
2352
|
-
if ((yield*
|
|
2432
|
+
let t = N(F(i, r));
|
|
2433
|
+
if ((yield* or(e)) === t) return yield* mr(e, r, i), {
|
|
2353
2434
|
kind: "up-to-date",
|
|
2354
2435
|
fingerprint: t
|
|
2355
2436
|
};
|
|
2356
2437
|
}
|
|
2357
|
-
let a = yield*
|
|
2438
|
+
let a = yield* Yt(e), o = yield* dr(e, a.tables);
|
|
2358
2439
|
o.length > 0 && (yield* d.logInfo(`auto-migrate: reaped ${o.length} test-fixture leftover(s)`).pipe(d.annotateLogs({
|
|
2359
2440
|
scope: "voltro:migrate",
|
|
2360
2441
|
count: o.length
|
|
2361
|
-
})), a = yield*
|
|
2362
|
-
let s =
|
|
2442
|
+
})), a = yield* Yt(e));
|
|
2443
|
+
let s = Mt({
|
|
2363
2444
|
declared: i,
|
|
2364
|
-
live: { tables: a.tables.filter((e) => !
|
|
2445
|
+
live: { tables: a.tables.filter((e) => !I(e.name)) },
|
|
2365
2446
|
dialect: r,
|
|
2366
|
-
...
|
|
2447
|
+
...fr()
|
|
2367
2448
|
});
|
|
2368
2449
|
if (s.summary.blocked > 0) {
|
|
2369
2450
|
let e = s.operations.filter((e) => e.blocked).every((e) => e.classification === "lossy");
|
|
@@ -2371,39 +2452,48 @@ BEGIN
|
|
|
2371
2452
|
kind: "refused-blocked",
|
|
2372
2453
|
plan: s
|
|
2373
2454
|
};
|
|
2374
|
-
s =
|
|
2455
|
+
s = pr(s);
|
|
2375
2456
|
}
|
|
2376
2457
|
return s.operations.length === 0 ? {
|
|
2377
2458
|
kind: "up-to-date",
|
|
2378
2459
|
fingerprint: s.toFingerprint
|
|
2379
2460
|
} : {
|
|
2380
2461
|
kind: "applied",
|
|
2381
|
-
applied: yield*
|
|
2462
|
+
applied: yield* ir(e, s, {
|
|
2382
2463
|
declared: t,
|
|
2383
2464
|
appliedBy: n.appliedBy,
|
|
2384
2465
|
environment: n.environment === "prod" ? "dev" : n.environment,
|
|
2385
|
-
source: "auto-diff"
|
|
2466
|
+
source: "auto-diff",
|
|
2467
|
+
replan: (e) => d.gen(function* () {
|
|
2468
|
+
let t = yield* Yt(e);
|
|
2469
|
+
return Mt({
|
|
2470
|
+
declared: i,
|
|
2471
|
+
live: { tables: t.tables.filter((e) => !I(e.name)) },
|
|
2472
|
+
dialect: r,
|
|
2473
|
+
...fr()
|
|
2474
|
+
});
|
|
2475
|
+
})
|
|
2386
2476
|
}),
|
|
2387
2477
|
plan: s
|
|
2388
2478
|
};
|
|
2389
|
-
}),
|
|
2479
|
+
}), gr = (e, t, n) => process.env.VOLTRO_AUTO_MIGRATE === "0" ? d.succeed({
|
|
2390
2480
|
kind: "skipped",
|
|
2391
2481
|
reason: "VOLTRO_AUTO_MIGRATE=0"
|
|
2392
|
-
}) : n.environment === "prod" ?
|
|
2482
|
+
}) : n.environment === "prod" ? cr(e, t) : hr(e, t, n), _r = (e, t) => {
|
|
2393
2483
|
switch (e.kind) {
|
|
2394
2484
|
case "skipped": return `auto-migrate: skipped (${e.reason})`;
|
|
2395
|
-
case "up-to-date": return `auto-migrate: schema up to date (${t}, fingerprint=${
|
|
2485
|
+
case "up-to-date": return `auto-migrate: schema up to date (${t}, fingerprint=${P(e.fingerprint)})`;
|
|
2396
2486
|
case "applied": {
|
|
2397
2487
|
let t = e.plan.summary;
|
|
2398
|
-
return `auto-migrate: applied ${e.
|
|
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=${P(e.applied.fingerprint)}`;
|
|
2399
2489
|
}
|
|
2400
|
-
case "prod-mismatch": return `auto-migrate: SCHEMA FINGERPRINT MISMATCH — declared=${
|
|
2490
|
+
case "prod-mismatch": return `auto-migrate: SCHEMA FINGERPRINT MISMATCH — declared=${P(e.expected)}` + (e.actual ? ` live=${P(e.actual)}` : " live=<no _voltro_migration_plans row>") + ". Run `voltro db apply --plan plan.json` from the deploy pipeline before serving.";
|
|
2401
2491
|
case "refused-blocked": {
|
|
2402
|
-
let t = e.plan.operations.filter((e) => e.blocked), n = t.filter((e) => e.op.kind === "drop-table").length, r = t.filter((e) => e.op.kind === "add-column").length, i = t.filter((e) => e.op.kind === "drop-column").length, a = t.filter((e) => e.classification === "needs-rename-annotation").length, o = `auto-migrate: REFUSED — ${e.plan.summary.blocked} blocked operation(s):\n` +
|
|
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, i = t.filter((e) => e.op.kind === "drop-column").length, a = t.filter((e) => e.classification === "needs-rename-annotation").length, o = `auto-migrate: REFUSED — ${e.plan.summary.blocked} blocked operation(s):\n` + ar(e.plan), s = [""];
|
|
2403
2493
|
return n > 0 && s.push(`${n} table(s) exist in the live DB but aren't in your declared schema.`, "This is usually one of three things:", " (a) You're iterating on the schema — the table file got renamed, moved, or temporarily commented out.", " → Restore the declaration. Your data stays intact.", " (b) You want to KEEP the table but NOT manage it with Voltro (a leftover from another tool —", " a Strapi/Rails/legacy migration artifact, or an externally-owned table).", ` → Set \`VOLTRO_DB_IGNORE_TABLES=${t.filter((e) => e.op.kind === "drop-table").map((e) => "table" in e.op ? e.op.table : "").filter(Boolean).join(",")}\` (comma-separated).`, " The planner excludes those tables from the diff entirely — it never drops them, and they", " stop blocking your OTHER (additive) changes. This is the fix when a leftover freezes your schema.", " (c) You actually want to drop the table.", " → Add it to your declared set + chain `.dropped()` on it, OR", " write a file-based migration in `migrations/` that DROPs it, OR", " set `VOLTRO_DESTRUCTIVE_OK=1` for ONE `voltro dev` run (acknowledges data loss).", " Soft-drop: set `VOLTRO_SOFT_DROP=1` alongside DESTRUCTIVE_OK to RENAME instead of DROP", " (data survives as `<name>__dropped_<ts>` for ~7d; restorable via `voltro db restore-snapshot`)."), r > 0 && s.push(`${r} required column(s) need a backfill strategy before adding to a populated table.`, " → Annotate the column: `.backfill(sql`<expr>`)` or `.backfill(row => <fn>)` or `.default(<value>)`.", " Existing rows get the backfill value; the column then lands as NOT NULL."), i > 0 && s.push(`${i} column(s) are missing from your declared schema.`, " → If intentional: chain `.dropped()` on the column slot in the table declaration.", " → If a typo: restore the field. Data survives until you drop it."), a > 0 && s.push(`${a} column(s) look like renames (one column gone + a new one of same shape appeared).`, " → On the NEW column add `.renamedFrom('<oldName>')` so the planner emits RENAME instead of DROP+ADD."), s.push("", "See `voltro db plan` for the full machine-readable diff."), o + "\n" + s.join("\n");
|
|
2404
2494
|
}
|
|
2405
2495
|
}
|
|
2406
|
-
},
|
|
2496
|
+
}, vr = /* @__PURE__ */ new Set([
|
|
2407
2497
|
"node_modules",
|
|
2408
2498
|
"dist",
|
|
2409
2499
|
"build",
|
|
@@ -2412,11 +2502,11 @@ BEGIN
|
|
|
2412
2502
|
".next",
|
|
2413
2503
|
".git",
|
|
2414
2504
|
".framework"
|
|
2415
|
-
]),
|
|
2505
|
+
]), yr = async (e) => {
|
|
2416
2506
|
let t = [], n = async (e) => {
|
|
2417
2507
|
let r = await h.readdir(e, { withFileTypes: !0 }).catch(() => []);
|
|
2418
2508
|
for (let i of r) {
|
|
2419
|
-
if (
|
|
2509
|
+
if (vr.has(i.name)) continue;
|
|
2420
2510
|
let r = g(e, i.name);
|
|
2421
2511
|
i.isDirectory() ? await n(r) : i.isFile() && l.test(i.name) && t.push(r);
|
|
2422
2512
|
}
|
|
@@ -2425,7 +2515,7 @@ BEGIN
|
|
|
2425
2515
|
let n = e.split("/").pop() ?? e, r = t.split("/").pop() ?? t;
|
|
2426
2516
|
return n.localeCompare(r);
|
|
2427
2517
|
});
|
|
2428
|
-
},
|
|
2518
|
+
}, br = async (e) => {
|
|
2429
2519
|
let t = [];
|
|
2430
2520
|
for (let n of e) {
|
|
2431
2521
|
let e = (await import(ee(n).href)).default;
|
|
@@ -2439,11 +2529,11 @@ BEGIN
|
|
|
2439
2529
|
});
|
|
2440
2530
|
}
|
|
2441
2531
|
return t;
|
|
2442
|
-
},
|
|
2532
|
+
}, xr = (e) => e`
|
|
2443
2533
|
SELECT ${e("id")}
|
|
2444
2534
|
FROM ${e("_voltro_migration_plans")}
|
|
2445
2535
|
WHERE ${e("source")} = 'file'
|
|
2446
|
-
`.pipe(d.map((e) => e.map((e) => e.id)), d.catchAll(() => d.succeed([]))),
|
|
2536
|
+
`.pipe(d.map((e) => e.map((e) => e.id)), d.catchAll(() => d.succeed([]))), Sr = (e, t, n, r) => d.gen(function* () {
|
|
2447
2537
|
let i = Date.now(), a = (/* @__PURE__ */ new Date()).toISOString(), o = {
|
|
2448
2538
|
sql: e,
|
|
2449
2539
|
log: {
|
|
@@ -2476,70 +2566,76 @@ BEGIN
|
|
|
2476
2566
|
${r}, ${n}, ${"file"},
|
|
2477
2567
|
${c}, ${a}, ${t.migration.description})
|
|
2478
2568
|
`, { durationMs: c };
|
|
2479
|
-
}),
|
|
2569
|
+
}), Cr = (e, t) => d.gen(function* () {
|
|
2480
2570
|
let n = yield* d.tryPromise({
|
|
2481
|
-
try: () =>
|
|
2571
|
+
try: () => yr(g(t, "migrations")),
|
|
2482
2572
|
catch: (e) => e
|
|
2483
2573
|
});
|
|
2484
2574
|
if (n.length === 0) return {
|
|
2485
|
-
|
|
2575
|
+
pending: [],
|
|
2486
2576
|
skipped: []
|
|
2487
2577
|
};
|
|
2488
2578
|
let r = yield* d.tryPromise({
|
|
2489
|
-
try: () =>
|
|
2579
|
+
try: () => br(n),
|
|
2490
2580
|
catch: (e) => e
|
|
2491
2581
|
});
|
|
2492
2582
|
if (r.length === 0) return {
|
|
2493
|
-
|
|
2583
|
+
pending: [],
|
|
2494
2584
|
skipped: []
|
|
2495
2585
|
};
|
|
2496
|
-
let i = new Set(yield*
|
|
2497
|
-
|
|
2586
|
+
let i = new Set(yield* xr(e));
|
|
2587
|
+
return {
|
|
2588
|
+
pending: r.filter((e) => !i.has(e.migration.id)),
|
|
2589
|
+
skipped: r.filter((e) => i.has(e.migration.id)).map((e) => e.migration.id)
|
|
2590
|
+
};
|
|
2591
|
+
}), wr = (e, t) => Cr(e, t).pipe(d.map((e) => e.pending.map((e) => e.migration.id))), Tr = (e, t) => d.gen(function* () {
|
|
2592
|
+
let { pending: n, skipped: r } = yield* Cr(e, t.projectRoot);
|
|
2593
|
+
if (n.length === 0) return {
|
|
2498
2594
|
applied: [],
|
|
2499
|
-
skipped:
|
|
2595
|
+
skipped: r
|
|
2500
2596
|
};
|
|
2501
|
-
yield*
|
|
2502
|
-
let
|
|
2597
|
+
yield* T(e);
|
|
2598
|
+
let i = [];
|
|
2503
2599
|
try {
|
|
2504
|
-
for (let
|
|
2600
|
+
for (let r of n) {
|
|
2505
2601
|
yield* d.logInfo("file-based migration applying").pipe(d.annotateLogs({
|
|
2506
2602
|
scope: "voltro:migrate",
|
|
2507
|
-
id:
|
|
2508
|
-
file:
|
|
2603
|
+
id: r.migration.id,
|
|
2604
|
+
file: r.file
|
|
2509
2605
|
}));
|
|
2510
|
-
let { durationMs:
|
|
2511
|
-
|
|
2512
|
-
id:
|
|
2513
|
-
durationMs:
|
|
2606
|
+
let { durationMs: n } = yield* Sr(e, r, t.env, t.appliedBy);
|
|
2607
|
+
i.push({
|
|
2608
|
+
id: r.migration.id,
|
|
2609
|
+
durationMs: n
|
|
2514
2610
|
}), yield* d.logInfo("file-based migration applied").pipe(d.annotateLogs({
|
|
2515
2611
|
scope: "voltro:migrate",
|
|
2516
|
-
id:
|
|
2517
|
-
durationMs:
|
|
2612
|
+
id: r.migration.id,
|
|
2613
|
+
durationMs: n
|
|
2518
2614
|
}));
|
|
2519
2615
|
}
|
|
2520
2616
|
} finally {
|
|
2521
|
-
yield*
|
|
2617
|
+
yield* E(e).pipe(d.orDie);
|
|
2522
2618
|
}
|
|
2523
2619
|
return {
|
|
2524
|
-
applied:
|
|
2525
|
-
skipped:
|
|
2620
|
+
applied: i,
|
|
2621
|
+
skipped: r
|
|
2526
2622
|
};
|
|
2527
|
-
}),
|
|
2623
|
+
}), Er = (e, t) => e`
|
|
2528
2624
|
SELECT ${e("id")}
|
|
2529
2625
|
FROM ${e("_voltro_migration_plans")}
|
|
2530
2626
|
WHERE ${e("id")} = ${t} AND ${e("source")} = 'file'
|
|
2531
2627
|
LIMIT 1
|
|
2532
|
-
`,
|
|
2533
|
-
if (!(yield*
|
|
2628
|
+
`, Dr = (e, t) => d.gen(function* () {
|
|
2629
|
+
if (!(yield* Er(e, t.id))[0]) return yield* d.fail(/* @__PURE__ */ Error(`rollback: ${t.id} not found in _voltro_migration_plans (file source)`));
|
|
2534
2630
|
let n = yield* d.tryPromise({
|
|
2535
|
-
try: () =>
|
|
2631
|
+
try: () => yr(g(t.projectRoot, "migrations")),
|
|
2536
2632
|
catch: (e) => e
|
|
2537
2633
|
}), r = (yield* d.tryPromise({
|
|
2538
|
-
try: () =>
|
|
2634
|
+
try: () => br(n),
|
|
2539
2635
|
catch: (e) => e
|
|
2540
2636
|
})).find((e) => e.migration.id === t.id);
|
|
2541
2637
|
if (!r) return yield* d.fail(/* @__PURE__ */ Error(`rollback: file for migration ${t.id} not found on disk under ${t.projectRoot}/migrations/`));
|
|
2542
|
-
yield*
|
|
2638
|
+
yield* T(e);
|
|
2543
2639
|
let i = Date.now();
|
|
2544
2640
|
try {
|
|
2545
2641
|
let n = {
|
|
@@ -2566,9 +2662,9 @@ BEGIN
|
|
|
2566
2662
|
durationMs: o
|
|
2567
2663
|
};
|
|
2568
2664
|
} finally {
|
|
2569
|
-
yield*
|
|
2665
|
+
yield* E(e).pipe(d.orDie);
|
|
2570
2666
|
}
|
|
2571
|
-
}),
|
|
2667
|
+
}), Or = (e) => d.gen(function* () {
|
|
2572
2668
|
let t = yield* p.SqlClient, n = yield* t`
|
|
2573
2669
|
SELECT id, fingerprint, appliedAt FROM _voltro_migration_plans
|
|
2574
2670
|
WHERE source = 'auto-diff'
|
|
@@ -2613,10 +2709,10 @@ BEGIN
|
|
|
2613
2709
|
snapshotFingerprint: e.fingerprint,
|
|
2614
2710
|
snapshotId: i
|
|
2615
2711
|
};
|
|
2616
|
-
}),
|
|
2712
|
+
}), kr = (e, ...t) => ({
|
|
2617
2713
|
_tag: "RawSqlFragment",
|
|
2618
2714
|
strings: [...e],
|
|
2619
2715
|
values: [...t]
|
|
2620
|
-
}),
|
|
2716
|
+
}), Ar = (e) => typeof e == "object" && !!e && e._tag === "RawSqlFragment";
|
|
2621
2717
|
//#endregion
|
|
2622
|
-
export { l as FILE_MIGRATION_PATTERN,
|
|
2718
|
+
export { l as FILE_MIGRATION_PATTERN, it as REACTIVE_TRIGGER_PREFIX, te as VOLTRO_MIGRATION_LOCK_KEY, ft as _internalCmp, T as acquireMigrationLock, Ke as applyNamespacedSchema, ir as applyPlan, Be as applySchema, zt as chunkTables, F as declaredSnapshot, ve as defaultArrayClause, _e as defaultClause, k as defaultJsonClause, _r as describeOutcome, at as detectReactiveTriggerDrift, tn as emitDropColumnDdl, nn as emitDropColumnDdlMysql, ze as emitFrameworkBootstrapSql, Le as emitNamespaceProvisionDdl, Re as emitNamespacedSchemaSql, M as emitSchemaSql, N as fingerprintSchema, ot as formatReactiveTriggerDrift, fr as ignoreTablesFromEnv, Yt as introspectSchema, o as isFileMigration, Ar as isRawSqlFragment, Pt as mapPgType, s as migration, A as numericIdSql, Nt as parseEnumCheck, wr as pendingFileMigrationIds, Mt as planMigrations, qe as provisionTenantNamespace, E as releaseMigrationLock, gn as renderColumnMysql, pn as renderColumnPg, Dr as rollbackFileBasedMigration, Tr as runFileBasedMigrations, Je as runFrameworkBootstrap, Ge as runMigrate, gr as runPlannedMigrations, P as shortFingerprint, et as snapshotColumn, kr as sql, O as sqlType, Or as squashMigrationPlans, pr as unblockLossy, he as withMigrationLock };
|