@voltro/database 0.13.0 → 0.15.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 +412 -0
- package/dist/{fileBased-DEW2BvnP.js → fileBased-Dfuv6JWP.js} +67 -67
- package/dist/index.d.ts +52 -7
- package/dist/index.js +516 -516
- package/dist/sql.d.ts +90 -32
- package/dist/sql.js +748 -679
- 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, "`"), b = (e) => typeof e == "string" ? e : e.name ?? String(e),
|
|
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) {
|
|
@@ -51,7 +51,7 @@ var _ = (e, t, n, r = 400) => {
|
|
|
51
51
|
for (let r of t.fields) {
|
|
52
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
|
-
}),
|
|
113
|
-
mysql: () =>
|
|
114
|
-
mssql: () =>
|
|
115
|
-
sqlite: () =>
|
|
116
|
-
orElse: () =>
|
|
117
|
-
}),
|
|
118
|
-
mysql: () =>
|
|
119
|
-
mssql: () =>
|
|
120
|
-
sqlite: () =>
|
|
121
|
-
orElse: () =>
|
|
122
|
-
}),
|
|
123
|
-
|
|
124
|
-
},
|
|
125
|
-
let
|
|
126
|
-
if (
|
|
127
|
-
if (
|
|
128
|
-
throw Error(`@voltro/plugin-postgis: ${
|
|
129
|
-
}
|
|
130
|
-
if (
|
|
131
|
-
if (
|
|
132
|
-
return
|
|
133
|
-
}
|
|
134
|
-
if (
|
|
135
|
-
if (
|
|
136
|
-
...
|
|
137
|
-
type:
|
|
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({
|
|
118
|
+
mysql: () => le(e),
|
|
119
|
+
mssql: () => pe(e),
|
|
120
|
+
sqlite: () => me,
|
|
121
|
+
orElse: () => ae(e)
|
|
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,26 +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
|
-
},
|
|
240
|
-
if (n !== "postgres" || t.type !== "array" || t.arrayElement === void 0) return
|
|
241
|
-
let r =
|
|
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
242
|
...t,
|
|
243
243
|
type: t.arrayElement,
|
|
244
244
|
arrayElement: void 0
|
|
245
245
|
}, n);
|
|
246
246
|
return `DEFAULT '{${e.map((e) => typeof e == "number" || typeof e == "boolean" ? String(e) : `"${String(e).replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"`).join(",").replace(/'/g, "''")}}'::${r}[]`;
|
|
247
|
-
},
|
|
247
|
+
}, k = (e, t) => {
|
|
248
248
|
let n = JSON.stringify(e).replace(/'/g, "''");
|
|
249
249
|
return t === "postgres" ? `DEFAULT '${n}'::jsonb` : t === "mysql" || t === "mariadb" ? `DEFAULT (CAST('${n}' AS JSON))` : `DEFAULT '${n}'`;
|
|
250
|
-
},
|
|
250
|
+
}, A = (e, t) => {
|
|
251
251
|
switch (t) {
|
|
252
252
|
case "postgres": return `"${e}" BIGSERIAL PRIMARY KEY`;
|
|
253
253
|
case "mysql":
|
|
@@ -256,7 +256,7 @@ var _ = (e, t, n, r = 400) => {
|
|
|
256
256
|
case "sqlite": return `"${e}" INTEGER PRIMARY KEY AUTOINCREMENT`;
|
|
257
257
|
case "turso": return `"${e}" INTEGER PRIMARY KEY`;
|
|
258
258
|
}
|
|
259
|
-
},
|
|
259
|
+
}, j = (e, t) => {
|
|
260
260
|
if (e === "restrict" && t === "mssql") return "NO ACTION";
|
|
261
261
|
switch (e) {
|
|
262
262
|
case "cascade": return "CASCADE";
|
|
@@ -264,107 +264,107 @@ var _ = (e, t, n, r = 400) => {
|
|
|
264
264
|
case "setNull": return "SET NULL";
|
|
265
265
|
case "noAction": return "NO ACTION";
|
|
266
266
|
}
|
|
267
|
-
},
|
|
268
|
-
let
|
|
269
|
-
if (
|
|
270
|
-
let
|
|
271
|
-
if (!
|
|
272
|
-
let
|
|
273
|
-
return
|
|
274
|
-
},
|
|
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;
|
|
274
|
+
}, Se = (e, t) => {
|
|
275
275
|
if (!e.generatedAs) return null;
|
|
276
276
|
let { expr: n, stored: r } = e.generatedAs;
|
|
277
|
-
if (t === "postgres") return r ||
|
|
277
|
+
if (t === "postgres") return r || D("[voltro:migrate] generated column requested as VIRTUAL but postgres only supports STORED — promoting"), `GENERATED ALWAYS AS (${n}) STORED`;
|
|
278
278
|
if (t === "mysql" || t === "mariadb") return `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
|
|
279
279
|
if (t === "mssql") return `AS (${n})${r ? " PERSISTED" : ""}`;
|
|
280
280
|
if (t === "turso") throw Error("@voltro/sql-turso: generated columns (.generatedAs(...)) are not supported — Turso's MVCC mode (journal_mode=experimental_mvcc) rejects them. Drop the generated column, or use the 'sqlite' / 'postgres' dialect for this table.");
|
|
281
281
|
return `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
|
|
282
|
-
},
|
|
283
|
-
if (n.type === "id" && n.idScheme?.kind === "numeric") return
|
|
284
|
-
let s = r === "mssql" && n.type === "text" && !n.generatedAs && n.maxLength === void 0 && i?.has(t) ? "NVARCHAR(450)" :
|
|
282
|
+
}, Ce = (t, n, r, i, a = !1, o = !1) => {
|
|
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];
|
|
285
285
|
n.type === "id" && !o && c.push("PRIMARY KEY");
|
|
286
|
-
let l =
|
|
286
|
+
let l = Se(n, r);
|
|
287
287
|
if (l) c.push(l);
|
|
288
288
|
else {
|
|
289
289
|
n.nullable || c.push("NOT NULL"), n.unique && n.type !== "id" && c.push("UNIQUE");
|
|
290
|
-
let e =
|
|
290
|
+
let e = _e(n, r);
|
|
291
291
|
e && c.push(e);
|
|
292
292
|
}
|
|
293
293
|
if (n.type === "reference" && n.references && !a) {
|
|
294
|
-
let
|
|
295
|
-
c.push(`REFERENCES ${
|
|
296
|
-
let
|
|
297
|
-
c.push(`ON DELETE ${
|
|
298
|
-
let
|
|
299
|
-
|
|
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}`);
|
|
300
300
|
}
|
|
301
301
|
if (n.oneOf && n.oneOf.length > 0) {
|
|
302
|
-
let
|
|
303
|
-
c.push(`CHECK (${
|
|
302
|
+
let i = n.oneOf.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
|
|
303
|
+
c.push(`CHECK (${e(t, r)} IN (${i}))`);
|
|
304
304
|
}
|
|
305
305
|
if (n.checks && n.checks.length > 0) for (let e of n.checks) c.push(`CHECK (${e})`);
|
|
306
|
-
if (n.type === "enum" && n.enumValues && n.enumValues.length > 0 && (r === "mssql" ||
|
|
307
|
-
let
|
|
308
|
-
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}))`);
|
|
309
309
|
}
|
|
310
310
|
if (n.type === "json" || n.type === "array") {
|
|
311
|
-
let n =
|
|
312
|
-
|
|
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)`);
|
|
313
313
|
}
|
|
314
314
|
return c.join(" ");
|
|
315
|
-
},
|
|
316
|
-
let
|
|
317
|
-
for (let
|
|
318
|
-
for (let
|
|
319
|
-
let
|
|
320
|
-
let
|
|
321
|
-
return ` CONSTRAINT ${
|
|
322
|
-
}),
|
|
323
|
-
...
|
|
324
|
-
...
|
|
325
|
-
...
|
|
326
|
-
], f = d.length > 0 ? `${
|
|
327
|
-
if (
|
|
328
|
-
let
|
|
329
|
-
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, "''")}');`;
|
|
330
330
|
}
|
|
331
331
|
return [
|
|
332
332
|
`CREATE TABLE IF NOT EXISTS ${p} (`,
|
|
333
333
|
f,
|
|
334
334
|
");"
|
|
335
335
|
].join("\n");
|
|
336
|
-
},
|
|
337
|
-
let
|
|
338
|
-
return
|
|
339
|
-
},
|
|
340
|
-
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) => {
|
|
341
341
|
let o = {
|
|
342
342
|
using: "",
|
|
343
343
|
withSuffix: "",
|
|
344
344
|
skip: !1
|
|
345
345
|
};
|
|
346
346
|
if (i === void 0 || i === "btree") return o;
|
|
347
|
-
if (i === "gist") return
|
|
347
|
+
if (i === "gist") return r === "postgres" ? {
|
|
348
348
|
using: " USING GIST",
|
|
349
349
|
withSuffix: "",
|
|
350
350
|
skip: !1
|
|
351
|
-
} : (
|
|
352
|
-
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" ? {
|
|
353
353
|
using: " USING GIN",
|
|
354
354
|
withSuffix: "",
|
|
355
355
|
skip: !1
|
|
356
|
-
} :
|
|
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(...).`), {
|
|
357
357
|
using: "",
|
|
358
358
|
withSuffix: "",
|
|
359
359
|
skip: !0
|
|
360
|
-
}) : (
|
|
361
|
-
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" ? {
|
|
362
362
|
using: " USING BRIN",
|
|
363
363
|
withSuffix: "",
|
|
364
364
|
skip: !1
|
|
365
|
-
} : (
|
|
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);
|
|
366
366
|
if (i === "hnsw") {
|
|
367
|
-
if (
|
|
367
|
+
if (r === "postgres") {
|
|
368
368
|
let e = a?.hnsw?.m ?? 16, n = a?.hnsw?.efConstruction ?? 64, r = a?.hnsw?.opclass ?? t(a?.hnsw?.distance);
|
|
369
369
|
return {
|
|
370
370
|
using: " USING hnsw",
|
|
@@ -373,65 +373,65 @@ var _ = (e, t, n, r = 400) => {
|
|
|
373
373
|
skip: !1
|
|
374
374
|
};
|
|
375
375
|
}
|
|
376
|
-
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.`), {
|
|
377
377
|
using: "",
|
|
378
378
|
withSuffix: "",
|
|
379
379
|
skip: !0
|
|
380
380
|
};
|
|
381
381
|
}
|
|
382
382
|
return o;
|
|
383
|
-
},
|
|
384
|
-
let
|
|
385
|
-
if (typeof
|
|
386
|
-
if ("jsonPath" in
|
|
387
|
-
let { column:
|
|
388
|
-
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 })})`;
|
|
389
389
|
}
|
|
390
|
-
return `(${
|
|
390
|
+
return `(${e.expr})`;
|
|
391
391
|
});
|
|
392
|
-
return
|
|
393
|
-
}, d = (
|
|
394
|
-
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);
|
|
395
395
|
if (f.skip) return "";
|
|
396
|
-
let p =
|
|
397
|
-
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};`;
|
|
398
398
|
};
|
|
399
|
-
for (let t of
|
|
400
|
-
let
|
|
401
|
-
let
|
|
402
|
-
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}')`;
|
|
403
403
|
}).join(" || ");
|
|
404
|
-
|
|
405
|
-
} else if (
|
|
406
|
-
let
|
|
407
|
-
|
|
408
|
-
} else if (
|
|
409
|
-
else
|
|
410
|
-
for (let
|
|
411
|
-
if ((
|
|
412
|
-
|
|
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(...).`);
|
|
413
413
|
continue;
|
|
414
414
|
}
|
|
415
|
-
if (
|
|
416
|
-
let
|
|
417
|
-
|
|
418
|
-
let
|
|
419
|
-
|
|
420
|
-
}
|
|
421
|
-
for (let [
|
|
422
|
-
if (
|
|
423
|
-
let r = `${
|
|
424
|
-
|
|
425
|
-
}
|
|
426
|
-
return
|
|
427
|
-
},
|
|
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");
|
|
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) => `
|
|
428
428
|
ALTER TABLE "${e.tableName}" REPLICA IDENTITY FULL;
|
|
429
429
|
DROP TRIGGER IF EXISTS framework_changes_${e.tableName} ON "${e.tableName}";
|
|
430
430
|
CREATE TRIGGER framework_changes_${e.tableName}
|
|
431
431
|
AFTER INSERT OR UPDATE OR DELETE ON "${e.tableName}"
|
|
432
432
|
FOR EACH ROW EXECUTE FUNCTION framework_notify_change();
|
|
433
|
-
`.trim(),
|
|
434
|
-
let t = new Map(e.map((e) => [e.tableName, e])), n =
|
|
433
|
+
`.trim(), 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) => {
|
|
434
|
+
let t = new Map(e.map((e) => [e.tableName, e])), n = w(e.map((e) => e.tableName), (e) => {
|
|
435
435
|
let n = t.get(e);
|
|
436
436
|
return n ? Object.entries(n.fields).flatMap(([e, n]) => {
|
|
437
437
|
if (n.type !== "reference" || !n.references) return [];
|
|
@@ -442,7 +442,7 @@ FOR EACH ROW EXECUTE FUNCTION framework_notify_change();
|
|
|
442
442
|
}] : [];
|
|
443
443
|
}) : [];
|
|
444
444
|
}), r = [];
|
|
445
|
-
for (let t of e) for (let [e, i] of Object.entries(t.fields)) i.type !== "reference" || !i.references || n.has(
|
|
445
|
+
for (let t of e) for (let [e, i] of Object.entries(t.fields)) i.type !== "reference" || !i.references || n.has(C(t.tableName, e)) && r.push({
|
|
446
446
|
table: t.tableName,
|
|
447
447
|
column: e,
|
|
448
448
|
targetTable: i.references().tableName,
|
|
@@ -453,7 +453,7 @@ FOR EACH ROW EXECUTE FUNCTION framework_notify_change();
|
|
|
453
453
|
if (!(i.has(e.tableName) || a.has(e.tableName))) {
|
|
454
454
|
a.add(e.tableName);
|
|
455
455
|
for (let [r, i] of Object.entries(e.fields)) {
|
|
456
|
-
if (i.type !== "reference" || !i.references || n.has(
|
|
456
|
+
if (i.type !== "reference" || !i.references || n.has(C(e.tableName, r))) continue;
|
|
457
457
|
let a = i.references();
|
|
458
458
|
if (a.tableName === e.tableName) continue;
|
|
459
459
|
let o = t.get(a.tableName);
|
|
@@ -467,30 +467,30 @@ FOR EACH ROW EXECUTE FUNCTION framework_notify_change();
|
|
|
467
467
|
sorted: o,
|
|
468
468
|
cyclic: r
|
|
469
469
|
};
|
|
470
|
-
},
|
|
471
|
-
let
|
|
472
|
-
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) {
|
|
473
473
|
case "postgres": return [
|
|
474
474
|
"DO $$ BEGIN",
|
|
475
475
|
" IF NOT EXISTS (SELECT 1 FROM pg_constraint",
|
|
476
|
-
` WHERE conname = '${
|
|
477
|
-
` ALTER TABLE ${
|
|
476
|
+
` WHERE conname = '${a}' AND conrelid = '${r ? `${r}.` : ""}${t.table}'::regclass) THEN`,
|
|
477
|
+
` ALTER TABLE ${i(t.table)} ${l(!1)};`,
|
|
478
478
|
" END IF;",
|
|
479
479
|
"END $$;"
|
|
480
480
|
].join("\n");
|
|
481
|
-
case "mssql": return `IF NOT EXISTS (SELECT 1 FROM sys.foreign_keys WHERE name = '${
|
|
482
|
-
case "mariadb": return `ALTER TABLE ${
|
|
483
|
-
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)};`;
|
|
484
484
|
}
|
|
485
|
-
},
|
|
486
|
-
let
|
|
487
|
-
if (
|
|
488
|
-
for (let
|
|
489
|
-
let
|
|
490
|
-
|
|
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);
|
|
491
491
|
}
|
|
492
|
-
return
|
|
493
|
-
},
|
|
492
|
+
return n;
|
|
493
|
+
}, Pe = (e, t) => {
|
|
494
494
|
if (t !== "postgres") return "";
|
|
495
495
|
let n = /* @__PURE__ */ new Map();
|
|
496
496
|
for (let t of e) for (let e of Object.values(t.fields)) {
|
|
@@ -506,12 +506,12 @@ FOR EACH ROW EXECUTE FUNCTION framework_notify_change();
|
|
|
506
506
|
r.push(`DO $$ BEGIN\n IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = '${e.replace(/'/g, "''")}') THEN\n CREATE TYPE "${e}" AS ENUM (${n});\n END IF;\nEND $$;`);
|
|
507
507
|
}
|
|
508
508
|
return r.join("\n\n");
|
|
509
|
-
},
|
|
509
|
+
}, Fe = (e, t) => {
|
|
510
510
|
if (t !== "postgres") return "";
|
|
511
511
|
let n = /* @__PURE__ */ new Set();
|
|
512
512
|
for (let t of e) for (let e of Object.values(t.fields)) e.type === "enum" && e.enumName && n.add(e.enumName);
|
|
513
513
|
let r = [];
|
|
514
|
-
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)) {
|
|
515
515
|
let i = e.replace(/'/g, "''"), a = t.replace(/'/g, "''"), o = n.replace(/'/g, "''");
|
|
516
516
|
r.push(`DO \$\$
|
|
517
517
|
DECLARE
|
|
@@ -520,94 +520,94 @@ BEGIN
|
|
|
520
520
|
SELECT oid INTO type_oid FROM pg_type WHERE typname = '${i}';\n IF type_oid IS NOT NULL\n AND EXISTS (SELECT 1 FROM pg_enum WHERE enumtypid = type_oid AND enumlabel = '${a}')\n AND NOT EXISTS (SELECT 1 FROM pg_enum WHERE enumtypid = type_oid AND enumlabel = '${o}') THEN\n IF current_setting('server_version_num')::int >= 140000 THEN\n EXECUTE format('ALTER TYPE %I RENAME VALUE %L TO %L', '${i}', '${a}', '${o}');\n ELSE\n UPDATE pg_enum SET enumlabel = '${o}' WHERE enumtypid = type_oid AND enumlabel = '${a}';\n END IF;\n END IF;\nEND $$;`);
|
|
521
521
|
}
|
|
522
522
|
return r.join("\n\n");
|
|
523
|
-
},
|
|
523
|
+
}, Ie = (e) => {
|
|
524
524
|
let t = [], r = [];
|
|
525
525
|
for (let i of e) n(i) ? r.push(i) : t.push(i);
|
|
526
526
|
return {
|
|
527
527
|
tables: t,
|
|
528
528
|
views: r
|
|
529
529
|
};
|
|
530
|
-
},
|
|
531
|
-
let { tables:
|
|
532
|
-
|
|
533
|
-
let
|
|
534
|
-
|
|
535
|
-
let d =
|
|
536
|
-
d &&
|
|
537
|
-
for (let e of
|
|
538
|
-
if (!
|
|
539
|
-
for (let e of
|
|
540
|
-
let
|
|
541
|
-
|
|
542
|
-
}
|
|
543
|
-
let f =
|
|
544
|
-
if (f.length > 0 &&
|
|
545
|
-
|
|
546
|
-
for (let e of f)
|
|
547
|
-
}
|
|
548
|
-
for (let e of
|
|
549
|
-
return
|
|
550
|
-
},
|
|
551
|
-
let
|
|
552
|
-
switch (
|
|
553
|
-
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};`;
|
|
554
554
|
case "mysql":
|
|
555
|
-
case "mariadb": return `CREATE DATABASE IF NOT EXISTS ${
|
|
556
|
-
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, "''")}');`;
|
|
557
557
|
case "turso":
|
|
558
|
-
case "sqlite": return `ATTACH DATABASE '${(
|
|
559
|
-
}
|
|
560
|
-
},
|
|
561
|
-
let a =
|
|
562
|
-
if (n === "postgres") return `${a}\n\nSET search_path TO ${o};\n\n${
|
|
563
|
-
if (n === "mysql" || n === "mariadb") return `${a}\n\nUSE ${o};\n\n${
|
|
564
|
-
let { sorted: s, cyclic: c } =
|
|
565
|
-
for (let e of s) d.push(
|
|
566
|
-
if (!
|
|
558
|
+
case "sqlite": return `ATTACH DATABASE '${(r ?? `${t}.db`).replace(/'/g, "''")}' AS ${i};`;
|
|
559
|
+
}
|
|
560
|
+
}, Re = (t, n, r, i) => {
|
|
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)}`;
|
|
564
|
+
let { sorted: s, cyclic: c } = je(t), l = Ne(c, n), d = [a];
|
|
565
|
+
for (let e of s) d.push(we(e, n, r, l.get(e.tableName)));
|
|
566
|
+
if (!u(n)) for (let e of c) d.push(Me(e, n, r));
|
|
567
567
|
for (let e of s) {
|
|
568
|
-
let t =
|
|
568
|
+
let t = Ee(e, n, r);
|
|
569
569
|
t && d.push(t);
|
|
570
570
|
}
|
|
571
571
|
return d.join("\n\n") + "\n";
|
|
572
|
-
},
|
|
573
|
-
if (
|
|
574
|
-
let { sorted:
|
|
575
|
-
|
|
576
|
-
let
|
|
577
|
-
|
|
578
|
-
for (let e of
|
|
579
|
-
for (let e of
|
|
580
|
-
for (let
|
|
581
|
-
let
|
|
582
|
-
if (
|
|
583
|
-
let
|
|
584
|
-
let
|
|
585
|
-
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};`;
|
|
586
586
|
});
|
|
587
|
-
|
|
587
|
+
o.push(i.join("\n"));
|
|
588
588
|
}
|
|
589
|
-
for (let e of
|
|
590
|
-
let
|
|
591
|
-
|
|
589
|
+
for (let e of r) {
|
|
590
|
+
let t = Ee(e, n);
|
|
591
|
+
t && o.push(t);
|
|
592
592
|
}
|
|
593
|
-
let
|
|
594
|
-
if (
|
|
595
|
-
|
|
596
|
-
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));
|
|
597
597
|
}
|
|
598
|
-
return
|
|
599
|
-
},
|
|
598
|
+
return o.join("\n\n") + "\n";
|
|
599
|
+
}, Be = (e, t = "postgres") => d.gen(function* () {
|
|
600
600
|
let n = yield* p.SqlClient;
|
|
601
|
-
yield*
|
|
602
|
-
}),
|
|
601
|
+
yield* he(n, Ue(n, M(e, t), t)).pipe(d.orDie);
|
|
602
|
+
}), Ve = (e, t) => {
|
|
603
603
|
let n = t.cause ?? {};
|
|
604
604
|
return (n.errno === 1061 || n.code === "ER_DUP_KEYNAME") && /^\s*CREATE\s+(UNIQUE\s+|FULLTEXT\s+)?INDEX\b/i.test(e);
|
|
605
|
-
},
|
|
605
|
+
}, He = (e) => d.gen(function* () {
|
|
606
606
|
let t = yield* p.SqlClient;
|
|
607
|
-
for (let n of
|
|
608
|
-
|
|
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));
|
|
609
609
|
})), d.orDieWith((e) => Error(_("migrate: statement failed", n, e, 400).trim())));
|
|
610
|
-
}),
|
|
610
|
+
}), Ue = (e, t, n) => (n === "turso" ? He(t) : e.withTransaction(He(t))).pipe(d.orDie), We = (e) => {
|
|
611
611
|
let t = [], n = "", r = !1;
|
|
612
612
|
for (let i = 0; i < e.length; i++) {
|
|
613
613
|
if (e.slice(i, i + 2) === "$$") {
|
|
@@ -622,40 +622,40 @@ BEGIN
|
|
|
622
622
|
}
|
|
623
623
|
let i = n.trim();
|
|
624
624
|
return i.length > 0 && t.push(i), t;
|
|
625
|
-
},
|
|
626
|
-
await d.runPromise(
|
|
627
|
-
},
|
|
628
|
-
let r =
|
|
629
|
-
yield*
|
|
630
|
-
}),
|
|
631
|
-
await d.runPromise(
|
|
632
|
-
},
|
|
625
|
+
}, Ge = async (e, t, n = "postgres") => {
|
|
626
|
+
await d.runPromise(Be(e, n).pipe(d.provide(t)));
|
|
627
|
+
}, Ke = (e, t, n = "postgres") => d.gen(function* () {
|
|
628
|
+
let r = Re(e, n, t), i = yield* p.SqlClient;
|
|
629
|
+
yield* he(i, Ue(i, r, n)).pipe(d.orDie);
|
|
630
|
+
}), qe = async (e, t, n, r = "postgres") => {
|
|
631
|
+
await d.runPromise(Ke(e, t, r).pipe(d.provide(n)));
|
|
632
|
+
}, Je = async (e, t, n = "postgres") => {
|
|
633
633
|
await d.runPromise(d.gen(function* () {
|
|
634
|
-
let t =
|
|
635
|
-
yield*
|
|
634
|
+
let t = ze(e, n), r = yield* p.SqlClient;
|
|
635
|
+
yield* he(r, Ue(r, t, n)).pipe(d.orDie);
|
|
636
636
|
}).pipe(d.provide(t)));
|
|
637
|
-
},
|
|
637
|
+
}, Ye = (e) => {
|
|
638
638
|
if (e == null) return e;
|
|
639
|
-
if (Array.isArray(e)) return e.map(
|
|
639
|
+
if (Array.isArray(e)) return e.map(Ye);
|
|
640
640
|
if (typeof e != "object") return e;
|
|
641
641
|
let t = {};
|
|
642
642
|
for (let n of Object.keys(e).sort()) {
|
|
643
643
|
let r = e[n];
|
|
644
|
-
r !== void 0 && (t[n] =
|
|
644
|
+
r !== void 0 && (t[n] = Ye(r));
|
|
645
645
|
}
|
|
646
646
|
return t;
|
|
647
|
-
},
|
|
647
|
+
}, Xe = (e) => {
|
|
648
648
|
if (!e.idScheme && !e.sensitive && !e.safe) return e;
|
|
649
649
|
let { idScheme: t, sensitive: n, safe: r, ...i } = e;
|
|
650
650
|
return i;
|
|
651
|
-
},
|
|
651
|
+
}, Ze = (e) => [...e].map(Xe).sort((e, t) => e.name.localeCompare(t.name)), Qe = (e) => [...e].sort((e, t) => e.name.localeCompare(t.name)), $e = (e) => [...e].map((e) => ({
|
|
652
652
|
name: e.name,
|
|
653
|
-
columns:
|
|
654
|
-
indexes:
|
|
655
|
-
})).sort((e, t) => e.name.localeCompare(t.name)),
|
|
656
|
-
let t = { tables:
|
|
653
|
+
columns: Ze(e.columns),
|
|
654
|
+
indexes: Qe(e.indexes)
|
|
655
|
+
})).sort((e, t) => e.name.localeCompare(t.name)), N = (e) => {
|
|
656
|
+
let t = { tables: $e(e.tables) }, n = JSON.stringify(Ye(t));
|
|
657
657
|
return m("sha256").update(n).digest("hex");
|
|
658
|
-
},
|
|
658
|
+
}, P = (e) => e.slice(0, 16), et = (e, t) => {
|
|
659
659
|
let n = t.references ? {
|
|
660
660
|
table: t.references().tableName,
|
|
661
661
|
column: "id",
|
|
@@ -693,7 +693,7 @@ BEGIN
|
|
|
693
693
|
...t.enumValues === void 0 ? {} : { enumValues: t.enumValues },
|
|
694
694
|
...t.spatial === void 0 ? {} : { spatial: t.spatial }
|
|
695
695
|
};
|
|
696
|
-
},
|
|
696
|
+
}, tt = (e) => {
|
|
697
697
|
let t = [], n = /* @__PURE__ */ new Set(), r = (e) => {
|
|
698
698
|
n.has(e.name) || (n.add(e.name), t.push(e));
|
|
699
699
|
}, i = e.appliedPrimaryKey ?? [];
|
|
@@ -727,13 +727,13 @@ BEGIN
|
|
|
727
727
|
columns: t.fields,
|
|
728
728
|
unique: !0
|
|
729
729
|
});
|
|
730
|
-
let
|
|
731
|
-
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"));
|
|
732
732
|
for (let [t, n] of Object.entries(e.fields)) {
|
|
733
733
|
let i = n;
|
|
734
|
-
if (i.dropped || !i.references || i.fkAutoIndex === !1 ||
|
|
734
|
+
if (i.dropped || !i.references || i.fkAutoIndex === !1 || s.has(t)) continue;
|
|
735
735
|
let a = `${e.tableName}_${t}_idx`;
|
|
736
|
-
|
|
736
|
+
c(e.tableName, a, !0, [t]), r({
|
|
737
737
|
name: a,
|
|
738
738
|
table: e.tableName,
|
|
739
739
|
columns: [t],
|
|
@@ -741,11 +741,11 @@ BEGIN
|
|
|
741
741
|
});
|
|
742
742
|
}
|
|
743
743
|
return t;
|
|
744
|
-
},
|
|
744
|
+
}, nt = (e) => {
|
|
745
745
|
let t = new Set((e.appliedUniques ?? []).filter((e) => e.fields.length === 1).map((e) => e.fields[0])), n = [];
|
|
746
746
|
for (let [r, i] of Object.entries(e.fields)) {
|
|
747
747
|
if (i.dropped) continue;
|
|
748
|
-
let e =
|
|
748
|
+
let e = et(r, i);
|
|
749
749
|
n.push(t.has(r) ? {
|
|
750
750
|
...e,
|
|
751
751
|
unique: !0
|
|
@@ -755,32 +755,66 @@ BEGIN
|
|
|
755
755
|
return {
|
|
756
756
|
name: e.tableName,
|
|
757
757
|
columns: n,
|
|
758
|
-
indexes:
|
|
758
|
+
indexes: tt(e),
|
|
759
759
|
...r.length > 0 ? { primaryKey: [...r] } : {}
|
|
760
760
|
};
|
|
761
|
-
},
|
|
761
|
+
}, rt = (e) => {
|
|
762
762
|
let t = /* @__PURE__ */ new Map();
|
|
763
763
|
for (let n of e) for (let e of n.indexes) {
|
|
764
764
|
let r = t.get(e.name);
|
|
765
765
|
if (r !== void 0 && r !== n.name) throw Error(`duplicate index name '${e.name}' across tables '${r}' and '${n.name}'. Index names must be unique per SCHEMA, not just per table — the DB creates only one, so the other never applies and 'db plan' re-emits it forever. Give each an explicit, table-prefixed name (e.g. '${n.name}_${e.name}').`);
|
|
766
766
|
t.set(e.name, n.name);
|
|
767
767
|
}
|
|
768
|
-
},
|
|
769
|
-
let n = e.map((e) =>
|
|
770
|
-
return
|
|
771
|
-
},
|
|
768
|
+
}, F = (e, t) => {
|
|
769
|
+
let n = e.map((e) => nt(S(e, t)));
|
|
770
|
+
return rt(n), { tables: n };
|
|
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 = {
|
|
772
806
|
postgres: !0,
|
|
773
807
|
mysql: !0,
|
|
774
808
|
mariadb: !0,
|
|
775
809
|
mssql: !0,
|
|
776
810
|
sqlite: !0
|
|
777
|
-
},
|
|
811
|
+
}, lt = {
|
|
778
812
|
postgres: !0,
|
|
779
813
|
mysql: !1,
|
|
780
814
|
mariadb: !1,
|
|
781
815
|
mssql: !0,
|
|
782
816
|
sqlite: !0
|
|
783
|
-
},
|
|
817
|
+
}, ut = (e) => {
|
|
784
818
|
switch (e) {
|
|
785
819
|
case "add-column":
|
|
786
820
|
case "drop-column":
|
|
@@ -790,43 +824,43 @@ BEGIN
|
|
|
790
824
|
case "add-foreign-key":
|
|
791
825
|
case "add-unique":
|
|
792
826
|
case "add-unique-composite":
|
|
793
|
-
case "add-check": return
|
|
794
|
-
default: return
|
|
827
|
+
case "add-check": return lt;
|
|
828
|
+
default: return ct;
|
|
795
829
|
}
|
|
796
|
-
},
|
|
830
|
+
}, dt = (e, t) => {
|
|
797
831
|
let n = new Map(t.tables.map((e) => [e.name, e]));
|
|
798
832
|
return new Map(e.map((e) => [e.tableName, {
|
|
799
833
|
table: e,
|
|
800
834
|
snapshot: n.get(e.tableName),
|
|
801
835
|
columnDefs: e.fields
|
|
802
836
|
}]));
|
|
803
|
-
},
|
|
837
|
+
}, ft = (e) => (t, n) => t.name === e ? -1 : n.name === e ? 1 : t.name.localeCompare(n.name), L = (e) => {
|
|
804
838
|
if (typeof e != "object" || !e) return JSON.stringify(e);
|
|
805
|
-
if (Array.isArray(e)) return `[${e.map(
|
|
839
|
+
if (Array.isArray(e)) return `[${e.map(L).join(",")}]`;
|
|
806
840
|
let t = e;
|
|
807
|
-
return `{${Object.keys(t).sort().map((e) => `${JSON.stringify(e)}:${
|
|
808
|
-
},
|
|
841
|
+
return `{${Object.keys(t).sort().map((e) => `${JSON.stringify(e)}:${L(t[e])}`).join(",")}}`;
|
|
842
|
+
}, pt = (e) => {
|
|
809
843
|
if (!e.hasDefault || e.defaultValue === void 0 || e.defaultValue === null) return null;
|
|
810
844
|
let t = e.defaultValue;
|
|
811
845
|
if (typeof t == "boolean") return t ? "__BOOL_TRUE__" : "__BOOL_FALSE__";
|
|
812
846
|
if (typeof t == "number") return String(t);
|
|
813
|
-
if (typeof t != "string") return
|
|
847
|
+
if (typeof t != "string") return L(t);
|
|
814
848
|
let n = t.trim(), r = n.toLowerCase().replace(/\s+/g, "");
|
|
815
849
|
if (r === "now" || r === "now()" || /^current_timestamp(\(\d*\))?$/.test(r) || r === "sysutcdatetime()" || r === "sysdatetime()" || r === "getutcdate()" || r === "getdate()") return "__NOW__";
|
|
816
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);
|
|
817
851
|
if (o) try {
|
|
818
|
-
return
|
|
852
|
+
return L(JSON.parse(o[1]));
|
|
819
853
|
} catch {}
|
|
820
854
|
if (a.startsWith("{") || a.startsWith("[")) try {
|
|
821
|
-
return
|
|
855
|
+
return L(JSON.parse(a));
|
|
822
856
|
} catch {}
|
|
823
857
|
return /^-?\d+(\.\d+)?$/.test(a) ? String(Number(a)) : a;
|
|
824
|
-
},
|
|
825
|
-
let n =
|
|
858
|
+
}, mt = (e, t) => {
|
|
859
|
+
let n = pt(e), r = pt(t);
|
|
826
860
|
if (n === r) return !0;
|
|
827
861
|
let i = (e) => e === "1" || e === "true" ? "__BOOL_TRUE__" : e === "0" || e === "false" ? "__BOOL_FALSE__" : e;
|
|
828
862
|
return i(n) === i(r);
|
|
829
|
-
},
|
|
863
|
+
}, R = (e) => {
|
|
830
864
|
if (!e) return null;
|
|
831
865
|
let t = (e) => e === "restrict" ? "noAction" : e;
|
|
832
866
|
return {
|
|
@@ -835,18 +869,18 @@ BEGIN
|
|
|
835
869
|
onDelete: t(e.onDelete),
|
|
836
870
|
onUpdate: t(e.onUpdate)
|
|
837
871
|
};
|
|
838
|
-
},
|
|
872
|
+
}, ht = (e, t) => {
|
|
839
873
|
let n = e && e.length > 0 ? e : void 0, r = t && t.length > 0 ? t : void 0;
|
|
840
874
|
if (!n && !r) return !0;
|
|
841
875
|
if (!n || !r || n.length !== r.length) return !1;
|
|
842
876
|
let i = [...n].sort(), a = [...r].sort();
|
|
843
877
|
return i.every((e, t) => e === a[t]);
|
|
844
|
-
},
|
|
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({
|
|
845
879
|
kind: "add-check",
|
|
846
880
|
table: e,
|
|
847
881
|
column: t.name,
|
|
848
882
|
values: t.oneOf
|
|
849
|
-
}, "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) => {
|
|
850
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 = [];
|
|
851
885
|
for (let t of e.columns) {
|
|
852
886
|
let e = n.get(t.name);
|
|
@@ -854,7 +888,7 @@ BEGIN
|
|
|
854
888
|
i.push(t);
|
|
855
889
|
continue;
|
|
856
890
|
}
|
|
857
|
-
|
|
891
|
+
gt(t, e) || o.push({
|
|
858
892
|
declared: t,
|
|
859
893
|
live: e
|
|
860
894
|
});
|
|
@@ -865,47 +899,47 @@ BEGIN
|
|
|
865
899
|
removed: a,
|
|
866
900
|
changed: o
|
|
867
901
|
};
|
|
868
|
-
},
|
|
902
|
+
}, bt = (e, t) => {
|
|
869
903
|
let n = new Map(t.indexes.map((e) => [e.name, e])), r = new Map(e.indexes.map((e) => [e.name, e])), i = [], a = [];
|
|
870
904
|
for (let t of e.indexes) {
|
|
871
905
|
let e = n.get(t.name);
|
|
872
|
-
(!e || !
|
|
906
|
+
(!e || !vt(t, e)) && i.push(t);
|
|
873
907
|
}
|
|
874
908
|
for (let e of t.indexes) r.has(e.name) || a.push(e);
|
|
875
909
|
return {
|
|
876
910
|
added: i,
|
|
877
911
|
removed: a
|
|
878
912
|
};
|
|
879
|
-
},
|
|
913
|
+
}, z = (e, t, n, r) => ({
|
|
880
914
|
op: e,
|
|
881
915
|
classification: t,
|
|
882
|
-
atomicByDialect:
|
|
916
|
+
atomicByDialect: ut(e.kind),
|
|
883
917
|
...n ? { reason: n } : {},
|
|
884
918
|
...r ? { blocked: r } : {}
|
|
885
|
-
}),
|
|
919
|
+
}), xt = (e, t, n) => {
|
|
886
920
|
let r = {
|
|
887
921
|
kind: "add-column",
|
|
888
922
|
table: e,
|
|
889
923
|
column: t
|
|
890
924
|
};
|
|
891
|
-
return t.nullable ?
|
|
892
|
-
},
|
|
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) => {
|
|
893
927
|
let r = {
|
|
894
928
|
kind: "drop-column",
|
|
895
929
|
table: e,
|
|
896
930
|
column: t.name
|
|
897
931
|
};
|
|
898
|
-
return n?.dropped ?
|
|
899
|
-
},
|
|
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({
|
|
900
934
|
kind: "create-table",
|
|
901
935
|
table: e,
|
|
902
936
|
columns: t,
|
|
903
937
|
indexes: n,
|
|
904
938
|
...r && r.length > 0 ? { primaryKey: r } : {}
|
|
905
|
-
}, "safe", "new table — no data to preserve"),
|
|
939
|
+
}, "safe", "new table — no data to preserve"), wt = (e) => z({
|
|
906
940
|
kind: "drop-table",
|
|
907
941
|
table: e
|
|
908
|
-
}, "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) => {
|
|
909
943
|
let i = (n ?? 0) >= r, a;
|
|
910
944
|
return a = t.unique ? t.columns.length === 1 ? {
|
|
911
945
|
kind: "add-unique",
|
|
@@ -920,16 +954,16 @@ BEGIN
|
|
|
920
954
|
kind: "add-index",
|
|
921
955
|
table: e,
|
|
922
956
|
index: t
|
|
923
|
-
}, i ?
|
|
924
|
-
},
|
|
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({
|
|
925
959
|
kind: "drop-unique-composite",
|
|
926
960
|
table: e,
|
|
927
961
|
name: t.name
|
|
928
|
-
}, "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({
|
|
929
963
|
kind: "drop-index",
|
|
930
964
|
table: e,
|
|
931
965
|
index: t.name
|
|
932
|
-
}, "safe", "drop index (no data loss — index is derived data)"),
|
|
966
|
+
}, "safe", "drop index (no data loss — index is derived data)"), Ot = (e, t) => {
|
|
933
967
|
if (e === "reference") return "text";
|
|
934
968
|
switch (t) {
|
|
935
969
|
case "sqlite":
|
|
@@ -937,7 +971,7 @@ BEGIN
|
|
|
937
971
|
case "mssql": return e === "json" ? "text" : e;
|
|
938
972
|
default: return e;
|
|
939
973
|
}
|
|
940
|
-
},
|
|
974
|
+
}, kt = (e, t, n, r, i, a) => {
|
|
941
975
|
let o = [];
|
|
942
976
|
if (t.nullable !== n.nullable) {
|
|
943
977
|
let n = {
|
|
@@ -946,7 +980,7 @@ BEGIN
|
|
|
946
980
|
column: t.name,
|
|
947
981
|
toNullable: t.nullable
|
|
948
982
|
};
|
|
949
|
-
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`));
|
|
950
984
|
}
|
|
951
985
|
if (t.unique !== n.unique) if (t.unique) {
|
|
952
986
|
let n = {
|
|
@@ -954,13 +988,13 @@ BEGIN
|
|
|
954
988
|
table: e,
|
|
955
989
|
column: t.name
|
|
956
990
|
}, r = (i ?? 0) >= a;
|
|
957
|
-
o.push(r ?
|
|
958
|
-
} 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({
|
|
959
993
|
kind: "drop-unique",
|
|
960
994
|
table: e,
|
|
961
995
|
column: t.name
|
|
962
996
|
}, "safe", `drop unique constraint on ${e}.${t.name} — constraint is derived metadata, no data loss`));
|
|
963
|
-
if (
|
|
997
|
+
if (Ot(t.type, r) !== Ot(n.type, r)) {
|
|
964
998
|
let r = t.narrowedFrom;
|
|
965
999
|
if (r && r.from === n.type) {
|
|
966
1000
|
let i = {
|
|
@@ -971,7 +1005,7 @@ BEGIN
|
|
|
971
1005
|
to: t.type,
|
|
972
1006
|
...r.using === void 0 ? {} : { using: r.using }
|
|
973
1007
|
};
|
|
974
|
-
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)")));
|
|
975
1009
|
} else {
|
|
976
1010
|
let r = {
|
|
977
1011
|
kind: "alter-column-type",
|
|
@@ -980,10 +1014,10 @@ BEGIN
|
|
|
980
1014
|
from: n.type,
|
|
981
1015
|
to: t.type
|
|
982
1016
|
};
|
|
983
|
-
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` }));
|
|
984
1018
|
}
|
|
985
1019
|
}
|
|
986
|
-
if (!
|
|
1020
|
+
if (!mt(t, n)) {
|
|
987
1021
|
let n = {
|
|
988
1022
|
kind: "alter-column-default",
|
|
989
1023
|
table: e,
|
|
@@ -991,18 +1025,18 @@ BEGIN
|
|
|
991
1025
|
hasDefault: t.hasDefault,
|
|
992
1026
|
...t.defaultValue === void 0 ? {} : { defaultValue: t.defaultValue }
|
|
993
1027
|
};
|
|
994
|
-
o.push(
|
|
1028
|
+
o.push(z(n, "safe", `default change on ${e}.${t.name} affects only future inserts`));
|
|
995
1029
|
}
|
|
996
|
-
if (!
|
|
997
|
-
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({
|
|
998
1032
|
kind: "drop-check",
|
|
999
1033
|
table: e,
|
|
1000
1034
|
column: t.name
|
|
1001
1035
|
}, "safe", `drop stale enum CHECK on ${e}.${t.name}`));
|
|
1002
|
-
let r =
|
|
1036
|
+
let r = _t(e, t);
|
|
1003
1037
|
r && o.push(r);
|
|
1004
1038
|
}
|
|
1005
|
-
if (JSON.stringify(
|
|
1039
|
+
if (JSON.stringify(R(t.references)) !== JSON.stringify(R(n.references)) && (n.references && o.push(z({
|
|
1006
1040
|
kind: "drop-foreign-key",
|
|
1007
1041
|
table: e,
|
|
1008
1042
|
column: t.name
|
|
@@ -1016,17 +1050,17 @@ BEGIN
|
|
|
1016
1050
|
...t.references.onDelete ? { onDelete: t.references.onDelete } : {},
|
|
1017
1051
|
...t.references.onUpdate ? { onUpdate: t.references.onUpdate } : {}
|
|
1018
1052
|
};
|
|
1019
|
-
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({
|
|
1020
1054
|
...i,
|
|
1021
1055
|
orphanPolicy: r
|
|
1022
|
-
}, "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')`));
|
|
1023
1057
|
}
|
|
1024
1058
|
return o;
|
|
1025
|
-
},
|
|
1059
|
+
}, At = (e, t, n) => {
|
|
1026
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));
|
|
1027
1061
|
for (let [n, c] of Object.entries(t)) {
|
|
1028
1062
|
let t = c.renamedFrom;
|
|
1029
|
-
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({
|
|
1030
1064
|
kind: "rename-column",
|
|
1031
1065
|
table: e.tableName,
|
|
1032
1066
|
from: t,
|
|
@@ -1038,7 +1072,7 @@ BEGIN
|
|
|
1038
1072
|
consumedAddedNames: i,
|
|
1039
1073
|
consumedRemovedNames: a
|
|
1040
1074
|
};
|
|
1041
|
-
},
|
|
1075
|
+
}, jt = (e) => {
|
|
1042
1076
|
let t = {
|
|
1043
1077
|
safe: 0,
|
|
1044
1078
|
needsDefault: 0,
|
|
@@ -1073,37 +1107,37 @@ BEGIN
|
|
|
1073
1107
|
break;
|
|
1074
1108
|
}
|
|
1075
1109
|
return t;
|
|
1076
|
-
},
|
|
1077
|
-
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 = [];
|
|
1078
1112
|
for (let e of t.tables) if (!r.has(e.name)) {
|
|
1079
|
-
a.push(
|
|
1113
|
+
a.push(Ct(e.name, e.columns, e.indexes, e.primaryKey));
|
|
1080
1114
|
for (let t of e.columns) {
|
|
1081
|
-
let n =
|
|
1115
|
+
let n = _t(e.name, t);
|
|
1082
1116
|
n && a.push(n);
|
|
1083
1117
|
}
|
|
1084
1118
|
}
|
|
1085
1119
|
let o = new Set(e.ignoreTables ?? []);
|
|
1086
|
-
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));
|
|
1087
1121
|
for (let o of t.tables) {
|
|
1088
1122
|
let t = r.get(o.name);
|
|
1089
1123
|
if (!t) continue;
|
|
1090
|
-
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);
|
|
1091
1125
|
a.push(...u.ops);
|
|
1092
1126
|
for (let e of c.removed) {
|
|
1093
1127
|
if (u.consumedRemovedNames.has(e.name)) continue;
|
|
1094
1128
|
let t = s.columnDefs[e.name];
|
|
1095
|
-
a.push(
|
|
1129
|
+
a.push(St(o.name, e, t));
|
|
1096
1130
|
}
|
|
1097
1131
|
for (let e of c.added) {
|
|
1098
1132
|
if (u.consumedAddedNames.has(e.name)) continue;
|
|
1099
1133
|
let t = s.columnDefs[e.name];
|
|
1100
|
-
a.push(
|
|
1101
|
-
let n =
|
|
1134
|
+
a.push(xt(o.name, e, t));
|
|
1135
|
+
let n = _t(o.name, e);
|
|
1102
1136
|
n && a.push(n);
|
|
1103
1137
|
}
|
|
1104
|
-
for (let e of l.added) a.push(
|
|
1105
|
-
for (let e of l.removed) a.push(
|
|
1106
|
-
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));
|
|
1107
1141
|
}
|
|
1108
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) => {
|
|
1109
1143
|
let t = c.get(e);
|
|
@@ -1111,8 +1145,8 @@ BEGIN
|
|
|
1111
1145
|
column: e.name,
|
|
1112
1146
|
target: e.references.table
|
|
1113
1147
|
}] : []) : [];
|
|
1114
|
-
}, u =
|
|
1115
|
-
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({
|
|
1116
1150
|
kind: "add-foreign-key",
|
|
1117
1151
|
table: e.name,
|
|
1118
1152
|
column: t.name,
|
|
@@ -1127,8 +1161,8 @@ BEGIN
|
|
|
1127
1161
|
let n = a[t];
|
|
1128
1162
|
if (n.op.kind !== "create-table") continue;
|
|
1129
1163
|
let r = n.op;
|
|
1130
|
-
if (!r.columns.some((e) => u.has(
|
|
1131
|
-
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);
|
|
1132
1166
|
a[t] = {
|
|
1133
1167
|
...n,
|
|
1134
1168
|
op: {
|
|
@@ -1148,7 +1182,7 @@ BEGIN
|
|
|
1148
1182
|
let i = new Set(t).add(e), a = 0;
|
|
1149
1183
|
for (let t of r.columns) {
|
|
1150
1184
|
let n = t.references?.table;
|
|
1151
|
-
n && n !== e && !u.has(
|
|
1185
|
+
n && n !== e && !u.has(C(e, t.name)) && (a = Math.max(a, m(n, i) + 1));
|
|
1152
1186
|
}
|
|
1153
1187
|
return p.set(e, a), a;
|
|
1154
1188
|
}, h = (e) => e === "create-table" ? 0 : e === "drop-table" ? 2 : 1, g = (e) => {
|
|
@@ -1183,11 +1217,11 @@ BEGIN
|
|
|
1183
1217
|
});
|
|
1184
1218
|
return {
|
|
1185
1219
|
operations: v,
|
|
1186
|
-
fromFingerprint:
|
|
1187
|
-
toFingerprint:
|
|
1188
|
-
summary:
|
|
1220
|
+
fromFingerprint: N(e.live),
|
|
1221
|
+
toFingerprint: N(t),
|
|
1222
|
+
summary: jt(v)
|
|
1189
1223
|
};
|
|
1190
|
-
},
|
|
1224
|
+
}, Nt = (e) => {
|
|
1191
1225
|
let t = /[`"[]?([A-Za-z_][A-Za-z0-9_]*)[`"\]]?\s*(?:in\b|=)/i.exec(e);
|
|
1192
1226
|
if (!t) return null;
|
|
1193
1227
|
let n = [...e.matchAll(/'((?:[^']|'')*)'/g)].map((e) => e[1].replace(/''/g, "'"));
|
|
@@ -1195,7 +1229,7 @@ BEGIN
|
|
|
1195
1229
|
column: t[1],
|
|
1196
1230
|
values: n
|
|
1197
1231
|
};
|
|
1198
|
-
},
|
|
1232
|
+
}, Pt = (e, t) => {
|
|
1199
1233
|
if (t === "vector") return "vector";
|
|
1200
1234
|
switch (e) {
|
|
1201
1235
|
case "text":
|
|
@@ -1222,7 +1256,7 @@ BEGIN
|
|
|
1222
1256
|
case "USER-DEFINED": return "text";
|
|
1223
1257
|
default: return "text";
|
|
1224
1258
|
}
|
|
1225
|
-
},
|
|
1259
|
+
}, B = (e) => {
|
|
1226
1260
|
switch (e.toUpperCase()) {
|
|
1227
1261
|
case "CASCADE": return "cascade";
|
|
1228
1262
|
case "RESTRICT": return "restrict";
|
|
@@ -1230,25 +1264,25 @@ BEGIN
|
|
|
1230
1264
|
case "SET DEFAULT": return "noAction";
|
|
1231
1265
|
default: return "noAction";
|
|
1232
1266
|
}
|
|
1233
|
-
},
|
|
1267
|
+
}, Ft = (e, t) => {
|
|
1234
1268
|
let n = e !== void 0 && e !== "" ? Number(e) : NaN;
|
|
1235
1269
|
return Number.isInteger(n) && n > 0 ? n : t;
|
|
1236
|
-
},
|
|
1270
|
+
}, It = () => Ft(process.env.VOLTRO_INTROSPECT_BATCH, 20), Lt = 300, Rt = () => {
|
|
1237
1271
|
let e = process.env.VOLTRO_INTROSPECT_TIMEOUT_MS;
|
|
1238
|
-
return e !== void 0 && e.trim() === "0" ? 0 :
|
|
1239
|
-
},
|
|
1272
|
+
return e !== void 0 && e.trim() === "0" ? 0 : Ft(e, 3e4);
|
|
1273
|
+
}, zt = (e, t) => {
|
|
1240
1274
|
let n = Number.isFinite(t) && t >= 1 ? Math.floor(t) : 1, r = [];
|
|
1241
1275
|
for (let t = 0; t < e.length; t += n) r.push(e.slice(t, t + n));
|
|
1242
1276
|
return r;
|
|
1243
|
-
},
|
|
1244
|
-
let t =
|
|
1277
|
+
}, Bt = (e) => {
|
|
1278
|
+
let t = Rt(), n = d.gen(function* () {
|
|
1245
1279
|
t > 0 && (yield* e.unsafe(`SET LOCAL statement_timeout = ${t}`));
|
|
1246
|
-
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* () {
|
|
1247
1281
|
let r = [];
|
|
1248
|
-
for (let a of
|
|
1282
|
+
for (let a of zt(e, i)) a.length !== 0 && r.push(...yield* t(n(a)));
|
|
1249
1283
|
return r;
|
|
1250
1284
|
}), o = [];
|
|
1251
|
-
for (let t = 0;; t +=
|
|
1285
|
+
for (let t = 0;; t += Lt) {
|
|
1252
1286
|
let n = yield* e`
|
|
1253
1287
|
SELECT c.relname AS table_name,
|
|
1254
1288
|
COALESCE(c.reltuples::bigint, 0) AS row_count
|
|
@@ -1256,9 +1290,9 @@ BEGIN
|
|
|
1256
1290
|
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
1257
1291
|
WHERE n.nspname = current_schema() AND c.relkind = 'r'
|
|
1258
1292
|
ORDER BY c.relname
|
|
1259
|
-
LIMIT ${r(
|
|
1293
|
+
LIMIT ${r(Lt)} OFFSET ${r(t)}
|
|
1260
1294
|
`;
|
|
1261
|
-
if (o.push(...n), n.length <
|
|
1295
|
+
if (o.push(...n), n.length < Lt) break;
|
|
1262
1296
|
}
|
|
1263
1297
|
let s = /* @__PURE__ */ new Set(), c = [];
|
|
1264
1298
|
for (let e of o) s.has(e.table_name) || (s.add(e.table_name), c.push(e));
|
|
@@ -1343,7 +1377,7 @@ BEGIN
|
|
|
1343
1377
|
AND c.relname IN ${t}
|
|
1344
1378
|
)
|
|
1345
1379
|
SELECT * FROM ix ORDER BY table_name, index_name, position
|
|
1346
|
-
`), _ = /* @__PURE__ */ new Map(), v = /* @__PURE__ */ new Map(), y = /* @__PURE__ */ new Map(), b = /* @__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();
|
|
1347
1381
|
for (let e of u) {
|
|
1348
1382
|
let t = _.get(e.table_name);
|
|
1349
1383
|
t || (t = [], _.set(e.table_name, t)), t.push(e);
|
|
@@ -1352,18 +1386,18 @@ BEGIN
|
|
|
1352
1386
|
let t = v.get(e.table_name);
|
|
1353
1387
|
t || (t = /* @__PURE__ */ new Set(), v.set(e.table_name, t)), t.add(e.column_name);
|
|
1354
1388
|
}
|
|
1355
|
-
let
|
|
1389
|
+
let C = /* @__PURE__ */ new Map();
|
|
1356
1390
|
for (let e of p) {
|
|
1357
|
-
let t = `${e.table_name}${e.constraint_name}`, n =
|
|
1391
|
+
let t = `${e.table_name}${e.constraint_name}`, n = C.get(t);
|
|
1358
1392
|
n || (n = {
|
|
1359
1393
|
table: e.table_name,
|
|
1360
1394
|
columns: []
|
|
1361
|
-
},
|
|
1395
|
+
}, C.set(t, n)), n.columns.push({
|
|
1362
1396
|
name: e.column_name,
|
|
1363
1397
|
position: e.position
|
|
1364
1398
|
});
|
|
1365
1399
|
}
|
|
1366
|
-
for (let [e, t] of
|
|
1400
|
+
for (let [e, t] of C) {
|
|
1367
1401
|
let n = [...t.columns].sort((e, t) => e.position - t.position).map((e) => e.name);
|
|
1368
1402
|
if (n.length === 1) {
|
|
1369
1403
|
let e = y.get(t.table);
|
|
@@ -1379,23 +1413,23 @@ BEGIN
|
|
|
1379
1413
|
}
|
|
1380
1414
|
}
|
|
1381
1415
|
for (let e of g) {
|
|
1382
|
-
let t =
|
|
1383
|
-
t || (t = [],
|
|
1416
|
+
let t = x.get(e.source_table);
|
|
1417
|
+
t || (t = [], x.set(e.source_table, t)), t.push(e);
|
|
1384
1418
|
}
|
|
1385
1419
|
for (let e of ee) {
|
|
1386
|
-
let t =
|
|
1387
|
-
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));
|
|
1388
1422
|
let n = t.get(e.index_name);
|
|
1389
1423
|
n || (n = [], t.set(e.index_name, n)), n.push(e);
|
|
1390
1424
|
}
|
|
1391
|
-
let
|
|
1425
|
+
let w = [];
|
|
1392
1426
|
for (let e of c) {
|
|
1393
|
-
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 =
|
|
1394
|
-
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 ? {
|
|
1395
1429
|
table: a.target_table,
|
|
1396
1430
|
column: a.target_column,
|
|
1397
|
-
onDelete:
|
|
1398
|
-
onUpdate:
|
|
1431
|
+
onDelete: B(a.delete_rule),
|
|
1432
|
+
onUpdate: B(a.update_rule)
|
|
1399
1433
|
} : void 0, l = h.get(`${e.table_name}.${t.column_name}`);
|
|
1400
1434
|
return {
|
|
1401
1435
|
name: t.column_name,
|
|
@@ -1407,7 +1441,7 @@ BEGIN
|
|
|
1407
1441
|
...c ? { references: c } : {},
|
|
1408
1442
|
...l ? { oneOf: l } : {}
|
|
1409
1443
|
};
|
|
1410
|
-
}), l = [], u =
|
|
1444
|
+
}), l = [], u = S.get(e.table_name);
|
|
1411
1445
|
if (u) for (let [t, n] of u) {
|
|
1412
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) => {
|
|
1413
1447
|
let t = e.position;
|
|
@@ -1431,20 +1465,20 @@ BEGIN
|
|
|
1431
1465
|
unique: !0
|
|
1432
1466
|
});
|
|
1433
1467
|
let d = Number(e.row_count ?? 0);
|
|
1434
|
-
|
|
1468
|
+
w.push({
|
|
1435
1469
|
name: e.table_name,
|
|
1436
1470
|
columns: c,
|
|
1437
1471
|
indexes: l,
|
|
1438
1472
|
...d > 0 ? { rowCount: d } : {}
|
|
1439
1473
|
});
|
|
1440
1474
|
}
|
|
1441
|
-
return { tables:
|
|
1475
|
+
return { tables: w };
|
|
1442
1476
|
});
|
|
1443
1477
|
return (t > 0 ? e.withTransaction(n) : n).pipe(d.catchAll((e) => {
|
|
1444
1478
|
let n = `${String(e)} ${String(e.cause ?? "")}`.toLowerCase();
|
|
1445
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);
|
|
1446
1480
|
}));
|
|
1447
|
-
},
|
|
1481
|
+
}, Vt = (e, t) => {
|
|
1448
1482
|
switch (e.toLowerCase()) {
|
|
1449
1483
|
case "varchar":
|
|
1450
1484
|
case "char":
|
|
@@ -1476,20 +1510,20 @@ BEGIN
|
|
|
1476
1510
|
case "json": return "json";
|
|
1477
1511
|
default: return "text";
|
|
1478
1512
|
}
|
|
1479
|
-
},
|
|
1513
|
+
}, V = (e) => e.map((e) => {
|
|
1480
1514
|
let t = e, n = {};
|
|
1481
1515
|
for (let e of Object.keys(t)) n[e.toLowerCase()] = t[e];
|
|
1482
1516
|
return n;
|
|
1483
|
-
}),
|
|
1484
|
-
let t =
|
|
1517
|
+
}), Ht = (e) => d.gen(function* () {
|
|
1518
|
+
let t = V(yield* e`
|
|
1485
1519
|
SELECT table_name, COALESCE(table_rows, 0) AS table_rows
|
|
1486
1520
|
FROM information_schema.tables
|
|
1487
1521
|
WHERE table_schema = DATABASE() AND table_type = 'BASE TABLE'
|
|
1488
|
-
ORDER BY table_name`), n =
|
|
1522
|
+
ORDER BY table_name`), n = V(yield* e`
|
|
1489
1523
|
SELECT table_name, column_name, data_type, column_type, is_nullable, column_default, column_key
|
|
1490
1524
|
FROM information_schema.columns
|
|
1491
1525
|
WHERE table_schema = DATABASE()
|
|
1492
|
-
ORDER BY table_name, ordinal_position`), r =
|
|
1526
|
+
ORDER BY table_name, ordinal_position`), r = V(yield* e`
|
|
1493
1527
|
SELECT k.table_name AS source_table,
|
|
1494
1528
|
k.column_name AS source_column,
|
|
1495
1529
|
k.referenced_table_name AS target_table,
|
|
@@ -1499,11 +1533,11 @@ BEGIN
|
|
|
1499
1533
|
JOIN information_schema.referential_constraints r
|
|
1500
1534
|
ON k.constraint_name = r.constraint_name
|
|
1501
1535
|
AND k.table_schema = r.constraint_schema
|
|
1502
|
-
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`
|
|
1503
1537
|
SELECT table_name, index_name, non_unique, column_name, seq_in_index
|
|
1504
1538
|
FROM information_schema.statistics
|
|
1505
1539
|
WHERE table_schema = DATABASE() AND index_name <> 'PRIMARY'
|
|
1506
|
-
ORDER BY table_name, index_name, seq_in_index`), a =
|
|
1540
|
+
ORDER BY table_name, index_name, seq_in_index`), a = V(yield* e`
|
|
1507
1541
|
SELECT table_name, check_clause
|
|
1508
1542
|
FROM information_schema.check_constraints
|
|
1509
1543
|
WHERE constraint_schema = DATABASE()`.unprepared.pipe(d.orElseSucceed(() => []))), o = /* @__PURE__ */ new Set(), s = /* @__PURE__ */ new Map();
|
|
@@ -1513,7 +1547,7 @@ BEGIN
|
|
|
1513
1547
|
o.add(`${e.table_name}.${t[1]}`);
|
|
1514
1548
|
continue;
|
|
1515
1549
|
}
|
|
1516
|
-
let n =
|
|
1550
|
+
let n = Nt(e.check_clause);
|
|
1517
1551
|
n && s.set(`${e.table_name}.${n.column}`, n.values);
|
|
1518
1552
|
}
|
|
1519
1553
|
let c = /* @__PURE__ */ new Map(), l = /* @__PURE__ */ new Map(), u = /* @__PURE__ */ new Map();
|
|
@@ -1536,11 +1570,11 @@ BEGIN
|
|
|
1536
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);
|
|
1537
1571
|
if (d) for (let e of d.values()) e.length === 1 && e[0].non_unique === 0 && a.add(e[0].column_name);
|
|
1538
1572
|
let p = t.map((t) => {
|
|
1539
|
-
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 ? {
|
|
1540
1574
|
table: c.target_table,
|
|
1541
1575
|
column: c.target_column,
|
|
1542
|
-
onDelete:
|
|
1543
|
-
onUpdate:
|
|
1576
|
+
onDelete: B(c.delete_rule),
|
|
1577
|
+
onUpdate: B(c.update_rule)
|
|
1544
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}`);
|
|
1545
1579
|
return {
|
|
1546
1580
|
name: t.column_name,
|
|
@@ -1577,10 +1611,10 @@ BEGIN
|
|
|
1577
1611
|
});
|
|
1578
1612
|
}
|
|
1579
1613
|
return { tables: f };
|
|
1580
|
-
}),
|
|
1614
|
+
}), Ut = (e) => {
|
|
1581
1615
|
let t = e.toUpperCase();
|
|
1582
1616
|
return t.includes("INT") ? "integer" : t.includes("REAL") || t.includes("FLOA") || t.includes("DOUB") ? "real" : t.includes("BLOB") ? "bytes" : "text";
|
|
1583
|
-
},
|
|
1617
|
+
}, Wt = (e) => d.gen(function* () {
|
|
1584
1618
|
let t = yield* e`
|
|
1585
1619
|
SELECT name, sql FROM sqlite_master
|
|
1586
1620
|
WHERE type = 'table' AND name NOT LIKE 'sqlite_%'
|
|
@@ -1597,11 +1631,11 @@ BEGIN
|
|
|
1597
1631
|
d.set(t.name, r), t.unique === 1 && r.length === 1 && f.add(r[0]);
|
|
1598
1632
|
}
|
|
1599
1633
|
let p = o.map((e) => {
|
|
1600
|
-
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 ? {
|
|
1601
1635
|
table: r.table,
|
|
1602
1636
|
column: r.to,
|
|
1603
|
-
onDelete:
|
|
1604
|
-
onUpdate:
|
|
1637
|
+
onDelete: B(r.on_delete),
|
|
1638
|
+
onUpdate: B(r.on_update)
|
|
1605
1639
|
} : void 0, o = t.get(e.name);
|
|
1606
1640
|
return {
|
|
1607
1641
|
name: e.name,
|
|
@@ -1636,7 +1670,7 @@ BEGIN
|
|
|
1636
1670
|
});
|
|
1637
1671
|
}
|
|
1638
1672
|
return { tables: r };
|
|
1639
|
-
}),
|
|
1673
|
+
}), Gt = (e) => {
|
|
1640
1674
|
switch (e.toLowerCase()) {
|
|
1641
1675
|
case "int":
|
|
1642
1676
|
case "smallint":
|
|
@@ -1658,7 +1692,7 @@ BEGIN
|
|
|
1658
1692
|
case "image": return "bytes";
|
|
1659
1693
|
default: return "text";
|
|
1660
1694
|
}
|
|
1661
|
-
},
|
|
1695
|
+
}, H = (e) => e === !0 || e === 1, Kt = (e) => d.gen(function* () {
|
|
1662
1696
|
let t = yield* e`
|
|
1663
1697
|
SELECT TABLE_NAME AS table_name FROM INFORMATION_SCHEMA.TABLES
|
|
1664
1698
|
WHERE TABLE_TYPE = 'BASE TABLE' ORDER BY TABLE_NAME`, n = yield* e`
|
|
@@ -1714,16 +1748,16 @@ BEGIN
|
|
|
1714
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();
|
|
1715
1749
|
if (a) for (let [, e] of a) {
|
|
1716
1750
|
let t = [...e].sort((e, t) => e.key_ordinal - t.key_ordinal);
|
|
1717
|
-
if (
|
|
1718
|
-
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);
|
|
1719
1753
|
}
|
|
1720
1754
|
let p = t.map((t) => {
|
|
1721
|
-
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 ? {
|
|
1722
1756
|
table: i.target_table,
|
|
1723
1757
|
column: i.target_column,
|
|
1724
|
-
onDelete:
|
|
1725
|
-
onUpdate:
|
|
1726
|
-
} : 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}`);
|
|
1727
1761
|
return {
|
|
1728
1762
|
name: t.column_name,
|
|
1729
1763
|
type: a,
|
|
@@ -1737,11 +1771,11 @@ BEGIN
|
|
|
1737
1771
|
}), m = [];
|
|
1738
1772
|
if (a) for (let [t, n] of a) {
|
|
1739
1773
|
let r = [...n].sort((e, t) => e.key_ordinal - t.key_ordinal);
|
|
1740
|
-
|
|
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({
|
|
1741
1775
|
name: t,
|
|
1742
1776
|
table: e,
|
|
1743
1777
|
columns: r.map((e) => e.column_name),
|
|
1744
|
-
unique:
|
|
1778
|
+
unique: H(r[0].is_unique)
|
|
1745
1779
|
});
|
|
1746
1780
|
}
|
|
1747
1781
|
d.length > 0 && m.push({
|
|
@@ -1756,37 +1790,37 @@ BEGIN
|
|
|
1756
1790
|
});
|
|
1757
1791
|
}
|
|
1758
1792
|
return { tables: u };
|
|
1759
|
-
}),
|
|
1793
|
+
}), qt = (e) => {
|
|
1760
1794
|
switch (e.toUpperCase().replace(/_/g, " ")) {
|
|
1761
1795
|
case "CASCADE": return "cascade";
|
|
1762
1796
|
case "SET NULL": return "setNull";
|
|
1763
1797
|
case "SET DEFAULT": return "noAction";
|
|
1764
1798
|
default: return "noAction";
|
|
1765
1799
|
}
|
|
1766
|
-
},
|
|
1800
|
+
}, Jt = (e) => {
|
|
1767
1801
|
let t = e.trim();
|
|
1768
1802
|
for (; t.startsWith("(") && t.endsWith(")");) t = t.slice(1, -1).trim();
|
|
1769
1803
|
return t.startsWith("N'") && t.endsWith("'") ? t = t.slice(2, -1) : t.startsWith("'") && t.endsWith("'") && (t = t.slice(1, -1)), t;
|
|
1770
|
-
},
|
|
1771
|
-
mysql: () =>
|
|
1772
|
-
mssql: () =>
|
|
1773
|
-
sqlite: () =>
|
|
1774
|
-
orElse: () =>
|
|
1775
|
-
}),
|
|
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) => {
|
|
1776
1810
|
if (!e.spatial && e.type !== "vector" && e.type !== "array" && e.type !== "enum") return;
|
|
1777
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;
|
|
1778
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.`);
|
|
1779
|
-
return
|
|
1780
|
-
},
|
|
1781
|
-
let t =
|
|
1782
|
-
return t === void 0 ?
|
|
1783
|
-
},
|
|
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) => {
|
|
1784
1818
|
switch (e.type) {
|
|
1785
1819
|
case "id": return "text";
|
|
1786
1820
|
case "text": return "text";
|
|
1787
1821
|
case "integer": return "integer";
|
|
1788
1822
|
case "real": return "double precision";
|
|
1789
|
-
case "decimal": return
|
|
1823
|
+
case "decimal": return Xt(e, "NUMERIC");
|
|
1790
1824
|
case "bigint": return "bigint";
|
|
1791
1825
|
case "boolean": return "boolean";
|
|
1792
1826
|
case "timestamp": return "timestamptz";
|
|
@@ -1800,15 +1834,15 @@ BEGIN
|
|
|
1800
1834
|
case "interval": return "interval";
|
|
1801
1835
|
case "raw": return e.rawDdl ?? "text";
|
|
1802
1836
|
}
|
|
1803
|
-
},
|
|
1804
|
-
let t =
|
|
1837
|
+
}, en = (e) => {
|
|
1838
|
+
let t = Zt(e, "mariadb");
|
|
1805
1839
|
if (t !== void 0) return t;
|
|
1806
1840
|
switch (e.type) {
|
|
1807
1841
|
case "id": return "VARCHAR(64)";
|
|
1808
1842
|
case "text": return e.hasDefault && e.defaultValue !== void 0 || e.oneOf && e.oneOf.length > 0 ? "VARCHAR(255)" : "LONGTEXT";
|
|
1809
1843
|
case "integer": return "INT";
|
|
1810
1844
|
case "real": return "DOUBLE";
|
|
1811
|
-
case "decimal": return
|
|
1845
|
+
case "decimal": return Xt(e, "DECIMAL");
|
|
1812
1846
|
case "bigint": return "BIGINT";
|
|
1813
1847
|
case "boolean": return "TINYINT(1)";
|
|
1814
1848
|
case "timestamp": return "DATETIME(6)";
|
|
@@ -1822,82 +1856,82 @@ BEGIN
|
|
|
1822
1856
|
case "interval": return "BIGINT";
|
|
1823
1857
|
case "raw": return e.rawDdl ?? "LONGTEXT";
|
|
1824
1858
|
}
|
|
1825
|
-
},
|
|
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) => {
|
|
1826
1860
|
let n = t(e.defaultValue);
|
|
1827
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.`);
|
|
1828
1862
|
return n;
|
|
1829
|
-
},
|
|
1830
|
-
let r =
|
|
1831
|
-
return r ?
|
|
1832
|
-
},
|
|
1833
|
-
let r = n ?? e.nullable, i =
|
|
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");
|
|
1834
1868
|
return [
|
|
1835
|
-
|
|
1836
|
-
|
|
1869
|
+
W(t),
|
|
1870
|
+
O(e, "mariadb"),
|
|
1837
1871
|
r ? null : "NOT NULL",
|
|
1838
1872
|
i
|
|
1839
1873
|
].filter(Boolean).join(" ");
|
|
1840
|
-
},
|
|
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) => {
|
|
1841
1875
|
if (!e.generatedAs) return null;
|
|
1842
1876
|
let { expr: n, stored: r } = e.generatedAs;
|
|
1843
1877
|
return t === "postgres" ? `GENERATED ALWAYS AS (${n}) STORED` : t === "mssql" ? `AS (${n})${r ? " PERSISTED" : ""}` : `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
|
|
1844
|
-
},
|
|
1845
|
-
if (e.type === "id" && e.idScheme?.kind === "numeric") return
|
|
1846
|
-
let t =
|
|
1847
|
-
if (t) return `${
|
|
1848
|
-
let n = [
|
|
1878
|
+
}, pn = (e) => {
|
|
1879
|
+
if (e.type === "id" && e.idScheme?.kind === "numeric") return A(e.name, "postgres");
|
|
1880
|
+
let t = K(e, "postgres");
|
|
1881
|
+
if (t) return `${U(e.name)} ${Qt(e)} ${t}`;
|
|
1882
|
+
let n = [U(e.name), Qt(e)];
|
|
1849
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) {
|
|
1850
|
-
let t =
|
|
1884
|
+
let t = fn(e.defaultValue, e);
|
|
1851
1885
|
t && n.push(t);
|
|
1852
1886
|
}
|
|
1853
|
-
return e.references && (n.push(`REFERENCES ${
|
|
1887
|
+
return e.references && (n.push(`REFERENCES ${U(e.references.table)} (${U(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${{
|
|
1854
1888
|
cascade: "CASCADE",
|
|
1855
1889
|
restrict: "RESTRICT",
|
|
1856
1890
|
setNull: "SET NULL",
|
|
1857
1891
|
noAction: "NO ACTION"
|
|
1858
1892
|
}[e.references.onDelete]}`)), n.join(" ");
|
|
1859
|
-
},
|
|
1860
|
-
let t = e.columns.map((e) => ` ${
|
|
1861
|
-
for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${
|
|
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(", ")})`);
|
|
1862
1896
|
return n;
|
|
1863
|
-
},
|
|
1864
|
-
let t =
|
|
1897
|
+
}, hn = 191, J = (e) => {
|
|
1898
|
+
let t = en(e).toUpperCase();
|
|
1865
1899
|
return t.endsWith("TEXT") || t.endsWith("BLOB");
|
|
1866
|
-
},
|
|
1867
|
-
if (e.type === "id" && e.idScheme?.kind === "numeric") return
|
|
1868
|
-
let t =
|
|
1869
|
-
if (t) return `${
|
|
1870
|
-
let n = [
|
|
1871
|
-
if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && !
|
|
1872
|
-
let t =
|
|
1900
|
+
}, gn = (e) => {
|
|
1901
|
+
if (e.type === "id" && e.idScheme?.kind === "numeric") return A(e.name, "mariadb");
|
|
1902
|
+
let t = K(e, "mariadb");
|
|
1903
|
+
if (t) return `${W(e.name)} ${en(e)} ${t}`;
|
|
1904
|
+
let n = [W(e.name), en(e)];
|
|
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) {
|
|
1906
|
+
let t = un(e.defaultValue, e);
|
|
1873
1907
|
t && n.push(t);
|
|
1874
1908
|
}
|
|
1875
|
-
return e.references && (n.push(`REFERENCES ${
|
|
1909
|
+
return e.references && (n.push(`REFERENCES ${W(e.references.table)} (${W(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${{
|
|
1876
1910
|
cascade: "CASCADE",
|
|
1877
1911
|
restrict: "RESTRICT",
|
|
1878
1912
|
setNull: "SET NULL",
|
|
1879
1913
|
noAction: "NO ACTION"
|
|
1880
1914
|
}[e.references.onDelete]}`)), n.join(" ");
|
|
1881
|
-
},
|
|
1915
|
+
}, _n = (e) => {
|
|
1882
1916
|
let t = new Map(e.columns.map((e) => [e.name, e])), n = (e) => {
|
|
1883
1917
|
let n = t.get(e);
|
|
1884
|
-
return n &&
|
|
1885
|
-
}, r = e.columns.map((e) => ` ${
|
|
1886
|
-
for (let t of e.columns) t.unique && t.type !== "id" &&
|
|
1887
|
-
for (let t of e.indexes) t.name !== `${e.table}_pkey` && i.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${
|
|
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)`];
|
|
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)})`);
|
|
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(", ")})`);
|
|
1888
1922
|
return i;
|
|
1889
|
-
},
|
|
1923
|
+
}, vn = {
|
|
1890
1924
|
cascade: "CASCADE",
|
|
1891
1925
|
restrict: "RESTRICT",
|
|
1892
1926
|
setNull: "SET NULL",
|
|
1893
1927
|
noAction: "NO ACTION"
|
|
1894
|
-
},
|
|
1928
|
+
}, yn = {
|
|
1895
1929
|
cascade: "CASCADE",
|
|
1896
1930
|
restrict: "NO ACTION",
|
|
1897
1931
|
setNull: "SET NULL",
|
|
1898
1932
|
noAction: "NO ACTION"
|
|
1899
|
-
},
|
|
1900
|
-
let t =
|
|
1933
|
+
}, bn = (e) => {
|
|
1934
|
+
let t = Zt(e, "sqlite");
|
|
1901
1935
|
if (t !== void 0) return t;
|
|
1902
1936
|
switch (e.type) {
|
|
1903
1937
|
case "integer":
|
|
@@ -1908,60 +1942,60 @@ BEGIN
|
|
|
1908
1942
|
case "bytes": return "BLOB";
|
|
1909
1943
|
default: return "TEXT";
|
|
1910
1944
|
}
|
|
1911
|
-
}, 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" ?
|
|
1912
|
-
if (e.type === "id" && e.idScheme?.kind === "numeric") return
|
|
1913
|
-
let t =
|
|
1914
|
-
if (t) return `${
|
|
1915
|
-
let n = [
|
|
1945
|
+
}, Y = (e, t) => e == null ? null : e === "now" ? `DEFAULT ${t}` : typeof e == "boolean" ? `DEFAULT ${+!!e}` : typeof e == "number" ? `DEFAULT ${e}` : typeof e == "string" ? /[()]|^'/.test(e) ? `DEFAULT ${e}` : `DEFAULT '${e.replace(/'/g, "''")}'` : typeof e == "object" ? k(e, "sqlite") : null, xn = (e) => {
|
|
1946
|
+
if (e.type === "id" && e.idScheme?.kind === "numeric") return A(e.name, "sqlite");
|
|
1947
|
+
let t = K(e, "sqlite");
|
|
1948
|
+
if (t) return `${U(e.name)} ${bn(e)} ${t}`;
|
|
1949
|
+
let n = [U(e.name), bn(e)];
|
|
1916
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) {
|
|
1917
1951
|
let t = Y(e.defaultValue, "CURRENT_TIMESTAMP");
|
|
1918
1952
|
t && n.push(t);
|
|
1919
1953
|
}
|
|
1920
|
-
if (e.references && (n.push(`REFERENCES ${
|
|
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) {
|
|
1921
1955
|
let t = e.oneOf.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
|
|
1922
|
-
n.push(`CHECK (${
|
|
1956
|
+
n.push(`CHECK (${U(e.name)} IN (${t}))`);
|
|
1923
1957
|
}
|
|
1924
1958
|
return n.join(" ");
|
|
1925
|
-
},
|
|
1926
|
-
let t = e.columns.map((e) => ` ${
|
|
1927
|
-
for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${
|
|
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)`];
|
|
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(", ")})`);
|
|
1928
1962
|
return n;
|
|
1929
1963
|
}, X = (e, t) => {
|
|
1930
1964
|
let n = t.find((t) => t.tableName === e);
|
|
1931
1965
|
if (!n) return [];
|
|
1932
|
-
let r =
|
|
1933
|
-
...
|
|
1966
|
+
let r = F([n]).tables[0], i = `${e}__voltro_rebuild`, a = r.columns.map((e) => U(e.name)).join(", "), o = [
|
|
1967
|
+
...Sn({
|
|
1934
1968
|
kind: "create-table",
|
|
1935
1969
|
table: i,
|
|
1936
1970
|
columns: r.columns,
|
|
1937
1971
|
indexes: [],
|
|
1938
1972
|
...r.primaryKey ? { primaryKey: r.primaryKey } : {}
|
|
1939
1973
|
}),
|
|
1940
|
-
`INSERT INTO ${
|
|
1941
|
-
`DROP TABLE ${
|
|
1942
|
-
`ALTER TABLE ${
|
|
1974
|
+
`INSERT INTO ${U(i)} (${a}) SELECT ${a} FROM ${U(e)}`,
|
|
1975
|
+
`DROP TABLE ${U(e)}`,
|
|
1976
|
+
`ALTER TABLE ${U(i)} RENAME TO ${U(e)}`
|
|
1943
1977
|
];
|
|
1944
|
-
for (let t of r.indexes) t.name !== `${e}_pkey` && o.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${
|
|
1978
|
+
for (let t of r.indexes) t.name !== `${e}_pkey` && o.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${U(t.name)} ON ${U(e)} (${t.columns.map(U).join(", ")})`);
|
|
1945
1979
|
return o;
|
|
1946
|
-
},
|
|
1980
|
+
}, Cn = (e, t, n, r) => {
|
|
1947
1981
|
let i = r ?? e.nullable;
|
|
1948
|
-
return `ALTER TABLE ${Z(n)} ALTER COLUMN ${Z(t)} ${
|
|
1949
|
-
},
|
|
1982
|
+
return `ALTER TABLE ${Z(n)} ALTER COLUMN ${Z(t)} ${O(e, "mssql")} ${i ? "NULL" : "NOT NULL"};`;
|
|
1983
|
+
}, wn = (e) => {
|
|
1950
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 + ']');`;
|
|
1951
1985
|
if (!e.hasDefault) return t;
|
|
1952
1986
|
let n = Y(e.defaultValue, "SYSUTCDATETIME()");
|
|
1953
1987
|
if (!n) return t;
|
|
1954
1988
|
let r = n.replace(/^DEFAULT\s+/i, "");
|
|
1955
1989
|
return `${t} ALTER TABLE ${Z(e.table)} ADD DEFAULT ${r} FOR ${Z(e.column)};`;
|
|
1956
|
-
}, Z = (e) => `[${e.replace(/]/g, "]]")}]`,
|
|
1957
|
-
let t =
|
|
1990
|
+
}, Z = (e) => `[${e.replace(/]/g, "]]")}]`, Tn = (e) => {
|
|
1991
|
+
let t = Zt(e, "mssql");
|
|
1958
1992
|
if (t !== void 0) return t;
|
|
1959
1993
|
switch (e.type) {
|
|
1960
1994
|
case "id":
|
|
1961
1995
|
case "reference": return "NVARCHAR(64)";
|
|
1962
1996
|
case "integer": return "INT";
|
|
1963
1997
|
case "real": return "FLOAT";
|
|
1964
|
-
case "decimal": return
|
|
1998
|
+
case "decimal": return Xt(e, "DECIMAL");
|
|
1965
1999
|
case "bigint": return "BIGINT";
|
|
1966
2000
|
case "boolean": return "BIT";
|
|
1967
2001
|
case "timestamp": return "DATETIME2(6)";
|
|
@@ -1969,34 +2003,34 @@ BEGIN
|
|
|
1969
2003
|
case "bytes": return "VARBINARY(MAX)";
|
|
1970
2004
|
default: return "NVARCHAR(MAX)";
|
|
1971
2005
|
}
|
|
1972
|
-
},
|
|
1973
|
-
if (e.type === "id" && e.idScheme?.kind === "numeric") return
|
|
1974
|
-
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");
|
|
1975
2009
|
if (r) return `${Z(e.name)} ${r}`;
|
|
1976
2010
|
let i = [Z(e.name), n];
|
|
1977
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) {
|
|
1978
2012
|
let t = Y(e.defaultValue, "SYSUTCDATETIME()");
|
|
1979
2013
|
t && i.push(t);
|
|
1980
2014
|
}
|
|
1981
|
-
return e.references && (i.push(`REFERENCES ${Z(e.references.table)} (${Z(e.references.column)})`), e.references.onDelete && i.push(`ON DELETE ${
|
|
1982
|
-
},
|
|
1983
|
-
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)}')`];
|
|
1984
2018
|
for (let n of e.indexes) {
|
|
1985
2019
|
if (n.name === `${e.table}_pkey`) continue;
|
|
1986
2020
|
let r = `CREATE ${n.unique ? "UNIQUE " : ""}INDEX ${Z(n.name)} ON ${Z(e.table)} (${n.columns.map(Z).join(", ")})`;
|
|
1987
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)}')`);
|
|
1988
2022
|
}
|
|
1989
2023
|
return a;
|
|
1990
|
-
},
|
|
1991
|
-
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)}`;
|
|
1992
2026
|
return `ALTER TABLE ${n(e.table)} RENAME TO ${n(r)};`;
|
|
1993
|
-
},
|
|
1994
|
-
let r =
|
|
1995
|
-
return r ?
|
|
1996
|
-
},
|
|
2027
|
+
}, jn = (e, t, n) => {
|
|
2028
|
+
let r = G(e, t, n);
|
|
2029
|
+
return r ? J({ type: r.type }) : !1;
|
|
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) => {
|
|
1997
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(", ")})`;
|
|
1998
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)}');`;
|
|
1999
|
-
},
|
|
2033
|
+
}, Bn = (e, t, n) => {
|
|
2000
2034
|
let r = n.find((t) => t.tableName === e);
|
|
2001
2035
|
if (!r) return [];
|
|
2002
2036
|
let i = [];
|
|
@@ -2005,13 +2039,13 @@ BEGIN
|
|
|
2005
2039
|
t && t.type === "text" && !t.generatedAs && i.push(`ALTER TABLE ${Z(e)} ALTER COLUMN ${Z(n)} NVARCHAR(450) ${t.nullable ? "NULL" : "NOT NULL"};`);
|
|
2006
2040
|
}
|
|
2007
2041
|
return i;
|
|
2008
|
-
},
|
|
2009
|
-
let t = e.fields.map((e) =>
|
|
2010
|
-
return `ALTER TABLE ${
|
|
2011
|
-
},
|
|
2012
|
-
let n = e.fields.map((n) =>
|
|
2013
|
-
return `ALTER TABLE ${
|
|
2014
|
-
},
|
|
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) => {
|
|
2043
|
+
let t = e.fields.map((e) => U(e)).join(", ");
|
|
2044
|
+
return `ALTER TABLE ${U(e.table)} ADD CONSTRAINT ${U(e.name)} UNIQUE (${t});`;
|
|
2045
|
+
}, Wn = (e, t) => {
|
|
2046
|
+
let n = e.fields.map((n) => Mn(t, e.table, n)).join(", ");
|
|
2047
|
+
return `ALTER TABLE ${W(e.table)} ADD CONSTRAINT ${W(e.name)} UNIQUE (${n});`;
|
|
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) => {
|
|
2015
2049
|
let n = [], r = t(e.table), i = t(e.column), a = t(e.targetTable), o = t(e.targetColumn);
|
|
2016
2050
|
if (e.orphanPolicy) {
|
|
2017
2051
|
let t = `${i} IS NOT NULL AND ${i} NOT IN (SELECT ${o} FROM ${a})`;
|
|
@@ -2029,11 +2063,11 @@ BEGIN
|
|
|
2029
2063
|
setNull: "SET NULL",
|
|
2030
2064
|
noAction: "NO ACTION"
|
|
2031
2065
|
}[e.onDelete]}`), n.push(s.join(" ") + ";"), n;
|
|
2032
|
-
},
|
|
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) => {
|
|
2033
2067
|
let n = e.values.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
|
|
2034
2068
|
return `ALTER TABLE ${t(e.table)} ADD CONSTRAINT ${t(`${e.table}_${e.column}_check`)} CHECK (${t(e.column)} IN (${n}));`;
|
|
2035
|
-
},
|
|
2036
|
-
let i = e.column, a = r === "mariadb", o = 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);
|
|
2037
2071
|
if (u) {
|
|
2038
2072
|
let t = r === "mssql" ? `${o(i.name)} ${u}` : `${o(i.name)} ${s} ${u}`;
|
|
2039
2073
|
return {
|
|
@@ -2061,7 +2095,7 @@ BEGIN
|
|
|
2061
2095
|
post: f ? [f] : []
|
|
2062
2096
|
};
|
|
2063
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;
|
|
2064
|
-
},
|
|
2098
|
+
}, nr = (e) => {
|
|
2065
2099
|
let t = new Map(e.map((e) => [e.tableName, e]));
|
|
2066
2100
|
return (e, n) => {
|
|
2067
2101
|
let r = t.get(e);
|
|
@@ -2083,95 +2117,95 @@ BEGIN
|
|
|
2083
2117
|
};
|
|
2084
2118
|
}, Q = (e, t, n) => e.unsafe(t).pipe(d.tapError((e) => d.sync(() => {
|
|
2085
2119
|
process.stderr.write(_(`applier: statement failed (op=${n})`, t, e, 400));
|
|
2086
|
-
})), d.map(() => void 0)), $ = (e, t, n) => d.forEach(t, (t) => Q(e, t, n), { discard: !0 }),
|
|
2087
|
-
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;
|
|
2088
2122
|
switch (a.kind) {
|
|
2089
2123
|
case "create-table": {
|
|
2090
2124
|
let t = yield* e.onDialectOrElse({
|
|
2091
|
-
mysql: () => d.succeed(
|
|
2092
|
-
mssql: () => d.succeed(
|
|
2093
|
-
sqlite: () => d.succeed(
|
|
2094
|
-
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))
|
|
2095
2129
|
});
|
|
2096
2130
|
for (let n of t) yield* Q(e, n, a.kind);
|
|
2097
2131
|
break;
|
|
2098
2132
|
}
|
|
2099
2133
|
case "drop-table": {
|
|
2100
|
-
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);
|
|
2101
2135
|
yield* e.onDialectOrElse({
|
|
2102
|
-
mysql: () => Q(e, r(
|
|
2103
|
-
orElse: () => Q(e, r(
|
|
2136
|
+
mysql: () => Q(e, r(W), a.kind),
|
|
2137
|
+
orElse: () => Q(e, r(U), a.kind)
|
|
2104
2138
|
});
|
|
2105
2139
|
break;
|
|
2106
2140
|
}
|
|
2107
2141
|
case "drop-column": {
|
|
2108
2142
|
let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString();
|
|
2109
2143
|
yield* e.onDialectOrElse({
|
|
2110
|
-
mysql: () => Q(e, t ?
|
|
2111
|
-
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)
|
|
2112
2146
|
});
|
|
2113
2147
|
break;
|
|
2114
2148
|
}
|
|
2115
2149
|
case "rename-column":
|
|
2116
2150
|
yield* e.onDialectOrElse({
|
|
2117
|
-
mysql: () => Q(e,
|
|
2151
|
+
mysql: () => Q(e, rn(a, W), a.kind),
|
|
2118
2152
|
mssql: () => Q(e, `EXEC sp_rename N'${a.table.replace(/'/g, "''")}.${a.from.replace(/'/g, "''")}', N'${a.to.replace(/'/g, "''")}', 'COLUMN';`, a.kind),
|
|
2119
|
-
orElse: () => Q(e,
|
|
2153
|
+
orElse: () => Q(e, rn(a, U), a.kind)
|
|
2120
2154
|
});
|
|
2121
2155
|
break;
|
|
2122
2156
|
case "add-index":
|
|
2123
2157
|
yield* e.onDialectOrElse({
|
|
2124
|
-
mysql: () => Q(e,
|
|
2125
|
-
mssql: () => $(e, [...
|
|
2126
|
-
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)
|
|
2127
2161
|
});
|
|
2128
2162
|
break;
|
|
2129
2163
|
case "drop-index":
|
|
2130
2164
|
yield* e.onDialectOrElse({
|
|
2131
|
-
mysql: () => Q(e,
|
|
2132
|
-
mssql: () => Q(e,
|
|
2133
|
-
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)
|
|
2134
2168
|
});
|
|
2135
2169
|
break;
|
|
2136
2170
|
case "add-unique":
|
|
2137
2171
|
yield* e.onDialectOrElse({
|
|
2138
|
-
mysql: () => Q(e,
|
|
2172
|
+
mysql: () => Q(e, Hn(a, n.declared), a.kind),
|
|
2139
2173
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2140
|
-
mssql: () => $(e, [...
|
|
2141
|
-
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)
|
|
2142
2176
|
});
|
|
2143
2177
|
break;
|
|
2144
2178
|
case "drop-unique":
|
|
2145
2179
|
yield* e.onDialectOrElse({
|
|
2146
|
-
mysql: () => Q(e,
|
|
2180
|
+
mysql: () => Q(e, Jn(a), a.kind),
|
|
2147
2181
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2148
|
-
orElse: () => Q(e,
|
|
2182
|
+
orElse: () => Q(e, qn(a), a.kind)
|
|
2149
2183
|
});
|
|
2150
2184
|
break;
|
|
2151
2185
|
case "add-unique-composite":
|
|
2152
2186
|
yield* e.onDialectOrElse({
|
|
2153
|
-
mysql: () => Q(e,
|
|
2187
|
+
mysql: () => Q(e, Wn(a, n.declared), a.kind),
|
|
2154
2188
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2155
|
-
mssql: () => $(e, [...
|
|
2156
|
-
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)
|
|
2157
2191
|
});
|
|
2158
2192
|
break;
|
|
2159
2193
|
case "drop-unique-composite":
|
|
2160
2194
|
yield* e.onDialectOrElse({
|
|
2161
|
-
mysql: () => Q(e,
|
|
2195
|
+
mysql: () => Q(e, Kn(a), a.kind),
|
|
2162
2196
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2163
|
-
orElse: () => Q(e,
|
|
2197
|
+
orElse: () => Q(e, Gn(a), a.kind)
|
|
2164
2198
|
});
|
|
2165
2199
|
break;
|
|
2166
2200
|
case "add-foreign-key":
|
|
2167
2201
|
yield* e.onDialectOrElse({
|
|
2168
|
-
mysql: () => $(e,
|
|
2202
|
+
mysql: () => $(e, Yn(a, W), a.kind),
|
|
2169
2203
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2170
|
-
orElse: () => $(e,
|
|
2204
|
+
orElse: () => $(e, Yn(a, U), a.kind)
|
|
2171
2205
|
});
|
|
2172
2206
|
break;
|
|
2173
2207
|
case "add-column": {
|
|
2174
|
-
let n =
|
|
2208
|
+
let n = tr(a, t, i, yield* e.onDialectOrElse({
|
|
2175
2209
|
mysql: () => d.succeed("mariadb"),
|
|
2176
2210
|
mssql: () => d.succeed("mssql"),
|
|
2177
2211
|
sqlite: () => d.succeed("sqlite"),
|
|
@@ -2216,41 +2250,41 @@ BEGIN
|
|
|
2216
2250
|
case "alter-column-nullability":
|
|
2217
2251
|
yield* e.onDialectOrElse({
|
|
2218
2252
|
mysql: () => {
|
|
2219
|
-
let t =
|
|
2220
|
-
return t ? Q(e, `ALTER TABLE ${
|
|
2253
|
+
let t = G(n.declared, a.table, a.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.`));
|
|
2221
2255
|
},
|
|
2222
2256
|
mssql: () => {
|
|
2223
|
-
let t =
|
|
2224
|
-
return t ? Q(e,
|
|
2257
|
+
let t = G(n.declared, a.table, a.column);
|
|
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}'.`));
|
|
2225
2259
|
},
|
|
2226
2260
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2227
|
-
orElse: () => Q(e, `ALTER TABLE ${
|
|
2261
|
+
orElse: () => Q(e, `ALTER TABLE ${U(a.table)} ALTER COLUMN ${U(a.column)} ${a.toNullable ? "DROP NOT NULL" : "SET NOT NULL"};`, a.kind)
|
|
2228
2262
|
});
|
|
2229
2263
|
break;
|
|
2230
2264
|
case "alter-column-default": {
|
|
2231
|
-
let t =
|
|
2265
|
+
let t = cn(n.declared, a.table, a.column);
|
|
2232
2266
|
yield* e.onDialectOrElse({
|
|
2233
|
-
mysql: () => Q(e,
|
|
2234
|
-
mssql: () => Q(e,
|
|
2267
|
+
mysql: () => Q(e, on(a, W, (e) => un(e, t)), a.kind),
|
|
2268
|
+
mssql: () => Q(e, wn(a), a.kind),
|
|
2235
2269
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2236
|
-
orElse: () => Q(e,
|
|
2270
|
+
orElse: () => Q(e, on(a, U, (e) => fn(e, t)), a.kind)
|
|
2237
2271
|
});
|
|
2238
2272
|
break;
|
|
2239
2273
|
}
|
|
2240
2274
|
case "alter-column-type": {
|
|
2241
|
-
let r =
|
|
2275
|
+
let r = Qt(cn(n.declared, a.table, a.column) ?? { type: a.to }), i = a.using ? ` USING ${a.using}` : "";
|
|
2242
2276
|
if (t.classification !== "online-required") {
|
|
2243
2277
|
yield* e.onDialectOrElse({
|
|
2244
2278
|
mysql: () => {
|
|
2245
|
-
let t =
|
|
2246
|
-
return t ? Q(e, `ALTER TABLE ${
|
|
2279
|
+
let t = G(n.declared, a.table, a.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.`));
|
|
2247
2281
|
},
|
|
2248
2282
|
mssql: () => {
|
|
2249
|
-
let t =
|
|
2250
|
-
return t ? Q(e,
|
|
2283
|
+
let t = G(n.declared, a.table, a.column);
|
|
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}'.`));
|
|
2251
2285
|
},
|
|
2252
2286
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2253
|
-
orElse: () => Q(e, `ALTER TABLE ${
|
|
2287
|
+
orElse: () => Q(e, `ALTER TABLE ${U(a.table)} ALTER COLUMN ${U(a.column)} TYPE ${r}${i};`, a.kind)
|
|
2254
2288
|
});
|
|
2255
2289
|
break;
|
|
2256
2290
|
}
|
|
@@ -2259,35 +2293,35 @@ BEGIN
|
|
|
2259
2293
|
orElse: () => d.void
|
|
2260
2294
|
});
|
|
2261
2295
|
let o = `${a.column}__shadow`, s = `${a.column}__old`;
|
|
2262
|
-
yield* e.unsafe(`ALTER TABLE ${
|
|
2263
|
-
let c = a.using ??
|
|
2296
|
+
yield* e.unsafe(`ALTER TABLE ${U(a.table)} ADD COLUMN ${U(o)} ${r}`);
|
|
2297
|
+
let c = a.using ?? U(a.column), l;
|
|
2264
2298
|
for (;;) {
|
|
2265
2299
|
let t = l === void 0 ? yield* e`SELECT ${e("id")} FROM ${e(a.table)} WHERE ${e(o)} IS NULL ORDER BY ${e("id")} LIMIT 5000` : yield* e`SELECT ${e("id")} FROM ${e(a.table)} WHERE ${e(o)} IS NULL AND ${e("id")} > ${l} ORDER BY ${e("id")} LIMIT 5000`;
|
|
2266
2300
|
if (t.length === 0) break;
|
|
2267
|
-
yield* e.unsafe(`UPDATE ${
|
|
2301
|
+
yield* e.unsafe(`UPDATE ${U(a.table)} SET ${U(o)} = ${c} WHERE ${U(a.column)} IS NOT NULL AND ${U(o)} IS NULL AND ${U("id")} IN (${t.map((e) => `'${e.id.replace(/'/g, "''")}'`).join(",")})`), l = t[t.length - 1].id;
|
|
2268
2302
|
}
|
|
2269
|
-
yield* d.logInfo(`alter-column-type shadow ${a.table}.${a.column}: shadow populated`).pipe(d.annotateLogs({ scope: "voltro:migrate" })), yield* e.unsafe(`ALTER TABLE ${
|
|
2303
|
+
yield* d.logInfo(`alter-column-type shadow ${a.table}.${a.column}: shadow populated`).pipe(d.annotateLogs({ scope: "voltro:migrate" })), yield* e.unsafe(`ALTER TABLE ${U(a.table)} RENAME COLUMN ${U(a.column)} TO ${U(s)}`), yield* e.unsafe(`ALTER TABLE ${U(a.table)} RENAME COLUMN ${U(o)} TO ${U(a.column)}`), yield* e.unsafe(`ALTER TABLE ${U(a.table)} DROP COLUMN ${U(s)}`);
|
|
2270
2304
|
break;
|
|
2271
2305
|
}
|
|
2272
2306
|
case "drop-foreign-key":
|
|
2273
2307
|
yield* e.onDialectOrElse({
|
|
2274
|
-
mysql: () => Q(e,
|
|
2308
|
+
mysql: () => Q(e, Zn(a), a.kind),
|
|
2275
2309
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2276
|
-
orElse: () => Q(e,
|
|
2310
|
+
orElse: () => Q(e, Xn(a), a.kind)
|
|
2277
2311
|
});
|
|
2278
2312
|
break;
|
|
2279
2313
|
case "add-check":
|
|
2280
2314
|
yield* e.onDialectOrElse({
|
|
2281
|
-
mysql: () => Q(e,
|
|
2315
|
+
mysql: () => Q(e, Qn(a, W), a.kind),
|
|
2282
2316
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2283
|
-
orElse: () => Q(e,
|
|
2317
|
+
orElse: () => Q(e, Qn(a, U), a.kind)
|
|
2284
2318
|
});
|
|
2285
2319
|
break;
|
|
2286
2320
|
case "drop-check":
|
|
2287
2321
|
yield* e.onDialectOrElse({
|
|
2288
|
-
mysql: () => Q(e,
|
|
2322
|
+
mysql: () => Q(e, er(a), a.kind),
|
|
2289
2323
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2290
|
-
orElse: () => Q(e,
|
|
2324
|
+
orElse: () => Q(e, $n(a), a.kind)
|
|
2291
2325
|
});
|
|
2292
2326
|
break;
|
|
2293
2327
|
}
|
|
@@ -2296,10 +2330,10 @@ BEGIN
|
|
|
2296
2330
|
status: "applied",
|
|
2297
2331
|
durationMs: Number((process.hrtime.bigint() - r) / 1000000n)
|
|
2298
2332
|
};
|
|
2299
|
-
}),
|
|
2333
|
+
}), ir = (e, t, n) => d.gen(function* () {
|
|
2300
2334
|
let r = t.operations.filter((e) => e.blocked);
|
|
2301
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.`));
|
|
2302
|
-
yield*
|
|
2336
|
+
yield* T(e);
|
|
2303
2337
|
let i = Date.now(), a = [];
|
|
2304
2338
|
try {
|
|
2305
2339
|
let r = yield* e.onDialectOrElse({
|
|
@@ -2309,11 +2343,11 @@ BEGIN
|
|
|
2309
2343
|
}), i = r ? t.operations.filter((e) => e.classification !== "online-required") : [], o = r ? t.operations.filter((e) => e.classification === "online-required") : t.operations;
|
|
2310
2344
|
i.length > 0 && (yield* e.withTransaction(d.gen(function* () {
|
|
2311
2345
|
let e = yield* p.SqlClient;
|
|
2312
|
-
for (let t of i) a.push(yield*
|
|
2346
|
+
for (let t of i) a.push(yield* rr(e, t, n));
|
|
2313
2347
|
})));
|
|
2314
|
-
for (let t of o) a.push(yield*
|
|
2348
|
+
for (let t of o) a.push(yield* rr(e, t, n));
|
|
2315
2349
|
} finally {
|
|
2316
|
-
yield*
|
|
2350
|
+
yield* E(e).pipe(d.orDie);
|
|
2317
2351
|
}
|
|
2318
2352
|
let o = yield* n.replan(e);
|
|
2319
2353
|
if (o.operations.length > 0) {
|
|
@@ -2345,19 +2379,19 @@ BEGIN
|
|
|
2345
2379
|
source: n.source,
|
|
2346
2380
|
...n.notes ? { notes: n.notes } : {}
|
|
2347
2381
|
};
|
|
2348
|
-
}),
|
|
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`
|
|
2349
2383
|
SELECT fingerprint
|
|
2350
2384
|
FROM _voltro_migration_plans
|
|
2351
2385
|
ORDER BY ${e("appliedAt")} DESC
|
|
2352
2386
|
LIMIT 1
|
|
2353
|
-
`.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({
|
|
2354
2388
|
pg: () => "postgres",
|
|
2355
2389
|
mysql: () => "mysql",
|
|
2356
2390
|
mssql: () => "mssql",
|
|
2357
2391
|
sqlite: () => "sqlite",
|
|
2358
2392
|
orElse: () => "sqlite"
|
|
2359
|
-
}),
|
|
2360
|
-
let n =
|
|
2393
|
+
}), cr = (e, t) => d.gen(function* () {
|
|
2394
|
+
let n = N(F(t, sr(e))), r = yield* or(e);
|
|
2361
2395
|
return r === n ? {
|
|
2362
2396
|
kind: "up-to-date",
|
|
2363
2397
|
fingerprint: n
|
|
@@ -2366,97 +2400,126 @@ BEGIN
|
|
|
2366
2400
|
expected: n,
|
|
2367
2401
|
...r === void 0 ? {} : { actual: r }
|
|
2368
2402
|
};
|
|
2369
|
-
}),
|
|
2403
|
+
}), lr = [
|
|
2370
2404
|
"pgeagertest_",
|
|
2371
2405
|
"mig_e2e_",
|
|
2372
2406
|
"mig_test_",
|
|
2373
2407
|
"mysqleagertest_",
|
|
2374
2408
|
"mssqleagertest_",
|
|
2375
2409
|
"sqliteeagertest_"
|
|
2376
|
-
],
|
|
2410
|
+
], ur = (e) => lr.some((t) => e.startsWith(t)), dr = (e, t) => d.gen(function* () {
|
|
2377
2411
|
if (process.env.VOLTRO_TEST_FIXTURE_GC === "off") return [];
|
|
2378
|
-
let n = t.filter((e) =>
|
|
2412
|
+
let n = t.filter((e) => ur(e.name)).map((e) => e.name);
|
|
2379
2413
|
if (n.length === 0) return [];
|
|
2380
2414
|
for (let t of n) yield* e.unsafe(`DROP TABLE IF EXISTS "${t}" CASCADE`).pipe(d.catchAll(() => d.void));
|
|
2381
2415
|
return n;
|
|
2382
|
-
}),
|
|
2416
|
+
}), fr = () => {
|
|
2383
2417
|
let e = (process.env.VOLTRO_DB_IGNORE_TABLES ?? "").split(",").map((e) => e.trim()).filter((e) => e.length > 0);
|
|
2384
2418
|
return e.length > 0 ? { ignoreTables: e } : {};
|
|
2385
|
-
},
|
|
2419
|
+
}, pr = (e) => {
|
|
2420
|
+
if (e === void 0) return;
|
|
2421
|
+
let t = e.trim();
|
|
2422
|
+
if (t === "") return;
|
|
2423
|
+
if (t === "1" || t.toLowerCase() === "true") return { kind: "all" };
|
|
2424
|
+
let n = t.split(",").map((e) => e.trim()).filter((e) => e.length > 0);
|
|
2425
|
+
return n.length > 0 ? {
|
|
2426
|
+
kind: "tables",
|
|
2427
|
+
tables: new Set(n)
|
|
2428
|
+
} : void 0;
|
|
2429
|
+
}, mr = (e) => typeof e.table == "string" ? e.table : void 0, hr = (e, t = { kind: "all" }) => ({
|
|
2386
2430
|
...e,
|
|
2387
2431
|
operations: e.operations.map((e) => {
|
|
2388
2432
|
if (!e.blocked || e.classification !== "lossy") return e;
|
|
2389
|
-
|
|
2390
|
-
|
|
2433
|
+
if (t?.kind === "tables") {
|
|
2434
|
+
let n = mr(e.op);
|
|
2435
|
+
if (n === void 0 || !t.tables.has(n)) return e;
|
|
2436
|
+
}
|
|
2437
|
+
let { blocked: n, ...r } = e;
|
|
2438
|
+
return r;
|
|
2391
2439
|
})
|
|
2392
|
-
}),
|
|
2393
|
-
let
|
|
2440
|
+
}), gr = (e, t, n) => t === "postgres" ? at(e, n).pipe(d.flatMap((e) => {
|
|
2441
|
+
let t = ot(e);
|
|
2442
|
+
return t === void 0 ? d.void : d.logWarning(`auto-migrate: ${t}`).pipe(d.annotateLogs({ scope: "voltro:migrate" }));
|
|
2443
|
+
}), d.catchAll(() => d.void)) : d.void, _r = (e, t, n) => d.gen(function* () {
|
|
2444
|
+
let r = sr(e), i = t.filter((e) => !I(e.tableName));
|
|
2394
2445
|
if (process.env.VOLTRO_MIGRATE_FORCE !== "1") {
|
|
2395
|
-
let t =
|
|
2396
|
-
if ((yield*
|
|
2446
|
+
let t = N(F(i, r));
|
|
2447
|
+
if ((yield* or(e)) === t) return yield* gr(e, r, i), {
|
|
2397
2448
|
kind: "up-to-date",
|
|
2398
2449
|
fingerprint: t
|
|
2399
2450
|
};
|
|
2400
2451
|
}
|
|
2401
|
-
let a = yield*
|
|
2452
|
+
let a = yield* Yt(e), o = yield* dr(e, a.tables);
|
|
2402
2453
|
o.length > 0 && (yield* d.logInfo(`auto-migrate: reaped ${o.length} test-fixture leftover(s)`).pipe(d.annotateLogs({
|
|
2403
2454
|
scope: "voltro:migrate",
|
|
2404
2455
|
count: o.length
|
|
2405
|
-
})), a = yield*
|
|
2406
|
-
let s =
|
|
2456
|
+
})), a = yield* Yt(e));
|
|
2457
|
+
let s = Mt({
|
|
2407
2458
|
declared: i,
|
|
2408
|
-
live: { tables: a.tables.filter((e) => !
|
|
2459
|
+
live: { tables: a.tables.filter((e) => !I(e.name)) },
|
|
2409
2460
|
dialect: r,
|
|
2410
|
-
...
|
|
2461
|
+
...fr()
|
|
2411
2462
|
});
|
|
2412
2463
|
if (s.summary.blocked > 0) {
|
|
2413
|
-
let e = s.operations.filter((e) => e.blocked).every((e) => e.classification === "lossy");
|
|
2414
|
-
if (
|
|
2464
|
+
let e = s.operations.filter((e) => e.blocked).every((e) => e.classification === "lossy"), t = pr(process.env.VOLTRO_DESTRUCTIVE_OK);
|
|
2465
|
+
if (t === void 0 || !e || (s = hr(s, t), s.operations.some((e) => e.blocked))) return {
|
|
2415
2466
|
kind: "refused-blocked",
|
|
2416
2467
|
plan: s
|
|
2417
2468
|
};
|
|
2418
|
-
s = ur(s);
|
|
2419
2469
|
}
|
|
2420
2470
|
return s.operations.length === 0 ? {
|
|
2421
2471
|
kind: "up-to-date",
|
|
2422
2472
|
fingerprint: s.toFingerprint
|
|
2423
2473
|
} : {
|
|
2424
2474
|
kind: "applied",
|
|
2425
|
-
applied: yield*
|
|
2475
|
+
applied: yield* ir(e, s, {
|
|
2426
2476
|
declared: t,
|
|
2427
2477
|
appliedBy: n.appliedBy,
|
|
2428
2478
|
environment: n.environment === "prod" ? "dev" : n.environment,
|
|
2429
2479
|
source: "auto-diff",
|
|
2430
2480
|
replan: (e) => d.gen(function* () {
|
|
2431
|
-
let t = yield*
|
|
2432
|
-
return
|
|
2481
|
+
let t = yield* Yt(e);
|
|
2482
|
+
return Mt({
|
|
2433
2483
|
declared: i,
|
|
2434
|
-
live: { tables: t.tables.filter((e) => !
|
|
2484
|
+
live: { tables: t.tables.filter((e) => !I(e.name)) },
|
|
2435
2485
|
dialect: r,
|
|
2436
|
-
...
|
|
2486
|
+
...fr()
|
|
2437
2487
|
});
|
|
2438
2488
|
})
|
|
2439
2489
|
}),
|
|
2440
2490
|
plan: s
|
|
2441
2491
|
};
|
|
2442
|
-
}),
|
|
2492
|
+
}), vr = (e, t, n) => process.env.VOLTRO_AUTO_MIGRATE === "0" ? d.succeed({
|
|
2443
2493
|
kind: "skipped",
|
|
2444
2494
|
reason: "VOLTRO_AUTO_MIGRATE=0"
|
|
2445
|
-
}) : n.environment === "prod" ?
|
|
2495
|
+
}) : n.environment === "prod" ? cr(e, t) : _r(e, t, n), yr = (e, t) => {
|
|
2446
2496
|
switch (e.kind) {
|
|
2447
2497
|
case "skipped": return `auto-migrate: skipped (${e.reason})`;
|
|
2448
|
-
case "up-to-date": return `auto-migrate: schema up to date (${t}, fingerprint=${
|
|
2498
|
+
case "up-to-date": return `auto-migrate: schema up to date (${t}, fingerprint=${P(e.fingerprint)})`;
|
|
2449
2499
|
case "applied": {
|
|
2450
2500
|
let t = e.plan.summary;
|
|
2451
|
-
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=${
|
|
2501
|
+
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)}`;
|
|
2452
2502
|
}
|
|
2453
|
-
case "prod-mismatch": return `auto-migrate: SCHEMA FINGERPRINT MISMATCH — declared=${
|
|
2503
|
+
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.";
|
|
2454
2504
|
case "refused-blocked": {
|
|
2455
|
-
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,
|
|
2456
|
-
|
|
2505
|
+
let t = e.plan.operations.filter((e) => e.blocked), n = t.filter((e) => e.op.kind === "drop-table").length, r = t.filter((e) => e.op.kind === "drop-table").map((e) => "table" in e.op ? e.op.table : "").filter(Boolean), i = t.filter((e) => e.op.kind === "add-column").length, a = t.filter((e) => e.op.kind === "drop-column").length, o = t.filter((e) => e.classification === "needs-rename-annotation").length, s = `auto-migrate: REFUSED — ${e.plan.summary.blocked} blocked operation(s):\n` + ar(e.plan), c = [""];
|
|
2506
|
+
if (n > 0 && c.push(`${n} table(s) exist in the live DB but aren't in your declared schema.`, "This is usually one of three things:", " (a) You're iterating on the schema — the table file got renamed, moved, or temporarily commented out.", " → Restore the declaration. Your data stays intact.", " (b) You want to KEEP the table but NOT manage it with Voltro (a leftover from another tool —", " a Strapi/Rails/legacy migration artifact, or an externally-owned table).", ` → Set \`VOLTRO_DB_IGNORE_TABLES=${r.join(",")}\` (comma-separated).`, " The planner excludes those tables from the diff entirely — it never drops them, and they", " stop blocking your OTHER (additive) changes. This is the fix when a leftover freezes your schema.", " (c) You actually want to drop the table.", ` → Set \`VOLTRO_DESTRUCTIVE_OK=${r.join(",")}\` for ONE run — it acknowledges`, " the data loss for THOSE tables only; every other lossy op in this plan stays blocked.", " (`VOLTRO_DESTRUCTIVE_OK=1` acknowledges all of them, which is rarely what you mean.)", " There is deliberately no `dropped()` marker for a TABLE, unlike for a column: a", " dropped column leaves a slot worth documenting in the declaration, a dropped table", " leaves nothing — the marker would be a dead entry you must remember to delete.", " Soft-drop: set `VOLTRO_SOFT_DROP=1` alongside DESTRUCTIVE_OK to RENAME instead of DROP", " (data survives as `<name>__dropped_<ts>` for ~7d; restorable via `voltro db restore-snapshot`)."), i > 0 && c.push(`${i} required column(s) need a backfill strategy before adding to a populated table.`, " → Annotate the column: `.backfill(sql`<expr>`)` or `.backfill(row => <fn>)` or `.default(<value>)`.", " Existing rows get the backfill value; the column then lands as NOT NULL."), a > 0) {
|
|
2507
|
+
let t = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map();
|
|
2508
|
+
for (let r of e.plan.operations) {
|
|
2509
|
+
let e = "table" in r.op ? r.op.table : void 0;
|
|
2510
|
+
if (e === void 0) continue;
|
|
2511
|
+
let i = "column" in r.op ? String(r.op.column) : void 0;
|
|
2512
|
+
if (i === void 0) continue;
|
|
2513
|
+
let a = r.op.kind === "drop-column" ? t : r.op.kind === "add-column" ? n : void 0;
|
|
2514
|
+
a !== void 0 && a.set(e, [...a.get(e) ?? [], i]);
|
|
2515
|
+
}
|
|
2516
|
+
let r = [...t.entries()].filter(([e]) => (n.get(e)?.length ?? 0) > 0).map(([e, t]) => `${e}: ${t.join(", ")} gone, ${n.get(e).join(", ")} new`);
|
|
2517
|
+
c.push(`${a} column(s) are missing from your declared schema.`), r.length > 0 && c.push(" → DID YOU RENAME ONE? This plan drops AND adds columns on the same table:", ...r.map((e) => ` ${e}`), " If so, add `.renamedFrom('<oldName>')` to the NEW column — the planner then emits a", " RENAME and the data moves with it. Dropping and re-adding loses every value."), c.push(" → If intentional: give the field the `dropped()` marker as its VALUE —", " `<column>: dropped()` (import it from `@voltro/database`). It is not a method", " chained onto the column; the slot stays, documenting the hole.", " → If a typo: restore the field. Data survives until you drop it.");
|
|
2518
|
+
}
|
|
2519
|
+
return o > 0 && c.push(`${o} column(s) look like renames (one column gone + a new one of same shape appeared).`, " → On the NEW column add `.renamedFrom('<oldName>')` so the planner emits RENAME instead of DROP+ADD."), c.push("", "See `voltro db plan` for the full machine-readable diff."), s + "\n" + c.join("\n");
|
|
2457
2520
|
}
|
|
2458
2521
|
}
|
|
2459
|
-
},
|
|
2522
|
+
}, br = /* @__PURE__ */ new Set([
|
|
2460
2523
|
"node_modules",
|
|
2461
2524
|
"dist",
|
|
2462
2525
|
"build",
|
|
@@ -2465,11 +2528,11 @@ BEGIN
|
|
|
2465
2528
|
".next",
|
|
2466
2529
|
".git",
|
|
2467
2530
|
".framework"
|
|
2468
|
-
]),
|
|
2531
|
+
]), xr = async (e) => {
|
|
2469
2532
|
let t = [], n = async (e) => {
|
|
2470
2533
|
let r = await h.readdir(e, { withFileTypes: !0 }).catch(() => []);
|
|
2471
2534
|
for (let i of r) {
|
|
2472
|
-
if (
|
|
2535
|
+
if (br.has(i.name)) continue;
|
|
2473
2536
|
let r = g(e, i.name);
|
|
2474
2537
|
i.isDirectory() ? await n(r) : i.isFile() && l.test(i.name) && t.push(r);
|
|
2475
2538
|
}
|
|
@@ -2478,7 +2541,7 @@ BEGIN
|
|
|
2478
2541
|
let n = e.split("/").pop() ?? e, r = t.split("/").pop() ?? t;
|
|
2479
2542
|
return n.localeCompare(r);
|
|
2480
2543
|
});
|
|
2481
|
-
},
|
|
2544
|
+
}, Sr = async (e) => {
|
|
2482
2545
|
let t = [];
|
|
2483
2546
|
for (let n of e) {
|
|
2484
2547
|
let e = (await import(ee(n).href)).default;
|
|
@@ -2492,11 +2555,11 @@ BEGIN
|
|
|
2492
2555
|
});
|
|
2493
2556
|
}
|
|
2494
2557
|
return t;
|
|
2495
|
-
},
|
|
2558
|
+
}, Cr = (e) => e`
|
|
2496
2559
|
SELECT ${e("id")}
|
|
2497
2560
|
FROM ${e("_voltro_migration_plans")}
|
|
2498
2561
|
WHERE ${e("source")} = 'file'
|
|
2499
|
-
`.pipe(d.map((e) => e.map((e) => e.id)), d.catchAll(() => d.succeed([]))),
|
|
2562
|
+
`.pipe(d.map((e) => e.map((e) => e.id)), d.catchAll(() => d.succeed([]))), wr = (e, t, n, r) => d.gen(function* () {
|
|
2500
2563
|
let i = Date.now(), a = (/* @__PURE__ */ new Date()).toISOString(), o = {
|
|
2501
2564
|
sql: e,
|
|
2502
2565
|
log: {
|
|
@@ -2529,70 +2592,76 @@ BEGIN
|
|
|
2529
2592
|
${r}, ${n}, ${"file"},
|
|
2530
2593
|
${c}, ${a}, ${t.migration.description})
|
|
2531
2594
|
`, { durationMs: c };
|
|
2532
|
-
}),
|
|
2595
|
+
}), Tr = (e, t) => d.gen(function* () {
|
|
2533
2596
|
let n = yield* d.tryPromise({
|
|
2534
|
-
try: () =>
|
|
2597
|
+
try: () => xr(g(t, "migrations")),
|
|
2535
2598
|
catch: (e) => e
|
|
2536
2599
|
});
|
|
2537
2600
|
if (n.length === 0) return {
|
|
2538
|
-
|
|
2601
|
+
pending: [],
|
|
2539
2602
|
skipped: []
|
|
2540
2603
|
};
|
|
2541
2604
|
let r = yield* d.tryPromise({
|
|
2542
|
-
try: () =>
|
|
2605
|
+
try: () => Sr(n),
|
|
2543
2606
|
catch: (e) => e
|
|
2544
2607
|
});
|
|
2545
2608
|
if (r.length === 0) return {
|
|
2546
|
-
|
|
2609
|
+
pending: [],
|
|
2547
2610
|
skipped: []
|
|
2548
2611
|
};
|
|
2549
|
-
let i = new Set(yield*
|
|
2550
|
-
|
|
2612
|
+
let i = new Set(yield* Cr(e));
|
|
2613
|
+
return {
|
|
2614
|
+
pending: r.filter((e) => !i.has(e.migration.id)),
|
|
2615
|
+
skipped: r.filter((e) => i.has(e.migration.id)).map((e) => e.migration.id)
|
|
2616
|
+
};
|
|
2617
|
+
}), Er = (e, t) => Tr(e, t).pipe(d.map((e) => e.pending.map((e) => e.migration.id))), Dr = (e, t) => d.gen(function* () {
|
|
2618
|
+
let { pending: n, skipped: r } = yield* Tr(e, t.projectRoot);
|
|
2619
|
+
if (n.length === 0) return {
|
|
2551
2620
|
applied: [],
|
|
2552
|
-
skipped:
|
|
2621
|
+
skipped: r
|
|
2553
2622
|
};
|
|
2554
|
-
yield*
|
|
2555
|
-
let
|
|
2623
|
+
yield* T(e);
|
|
2624
|
+
let i = [];
|
|
2556
2625
|
try {
|
|
2557
|
-
for (let
|
|
2626
|
+
for (let r of n) {
|
|
2558
2627
|
yield* d.logInfo("file-based migration applying").pipe(d.annotateLogs({
|
|
2559
2628
|
scope: "voltro:migrate",
|
|
2560
|
-
id:
|
|
2561
|
-
file:
|
|
2629
|
+
id: r.migration.id,
|
|
2630
|
+
file: r.file
|
|
2562
2631
|
}));
|
|
2563
|
-
let { durationMs:
|
|
2564
|
-
|
|
2565
|
-
id:
|
|
2566
|
-
durationMs:
|
|
2632
|
+
let { durationMs: n } = yield* wr(e, r, t.env, t.appliedBy);
|
|
2633
|
+
i.push({
|
|
2634
|
+
id: r.migration.id,
|
|
2635
|
+
durationMs: n
|
|
2567
2636
|
}), yield* d.logInfo("file-based migration applied").pipe(d.annotateLogs({
|
|
2568
2637
|
scope: "voltro:migrate",
|
|
2569
|
-
id:
|
|
2570
|
-
durationMs:
|
|
2638
|
+
id: r.migration.id,
|
|
2639
|
+
durationMs: n
|
|
2571
2640
|
}));
|
|
2572
2641
|
}
|
|
2573
2642
|
} finally {
|
|
2574
|
-
yield*
|
|
2643
|
+
yield* E(e).pipe(d.orDie);
|
|
2575
2644
|
}
|
|
2576
2645
|
return {
|
|
2577
|
-
applied:
|
|
2578
|
-
skipped:
|
|
2646
|
+
applied: i,
|
|
2647
|
+
skipped: r
|
|
2579
2648
|
};
|
|
2580
|
-
}),
|
|
2649
|
+
}), Or = (e, t) => e`
|
|
2581
2650
|
SELECT ${e("id")}
|
|
2582
2651
|
FROM ${e("_voltro_migration_plans")}
|
|
2583
2652
|
WHERE ${e("id")} = ${t} AND ${e("source")} = 'file'
|
|
2584
2653
|
LIMIT 1
|
|
2585
|
-
`,
|
|
2586
|
-
if (!(yield*
|
|
2654
|
+
`, kr = (e, t) => d.gen(function* () {
|
|
2655
|
+
if (!(yield* Or(e, t.id))[0]) return yield* d.fail(/* @__PURE__ */ Error(`rollback: ${t.id} not found in _voltro_migration_plans (file source)`));
|
|
2587
2656
|
let n = yield* d.tryPromise({
|
|
2588
|
-
try: () =>
|
|
2657
|
+
try: () => xr(g(t.projectRoot, "migrations")),
|
|
2589
2658
|
catch: (e) => e
|
|
2590
2659
|
}), r = (yield* d.tryPromise({
|
|
2591
|
-
try: () =>
|
|
2660
|
+
try: () => Sr(n),
|
|
2592
2661
|
catch: (e) => e
|
|
2593
2662
|
})).find((e) => e.migration.id === t.id);
|
|
2594
2663
|
if (!r) return yield* d.fail(/* @__PURE__ */ Error(`rollback: file for migration ${t.id} not found on disk under ${t.projectRoot}/migrations/`));
|
|
2595
|
-
yield*
|
|
2664
|
+
yield* T(e);
|
|
2596
2665
|
let i = Date.now();
|
|
2597
2666
|
try {
|
|
2598
2667
|
let n = {
|
|
@@ -2619,9 +2688,9 @@ BEGIN
|
|
|
2619
2688
|
durationMs: o
|
|
2620
2689
|
};
|
|
2621
2690
|
} finally {
|
|
2622
|
-
yield*
|
|
2691
|
+
yield* E(e).pipe(d.orDie);
|
|
2623
2692
|
}
|
|
2624
|
-
}),
|
|
2693
|
+
}), Ar = (e) => d.gen(function* () {
|
|
2625
2694
|
let t = yield* p.SqlClient, n = yield* t`
|
|
2626
2695
|
SELECT id, fingerprint, appliedAt FROM _voltro_migration_plans
|
|
2627
2696
|
WHERE source = 'auto-diff'
|
|
@@ -2666,10 +2735,10 @@ BEGIN
|
|
|
2666
2735
|
snapshotFingerprint: e.fingerprint,
|
|
2667
2736
|
snapshotId: i
|
|
2668
2737
|
};
|
|
2669
|
-
}),
|
|
2738
|
+
}), jr = (e, ...t) => ({
|
|
2670
2739
|
_tag: "RawSqlFragment",
|
|
2671
2740
|
strings: [...e],
|
|
2672
2741
|
values: [...t]
|
|
2673
|
-
}),
|
|
2742
|
+
}), Mr = (e) => typeof e == "object" && !!e && e._tag === "RawSqlFragment";
|
|
2674
2743
|
//#endregion
|
|
2675
|
-
export { l as FILE_MIGRATION_PATTERN,
|
|
2744
|
+
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, yr as describeOutcome, pr as destructiveScope, 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, Mr as isRawSqlFragment, Pt as mapPgType, s as migration, A as numericIdSql, Nt as parseEnumCheck, Er as pendingFileMigrationIds, Mt as planMigrations, qe as provisionTenantNamespace, E as releaseMigrationLock, gn as renderColumnMysql, pn as renderColumnPg, kr as rollbackFileBasedMigration, Dr as runFileBasedMigrations, Je as runFrameworkBootstrap, Ge as runMigrate, vr as runPlannedMigrations, P as shortFingerprint, et as snapshotColumn, jr as sql, O as sqlType, Ar as squashMigrationPlans, hr as unblockLossy, he as withMigrationLock };
|