@voltro/database 0.20.2 → 0.21.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 +149 -0
- package/THIRD-PARTY-NOTICES.md +1 -1
- package/dist/index.d.ts +52 -1
- package/dist/index.js +485 -442
- package/dist/sql.d.ts +25 -10
- package/dist/sql.js +313 -278
- package/package.json +4 -4
package/dist/sql.js
CHANGED
|
@@ -74,7 +74,7 @@ var _ = (e, t, n, r = 400) => {
|
|
|
74
74
|
appliedIndexes: r,
|
|
75
75
|
appliedUniques: [...e.appliedUniques ?? [], ...i]
|
|
76
76
|
};
|
|
77
|
-
}, x = (e, t) => `${e}::${t}`,
|
|
77
|
+
}, x = (e, t) => `${e}::${t}`, re = (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));
|
|
@@ -83,43 +83,43 @@ var _ = (e, t, n, r = 400) => {
|
|
|
83
83
|
};
|
|
84
84
|
for (let t of [...e].sort()) r.has(t) || a(t);
|
|
85
85
|
return i;
|
|
86
|
-
},
|
|
86
|
+
}, S = 6322741009312437n, ie = 250, ae = () => {
|
|
87
87
|
let e = Number(process.env.VOLTRO_MIGRATION_LOCK_TIMEOUT_MS);
|
|
88
88
|
return Number.isFinite(e) && e > 0 ? e : 3e4;
|
|
89
|
-
},
|
|
90
|
-
let t =
|
|
89
|
+
}, oe = (e) => d.gen(function* () {
|
|
90
|
+
let t = ae(), n = Date.now();
|
|
91
91
|
for (;;) {
|
|
92
92
|
if ((yield* e`
|
|
93
93
|
SELECT pg_try_advisory_lock(${"6322741009312437"}::bigint) AS got`)[0]?.got) return;
|
|
94
|
-
Date.now() - n >= t && (yield* d.die(/* @__PURE__ */ Error(`could not acquire the postgres migration advisory lock within ${Math.round(t / 1e3)}s. Another migration is in progress, or a prior boot crashed while holding it. (A crashed process's session-level advisory lock is released once its DB connection closes; if this persists, find + terminate the holder via pg_stat_activity, or raise VOLTRO_MIGRATION_LOCK_TIMEOUT_MS.)`))), yield* d.sleep(`${
|
|
94
|
+
Date.now() - n >= t && (yield* d.die(/* @__PURE__ */ Error(`could not acquire the postgres migration advisory lock within ${Math.round(t / 1e3)}s. Another migration is in progress, or a prior boot crashed while holding it. (A crashed process's session-level advisory lock is released once its DB connection closes; if this persists, find + terminate the holder via pg_stat_activity, or raise VOLTRO_MIGRATION_LOCK_TIMEOUT_MS.)`))), yield* d.sleep(`${ie} millis`);
|
|
95
95
|
}
|
|
96
|
-
}),
|
|
97
|
-
yield* e`SELECT pg_advisory_unlock(${
|
|
98
|
-
}),
|
|
96
|
+
}), se = (e) => d.gen(function* () {
|
|
97
|
+
yield* e`SELECT pg_advisory_unlock(${S.toString()}::bigint)`;
|
|
98
|
+
}), ce = `voltro_migration_${S.toString(36)}`, le = 30, ue = (e) => d.gen(function* () {
|
|
99
99
|
(yield* e`
|
|
100
|
-
SELECT GET_LOCK(${
|
|
101
|
-
}),
|
|
102
|
-
yield* e`SELECT RELEASE_LOCK(${
|
|
103
|
-
}),
|
|
100
|
+
SELECT GET_LOCK(${ce}, ${le}) AS got`)[0]?.got !== 1 && (yield* d.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${ce}' within ${le}s (another migration is in progress, or a prior one left it held).`)));
|
|
101
|
+
}), de = (e) => d.gen(function* () {
|
|
102
|
+
yield* e`SELECT RELEASE_LOCK(${ce})`;
|
|
103
|
+
}), fe = `voltro_migration_${S.toString(36)}`, pe = 3e4, me = (e) => d.gen(function* () {
|
|
104
104
|
let t = yield* e`
|
|
105
105
|
DECLARE @res int;
|
|
106
|
-
EXEC @res = sp_getapplock @Resource = ${
|
|
107
|
-
@LockOwner = 'Session', @LockTimeout = ${
|
|
106
|
+
EXEC @res = sp_getapplock @Resource = ${fe}, @LockMode = 'Exclusive',
|
|
107
|
+
@LockOwner = 'Session', @LockTimeout = ${pe};
|
|
108
108
|
SELECT @res AS res`;
|
|
109
|
-
(t[0]?.res ?? -999) < 0 && (yield* d.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${
|
|
110
|
-
}),
|
|
111
|
-
yield* e`EXEC sp_releaseapplock @Resource = ${
|
|
112
|
-
}),
|
|
113
|
-
mysql: () => le(e),
|
|
114
|
-
mssql: () => pe(e),
|
|
115
|
-
sqlite: () => he,
|
|
116
|
-
orElse: () => ae(e)
|
|
117
|
-
}), T = (e) => e.onDialectOrElse({
|
|
109
|
+
(t[0]?.res ?? -999) < 0 && (yield* d.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${fe}' (sp_getapplock returned ${t[0]?.res ?? "no row"}; another migration is in progress).`)));
|
|
110
|
+
}), he = (e) => d.gen(function* () {
|
|
111
|
+
yield* e`EXEC sp_releaseapplock @Resource = ${fe}, @LockOwner = 'Session'`;
|
|
112
|
+
}), ge = d.void, C = (e) => e.onDialectOrElse({
|
|
118
113
|
mysql: () => ue(e),
|
|
119
114
|
mssql: () => me(e),
|
|
120
|
-
sqlite: () =>
|
|
115
|
+
sqlite: () => ge,
|
|
121
116
|
orElse: () => oe(e)
|
|
122
|
-
}),
|
|
117
|
+
}), w = (e) => e.onDialectOrElse({
|
|
118
|
+
mysql: () => de(e),
|
|
119
|
+
mssql: () => he(e),
|
|
120
|
+
sqlite: () => ge,
|
|
121
|
+
orElse: () => se(e)
|
|
122
|
+
}), T = (e, t) => d.acquireUseRelease(C(e), () => t, () => w(e).pipe(d.orDie)), _e = f({ scope: "voltro:migrate" }), E = (e) => {
|
|
123
123
|
_e.warn(e.replace(/^\[voltro:migrate\]\s*/, ""));
|
|
124
124
|
}, D = (e, t) => {
|
|
125
125
|
let n = e.type;
|
|
@@ -431,7 +431,7 @@ CREATE TRIGGER framework_changes_${e.tableName}
|
|
|
431
431
|
AFTER INSERT OR UPDATE OR DELETE ON "${e.tableName}"
|
|
432
432
|
FOR EACH ROW EXECUTE FUNCTION framework_notify_change();
|
|
433
433
|
`.trim(), je = (e) => e.some((e) => Object.values(e.fields).some((e) => e.type === "vector")), Me = (e) => e.some((e) => Object.values(e.fields).some((e) => e.spatial !== void 0)), Ne = (e) => {
|
|
434
|
-
let t = new Map(e.map((e) => [e.tableName, e])), n =
|
|
434
|
+
let t = new Map(e.map((e) => [e.tableName, e])), n = re(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 [];
|
|
@@ -598,7 +598,7 @@ BEGIN
|
|
|
598
598
|
return o.join("\n\n") + "\n";
|
|
599
599
|
}, He = (e, t = "postgres") => d.gen(function* () {
|
|
600
600
|
let n = yield* p.SqlClient;
|
|
601
|
-
yield*
|
|
601
|
+
yield* T(n, Ge(n, A(e, t), t)).pipe(d.orDie);
|
|
602
602
|
}), Ue = (e, t) => {
|
|
603
603
|
let n = t.cause ?? {};
|
|
604
604
|
return (n.errno === 1061 || n.code === "ER_DUP_KEYNAME") && /^\s*CREATE\s+(UNIQUE\s+|FULLTEXT\s+)?INDEX\b/i.test(e);
|
|
@@ -626,13 +626,13 @@ BEGIN
|
|
|
626
626
|
await d.runPromise(He(e, n).pipe(d.provide(t)));
|
|
627
627
|
}, Je = (e, t, n = "postgres") => d.gen(function* () {
|
|
628
628
|
let r = Be(e, n, t), i = yield* p.SqlClient;
|
|
629
|
-
yield*
|
|
629
|
+
yield* T(i, Ge(i, r, n)).pipe(d.orDie);
|
|
630
630
|
}), Ye = async (e, t, n, r = "postgres") => {
|
|
631
631
|
await d.runPromise(Je(e, t, r).pipe(d.provide(n)));
|
|
632
632
|
}, Xe = async (e, t, n = "postgres") => {
|
|
633
633
|
await d.runPromise(d.gen(function* () {
|
|
634
634
|
let t = Ve(e, n), r = yield* p.SqlClient;
|
|
635
|
-
yield*
|
|
635
|
+
yield* T(r, Ge(r, t, n)).pipe(d.orDie);
|
|
636
636
|
}).pipe(d.provide(t)));
|
|
637
637
|
}, Ze = (e) => {
|
|
638
638
|
if (e == null) return e;
|
|
@@ -674,6 +674,7 @@ BEGIN
|
|
|
674
674
|
...t.oneOf && t.oneOf.length > 0 ? { oneOf: t.oneOf } : {},
|
|
675
675
|
...t.idScheme ? { idScheme: { kind: t.idScheme.kind } } : {},
|
|
676
676
|
...t.rawDdl === void 0 ? {} : { rawDdl: t.rawDdl },
|
|
677
|
+
...t.maxLength === void 0 ? {} : { maxLength: t.maxLength },
|
|
677
678
|
...t.precision === void 0 ? {} : { precision: t.precision },
|
|
678
679
|
...t.scale === void 0 ? {} : { scale: t.scale },
|
|
679
680
|
...t.generatedAs ? { generatedAs: {
|
|
@@ -875,35 +876,42 @@ BEGIN
|
|
|
875
876
|
if (!n || !r || n.length !== r.length) return !1;
|
|
876
877
|
let i = [...n].sort(), a = [...r].sort();
|
|
877
878
|
return i.every((e, t) => e === a[t]);
|
|
878
|
-
}, yt = (e, t) =>
|
|
879
|
+
}, yt = (e, t) => {
|
|
880
|
+
try {
|
|
881
|
+
let n = /\((\d+)\)/.exec(D(e, t));
|
|
882
|
+
return n ? Number(n[1]) : void 0;
|
|
883
|
+
} catch {
|
|
884
|
+
return;
|
|
885
|
+
}
|
|
886
|
+
}, bt = (e, t, n) => n === void 0 || u(n) ? !0 : e.type !== "text" || t.type !== "text" || yt(e, n) === t.maxLength, xt = (e, t, n) => e.type === t.type && e.nullable === t.nullable && e.unique === t.unique && _t(e, t) && bt(e, t, n) && JSON.stringify(I(e.references)) === JSON.stringify(I(t.references)) && vt(e.oneOf, t.oneOf), St = (e, t) => t.oneOf && t.oneOf.length > 0 ? L({
|
|
879
887
|
kind: "add-check",
|
|
880
888
|
table: e,
|
|
881
889
|
column: t.name,
|
|
882
890
|
values: t.oneOf
|
|
883
|
-
}, "safe", `enum-membership CHECK on ${e}.${t.name}`) : void 0,
|
|
884
|
-
let
|
|
891
|
+
}, "safe", `enum-membership CHECK on ${e}.${t.name}`) : void 0, Ct = (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])), wt = (e, t, n) => {
|
|
892
|
+
let r = new Map(t.columns.map((e) => [e.name, e])), i = new Map(e.columns.map((e) => [e.name, e])), a = [], o = [], s = [];
|
|
885
893
|
for (let t of e.columns) {
|
|
886
|
-
let e =
|
|
894
|
+
let e = r.get(t.name);
|
|
887
895
|
if (!e) {
|
|
888
|
-
|
|
896
|
+
a.push(t);
|
|
889
897
|
continue;
|
|
890
898
|
}
|
|
891
|
-
|
|
899
|
+
xt(t, e, n) || s.push({
|
|
892
900
|
declared: t,
|
|
893
901
|
live: e
|
|
894
902
|
});
|
|
895
903
|
}
|
|
896
|
-
for (let e of t.columns)
|
|
904
|
+
for (let e of t.columns) i.has(e.name) || o.push(e);
|
|
897
905
|
return {
|
|
898
|
-
added:
|
|
899
|
-
removed:
|
|
900
|
-
changed:
|
|
906
|
+
added: a,
|
|
907
|
+
removed: o,
|
|
908
|
+
changed: s
|
|
901
909
|
};
|
|
902
|
-
},
|
|
910
|
+
}, Tt = (e, t) => {
|
|
903
911
|
let n = new Map(t.indexes.map((e) => [e.name, e])), r = new Map(e.indexes.map((e) => [e.name, e])), i = [], a = [];
|
|
904
912
|
for (let t of e.indexes) {
|
|
905
913
|
let e = n.get(t.name);
|
|
906
|
-
(!e || !
|
|
914
|
+
(!e || !Ct(t, e)) && i.push(t);
|
|
907
915
|
}
|
|
908
916
|
for (let e of t.indexes) r.has(e.name) || a.push(e);
|
|
909
917
|
return {
|
|
@@ -916,30 +924,30 @@ BEGIN
|
|
|
916
924
|
atomicByDialect: mt(e.kind),
|
|
917
925
|
...n ? { reason: n } : {},
|
|
918
926
|
...r ? { blocked: r } : {}
|
|
919
|
-
}),
|
|
927
|
+
}), Et = (e, t, n) => {
|
|
920
928
|
let r = {
|
|
921
929
|
kind: "add-column",
|
|
922
930
|
table: e,
|
|
923
931
|
column: t
|
|
924
932
|
};
|
|
925
933
|
return t.nullable ? L(r, "safe", "nullable column add — no backfill needed") : t.hasDefault && t.defaultValue !== void 0 ? L(r, "needs-default", "NOT NULL with literal default — DDL DEFAULT will populate existing rows") : n?.backfill ? L(r, "needs-backfill", `backfill declared (kind=${n.backfill.kind}) — applier will run 3-step add/update/set-not-null`) : L(r, "needs-backfill", "NOT NULL column on a table whose row count is unknown", { fix: `declare \`${t.name}: <type>().backfill(sql\`...\`)\` OR \`.default(value)\` so existing rows survive the migration` });
|
|
926
|
-
},
|
|
934
|
+
}, Dt = (e, t, n) => {
|
|
927
935
|
let r = {
|
|
928
936
|
kind: "drop-column",
|
|
929
937
|
table: e,
|
|
930
938
|
column: t.name
|
|
931
939
|
};
|
|
932
940
|
return n?.dropped ? L(r, "lossy", `column dropped via \`${t.name}: dropped()\` marker — intentional`) : L(r, "lossy", "column missing from declared schema", { fix: `if intentional, add \`${t.name}: dropped()\` to the schema. If a typo, restore the field` });
|
|
933
|
-
},
|
|
941
|
+
}, Ot = (e, t, n, r) => L({
|
|
934
942
|
kind: "create-table",
|
|
935
943
|
table: e,
|
|
936
944
|
columns: t,
|
|
937
945
|
indexes: n,
|
|
938
946
|
...r && r.length > 0 ? { primaryKey: r } : {}
|
|
939
|
-
}, "safe", "new table — no data to preserve"),
|
|
947
|
+
}, "safe", "new table — no data to preserve"), kt = (e) => L({
|
|
940
948
|
kind: "drop-table",
|
|
941
949
|
table: e
|
|
942
|
-
}, "lossy", "table missing from declared schema", { fix: "if intentional, set VOLTRO_DESTRUCTIVE_OK=1 OR add a file-based migration. If a typo, restore the table declaration" }),
|
|
950
|
+
}, "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" }), At = 5e4, jt = (e, t, n, r) => {
|
|
943
951
|
let i = (n ?? 0) >= r, a;
|
|
944
952
|
return a = t.unique ? t.columns.length === 1 ? {
|
|
945
953
|
kind: "add-unique",
|
|
@@ -955,7 +963,7 @@ BEGIN
|
|
|
955
963
|
table: e,
|
|
956
964
|
index: t
|
|
957
965
|
}, i ? L(a, "online-required", `online build on ${n} rows — CONCURRENTLY / INPLACE / WITH(ONLINE=ON) depending on dialect`) : L(a, "safe", t.unique ? t.columns.length === 1 ? "add unique constraint" : "add composite UNIQUE constraint" : "add B-tree index");
|
|
958
|
-
},
|
|
966
|
+
}, Mt = (e, t) => t.unique && t.columns.length > 1 ? L({
|
|
959
967
|
kind: "drop-unique-composite",
|
|
960
968
|
table: e,
|
|
961
969
|
name: t.name
|
|
@@ -963,7 +971,7 @@ BEGIN
|
|
|
963
971
|
kind: "drop-index",
|
|
964
972
|
table: e,
|
|
965
973
|
index: t.name
|
|
966
|
-
}, "safe", "drop index (no data loss — index is derived data)"),
|
|
974
|
+
}, "safe", "drop index (no data loss — index is derived data)"), Nt = (e, t) => {
|
|
967
975
|
if (e === "reference") return "text";
|
|
968
976
|
switch (t) {
|
|
969
977
|
case "sqlite":
|
|
@@ -971,7 +979,7 @@ BEGIN
|
|
|
971
979
|
case "mssql": return e === "json" ? "text" : e;
|
|
972
980
|
default: return e;
|
|
973
981
|
}
|
|
974
|
-
},
|
|
982
|
+
}, Pt = (e, t, n, r, i, a) => {
|
|
975
983
|
let o = [];
|
|
976
984
|
if (t.nullable !== n.nullable) {
|
|
977
985
|
let n = {
|
|
@@ -994,7 +1002,7 @@ BEGIN
|
|
|
994
1002
|
table: e,
|
|
995
1003
|
column: t.name
|
|
996
1004
|
}, "safe", `drop unique constraint on ${e}.${t.name} — constraint is derived metadata, no data loss`));
|
|
997
|
-
if (
|
|
1005
|
+
if (Nt(t.type, r) !== Nt(n.type, r)) {
|
|
998
1006
|
let r = t.narrowedFrom;
|
|
999
1007
|
if (r && r.from === n.type) {
|
|
1000
1008
|
let i = {
|
|
@@ -1017,6 +1025,16 @@ BEGIN
|
|
|
1017
1025
|
o.push(L(r, "lossy", `type change ${n.type} → ${t.type} on ${e}.${t.name} may not be value-preserving`, { fix: `acknowledge it on the column: \`.narrowedFrom('${n.type}', { using: '${t.name}::${t.type}' })\` (drop \`using\` if the cast is implicit), or use a file-based migration` }));
|
|
1018
1026
|
}
|
|
1019
1027
|
}
|
|
1028
|
+
if (t.type === "text" && n.type === "text" && !u(r ?? "postgres") && t.maxLength !== n.maxLength) {
|
|
1029
|
+
let r = t.maxLength === void 0 || n.maxLength !== void 0 && t.maxLength > n.maxLength, i = n.maxLength === void 0 ? "unbounded" : `varchar(${n.maxLength})`, a = t.maxLength === void 0 ? "unbounded" : `varchar(${t.maxLength})`;
|
|
1030
|
+
o.push(L({
|
|
1031
|
+
kind: "alter-column-type",
|
|
1032
|
+
table: e,
|
|
1033
|
+
column: t.name,
|
|
1034
|
+
from: "text",
|
|
1035
|
+
to: "text"
|
|
1036
|
+
}, r ? "safe" : "needs-backfill", r ? `text length ${i} → ${a} on ${e}.${t.name} — widening, no data can be lost` : `text length ${i} → ${a} on ${e}.${t.name} — NARROWING; the ALTER fails if any existing value is longer than ${String(t.maxLength)}`, r ? void 0 : { fix: `check first: SELECT COUNT(*) FROM ${e} WHERE LENGTH(${t.name}) > ${String(t.maxLength)}` }));
|
|
1037
|
+
}
|
|
1020
1038
|
if (!_t(t, n)) {
|
|
1021
1039
|
let n = {
|
|
1022
1040
|
kind: "alter-column-default",
|
|
@@ -1033,7 +1051,7 @@ BEGIN
|
|
|
1033
1051
|
table: e,
|
|
1034
1052
|
column: t.name
|
|
1035
1053
|
}, "safe", `drop stale enum CHECK on ${e}.${t.name}`));
|
|
1036
|
-
let r =
|
|
1054
|
+
let r = St(e, t);
|
|
1037
1055
|
r && o.push(r);
|
|
1038
1056
|
}
|
|
1039
1057
|
if (JSON.stringify(I(t.references)) !== JSON.stringify(I(n.references)) && (n.references && o.push(L({
|
|
@@ -1056,7 +1074,7 @@ BEGIN
|
|
|
1056
1074
|
}, "lossy", r === "delete" ? `add FK ${e}.${t.name} → ${n}: orphanPolicy 'delete' first DELETES rows whose ${t.name} points at a missing ${n}` : `add FK ${e}.${t.name} → ${n}: orphanPolicy 'null' first NULLs ${t.name} where it points at a missing ${n}`)) : o.push(L(i, "needs-backfill", `add FK ${e}.${t.name} → ${n} — existing rows must already reference a valid ${n} (else set orphanPolicy:'null'/'delete')`));
|
|
1057
1075
|
}
|
|
1058
1076
|
return o;
|
|
1059
|
-
},
|
|
1077
|
+
}, Ft = (e, t, n) => {
|
|
1060
1078
|
let r = [], i = /* @__PURE__ */ new Set(), a = /* @__PURE__ */ new Set(), o = new Set(n.removed.map((e) => e.name)), s = new Set(n.added.map((e) => e.name));
|
|
1061
1079
|
for (let [n, c] of Object.entries(t)) {
|
|
1062
1080
|
let t = c.renamedFrom;
|
|
@@ -1072,7 +1090,7 @@ BEGIN
|
|
|
1072
1090
|
consumedAddedNames: i,
|
|
1073
1091
|
consumedRemovedNames: a
|
|
1074
1092
|
};
|
|
1075
|
-
},
|
|
1093
|
+
}, It = (e) => {
|
|
1076
1094
|
let t = {
|
|
1077
1095
|
safe: 0,
|
|
1078
1096
|
needsDefault: 0,
|
|
@@ -1107,37 +1125,37 @@ BEGIN
|
|
|
1107
1125
|
break;
|
|
1108
1126
|
}
|
|
1109
1127
|
return t;
|
|
1110
|
-
},
|
|
1111
|
-
let t = N(e.declared, e.dialect), n = ht(e.declared, t), r = new Map(e.live.tables.map((e) => [e.name, e])), i = e.onlineAfter ??
|
|
1128
|
+
}, Lt = (e) => {
|
|
1129
|
+
let t = N(e.declared, e.dialect), n = ht(e.declared, t), r = new Map(e.live.tables.map((e) => [e.name, e])), i = e.onlineAfter ?? At, a = [];
|
|
1112
1130
|
for (let e of t.tables) if (!r.has(e.name)) {
|
|
1113
|
-
a.push(
|
|
1131
|
+
a.push(Ot(e.name, e.columns, e.indexes, e.primaryKey));
|
|
1114
1132
|
for (let t of e.columns) {
|
|
1115
|
-
let n =
|
|
1133
|
+
let n = St(e.name, t);
|
|
1116
1134
|
n && a.push(n);
|
|
1117
1135
|
}
|
|
1118
1136
|
}
|
|
1119
1137
|
let o = new Set(e.ignoreTables ?? []);
|
|
1120
|
-
for (let t of e.live.tables) n.has(t.name) || P(t.name) || dt(t.name) || o.has(t.name) || a.push(
|
|
1138
|
+
for (let t of e.live.tables) n.has(t.name) || P(t.name) || dt(t.name) || o.has(t.name) || a.push(kt(t.name));
|
|
1121
1139
|
for (let o of t.tables) {
|
|
1122
1140
|
let t = r.get(o.name);
|
|
1123
1141
|
if (!t) continue;
|
|
1124
|
-
let s = n.get(o.name), c =
|
|
1142
|
+
let s = n.get(o.name), c = wt(o, t, e.dialect), l = Tt(o, t), u = Ft(s.table, s.columnDefs, c);
|
|
1125
1143
|
a.push(...u.ops);
|
|
1126
1144
|
for (let e of c.removed) {
|
|
1127
1145
|
if (u.consumedRemovedNames.has(e.name) || dt(e.name)) continue;
|
|
1128
1146
|
let t = s.columnDefs[e.name];
|
|
1129
|
-
a.push(
|
|
1147
|
+
a.push(Dt(o.name, e, t));
|
|
1130
1148
|
}
|
|
1131
1149
|
for (let e of c.added) {
|
|
1132
1150
|
if (u.consumedAddedNames.has(e.name)) continue;
|
|
1133
1151
|
let t = s.columnDefs[e.name];
|
|
1134
|
-
a.push(
|
|
1135
|
-
let n =
|
|
1152
|
+
a.push(Et(o.name, e, t));
|
|
1153
|
+
let n = St(o.name, e);
|
|
1136
1154
|
n && a.push(n);
|
|
1137
1155
|
}
|
|
1138
|
-
for (let e of l.added) a.push(
|
|
1139
|
-
for (let e of l.removed) a.push(
|
|
1140
|
-
for (let { declared: n, live: r } of c.changed) a.push(...
|
|
1156
|
+
for (let e of l.added) a.push(jt(o.name, e, t.rowCount, i));
|
|
1157
|
+
for (let e of l.removed) a.push(Mt(o.name, e));
|
|
1158
|
+
for (let { declared: n, live: r } of c.changed) a.push(...Pt(o.name, n, r, e.dialect, t.rowCount, i));
|
|
1141
1159
|
}
|
|
1142
1160
|
let s = new Set(a.flatMap((e) => e.op.kind === "create-table" ? [e.op.table] : [])), c = new Map(t.tables.map((e) => [e.name, e])), l = (e) => {
|
|
1143
1161
|
let t = c.get(e);
|
|
@@ -1145,7 +1163,7 @@ BEGIN
|
|
|
1145
1163
|
column: e.name,
|
|
1146
1164
|
target: e.references.table
|
|
1147
1165
|
}] : []) : [];
|
|
1148
|
-
}, u =
|
|
1166
|
+
}, u = re([...s], l), d = [];
|
|
1149
1167
|
for (let e of t.tables) if (s.has(e.name)) for (let t of e.columns) !t.references || !u.has(x(e.name, t.name)) || d.push(L({
|
|
1150
1168
|
kind: "add-foreign-key",
|
|
1151
1169
|
table: e.name,
|
|
@@ -1219,9 +1237,9 @@ BEGIN
|
|
|
1219
1237
|
operations: v,
|
|
1220
1238
|
fromFingerprint: j(e.live),
|
|
1221
1239
|
toFingerprint: j(t),
|
|
1222
|
-
summary:
|
|
1240
|
+
summary: It(v)
|
|
1223
1241
|
};
|
|
1224
|
-
},
|
|
1242
|
+
}, Rt = (e) => {
|
|
1225
1243
|
let t = /[`"[]?([A-Za-z_][A-Za-z0-9_]*)[`"\]]?\s*(?:in\b|=)/i.exec(e);
|
|
1226
1244
|
if (!t) return null;
|
|
1227
1245
|
let n = [...e.matchAll(/'((?:[^']|'')*)'/g)].map((e) => e[1].replace(/''/g, "'"));
|
|
@@ -1229,7 +1247,7 @@ BEGIN
|
|
|
1229
1247
|
column: t[1],
|
|
1230
1248
|
values: n
|
|
1231
1249
|
};
|
|
1232
|
-
},
|
|
1250
|
+
}, zt = (e, t) => {
|
|
1233
1251
|
if (t === "vector") return "vector";
|
|
1234
1252
|
switch (e) {
|
|
1235
1253
|
case "text":
|
|
@@ -1264,25 +1282,25 @@ BEGIN
|
|
|
1264
1282
|
case "SET DEFAULT": return "noAction";
|
|
1265
1283
|
default: return "noAction";
|
|
1266
1284
|
}
|
|
1267
|
-
},
|
|
1285
|
+
}, Bt = (e, t) => {
|
|
1268
1286
|
let n = e !== void 0 && e !== "" ? Number(e) : NaN;
|
|
1269
1287
|
return Number.isInteger(n) && n > 0 ? n : t;
|
|
1270
|
-
},
|
|
1288
|
+
}, Vt = () => Bt(process.env.VOLTRO_INTROSPECT_BATCH, 20), Ht = 300, Ut = () => {
|
|
1271
1289
|
let e = process.env.VOLTRO_INTROSPECT_TIMEOUT_MS;
|
|
1272
|
-
return e !== void 0 && e.trim() === "0" ? 0 :
|
|
1273
|
-
},
|
|
1290
|
+
return e !== void 0 && e.trim() === "0" ? 0 : Bt(e, 3e4);
|
|
1291
|
+
}, Wt = (e, t) => {
|
|
1274
1292
|
let n = Number.isFinite(t) && t >= 1 ? Math.floor(t) : 1, r = [];
|
|
1275
1293
|
for (let t = 0; t < e.length; t += n) r.push(e.slice(t, t + n));
|
|
1276
1294
|
return r;
|
|
1277
|
-
},
|
|
1278
|
-
let t =
|
|
1295
|
+
}, Gt = (e) => {
|
|
1296
|
+
let t = Ut(), n = d.gen(function* () {
|
|
1279
1297
|
t > 0 && (yield* e.unsafe(`SET LOCAL statement_timeout = ${t}`));
|
|
1280
|
-
let n = (t) => e.unsafe("(" + t.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ") + ")"), r = (t) => e.unsafe(String(Math.max(0, Math.trunc(t)))), i =
|
|
1298
|
+
let n = (t) => e.unsafe("(" + t.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ") + ")"), r = (t) => e.unsafe(String(Math.max(0, Math.trunc(t)))), i = Vt(), a = (e, t) => d.gen(function* () {
|
|
1281
1299
|
let r = [];
|
|
1282
|
-
for (let a of
|
|
1300
|
+
for (let a of Wt(e, i)) a.length !== 0 && r.push(...yield* t(n(a)));
|
|
1283
1301
|
return r;
|
|
1284
1302
|
}), o = [];
|
|
1285
|
-
for (let t = 0;; t +=
|
|
1303
|
+
for (let t = 0;; t += Ht) {
|
|
1286
1304
|
let n = yield* e`
|
|
1287
1305
|
SELECT c.relname AS table_name,
|
|
1288
1306
|
COALESCE(c.reltuples::bigint, 0) AS row_count
|
|
@@ -1290,14 +1308,15 @@ BEGIN
|
|
|
1290
1308
|
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
1291
1309
|
WHERE n.nspname = current_schema() AND c.relkind = 'r'
|
|
1292
1310
|
ORDER BY c.relname
|
|
1293
|
-
LIMIT ${r(
|
|
1311
|
+
LIMIT ${r(Ht)} OFFSET ${r(t)}
|
|
1294
1312
|
`;
|
|
1295
|
-
if (o.push(...n), n.length <
|
|
1313
|
+
if (o.push(...n), n.length < Ht) break;
|
|
1296
1314
|
}
|
|
1297
1315
|
let s = /* @__PURE__ */ new Set(), c = [];
|
|
1298
1316
|
for (let e of o) s.has(e.table_name) || (s.add(e.table_name), c.push(e));
|
|
1299
1317
|
let l = c.map((e) => e.table_name), u = yield* a(l, (t) => e`
|
|
1300
|
-
SELECT table_name, column_name, data_type, udt_name, is_nullable, column_default
|
|
1318
|
+
SELECT table_name, column_name, data_type, udt_name, is_nullable, column_default,
|
|
1319
|
+
character_maximum_length
|
|
1301
1320
|
FROM information_schema.columns
|
|
1302
1321
|
WHERE table_schema = current_schema() AND table_name IN ${t}
|
|
1303
1322
|
ORDER BY table_name, ordinal_position
|
|
@@ -1422,10 +1441,10 @@ BEGIN
|
|
|
1422
1441
|
let n = t.get(e.index_name);
|
|
1423
1442
|
n || (n = [], t.set(e.index_name, n)), n.push(e);
|
|
1424
1443
|
}
|
|
1425
|
-
let
|
|
1444
|
+
let re = [];
|
|
1426
1445
|
for (let e of c) {
|
|
1427
1446
|
let t = /* @__PURE__ */ new Set(), n = (_.get(e.table_name) ?? []).filter((e) => t.has(e.column_name) ? !1 : (t.add(e.column_name), !0)), r = v.get(e.table_name) ?? /* @__PURE__ */ new Set(), i = te.get(e.table_name) ?? /* @__PURE__ */ new Set(), a = ne.get(e.table_name) ?? [], o = new Map(a.map((e) => [e.source_column, e])), s = new Set(n.filter((e) => e.udt_name === "tsvector").map((e) => e.column_name)), c = n.filter((e) => !s.has(e.column_name)).map((t) => {
|
|
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" :
|
|
1447
|
+
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" : zt(t.data_type, t.udt_name), c = a ? {
|
|
1429
1448
|
table: a.target_table,
|
|
1430
1449
|
column: a.target_column,
|
|
1431
1450
|
onDelete: R(a.delete_rule),
|
|
@@ -1434,6 +1453,7 @@ BEGIN
|
|
|
1434
1453
|
return {
|
|
1435
1454
|
name: t.column_name,
|
|
1436
1455
|
type: s,
|
|
1456
|
+
...V(t.data_type, t.character_maximum_length) === void 0 ? {} : { maxLength: V(t.data_type, t.character_maximum_length) },
|
|
1437
1457
|
nullable: t.is_nullable === "YES",
|
|
1438
1458
|
unique: i.has(t.column_name) || n && t.column_name === "id",
|
|
1439
1459
|
hasDefault: t.column_default !== null,
|
|
@@ -1465,20 +1485,20 @@ BEGIN
|
|
|
1465
1485
|
unique: !0
|
|
1466
1486
|
});
|
|
1467
1487
|
let d = Number(e.row_count ?? 0);
|
|
1468
|
-
|
|
1488
|
+
re.push({
|
|
1469
1489
|
name: e.table_name,
|
|
1470
1490
|
columns: c,
|
|
1471
1491
|
indexes: l,
|
|
1472
1492
|
...d > 0 ? { rowCount: d } : {}
|
|
1473
1493
|
});
|
|
1474
1494
|
}
|
|
1475
|
-
return { tables:
|
|
1495
|
+
return { tables: re };
|
|
1476
1496
|
});
|
|
1477
1497
|
return (t > 0 ? e.withTransaction(n) : n).pipe(d.catchAll((e) => {
|
|
1478
1498
|
let n = `${String(e)} ${String(e.cause ?? "")}`.toLowerCase();
|
|
1479
1499
|
return n.includes("statement timeout") || n.includes("57014") ? d.die(/* @__PURE__ */ Error(`schema introspection exceeded VOLTRO_INTROSPECT_TIMEOUT_MS (${t}ms) — the schema is very large / FK-dense or the database is slow. Raise VOLTRO_INTROSPECT_TIMEOUT_MS, set it to 0 to disable the ceiling, or use DB_DIRECT_URL for a non-pooler connection.`)) : d.fail(e);
|
|
1480
1500
|
}));
|
|
1481
|
-
},
|
|
1501
|
+
}, Kt = (e, t) => {
|
|
1482
1502
|
switch (e.toLowerCase()) {
|
|
1483
1503
|
case "varchar":
|
|
1484
1504
|
case "char":
|
|
@@ -1514,13 +1534,14 @@ BEGIN
|
|
|
1514
1534
|
let t = e, n = {};
|
|
1515
1535
|
for (let e of Object.keys(t)) n[e.toLowerCase()] = t[e];
|
|
1516
1536
|
return n;
|
|
1517
|
-
}),
|
|
1537
|
+
}), qt = (e) => d.gen(function* () {
|
|
1518
1538
|
let t = z(yield* e`
|
|
1519
1539
|
SELECT table_name, COALESCE(table_rows, 0) AS table_rows
|
|
1520
1540
|
FROM information_schema.tables
|
|
1521
1541
|
WHERE table_schema = DATABASE() AND table_type = 'BASE TABLE'
|
|
1522
1542
|
ORDER BY table_name`), n = z(yield* e`
|
|
1523
|
-
SELECT table_name, column_name, data_type, column_type, is_nullable, column_default, column_key
|
|
1543
|
+
SELECT table_name, column_name, data_type, column_type, is_nullable, column_default, column_key,
|
|
1544
|
+
character_maximum_length
|
|
1524
1545
|
FROM information_schema.columns
|
|
1525
1546
|
WHERE table_schema = DATABASE()
|
|
1526
1547
|
ORDER BY table_name, ordinal_position`), r = z(yield* e`
|
|
@@ -1547,7 +1568,7 @@ BEGIN
|
|
|
1547
1568
|
o.add(`${e.table_name}.${t[1]}`);
|
|
1548
1569
|
continue;
|
|
1549
1570
|
}
|
|
1550
|
-
let n =
|
|
1571
|
+
let n = Rt(e.check_clause);
|
|
1551
1572
|
n && s.set(`${e.table_name}.${n.column}`, n.values);
|
|
1552
1573
|
}
|
|
1553
1574
|
let c = /* @__PURE__ */ new Map(), l = /* @__PURE__ */ new Map(), u = /* @__PURE__ */ new Map();
|
|
@@ -1570,7 +1591,7 @@ BEGIN
|
|
|
1570
1591
|
let t = c.get(e.table_name) ?? [], n = l.get(e.table_name) ?? [], r = new Map(n.map((e) => [e.source_column, e])), i = t.filter((e) => e.column_key === "PRI").map((e) => e.column_name), a = /* @__PURE__ */ new Set(), d = u.get(e.table_name);
|
|
1571
1592
|
if (d) for (let e of d.values()) e.length === 1 && e[0].non_unique === 0 && a.add(e[0].column_name);
|
|
1572
1593
|
let p = t.map((t) => {
|
|
1573
|
-
let n = i.includes(t.column_name) && i.length === 1, c = r.get(t.column_name), l = c ? "reference" : n && t.column_name === "id" ? "id" : o.has(`${e.table_name}.${t.column_name}`) ? "json" :
|
|
1594
|
+
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" : Kt(t.data_type, t.column_type), u = c ? {
|
|
1574
1595
|
table: c.target_table,
|
|
1575
1596
|
column: c.target_column,
|
|
1576
1597
|
onDelete: R(c.delete_rule),
|
|
@@ -1580,6 +1601,7 @@ BEGIN
|
|
|
1580
1601
|
name: t.column_name,
|
|
1581
1602
|
type: l,
|
|
1582
1603
|
nullable: t.is_nullable === "YES",
|
|
1604
|
+
...V(t.data_type, t.character_maximum_length) === void 0 ? {} : { maxLength: V(t.data_type, t.character_maximum_length) },
|
|
1583
1605
|
unique: d,
|
|
1584
1606
|
hasDefault: f !== null,
|
|
1585
1607
|
...f === null ? {} : { defaultValue: f },
|
|
@@ -1611,10 +1633,10 @@ BEGIN
|
|
|
1611
1633
|
});
|
|
1612
1634
|
}
|
|
1613
1635
|
return { tables: f };
|
|
1614
|
-
}),
|
|
1636
|
+
}), Jt = (e) => {
|
|
1615
1637
|
let t = e.toUpperCase();
|
|
1616
1638
|
return t.includes("INT") ? "integer" : t.includes("REAL") || t.includes("FLOA") || t.includes("DOUB") ? "real" : t.includes("BLOB") ? "bytes" : "text";
|
|
1617
|
-
},
|
|
1639
|
+
}, Yt = (e) => d.gen(function* () {
|
|
1618
1640
|
let t = yield* e`
|
|
1619
1641
|
SELECT name, sql FROM sqlite_master
|
|
1620
1642
|
WHERE type = 'table' AND name NOT LIKE 'sqlite_%'
|
|
@@ -1631,7 +1653,7 @@ BEGIN
|
|
|
1631
1653
|
d.set(t.name, r), t.unique === 1 && r.length === 1 && f.add(r[0]);
|
|
1632
1654
|
}
|
|
1633
1655
|
let p = o.map((e) => {
|
|
1634
|
-
let n = u.length === 1 && u[0] === e.name, r = l.get(e.name), i = r ? "reference" : n && e.name === "id" ? "id" :
|
|
1656
|
+
let n = u.length === 1 && u[0] === e.name, r = l.get(e.name), i = r ? "reference" : n && e.name === "id" ? "id" : Jt(e.type), a = r ? {
|
|
1635
1657
|
table: r.table,
|
|
1636
1658
|
column: r.to,
|
|
1637
1659
|
onDelete: R(r.on_delete),
|
|
@@ -1670,7 +1692,7 @@ BEGIN
|
|
|
1670
1692
|
});
|
|
1671
1693
|
}
|
|
1672
1694
|
return { tables: r };
|
|
1673
|
-
}),
|
|
1695
|
+
}), Xt = (e) => {
|
|
1674
1696
|
switch (e.toLowerCase()) {
|
|
1675
1697
|
case "int":
|
|
1676
1698
|
case "smallint":
|
|
@@ -1692,12 +1714,13 @@ BEGIN
|
|
|
1692
1714
|
case "image": return "bytes";
|
|
1693
1715
|
default: return "text";
|
|
1694
1716
|
}
|
|
1695
|
-
}, B = (e) => e === !0 || e === 1,
|
|
1717
|
+
}, B = (e) => e === !0 || e === 1, Zt = (e) => d.gen(function* () {
|
|
1696
1718
|
let t = yield* e`
|
|
1697
1719
|
SELECT TABLE_NAME AS table_name FROM INFORMATION_SCHEMA.TABLES
|
|
1698
1720
|
WHERE TABLE_TYPE = 'BASE TABLE' ORDER BY TABLE_NAME`, n = yield* e`
|
|
1699
1721
|
SELECT TABLE_NAME AS table_name, COLUMN_NAME AS column_name, DATA_TYPE AS data_type,
|
|
1700
|
-
IS_NULLABLE AS is_nullable, COLUMN_DEFAULT AS column_default
|
|
1722
|
+
IS_NULLABLE AS is_nullable, COLUMN_DEFAULT AS column_default,
|
|
1723
|
+
CHARACTER_MAXIMUM_LENGTH AS character_maximum_length
|
|
1701
1724
|
FROM INFORMATION_SCHEMA.COLUMNS ORDER BY TABLE_NAME, ORDINAL_POSITION`, r = yield* e`
|
|
1702
1725
|
SELECT st.name AS source_table, sc.name AS source_column,
|
|
1703
1726
|
tt.name AS target_table, tc.name AS target_column,
|
|
@@ -1752,16 +1775,17 @@ BEGIN
|
|
|
1752
1775
|
else B(t[0].is_unique) && t.length === 1 && f.add(t[0].column_name);
|
|
1753
1776
|
}
|
|
1754
1777
|
let p = t.map((t) => {
|
|
1755
|
-
let n = d.length === 1 && d[0] === t.column_name, i = r.get(t.column_name), a = i ? "reference" : n && t.column_name === "id" ? "id" :
|
|
1778
|
+
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" : Xt(t.data_type), s = i ? {
|
|
1756
1779
|
table: i.target_table,
|
|
1757
1780
|
column: i.target_column,
|
|
1758
|
-
onDelete:
|
|
1759
|
-
onUpdate:
|
|
1760
|
-
} : void 0, c = t.column_default === null ? null :
|
|
1781
|
+
onDelete: Qt(i.delete_rule),
|
|
1782
|
+
onUpdate: Qt(i.update_rule)
|
|
1783
|
+
} : void 0, c = t.column_default === null ? null : $t(t.column_default), l = o.get(`${e}.${t.column_name}`);
|
|
1761
1784
|
return {
|
|
1762
1785
|
name: t.column_name,
|
|
1763
1786
|
type: a,
|
|
1764
1787
|
nullable: t.is_nullable === "YES",
|
|
1788
|
+
...V(t.data_type, t.character_maximum_length) === void 0 ? {} : { maxLength: V(t.data_type, t.character_maximum_length) },
|
|
1765
1789
|
unique: f.has(t.column_name) || n && t.column_name === "id",
|
|
1766
1790
|
hasDefault: c !== null,
|
|
1767
1791
|
...c === null ? {} : { defaultValue: c },
|
|
@@ -1790,37 +1814,48 @@ BEGIN
|
|
|
1790
1814
|
});
|
|
1791
1815
|
}
|
|
1792
1816
|
return { tables: u };
|
|
1793
|
-
}),
|
|
1817
|
+
}), Qt = (e) => {
|
|
1794
1818
|
switch (e.toUpperCase().replace(/_/g, " ")) {
|
|
1795
1819
|
case "CASCADE": return "cascade";
|
|
1796
1820
|
case "SET NULL": return "setNull";
|
|
1797
1821
|
case "SET DEFAULT": return "noAction";
|
|
1798
1822
|
default: return "noAction";
|
|
1799
1823
|
}
|
|
1800
|
-
},
|
|
1824
|
+
}, $t = (e) => {
|
|
1801
1825
|
let t = e.trim();
|
|
1802
1826
|
for (; t.startsWith("(") && t.endsWith(")");) t = t.slice(1, -1).trim();
|
|
1803
1827
|
return t.startsWith("N'") && t.endsWith("'") ? t = t.slice(2, -1) : t.startsWith("'") && t.endsWith("'") && (t = t.slice(1, -1)), t;
|
|
1804
|
-
},
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1828
|
+
}, en = /* @__PURE__ */ new Set([
|
|
1829
|
+
"character varying",
|
|
1830
|
+
"varchar",
|
|
1831
|
+
"nvarchar",
|
|
1832
|
+
"char",
|
|
1833
|
+
"character",
|
|
1834
|
+
"nchar"
|
|
1835
|
+
]), V = (e, t) => {
|
|
1836
|
+
if (!en.has(e.toLowerCase())) return;
|
|
1837
|
+
let n = Number(t);
|
|
1838
|
+
if (!(!Number.isFinite(n) || n <= 0)) return n;
|
|
1839
|
+
}, H = (e) => e.onDialectOrElse({
|
|
1840
|
+
mysql: () => qt(e),
|
|
1841
|
+
mssql: () => Zt(e),
|
|
1842
|
+
sqlite: () => Yt(e),
|
|
1843
|
+
orElse: () => Gt(e)
|
|
1844
|
+
}), tn = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, U = (e, t) => {
|
|
1845
|
+
if (!(e.type === "text" && e.maxLength !== void 0) && !e.spatial && e.type !== "vector" && e.type !== "array" && e.type !== "enum") return;
|
|
1811
1846
|
let n = e.type === "vector" && e.vectorDim === void 0 ? "vector dimension" : e.type === "array" && e.arrayElement === void 0 ? "array element type" : e.type === "enum" && e.enumName === void 0 && e.enumValues === void 0 ? "enum name/values" : void 0;
|
|
1812
1847
|
if (n !== void 0) throw Error(`migration applier: cannot render '${e.name}' (${e.type}) — the schema snapshot carries no ${n}. Rendering it as 'text' would emit DDL that applies successfully and changes nothing, so this fails instead. This is a framework bug: declaredSchema.ts must carry the parameter into the ColumnSnapshot.`);
|
|
1813
1848
|
return D(e, t);
|
|
1814
|
-
},
|
|
1815
|
-
let t =
|
|
1816
|
-
return t === void 0 ?
|
|
1817
|
-
},
|
|
1849
|
+
}, W = (e) => {
|
|
1850
|
+
let t = U(e, "postgres");
|
|
1851
|
+
return t === void 0 ? nn(e) : t;
|
|
1852
|
+
}, nn = (e) => {
|
|
1818
1853
|
switch (e.type) {
|
|
1819
1854
|
case "id": return "text";
|
|
1820
1855
|
case "text": return "text";
|
|
1821
1856
|
case "integer": return "integer";
|
|
1822
1857
|
case "real": return "double precision";
|
|
1823
|
-
case "decimal": return
|
|
1858
|
+
case "decimal": return tn(e, "NUMERIC");
|
|
1824
1859
|
case "bigint": return "bigint";
|
|
1825
1860
|
case "boolean": return "boolean";
|
|
1826
1861
|
case "timestamp": return "timestamptz";
|
|
@@ -1834,15 +1869,15 @@ BEGIN
|
|
|
1834
1869
|
case "interval": return "interval";
|
|
1835
1870
|
case "raw": return e.rawDdl ?? "text";
|
|
1836
1871
|
}
|
|
1837
|
-
},
|
|
1838
|
-
let t =
|
|
1872
|
+
}, rn = (e) => {
|
|
1873
|
+
let t = U(e, "mariadb");
|
|
1839
1874
|
if (t !== void 0) return t;
|
|
1840
1875
|
switch (e.type) {
|
|
1841
1876
|
case "id": return "VARCHAR(64)";
|
|
1842
1877
|
case "text": return e.hasDefault && e.defaultValue !== void 0 || e.oneOf && e.oneOf.length > 0 ? "VARCHAR(255)" : "LONGTEXT";
|
|
1843
1878
|
case "integer": return "INT";
|
|
1844
1879
|
case "real": return "DOUBLE";
|
|
1845
|
-
case "decimal": return
|
|
1880
|
+
case "decimal": return tn(e, "DECIMAL");
|
|
1846
1881
|
case "bigint": return "BIGINT";
|
|
1847
1882
|
case "boolean": return "TINYINT(1)";
|
|
1848
1883
|
case "timestamp": return "DATETIME(6)";
|
|
@@ -1856,14 +1891,14 @@ BEGIN
|
|
|
1856
1891
|
case "interval": return "BIGINT";
|
|
1857
1892
|
case "raw": return e.rawDdl ?? "LONGTEXT";
|
|
1858
1893
|
}
|
|
1859
|
-
}, G = (e) => `"${e}"`, K = (e) => `\`${e.replace(/`/g, "``")}\``,
|
|
1894
|
+
}, G = (e) => `"${e}"`, K = (e) => `\`${e.replace(/`/g, "``")}\``, an = (e, t) => `ALTER TABLE ${t(e.table)} DROP COLUMN IF EXISTS ${t(e.column)};`, on = (e) => `ALTER TABLE ${K(e.table)} DROP COLUMN IF EXISTS ${K(e.column)}, ALGORITHM=COPY;`, sn = (e, t) => `ALTER TABLE ${t(e.table)} RENAME COLUMN ${t(e.from)} TO ${t(e.to)};`, cn = (e, t, n) => `ALTER TABLE ${n(e.table)} RENAME COLUMN ${n(e.column)} TO ${n(`${e.column}${Nn(t)}`)};`, ln = (e, t, n) => e.hasDefault && e.defaultValue !== void 0 ? `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} SET ${un(e, n)};` : `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} DROP DEFAULT;`, un = (e, t) => {
|
|
1860
1895
|
let n = t(e.defaultValue);
|
|
1861
1896
|
if (n === null) throw Error(`migration applier: cannot render the declared default for '${e.table}.${e.column}' (${JSON.stringify(e.defaultValue)}). Emitting 'DEFAULT NULL' would apply cleanly and drop the default silently, so this fails instead. This is a framework bug — report the column type + default.`);
|
|
1862
1897
|
return n;
|
|
1863
|
-
}, q = (e, t, n) => e.find((e) => e.tableName === t)?.fields[n],
|
|
1898
|
+
}, q = (e, t, n) => e.find((e) => e.tableName === t)?.fields[n], dn = (e, t, n) => {
|
|
1864
1899
|
let r = q(e, t, n);
|
|
1865
1900
|
return r ? nt(n, r) : void 0;
|
|
1866
|
-
},
|
|
1901
|
+
}, fn = (e, t, n) => {
|
|
1867
1902
|
let r = n ?? e.nullable, i = ve(e, "mariadb");
|
|
1868
1903
|
return [
|
|
1869
1904
|
K(t),
|
|
@@ -1871,17 +1906,17 @@ BEGIN
|
|
|
1871
1906
|
r ? null : "NOT NULL",
|
|
1872
1907
|
i
|
|
1873
1908
|
].filter(Boolean).join(" ");
|
|
1874
|
-
},
|
|
1909
|
+
}, pn = (e, t) => e == null ? null : Array.isArray(e) ? mn(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" ? O(e, "mysql") : null, mn = (e, t, n) => ye(e, t ?? { type: "json" }, n), hn = (e, t) => e == null ? null : Array.isArray(e) ? mn(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" ? O(e, "postgres") : null, J = (e, t) => {
|
|
1875
1910
|
if (!e.generatedAs) return null;
|
|
1876
1911
|
let { expr: n, stored: r } = e.generatedAs;
|
|
1877
1912
|
return t === "postgres" ? `GENERATED ALWAYS AS (${n}) STORED` : t === "mssql" ? `AS (${n})${r ? " PERSISTED" : ""}` : `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
|
|
1878
|
-
},
|
|
1913
|
+
}, gn = (e) => {
|
|
1879
1914
|
if (e.type === "id" && e.idScheme?.kind === "numeric") return k(e.name, "postgres");
|
|
1880
1915
|
let t = J(e, "postgres");
|
|
1881
|
-
if (t) return `${G(e.name)} ${
|
|
1882
|
-
let n = [G(e.name),
|
|
1916
|
+
if (t) return `${G(e.name)} ${W(e)} ${t}`;
|
|
1917
|
+
let n = [G(e.name), W(e)];
|
|
1883
1918
|
if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && n.push("UNIQUE"), e.hasDefault) {
|
|
1884
|
-
let t =
|
|
1919
|
+
let t = hn(e.defaultValue, e);
|
|
1885
1920
|
t && n.push(t);
|
|
1886
1921
|
}
|
|
1887
1922
|
return e.references && (n.push(`REFERENCES ${G(e.references.table)} (${G(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${{
|
|
@@ -1890,20 +1925,20 @@ BEGIN
|
|
|
1890
1925
|
setNull: "SET NULL",
|
|
1891
1926
|
noAction: "NO ACTION"
|
|
1892
1927
|
}[e.references.onDelete]}`)), n.join(" ");
|
|
1893
|
-
},
|
|
1894
|
-
let t = e.columns.map((e) => ` ${
|
|
1895
|
-
for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${G(t.name)} ON ${G(e.table)} (${t.columns.map(
|
|
1928
|
+
}, _n = (e, t) => e.primaryKey && e.primaryKey.length > 0 ? `,\n PRIMARY KEY (${e.primaryKey.map(t).join(", ")})` : "", vn = (e) => {
|
|
1929
|
+
let t = e.columns.map((e) => ` ${gn(e)}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${G(e.table)} (\n${t}${_n(e, G)}\n)`];
|
|
1930
|
+
for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${G(t.name)} ON ${G(e.table)} (${t.columns.map(Rn).join(", ")})`);
|
|
1896
1931
|
return n;
|
|
1897
|
-
},
|
|
1898
|
-
let t =
|
|
1932
|
+
}, yn = 191, bn = (e) => {
|
|
1933
|
+
let t = rn(e).toUpperCase();
|
|
1899
1934
|
return t.endsWith("TEXT") || t.endsWith("BLOB");
|
|
1900
|
-
},
|
|
1935
|
+
}, xn = (e) => {
|
|
1901
1936
|
if (e.type === "id" && e.idScheme?.kind === "numeric") return k(e.name, "mariadb");
|
|
1902
1937
|
let t = J(e, "mariadb");
|
|
1903
|
-
if (t) return `${K(e.name)} ${
|
|
1904
|
-
let n = [K(e.name),
|
|
1905
|
-
if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && !
|
|
1906
|
-
let t =
|
|
1938
|
+
if (t) return `${K(e.name)} ${rn(e)} ${t}`;
|
|
1939
|
+
let n = [K(e.name), rn(e)];
|
|
1940
|
+
if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && !bn(e) && n.push("UNIQUE"), e.hasDefault) {
|
|
1941
|
+
let t = pn(e.defaultValue, e);
|
|
1907
1942
|
t && n.push(t);
|
|
1908
1943
|
}
|
|
1909
1944
|
return e.references && (n.push(`REFERENCES ${K(e.references.table)} (${K(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${{
|
|
@@ -1912,26 +1947,26 @@ BEGIN
|
|
|
1912
1947
|
setNull: "SET NULL",
|
|
1913
1948
|
noAction: "NO ACTION"
|
|
1914
1949
|
}[e.references.onDelete]}`)), n.join(" ");
|
|
1915
|
-
},
|
|
1950
|
+
}, Sn = (e) => {
|
|
1916
1951
|
let t = new Map(e.columns.map((e) => [e.name, e])), n = (e) => {
|
|
1917
1952
|
let n = t.get(e);
|
|
1918
|
-
return n &&
|
|
1919
|
-
}, r = e.columns.map((e) => ` ${
|
|
1920
|
-
for (let t of e.columns) t.unique && t.type !== "id" &&
|
|
1953
|
+
return n && bn(n) ? `${K(e)}(${yn})` : K(e);
|
|
1954
|
+
}, r = e.columns.map((e) => ` ${xn(e)}`).join(",\n"), i = [`CREATE TABLE IF NOT EXISTS ${K(e.table)} (\n${r}${_n(e, n)}\n)`];
|
|
1955
|
+
for (let t of e.columns) t.unique && t.type !== "id" && bn(t) && i.push(`CREATE UNIQUE INDEX IF NOT EXISTS ${K(`${e.table}_${t.name}_key`)} ON ${K(e.table)} (${n(t.name)})`);
|
|
1921
1956
|
for (let t of e.indexes) t.name !== `${e.table}_pkey` && i.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${K(t.name)} ON ${K(e.table)} (${t.columns.map(n).join(", ")})`);
|
|
1922
1957
|
return i;
|
|
1923
|
-
},
|
|
1958
|
+
}, Cn = {
|
|
1924
1959
|
cascade: "CASCADE",
|
|
1925
1960
|
restrict: "RESTRICT",
|
|
1926
1961
|
setNull: "SET NULL",
|
|
1927
1962
|
noAction: "NO ACTION"
|
|
1928
|
-
},
|
|
1963
|
+
}, wn = {
|
|
1929
1964
|
cascade: "CASCADE",
|
|
1930
1965
|
restrict: "NO ACTION",
|
|
1931
1966
|
setNull: "SET NULL",
|
|
1932
1967
|
noAction: "NO ACTION"
|
|
1933
|
-
},
|
|
1934
|
-
let t =
|
|
1968
|
+
}, Tn = (e) => {
|
|
1969
|
+
let t = U(e, "sqlite");
|
|
1935
1970
|
if (t !== void 0) return t;
|
|
1936
1971
|
switch (e.type) {
|
|
1937
1972
|
case "integer":
|
|
@@ -1942,29 +1977,29 @@ BEGIN
|
|
|
1942
1977
|
case "bytes": return "BLOB";
|
|
1943
1978
|
default: return "TEXT";
|
|
1944
1979
|
}
|
|
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" ? O(e, "sqlite") : null,
|
|
1980
|
+
}, 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" ? O(e, "sqlite") : null, En = (e) => {
|
|
1946
1981
|
if (e.type === "id" && e.idScheme?.kind === "numeric") return k(e.name, "sqlite");
|
|
1947
1982
|
let t = J(e, "sqlite");
|
|
1948
|
-
if (t) return `${G(e.name)} ${
|
|
1949
|
-
let n = [G(e.name),
|
|
1983
|
+
if (t) return `${G(e.name)} ${Tn(e)} ${t}`;
|
|
1984
|
+
let n = [G(e.name), Tn(e)];
|
|
1950
1985
|
if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && n.push("UNIQUE"), e.hasDefault) {
|
|
1951
1986
|
let t = Y(e.defaultValue, "CURRENT_TIMESTAMP");
|
|
1952
1987
|
t && n.push(t);
|
|
1953
1988
|
}
|
|
1954
|
-
if (e.references && (n.push(`REFERENCES ${G(e.references.table)} (${G(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${
|
|
1989
|
+
if (e.references && (n.push(`REFERENCES ${G(e.references.table)} (${G(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${Cn[e.references.onDelete]}`)), e.oneOf && e.oneOf.length > 0) {
|
|
1955
1990
|
let t = e.oneOf.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
|
|
1956
1991
|
n.push(`CHECK (${G(e.name)} IN (${t}))`);
|
|
1957
1992
|
}
|
|
1958
1993
|
return n.join(" ");
|
|
1959
|
-
},
|
|
1960
|
-
let t = e.columns.map((e) => ` ${
|
|
1994
|
+
}, Dn = (e) => {
|
|
1995
|
+
let t = e.columns.map((e) => ` ${En(e)}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${G(e.table)} (\n${t}${_n(e, G)}\n)`];
|
|
1961
1996
|
for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${G(t.name)} ON ${G(e.table)} (${t.columns.map(G).join(", ")})`);
|
|
1962
1997
|
return n;
|
|
1963
1998
|
}, X = (e, t) => {
|
|
1964
1999
|
let n = t.find((t) => t.tableName === e);
|
|
1965
2000
|
if (!n) return [];
|
|
1966
2001
|
let r = N([n]).tables[0], i = `${e}__voltro_rebuild`, a = r.columns.map((e) => G(e.name)).join(", "), o = [
|
|
1967
|
-
...
|
|
2002
|
+
...Dn({
|
|
1968
2003
|
kind: "create-table",
|
|
1969
2004
|
table: i,
|
|
1970
2005
|
columns: r.columns,
|
|
@@ -1977,25 +2012,25 @@ BEGIN
|
|
|
1977
2012
|
];
|
|
1978
2013
|
for (let t of r.indexes) t.name !== `${e}_pkey` && o.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${G(t.name)} ON ${G(e)} (${t.columns.map(G).join(", ")})`);
|
|
1979
2014
|
return o;
|
|
1980
|
-
},
|
|
2015
|
+
}, On = (e, t, n, r) => {
|
|
1981
2016
|
let i = r ?? e.nullable;
|
|
1982
2017
|
return `ALTER TABLE ${Z(n)} ALTER COLUMN ${Z(t)} ${D(e, "mssql")} ${i ? "NULL" : "NOT NULL"};`;
|
|
1983
|
-
},
|
|
2018
|
+
}, kn = (e) => {
|
|
1984
2019
|
let t = `DECLARE @dc sysname; SELECT @dc = dc.name FROM sys.default_constraints dc JOIN sys.columns col ON col.object_id = dc.parent_object_id AND col.column_id = dc.parent_column_id WHERE dc.parent_object_id = OBJECT_ID(N'${e.table.replace(/'/g, "''")}') AND col.name = N'${e.column.replace(/'/g, "''")}'; IF @dc IS NOT NULL EXEC(N'ALTER TABLE ${Z(e.table)} DROP CONSTRAINT [' + @dc + ']');`;
|
|
1985
2020
|
if (!e.hasDefault) return t;
|
|
1986
2021
|
let n = Y(e.defaultValue, "SYSUTCDATETIME()");
|
|
1987
2022
|
if (!n) return t;
|
|
1988
2023
|
let r = n.replace(/^DEFAULT\s+/i, "");
|
|
1989
2024
|
return `${t} ALTER TABLE ${Z(e.table)} ADD DEFAULT ${r} FOR ${Z(e.column)};`;
|
|
1990
|
-
}, Z = (e) => `[${e.replace(/]/g, "]]")}]`,
|
|
1991
|
-
let t =
|
|
2025
|
+
}, Z = (e) => `[${e.replace(/]/g, "]]")}]`, An = (e) => {
|
|
2026
|
+
let t = U(e, "mssql");
|
|
1992
2027
|
if (t !== void 0) return t;
|
|
1993
2028
|
switch (e.type) {
|
|
1994
2029
|
case "id":
|
|
1995
2030
|
case "reference": return "NVARCHAR(64)";
|
|
1996
2031
|
case "integer": return "INT";
|
|
1997
2032
|
case "real": return "FLOAT";
|
|
1998
|
-
case "decimal": return
|
|
2033
|
+
case "decimal": return tn(e, "DECIMAL");
|
|
1999
2034
|
case "bigint": return "BIGINT";
|
|
2000
2035
|
case "boolean": return "BIT";
|
|
2001
2036
|
case "timestamp": return "DATETIME2(6)";
|
|
@@ -2003,34 +2038,34 @@ BEGIN
|
|
|
2003
2038
|
case "bytes": return "VARBINARY(MAX)";
|
|
2004
2039
|
default: return "NVARCHAR(MAX)";
|
|
2005
2040
|
}
|
|
2006
|
-
},
|
|
2041
|
+
}, jn = (e, t) => {
|
|
2007
2042
|
if (e.type === "id" && e.idScheme?.kind === "numeric") return k(e.name, "mssql");
|
|
2008
|
-
let n = e.type === "text" && t?.has(e.name) ? "NVARCHAR(450)" :
|
|
2043
|
+
let n = e.type === "text" && t?.has(e.name) ? "NVARCHAR(450)" : An(e), r = J(e, "mssql");
|
|
2009
2044
|
if (r) return `${Z(e.name)} ${r}`;
|
|
2010
2045
|
let i = [Z(e.name), n];
|
|
2011
2046
|
if (e.type === "id" && i.push("PRIMARY KEY"), e.nullable || i.push("NOT NULL"), e.unique && e.type !== "id" && i.push("UNIQUE"), e.hasDefault) {
|
|
2012
2047
|
let t = Y(e.defaultValue, "SYSUTCDATETIME()");
|
|
2013
2048
|
t && i.push(t);
|
|
2014
2049
|
}
|
|
2015
|
-
return e.references && (i.push(`REFERENCES ${Z(e.references.table)} (${Z(e.references.column)})`), e.references.onDelete && i.push(`ON DELETE ${
|
|
2016
|
-
},
|
|
2017
|
-
let t = (e) => e.replace(/'/g, "''"), n = new Set(e.indexes.flatMap((e) => e.columns)), r = e.columns.map((e) => ` ${
|
|
2050
|
+
return e.references && (i.push(`REFERENCES ${Z(e.references.table)} (${Z(e.references.column)})`), e.references.onDelete && i.push(`ON DELETE ${wn[e.references.onDelete]}`)), i.join(" ");
|
|
2051
|
+
}, Mn = (e) => {
|
|
2052
|
+
let t = (e) => e.replace(/'/g, "''"), n = new Set(e.indexes.flatMap((e) => e.columns)), r = e.columns.map((e) => ` ${jn(e, n)}`).join(",\n"), i = `CREATE TABLE ${Z(e.table)} (\n${r}${_n(e, Z)}\n)`, a = [`IF OBJECT_ID(N'${t(e.table)}', N'U') IS NULL EXEC(N'${t(i)}')`];
|
|
2018
2053
|
for (let n of e.indexes) {
|
|
2019
2054
|
if (n.name === `${e.table}_pkey`) continue;
|
|
2020
2055
|
let r = `CREATE ${n.unique ? "UNIQUE " : ""}INDEX ${Z(n.name)} ON ${Z(e.table)} (${n.columns.map(Z).join(", ")})`;
|
|
2021
2056
|
a.push(`IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = N'${t(n.name)}' AND object_id = OBJECT_ID(N'${t(e.table)}')) EXEC(N'${t(r)}')`);
|
|
2022
2057
|
}
|
|
2023
2058
|
return a;
|
|
2024
|
-
},
|
|
2025
|
-
let r = `${e.table}${
|
|
2059
|
+
}, Nn = (e) => `__dropped_${e.replace(/[-:T.Z]/g, "").slice(0, 14)}`, Pn = (e, t) => `DROP TABLE IF EXISTS ${t(e.table)};`, Fn = (e, t, n) => {
|
|
2060
|
+
let r = `${e.table}${Nn(t)}`;
|
|
2026
2061
|
return `ALTER TABLE ${n(e.table)} RENAME TO ${n(r)};`;
|
|
2027
|
-
},
|
|
2062
|
+
}, In = (e, t, n) => {
|
|
2028
2063
|
let r = q(e, t, n);
|
|
2029
|
-
return r ?
|
|
2030
|
-
},
|
|
2064
|
+
return r ? bn({ type: r.type }) : !1;
|
|
2065
|
+
}, Ln = (e, t, n) => In(e, t, n) ? `${K(n)}(${yn})` : K(n), Rn = (e) => e.startsWith("(") ? e : G(e), zn = (e, t) => `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX ${t ? "CONCURRENTLY " : ""}IF NOT EXISTS ${G(e.index.name)} ON ${G(e.table)} (${e.index.columns.map(Rn).join(", ")});`, Bn = (e, t) => `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${K(e.index.name)} ON ${K(e.table)} (${e.index.columns.map((n) => Ln(t, e.table, n)).join(", ")});`, Vn = (e) => `DROP INDEX IF EXISTS ${G(e.index)};`, Hn = (e) => `DROP INDEX ${K(e.index)} ON ${K(e.table)};`, Un = (e) => `DROP INDEX IF EXISTS ${Z(e.index)} ON ${Z(e.table)};`, Wn = (e) => {
|
|
2031
2066
|
let t = (e) => e.replace(/'/g, "''"), n = `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX ${Z(e.index.name)} ON ${Z(e.table)} (${e.index.columns.map(Z).join(", ")})`;
|
|
2032
2067
|
return `IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = N'${t(e.index.name)}' AND object_id = OBJECT_ID(N'${t(e.table)}')) EXEC(N'${t(n)}');`;
|
|
2033
|
-
},
|
|
2068
|
+
}, Gn = (e, t, n) => {
|
|
2034
2069
|
let r = n.find((t) => t.tableName === e);
|
|
2035
2070
|
if (!r) return [];
|
|
2036
2071
|
let i = [];
|
|
@@ -2039,13 +2074,13 @@ BEGIN
|
|
|
2039
2074
|
t && t.type === "text" && !t.generatedAs && i.push(`ALTER TABLE ${Z(e)} ALTER COLUMN ${Z(n)} NVARCHAR(450) ${t.nullable ? "NULL" : "NOT NULL"};`);
|
|
2040
2075
|
}
|
|
2041
2076
|
return i;
|
|
2042
|
-
},
|
|
2077
|
+
}, Kn = (e) => `ALTER TABLE ${G(e.table)} ADD CONSTRAINT ${G(`${e.table}_${e.column}_key`)} UNIQUE (${G(e.column)});`, qn = (e, t) => `ALTER TABLE ${K(e.table)} ADD CONSTRAINT ${K(`${e.table}_${e.column}_key`)} UNIQUE (${Ln(t, e.table, e.column)});`, Jn = (e) => {
|
|
2043
2078
|
let t = e.fields.map((e) => G(e)).join(", ");
|
|
2044
2079
|
return `ALTER TABLE ${G(e.table)} ADD CONSTRAINT ${G(e.name)} UNIQUE (${t});`;
|
|
2045
|
-
},
|
|
2046
|
-
let n = e.fields.map((n) =>
|
|
2080
|
+
}, Yn = (e, t) => {
|
|
2081
|
+
let n = e.fields.map((n) => Ln(t, e.table, n)).join(", ");
|
|
2047
2082
|
return `ALTER TABLE ${K(e.table)} ADD CONSTRAINT ${K(e.name)} UNIQUE (${n});`;
|
|
2048
|
-
},
|
|
2083
|
+
}, Xn = (e) => `ALTER TABLE ${G(e.table)} DROP CONSTRAINT IF EXISTS ${G(e.name)};`, Zn = (e) => `ALTER TABLE ${K(e.table)} DROP INDEX ${K(e.name)};`, Qn = (e) => `ALTER TABLE ${G(e.table)} DROP CONSTRAINT IF EXISTS ${G(`${e.table}_${e.column}_key`)};`, $n = (e) => `ALTER TABLE ${K(e.table)} DROP INDEX ${K(`${e.table}_${e.column}_key`)};`, er = (e, t) => {
|
|
2049
2084
|
let n = [], r = t(e.table), i = t(e.column), a = t(e.targetTable), o = t(e.targetColumn);
|
|
2050
2085
|
if (e.orphanPolicy) {
|
|
2051
2086
|
let t = `${i} IS NOT NULL AND ${i} NOT IN (SELECT ${o} FROM ${a})`;
|
|
@@ -2063,11 +2098,11 @@ BEGIN
|
|
|
2063
2098
|
setNull: "SET NULL",
|
|
2064
2099
|
noAction: "NO ACTION"
|
|
2065
2100
|
}[e.onDelete]}`), n.push(s.join(" ") + ";"), n;
|
|
2066
|
-
},
|
|
2101
|
+
}, tr = (e) => `ALTER TABLE ${G(e.table)} DROP CONSTRAINT IF EXISTS ${G(`${e.table}_${e.column}_fkey`)};`, nr = (e) => `ALTER TABLE ${K(e.table)} DROP FOREIGN KEY ${K(`${e.table}_${e.column}_fkey`)};`, rr = (e, t) => {
|
|
2067
2102
|
let n = e.values.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
|
|
2068
2103
|
return `ALTER TABLE ${t(e.table)} ADD CONSTRAINT ${t(`${e.table}_${e.column}_check`)} CHECK (${t(e.column)} IN (${n}));`;
|
|
2069
|
-
},
|
|
2070
|
-
let i = e.column, a = r === "mariadb", o = a ? K : r === "mssql" ? Z : G, s = a ?
|
|
2104
|
+
}, ir = (e) => `ALTER TABLE ${G(e.table)} DROP CONSTRAINT IF EXISTS ${G(`${e.table}_${e.column}_check`)};`, ar = (e) => `ALTER TABLE ${K(e.table)} DROP CHECK ${K(`${e.table}_${e.column}_check`)};`, or = (e, t, n, r) => {
|
|
2105
|
+
let i = e.column, a = r === "mariadb", o = a ? K : r === "mssql" ? Z : G, s = a ? rn(i) : r === "mssql" ? An(i) : r === "sqlite" ? Tn(i) : W(i), c = r === "mssql" ? "ADD" : "ADD COLUMN", l = (e) => a ? pn(e, i) : r === "mssql" ? Y(e, "SYSUTCDATETIME()") : r === "sqlite" ? Y(e, "CURRENT_TIMESTAMP") : hn(e, i), u = J(i, r);
|
|
2071
2106
|
if (u) {
|
|
2072
2107
|
let t = r === "mssql" ? `${o(i.name)} ${u}` : `${o(i.name)} ${s} ${u}`;
|
|
2073
2108
|
return {
|
|
@@ -2095,7 +2130,7 @@ BEGIN
|
|
|
2095
2130
|
post: f ? [f] : []
|
|
2096
2131
|
};
|
|
2097
2132
|
return d?.sql && (p.backfillKind = "sql", p.backfillSql = d.sql), d?.js && (p.backfillKind = "js", p.backfillJs = d.js), d?.batchSize !== void 0 && (p.batchSize = d.batchSize), d?.sleepMs !== void 0 && (p.sleepMs = d.sleepMs), p;
|
|
2098
|
-
},
|
|
2133
|
+
}, sr = (e) => {
|
|
2099
2134
|
let t = new Map(e.map((e) => [e.tableName, e]));
|
|
2100
2135
|
return (e, n) => {
|
|
2101
2136
|
let r = t.get(e);
|
|
@@ -2120,21 +2155,21 @@ BEGIN
|
|
|
2120
2155
|
})), d.mapError((e) => {
|
|
2121
2156
|
let r = _(`applier: statement failed (op=${n})`, t, e, 400).trim();
|
|
2122
2157
|
return Object.assign(e, { message: r });
|
|
2123
|
-
}), d.map(() => void 0)), $ = (e, t, n) => d.forEach(t, (t) => Q(e, t, n), { discard: !0 }),
|
|
2124
|
-
let r = process.hrtime.bigint(), i =
|
|
2158
|
+
}), d.map(() => void 0)), $ = (e, t, n) => d.forEach(t, (t) => Q(e, t, n), { discard: !0 }), cr = (e, t, n) => d.gen(function* () {
|
|
2159
|
+
let r = process.hrtime.bigint(), i = sr(n.declared), a = t.op;
|
|
2125
2160
|
switch (a.kind) {
|
|
2126
2161
|
case "create-table": {
|
|
2127
2162
|
let t = yield* e.onDialectOrElse({
|
|
2128
|
-
mysql: () => d.succeed(
|
|
2129
|
-
mssql: () => d.succeed(
|
|
2130
|
-
sqlite: () => d.succeed(
|
|
2131
|
-
orElse: () => d.succeed(
|
|
2163
|
+
mysql: () => d.succeed(Sn(a)),
|
|
2164
|
+
mssql: () => d.succeed(Mn(a)),
|
|
2165
|
+
sqlite: () => d.succeed(Dn(a)),
|
|
2166
|
+
orElse: () => d.succeed(vn(a))
|
|
2132
2167
|
});
|
|
2133
2168
|
for (let n of t) yield* Q(e, n, a.kind);
|
|
2134
2169
|
break;
|
|
2135
2170
|
}
|
|
2136
2171
|
case "drop-table": {
|
|
2137
|
-
let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString(), r = (e) => t ?
|
|
2172
|
+
let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString(), r = (e) => t ? Fn(a, n, e) : Pn(a, e);
|
|
2138
2173
|
yield* e.onDialectOrElse({
|
|
2139
2174
|
mysql: () => Q(e, r(K), a.kind),
|
|
2140
2175
|
orElse: () => Q(e, r(G), a.kind)
|
|
@@ -2144,71 +2179,71 @@ BEGIN
|
|
|
2144
2179
|
case "drop-column": {
|
|
2145
2180
|
let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString();
|
|
2146
2181
|
yield* e.onDialectOrElse({
|
|
2147
|
-
mysql: () => Q(e, t ?
|
|
2148
|
-
orElse: () => Q(e, t ?
|
|
2182
|
+
mysql: () => Q(e, t ? cn(a, n, K) : on(a), a.kind),
|
|
2183
|
+
orElse: () => Q(e, t ? cn(a, n, G) : an(a, G), a.kind)
|
|
2149
2184
|
});
|
|
2150
2185
|
break;
|
|
2151
2186
|
}
|
|
2152
2187
|
case "rename-column":
|
|
2153
2188
|
yield* e.onDialectOrElse({
|
|
2154
|
-
mysql: () => Q(e,
|
|
2189
|
+
mysql: () => Q(e, sn(a, K), a.kind),
|
|
2155
2190
|
mssql: () => Q(e, `EXEC sp_rename N'${a.table.replace(/'/g, "''")}.${a.from.replace(/'/g, "''")}', N'${a.to.replace(/'/g, "''")}', 'COLUMN';`, a.kind),
|
|
2156
|
-
orElse: () => Q(e,
|
|
2191
|
+
orElse: () => Q(e, sn(a, G), a.kind)
|
|
2157
2192
|
});
|
|
2158
2193
|
break;
|
|
2159
2194
|
case "add-index":
|
|
2160
2195
|
yield* e.onDialectOrElse({
|
|
2161
|
-
mysql: () => Q(e,
|
|
2162
|
-
mssql: () => $(e, [...
|
|
2163
|
-
orElse: () => Q(e,
|
|
2196
|
+
mysql: () => Q(e, Bn(a, n.declared), a.kind),
|
|
2197
|
+
mssql: () => $(e, [...Gn(a.table, a.index.columns, n.declared), Wn(a)], a.kind),
|
|
2198
|
+
orElse: () => Q(e, zn(a, t.classification === "online-required"), a.kind)
|
|
2164
2199
|
});
|
|
2165
2200
|
break;
|
|
2166
2201
|
case "drop-index":
|
|
2167
2202
|
yield* e.onDialectOrElse({
|
|
2168
|
-
mysql: () => Q(e,
|
|
2169
|
-
mssql: () => Q(e,
|
|
2170
|
-
orElse: () => Q(e,
|
|
2203
|
+
mysql: () => Q(e, Hn(a), a.kind),
|
|
2204
|
+
mssql: () => Q(e, Un(a), a.kind),
|
|
2205
|
+
orElse: () => Q(e, Vn(a), a.kind)
|
|
2171
2206
|
});
|
|
2172
2207
|
break;
|
|
2173
2208
|
case "add-unique":
|
|
2174
2209
|
yield* e.onDialectOrElse({
|
|
2175
|
-
mysql: () => Q(e,
|
|
2210
|
+
mysql: () => Q(e, qn(a, n.declared), a.kind),
|
|
2176
2211
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2177
|
-
mssql: () => $(e, [...
|
|
2178
|
-
orElse: () => Q(e,
|
|
2212
|
+
mssql: () => $(e, [...Gn(a.table, [a.column], n.declared), Kn(a)], a.kind),
|
|
2213
|
+
orElse: () => Q(e, Kn(a), a.kind)
|
|
2179
2214
|
});
|
|
2180
2215
|
break;
|
|
2181
2216
|
case "drop-unique":
|
|
2182
2217
|
yield* e.onDialectOrElse({
|
|
2183
|
-
mysql: () => Q(e,
|
|
2218
|
+
mysql: () => Q(e, $n(a), a.kind),
|
|
2184
2219
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2185
|
-
orElse: () => Q(e,
|
|
2220
|
+
orElse: () => Q(e, Qn(a), a.kind)
|
|
2186
2221
|
});
|
|
2187
2222
|
break;
|
|
2188
2223
|
case "add-unique-composite":
|
|
2189
2224
|
yield* e.onDialectOrElse({
|
|
2190
|
-
mysql: () => Q(e,
|
|
2225
|
+
mysql: () => Q(e, Yn(a, n.declared), a.kind),
|
|
2191
2226
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2192
|
-
mssql: () => $(e, [...
|
|
2193
|
-
orElse: () => Q(e,
|
|
2227
|
+
mssql: () => $(e, [...Gn(a.table, a.fields, n.declared), Jn(a)], a.kind),
|
|
2228
|
+
orElse: () => Q(e, Jn(a), a.kind)
|
|
2194
2229
|
});
|
|
2195
2230
|
break;
|
|
2196
2231
|
case "drop-unique-composite":
|
|
2197
2232
|
yield* e.onDialectOrElse({
|
|
2198
|
-
mysql: () => Q(e,
|
|
2233
|
+
mysql: () => Q(e, Zn(a), a.kind),
|
|
2199
2234
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2200
|
-
orElse: () => Q(e,
|
|
2235
|
+
orElse: () => Q(e, Xn(a), a.kind)
|
|
2201
2236
|
});
|
|
2202
2237
|
break;
|
|
2203
2238
|
case "add-foreign-key":
|
|
2204
2239
|
yield* e.onDialectOrElse({
|
|
2205
|
-
mysql: () => $(e,
|
|
2240
|
+
mysql: () => $(e, er(a, K), a.kind),
|
|
2206
2241
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2207
|
-
orElse: () => $(e,
|
|
2242
|
+
orElse: () => $(e, er(a, G), a.kind)
|
|
2208
2243
|
});
|
|
2209
2244
|
break;
|
|
2210
2245
|
case "add-column": {
|
|
2211
|
-
let n =
|
|
2246
|
+
let n = or(a, t, i, yield* e.onDialectOrElse({
|
|
2212
2247
|
mysql: () => d.succeed("mariadb"),
|
|
2213
2248
|
mssql: () => d.succeed("mssql"),
|
|
2214
2249
|
sqlite: () => d.succeed("sqlite"),
|
|
@@ -2254,37 +2289,37 @@ BEGIN
|
|
|
2254
2289
|
yield* e.onDialectOrElse({
|
|
2255
2290
|
mysql: () => {
|
|
2256
2291
|
let t = q(n.declared, a.table, a.column);
|
|
2257
|
-
return t ? Q(e, `ALTER TABLE ${K(a.table)} MODIFY COLUMN ${
|
|
2292
|
+
return t ? Q(e, `ALTER TABLE ${K(a.table)} MODIFY COLUMN ${fn(t, a.column, a.toNullable)};`, a.kind) : d.die(/* @__PURE__ */ Error(`alter-column-nullability on mariadb needs the declared column '${a.table}.${a.column}' (to render MODIFY COLUMN); it was not in ctx.declared.`));
|
|
2258
2293
|
},
|
|
2259
2294
|
mssql: () => {
|
|
2260
2295
|
let t = q(n.declared, a.table, a.column);
|
|
2261
|
-
return t ? Q(e,
|
|
2296
|
+
return t ? Q(e, On(t, a.column, a.table, a.toNullable), a.kind) : d.die(/* @__PURE__ */ Error(`alter-column-nullability on mssql needs the declared column '${a.table}.${a.column}'.`));
|
|
2262
2297
|
},
|
|
2263
2298
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2264
2299
|
orElse: () => Q(e, `ALTER TABLE ${G(a.table)} ALTER COLUMN ${G(a.column)} ${a.toNullable ? "DROP NOT NULL" : "SET NOT NULL"};`, a.kind)
|
|
2265
2300
|
});
|
|
2266
2301
|
break;
|
|
2267
2302
|
case "alter-column-default": {
|
|
2268
|
-
let t =
|
|
2303
|
+
let t = dn(n.declared, a.table, a.column);
|
|
2269
2304
|
yield* e.onDialectOrElse({
|
|
2270
|
-
mysql: () => Q(e,
|
|
2271
|
-
mssql: () => Q(e,
|
|
2305
|
+
mysql: () => Q(e, ln(a, K, (e) => pn(e, t)), a.kind),
|
|
2306
|
+
mssql: () => Q(e, kn(a), a.kind),
|
|
2272
2307
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2273
|
-
orElse: () => Q(e,
|
|
2308
|
+
orElse: () => Q(e, ln(a, G, (e) => hn(e, t)), a.kind)
|
|
2274
2309
|
});
|
|
2275
2310
|
break;
|
|
2276
2311
|
}
|
|
2277
2312
|
case "alter-column-type": {
|
|
2278
|
-
let r =
|
|
2313
|
+
let r = W(dn(n.declared, a.table, a.column) ?? { type: a.to }), i = a.using ? ` USING ${a.using}` : "";
|
|
2279
2314
|
if (t.classification !== "online-required") {
|
|
2280
2315
|
yield* e.onDialectOrElse({
|
|
2281
2316
|
mysql: () => {
|
|
2282
2317
|
let t = q(n.declared, a.table, a.column);
|
|
2283
|
-
return t ? Q(e, `ALTER TABLE ${K(a.table)} MODIFY COLUMN ${
|
|
2318
|
+
return t ? Q(e, `ALTER TABLE ${K(a.table)} MODIFY COLUMN ${fn(t, a.column)};`, a.kind) : d.die(/* @__PURE__ */ Error(`alter-column-type on mariadb needs the declared column '${a.table}.${a.column}' (to render MODIFY COLUMN); it was not in ctx.declared.`));
|
|
2284
2319
|
},
|
|
2285
2320
|
mssql: () => {
|
|
2286
2321
|
let t = q(n.declared, a.table, a.column);
|
|
2287
|
-
return t ? Q(e,
|
|
2322
|
+
return t ? Q(e, On(t, a.column, a.table), a.kind) : d.die(/* @__PURE__ */ Error(`alter-column-type on mssql needs the declared column '${a.table}.${a.column}'.`));
|
|
2288
2323
|
},
|
|
2289
2324
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2290
2325
|
orElse: () => Q(e, `ALTER TABLE ${G(a.table)} ALTER COLUMN ${G(a.column)} TYPE ${r}${i};`, a.kind)
|
|
@@ -2308,23 +2343,23 @@ BEGIN
|
|
|
2308
2343
|
}
|
|
2309
2344
|
case "drop-foreign-key":
|
|
2310
2345
|
yield* e.onDialectOrElse({
|
|
2311
|
-
mysql: () => Q(e,
|
|
2346
|
+
mysql: () => Q(e, nr(a), a.kind),
|
|
2312
2347
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2313
|
-
orElse: () => Q(e,
|
|
2348
|
+
orElse: () => Q(e, tr(a), a.kind)
|
|
2314
2349
|
});
|
|
2315
2350
|
break;
|
|
2316
2351
|
case "add-check":
|
|
2317
2352
|
yield* e.onDialectOrElse({
|
|
2318
|
-
mysql: () => Q(e,
|
|
2353
|
+
mysql: () => Q(e, rr(a, K), a.kind),
|
|
2319
2354
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2320
|
-
orElse: () => Q(e,
|
|
2355
|
+
orElse: () => Q(e, rr(a, G), a.kind)
|
|
2321
2356
|
});
|
|
2322
2357
|
break;
|
|
2323
2358
|
case "drop-check":
|
|
2324
2359
|
yield* e.onDialectOrElse({
|
|
2325
|
-
mysql: () => Q(e,
|
|
2360
|
+
mysql: () => Q(e, ar(a), a.kind),
|
|
2326
2361
|
sqlite: () => $(e, X(a.table, n.declared), a.kind),
|
|
2327
|
-
orElse: () => Q(e,
|
|
2362
|
+
orElse: () => Q(e, ir(a), a.kind)
|
|
2328
2363
|
});
|
|
2329
2364
|
break;
|
|
2330
2365
|
}
|
|
@@ -2333,10 +2368,10 @@ BEGIN
|
|
|
2333
2368
|
status: "applied",
|
|
2334
2369
|
durationMs: Number((process.hrtime.bigint() - r) / 1000000n)
|
|
2335
2370
|
};
|
|
2336
|
-
}),
|
|
2371
|
+
}), lr = (e, t, n) => d.gen(function* () {
|
|
2337
2372
|
let r = t.operations.filter((e) => e.blocked);
|
|
2338
2373
|
if (r.length > 0) return yield* d.die(/* @__PURE__ */ Error(`applyPlan: refusing to execute — ${r.length} blocked operations. Run \`voltro db plan\` to see the fixes.`));
|
|
2339
|
-
yield*
|
|
2374
|
+
yield* C(e);
|
|
2340
2375
|
let i = Date.now(), a = [];
|
|
2341
2376
|
try {
|
|
2342
2377
|
let r = yield* e.onDialectOrElse({
|
|
@@ -2346,11 +2381,11 @@ BEGIN
|
|
|
2346
2381
|
}), i = r ? t.operations.filter((e) => e.classification !== "online-required") : [], o = r ? t.operations.filter((e) => e.classification === "online-required") : t.operations;
|
|
2347
2382
|
i.length > 0 && (yield* e.withTransaction(d.gen(function* () {
|
|
2348
2383
|
let e = yield* p.SqlClient;
|
|
2349
|
-
for (let t of i) a.push(yield*
|
|
2384
|
+
for (let t of i) a.push(yield* cr(e, t, n));
|
|
2350
2385
|
})));
|
|
2351
|
-
for (let t of o) a.push(yield*
|
|
2386
|
+
for (let t of o) a.push(yield* cr(e, t, n));
|
|
2352
2387
|
} finally {
|
|
2353
|
-
yield*
|
|
2388
|
+
yield* w(e).pipe(d.orDie);
|
|
2354
2389
|
}
|
|
2355
2390
|
let o = yield* n.replan(e);
|
|
2356
2391
|
if (o.operations.length > 0) {
|
|
@@ -2382,19 +2417,19 @@ BEGIN
|
|
|
2382
2417
|
source: n.source,
|
|
2383
2418
|
...n.notes ? { notes: n.notes } : {}
|
|
2384
2419
|
};
|
|
2385
|
-
}),
|
|
2420
|
+
}), ur = (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"), dr = (e) => e`
|
|
2386
2421
|
SELECT fingerprint
|
|
2387
2422
|
FROM _voltro_migration_plans
|
|
2388
2423
|
ORDER BY ${e("appliedAt")} DESC
|
|
2389
2424
|
LIMIT 1
|
|
2390
|
-
`.pipe(d.map((e) => e.length > 0 ? e[0].fingerprint : void 0), d.catchAll(() => d.succeed(void 0))),
|
|
2425
|
+
`.pipe(d.map((e) => e.length > 0 ? e[0].fingerprint : void 0), d.catchAll(() => d.succeed(void 0))), fr = (e) => e.onDialectOrElse({
|
|
2391
2426
|
pg: () => "postgres",
|
|
2392
2427
|
mysql: () => "mysql",
|
|
2393
2428
|
mssql: () => "mssql",
|
|
2394
2429
|
sqlite: () => "sqlite",
|
|
2395
2430
|
orElse: () => "sqlite"
|
|
2396
|
-
}),
|
|
2397
|
-
let n = j(N(t,
|
|
2431
|
+
}), pr = (e, t) => d.gen(function* () {
|
|
2432
|
+
let n = j(N(t, fr(e))), r = yield* dr(e);
|
|
2398
2433
|
return r === n ? {
|
|
2399
2434
|
kind: "up-to-date",
|
|
2400
2435
|
fingerprint: n
|
|
@@ -2403,23 +2438,23 @@ BEGIN
|
|
|
2403
2438
|
expected: n,
|
|
2404
2439
|
...r === void 0 ? {} : { actual: r }
|
|
2405
2440
|
};
|
|
2406
|
-
}),
|
|
2441
|
+
}), mr = [
|
|
2407
2442
|
"pgeagertest_",
|
|
2408
2443
|
"mig_e2e_",
|
|
2409
2444
|
"mig_test_",
|
|
2410
2445
|
"mysqleagertest_",
|
|
2411
2446
|
"mssqleagertest_",
|
|
2412
2447
|
"sqliteeagertest_"
|
|
2413
|
-
],
|
|
2448
|
+
], hr = (e) => mr.some((t) => e.startsWith(t)), gr = (e, t) => d.gen(function* () {
|
|
2414
2449
|
if (process.env.VOLTRO_TEST_FIXTURE_GC === "off") return [];
|
|
2415
|
-
let n = t.filter((e) =>
|
|
2450
|
+
let n = t.filter((e) => hr(e.name)).map((e) => e.name);
|
|
2416
2451
|
if (n.length === 0) return [];
|
|
2417
2452
|
for (let t of n) yield* e.unsafe(`DROP TABLE IF EXISTS "${t}" CASCADE`).pipe(d.catchAll(() => d.void));
|
|
2418
2453
|
return n;
|
|
2419
|
-
}),
|
|
2454
|
+
}), _r = () => {
|
|
2420
2455
|
let e = (process.env.VOLTRO_DB_IGNORE_TABLES ?? "").split(",").map((e) => e.trim()).filter((e) => e.length > 0);
|
|
2421
2456
|
return e.length > 0 ? { ignoreTables: e } : {};
|
|
2422
|
-
},
|
|
2457
|
+
}, vr = (e) => {
|
|
2423
2458
|
if (e === void 0) return;
|
|
2424
2459
|
let t = e.trim();
|
|
2425
2460
|
if (t === "") return;
|
|
@@ -2429,43 +2464,43 @@ BEGIN
|
|
|
2429
2464
|
kind: "tables",
|
|
2430
2465
|
tables: new Set(n)
|
|
2431
2466
|
} : void 0;
|
|
2432
|
-
},
|
|
2467
|
+
}, yr = (e) => typeof e.table == "string" ? e.table : void 0, br = (e, t = { kind: "all" }) => ({
|
|
2433
2468
|
...e,
|
|
2434
2469
|
operations: e.operations.map((e) => {
|
|
2435
2470
|
if (!e.blocked || e.classification !== "lossy") return e;
|
|
2436
2471
|
if (t?.kind === "tables") {
|
|
2437
|
-
let n =
|
|
2472
|
+
let n = yr(e.op);
|
|
2438
2473
|
if (n === void 0 || !t.tables.has(n)) return e;
|
|
2439
2474
|
}
|
|
2440
2475
|
let { blocked: n, ...r } = e;
|
|
2441
2476
|
return r;
|
|
2442
2477
|
})
|
|
2443
|
-
}),
|
|
2478
|
+
}), xr = (e, t, n) => t === "postgres" ? st(e, n).pipe(d.flatMap((e) => {
|
|
2444
2479
|
let t = ct(e);
|
|
2445
2480
|
return t === void 0 ? d.void : d.logWarning(`auto-migrate: ${t}`).pipe(d.annotateLogs({ scope: "voltro:migrate" }));
|
|
2446
|
-
}), d.catchAll(() => d.void)) : d.void,
|
|
2447
|
-
let r =
|
|
2481
|
+
}), d.catchAll(() => d.void)) : d.void, Sr = (e, t, n) => d.gen(function* () {
|
|
2482
|
+
let r = fr(e), i = t.filter((e) => !P(e.tableName));
|
|
2448
2483
|
if (process.env.VOLTRO_MIGRATE_FORCE !== "1") {
|
|
2449
2484
|
let t = j(N(i, r));
|
|
2450
|
-
if ((yield*
|
|
2485
|
+
if ((yield* dr(e)) === t) return yield* xr(e, r, i), {
|
|
2451
2486
|
kind: "up-to-date",
|
|
2452
2487
|
fingerprint: t
|
|
2453
2488
|
};
|
|
2454
2489
|
}
|
|
2455
|
-
let a = yield*
|
|
2490
|
+
let a = yield* H(e), o = yield* gr(e, a.tables);
|
|
2456
2491
|
o.length > 0 && (yield* d.logInfo(`auto-migrate: reaped ${o.length} test-fixture leftover(s)`).pipe(d.annotateLogs({
|
|
2457
2492
|
scope: "voltro:migrate",
|
|
2458
2493
|
count: o.length
|
|
2459
|
-
})), a = yield*
|
|
2460
|
-
let s =
|
|
2494
|
+
})), a = yield* H(e));
|
|
2495
|
+
let s = Lt({
|
|
2461
2496
|
declared: i,
|
|
2462
2497
|
live: { tables: a.tables.filter((e) => !P(e.name)) },
|
|
2463
2498
|
dialect: r,
|
|
2464
|
-
...
|
|
2499
|
+
..._r()
|
|
2465
2500
|
});
|
|
2466
2501
|
if (s.summary.blocked > 0) {
|
|
2467
|
-
let e = s.operations.filter((e) => e.blocked).every((e) => e.classification === "lossy"), t =
|
|
2468
|
-
if (t === void 0 || !e || (s =
|
|
2502
|
+
let e = s.operations.filter((e) => e.blocked).every((e) => e.classification === "lossy"), t = vr(process.env.VOLTRO_DESTRUCTIVE_OK);
|
|
2503
|
+
if (t === void 0 || !e || (s = br(s, t), s.operations.some((e) => e.blocked))) return {
|
|
2469
2504
|
kind: "refused-blocked",
|
|
2470
2505
|
plan: s
|
|
2471
2506
|
};
|
|
@@ -2475,27 +2510,27 @@ BEGIN
|
|
|
2475
2510
|
fingerprint: s.toFingerprint
|
|
2476
2511
|
} : {
|
|
2477
2512
|
kind: "applied",
|
|
2478
|
-
applied: yield*
|
|
2513
|
+
applied: yield* lr(e, s, {
|
|
2479
2514
|
declared: t,
|
|
2480
2515
|
appliedBy: n.appliedBy,
|
|
2481
2516
|
environment: n.environment === "prod" ? "dev" : n.environment,
|
|
2482
2517
|
source: "auto-diff",
|
|
2483
2518
|
replan: (e) => d.gen(function* () {
|
|
2484
|
-
let t = yield*
|
|
2485
|
-
return
|
|
2519
|
+
let t = yield* H(e);
|
|
2520
|
+
return Lt({
|
|
2486
2521
|
declared: i,
|
|
2487
2522
|
live: { tables: t.tables.filter((e) => !P(e.name)) },
|
|
2488
2523
|
dialect: r,
|
|
2489
|
-
...
|
|
2524
|
+
..._r()
|
|
2490
2525
|
});
|
|
2491
2526
|
})
|
|
2492
2527
|
}),
|
|
2493
2528
|
plan: s
|
|
2494
2529
|
};
|
|
2495
|
-
}),
|
|
2530
|
+
}), Cr = (e, t, n) => process.env.VOLTRO_AUTO_MIGRATE === "0" ? d.succeed({
|
|
2496
2531
|
kind: "skipped",
|
|
2497
2532
|
reason: "VOLTRO_AUTO_MIGRATE=0"
|
|
2498
|
-
}) : n.environment === "prod" ?
|
|
2533
|
+
}) : n.environment === "prod" ? pr(e, t) : Sr(e, t, n), wr = (e, t) => {
|
|
2499
2534
|
switch (e.kind) {
|
|
2500
2535
|
case "skipped": return `auto-migrate: skipped (${e.reason})`;
|
|
2501
2536
|
case "up-to-date": return `auto-migrate: schema up to date (${t}, fingerprint=${M(e.fingerprint)})`;
|
|
@@ -2505,7 +2540,7 @@ BEGIN
|
|
|
2505
2540
|
}
|
|
2506
2541
|
case "prod-mismatch": return `auto-migrate: SCHEMA FINGERPRINT MISMATCH — declared=${M(e.expected)}` + (e.actual ? ` live=${M(e.actual)}` : " live=<no _voltro_migration_plans row>") + ". Run `voltro db apply --plan plan.json` from the deploy pipeline before serving.";
|
|
2507
2542
|
case "refused-blocked": {
|
|
2508
|
-
let t = e.plan.operations.filter((e) => e.blocked), n = t.filter((e) => e.op.kind === "drop-table").length, r = t.filter((e) => e.op.kind === "drop-table").map((e) => "table" in e.op ? e.op.table : "").filter(Boolean), i = t.filter((e) => e.op.kind === "add-column").length, a = t.filter((e) => e.op.kind === "drop-column").length, o = t.filter((e) => e.classification === "needs-rename-annotation").length, s = `auto-migrate: REFUSED — ${e.plan.summary.blocked} blocked operation(s):\n` +
|
|
2543
|
+
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` + ur(e.plan), c = [""];
|
|
2509
2544
|
if (n > 0 && c.push(`${n} table(s) exist in the live DB but aren't in your declared schema.`, "This is usually one of three things:", " (a) You're iterating on the schema — the table file got renamed, moved, or temporarily commented out.", " → Restore the declaration. Your data stays intact.", " (b) You want to KEEP the table but NOT manage it with Voltro (a leftover from another tool —", " a Strapi/Rails/legacy migration artifact, or an externally-owned table).", ` → Set \`VOLTRO_DB_IGNORE_TABLES=${r.join(",")}\` (comma-separated).`, " The planner excludes those tables from the diff entirely — it never drops them, and they", " stop blocking your OTHER (additive) changes. This is the fix when a leftover freezes your schema.", " (c) You actually want to drop the table.", ` → Set \`VOLTRO_DESTRUCTIVE_OK=${r.join(",")}\` for ONE run — it acknowledges`, " the data loss for THOSE tables only; every other lossy op in this plan stays blocked.", " (`VOLTRO_DESTRUCTIVE_OK=1` acknowledges all of them, which is rarely what you mean.)", " There is deliberately no `dropped()` marker for a TABLE, unlike for a column: a", " dropped column leaves a slot worth documenting in the declaration, a dropped table", " leaves nothing — the marker would be a dead entry you must remember to delete.", " Soft-drop: set `VOLTRO_SOFT_DROP=1` alongside DESTRUCTIVE_OK to RENAME instead of DROP", " (data survives as `<name>__dropped_<ts>` for ~7d; restorable via `voltro db restore-snapshot`)."), i > 0 && c.push(`${i} required column(s) need a backfill strategy before adding to a populated table.`, " → Annotate the column: `.backfill(sql`<expr>`)` or `.backfill(row => <fn>)` or `.default(<value>)`.", " Existing rows get the backfill value; the column then lands as NOT NULL."), a > 0) {
|
|
2510
2545
|
let t = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map();
|
|
2511
2546
|
for (let r of e.plan.operations) {
|
|
@@ -2522,7 +2557,7 @@ BEGIN
|
|
|
2522
2557
|
return o > 0 && c.push(`${o} column(s) look like renames (one column gone + a new one of same shape appeared).`, " → On the NEW column add `.renamedFrom('<oldName>')` so the planner emits RENAME instead of DROP+ADD."), c.push("", "See `voltro db plan` for the full machine-readable diff."), s + "\n" + c.join("\n");
|
|
2523
2558
|
}
|
|
2524
2559
|
}
|
|
2525
|
-
},
|
|
2560
|
+
}, Tr = /* @__PURE__ */ new Set([
|
|
2526
2561
|
"node_modules",
|
|
2527
2562
|
"dist",
|
|
2528
2563
|
"build",
|
|
@@ -2531,11 +2566,11 @@ BEGIN
|
|
|
2531
2566
|
".next",
|
|
2532
2567
|
".git",
|
|
2533
2568
|
".framework"
|
|
2534
|
-
]),
|
|
2569
|
+
]), Er = async (e) => {
|
|
2535
2570
|
let t = [], n = async (e) => {
|
|
2536
2571
|
let r = await h.readdir(e, { withFileTypes: !0 }).catch(() => []);
|
|
2537
2572
|
for (let i of r) {
|
|
2538
|
-
if (
|
|
2573
|
+
if (Tr.has(i.name)) continue;
|
|
2539
2574
|
let r = g(e, i.name);
|
|
2540
2575
|
i.isDirectory() ? await n(r) : i.isFile() && l.test(i.name) && t.push(r);
|
|
2541
2576
|
}
|
|
@@ -2544,7 +2579,7 @@ BEGIN
|
|
|
2544
2579
|
let n = e.split("/").pop() ?? e, r = t.split("/").pop() ?? t;
|
|
2545
2580
|
return n.localeCompare(r);
|
|
2546
2581
|
});
|
|
2547
|
-
},
|
|
2582
|
+
}, Dr = async (e) => {
|
|
2548
2583
|
let t = [];
|
|
2549
2584
|
for (let n of e) {
|
|
2550
2585
|
let e = (await import(ee(n).href)).default;
|
|
@@ -2558,11 +2593,11 @@ BEGIN
|
|
|
2558
2593
|
});
|
|
2559
2594
|
}
|
|
2560
2595
|
return t;
|
|
2561
|
-
},
|
|
2596
|
+
}, Or = (e) => e`
|
|
2562
2597
|
SELECT ${e("id")}
|
|
2563
2598
|
FROM ${e("_voltro_migration_plans")}
|
|
2564
2599
|
WHERE ${e("source")} = 'file'
|
|
2565
|
-
`.pipe(d.map((e) => e.map((e) => e.id)), d.catchAll(() => d.succeed([]))),
|
|
2600
|
+
`.pipe(d.map((e) => e.map((e) => e.id)), d.catchAll(() => d.succeed([]))), kr = (e, t, n, r) => d.gen(function* () {
|
|
2566
2601
|
let i = Date.now(), a = (/* @__PURE__ */ new Date()).toISOString(), o = {
|
|
2567
2602
|
sql: e,
|
|
2568
2603
|
log: {
|
|
@@ -2595,9 +2630,9 @@ BEGIN
|
|
|
2595
2630
|
${r}, ${n}, ${"file"},
|
|
2596
2631
|
${c}, ${a}, ${t.migration.description})
|
|
2597
2632
|
`, { durationMs: c };
|
|
2598
|
-
}),
|
|
2633
|
+
}), Ar = (e, t) => d.gen(function* () {
|
|
2599
2634
|
let n = yield* d.tryPromise({
|
|
2600
|
-
try: () =>
|
|
2635
|
+
try: () => Er(g(t, "migrations")),
|
|
2601
2636
|
catch: (e) => e
|
|
2602
2637
|
});
|
|
2603
2638
|
if (n.length === 0) return {
|
|
@@ -2605,25 +2640,25 @@ BEGIN
|
|
|
2605
2640
|
skipped: []
|
|
2606
2641
|
};
|
|
2607
2642
|
let r = yield* d.tryPromise({
|
|
2608
|
-
try: () =>
|
|
2643
|
+
try: () => Dr(n),
|
|
2609
2644
|
catch: (e) => e
|
|
2610
2645
|
});
|
|
2611
2646
|
if (r.length === 0) return {
|
|
2612
2647
|
pending: [],
|
|
2613
2648
|
skipped: []
|
|
2614
2649
|
};
|
|
2615
|
-
let i = new Set(yield*
|
|
2650
|
+
let i = new Set(yield* Or(e));
|
|
2616
2651
|
return {
|
|
2617
2652
|
pending: r.filter((e) => !i.has(e.migration.id)),
|
|
2618
2653
|
skipped: r.filter((e) => i.has(e.migration.id)).map((e) => e.migration.id)
|
|
2619
2654
|
};
|
|
2620
|
-
}),
|
|
2621
|
-
let { pending: n, skipped: r } = yield*
|
|
2655
|
+
}), jr = (e, t) => Ar(e, t).pipe(d.map((e) => e.pending.map((e) => e.migration.id))), Mr = (e, t) => d.gen(function* () {
|
|
2656
|
+
let { pending: n, skipped: r } = yield* Ar(e, t.projectRoot);
|
|
2622
2657
|
if (n.length === 0) return {
|
|
2623
2658
|
applied: [],
|
|
2624
2659
|
skipped: r
|
|
2625
2660
|
};
|
|
2626
|
-
yield*
|
|
2661
|
+
yield* C(e);
|
|
2627
2662
|
let i = [];
|
|
2628
2663
|
try {
|
|
2629
2664
|
for (let r of n) {
|
|
@@ -2632,7 +2667,7 @@ BEGIN
|
|
|
2632
2667
|
id: r.migration.id,
|
|
2633
2668
|
file: r.file
|
|
2634
2669
|
}));
|
|
2635
|
-
let { durationMs: n } = yield*
|
|
2670
|
+
let { durationMs: n } = yield* kr(e, r, t.env, t.appliedBy);
|
|
2636
2671
|
i.push({
|
|
2637
2672
|
id: r.migration.id,
|
|
2638
2673
|
durationMs: n
|
|
@@ -2643,28 +2678,28 @@ BEGIN
|
|
|
2643
2678
|
}));
|
|
2644
2679
|
}
|
|
2645
2680
|
} finally {
|
|
2646
|
-
yield*
|
|
2681
|
+
yield* w(e).pipe(d.orDie);
|
|
2647
2682
|
}
|
|
2648
2683
|
return {
|
|
2649
2684
|
applied: i,
|
|
2650
2685
|
skipped: r
|
|
2651
2686
|
};
|
|
2652
|
-
}),
|
|
2687
|
+
}), Nr = (e, t) => e`
|
|
2653
2688
|
SELECT ${e("id")}
|
|
2654
2689
|
FROM ${e("_voltro_migration_plans")}
|
|
2655
2690
|
WHERE ${e("id")} = ${t} AND ${e("source")} = 'file'
|
|
2656
2691
|
LIMIT 1
|
|
2657
|
-
`,
|
|
2658
|
-
if (!(yield*
|
|
2692
|
+
`, Pr = (e, t) => d.gen(function* () {
|
|
2693
|
+
if (!(yield* Nr(e, t.id))[0]) return yield* d.fail(/* @__PURE__ */ Error(`rollback: ${t.id} not found in _voltro_migration_plans (file source)`));
|
|
2659
2694
|
let n = yield* d.tryPromise({
|
|
2660
|
-
try: () =>
|
|
2695
|
+
try: () => Er(g(t.projectRoot, "migrations")),
|
|
2661
2696
|
catch: (e) => e
|
|
2662
2697
|
}), r = (yield* d.tryPromise({
|
|
2663
|
-
try: () =>
|
|
2698
|
+
try: () => Dr(n),
|
|
2664
2699
|
catch: (e) => e
|
|
2665
2700
|
})).find((e) => e.migration.id === t.id);
|
|
2666
2701
|
if (!r) return yield* d.fail(/* @__PURE__ */ Error(`rollback: file for migration ${t.id} not found on disk under ${t.projectRoot}/migrations/`));
|
|
2667
|
-
yield*
|
|
2702
|
+
yield* C(e);
|
|
2668
2703
|
let i = Date.now();
|
|
2669
2704
|
try {
|
|
2670
2705
|
let n = {
|
|
@@ -2691,9 +2726,9 @@ BEGIN
|
|
|
2691
2726
|
durationMs: o
|
|
2692
2727
|
};
|
|
2693
2728
|
} finally {
|
|
2694
|
-
yield*
|
|
2729
|
+
yield* w(e).pipe(d.orDie);
|
|
2695
2730
|
}
|
|
2696
|
-
}),
|
|
2731
|
+
}), Fr = (e) => d.gen(function* () {
|
|
2697
2732
|
let t = yield* p.SqlClient, n = yield* t`
|
|
2698
2733
|
SELECT id, fingerprint, appliedAt FROM _voltro_migration_plans
|
|
2699
2734
|
WHERE source = 'auto-diff'
|
|
@@ -2738,10 +2773,10 @@ BEGIN
|
|
|
2738
2773
|
snapshotFingerprint: e.fingerprint,
|
|
2739
2774
|
snapshotId: i
|
|
2740
2775
|
};
|
|
2741
|
-
}),
|
|
2776
|
+
}), Ir = (e, ...t) => ({
|
|
2742
2777
|
_tag: "RawSqlFragment",
|
|
2743
2778
|
strings: [...e],
|
|
2744
2779
|
values: [...t]
|
|
2745
|
-
}),
|
|
2780
|
+
}), Lr = (e) => typeof e == "object" && !!e && e._tag === "RawSqlFragment";
|
|
2746
2781
|
//#endregion
|
|
2747
|
-
export { l as FILE_MIGRATION_PATTERN, ot as REACTIVE_TRIGGER_PREFIX,
|
|
2782
|
+
export { l as FILE_MIGRATION_PATTERN, ot as REACTIVE_TRIGGER_PREFIX, S as VOLTRO_MIGRATION_LOCK_KEY, C as acquireMigrationLock, Je as applyNamespacedSchema, lr as applyPlan, He as applySchema, Wt as chunkTables, N as declaredSnapshot, ye as defaultArrayClause, ve as defaultClause, O as defaultJsonClause, wr as describeOutcome, vr as destructiveScope, st as detectReactiveTriggerDrift, an as emitDropColumnDdl, on as emitDropColumnDdlMysql, Ve as emitFrameworkBootstrapSql, ze as emitNamespaceProvisionDdl, Be as emitNamespacedSchemaSql, A as emitSchemaSql, j as fingerprintSchema, ct as formatReactiveTriggerDrift, _r as ignoreTablesFromEnv, H as introspectSchema, o as isFileMigration, Lr as isRawSqlFragment, zt as mapPgType, s as migration, k as numericIdSql, Rt as parseEnumCheck, jr as pendingFileMigrationIds, Lt as planMigrations, Ye as provisionTenantNamespace, w as releaseMigrationLock, xn as renderColumnMysql, gn as renderColumnPg, Pr as rollbackFileBasedMigration, Mr as runFileBasedMigrations, Xe as runFrameworkBootstrap, qe as runMigrate, Cr as runPlannedMigrations, M as shortFingerprint, nt as snapshotColumn, Ir as sql, D as sqlType, Fr as squashMigrationPlans, br as unblockLossy, T as withMigrationLock };
|