okmodel 0.8.0 → 0.9.1

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 (237) hide show
  1. package/README.md +23 -1
  2. package/dist/adapters/pg/bunsql-extra.d.ts +5 -5
  3. package/dist/adapters/pg/bunsql.d.ts +6 -2
  4. package/dist/adapters/pg/nodepostgres.d.ts +16 -1
  5. package/dist/adapters/pg/postgres-extra.d.ts +3 -17
  6. package/dist/adapters/pg/postgresjs.d.ts +2 -1
  7. package/dist/contracts/driver.d.ts +3 -2
  8. package/dist/contracts/error.d.ts +1 -1
  9. package/dist/dialects/pg/errors.d.ts +2 -0
  10. package/dist/dialects/pg/ext/btree-gin.d.ts +26 -0
  11. package/dist/dialects/pg/ext/btree-gin.js +20 -0
  12. package/dist/dialects/pg/ext/btree-gist.d.ts +26 -0
  13. package/dist/dialects/pg/ext/btree-gist.js +20 -0
  14. package/dist/dialects/pg/ext/call.d.ts +53 -0
  15. package/dist/dialects/pg/ext/citext.js +1 -1
  16. package/dist/dialects/pg/ext/feature.d.ts +26 -0
  17. package/dist/dialects/pg/ext/fuzzystrmatch.d.ts +34 -0
  18. package/dist/dialects/pg/ext/fuzzystrmatch.js +33 -0
  19. package/dist/dialects/pg/ext/hstore.d.ts +41 -0
  20. package/dist/dialects/pg/ext/hstore.js +29 -0
  21. package/dist/dialects/pg/ext/index.d.ts +56 -0
  22. package/dist/dialects/pg/ext/index.js +1 -1
  23. package/dist/dialects/pg/ext/ltree.d.ts +41 -0
  24. package/dist/dialects/pg/ext/ltree.js +29 -0
  25. package/dist/dialects/pg/ext/pg-trgm.js +4 -13
  26. package/dist/dialects/pg/ext/pgcrypto.d.ts +33 -0
  27. package/dist/dialects/pg/ext/pgcrypto.js +33 -0
  28. package/dist/dialects/pg/ext/unaccent.d.ts +26 -0
  29. package/dist/dialects/pg/ext/unaccent.js +21 -0
  30. package/dist/dialects/pg/ext/using.d.ts +23 -0
  31. package/dist/dialects/pg/ext/versions.d.ts +36 -0
  32. package/dist/dialects/pg/external.d.ts +19 -0
  33. package/dist/dialects/pg/filters.d.ts +2 -2
  34. package/dist/dialects/pg/fn/index.js +5 -5
  35. package/dist/dialects/pg/index.d.ts +1 -0
  36. package/dist/dialects/pg/index.js +19 -14
  37. package/dist/dialects/pg/introspect.d.ts +12 -0
  38. package/dist/dialects/pg/view/index.js +7 -7
  39. package/dist/dialects/pg/view/scratch.d.ts +4 -1
  40. package/dist/runtime/artifact-file.d.ts +22 -0
  41. package/dist/runtime/client.d.ts +10 -0
  42. package/dist/runtime/drift-detail.d.ts +2 -1
  43. package/dist/runtime/drift.d.ts +3 -10
  44. package/dist/runtime/param-limit.d.ts +20 -0
  45. package/dist/runtime/pg/bun.js +4 -4
  46. package/dist/runtime/pg/neon.js +4 -4
  47. package/dist/runtime/pg/pg.js +4 -4
  48. package/dist/runtime/pg/pglite.js +4 -4
  49. package/dist/runtime/pg/postgresjs.js +11 -11
  50. package/dist/runtime/server-check.d.ts +36 -6
  51. package/dist/runtime/tenancy/index.js +1 -1
  52. package/dist/runtime/traits/index.js +6 -6
  53. package/dist/runtime/validate/index.js +2 -2
  54. package/dist/runtime/write.d.ts +1 -1
  55. package/dist/shared/{4m6hskg8.js → 0j6qe91y.js} +4 -4
  56. package/dist/shared/{6m78c8ss.js → 1h5h1rf5.js} +1 -1
  57. package/dist/shared/{4vbf83xx.js → 2vcnpf0n.js} +1 -1
  58. package/dist/shared/{qd9hhd8f.js → 3ap5hxvj.js} +2 -1
  59. package/dist/shared/{v1wad97q.js → 3d7a80fq.js} +1 -1
  60. package/dist/shared/{wcrheftc.js → 3dr444ny.js} +58 -79
  61. package/dist/shared/{hm5f8jby.js → 3vvpcphd.js} +8 -7
  62. package/dist/shared/{760ppr76.js → 4a3mmhhe.js} +2 -2
  63. package/dist/shared/{mkrn359n.js → 4pkz5nvw.js} +222 -39
  64. package/dist/shared/{agsfb86s.js → 4te76xc5.js} +4 -4
  65. package/dist/shared/{63f4ksbz.js → 60y4ahmw.js} +1 -1
  66. package/dist/shared/61bmrmhr.js +35 -0
  67. package/dist/shared/{bxas03mq.js → 63qjmhnp.js} +100 -17
  68. package/dist/shared/{g5yc06ka.js → 67w3kn71.js} +1 -1
  69. package/dist/shared/{jgqj11w4.js → 6f0z3hzh.js} +4 -0
  70. package/dist/shared/{njga14v4.js → 6vfvsdkt.js} +10 -8
  71. package/dist/shared/{kj9d8maq.js → 6xqvesa5.js} +1 -1
  72. package/dist/shared/8gdbty5v.js +665 -0
  73. package/dist/shared/{pan0370z.js → 8ma6drzr.js} +211 -30
  74. package/dist/shared/{mnvjvqyp.js → 8p2bgye0.js} +124 -32
  75. package/dist/shared/{mfedzr74.js → 8qwqrxed.js} +14 -6
  76. package/dist/shared/{hfqmpasr.js → 8v7vzpgt.js} +11 -8
  77. package/dist/shared/{7ghwamrf.js → 99qp9vtg.js} +1 -1
  78. package/dist/shared/{zgex00fd.js → ak61ye1f.js} +5 -5
  79. package/dist/shared/{dpc2r7rb.js → bdekbvmt.js} +218 -95
  80. package/dist/shared/{jebgrkeq.js → bxjq6xqv.js} +2 -2
  81. package/dist/shared/c7dqd3gk.js +1806 -0
  82. package/dist/shared/ddh72ym5.js +20 -0
  83. package/dist/shared/e1c55v04.js +10 -0
  84. package/dist/shared/{mtw6jz76.js → e275q7sd.js} +1 -1
  85. package/dist/shared/{k86n8vq3.js → ekhq3ytz.js} +1 -1
  86. package/dist/shared/esy4dyxe.js +17 -0
  87. package/dist/shared/{gcefca6p.js → f9t9g54z.js} +22 -9
  88. package/dist/shared/{sjk86yrx.js → fk9vef30.js} +84 -73
  89. package/dist/shared/fkjne6gx.js +8 -0
  90. package/dist/shared/{e8zyaqvj.js → fne90dvz.js} +4 -1
  91. package/dist/shared/{needfe47.js → g89fmz5s.js} +1 -1
  92. package/dist/shared/{m4xff2a6.js → ghqzdp94.js} +2 -2
  93. package/dist/shared/{n0jmpgj1.js → gr9sn4za.js} +1 -1
  94. package/dist/shared/{5mtf6cj3.js → gzgfsspx.js} +5 -2
  95. package/dist/shared/h9811jjm.js +17 -0
  96. package/dist/shared/{z581d7ny.js → hgt69zjf.js} +2 -2
  97. package/dist/shared/{35q0n9tz.js → jvxcp1qk.js} +71 -87
  98. package/dist/shared/k73e8n9d.js +136 -0
  99. package/dist/shared/{195pzzzz.js → kzgrcy8s.js} +12 -8
  100. package/dist/shared/kzgrnckd.js +29 -0
  101. package/dist/shared/{p3xbdcvt.js → mz48rs74.js} +68 -8
  102. package/dist/shared/{zbqbmmrp.js → n6je5b28.js} +13 -26
  103. package/dist/shared/{b6d6p0zc.js → ns35jqz0.js} +75 -49
  104. package/dist/shared/{n05z9nwz.js → nstwgzn8.js} +1 -1
  105. package/dist/{tooling/shared/08kemxjd.js → shared/pgsak1yw.js} +1 -1
  106. package/dist/shared/py2zrrm6.js +451 -0
  107. package/dist/shared/{9dr2qnx7.js → qqm3ze6q.js} +1 -1
  108. package/dist/shared/{wvdjznah.js → rcjm0yn7.js} +31 -38
  109. package/dist/shared/rged92v6.js +17 -0
  110. package/dist/shared/{jp36k7dp.js → rw4tpcd0.js} +81 -51
  111. package/dist/shared/{bsek72fg.js → s5qe47a6.js} +3 -0
  112. package/dist/shared/{1d9q9cv2.js → smxzjz60.js} +2 -2
  113. package/dist/shared/{wz2a78mp.js → th5rnaxw.js} +1 -1
  114. package/dist/{tooling/shared/rs1jb051.js → shared/tr64w5p0.js} +1 -1
  115. package/dist/shared/{14x60fbf.js → tyqapcgk.js} +73 -10
  116. package/dist/shared/vsna85qf.js +8 -0
  117. package/dist/shared/{63qtkrca.js → vy47ryqa.js} +55 -5
  118. package/dist/shared/{jx2m62cs.js → wbdh9qbg.js} +7 -5
  119. package/dist/shared/{f4jy1j7x.js → wp7y8q3y.js} +946 -105
  120. package/dist/shared/{16kvjebh.js → xbd9xs6p.js} +7 -26
  121. package/dist/shared/{bah9nbg3.js → xbvz446k.js} +18 -23
  122. package/dist/shared/{p5nh3r8q.js → y6tfjk9q.js} +2 -2
  123. package/dist/shared/{3bb7wsqt.js → ycnft340.js} +1 -1
  124. package/dist/shared/{z7s6fpxv.js → ymenf259.js} +1 -1
  125. package/dist/shared/{0wrea3jq.js → ysdw2fg3.js} +10 -2
  126. package/dist/shared/zecrwdk9.js +61 -0
  127. package/dist/shared/{3t6kw83m.js → zm2rzqba.js} +2 -1
  128. package/dist/tooling/cli.js +200 -50
  129. package/dist/tooling/driver-run.js +109 -343
  130. package/dist/tooling/github/comment.d.ts +56 -0
  131. package/dist/tooling/github/post-comment.d.ts +17 -0
  132. package/dist/tooling/migrate/apply.d.ts +17 -2
  133. package/dist/tooling/migrate/commands.d.ts +2 -1
  134. package/dist/tooling/migrate/config.d.ts +13 -0
  135. package/dist/tooling/migrate/drift.d.ts +12 -0
  136. package/dist/tooling/migrate/driver-url.d.ts +17 -0
  137. package/dist/tooling/migrate/export.d.ts +165 -0
  138. package/dist/tooling/migrate/ext-surface.d.ts +80 -0
  139. package/dist/tooling/migrate/ext.d.ts +31 -4
  140. package/dist/tooling/migrate/import-drizzle.d.ts +40 -0
  141. package/dist/tooling/migrate/index.d.ts +3 -0
  142. package/dist/tooling/migrate/index.js +57 -10
  143. package/dist/tooling/migrate/lint-rules.d.ts +18 -1
  144. package/dist/tooling/migrate/lint.d.ts +14 -1
  145. package/dist/tooling/migrate/place.d.ts +18 -0
  146. package/dist/tooling/migrate/plan-json.d.ts +65 -0
  147. package/dist/tooling/migrate/policy.d.ts +17 -5
  148. package/dist/tooling/migrate/pooler-probe.d.ts +23 -0
  149. package/dist/tooling/migrate/project.d.ts +10 -1
  150. package/dist/tooling/migrate/pull-emit.d.ts +98 -0
  151. package/dist/tooling/migrate/pull-routines.d.ts +126 -0
  152. package/dist/tooling/migrate/pull-verify.d.ts +26 -0
  153. package/dist/tooling/migrate/pull.d.ts +65 -0
  154. package/dist/tooling/migrate/reprint.d.ts +32 -0
  155. package/dist/tooling/migrate/runner.d.ts +24 -1
  156. package/dist/tooling/migrate/sandbox.d.ts +8 -2
  157. package/dist/tooling/migrate/schema-api.d.ts +43 -0
  158. package/dist/tooling/migrate/sql-lex.d.ts +18 -0
  159. package/dist/tooling/shared/{ppnnnvj8.js → 09a6vsys.js} +1 -1
  160. package/dist/tooling/shared/{7ae7rjmn.js → 0v9ptnxp.js} +8 -8
  161. package/dist/tooling/shared/{fb9k2qwd.js → 0wtzps9p.js} +11 -30
  162. package/dist/tooling/shared/{a6pp9d12.js → 0yhf1db4.js} +6 -6
  163. package/dist/tooling/shared/{dy672fz6.js → 19msgrsc.js} +2 -2
  164. package/dist/{shared/q0cqt2sp.js → tooling/shared/1fwfm5m3.js} +1 -1
  165. package/dist/tooling/shared/{f9mphxej.js → 2jdn09e2.js} +401 -24
  166. package/dist/tooling/shared/{jne7b93p.js → 2qrte2ct.js} +5 -5
  167. package/dist/tooling/shared/{5bvw2nev.js → 2v4nwnkb.js} +1 -1
  168. package/dist/tooling/shared/{spk1jg3r.js → 33z39trp.js} +106 -23
  169. package/dist/tooling/shared/{z8d7ptht.js → 353vnw9z.js} +5 -5
  170. package/dist/tooling/shared/{dw08f3m8.js → 390kry9g.js} +2 -2
  171. package/dist/tooling/shared/{xjs6zqtc.js → 3f6etb9z.js} +18 -31
  172. package/dist/{shared/bnby0esn.js → tooling/shared/3t2cqmsx.js} +1 -1
  173. package/dist/tooling/shared/{wwnekq5n.js → 4dzvjtpy.js} +1 -1
  174. package/dist/tooling/shared/{y5656f0e.js → 4ec0nxvw.js} +10 -10
  175. package/dist/tooling/shared/{3m1hkg7z.js → 4tg2bn41.js} +59 -78
  176. package/dist/tooling/shared/{zvnhh1n0.js → 5rah55z0.js} +2 -2
  177. package/dist/tooling/shared/{pqy21k24.js → 804w1t69.js} +4 -4
  178. package/dist/tooling/shared/8g0m0rvd.js +134 -0
  179. package/dist/tooling/shared/8msbtw5s.js +8 -0
  180. package/dist/tooling/shared/{4d2w25vw.js → 8t22h3h7.js} +2 -2
  181. package/dist/tooling/shared/{smn6kz1p.js → 91c59b7b.js} +2 -2
  182. package/dist/tooling/shared/{aftb2mwr.js → adk9k6va.js} +1 -1
  183. package/dist/tooling/shared/{j9t5s12a.js → ajjd5cwz.js} +2 -2
  184. package/dist/tooling/shared/{cmptmb4f.js → angjck01.js} +1 -1
  185. package/dist/tooling/shared/{yw30vnq2.js → asnnc3v5.js} +1 -1
  186. package/dist/tooling/shared/{ma2340rx.js → bj1kyqc8.js} +2 -2
  187. package/dist/tooling/shared/{2wtvc7rw.js → bt3tjemb.js} +11 -3
  188. package/dist/tooling/shared/{ec71zqgt.js → chk2bh4f.js} +2 -2
  189. package/dist/tooling/shared/{gmcf9cxf.js → ckq4z5ax.js} +5 -2
  190. package/dist/tooling/shared/{w7qe8sj1.js → d3rhb24q.js} +1 -1
  191. package/dist/tooling/shared/{y031jct9.js → d8q00vxg.js} +4 -4
  192. package/dist/tooling/shared/{vs0t6qt8.js → dx188rxs.js} +2 -2
  193. package/dist/tooling/shared/{g9ad4n80.js → efq6p9df.js} +35 -42
  194. package/dist/tooling/shared/{ddjtfgnx.js → en6rwzq0.js} +3 -3
  195. package/dist/tooling/shared/{6nyfyw70.js → f2r5g0fs.js} +2 -2
  196. package/dist/tooling/shared/{03k6res6.js → f4gep0nk.js} +1 -1
  197. package/dist/tooling/shared/{gfvtj6d0.js → f8a010fm.js} +13 -11
  198. package/dist/tooling/shared/{3tq8pnb8.js → fdsek6pa.js} +1 -1
  199. package/dist/tooling/shared/fvmrxsd1.js +8 -0
  200. package/dist/tooling/shared/{733a1tq3.js → g3xybeqf.js} +4 -3
  201. package/dist/tooling/shared/{pwsytxm5.js → gefmpwsa.js} +1 -1
  202. package/dist/tooling/shared/{mtrqn2hn.js → gjj71hfh.js} +25 -30
  203. package/dist/tooling/shared/{8sqrsw3s.js → jgzt69pa.js} +5 -5
  204. package/dist/tooling/shared/{nf7jmhfa.js → jm30k2ca.js} +10 -8
  205. package/dist/tooling/shared/{vx86qjv8.js → kayqzpbk.js} +6 -3
  206. package/dist/tooling/shared/{zhwnfyb2.js → kvw1672d.js} +1 -1
  207. package/dist/tooling/shared/{rq5kk8j6.js → mr1kcgpw.js} +3 -3
  208. package/dist/tooling/shared/{72fyg4zv.js → mwbdf409.js} +1 -1
  209. package/dist/tooling/shared/{wt7j7nf6.js → ns9207v3.js} +1 -1
  210. package/dist/tooling/shared/{9xzm7hjg.js → p6tjv97k.js} +3 -3
  211. package/dist/tooling/shared/{yfr8hzhm.js → p73evwf0.js} +1 -1
  212. package/dist/tooling/shared/{dzx85q70.js → phc1nc4g.js} +1 -1
  213. package/dist/tooling/shared/{417zdsk7.js → ppybjw50.js} +79 -16
  214. package/dist/tooling/shared/{yk9mp7vb.js → qdrn8ghn.js} +5 -4
  215. package/dist/tooling/shared/rd8h01ta.js +20 -0
  216. package/dist/tooling/shared/{bz2dqhab.js → rwg8y90m.js} +3 -3
  217. package/dist/tooling/shared/{xhrnjch9.js → ry2f3w8p.js} +3 -3
  218. package/dist/tooling/shared/{a7q7t4n3.js → ryc5sa58.js} +8 -8
  219. package/dist/tooling/shared/{2revefqt.js → ss87qxwv.js} +2 -2
  220. package/dist/tooling/shared/{rf83gr2d.js → vg68k11z.js} +7 -3
  221. package/dist/tooling/shared/{p7f08ktn.js → vms9dta5.js} +73 -89
  222. package/dist/tooling/shared/{3rrw5w8f.js → xchpnbdv.js} +1 -1
  223. package/dist/tooling/shared/{djydjpqt.js → xn6p01fh.js} +5 -5
  224. package/dist/tooling/shared/{9kazs5p6.js → xwr6q618.js} +3 -3
  225. package/dist/tooling/shared/{ep8zh3bk.js → xx3gmq94.js} +1 -1
  226. package/dist/tooling/shared/{tn8gay14.js → y2bd7yfx.js} +21 -13
  227. package/dist/tooling/shared/{vraj6d74.js → y4gq9rbe.js} +11 -11
  228. package/dist/tooling/shared/y4vwft92.js +9 -0
  229. package/dist/tooling/shared/{345tbc2k.js → yz68xcmc.js} +1 -1
  230. package/dist/tooling/testing/factories.d.ts +1 -3
  231. package/dist/tooling/testing/index.js +2 -2
  232. package/package.json +39 -9
  233. package/dist/shared/3449rcae.js +0 -14
  234. package/dist/shared/fjpnhqan.js +0 -71
  235. package/dist/shared/n41w4fbz.js +0 -113
  236. package/dist/tooling/shared/pw8fgahx.js +0 -69
  237. /package/dist/shared/{ae4j5f42.js → mfvx6kjx.js} +0 -0
