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
@@ -4,24 +4,26 @@ import {
4
4
  viewDependencyEdges,
5
5
  PUBLIC,
6
6
  introspectSchema
7
- } from "./fancm5pt.js";
7
+ } from "./b5pftnn2.js";
8
8
  import {
9
9
  planMigration,
10
+ sessionFailure,
11
+ finishQuiet,
10
12
  assertDirectConnection,
11
13
  assertStableBackend
12
- } from "./ga3sfy93.js";
14
+ } from "./tsvww22q.js";
13
15
  import {
14
16
  quoteIdent,
15
17
  createObjectSql
16
- } from "./8xsbagad.js";
18
+ } from "./9s0ypp87.js";
17
19
  import {
18
20
  normaliseViewQuery,
19
21
  viewObject,
20
22
  materializedViewObject
21
- } from "./y005b761.js";
23
+ } from "./zy8r7qvz.js";
22
24
  import {
23
25
  catalog
24
- } from "./g7ez901n.js";
26
+ } from "./ywspezzx.js";
25
27
  import {
26
28
  OkmError2
27
29
  } from "./52szzakm.js";
@@ -88,7 +90,8 @@ async function sealViews(runner, source) {
88
90
  query,
89
91
  owner: object.owner,
90
92
  provenance: object.provenance,
91
- dependencies
93
+ dependencies,
94
+ ...object.definition.securityInvoker === true ? { securityInvoker: true } : {}
92
95
  });
93
96
  }
