@intentius/chant-lexicon-sql 0.124.46 → 0.124.49

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 (402) hide show
  1. package/dist/change-set.d.ts +1 -1
  2. package/dist/change-set.d.ts.map +1 -1
  3. package/dist/change-set.js +2 -1
  4. package/dist/clickhouse/apply/statements.d.ts +9 -0
  5. package/dist/clickhouse/apply/statements.d.ts.map +1 -1
  6. package/dist/clickhouse/apply/statements.js +24 -0
  7. package/dist/clickhouse/import/live-export.d.ts +7 -3
  8. package/dist/clickhouse/import/live-export.d.ts.map +1 -1
  9. package/dist/clickhouse/import/live-export.js +21 -5
  10. package/dist/clickhouse/live/named-collections.d.ts +27 -0
  11. package/dist/clickhouse/live/named-collections.d.ts.map +1 -0
  12. package/dist/clickhouse/live/named-collections.js +53 -0
  13. package/dist/clickhouse/live/undeclarable.d.ts +15 -3
  14. package/dist/clickhouse/live/undeclarable.d.ts.map +1 -1
  15. package/dist/clickhouse/live/undeclarable.js +18 -4
  16. package/dist/clickhouse/named-collections.d.ts +83 -0
  17. package/dist/clickhouse/named-collections.d.ts.map +1 -0
  18. package/dist/clickhouse/named-collections.js +203 -0
  19. package/dist/clickhouse/parser.d.ts.map +1 -1
  20. package/dist/clickhouse/parser.js +1 -1
  21. package/dist/clickhouse/plan/commands.d.ts +2 -1
  22. package/dist/clickhouse/plan/commands.d.ts.map +1 -1
  23. package/dist/clickhouse/plan/commands.js +17 -2
  24. package/dist/clickhouse/plan/diff.d.ts +15 -0
  25. package/dist/clickhouse/plan/diff.d.ts.map +1 -1
  26. package/dist/clickhouse/plan/diff.js +43 -1
  27. package/dist/clickhouse/plan/disruption.d.ts.map +1 -1
  28. package/dist/clickhouse/plan/disruption.js +5 -0
  29. package/dist/clickhouse/plan/rebuild-handoff.d.ts.map +1 -1
  30. package/dist/clickhouse/plan/rebuild-handoff.js +4 -0
  31. package/dist/clickhouse/plan/report.d.ts.map +1 -1
  32. package/dist/clickhouse/plan/report.js +6 -1
  33. package/dist/clickhouse/plan/rules.d.ts +5 -1
  34. package/dist/clickhouse/plan/rules.d.ts.map +1 -1
  35. package/dist/clickhouse/plan/rules.js +7 -3
  36. package/dist/clickhouse/plan/statements.d.ts +29 -0
  37. package/dist/clickhouse/plan/statements.d.ts.map +1 -0
  38. package/dist/clickhouse/plan/statements.js +334 -0
  39. package/dist/clickhouse/plan/stream.d.ts +40 -0
  40. package/dist/clickhouse/plan/stream.d.ts.map +1 -0
  41. package/dist/clickhouse/plan/stream.js +107 -0
  42. package/dist/clickhouse/rebuild/observe.d.ts +3 -1
  43. package/dist/clickhouse/rebuild/observe.d.ts.map +1 -1
  44. package/dist/clickhouse/rebuild/observe.js +14 -1
  45. package/dist/clickhouse/review-catalog.d.ts +213 -0
  46. package/dist/clickhouse/review-catalog.d.ts.map +1 -0
  47. package/dist/clickhouse/review-catalog.js +330 -0
  48. package/dist/codegen/classifier-page.d.ts.map +1 -1
  49. package/dist/codegen/classifier-page.js +44 -4
  50. package/dist/codegen/clickhouse-module.d.ts.map +1 -1
  51. package/dist/codegen/clickhouse-module.js +3 -0
  52. package/dist/codegen/coverage-page.d.ts.map +1 -1
  53. package/dist/codegen/coverage-page.js +5 -3
  54. package/dist/codegen/docs.js +1 -1
  55. package/dist/codegen/postgres-classifier-page.js +2 -2
  56. package/dist/codegen/registry.d.ts.map +1 -1
  57. package/dist/codegen/registry.js +10 -0
  58. package/dist/composites/catalog.d.ts.map +1 -1
  59. package/dist/composites/catalog.js +100 -0
  60. package/dist/composites/clickhouse.d.ts +2 -0
  61. package/dist/composites/clickhouse.d.ts.map +1 -1
  62. package/dist/composites/clickhouse.js +2 -0
  63. package/dist/composites/otel-tables.d.ts +100 -0
  64. package/dist/composites/otel-tables.d.ts.map +1 -0
  65. package/dist/composites/otel-tables.js +282 -0
  66. package/dist/composites/stream-ingest.d.ts +63 -0
  67. package/dist/composites/stream-ingest.d.ts.map +1 -0
  68. package/dist/composites/stream-ingest.js +39 -0
  69. package/dist/core/statement-class.d.ts +55 -0
  70. package/dist/core/statement-class.d.ts.map +1 -0
  71. package/dist/core/statement-class.js +43 -0
  72. package/dist/coverage/clickhouse.json +1 -1
  73. package/dist/coverage/postgres.json +12 -12
  74. package/dist/coverage.d.ts +16 -6
  75. package/dist/coverage.d.ts.map +1 -1
  76. package/dist/coverage.js +10 -5
  77. package/dist/drizzle-command.d.ts +17 -0
  78. package/dist/drizzle-command.d.ts.map +1 -0
  79. package/dist/drizzle-command.js +91 -0
  80. package/dist/drizzle.d.ts +70 -0
  81. package/dist/drizzle.d.ts.map +1 -0
  82. package/dist/drizzle.js +689 -0
  83. package/dist/files/clickhouse.d.ts.map +1 -1
  84. package/dist/files/clickhouse.js +8 -1
  85. package/dist/files/common.d.ts +13 -0
  86. package/dist/files/common.d.ts.map +1 -1
  87. package/dist/files/common.js +5 -0
  88. package/dist/files/postgres.d.ts.map +1 -1
  89. package/dist/files/postgres.js +35 -3
  90. package/dist/generated/clickhouse.d.ts +2 -0
  91. package/dist/generated/clickhouse.d.ts.map +1 -1
  92. package/dist/generated/clickhouse.js +2 -0
  93. package/dist/import-parser.d.ts +21 -1
  94. package/dist/import-parser.d.ts.map +1 -1
  95. package/dist/import-parser.js +79 -5
  96. package/dist/index.d.ts +1 -1
  97. package/dist/index.d.ts.map +1 -1
  98. package/dist/index.js +1 -1
  99. package/dist/integrity.json +7 -6
  100. package/dist/lint/post-synth/audit-entries.d.ts.map +1 -1
  101. package/dist/lint/post-synth/audit-entries.js +1 -0
  102. package/dist/lint/post-synth/index.d.ts.map +1 -1
  103. package/dist/lint/post-synth/index.js +2 -0
  104. package/dist/lint/post-synth/postgres-names.d.ts.map +1 -1
  105. package/dist/lint/post-synth/postgres-names.js +3 -0
  106. package/dist/lint/post-synth/sqlch128.d.ts +18 -0
  107. package/dist/lint/post-synth/sqlch128.d.ts.map +1 -0
  108. package/dist/lint/post-synth/sqlch128.js +222 -0
  109. package/dist/lint/rules/postgres-templates.js +2 -2
  110. package/dist/lsp/postgres-template.d.ts.map +1 -1
  111. package/dist/lsp/postgres-template.js +21 -0
  112. package/dist/manifest.json +1 -1
  113. package/dist/mcp/postgres.js +1 -1
  114. package/dist/meta.json +50 -0
  115. package/dist/migrate/from-postgres/detect.d.ts +4 -0
  116. package/dist/migrate/from-postgres/detect.d.ts.map +1 -0
  117. package/dist/migrate/from-postgres/detect.js +7 -0
  118. package/dist/migrate/from-postgres/emit.d.ts +26 -0
  119. package/dist/migrate/from-postgres/emit.d.ts.map +1 -0
  120. package/dist/migrate/from-postgres/emit.js +86 -0
  121. package/dist/migrate/from-postgres/index.d.ts +51 -0
  122. package/dist/migrate/from-postgres/index.d.ts.map +1 -0
  123. package/dist/migrate/from-postgres/index.js +115 -0
  124. package/dist/migrate/from-postgres/translate.d.ts +73 -0
  125. package/dist/migrate/from-postgres/translate.d.ts.map +1 -0
  126. package/dist/migrate/from-postgres/translate.js +261 -0
  127. package/dist/migrate/from-postgres/types.d.ts +51 -0
  128. package/dist/migrate/from-postgres/types.d.ts.map +1 -0
  129. package/dist/migrate/from-postgres/types.js +211 -0
  130. package/dist/migration-classify.d.ts +23 -0
  131. package/dist/migration-classify.d.ts.map +1 -0
  132. package/dist/migration-classify.js +44 -0
  133. package/dist/migration-replay.d.ts +73 -0
  134. package/dist/migration-replay.d.ts.map +1 -0
  135. package/dist/migration-replay.js +294 -0
  136. package/dist/okf/index.md +11 -0
  137. package/dist/okf/rules/SQLCH128.md +11 -0
  138. package/dist/okf/types/PostgresForeignDataWrapper.md +9 -0
  139. package/dist/okf/types/PostgresForeignServer.md +9 -0
  140. package/dist/okf/types/PostgresForeignTable.md +9 -0
  141. package/dist/okf/types/PostgresOperator.md +9 -0
  142. package/dist/okf/types/PostgresOperatorClass.md +9 -0
  143. package/dist/okf/types/PostgresOperatorFamily.md +9 -0
  144. package/dist/okf/types/PostgresPublication.md +9 -0
  145. package/dist/okf/types/PostgresStatistics.md +9 -0
  146. package/dist/okf/types/PostgresTextSearchConfiguration.md +9 -0
  147. package/dist/okf/types/PostgresTextSearchDictionary.md +9 -0
  148. package/dist/op/activities/postgres-migration.d.ts.map +1 -1
  149. package/dist/op/activities/postgres-migration.js +4 -0
  150. package/dist/op/activity-contracts.d.ts +20 -0
  151. package/dist/op/activity-contracts.d.ts.map +1 -1
  152. package/dist/op/activity-contracts.js +2 -0
  153. package/dist/plugin.d.ts.map +1 -1
  154. package/dist/plugin.js +49 -2
  155. package/dist/postgres/access/acl.js +1 -1
  156. package/dist/postgres/access/import.js +1 -1
  157. package/dist/postgres/apply/apply.js +13 -1
  158. package/dist/postgres/apply/statements.d.ts.map +1 -1
  159. package/dist/postgres/apply/statements.js +243 -4
  160. package/dist/postgres/constraint-names.d.ts +30 -0
  161. package/dist/postgres/constraint-names.d.ts.map +1 -0
  162. package/dist/postgres/constraint-names.js +72 -0
  163. package/dist/postgres/entities.d.ts +229 -2
  164. package/dist/postgres/entities.d.ts.map +1 -1
  165. package/dist/postgres/entities.js +326 -5
  166. package/dist/postgres/entity-types.d.ts +10 -0
  167. package/dist/postgres/entity-types.d.ts.map +1 -1
  168. package/dist/postgres/entity-types.js +10 -0
  169. package/dist/postgres/import/generator.d.ts.map +1 -1
  170. package/dist/postgres/import/generator.js +65 -2
  171. package/dist/postgres/import/live-export.d.ts.map +1 -1
  172. package/dist/postgres/import/live-export.js +2 -0
  173. package/dist/postgres/live/catalog-kinds.d.ts +20 -0
  174. package/dist/postgres/live/catalog-kinds.d.ts.map +1 -1
  175. package/dist/postgres/live/catalog-kinds.js +452 -0
  176. package/dist/postgres/live/catalog.d.ts +2 -0
  177. package/dist/postgres/live/catalog.d.ts.map +1 -1
  178. package/dist/postgres/live/catalog.js +3 -1
  179. package/dist/postgres/live/describe-resources.d.ts.map +1 -1
  180. package/dist/postgres/live/describe-resources.js +12 -2
  181. package/dist/postgres/migrate/backfill.d.ts +2 -0
  182. package/dist/postgres/migrate/backfill.d.ts.map +1 -1
  183. package/dist/postgres/migrate/backfill.js +7 -1
  184. package/dist/postgres/migrate/carry.d.ts +45 -1
  185. package/dist/postgres/migrate/carry.d.ts.map +1 -1
  186. package/dist/postgres/migrate/carry.js +72 -8
  187. package/dist/postgres/migrate/observe.d.ts +28 -4
  188. package/dist/postgres/migrate/observe.d.ts.map +1 -1
  189. package/dist/postgres/migrate/observe.js +45 -13
  190. package/dist/postgres/migrate/op.d.ts +26 -1
  191. package/dist/postgres/migrate/op.d.ts.map +1 -1
  192. package/dist/postgres/migrate/op.js +3 -1
  193. package/dist/postgres/migrate/replication.d.ts +42 -0
  194. package/dist/postgres/migrate/replication.d.ts.map +1 -1
  195. package/dist/postgres/migrate/replication.js +53 -0
  196. package/dist/postgres/migrate/steps.d.ts +35 -2
  197. package/dist/postgres/migrate/steps.d.ts.map +1 -1
  198. package/dist/postgres/migrate/steps.js +158 -12
  199. package/dist/postgres/parser.d.ts +144 -1
  200. package/dist/postgres/parser.d.ts.map +1 -1
  201. package/dist/postgres/parser.js +370 -4
  202. package/dist/postgres/plan/deep.d.ts.map +1 -1
  203. package/dist/postgres/plan/deep.js +43 -4
  204. package/dist/postgres/plan/diff.d.ts.map +1 -1
  205. package/dist/postgres/plan/diff.js +154 -1
  206. package/dist/postgres/plan/normalize.d.ts +28 -2
  207. package/dist/postgres/plan/normalize.d.ts.map +1 -1
  208. package/dist/postgres/plan/normalize.js +260 -1
  209. package/dist/postgres/plan/rules.d.ts +4 -0
  210. package/dist/postgres/plan/rules.d.ts.map +1 -1
  211. package/dist/postgres/plan/rules.js +6 -2
  212. package/dist/postgres/plan/schema.js +1 -1
  213. package/dist/postgres/plan/statements.d.ts +26 -0
  214. package/dist/postgres/plan/statements.d.ts.map +1 -0
  215. package/dist/postgres/plan/statements.js +364 -0
  216. package/dist/postgres/secret-options.d.ts +10 -0
  217. package/dist/postgres/secret-options.d.ts.map +1 -0
  218. package/dist/postgres/secret-options.js +9 -0
  219. package/dist/postgres/testing/roundtrip-schema.d.ts +4 -2
  220. package/dist/postgres/testing/roundtrip-schema.d.ts.map +1 -1
  221. package/dist/postgres/testing/roundtrip-schema.js +24 -1
  222. package/dist/postgres.d.ts +1 -1
  223. package/dist/postgres.d.ts.map +1 -1
  224. package/dist/postgres.js +1 -1
  225. package/dist/rules/audit-entries.ts +1 -0
  226. package/dist/rules/postgres-names.ts +2 -0
  227. package/dist/rules/postgres-templates.ts +2 -2
  228. package/dist/rules/sqlch128.ts +230 -0
  229. package/dist/serializer.d.ts +5 -0
  230. package/dist/serializer.d.ts.map +1 -1
  231. package/dist/serializer.js +13 -2
  232. package/dist/sql-types-command.d.ts +13 -0
  233. package/dist/sql-types-command.d.ts.map +1 -1
  234. package/dist/sql-types-command.js +31 -16
  235. package/dist/sql-types.d.ts +22 -0
  236. package/dist/sql-types.d.ts.map +1 -1
  237. package/dist/sql-types.js +10 -6
  238. package/dist/sqlserver/lexer.d.ts +37 -0
  239. package/dist/sqlserver/lexer.d.ts.map +1 -0
  240. package/dist/sqlserver/lexer.js +254 -0
  241. package/dist/sqlserver/parse.d.ts +185 -0
  242. package/dist/sqlserver/parse.d.ts.map +1 -0
  243. package/dist/sqlserver/parse.js +767 -0
  244. package/dist/sqlserver/translate.d.ts +34 -0
  245. package/dist/sqlserver/translate.d.ts.map +1 -0
  246. package/dist/sqlserver/translate.js +495 -0
  247. package/dist/sqlserver/types.d.ts +44 -0
  248. package/dist/sqlserver/types.d.ts.map +1 -0
  249. package/dist/sqlserver/types.js +133 -0
  250. package/dist/sqlserver/validate.d.ts +31 -0
  251. package/dist/sqlserver/validate.d.ts.map +1 -0
  252. package/dist/sqlserver/validate.js +67 -0
  253. package/dist/validate.d.ts.map +1 -1
  254. package/dist/validate.js +10 -0
  255. package/package.json +2 -2
  256. package/src/change-set.ts +2 -1
  257. package/src/clickhouse/apply/statements.ts +25 -0
  258. package/src/clickhouse/import/live-export.ts +20 -5
  259. package/src/clickhouse/live/named-collections.e2e.test.ts +88 -0
  260. package/src/clickhouse/live/named-collections.ts +61 -0
  261. package/src/clickhouse/live/undeclarable.e2e.test.ts +5 -3
  262. package/src/clickhouse/live/undeclarable.ts +20 -4
  263. package/src/clickhouse/named-collections.test.ts +187 -0
  264. package/src/clickhouse/named-collections.ts +224 -0
  265. package/src/clickhouse/parser.ts +2 -1
  266. package/src/clickhouse/plan/commands.ts +17 -2
  267. package/src/clickhouse/plan/diff.ts +57 -1
  268. package/src/clickhouse/plan/disruption.ts +5 -0
  269. package/src/clickhouse/plan/rebuild-handoff.ts +3 -0
  270. package/src/clickhouse/plan/report.ts +6 -1
  271. package/src/clickhouse/plan/rules.ts +14 -4
  272. package/src/clickhouse/plan/statements.test.ts +61 -0
  273. package/src/clickhouse/plan/statements.ts +306 -0
  274. package/src/clickhouse/plan/stream-s3queue.e2e.test.ts +148 -0
  275. package/src/clickhouse/plan/stream.test.ts +237 -0
  276. package/src/clickhouse/plan/stream.ts +111 -0
  277. package/src/clickhouse/rebuild/observe.ts +15 -1
  278. package/src/clickhouse/review-catalog.test.ts +181 -0
  279. package/src/clickhouse/review-catalog.ts +489 -0
  280. package/src/codegen/classifier-page.ts +44 -4
  281. package/src/codegen/clickhouse-module.ts +3 -0
  282. package/src/codegen/coverage-page.ts +5 -3
  283. package/src/codegen/docs.ts +1 -1
  284. package/src/codegen/postgres-classifier-page.ts +2 -2
  285. package/src/codegen/registry.ts +10 -0
  286. package/src/composites/catalog.test.ts +6 -1
  287. package/src/composites/catalog.ts +100 -0
  288. package/src/composites/clickhouse.ts +2 -0
  289. package/src/composites/composites.test.ts +1 -1
  290. package/src/composites/otel-tables.test.ts +118 -0
  291. package/src/composites/otel-tables.ts +339 -0
  292. package/src/composites/stream-ingest.test.ts +114 -0
  293. package/src/composites/stream-ingest.ts +82 -0
  294. package/src/core/statement-class.ts +88 -0
  295. package/src/core/undeclarable.test.ts +6 -5
  296. package/src/coverage/clickhouse.json +1 -1
  297. package/src/coverage/postgres.json +12 -12
  298. package/src/coverage.test.ts +27 -2
  299. package/src/coverage.ts +18 -7
  300. package/src/drizzle-command.ts +94 -0
  301. package/src/drizzle-kit.e2e.test.ts +89 -0
  302. package/src/drizzle-types.e2e.test.ts +67 -0
  303. package/src/drizzle.test.ts +358 -0
  304. package/src/drizzle.ts +742 -0
  305. package/src/files/clickhouse.ts +8 -1
  306. package/src/files/common.ts +14 -1
  307. package/src/files/postgres.ts +34 -3
  308. package/src/generated/clickhouse.ts +3 -0
  309. package/src/generated/lexicon-sql.json +50 -0
  310. package/src/import-parser.sqlserver.test.ts +92 -0
  311. package/src/import-parser.ts +79 -5
  312. package/src/index.ts +1 -1
  313. package/src/lint/post-synth/audit-entries.ts +1 -0
  314. package/src/lint/post-synth/index.ts +2 -0
  315. package/src/lint/post-synth/postgres-checks.test.ts +8 -1
  316. package/src/lint/post-synth/postgres-names.ts +2 -0
  317. package/src/lint/post-synth/sqlch128.test.ts +107 -0
  318. package/src/lint/post-synth/sqlch128.ts +230 -0
  319. package/src/lint/rules/postgres-templates.ts +2 -2
  320. package/src/lsp/postgres-template.ts +20 -0
  321. package/src/mcp/postgres.ts +1 -1
  322. package/src/migrate/from-postgres/cli.test.ts +165 -0
  323. package/src/migrate/from-postgres/detect.ts +7 -0
  324. package/src/migrate/from-postgres/emit.ts +96 -0
  325. package/src/migrate/from-postgres/example.test.ts +205 -0
  326. package/src/migrate/from-postgres/index.ts +122 -0
  327. package/src/migrate/from-postgres/translate.test.ts +242 -0
  328. package/src/migrate/from-postgres/translate.ts +359 -0
  329. package/src/migrate/from-postgres/types.test.ts +116 -0
  330. package/src/migrate/from-postgres/types.ts +236 -0
  331. package/src/migrate/from-postgres/validate.e2e.test.ts +44 -0
  332. package/src/migrate/from-postgres/workspace.e2e.test.ts +114 -0
  333. package/src/migration-classify.test.ts +150 -0
  334. package/src/migration-classify.ts +45 -0
  335. package/src/migration-replay.e2e.test.ts +155 -0
  336. package/src/migration-replay.test.ts +173 -0
  337. package/src/migration-replay.ts +289 -0
  338. package/src/op/__snapshots__/watch-pipeline.test.ts.snap +2 -2
  339. package/src/op/activities/postgres-migration.ts +4 -0
  340. package/src/op/activity-contracts.ts +2 -0
  341. package/src/op/watch-pipeline.test.ts +8 -1
  342. package/src/plugin.ts +51 -2
  343. package/src/postgres/access/acl.ts +1 -1
  344. package/src/postgres/access/import.ts +1 -1
  345. package/src/postgres/apply/apply.ts +14 -1
  346. package/src/postgres/apply/statements.ts +225 -4
  347. package/src/postgres/constraint-names.ts +71 -0
  348. package/src/postgres/database-kinds.test.ts +865 -0
  349. package/src/postgres/entities.ts +541 -5
  350. package/src/postgres/entity-types.ts +10 -0
  351. package/src/postgres/import/generator.ts +54 -2
  352. package/src/postgres/import/live-export.ts +1 -0
  353. package/src/postgres/live/catalog-kinds.ts +494 -0
  354. package/src/postgres/live/catalog.ts +6 -1
  355. package/src/postgres/live/database-kinds.e2e.test.ts +164 -0
  356. package/src/postgres/live/describe-resources.ts +13 -2
  357. package/src/postgres/live/undeclarable.e2e.test.ts +13 -6
  358. package/src/postgres/migrate/backfill.ts +13 -1
  359. package/src/postgres/migrate/carry.ts +103 -8
  360. package/src/postgres/migrate/followups.e2e.test.ts +218 -0
  361. package/src/postgres/migrate/followups.test.ts +199 -0
  362. package/src/postgres/migrate/kinds.e2e.test.ts +5 -5
  363. package/src/postgres/migrate/observe.ts +56 -15
  364. package/src/postgres/migrate/op.ts +28 -1
  365. package/src/postgres/migrate/partition.e2e.test.ts +129 -0
  366. package/src/postgres/migrate/partition.test.ts +206 -0
  367. package/src/postgres/migrate/replication.ts +66 -0
  368. package/src/postgres/migrate/steps.ts +157 -12
  369. package/src/postgres/migrate/subscriber.e2e.test.ts +141 -0
  370. package/src/postgres/migrate/subscriber.test.ts +59 -0
  371. package/src/postgres/parser.ts +455 -4
  372. package/src/postgres/plan/deep.ts +42 -4
  373. package/src/postgres/plan/diff.ts +137 -1
  374. package/src/postgres/plan/normalize.ts +277 -1
  375. package/src/postgres/plan/rules.ts +32 -4
  376. package/src/postgres/plan/schema.ts +1 -1
  377. package/src/postgres/plan/statements.test.ts +78 -0
  378. package/src/postgres/plan/statements.ts +299 -0
  379. package/src/postgres/secret-options.ts +10 -0
  380. package/src/postgres/testing/roundtrip-schema.ts +24 -1
  381. package/src/postgres.ts +33 -0
  382. package/src/serializer.ts +13 -2
  383. package/src/skills/chant-sql-postgres-migration.md +4 -3
  384. package/src/skills/chant-sql-postgres.md +11 -1
  385. package/src/skills/chant-sql.md +2 -1
  386. package/src/sql-files.test.ts +33 -0
  387. package/src/sql-types-command.ts +38 -16
  388. package/src/sql-types.ts +11 -6
  389. package/src/sqlserver/fixture.test.ts +186 -0
  390. package/src/sqlserver/import-cli.test.ts +61 -0
  391. package/src/sqlserver/lexer.ts +260 -0
  392. package/src/sqlserver/parse.ts +865 -0
  393. package/src/sqlserver/translate.test.ts +396 -0
  394. package/src/sqlserver/translate.ts +558 -0
  395. package/src/sqlserver/types.test.ts +102 -0
  396. package/src/sqlserver/types.ts +154 -0
  397. package/src/sqlserver/validate.e2e.test.ts +32 -0
  398. package/src/sqlserver/validate.test.ts +49 -0
  399. package/src/sqlserver/validate.ts +76 -0
  400. package/src/validate.ts +10 -0
  401. package/src/workspace-kinds.test.ts +11 -0
  402. package/workspace-kinds.json +100 -2
