okmodel 0.4.0 → 0.5.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/README.md +86 -6
- package/dist/contracts/catalog/document.d.ts +20 -0
- package/dist/contracts/driver.d.ts +7 -0
- package/dist/dialects/pg/introspect.d.ts +6 -0
- package/dist/dialects/pg/role/sql.d.ts +10 -0
- package/dist/dialects/pg/schema.d.ts +15 -6
- package/dist/dialects/pg/view/index.d.ts +20 -6
- package/dist/dialects/pg/view/scratch.d.ts +2 -2
- package/dist/runtime/pg/bun.d.ts +12 -7
- package/dist/runtime/pg/bun.js +4 -1
- package/dist/runtime/pg/pg.d.ts +12 -6
- package/dist/runtime/pg/pg.js +4 -1
- package/dist/runtime/pg/pglite.d.ts +11 -3
- package/dist/runtime/pg/pglite.js +4 -1
- package/dist/runtime/pg/postgresjs.d.ts +12 -6
- package/dist/runtime/pg/postgresjs.js +4 -1
- package/dist/runtime/plan.d.ts +3 -1
- package/dist/runtime/tenancy/index.js +1 -1
- package/dist/runtime/topology.d.ts +191 -0
- package/dist/runtime/traits/index.js +6 -6
- package/dist/runtime/types.d.ts +57 -2
- package/dist/runtime/validate/index.js +1 -1
- package/dist/shared/{nxb42q7h.js → 47xzb9fc.js} +2 -2
- package/dist/shared/{6693j9rs.js → 5fqx9yh4.js} +6 -2
- package/dist/shared/{8jb4ymh2.js → 8bwbwy8h.js} +12 -1
- package/dist/shared/{41kv2xdm.js → 8xsbagad.js} +1 -1
- package/dist/shared/{sr5ms7b3.js → 922qbgnw.js} +3 -3
- package/dist/shared/{tny2t3sm.js → 990a291j.js} +4 -4
- package/dist/shared/{jns2wx4t.js → 9tgmr1gh.js} +1 -1
- package/dist/shared/{n5y9zyj1.js → ayz64vzj.js} +13 -12
- package/dist/shared/{kkzwp3d2.js → bt9sfq0z.js} +16 -14
- package/dist/shared/{c5g81ngb.js → bzsjtd7c.js} +7 -5
- package/dist/shared/{radd3z4g.js → ckjbyrt9.js} +1 -1
- package/dist/shared/{zg24x0hm.js → dxjp14rk.js} +10 -2
- package/dist/shared/{xghkt7a9.js → fancm5pt.js} +6 -233
- package/dist/shared/{yjw02enp.js → fyqkk1m0.js} +4 -4
- package/dist/shared/{ygem90rn.js → g516zdsb.js} +8 -3
- package/dist/shared/{v7tpnhnz.js → h4nqvjkp.js} +5 -3
- package/dist/shared/{edwqqryd.js → h8ne16fq.js} +1 -1
- package/dist/shared/{ady1ms74.js → jdgqqx31.js} +5 -5
- package/dist/shared/{kafaa5zv.js → k7cc9nzk.js} +24 -7
- package/dist/shared/{7nk68fj8.js → kdkxh3kb.js} +17 -10
- package/dist/shared/nkc9sfqb.js +1161 -0
- package/dist/shared/{awrsqrn7.js → p7pfx624.js} +2 -2
- package/dist/shared/{xrfnq5k8.js → qgvt8nx1.js} +11 -2
- package/dist/shared/{84ptn35q.js → qy9rdq0g.js} +6 -5
- package/dist/shared/{qn0srwwq.js → r6pj4fq2.js} +5 -3
- package/dist/shared/{2321avmn.js → r73pt594.js} +21 -13
- package/dist/shared/{kj680nxv.js → rasvvzgz.js} +8 -6
- package/dist/shared/{hcmdtwgh.js → szm0cksa.js} +4 -1
- package/dist/shared/{axhk06q1.js → tq9afp8d.js} +1 -1
- package/dist/shared/wxn4b7pp.js +252 -0
- package/dist/shared/{q6zsyh31.js → xdpj5kkm.js} +19 -8
- package/dist/shared/{s4mb6a4b.js → xhh1srw3.js} +54 -10
- package/dist/shared/{jgxzjzcz.js → xsq7v6wp.js} +2 -2
- package/dist/shared/{hqjsxnz7.js → ykv7wh5b.js} +5 -4
- package/dist/shared/{q795afwa.js → z2rnngj4.js} +3 -3
- package/dist/tooling/cli.js +12 -12
- package/dist/tooling/migrate/apply.d.ts +2 -0
- package/dist/tooling/migrate/files.d.ts +7 -0
- package/dist/tooling/migrate/index.js +8 -6
- package/dist/tooling/testing/facts.d.ts +3 -0
- package/dist/tooling/testing/index.js +3 -3
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
open2
|
|
3
3
|
} from "./wqem4jed.js";
|
|
4
|
-
import"./
|
|
4
|
+
import"./8bwbwy8h.js";
|
|
5
5
|
import"./n442h54c.js";
|
|
6
6
|
import {
|
|
7
7
|
CURRENT,
|
|
@@ -15,14 +15,16 @@ import {
|
|
|
15
15
|
loadMigrations,
|
|
16
16
|
expandProvisioned,
|
|
17
17
|
provisionHistoryIsKnown
|
|
18
|
-
} from "./
|
|
18
|
+
} from "./kdkxh3kb.js";
|
|
19
|
+
import"./szm0cksa.js";
|
|
20
|
+
import"./fancm5pt.js";
|
|
19
21
|
import {
|
|
20
22
|
assertTargetPolicy,
|
|
21
23
|
listTargets,
|
|
22
24
|
loadConfig
|
|
23
|
-
} from "./
|
|
24
|
-
import"./
|
|
25
|
-
import"./
|
|
25
|
+
} from "./xdpj5kkm.js";
|
|
26
|
+
import"./ayz64vzj.js";
|
|
27
|
+
import"./8xsbagad.js";
|
|
26
28
|
import {
|
|
27
29
|
OkmError2
|
|
28
30
|
} from "./52szzakm.js";
|
|
@@ -3,10 +3,10 @@ import {
|
|
|
3
3
|
readHandle,
|
|
4
4
|
readCall,
|
|
5
5
|
attachHttp
|
|
6
|
-
} from "./
|
|
6
|
+
} from "./bt9sfq0z.js";
|
|
7
7
|
import {
|
|
8
8
|
fail
|
|
9
|
-
} from "./
|
|
9
|
+
} from "./qgvt8nx1.js";
|
|
10
10
|
import {
|
|
11
11
|
OkmError2,
|
|
12
12
|
throwNamed2
|
|
@@ -27,6 +27,14 @@ function build(session, table, options, mods, view) {
|
|
|
27
27
|
}
|
|
28
28
|
function plan(session, table, options, mods, view) {
|
|
29
29
|
const { lock, wait, ...rest } = options;
|
|
30
|
+
const forced = session.pool.forcedRoute;
|
|
31
|
+
if (rest.route === "replica" || forced === "replica") {
|
|
32
|
+
throw new OkmError2("OKM1840", "A locking read needs the primary.", {
|
|
33
|
+
fix: {
|
|
34
|
+
summary: "Run the operation on the primary. Writes, batch, locks, and tx() never go to a replica."
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
}
|
|
30
38
|
if (session.tx === undefined) {
|
|
31
39
|
throw new OkmError2("OKM1830", "A row lock needs a transaction. find was called outside tx().", {
|
|
32
40
|
fix: { summary: "Move the find into tx(): the lock lasts until the transaction ends." }
|
|
@@ -2,14 +2,10 @@ import {
|
|
|
2
2
|
roleObject,
|
|
3
3
|
grantObject,
|
|
4
4
|
defaultPrivilegeObject
|
|
5
|
-
} from "./
|
|
5
|
+
} from "./8bwbwy8h.js";
|
|
6
6
|
import {
|
|
7
|
-
|
|
8
|
-
} from "./
|
|
9
|
-
import {
|
|
10
|
-
quoteIdent,
|
|
11
|
-
createObjectSql
|
|
12
|
-
} from "./41kv2xdm.js";
|
|
7
|
+
quoteIdent
|
|
8
|
+
} from "./8xsbagad.js";
|
|
13
9
|
import {
|
|
14
10
|
functionObject,
|
|
15
11
|
triggerObject
|
|
@@ -40,12 +36,6 @@ import {
|
|
|
40
36
|
import {
|
|
41
37
|
referentialAction
|
|
42
38
|
} from "./4e4c6vq2.js";
|
|
43
|
-
import {
|
|
44
|
-
OkmError2
|
|
45
|
-
} from "./52szzakm.js";
|
|
46
|
-
|
|
47
|
-
// src/tooling/migrate/drift.ts
|
|
48
|
-
import postgres from "postgres";
|
|
49
39
|
|
|
50
40
|
// src/dialects/pg/view/depend.ts
|
|
51
41
|
function cellText(value) {
|
|
@@ -446,8 +436,9 @@ var RELATION_GRANTS = `select c.relname as name,
|
|
|
446
436
|
select 1 from pg_depend d
|
|
447
437
|
where d.classid = 'pg_class'::regclass and d.objid = c.oid and d.deptype = 'e'
|
|
448
438
|
)`;
|
|
439
|
+
var FUNCTION_ARG_TYPES = "replace(oidvectortypes(p.proargtypes), ' ', '')";
|
|
449
440
|
var FUNCTION_GRANTS = `select p.proname as name,
|
|
450
|
-
|
|
441
|
+
${FUNCTION_ARG_TYPES} as args,
|
|
451
442
|
r.rolname as role, a.privilege_type as privilege
|
|
452
443
|
from pg_proc p
|
|
453
444
|
join pg_namespace n on n.oid = p.pronamespace
|
|
@@ -923,222 +914,4 @@ function flag(row, key) {
|
|
|
923
914
|
return value === true || value === "true" || value === "t";
|
|
924
915
|
}
|
|
925
916
|
|
|
926
|
-
|
|
927
|
-
var SCRATCH = "okm_view_seal";
|
|
928
|
-
var VIEW_SHAPE = `
|
|
929
|
-
select c.relname as name, c.relkind as kind, pg_get_viewdef(c.oid, true) as query,
|
|
930
|
-
(
|
|
931
|
-
select coalesce(string_agg(
|
|
932
|
-
a.attname || '|' || format_type(a.atttypid, a.atttypmod),
|
|
933
|
-
E'\\n' order by a.attnum
|
|
934
|
-
), '')
|
|
935
|
-
from pg_attribute a
|
|
936
|
-
where a.attrelid = c.oid and a.attnum > 0 and not a.attisdropped
|
|
937
|
-
) as columns
|
|
938
|
-
from pg_class c
|
|
939
|
-
join pg_namespace n on n.oid = c.relnamespace
|
|
940
|
-
where n.nspname = $1 and c.relkind in ('v', 'm')
|
|
941
|
-
`;
|
|
942
|
-
async function sealViews(runner, source) {
|
|
943
|
-
const views = source.objects.filter((object) => object.kind === "view" || object.kind === "materializedView");
|
|
944
|
-
if (views.length === 0)
|
|
945
|
-
return source;
|
|
946
|
-
await dropScratch(runner);
|
|
947
|
-
await runner.query(`create schema ${quoteIdent(SCRATCH)}`);
|
|
948
|
-
try {
|
|
949
|
-
await runner.query(`set search_path to ${quoteIdent(SCRATCH)}`);
|
|
950
|
-
for (const object of source.objects) {
|
|
951
|
-
if (object.kind !== "type")
|
|
952
|
-
continue;
|
|
953
|
-
const statement = createObjectSql(object, SCRATCH);
|
|
954
|
-
if (statement !== undefined)
|
|
955
|
-
await runner.query(statement);
|
|
956
|
-
}
|
|
957
|
-
for (const object of source.objects) {
|
|
958
|
-
if (object.kind !== "table")
|
|
959
|
-
continue;
|
|
960
|
-
await runner.query(stubTable(object, source));
|
|
961
|
-
}
|
|
962
|
-
await createViews(runner, views);
|
|
963
|
-
const shapes = await runner.query(VIEW_SHAPE, [SCRATCH]);
|
|
964
|
-
const deps = await runner.query(VIEW_DEPENDENCIES, [SCRATCH]);
|
|
965
|
-
const edges = viewDependencyEdges(deps, PUBLIC, source.objects);
|
|
966
|
-
const byName = new Map(shapes.map((row) => [cellText(row.name), row]));
|
|
967
|
-
const next = source.objects.map((object) => {
|
|
968
|
-
if (object.kind !== "view" && object.kind !== "materializedView")
|
|
969
|
-
return object;
|
|
970
|
-
const row = byName.get(object.identity.name);
|
|
971
|
-
if (row === undefined) {
|
|
972
|
-
throw new OkmError2("OKM1020", `View ${object.identity.name} was not created in the scratch schema.`, {
|
|
973
|
-
fix: { summary: "The query has to run against the tables in this schema." }
|
|
974
|
-
});
|
|
975
|
-
}
|
|
976
|
-
const columns = readColumns(object, cellText(row.columns));
|
|
977
|
-
const query = normaliseViewQuery(cellText(row.query));
|
|
978
|
-
const dependencies = edges.get(object.identity.name) ?? [];
|
|
979
|
-
if (object.kind === "view") {
|
|
980
|
-
return viewObject({
|
|
981
|
-
namespace: object.identity.namespace,
|
|
982
|
-
name: object.identity.name,
|
|
983
|
-
columns,
|
|
984
|
-
query,
|
|
985
|
-
owner: object.owner,
|
|
986
|
-
provenance: object.provenance,
|
|
987
|
-
dependencies
|
|
988
|
-
});
|
|
989
|
-
}
|
|
990
|
-
return materializedViewObject({
|
|
991
|
-
namespace: object.identity.namespace,
|
|
992
|
-
name: object.identity.name,
|
|
993
|
-
columns,
|
|
994
|
-
query,
|
|
995
|
-
owner: object.owner,
|
|
996
|
-
provenance: object.provenance,
|
|
997
|
-
dependencies,
|
|
998
|
-
...object.definition.refresh !== undefined ? { refresh: object.definition.refresh } : {}
|
|
999
|
-
});
|
|
1000
|
-
});
|
|
1001
|
-
return catalog(next);
|
|
1002
|
-
} finally {
|
|
1003
|
-
await runner.query("set search_path to public");
|
|
1004
|
-
await dropScratch(runner);
|
|
1005
|
-
}
|
|
1006
|
-
}
|
|
1007
|
-
async function createViews(runner, views) {
|
|
1008
|
-
const pending = [...views];
|
|
1009
|
-
let last = "";
|
|
1010
|
-
for (let pass = 0;pass < views.length && pending.length > 0; pass += 1) {
|
|
1011
|
-
const failed = [];
|
|
1012
|
-
let created = 0;
|
|
1013
|
-
for (const object of pending) {
|
|
1014
|
-
const sql = object.kind === "materializedView" ? `create materialized view ${quoteIdent(object.identity.name)} as ${object.definition.query} with no data` : `create view ${quoteIdent(object.identity.name)} as ${object.definition.query}`;
|
|
1015
|
-
try {
|
|
1016
|
-
await runner.query(sql);
|
|
1017
|
-
created += 1;
|
|
1018
|
-
} catch (error) {
|
|
1019
|
-
last = error instanceof Error ? error.message : String(error);
|
|
1020
|
-
failed.push(object);
|
|
1021
|
-
}
|
|
1022
|
-
}
|
|
1023
|
-
if (created === 0) {
|
|
1024
|
-
throw new OkmError2("OKM1020", `View ${failed[0]?.identity.name ?? ""} could not be created. ${last}`, {
|
|
1025
|
-
fix: { summary: "The query has to run against the tables in this schema." }
|
|
1026
|
-
});
|
|
1027
|
-
}
|
|
1028
|
-
pending.length = 0;
|
|
1029
|
-
pending.push(...failed);
|
|
1030
|
-
}
|
|
1031
|
-
}
|
|
1032
|
-
function stubTable(object, source) {
|
|
1033
|
-
const columns = source.objects.filter((item) => item.kind === "column" && item.identity.parent.name === object.identity.name);
|
|
1034
|
-
const lines = columns.map((column) => `${quoteIdent(column.identity.name)} ${column.definition.dataType}`);
|
|
1035
|
-
return `create table ${quoteIdent(object.identity.name)} (${lines.join(", ")})`;
|
|
1036
|
-
}
|
|
1037
|
-
function readColumns(object, printed) {
|
|
1038
|
-
const live = printed.length === 0 ? [] : printed.split(`
|
|
1039
|
-
`);
|
|
1040
|
-
const declared = object.definition.columns;
|
|
1041
|
-
if (live.length !== declared.length) {
|
|
1042
|
-
throw mismatch(object.identity.name, declared.map((column) => column.name).join(", "), printed);
|
|
1043
|
-
}
|
|
1044
|
-
return declared.map((column, index) => {
|
|
1045
|
-
const line = live[index] ?? "";
|
|
1046
|
-
const splitAt = line.indexOf("|");
|
|
1047
|
-
const name = splitAt < 0 ? line : line.slice(0, splitAt);
|
|
1048
|
-
const type = splitAt < 0 ? "" : line.slice(splitAt + 1);
|
|
1049
|
-
if (name !== column.name || type !== column.dataType) {
|
|
1050
|
-
throw mismatch(object.identity.name, `${column.name}:${column.dataType}`, live[index] ?? "");
|
|
1051
|
-
}
|
|
1052
|
-
return column;
|
|
1053
|
-
});
|
|
1054
|
-
}
|
|
1055
|
-
function mismatch(view, declared, live) {
|
|
1056
|
-
return new OkmError2("OKM1020", `View ${view} declares ${declared} and the database has ${live}.`, { fix: { summary: "Declare the columns the query returns, in that order, with those types." } });
|
|
1057
|
-
}
|
|
1058
|
-
async function dropScratch(runner) {
|
|
1059
|
-
const present = await runner.query(`select 1 as ok from pg_namespace where nspname = $1`, [
|
|
1060
|
-
SCRATCH
|
|
1061
|
-
]);
|
|
1062
|
-
if (present.length === 0)
|
|
1063
|
-
return;
|
|
1064
|
-
const rows = await runner.query(`
|
|
1065
|
-
select c.relname as name, c.relkind as kind
|
|
1066
|
-
from pg_class c
|
|
1067
|
-
join pg_namespace n on n.oid = c.relnamespace
|
|
1068
|
-
where n.nspname = $1 and c.relkind in ('v', 'm', 'r')
|
|
1069
|
-
`, [SCRATCH]);
|
|
1070
|
-
const views = rows.filter((row) => cellText(row.kind) === "v" || cellText(row.kind) === "m");
|
|
1071
|
-
for (let pass = 0;pass < Math.max(views.length, 1); pass += 1) {
|
|
1072
|
-
for (const row of views) {
|
|
1073
|
-
const kind = cellText(row.kind) === "m" ? "materialized view" : "view";
|
|
1074
|
-
try {
|
|
1075
|
-
await runner.query(`drop ${kind} if exists ${quoteIdent(SCRATCH)}.${quoteIdent(cellText(row.name))}`);
|
|
1076
|
-
} catch {}
|
|
1077
|
-
}
|
|
1078
|
-
}
|
|
1079
|
-
for (const row of rows) {
|
|
1080
|
-
if (cellText(row.kind) !== "r")
|
|
1081
|
-
continue;
|
|
1082
|
-
await runner.query(`drop table if exists ${quoteIdent(SCRATCH)}.${quoteIdent(cellText(row.name))}`);
|
|
1083
|
-
}
|
|
1084
|
-
await runner.query(`drop schema if exists ${quoteIdent(SCRATCH)} cascade`);
|
|
1085
|
-
}
|
|
1086
|
-
|
|
1087
|
-
// src/tooling/migrate/drift.ts
|
|
1088
|
-
async function assertAuthorDrift2(url, author, roles) {
|
|
1089
|
-
const sql = postgres(url, {
|
|
1090
|
-
max: 1,
|
|
1091
|
-
connect_timeout: 5,
|
|
1092
|
-
idle_timeout: 1,
|
|
1093
|
-
onnotice: () => {}
|
|
1094
|
-
});
|
|
1095
|
-
try {
|
|
1096
|
-
const present = await sql`
|
|
1097
|
-
select to_regclass('public.okm_meta')::text as reg
|
|
1098
|
-
`;
|
|
1099
|
-
if (present[0]?.reg == null)
|
|
1100
|
-
return;
|
|
1101
|
-
const runner = catalogQuery2(sql);
|
|
1102
|
-
const authorOnServer = await sealViews(runner, author);
|
|
1103
|
-
const live = await introspectSchema(runner, "public", "public", managedRoleOptions2(roles));
|
|
1104
|
-
const plan = planMigration({ before: live, after: authorOnServer, name: "check" });
|
|
1105
|
-
if (plan.steps.length === 0)
|
|
1106
|
-
return;
|
|
1107
|
-
throw new OkmError2("OKM1520", `The database differs from the schema.
|
|
1108
|
-
${plan.steps.map((step) => step.sql).join(`
|
|
1109
|
-
`)}`, {
|
|
1110
|
-
fix: {
|
|
1111
|
-
summary: "Change the schema or the database so okm check reports no difference."
|
|
1112
|
-
}
|
|
1113
|
-
});
|
|
1114
|
-
} finally {
|
|
1115
|
-
await sql.end({ timeout: 5 });
|
|
1116
|
-
}
|
|
1117
|
-
}
|
|
1118
|
-
function catalogQuery2(sql) {
|
|
1119
|
-
return {
|
|
1120
|
-
async query(text, params) {
|
|
1121
|
-
const rows = await sql.unsafe(text, params === undefined ? undefined : [...params]);
|
|
1122
|
-
return rows.map((row) => {
|
|
1123
|
-
const copy = {};
|
|
1124
|
-
for (const [key, value] of Object.entries(row))
|
|
1125
|
-
copy[key] = value;
|
|
1126
|
-
return copy;
|
|
1127
|
-
});
|
|
1128
|
-
}
|
|
1129
|
-
};
|
|
1130
|
-
}
|
|
1131
|
-
function managedRoleOptions2(roles) {
|
|
1132
|
-
const names = managedRoleNames(roles);
|
|
1133
|
-
return names === undefined ? undefined : { managedRoles: names };
|
|
1134
|
-
}
|
|
1135
|
-
function managedRoleNames(roles) {
|
|
1136
|
-
if (roles === undefined)
|
|
1137
|
-
return;
|
|
1138
|
-
const names = new Set([roles.migration, roles.app]);
|
|
1139
|
-
for (const role of roles.managed ?? [])
|
|
1140
|
-
names.add(role.name);
|
|
1141
|
-
return [...names];
|
|
1142
|
-
}
|
|
1143
|
-
|
|
1144
|
-
export { introspectSchema, sealViews, assertAuthorDrift2, catalogQuery2, managedRoleOptions2 };
|
|
917
|
+
export { cellText, VIEW_DEPENDENCIES, viewDependencyEdges, PUBLIC, introspectSchema, FUNCTION_ARG_TYPES };
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import"./
|
|
1
|
+
import"./8bwbwy8h.js";
|
|
2
2
|
import"./n442h54c.js";
|
|
3
3
|
import"./wqem4jed.js";
|
|
4
4
|
import {
|
|
5
5
|
listTargets,
|
|
6
6
|
loadConfig
|
|
7
|
-
} from "./
|
|
8
|
-
import"./
|
|
9
|
-
import"./
|
|
7
|
+
} from "./xdpj5kkm.js";
|
|
8
|
+
import"./ayz64vzj.js";
|
|
9
|
+
import"./8xsbagad.js";
|
|
10
10
|
|
|
11
11
|
// src/tooling/migrate/dev.ts
|
|
12
12
|
import { mkdirSync } from "node:fs";
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
renderCatalog
|
|
3
|
-
} from "./
|
|
3
|
+
} from "./8xsbagad.js";
|
|
4
4
|
import {
|
|
5
5
|
createClient
|
|
6
|
-
} from "./
|
|
6
|
+
} from "./bt9sfq0z.js";
|
|
7
7
|
import {
|
|
8
8
|
OkmError2
|
|
9
9
|
} from "./52szzakm.js";
|
|
@@ -12,10 +12,15 @@ import {
|
|
|
12
12
|
var tenantProbe = "00000000-0000-4000-8000-000000000001";
|
|
13
13
|
function readFacts(schema) {
|
|
14
14
|
const foreign = foreignKeys(schema.catalog);
|
|
15
|
+
const tables = new Set;
|
|
16
|
+
for (const object of schema.catalog.objects) {
|
|
17
|
+
if (object.kind === "table")
|
|
18
|
+
tables.add(object.identity.name);
|
|
19
|
+
}
|
|
15
20
|
const facts = [];
|
|
16
21
|
for (const name of Object.keys(schema.model)) {
|
|
17
22
|
const model = schema.model[name];
|
|
18
|
-
if (model === undefined)
|
|
23
|
+
if (model === undefined || !tables.has(model.sql))
|
|
19
24
|
continue;
|
|
20
25
|
const keys = foreign.get(model.sql) ?? [];
|
|
21
26
|
facts.push({
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
readHandle,
|
|
4
4
|
readCall,
|
|
5
5
|
attachHttp
|
|
6
|
-
} from "./
|
|
6
|
+
} from "./bt9sfq0z.js";
|
|
7
7
|
import {
|
|
8
8
|
selectedColumns,
|
|
9
9
|
parseOrder,
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
isRecord,
|
|
16
16
|
registerFailFix,
|
|
17
17
|
fail
|
|
18
|
-
} from "./
|
|
18
|
+
} from "./qgvt8nx1.js";
|
|
19
19
|
import {
|
|
20
20
|
OkmError2,
|
|
21
21
|
throwNamed2
|
|
@@ -30,6 +30,7 @@ var OPTIONS = [
|
|
|
30
30
|
"limit",
|
|
31
31
|
"include",
|
|
32
32
|
"after",
|
|
33
|
+
"route",
|
|
33
34
|
"signal",
|
|
34
35
|
"timeout"
|
|
35
36
|
];
|
|
@@ -69,7 +70,8 @@ function plan(session, table, options, mods, view) {
|
|
|
69
70
|
limit: size + 1,
|
|
70
71
|
include: record.include,
|
|
71
72
|
signal: record.signal,
|
|
72
|
-
timeout: record.timeout
|
|
73
|
+
timeout: record.timeout,
|
|
74
|
+
route: record.route
|
|
73
75
|
}, undefined, session.scope, session.schema.model[table], session.schema, view),
|
|
74
76
|
...after !== undefined ? { after } : {}
|
|
75
77
|
};
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
open2
|
|
3
3
|
} from "./wqem4jed.js";
|
|
4
|
-
import"./
|
|
4
|
+
import"./8bwbwy8h.js";
|
|
5
5
|
import {
|
|
6
6
|
createdOf,
|
|
7
7
|
testing2
|
|
8
|
-
} from "./
|
|
8
|
+
} from "./g516zdsb.js";
|
|
9
9
|
import"./n442h54c.js";
|
|
10
10
|
import {
|
|
11
11
|
assertTargetPolicy,
|
|
@@ -13,9 +13,9 @@ import {
|
|
|
13
13
|
selectTarget,
|
|
14
14
|
loadConfig,
|
|
15
15
|
loadSchema
|
|
16
|
-
} from "./
|
|
17
|
-
import"./
|
|
18
|
-
import"./
|
|
16
|
+
} from "./xdpj5kkm.js";
|
|
17
|
+
import"./ayz64vzj.js";
|
|
18
|
+
import"./8xsbagad.js";
|
|
19
19
|
import {
|
|
20
20
|
OkmError2
|
|
21
21
|
} from "./52szzakm.js";
|
|
@@ -5,12 +5,12 @@ import {
|
|
|
5
5
|
openClient,
|
|
6
6
|
withHttp,
|
|
7
7
|
settleCall
|
|
8
|
-
} from "./
|
|
8
|
+
} from "./bt9sfq0z.js";
|
|
9
9
|
import {
|
|
10
10
|
rejectKeys,
|
|
11
11
|
isRecord,
|
|
12
12
|
fail
|
|
13
|
-
} from "./
|
|
13
|
+
} from "./qgvt8nx1.js";
|
|
14
14
|
import {
|
|
15
15
|
OkmError2
|
|
16
16
|
} from "./52szzakm.js";
|
|
@@ -312,8 +312,16 @@ function held(session, frame, after, depth) {
|
|
|
312
312
|
};
|
|
313
313
|
const pool = depth === 0 ? {
|
|
314
314
|
capabilities: base.capabilities,
|
|
315
|
-
execute: (text, params, options) =>
|
|
316
|
-
|
|
315
|
+
execute: (text, params, options) => {
|
|
316
|
+
if (options?.route === "replica")
|
|
317
|
+
replicaInside();
|
|
318
|
+
return guarded(() => frame.conn.execute(text, params, stoppable(frame, options)), false);
|
|
319
|
+
},
|
|
320
|
+
batch: (statements, options) => {
|
|
321
|
+
if (options?.route === "replica")
|
|
322
|
+
replicaInside();
|
|
323
|
+
return guarded(() => frame.conn.batch(statements, stoppable(frame, options)), true);
|
|
324
|
+
},
|
|
317
325
|
stats: () => base.stats(),
|
|
318
326
|
close: () => Promise.resolve()
|
|
319
327
|
} : base;
|
|
@@ -364,13 +372,22 @@ function lockKey(key) {
|
|
|
364
372
|
return ["select pg_advisory_xact_lock($1::bigint)", String(key)];
|
|
365
373
|
}
|
|
366
374
|
function callOf(options) {
|
|
367
|
-
if (options?.signal === undefined && options?.timeout === undefined)
|
|
375
|
+
if (options?.signal === undefined && options?.timeout === undefined && options?.route === undefined) {
|
|
368
376
|
return;
|
|
377
|
+
}
|
|
369
378
|
return {
|
|
370
|
-
...options
|
|
371
|
-
...options
|
|
379
|
+
...options?.signal !== undefined ? { signal: options.signal } : {},
|
|
380
|
+
...options?.timeout !== undefined ? { timeout: options.timeout } : {},
|
|
381
|
+
...options?.route !== undefined ? { route: options.route } : {}
|
|
372
382
|
};
|
|
373
383
|
}
|
|
384
|
+
function replicaInside() {
|
|
385
|
+
throw new OkmError2("OKM1840", "This operation needs the primary.", {
|
|
386
|
+
fix: {
|
|
387
|
+
summary: "Run the operation on the primary. Writes, batch, locks, and tx() never go to a replica."
|
|
388
|
+
}
|
|
389
|
+
});
|
|
390
|
+
}
|
|
374
391
|
export {
|
|
375
392
|
tx
|
|
376
393
|
};
|
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
import {
|
|
2
2
|
serializeCatalog2,
|
|
3
3
|
catalogHash2,
|
|
4
|
+
startupCatalog2,
|
|
4
5
|
parseCatalog2
|
|
5
|
-
} from "./
|
|
6
|
+
} from "./8bwbwy8h.js";
|
|
6
7
|
import {
|
|
7
8
|
roleExists
|
|
8
|
-
} from "./
|
|
9
|
+
} from "./szm0cksa.js";
|
|
9
10
|
import {
|
|
10
11
|
assertTargetPolicy
|
|
11
|
-
} from "./
|
|
12
|
+
} from "./xdpj5kkm.js";
|
|
12
13
|
import {
|
|
13
14
|
canonicalTypeName,
|
|
14
15
|
createdRoleName,
|
|
16
|
+
createRoleOnce,
|
|
15
17
|
DEFAULT_BACKFILL_PAUSE_MS,
|
|
16
18
|
DEFAULT_BACKFILL_STATEMENT_TIMEOUT_MS,
|
|
17
19
|
boundaryQuery,
|
|
@@ -19,11 +21,11 @@ import {
|
|
|
19
21
|
omitManagedObjects,
|
|
20
22
|
planMigration,
|
|
21
23
|
parsePlan
|
|
22
|
-
} from "./
|
|
24
|
+
} from "./ayz64vzj.js";
|
|
23
25
|
import {
|
|
24
26
|
quoteIdent,
|
|
25
27
|
qualify
|
|
26
|
-
} from "./
|
|
28
|
+
} from "./8xsbagad.js";
|
|
27
29
|
import {
|
|
28
30
|
alignExtensionVersions
|
|
29
31
|
} from "./8ktwd3rh.js";
|
|
@@ -98,8 +100,10 @@ async function runUnit(connection, unit, run, session) {
|
|
|
98
100
|
await rebuildInvalidIndex(connection, item.step.sql);
|
|
99
101
|
const created = createdRoleName(item.step.sql);
|
|
100
102
|
const existed = created !== undefined && await roleExists(connection, created);
|
|
101
|
-
if (created === undefined
|
|
103
|
+
if (created === undefined)
|
|
102
104
|
await connection.execute(item.step.sql);
|
|
105
|
+
else if (!existed)
|
|
106
|
+
await connection.execute(createRoleOnce(item.step.sql));
|
|
103
107
|
if (created !== undefined && created === run.migrationRole) {
|
|
104
108
|
if (!existed) {
|
|
105
109
|
await grantSchema(connection, run.schema ?? "public", created);
|
|
@@ -377,8 +381,10 @@ function loadMigrations(directory) {
|
|
|
377
381
|
});
|
|
378
382
|
}
|
|
379
383
|
const plan = parsePlan(readFileSync(join(directory, file), "utf8"));
|
|
380
|
-
const
|
|
381
|
-
|
|
384
|
+
const stored = parseCatalog2(readFileSync(catalogPath, "utf8"));
|
|
385
|
+
const startup = startupCatalog2(stored);
|
|
386
|
+
const hash = catalogHash2(startup);
|
|
387
|
+
migrations.push(startup === stored ? { id, catalogHash: hash, steps: plan.steps } : { id, catalogHash: hash, legacyHash: catalogHash2(stored), steps: plan.steps });
|
|
382
388
|
}
|
|
383
389
|
return migrations;
|
|
384
390
|
}
|
|
@@ -601,11 +607,12 @@ async function installSnapshot(connection, head, schema, reference, session, mig
|
|
|
601
607
|
await assumeRole(connection, created, session);
|
|
602
608
|
continue;
|
|
603
609
|
}
|
|
610
|
+
const sql = created === undefined ? step.sql : createRoleOnce(step.sql);
|
|
604
611
|
if (step.transactional && !statementOutsideTransaction(step.sql)) {
|
|
605
|
-
batch.push(
|
|
612
|
+
batch.push(sql);
|
|
606
613
|
} else {
|
|
607
614
|
await flush();
|
|
608
|
-
await connection.execute(
|
|
615
|
+
await connection.execute(sql);
|
|
609
616
|
}
|
|
610
617
|
if (created !== undefined && created === migrationRole) {
|
|
611
618
|
await flush();
|