@intentius/chant-lexicon-sql 0.0.0-stage → 0.112.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 (936) hide show
  1. package/README.md +39 -2
  2. package/dist/clickhouse/apply/apply.d.ts +82 -0
  3. package/dist/clickhouse/apply/apply.d.ts.map +1 -0
  4. package/dist/clickhouse/apply/mutations.d.ts +46 -0
  5. package/dist/clickhouse/apply/mutations.d.ts.map +1 -0
  6. package/dist/clickhouse/apply/statements.d.ts +99 -0
  7. package/dist/clickhouse/apply/statements.d.ts.map +1 -0
  8. package/dist/clickhouse/catalog-types.d.ts +76 -0
  9. package/dist/clickhouse/catalog-types.d.ts.map +1 -0
  10. package/dist/clickhouse/container.d.ts +63 -0
  11. package/dist/clickhouse/container.d.ts.map +1 -0
  12. package/dist/clickhouse/engine-syntax.d.ts +43 -0
  13. package/dist/clickhouse/engine-syntax.d.ts.map +1 -0
  14. package/dist/clickhouse/entities.d.ts +183 -0
  15. package/dist/clickhouse/entities.d.ts.map +1 -0
  16. package/dist/clickhouse/http.d.ts +40 -0
  17. package/dist/clickhouse/http.d.ts.map +1 -0
  18. package/dist/clickhouse/import/generator.d.ts +16 -0
  19. package/dist/clickhouse/import/generator.d.ts.map +1 -0
  20. package/dist/clickhouse/import/ir.d.ts +52 -0
  21. package/dist/clickhouse/import/ir.d.ts.map +1 -0
  22. package/dist/clickhouse/import/live-export.d.ts +28 -0
  23. package/dist/clickhouse/import/live-export.d.ts.map +1 -0
  24. package/dist/clickhouse/import/parser.d.ts +10 -0
  25. package/dist/clickhouse/import/parser.d.ts.map +1 -0
  26. package/dist/clickhouse/live/bind.d.ts +56 -0
  27. package/dist/clickhouse/live/bind.d.ts.map +1 -0
  28. package/dist/clickhouse/live/catalog.d.ts +39 -0
  29. package/dist/clickhouse/live/catalog.d.ts.map +1 -0
  30. package/dist/clickhouse/live/describe-resources.d.ts +34 -0
  31. package/dist/clickhouse/live/describe-resources.d.ts.map +1 -0
  32. package/dist/clickhouse/overlays/codecs.d.ts +28 -0
  33. package/dist/clickhouse/overlays/codecs.d.ts.map +1 -0
  34. package/dist/clickhouse/overlays/engines.d.ts +20 -0
  35. package/dist/clickhouse/overlays/engines.d.ts.map +1 -0
  36. package/dist/clickhouse/overlays/kinds.d.ts +38 -0
  37. package/dist/clickhouse/overlays/kinds.d.ts.map +1 -0
  38. package/dist/clickhouse/overlays/projections.d.ts +27 -0
  39. package/dist/clickhouse/overlays/projections.d.ts.map +1 -0
  40. package/dist/clickhouse/overlays/skip-indexes.d.ts +10 -0
  41. package/dist/clickhouse/overlays/skip-indexes.d.ts.map +1 -0
  42. package/dist/clickhouse/overlays/ttl.d.ts +35 -0
  43. package/dist/clickhouse/overlays/ttl.d.ts.map +1 -0
  44. package/dist/clickhouse/overlays/types.d.ts +21 -0
  45. package/dist/clickhouse/overlays/types.d.ts.map +1 -0
  46. package/dist/clickhouse/ownership.d.ts +71 -0
  47. package/dist/clickhouse/ownership.d.ts.map +1 -0
  48. package/dist/clickhouse/parser.d.ts +130 -0
  49. package/dist/clickhouse/parser.d.ts.map +1 -0
  50. package/dist/clickhouse/plan/commands.d.ts +26 -0
  51. package/dist/clickhouse/plan/commands.d.ts.map +1 -0
  52. package/dist/clickhouse/plan/deep.d.ts +32 -0
  53. package/dist/clickhouse/plan/deep.d.ts.map +1 -0
  54. package/dist/clickhouse/plan/diff.d.ts +37 -0
  55. package/dist/clickhouse/plan/diff.d.ts.map +1 -0
  56. package/dist/clickhouse/plan/disruption.d.ts +17 -0
  57. package/dist/clickhouse/plan/disruption.d.ts.map +1 -0
  58. package/dist/clickhouse/plan/normalize.d.ts +97 -0
  59. package/dist/clickhouse/plan/normalize.d.ts.map +1 -0
  60. package/dist/clickhouse/plan/rebuild-handoff.d.ts +38 -0
  61. package/dist/clickhouse/plan/rebuild-handoff.d.ts.map +1 -0
  62. package/dist/clickhouse/plan/report.d.ts +6 -0
  63. package/dist/clickhouse/plan/report.d.ts.map +1 -0
  64. package/dist/clickhouse/plan/rules.d.ts +60 -0
  65. package/dist/clickhouse/plan/rules.d.ts.map +1 -0
  66. package/dist/clickhouse/plan/schema.d.ts +23 -0
  67. package/dist/clickhouse/plan/schema.d.ts.map +1 -0
  68. package/dist/clickhouse/plan/server-format.d.ts +12 -0
  69. package/dist/clickhouse/plan/server-format.d.ts.map +1 -0
  70. package/dist/clickhouse/rebuild/backfill.d.ts +70 -0
  71. package/dist/clickhouse/rebuild/backfill.d.ts.map +1 -0
  72. package/dist/clickhouse/rebuild/observe.d.ts +157 -0
  73. package/dist/clickhouse/rebuild/observe.d.ts.map +1 -0
  74. package/dist/clickhouse/rebuild/op.d.ts +108 -0
  75. package/dist/clickhouse/rebuild/op.d.ts.map +1 -0
  76. package/dist/clickhouse/rebuild/partitions.d.ts +24 -0
  77. package/dist/clickhouse/rebuild/partitions.d.ts.map +1 -0
  78. package/dist/clickhouse/rebuild/receipts.d.ts +76 -0
  79. package/dist/clickhouse/rebuild/receipts.d.ts.map +1 -0
  80. package/dist/clickhouse/rebuild/replicas.d.ts +78 -0
  81. package/dist/clickhouse/rebuild/replicas.d.ts.map +1 -0
  82. package/dist/clickhouse/rebuild/steps.d.ts +151 -0
  83. package/dist/clickhouse/rebuild/steps.d.ts.map +1 -0
  84. package/dist/clickhouse/rebuild/verify.d.ts +51 -0
  85. package/dist/clickhouse/rebuild/verify.d.ts.map +1 -0
  86. package/dist/clickhouse/testing/fake-server.d.ts +27 -0
  87. package/dist/clickhouse/testing/fake-server.d.ts.map +1 -0
  88. package/dist/clickhouse/testing/roundtrip-schema.d.ts +3 -0
  89. package/dist/clickhouse/testing/roundtrip-schema.d.ts.map +1 -0
  90. package/dist/clickhouse/testing/writable-server.d.ts +35 -0
  91. package/dist/clickhouse/testing/writable-server.d.ts.map +1 -0
  92. package/dist/clickhouse/tokens.d.ts +15 -0
  93. package/dist/clickhouse/tokens.d.ts.map +1 -0
  94. package/dist/clickhouse.d.ts +24 -0
  95. package/dist/clickhouse.d.ts.map +1 -0
  96. package/dist/codegen/classifier-page.d.ts +6 -0
  97. package/dist/codegen/classifier-page.d.ts.map +1 -0
  98. package/dist/codegen/clickhouse-module.d.ts +23 -0
  99. package/dist/codegen/clickhouse-module.d.ts.map +1 -0
  100. package/dist/codegen/docs-cli.d.ts +3 -0
  101. package/dist/codegen/docs-cli.d.ts.map +1 -0
  102. package/dist/codegen/docs.d.ts +8 -0
  103. package/dist/codegen/docs.d.ts.map +1 -0
  104. package/dist/codegen/generate-cli.d.ts +3 -0
  105. package/dist/codegen/generate-cli.d.ts.map +1 -0
  106. package/dist/codegen/generate.d.ts +40 -0
  107. package/dist/codegen/generate.d.ts.map +1 -0
  108. package/dist/codegen/package.d.ts +7 -0
  109. package/dist/codegen/package.d.ts.map +1 -0
  110. package/dist/codegen/postgres-classifier-page.d.ts +7 -0
  111. package/dist/codegen/postgres-classifier-page.d.ts.map +1 -0
  112. package/dist/codegen/postgres-module.d.ts +30 -0
  113. package/dist/codegen/postgres-module.d.ts.map +1 -0
  114. package/dist/codegen/registry.d.ts +12 -0
  115. package/dist/codegen/registry.d.ts.map +1 -0
  116. package/dist/composites/audit-log-table.d.ts +31 -0
  117. package/dist/composites/audit-log-table.d.ts.map +1 -0
  118. package/dist/composites/catalog.d.ts +3 -0
  119. package/dist/composites/catalog.d.ts.map +1 -0
  120. package/dist/composites/cdc-mirror.d.ts +32 -0
  121. package/dist/composites/cdc-mirror.d.ts.map +1 -0
  122. package/dist/composites/clickhouse.d.ts +7 -0
  123. package/dist/composites/clickhouse.d.ts.map +1 -0
  124. package/dist/composites/events-table.d.ts +32 -0
  125. package/dist/composites/events-table.d.ts.map +1 -0
  126. package/dist/composites/index.d.ts +9 -0
  127. package/dist/composites/index.d.ts.map +1 -0
  128. package/dist/composites/join-table.d.ts +41 -0
  129. package/dist/composites/join-table.d.ts.map +1 -0
  130. package/dist/composites/postgres.d.ts +7 -0
  131. package/dist/composites/postgres.d.ts.map +1 -0
  132. package/dist/composites/refreshed-view.d.ts +32 -0
  133. package/dist/composites/refreshed-view.d.ts.map +1 -0
  134. package/dist/composites/replacing-table.d.ts +34 -0
  135. package/dist/composites/replacing-table.d.ts.map +1 -0
  136. package/dist/composites/rollup-view.d.ts +39 -0
  137. package/dist/composites/rollup-view.d.ts.map +1 -0
  138. package/dist/composites/sharded-table.d.ts +35 -0
  139. package/dist/composites/sharded-table.d.ts.map +1 -0
  140. package/dist/composites/soft-delete-table.d.ts +40 -0
  141. package/dist/composites/soft-delete-table.d.ts.map +1 -0
  142. package/dist/composites/tenant-table.d.ts +34 -0
  143. package/dist/composites/tenant-table.d.ts.map +1 -0
  144. package/dist/config.d.ts +213 -0
  145. package/dist/config.d.ts.map +1 -0
  146. package/dist/core/apply.d.ts +89 -0
  147. package/dist/core/apply.d.ts.map +1 -0
  148. package/dist/core/classifier.d.ts +88 -0
  149. package/dist/core/classifier.d.ts.map +1 -0
  150. package/dist/core/container.d.ts +45 -0
  151. package/dist/core/container.d.ts.map +1 -0
  152. package/dist/core/cursor.d.ts +67 -0
  153. package/dist/core/cursor.d.ts.map +1 -0
  154. package/dist/core/diff.d.ts +49 -0
  155. package/dist/core/diff.d.ts.map +1 -0
  156. package/dist/core/entity.d.ts +41 -0
  157. package/dist/core/entity.d.ts.map +1 -0
  158. package/dist/core/find-templates.d.ts +69 -0
  159. package/dist/core/find-templates.d.ts.map +1 -0
  160. package/dist/core/handoff.d.ts +36 -0
  161. package/dist/core/handoff.d.ts.map +1 -0
  162. package/dist/core/index.d.ts +61 -0
  163. package/dist/core/index.d.ts.map +1 -0
  164. package/dist/core/interpolation.d.ts +88 -0
  165. package/dist/core/interpolation.d.ts.map +1 -0
  166. package/dist/core/normalize.d.ts +18 -0
  167. package/dist/core/normalize.d.ts.map +1 -0
  168. package/dist/core/ownership.d.ts +60 -0
  169. package/dist/core/ownership.d.ts.map +1 -0
  170. package/dist/core/receipts.d.ts +28 -0
  171. package/dist/core/receipts.d.ts.map +1 -0
  172. package/dist/core/references.d.ts +37 -0
  173. package/dist/core/references.d.ts.map +1 -0
  174. package/dist/core/template.d.ts +41 -0
  175. package/dist/core/template.d.ts.map +1 -0
  176. package/dist/core/testing/http-stub.d.ts +17 -0
  177. package/dist/core/testing/http-stub.d.ts.map +1 -0
  178. package/dist/core/tokens.d.ts +102 -0
  179. package/dist/core/tokens.d.ts.map +1 -0
  180. package/dist/coverage.d.ts +25 -0
  181. package/dist/coverage.d.ts.map +1 -0
  182. package/dist/detect.d.ts +15 -0
  183. package/dist/detect.d.ts.map +1 -0
  184. package/dist/dialects.d.ts +20 -0
  185. package/dist/dialects.d.ts.map +1 -0
  186. package/dist/generated/clickhouse-types.d.ts +4380 -0
  187. package/dist/generated/clickhouse-types.d.ts.map +1 -0
  188. package/dist/generated/clickhouse.d.ts +11 -0
  189. package/dist/generated/clickhouse.d.ts.map +1 -0
  190. package/dist/generated/postgres-types.d.ts +1579 -0
  191. package/dist/generated/postgres-types.d.ts.map +1 -0
  192. package/dist/generated/postgres.d.ts +9 -0
  193. package/dist/generated/postgres.d.ts.map +1 -0
  194. package/dist/import-generator.d.ts +8 -0
  195. package/dist/import-generator.d.ts.map +1 -0
  196. package/dist/index.d.ts +7 -0
  197. package/dist/index.d.ts.map +1 -0
  198. package/dist/init-templates.d.ts +20 -0
  199. package/dist/init-templates.d.ts.map +1 -0
  200. package/dist/integrity.json +61 -0
  201. package/dist/lint/audit-catalog.d.ts +10 -0
  202. package/dist/lint/audit-catalog.d.ts.map +1 -0
  203. package/dist/lint/audit-lineage.d.ts +25 -0
  204. package/dist/lint/audit-lineage.d.ts.map +1 -0
  205. package/dist/lint/post-synth/audit-entries.d.ts +8 -0
  206. package/dist/lint/post-synth/audit-entries.d.ts.map +1 -0
  207. package/dist/lint/post-synth/clickhouse-helpers.d.ts +85 -0
  208. package/dist/lint/post-synth/clickhouse-helpers.d.ts.map +1 -0
  209. package/dist/lint/post-synth/index.d.ts +3 -0
  210. package/dist/lint/post-synth/index.d.ts.map +1 -0
  211. package/dist/lint/post-synth/postgres-audit-entries.d.ts +9 -0
  212. package/dist/lint/post-synth/postgres-audit-entries.d.ts.map +1 -0
  213. package/dist/lint/post-synth/postgres-helpers.d.ts +89 -0
  214. package/dist/lint/post-synth/postgres-helpers.d.ts.map +1 -0
  215. package/dist/lint/post-synth/sql-helpers.d.ts +27 -0
  216. package/dist/lint/post-synth/sql-helpers.d.ts.map +1 -0
  217. package/dist/lint/post-synth/sqlch101.d.ts +12 -0
  218. package/dist/lint/post-synth/sqlch101.d.ts.map +1 -0
  219. package/dist/lint/post-synth/sqlch102.d.ts +9 -0
  220. package/dist/lint/post-synth/sqlch102.d.ts.map +1 -0
  221. package/dist/lint/post-synth/sqlch103.d.ts +10 -0
  222. package/dist/lint/post-synth/sqlch103.d.ts.map +1 -0
  223. package/dist/lint/post-synth/sqlch104.d.ts +9 -0
  224. package/dist/lint/post-synth/sqlch104.d.ts.map +1 -0
  225. package/dist/lint/post-synth/sqlch105.d.ts +10 -0
  226. package/dist/lint/post-synth/sqlch105.d.ts.map +1 -0
  227. package/dist/lint/post-synth/sqlch106.d.ts +11 -0
  228. package/dist/lint/post-synth/sqlch106.d.ts.map +1 -0
  229. package/dist/lint/post-synth/sqlch107.d.ts +10 -0
  230. package/dist/lint/post-synth/sqlch107.d.ts.map +1 -0
  231. package/dist/lint/post-synth/sqlch108.d.ts +11 -0
  232. package/dist/lint/post-synth/sqlch108.d.ts.map +1 -0
  233. package/dist/lint/post-synth/sqlch109.d.ts +10 -0
  234. package/dist/lint/post-synth/sqlch109.d.ts.map +1 -0
  235. package/dist/lint/post-synth/sqlch110.d.ts +12 -0
  236. package/dist/lint/post-synth/sqlch110.d.ts.map +1 -0
  237. package/dist/lint/post-synth/sqlch111.d.ts +11 -0
  238. package/dist/lint/post-synth/sqlch111.d.ts.map +1 -0
  239. package/dist/lint/post-synth/sqlch112.d.ts +12 -0
  240. package/dist/lint/post-synth/sqlch112.d.ts.map +1 -0
  241. package/dist/lint/post-synth/sqlch113.d.ts +9 -0
  242. package/dist/lint/post-synth/sqlch113.d.ts.map +1 -0
  243. package/dist/lint/post-synth/sqlch114.d.ts +8 -0
  244. package/dist/lint/post-synth/sqlch114.d.ts.map +1 -0
  245. package/dist/lint/post-synth/sqlch115.d.ts +13 -0
  246. package/dist/lint/post-synth/sqlch115.d.ts.map +1 -0
  247. package/dist/lint/post-synth/sqlch116.d.ts +10 -0
  248. package/dist/lint/post-synth/sqlch116.d.ts.map +1 -0
  249. package/dist/lint/post-synth/sqlch117.d.ts +9 -0
  250. package/dist/lint/post-synth/sqlch117.d.ts.map +1 -0
  251. package/dist/lint/post-synth/sqlch118.d.ts +10 -0
  252. package/dist/lint/post-synth/sqlch118.d.ts.map +1 -0
  253. package/dist/lint/post-synth/sqlch119.d.ts +11 -0
  254. package/dist/lint/post-synth/sqlch119.d.ts.map +1 -0
  255. package/dist/lint/post-synth/sqlch120.d.ts +10 -0
  256. package/dist/lint/post-synth/sqlch120.d.ts.map +1 -0
  257. package/dist/lint/post-synth/sqlpg101.d.ts +12 -0
  258. package/dist/lint/post-synth/sqlpg101.d.ts.map +1 -0
  259. package/dist/lint/post-synth/sqlpg102.d.ts +11 -0
  260. package/dist/lint/post-synth/sqlpg102.d.ts.map +1 -0
  261. package/dist/lint/post-synth/sqlpg103.d.ts +11 -0
  262. package/dist/lint/post-synth/sqlpg103.d.ts.map +1 -0
  263. package/dist/lint/post-synth/sqlpg104.d.ts +10 -0
  264. package/dist/lint/post-synth/sqlpg104.d.ts.map +1 -0
  265. package/dist/lint/post-synth/sqlpg105.d.ts +10 -0
  266. package/dist/lint/post-synth/sqlpg105.d.ts.map +1 -0
  267. package/dist/lint/post-synth/sqlpg106.d.ts +9 -0
  268. package/dist/lint/post-synth/sqlpg106.d.ts.map +1 -0
  269. package/dist/lint/post-synth/sqlpg107.d.ts +10 -0
  270. package/dist/lint/post-synth/sqlpg107.d.ts.map +1 -0
  271. package/dist/lint/post-synth/sqlpg108.d.ts +11 -0
  272. package/dist/lint/post-synth/sqlpg108.d.ts.map +1 -0
  273. package/dist/lint/post-synth/sqlpg109.d.ts +11 -0
  274. package/dist/lint/post-synth/sqlpg109.d.ts.map +1 -0
  275. package/dist/lint/post-synth/sqlpg110.d.ts +12 -0
  276. package/dist/lint/post-synth/sqlpg110.d.ts.map +1 -0
  277. package/dist/lint/post-synth/sqlpg111.d.ts +10 -0
  278. package/dist/lint/post-synth/sqlpg111.d.ts.map +1 -0
  279. package/dist/lint/post-synth/sqlpg112.d.ts +10 -0
  280. package/dist/lint/post-synth/sqlpg112.d.ts.map +1 -0
  281. package/dist/lint/post-synth/sqlpg113.d.ts +11 -0
  282. package/dist/lint/post-synth/sqlpg113.d.ts.map +1 -0
  283. package/dist/lint/post-synth/sqlpg114.d.ts +13 -0
  284. package/dist/lint/post-synth/sqlpg114.d.ts.map +1 -0
  285. package/dist/lint/post-synth/sqlpg115.d.ts +13 -0
  286. package/dist/lint/post-synth/sqlpg115.d.ts.map +1 -0
  287. package/dist/lint/post-synth/sqlpg116.d.ts +11 -0
  288. package/dist/lint/post-synth/sqlpg116.d.ts.map +1 -0
  289. package/dist/lint/post-synth/sqlpg117.d.ts +12 -0
  290. package/dist/lint/post-synth/sqlpg117.d.ts.map +1 -0
  291. package/dist/lint/post-synth/sqlpg118.d.ts +12 -0
  292. package/dist/lint/post-synth/sqlpg118.d.ts.map +1 -0
  293. package/dist/lint/rules/index.d.ts +12 -0
  294. package/dist/lint/rules/index.d.ts.map +1 -0
  295. package/dist/lint/rules/postgres-templates.d.ts +18 -0
  296. package/dist/lint/rules/postgres-templates.d.ts.map +1 -0
  297. package/dist/lint/rules/sqlch001.d.ts +12 -0
  298. package/dist/lint/rules/sqlch001.d.ts.map +1 -0
  299. package/dist/lint/rules/sqlch002.d.ts +11 -0
  300. package/dist/lint/rules/sqlch002.d.ts.map +1 -0
  301. package/dist/lint/rules/sqlch003.d.ts +12 -0
  302. package/dist/lint/rules/sqlch003.d.ts.map +1 -0
  303. package/dist/lint/rules/sqlpg001.d.ts +16 -0
  304. package/dist/lint/rules/sqlpg001.d.ts.map +1 -0
  305. package/dist/lint/rules/sqlpg002.d.ts +12 -0
  306. package/dist/lint/rules/sqlpg002.d.ts.map +1 -0
  307. package/dist/lint/rules/sqlpg003.d.ts +16 -0
  308. package/dist/lint/rules/sqlpg003.d.ts.map +1 -0
  309. package/dist/lint/rules/sqlpg004.d.ts +21 -0
  310. package/dist/lint/rules/sqlpg004.d.ts.map +1 -0
  311. package/dist/lint/rules/templates.d.ts +23 -0
  312. package/dist/lint/rules/templates.d.ts.map +1 -0
  313. package/dist/live-dialect.d.ts +25 -0
  314. package/dist/live-dialect.d.ts.map +1 -0
  315. package/dist/lsp/catalog.d.ts +22 -0
  316. package/dist/lsp/catalog.d.ts.map +1 -0
  317. package/dist/lsp/completions.d.ts +13 -0
  318. package/dist/lsp/completions.d.ts.map +1 -0
  319. package/dist/lsp/hover.d.ts +12 -0
  320. package/dist/lsp/hover.d.ts.map +1 -0
  321. package/dist/lsp/postgres-catalog.d.ts +85 -0
  322. package/dist/lsp/postgres-catalog.d.ts.map +1 -0
  323. package/dist/lsp/postgres-template.d.ts +35 -0
  324. package/dist/lsp/postgres-template.d.ts.map +1 -0
  325. package/dist/lsp/postgres.d.ts +20 -0
  326. package/dist/lsp/postgres.d.ts.map +1 -0
  327. package/dist/lsp/refs.d.ts +8 -0
  328. package/dist/lsp/refs.d.ts.map +1 -0
  329. package/dist/lsp/registry.d.ts +4 -0
  330. package/dist/lsp/registry.d.ts.map +1 -0
  331. package/dist/lsp/template.d.ts +34 -0
  332. package/dist/lsp/template.d.ts.map +1 -0
  333. package/dist/manifest.json +8 -0
  334. package/dist/mcp/index.d.ts +13 -0
  335. package/dist/mcp/index.d.ts.map +1 -0
  336. package/dist/mcp/postgres.d.ts +32 -0
  337. package/dist/mcp/postgres.d.ts.map +1 -0
  338. package/dist/meta.json +67 -0
  339. package/dist/okf/index.md +67 -0
  340. package/dist/okf/rules/SQLCH001.md +11 -0
  341. package/dist/okf/rules/SQLCH002.md +11 -0
  342. package/dist/okf/rules/SQLCH003.md +11 -0
  343. package/dist/okf/rules/SQLCH101.md +15 -0
  344. package/dist/okf/rules/SQLCH102.md +11 -0
  345. package/dist/okf/rules/SQLCH103.md +11 -0
  346. package/dist/okf/rules/SQLCH104.md +11 -0
  347. package/dist/okf/rules/SQLCH105.md +11 -0
  348. package/dist/okf/rules/SQLCH106.md +11 -0
  349. package/dist/okf/rules/SQLCH107.md +11 -0
  350. package/dist/okf/rules/SQLCH108.md +15 -0
  351. package/dist/okf/rules/SQLCH109.md +11 -0
  352. package/dist/okf/rules/SQLCH110.md +11 -0
  353. package/dist/okf/rules/SQLCH111.md +11 -0
  354. package/dist/okf/rules/SQLCH112.md +11 -0
  355. package/dist/okf/rules/SQLCH113.md +11 -0
  356. package/dist/okf/rules/SQLCH114.md +11 -0
  357. package/dist/okf/rules/SQLCH115.md +11 -0
  358. package/dist/okf/rules/SQLCH116.md +11 -0
  359. package/dist/okf/rules/SQLCH117.md +15 -0
  360. package/dist/okf/rules/SQLCH118.md +15 -0
  361. package/dist/okf/rules/SQLCH119.md +15 -0
  362. package/dist/okf/rules/SQLCH120.md +15 -0
  363. package/dist/okf/rules/SQLPG001.md +11 -0
  364. package/dist/okf/rules/SQLPG002.md +11 -0
  365. package/dist/okf/rules/SQLPG003.md +11 -0
  366. package/dist/okf/rules/SQLPG004.md +11 -0
  367. package/dist/okf/rules/SQLPG101.md +11 -0
  368. package/dist/okf/rules/SQLPG102.md +11 -0
  369. package/dist/okf/rules/SQLPG103.md +11 -0
  370. package/dist/okf/rules/SQLPG104.md +11 -0
  371. package/dist/okf/rules/SQLPG105.md +11 -0
  372. package/dist/okf/rules/SQLPG106.md +11 -0
  373. package/dist/okf/rules/SQLPG107.md +11 -0
  374. package/dist/okf/rules/SQLPG108.md +11 -0
  375. package/dist/okf/rules/SQLPG109.md +11 -0
  376. package/dist/okf/rules/SQLPG110.md +11 -0
  377. package/dist/okf/rules/SQLPG111.md +11 -0
  378. package/dist/okf/rules/SQLPG112.md +11 -0
  379. package/dist/okf/rules/SQLPG113.md +24 -0
  380. package/dist/okf/rules/SQLPG114.md +11 -0
  381. package/dist/okf/rules/SQLPG115.md +11 -0
  382. package/dist/okf/rules/SQLPG116.md +15 -0
  383. package/dist/okf/rules/SQLPG117.md +11 -0
  384. package/dist/okf/rules/SQLPG118.md +11 -0
  385. package/dist/okf/types/Database.md +15 -0
  386. package/dist/okf/types/MaterializedView.md +14 -0
  387. package/dist/okf/types/PostgresDomain.md +13 -0
  388. package/dist/okf/types/PostgresEnum.md +13 -0
  389. package/dist/okf/types/PostgresExtension.md +13 -0
  390. package/dist/okf/types/PostgresIndex.md +9 -0
  391. package/dist/okf/types/PostgresMaterializedView.md +13 -0
  392. package/dist/okf/types/PostgresSchema.md +13 -0
  393. package/dist/okf/types/PostgresSequence.md +13 -0
  394. package/dist/okf/types/PostgresTable.md +13 -0
  395. package/dist/okf/types/PostgresView.md +13 -0
  396. package/dist/okf/types/Table.md +15 -0
  397. package/dist/okf/types/View.md +13 -0
  398. package/dist/op/activities/clickhouse-apply.d.ts +56 -0
  399. package/dist/op/activities/clickhouse-apply.d.ts.map +1 -0
  400. package/dist/op/activities/clickhouse-emulator.d.ts +26 -0
  401. package/dist/op/activities/clickhouse-emulator.d.ts.map +1 -0
  402. package/dist/op/activities/clickhouse-rebuild.d.ts +43 -0
  403. package/dist/op/activities/clickhouse-rebuild.d.ts.map +1 -0
  404. package/dist/op/activities/index.d.ts +19 -0
  405. package/dist/op/activities/index.d.ts.map +1 -0
  406. package/dist/op/activities/postgres-apply.d.ts +69 -0
  407. package/dist/op/activities/postgres-apply.d.ts.map +1 -0
  408. package/dist/op/activities/postgres-emulator.d.ts +33 -0
  409. package/dist/op/activities/postgres-emulator.d.ts.map +1 -0
  410. package/dist/op/activities/postgres-migration.d.ts +48 -0
  411. package/dist/op/activities/postgres-migration.d.ts.map +1 -0
  412. package/dist/op/activity-contracts.d.ts +464 -0
  413. package/dist/op/activity-contracts.d.ts.map +1 -0
  414. package/dist/package-cli.d.ts +3 -0
  415. package/dist/package-cli.d.ts.map +1 -0
  416. package/dist/plugin.d.ts +12 -0
  417. package/dist/plugin.d.ts.map +1 -0
  418. package/dist/postgres/apply/apply.d.ts +163 -0
  419. package/dist/postgres/apply/apply.d.ts.map +1 -0
  420. package/dist/postgres/apply/statements.d.ts +138 -0
  421. package/dist/postgres/apply/statements.d.ts.map +1 -0
  422. package/dist/postgres/catalog-types.d.ts +50 -0
  423. package/dist/postgres/catalog-types.d.ts.map +1 -0
  424. package/dist/postgres/container.d.ts +23 -0
  425. package/dist/postgres/container.d.ts.map +1 -0
  426. package/dist/postgres/entities.d.ts +322 -0
  427. package/dist/postgres/entities.d.ts.map +1 -0
  428. package/dist/postgres/entity-types.d.ts +17 -0
  429. package/dist/postgres/entity-types.d.ts.map +1 -0
  430. package/dist/postgres/import/generator.d.ts +28 -0
  431. package/dist/postgres/import/generator.d.ts.map +1 -0
  432. package/dist/postgres/import/ir.d.ts +24 -0
  433. package/dist/postgres/import/ir.d.ts.map +1 -0
  434. package/dist/postgres/import/live-export.d.ts +26 -0
  435. package/dist/postgres/import/live-export.d.ts.map +1 -0
  436. package/dist/postgres/keywords.d.ts +22 -0
  437. package/dist/postgres/keywords.d.ts.map +1 -0
  438. package/dist/postgres/live/bind.d.ts +76 -0
  439. package/dist/postgres/live/bind.d.ts.map +1 -0
  440. package/dist/postgres/live/catalog.d.ts +98 -0
  441. package/dist/postgres/live/catalog.d.ts.map +1 -0
  442. package/dist/postgres/live/client.d.ts +32 -0
  443. package/dist/postgres/live/client.d.ts.map +1 -0
  444. package/dist/postgres/live/describe-resources.d.ts +41 -0
  445. package/dist/postgres/live/describe-resources.d.ts.map +1 -0
  446. package/dist/postgres/migrate/backfill.d.ts +103 -0
  447. package/dist/postgres/migrate/backfill.d.ts.map +1 -0
  448. package/dist/postgres/migrate/batches.d.ts +90 -0
  449. package/dist/postgres/migrate/batches.d.ts.map +1 -0
  450. package/dist/postgres/migrate/carry.d.ts +196 -0
  451. package/dist/postgres/migrate/carry.d.ts.map +1 -0
  452. package/dist/postgres/migrate/handoff.d.ts +46 -0
  453. package/dist/postgres/migrate/handoff.d.ts.map +1 -0
  454. package/dist/postgres/migrate/names.d.ts +55 -0
  455. package/dist/postgres/migrate/names.d.ts.map +1 -0
  456. package/dist/postgres/migrate/observe.d.ts +139 -0
  457. package/dist/postgres/migrate/observe.d.ts.map +1 -0
  458. package/dist/postgres/migrate/op.d.ts +128 -0
  459. package/dist/postgres/migrate/op.d.ts.map +1 -0
  460. package/dist/postgres/migrate/receipts.d.ts +63 -0
  461. package/dist/postgres/migrate/receipts.d.ts.map +1 -0
  462. package/dist/postgres/migrate/replication.d.ts +80 -0
  463. package/dist/postgres/migrate/replication.d.ts.map +1 -0
  464. package/dist/postgres/migrate/steps.d.ts +225 -0
  465. package/dist/postgres/migrate/steps.d.ts.map +1 -0
  466. package/dist/postgres/overlays/columns.d.ts +6 -0
  467. package/dist/postgres/overlays/columns.d.ts.map +1 -0
  468. package/dist/postgres/overlays/constraints.d.ts +8 -0
  469. package/dist/postgres/overlays/constraints.d.ts.map +1 -0
  470. package/dist/postgres/overlays/indexes.d.ts +8 -0
  471. package/dist/postgres/overlays/indexes.d.ts.map +1 -0
  472. package/dist/postgres/overlays/kinds.d.ts +48 -0
  473. package/dist/postgres/overlays/kinds.d.ts.map +1 -0
  474. package/dist/postgres/overlays/partitioning.d.ts +5 -0
  475. package/dist/postgres/overlays/partitioning.d.ts.map +1 -0
  476. package/dist/postgres/overlays/relations.d.ts +6 -0
  477. package/dist/postgres/overlays/relations.d.ts.map +1 -0
  478. package/dist/postgres/overlays/storage.d.ts +28 -0
  479. package/dist/postgres/overlays/storage.d.ts.map +1 -0
  480. package/dist/postgres/overlays/type-ddl.d.ts +7 -0
  481. package/dist/postgres/overlays/type-ddl.d.ts.map +1 -0
  482. package/dist/postgres/overlays/types.d.ts +24 -0
  483. package/dist/postgres/overlays/types.d.ts.map +1 -0
  484. package/dist/postgres/parser.d.ts +216 -0
  485. package/dist/postgres/parser.d.ts.map +1 -0
  486. package/dist/postgres/plan/commands.d.ts +61 -0
  487. package/dist/postgres/plan/commands.d.ts.map +1 -0
  488. package/dist/postgres/plan/deep.d.ts +33 -0
  489. package/dist/postgres/plan/deep.d.ts.map +1 -0
  490. package/dist/postgres/plan/diff.d.ts +45 -0
  491. package/dist/postgres/plan/diff.d.ts.map +1 -0
  492. package/dist/postgres/plan/disruption.d.ts +14 -0
  493. package/dist/postgres/plan/disruption.d.ts.map +1 -0
  494. package/dist/postgres/plan/normalize.d.ts +108 -0
  495. package/dist/postgres/plan/normalize.d.ts.map +1 -0
  496. package/dist/postgres/plan/report.d.ts +6 -0
  497. package/dist/postgres/plan/report.d.ts.map +1 -0
  498. package/dist/postgres/plan/rules.d.ts +84 -0
  499. package/dist/postgres/plan/rules.d.ts.map +1 -0
  500. package/dist/postgres/plan/schema.d.ts +50 -0
  501. package/dist/postgres/plan/schema.d.ts.map +1 -0
  502. package/dist/postgres/plan/server-normalize.d.ts +26 -0
  503. package/dist/postgres/plan/server-normalize.d.ts.map +1 -0
  504. package/dist/postgres/providers/aurora.d.ts +12 -0
  505. package/dist/postgres/providers/aurora.d.ts.map +1 -0
  506. package/dist/postgres/providers/azure.d.ts +14 -0
  507. package/dist/postgres/providers/azure.d.ts.map +1 -0
  508. package/dist/postgres/providers/cloud-sql.d.ts +11 -0
  509. package/dist/postgres/providers/cloud-sql.d.ts.map +1 -0
  510. package/dist/postgres/providers/index.d.ts +35 -0
  511. package/dist/postgres/providers/index.d.ts.map +1 -0
  512. package/dist/postgres/providers/neon.d.ts +13 -0
  513. package/dist/postgres/providers/neon.d.ts.map +1 -0
  514. package/dist/postgres/providers/rds.d.ts +10 -0
  515. package/dist/postgres/providers/rds.d.ts.map +1 -0
  516. package/dist/postgres/providers/supabase.d.ts +12 -0
  517. package/dist/postgres/providers/supabase.d.ts.map +1 -0
  518. package/dist/postgres/providers/types.d.ts +59 -0
  519. package/dist/postgres/providers/types.d.ts.map +1 -0
  520. package/dist/postgres/testing/fake-client.d.ts +38 -0
  521. package/dist/postgres/testing/fake-client.d.ts.map +1 -0
  522. package/dist/postgres/testing/migration.d.ts +25 -0
  523. package/dist/postgres/testing/migration.d.ts.map +1 -0
  524. package/dist/postgres/testing/roundtrip-schema.d.ts +11 -0
  525. package/dist/postgres/testing/roundtrip-schema.d.ts.map +1 -0
  526. package/dist/postgres/testing/server.d.ts +17 -0
  527. package/dist/postgres/testing/server.d.ts.map +1 -0
  528. package/dist/postgres/testing/writable-server.d.ts +45 -0
  529. package/dist/postgres/testing/writable-server.d.ts.map +1 -0
  530. package/dist/postgres/tokens.d.ts +26 -0
  531. package/dist/postgres/tokens.d.ts.map +1 -0
  532. package/dist/postgres.d.ts +13 -0
  533. package/dist/postgres.d.ts.map +1 -0
  534. package/dist/rules/audit-entries.ts +29 -0
  535. package/dist/rules/clickhouse-helpers.ts +206 -0
  536. package/dist/rules/postgres-audit-entries.ts +29 -0
  537. package/dist/rules/postgres-helpers.ts +126 -0
  538. package/dist/rules/postgres-templates.ts +36 -0
  539. package/dist/rules/sql-helpers.ts +53 -0
  540. package/dist/rules/sqlch001.ts +53 -0
  541. package/dist/rules/sqlch002.ts +115 -0
  542. package/dist/rules/sqlch003.ts +68 -0
  543. package/dist/rules/sqlch101.ts +35 -0
  544. package/dist/rules/sqlch102.ts +23 -0
  545. package/dist/rules/sqlch103.ts +45 -0
  546. package/dist/rules/sqlch104.ts +42 -0
  547. package/dist/rules/sqlch105.ts +35 -0
  548. package/dist/rules/sqlch106.ts +27 -0
  549. package/dist/rules/sqlch107.ts +35 -0
  550. package/dist/rules/sqlch108.ts +27 -0
  551. package/dist/rules/sqlch109.ts +21 -0
  552. package/dist/rules/sqlch110.ts +29 -0
  553. package/dist/rules/sqlch111.ts +40 -0
  554. package/dist/rules/sqlch112.ts +30 -0
  555. package/dist/rules/sqlch113.ts +20 -0
  556. package/dist/rules/sqlch114.ts +26 -0
  557. package/dist/rules/sqlch115.ts +31 -0
  558. package/dist/rules/sqlch116.ts +22 -0
  559. package/dist/rules/sqlch117.ts +25 -0
  560. package/dist/rules/sqlch118.ts +26 -0
  561. package/dist/rules/sqlch119.ts +31 -0
  562. package/dist/rules/sqlch120.ts +21 -0
  563. package/dist/rules/sqlpg001.ts +88 -0
  564. package/dist/rules/sqlpg002.ts +68 -0
  565. package/dist/rules/sqlpg003.ts +59 -0
  566. package/dist/rules/sqlpg004.ts +73 -0
  567. package/dist/rules/sqlpg101.ts +24 -0
  568. package/dist/rules/sqlpg102.ts +30 -0
  569. package/dist/rules/sqlpg103.ts +23 -0
  570. package/dist/rules/sqlpg104.ts +23 -0
  571. package/dist/rules/sqlpg105.ts +22 -0
  572. package/dist/rules/sqlpg106.ts +22 -0
  573. package/dist/rules/sqlpg107.ts +22 -0
  574. package/dist/rules/sqlpg108.ts +27 -0
  575. package/dist/rules/sqlpg109.ts +37 -0
  576. package/dist/rules/sqlpg110.ts +33 -0
  577. package/dist/rules/sqlpg111.ts +23 -0
  578. package/dist/rules/sqlpg112.ts +25 -0
  579. package/dist/rules/sqlpg113.ts +28 -0
  580. package/dist/rules/sqlpg114.ts +37 -0
  581. package/dist/rules/sqlpg115.ts +38 -0
  582. package/dist/rules/sqlpg116.ts +25 -0
  583. package/dist/rules/sqlpg117.ts +24 -0
  584. package/dist/rules/sqlpg118.ts +22 -0
  585. package/dist/rules/templates.ts +35 -0
  586. package/dist/serializer.d.ts +37 -0
  587. package/dist/serializer.d.ts.map +1 -0
  588. package/dist/skill-defs.d.ts +3 -0
  589. package/dist/skill-defs.d.ts.map +1 -0
  590. package/dist/spec/catalog.d.ts +125 -0
  591. package/dist/spec/catalog.d.ts.map +1 -0
  592. package/dist/spec/fetch.d.ts +43 -0
  593. package/dist/spec/fetch.d.ts.map +1 -0
  594. package/dist/spec/pin.d.ts +39 -0
  595. package/dist/spec/pin.d.ts.map +1 -0
  596. package/dist/spec/postgres-catalog.d.ts +108 -0
  597. package/dist/spec/postgres-catalog.d.ts.map +1 -0
  598. package/dist/spec/postgres-fetch.d.ts +46 -0
  599. package/dist/spec/postgres-fetch.d.ts.map +1 -0
  600. package/dist/spec/postgres-pin.d.ts +67 -0
  601. package/dist/spec/postgres-pin.d.ts.map +1 -0
  602. package/dist/types/index.d.ts +4386 -0
  603. package/dist/validate-cli.d.ts +3 -0
  604. package/dist/validate-cli.d.ts.map +1 -0
  605. package/dist/validate.d.ts +15 -0
  606. package/dist/validate.d.ts.map +1 -0
  607. package/package.json +74 -4
  608. package/src/clickhouse/apply/apply.ts +288 -0
  609. package/src/clickhouse/apply/mutations.ts +90 -0
  610. package/src/clickhouse/apply/statements.ts +393 -0
  611. package/src/clickhouse/catalog-types.ts +84 -0
  612. package/src/clickhouse/container.ts +176 -0
  613. package/src/clickhouse/engine-syntax.test.ts +53 -0
  614. package/src/clickhouse/engine-syntax.ts +173 -0
  615. package/src/clickhouse/entities.test.ts +188 -0
  616. package/src/clickhouse/entities.ts +425 -0
  617. package/src/clickhouse/http.ts +76 -0
  618. package/src/clickhouse/import/generator.ts +153 -0
  619. package/src/clickhouse/import/import.test.ts +157 -0
  620. package/src/clickhouse/import/ir.ts +171 -0
  621. package/src/clickhouse/import/live-export.ts +53 -0
  622. package/src/clickhouse/import/parser.ts +27 -0
  623. package/src/clickhouse/import/roundtrip.test.ts +90 -0
  624. package/src/clickhouse/live/bind.ts +126 -0
  625. package/src/clickhouse/live/catalog.ts +96 -0
  626. package/src/clickhouse/live/describe-resources.ts +98 -0
  627. package/src/clickhouse/live/live.test.ts +143 -0
  628. package/src/clickhouse/live/roundtrip.e2e.test.ts +93 -0
  629. package/src/clickhouse/overlays/codecs.ts +68 -0
  630. package/src/clickhouse/overlays/engines.ts +108 -0
  631. package/src/clickhouse/overlays/kinds.ts +38 -0
  632. package/src/clickhouse/overlays/projections.ts +36 -0
  633. package/src/clickhouse/overlays/skip-indexes.ts +44 -0
  634. package/src/clickhouse/overlays/ttl.ts +55 -0
  635. package/src/clickhouse/overlays/types.ts +58 -0
  636. package/src/clickhouse/ownership.test.ts +20 -0
  637. package/src/clickhouse/ownership.ts +103 -0
  638. package/src/clickhouse/parser.test.ts +166 -0
  639. package/src/clickhouse/parser.ts +459 -0
  640. package/src/clickhouse/plan/commands.ts +101 -0
  641. package/src/clickhouse/plan/deep.ts +124 -0
  642. package/src/clickhouse/plan/diff.ts +203 -0
  643. package/src/clickhouse/plan/disruption.ts +61 -0
  644. package/src/clickhouse/plan/normalize.ts +352 -0
  645. package/src/clickhouse/plan/plan-wiring.test.ts +77 -0
  646. package/src/clickhouse/plan/plan.e2e.test.ts +77 -0
  647. package/src/clickhouse/plan/plan.test.ts +201 -0
  648. package/src/clickhouse/plan/rebuild-handoff.ts +59 -0
  649. package/src/clickhouse/plan/report.ts +19 -0
  650. package/src/clickhouse/plan/rules.ts +241 -0
  651. package/src/clickhouse/plan/schema.ts +56 -0
  652. package/src/clickhouse/plan/server-format.ts +39 -0
  653. package/src/clickhouse/rebuild/backfill.ts +186 -0
  654. package/src/clickhouse/rebuild/observe.ts +380 -0
  655. package/src/clickhouse/rebuild/op.ts +206 -0
  656. package/src/clickhouse/rebuild/partitions.ts +62 -0
  657. package/src/clickhouse/rebuild/rebuild-replicated.e2e.test.ts +513 -0
  658. package/src/clickhouse/rebuild/rebuild.e2e.test.ts +351 -0
  659. package/src/clickhouse/rebuild/rebuild.test.ts +190 -0
  660. package/src/clickhouse/rebuild/receipts.ts +143 -0
  661. package/src/clickhouse/rebuild/replicas.test.ts +70 -0
  662. package/src/clickhouse/rebuild/replicas.ts +148 -0
  663. package/src/clickhouse/rebuild/steps.ts +382 -0
  664. package/src/clickhouse/rebuild/verify.ts +124 -0
  665. package/src/clickhouse/testdata/NOTICE +5 -0
  666. package/src/clickhouse/testdata/clickhouse-tests-corpus.json +302 -0
  667. package/src/clickhouse/testing/fake-server.ts +65 -0
  668. package/src/clickhouse/testing/roundtrip-schema.ts +25 -0
  669. package/src/clickhouse/testing/writable-server.ts +141 -0
  670. package/src/clickhouse/tokens.ts +28 -0
  671. package/src/clickhouse.ts +63 -0
  672. package/src/codegen/classifier-page.test.ts +16 -0
  673. package/src/codegen/classifier-page.ts +76 -0
  674. package/src/codegen/clickhouse-module.test.ts +63 -0
  675. package/src/codegen/clickhouse-module.ts +269 -0
  676. package/src/codegen/docs-cli.ts +4 -0
  677. package/src/codegen/docs.ts +225 -0
  678. package/src/codegen/generate-cli.ts +13 -0
  679. package/src/codegen/generate.ts +126 -0
  680. package/src/codegen/package.ts +36 -0
  681. package/src/codegen/postgres-classifier-page.ts +81 -0
  682. package/src/codegen/postgres-module.test.ts +77 -0
  683. package/src/codegen/postgres-module.ts +434 -0
  684. package/src/codegen/registry.ts +36 -0
  685. package/src/composites/audit-log-table.ts +54 -0
  686. package/src/composites/catalog.test.ts +61 -0
  687. package/src/composites/catalog.ts +529 -0
  688. package/src/composites/cdc-mirror.ts +54 -0
  689. package/src/composites/clickhouse.ts +7 -0
  690. package/src/composites/composites.test.ts +758 -0
  691. package/src/composites/events-table.ts +49 -0
  692. package/src/composites/index.ts +9 -0
  693. package/src/composites/join-table.ts +57 -0
  694. package/src/composites/postgres.ts +7 -0
  695. package/src/composites/refreshed-view.ts +46 -0
  696. package/src/composites/replacing-table.ts +49 -0
  697. package/src/composites/rollup-view.ts +55 -0
  698. package/src/composites/sharded-table.ts +49 -0
  699. package/src/composites/soft-delete-table.ts +61 -0
  700. package/src/composites/tenant-table.ts +50 -0
  701. package/src/config.ts +157 -0
  702. package/src/core/apply.ts +153 -0
  703. package/src/core/classifier.ts +186 -0
  704. package/src/core/container.ts +93 -0
  705. package/src/core/core.test.ts +254 -0
  706. package/src/core/cursor.ts +189 -0
  707. package/src/core/diff.ts +72 -0
  708. package/src/core/entity.ts +85 -0
  709. package/src/core/find-templates.ts +158 -0
  710. package/src/core/handoff.ts +44 -0
  711. package/src/core/index.ts +61 -0
  712. package/src/core/interpolation.ts +225 -0
  713. package/src/core/normalize.ts +39 -0
  714. package/src/core/ownership.test.ts +36 -0
  715. package/src/core/ownership.ts +133 -0
  716. package/src/core/receipts.ts +29 -0
  717. package/src/core/references.ts +74 -0
  718. package/src/core/template.ts +83 -0
  719. package/src/core/testing/http-stub.ts +33 -0
  720. package/src/core/tokens.ts +252 -0
  721. package/src/coverage.ts +64 -0
  722. package/src/detect.ts +32 -0
  723. package/src/dialects.ts +21 -0
  724. package/src/generated/clickhouse-types.ts +4386 -0
  725. package/src/generated/clickhouse.ts +2476 -0
  726. package/src/generated/index.d.ts +4386 -0
  727. package/src/generated/lexicon-sql.json +67 -0
  728. package/src/generated/postgres-types.ts +1190 -0
  729. package/src/generated/postgres.ts +1039 -0
  730. package/src/import-generator.ts +18 -0
  731. package/src/index.ts +21 -0
  732. package/src/init-templates.test.ts +108 -0
  733. package/src/init-templates.ts +327 -0
  734. package/src/lint/audit-catalog.ts +73 -0
  735. package/src/lint/audit-lineage.ts +47 -0
  736. package/src/lint/post-synth/audit-entries.ts +29 -0
  737. package/src/lint/post-synth/clickhouse-checks.test.ts +278 -0
  738. package/src/lint/post-synth/clickhouse-helpers.ts +206 -0
  739. package/src/lint/post-synth/index.ts +81 -0
  740. package/src/lint/post-synth/post-synth.test.ts +33 -0
  741. package/src/lint/post-synth/postgres-audit-entries.ts +29 -0
  742. package/src/lint/post-synth/postgres-checks.test.ts +257 -0
  743. package/src/lint/post-synth/postgres-helpers.ts +126 -0
  744. package/src/lint/post-synth/sql-helpers.ts +53 -0
  745. package/src/lint/post-synth/sqlch101.ts +35 -0
  746. package/src/lint/post-synth/sqlch102.ts +23 -0
  747. package/src/lint/post-synth/sqlch103.ts +45 -0
  748. package/src/lint/post-synth/sqlch104.ts +42 -0
  749. package/src/lint/post-synth/sqlch105.ts +35 -0
  750. package/src/lint/post-synth/sqlch106.ts +27 -0
  751. package/src/lint/post-synth/sqlch107.ts +35 -0
  752. package/src/lint/post-synth/sqlch108.ts +27 -0
  753. package/src/lint/post-synth/sqlch109.ts +21 -0
  754. package/src/lint/post-synth/sqlch110.ts +29 -0
  755. package/src/lint/post-synth/sqlch111.ts +40 -0
  756. package/src/lint/post-synth/sqlch112.ts +30 -0
  757. package/src/lint/post-synth/sqlch113.ts +20 -0
  758. package/src/lint/post-synth/sqlch114.ts +26 -0
  759. package/src/lint/post-synth/sqlch115.ts +31 -0
  760. package/src/lint/post-synth/sqlch116.ts +22 -0
  761. package/src/lint/post-synth/sqlch117.ts +25 -0
  762. package/src/lint/post-synth/sqlch118.ts +26 -0
  763. package/src/lint/post-synth/sqlch119.ts +31 -0
  764. package/src/lint/post-synth/sqlch120.ts +21 -0
  765. package/src/lint/post-synth/sqlpg101.ts +24 -0
  766. package/src/lint/post-synth/sqlpg102.ts +30 -0
  767. package/src/lint/post-synth/sqlpg103.ts +23 -0
  768. package/src/lint/post-synth/sqlpg104.ts +23 -0
  769. package/src/lint/post-synth/sqlpg105.ts +22 -0
  770. package/src/lint/post-synth/sqlpg106.ts +22 -0
  771. package/src/lint/post-synth/sqlpg107.ts +22 -0
  772. package/src/lint/post-synth/sqlpg108.ts +27 -0
  773. package/src/lint/post-synth/sqlpg109.ts +37 -0
  774. package/src/lint/post-synth/sqlpg110.ts +33 -0
  775. package/src/lint/post-synth/sqlpg111.ts +23 -0
  776. package/src/lint/post-synth/sqlpg112.ts +25 -0
  777. package/src/lint/post-synth/sqlpg113.ts +28 -0
  778. package/src/lint/post-synth/sqlpg114.ts +37 -0
  779. package/src/lint/post-synth/sqlpg115.ts +38 -0
  780. package/src/lint/post-synth/sqlpg116.ts +25 -0
  781. package/src/lint/post-synth/sqlpg117.ts +24 -0
  782. package/src/lint/post-synth/sqlpg118.ts +22 -0
  783. package/src/lint/rules/index.ts +13 -0
  784. package/src/lint/rules/postgres-templates.ts +36 -0
  785. package/src/lint/rules/rules.test.ts +228 -0
  786. package/src/lint/rules/sqlch001.ts +53 -0
  787. package/src/lint/rules/sqlch002.ts +115 -0
  788. package/src/lint/rules/sqlch003.ts +68 -0
  789. package/src/lint/rules/sqlpg001.ts +88 -0
  790. package/src/lint/rules/sqlpg002.ts +68 -0
  791. package/src/lint/rules/sqlpg003.ts +59 -0
  792. package/src/lint/rules/sqlpg004.ts +73 -0
  793. package/src/lint/rules/templates.ts +35 -0
  794. package/src/live-dialect.ts +37 -0
  795. package/src/lsp/catalog.ts +60 -0
  796. package/src/lsp/completions.test.ts +111 -0
  797. package/src/lsp/completions.ts +128 -0
  798. package/src/lsp/diagnostics.test.ts +26 -0
  799. package/src/lsp/hover.test.ts +90 -0
  800. package/src/lsp/hover.ts +113 -0
  801. package/src/lsp/postgres-catalog.ts +234 -0
  802. package/src/lsp/postgres-template.ts +161 -0
  803. package/src/lsp/postgres.test.ts +150 -0
  804. package/src/lsp/postgres.ts +270 -0
  805. package/src/lsp/refs.ts +53 -0
  806. package/src/lsp/registry.ts +19 -0
  807. package/src/lsp/template.ts +166 -0
  808. package/src/mcp/index.ts +304 -0
  809. package/src/mcp/mcp.test.ts +184 -0
  810. package/src/mcp/postgres.ts +125 -0
  811. package/src/op/activities/clickhouse-apply.e2e.test.ts +150 -0
  812. package/src/op/activities/clickhouse-apply.test.ts +265 -0
  813. package/src/op/activities/clickhouse-apply.ts +113 -0
  814. package/src/op/activities/clickhouse-emulator.test.ts +23 -0
  815. package/src/op/activities/clickhouse-emulator.ts +37 -0
  816. package/src/op/activities/clickhouse-rebuild.ts +136 -0
  817. package/src/op/activities/index.ts +50 -0
  818. package/src/op/activities/postgres-apply.e2e.test.ts +184 -0
  819. package/src/op/activities/postgres-apply.test.ts +304 -0
  820. package/src/op/activities/postgres-apply.ts +170 -0
  821. package/src/op/activities/postgres-emulator.test.ts +26 -0
  822. package/src/op/activities/postgres-emulator.ts +44 -0
  823. package/src/op/activities/postgres-migration.ts +182 -0
  824. package/src/op/activity-contracts.ts +210 -0
  825. package/src/package-cli.ts +17 -0
  826. package/src/plugin.test.ts +74 -0
  827. package/src/plugin.ts +242 -0
  828. package/src/postgres/apply/apply.ts +582 -0
  829. package/src/postgres/apply/statements.test.ts +155 -0
  830. package/src/postgres/apply/statements.ts +603 -0
  831. package/src/postgres/catalog-types.ts +59 -0
  832. package/src/postgres/container.ts +72 -0
  833. package/src/postgres/entities.test.ts +170 -0
  834. package/src/postgres/entities.ts +1016 -0
  835. package/src/postgres/entity-types.ts +18 -0
  836. package/src/postgres/import/generator.ts +176 -0
  837. package/src/postgres/import/import.test.ts +71 -0
  838. package/src/postgres/import/ir.ts +67 -0
  839. package/src/postgres/import/live-export.ts +53 -0
  840. package/src/postgres/import/live-warnings.test.ts +45 -0
  841. package/src/postgres/keywords.ts +40 -0
  842. package/src/postgres/live/bind.ts +146 -0
  843. package/src/postgres/live/catalog.ts +581 -0
  844. package/src/postgres/live/client.ts +84 -0
  845. package/src/postgres/live/describe-resources.ts +111 -0
  846. package/src/postgres/live/live.test.ts +198 -0
  847. package/src/postgres/live/roundtrip.e2e.test.ts +111 -0
  848. package/src/postgres/migrate/backfill.ts +233 -0
  849. package/src/postgres/migrate/batches.e2e.test.ts +163 -0
  850. package/src/postgres/migrate/batches.test.ts +36 -0
  851. package/src/postgres/migrate/batches.ts +159 -0
  852. package/src/postgres/migrate/carry.e2e.test.ts +335 -0
  853. package/src/postgres/migrate/carry.test.ts +103 -0
  854. package/src/postgres/migrate/carry.ts +653 -0
  855. package/src/postgres/migrate/handoff.ts +73 -0
  856. package/src/postgres/migrate/kinds.e2e.test.ts +204 -0
  857. package/src/postgres/migrate/migrate.e2e.test.ts +362 -0
  858. package/src/postgres/migrate/migrate.test.ts +322 -0
  859. package/src/postgres/migrate/names.ts +93 -0
  860. package/src/postgres/migrate/observe.ts +521 -0
  861. package/src/postgres/migrate/op.ts +242 -0
  862. package/src/postgres/migrate/receipts.ts +135 -0
  863. package/src/postgres/migrate/replication.ts +151 -0
  864. package/src/postgres/migrate/steps.ts +657 -0
  865. package/src/postgres/overlays/columns.ts +34 -0
  866. package/src/postgres/overlays/constraints.ts +56 -0
  867. package/src/postgres/overlays/indexes.ts +27 -0
  868. package/src/postgres/overlays/kinds.ts +53 -0
  869. package/src/postgres/overlays/partitioning.ts +26 -0
  870. package/src/postgres/overlays/relations.ts +29 -0
  871. package/src/postgres/overlays/storage.ts +75 -0
  872. package/src/postgres/overlays/type-ddl.ts +38 -0
  873. package/src/postgres/overlays/types.ts +56 -0
  874. package/src/postgres/parser.test.ts +214 -0
  875. package/src/postgres/parser.ts +1062 -0
  876. package/src/postgres/plan/commands.ts +124 -0
  877. package/src/postgres/plan/deep.ts +177 -0
  878. package/src/postgres/plan/diff.ts +323 -0
  879. package/src/postgres/plan/disruption.ts +52 -0
  880. package/src/postgres/plan/normalize.test.ts +148 -0
  881. package/src/postgres/plan/normalize.ts +542 -0
  882. package/src/postgres/plan/plan.e2e.test.ts +117 -0
  883. package/src/postgres/plan/plan.test.ts +244 -0
  884. package/src/postgres/plan/report.ts +24 -0
  885. package/src/postgres/plan/rules.ts +276 -0
  886. package/src/postgres/plan/schema.ts +114 -0
  887. package/src/postgres/plan/server-normalize.ts +123 -0
  888. package/src/postgres/providers/aurora.ts +45 -0
  889. package/src/postgres/providers/azure.ts +54 -0
  890. package/src/postgres/providers/cloud-sql.ts +42 -0
  891. package/src/postgres/providers/index.ts +90 -0
  892. package/src/postgres/providers/neon.ts +45 -0
  893. package/src/postgres/providers/providers.test.ts +136 -0
  894. package/src/postgres/providers/rds.ts +48 -0
  895. package/src/postgres/providers/supabase.ts +46 -0
  896. package/src/postgres/providers/types.ts +70 -0
  897. package/src/postgres/testdata/NOTICE +31 -0
  898. package/src/postgres/testdata/postgres-regress-corpus.json +460 -0
  899. package/src/postgres/testing/fake-client.ts +42 -0
  900. package/src/postgres/testing/migration.ts +52 -0
  901. package/src/postgres/testing/roundtrip-schema.ts +46 -0
  902. package/src/postgres/testing/server.ts +58 -0
  903. package/src/postgres/testing/writable-server.ts +188 -0
  904. package/src/postgres/tokens.ts +46 -0
  905. package/src/postgres.ts +75 -0
  906. package/src/serializer.test.ts +128 -0
  907. package/src/serializer.ts +148 -0
  908. package/src/skill-defs.test.ts +81 -0
  909. package/src/skill-defs.ts +102 -0
  910. package/src/skills/chant-sql-plan.md +123 -0
  911. package/src/skills/chant-sql-postgres-migration.md +126 -0
  912. package/src/skills/chant-sql-postgres-plan.md +194 -0
  913. package/src/skills/chant-sql-postgres.md +165 -0
  914. package/src/skills/chant-sql-rebuild.md +68 -0
  915. package/src/skills/chant-sql.md +123 -0
  916. package/src/spec/catalog.e2e.test.ts +29 -0
  917. package/src/spec/catalog.test.ts +56 -0
  918. package/src/spec/catalog.ts +311 -0
  919. package/src/spec/clickhouse-catalog.snapshot.json +5246 -0
  920. package/src/spec/fetch.test.ts +77 -0
  921. package/src/spec/fetch.ts +112 -0
  922. package/src/spec/pin.ts +47 -0
  923. package/src/spec/postgres-catalog-14.snapshot.json +3494 -0
  924. package/src/spec/postgres-catalog-15.snapshot.json +3529 -0
  925. package/src/spec/postgres-catalog-16.snapshot.json +3597 -0
  926. package/src/spec/postgres-catalog-17.snapshot.json +3656 -0
  927. package/src/spec/postgres-catalog-18.snapshot.json +3747 -0
  928. package/src/spec/postgres-catalog.test.ts +43 -0
  929. package/src/spec/postgres-catalog.ts +301 -0
  930. package/src/spec/postgres-fetch.test.ts +75 -0
  931. package/src/spec/postgres-fetch.ts +112 -0
  932. package/src/spec/postgres-pin.test.ts +64 -0
  933. package/src/spec/postgres-pin.ts +101 -0
  934. package/src/typecheck.test.ts +104 -0
  935. package/src/validate-cli.ts +6 -0
  936. package/src/validate.ts +149 -0
