@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
@@ -0,0 +1,203 @@
1
+ /**
2
+ * Named collections, referenced by name (#4395).
3
+ *
4
+ * A named collection holds an integration's connection settings and its
5
+ * credentials. Those are the environment's, so chant never declares one and
6
+ * never reads its values (the coverage table's `referenced` status,
7
+ * `../coverage/clickhouse.json`). A declaration may name one where the server
8
+ * takes a collection in place of inline arguments:
9
+ *
10
+ * - an integration engine's first argument: `ENGINE = S3(lake_creds, format = 'Parquet')`,
11
+ * `ENGINE = Kafka(kafka_creds)`, a database's `ENGINE = PostgreSQL(pg_creds)`;
12
+ * - a table function's first argument: `AS s3(lake_creds)`, `SELECT ... FROM mysql(mysql_creds, table = 't')`;
13
+ * - a dictionary source's `NAME`: `SOURCE(MYSQL(NAME mysql_creds))`.
14
+ *
15
+ * The build records each reference (`namedCollections` on the object and on
16
+ * the document, `../serializer.ts`), and `chant sql plan` checks that every
17
+ * one exists on the server by name (`./plan/commands.ts`).
18
+ */
19
+ import { DATABASE_ENGINES, TABLE_ENGINES, TABLE_FUNCTIONS } from "../generated/clickhouse.js";
20
+ import { unquoteWith } from "../core/cursor.js";
21
+ import { isTrivia, tokenizeText } from "./tokens.js";
22
+ /**
23
+ * The table and database engines whose first argument may be a named
24
+ * collection, as the 26.8 reference documents them for each engine.
25
+ * Filtered to the engines the pinned server has.
26
+ */
27
+ const COLLECTION_ENGINE_NAMES = [
28
+ "S3",
29
+ "S3Queue",
30
+ "AzureBlobStorage",
31
+ "AzureQueue",
32
+ "Iceberg",
33
+ "IcebergS3",
34
+ "IcebergAzure",
35
+ "DeltaLake",
36
+ "DeltaLakeS3",
37
+ "DeltaLakeAzure",
38
+ "Hudi",
39
+ "Paimon",
40
+ "PaimonS3",
41
+ "HDFS",
42
+ "URL",
43
+ "Kafka",
44
+ "RabbitMQ",
45
+ "NATS",
46
+ "MySQL",
47
+ "PostgreSQL",
48
+ "MaterializedPostgreSQL",
49
+ "MongoDB",
50
+ "Redis",
51
+ "ArrowFlight",
52
+ "YTsaurus",
53
+ "DataLakeCatalog",
54
+ ];
55
+ const ENGINES = { ...TABLE_ENGINES, ...DATABASE_ENGINES };
56
+ /** The engines a named collection may be the first argument of. */
57
+ export const COLLECTION_ENGINES = new Set(COLLECTION_ENGINE_NAMES.filter((n) => n in ENGINES));
58
+ /**
59
+ * The table functions a named collection may be the first argument of, lower
60
+ * case. A `...Cluster` function's first argument is the cluster, so those are
61
+ * left out.
62
+ */
63
+ export const COLLECTION_FUNCTIONS = new Set(TABLE_FUNCTIONS.filter((f) => !/Cluster$/.test(f) && /^(s3|gcs|oss|cosn|url|hdfs|mysql|postgresql|mongodb|redis|remote|azureblobstorage|iceberg|deltalake|hudi|paimon|arrowflight|ytsaurus)/i.test(f)).map((f) => f.toLowerCase()));
64
+ /** `lake_creds` or `` `lake creds` ``: an identifier, not a string, a call or `key = value`. */
65
+ function identifierName(text) {
66
+ const t = text.trim();
67
+ if (/^[A-Za-z_][A-Za-z0-9_]*$/.test(t))
68
+ return t.toUpperCase() === "NOSIGN" ? undefined : t;
69
+ if (/^`(?:[^`\\]|\\.)+`$/.test(t))
70
+ return unquoteWith(t, "`");
71
+ return undefined;
72
+ }
73
+ /** The collection an engine names in its first argument, when it is one of the engines that take one. */
74
+ export function engineCollection(engine) {
75
+ if (!engine || !COLLECTION_ENGINES.has(engine.name) || !engine.args || engine.args.length === 0)
76
+ return undefined;
77
+ return identifierName(engine.args[0]);
78
+ }
79
+ const significant = (text) => {
80
+ try {
81
+ return tokenizeText(text, 0).filter((t) => !isTrivia(t));
82
+ }
83
+ catch {
84
+ return [];
85
+ }
86
+ };
87
+ /** The collections a SQL text's table function calls name: `s3(lake_creds, ...)`, `mysql(mysql_creds)`. */
88
+ export function functionCollections(text) {
89
+ const tokens = significant(text);
90
+ const out = [];
91
+ for (let i = 0; i + 3 < tokens.length; i++) {
92
+ const [fn, open, arg, after] = [tokens[i], tokens[i + 1], tokens[i + 2], tokens[i + 3]];
93
+ if (fn.kind !== "ident" || !COLLECTION_FUNCTIONS.has(fn.text.toLowerCase()))
94
+ continue;
95
+ if (open.kind !== "punct" || open.text !== "(")
96
+ continue;
97
+ if (tokens[i - 1]?.kind === "punct" && tokens[i - 1].text === ".")
98
+ continue;
99
+ if (arg.kind !== "ident" && arg.kind !== "qident")
100
+ continue;
101
+ if (after.kind !== "punct" || (after.text !== "," && after.text !== ")"))
102
+ continue;
103
+ const name = identifierName(arg.text);
104
+ if (name)
105
+ out.push(name);
106
+ }
107
+ return out;
108
+ }
109
+ /** The collection a dictionary source names: `MYSQL(NAME mysql_creds)`. */
110
+ export function sourceCollections(dataSource) {
111
+ const tokens = significant(dataSource);
112
+ const out = [];
113
+ for (let i = 0; i + 1 < tokens.length; i++) {
114
+ if (tokens[i].kind !== "ident" || tokens[i].text.toUpperCase() !== "NAME")
115
+ continue;
116
+ const v = tokens[i + 1];
117
+ if (v.kind === "ident" || v.kind === "qident")
118
+ out.push(v.kind === "qident" ? unquoteWith(v.text, '`"') : v.text);
119
+ else if (v.kind === "string")
120
+ out.push(unquoteWith(v.text, "'"));
121
+ }
122
+ return out;
123
+ }
124
+ /** Every named collection an object names, once each, in the order written. */
125
+ export function namedCollectionReferences(o) {
126
+ const names = [
127
+ ...(engineCollection(o.engine) !== undefined ? [engineCollection(o.engine)] : []),
128
+ ...(o.asFunction ? functionCollections(o.asFunction) : []),
129
+ ...(o.select ? functionCollections(o.select) : []),
130
+ ...(o.dataSource ? sourceCollections(o.dataSource) : []),
131
+ ];
132
+ return [...new Set(names)];
133
+ }
134
+ /** `CREATE NAMED COLLECTION [IF NOT EXISTS] name ...`: the name, or undefined for another statement. */
135
+ export function createdCollectionName(sql) {
136
+ const m = /^\s*CREATE\s+NAMED\s+COLLECTION\s+(?:IF\s+NOT\s+EXISTS\s+)?(`(?:[^`\\]|\\.)+`|"(?:[^"\\]|\\.)+"|[A-Za-z_][A-Za-z0-9_]*)/i.exec(sql);
137
+ return m ? unquoteWith(m[1], '`"') : undefined;
138
+ }
139
+ /**
140
+ * The collections a whole statement names, read off its tokens: what
141
+ * {@link namedCollectionReferences} reads from a parsed declaration, for a
142
+ * statement import has only as text (`SHOW CREATE`).
143
+ */
144
+ export function statementCollections(ddl) {
145
+ const tokens = significant(ddl);
146
+ const out = [];
147
+ for (let i = 0; i < tokens.length; i++) {
148
+ const t = tokens[i];
149
+ if (t.kind !== "ident")
150
+ continue;
151
+ const word = t.text.toUpperCase();
152
+ if (word === "ENGINE" && tokens[i + 1]?.text === "=" && tokens[i + 3]?.text === "(") {
153
+ const engine = tokens[i + 2];
154
+ const arg = tokens[i + 4];
155
+ const after = tokens[i + 5];
156
+ if (COLLECTION_ENGINES.has(engine.text) && arg && (arg.kind === "ident" || arg.kind === "qident") && (after?.text === "," || after?.text === ")")) {
157
+ const name = identifierName(arg.text);
158
+ if (name)
159
+ out.push(name);
160
+ }
161
+ }
162
+ else if (word === "SOURCE" && tokens[i + 1]?.text === "(") {
163
+ let depth = 0;
164
+ let j = i + 1;
165
+ for (; j < tokens.length; j++) {
166
+ if (tokens[j].text === "(")
167
+ depth++;
168
+ else if (tokens[j].text === ")" && --depth === 0)
169
+ break;
170
+ }
171
+ out.push(...sourceCollections(tokens.slice(i + 2, j).map((x) => x.text).join(" ")));
172
+ i = j;
173
+ }
174
+ }
175
+ out.push(...functionCollections(ddl));
176
+ return [...new Set(out)];
177
+ }
178
+ /**
179
+ * The named collections an import found as prerequisites (#4395), each with
180
+ * the imported objects that name it, and a warning for each. A collection an
181
+ * imported object names that was not found is listed too: a live reader
182
+ * without `SHOW NAMED COLLECTIONS` sees none.
183
+ */
184
+ export function namedCollectionPrerequisites(found, objects, wording) {
185
+ const by = new Map(found.map((o) => [o.name, []]));
186
+ for (const o of objects) {
187
+ for (const c of statementCollections(o.ddl)) {
188
+ if (!by.has(c))
189
+ by.set(c, []);
190
+ by.get(c).push(o.database ? `${o.database}.${o.name}` : o.name);
191
+ }
192
+ }
193
+ const prerequisites = [...by]
194
+ .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))
195
+ .map(([name, referencedBy]) => ({ kind: "named collection", name, referencedBy }));
196
+ const seen = new Set(found.map((o) => o.name));
197
+ const warnings = prerequisites.map((p) => {
198
+ const used = p.referencedBy.length > 0 ? `, named by ${p.referencedBy.join(", ")}` : "";
199
+ return (`named collection ${p.name} is a prerequisite${wording.of ? ` of ${wording.of}` : ""}${used}: ${seen.has(p.name) ? wording.found : wording.unseen}, ` +
200
+ "and chant does not declare it or read its values. Create it on every server the project applies to; chant sql plan checks that it exists");
201
+ });
202
+ return { prerequisites, warnings };
203
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/clickhouse/parser.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/clickhouse/parser.ts"],"names":[],"mappings":"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"}
@@ -51,7 +51,7 @@ export const REFUSED_CREATE_KINDS = [
51
51
  {
52
52
  words: ["NAMED", "COLLECTION"],
53
53
  kind: "NAMED COLLECTION",
54
- reason: "a named collection holds credentials (a password, a secret key), which are the environment's and never in a build; the server hides its values, so a plan could not compare them either. Create it from the server's configuration or by hand",
54
+ reason: "a named collection holds credentials (a password, a secret key), which are the environment's and never in a build. Create it on the server, and name it where it is used: ENGINE = S3(lake_creds, format = 'Parquet'), s3(lake_creds), SOURCE(MYSQL(NAME mysql_creds)). A plan checks that it exists",
55
55
  },
56
56
  { words: ["MASKING", "POLICY"], kind: "MASKING POLICY", reason: "masking policies are available only in ClickHouse Cloud, not on the pinned server" },
57
57
  { words: ["WORKLOAD"], kind: "WORKLOAD", reason: "a workload is server-level scheduling, configured with the server, not a schema object" },
@@ -13,7 +13,8 @@
13
13
  * expressions the rules leave different. Both exit 2 when a change needs a
14
14
  * rebuild, which a plan refuses to make in place, and `plan` also when the
15
15
  * declared databases hold an object whose definition it cannot read (#3653),
16
- * which it names; 0 otherwise. For each
16
+ * which it names, or when the build references a named collection the
17
+ * server does not have (#4395), which it names; 0 otherwise. For each
17
18
  * refused table they name the `ClickHouseRebuildOp` to run instead
18
19
  * (`rebuildOps` in `--json`, `./rebuild-handoff.ts`).
19
20
  *
@@ -1 +1 @@
1
- {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../../src/clickhouse/plan/commands.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AAC5F,OAAO,EAAe,KAAK,UAAU,EAAwB,MAAM,QAAQ,CAAC;AAM5E,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAyD9C,wBAAsB,OAAO,CAAC,GAAG,EAAE,mBAAmB,GAAG,OAAO,CAAC,MAAM,CAAC,CAsBvE;AAED,mFAAmF;AACnF,wBAAsB,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,GAAE,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC,CAAC,CAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAyBvJ;AAED,wBAAsB,OAAO,CAAC,GAAG,EAAE,mBAAmB,GAAG,OAAO,CAAC,MAAM,CAAC,CAYvE;AAED,eAAO,MAAM,WAAW,EAAE,YAYzB,CAAC"}
1
+ {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../../src/clickhouse/plan/commands.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AAC5F,OAAO,EAAe,KAAK,UAAU,EAAwB,MAAM,QAAQ,CAAC;AAM5E,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AA0D9C,wBAAsB,OAAO,CAAC,GAAG,EAAE,mBAAmB,GAAG,OAAO,CAAC,MAAM,CAAC,CAsBvE;AAED,mFAAmF;AACnF,wBAAsB,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,GAAE,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC,CAAC,CAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CA4BvJ;AAED,wBAAsB,OAAO,CAAC,GAAG,EAAE,mBAAmB,GAAG,OAAO,CAAC,MAAM,CAAC,CAYvE;AAED,eAAO,MAAM,WAAW,EAAE,YAsBzB,CAAC"}
@@ -13,7 +13,8 @@
13
13
  * expressions the rules leave different. Both exit 2 when a change needs a
14
14
  * rebuild, which a plan refuses to make in place, and `plan` also when the
15
15
  * declared databases hold an object whose definition it cannot read (#3653),
16
- * which it names; 0 otherwise. For each
16
+ * which it names, or when the build references a named collection the
17
+ * server does not have (#4395), which it names; 0 otherwise. For each
17
18
  * refused table they name the `ClickHouseRebuildOp` to run instead
18
19
  * (`rebuildOps` in `--json`, `./rebuild-handoff.ts`).
19
20
  *
@@ -38,6 +39,7 @@ import { bindClickHouse } from "../live/bind.js";
38
39
  import { rebuildOpSuggestions } from "./rebuild-handoff.js";
39
40
  import { readFileSync } from "node:fs";
40
41
  import { parseTopology } from "../topology.js";
42
+ import { checkNamedCollections, namedCollectionsFail, referencedCollectionsOf } from "../live/named-collections.js";
41
43
  /** The dialect a build output names. */
42
44
  function outputDialect(path) {
43
45
  try {
@@ -81,7 +83,7 @@ async function runDiffStatements(before, after, json, topology) {
81
83
  }
82
84
  function emit(diff, json, title) {
83
85
  console.log(json ? JSON.stringify(diff, null, 2) : renderDiff(diff, { title }));
84
- return diff.rebuilds.length > 0 || (diff.unreadable?.length ?? 0) > 0 ? 2 : 0;
86
+ return diff.rebuilds.length > 0 || (diff.unreadable?.length ?? 0) > 0 || namedCollectionsFail(diff.namedCollections) ? 2 : 0;
85
87
  }
86
88
  export async function runDiff(ctx) {
87
89
  const { positional, json, statements, topology: topologyArg } = split(ctx.rawArgs);
@@ -121,6 +123,8 @@ export async function planAgainstServer(environment, buildFile, options = {}) {
121
123
  const diff = diffSchemas(live, declared);
122
124
  const changes = await dropFormattingOnly(target.endpoint, diff.changes);
123
125
  const rebuildOps = rebuildOpSuggestions({ ...diff, changes, rebuilds: changes.filter((c) => c.class === "rebuild") }, new Map(declared.map((o) => [o.key, o.canonical])), environment);
126
+ // Each named collection the build references must exist on the server, by name; its values are never read (#4395).
127
+ const namedCollections = await checkNamedCollections(target.endpoint, referencedCollectionsOf(buildFile));
124
128
  const label = new Map(declared.map((o) => [o.key, o.exportName === o.key ? o.key : `${o.exportName} (${o.key})`]));
125
129
  const relabel = changes.map((c) => ({ ...c, object: label.get(c.object) ?? c.object }));
126
130
  return {
@@ -129,6 +133,7 @@ export async function planAgainstServer(environment, buildFile, options = {}) {
129
133
  hints: unmanaged > 0 ? [...diff.hints, accessUnmanagedHint(unmanaged, environment)] : diff.hints,
130
134
  ...(rebuildOps.length > 0 ? { rebuildOps } : {}),
131
135
  ...(unreadable.length > 0 ? { unreadable } : {}),
136
+ ...(namedCollections ? { namedCollections } : {}),
132
137
  };
133
138
  }
134
139
  export async function runPlan(ctx) {
@@ -155,5 +160,15 @@ export const sqlCommands = {
155
160
  description: "Write sql-types.d.ts: typed columns for each table, view and dictionary the build declares, for tags given their name (table<\"app.users\">) and RowOf; --output <path> writes it elsewhere; --check compares instead of writing and exits 1 when the file differs",
156
161
  handler: async (ctx) => (await import("../../sql-types-command.js")).runTypes(ctx),
157
162
  },
163
+ {
164
+ name: "replay",
165
+ description: "Replay a goose, golang-migrate, clickhouse-migrations or Flyway directory into the empty server --env binds, and record the tables and columns it makes as chant.replay.json; --check compares instead of writing",
166
+ handler: async (ctx) => (await import("../../migration-replay.js")).runReplay(ctx),
167
+ },
168
+ {
169
+ name: "drizzle",
170
+ description: "Write a Drizzle schema module (drizzle-schema.ts) from a Postgres build: pgTable per table with columns, keys, indexes, enums, sequences and views, so an application queries with Drizzle's row types while chant owns the schema; --output <path> writes it elsewhere; --check compares instead of writing and exits 1 when the file differs; --bigint bigint reads bigint columns as bigint, not number",
171
+ handler: async (ctx) => (await import("../../drizzle-command.js")).runDrizzle(ctx),
172
+ },
158
173
  ],
159
174
  };
@@ -33,6 +33,21 @@ export interface SchemaDiff extends ChangeSet<Change> {
33
33
  * it out.
34
34
  */
35
35
  unreadable?: UnreadableEntry[];
36
+ /**
37
+ * The named collections the build references, checked against the server
38
+ * by name (#4395). A plan with one `missing`, or whose check could not run
39
+ * (`unread`), fails naming it. Their values are never read.
40
+ */
41
+ namedCollections?: NamedCollectionCheck;
42
+ }
43
+ /** What a plan found of the named collections a build references: each by name, never its values. */
44
+ export interface NamedCollectionCheck {
45
+ /** Every collection the build names, sorted. */
46
+ referenced: string[];
47
+ /** Those the server has no collection of, or that the plan's user may not see. */
48
+ missing: string[];
49
+ /** Why the server's collections could not be read, when they could not. */
50
+ unread?: string;
36
51
  }
37
52
  /** An object a plan could not read: `database.name`, its type and why. */
38
53
  export interface UnreadableEntry {
@@ -1 +1 @@
1
- {"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../../src/clickhouse/plan/diff.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAoB,KAAK,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,SAAS,CAAC;AACpF,OAAO,KAAK,EAAmB,eAAe,EAAE,MAAM,aAAa,CAAC;AACpE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAE7D,OAAO,EAAoB,KAAK,SAAS,EAAE,KAAK,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAChG,OAAO,EAAmC,KAAK,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAE9E,MAAM,MAAM,YAAY,GAAG,KAAK,CAAC,eAAe,CAAC,CAAC;AAElD,MAAM,MAAM,MAAM,GAAG,gBAAgB,CAAC,gBAAgB,EAAE,WAAW,CAAC,CAAC;AAErE,MAAM,WAAW,UAAW,SAAQ,SAAS,CAAC,MAAM,CAAC;IACnD,wDAAwD;IACxD,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,6GAA6G;IAC7G,UAAU,CAAC,EAAE,mBAAmB,EAAE,CAAC;IACnC;;;;OAIG;IACH,UAAU,CAAC,EAAE,eAAe,EAAE,CAAC;CAChC;AAED,0EAA0E;AAC1E,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAgQD;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,EAAE,KAAK,EAAE,SAAS,YAAY,EAAE,GAAG,UAAU,CAqBvG"}
1
+ {"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../../src/clickhouse/plan/diff.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAoB,KAAK,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,SAAS,CAAC;AACpF,OAAO,KAAK,EAAmB,eAAe,EAAE,MAAM,aAAa,CAAC;AACpE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAG7D,OAAO,EAAoB,KAAK,SAAS,EAAE,KAAK,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAChG,OAAO,EAAmC,KAAK,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAE9E,MAAM,MAAM,YAAY,GAAG,KAAK,CAAC,eAAe,CAAC,CAAC;AAElD,MAAM,MAAM,MAAM,GAAG,gBAAgB,CAAC,gBAAgB,EAAE,WAAW,CAAC,CAAC;AAErE,MAAM,WAAW,UAAW,SAAQ,SAAS,CAAC,MAAM,CAAC;IACnD,wDAAwD;IACxD,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,6GAA6G;IAC7G,UAAU,CAAC,EAAE,mBAAmB,EAAE,CAAC;IACnC;;;;OAIG;IACH,UAAU,CAAC,EAAE,eAAe,EAAE,CAAC;IAC/B;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,oBAAoB,CAAC;CACzC;AAED,qGAAqG;AACrG,MAAM,WAAW,oBAAoB;IACnC,gDAAgD;IAChD,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,kFAAkF;IAClF,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,2EAA2E;IAC3E,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,0EAA0E;AAC1E,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AA4RD;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,EAAE,KAAK,EAAE,SAAS,YAAY,EAAE,GAAG,UAAU,CAgCvG"}
@@ -17,6 +17,7 @@
17
17
  */
18
18
  import { CLASSIFIER_RULES } from "./rules.js";
19
19
  import { MERGE_TREE_SETTINGS } from "../../generated/clickhouse.js";
20
+ import { isStreamEngine, isStreamTable, positionWarnings, readsTable } from "./stream.js";
20
21
  import { classifiedChange } from "../../core/classifier.js";
21
22
  import { changedEntries, matchByIdentity } from "../../core/diff.js";
22
23
  const qualified = (o) => (o.database ? `${o.database}.${o.name}` : o.name);
@@ -203,9 +204,14 @@ function diffObject(key, before, after, out, hints) {
203
204
  diffTableFunction(key, before, after, out);
204
205
  return;
205
206
  }
207
+ // A stream table (#4396): replaced, not altered, and not rebuilt, since it holds no rows.
208
+ if (isStreamTable(before) && isStreamTable(after)) {
209
+ diffStreamTable(key, before, after, out);
210
+ return;
211
+ }
206
212
  // A table.
207
213
  if (before.engine !== after.engine)
208
- out.push(change(key, "engine", "SQLCH223", before.engine, after.engine));
214
+ out.push(change(key, "engine", "SQLCH223", before.engine, after.engine, isStreamEngine(before.engineName) || isStreamEngine(after.engineName) ? { note: "one side is a stream engine and the other is not, which is a different kind of table: neither the replace nor the rebuild applies" } : {}));
209
215
  const added = diffColumns(key, before, after, out, hints);
210
216
  const beforePk = before.primaryKey ?? before.orderBy;
211
217
  const afterPk = after.primaryKey ?? after.orderBy;
@@ -234,6 +240,32 @@ function diffObject(key, before, after, out, hints) {
234
240
  diffMap(key, "projections", before.projections, after.projections, "SQLCH214", out);
235
241
  diffMap(key, "constraints", before.constraints, after.constraints, "SQLCH215", out);
236
242
  }
243
+ /**
244
+ * A table on a stream engine, on both sides (#4396). Its engine, its settings
245
+ * and its columns are all replaced the same way (SQLCH225); the comment is
246
+ * compared before this. A change that loses the table's position says so in
247
+ * its note.
248
+ */
249
+ function diffStreamTable(key, before, after, out) {
250
+ const start = out.length;
251
+ if (before.engine !== after.engine)
252
+ out.push(change(key, "engine", "SQLCH225", before.engine, after.engine));
253
+ for (const name of changedEntries(before.settings, after.settings))
254
+ out.push(change(key, `settings.${name}`, "SQLCH225", before.settings[name], after.settings[name]));
255
+ const column = (c) => [c.type, c.nullable ? "NULL" : "", c.defaultKind ?? "", c.defaultExpr ?? "", c.codec ? `CODEC(${c.codec})` : ""].filter(Boolean).join(" ");
256
+ const b = new Map(before.columns.map((c) => [c.name, column(c)]));
257
+ const a = new Map(after.columns.map((c) => [c.name, column(c)]));
258
+ for (const name of new Set([...b.keys(), ...a.keys()])) {
259
+ if (b.get(name) !== a.get(name))
260
+ out.push(change(key, `columns.${name}`, "SQLCH225", b.get(name), a.get(name)));
261
+ }
262
+ const order = (o) => o.columns.map((c) => c.name).join(", ");
263
+ if (order(before) !== order(after) && a.size === b.size && [...a.keys()].every((n) => b.has(n)))
264
+ out.push(change(key, "columns.order", "SQLCH225", order(before), order(after)));
265
+ const warnings = positionWarnings(before, after);
266
+ if (warnings.length > 0 && out.length > start)
267
+ out[start] = { ...out[start], note: `loses its position: ${warnings.join("; ")}` };
268
+ }
237
269
  /**
238
270
  * A table over a table function (#3911), on either side. It stores nothing,
239
271
  * so every change but its comment replaces it (SQLCH219); a table with data
@@ -308,5 +340,15 @@ export function diffSchemas(before, after) {
308
340
  changes.push(change(b.key, "object", "SQLCH250", qualified(b.canonical), undefined, { destructive: b.canonical.kind === "table" || b.canonical.kind === "materializedView" }));
309
341
  }
310
342
  }
343
+ // A replaced stream table is replaced around the views that read it (#4396): say which.
344
+ const replaced = new Set(changes.filter((c) => c.rule === "SQLCH225").map((c) => c.object));
345
+ for (const m of matches) {
346
+ if (m.kind !== "matched" || !replaced.has(m.after.key))
347
+ continue;
348
+ const readers = before.filter((o) => readsTable(o.canonical, m.before.canonical)).map((o) => qualified(o.canonical));
349
+ hints.push(readers.length > 0
350
+ ? `${qualified(m.before.canonical)} is replaced: ${readers.join(", ")} ${readers.length === 1 ? "reads it and is" : "read it and are"} detached first and attached after`
351
+ : `${qualified(m.before.canonical)} is replaced; no materialized view reads it`);
352
+ }
311
353
  return { changes, rebuilds: changes.filter((c) => c.class === "rebuild"), hints };
312
354
  }
@@ -1 +1 @@
1
- {"version":3,"file":"disruption.d.ts","sourceRoot":"","sources":["../../../src/clickhouse/plan/disruption.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAqChG,wBAAgB,kBAAkB,CAAC,OAAO,EAAE;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,eAAe,EAAE,CAAA;CAAE,GAAG,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAWlI"}
1
+ {"version":3,"file":"disruption.d.ts","sourceRoot":"","sources":["../../../src/clickhouse/plan/disruption.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AA0ChG,wBAAgB,kBAAkB,CAAC,OAAO,EAAE;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,eAAe,EAAE,CAAA;CAAE,GAAG,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAWlI"}
@@ -12,6 +12,8 @@
12
12
  import { MERGE_TREE_SETTINGS } from "../../generated/clickhouse.js";
13
13
  import { classifyDisruptionWith } from "../../core/classifier.js";
14
14
  import { CHANGE_CLASSES, CLASSIFIER_RULES } from "./rules.js";
15
+ /** Settings only a stream engine takes; the path alone cannot name the engine. */
16
+ const STREAM_SETTING = /^(?:kafka_|rabbitmq_|nats_|s3queue_|azure_queue_|keeper_path$)/;
15
17
  function ruleFor(path) {
16
18
  const root = path.split(/[.[]/)[0];
17
19
  if (root === "name" || root === "database")
@@ -42,6 +44,9 @@ function ruleFor(path) {
42
44
  return "SQLCH244";
43
45
  if (root === "settings") {
44
46
  const key = path.split(".")[1];
47
+ // A stream engine's own settings (Kafka, RabbitMQ, NATS, S3Queue's keeper_path) have no MODIFY SETTING: the table is replaced (#4396).
48
+ if (key !== undefined && STREAM_SETTING.test(key))
49
+ return "SQLCH225";
45
50
  const spec = key ? MERGE_TREE_SETTINGS[key] : undefined;
46
51
  return spec?.readonly ? "SQLCH218" : "SQLCH206";
47
52
  }
@@ -1 +1 @@
1
- {"version":3,"file":"rebuild-handoff.d.ts","sourceRoot":"","sources":["../../../src/clickhouse/plan/rebuild-handoff.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACzC,OAAO,EAAuC,KAAK,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAGrG,MAAM,WAAW,mBAAoB,SAAQ,qBAAqB;IAChE,yCAAyC;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE;QAAE,IAAI,EAAE,mBAAmB,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,IAAI,EAAE,KAAK,CAAA;KAAE,CAAC;IAClF,2GAA2G;IAC3G,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAID;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,eAAe,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,mBAAmB,EAAE,CA0BzI;AAED,+CAA+C;AAC/C,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,SAAS,mBAAmB,EAAE,GAAG,MAAM,EAAE,CAG9E"}
1
+ {"version":3,"file":"rebuild-handoff.d.ts","sourceRoot":"","sources":["../../../src/clickhouse/plan/rebuild-handoff.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACzC,OAAO,EAAuC,KAAK,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAIrG,MAAM,WAAW,mBAAoB,SAAQ,qBAAqB;IAChE,yCAAyC;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE;QAAE,IAAI,EAAE,mBAAmB,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,IAAI,EAAE,KAAK,CAAA;KAAE,CAAC;IAClF,2GAA2G;IAC3G,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAID;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,eAAe,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,mBAAmB,EAAE,CA4BzI;AAED,+CAA+C;AAC/C,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,SAAS,mBAAmB,EAAE,GAAG,MAAM,EAAE,CAG9E"}
@@ -16,6 +16,7 @@
16
16
  * suggestion are ClickHouse's.
17
17
  */
18
18
  import { migrationOpName, renderMigrationOps } from "../../core/handoff.js";
19
+ import { isStreamEngine } from "./stream.js";
19
20
  import { collapsesRows } from "../rebuild/engines.js";
20
21
  const TIME_TYPE = /^(?:Nullable\s*\(\s*)?(?:Date|Date32|DateTime|DateTime64)\b/;
21
22
  /**
@@ -29,6 +30,9 @@ export function rebuildOpSuggestions(diff, declared, env) {
29
30
  const c = declared.get(key);
30
31
  if (!c || c.kind !== "table")
31
32
  continue;
33
+ // The Op refuses a stream-engine table (#4396); a change to one that reaches here is a move to or from a stream engine, for review.
34
+ if (isStreamEngine(c.engineName))
35
+ continue;
32
36
  const table = `${c.database ?? "default"}.${c.name}`;
33
37
  const time = c.columns.find((col) => !col.nullable && TIME_TYPE.test(col.type) && (!col.defaultKind || col.defaultKind === "DEFAULT"));
34
38
  const dualWrite = time ? { mode: "materialized-view", cutoverColumn: time.name } : { mode: "app" };
@@ -1 +1 @@
1
- {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../../src/clickhouse/plan/report.ts"],"names":[],"mappings":"AAAA,qHAAqH;AAIrH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAGzC,wBAAgB,UAAU,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,MAAM,CAsBlF"}
1
+ {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../../src/clickhouse/plan/report.ts"],"names":[],"mappings":"AAAA,qHAAqH;AAIrH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAIzC,wBAAgB,UAAU,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,MAAM,CA0BlF"}
@@ -2,6 +2,7 @@
2
2
  import { renderChangeSet } from "../../core/classifier.js";
3
3
  import { CHANGE_CLASSES, CLASSIFIER_RULES } from "./rules.js";
4
4
  import { renderRebuildOps } from "./rebuild-handoff.js";
5
+ import { renderNamedCollections } from "../live/named-collections.js";
5
6
  export function renderDiff(diff, opts = {}) {
6
7
  const unreadable = diff.unreadable ?? [];
7
8
  const refusedRead = unreadable.length > 0
@@ -13,6 +14,7 @@ export function renderDiff(diff, opts = {}) {
13
14
  : [];
14
15
  const trailer = [
15
16
  ...refusedRead,
17
+ ...renderNamedCollections(diff.namedCollections),
16
18
  ...(diff.rebuilds.length > 0
17
19
  ? [
18
20
  "",
@@ -22,5 +24,8 @@ export function renderDiff(diff, opts = {}) {
22
24
  ]
23
25
  : []),
24
26
  ];
25
- return renderChangeSet(diff, { ...(opts.title ? { title: opts.title } : {}), rules: CLASSIFIER_RULES, classes: CHANGE_CLASSES, trailer });
27
+ const text = renderChangeSet(diff, { ...(opts.title ? { title: opts.title } : {}), rules: CLASSIFIER_RULES, classes: CHANGE_CLASSES, trailer });
28
+ // The shared report prints no trailer under "No changes."; a missing named collection fails the plan all the same (#4395).
29
+ const missing = renderNamedCollections(diff.namedCollections);
30
+ return diff.changes.length === 0 && missing.length > 0 ? [text, ...missing].join("\n") : text;
26
31
  }
@@ -10,13 +10,16 @@
10
10
  * parts until `MATERIALIZE INDEX`).
11
11
  * - `rewrite`: the change is a mutation that rewrites existing parts in the
12
12
  * background (`system.mutations`), with no rollback.
13
+ * - `replace`: ClickHouse cannot alter the object, but it holds no rows to
14
+ * keep, so the applier drops and creates it, around the views that read it
15
+ * (a stream-engine table, #4396). Nothing is copied.
13
16
  * - `rebuild`: ClickHouse cannot make the change to the table it has; the data
14
17
  * has to be copied into a new table. A plan refuses to make one in place.
15
18
  *
16
19
  * Creating and dropping whole objects are classed `create` and `drop`.
17
20
  */
18
21
  import { type ChangeClasses, type ClassifierRule as SqlClassifierRule } from "../../core/classifier.js";
19
- export type ChangeClass = "metadata" | "rewrite" | "rebuild" | "create" | "drop";
22
+ export type ChangeClass = "metadata" | "rewrite" | "replace" | "rebuild" | "create" | "drop";
20
23
  /** A ClickHouse rule: the shared core's rule shape over these classes, citing a clickhouse.com page. */
21
24
  export type ClassifierRule = SqlClassifierRule<ChangeClass>;
22
25
  /** The classes as data: report order and labels, and what each costs for `classifyDisruption()`. */
@@ -47,6 +50,7 @@ export declare const CLASSIFIER_RULES: {
47
50
  readonly SQLCH222: ClassifierRule;
48
51
  readonly SQLCH223: ClassifierRule;
49
52
  readonly SQLCH224: ClassifierRule;
53
+ readonly SQLCH225: ClassifierRule;
50
54
  readonly SQLCH230: ClassifierRule;
51
55
  readonly SQLCH231: ClassifierRule;
52
56
  readonly SQLCH232: ClassifierRule;
@@ -1 +1 @@
1
- {"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../../src/clickhouse/plan/rules.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAkB,KAAK,aAAa,EAAE,KAAK,cAAc,IAAI,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAErH,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEjF,wGAAwG;AACxG,MAAM,MAAM,cAAc,GAAG,iBAAiB,CAAC,WAAW,CAAC,CAAC;AAE5D,oGAAoG;AACpG,eAAO,MAAM,cAAc,EAAE,aAAa,CAAC,WAAW,CAIrD,CAAC;AAMF,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiRsB,CAAC;AAEpD,MAAM,MAAM,gBAAgB,GAAG,MAAM,OAAO,gBAAgB,CAAC"}
1
+ {"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../../src/clickhouse/plan/rules.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAkB,KAAK,aAAa,EAAE,KAAK,cAAc,IAAI,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAErH,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,CAAC;AAE7F,wGAAwG;AACxG,MAAM,MAAM,cAAc,GAAG,iBAAiB,CAAC,WAAW,CAAC,CAAC;AAE5D,oGAAoG;AACpG,eAAO,MAAM,cAAc,EAAE,aAAa,CAAC,WAAW,CAIrD,CAAC;AAMF,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwRsB,CAAC;AAEpD,MAAM,MAAM,gBAAgB,GAAG,MAAM,OAAO,gBAAgB,CAAC"}
@@ -10,6 +10,9 @@
10
10
  * parts until `MATERIALIZE INDEX`).
11
11
  * - `rewrite`: the change is a mutation that rewrites existing parts in the
12
12
  * background (`system.mutations`), with no rollback.
13
+ * - `replace`: ClickHouse cannot alter the object, but it holds no rows to
14
+ * keep, so the applier drops and creates it, around the views that read it
15
+ * (a stream-engine table, #4396). Nothing is copied.
13
16
  * - `rebuild`: ClickHouse cannot make the change to the table it has; the data
14
17
  * has to be copied into a new table. A plan refuses to make one in place.
15
18
  *
@@ -18,9 +21,9 @@
18
21
  import { classifierRule } from "../../core/classifier.js";
19
22
  /** The classes as data: report order and labels, and what each costs for `classifyDisruption()`. */
20
23
  export const CHANGE_CLASSES = {
21
- order: ["create", "metadata", "rewrite", "rebuild", "drop"],
22
- label: { create: "create", drop: "drop", metadata: "metadata only", rewrite: "background rewrite", rebuild: "REBUILD" },
23
- disruption: { metadata: "in-place", rewrite: "rolling", rebuild: "replace", create: "in-place", drop: "destroy" },
24
+ order: ["create", "metadata", "rewrite", "replace", "rebuild", "drop"],
25
+ label: { create: "create", drop: "drop", metadata: "metadata only", rewrite: "background rewrite", replace: "replace table", rebuild: "REBUILD" },
26
+ disruption: { metadata: "in-place", rewrite: "rolling", replace: "replace", rebuild: "replace", create: "in-place", drop: "destroy" },
24
27
  };
25
28
  const DOCS = "https://clickhouse.com/docs/sql-reference/statements";
26
29
  const rule = (id, cls, title, restriction, cite) => classifierRule(id, cls, title, restriction, cite);
@@ -50,6 +53,7 @@ export const CLASSIFIER_RULES = {
50
53
  SQLCH222: rule("SQLCH222", "rebuild", "Change the partition key", "There is no ALTER for the partition key; parts are laid out by it when they are written.", `${DOCS}/alter`),
51
54
  SQLCH223: rule("SQLCH223", "rebuild", "Change the table engine or its arguments", "There is no ALTER for a table's engine or its arguments (a ReplacingMergeTree version column, a Distributed sharding key); a different engine is a different table.", `${DOCS}/alter`),
52
55
  SQLCH224: rule("SQLCH224", "rebuild", "Change what kind of object it is", "A table cannot become a view or a view a table; the old object is dropped and the new one created.", `${DOCS}/create`),
56
+ SQLCH225: rule("SQLCH225", "replace", "Change a stream table", "A Kafka, S3Queue, AzureQueue, RabbitMQ, NATS or FileLog table stores no rows and has no ALTER for its engine arguments, settings or columns; the views that read it are detached, the table is dropped and created, and the views are attached again. Its position (a Kafka group's offsets, an S3Queue's record of processed files) is kept by the broker or Keeper, not by the table.", `${DOCS}/create/table`),
53
57
  SQLCH230: rule("SQLCH230", "metadata", "Rename or move a table or view", "RENAME TABLE changes the name, or moves the object to another database, in metadata on an Atomic database.", `${DOCS}/rename`),
54
58
  SQLCH231: rule("SQLCH231", "metadata", "Rename a database", "RENAME DATABASE is metadata only, for an Atomic database.", `${DOCS}/rename`),
55
59
  SQLCH232: rule("SQLCH232", "rebuild", "Change a database's engine", "A database's engine is fixed at creation; there is no ALTER for it.", `${DOCS}/create/database`),
@@ -0,0 +1,29 @@
1
+ /**
2
+ * The ClickHouse statement classifier (#4407): a migration file's statements,
3
+ * each given the class and rule the schema-diff classifier (`./rules.ts`)
4
+ * gives the same change. It reads text and contacts no server.
5
+ *
6
+ * `CREATE` goes through the declaration parser (`../parser.ts`), which also
7
+ * tells the classifier a table's keys when the file creates the table. The
8
+ * parser has no `ALTER` grammar, so `ALTER`, `DROP` and `RENAME` are read word
9
+ * by word from the same tokens.
10
+ *
11
+ * A statement alone cannot decide some changes, and those answer `undecided`
12
+ * naming both rules, the way `./disruption.ts` answers `unknown`:
13
+ *
14
+ * - `MODIFY COLUMN c <type>` is SQLCH210 (a rewrite), or SQLCH211 (a rebuild)
15
+ * when `c` is in a key. The file states the keys only when it creates the
16
+ * table.
17
+ * - `DROP COLUMN` is SQLCH202 or SQLCH213, and `RENAME COLUMN` SQLCH212 or
18
+ * SQLCH213, on the same condition.
19
+ * - `MODIFY ORDER BY` that the same `ALTER` pairs with `ADD COLUMN` is SQLCH216
20
+ * when it only appends those columns and SQLCH220 (a rebuild) otherwise.
21
+ * Without such a column it is SQLCH220.
22
+ */
23
+ import { type StatementVerdict } from "../../core/statement-class.js";
24
+ /**
25
+ * Classify a migration's up statements, in order. The statements are the
26
+ * file's own text, one per entry.
27
+ */
28
+ export declare function classifyClickHouseStatements(statements: readonly string[]): StatementVerdict[];
29
+ //# sourceMappingURL=statements.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"statements.d.ts","sourceRoot":"","sources":["../../../src/clickhouse/plan/statements.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAMH,OAAO,EAAkE,KAAK,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AA0PnI;;;GAGG;AACH,wBAAgB,4BAA4B,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,GAAG,gBAAgB,EAAE,CAwB9F"}