okmodel 0.5.0 → 0.6.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 +36 -18
- package/dist/adapters/pg/no-inflight-timeout.d.ts +17 -0
- package/dist/adapters/pg/postgres-extra.d.ts +22 -0
- package/dist/contracts/catalog/document.d.ts +19 -5
- package/dist/contracts/catalog/object.d.ts +2 -1
- package/dist/contracts/catalog/policy.d.ts +48 -0
- package/dist/contracts/catalog/types.d.ts +25 -1
- package/dist/contracts/catalog/view.d.ts +2 -0
- package/dist/contracts/internal.js +1 -1
- package/dist/contracts/location.d.ts +10 -0
- package/dist/dialects/pg/column.d.ts +13 -2
- package/dist/dialects/pg/ddl.d.ts +37 -1
- package/dist/dialects/pg/emit.d.ts +19 -1
- package/dist/dialects/pg/errors.d.ts +32 -1
- package/dist/dialects/pg/ext/citext.js +1 -1
- package/dist/dialects/pg/ext/index.js +1 -1
- package/dist/dialects/pg/ext/pg-trgm.js +1 -1
- package/dist/dialects/pg/filter-parse.d.ts +10 -3
- package/dist/dialects/pg/fn/index.js +10 -2
- package/dist/dialects/pg/index.d.ts +2 -1
- package/dist/dialects/pg/index.js +29 -17
- package/dist/dialects/pg/introspect.d.ts +7 -0
- package/dist/dialects/pg/model.d.ts +7 -2
- package/dist/dialects/pg/ops/or.d.ts +1 -1
- package/dist/dialects/pg/owner.d.ts +42 -0
- package/dist/dialects/pg/path-endpoint.d.ts +20 -0
- package/dist/dialects/pg/role/check.d.ts +3 -0
- package/dist/dialects/pg/role/index.d.ts +71 -6
- package/dist/dialects/pg/role/sql.d.ts +11 -0
- package/dist/dialects/pg/schema.d.ts +2 -0
- package/dist/dialects/pg/table.d.ts +25 -3
- package/dist/dialects/pg/temporal.d.ts +5 -76
- package/dist/dialects/pg/tenancy.d.ts +45 -3
- package/dist/dialects/pg/view/client.d.ts +19 -1
- package/dist/dialects/pg/view/index.d.ts +4 -0
- package/dist/dialects/pg/view/index.js +21 -178
- package/dist/dialects/pg/view/refresh.d.ts +24 -0
- package/dist/runtime/batch.d.ts +1 -1
- package/dist/runtime/client.d.ts +6 -1
- package/dist/runtime/conflict.d.ts +2 -1
- package/dist/runtime/drift.d.ts +9 -0
- package/dist/runtime/inflight.d.ts +14 -0
- package/dist/runtime/pg/bun.js +6 -5
- package/dist/runtime/pg/pg.js +5 -5
- package/dist/runtime/pg/pglite.js +6 -5
- package/dist/runtime/pg/postgresjs.js +5 -5
- package/dist/runtime/plan.d.ts +22 -1
- package/dist/runtime/predicate.d.ts +19 -0
- package/dist/runtime/safety/index.js +1 -1
- package/dist/runtime/tenancy/composite.d.ts +26 -0
- package/dist/runtime/tenancy/context.d.ts +16 -0
- package/dist/runtime/tenancy/index.d.ts +9 -5
- package/dist/runtime/tenancy/index.js +1508 -37
- package/dist/runtime/tenancy/path.d.ts +87 -0
- package/dist/runtime/tenancy/rls.d.ts +67 -0
- package/dist/runtime/tenancy/via.d.ts +22 -0
- package/dist/runtime/traits/index.js +17 -11
- package/dist/runtime/types.d.ts +13 -1
- package/dist/runtime/validate/index.js +4 -4
- package/dist/runtime/write.d.ts +1 -1
- package/dist/shared/09p049xa.js +702 -0
- package/dist/shared/{ykv7wh5b.js → 1f0xa3cb.js} +5 -5
- package/dist/shared/1nw1f3vs.js +23 -0
- package/dist/shared/{6p5k20sm.js → 1z04fa85.js} +21 -11
- package/dist/shared/{p7pfx624.js → 2cg3wnxc.js} +314 -65
- package/dist/shared/{dyj86cmj.js → 2jd1sn0e.js} +2 -2
- package/dist/shared/{qgvt8nx1.js → 2z7wv5tj.js} +21 -5
- package/dist/shared/{kyxb62mc.js → 31vm914h.js} +9 -1
- package/dist/shared/{sf8m6tfy.js → 32cnm7kn.js} +8 -3
- package/dist/shared/{t4tbsy9h.js → 358zsv4r.js} +1 -1
- package/dist/shared/{jdgqqx31.js → 3fqwmr09.js} +38 -14
- package/dist/shared/{922qbgnw.js → 3qnhc7w5.js} +16 -9
- package/dist/shared/{zvbjc949.js → 4az561fn.js} +1 -1
- package/dist/shared/{k3ted12y.js → 54tqkxja.js} +20 -2
- package/dist/shared/{k7cc9nzk.js → 5d8t84hg.js} +15 -3
- package/dist/shared/{fa9vt245.js → 5j36z8dn.js} +17 -6
- package/dist/shared/{1g0drakv.js → 5yv4k6a6.js} +1 -1
- package/dist/shared/8dqhth8c.js +12 -0
- package/dist/shared/8etn7d8w.js +62 -0
- package/dist/shared/{g516zdsb.js → 8x72s86k.js} +476 -30
- package/dist/shared/{nkc9sfqb.js → 929h19xp.js} +145 -7
- package/dist/shared/{gjthds9j.js → 9628a9xt.js} +1 -1
- package/dist/shared/{8xsbagad.js → 9s0ypp87.js} +88 -7
- package/dist/shared/{b066g80h.js → ag4c7516.js} +2 -2
- package/dist/shared/b3awxn7h.js +45 -0
- package/dist/shared/b4v57v3x.js +9 -0
- package/dist/shared/bdk4sty6.js +58 -0
- package/dist/shared/{s6gqfn5j.js → c58secgj.js} +125 -8
- package/dist/shared/{rrstp3kb.js → cgbamx3e.js} +2 -2
- package/dist/shared/d5azex6s.js +6 -0
- package/dist/shared/{5fqx9yh4.js → dk8v79p3.js} +3 -1
- package/dist/shared/{4m9fn52z.js → ed0b8k4s.js} +1 -1
- package/dist/shared/{z2rnngj4.js → ek2wt2dz.js} +8 -5
- package/dist/shared/{wxn4b7pp.js → f0f1n281.js} +59 -12
- package/dist/shared/{gdh9mrtp.js → g90m9b0g.js} +3 -2
- package/dist/shared/{tbszx8mz.js → gwn6v667.js} +2 -2
- package/dist/shared/{c8aghh05.js → h15jx9bc.js} +8 -2
- package/dist/shared/{3p4b1fg0.js → hazqqecq.js} +17 -93
- package/dist/shared/{4ef7mmqf.js → j3rkk835.js} +34 -11
- package/dist/shared/{bt9sfq0z.js → j60w0dvr.js} +56 -21
- package/dist/shared/{ycatkxmq.js → jgqj11w4.js} +1 -1
- package/dist/shared/k68eedmy.js +85 -0
- package/dist/shared/{szm0cksa.js → knmes2kh.js} +34 -6
- package/dist/shared/{ckjbyrt9.js → mb2ycs1p.js} +7 -9
- package/dist/shared/{tq9afp8d.js → n076ydsc.js} +1 -1
- package/dist/shared/{xhh1srw3.js → nx9hh281.js} +50 -32
- package/dist/shared/{kdkxh3kb.js → p248q79y.js} +58 -59
- package/dist/shared/{990a291j.js → p6bjzq9q.js} +14 -9
- package/dist/shared/{h4nqvjkp.js → pjr6xrm5.js} +2 -2
- package/dist/shared/pz6rj8ay.js +212 -0
- package/dist/shared/{5vdm4sgp.js → q3j1tq7a.js} +36 -23
- package/dist/shared/{8bwbwy8h.js → qq3899ht.js} +128 -18
- package/dist/shared/{dxjp14rk.js → r11n8grd.js} +2 -2
- package/dist/shared/r1fdd0f6.js +19 -0
- package/dist/shared/{8ktwd3rh.js → r3j8s5y0.js} +1 -1
- package/dist/shared/rhs3xe4k.js +7 -0
- package/dist/shared/{jsd07prz.js → rpycarcr.js} +6 -6
- package/dist/shared/{xsq7v6wp.js → sbdme3vy.js} +14 -2
- package/dist/shared/{xdpj5kkm.js → t3g0k88x.js} +775 -264
- package/dist/shared/{ayz64vzj.js → ttmg09vd.js} +708 -19
- package/dist/shared/{r6pj4fq2.js → venqrjna.js} +8 -4
- package/dist/shared/{fancm5pt.js → vjpnzwjz.js} +138 -15
- package/dist/shared/{9tgmr1gh.js → vmfkhszw.js} +44 -9
- package/dist/shared/{wqem4jed.js → wkme6tep.js} +11 -9
- package/dist/shared/{qy9rdq0g.js → wt5rzv1h.js} +15 -11
- package/dist/shared/wxr8cwns.js +6 -0
- package/dist/shared/{bzsjtd7c.js → wynzeggs.js} +19 -14
- package/dist/shared/x3jc53kg.js +220 -0
- package/dist/shared/{7p2wbz7f.js → x72jb7ad.js} +1 -1
- package/dist/shared/{fyqkk1m0.js → xq0mvhts.js} +10 -9
- package/dist/shared/xqve9598.js +53 -0
- package/dist/shared/{47xzb9fc.js → y2t3jktd.js} +2 -2
- package/dist/shared/{9x25fxhc.js → y34a8714.js} +1 -1
- package/dist/shared/{k7dwkhvq.js → y6jdds7g.js} +4 -1
- package/dist/shared/{h8ne16fq.js → ys0xzyaj.js} +1 -1
- package/dist/shared/{c9z5g0fm.js → ywr8hmey.js} +5 -2
- package/dist/shared/{g7ez901n.js → ywspezzx.js} +1 -1
- package/dist/shared/{9m80mkac.js → ze4hxsmy.js} +1 -1
- package/dist/shared/{fb00y8fp.js → zm0mafk4.js} +12 -6
- package/dist/shared/{y005b761.js → zy8r7qvz.js} +6 -2
- package/dist/tooling/cli.js +97 -24
- package/dist/tooling/migrate/apply.d.ts +14 -0
- package/dist/tooling/migrate/check.d.ts +3 -4
- package/dist/tooling/migrate/classify.d.ts +4 -0
- package/dist/tooling/migrate/commands.d.ts +1 -2
- package/dist/tooling/migrate/config.d.ts +3 -2
- package/dist/tooling/migrate/drift.d.ts +1 -1
- package/dist/tooling/migrate/estimate.d.ts +14 -1
- package/dist/tooling/migrate/files.d.ts +11 -1
- package/dist/tooling/migrate/index.js +17 -16
- package/dist/tooling/migrate/lint.d.ts +4 -4
- package/dist/tooling/migrate/lost.d.ts +28 -0
- package/dist/tooling/migrate/paths.d.ts +14 -0
- package/dist/tooling/migrate/plan.d.ts +10 -3
- package/dist/tooling/migrate/policy.d.ts +11 -0
- package/dist/tooling/migrate/runner.d.ts +25 -0
- package/dist/tooling/migrate/sandbox.d.ts +57 -0
- package/dist/tooling/migrate/sql-lex.d.ts +39 -0
- package/dist/tooling/migrate/text.d.ts +42 -0
- package/dist/tooling/node-version.d.ts +21 -0
- package/dist/tooling/testing/factories.d.ts +10 -0
- package/dist/tooling/testing/facts.d.ts +33 -5
- package/dist/tooling/testing/index.d.ts +1 -1
- package/dist/tooling/testing/index.js +3 -3
- package/dist/tooling/testing/isolation.d.ts +15 -8
- package/package.json +10 -6
- package/dist/shared/0v1g424p.js +0 -26
- package/dist/shared/r73pt594.js +0 -426
- package/dist/shared/rasvvzgz.js +0 -21
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
isConnectionSqlstate,
|
|
3
|
+
isConnectionErrno
|
|
4
|
+
} from "./gwn6v667.js";
|
|
4
5
|
import {
|
|
5
6
|
createClient
|
|
6
|
-
} from "./
|
|
7
|
+
} from "./j60w0dvr.js";
|
|
7
8
|
import {
|
|
8
9
|
OkmError2
|
|
9
10
|
} from "./52szzakm.js";
|
|
@@ -330,7 +331,8 @@ async function openEndpoint(open, url, max, defaults, name, role, weight, probeM
|
|
|
330
331
|
timer: undefined,
|
|
331
332
|
current: 0,
|
|
332
333
|
inflight: 0,
|
|
333
|
-
latencyMs: null
|
|
334
|
+
latencyMs: null,
|
|
335
|
+
generation: 0
|
|
334
336
|
};
|
|
335
337
|
}
|
|
336
338
|
async function detectPosition(endpoint) {
|
|
@@ -344,8 +346,11 @@ async function detectPosition(endpoint) {
|
|
|
344
346
|
async function sample(handle, endpoint) {
|
|
345
347
|
try {
|
|
346
348
|
const sampled = await readPosition(handle, endpoint);
|
|
349
|
+
const reopened = endpoint.circuit === "open";
|
|
347
350
|
endpoint.failures = 0;
|
|
348
351
|
endpoint.circuit = "closed";
|
|
352
|
+
if (reopened)
|
|
353
|
+
endpoint.generation += 1;
|
|
349
354
|
applySample(endpoint, sampled);
|
|
350
355
|
} catch {
|
|
351
356
|
endpoint.failures += 1;
|
|
@@ -514,6 +519,7 @@ function routePool(handle) {
|
|
|
514
519
|
replicaRefused();
|
|
515
520
|
const reason = options?.route === "primary" ? "constraint:primary" : "primary-required";
|
|
516
521
|
tell(handle, { op: "write", endpoint: primary.name, reason });
|
|
522
|
+
await callGuard(primary);
|
|
517
523
|
const result = await primary.pool.batch(statements, strip(options));
|
|
518
524
|
await noteWrite(handle, primary.pool);
|
|
519
525
|
return result;
|
|
@@ -554,6 +560,14 @@ function routePool(handle) {
|
|
|
554
560
|
endpoint.pool.cancel?.();
|
|
555
561
|
};
|
|
556
562
|
}
|
|
563
|
+
const routed = pool;
|
|
564
|
+
routed.okmReadOnlyUnit = (text, params, prelude, options) => readOnlyUnit(handle, text, params, prelude, options);
|
|
565
|
+
routed.okmReadOnlyStream = (text, params, prelude, options) => readOnlyStream(handle, text, params, prelude, options);
|
|
566
|
+
routed.okmEndpoints = () => handle.endpoints.map((endpoint) => ({
|
|
567
|
+
name: endpoint.name,
|
|
568
|
+
generation: endpoint.generation,
|
|
569
|
+
pool: endpoint.pool
|
|
570
|
+
}));
|
|
557
571
|
return pool;
|
|
558
572
|
}
|
|
559
573
|
function derive(schema, handle, router, shared, route) {
|
|
@@ -600,8 +614,82 @@ function force(handle, router, route) {
|
|
|
600
614
|
}
|
|
601
615
|
if (router.cancel !== undefined)
|
|
602
616
|
pool.cancel = () => router.cancel();
|
|
617
|
+
const unit = router.okmReadOnlyUnit;
|
|
618
|
+
const stream = router.okmReadOnlyStream;
|
|
619
|
+
const forced = pool;
|
|
620
|
+
if (unit !== undefined) {
|
|
621
|
+
forced.okmReadOnlyUnit = (text, params, prelude, options) => unit(text, params, prelude, { ...options, route });
|
|
622
|
+
}
|
|
623
|
+
if (stream !== undefined) {
|
|
624
|
+
forced.okmReadOnlyStream = (text, params, prelude, options) => stream(text, params, prelude, { ...options, route });
|
|
625
|
+
}
|
|
603
626
|
return pool;
|
|
604
627
|
}
|
|
628
|
+
async function readOnlyUnit(handle, text, params, prelude, options) {
|
|
629
|
+
if (handle.closed)
|
|
630
|
+
closed();
|
|
631
|
+
const choice = await choose(handle, text, options?.route);
|
|
632
|
+
return attempt(handle, choice, async (endpoint) => {
|
|
633
|
+
if (endpoint.pool.reserve === undefined)
|
|
634
|
+
replicaReserve();
|
|
635
|
+
const conn = await endpoint.pool.reserve();
|
|
636
|
+
try {
|
|
637
|
+
await conn.execute("begin read only");
|
|
638
|
+
try {
|
|
639
|
+
await conn.execute(prelude.text, prelude.params);
|
|
640
|
+
const result = await conn.execute(text, params, strip(options));
|
|
641
|
+
await conn.execute("commit");
|
|
642
|
+
return result;
|
|
643
|
+
} catch (error) {
|
|
644
|
+
await conn.execute("rollback").catch(() => {
|
|
645
|
+
return;
|
|
646
|
+
});
|
|
647
|
+
throw error;
|
|
648
|
+
}
|
|
649
|
+
} finally {
|
|
650
|
+
await conn.release();
|
|
651
|
+
}
|
|
652
|
+
});
|
|
653
|
+
}
|
|
654
|
+
function readOnlyStream(handle, text, params, prelude, options) {
|
|
655
|
+
return async function* () {
|
|
656
|
+
if (handle.closed)
|
|
657
|
+
closed();
|
|
658
|
+
const choice = await choose(handle, text, options?.route);
|
|
659
|
+
tell(handle, { op: choice.op, endpoint: choice.endpoint.name, reason: choice.reason });
|
|
660
|
+
await callGuard(choice.endpoint);
|
|
661
|
+
if (choice.endpoint.pool.reserve === undefined)
|
|
662
|
+
replicaReserve();
|
|
663
|
+
const conn = await choice.endpoint.pool.reserve();
|
|
664
|
+
try {
|
|
665
|
+
await conn.execute("begin read only");
|
|
666
|
+
try {
|
|
667
|
+
await conn.execute(prelude.text, prelude.params);
|
|
668
|
+
await conn.execute(`declare okm_rls no scroll cursor for ${text}`, params);
|
|
669
|
+
for (;; ) {
|
|
670
|
+
const chunk = await conn.execute("fetch 64 from okm_rls");
|
|
671
|
+
if (chunk.rows.length === 0)
|
|
672
|
+
break;
|
|
673
|
+
yield chunk.rows;
|
|
674
|
+
}
|
|
675
|
+
await conn.execute("close okm_rls");
|
|
676
|
+
await conn.execute("commit");
|
|
677
|
+
} catch (error) {
|
|
678
|
+
await conn.execute("rollback").catch(() => {
|
|
679
|
+
return;
|
|
680
|
+
});
|
|
681
|
+
throw error;
|
|
682
|
+
}
|
|
683
|
+
} finally {
|
|
684
|
+
await conn.release();
|
|
685
|
+
}
|
|
686
|
+
}();
|
|
687
|
+
}
|
|
688
|
+
function replicaReserve() {
|
|
689
|
+
throw new OkmError2("OKM1111", "Row-level security needs a driver that can reserve a connection.", {
|
|
690
|
+
fix: { summary: "Use a Postgres driver that supports interactive transactions." }
|
|
691
|
+
});
|
|
692
|
+
}
|
|
605
693
|
function classOf(text) {
|
|
606
694
|
const head = text.trimStart().toLowerCase().replace(/\s+/g, " ");
|
|
607
695
|
if (/^(begin|start transaction|commit|rollback|savepoint|release|set|reset)\b/.test(head)) {
|
|
@@ -611,7 +699,7 @@ function classOf(text) {
|
|
|
611
699
|
return "lock";
|
|
612
700
|
if (/\sfor (no key update|key share|update|share)\b/.test(head))
|
|
613
701
|
return "lock";
|
|
614
|
-
if (/^(insert|update|delete|with|create|alter|drop|truncate|grant|revoke|comment|vacuum|analyze|reindex|copy)\b/.test(head)) {
|
|
702
|
+
if (/^(insert|update|delete|refresh|with|create|alter|drop|truncate|grant|revoke|comment|vacuum|analyze|reindex|copy)\b/.test(head)) {
|
|
615
703
|
return "write";
|
|
616
704
|
}
|
|
617
705
|
return "read";
|
|
@@ -625,7 +713,7 @@ async function choose(handle, text, route) {
|
|
|
625
713
|
if (primary === undefined)
|
|
626
714
|
throw new OkmError2("OKM1120", "A topology needs one primary URL.");
|
|
627
715
|
if (text.trimStart().toLowerCase().startsWith("select current_setting")) {
|
|
628
|
-
return { endpoint: primary, op: "read", reason: "primary-required" };
|
|
716
|
+
return { endpoint: primary, op: "read", reason: "primary-required", skipGuard: true };
|
|
629
717
|
}
|
|
630
718
|
if (route === "replica" && op !== "read")
|
|
631
719
|
replicaRefused();
|
|
@@ -672,17 +760,67 @@ async function* readStream(handle, text, route, params, fallback) {
|
|
|
672
760
|
async function attempt(handle, choice, run) {
|
|
673
761
|
tell(handle, { op: choice.op, endpoint: choice.endpoint.name, reason: choice.reason });
|
|
674
762
|
try {
|
|
763
|
+
if (choice.skipGuard !== true)
|
|
764
|
+
await callGuard(choice.endpoint);
|
|
675
765
|
return await tracked(choice.endpoint, choice.op === "read", () => run(choice.endpoint));
|
|
676
766
|
} catch (error) {
|
|
677
|
-
if (choice.op !== "read" || !
|
|
767
|
+
if (choice.op !== "read" || !isUnreachable(error))
|
|
678
768
|
throw error;
|
|
769
|
+
choice.endpoint.generation += 1;
|
|
679
770
|
const next = await retryOf(handle, choice);
|
|
680
771
|
if (next === undefined)
|
|
681
772
|
throw error;
|
|
682
773
|
tell(handle, { op: "read", endpoint: next.endpoint.name, reason: next.reason });
|
|
774
|
+
if (choice.skipGuard !== true)
|
|
775
|
+
await callGuard(next.endpoint);
|
|
683
776
|
return tracked(next.endpoint, true, () => run(next.endpoint));
|
|
684
777
|
}
|
|
685
778
|
}
|
|
779
|
+
function callGuard(endpoint) {
|
|
780
|
+
const guard = endpoint.pool.okmGuard;
|
|
781
|
+
if (guard === undefined)
|
|
782
|
+
return Promise.resolve();
|
|
783
|
+
return guard({
|
|
784
|
+
name: endpoint.name,
|
|
785
|
+
generation: endpoint.generation,
|
|
786
|
+
pool: endpoint.pool
|
|
787
|
+
});
|
|
788
|
+
}
|
|
789
|
+
var CHAIN_DEPTH = 8;
|
|
790
|
+
function isUnreachable(error) {
|
|
791
|
+
const seen = new Set;
|
|
792
|
+
const visit = (value, depth) => {
|
|
793
|
+
if (typeof value !== "object" || value === null || depth > CHAIN_DEPTH)
|
|
794
|
+
return false;
|
|
795
|
+
if (seen.has(value))
|
|
796
|
+
return false;
|
|
797
|
+
seen.add(value);
|
|
798
|
+
if (unreachableNode(value))
|
|
799
|
+
return true;
|
|
800
|
+
if (visit(Reflect.get(value, "cause"), depth + 1))
|
|
801
|
+
return true;
|
|
802
|
+
const errors = Reflect.get(value, "errors");
|
|
803
|
+
return Array.isArray(errors) && errors.some((item) => visit(item, depth + 1));
|
|
804
|
+
};
|
|
805
|
+
return visit(error, 0);
|
|
806
|
+
}
|
|
807
|
+
function unreachableNode(node) {
|
|
808
|
+
for (const key of ["sqlstate", "code", "errno"]) {
|
|
809
|
+
const code = Reflect.get(node, key);
|
|
810
|
+
if (typeof code !== "string" || code.length === 0)
|
|
811
|
+
continue;
|
|
812
|
+
if (isConnectionSqlstate(code) || isConnectionErrno(code))
|
|
813
|
+
return true;
|
|
814
|
+
if (code.startsWith("ERR_POSTGRES_CONNECTION_"))
|
|
815
|
+
return true;
|
|
816
|
+
if (code === "ERR_POSTGRES_IDLE_TIMEOUT" || code === "ERR_POSTGRES_LIFETIME_TIMEOUT") {
|
|
817
|
+
return true;
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
if (!(node instanceof Error))
|
|
821
|
+
return false;
|
|
822
|
+
return node.message.includes("ECONNREFUSED") || node.message.includes("ECONNRESET") || node.message.includes("CONNECTION_CLOSED") || node.message.includes("terminating connection") || node.message.includes("The pool is closed");
|
|
823
|
+
}
|
|
686
824
|
async function tracked(endpoint, time, run) {
|
|
687
825
|
const replica = endpoint.role === "replica";
|
|
688
826
|
if (replica)
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
creationOrder2
|
|
3
|
-
} from "./
|
|
3
|
+
} from "./qq3899ht.js";
|
|
4
4
|
import {
|
|
5
5
|
isDomain
|
|
6
|
-
} from "./
|
|
6
|
+
} from "./ywspezzx.js";
|
|
7
7
|
import {
|
|
8
8
|
quoteLiteral
|
|
9
9
|
} from "./94ez8kzh.js";
|
|
10
10
|
import {
|
|
11
11
|
identityKey2
|
|
12
|
-
} from "./
|
|
12
|
+
} from "./358zsv4r.js";
|
|
13
13
|
import {
|
|
14
14
|
fitIdentifier2
|
|
15
15
|
} from "./nfzc5z0w.js";
|
|
@@ -22,6 +22,7 @@ function renderCatalog(source, schema) {
|
|
|
22
22
|
const folded = foldedKeys(source);
|
|
23
23
|
const statements = [];
|
|
24
24
|
const ordered = creationOrder2(source);
|
|
25
|
+
const created = uniqueBeforeForeignKey(ordered);
|
|
25
26
|
for (const object of ordered) {
|
|
26
27
|
if (object.kind !== "type" || object.owner === "ignored")
|
|
27
28
|
continue;
|
|
@@ -29,8 +30,8 @@ function renderCatalog(source, schema) {
|
|
|
29
30
|
if (sql !== undefined)
|
|
30
31
|
statements.push(sql);
|
|
31
32
|
}
|
|
32
|
-
for (const object of
|
|
33
|
-
if (object.kind === "type" || object.kind === "function" || object.kind === "trigger" || object.kind === "view" || object.kind === "materializedView" || ownedByView(object)) {
|
|
33
|
+
for (const object of created) {
|
|
34
|
+
if (object.kind === "type" || object.kind === "function" || object.kind === "trigger" || object.kind === "view" || object.kind === "materializedView" || object.kind === "policy" || ownedByView(object)) {
|
|
34
35
|
continue;
|
|
35
36
|
}
|
|
36
37
|
if (object.owner === "ignored")
|
|
@@ -46,6 +47,12 @@ function renderCatalog(source, schema) {
|
|
|
46
47
|
if (sql !== undefined)
|
|
47
48
|
statements.push(sql);
|
|
48
49
|
}
|
|
50
|
+
for (const object of created) {
|
|
51
|
+
if (object.kind !== "policy" || object.owner === "ignored")
|
|
52
|
+
continue;
|
|
53
|
+
for (const step of policyCreatePlan(object, schema))
|
|
54
|
+
statements.push(step.sql);
|
|
55
|
+
}
|
|
49
56
|
for (const kind of ["function", "trigger"]) {
|
|
50
57
|
for (const object of ordered) {
|
|
51
58
|
if (object.kind !== kind || object.owner === "ignored")
|
|
@@ -73,6 +80,48 @@ function renderCatalog(source, schema) {
|
|
|
73
80
|
}
|
|
74
81
|
return statements;
|
|
75
82
|
}
|
|
83
|
+
function uniqueBeforeForeignKey(objects) {
|
|
84
|
+
const uniques = objects.filter((object) => object.kind === "constraint" && object.definition.constraintKind === "unique");
|
|
85
|
+
if (uniques.length === 0)
|
|
86
|
+
return objects;
|
|
87
|
+
const emitted = new Set;
|
|
88
|
+
const result = [];
|
|
89
|
+
for (const object of objects) {
|
|
90
|
+
if (emitted.has(object))
|
|
91
|
+
continue;
|
|
92
|
+
if (object.kind === "constraint" && object.definition.constraintKind === "foreignKey") {
|
|
93
|
+
const target = object.definition.references;
|
|
94
|
+
if (target !== undefined && !coveredByPrimary(objects, target.parent, target.columns)) {
|
|
95
|
+
const columns = target.columns.join("\x00");
|
|
96
|
+
for (const unique of uniques) {
|
|
97
|
+
if (emitted.has(unique))
|
|
98
|
+
continue;
|
|
99
|
+
if (!sameRef(unique.identity.parent, target.parent))
|
|
100
|
+
continue;
|
|
101
|
+
if (unique.definition.columns.join("\x00") !== columns)
|
|
102
|
+
continue;
|
|
103
|
+
result.push(unique);
|
|
104
|
+
emitted.add(unique);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
result.push(object);
|
|
109
|
+
emitted.add(object);
|
|
110
|
+
}
|
|
111
|
+
return result;
|
|
112
|
+
}
|
|
113
|
+
function coveredByPrimary(objects, parent, columns) {
|
|
114
|
+
const key = columns.join("\x00");
|
|
115
|
+
return objects.some((object) => object.kind === "constraint" && object.definition.constraintKind === "primaryKey" && sameRef(object.identity.parent, parent) && object.definition.columns.join("\x00") === key);
|
|
116
|
+
}
|
|
117
|
+
function sameRef(left, right) {
|
|
118
|
+
if (left.name !== right.name || left.namespace.form !== right.namespace.form)
|
|
119
|
+
return false;
|
|
120
|
+
if (left.namespace.form === "static" && right.namespace.form === "static") {
|
|
121
|
+
return left.namespace.name === right.namespace.name;
|
|
122
|
+
}
|
|
123
|
+
return left.namespace.form === "template" && right.namespace.form === "template" ? left.namespace.pattern === right.namespace.pattern : false;
|
|
124
|
+
}
|
|
76
125
|
function ownedByView(object) {
|
|
77
126
|
if (object.kind !== "index")
|
|
78
127
|
return false;
|
|
@@ -149,7 +198,39 @@ function functionSql(object, schema, replace) {
|
|
|
149
198
|
}
|
|
150
199
|
function viewSql(object, schema, replace) {
|
|
151
200
|
const verb = replace ? "create or replace view" : "create view";
|
|
152
|
-
|
|
201
|
+
const invoker = object.definition.securityInvoker === true ? " with (security_invoker = true)" : "";
|
|
202
|
+
return `${verb} ${qualify(schema, object.identity.name)}${invoker} as ${object.definition.query}`;
|
|
203
|
+
}
|
|
204
|
+
function policyCreatePlan(object, schema) {
|
|
205
|
+
const table = qualify(schema, object.identity.parent.name);
|
|
206
|
+
const name = quoteIdent(object.identity.name);
|
|
207
|
+
const command = object.definition.command === "all" ? "all" : "select";
|
|
208
|
+
const check = object.definition.command === "all" ? ` with check ${object.definition.expression}` : "";
|
|
209
|
+
const create = {
|
|
210
|
+
sql: `create policy ${name} on ${table} as permissive for ${command} using ${object.definition.expression}${check}`,
|
|
211
|
+
kind: "create-policy"
|
|
212
|
+
};
|
|
213
|
+
if (object.definition.command !== "all")
|
|
214
|
+
return [create];
|
|
215
|
+
return [
|
|
216
|
+
{ sql: `alter table ${table} enable row level security`, kind: "enable-rls" },
|
|
217
|
+
{ sql: `alter table ${table} force row level security`, kind: "enable-rls" },
|
|
218
|
+
create
|
|
219
|
+
];
|
|
220
|
+
}
|
|
221
|
+
function policyDropPlan(object, schema) {
|
|
222
|
+
const table = qualify(schema, object.identity.parent.name);
|
|
223
|
+
const drop = {
|
|
224
|
+
sql: `drop policy ${quoteIdent(object.identity.name)} on ${table}`,
|
|
225
|
+
kind: "drop-policy"
|
|
226
|
+
};
|
|
227
|
+
if (object.definition.command !== "all")
|
|
228
|
+
return [drop];
|
|
229
|
+
return [
|
|
230
|
+
drop,
|
|
231
|
+
{ sql: `alter table ${table} no force row level security`, kind: "disable-rls" },
|
|
232
|
+
{ sql: `alter table ${table} disable row level security`, kind: "disable-rls" }
|
|
233
|
+
];
|
|
153
234
|
}
|
|
154
235
|
function materializedViewSql(object, schema) {
|
|
155
236
|
return `create materialized view ${qualify(schema, object.identity.name)} as ${object.definition.query} with no data`;
|
|
@@ -315,4 +396,4 @@ function qualify(schema, name) {
|
|
|
315
396
|
return `${quoteIdent(schema)}.${quoteIdent(name)}`;
|
|
316
397
|
}
|
|
317
398
|
|
|
318
|
-
export { quoteIdent, renderCatalog, ownedByView, dropObjectSql, createObjectSql, functionSql, viewSql, refreshMaterializedViewSql, alterColumnSql, identitySequence, createTableSql, qualify };
|
|
399
|
+
export { quoteIdent, renderCatalog, uniqueBeforeForeignKey, ownedByView, dropObjectSql, createObjectSql, functionSql, viewSql, policyCreatePlan, policyDropPlan, refreshMaterializedViewSql, alterColumnSql, identitySequence, createTableSql, qualify };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import {
|
|
2
|
+
isRecord,
|
|
3
|
+
orFail
|
|
4
|
+
} from "./2z7wv5tj.js";
|
|
5
|
+
import {
|
|
6
|
+
isOperator,
|
|
7
|
+
operatorName,
|
|
8
|
+
operatorValue
|
|
9
|
+
} from "./cn0n68ft.js";
|
|
10
|
+
|
|
11
|
+
// src/runtime/predicate.ts
|
|
12
|
+
function effectivePredicate(where) {
|
|
13
|
+
if (where === undefined)
|
|
14
|
+
return false;
|
|
15
|
+
if (isOperator(where)) {
|
|
16
|
+
const name = operatorName(where);
|
|
17
|
+
const value = operatorValue(where);
|
|
18
|
+
if (name === "or") {
|
|
19
|
+
if (!Array.isArray(value))
|
|
20
|
+
orFail(false);
|
|
21
|
+
if (value.length === 0)
|
|
22
|
+
return true;
|
|
23
|
+
for (const branch of value) {
|
|
24
|
+
if (!effectivePredicate(branch))
|
|
25
|
+
orFail(true);
|
|
26
|
+
}
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
if (name === "and") {
|
|
30
|
+
return Array.isArray(value) && value.some((part) => effectivePredicate(part));
|
|
31
|
+
}
|
|
32
|
+
if (name === "not")
|
|
33
|
+
return effectivePredicate(value);
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
if (!isRecord(where))
|
|
37
|
+
return true;
|
|
38
|
+
for (const key of Object.keys(where)) {
|
|
39
|
+
if (where[key] !== undefined)
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export { effectivePredicate };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// src/runtime/inflight.ts
|
|
2
|
+
async function refuseUncancellableTimeout(pool, timeout) {
|
|
3
|
+
if (pool.capabilities.cancel === true || timeout === undefined || !(timeout > 0))
|
|
4
|
+
return;
|
|
5
|
+
const { noTimeout } = await import("./wxr8cwns.js");
|
|
6
|
+
noTimeout({ timeout });
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export { refuseUncancellableTimeout };
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import {
|
|
2
|
+
assertNamespace2,
|
|
3
|
+
normaliseEdges,
|
|
4
|
+
assertProvenance
|
|
5
|
+
} from "./358zsv4r.js";
|
|
6
|
+
import {
|
|
7
|
+
isReservedIdentifier2,
|
|
8
|
+
assertIdentifier2,
|
|
9
|
+
fitIdentifier2,
|
|
10
|
+
assertStoredText
|
|
11
|
+
} from "./nfzc5z0w.js";
|
|
12
|
+
import {
|
|
13
|
+
catalogError2
|
|
14
|
+
} from "./52szzakm.js";
|
|
15
|
+
|
|
16
|
+
// src/contracts/catalog/policy.ts
|
|
17
|
+
var BARE_IDENT = /^[a-z_][a-z0-9_$]*$/;
|
|
18
|
+
function policyIdent(name) {
|
|
19
|
+
if (BARE_IDENT.test(name) && !isReservedIdentifier2(name))
|
|
20
|
+
return name;
|
|
21
|
+
return `"${name.replaceAll('"', '""')}"`;
|
|
22
|
+
}
|
|
23
|
+
function tenantPolicyExpression(column, dataType) {
|
|
24
|
+
return `(${policyIdent(column)} = (NULLIF(current_setting('app.tenant'::text, true), ''::text))::${dataType})`;
|
|
25
|
+
}
|
|
26
|
+
function unscopedPolicyExpression() {
|
|
27
|
+
return `(current_setting('app.unscoped'::text, true) = 'on'::text)`;
|
|
28
|
+
}
|
|
29
|
+
function policyObject(input) {
|
|
30
|
+
assertNamespace2(input.parent.namespace);
|
|
31
|
+
assertIdentifier2(input.parent.name, "policy parent");
|
|
32
|
+
assertIdentifier2(input.name, "policy");
|
|
33
|
+
assertStoredText(input.expression, "policy expression");
|
|
34
|
+
if (input.command !== "all" && input.command !== "select") {
|
|
35
|
+
catalogError2("OKM1020", `Policy ${input.name} command is not supported.`);
|
|
36
|
+
}
|
|
37
|
+
assertProvenance(input.provenance);
|
|
38
|
+
const parent = {
|
|
39
|
+
kind: "table",
|
|
40
|
+
namespace: input.parent.namespace,
|
|
41
|
+
name: input.parent.name
|
|
42
|
+
};
|
|
43
|
+
const definition = {
|
|
44
|
+
command: input.command,
|
|
45
|
+
expression: input.expression,
|
|
46
|
+
force: input.force
|
|
47
|
+
};
|
|
48
|
+
return {
|
|
49
|
+
kind: "policy",
|
|
50
|
+
identity: { kind: "policy", parent: input.parent, name: fitIdentifier2(input.name) },
|
|
51
|
+
owner: input.owner ?? "managed",
|
|
52
|
+
definition,
|
|
53
|
+
dependencies: normaliseEdges([parent, ...input.dependencies ?? []]),
|
|
54
|
+
provenance: input.provenance
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export { tenantPolicyExpression, unscopedPolicyExpression, policyObject };
|