94
97
  return materializedViewObject({
@@ -256,8 +259,10 @@ ${plan.steps.map((step) => step.sql).join(`
256
259
  summary: "Change the schema or the database so okm check reports no difference."
257
260
  }
258
261
  });
262
+ } catch (error) {
263
+ throw sessionFailure(error) ?? error;
259
264
  } finally {
260
- await sql.end({ timeout: 5 });
265
+ await finishQuiet(() => sql.end({ timeout: 5 }));
261
266
  }
262
267
  }
263
268
  function catalogQuery2(sql) {
@@ -275,12 +280,17 @@ function catalogQuery2(sql) {
275
280
  }
276
281
  function managedRoleOptions2(roles) {
277
282
  const names = managedRoleNames(roles);
278
- return names === undefined ? undefined : { managedRoles: names };
283
+ return names === undefined ? undefined : {
284
+ managedRoles: names,
285
+ ...roles?.reporting !== undefined ? { reportingRole: roles.reporting } : {}
286
+ };
279
287
  }
280
288
  function managedRoleNames(roles) {
281
289
  if (roles === undefined)
282
290
  return;
283
291
  const names = new Set([roles.migration, roles.app]);
292
+ if (roles.reporting !== undefined)
293
+ names.add(roles.reporting);
284
294
  for (const role of roles.managed ?? [])
285
295
  names.add(role.name);
286
296
  return [...names];
@@ -1,14 +1,16 @@
1
1
  import {
2
- open3
3
- } from "./87jvvhnt.js";
2
+ open3,
3
+ seal2
4
+ } from "./81ebdx9p.js";
4
5
  import {
5
6
  PGLITE_CAPABILITIES,
6
7
  readCapability2,
7
8
  hasCapability2
8
- } from "./cgbamx3e.js";
9
+ } from "./kb2sdhfb.js";
9
10
  export {
10
11
  PGLITE_CAPABILITIES as capabilities,
11
12
  hasCapability2 as hasCapability,
12
13
  open3 as open,
13
- readCapability2 as readCapability
14
+ readCapability2 as readCapability,
15
+ seal2 as seal
14
16
  };
@@ -2,28 +2,34 @@ import {
2
2
  roleObject,
3
3
  grantObject,
4
4
  defaultPrivilegeObject
5
- } from "./8bwbwy8h.js";
5
+ } from "./qq3899ht.js";
6
+ import {
7
+ columnPrivilege
8
+ } from "./tsvww22q.js";
6
9
  import {
7
10
  quoteIdent
8
- } from "./8xsbagad.js";
11
+ } from "./9s0ypp87.js";
12
+ import {
13
+ policyObject
14
+ } from "./bdk4sty6.js";
9
15
  import {
10
16
  functionObject,
11
17
  triggerObject
12
- } from "./9x25fxhc.js";
18
+ } from "./y34a8714.js";
13
19
  import {
14
20
  normaliseViewQuery,
15
21
  viewObject,
16
22
  materializedViewObject,
17
23
  materializedViewIndex
18
- } from "./y005b761.js";
24
+ } from "./zy8r7qvz.js";
19
25
  import {
20
26
  extensionObject
21
- } from "./8ktwd3rh.js";
27
+ } from "./r3j8s5y0.js";
22
28
  import {
23
29
  catalog,
24
30
  enumType,
25
31
  domainType
26
- } from "./g7ez901n.js";
32
+ } from "./ywspezzx.js";
27
33
  import {
28
34
  staticNamespace2,
29
35
  identityKey2,
@@ -32,7 +38,7 @@ import {
32
38
  index3,
33
39
  constraint2,
34
40
  sequence2
35
- } from "./t4tbsy9h.js";
41
+ } from "./358zsv4r.js";
36
42
  import {
37
43
  referentialAction
38
44
  } from "./4e4c6vq2.js";
@@ -123,7 +129,8 @@ async function introspectSchema(runner, concrete, logical = "public", options) {
123
129
  triggers,
124
130
  functionDeps,
125
131
  views,
126
- viewDeps
132
+ viewDeps,
133
+ policies
127
134
  ] = await Promise.all([
128
135
  runner.query(TABLES, params),
129
136
  runner.query(COLUMNS, params),
@@ -137,7 +144,8 @@ async function introspectSchema(runner, concrete, logical = "public", options) {
137
144
  runner.query(TRIGGERS, params),
138
145
  runner.query(FUNCTION_DEPS, params),
139
146
  runner.query(VIEWS, params),
140
- runner.query(VIEW_DEPENDENCIES, params)
147
+ runner.query(VIEW_DEPENDENCIES, params),
148
+ runner.query(POLICIES, params)
141
149
  ]);
142
150
  const objects = [];
143
151
  const parents = new Map;
@@ -380,12 +388,38 @@ async function introspectSchema(runner, concrete, logical = "public", options) {
380
388
  const columns = printedColumns(text(row, "columns"));
381
389
  const query = normaliseViewQuery(text(row, "query"));
382
390
  const name = text(row, "name");
391
+ const invoker = kind === "view" && securityInvokerOption(text(row, "options"));
383
392
  if (kind === "materializedView") {
384
393
  objects.push(materializedViewObject({ namespace, name, columns, query, provenance }));
385
394
  } else {
386
- objects.push(viewObject({ namespace, name, columns, query, provenance }));
395
+ objects.push(viewObject({
396
+ namespace,
397
+ name,
398
+ columns,
399
+ query,
400
+ provenance,
401
+ ...invoker ? { securityInvoker: true } : {}
402
+ }));
387
403
  }
388
404
  }
405
+ for (const row of policies) {
406
+ const parentName = text(row, "table_name");
407
+ const parent = parents.get(parentName);
408
+ if (parent === undefined)
409
+ continue;
410
+ const command = policyCommand(text(row, "command"));
411
+ if (command === undefined || text(row, "enabled") !== "true")
412
+ continue;
413
+ objects.push(policyObject({
414
+ parent,
415
+ name: text(row, "name"),
416
+ command,
417
+ expression: text(row, "using_expr"),
418
+ force: text(row, "force") === "true",
419
+ provenance,
420
+ dependencies: [{ kind: "table", namespace, name: parentName }]
421
+ }));
422
+ }
389
423
  const viewEdges = viewDependencyEdges(viewDeps, namespace, objects);
390
424
  for (let index = 0;index < objects.length; index += 1) {
391
425
  const object = objects[index];
@@ -402,7 +436,8 @@ async function introspectSchema(runner, concrete, logical = "public", options) {
402
436
  columns: object.definition.columns,
403
437
  query: object.definition.query,
404
438
  provenance,
405
- dependencies
439
+ dependencies,
440
+ ...object.definition.securityInvoker === true ? { securityInvoker: true } : {}
406
441
  }) : materializedViewObject({
407
442
  namespace,
408
443
  name: object.identity.name,
@@ -413,7 +448,7 @@ async function introspectSchema(runner, concrete, logical = "public", options) {
413
448
  });
414
449
  }
415
450
  if (options?.managedRoles !== undefined) {
416
- objects.push(...await readPrivileges(runner, concrete, namespace, provenance, objects, options.managedRoles));
451
+ objects.push(...await readPrivileges(runner, concrete, logical, namespace, provenance, objects, options.managedRoles, options.reportingRole));
417
452
  }
418
453
  return catalog(objects);
419
454
  }
@@ -452,6 +487,30 @@ var FUNCTION_GRANTS = `select p.proname as name,
452
487
  select 1 from pg_depend d
453
488
  where d.classid = 'pg_proc'::regclass and d.objid = p.oid and d.deptype = 'e'
454
489
  )`;
490
+ var COLUMN_GRANTS = `select c.relname as name,
491
+ case c.relkind when 'v' then 'view' when 'm' then 'materializedView' else 'table' end as kind,
492
+ a.attname as column_name,
493
+ r.rolname as role, x.privilege_type as privilege
494
+ from pg_class c
495
+ join pg_namespace n on n.oid = c.relnamespace
496
+ join pg_attribute a on a.attrelid = c.oid and a.attnum > 0 and not a.attisdropped
497
+ cross join lateral aclexplode(a.attacl) as x
498
+ join pg_roles r on r.oid = x.grantee
499
+ where n.nspname = $1
500
+ and c.relkind in ('r', 'p', 'v', 'm')
501
+ and a.attacl is not null
502
+ and x.grantee <> 0
503
+ and x.grantee <> c.relowner`;
504
+ var SCHEMA_USAGE = `select 1 as ok
505
+ from pg_namespace n
506
+ cross join lateral aclexplode(n.nspacl) as a
507
+ where n.nspname = $1
508
+ and a.privilege_type = 'USAGE'
509
+ and (
510
+ a.grantee = 0
511
+ or a.grantee = (select oid from pg_roles where rolname = $2)
512
+ )
513
+ limit 1`;
455
514
  var DEFAULT_PRIVILEGES = `select owner_role.rolname as for_role, grantee.rolname as grantee,
456
515
  case d.defaclobjtype when 'S' then 'sequence' when 'f' then 'function' else 'table' end as object_kind,
457
516
  a.privilege_type as privilege
@@ -463,13 +522,15 @@ var DEFAULT_PRIVILEGES = `select owner_role.rolname as for_role, grantee.rolname
463
522
  where n.nspname = $1
464
523
  and d.defaclobjtype in ('r', 'S', 'f')
465
524
  and a.grantee <> 0`;
466
- async function readPrivileges(runner, concrete, namespace, provenance, built, managedRoles) {
525
+ async function readPrivileges(runner, concrete, logical, namespace, provenance, built, managedRoles, reportingRole) {
467
526
  const managed = new Set(managedRoles);
468
- const [roles, relations, functions, defaults] = await Promise.all([
527
+ const [roles, relations, functions, defaults, columns, usage] = await Promise.all([
469
528
  runner.query(ROLES, []),
470
529
  runner.query(RELATION_GRANTS, [concrete]),
471
530
  runner.query(FUNCTION_GRANTS, [concrete]),
472
- runner.query(DEFAULT_PRIVILEGES, [concrete])
531
+ runner.query(DEFAULT_PRIVILEGES, [concrete]),
532
+ runner.query(COLUMN_GRANTS, [concrete]),
533
+ reportingRole === undefined ? Promise.resolve([]) : runner.query(SCHEMA_USAGE, [concrete, reportingRole])
473
534
  ]);
474
535
  const objects = [];
475
536
  for (const row of roles) {
@@ -530,6 +591,42 @@ async function readPrivileges(runner, concrete, namespace, provenance, built, ma
530
591
  ]
531
592
  }));
532
593
  }
594
+ const grouped = new Map;
595
+ for (const row of columns) {
596
+ const privilege = text(row, "privilege").toUpperCase();
597
+ if (privilege !== "SELECT" && privilege !== "UPDATE")
598
+ continue;
599
+ const kind = grantKind(text(row, "kind"));
600
+ if (kind !== "table" && kind !== "view" && kind !== "materializedView")
601
+ continue;
602
+ const name = text(row, "name");
603
+ const role = text(row, "role");
604
+ const key = `${role}\x00${kind}\x00${name}\x00${privilege}`;
605
+ const current = grouped.get(key) ?? { role, kind, name, privilege, columns: [] };
606
+ current.columns.push(text(row, "column_name"));
607
+ grouped.set(key, current);
608
+ }
609
+ for (const group of grouped.values()) {
610
+ const target = built.find((object) => privilegeTarget(object) === `${group.kind}:${group.name}`);
611
+ if (target === undefined)
612
+ continue;
613
+ objects.push(grantObject({
614
+ role: group.role,
615
+ object: { kind: group.kind, namespace, name: group.name },
616
+ privilege: columnPrivilege(group.privilege, group.columns),
617
+ provenance,
618
+ dependencies: [{ kind: "role", name: group.role }, target.identity]
619
+ }));
620
+ }
621
+ if (usage.length > 0 && reportingRole !== undefined) {
622
+ objects.push(grantObject({
623
+ role: reportingRole,
624
+ object: { kind: "namespace", namespace, name: logical },
625
+ privilege: "USAGE",
626
+ provenance,
627
+ dependencies: [{ kind: "role", name: reportingRole }]
628
+ }));
629
+ }
533
630
  return objects;
534
631
  }
535
632
  function privilegeTarget(object) {
@@ -788,6 +885,7 @@ var TRIGGERS = `
788
885
  `;
789
886
  var VIEWS = `
790
887
  select c.relname as name, c.relkind as kind, pg_get_viewdef(c.oid, true) as query,
888
+ coalesce(array_to_string(c.reloptions, ','), '') as options,
791
889
  (
792
890
  select coalesce(string_agg(
793
891
  a.attname || '|' || format_type(a.atttypid, a.atttypmod),
@@ -821,6 +919,31 @@ var FUNCTION_DEPS = `
821
919
  and p.prokind = 'f'
822
920
  and p.prosrc = ''
823
921
  `;
922
+ var POLICIES = `
923
+ select c.relname as table_name,
924
+ p.polname as name,
925
+ p.polcmd as command,
926
+ coalesce(pg_get_expr(p.polqual, p.polrelid), '') as using_expr,
927
+ c.relforcerowsecurity::text as force,
928
+ c.relrowsecurity::text as enabled
929
+ from pg_policy p
930
+ join pg_class c on c.oid = p.polrelid
931
+ join pg_namespace n on n.oid = c.relnamespace
932
+ where n.nspname = $1
933
+ and c.relkind = 'r'
934
+ and ${CHILD}
935
+ and ${member("c.oid", "pg_class")}
936
+ `;
937
+ function securityInvokerOption(options) {
938
+ return options.split(",").some((item) => item === "security_invoker=true" || item === "security_invoker=on");
939
+ }
940
+ function policyCommand(command) {
941
+ if (command === "*")
942
+ return "all";
943
+ if (command === "r")
944
+ return "select";
945
+ return;
946
+ }
824
947
  function member(oid, classid) {
825
948
  return `not exists (
826
949
  select 1 from pg_depend member
@@ -2,10 +2,10 @@ import {
2
2
  DriverError2,
3
3
  outcomeUnknown2,
4
4
  mapDriverError2
5
- } from "./31vm914h.js";
5
+ } from "./cm3w0ywp.js";
6
6
  import {
7
7
  isConnectionLost
8
- } from "./pf0d8f77.js";
8
+ } from "./cnkky55j.js";
9
9
 
10
10
  // src/adapters/pg/batch.ts
11
11
  var savepointIds = 0;
@@ -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 };
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  touchFields,
3
3
  fieldSealed
4
- } from "./7m88x3e9.js";
4
+ } from "./1w508jbr.js";
5
5
  import {
6
6
  projectExpr,
7
7
  quote,
8
8
  list,
9
9
  isRecord,
10
10
  registerFailFix,
11
- fail
12
- } from "./gbtcc2d7.js";
11
+ fail2
12
+ } from "./67txcrcw.js";
13
13
  import {
14
14
  throwNamed2
15
15
  } from "./52szzakm.js";