@@ -1,9 +1,18 @@
1
1
  import {
2
2
  open2
3
- } from "./35q0n9tz.js";
3
+ } from "./jvxcp1qk.js";
4
4
  import {
5
5
  startupHash2
6
6
  } from "./12z7aznj.js";
7
+ import {
8
+ quoteIdent2
9
+ } from "./fk9vef30.js";
10
+ import {
11
+ sealViews,
12
+ sealDomainChecks2,
13
+ catalogQuery2,
14
+ managedRoleOptions2
15
+ } from "./4pkz5nvw.js";
7
16
  import {
8
17
  runTarget,
9
18
  assumeRole,
@@ -14,14 +23,21 @@ import {
14
23
  provisionMark,
15
24
  expandProvisioned,
16
25
  installSnapshot
17
- } from "./mnvjvqyp.js";
26
+ } from "./8p2bgye0.js";
18
27
  import {
19
28
  assertCreateRole,
20
29
  currentUser,
21
30
  roleExists
22
- } from "./kj9d8maq.js";
31
+ } from "./6xqvesa5.js";
32
+ import {
33
+ probeStableBackend
34
+ } from "./e1c55v04.js";
35
+ import {
36
+ introspectSchema
37
+ } from "./mz48rs74.js";
23
38
  import {
24
39
  projectPath,
40
+ assertSnapshots,
25
41
  loadMigrations,
26
42
  loadHeadSnapshot,
27
43
  lintMigrationDirectory,
@@ -30,8 +46,9 @@ import {
30
46
  projectHead,
31
47
  loadBuiltSchema,
32
48
  loadConfig
33
- } from "./f4jy1j7x.js";
49
+ } from "./wp7y8q3y.js";
34
50
  import {
51
+ driverUrl,
35
52
  changesRole,
36
53
  batchSizeField,
37
54
  assertExtensionsAvailable,
@@ -39,9 +56,8 @@ import {
39
56
  finishQuiet,
40
57
  assertTargetPolicy,
41
58
  assertDirectConnection,
42
- assertStableBackend,
43
59
  selectTarget
44
- } from "./dpc2r7rb.js";
60
+ } from "./bdekbvmt.js";
45
61
  import {
46
62
  UUIDV7_POSTGRES,
47
63
  uuidv7NeedsPostgres
@@ -96,6 +112,7 @@ function unquote(name) {
96
112
  }
97
113
 
98
114
  // src/tooling/migrate/apply.ts
115
+ import postgres from "postgres";
99
116
  var DEFAULT_LOCK_MS = 5000;
100
117
  var DEFAULT_STATEMENT_MS = 30000;
101
118
  var DEFAULT_RETRIES = 3;
@@ -170,8 +187,9 @@ function applyUnits(migration, done) {
170
187
  }
171
188
  async function applyTarget2(request) {
172
189
  assertDirectConnection(request.url, request.allowPooler === true);
190
+ const url = driverUrl(request.url);
173
191
  const pool = open2({
174
- url: request.url,
192
+ url,
175
193
  max: 1,
176
194
  ...request.searchPath !== undefined ? { searchPath: request.searchPath } : {}
177
195
  });
@@ -185,7 +203,7 @@ async function applyTarget2(request) {
185
203
  const connection = reserved;
186
204
  let locked = false;
187
205
  try {
188
- await assertStableBackend(() => backendPid(connection), request.allowPooler === true);
206
+ await probeStableBackend(request.url, () => backendPid(connection), request.allowPooler === true);
189
207
  await assertStandardStrings(connection);
190
208
  await setTimeouts(connection, request);
191
209
  await lockTarget(connection, request.target);
@@ -198,6 +216,7 @@ async function applyTarget2(request) {
198
216
  await prepareMigrationRole(connection, request, session);
199
217
  await assertExtensionsAvailable(connection, request.migrations);
200
218
  await assertUuidV7Available(connection, request.migrations);
219
+ await enterCatalogSchema(connection, request.schema ?? "public");
201
220
  const state = request.snapshot === undefined ? undefined : await targetState(connection);
202
221
  if (request.snapshot !== undefined && state !== undefined) {
203
222
  if (state.kind === "empty") {
@@ -230,8 +249,11 @@ async function applyTarget2(request) {
230
249
  if (request.snapshot !== undefined) {
231
250
  await insertReference(connection, request);
232
251
  }
252
+ const desiredHash = request.headHash;
253
+ const headStamp = desiredHash === undefined || request.restampHead !== true ? [] : await restampHeadHash(connection, request, nextSequenceId("restamp", history.ids), desiredHash);
233
254
  await grantAppMeta(connection, request.appRole, session);
234
- return restamped.length === 0 ? report : { ...report, restamped };
255
+ const stamped = [...restamped, ...headStamp];
256
+ return stamped.length === 0 ? report : { ...report, restamped: stamped };
235
257
  } finally {
236
258
  if (locked) {
237
259
  await finishQuiet(() => connection.execute("select pg_advisory_unlock(hashtext($1))", [lockKey(request.target)]));
@@ -255,7 +277,10 @@ nothing to apply
255
277
  return;
256
278
  throw error;
257
279
  });
280
+ if (built !== undefined)
281
+ assertSnapshots(cwd, config, built.catalog);
258
282
  const progress = [];
283
+ const externalConfigured = (config.external ?? []).length > 0;
259
284
  const report = await applyTarget2({
260
285
  url: target.url,
261
286
  target: target.name,
@@ -272,7 +297,10 @@ nothing to apply
272
297
  catalogHash: head.catalogHash,
273
298
  reference: built === undefined ? [] : readReference(built.tables, built.casing, head.catalog)
274
299
  },
300
+ ...built !== undefined ? { headHash: startupHash2(built.catalog) } : {},
301
+ ...externalConfigured ? { restampHead: true } : {},
275
302
  ...config.roles !== undefined ? { migrationRole: config.roles.migration, appRole: config.roles.app } : {},
303
+ ...catalogSchema(config.namespace),
276
304
  lintDirectory: directory,
277
305
  onProgress: (line) => {
278
306
  if (write !== undefined)
@@ -294,35 +322,176 @@ async function pushProject2(cwd, flags) {
294
322
  const target = selectTarget(config, flags.target);
295
323
  assertTargetPolicy(target, "push", flags.allowProtected);
296
324
  const head = await projectHead(cwd);
297
- const plan = planMigration({
298
- before: head.previous,
299
- after: head.catalog,
300
- renames: head.renames,
301
- name: "push",
302
- ...batchSizeField(config.backfill?.batchSize)
303
- });
304
- if (plan.steps.length === 0)
305
- return `target ${target.name}
306
- no changes
307
- `;
308
- const report = await applyTarget2({
325
+ assertSnapshots(cwd, config, head.catalog);
326
+ const catalogHash = startupHash2(head.catalog);
327
+ const report = await pushTarget({
309
328
  url: target.url,
310
329
  target: target.name,
311
330
  protected: target.protected,
312
331
  allowProtected: flags.allowProtected,
313
332
  allowPooler: flags.allowPooler || config.allowPooler === true,
314
333
  ...backfillTiming2(config.backfill),
315
- migrations: [
316
- {
317
- id: "push",
318
- catalogHash: startupHash2(head.catalog),
319
- steps: plan.steps
320
- }
321
- ],
322
- ...config.roles !== undefined ? { migrationRole: config.roles.migration, appRole: config.roles.app } : {}
334
+ after: head.catalog,
335
+ renames: head.renames,
336
+ catalogHash,
337
+ ...config.roles !== undefined ? { migrationRole: config.roles.migration, appRole: config.roles.app, roles: config.roles } : {},
338
+ ...catalogSchema(config.namespace),
339
+ ...batchSizeField(config.backfill?.batchSize)
323
340
  });
341
+ if (report.applied.length === 0 && (report.restamped ?? []).length === 0) {
342
+ return `target ${target.name}
343
+ no changes
344
+ `;
345
+ }
324
346
  return formatReport(report);
325
347
  }
348
+ async function pushTarget(request) {
349
+ assertDirectConnection(request.url, request.allowPooler === true);
350
+ const url = driverUrl(request.url);
351
+ const pool = open2({
352
+ url,
353
+ max: 1,
354
+ ...request.searchPath !== undefined ? { searchPath: request.searchPath } : {}
355
+ });
356
+ if (pool.reserve === undefined) {
357
+ await pool.close();
358
+ throw new OkmError2("invalid", "The driver cannot reserve a connection.", {
359
+ fix: { summary: "Push needs a driver with interactive transactions." }
360
+ });
361
+ }
362
+ const connection = await pool.reserve();
363
+ let locked = false;
364
+ try {
365
+ await probeStableBackend(request.url, () => backendPid(connection), request.allowPooler === true);
366
+ await assertStandardStrings(connection);
367
+ await setTimeouts(connection, {
368
+ url: request.url,
369
+ target: request.target,
370
+ protected: request.protected,
371
+ migrations: []
372
+ });
373
+ await lockTarget(connection, request.target);
374
+ locked = true;
375
+ const session = {};
376
+ const schema = request.schema ?? "public";
377
+ await enterCatalogSchema(connection, schema);
378
+ await ensureMigrationTables2((sql) => connection.execute(sql));
379
+ const history = await readHistory(connection);
380
+ const pushId = nextSequenceId("push", history.ids);
381
+ const sql = postgres(url, {
382
+ max: 1,
383
+ connect_timeout: 5,
384
+ idle_timeout: 1,
385
+ onnotice: () => {},
386
+ ...schema !== "public" ? { connection: { search_path: schema } } : {}
387
+ });
388
+ let planSteps = [];
389
+ try {
390
+ const runner = catalogQuery2(sql);
391
+ if (schema !== "public") {
392
+ await sql.unsafe(`create schema if not exists ${quoteIdent2(schema)}`);
393
+ await sql.unsafe(`set search_path to ${quoteIdent2(schema)}`);
394
+ }
395
+ const authorViews = await sealViews(runner, request.after);
396
+ const author = await sealDomainChecks2(runner, authorViews);
397
+ const live = await introspectSchema(runner, schema, schema, managedRoleOptions2(request.roles));
398
+ const plan = planMigration({
399
+ before: live,
400
+ after: author,
401
+ renames: request.renames,
402
+ name: pushId,
403
+ ...request.schema !== undefined ? { schema: request.schema } : {},
404
+ ...request.batchSize !== undefined ? { batchSize: request.batchSize } : {}
405
+ });
406
+ planSteps = plan.steps;
407
+ } finally {
408
+ await finishQuiet(() => sql.end({ timeout: 5 }));
409
+ }
410
+ if (planSteps.length === 0) {
411
+ const stamped = await restampHeadHash(connection, request, pushId, request.catalogHash);
412
+ await grantAppMeta(connection, request.appRole, session);
413
+ if (stamped.length === 0) {
414
+ return { target: request.target, applied: [] };
415
+ }
416
+ return { target: request.target, applied: [], restamped: stamped };
417
+ }
418
+ const migration = {
419
+ id: pushId,
420
+ catalogHash: request.catalogHash,
421
+ steps: planSteps
422
+ };
423
+ await prepareMigrationRole(connection, {
424
+ url: request.url,
425
+ target: request.target,
426
+ protected: request.protected,
427
+ migrations: [migration],
428
+ ...request.migrationRole !== undefined ? { migrationRole: request.migrationRole } : {},
429
+ ...request.schema !== undefined ? { schema: request.schema } : {}
430
+ }, session);
431
+ await assertExtensionsAvailable(connection, [migration]);
432
+ await assertUuidV7Available(connection, [migration]);
433
+ const units = applyUnits(migration, new Set);
434
+ const report = await runTarget(connection, {
435
+ policy: {
436
+ target: request.target,
437
+ protected: request.protected,
438
+ allowProtected: request.allowProtected === true
439
+ },
440
+ units,
441
+ retries: DEFAULT_RETRIES,
442
+ lockTimeoutMs: DEFAULT_LOCK_MS,
443
+ statementTimeoutMs: DEFAULT_STATEMENT_MS,
444
+ backfillStatementTimeoutMs: request.backfillStatementTimeoutMs ?? DEFAULT_STATEMENT_MS,
445
+ ...request.backfillPauseMs !== undefined ? { backfillPauseMs: request.backfillPauseMs } : {},
446
+ ...request.migrationRole !== undefined ? { migrationRole: request.migrationRole } : {},
447
+ ...request.schema !== undefined ? { schema: request.schema } : {}
448
+ }, session);
449
+ await grantAppMeta(connection, request.appRole, session);
450
+ return report;
451
+ } finally {
452
+ if (locked) {
453
+ await finishQuiet(() => connection.execute("select pg_advisory_unlock(hashtext($1))", [lockKey(request.target)]));
454
+ }
455
+ await finishQuiet(() => connection.release());
456
+ await finishQuiet(() => pool.close());
457
+ }
458
+ }
459
+ async function restampHeadHash(connection, request, migrationId, catalogHash) {
460
+ const present = await connection.execute("select to_regclass('okm_meta') is not null");
461
+ if (!wireTrue(present.rows[0]?.[0]))
462
+ return [];
463
+ const current = await connection.execute("select catalog_hash from okm_meta where id = 'head'");
464
+ const stored = current.rows[0]?.[0];
465
+ if (typeof stored === "string" && stored === catalogHash)
466
+ return [];
467
+ assertTargetPolicy({ name: request.target, protected: request.protected }, "history-repair", request.allowProtected === true);
468
+ await connection.execute("begin");
469
+ try {
470
+ await connection.execute("insert into okm_history (migration_id, step_index, class, catalog_hash) values ($1, 0, 'expand', $2)", [migrationId, catalogHash]);
471
+ await connection.execute(`insert into okm_meta (id, catalog_hash, migration_id) values ('head', $1, $2)
472
+ on conflict (id) do update set catalog_hash = excluded.catalog_hash, migration_id = excluded.migration_id`, [catalogHash, migrationId]);
473
+ await connection.execute("commit");
474
+ } catch (error) {
475
+ await connection.execute("rollback").catch(() => {
476
+ return;
477
+ });
478
+ throw error;
479
+ }
480
+ return [migrationId];
481
+ }
482
+ function nextSequenceId(prefix, ids) {
483
+ const pattern = new RegExp(`^${prefix}-(\\d+)$`);
484
+ let max = 0;
485
+ for (const id of ids) {
486
+ const match = pattern.exec(id);
487
+ if (match === null)
488
+ continue;
489
+ const value = Number(match[1]);
490
+ if (Number.isFinite(value) && value > max)
491
+ max = value;
492
+ }
493
+ return `${prefix}-${String(max + 1)}`;
494
+ }
326
495
  function backfillTiming2(backfill) {
327
496
  return {
328
497
  ...backfill?.pauseMs !== undefined ? { backfillPauseMs: backfill.pauseMs } : {},
@@ -334,10 +503,11 @@ function formatReport(report) {
334
503
  ` : "";
335
504
  const restamped = (report.restamped ?? []).map((id) => `restamped ${id}
336
505
  `).join("");
337
- if (report.applied.length === 0)
506
+ if (report.applied.length === 0) {
338
507
  return `target ${report.target}
339
508
  ${role}${restamped}nothing to apply
340
509
  `;
510
+ }
341
511
  return `target ${report.target}
342
512
  ${role}${restamped}${report.applied.map((id) => `applied ${id}`).join(`
343
513
  `)}
@@ -514,6 +684,17 @@ async function insertReference(connection, request) {
514
684
  function concreteSchema(request) {
515
685
  return request.searchPath ?? request.schema ?? "public";
516
686
  }
687
+ function catalogSchema(namespace) {
688
+ if (namespace === undefined || namespace === "public")
689
+ return;
690
+ return { schema: namespace };
691
+ }
692
+ async function enterCatalogSchema(connection, schema) {
693
+ if (schema === "public")
694
+ return;
695
+ await connection.execute(`create schema if not exists ${quoteIdent2(schema)}`);
696
+ await connection.execute(`set search_path to ${quoteIdent2(schema)}`);
697
+ }
517
698
  async function targetState(connection) {
518
699
  const meta = await connection.execute(`select to_regclass('okm_meta') is not null
519
700
  or to_regclass('okm_history') is not null
@@ -1,13 +1,18 @@
1
1
  import {
2
2
  serializeCatalog2
3
3
  } from "./12z7aznj.js";
4
+ import {
5
+ quoteIdent2,
6
+ qualify2
7
+ } from "./fk9vef30.js";
4
8
  import {
5
9
  roleExists
6
- } from "./kj9d8maq.js";
10
+ } from "./6xqvesa5.js";
7
11
  import {
8
12
  canonicalTypeName,
9
13
  createdRoleName,
10
14
  createRoleOnce,
15
+ changesRole,
11
16
  DEFAULT_BACKFILL_PAUSE_MS,
12
17
  DEFAULT_BACKFILL_STATEMENT_TIMEOUT_MS,
13
18
  boundaryQuery,
@@ -16,14 +21,10 @@ import {
16
21
  planMigration,
17
22
  sessionFailure,
18
23
  assertTargetPolicy
19
- } from "./dpc2r7rb.js";
24
+ } from "./bdekbvmt.js";
20
25
  import {
21
26
  snakeCase
22
- } from "./gcefca6p.js";
23
- import {
24
- quoteIdent,
25
- qualify
26
- } from "./sjk86yrx.js";
27
+ } from "./f9t9g54z.js";
27
28
  import {
28
29
  catalog,
29
30
  isDomain
@@ -70,21 +71,97 @@ async function runTarget(connection, run, session) {
70
71
  async function assumeRole(connection, role, session) {
71
72
  if (session.setRole === role)
72
73
  return;
73
- await connection.execute(`set role ${quoteIdent(role)}`);
74
+ await ensureSetOption(connection, role);
75
+ await connection.execute(`set role ${quoteIdent2(role)}`);
74
76
  session.setRole = role;
75
77
  }
78
+ async function ensureSetOption(connection, role) {
79
+ const who = await connection.execute("select current_user, rolsuper from pg_roles where rolname = current_user");
80
+ const current = who.rows[0]?.[0];
81
+ if (typeof current !== "string" || current === role)
82
+ return;
83
+ if (roleFlag(who.rows[0]?.[1]))
84
+ return;
85
+ const version = await connection.execute("show server_version_num");
86
+ const versionNum = Number(version.rows[0]?.[0] ?? 0);
87
+ if (Number.isFinite(versionNum) && versionNum >= 160000) {
88
+ const option = await connection.execute(`select am.set_option
89
+ from pg_auth_members am
90
+ join pg_roles r on r.oid = am.roleid
91
+ join pg_roles m on m.oid = am.member
92
+ where r.rolname = $1 and m.rolname = $2`, [role, current]);
93
+ if (roleFlag(option.rows[0]?.[0]))
94
+ return;
95
+ await connection.execute(`grant ${quoteIdent2(role)} to ${quoteIdent2(current)} with set true`);
96
+ return;
97
+ }
98
+ const member = await connection.execute("select pg_has_role($1, $2, 'MEMBER')", [current, role]);
99
+ if (roleFlag(member.rows[0]?.[0]))
100
+ return;
101
+ await connection.execute(`grant ${quoteIdent2(role)} to ${quoteIdent2(current)}`);
102
+ }
103
+ function rolePrivilegeError(error, role) {
104
+ const message = error instanceof Error ? error.message : String(error);
105
+ if (/permission denied to create role/i.test(message)) {
106
+ return new OkmError2("forbidden", "CREATEROLE is required to create roles. Nothing was changed.", {
107
+ kind: "forbidden",
108
+ cause: error,
109
+ fix: {
110
+ summary: "Grant CREATEROLE to the connecting role, or connect as a superuser."
111
+ }
112
+ });
113
+ }
114
+ if (/permission denied to set role/i.test(message)) {
115
+ const name = role ?? "the migration role";
116
+ return new OkmError2("forbidden", `Cannot SET ROLE ${name}: the connecting role lacks the SET option on that membership.`, {
117
+ kind: "forbidden",
118
+ cause: error,
119
+ fix: {
120
+ summary: `Grant ${name} to the connecting role (WITH SET TRUE on Postgres 16+), or connect as a superuser.`
121
+ }
122
+ });
123
+ }
124
+ if (/must be able to SET ROLE|not a member/i.test(message)) {
125
+ const name = role ?? "the migration role";
126
+ return new OkmError2("forbidden", `Cannot SET ROLE ${name}: the connecting role is not a member with the SET option.`, {
127
+ kind: "forbidden",
128
+ cause: error,
129
+ fix: {
130
+ summary: `Grant ${name} to the connecting role (WITH SET TRUE on Postgres 16+), or connect as a superuser.`
131
+ }
132
+ });
133
+ }
134
+ return;
135
+ }
76
136
  async function grantAppMeta(connection, role, session) {
77
137
  if (role === undefined)
78
138
  return;
79
139
  const previous = session.setRole;
80
140
  if (previous !== undefined)
81
141
  await connection.execute("reset role");
82
- await connection.execute(`grant select on okm_meta to ${quoteIdent(role)}`);
142
+ await connection.execute(`grant select on okm_meta to ${quoteIdent2(role)}`);
83
143
  if (previous !== undefined)
84
- await connection.execute(`set role ${quoteIdent(previous)}`);
144
+ await connection.execute(`set role ${quoteIdent2(previous)}`);
85
145
  }
86
146
  async function grantSchema(connection, schema, role) {
87
- await connection.execute(`grant usage, create on schema ${quoteIdent(schema)} to ${quoteIdent(role)}`);
147
+ await connection.execute(`grant usage, create on schema ${quoteIdent2(schema)} to ${quoteIdent2(role)}`);
148
+ }
149
+ async function ownSchema(connection, schema, role) {
150
+ await ensureSetOption(connection, role);
151
+ await connection.execute("savepoint okm_own_schema");
152
+ try {
153
+ const database = await databaseName(connection);
154
+ await connection.execute(`grant create on database ${quoteIdent2(database)} to ${quoteIdent2(role)}`);
155
+ await connection.execute(`alter schema ${quoteIdent2(schema)} owner to ${quoteIdent2(role)}`);
156
+ await connection.execute("release savepoint okm_own_schema");
157
+ } catch {
158
+ await connection.execute("rollback to savepoint okm_own_schema");
159
+ }
160
+ }
161
+ async function databaseName(connection) {
162
+ const result = await connection.execute("select current_database()");
163
+ const name = result.rows[0]?.[0];
164
+ return typeof name === "string" ? name : "postgres";
88
165
  }
89
166
  async function runUnit(connection, unit, run, session) {
90
167
  const only = unit.steps.length === 1 ? unit.steps[0] : undefined;
@@ -102,6 +179,9 @@ async function runUnit(connection, unit, run, session) {
102
179
  }
103
180
  for (const item of unit.steps) {
104
181
  current = item.index;
182
+ if (run.migrationRole !== undefined && !changesRole(item.step.sql) && session.setRole !== run.migrationRole && await roleExists(connection, run.migrationRole)) {
183
+ await assumeRole(connection, run.migrationRole, session);
184
+ }
105
185
  await rebuildInvalidIndex(connection, item.step.sql);
106
186
  const created = createdRoleName(item.step.sql);
107
187
  const existed = created !== undefined && await roleExists(connection, created);
@@ -110,12 +190,10 @@ async function runUnit(connection, unit, run, session) {
110
190
  await assertSchemaUsageLanded(connection, item.step.sql);
111
191
  } else if (!existed)
112
192
  await connection.execute(createRoleOnce(item.step.sql));
113
- if (created !== undefined && created === run.migrationRole) {
114
- if (!existed) {
115
- await grantSchema(connection, run.schema ?? "public", created);
116
- await connection.execute(`grant select, insert, update on okm_meta, okm_history, okm_backfill to ${quoteIdent(created)}`);
117
- }
118
- await assumeRole(connection, created, session);
193
+ if (created !== undefined && created === run.migrationRole && !existed) {
194
+ await grantSchema(connection, run.schema ?? "public", created);
195
+ await ownSchema(connection, run.schema ?? "public", created);
196
+ await connection.execute(`grant select, insert, update on okm_meta, okm_history, okm_backfill to ${quoteIdent2(created)}`);
119
197
  }
120
198
  if (!unit.transactional) {
121
199
  await connection.execute("begin");
@@ -127,6 +205,9 @@ async function runUnit(connection, unit, run, session) {
127
205
  began = false;
128
206
  }
129
207
  }
208
+ if (run.migrationRole !== undefined && session.setRole !== run.migrationRole && await roleExists(connection, run.migrationRole)) {
209
+ await assumeRole(connection, run.migrationRole, session);
210
+ }
130
211
  if (unit.transactional) {
131
212
  for (const item of unit.steps)
132
213
  await writeStep(connection, unit, item);
@@ -182,7 +263,7 @@ async function runBackfill(connection, unit, item, spec, run) {
182
263
  rows,
183
264
  lastKey: committed.lastKey
184
265
  };
185
- run.onProgress?.(`backfill ${unit.migrationId} step ${String(item.index)} batch ${String(batches)} rows ${String(rows)} key ${committed.lastKey ?? "-"}`);
266
+ run.onProgress?.(`backfill ${unit.migrationId} step ${String(item.index + 1)} batch ${String(batches)} rows ${String(rows)} key ${committed.lastKey ?? "-"}`);
186
267
  await run.afterBatch?.(note);
187
268
  if (committed.final)
188
269
  return;
@@ -305,7 +386,7 @@ async function rebuildInvalidIndex(connection, sql) {
305
386
  const valid = found.rows[0]?.[0];
306
387
  if (valid === undefined || wireTrue(valid))
307
388
  return;
308
- await connection.execute(`drop index concurrently if exists ${quoteIdent(name)}`);
389
+ await connection.execute(`drop index concurrently if exists ${quoteIdent2(name)}`);
309
390
  }
310
391
  function concurrentIndexName(sql) {
311
392
  const match = /^create\s+(?:unique\s+)?index\s+concurrently\s+(?:if\s+not\s+exists\s+)?(?:"([^"]+)"|([A-Za-z_][\w$]*))/i.exec(sql.trim());
@@ -325,13 +406,12 @@ async function assertSchemaUsageLanded(connection, sql) {
325
406
  join pg_roles r on r.oid = a.grantee
326
407
  where n.nspname = $1 and r.rolname = $2 and a.privilege_type = 'USAGE'
327
408
  )`, [schema, role]);
328
- const landed = found.rows[0]?.[0];
329
- if (landed === "t" || landed === "true")
409
+ if (roleFlag(found.rows[0]?.[0]))
330
410
  return;
331
411
  throw new OkmError2("OKM1825", `Grant usage on schema ${schema} to ${role} did not take effect.`, {
332
412
  kind: "forbidden",
333
413
  fix: {
334
- summary: `Make the migration role the owner of schema ${schema}. ALTER SCHEMA ${quoteIdent(schema)} OWNER TO <migration role>.`
414
+ summary: `Make the migration role the owner of schema ${schema}. ALTER SCHEMA ${quoteIdent2(schema)} OWNER TO <migration role>.`
335
415
  }
336
416
  });
337
417
  }
@@ -340,6 +420,10 @@ function failStep(unit, index, error) {
340
420
  if (lost !== undefined) {
341
421
  return new OkmError2(lost.code, `Migration ${unit.migrationId} failed at step ${String(index + 1)}: ${lost.message}`, { kind: lost.kind, cause: error, fix: lost.fix });
342
422
  }
423
+ const privilege = rolePrivilegeError(error, undefined);
424
+ if (privilege !== undefined) {
425
+ return new OkmError2(privilege.code, `Migration ${unit.migrationId} failed at step ${String(index + 1)}: ${privilege.message}`, { kind: privilege.kind, cause: error, fix: privilege.fix });
426
+ }
343
427
  if (error instanceof OkmError2)
344
428
  return error;
345
429
  const message = error instanceof Error ? error.message : "The step failed.";
@@ -359,6 +443,9 @@ function isLockTimeout(error) {
359
443
  function wireTrue(value) {
360
444
  return value === "t" || value === "true";
361
445
  }
446
+ function roleFlag(value) {
447
+ return value === true || value === "t" || value === "true";
448
+ }
362
449
  function unquote(token) {
363
450
  if (token.startsWith('"') && token.endsWith('"')) {
364
451
  return token.slice(1, -1).replaceAll('""', '"');
@@ -423,11 +510,11 @@ function readReference(tables, casing, head) {
423
510
  function referenceInserts(tables, schema) {
424
511
  const statements = [];
425
512
  for (const item of tables) {
426
- const conflict = item.key.map((name) => quoteIdent(name)).join(", ");
513
+ const conflict = item.key.map((name) => quoteIdent2(name)).join(", ");
427
514
  for (const row of item.rows) {
428
- const columns = row.map(([name]) => quoteIdent(name)).join(", ");
515
+ const columns = row.map(([name]) => quoteIdent2(name)).join(", ");
429
516
  const values = row.map(([, value]) => literal(value)).join(", ");
430
- statements.push(`insert into ${qualify(schema, item.table)} (${columns}) values (${values}) on conflict (${conflict}) do nothing`);
517
+ statements.push(`insert into ${qualify2(schema, item.table)} (${columns}) values (${values}) on conflict (${conflict}) do nothing`);
431
518
  }
432
519
  }
433
520
  return statements;
@@ -598,13 +685,14 @@ async function installSnapshot(connection, head, schema, reference, session, mig
598
685
  for (const step of plan.steps) {
599
686
  if (step.backfill !== undefined)
600
687
  continue;
688
+ if (migrationRole !== undefined && !changesRole(step.sql) && session.setRole !== migrationRole && await roleExists(connection, migrationRole)) {
689
+ await flush();
690
+ await assumeRole(connection, migrationRole, session);
691
+ }
601
692
  const created = createdRoleName(step.sql);
602
693
  const existed = created !== undefined && await roleExists(connection, created);
603
- if (created !== undefined && existed) {
604
- if (created === migrationRole)
605
- await assumeRole(connection, created, session);
694
+ if (created !== undefined && existed)
606
695
  continue;
607
- }
608
696
  const sql = created === undefined ? step.sql : createRoleOnce(step.sql);
609
697
  if (step.transactional && !statementOutsideTransaction(step.sql)) {
610
698
  batch.push(sql);
@@ -616,10 +704,14 @@ async function installSnapshot(connection, head, schema, reference, session, mig
616
704
  if (created !== undefined && created === migrationRole) {
617
705
  await flush();
618
706
  await grantSchema(connection, schema, created);
619
- await connection.execute(`grant select, insert, update on okm_meta, okm_history, okm_backfill to ${quoteIdent(created)}`);
620
- await assumeRole(connection, created, session);
707
+ await ownSchema(connection, schema, created);
708
+ await connection.execute(`grant select, insert, update on okm_meta, okm_history, okm_backfill to ${quoteIdent2(created)}`);
621
709
  }
622
710
  }
711
+ if (migrationRole !== undefined && session.setRole !== migrationRole && await roleExists(connection, migrationRole)) {
712
+ await flush();
713
+ await assumeRole(connection, migrationRole, session);
714
+ }
623
715
  await flush();
624
716
  for (const sql of referenceInserts(reference, schema)) {
625
717
  if (!began) {
@@ -754,4 +846,4 @@ function normaliseFunction(object) {
754
846
  };
755
847
  }
756
848
 
757
- export { runTarget, assumeRole, grantAppMeta, grantSchema, assertSchemaUsageLanded, statementOutsideTransaction, readReference, referenceInserts, catalogsEqual, provisionMark, expandProvisioned, provisionHistoryIsKnown, installSnapshot, snapshotDifference };
849
+ export { runTarget, assumeRole, grantAppMeta, grantSchema, ownSchema, assertSchemaUsageLanded, statementOutsideTransaction, readReference, referenceInserts, catalogsEqual, provisionMark, expandProvisioned, provisionHistoryIsKnown, installSnapshot, snapshotDifference };