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.
Files changed (233) hide show
  1. package/README.md +100 -1116
  2. package/dist/adapters/capabilities.d.ts +3 -0
  3. package/dist/adapters/failure.d.ts +13 -2
  4. package/dist/adapters/lazy-errors.d.ts +22 -0
  5. package/dist/adapters/pg/bunsql-extra.d.ts +54 -3
  6. package/dist/adapters/pg/bunsql.d.ts +14 -1
  7. package/dist/adapters/pg/cursor.d.ts +17 -0
  8. package/dist/adapters/pg/no-inflight-timeout.d.ts +20 -0
  9. package/dist/adapters/pg/nodepostgres-extra.d.ts +22 -1
  10. package/dist/adapters/pg/nodepostgres.d.ts +12 -0
  11. package/dist/adapters/pg/pglite-wire.d.ts +24 -0
  12. package/dist/adapters/pg/pglite.d.ts +10 -0
  13. package/dist/adapters/pg/postgres-extra.d.ts +41 -3
  14. package/dist/adapters/pg/reserved.d.ts +42 -0
  15. package/dist/adapters/pg/session.d.ts +0 -18
  16. package/dist/contracts/catalog/document.d.ts +19 -5
  17. package/dist/contracts/catalog/object.d.ts +2 -1
  18. package/dist/contracts/catalog/policy.d.ts +48 -0
  19. package/dist/contracts/catalog/types.d.ts +25 -1
  20. package/dist/contracts/catalog/view.d.ts +2 -0
  21. package/dist/contracts/connection.d.ts +7 -6
  22. package/dist/contracts/internal.js +1 -1
  23. package/dist/contracts/location.d.ts +10 -0
  24. package/dist/dialects/pg/column.d.ts +13 -2
  25. package/dist/dialects/pg/ddl.d.ts +37 -1
  26. package/dist/dialects/pg/emit.d.ts +19 -1
  27. package/dist/dialects/pg/errors.d.ts +32 -1
  28. package/dist/dialects/pg/ext/citext.js +1 -1
  29. package/dist/dialects/pg/ext/index.js +1 -1
  30. package/dist/dialects/pg/ext/pg-trgm.js +1 -1
  31. package/dist/dialects/pg/filter-parse.d.ts +5 -4
  32. package/dist/dialects/pg/floor.d.ts +68 -0
  33. package/dist/dialects/pg/fn/index.js +2 -2
  34. package/dist/dialects/pg/index.d.ts +8 -2
  35. package/dist/dialects/pg/index.js +67 -171
  36. package/dist/dialects/pg/introspect.d.ts +7 -0
  37. package/dist/dialects/pg/keys.d.ts +11 -8
  38. package/dist/dialects/pg/model.d.ts +47 -2
  39. package/dist/dialects/pg/morph.d.ts +43 -0
  40. package/dist/dialects/pg/operator-fit.d.ts +2 -2
  41. package/dist/dialects/pg/operators.d.ts +14 -7
  42. package/dist/dialects/pg/ops/bucket.d.ts +65 -0
  43. package/dist/dialects/pg/ops/inc.d.ts +2 -2
  44. package/dist/dialects/pg/ops/matches.d.ts +9 -12
  45. package/dist/dialects/pg/ops/relevance.d.ts +13 -0
  46. package/dist/dialects/pg/ops/search-query.d.ts +22 -0
  47. package/dist/dialects/pg/ops/window.d.ts +103 -0
  48. package/dist/dialects/pg/owner.d.ts +42 -0
  49. package/dist/dialects/pg/path-endpoint.d.ts +20 -0
  50. package/dist/dialects/pg/preset.d.ts +1 -1
  51. package/dist/dialects/pg/relations.d.ts +100 -3
  52. package/dist/dialects/pg/role/check.d.ts +3 -0
  53. package/dist/dialects/pg/role/index.d.ts +71 -6
  54. package/dist/dialects/pg/role/sql.d.ts +11 -0
  55. package/dist/dialects/pg/schema.d.ts +33 -3
  56. package/dist/dialects/pg/table.d.ts +25 -3
  57. package/dist/dialects/pg/tenancy.d.ts +45 -3
  58. package/dist/dialects/pg/view/client.d.ts +19 -1
  59. package/dist/dialects/pg/view/index.d.ts +4 -0
  60. package/dist/dialects/pg/view/index.js +21 -178
  61. package/dist/dialects/pg/view/refresh.d.ts +24 -0
  62. package/dist/runtime/aggregate.d.ts +8 -2
  63. package/dist/runtime/batch.d.ts +1 -1
  64. package/dist/runtime/bucket-group.d.ts +70 -0
  65. package/dist/runtime/conflict.d.ts +24 -6
  66. package/dist/runtime/drift.d.ts +9 -0
  67. package/dist/runtime/include.d.ts +0 -8
  68. package/dist/runtime/inflight.d.ts +14 -0
  69. package/dist/runtime/page.d.ts +4 -1
  70. package/dist/runtime/pg/bun.js +12 -5
  71. package/dist/runtime/pg/pg.js +5 -5
  72. package/dist/runtime/pg/pglite.d.ts +1 -0
  73. package/dist/runtime/pg/pglite.js +9 -8
  74. package/dist/runtime/pg/postgresjs.js +5 -5
  75. package/dist/runtime/plan.d.ts +113 -15
  76. package/dist/runtime/predicate.d.ts +19 -0
  77. package/dist/runtime/read-stream.d.ts +13 -16
  78. package/dist/runtime/result-name.d.ts +17 -0
  79. package/dist/runtime/safety/index.js +1 -1
  80. package/dist/runtime/server-check.d.ts +3 -3
  81. package/dist/runtime/sort-bind.d.ts +21 -0
  82. package/dist/runtime/sort.d.ts +56 -0
  83. package/dist/runtime/sync.d.ts +70 -0
  84. package/dist/runtime/tenancy/composite.d.ts +26 -0
  85. package/dist/runtime/tenancy/context.d.ts +16 -0
  86. package/dist/runtime/tenancy/index.d.ts +9 -5
  87. package/dist/runtime/tenancy/index.js +1511 -38
  88. package/dist/runtime/tenancy/path.d.ts +87 -0
  89. package/dist/runtime/tenancy/rls.d.ts +67 -0
  90. package/dist/runtime/tenancy/via.d.ts +22 -0
  91. package/dist/runtime/text-search.d.ts +20 -0
  92. package/dist/runtime/traits/index.d.ts +80 -0
  93. package/dist/runtime/traits/index.js +187 -17
  94. package/dist/runtime/tree.d.ts +38 -0
  95. package/dist/runtime/types.d.ts +231 -23
  96. package/dist/runtime/validate/index.js +4 -4
  97. package/dist/runtime/version.d.ts +39 -0
  98. package/dist/runtime/window.d.ts +21 -0
  99. package/dist/runtime/write.d.ts +55 -3
  100. package/dist/shared/{krxx77g0.js → 14vx95q4.js} +12 -18
  101. package/dist/shared/1est4ezg.js +313 -0
  102. package/dist/shared/{4az561fn.js → 1qa0qajz.js} +8 -23
  103. package/dist/shared/1w508jbr.js +1611 -0
  104. package/dist/shared/2c13q96h.js +18 -0
  105. package/dist/shared/2d3xq4ps.js +9 -0
  106. package/dist/shared/2shdbn8q.js +23 -0
  107. package/dist/shared/{t4tbsy9h.js → 358zsv4r.js} +1 -1
  108. package/dist/shared/3v7t1yrv.js +208 -0
  109. package/dist/shared/5e3tf63j.js +220 -0
  110. package/dist/shared/5fe3kbsh.js +10 -0
  111. package/dist/shared/5v3xf80k.js +37 -0
  112. package/dist/shared/{51mvgj8w.js → 63qtkrca.js} +130 -3
  113. package/dist/shared/{gbtcc2d7.js → 67txcrcw.js} +62 -66
  114. package/dist/shared/79dt02vc.js +12 -0
  115. package/dist/shared/{v36c5g6p.js → 7k9grvf6.js} +407 -14
  116. package/dist/shared/7kms6fvj.js +20 -0
  117. package/dist/shared/7mnme5tn.js +8 -0
  118. package/dist/shared/7n7ddwt4.js +6 -0
  119. package/dist/shared/{87jvvhnt.js → 81ebdx9p.js} +48 -68
  120. package/dist/shared/{szm0cksa.js → 8skf0cam.js} +34 -6
  121. package/dist/shared/{gjthds9j.js → 9628a9xt.js} +1 -1
  122. package/dist/shared/9a4ae4p8.js +31 -0
  123. package/dist/shared/{8xsbagad.js → 9s0ypp87.js} +88 -7
  124. package/dist/shared/9y3mmmh1.js +436 -0
  125. package/dist/shared/ab9gmbwy.js +213 -0
  126. package/dist/shared/{sycnx8gt.js → ax7qv55k.js} +18 -8
  127. package/dist/shared/{f5cw5q5r.js → aytqh5y2.js} +6 -4
  128. package/dist/shared/{fancm5pt.js → b5pftnn2.js} +138 -15
  129. package/dist/shared/{efmy2gcg.js → b76b8d95.js} +2 -2
  130. package/dist/shared/bdk4sty6.js +58 -0
  131. package/dist/shared/{32zqc1dw.js → bg3rym3g.js} +63 -32
  132. package/dist/shared/{0t22wwh1.js → bm22fvzr.js} +16 -14
  133. package/dist/shared/bz84tkzm.js +342 -0
  134. package/dist/shared/{31vm914h.js → cm3w0ywp.js} +15 -16
  135. package/dist/shared/cn957f8d.js +179 -0
  136. package/dist/shared/{pf0d8f77.js → cnkky55j.js} +25 -14
  137. package/dist/shared/{5fqx9yh4.js → dk8v79p3.js} +3 -1
  138. package/dist/shared/{nkaxvt9q.js → dkxgzaqd.js} +224 -19
  139. package/dist/shared/dzj09cye.js +10 -0
  140. package/dist/shared/{4m9fn52z.js → ed0b8k4s.js} +1 -1
  141. package/dist/shared/{z2rnngj4.js → ek2wt2dz.js} +8 -5
  142. package/dist/shared/exn3sd90.js +359 -0
  143. package/dist/shared/g6evj1j3.js +66 -0
  144. package/dist/shared/ga9j92qj.js +25 -0
  145. package/dist/shared/{qv2ydck9.js → gs74dbj5.js} +651 -76
  146. package/dist/shared/gzaveazc.js +285 -0
  147. package/dist/shared/{8rsy3hxz.js → h15jx9bc.js} +1 -1
  148. package/dist/shared/{dyj86cmj.js → hyh73qk6.js} +3 -3
  149. package/dist/shared/je4axnm8.js +22 -0
  150. package/dist/shared/{ycatkxmq.js → jgqj11w4.js} +1 -1
  151. package/dist/shared/{6qd27mx0.js → jvd0mqag.js} +5 -5
  152. package/dist/shared/jznfax0y.js +155 -0
  153. package/dist/shared/{cgbamx3e.js → kb2sdhfb.js} +7 -4
  154. package/dist/shared/{ps7a6h14.js → kr0jzbw2.js} +12 -8
  155. package/dist/shared/{janx09m5.js → ktz42yez.js} +20 -8
  156. package/dist/shared/{gde73es6.js → m6p12kbr.js} +56 -55
  157. package/dist/shared/{r6nwkxnt.js → m7n9h2a5.js} +4 -4
  158. package/dist/shared/{672t5vym.js → mss6ctgv.js} +2 -2
  159. package/dist/shared/{nxdp2ze3.js → mtaszv5a.js} +144 -12
  160. package/dist/shared/n816peh1.js +45 -0
  161. package/dist/shared/nbw1z4yd.js +18 -0
  162. package/dist/shared/{cctw17hj.js → p6qc5gcp.js} +38 -34
  163. package/dist/shared/{6rk2gen5.js → pbp1ss85.js} +20 -17
  164. package/dist/shared/pt94kz7f.js +6 -0
  165. package/dist/shared/{wq9n6pwr.js → pz6rj8ay.js} +82 -9
  166. package/dist/shared/q5c6ngn3.js +13 -0
  167. package/dist/shared/{8bwbwy8h.js → qq3899ht.js} +128 -18
  168. package/dist/shared/{8ktwd3rh.js → r3j8s5y0.js} +1 -1
  169. package/dist/shared/rhs3xe4k.js +7 -0
  170. package/dist/shared/{ntneex2a.js → rpycarcr.js} +6 -6
  171. package/dist/shared/{sdc7r2ww.js → rs73fca9.js} +8 -8
  172. package/dist/shared/{tm5ab8we.js → sfz1ksn6.js} +7 -4
  173. package/dist/shared/{6mnp99hx.js → svncdeh5.js} +16 -12
  174. package/dist/shared/{hf22e0wt.js → tbrvgw6z.js} +62 -42
  175. package/dist/shared/te5as7z7.js +622 -0
  176. package/dist/shared/{ga3sfy93.js → tsvww22q.js} +535 -200
  177. package/dist/shared/{47x8x9ze.js → ttsqgp4p.js} +20 -13
  178. package/dist/shared/{x72jb7ad.js → v8g1vgv8.js} +1 -1
  179. package/dist/shared/vb6qfyve.js +152 -0
  180. package/dist/shared/{r2sp8hrc.js → vczs8gd4.js} +22 -13
  181. package/dist/shared/{1g0drakv.js → vqrjpcqn.js} +145 -3
  182. package/dist/shared/{2pqx26h8.js → w72kgg4q.js} +31 -22
  183. package/dist/shared/{96qcj21c.js → w79hsckn.js} +16 -51
  184. package/dist/shared/wa07eas9.js +730 -0
  185. package/dist/shared/{k8v5v5wj.js → x933k9a3.js} +75 -34
  186. package/dist/shared/{cr74e96e.js → xhfsfkgk.js} +62 -28
  187. package/dist/shared/xjk7hnn5.js +272 -0
  188. package/dist/shared/{5enne4ma.js → xnxsed62.js} +66 -113
  189. package/dist/shared/xqve9598.js +53 -0
  190. package/dist/shared/{9x25fxhc.js → y34a8714.js} +1 -1
  191. package/dist/shared/{k7dwkhvq.js → y6jdds7g.js} +4 -1
  192. package/dist/shared/y6njgyda.js +249 -0
  193. package/dist/shared/{c9z5g0fm.js → ywr8hmey.js} +5 -2
  194. package/dist/shared/{g7ez901n.js → ywspezzx.js} +1 -1
  195. package/dist/shared/z7s6fpxv.js +62 -0
  196. package/dist/shared/{n7mcc1gk.js → zchaghkf.js} +4 -3
  197. package/dist/shared/{9m80mkac.js → ze4hxsmy.js} +1 -1
  198. package/dist/shared/zm0ptry0.js +40 -0
  199. package/dist/shared/{nsva2a6b.js → znm0bpp5.js} +3 -0
  200. package/dist/shared/zp9fmend.js +145 -0
  201. package/dist/shared/{y005b761.js → zy8r7qvz.js} +6 -2
  202. package/dist/tooling/cli.js +41 -15
  203. package/dist/tooling/migrate/apply.d.ts +14 -0
  204. package/dist/tooling/migrate/check.d.ts +3 -4
  205. package/dist/tooling/migrate/classify.d.ts +4 -0
  206. package/dist/tooling/migrate/config.d.ts +3 -2
  207. package/dist/tooling/migrate/engine.d.ts +3 -2
  208. package/dist/tooling/migrate/files.d.ts +11 -1
  209. package/dist/tooling/migrate/index.js +14 -14
  210. package/dist/tooling/migrate/lint.d.ts +1 -1
  211. package/dist/tooling/migrate/lost.d.ts +28 -0
  212. package/dist/tooling/migrate/paths.d.ts +14 -0
  213. package/dist/tooling/migrate/plan.d.ts +6 -3
  214. package/dist/tooling/migrate/runner.d.ts +25 -0
  215. package/dist/tooling/migrate/sandbox.d.ts +57 -0
  216. package/dist/tooling/migrate/sql-lex.d.ts +20 -3
  217. package/dist/tooling/migrate/text.d.ts +42 -0
  218. package/dist/tooling/node-version.d.ts +21 -0
  219. package/dist/tooling/testing/facts.d.ts +33 -5
  220. package/dist/tooling/testing/index.d.ts +1 -1
  221. package/dist/tooling/testing/index.js +3 -3
  222. package/dist/tooling/testing/isolation.d.ts +11 -5
  223. package/package.json +8 -3
  224. package/dist/shared/7m88x3e9.js +0 -45
  225. package/dist/shared/7zwwyh0v.js +0 -448
  226. package/dist/shared/aj2qxyhj.js +0 -90
  227. package/dist/shared/caw8b9d8.js +0 -204
  228. package/dist/shared/jwtxdj06.js +0 -76
  229. package/dist/shared/kfjp0gck.js +0 -212
  230. package/dist/shared/q58y17hy.js +0 -21
  231. package/dist/shared/qm7cdtvr.js +0 -912
  232. package/dist/shared/r8x5qhd7.js +0 -86
  233. package/dist/shared/zqrnhwsq.js +0 -31