@@ -10,6 +10,7 @@
10
10
  * | On the old column | Before the switch | In the switch's transaction |
11
11
  * |---|---|---|
12
12
  * | an index | `CREATE INDEX CONCURRENTLY` on the new column | the old one dropped (a type change) or kept as `<name>__chant_old` (a rename), the new one renamed to the name |
13
+ * | an index on a partitioned table | `CREATE INDEX ... ON ONLY` the table, `CONCURRENTLY` on each partition, `ALTER INDEX ... ATTACH PARTITION` | as an index; the partitions' indexes go with the old one |
13
14
  * | a primary key or unique constraint | its unique index built `CONCURRENTLY` | the old constraint dropped (or a rename's unique one kept as `__chant_old`), `ADD CONSTRAINT ... USING INDEX` |
14
15
  * | a check or foreign key, this table's or another's that references the column | added `NOT VALID`, then `VALIDATE` | the old one dropped, the new one renamed to the name |
15
16
  * | a view (and the views that read it) | nothing | dropped, then created again from its declaration once the columns are swapped, with its grants and owner |
@@ -33,7 +34,8 @@
33
34
  * key or index the build declares on the new column takes the declared name.
34
35
  *
35
36
  * Refused, each named with what to do: exclusion constraints and constraint
36
- * triggers (no `USING INDEX` form), materialized views (made again only by
37
+ * triggers (no `USING INDEX` form), a key or foreign key on a partitioned table,
38
+ * a partitioned index over a foreign-table partition, materialized views (made again only by
37
39
  * a full scan in the switch), rules, triggers, policies and statistics on the
38
40
  * column, a generated column computed from it, an INVALID index on it, a view
39
41
  * the build does not declare, a view something other than a view depends on.
@@ -77,6 +79,12 @@ export interface CarriedObject {
77
79
  indexComment?: string;
78
80
  replicaIdentity?: boolean;
79
81
  clustered?: boolean;
82
+ /**
83
+ * An index on a partitioned table (#3333): `definition` is the `CREATE INDEX ... ON ONLY` that makes the
84
+ * partitioned index without building anything. Each partition's index is built `CONCURRENTLY` on its own and
85
+ * attached (`partitionIndexStatement`, `carryPartitionedIndex` in `./steps.ts`).
86
+ */
87
+ partitioned?: boolean;
80
88
  }
81
89
  /** A view on the old column (or on such a view), made again at the switch from its declaration. */
82
90
  export interface CarriedView {
@@ -130,6 +138,38 @@ export declare function replaceInForeignKey(def: string, from: string, to: strin
130
138
  * the `CONCURRENTLY` build of `working` on the new column.
131
139
  */
132
140
  export declare function carriedIndexStatement(def: string, working: string, from: string, to: string): string;
141
+ /**
142
+ * A partitioned index (`pg_get_indexdef` prints it `ON ONLY`) as the
143
+ * `CREATE INDEX ... ON ONLY` of `working` on the new column: it builds nothing
144
+ * and stays INVALID until every partition's index is attached.
145
+ */
146
+ export declare function carriedPartitionedIndexStatement(def: string, working: string, from: string, to: string): string;
147
+ /** One table of a partition tree. */
148
+ export interface PartitionNode {
149
+ oid: string;
150
+ schema: string;
151
+ name: string;
152
+ /** Quoted and qualified. */
153
+ ident: string;
154
+ /** The partitioned table (or partition) it is a partition of; absent for the root. */
155
+ parent?: string;
156
+ /** Not partitioned further: the tables that hold rows. */
157
+ leaf: boolean;
158
+ /** `r` (ordinary), `p` (partitioned) or `f` (foreign). */
159
+ kind: string;
160
+ level: number;
161
+ }
162
+ /** The partition tree under a partitioned table, the table itself first (level 0). */
163
+ export declare function partitionTree(client: Pick<PostgresClient, "query">, tableOid: string): Promise<PartitionNode[]>;
164
+ /** The name of the index a partitioned index's working copy has on one partition. */
165
+ export declare const partitionIndexName: (partition: Pick<PartitionNode, "name">, working: string) => string;
166
+ /**
167
+ * The statement that makes a partitioned index's working copy on one
168
+ * partition. A partition that is partitioned further gets `ON ONLY` (it is
169
+ * valid once its own partitions are attached); one that holds rows gets the
170
+ * `CONCURRENTLY` build, so writes go on.
171
+ */
172
+ export declare function partitionIndexStatement(c: Pick<CarriedObject, "definition">, node: Pick<PartitionNode, "ident" | "leaf">, indexName: string): string;
133
173
  /**
134
174
  * The name Postgres gives an object it names after its columns
135
175
  * (`users_email_key`, `orders_user_id_fkey`, `users_email_idx`), when `name`
@@ -149,7 +189,11 @@ interface DiscoverInput {
149
189
  defaultSchema: string;
150
190
  /** The table is partitioned: its indexes cannot be built CONCURRENTLY, nor its keys attached USING INDEX. */
151
191
  partitioned?: boolean;
192
+ /** A rename keeps the column's sequence on the old column until the contract (`defaultAtContract`), instead of being refused. */
193
+ keepSequence?: boolean;
152
194
  }
195
+ /** The sequence that belongs to a column (an identity's, or a `serial`'s), if it has one. */
196
+ export declare function columnSequence(client: PostgresClient, tableOid: string, attnum: number): Promise<ColumnSequence | undefined>;
153
197
  /** What uses the column the values come from, sorted into what the Op carries over and what it refuses. */
154
198
  export declare function discoverDependents(input: DiscoverInput): Promise<Dependents>;
155
199
  /** `ALTER TABLE ... ADD CONSTRAINT <working> <body> NOT VALID`: a check or foreign key on the new column. */
@@ -1 +1 @@
1
- {"version":3,"file":"carry.d.ts","sourceRoot":"","sources":["../../../src/postgres/migrate/carry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"carry.d.ts","sourceRoot":"","sources":["../../../src/postgres/migrate/carry.ts"],"names":[],"mappings":"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"}
@@ -10,6 +10,7 @@
10
10
  * | On the old column | Before the switch | In the switch's transaction |
11
11
  * |---|---|---|
12
12
  * | an index | `CREATE INDEX CONCURRENTLY` on the new column | the old one dropped (a type change) or kept as `<name>__chant_old` (a rename), the new one renamed to the name |
13
+ * | an index on a partitioned table | `CREATE INDEX ... ON ONLY` the table, `CONCURRENTLY` on each partition, `ALTER INDEX ... ATTACH PARTITION` | as an index; the partitions' indexes go with the old one |
13
14
  * | a primary key or unique constraint | its unique index built `CONCURRENTLY` | the old constraint dropped (or a rename's unique one kept as `__chant_old`), `ADD CONSTRAINT ... USING INDEX` |
14
15
  * | a check or foreign key, this table's or another's that references the column | added `NOT VALID`, then `VALIDATE` | the old one dropped, the new one renamed to the name |
15
16
  * | a view (and the views that read it) | nothing | dropped, then created again from its declaration once the columns are swapped, with its grants and owner |
@@ -33,7 +34,8 @@
33
34
  * key or index the build declares on the new column takes the declared name.
34
35
  *
35
36
  * Refused, each named with what to do: exclusion constraints and constraint
36
- * triggers (no `USING INDEX` form), materialized views (made again only by
37
+ * triggers (no `USING INDEX` form), a key or foreign key on a partitioned table,
38
+ * a partitioned index over a foreign-table partition, materialized views (made again only by
37
39
  * a full scan in the switch), rules, triggers, policies and statistics on the
38
40
  * column, a generated column computed from it, an INVALID index on it, a view
39
41
  * the build does not declare, a view something other than a view depends on.
@@ -120,6 +122,53 @@ export function carriedIndexStatement(def, working, from, to) {
120
122
  throw new Error(`unexpected index definition: ${def}`);
121
123
  return `CREATE ${m[1] ?? ""}INDEX CONCURRENTLY ${quoteIdent(working)} ON ${replaceColumn(m[2], from, to)}`;
122
124
  }
125
+ /**
126
+ * A partitioned index (`pg_get_indexdef` prints it `ON ONLY`) as the
127
+ * `CREATE INDEX ... ON ONLY` of `working` on the new column: it builds nothing
128
+ * and stays INVALID until every partition's index is attached.
129
+ */
130
+ export function carriedPartitionedIndexStatement(def, working, from, to) {
131
+ const m = /^CREATE (UNIQUE )?INDEX (?:"(?:[^"]|"")+"|\S+) ON (?:ONLY )?(.*)$/s.exec(def);
132
+ if (!m)
133
+ throw new Error(`unexpected index definition: ${def}`);
134
+ return `CREATE ${m[1] ?? ""}INDEX ${quoteIdent(working)} ON ONLY ${replaceColumn(m[2], from, to)}`;
135
+ }
136
+ /** The partition tree under a partitioned table, the table itself first (level 0). */
137
+ export async function partitionTree(client, tableOid) {
138
+ const rows = await client.query(`SELECT t.relid::oid::text AS oid, n.nspname AS schema, c.relname AS name, t.parentrelid::oid::text AS parent, t.isleaf AS leaf, c.relkind::text AS kind, t.level
139
+ FROM pg_catalog.pg_partition_tree($1::oid::pg_catalog.regclass) t JOIN pg_catalog.pg_class c ON c.oid = t.relid JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
140
+ ORDER BY t.level, n.nspname, c.relname`, [tableOid]);
141
+ return rows.map((r) => ({
142
+ oid: String(r.oid),
143
+ schema: r.schema,
144
+ name: r.name,
145
+ ident: `${quoteIdent(r.schema)}.${quoteIdent(r.name)}`,
146
+ ...(r.parent !== null ? { parent: String(r.parent) } : {}),
147
+ leaf: r.leaf === true,
148
+ kind: r.kind,
149
+ level: Number(r.level),
150
+ }));
151
+ }
152
+ /** The name of the index a partitioned index's working copy has on one partition. */
153
+ export const partitionIndexName = (partition, working) => pgName(`${partition.name}_${working}`);
154
+ /**
155
+ * The statement that makes a partitioned index's working copy on one
156
+ * partition. A partition that is partitioned further gets `ON ONLY` (it is
157
+ * valid once its own partitions are attached); one that holds rows gets the
158
+ * `CONCURRENTLY` build, so writes go on.
159
+ */
160
+ export function partitionIndexStatement(c, node, indexName) {
161
+ const m = /^CREATE (UNIQUE )?INDEX (?:"(?:[^"]|"")+"|\S+) ON ONLY (.*)$/s.exec(c.definition);
162
+ if (!m)
163
+ throw new Error(`unexpected partitioned index definition: ${c.definition}`);
164
+ const using = m[2].indexOf(" USING ");
165
+ if (using < 0)
166
+ throw new Error(`unexpected partitioned index definition: ${c.definition}`);
167
+ const tail = m[2].slice(using);
168
+ return node.leaf
169
+ ? `CREATE ${m[1] ?? ""}INDEX CONCURRENTLY ${quoteIdent(indexName)} ON ${node.ident}${tail}`
170
+ : `CREATE ${m[1] ?? ""}INDEX ${quoteIdent(indexName)} ON ONLY ${node.ident}${tail}`;
171
+ }
123
172
  /**
124
173
  * The name Postgres gives an object it names after its columns
125
174
  * (`users_email_key`, `orders_user_id_fkey`, `users_email_idx`), when `name`
@@ -134,6 +183,15 @@ export function renamedDefault(name, table, oldCols, newCols, suffix) {
134
183
  return Buffer.byteLength(next, "utf8") <= 63 && next !== name ? next : undefined;
135
184
  }
136
185
  const sameColumns = (a, b) => a.length === b.length && a.every((c, i) => c === b[i]);
186
+ /** The sequence that belongs to a column (an identity's, or a `serial`'s), if it has one. */
187
+ export async function columnSequence(client, tableOid, attnum) {
188
+ const [row] = await client.query(`SELECT n.nspname AS schema, c.relname AS name, d.deptype::text AS deptype
189
+ FROM pg_catalog.pg_depend d JOIN pg_catalog.pg_class c ON c.oid = d.objid AND d.classid = 'pg_catalog.pg_class'::pg_catalog.regclass JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
190
+ WHERE d.refclassid = 'pg_catalog.pg_class'::pg_catalog.regclass AND d.refobjid = $1::oid AND d.refobjsubid = $2 AND d.deptype IN ('a', 'i') AND c.relkind = 'S'`, [tableOid, attnum]);
191
+ if (!row)
192
+ return undefined;
193
+ return { kind: row.deptype === "i" ? "identity" : "serial", schema: row.schema, name: row.name, ident: `${quoteIdent(row.schema)}.${quoteIdent(row.name)}` };
194
+ }
137
195
  /** What uses the column the values come from, sorted into what the Op carries over and what it refuses. */
138
196
  export async function discoverDependents(input) {
139
197
  const { client, names: n, oid, attnum } = input;
@@ -251,10 +309,6 @@ export async function discoverDependents(input) {
251
309
  if (kind === "i" || kind === "I") {
252
310
  if (keyIndexes.has(String(r.oid)))
253
311
  continue;
254
- if (kind === "I") {
255
- refused.push(`index ${r.schema}.${name} is a partitioned index, which cannot be built CONCURRENTLY; drop it, migrate, then declare it again (chant #3333)`);
256
- continue;
257
- }
258
312
  if (r.valid !== true) {
259
313
  refused.push(`index ${r.schema}.${name} is INVALID (a failed CONCURRENTLY build); drop it, or REINDEX it, first`);
260
314
  continue;
@@ -277,6 +331,14 @@ export async function discoverDependents(input) {
277
331
  });
278
332
  target = declaredIndex?.canonical.name ?? (r.has_exprs === true ? undefined : renamedDefault(name, table, oldCols, cols, "idx")) ?? name;
279
333
  }
334
+ if (kind === "I") {
335
+ // A partition the index cannot be built on (a foreign table) stops the carry before anything is made.
336
+ const foreign = (await partitionTree(client, oid)).filter((p) => p.kind === "f");
337
+ if (foreign.length > 0) {
338
+ refused.push(`partitioned index ${r.schema}.${name}: ${foreign.map((p) => `${p.schema}.${p.name}`).join(", ")} is a foreign table, which holds no index to attach; drop the index, migrate, then declare it again`);
339
+ continue;
340
+ }
341
+ }
280
342
  carried.push({
281
343
  kind: "index",
282
344
  name,
@@ -286,7 +348,8 @@ export async function discoverDependents(input) {
286
348
  schema: String(r.schema),
287
349
  working,
288
350
  target,
289
- definition: carriedIndexStatement(String(r.def), working, from, to),
351
+ definition: kind === "I" ? carriedPartitionedIndexStatement(String(r.def), working, from, to) : carriedIndexStatement(String(r.def), working, from, to),
352
+ ...(kind === "I" ? { partitioned: true } : {}),
290
353
  validated: true,
291
354
  ...(r.comment !== null ? { comment: String(r.comment) } : {}),
292
355
  ...(r.replident === true ? { replicaIdentity: true } : {}),
@@ -296,8 +359,9 @@ export async function discoverDependents(input) {
296
359
  else if (kind === "S") {
297
360
  const dep = deps.find((d) => d.kind === "class" && d.objid === String(r.oid));
298
361
  const seq = { kind: dep?.deptype === "i" ? "identity" : "serial", schema: String(r.schema), name, ident: `${quoteIdent(String(r.schema))}.${quoteIdent(name)}` };
299
- if (rename) {
300
- refused.push(`sequence ${r.schema}.${name} gives the column its values (${seq.kind === "identity" ? "an identity column" : "a serial column's default"}); during a rename a writer that names the new column would be given the old one's next value by the trigger, which it cannot tell from a value the writer chose; a rename that keeps its sequence needs versioned views (chant #3331)`);
362
+ if (rename && !input.keepSequence) {
363
+ refused.push(`sequence ${r.schema}.${name} gives the column its values (${seq.kind === "identity" ? "an identity column" : "a serial column's default"}); during a rename a writer that names the new column would get the old one's next value, and the trigger would take it over the writer's, ` +
364
+ `because it cannot tell a defaulted value from one the writer gave. Set defaultAtContract: true to leave the new column without the default until the contract (see the Op's reference), or drop the default first`);
301
365
  }
302
366
  else
303
367
  sequence = seq;
@@ -24,12 +24,13 @@
24
24
  * - `done`: the server holds the declared column and nothing of the
25
25
  * migration is left.
26
26
  *
27
+ * A partitioned table's indexes are carried over per partition (`./steps.ts`).
27
28
  * Anything else is refused with a {@link MigrationRefusal}, naming what to
28
29
  * do: a table that is not there, a partition (run it on the partitioned
29
30
  * table) or an inheritance tree; no primary key to batch by; a column in the
30
31
  * partition key; a generated column; a column change the Op does not make
31
- * (a rename and a type change at once, a rename of a column with a default
32
- * or a sequence); something that uses the column and is
32
+ * (a rename and a type change without `reverse`, a rename of a column with a
33
+ * default or a sequence without `defaultAtContract`); something that uses the column and is
33
34
  * not carried over to the new one (`./carry.ts`: indexes, key, check and
34
35
  * foreign key constraints and declared views are); a publication that sends
35
36
  * it; a working object chant did not make.
@@ -43,7 +44,7 @@ import type { DeclaredPgObject } from "../apply/statements.js";
43
44
  import { MIGRATION_TRAILER_KEY, type MigrationNames } from "./names.js";
44
45
  import { type PublicationHit } from "./replication.js";
45
46
  import { type KeyColumn } from "./batches.js";
46
- import { type CarriedObject, type CarriedState, type CarriedView, type ColumnSequence } from "./carry.js";
47
+ import { type CarriedObject, type CarriedState, type CarriedView, type ColumnSequence, type Dependents } from "./carry.js";
47
48
  /** A refusal: the migration cannot start, or cannot go on, for a reason a person has to act on. */
48
49
  export declare class MigrationRefusal extends Error {
49
50
  constructor(message: string);
@@ -87,7 +88,7 @@ export interface MigrationObservation {
87
88
  carriedStates: Map<string, CarriedState>;
88
89
  /** The views that read the old column, made again at the switch. */
89
90
  views: CarriedView[];
90
- /** The sequence that gives the old column its values (identity or serial), moved to the new column at the switch. */
91
+ /** The sequence that gives the old column its values (identity or serial): moved to the new column at the switch for a type change, at the contract for a rename. */
91
92
  sequence?: ColumnSequence;
92
93
  /** The table is partitioned: every step runs on it, and its partitions follow. */
93
94
  partitioned: boolean;
@@ -105,6 +106,10 @@ export interface MigrationObservation {
105
106
  changes: PgChange[];
106
107
  /** The expression the new column's value is computed with, over the old row's columns. */
107
108
  expression: string;
109
+ /** A rename with a type change: the expression over the new row's columns that gives the old column's value. */
110
+ reverse?: string;
111
+ /** A rename keeps its default, serial or identity on the old column until the contract (`defaultAtContract`). */
112
+ defaultAtContract?: boolean;
108
113
  publications: PublicationHit[];
109
114
  major: number;
110
115
  }
@@ -118,6 +123,10 @@ export interface ObserveInput {
118
123
  objects?: readonly DeclaredPgObject[];
119
124
  /** The type change's expression, over the old row's columns. Default: `CAST(<column> AS <declared type>)`. */
120
125
  using?: string;
126
+ /** A rename with a type change: the expression over the new row's columns that gives the old column's value. */
127
+ reverse?: string;
128
+ /** A rename of a column with a default, serial or identity: the declared default lands on the new column at the contract, not the switch. */
129
+ defaultAtContract?: boolean;
121
130
  /** The major the build targets; the server's own wins. */
122
131
  major?: number;
123
132
  }
@@ -125,8 +134,23 @@ export interface ObserveInput {
125
134
  export declare function declaredTable(declared: readonly DeclaredPgObject[], key: string): DeclaredPgObject;
126
135
  /** The server's major, from `server_version_num`. */
127
136
  export declare function serverMajor(client: PostgresClient): Promise<number>;
137
+ export interface RelationRow {
138
+ oid: string;
139
+ kind: string;
140
+ partition: boolean;
141
+ parents: string | null;
142
+ children: string | null;
143
+ partkey: string | null;
144
+ partattrs: number[] | null;
145
+ }
128
146
  /** Observe the migration of the declared table's column on the server. */
129
147
  export declare function observeMigration(input: ObserveInput): Promise<MigrationObservation>;
148
+ /** The checks that hold only while there is something to migrate. Returns the batch key and what the Op carries over. */
149
+ export declare function refuseUnsupported(input: ObserveInput, names: MigrationNames, rel: RelationRow, source: ServerColumn, column: ColumnDef, changes: readonly PgChange[], rename: boolean, typeChange: PgChange | undefined): Promise<{
150
+ batchKey: string;
151
+ keyColumns: KeyColumn[];
152
+ dependents: Pick<Dependents, "carried" | "views" | "sequence">;
153
+ }>;
130
154
  /**
131
155
  * What the migration will do, independent of how far it has got: the
132
156
  * change, the column on both sides, the expression, the batch key. The
@@ -1 +1 @@
1
- {"version":3,"file":"observe.d.ts","sourceRoot":"","sources":["../../../src/postgres/migrate/observe.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"observe.d.ts","sourceRoot":"","sources":["../../../src/postgres/migrate/observe.ts"],"names":[],"mappings":"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"}
@@ -24,12 +24,13 @@
24
24
  * - `done`: the server holds the declared column and nothing of the
25
25
  * migration is left.
26
26
  *
27
+ * A partitioned table's indexes are carried over per partition (`./steps.ts`).
27
28
  * Anything else is refused with a {@link MigrationRefusal}, naming what to
28
29
  * do: a table that is not there, a partition (run it on the partitioned
29
30
  * table) or an inheritance tree; no primary key to batch by; a column in the
30
31
  * partition key; a generated column; a column change the Op does not make
31
- * (a rename and a type change at once, a rename of a column with a default
32
- * or a sequence); something that uses the column and is
32
+ * (a rename and a type change without `reverse`, a rename of a column with a
33
+ * default or a sequence without `defaultAtContract`); something that uses the column and is
33
34
  * not carried over to the new one (`./carry.ts`: indexes, key, check and
34
35
  * foreign key constraints and declared views are); a publication that sends
35
36
  * it; a working object chant did not make.
@@ -41,9 +42,9 @@ import { PG_CLASSIFIER_RULES } from "../plan/rules.js";
41
42
  import { qualifiedKey } from "../plan/schema.js";
42
43
  import { POSTGRES_ENTITY_TYPES } from "../entity-types.js";
43
44
  import { col, migrationNames, MIGRATION_TRAILER_KEY, pgName } from "./names.js";
44
- import { publicationsOf } from "./replication.js";
45
+ import { publicationsOf, subscriptionRefusal, subscriptionsOf } from "./replication.js";
45
46
  import { keyText } from "./batches.js";
46
- import { carriedStates, carriedSubject, discoverDependents, replaceColumn, storedType } from "./carry.js";
47
+ import { carriedStates, carriedSubject, columnSequence, discoverDependents, replaceColumn, storedType } from "./carry.js";
47
48
  /** A refusal: the migration cannot start, or cannot go on, for a reason a person has to act on. */
48
49
  export class MigrationRefusal extends Error {
49
50
  constructor(message) {
@@ -241,7 +242,8 @@ export async function observeMigration(input) {
241
242
  }, (what) => {
242
243
  throw new MigrationRefusal(`${where}: ${what} exists and is not this migration's (its comment carries no migration=${names.key} role=carry marker for this project). The migration uses that name, so it stops rather than touch it; rename or drop it by hand.`);
243
244
  });
244
- if (change === "type") {
245
+ const retyped = change === "rename" && input.reverse !== undefined;
246
+ if (change === "type" || retyped) {
245
247
  expression = input.using ?? `CAST(${col(sourceName)} AS ${storedType(column.type)})`;
246
248
  if (expression.includes("$chant$"))
247
249
  throw new MigrationRefusal(`${where}: the using expression may not contain $chant$, which quotes the dual-write function's body`);
@@ -251,7 +253,7 @@ export async function observeMigration(input) {
251
253
  }
252
254
  // The declared type as the classifier compared it: the server's spelling (character varying(10), not varchar(10)).
253
255
  const serial = storedType(column.type) !== column.type;
254
- const expectedType = change === "type" ? (serial ? storedType(column.type) : String(typeChange?.after ?? column.type)) : source.type;
256
+ const expectedType = change === "type" || retyped ? (serial ? storedType(column.type) : String(typeChange?.after ?? column.type)) : source.type;
255
257
  if (newColumn && newColumn.type !== expectedType) {
256
258
  throw new MigrationRefusal(`${where}: ${newColumn.name} was made as ${newColumn.type}, from another declaration of ${input.column} (now ${column.type}). The run fails so onFailure drops it, and the next run starts again from the current declaration.`);
257
259
  }
@@ -263,6 +265,15 @@ export async function observeMigration(input) {
263
265
  `Leave the column out of the publication with a column list (15 and later), or migrate the subscriber's table as well and run this Op on a table no publication sends. ` +
264
266
  `A migration of the publisher and the subscriber together is chant #3332.`);
265
267
  }
268
+ const subscriptions = await subscriptionsOf(client, schema, table, major);
269
+ if (subscriptions.length > 0)
270
+ throw new MigrationRefusal(subscriptionRefusal(where, input.column, subscriptions));
271
+ }
272
+ // After a rename's switch the old column still holds the default or the identity the contract moves, and its sequence is read for it.
273
+ if (state === "switched" && old && (old.identity || old.default?.includes("nextval("))) {
274
+ const seq = await columnSequence(client, rel.oid, old.attnum);
275
+ if (seq)
276
+ dependents = { ...dependents, sequence: seq };
266
277
  }
267
278
  return {
268
279
  state,
@@ -286,23 +297,41 @@ export async function observeMigration(input) {
286
297
  ...(check ? { check } : {}),
287
298
  changes,
288
299
  expression,
300
+ ...(input.reverse !== undefined && state === "migrate" ? { reverse: input.reverse } : {}),
301
+ ...(input.defaultAtContract && state === "migrate" ? { defaultAtContract: true } : {}),
289
302
  publications,
290
303
  major,
291
304
  };
292
305
  }
293
306
  /** The checks that hold only while there is something to migrate. Returns the batch key and what the Op carries over. */
294
- async function refuseUnsupported(input, names, rel, source, column, changes, rename, typeChange) {
307
+ export async function refuseUnsupported(input, names, rel, source, column, changes, rename, typeChange) {
295
308
  const where = `${names.schema}.${names.table}`;
296
309
  const oid = rel.oid;
297
- if (rename && typeChange) {
310
+ if (rename && typeChange && input.reverse === undefined) {
298
311
  throw new MigrationRefusal(`${where}: ${source.name} is renamed to ${names.column} and its type changes (${typeChange.before} -> ${typeChange.after}) in one declaration. ` +
299
- `Migrate one at a time: declare the rename with the old type, run the Op to its end, then change the type. ` +
300
- `(In one run both names would stay written until the contract, which needs a conversion back to the old type for writers of the new name; chant #3331.)`);
312
+ `Both names stay written until the contract, so a writer of the new name needs its value converted back to the old type: give that expression as reverse ` +
313
+ `(over the row's columns, the new column by its declared name; using gives the new value from the old one). The verification fails the run unless reverse over every new value gives the old one back. ` +
314
+ `Or migrate one at a time: declare the rename with the old type, run the Op to its end, then change the type.`);
315
+ }
316
+ if (input.reverse !== undefined && !(rename && typeChange)) {
317
+ throw new MigrationRefusal(`${where}.${names.column}: reverse is for a rename combined with a type change, and this migration is ${rename ? "a rename only" : "a type change without a rename"}`);
318
+ }
319
+ if (input.reverse !== undefined && input.reverse.includes("$chant$")) {
320
+ throw new MigrationRefusal(`${where}: the reverse expression may not contain $chant$, which quotes the dual-write function's body`);
301
321
  }
302
- if (rename && (source.default !== undefined || column.default !== undefined)) {
303
- throw new MigrationRefusal(`${where}: ${source.name} has a default (${source.default ?? column.default}). During a rename both columns are written, each from the other, ` +
322
+ const hasDefault = source.default !== undefined || column.default !== undefined;
323
+ if (rename && typeChange && (hasDefault || source.identity || column.generated?.kind === "identity")) {
324
+ throw new MigrationRefusal(`${where}: ${source.name} has a default, serial or identity, and its rename also changes its type. The default is an expression of the old type; converting it, and the sequence's type, ` +
325
+ `is a third conversion on top of using and reverse that nothing verifies. Rename first (defaultAtContract: true), run the Op to its end, then change the type.`);
326
+ }
327
+ if (rename && (hasDefault || source.identity) && !input.defaultAtContract) {
328
+ throw new MigrationRefusal(`${where}: ${source.name} has a default (${source.default ?? column.default ?? "identity"}). During a rename both columns are written, each from the other, ` +
304
329
  `and a row inserted by a writer that names one column would get the other's default, which the trigger cannot tell from a value it was given. ` +
305
- `Drop the default first (the applier does), rename, then declare it again. A rename that keeps its default needs versioned views (chant #3331).`);
330
+ `Set defaultAtContract: true to leave the new column without the default until the contract, which gives the default to the new column in the contract's transaction; ` +
331
+ `until then an INSERT that names the new column with an explicit NULL gets the default, and UPDATE ... SET <new> = DEFAULT sets NULL. Or drop the default first (the applier does), rename, then declare it again.`);
332
+ }
333
+ if (input.defaultAtContract && !(rename && (hasDefault || source.identity))) {
334
+ throw new MigrationRefusal(`${where}.${names.column}: defaultAtContract is for a rename of a column with a default, serial or identity, and this migration is not one`);
306
335
  }
307
336
  if (source.generated || (column.generated && column.generated.kind !== "identity")) {
308
337
  throw new MigrationRefusal(`${where}.${source.name} is a generated column. There is no expand and contract for one: Postgres cannot make an existing column generated, so the new column could only be added generated, ` +
@@ -324,6 +353,7 @@ async function refuseUnsupported(input, names, rel, source, column, changes, ren
324
353
  declared: input.declared,
325
354
  defaultSchema: input.target.defaultSchema,
326
355
  partitioned: rel.kind === "p",
356
+ ...(input.defaultAtContract ? { keepSequence: true } : {}),
327
357
  });
328
358
  if (dependents.refused.length > 0) {
329
359
  throw new MigrationRefusal(`${where}.${source.name} is used by what the migration Op does not carry over to the new column: ${dependents.refused.join("; ")}. ` +
@@ -351,6 +381,8 @@ export function migrationPlanSubject(o) {
351
381
  from: o.source ? { name: o.source.name, type: o.source.type, notNull: o.source.notNull, default: o.source.default ?? null } : null,
352
382
  to: { name: o.column.name, type: o.column.type ?? null, notNull: o.column.notNull === true, default: o.column.default ?? null, comment: o.column.comment ?? null },
353
383
  expression: o.expression,
384
+ ...(o.reverse !== undefined ? { reverse: o.reverse } : {}),
385
+ ...(o.defaultAtContract ? { defaultAtContract: true } : {}),
354
386
  batchKey: o.batchKey,
355
387
  rules: o.changes.map((c) => c.rule),
356
388
  ...(o.carried.length > 0 || o.views.length > 0 || o.sequence ? { dependents: carriedSubject(o) } : {}),
@@ -20,7 +20,7 @@
20
20
  * | Expand | add the new column, nullable, no default (a catalog change) |
21
21
  * | Dual write | a trigger that keeps the new column written: computed from the old one for a type change, both ways for a rename |
22
22
  * | Backfill | `UPDATE` per key range, each batch with its receipt in its own transaction, under `lock_timeout`, pausing while a replica is behind |
23
- * | Carry over | each index on the old column built again on the new one `CONCURRENTLY`, each check and foreign key (another table's too) added `NOT VALID` and validated (`./carry.ts`) |
23
+ * | Carry over | each index on the old column built again on the new one `CONCURRENTLY` (on a partitioned table: `ON ONLY` the table, `CONCURRENTLY` per partition, then attached), each check and foreign key (another table's too) added `NOT VALID` and validated (`./carry.ts`) |
24
24
  * | Verify | rows, mismatches and checksums of the new column against the old |
25
25
  * | Approve | a gate bound to the plan and the verified new column |
26
26
  * | Switch | NOT NULL proven by a validated check; then one short transaction: a type change swaps the columns by name, a rename finishes the new column; the carried indexes and constraints take their names (keys `USING INDEX`), and the views that read the column are made again from their declarations |
@@ -60,6 +60,29 @@ export interface PostgresMigrationOpConfig {
60
60
  * and the verification all use it.
61
61
  */
62
62
  using?: string;
63
+ /**
64
+ * A rename combined with a type change: the SQL expression that gives the
65
+ * old column's value from the new column's, over the row's columns (the
66
+ * new column by its declared name). `using` gives the new value from the
67
+ * old one. Both stay in force until the contract: a writer of the old name
68
+ * has `using` applied, a writer of the new name has `reverse` applied. The
69
+ * verification fails the run unless `reverse` over every new value gives
70
+ * the old value back. A new value the old type cannot hold fails the
71
+ * writer's statement until the contract drops the old column.
72
+ */
73
+ reverse?: string;
74
+ /**
75
+ * A rename of a column with a default, an identity or a serial sequence.
76
+ * The declared default (or identity, or the serial's default) lands on the
77
+ * new column at the contract, not at the switch, so that until then a
78
+ * writer of either name gets the old column's default once. Two writes
79
+ * differ from the declaration until then, and `true` accepts both: an
80
+ * INSERT that names the new column with an explicit NULL gets the default
81
+ * instead of NULL, and `UPDATE ... SET <new> = DEFAULT` sets NULL. An
82
+ * `ApplyOp` between the switch and the contract must not set the default
83
+ * on the new column. Needs `gates: "own"` to end with the contract.
84
+ */
85
+ defaultAtContract?: boolean;
63
86
  /** The build output the declaration is read from. Default: `dist/schema.json`. */
64
87
  output?: string;
65
88
  /** Project directory to build. Default: `.`. */
@@ -139,6 +162,8 @@ export interface PostgresMigrationArgs {
139
162
  buildPath: string;
140
163
  environment?: string;
141
164
  using?: string;
165
+ reverse?: string;
166
+ defaultAtContract?: boolean;
142
167
  retain?: string;
143
168
  batchSize?: number;
144
169
  replicationLag?: {
@@ -1 +1 @@
1
- {"version":3,"file":"op.d.ts","sourceRoot":"","sources":["../../../src/postgres/migrate/op.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"op.d.ts","sourceRoot":"","sources":["../../../src/postgres/migrate/op.ts"],"names":[],"mappings":"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"}
@@ -20,7 +20,7 @@
20
20
  * | Expand | add the new column, nullable, no default (a catalog change) |
21
21
  * | Dual write | a trigger that keeps the new column written: computed from the old one for a type change, both ways for a rename |
22
22
  * | Backfill | `UPDATE` per key range, each batch with its receipt in its own transaction, under `lock_timeout`, pausing while a replica is behind |
23
- * | Carry over | each index on the old column built again on the new one `CONCURRENTLY`, each check and foreign key (another table's too) added `NOT VALID` and validated (`./carry.ts`) |
23
+ * | Carry over | each index on the old column built again on the new one `CONCURRENTLY` (on a partitioned table: `ON ONLY` the table, `CONCURRENTLY` per partition, then attached), each check and foreign key (another table's too) added `NOT VALID` and validated (`./carry.ts`) |
24
24
  * | Verify | rows, mismatches and checksums of the new column against the old |
25
25
  * | Approve | a gate bound to the plan and the verified new column |
26
26
  * | Switch | NOT NULL proven by a validated check; then one short transaction: a type change swaps the columns by name, a rename finishes the new column; the carried indexes and constraints take their names (keys `USING INDEX`), and the views that read the column are made again from their declarations |
@@ -75,6 +75,8 @@ export function PostgresMigrationOp(config) {
75
75
  buildPath: config.output ?? "dist/schema.json",
76
76
  environment: config.env,
77
77
  ...(config.using !== undefined ? { using: config.using } : {}),
78
+ ...(config.reverse !== undefined ? { reverse: config.reverse } : {}),
79
+ ...(config.defaultAtContract ? { defaultAtContract: true } : {}),
78
80
  ...(config.retain ? { retain: config.retain } : {}),
79
81
  ...(config.batchSize !== undefined ? { batchSize: config.batchSize } : {}),
80
82
  ...(config.replicationLag !== undefined ? { replicationLag: config.replicationLag } : {}),
@@ -34,6 +34,32 @@
34
34
  * publication sends the migrated column of, naming each publication. A
35
35
  * publication with a column list (15 and later) that leaves the column out
36
36
  * sends neither it nor the new one, and does not stop the migration.
37
+ *
38
+ * ## Subscriptions (#4405)
39
+ *
40
+ * The other side: a table that is the target of a subscription. The
41
+ * subscription's apply worker runs with `session_replication_role = replica`
42
+ * ("Logical Replication", Architecture,
43
+ * https://www.postgresql.org/docs/18/logical-replication-architecture.html),
44
+ * and a trigger made by plain `CREATE TRIGGER` is `ENABLE ORIGIN`: it fires
45
+ * only while the setting is `origin` or `local`
46
+ * (https://www.postgresql.org/docs/18/runtime-config-client.html#GUC-SESSION-REPLICATION-ROLE).
47
+ * Only `ENABLE REPLICA` and `ENABLE ALWAYS` triggers fire for the worker
48
+ * (https://www.postgresql.org/docs/18/sql-altertable.html, the TRIGGER
49
+ * clauses). The architecture page says "by default, triggers and rules will
50
+ * not fire on a subscriber" and points to `ENABLE TRIGGER` to change it. So the dual write
51
+ * never sees a replicated row, and the new column goes stale. The initial
52
+ * table copy is the exception: it is a `COPY` and fires plain triggers.
53
+ *
54
+ * `ENABLE ALWAYS` would make the trigger fire, and the Plan phase refuses
55
+ * the table instead, because the Op's later steps assume it controls every
56
+ * writer of the old column. The publisher keeps sending the old column's name
57
+ * and the subscriber applies by name, so a rename's contract (which drops the
58
+ * old column) would stop the apply at the next row, and the switch of a
59
+ * type change would change the column under a running apply worker. Neither
60
+ * order can be made inside this Op's one connection to one server; that is
61
+ * the same limit #3332 recorded for the publisher side. The refusal names
62
+ * each subscription.
37
63
  */
38
64
  import type { PostgresClient } from "../live/client.js";
39
65
  export interface ReplicationLagBound {
@@ -77,4 +103,20 @@ export interface PublicationHit {
77
103
  * before 15 there are no column lists, and any publication of the table is.
78
104
  */
79
105
  export declare function publicationsOf(client: Pick<PostgresClient, "query">, schema: string, table: string, column: string, major: number): Promise<PublicationHit[]>;
106
+ /** One subscription that has the table, or a partition of it, as a target. */
107
+ export interface SubscriptionHit {
108
+ name: string;
109
+ enabled: boolean;
110
+ }
111
+ /**
112
+ * The subscriptions of the current database with a row in `pg_subscription_rel`
113
+ * for `schema.table` (and, on a partitioned table, for any of its
114
+ * partitions, which is where a subscription to a partitioned table lists the
115
+ * tables it applies to). Read at plan time; `pg_subscription_rel` is
116
+ * per database and `pg_subscription` is shared, so the join keeps this
117
+ * database's rows (`subdbid`).
118
+ */
119
+ export declare function subscriptionsOf(client: Pick<PostgresClient, "query">, schema: string, table: string, major: number): Promise<SubscriptionHit[]>;
120
+ /** The Plan phase's refusal for a table that a subscription applies to. */
121
+ export declare function subscriptionRefusal(where: string, column: string, hits: SubscriptionHit[]): string;
80
122
  //# sourceMappingURL=replication.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"replication.d.ts","sourceRoot":"","sources":["../../../src/postgres/migrate/replication.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAErD,MAAM,WAAW,mBAAmB;IAClC,oEAAoE;IACpE,QAAQ,EAAE,MAAM,CAAC;IACjB,mEAAmE;IACnE,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,eAAO,MAAM,uBAAuB,EAAE,mBAA+D,CAAC;AAEtG,sFAAsF;AACtF,qBAAa,mBAAoB,SAAQ,KAAK;gBAChC,OAAO,EAAE,MAAM;CAI5B;AAED,MAAM,WAAW,UAAU;IACzB,wEAAwE;IACxE,IAAI,EAAE,MAAM,CAAC;IACb,gEAAgE;IAChE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,kFAAkF;AAClF,wBAAsB,WAAW,CAAC,MAAM,EAAE,IAAI,CAAC,cAAc,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAO9F;AAED;;;GAGG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,IAAI,CAAC,cAAc,EAAE,OAAO,CAAC,EACrC,KAAK,EAAE,mBAAmB,EAC1B,IAAI,GAAE;IAAE,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAAC,MAAM,CAAC,EAAE,WAAW,CAAC;IAAC,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAA;CAAO,GACjJ,OAAO,CAAC,MAAM,CAAC,CA2BjB;AAED,sDAAsD;AACtD,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,sDAAsD;IACtD,UAAU,EAAE,OAAO,CAAC;CACrB;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,MAAM,EAAE,IAAI,CAAC,cAAc,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAanK"}
1
+ {"version":3,"file":"replication.d.ts","sourceRoot":"","sources":["../../../src/postgres/migrate/replication.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8DG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAErD,MAAM,WAAW,mBAAmB;IAClC,oEAAoE;IACpE,QAAQ,EAAE,MAAM,CAAC;IACjB,mEAAmE;IACnE,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,eAAO,MAAM,uBAAuB,EAAE,mBAA+D,CAAC;AAEtG,sFAAsF;AACtF,qBAAa,mBAAoB,SAAQ,KAAK;gBAChC,OAAO,EAAE,MAAM;CAI5B;AAED,MAAM,WAAW,UAAU;IACzB,wEAAwE;IACxE,IAAI,EAAE,MAAM,CAAC;IACb,gEAAgE;IAChE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,kFAAkF;AAClF,wBAAsB,WAAW,CAAC,MAAM,EAAE,IAAI,CAAC,cAAc,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAO9F;AAED;;;GAGG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,IAAI,CAAC,cAAc,EAAE,OAAO,CAAC,EACrC,KAAK,EAAE,mBAAmB,EAC1B,IAAI,GAAE;IAAE,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAAC,MAAM,CAAC,EAAE,WAAW,CAAC;IAAC,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAA;CAAO,GACjJ,OAAO,CAAC,MAAM,CAAC,CA2BjB;AAED,sDAAsD;AACtD,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,sDAAsD;IACtD,UAAU,EAAE,OAAO,CAAC;CACrB;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,MAAM,EAAE,IAAI,CAAC,cAAc,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAanK;AAgBD,8EAA8E;AAC9E,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;;GAOG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,IAAI,CAAC,cAAc,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAarJ;AAED,2EAA2E;AAC3E,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,EAAE,GAAG,MAAM,CAQlG"}