@@ -0,0 +1,657 @@
1
+ /**
2
+ * The expand-and-contract migration's steps (#3281), each one convergent: it
3
+ * observes the server (`./observe.ts`), does what is left of its own part,
4
+ * and reports. Running a step twice does what running it once did.
5
+ *
6
+ * Every statement runs in a transaction with `lock_timeout` and
7
+ * `statement_timeout` set by `SET LOCAL`, as the applier's do
8
+ * (`../apply/apply.ts`), and with the declarations' schema as its
9
+ * `search_path`. A statement that waits longer than the lock timeout behind
10
+ * another session gives up instead of queueing every later query behind it,
11
+ * and its transaction is tried again a few times before the step fails.
12
+ *
13
+ * The backfill and the verification are in `./backfill.ts`; the Op that
14
+ * orders the steps is `./op.ts`.
15
+ */
16
+
17
+ import type { OwnershipMarker } from "@intentius/chant/ownership";
18
+ import { computePlanDigest } from "@intentius/chant/op";
19
+ import { carriesMarker, readTrailerPairs, stampedComment } from "../../core/ownership";
20
+ import { PostgresQueryError, type PostgresClient } from "../live/client";
21
+ import type { PostgresTarget } from "../live/bind";
22
+ import { pgString, type DeclaredPgObject } from "../apply/statements";
23
+ import { quoteIdent } from "../keywords";
24
+ import { col, migrationNames, MIGRATION_TRAILER_KEY, type MigrationNames } from "./names";
25
+ import { MigrationRefusal, observeMigration, type MigrationObservation } from "./observe";
26
+ import { postgresReceiptStore, receiptAddress } from "./receipts";
27
+ import type { ReplicationLagBound } from "./replication";
28
+ import { addCarriedConstraint, carriedNotReady, carriedSwitchStatements, requiresNotNull, SERIAL_TYPES, storedType, type CarriedObject } from "./carry";
29
+
30
+ /** What every step is given. */
31
+ export interface MigrationRun {
32
+ client: PostgresClient;
33
+ target: PostgresTarget;
34
+ /** The declared table. */
35
+ declared: DeclaredPgObject;
36
+ /** Every object the build declares: the switch makes the views that read the column again from theirs. */
37
+ objects?: readonly DeclaredPgObject[];
38
+ /** The declared column being migrated. */
39
+ column: string;
40
+ /** The type change's expression over the old row's columns. */
41
+ using?: string;
42
+ /** This project's ownership marker, stamped on every working object. */
43
+ marker?: OwnershipMarker;
44
+ /** The major the build targets. */
45
+ major?: number;
46
+ /** The width of one batch's key range. */
47
+ batchSize: number;
48
+ /** How long the old column is kept after the switch, in milliseconds. */
49
+ retainMs: number;
50
+ /** The bound on replica lag the backfill pauses for, or false for no check. */
51
+ replicationLag: ReplicationLagBound | false;
52
+ /** `lock_timeout` for every statement, in ms. */
53
+ lockTimeoutMs: number;
54
+ /** `statement_timeout` for a statement that changes only the catalog, in ms. */
55
+ statementTimeoutMs: number;
56
+ /** How many times a transaction that hit the lock timeout is tried again. Default: 5. */
57
+ lockRetries?: number;
58
+ log: (line: string) => void;
59
+ signal?: AbortSignal;
60
+ /** The run's id, recorded on the receipts it writes. */
61
+ runId?: string;
62
+ }
63
+
64
+ export const observe = (run: MigrationRun): Promise<MigrationObservation> =>
65
+ observeMigration({
66
+ client: run.client,
67
+ target: run.target,
68
+ declared: run.declared,
69
+ column: run.column,
70
+ ...(run.objects ? { objects: run.objects } : {}),
71
+ ...(run.marker ? { marker: run.marker } : {}),
72
+ ...(run.using !== undefined ? { using: run.using } : {}),
73
+ ...(run.major !== undefined ? { major: run.major } : {}),
74
+ });
75
+
76
+ /** The server's clock, in milliseconds: the retention is the server's time, not this machine's. */
77
+ export async function serverNow(client: PostgresClient): Promise<number> {
78
+ const [row] = await client.query<{ t: string }>("SELECT (EXTRACT(EPOCH FROM pg_catalog.clock_timestamp()) * 1000)::bigint::text AS t");
79
+ return Number(row?.t ?? Date.now());
80
+ }
81
+
82
+ const SQLSTATE_LOCK_NOT_AVAILABLE = "55P03";
83
+ const ms = (n: number) => `'${Math.max(0, Math.floor(n))}ms'`;
84
+
85
+ /**
86
+ * Run `body` in one transaction under the run's timeouts (`scan` lifts the
87
+ * statement timeout, for a statement that reads every row) and the
88
+ * declarations' schema as `search_path`. A lock timeout rolls it back and
89
+ * tries again, waiting a little longer each time; any other error rolls it
90
+ * back and is thrown.
91
+ */
92
+ export async function inTransaction<T>(run: MigrationRun, body: (exec: (sql: string, params?: unknown[]) => Promise<Record<string, unknown>[]>) => Promise<T>, opts: { scan?: boolean } = {}): Promise<T> {
93
+ const retries = run.lockRetries ?? 5;
94
+ for (let attempt = 0; ; attempt++) {
95
+ run.signal?.throwIfAborted();
96
+ await run.client.query("BEGIN");
97
+ try {
98
+ await run.client.query(`SET LOCAL lock_timeout = ${ms(run.lockTimeoutMs)}`);
99
+ await run.client.query(`SET LOCAL statement_timeout = ${ms(opts.scan ? 0 : run.statementTimeoutMs)}`);
100
+ await run.client.query("SELECT pg_catalog.set_config('search_path', $1, true)", [quoteIdent(run.target.defaultSchema)]);
101
+ const out = await body(async (sql, params) => {
102
+ run.signal?.throwIfAborted();
103
+ run.log(sql);
104
+ return run.client.query(sql, params);
105
+ });
106
+ await run.client.query("COMMIT");
107
+ return out;
108
+ } catch (err) {
109
+ await run.client.query("ROLLBACK").catch(() => undefined);
110
+ if (run.signal?.aborted) throw err;
111
+ if (err instanceof PostgresQueryError && err.code === SQLSTATE_LOCK_NOT_AVAILABLE && attempt < retries) {
112
+ run.log(`-- lock_timeout ${run.lockTimeoutMs}ms: another session holds a lock this transaction needs; trying again (${attempt + 1}/${retries})`);
113
+ await new Promise((r) => setTimeout(r, 250 * 2 ** attempt));
114
+ continue;
115
+ }
116
+ if (err instanceof PostgresQueryError && err.code === SQLSTATE_LOCK_NOT_AVAILABLE) {
117
+ throw new PostgresQueryError(`${err.message} (lock_timeout ${run.lockTimeoutMs}ms, tried ${retries + 1} times: another session kept a lock this step needs; SQLSTATE 55P03)`, err.code);
118
+ }
119
+ throw err;
120
+ }
121
+ }
122
+ }
123
+
124
+ /**
125
+ * Run one statement outside any transaction (`CREATE INDEX CONCURRENTLY`,
126
+ * `DROP INDEX CONCURRENTLY`), with `lock_timeout` and `statement_timeout`
127
+ * set for the session first (none for a scan). A lock timeout leaves a
128
+ * `CONCURRENTLY` build's index INVALID: `cleanup` drops it, and the statement
129
+ * is tried again as a transaction is.
130
+ */
131
+ export async function outsideTransaction(run: MigrationRun, sql: string, opts: { scan?: boolean; cleanup?: () => Promise<void> } = {}): Promise<void> {
132
+ const retries = run.lockRetries ?? 5;
133
+ for (let attempt = 0; ; attempt++) {
134
+ run.signal?.throwIfAborted();
135
+ await run.client.query(`SET lock_timeout = ${ms(run.lockTimeoutMs)}`);
136
+ await run.client.query(`SET statement_timeout = ${ms(opts.scan ? 0 : run.statementTimeoutMs)}`);
137
+ try {
138
+ run.log(sql);
139
+ await run.client.query(sql);
140
+ return;
141
+ } catch (err) {
142
+ await opts.cleanup?.().catch(() => undefined);
143
+ if (run.signal?.aborted) throw err;
144
+ if (err instanceof PostgresQueryError && err.code === SQLSTATE_LOCK_NOT_AVAILABLE && attempt < retries) {
145
+ run.log(`-- lock_timeout ${run.lockTimeoutMs}ms: another session holds a lock this statement needs; trying again (${attempt + 1}/${retries})`);
146
+ await new Promise((r) => setTimeout(r, 250 * 2 ** attempt));
147
+ continue;
148
+ }
149
+ throw err;
150
+ }
151
+ }
152
+ }
153
+
154
+ /** A working object's role: the new column, the old one after the switch, the dual write, the NOT NULL proof, a carried index or constraint. */
155
+ export type WorkingRole = "new" | "old" | "dual" | "nn" | "carry";
156
+
157
+ /** The trailer pairs a working object carries besides the marker. */
158
+ const working = (names: MigrationNames, role: WorkingRole, extra: Record<string, string> = {}) => ({ [MIGRATION_TRAILER_KEY]: names.key, role, ...extra });
159
+
160
+ /** A working object's comment: a description, then chant's trailer. */
161
+ export const workingComment = (names: MigrationNames, marker: OwnershipMarker | undefined, role: WorkingRole, text: string, extra: Record<string, string> = {}): string =>
162
+ stampedComment(`chant migration of ${names.key}: ${text}`, marker, working(names, role, extra));
163
+
164
+ const commentOnColumn = (names: MigrationNames, column: string, text: string | undefined) =>
165
+ `COMMENT ON COLUMN ${names.qualifiedTable}.${col(column)} IS ${text === undefined ? "NULL" : pgString(text)}`;
166
+
167
+ // ── expand ─────────────────────────────────────────────────────────────
168
+
169
+ export interface ExpandResult {
170
+ state: MigrationObservation["state"];
171
+ /** The column being filled. */
172
+ column: string;
173
+ added: boolean;
174
+ }
175
+
176
+ /** The new column's type: the declared one, with its collation when it declares one. */
177
+ const newColumnType = (o: MigrationObservation): string => `${o.names.change === "rename" ? o.source!.type : storedType(o.column.type)}${o.column.collate ? ` COLLATE ${o.column.collate}` : ""}`;
178
+
179
+ /**
180
+ * Expand: add the new column, nullable and with no default, which changes
181
+ * only the catalog (SQLPG201), marked as this migration's. Its NOT NULL and
182
+ * default are set at the switch, once every row has a value.
183
+ */
184
+ export async function expand(run: MigrationRun): Promise<ExpandResult> {
185
+ const o = await observe(run);
186
+ const n = o.names;
187
+ if (o.state !== "migrate") return { state: o.state, column: n.column, added: false };
188
+ if (o.newColumn) {
189
+ run.log(`-- ${n.schema}.${n.table}.${n.newColumn} is there`);
190
+ return { state: o.state, column: n.newColumn, added: false };
191
+ }
192
+ await inTransaction(run, async (exec) => {
193
+ await exec(`ALTER TABLE ${n.qualifiedTable} ADD COLUMN ${col(n.newColumn)} ${newColumnType(o)}`);
194
+ await exec(commentOnColumn(n, n.newColumn, workingComment(n, run.marker, "new", n.change === "rename" ? `the new name of ${n.source}` : `${n.column} as ${o.column.type}`)));
195
+ });
196
+ return { state: o.state, column: n.newColumn, added: true };
197
+ }
198
+
199
+ // ── dual write ─────────────────────────────────────────────────────────
200
+
201
+ /**
202
+ * The dual-write trigger function's body.
203
+ *
204
+ * A type change: the new column is computed from the row on every insert and
205
+ * update, with the same expression the backfill uses, so a write the backfill
206
+ * already passed is not missed. A value the expression cannot convert fails
207
+ * the write, as the declared column would.
208
+ *
209
+ * A rename: both columns are kept equal, each from the other, so old writers
210
+ * (the old name) and new ones (the new name) both work until the contract.
211
+ * An insert takes the new column's value when it is given and the old one's
212
+ * otherwise; an update takes whichever of the two it changed.
213
+ */
214
+ export function dualWriteBody(o: Pick<MigrationObservation, "names" | "expression">): string {
215
+ const n = o.names;
216
+ const nw = `NEW.${col(n.newColumn)}`;
217
+ const src = `NEW.${col(n.source)}`;
218
+ if (n.change === "type") {
219
+ return [`BEGIN`, ` ${nw} := (SELECT ${o.expression} FROM (SELECT NEW.*) AS ${col(n.table)});`, ` RETURN NEW;`, `END`].join("\n");
220
+ }
221
+ return [
222
+ `BEGIN`,
223
+ ` IF TG_OP = 'INSERT' THEN`,
224
+ ` IF ${nw} IS NULL THEN ${nw} := ${src}; ELSE ${src} := ${nw}; END IF;`,
225
+ ` ELSIF ${nw} IS DISTINCT FROM OLD.${col(n.newColumn)} THEN`,
226
+ ` ${src} := ${nw};`,
227
+ ` ELSE`,
228
+ ` ${nw} := ${src};`,
229
+ ` END IF;`,
230
+ ` RETURN NEW;`,
231
+ `END`,
232
+ ].join("\n");
233
+ }
234
+
235
+ /** The statements that start the dual write: the function, the trigger, their comments. */
236
+ export function dualWriteStatements(o: Pick<MigrationObservation, "names" | "expression">, marker: OwnershipMarker | undefined, defaultSchema: string): string[] {
237
+ const n = o.names;
238
+ return [
239
+ `CREATE OR REPLACE FUNCTION ${n.qualifiedFn}() RETURNS trigger LANGUAGE plpgsql SET search_path = ${quoteIdent(defaultSchema)} AS $chant$\n${dualWriteBody(o)}\n$chant$`,
240
+ `COMMENT ON FUNCTION ${n.qualifiedFn}() IS ${pgString(workingComment(n, marker, "dual", "keeps the new column written"))}`,
241
+ `DROP TRIGGER IF EXISTS ${col(n.trigger)} ON ${n.qualifiedTable}`,
242
+ `CREATE TRIGGER ${col(n.trigger)} BEFORE INSERT OR UPDATE ON ${n.qualifiedTable} FOR EACH ROW EXECUTE FUNCTION ${n.qualifiedFn}()`,
243
+ `COMMENT ON TRIGGER ${col(n.trigger)} ON ${n.qualifiedTable} IS ${pgString(workingComment(n, marker, "dual", "keeps the new column written"))}`,
244
+ ];
245
+ }
246
+
247
+ export interface DualWriteResult {
248
+ state: MigrationObservation["state"];
249
+ trigger: string;
250
+ created: boolean;
251
+ }
252
+
253
+ /**
254
+ * Dual write: the trigger that keeps the new column written from here on.
255
+ * `CREATE TRIGGER` takes SHARE ROW EXCLUSIVE on the table, which waits for
256
+ * running writes; the lock timeout bounds that wait.
257
+ */
258
+ export async function startDualWrite(run: MigrationRun): Promise<DualWriteResult> {
259
+ const o = await observe(run);
260
+ const n = o.names;
261
+ if (o.state !== "migrate") return { state: o.state, trigger: n.trigger, created: false };
262
+ if (!o.newColumn) throw new MigrationRefusal(`${n.key}: the new column is not there yet; the Expand phase adds it`);
263
+ if (o.trigger && o.fn) return { state: o.state, trigger: n.trigger, created: false };
264
+ await inTransaction(run, async (exec) => {
265
+ for (const sql of dualWriteStatements(o, run.marker, run.target.defaultSchema)) await exec(sql);
266
+ });
267
+ return { state: o.state, trigger: n.trigger, created: true };
268
+ }
269
+
270
+ // ── carry over ─────────────────────────────────────────────────────────
271
+
272
+ export interface CarryResult {
273
+ state: MigrationObservation["state"];
274
+ /** Working copies made in this run. */
275
+ built: number;
276
+ /** Working copies already there and ready. */
277
+ ready: number;
278
+ /** Views the switch makes again. */
279
+ views: number;
280
+ /** Each carried object, `<kind> <name> -> <name after the switch>`. */
281
+ carried: string[];
282
+ }
283
+
284
+ const qualifiedIndex = (c: CarriedObject, name: string) => `${quoteIdent(c.schema)}.${quoteIdent(name)}`;
285
+
286
+ /**
287
+ * Carry over: make each index and constraint on the old column again on the
288
+ * new one, under a working name (`./carry.ts`). An index (a key's too) is
289
+ * built `CONCURRENTLY`, outside any transaction, so writes go on; a build
290
+ * that failed or was killed leaves an INVALID index, which the next run
291
+ * drops and builds again. A check or a foreign key is added `NOT VALID` with
292
+ * its comment in one transaction, then validated under SHARE UPDATE
293
+ * EXCLUSIVE. Runs after the backfill, so every row has its new value.
294
+ */
295
+ export async function carryOver(run: MigrationRun): Promise<CarryResult> {
296
+ const o = await observe(run);
297
+ const result: CarryResult = { state: o.state, built: 0, ready: 0, views: o.views.length, carried: [] };
298
+ if (o.state !== "migrate") return result;
299
+ const n = o.names;
300
+ if (!o.newColumn || !o.trigger) throw new MigrationRefusal(`${n.key}: the new column and its dual write are not there; the Expand and Dual write phases make them`);
301
+ // Indexes first: a foreign key onto the new column needs the working unique index it references.
302
+ const indexesFirst = [...o.carried].sort((a, b) => Number(a.kind !== "index" && a.kind !== "key") - Number(b.kind !== "index" && b.kind !== "key"));
303
+ for (const c of indexesFirst) {
304
+ result.carried.push(`${c.kind} ${c.tableName}.${c.name} -> ${c.target}`);
305
+ const state = o.carriedStates.get(c.working);
306
+ const comment = workingComment(n, run.marker, "carry", `${c.kind} ${c.name} on the new column`, { of: c.name });
307
+ if (c.kind === "index" || c.kind === "key") {
308
+ const ident = qualifiedIndex(c, c.working);
309
+ if (state?.ready) {
310
+ if (!state.marked) await inTransaction(run, (exec) => exec(`COMMENT ON INDEX ${ident} IS ${pgString(comment)}`));
311
+ result.ready++;
312
+ continue;
313
+ }
314
+ if (state?.present) await outsideTransaction(run, `DROP INDEX CONCURRENTLY IF EXISTS ${ident}`);
315
+ const dropInvalid = async () => {
316
+ const [row] = await run.client.query<{ invalid: boolean }>("SELECT NOT i.indisvalid AS invalid FROM pg_catalog.pg_index i WHERE i.indexrelid = pg_catalog.to_regclass($1)", [ident]);
317
+ if (row?.invalid) await run.client.query(`DROP INDEX CONCURRENTLY IF EXISTS ${ident}`);
318
+ };
319
+ await outsideTransaction(run, c.definition, { scan: true, cleanup: dropInvalid });
320
+ await inTransaction(run, (exec) => exec(`COMMENT ON INDEX ${ident} IS ${pgString(comment)}`));
321
+ result.built++;
322
+ continue;
323
+ }
324
+ if (state?.ready) {
325
+ result.ready++;
326
+ continue;
327
+ }
328
+ if (!state?.present) {
329
+ await inTransaction(run, async (exec) => {
330
+ await exec(addCarriedConstraint(c));
331
+ await exec(`COMMENT ON CONSTRAINT ${quoteIdent(c.working)} ON ${c.table} IS ${pgString(comment)}`);
332
+ });
333
+ }
334
+ if (c.validated) await inTransaction(run, (exec) => exec(`ALTER TABLE ${c.table} VALIDATE CONSTRAINT ${quoteIdent(c.working)}`), { scan: true });
335
+ result.built++;
336
+ }
337
+ if (o.carried.length > 0 || o.views.length > 0) {
338
+ run.log(`-- ${n.key}: ${o.carried.length} index(es) and constraint(s) on the new column (${result.built} made, ${result.ready} already there); ${o.views.length} view(s) made again at the switch`);
339
+ }
340
+ return result;
341
+ }
342
+
343
+ // ── switch ─────────────────────────────────────────────────────────────
344
+
345
+ export interface SwitchResult {
346
+ state: MigrationObservation["state"];
347
+ switched: boolean;
348
+ /** Where the old column is kept, and until when. */
349
+ oldColumn?: string;
350
+ retainUntil?: string;
351
+ }
352
+
353
+ /**
354
+ * The statements of the switch's one transaction. A type change swaps the
355
+ * columns by name, so readers of the column read the new one from the
356
+ * commit on, and stops writing the old one, which is kept as it was. A
357
+ * rename has nothing to swap: readers move to the new name in the
358
+ * application, and the trigger keeps both columns written until the
359
+ * contract, so a reader still on the old name goes on working.
360
+ */
361
+ /** Where the old column's sequence stood when the switch took its lock: what the moved identity carries on from. */
362
+ export interface SequenceState {
363
+ lastValue: string;
364
+ isCalled: boolean;
365
+ }
366
+
367
+ /**
368
+ * The statements that move the old column's sequence to the new one, after
369
+ * the columns are swapped. An identity cannot be handed from one column to
370
+ * another, so the old one is dropped (`DROP IDENTITY`, before the swap, which
371
+ * drops its sequence) and the new column gets one under the same sequence
372
+ * name, with the declared options, set to where the old one stood. A
373
+ * `serial` column's sequence is handed over with `OWNED BY`, takes the
374
+ * declared integer type, and becomes the new column's default.
375
+ */
376
+ function sequenceStatements(o: MigrationObservation, state: SequenceState | undefined): { before: string[]; after: string[] } {
377
+ const seq = o.sequence;
378
+ const n = o.names;
379
+ const t = n.qualifiedTable;
380
+ if (!seq || n.change !== "type") return { before: [], after: [] };
381
+ if (seq.kind === "identity") {
382
+ if (!state) throw new Error(`${n.key}: the switch moves the identity of ${n.source} and needs its sequence's state, read under the switch's lock`);
383
+ const g = o.column.generated;
384
+ const options = [`SEQUENCE NAME ${seq.ident}`, ...(g?.options ? [g.options.trim().replace(/^\(|\)$/g, "")] : [])].join(" ");
385
+ return {
386
+ before: [`ALTER TABLE ${t} ALTER COLUMN ${col(n.source)} DROP IDENTITY`],
387
+ after: [
388
+ `ALTER TABLE ${t} ALTER COLUMN ${col(n.column)} ADD GENERATED ${g?.always === false ? "BY DEFAULT" : "ALWAYS"} AS IDENTITY (${options})`,
389
+ `SELECT pg_catalog.setval(${pgString(seq.ident)}, ${BigInt(state.lastValue).toString()}, ${state.isCalled ? "true" : "false"})`,
390
+ ],
391
+ };
392
+ }
393
+ const intType = SERIAL_TYPES[o.column.type ?? ""];
394
+ return {
395
+ before: [],
396
+ after: [
397
+ ...(intType ? [`ALTER SEQUENCE ${seq.ident} AS ${intType}`] : []),
398
+ `ALTER SEQUENCE ${seq.ident} OWNED BY ${t}.${col(n.column)}`,
399
+ ...(intType ? [`ALTER TABLE ${t} ALTER COLUMN ${col(n.column)} SET DEFAULT pg_catalog.nextval(${pgString(seq.ident)}::pg_catalog.regclass)`] : []),
400
+ ],
401
+ };
402
+ }
403
+
404
+ export function switchStatements(o: MigrationObservation, marker: OwnershipMarker | undefined, retainUntil: string, sequenceState?: SequenceState): string[] {
405
+ const n = o.names;
406
+ const t = n.qualifiedTable;
407
+ const declared = o.column;
408
+ const oldComment = workingComment(n, marker, "old", `the old ${n.change === "rename" ? "name" : "column"}, kept until ${retainUntil}`, { "retain-until": retainUntil });
409
+ const carried = carriedSwitchStatements(
410
+ o.carried,
411
+ o.views,
412
+ n.change,
413
+ (c) => workingComment(n, marker, "old", `the old ${c.kind} ${c.name}, on ${n.oldColumn} until the contract drops it`, { of: c.name }),
414
+ marker,
415
+ );
416
+ const sequence = sequenceStatements(o, sequenceState);
417
+ const out: string[] = [];
418
+ if (requiresNotNull(declared, o.carried)) out.push(`ALTER TABLE ${t} ALTER COLUMN ${col(n.newColumn)} SET NOT NULL`);
419
+ if (o.check) out.push(`ALTER TABLE ${t} DROP CONSTRAINT ${col(n.check)}`);
420
+ if (n.change === "type") {
421
+ out.push(`DROP TRIGGER ${col(n.trigger)} ON ${t}`);
422
+ out.push(...carried.before);
423
+ out.push(...sequence.before);
424
+ if (o.source!.notNull) out.push(`ALTER TABLE ${t} ALTER COLUMN ${col(n.source)} DROP NOT NULL`);
425
+ if (o.source!.default !== undefined) out.push(`ALTER TABLE ${t} ALTER COLUMN ${col(n.source)} DROP DEFAULT`);
426
+ out.push(`ALTER TABLE ${t} RENAME COLUMN ${col(n.source)} TO ${col(n.oldColumn)}`);
427
+ out.push(`ALTER TABLE ${t} RENAME COLUMN ${col(n.newColumn)} TO ${col(n.column)}`);
428
+ if (declared.default !== undefined) out.push(`ALTER TABLE ${t} ALTER COLUMN ${col(n.column)} SET DEFAULT ${declared.default}`);
429
+ out.push(...sequence.after);
430
+ out.push(commentOnColumn(n, n.column, declared.comment));
431
+ out.push(commentOnColumn(n, n.oldColumn, oldComment));
432
+ out.push(`DROP FUNCTION ${n.qualifiedFn}()`);
433
+ } else {
434
+ out.push(...carried.before);
435
+ out.push(commentOnColumn(n, n.column, declared.comment));
436
+ out.push(commentOnColumn(n, n.oldColumn, oldComment));
437
+ }
438
+ out.push(...carried.after);
439
+ return out;
440
+ }
441
+
442
+ /**
443
+ * Switch, once the gate has approved the verified plan. A declared NOT NULL
444
+ * is proven first by a check added NOT VALID and then validated, which reads
445
+ * the table under SHARE UPDATE EXCLUSIVE while reads and writes go on, so
446
+ * `SET NOT NULL` in the switch is a catalog change (since 12). Then the
447
+ * switch runs in one short transaction under the lock timeout.
448
+ */
449
+ export async function switchColumns(run: MigrationRun): Promise<SwitchResult> {
450
+ const o = await observe(run);
451
+ const n = o.names;
452
+ if (o.state === "done") return { state: o.state, switched: false };
453
+ if (o.state === "switched") return { state: o.state, switched: false, oldColumn: n.oldColumn, ...retention(o) };
454
+ if (!o.newColumn || !o.trigger || !o.fn) throw new MigrationRefusal(`${n.key}: the new column and its dual write are not there; the Expand and Dual write phases make them`);
455
+ const notReady = carriedNotReady(o.carried, o.carriedStates);
456
+ if (notReady.length > 0) {
457
+ throw new MigrationRefusal(`${n.key}: ${notReady.map((c) => `${c.kind} ${c.working}`).join(", ")} on the new column is not there or not yet valid; the Carry over phase makes them`);
458
+ }
459
+ const notNull = requiresNotNull(o.column, o.carried);
460
+
461
+ if (notNull && !o.newColumn.notNull) {
462
+ if (!o.check) {
463
+ await inTransaction(run, async (exec) => {
464
+ await exec(`ALTER TABLE ${n.qualifiedTable} ADD CONSTRAINT ${col(n.check)} CHECK (${col(n.newColumn)} IS NOT NULL) NOT VALID`);
465
+ await exec(`COMMENT ON CONSTRAINT ${col(n.check)} ON ${n.qualifiedTable} IS ${pgString(workingComment(n, run.marker, "nn", `proves ${n.newColumn} NOT NULL`))}`);
466
+ });
467
+ }
468
+ if (!o.check?.validated) {
469
+ await inTransaction(run, (exec) => exec(`ALTER TABLE ${n.qualifiedTable} VALIDATE CONSTRAINT ${col(n.check)}`), { scan: true });
470
+ }
471
+ }
472
+ const retainUntil = new Date((await serverNow(run.client)) + run.retainMs).toISOString();
473
+ const withCheck = { ...o, check: o.check ?? (notNull && !o.newColumn.notNull ? { name: n.check, validated: true } : undefined) } as MigrationObservation;
474
+ await inTransaction(run, async (exec) => {
475
+ let state: SequenceState | undefined;
476
+ if (o.sequence?.kind === "identity" && n.change === "type") {
477
+ // Writers wait from here, so the sequence's position read next is where the moved identity carries on.
478
+ await exec(`LOCK TABLE ${n.qualifiedTable} IN ACCESS EXCLUSIVE MODE`);
479
+ const [row] = await exec(`SELECT last_value::text AS last, is_called AS called FROM ${o.sequence.ident}`);
480
+ state = { lastValue: String(row?.last), isCalled: row?.called === true };
481
+ }
482
+ for (const sql of switchStatements(withCheck, run.marker, retainUntil, state)) await exec(sql);
483
+ });
484
+ return { state: "switched", switched: true, oldColumn: n.oldColumn, retainUntil };
485
+ }
486
+
487
+ // ── retain and contract ────────────────────────────────────────────────
488
+
489
+ function retention(o: MigrationObservation): { retainUntil?: string } {
490
+ const until = o.old?.pairs?.get("retain-until");
491
+ return until ? { retainUntil: until } : {};
492
+ }
493
+
494
+ export interface RetainResult {
495
+ state: MigrationObservation["state"];
496
+ /** `schema.table.column`, the old column while it is kept. */
497
+ oldColumn?: string;
498
+ retainUntil?: string;
499
+ /** The retention date has passed. */
500
+ due: boolean;
501
+ /** What the contract gate approves: this old column, by its table's oid and attribute number, and its date. Absent when there is nothing to drop. */
502
+ contractDigest?: string;
503
+ }
504
+
505
+ /** Where the old column is kept and until when, and the digest the contract gate binds. */
506
+ export async function retainPlan(run: MigrationRun): Promise<RetainResult> {
507
+ const o = await observe(run);
508
+ if (!o.old) return { state: o.state, due: false };
509
+ const retainUntil = o.old.pairs?.get("retain-until");
510
+ const due = retainUntil !== undefined && (await serverNow(run.client)) >= Date.parse(retainUntil);
511
+ const oldColumn = `${o.names.schema}.${o.names.table}.${o.old.name}`;
512
+ return {
513
+ state: o.state,
514
+ oldColumn,
515
+ ...(retainUntil ? { retainUntil } : {}),
516
+ due,
517
+ contractDigest: computePlanDigest("postgres-migration-contract", { migration: o.names.key, table: o.oid, column: o.old.name, attnum: o.old.attnum, retainUntil: retainUntil ?? null }),
518
+ };
519
+ }
520
+
521
+ export interface ContractResult {
522
+ state: MigrationObservation["state"];
523
+ dropped: boolean;
524
+ oldColumn?: string;
525
+ retainUntil?: string;
526
+ }
527
+
528
+ /** The receipt address prefix of one migration's batches. */
529
+ export const batchPrefix = (identity: { stack?: string; env?: string }, key: string): string => receiptAddress(identity, `migrate/${key}/`);
530
+
531
+ export const identityOf = (marker: OwnershipMarker | undefined): { stack?: string; env?: string } => ({
532
+ ...(marker?.stack ? { stack: marker.stack } : {}),
533
+ ...(marker?.env ? { env: marker.env } : {}),
534
+ });
535
+
536
+ /**
537
+ * Contract, once the retention date has passed and the gate approved it:
538
+ * drop the old column, and for a rename the trigger and function that kept
539
+ * it written, in one transaction under the lock timeout (`DROP COLUMN` is a
540
+ * catalog change under ACCESS EXCLUSIVE). The migration's receipts go with
541
+ * them. Before the date, say until when and drop nothing.
542
+ */
543
+ export async function contract(run: MigrationRun): Promise<ContractResult> {
544
+ const plan = await retainPlan(run);
545
+ if (!plan.oldColumn) return { state: plan.state, dropped: false };
546
+ if (!plan.due) {
547
+ run.log(`-- ${plan.oldColumn} is kept until ${plan.retainUntil}; a run after that drops it`);
548
+ return { state: plan.state, dropped: false, oldColumn: plan.oldColumn, ...(plan.retainUntil ? { retainUntil: plan.retainUntil } : {}) };
549
+ }
550
+ const o = await observe(run);
551
+ const n = o.names;
552
+ await inTransaction(run, async (exec) => {
553
+ if (o.trigger) await exec(`DROP TRIGGER ${col(n.trigger)} ON ${n.qualifiedTable}`);
554
+ if (o.fn) await exec(`DROP FUNCTION ${n.qualifiedFn}()`);
555
+ await exec(`ALTER TABLE ${n.qualifiedTable} DROP COLUMN ${col(o.old!.name)}`);
556
+ });
557
+ await postgresReceiptStore(run.client, n.schema, identityOf(run.marker)).forget(batchPrefix(identityOf(run.marker), n.key));
558
+ return { state: "done", dropped: true, oldColumn: plan.oldColumn };
559
+ }
560
+
561
+ // ── onFailure ──────────────────────────────────────────────────────────
562
+
563
+ export interface CompensateResult {
564
+ dropped: string[];
565
+ }
566
+
567
+ /**
568
+ * onFailure: drop what the expand added, and nothing else: the trigger, its
569
+ * function, the NOT NULL check, the carried indexes and constraints (another
570
+ * table's foreign key onto the new column first, which would keep the column
571
+ * from being dropped) and the new column, each only when its
572
+ * comment names this migration and its role and carries this project's
573
+ * marker, and the migration's receipts. After the switch nothing is undone:
574
+ * the old column is kept (`role=old`) and the next run finishes the
575
+ * migration; the contract gate decides when the old column goes.
576
+ *
577
+ * It reads the server directly rather than through the observation, which
578
+ * may be what refused and failed the run.
579
+ */
580
+ export async function compensate(run: Pick<MigrationRun, "client" | "target" | "declared" | "column" | "marker" | "log" | "signal" | "lockTimeoutMs" | "statementTimeoutMs" | "lockRetries">): Promise<CompensateResult> {
581
+ const schema = run.declared.canonical.schema ?? run.target.defaultSchema;
582
+ const table = run.declared.canonical.name;
583
+ const n = migrationNames(schema, table, run.column, "type", run.column);
584
+ const ours = (comment: string | null | undefined, role: string) => {
585
+ const pairs = readTrailerPairs(comment ?? undefined);
586
+ return pairs?.get(MIGRATION_TRAILER_KEY) === n.key && pairs.get("role") === role && carriesMarker(comment ?? undefined, run.marker);
587
+ };
588
+ const [rel] = await run.client.query<{ oid: string | null }>("SELECT pg_catalog.to_regclass($1)::oid::text AS oid", [n.qualifiedTable]);
589
+ if (!rel?.oid) return { dropped: [] };
590
+ const cols = await run.client.query<{ name: string; comment: string | null }>(
591
+ "SELECT a.attname AS name, pg_catalog.col_description(a.attrelid, a.attnum) AS comment FROM pg_catalog.pg_attribute a WHERE a.attrelid = $1::oid AND a.attnum > 0 AND NOT a.attisdropped",
592
+ [rel.oid],
593
+ );
594
+ if (cols.some((c) => ours(c.comment, "old"))) {
595
+ run.log(`-- ${n.key} has been switched; onFailure leaves it for the next run to finish`);
596
+ return { dropped: [] };
597
+ }
598
+ const [trig] = await run.client.query<{ comment: string | null }>(
599
+ "SELECT pg_catalog.obj_description(t.oid, 'pg_trigger') AS comment FROM pg_catalog.pg_trigger t WHERE t.tgrelid = $1::oid AND t.tgname = $2",
600
+ [rel.oid, n.trigger],
601
+ );
602
+ const [fn] = await run.client.query<{ comment: string | null }>(
603
+ "SELECT pg_catalog.obj_description(p.oid, 'pg_proc') AS comment FROM pg_catalog.pg_proc p JOIN pg_catalog.pg_namespace s ON s.oid = p.pronamespace WHERE s.nspname = $1 AND p.proname = $2 AND p.pronargs = 0",
604
+ [schema, n.fn],
605
+ );
606
+ const checks = await run.client.query<{ name: string; comment: string | null }>(
607
+ "SELECT c.conname AS name, pg_catalog.obj_description(c.oid, 'pg_constraint') AS comment FROM pg_catalog.pg_constraint c WHERE c.conrelid = $1::oid",
608
+ [rel.oid],
609
+ );
610
+ const newColumns = cols.filter((c) => ours(c.comment, "new")).map((c) => c.name);
611
+ const nn = checks.filter((c) => ours(c.comment, "nn")).map((c) => c.name);
612
+ // Carried constraints, this table's and those of tables whose foreign keys were carried onto the new column.
613
+ const carriedConstraints = (
614
+ await run.client.query<{ name: string; rel: string; comment: string | null }>(
615
+ `SELECT k.conname AS name, k.conrelid::pg_catalog.regclass::text AS rel, pg_catalog.obj_description(k.oid, 'pg_constraint') AS comment
616
+ FROM pg_catalog.pg_constraint k WHERE pg_catalog.strpos(pg_catalog.obj_description(k.oid, 'pg_constraint'), $1) > 0 ORDER BY k.conrelid = $2::oid, k.conname`,
617
+ [`${MIGRATION_TRAILER_KEY}=`, rel.oid],
618
+ )
619
+ ).filter((c) => ours(c.comment, "carry"));
620
+ const carriedIndexes = (
621
+ await run.client.query<{ name: string; comment: string | null }>(
622
+ "SELECT i.indexrelid::pg_catalog.regclass::text AS name, pg_catalog.obj_description(i.indexrelid, 'pg_class') AS comment FROM pg_catalog.pg_index i WHERE i.indrelid = $1::oid ORDER BY 1",
623
+ [rel.oid],
624
+ )
625
+ ).filter((c) => ours(c.comment, "carry"));
626
+ const dropped: string[] = [];
627
+ const full: MigrationRun = { ...(run as MigrationRun), batchSize: 0, retainMs: 0, replicationLag: false };
628
+ await inTransaction(full, async (exec) => {
629
+ if (trig && ours(trig.comment, "dual")) {
630
+ await exec(`DROP TRIGGER ${col(n.trigger)} ON ${n.qualifiedTable}`);
631
+ dropped.push(`trigger ${n.trigger}`);
632
+ }
633
+ if (fn && ours(fn.comment, "dual")) {
634
+ await exec(`DROP FUNCTION ${n.qualifiedFn}()`);
635
+ dropped.push(`function ${schema}.${n.fn}`);
636
+ }
637
+ for (const c of nn) {
638
+ await exec(`ALTER TABLE ${n.qualifiedTable} DROP CONSTRAINT ${col(c)}`);
639
+ dropped.push(`constraint ${c}`);
640
+ }
641
+ for (const c of carriedConstraints) {
642
+ await exec(`ALTER TABLE ${c.rel} DROP CONSTRAINT ${col(c.name)}`);
643
+ dropped.push(`constraint ${c.name} on ${c.rel}`);
644
+ }
645
+ for (const c of carriedIndexes) {
646
+ await exec(`DROP INDEX ${c.name}`);
647
+ dropped.push(`index ${c.name}`);
648
+ }
649
+ for (const c of newColumns) {
650
+ await exec(`ALTER TABLE ${n.qualifiedTable} DROP COLUMN ${col(c)}`);
651
+ dropped.push(`column ${schema}.${table}.${c}`);
652
+ }
653
+ });
654
+ const forgotten = await postgresReceiptStore(run.client, schema, identityOf(run.marker)).forget(batchPrefix(identityOf(run.marker), n.key));
655
+ if (forgotten > 0) dropped.push(`${forgotten} receipt(s)`);
656
+ return { dropped };
657
+ }