@@ -0,0 +1,313 @@
1
+ import {
2
+ queryHandle,
3
+ readHandle,
4
+ readCall,
5
+ attachHttp
6
+ } from "./tbrvgw6z.js";
7
+ import {
8
+ emitWhere,
9
+ emitOrder,
10
+ refuseHidden,
11
+ rejectKeys,
12
+ readLimit,
13
+ projectExpr,
14
+ cell,
15
+ indexes,
16
+ quote,
17
+ list,
18
+ isRecord,
19
+ fail2
20
+ } from "./67txcrcw.js";
21
+ import {
22
+ OkmError2,
23
+ throwNamed2
24
+ } from "./52szzakm.js";
25
+
26
+ // src/runtime/aggregate.ts
27
+ var BUCKET = Symbol.for("okmodel.bucket");
28
+ var bucketChunk;
29
+ function loadBucketGroup() {
30
+ return bucketChunk ??= import("./3v7t1yrv.js");
31
+ }
32
+ var OPTIONS = [
33
+ "where",
34
+ "groupBy",
35
+ "count",
36
+ "sum",
37
+ "avg",
38
+ "min",
39
+ "max",
40
+ "orderBy",
41
+ "limit",
42
+ "route",
43
+ "signal",
44
+ "timeout"
45
+ ];
46
+ var NUMERIC = /^(smallint|integer|bigint|real|double precision|numeric|decimal)\b/;
47
+ var AS_NUMBER = (wire) => Number(wire);
48
+ var AS_TEXT = (wire) => wire;
49
+ var UNORDERED = /^(json|jsonb|bytea|point|line|tsvector)\b|\[\]$/;
50
+ var FUNCTIONS = [
51
+ { option: "sum", tag: "s", numeric: true },
52
+ { option: "avg", tag: "a", numeric: true },
53
+ { option: "min", tag: "n", numeric: false },
54
+ { option: "max", tag: "x", numeric: false }
55
+ ];
56
+ function build(session, table, options, mods, view) {
57
+ try {
58
+ if (seesBucket(options))
59
+ return bucketHandle(session, table, options, mods, view);
60
+ return plan(session, table, options, mods, view);
61
+ } catch (error) {
62
+ throw error instanceof OkmError2 ? attachHttp(session.http, error) : error;
63
+ }
64
+ }
65
+ function bucketHandle(session, table, options, mods, view) {
66
+ const open = () => loadBucketGroup().then((mod) => {
67
+ try {
68
+ return { it: plan(session, table, options, mods, view, mod) };
69
+ } catch (error) {
70
+ throw error instanceof OkmError2 ? attachHttp(session.http, error) : error;
71
+ }
72
+ });
73
+ return queryHandle(() => open().then((box) => box.it), {
74
+ inspect: () => open().then((box) => box.it.inspect()),
75
+ sql: () => open().then((box) => box.it.sql()),
76
+ all: (reason) => build(session, table, options, { ...mods, all: reason }, view)
77
+ });
78
+ }
79
+ function seesBucket(options) {
80
+ if (!isRecord(options))
81
+ return false;
82
+ const groupBy = options.groupBy;
83
+ if (!Array.isArray(groupBy))
84
+ return false;
85
+ for (const item of groupBy) {
86
+ if (typeof item === "object" && item !== null && BUCKET in item)
87
+ return true;
88
+ }
89
+ return false;
90
+ }
91
+ function plan(session, table, options, mods, view, buckets) {
92
+ const record = isRecord(options) ? options : {};
93
+ rejectKeys(record, OPTIONS, "aggregate");
94
+ const indexed = indexes(session.schema).get(table);
95
+ if (indexed === undefined)
96
+ fail2("OKM1120", `Table ${table} is not in the schema.`);
97
+ const spec = parse(indexed, record, buckets);
98
+ if (spec.groups.length > 0 && record.limit === undefined && mods.all === undefined) {
99
+ fail2("OKM1101", "aggregate() with groupBy needs a limit, or .all(reason) for every group.");
100
+ }
101
+ const names = groupNames(spec.groups);
102
+ const orderBy = record.orderBy;
103
+ if (orderBy !== undefined) {
104
+ if (!isRecord(orderBy))
105
+ fail2("OKM1120", "orderBy must be an object of fields.");
106
+ for (const field of Object.keys(orderBy)) {
107
+ if (!names.includes(field)) {
108
+ const column = indexed.columns.get(field);
109
+ if (column !== undefined)
110
+ refuseHidden(column);
111
+ throwNamed2("OKM1120", field, names, `aggregate() orders by a groupBy field. Accepted names: ${list(names)}.`);
112
+ }
113
+ }
114
+ }
115
+ if (record.limit !== undefined)
116
+ readLimit(record.limit);
117
+ const base = readCall("find", table, {
118
+ where: record.where,
119
+ orderBy,
120
+ limit: record.limit,
121
+ signal: record.signal,
122
+ timeout: record.timeout,
123
+ route: record.route
124
+ }, mods.all, session.scope, session.schema.model[table], session.schema, view);
125
+ const call = { ...base, op: "aggregate", build: statement(spec, buckets) };
126
+ return readHandle(session, table, call, mods, (compiled, rows) => decode(compiled, rows));
127
+ }
128
+ function parse(table, record, buckets) {
129
+ const grouped = readGroups(table, record.groupBy, buckets);
130
+ const count = record.count === true;
131
+ if (record.count !== undefined && typeof record.count !== "boolean") {
132
+ fail2("OKM1120", "count is true when you want a row count.");
133
+ }
134
+ const calls = [];
135
+ for (const { option, tag, numeric } of FUNCTIONS) {
136
+ for (const column of columns(table, record[option], option)) {
137
+ const fits = numeric ? NUMERIC.test(column.dataType) : !UNORDERED.test(column.dataType);
138
+ if (!fits) {
139
+ fail2("OKM1124", `${option} does not apply to ${column.dataType} column ${column.field}. ${numeric ? "sum and avg take integer, real, and numeric columns." : "min and max need an ordered type."}`);
140
+ }
141
+ calls.push({ option, tag, column, decode: numeric ? sumDecode(column) : column.decode });
142
+ }
143
+ }
144
+ if (!count && calls.length === 0 && grouped.groups.length === 0) {
145
+ fail2("OKM1120", "aggregate() needs count, sum, avg, min, max, or groupBy.");
146
+ }
147
+ return { groups: grouped.groups, bucketed: grouped.bucketed, count, calls };
148
+ }
149
+ function sumDecode(column) {
150
+ const kind = typeof (column.decode?.("0") ?? "");
151
+ if (kind === "string")
152
+ return AS_TEXT;
153
+ if (kind === "number")
154
+ return AS_NUMBER;
155
+ return fail2("OKM1124", `sum and avg need a column whose value is a number or a string. ${column.field} reads as ${kind}.`);
156
+ }
157
+ function columns(table, value, option) {
158
+ if (value === undefined)
159
+ return [];
160
+ if (!Array.isArray(value))
161
+ fail2("OKM1120", `${option} must be a list of field names.`);
162
+ const out = [];
163
+ for (const name of value) {
164
+ const column = typeof name === "string" ? table.columns.get(name) : undefined;
165
+ if (typeof name !== "string" || column === undefined) {
166
+ throwNamed2("OKM1120", String(name), table.names, `Field ${String(name)} is not on ${table.model.name}. Accepted names: ${list(table.names)}.`);
167
+ }
168
+ if (column.hidden) {
169
+ fail2("OKM1120", `Field ${column.field} is hidden, so ${option} cannot read it.`);
170
+ }
171
+ out.push(column);
172
+ }
173
+ return out;
174
+ }
175
+ function groupNames(groups) {
176
+ const names = [];
177
+ for (const group of groups)
178
+ names.push(group.kind === "field" ? group.column.field : group.as);
179
+ return names;
180
+ }
181
+ function readGroups(table, value, buckets) {
182
+ if (value === undefined)
183
+ return { groups: [], bucketed: false };
184
+ if (!Array.isArray(value))
185
+ fail2("OKM1120", "groupBy must be a list of field names.");
186
+ const fields = new Set;
187
+ const aliases = new Set;
188
+ const groups = [];
189
+ let bucketed = false;
190
+ for (const item of value) {
191
+ if (typeof item === "object" && item !== null && BUCKET in item) {
192
+ if (buckets === undefined)
193
+ fail2("OKM1120", "bucket group");
194
+ groups.push(buckets.readBucket(table, item, fields, aliases));
195
+ bucketed = true;
196
+ continue;
197
+ }
198
+ const column = typeof item === "string" ? table.columns.get(item) : undefined;
199
+ if (typeof item !== "string" || column === undefined) {
200
+ throwNamed2("OKM1120", String(item), table.names, `Field ${String(item)} is not on ${table.model.name}. Accepted names: ${list(table.names)}.`);
201
+ }
202
+ if (column.hidden) {
203
+ fail2("OKM1120", `Field ${column.field} is hidden, so groupBy cannot read it.`);
204
+ }
205
+ if (aliases.has(column.field)) {
206
+ fail2("OKM1120", `group field ${column.field} clashes with a bucket as.`);
207
+ }
208
+ fields.add(column.field);
209
+ groups.push({ kind: "field", column });
210
+ }
211
+ return { groups, bucketed };
212
+ }
213
+ function statement(spec, buckets) {
214
+ return (schema, table, sink, outputs, call) => {
215
+ sink.mark(`aggregate|${table.model.name}|g:${groupMark(spec.groups)}|c:${String(spec.count)}|${spec.calls.map((item) => `${item.tag}:${item.column.field}`).join(",")}|`);
216
+ sink.text("select ");
217
+ const wrote = { at: 0 };
218
+ for (const group of spec.groups) {
219
+ if (group.kind === "field") {
220
+ put(sink, outputs, wrote, projectExpr(`t.${quote(group.column.sql)}`, group.column.dataType), {
221
+ key: `g:${group.column.field}`,
222
+ decode: group.column.decode
223
+ });
224
+ } else {
225
+ if (buckets === undefined)
226
+ fail2("OKM1120", "bucket group");
227
+ buckets.writeBucket(sink, outputs, wrote, group);
228
+ }
229
+ }
230
+ if (spec.count)
231
+ put(sink, outputs, wrote, "count(*)::text", { key: "c:", decode: undefined });
232
+ for (const item of spec.calls) {
233
+ const ref = `t.${quote(item.column.sql)}`;
234
+ const expr = item.option === "sum" || item.option === "avg" ? `${item.option}(${ref})::text` : projectExpr(`${item.option}(${ref})`, item.column.dataType);
235
+ put(sink, outputs, wrote, expr, {
236
+ key: `${item.tag}:${item.column.field}`,
237
+ decode: item.decode
238
+ });
239
+ }
240
+ sink.text(" from ");
241
+ sink.text(quote(table.model.sql));
242
+ sink.text(" t");
243
+ emitWhere(schema, table, call.where, sink, "t", 0);
244
+ if (spec.groups.length > 0) {
245
+ sink.text(" group by ");
246
+ if (spec.bucketed) {
247
+ if (buckets === undefined)
248
+ fail2("OKM1120", "bucket group");
249
+ buckets.writeGrouped(sink, groupNames(spec.groups), call.orderBy);
250
+ } else {
251
+ sink.text(spec.groups.map((group) => fieldRef(group)).join(", "));
252
+ if (isRecord(call.orderBy) && Object.keys(call.orderBy).length > 0) {
253
+ emitOrder(table, call.orderBy, sink, "t");
254
+ } else {
255
+ sink.text(" order by ");
256
+ sink.text(spec.groups.map((group) => `${fieldRef(group)} asc nulls last`).join(", "));
257
+ }
258
+ }
259
+ }
260
+ if (call.limit !== undefined) {
261
+ const limit = String(call.limit);
262
+ sink.text(" limit ");
263
+ sink.param(limit);
264
+ sink.mark(`l:${limit}`);
265
+ }
266
+ if (typeof call.all === "string")
267
+ sink.mark(`all:${call.all}`);
268
+ };
269
+ }
270
+ function groupMark(groups) {
271
+ const parts = [];
272
+ for (const group of groups) {
273
+ parts.push(group.kind === "field" ? group.column.field : `b:${group.column.field}:${group.as}:${group.unit}:${String(group.shift)}`);
274
+ }
275
+ return parts.join(",");
276
+ }
277
+ function fieldRef(group) {
278
+ if (group.kind !== "field")
279
+ return fail2("OKM1120", "bucket group");
280
+ return `t.${quote(group.column.sql)}`;
281
+ }
282
+ function put(sink, outputs, wrote, expr, out) {
283
+ if (wrote.at > 0)
284
+ sink.text(", ");
285
+ sink.text(expr);
286
+ outputs?.fields.push({ key: out.key, at: wrote.at, decode: out.decode });
287
+ wrote.at += 1;
288
+ }
289
+ function decode(compiled, rows) {
290
+ const items = [];
291
+ for (const row of rows) {
292
+ const item = {};
293
+ for (const field of compiled.outputs.fields) {
294
+ const value = row[field.at];
295
+ const tag = field.key.slice(0, 2);
296
+ const name = field.key.slice(2);
297
+ if (tag === "g:") {
298
+ item[name] = cell(value, field.decode);
299
+ } else if (tag === "c:") {
300
+ item.count = Number(value ?? 0);
301
+ } else {
302
+ const group = tag === "s:" ? "sum" : tag === "a:" ? "avg" : tag === "n:" ? "min" : "max";
303
+ const into = item[group] ??= {};
304
+ into[name] = cell(value, field.decode);
305
+ }
306
+ }
307
+ items.push(item);
308
+ }
309
+ return items;
310
+ }
311
+ export {
312
+ build
313
+ };
@@ -4,12 +4,9 @@ import {
4
4
  nextTransactionDepth,
5
5
  EMPTY_NOTICES,
6
6
  resultFrom
7
- } from "./cgbamx3e.js";
7
+ } from "./kb2sdhfb.js";
8
8
 
