okmodel 0.5.1 → 0.7.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 +100 -1116
- package/dist/adapters/capabilities.d.ts +3 -0
- package/dist/adapters/failure.d.ts +13 -2
- package/dist/adapters/lazy-errors.d.ts +22 -0
- package/dist/adapters/pg/bunsql-extra.d.ts +54 -3
- package/dist/adapters/pg/bunsql.d.ts +14 -1
- package/dist/adapters/pg/cursor.d.ts +17 -0
- package/dist/adapters/pg/no-inflight-timeout.d.ts +20 -0
- package/dist/adapters/pg/nodepostgres-extra.d.ts +22 -1
- package/dist/adapters/pg/nodepostgres.d.ts +12 -0
- package/dist/adapters/pg/pglite-wire.d.ts +24 -0
- package/dist/adapters/pg/pglite.d.ts +10 -0
- package/dist/adapters/pg/postgres-extra.d.ts +41 -3
- package/dist/adapters/pg/reserved.d.ts +42 -0
- package/dist/adapters/pg/session.d.ts +0 -18
- 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/connection.d.ts +7 -6
- 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 +5 -4
- package/dist/dialects/pg/floor.d.ts +68 -0
- package/dist/dialects/pg/fn/index.js +2 -2
- package/dist/dialects/pg/index.d.ts +8 -2
- package/dist/dialects/pg/index.js +67 -171
- package/dist/dialects/pg/introspect.d.ts +7 -0
- package/dist/dialects/pg/keys.d.ts +11 -8
- package/dist/dialects/pg/model.d.ts +47 -2
- package/dist/dialects/pg/morph.d.ts +43 -0
- package/dist/dialects/pg/operator-fit.d.ts +2 -2
- package/dist/dialects/pg/operators.d.ts +14 -7
- package/dist/dialects/pg/ops/bucket.d.ts +65 -0
- package/dist/dialects/pg/ops/inc.d.ts +2 -2
- package/dist/dialects/pg/ops/matches.d.ts +9 -12
- package/dist/dialects/pg/ops/relevance.d.ts +13 -0
- package/dist/dialects/pg/ops/search-query.d.ts +22 -0
- package/dist/dialects/pg/ops/window.d.ts +103 -0
- package/dist/dialects/pg/owner.d.ts +42 -0
- package/dist/dialects/pg/path-endpoint.d.ts +20 -0
- package/dist/dialects/pg/preset.d.ts +1 -1
- package/dist/dialects/pg/relations.d.ts +100 -3
- 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 +33 -3
- package/dist/dialects/pg/table.d.ts +25 -3
- 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/aggregate.d.ts +8 -2
- package/dist/runtime/batch.d.ts +1 -1
- package/dist/runtime/bucket-group.d.ts +70 -0
- package/dist/runtime/conflict.d.ts +24 -6
- package/dist/runtime/drift.d.ts +9 -0
- package/dist/runtime/include.d.ts +0 -8
- package/dist/runtime/inflight.d.ts +14 -0
- package/dist/runtime/page.d.ts +4 -1
- package/dist/runtime/pg/bun.js +12 -5
- package/dist/runtime/pg/pg.js +5 -5
- package/dist/runtime/pg/pglite.d.ts +1 -0
- package/dist/runtime/pg/pglite.js +9 -8
- package/dist/runtime/pg/postgresjs.js +5 -5
- package/dist/runtime/plan.d.ts +113 -15
- package/dist/runtime/predicate.d.ts +19 -0
- package/dist/runtime/read-stream.d.ts +13 -16
- package/dist/runtime/result-name.d.ts +17 -0
- package/dist/runtime/safety/index.js +1 -1
- package/dist/runtime/server-check.d.ts +3 -3
- package/dist/runtime/sort-bind.d.ts +21 -0
- package/dist/runtime/sort.d.ts +56 -0
- package/dist/runtime/sync.d.ts +70 -0
- 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 +1511 -38
- 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/text-search.d.ts +20 -0
- package/dist/runtime/traits/index.d.ts +80 -0
- package/dist/runtime/traits/index.js +187 -17
- package/dist/runtime/tree.d.ts +38 -0
- package/dist/runtime/types.d.ts +231 -23
- package/dist/runtime/validate/index.js +4 -4
- package/dist/runtime/version.d.ts +39 -0
- package/dist/runtime/window.d.ts +21 -0
- package/dist/runtime/write.d.ts +55 -3
- package/dist/shared/{krxx77g0.js → 14vx95q4.js} +12 -18
- package/dist/shared/1est4ezg.js +313 -0
- package/dist/shared/{4az561fn.js → 1qa0qajz.js} +8 -23
- package/dist/shared/1w508jbr.js +1611 -0
- package/dist/shared/2c13q96h.js +18 -0
- package/dist/shared/2d3xq4ps.js +9 -0
- package/dist/shared/2shdbn8q.js +23 -0
- package/dist/shared/{t4tbsy9h.js → 358zsv4r.js} +1 -1
- package/dist/shared/3v7t1yrv.js +208 -0
- package/dist/shared/5e3tf63j.js +220 -0
- package/dist/shared/5fe3kbsh.js +10 -0
- package/dist/shared/5v3xf80k.js +37 -0
- package/dist/shared/{51mvgj8w.js → 63qtkrca.js} +130 -3
- package/dist/shared/{gbtcc2d7.js → 67txcrcw.js} +62 -66
- package/dist/shared/79dt02vc.js +12 -0
- package/dist/shared/{v36c5g6p.js → 7k9grvf6.js} +407 -14
- package/dist/shared/7kms6fvj.js +20 -0
- package/dist/shared/7mnme5tn.js +8 -0
- package/dist/shared/7n7ddwt4.js +6 -0
- package/dist/shared/{87jvvhnt.js → 81ebdx9p.js} +48 -68
- package/dist/shared/{szm0cksa.js → 8skf0cam.js} +34 -6
- package/dist/shared/{gjthds9j.js → 9628a9xt.js} +1 -1
- package/dist/shared/9a4ae4p8.js +31 -0
- package/dist/shared/{8xsbagad.js → 9s0ypp87.js} +88 -7
- package/dist/shared/9y3mmmh1.js +436 -0
- package/dist/shared/ab9gmbwy.js +213 -0
- package/dist/shared/{sycnx8gt.js → ax7qv55k.js} +18 -8
- package/dist/shared/{f5cw5q5r.js → aytqh5y2.js} +6 -4
- package/dist/shared/{fancm5pt.js → b5pftnn2.js} +138 -15
- package/dist/shared/{efmy2gcg.js → b76b8d95.js} +2 -2
- package/dist/shared/bdk4sty6.js +58 -0
- package/dist/shared/{32zqc1dw.js → bg3rym3g.js} +63 -32
- package/dist/shared/{0t22wwh1.js → bm22fvzr.js} +16 -14
- package/dist/shared/bz84tkzm.js +342 -0
- package/dist/shared/{31vm914h.js → cm3w0ywp.js} +15 -16
- package/dist/shared/cn957f8d.js +179 -0
- package/dist/shared/{pf0d8f77.js → cnkky55j.js} +25 -14
- package/dist/shared/{5fqx9yh4.js → dk8v79p3.js} +3 -1
- package/dist/shared/{nkaxvt9q.js → dkxgzaqd.js} +224 -19
- package/dist/shared/dzj09cye.js +10 -0
- package/dist/shared/{4m9fn52z.js → ed0b8k4s.js} +1 -1
- package/dist/shared/{z2rnngj4.js → ek2wt2dz.js} +8 -5
- package/dist/shared/exn3sd90.js +359 -0
- package/dist/shared/g6evj1j3.js +66 -0
- package/dist/shared/ga9j92qj.js +25 -0
- package/dist/shared/{qv2ydck9.js → gs74dbj5.js} +651 -76
- package/dist/shared/gzaveazc.js +285 -0
- package/dist/shared/{8rsy3hxz.js → h15jx9bc.js} +1 -1
- package/dist/shared/{dyj86cmj.js → hyh73qk6.js} +3 -3
- package/dist/shared/je4axnm8.js +22 -0
- package/dist/shared/{ycatkxmq.js → jgqj11w4.js} +1 -1
- package/dist/shared/{6qd27mx0.js → jvd0mqag.js} +5 -5
- package/dist/shared/jznfax0y.js +155 -0
- package/dist/shared/{cgbamx3e.js → kb2sdhfb.js} +7 -4
- package/dist/shared/{ps7a6h14.js → kr0jzbw2.js} +12 -8
- package/dist/shared/{janx09m5.js → ktz42yez.js} +20 -8
- package/dist/shared/{gde73es6.js → m6p12kbr.js} +56 -55
- package/dist/shared/{r6nwkxnt.js → m7n9h2a5.js} +4 -4
- package/dist/shared/{672t5vym.js → mss6ctgv.js} +2 -2
- package/dist/shared/{nxdp2ze3.js → mtaszv5a.js} +144 -12
- package/dist/shared/n816peh1.js +45 -0
- package/dist/shared/nbw1z4yd.js +18 -0
- package/dist/shared/{cctw17hj.js → p6qc5gcp.js} +38 -34
- package/dist/shared/{6rk2gen5.js → pbp1ss85.js} +20 -17
- package/dist/shared/pt94kz7f.js +6 -0
- package/dist/shared/{wq9n6pwr.js → pz6rj8ay.js} +82 -9
- package/dist/shared/q5c6ngn3.js +13 -0
- package/dist/shared/{8bwbwy8h.js → qq3899ht.js} +128 -18
- package/dist/shared/{8ktwd3rh.js → r3j8s5y0.js} +1 -1
- package/dist/shared/rhs3xe4k.js +7 -0
- package/dist/shared/{ntneex2a.js → rpycarcr.js} +6 -6
- package/dist/shared/{sdc7r2ww.js → rs73fca9.js} +8 -8
- package/dist/shared/{tm5ab8we.js → sfz1ksn6.js} +7 -4
- package/dist/shared/{6mnp99hx.js → svncdeh5.js} +16 -12
- package/dist/shared/{hf22e0wt.js → tbrvgw6z.js} +62 -42
- package/dist/shared/te5as7z7.js +622 -0
- package/dist/shared/{ga3sfy93.js → tsvww22q.js} +535 -200
- package/dist/shared/{47x8x9ze.js → ttsqgp4p.js} +20 -13
- package/dist/shared/{x72jb7ad.js → v8g1vgv8.js} +1 -1
- package/dist/shared/vb6qfyve.js +152 -0
- package/dist/shared/{r2sp8hrc.js → vczs8gd4.js} +22 -13
- package/dist/shared/{1g0drakv.js → vqrjpcqn.js} +145 -3
- package/dist/shared/{2pqx26h8.js → w72kgg4q.js} +31 -22
- package/dist/shared/{96qcj21c.js → w79hsckn.js} +16 -51
- package/dist/shared/wa07eas9.js +730 -0
- package/dist/shared/{k8v5v5wj.js → x933k9a3.js} +75 -34
- package/dist/shared/{cr74e96e.js → xhfsfkgk.js} +62 -28
- package/dist/shared/xjk7hnn5.js +272 -0
- package/dist/shared/{5enne4ma.js → xnxsed62.js} +66 -113
- package/dist/shared/xqve9598.js +53 -0
- package/dist/shared/{9x25fxhc.js → y34a8714.js} +1 -1
- package/dist/shared/{k7dwkhvq.js → y6jdds7g.js} +4 -1
- package/dist/shared/y6njgyda.js +249 -0
- package/dist/shared/{c9z5g0fm.js → ywr8hmey.js} +5 -2
- package/dist/shared/{g7ez901n.js → ywspezzx.js} +1 -1
- package/dist/shared/z7s6fpxv.js +62 -0
- package/dist/shared/{n7mcc1gk.js → zchaghkf.js} +4 -3
- package/dist/shared/{9m80mkac.js → ze4hxsmy.js} +1 -1
- package/dist/shared/zm0ptry0.js +40 -0
- package/dist/shared/{nsva2a6b.js → znm0bpp5.js} +3 -0
- package/dist/shared/zp9fmend.js +145 -0
- package/dist/shared/{y005b761.js → zy8r7qvz.js} +6 -2
- package/dist/tooling/cli.js +41 -15
- 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/config.d.ts +3 -2
- package/dist/tooling/migrate/engine.d.ts +3 -2
- package/dist/tooling/migrate/files.d.ts +11 -1
- package/dist/tooling/migrate/index.js +14 -14
- package/dist/tooling/migrate/lint.d.ts +1 -1
- 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 +6 -3
- 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 +20 -3
- package/dist/tooling/migrate/text.d.ts +42 -0
- package/dist/tooling/node-version.d.ts +21 -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 +11 -5
- package/package.json +8 -3
- package/dist/shared/7m88x3e9.js +0 -45
- package/dist/shared/7zwwyh0v.js +0 -448
- package/dist/shared/aj2qxyhj.js +0 -90
- package/dist/shared/caw8b9d8.js +0 -204
- package/dist/shared/jwtxdj06.js +0 -76
- package/dist/shared/kfjp0gck.js +0 -212
- package/dist/shared/q58y17hy.js +0 -21
- package/dist/shared/qm7cdtvr.js +0 -912
- package/dist/shared/r8x5qhd7.js +0 -86
- package/dist/shared/zqrnhwsq.js +0 -31
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
import {
|
|
2
|
+
runWrite
|
|
3
|
+
} from "./n4jqhpqz.js";
|
|
4
|
+
import {
|
|
5
|
+
withRowFilters,
|
|
6
|
+
emitWhere,
|
|
7
|
+
indexes,
|
|
8
|
+
quote,
|
|
9
|
+
isRecord,
|
|
10
|
+
fail2
|
|
11
|
+
} from "./67txcrcw.js";
|
|
12
|
+
import {
|
|
13
|
+
OkmError2
|
|
14
|
+
} from "./52szzakm.js";
|
|
15
|
+
|
|
16
|
+
// src/runtime/sort.ts
|
|
17
|
+
function insertAtEnd(table, columns, rows, group, tenantFields) {
|
|
18
|
+
const position = requiredColumn(table, "position");
|
|
19
|
+
const groupColumn = group === undefined ? undefined : requiredColumn(table, group);
|
|
20
|
+
const tenants = tenantColumns(table, tenantFields);
|
|
21
|
+
const planned = [];
|
|
22
|
+
const countOf = new Map;
|
|
23
|
+
const firstOf = new Map;
|
|
24
|
+
for (const row of rows) {
|
|
25
|
+
if (groupColumn !== undefined && !Object.hasOwn(row, groupColumn.field)) {
|
|
26
|
+
fail2("OKM1121", `insert on ${table.model.name} needs ${groupColumn.field} so position has a group.`, "Pass the group on the row. Position is assigned for you.");
|
|
27
|
+
}
|
|
28
|
+
const key = lockText(table.model.sql, wires(tenants, row), groupColumn === undefined ? null : cellWire(groupColumn, row[groupColumn.field]));
|
|
29
|
+
if (!firstOf.has(key))
|
|
30
|
+
firstOf.set(key, row);
|
|
31
|
+
const n = (countOf.get(key) ?? 0) + 1;
|
|
32
|
+
countOf.set(key, n);
|
|
33
|
+
planned.push({ key, n, row });
|
|
34
|
+
}
|
|
35
|
+
const params = [];
|
|
36
|
+
const bind = (wire, dataType) => {
|
|
37
|
+
params.push(wire);
|
|
38
|
+
return `$${String(params.length)}::${dataType}`;
|
|
39
|
+
};
|
|
40
|
+
const slotOf = new Map;
|
|
41
|
+
for (const key of firstOf.keys())
|
|
42
|
+
slotOf.set(key, bind(key, "text"));
|
|
43
|
+
const baseRows = [];
|
|
44
|
+
for (const [key, row] of firstOf) {
|
|
45
|
+
const parts = [slotOf.get(key) ?? bind(key, "text")];
|
|
46
|
+
if (groupColumn !== undefined)
|
|
47
|
+
parts.push(bind(cellWire(groupColumn, row[groupColumn.field]), groupColumn.dataType));
|
|
48
|
+
for (const column of tenants)
|
|
49
|
+
parts.push(bind(cellWire(column, row[column.field]), column.dataType));
|
|
50
|
+
baseRows.push(`(${parts.join(", ")})`);
|
|
51
|
+
}
|
|
52
|
+
const baseNames = ["okm_lock"];
|
|
53
|
+
if (groupColumn !== undefined)
|
|
54
|
+
baseNames.push("okm_g");
|
|
55
|
+
for (let index = 0;index < tenants.length; index += 1)
|
|
56
|
+
baseNames.push(`okm_t${String(index)}`);
|
|
57
|
+
const lists = planned.map((item) => {
|
|
58
|
+
const slot = slotOf.get(item.key) ?? bind(item.key, "text");
|
|
59
|
+
const slots = columns.map((column) => cell(column, item.row[column.field], bind));
|
|
60
|
+
slots.push(`((select b.pos from base b where b.okm_lock = ${slot}) + ${String(item.n)})::integer`);
|
|
61
|
+
return `(${slots.join(", ")})`;
|
|
62
|
+
});
|
|
63
|
+
const insertColumns = [...columns.map((column) => quote(column.sql)), quote(position.sql)];
|
|
64
|
+
const text = [
|
|
65
|
+
"with base as (",
|
|
66
|
+
"select i.okm_lock, coalesce(max(t.",
|
|
67
|
+
quote(position.sql),
|
|
68
|
+
"), 0) as pos from (values ",
|
|
69
|
+
baseRows.join(", "),
|
|
70
|
+
") as i(",
|
|
71
|
+
baseNames.join(", "),
|
|
72
|
+
") left join ",
|
|
73
|
+
quote(table.model.sql),
|
|
74
|
+
" as t on ",
|
|
75
|
+
joinOn(groupColumn, tenants),
|
|
76
|
+
" group by i.okm_lock",
|
|
77
|
+
") insert into ",
|
|
78
|
+
quote(table.model.sql),
|
|
79
|
+
" (",
|
|
80
|
+
insertColumns.join(", "),
|
|
81
|
+
") values ",
|
|
82
|
+
lists.join(", ")
|
|
83
|
+
].join("");
|
|
84
|
+
return { lock: groupLock([...firstOf.keys()]), text, params };
|
|
85
|
+
}
|
|
86
|
+
async function move(host, tableName, id, place, view) {
|
|
87
|
+
await host.connected;
|
|
88
|
+
const table = indexes(host.schema).get(tableName);
|
|
89
|
+
if (table === undefined)
|
|
90
|
+
fail2("OKM1120", `Table ${tableName} is not in the schema.`);
|
|
91
|
+
const group = groupField(table);
|
|
92
|
+
if (!sortable(table)) {
|
|
93
|
+
fail2("OKM1120", `move on ${tableName} needs sortable().`, "Add sortable() from okmodel/traits.");
|
|
94
|
+
}
|
|
95
|
+
const anchor = readPlace(place, tableName);
|
|
96
|
+
const key = moveColumn(host.schema, table);
|
|
97
|
+
if (sameId(id, anchor.id)) {
|
|
98
|
+
const current = await readOne(host, table, key, id, group, view);
|
|
99
|
+
if (current === undefined)
|
|
100
|
+
missing(tableName, id);
|
|
101
|
+
return { position: current.position };
|
|
102
|
+
}
|
|
103
|
+
const moved = await readOne(host, table, key, id, group, view);
|
|
104
|
+
if (moved === undefined)
|
|
105
|
+
missing(tableName, id);
|
|
106
|
+
const other = await readOne(host, table, key, anchor.id, group, view);
|
|
107
|
+
if (other === undefined)
|
|
108
|
+
missing(tableName, anchor.id);
|
|
109
|
+
if (moved.groupWire !== other.groupWire) {
|
|
110
|
+
const which = group ?? "group";
|
|
111
|
+
throw new OkmError2("OKM1120", `move on ${tableName} cannot place ${show(id)} ${anchor.side} ${show(anchor.id)}. ${show(anchor.id)} is in another ${which}.`, { fix: { summary: `Choose an anchor in the same ${which}.` } });
|
|
112
|
+
}
|
|
113
|
+
const statements = withRowFilters(host.scope, view, () => moveStatements(host.schema, table, key, id, anchor.id, moved, anchor.side, group));
|
|
114
|
+
const results = await runWrite(host, statements, callOptions(host));
|
|
115
|
+
const row = results[1]?.rows[0];
|
|
116
|
+
if (count(row?.[0]) !== 1)
|
|
117
|
+
missing(tableName, id);
|
|
118
|
+
if (count(row?.[1]) !== 1)
|
|
119
|
+
missing(tableName, anchor.id);
|
|
120
|
+
return { position: count(row?.[2]) };
|
|
121
|
+
}
|
|
122
|
+
function sortable(table) {
|
|
123
|
+
const traits = table.model.traits;
|
|
124
|
+
if (traits === undefined)
|
|
125
|
+
return false;
|
|
126
|
+
for (const trait of traits)
|
|
127
|
+
if (trait.name === "sortable")
|
|
128
|
+
return true;
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
function groupField(table) {
|
|
132
|
+
const traits = table.model.traits;
|
|
133
|
+
if (traits === undefined)
|
|
134
|
+
return;
|
|
135
|
+
for (const trait of traits) {
|
|
136
|
+
if (trait.name !== "sortable")
|
|
137
|
+
continue;
|
|
138
|
+
const group = trait.group;
|
|
139
|
+
return typeof group === "string" ? group : undefined;
|
|
140
|
+
}
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
function readPlace(place, table) {
|
|
144
|
+
if (!isRecord(place))
|
|
145
|
+
fail2("OKM1120", `move on ${table} needs { before } or { after }.`);
|
|
146
|
+
const before = Object.hasOwn(place, "before");
|
|
147
|
+
const after = Object.hasOwn(place, "after");
|
|
148
|
+
if (before === after) {
|
|
149
|
+
fail2("OKM1120", `move on ${table} needs before or after, not both.`, "Pass one anchor.");
|
|
150
|
+
}
|
|
151
|
+
for (const key of Object.keys(place)) {
|
|
152
|
+
if (key === "before" || key === "after")
|
|
153
|
+
continue;
|
|
154
|
+
fail2("OKM1120", `move on ${table} does not accept ${key}. Accepted options: before, after.`);
|
|
155
|
+
}
|
|
156
|
+
return { side: before ? "before" : "after", id: before ? place.before : place.after };
|
|
157
|
+
}
|
|
158
|
+
function moveColumn(schema, table) {
|
|
159
|
+
const tenants = new Set(tenantFieldNames(schema.tenancy, table));
|
|
160
|
+
const fields = table.model.primary.filter((field) => !tenants.has(field));
|
|
161
|
+
if (fields.length !== 1) {
|
|
162
|
+
fail2("OKM1120", `move on ${table.model.name} needs one primary key column besides the tenant key.`);
|
|
163
|
+
}
|
|
164
|
+
return requiredColumn(table, fields[0] ?? "");
|
|
165
|
+
}
|
|
166
|
+
function tenantFieldNames(tenancy, table) {
|
|
167
|
+
if (tenancy === undefined)
|
|
168
|
+
return [];
|
|
169
|
+
const keys = tenancy.keys ?? [tenancy.key];
|
|
170
|
+
return keys.filter((key) => table.columns.has(key));
|
|
171
|
+
}
|
|
172
|
+
async function readOne(host, table, key, id, group, view) {
|
|
173
|
+
const position = requiredColumn(table, "position");
|
|
174
|
+
const groupColumn = group === undefined ? undefined : requiredColumn(table, group);
|
|
175
|
+
const tenants = tenantColumns(table, tenantFieldNames(host.schema.tenancy, table));
|
|
176
|
+
const statement = withRowFilters(host.scope, view, () => {
|
|
177
|
+
const parts = [];
|
|
178
|
+
const params = [];
|
|
179
|
+
parts.push("select ");
|
|
180
|
+
parts.push(quote(position.sql));
|
|
181
|
+
if (groupColumn !== undefined) {
|
|
182
|
+
parts.push(", ");
|
|
183
|
+
parts.push(quote(groupColumn.sql));
|
|
184
|
+
}
|
|
185
|
+
for (const column of tenants) {
|
|
186
|
+
parts.push(", ");
|
|
187
|
+
parts.push(quote(column.sql));
|
|
188
|
+
}
|
|
189
|
+
parts.push(" from ");
|
|
190
|
+
parts.push(quote(table.model.sql));
|
|
191
|
+
parts.push(" as t where t.");
|
|
192
|
+
parts.push(quote(key.sql));
|
|
193
|
+
parts.push(" = $1::");
|
|
194
|
+
parts.push(key.dataType);
|
|
195
|
+
params.push(key.encode(id));
|
|
196
|
+
emitWhere(host.schema, table, undefined, sink(parts, params), "t", 0, true);
|
|
197
|
+
return { text: parts.join(""), params };
|
|
198
|
+
});
|
|
199
|
+
const result = await host.pool.execute(statement.text, statement.params, callOptions(host));
|
|
200
|
+
const found = result.rows[0];
|
|
201
|
+
if (found === undefined)
|
|
202
|
+
return;
|
|
203
|
+
let at = 1;
|
|
204
|
+
const groupWire = groupColumn === undefined ? null : decodeWire(groupColumn, found[at]);
|
|
205
|
+
if (groupColumn !== undefined)
|
|
206
|
+
at += 1;
|
|
207
|
+
const tenantWires = [];
|
|
208
|
+
for (const column of tenants) {
|
|
209
|
+
tenantWires.push(decodeWire(column, found[at]));
|
|
210
|
+
at += 1;
|
|
211
|
+
}
|
|
212
|
+
return { position: count(found[0]), groupWire, tenants: tenantWires };
|
|
213
|
+
}
|
|
214
|
+
function moveStatements(schema, table, key, id, anchor, moved, side, group) {
|
|
215
|
+
const lock = groupLock([lockText(table.model.sql, moved.tenants, moved.groupWire)]);
|
|
216
|
+
const place = moveStatement(schema, table, key, id, anchor, moved, side, group);
|
|
217
|
+
const tenants = tenantColumns(table, tenantFieldNames(schema.tenancy, table));
|
|
218
|
+
return [lock, place, flipStatement(table, moved, group, tenants)];
|
|
219
|
+
}
|
|
220
|
+
function moveStatement(schema, table, key, id, anchor, moved, side, group) {
|
|
221
|
+
const position = requiredColumn(table, "position");
|
|
222
|
+
const groupColumn = group === undefined ? undefined : requiredColumn(table, group);
|
|
223
|
+
const tenants = tenantColumns(table, tenantFieldNames(schema.tenancy, table));
|
|
224
|
+
const params = [];
|
|
225
|
+
const bind = (wire, dataType) => {
|
|
226
|
+
params.push(wire);
|
|
227
|
+
return `$${String(params.length)}::${dataType}`;
|
|
228
|
+
};
|
|
229
|
+
const groupSlot = groupColumn === undefined ? "" : bind(moved.groupWire, groupColumn.dataType);
|
|
230
|
+
const tenantSlots = tenants.map((column, index) => bind(moved.tenants[index] ?? null, column.dataType));
|
|
231
|
+
const movedSlot = bind(key.encode(id), key.dataType);
|
|
232
|
+
const anchorSlot = bind(key.encode(anchor), key.dataType);
|
|
233
|
+
const delta = bind(side === "before" ? "-0.5" : "0.5", "numeric");
|
|
234
|
+
const parts = [];
|
|
235
|
+
parts.push("with members as (select t.ctid as tid, t.tableoid as toid, t.");
|
|
236
|
+
parts.push(quote(position.sql));
|
|
237
|
+
parts.push(" as pos, t.");
|
|
238
|
+
parts.push(quote(key.sql));
|
|
239
|
+
parts.push(" as ident from ");
|
|
240
|
+
parts.push(quote(table.model.sql));
|
|
241
|
+
parts.push(" as t");
|
|
242
|
+
let filtered = false;
|
|
243
|
+
if (groupColumn !== undefined) {
|
|
244
|
+
parts.push(" where t.");
|
|
245
|
+
parts.push(quote(groupColumn.sql));
|
|
246
|
+
parts.push(" is not distinct from ");
|
|
247
|
+
parts.push(groupSlot);
|
|
248
|
+
filtered = true;
|
|
249
|
+
}
|
|
250
|
+
for (let index = 0;index < tenants.length; index += 1) {
|
|
251
|
+
const column = tenants[index];
|
|
252
|
+
if (column === undefined)
|
|
253
|
+
continue;
|
|
254
|
+
parts.push(filtered ? " and t." : " where t.");
|
|
255
|
+
parts.push(quote(column.sql));
|
|
256
|
+
parts.push(" is not distinct from ");
|
|
257
|
+
parts.push(tenantSlots[index] ?? "null");
|
|
258
|
+
filtered = true;
|
|
259
|
+
}
|
|
260
|
+
emitWhere(schema, table, undefined, sink(parts, params), "t", 0, filtered);
|
|
261
|
+
parts.push(" for update of t), numbered as (select ident, pos, tid, toid, row_number() over (order by pos, ident) as ord from members), placed as (select ident, pos, tid, toid, row_number() over (order by case when ident = ");
|
|
262
|
+
parts.push(movedSlot);
|
|
263
|
+
parts.push(" then (select ord from numbered where ident = ");
|
|
264
|
+
parts.push(anchorSlot);
|
|
265
|
+
parts.push(") + ");
|
|
266
|
+
parts.push(delta);
|
|
267
|
+
parts.push(" else ord end, case when ident = ");
|
|
268
|
+
parts.push(movedSlot);
|
|
269
|
+
parts.push(" then 0 else 1 end) as new_pos from numbered where (select count(*) from numbered where ident = ");
|
|
270
|
+
parts.push(movedSlot);
|
|
271
|
+
parts.push(") = 1 and (select count(*) from numbered where ident = ");
|
|
272
|
+
parts.push(anchorSlot);
|
|
273
|
+
parts.push(") = 1), changed as (update ");
|
|
274
|
+
parts.push(quote(table.model.sql));
|
|
275
|
+
parts.push(" as t set ");
|
|
276
|
+
parts.push(quote(position.sql));
|
|
277
|
+
parts.push(" = (-p.new_pos)::integer from placed as p where t.ctid = p.tid and t.tableoid = p.toid returning t.ctid) select (select count(*)::int from numbered where ident = ");
|
|
278
|
+
parts.push(movedSlot);
|
|
279
|
+
parts.push("), (select count(*)::int from numbered where ident = ");
|
|
280
|
+
parts.push(anchorSlot);
|
|
281
|
+
parts.push("), coalesce((select new_pos::int from placed where ident = ");
|
|
282
|
+
parts.push(movedSlot);
|
|
283
|
+
parts.push("), 0), (select count(*)::int from changed)");
|
|
284
|
+
return { text: parts.join(""), ...params.length > 0 ? { params } : {} };
|
|
285
|
+
}
|
|
286
|
+
function flipStatement(table, moved, group, tenants) {
|
|
287
|
+
const position = requiredColumn(table, "position");
|
|
288
|
+
const groupColumn = group === undefined ? undefined : requiredColumn(table, group);
|
|
289
|
+
const params = [];
|
|
290
|
+
const bind = (wire, dataType) => {
|
|
291
|
+
params.push(wire);
|
|
292
|
+
return `$${String(params.length)}::${dataType}`;
|
|
293
|
+
};
|
|
294
|
+
const parts = [
|
|
295
|
+
"update ",
|
|
296
|
+
quote(table.model.sql),
|
|
297
|
+
" as t set ",
|
|
298
|
+
quote(position.sql),
|
|
299
|
+
" = (-t.",
|
|
300
|
+
quote(position.sql),
|
|
301
|
+
")::integer where t.",
|
|
302
|
+
quote(position.sql),
|
|
303
|
+
" < 0"
|
|
304
|
+
];
|
|
305
|
+
if (groupColumn !== undefined) {
|
|
306
|
+
parts.push(" and t.");
|
|
307
|
+
parts.push(quote(groupColumn.sql));
|
|
308
|
+
parts.push(" is not distinct from ");
|
|
309
|
+
parts.push(bind(moved.groupWire, groupColumn.dataType));
|
|
310
|
+
}
|
|
311
|
+
for (let index = 0;index < tenants.length; index += 1) {
|
|
312
|
+
const column = tenants[index];
|
|
313
|
+
if (column === undefined)
|
|
314
|
+
continue;
|
|
315
|
+
parts.push(" and t.");
|
|
316
|
+
parts.push(quote(column.sql));
|
|
317
|
+
parts.push(" is not distinct from ");
|
|
318
|
+
parts.push(bind(moved.tenants[index] ?? null, column.dataType));
|
|
319
|
+
}
|
|
320
|
+
return { text: parts.join(""), ...params.length > 0 ? { params } : {} };
|
|
321
|
+
}
|
|
322
|
+
function joinOn(group, tenants) {
|
|
323
|
+
const parts = [];
|
|
324
|
+
if (group !== undefined)
|
|
325
|
+
parts.push(`t.${quote(group.sql)} is not distinct from i.okm_g`);
|
|
326
|
+
for (let index = 0;index < tenants.length; index += 1) {
|
|
327
|
+
const column = tenants[index];
|
|
328
|
+
if (column === undefined)
|
|
329
|
+
continue;
|
|
330
|
+
parts.push(`t.${quote(column.sql)} is not distinct from i.okm_t${String(index)}`);
|
|
331
|
+
}
|
|
332
|
+
return parts.length === 0 ? "true" : parts.join(" and ");
|
|
333
|
+
}
|
|
334
|
+
function lockText(sqlName, tenants, group) {
|
|
335
|
+
return JSON.stringify([sqlName, tenants, group]);
|
|
336
|
+
}
|
|
337
|
+
function groupLock(keys) {
|
|
338
|
+
const ordered = [...keys].sort(compareText);
|
|
339
|
+
const values = ordered.map((_, index) => `($${String(index + 1)}::text)`).join(", ");
|
|
340
|
+
return {
|
|
341
|
+
text: `select pg_advisory_xact_lock(hashtextextended(k.okm_lock, 0::bigint)) from (select v.okm_lock from (values ${values}) as v(okm_lock) order by v.okm_lock) as k`,
|
|
342
|
+
params: ordered
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
function compareText(left, right) {
|
|
346
|
+
if (left < right)
|
|
347
|
+
return -1;
|
|
348
|
+
if (left > right)
|
|
349
|
+
return 1;
|
|
350
|
+
return 0;
|
|
351
|
+
}
|
|
352
|
+
function wires(columns, row) {
|
|
353
|
+
return columns.map((column) => cellWire(column, row[column.field]));
|
|
354
|
+
}
|
|
355
|
+
function cellWire(column, value) {
|
|
356
|
+
if (value === undefined || value === null)
|
|
357
|
+
return null;
|
|
358
|
+
return column.encode(value);
|
|
359
|
+
}
|
|
360
|
+
function cell(column, value, bind) {
|
|
361
|
+
if (value === undefined)
|
|
362
|
+
return "default";
|
|
363
|
+
if (value === null)
|
|
364
|
+
return bind(null, column.dataType);
|
|
365
|
+
return bind(column.encode(value), column.dataType);
|
|
366
|
+
}
|
|
367
|
+
function decodeWire(column, value) {
|
|
368
|
+
if (value === null || value === undefined)
|
|
369
|
+
return null;
|
|
370
|
+
if (typeof value === "string") {
|
|
371
|
+
const decode = column.decode;
|
|
372
|
+
return column.encode(decode === undefined ? value : decode(value));
|
|
373
|
+
}
|
|
374
|
+
return column.encode(value);
|
|
375
|
+
}
|
|
376
|
+
function tenantColumns(table, fields) {
|
|
377
|
+
if (fields === undefined)
|
|
378
|
+
return [];
|
|
379
|
+
const columns = [];
|
|
380
|
+
for (const field of fields) {
|
|
381
|
+
const column = table.columns.get(field);
|
|
382
|
+
if (column !== undefined)
|
|
383
|
+
columns.push(column);
|
|
384
|
+
}
|
|
385
|
+
return columns;
|
|
386
|
+
}
|
|
387
|
+
function requiredColumn(table, field) {
|
|
388
|
+
const column = table.columns.get(field);
|
|
389
|
+
if (column === undefined)
|
|
390
|
+
fail2("OKM1120", `Table ${table.model.name} has no column ${field}.`);
|
|
391
|
+
return column;
|
|
392
|
+
}
|
|
393
|
+
function missing(table, id) {
|
|
394
|
+
throw new OkmError2("not_found", `move on ${table} could not find ${show(id)}.`, {
|
|
395
|
+
kind: "not_found",
|
|
396
|
+
table,
|
|
397
|
+
fix: { summary: "Pass the id of a row in this table." }
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
function show(id) {
|
|
401
|
+
if (typeof id === "string" || typeof id === "number")
|
|
402
|
+
return String(id);
|
|
403
|
+
return "that id";
|
|
404
|
+
}
|
|
405
|
+
function sameId(left, right) {
|
|
406
|
+
return left === right;
|
|
407
|
+
}
|
|
408
|
+
function count(value) {
|
|
409
|
+
if (typeof value === "number")
|
|
410
|
+
return value;
|
|
411
|
+
if (typeof value === "bigint")
|
|
412
|
+
return Number(value);
|
|
413
|
+
if (typeof value === "string" && value.length > 0)
|
|
414
|
+
return Number(value);
|
|
415
|
+
return 0;
|
|
416
|
+
}
|
|
417
|
+
function sink(parts, params) {
|
|
418
|
+
return {
|
|
419
|
+
text(value) {
|
|
420
|
+
parts.push(value);
|
|
421
|
+
},
|
|
422
|
+
param(encoded) {
|
|
423
|
+
params.push(encoded);
|
|
424
|
+
parts.push(`$${String(params.length)}`);
|
|
425
|
+
},
|
|
426
|
+
mark() {}
|
|
427
|
+
};
|
|
428
|
+
}
|
|
429
|
+
function callOptions(host) {
|
|
430
|
+
const limit = host.timeouts?.statement;
|
|
431
|
+
return limit === undefined ? undefined : { timeout: limit };
|
|
432
|
+
}
|
|
433
|
+
export {
|
|
434
|
+
insertAtEnd,
|
|
435
|
+
move
|
|
436
|
+
};
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DriverError2
|
|
3
|
+
} from "./cm3w0ywp.js";
|
|
4
|
+
import {
|
|
5
|
+
send2,
|
|
6
|
+
reserve,
|
|
7
|
+
park
|
|
8
|
+
} from "./x933k9a3.js";
|
|
9
|
+
import {
|
|
10
|
+
resetSession2,
|
|
11
|
+
refuseWhenLost2
|
|
12
|
+
} from "./zm0ptry0.js";
|
|
13
|
+
import {
|
|
14
|
+
cursorStream
|
|
15
|
+
} from "./7kms6fvj.js";
|
|
16
|
+
import {
|
|
17
|
+
isConnectionFailure
|
|
18
|
+
} from "./cnkky55j.js";
|
|
19
|
+
import {
|
|
20
|
+
noTimeout
|
|
21
|
+
} from "./79dt02vc.js";
|
|
22
|
+
import {
|
|
23
|
+
WireSession
|
|
24
|
+
} from "./1qa0qajz.js";
|
|
25
|
+
import {
|
|
26
|
+
rejectClosed,
|
|
27
|
+
runCall
|
|
28
|
+
} from "./kb2sdhfb.js";
|
|
29
|
+
|
|
30
|
+
// src/adapters/pg/bunsql-extra.ts
|
|
31
|
+
async function recover(sql, error, text, depth, clientRead, closedDuring, again) {
|
|
32
|
+
if (!lostQuery(error))
|
|
33
|
+
throw error;
|
|
34
|
+
await flushClosed(sql);
|
|
35
|
+
const alreadyDead = closedDuring || socketClosed(error);
|
|
36
|
+
if (!clientRead && !alreadyDead || depth !== 0 || !readStatement(text))
|
|
37
|
+
throw error;
|
|
38
|
+
try {
|
|
39
|
+
return await again();
|
|
40
|
+
} catch (next) {
|
|
41
|
+
if (lostQuery(next))
|
|
42
|
+
await flushClosed(sql);
|
|
43
|
+
throw next;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function drainClosed(sql) {
|
|
47
|
+
return flushClosed(sql).then(() => {
|
|
48
|
+
return;
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
function readStatement(text) {
|
|
52
|
+
const head = text.trimStart().toLowerCase().replace(/\s+/g, " ");
|
|
53
|
+
if (head.length === 0 || head.includes("pg_advisory"))
|
|
54
|
+
return false;
|
|
55
|
+
if (/\sfor (?:no key update|key share|update|share)\b/.test(head))
|
|
56
|
+
return false;
|
|
57
|
+
return !/^(?:insert|update|delete|refresh|with|create|alter|drop|truncate|grant|revoke|comment|vacuum|analyze|reindex|copy|begin|start|commit|rollback|savepoint|release|set|reset)\b/.test(head);
|
|
58
|
+
}
|
|
59
|
+
function lostQuery(error) {
|
|
60
|
+
return isConnectionFailure(error) || socketClosed(error);
|
|
61
|
+
}
|
|
62
|
+
function socketClosed(error) {
|
|
63
|
+
if (!(error instanceof Error))
|
|
64
|
+
return false;
|
|
65
|
+
if (error.message === "Connection closed")
|
|
66
|
+
return true;
|
|
67
|
+
return error.cause instanceof Error && error.cause.message === "Connection closed";
|
|
68
|
+
}
|
|
69
|
+
async function listen(sql, parked, closed, channel, onNotify) {
|
|
70
|
+
if (closed)
|
|
71
|
+
return rejectClosed();
|
|
72
|
+
const pending = parked.splice(0);
|
|
73
|
+
for (const reserved of pending) {
|
|
74
|
+
const done = reserved.release();
|
|
75
|
+
if (done instanceof Promise)
|
|
76
|
+
await done;
|
|
77
|
+
}
|
|
78
|
+
const subscription = await sql.listen(channel, onNotify);
|
|
79
|
+
return async () => {
|
|
80
|
+
await subscription.unlisten();
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
async function checkout(held) {
|
|
84
|
+
const { counters, isClosed } = held;
|
|
85
|
+
if (isClosed())
|
|
86
|
+
return rejectClosed();
|
|
87
|
+
const reserved = await takeOpen(held) ?? await reserve(held.sql, held.acquireMs, counters);
|
|
88
|
+
counters.reserved += 1;
|
|
89
|
+
const session = new WireSession((text, params) => send2(reserved, text, params), held.notices, isClosed, false, () => {
|
|
90
|
+
counters.reservedBusy += 1;
|
|
91
|
+
}, () => {
|
|
92
|
+
counters.reservedBusy = Math.max(0, counters.reservedBusy - 1);
|
|
93
|
+
});
|
|
94
|
+
let lost = { on: false };
|
|
95
|
+
const opened = held.closures();
|
|
96
|
+
const reconnected = () => {
|
|
97
|
+
if (held.closures() === opened)
|
|
98
|
+
return;
|
|
99
|
+
lost.on = true;
|
|
100
|
+
return Promise.reject(new DriverError2("Connection closed", { sqlstate: "08006" }));
|
|
101
|
+
};
|
|
102
|
+
const guard = (run) => refuseWhenLost2(lost, () => run().catch((error) => {
|
|
103
|
+
if (error instanceof Error && bunClosed(error.message)) {
|
|
104
|
+
throw new DriverError2(error.message, { cause: error, sqlstate: "08006" });
|
|
105
|
+
}
|
|
106
|
+
throw error;
|
|
107
|
+
}));
|
|
108
|
+
let released = false;
|
|
109
|
+
return {
|
|
110
|
+
execute: (text, params, options) => {
|
|
111
|
+
const refused = noTimeout(options);
|
|
112
|
+
if (refused !== undefined)
|
|
113
|
+
return refused;
|
|
114
|
+
const gone = reconnected();
|
|
115
|
+
if (gone !== undefined)
|
|
116
|
+
return gone;
|
|
117
|
+
return guard(() => runCall(isClosed(), options, (watch) => session.query(text, params, watch)));
|
|
118
|
+
},
|
|
119
|
+
batch: (statements, options) => {
|
|
120
|
+
const refused = noTimeout(options);
|
|
121
|
+
if (refused !== undefined)
|
|
122
|
+
return refused;
|
|
123
|
+
const gone = reconnected();
|
|
124
|
+
if (gone !== undefined)
|
|
125
|
+
return gone;
|
|
126
|
+
return guard(() => runCall(isClosed(), options, async (watch) => {
|
|
127
|
+
const { runAtomicBatch } = await import("./b76b8d95.js");
|
|
128
|
+
return runAtomicBatch(session, statements, watch);
|
|
129
|
+
}));
|
|
130
|
+
},
|
|
131
|
+
evict() {
|
|
132
|
+
lost.on = true;
|
|
133
|
+
},
|
|
134
|
+
async release() {
|
|
135
|
+
if (released)
|
|
136
|
+
return;
|
|
137
|
+
released = true;
|
|
138
|
+
if (!lost.on && reportsClosed(reserved))
|
|
139
|
+
lost.on = true;
|
|
140
|
+
try {
|
|
141
|
+
if (!lost.on)
|
|
142
|
+
await reset(session, reserved);
|
|
143
|
+
} catch (error) {
|
|
144
|
+
if (lostQuery(error) || reportsClosed(reserved))
|
|
145
|
+
lost.on = true;
|
|
146
|
+
else
|
|
147
|
+
throw error;
|
|
148
|
+
} finally {
|
|
149
|
+
counters.reserved = Math.max(0, counters.reserved - 1);
|
|
150
|
+
if (lost.on) {
|
|
151
|
+
try {
|
|
152
|
+
reserved.release();
|
|
153
|
+
} catch {}
|
|
154
|
+
await flushClosed(held.sql);
|
|
155
|
+
} else
|
|
156
|
+
await park(held.parked, reserved);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
function reportsClosed(reserved) {
|
|
162
|
+
return Reflect.get(reserved, "closed") === true;
|
|
163
|
+
}
|
|
164
|
+
async function takeOpen(held) {
|
|
165
|
+
while (held.parked.length > 0) {
|
|
166
|
+
const next = held.parked.pop();
|
|
167
|
+
if (next === undefined)
|
|
168
|
+
return;
|
|
169
|
+
if (!reportsClosed(next))
|
|
170
|
+
return next;
|
|
171
|
+
try {
|
|
172
|
+
next.release();
|
|
173
|
+
} catch {}
|
|
174
|
+
await flushClosed(held.sql);
|
|
175
|
+
}
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
async function flushClosed(sql) {
|
|
179
|
+
for (let attempt = 0;attempt < 3; attempt += 1) {
|
|
180
|
+
try {
|
|
181
|
+
await sql.unsafe("select 1");
|
|
182
|
+
return true;
|
|
183
|
+
} catch {}
|
|
184
|
+
}
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
function bunClosed(message) {
|
|
188
|
+
return message === "Connection closed" || message === "connection must be a PostgresSQLConnection";
|
|
189
|
+
}
|
|
190
|
+
async function reset(session, sql) {
|
|
191
|
+
const run = (text) => sql.unsafe(text);
|
|
192
|
+
await resetSession2(session.depth(), run);
|
|
193
|
+
}
|
|
194
|
+
function streamRows(checkout, text, params) {
|
|
195
|
+
return async function* () {
|
|
196
|
+
const connection = await checkout();
|
|
197
|
+
try {
|
|
198
|
+
yield* cursorStream((statement, values) => connection.execute(statement, values), text, params);
|
|
199
|
+
} catch (error) {
|
|
200
|
+
connection.evict?.();
|
|
201
|
+
throw error;
|
|
202
|
+
} finally {
|
|
203
|
+
await connection.release();
|
|
204
|
+
}
|
|
205
|
+
}();
|
|
206
|
+
}
|
|
207
|
+
export {
|
|
208
|
+
checkout,
|
|
209
|
+
drainClosed,
|
|
210
|
+
listen,
|
|
211
|
+
recover,
|
|
212
|
+
streamRows
|
|
213
|
+
};
|