@@ -24,13 +24,13 @@ function readConflict(table, value, allow = NO_ALLOW, tenantKey) {
24
24
  if (value === "ignore")
25
25
  return { kind: "ignore", columns: [], update: [] };
26
26
  if (!isRecord(value)) {
27
- fail("OKM1120", 'onConflict must be "error", "ignore", { on, update }, or { on, return: true }.');
27
+ fail2("OKM1120", 'onConflict must be "error", "ignore", { on, update }, or { on, return: true }.');
28
28
  }
29
29
  const keys = Object.keys(value);
30
30
  const update = value.update;
31
31
  const ret = value.return;
32
32
  if (update !== undefined && ret !== undefined) {
33
- fail("OKM1120", "onConflict takes update or return, not both.");
33
+ fail2("OKM1120", "onConflict takes update or return, not both.");
34
34
  }
35
35
  if (ret === true) {
36
36
  rejectConflictKeys(keys, ["on", "return"]);
@@ -44,9 +44,9 @@ function readConflict(table, value, allow = NO_ALLOW, tenantKey) {
44
44
  update: updateColumns(table, update, allow)
45
45
  };
46
46
  }
47
- fail("OKM1120", 'onConflict must be "error", "ignore", { on, update }, or { on, return: true }.');
47
+ fail2("OKM1120", 'onConflict must be "error", "ignore", { on, update }, or { on, return: true }.');
48
48
  }