9
9
  // src/adapters/pg/session.ts
10
- function quoteIdent2(name) {
11
- return `"${name.replaceAll('"', '""')}"`;
12
- }
13
10
  function noticeBuffer() {
14
11
  let notices;
15
12
  return {
@@ -63,7 +60,7 @@ class WireSession {
63
60
  return resultFrom(result, this.notices.since(start));
64
61
  }, (error) => {
65
62
  this.onLeave();
66
- return driverErrors().then((errors) => Promise.reject(errors.mapDriverError(error)));
63
+ return driverErrors().then((errors) => Promise.reject(errors.mapDriverError(stampQuery(error, text))));
67
64
  });
68
65
  }
69
66
  return this.watched(pending, watch, start, text);
@@ -110,7 +107,7 @@ class WireSession {
110
107
  return resultFrom(result, this.notices.since(start));
111
108
  }, (error) => {
112
109
  this.finishWatched(pending, watch, onAbort);
113
- return classify(error, watch);
110
+ return classify(stampQuery(error, text), watch);
114
111
  });
115
112
  }
116
113
  finishWatched(pending, watch, onAbort) {
@@ -119,22 +116,10 @@ class WireSession {
119
116
  watch.signal.removeEventListener("abort", onAbort);
120
117
  }
121
118
  }
122
- async function* cursorStream(run, text, params) {
123
- const name = "okm_stream";
124
- await run("BEGIN");
125
- try {
126
- await run(`DECLARE ${name} NO SCROLL CURSOR FOR ${text}`, params);
127
- for (;; ) {
128
- const chunk = await run(`FETCH 64 FROM ${name}`);
129
- if (chunk.rows.length === 0)
130
- break;
131
- yield chunk.rows;
132
- }
133
- } finally {
134
- await run("ROLLBACK").catch(() => {
135
- return;
136
- });
137
- }
119
+ function stampQuery(error, text) {
120
+ if (typeof error === "object" && error !== null && !("query" in error))
121
+ Reflect.set(error, "query", text);
122
+ return error;
138
123
  }
139
124
  async function classify(error, watch) {
140
125
  const errors = await driverErrors();
@@ -151,4 +136,4 @@ async function classify(error, watch) {
151
136
  return Promise.reject(errors.mapDriverError(error));
152
137
  }
153
138
 
154
- export { quoteIdent2, noticeBuffer, WireSession, cursorStream };
139
+ export { noticeBuffer, WireSession };