49
- function finishInsert(head, returning, params, plan, table, returningColumns, keys) {
49
+ function finishInsert(head, returning, params, plan, table) {
50
50
  if (plan.kind === "ignore") {
51
51
  return { text: `${head} on conflict do nothing${returning}`, params: [...params] };
52
52
  }
@@ -66,10 +66,13 @@ function finishInsert(head, returning, params, plan, table, returningColumns, ke
66
66
  params: [...params]
67
67
  };
68
68
  }
69
- return firstOrCreate(head, returning, params, plan.columns, table, returningColumns, keys);
69
+ return {
70
+ text: `${head} on conflict (${target})${conflictWhere(table, plan.columns)} do nothing${returning}`,
71
+ params: [...params]
72
+ };
70
73
  }
71
- function firstOrCreate(head, returning, params, keys, table, returningColumns, keyRows) {
72
- const next = [...params];
74
+ function lookupExisting(table, keys, returningColumns, keyRows) {
75
+ const params = [];
73
76
  const tuples = [];
74
77
  for (const row of keyRows) {
75
78
  const slots = [];
@@ -77,18 +80,21 @@ function firstOrCreate(head, returning, params, keys, table, returningColumns, k
77
80
  const column = keys[index];
78
81
  if (column === undefined)
79
82
  continue;
80
- next.push(row[index] ?? null);
81
- slots.push(`$${String(next.length)}::${column.dataType}`);
83
+ params.push(row[index] ?? null);
84
+ slots.push(`$${String(params.length)}::${column.dataType}`);
82
85
  }
83
86
  tuples.push(keys.length === 1 ? slots[0] ?? "null" : `(${slots.join(", ")})`);
84
87
  }
85
- const keyList = keys.map((column) => quote(column.sql)).join(", ");
86
88
  const left = keys.length === 1 ? `t.${quote(keys[0]?.sql ?? "")}` : `(${keys.map((column) => `t.${quote(column.sql)}`).join(", ")})`;
87
- const names = returningColumns.map((column) => quote(column.field)).join(", ");
88
- const fromTable = returningColumns.map((column) => projectExpr(`t.${quote(column.sql)}`, column.dataType)).join(", ");
89
- const match = keys.map((column) => `ins.${quote(column.field)} = t.${quote(column.sql)}`).join(" and ");
90
- const text = `with ins(${names}) as (${head} on conflict (${keyList})${conflictWhere(table, keys)} do nothing${returning}) select ${names} from ins union all select ${fromTable} from ${quote(table.model.sql)} t where ${left} in (${tuples.join(", ")}) and not exists (select 1 from ins where ${match})`;
91
- return { text, params: next };
89
+ const projected = returningColumns.map((column) => projectExpr(`t.${quote(column.sql)}`, column.dataType)).join(", ");
90
+ const text = `select ${projected} from ${quote(table.model.sql)} t where ${left} in (${tuples.join(", ")})${activeAnd(table, keys)}`;
91
+ return { text, params };
92
+ }
93
+ function activeAnd(table, columns) {
94
+ const clause = conflictWhere(table, columns);
95
+ if (clause === "")
96
+ return "";
97
+ return ` and t.${clause.replace(/^ where /, "")}`;
92
98
  }
93
99
  function conflictWhere(table, columns) {
94
100
  const archive = table.model.archive;
@@ -112,27 +118,29 @@ function samePrimary(table, columns) {
112
118
  }
113
119
  function uniqueColumns(table, on, tenantKey) {
114
120
  const names = conflictNames(on);
121
+ const keys = keyList(tenantKey);
115
122
  for (const unique of table.model.uniques) {
116
- if (!same(unique, names))
123
+ const fields = fieldsOf(unique, names, keys);
124
+ if (fields === undefined)
117
125
  continue;
118
126
  const columns = [];
119
- for (const name of names) {
127
+ for (const name of fields) {
120
128
  const column = table.columns.get(name);
121
129
  if (column === undefined) {
122
- fail("OKM1104", `onConflict column ${name} is not on ${table.model.name}.`);
130
+ fail2("OKM1104", `onConflict column ${name} is not on ${table.model.name}.`);
123
131
  }
124
132
  columns.push(column);
125
133
  }
126
134
  return columns;
127
135
  }
128
- const accepted = acceptedConstraints(table.model, tenantKey);
129
- const implicit = tenantKey === undefined ? "" : ` The tenant key ${tenantKey} is part of each one and is not named here.`;
136
+ const accepted = acceptedConstraints(table.model, keys);
137
+ const implicit = keys.length === 0 ? "" : ` The tenant key ${keys.join(", ")} is part of each one and is not named here.`;
130
138
  throwNamed2("OKM1104", names.join(", "), accepted, `onConflict on ${table.model.name} names ${names.join(", ")}, which is not a unique constraint. Accepted: ${list(accepted)}.${implicit}`);
131
139
  }
132
- function acceptedConstraints(model, key) {
140
+ function acceptedConstraints(model, keys) {
133
141
  const shown = new Set;
134
142
  for (const fields of model.uniques) {
135
- const named = key === undefined ? fields : fields.filter((field) => field !== key);
143
+ const named = keys.length === 0 ? fields : fields.filter((field) => !keys.includes(field));
136
144
  if (named.length === 0)
137
145
  continue;
138
146
  shown.add(named.length > 1 ? `(${named.join(", ")})` : named.join(""));
@@ -141,12 +149,12 @@ function acceptedConstraints(model, key) {
141
149
  }
142
150
  function updateColumns(table, value, allow) {
143
151
  if (!Array.isArray(value) || value.length === 0) {
144
- fail("OKM1120", "onConflict update must name at least one column.");
152
+ fail2("OKM1120", "onConflict update must name at least one column.");
145
153
  }
146
154
  const columns = [];
147
155
  for (const name of value) {
148
156
  if (typeof name !== "string")
149
- fail("OKM1120", "onConflict update must name columns.");
157
+ fail2("OKM1120", "onConflict update must name columns.");
150
158
  const column = table.columns.get(name);
151
159
  if (column === undefined) {
152
160
  throwNamed2("OKM1120", name, table.names, `Field ${name} is not on ${table.model.name}. Accepted names: ${list(table.names)}.`);
@@ -164,7 +172,29 @@ function conflictNames(on) {
164
172
  if (Array.isArray(on) && on.length > 0 && on.every((name) => typeof name === "string")) {
165
173
  return on;
166
174
  }
167
- fail("OKM1104", "onConflict on must name a unique constraint's columns.");
175
+ fail2("OKM1104", "onConflict on must name a unique constraint's columns.");
176
+ }
177
+ function fieldsOf(unique, names, tenantKeys) {
178
+ if (tenantKeys.some((key) => unique.includes(key))) {
179
+ const rest = [];
180
+ for (const field of unique) {
181
+ if (!tenantKeys.includes(field))
182
+ rest.push(field);
183
+ }
184
+ if (!same(rest, names))
185
+ return;
186
+ return unique;
187
+ }
188
+ if (!same(unique, names))
189
+ return;
190
+ return names;
191
+ }
192
+ function keyList(tenantKey) {
193
+ if (tenantKey === undefined)
194
+ return [];
195
+ if (typeof tenantKey === "string")
196
+ return [tenantKey];
197
+ return tenantKey;
168
198
  }
169
199
  function same(unique, names) {
170
200
  if (unique.length !== names.length)
@@ -186,17 +216,18 @@ function rejectConflictKeys(keys, accepted) {
186
216
  }
187
217
  function refuseWrite(table, column) {
188
218
  if (fieldSealed(table.model, column.field)) {
189
- fail("OKM1190", `Field ${table.model.name}.${column.field} is set by a trait. Input cannot set it.`);
219
+ fail2("OKM1190", `Field ${table.model.name}.${column.field} is set by a trait. Input cannot set it.`);
190
220
  }
191
221
  if (column.guardUpdate) {
192
- fail("OKM1190", `Field ${table.model.name}.${column.field} is a primary key. Input cannot change it.`);
222
+ fail2("OKM1190", `Field ${table.model.name}.${column.field} is a primary key. Input cannot change it.`);
193
223
  }
194
224
  if (column.guarded) {
195
- fail("OKM1190", `Field ${table.model.name}.${column.field} is guarded. Input cannot set it.`);
225
+ fail2("OKM1190", `Field ${table.model.name}.${column.field} is guarded. Input cannot set it.`);
196
226
  }
197
- fail("OKM1120", `Field ${table.model.name}.${column.field} cannot be written.`);
227
+ fail2("OKM1120", `Field ${table.model.name}.${column.field} cannot be written.`);
198
228
  }
199
229
  export {
200
230
  finishInsert,
231
+ lookupExisting,
201
232
  readConflict
202
233
  };