@intentius/chant-lexicon-sql 0.124.46 → 0.124.48

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 (360) 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/stream.d.ts +40 -0
  37. package/dist/clickhouse/plan/stream.d.ts.map +1 -0
  38. package/dist/clickhouse/plan/stream.js +107 -0
  39. package/dist/clickhouse/rebuild/observe.d.ts +3 -1
  40. package/dist/clickhouse/rebuild/observe.d.ts.map +1 -1
  41. package/dist/clickhouse/rebuild/observe.js +14 -1
  42. package/dist/clickhouse/review-catalog.d.ts +213 -0
  43. package/dist/clickhouse/review-catalog.d.ts.map +1 -0
  44. package/dist/clickhouse/review-catalog.js +330 -0
  45. package/dist/codegen/classifier-page.d.ts.map +1 -1
  46. package/dist/codegen/classifier-page.js +21 -4
  47. package/dist/codegen/clickhouse-module.d.ts.map +1 -1
  48. package/dist/codegen/clickhouse-module.js +3 -0
  49. package/dist/codegen/coverage-page.d.ts.map +1 -1
  50. package/dist/codegen/coverage-page.js +5 -3
  51. package/dist/codegen/docs.js +1 -1
  52. package/dist/codegen/postgres-classifier-page.js +1 -1
  53. package/dist/codegen/registry.d.ts.map +1 -1
  54. package/dist/codegen/registry.js +5 -0
  55. package/dist/composites/catalog.d.ts.map +1 -1
  56. package/dist/composites/catalog.js +100 -0
  57. package/dist/composites/clickhouse.d.ts +2 -0
  58. package/dist/composites/clickhouse.d.ts.map +1 -1
  59. package/dist/composites/clickhouse.js +2 -0
  60. package/dist/composites/otel-tables.d.ts +100 -0
  61. package/dist/composites/otel-tables.d.ts.map +1 -0
  62. package/dist/composites/otel-tables.js +282 -0
  63. package/dist/composites/stream-ingest.d.ts +63 -0
  64. package/dist/composites/stream-ingest.d.ts.map +1 -0
  65. package/dist/composites/stream-ingest.js +39 -0
  66. package/dist/coverage/clickhouse.json +1 -1
  67. package/dist/coverage/postgres.json +7 -7
  68. package/dist/coverage.d.ts +16 -6
  69. package/dist/coverage.d.ts.map +1 -1
  70. package/dist/coverage.js +10 -5
  71. package/dist/drizzle-command.d.ts +17 -0
  72. package/dist/drizzle-command.d.ts.map +1 -0
  73. package/dist/drizzle-command.js +91 -0
  74. package/dist/drizzle.d.ts +70 -0
  75. package/dist/drizzle.d.ts.map +1 -0
  76. package/dist/drizzle.js +684 -0
  77. package/dist/files/clickhouse.d.ts.map +1 -1
  78. package/dist/files/clickhouse.js +8 -1
  79. package/dist/files/common.d.ts +13 -0
  80. package/dist/files/common.d.ts.map +1 -1
  81. package/dist/files/common.js +5 -0
  82. package/dist/files/postgres.js +12 -2
  83. package/dist/generated/clickhouse.d.ts +2 -0
  84. package/dist/generated/clickhouse.d.ts.map +1 -1
  85. package/dist/generated/clickhouse.js +2 -0
  86. package/dist/import-parser.d.ts +21 -1
  87. package/dist/import-parser.d.ts.map +1 -1
  88. package/dist/import-parser.js +79 -5
  89. package/dist/index.d.ts +1 -1
  90. package/dist/index.d.ts.map +1 -1
  91. package/dist/index.js +1 -1
  92. package/dist/integrity.json +6 -5
  93. package/dist/lint/post-synth/audit-entries.d.ts.map +1 -1
  94. package/dist/lint/post-synth/audit-entries.js +1 -0
  95. package/dist/lint/post-synth/index.d.ts.map +1 -1
  96. package/dist/lint/post-synth/index.js +2 -0
  97. package/dist/lint/post-synth/sqlch128.d.ts +18 -0
  98. package/dist/lint/post-synth/sqlch128.d.ts.map +1 -0
  99. package/dist/lint/post-synth/sqlch128.js +222 -0
  100. package/dist/lint/rules/postgres-templates.js +2 -2
  101. package/dist/lsp/postgres-template.d.ts.map +1 -1
  102. package/dist/lsp/postgres-template.js +11 -0
  103. package/dist/manifest.json +1 -1
  104. package/dist/mcp/postgres.js +1 -1
  105. package/dist/meta.json +25 -0
  106. package/dist/migrate/from-postgres/detect.d.ts +4 -0
  107. package/dist/migrate/from-postgres/detect.d.ts.map +1 -0
  108. package/dist/migrate/from-postgres/detect.js +7 -0
  109. package/dist/migrate/from-postgres/emit.d.ts +26 -0
  110. package/dist/migrate/from-postgres/emit.d.ts.map +1 -0
  111. package/dist/migrate/from-postgres/emit.js +86 -0
  112. package/dist/migrate/from-postgres/index.d.ts +51 -0
  113. package/dist/migrate/from-postgres/index.d.ts.map +1 -0
  114. package/dist/migrate/from-postgres/index.js +115 -0
  115. package/dist/migrate/from-postgres/translate.d.ts +73 -0
  116. package/dist/migrate/from-postgres/translate.d.ts.map +1 -0
  117. package/dist/migrate/from-postgres/translate.js +261 -0
  118. package/dist/migrate/from-postgres/types.d.ts +51 -0
  119. package/dist/migrate/from-postgres/types.d.ts.map +1 -0
  120. package/dist/migrate/from-postgres/types.js +211 -0
  121. package/dist/migration-replay.d.ts +73 -0
  122. package/dist/migration-replay.d.ts.map +1 -0
  123. package/dist/migration-replay.js +294 -0
  124. package/dist/okf/index.md +6 -0
  125. package/dist/okf/rules/SQLCH128.md +11 -0
  126. package/dist/okf/types/PostgresForeignDataWrapper.md +9 -0
  127. package/dist/okf/types/PostgresForeignServer.md +9 -0
  128. package/dist/okf/types/PostgresOperator.md +9 -0
  129. package/dist/okf/types/PostgresPublication.md +9 -0
  130. package/dist/okf/types/PostgresStatistics.md +9 -0
  131. package/dist/op/activities/postgres-migration.d.ts.map +1 -1
  132. package/dist/op/activities/postgres-migration.js +4 -0
  133. package/dist/op/activity-contracts.d.ts +20 -0
  134. package/dist/op/activity-contracts.d.ts.map +1 -1
  135. package/dist/op/activity-contracts.js +2 -0
  136. package/dist/plugin.d.ts.map +1 -1
  137. package/dist/plugin.js +36 -2
  138. package/dist/postgres/apply/apply.js +8 -1
  139. package/dist/postgres/apply/statements.d.ts.map +1 -1
  140. package/dist/postgres/apply/statements.js +87 -2
  141. package/dist/postgres/constraint-names.d.ts +30 -0
  142. package/dist/postgres/constraint-names.d.ts.map +1 -0
  143. package/dist/postgres/constraint-names.js +72 -0
  144. package/dist/postgres/entities.d.ts +110 -1
  145. package/dist/postgres/entities.d.ts.map +1 -1
  146. package/dist/postgres/entities.js +146 -0
  147. package/dist/postgres/entity-types.d.ts +5 -0
  148. package/dist/postgres/entity-types.d.ts.map +1 -1
  149. package/dist/postgres/entity-types.js +5 -0
  150. package/dist/postgres/import/generator.d.ts.map +1 -1
  151. package/dist/postgres/import/generator.js +50 -2
  152. package/dist/postgres/import/live-export.d.ts.map +1 -1
  153. package/dist/postgres/import/live-export.js +2 -0
  154. package/dist/postgres/live/catalog-kinds.d.ts +14 -0
  155. package/dist/postgres/live/catalog-kinds.d.ts.map +1 -1
  156. package/dist/postgres/live/catalog-kinds.js +206 -0
  157. package/dist/postgres/live/catalog.d.ts +2 -0
  158. package/dist/postgres/live/catalog.d.ts.map +1 -1
  159. package/dist/postgres/live/catalog.js +3 -1
  160. package/dist/postgres/live/describe-resources.d.ts.map +1 -1
  161. package/dist/postgres/live/describe-resources.js +10 -2
  162. package/dist/postgres/migrate/backfill.d.ts +2 -0
  163. package/dist/postgres/migrate/backfill.d.ts.map +1 -1
  164. package/dist/postgres/migrate/backfill.js +7 -1
  165. package/dist/postgres/migrate/carry.d.ts +45 -1
  166. package/dist/postgres/migrate/carry.d.ts.map +1 -1
  167. package/dist/postgres/migrate/carry.js +72 -8
  168. package/dist/postgres/migrate/observe.d.ts +28 -4
  169. package/dist/postgres/migrate/observe.d.ts.map +1 -1
  170. package/dist/postgres/migrate/observe.js +41 -12
  171. package/dist/postgres/migrate/op.d.ts +26 -1
  172. package/dist/postgres/migrate/op.d.ts.map +1 -1
  173. package/dist/postgres/migrate/op.js +3 -1
  174. package/dist/postgres/migrate/steps.d.ts +35 -2
  175. package/dist/postgres/migrate/steps.d.ts.map +1 -1
  176. package/dist/postgres/migrate/steps.js +158 -12
  177. package/dist/postgres/parser.d.ts +72 -1
  178. package/dist/postgres/parser.d.ts.map +1 -1
  179. package/dist/postgres/parser.js +194 -2
  180. package/dist/postgres/plan/deep.d.ts.map +1 -1
  181. package/dist/postgres/plan/deep.js +29 -1
  182. package/dist/postgres/plan/diff.d.ts.map +1 -1
  183. package/dist/postgres/plan/diff.js +39 -1
  184. package/dist/postgres/plan/normalize.d.ts +17 -2
  185. package/dist/postgres/plan/normalize.d.ts.map +1 -1
  186. package/dist/postgres/plan/normalize.js +109 -1
  187. package/dist/postgres/plan/rules.d.ts +1 -0
  188. package/dist/postgres/plan/rules.d.ts.map +1 -1
  189. package/dist/postgres/plan/rules.js +3 -2
  190. package/dist/postgres/plan/schema.js +1 -1
  191. package/dist/postgres/secret-options.d.ts +10 -0
  192. package/dist/postgres/secret-options.d.ts.map +1 -0
  193. package/dist/postgres/secret-options.js +9 -0
  194. package/dist/postgres/testing/roundtrip-schema.d.ts +3 -2
  195. package/dist/postgres/testing/roundtrip-schema.d.ts.map +1 -1
  196. package/dist/postgres/testing/roundtrip-schema.js +13 -1
  197. package/dist/postgres.d.ts +1 -1
  198. package/dist/postgres.d.ts.map +1 -1
  199. package/dist/postgres.js +1 -1
  200. package/dist/rules/audit-entries.ts +1 -0
  201. package/dist/rules/postgres-templates.ts +2 -2
  202. package/dist/rules/sqlch128.ts +230 -0
  203. package/dist/serializer.d.ts +5 -0
  204. package/dist/serializer.d.ts.map +1 -1
  205. package/dist/serializer.js +13 -2
  206. package/dist/sql-types-command.d.ts +13 -0
  207. package/dist/sql-types-command.d.ts.map +1 -1
  208. package/dist/sql-types-command.js +31 -16
  209. package/dist/sql-types.d.ts +22 -0
  210. package/dist/sql-types.d.ts.map +1 -1
  211. package/dist/sql-types.js +10 -6
  212. package/dist/sqlserver/lexer.d.ts +37 -0
  213. package/dist/sqlserver/lexer.d.ts.map +1 -0
  214. package/dist/sqlserver/lexer.js +254 -0
  215. package/dist/sqlserver/parse.d.ts +185 -0
  216. package/dist/sqlserver/parse.d.ts.map +1 -0
  217. package/dist/sqlserver/parse.js +767 -0
  218. package/dist/sqlserver/translate.d.ts +34 -0
  219. package/dist/sqlserver/translate.d.ts.map +1 -0
  220. package/dist/sqlserver/translate.js +495 -0
  221. package/dist/sqlserver/types.d.ts +44 -0
  222. package/dist/sqlserver/types.d.ts.map +1 -0
  223. package/dist/sqlserver/types.js +133 -0
  224. package/dist/sqlserver/validate.d.ts +31 -0
  225. package/dist/sqlserver/validate.d.ts.map +1 -0
  226. package/dist/sqlserver/validate.js +67 -0
  227. package/dist/validate.d.ts.map +1 -1
  228. package/dist/validate.js +5 -0
  229. package/package.json +2 -2
  230. package/src/change-set.ts +2 -1
  231. package/src/clickhouse/apply/statements.ts +25 -0
  232. package/src/clickhouse/import/live-export.ts +20 -5
  233. package/src/clickhouse/live/named-collections.e2e.test.ts +88 -0
  234. package/src/clickhouse/live/named-collections.ts +61 -0
  235. package/src/clickhouse/live/undeclarable.e2e.test.ts +5 -3
  236. package/src/clickhouse/live/undeclarable.ts +20 -4
  237. package/src/clickhouse/named-collections.test.ts +187 -0
  238. package/src/clickhouse/named-collections.ts +224 -0
  239. package/src/clickhouse/parser.ts +2 -1
  240. package/src/clickhouse/plan/commands.ts +17 -2
  241. package/src/clickhouse/plan/diff.ts +57 -1
  242. package/src/clickhouse/plan/disruption.ts +5 -0
  243. package/src/clickhouse/plan/rebuild-handoff.ts +3 -0
  244. package/src/clickhouse/plan/report.ts +6 -1
  245. package/src/clickhouse/plan/rules.ts +14 -4
  246. package/src/clickhouse/plan/stream-s3queue.e2e.test.ts +148 -0
  247. package/src/clickhouse/plan/stream.test.ts +237 -0
  248. package/src/clickhouse/plan/stream.ts +111 -0
  249. package/src/clickhouse/rebuild/observe.ts +15 -1
  250. package/src/clickhouse/review-catalog.test.ts +181 -0
  251. package/src/clickhouse/review-catalog.ts +489 -0
  252. package/src/codegen/classifier-page.ts +21 -4
  253. package/src/codegen/clickhouse-module.ts +3 -0
  254. package/src/codegen/coverage-page.ts +5 -3
  255. package/src/codegen/docs.ts +1 -1
  256. package/src/codegen/postgres-classifier-page.ts +1 -1
  257. package/src/codegen/registry.ts +5 -0
  258. package/src/composites/catalog.test.ts +6 -1
  259. package/src/composites/catalog.ts +100 -0
  260. package/src/composites/clickhouse.ts +2 -0
  261. package/src/composites/composites.test.ts +1 -1
  262. package/src/composites/otel-tables.test.ts +118 -0
  263. package/src/composites/otel-tables.ts +339 -0
  264. package/src/composites/stream-ingest.test.ts +114 -0
  265. package/src/composites/stream-ingest.ts +82 -0
  266. package/src/core/undeclarable.test.ts +6 -5
  267. package/src/coverage/clickhouse.json +1 -1
  268. package/src/coverage/postgres.json +7 -7
  269. package/src/coverage.test.ts +27 -2
  270. package/src/coverage.ts +18 -7
  271. package/src/drizzle-command.ts +94 -0
  272. package/src/drizzle-kit.e2e.test.ts +89 -0
  273. package/src/drizzle-types.e2e.test.ts +67 -0
  274. package/src/drizzle.test.ts +358 -0
  275. package/src/drizzle.ts +737 -0
  276. package/src/files/clickhouse.ts +8 -1
  277. package/src/files/common.ts +14 -1
  278. package/src/files/postgres.ts +12 -2
  279. package/src/generated/clickhouse.ts +3 -0
  280. package/src/generated/lexicon-sql.json +25 -0
  281. package/src/import-parser.sqlserver.test.ts +92 -0
  282. package/src/import-parser.ts +79 -5
  283. package/src/index.ts +1 -1
  284. package/src/lint/post-synth/audit-entries.ts +1 -0
  285. package/src/lint/post-synth/index.ts +2 -0
  286. package/src/lint/post-synth/sqlch128.test.ts +107 -0
  287. package/src/lint/post-synth/sqlch128.ts +230 -0
  288. package/src/lint/rules/postgres-templates.ts +2 -2
  289. package/src/lsp/postgres-template.ts +11 -0
  290. package/src/mcp/postgres.ts +1 -1
  291. package/src/migrate/from-postgres/cli.test.ts +165 -0
  292. package/src/migrate/from-postgres/detect.ts +7 -0
  293. package/src/migrate/from-postgres/emit.ts +96 -0
  294. package/src/migrate/from-postgres/example.test.ts +205 -0
  295. package/src/migrate/from-postgres/index.ts +122 -0
  296. package/src/migrate/from-postgres/translate.test.ts +242 -0
  297. package/src/migrate/from-postgres/translate.ts +359 -0
  298. package/src/migrate/from-postgres/types.test.ts +116 -0
  299. package/src/migrate/from-postgres/types.ts +236 -0
  300. package/src/migrate/from-postgres/validate.e2e.test.ts +44 -0
  301. package/src/migrate/from-postgres/workspace.e2e.test.ts +114 -0
  302. package/src/migration-replay.e2e.test.ts +155 -0
  303. package/src/migration-replay.test.ts +173 -0
  304. package/src/migration-replay.ts +289 -0
  305. package/src/op/__snapshots__/watch-pipeline.test.ts.snap +2 -2
  306. package/src/op/activities/postgres-migration.ts +4 -0
  307. package/src/op/activity-contracts.ts +2 -0
  308. package/src/plugin.ts +37 -2
  309. package/src/postgres/apply/apply.ts +9 -1
  310. package/src/postgres/apply/statements.ts +74 -1
  311. package/src/postgres/constraint-names.ts +71 -0
  312. package/src/postgres/database-kinds.test.ts +384 -0
  313. package/src/postgres/entities.ts +266 -1
  314. package/src/postgres/entity-types.ts +5 -0
  315. package/src/postgres/import/generator.ts +42 -2
  316. package/src/postgres/import/live-export.ts +1 -0
  317. package/src/postgres/live/catalog-kinds.ts +223 -0
  318. package/src/postgres/live/catalog.ts +6 -1
  319. package/src/postgres/live/database-kinds.e2e.test.ts +164 -0
  320. package/src/postgres/live/describe-resources.ts +11 -2
  321. package/src/postgres/live/undeclarable.e2e.test.ts +13 -6
  322. package/src/postgres/migrate/backfill.ts +13 -1
  323. package/src/postgres/migrate/carry.ts +103 -8
  324. package/src/postgres/migrate/followups.e2e.test.ts +218 -0
  325. package/src/postgres/migrate/followups.test.ts +199 -0
  326. package/src/postgres/migrate/kinds.e2e.test.ts +5 -5
  327. package/src/postgres/migrate/observe.ts +53 -14
  328. package/src/postgres/migrate/op.ts +28 -1
  329. package/src/postgres/migrate/partition.e2e.test.ts +129 -0
  330. package/src/postgres/migrate/partition.test.ts +206 -0
  331. package/src/postgres/migrate/steps.ts +157 -12
  332. package/src/postgres/parser.ts +234 -2
  333. package/src/postgres/plan/deep.ts +28 -1
  334. package/src/postgres/plan/diff.ts +36 -1
  335. package/src/postgres/plan/normalize.ts +122 -1
  336. package/src/postgres/plan/rules.ts +10 -3
  337. package/src/postgres/plan/schema.ts +1 -1
  338. package/src/postgres/secret-options.ts +10 -0
  339. package/src/postgres/testing/roundtrip-schema.ts +13 -1
  340. package/src/postgres.ts +16 -0
  341. package/src/serializer.ts +13 -2
  342. package/src/skills/chant-sql-postgres-migration.md +3 -3
  343. package/src/skills/chant-sql-postgres.md +6 -1
  344. package/src/skills/chant-sql.md +2 -1
  345. package/src/sql-types-command.ts +38 -16
  346. package/src/sql-types.ts +11 -6
  347. package/src/sqlserver/fixture.test.ts +186 -0
  348. package/src/sqlserver/import-cli.test.ts +61 -0
  349. package/src/sqlserver/lexer.ts +260 -0
  350. package/src/sqlserver/parse.ts +865 -0
  351. package/src/sqlserver/translate.test.ts +396 -0
  352. package/src/sqlserver/translate.ts +558 -0
  353. package/src/sqlserver/types.test.ts +102 -0
  354. package/src/sqlserver/types.ts +154 -0
  355. package/src/sqlserver/validate.e2e.test.ts +32 -0
  356. package/src/sqlserver/validate.test.ts +49 -0
  357. package/src/sqlserver/validate.ts +76 -0
  358. package/src/validate.ts +5 -0
  359. package/src/workspace-kinds.test.ts +11 -0
  360. package/workspace-kinds.json +100 -2
@@ -0,0 +1,330 @@
1
+ /**
2
+ * The needs-review catalog: the judgment calls that turn a table from another
3
+ * database into a ClickHouse table, each as a finding with the evidence it
4
+ * used. A source reader (`chant import` of SQL Server, #4398; `chant migrate`
5
+ * of Postgres, #4399) does the mechanical work, a type map and a rename,
6
+ * and asks this module for everything that is a decision.
7
+ *
8
+ * Nothing here knows a source dialect. A reader describes its table in the
9
+ * neutral facts below (a candidate sort key, a column's nullability, a
10
+ * constraint) and gets back the ClickHouse choice, a finding to report, and
11
+ * for a constraint the comment lines to keep in the DDL. The rules are the
12
+ * same whichever database the table came from.
13
+ *
14
+ * ## API
15
+ *
16
+ * - {@link sortKeyReview}: `ORDER BY` from the candidates the source offers,
17
+ * in the priority `explicit-order`, `clustering-key`, `primary-key`,
18
+ * `unique-key`, then `tuple()`. Returns `orderBy`, the `settings` the key
19
+ * needs (`allow_nullable_key` when a key column is `Nullable`), and a
20
+ * finding that names the chosen candidate and the others it passed over.
21
+ * - {@link engineReview}: `MergeTree` for an append-only table;
22
+ * `ReplacingMergeTree(_version, _deleted)` for a CDC mirror, with the two
23
+ * columns it adds in `extraColumns`. `cdcColumns` names them otherwise
24
+ * (the Postgres pair uses the `CdcMirror` composite's `_is_deleted`).
25
+ * - {@link nullableReview}: a column's final type. A `NOT NULL` column keeps
26
+ * its type with no finding. A nullable column becomes `Nullable(T)` with a
27
+ * finding; when it has a default the finding says the default could
28
+ * replace `Nullable`.
29
+ * - {@link lowCardinalityReview}: a finding for a `String` column whose name
30
+ * and declared length suggest few distinct values. It never changes the
31
+ * type; offline, the name and the type are all there is to read.
32
+ * - {@link constraintReview}: foreign keys, checks, unique and exclusion
33
+ * constraints, which ClickHouse does not enforce. Returns `comments` (SQL `--` lines to
34
+ * put before the `CREATE`) and one finding per constraint.
35
+ * - {@link REVIEW_RULES}: every rule id with its summary and the ClickHouse
36
+ * documentation it rests on, for report metadata.
37
+ * - {@link findingText}: a finding as one line (object, message, evidence,
38
+ * suggestion), the form a SARIF `message` takes.
39
+ *
40
+ * A finding's `severity` is `warning` for a decision the author must confirm
41
+ * and `info` for a note that changes nothing. The caller maps findings to its
42
+ * own diagnostic type; `at` carries the source line and column when the
43
+ * reader knows them.
44
+ *
45
+ * Every ClickHouse type and engine this module writes is checked against the
46
+ * pinned catalog (`src/generated/clickhouse.ts`, ClickHouse 26.8) in
47
+ * `review-catalog.test.ts`, so a pin move that drops one fails there.
48
+ *
49
+ * Sources: the MergeTree sorting key and `allow_nullable_key`
50
+ * (https://clickhouse.com/docs/engines/table-engines/mergetree-family/mergetree),
51
+ * `ReplacingMergeTree(ver, is_deleted)`
52
+ * (https://clickhouse.com/docs/engines/table-engines/mergetree-family/replacingmergetree),
53
+ * `Nullable` (https://clickhouse.com/docs/sql-reference/data-types/nullable),
54
+ * `LowCardinality`
55
+ * (https://clickhouse.com/docs/sql-reference/data-types/lowcardinality).
56
+ */
57
+ const CH_MERGETREE = "https://clickhouse.com/docs/engines/table-engines/mergetree-family/mergetree";
58
+ /**
59
+ * The rules. SQLRV001 to SQLRV005 are the shared ones; the rest are raised by
60
+ * a source reader for what only its dialect has, and live here so a report
61
+ * lists one catalog.
62
+ */
63
+ export const REVIEW_RULES = {
64
+ SQLRV001: {
65
+ id: "SQLRV001",
66
+ name: "sort-key",
67
+ summary: "The ORDER BY key is a suggestion from the source's indexes.",
68
+ docs: [CH_MERGETREE],
69
+ },
70
+ SQLRV002: {
71
+ id: "SQLRV002",
72
+ name: "engine",
73
+ summary: "The table engine is a choice the source does not make.",
74
+ docs: [CH_MERGETREE, "https://clickhouse.com/docs/engines/table-engines/mergetree-family/replacingmergetree"],
75
+ },
76
+ SQLRV003: {
77
+ id: "SQLRV003",
78
+ name: "nullable",
79
+ summary: "A nullable column becomes Nullable(T), which costs storage and speed; a default can replace it.",
80
+ docs: ["https://clickhouse.com/docs/sql-reference/data-types/nullable"],
81
+ },
82
+ SQLRV004: {
83
+ id: "SQLRV004",
84
+ name: "low-cardinality",
85
+ summary: "A String column that may hold few distinct values could be LowCardinality(String).",
86
+ docs: ["https://clickhouse.com/docs/sql-reference/data-types/lowcardinality"],
87
+ },
88
+ SQLRV005: {
89
+ id: "SQLRV005",
90
+ name: "constraint",
91
+ summary: "ClickHouse does not enforce this constraint; it is kept as a comment.",
92
+ docs: ["https://clickhouse.com/docs/sql-reference/statements/create/table"],
93
+ },
94
+ SQLRV006: {
95
+ id: "SQLRV006",
96
+ name: "generated-column",
97
+ summary: "An identity, sequence, computed or system-generated column has no ClickHouse equivalent.",
98
+ docs: ["https://clickhouse.com/docs/sql-reference/statements/create/table"],
99
+ },
100
+ SQLRV007: {
101
+ id: "SQLRV007",
102
+ name: "type-judgment",
103
+ summary: "The type has no exact ClickHouse match; the nearest one was chosen.",
104
+ docs: ["https://clickhouse.com/docs/sql-reference/data-types"],
105
+ },
106
+ SQLRV008: {
107
+ id: "SQLRV008",
108
+ name: "default-expression",
109
+ summary: "A default expression was translated or dropped.",
110
+ docs: ["https://clickhouse.com/docs/sql-reference/statements/create/table"],
111
+ },
112
+ SQLRV009: {
113
+ id: "SQLRV009",
114
+ name: "storage-option",
115
+ summary: "A storage option of the source (filegroup, partitioning, compression, versioning) has no counterpart here.",
116
+ docs: [CH_MERGETREE],
117
+ },
118
+ SQLRV010: {
119
+ id: "SQLRV010",
120
+ name: "query-text",
121
+ summary: "A view body is copied as written and is not translated.",
122
+ docs: ["https://clickhouse.com/docs/sql-reference/statements/create/view"],
123
+ },
124
+ SQLRV011: {
125
+ id: "SQLRV011",
126
+ name: "not-carried",
127
+ summary: "An object or statement of the source is not carried over, and is named here.",
128
+ docs: [],
129
+ },
130
+ SQLRV012: {
131
+ id: "SQLRV012",
132
+ name: "emulator-rejected",
133
+ summary: "The ClickHouse emulator refused a statement the import would write.",
134
+ docs: [],
135
+ },
136
+ };
137
+ /** A finding as one line. */
138
+ export function findingText(f) {
139
+ const where = f.column ? `${f.object}.${f.column}` : f.object;
140
+ const parts = [`${where}: ${f.message}`];
141
+ if (f.evidence.length > 0)
142
+ parts.push(`Evidence: ${f.evidence.join("; ")}.`);
143
+ if (f.suggestion)
144
+ parts.push(`Suggestion: ${f.suggestion}`);
145
+ return parts.join(" ");
146
+ }
147
+ const q = (name) => (/^[A-Za-z_][A-Za-z0-9_]*$/.test(name) ? name : `\`${name.replace(/`/g, "\\`")}\``);
148
+ const list = (names) => names.join(", ");
149
+ const SORT_KEY_PRIORITY = ["explicit-order", "clustering-key", "primary-key", "unique-key"];
150
+ export function sortKeyReview(input) {
151
+ const ranked = SORT_KEY_PRIORITY.flatMap((kind) => input.candidates.filter((c) => c.kind === kind && c.columns.length > 0));
152
+ const chosen = ranked[0];
153
+ const evidence = [];
154
+ const settings = {};
155
+ let orderBy = [];
156
+ let message;
157
+ let suggestion;
158
+ if (chosen) {
159
+ orderBy = [...chosen.columns];
160
+ evidence.push(`${chosen.source} (${list(chosen.columns)})`);
161
+ for (const other of ranked.slice(1))
162
+ evidence.push(`passed over: ${other.source} (${list(other.columns)})`);
163
+ if (chosen.descending && chosen.descending.length > 0)
164
+ evidence.push(`descending in the source, ascending here: ${list(chosen.descending)}`);
165
+ const nullable = orderBy.filter((c) => (input.columnTypes[c] ?? "").startsWith("Nullable("));
166
+ if (nullable.length > 0) {
167
+ settings.allow_nullable_key = "1";
168
+ evidence.push(`Nullable key column${nullable.length > 1 ? "s" : ""}: ${list(nullable)}, so allow_nullable_key = 1 is set`);
169
+ }
170
+ message = `ORDER BY (${list(orderBy.map(q))}) suggested from the ${chosen.kind.replace("-", " ")}.`;
171
+ suggestion = "Put the columns your queries filter on first, and the one with the fewest distinct values before the one with the most.";
172
+ }
173
+ else {
174
+ orderBy = [];
175
+ evidence.push("no clustering key, primary key or unique key in the source");
176
+ message = "ORDER BY tuple() used because the source gives no key to suggest.";
177
+ suggestion = "Choose the columns your queries filter on; a MergeTree table without a sort key cannot skip granules.";
178
+ }
179
+ return {
180
+ orderBy,
181
+ settings,
182
+ finding: { ruleId: "SQLRV001", severity: "warning", object: input.object, message, evidence, ...(suggestion ? { suggestion } : {}), ...(input.at ? { at: input.at } : {}) },
183
+ };
184
+ }
185
+ export const CDC_VERSION_COLUMN = { name: "_version", type: "UInt64" };
186
+ export const CDC_DELETED_COLUMN = { name: "_deleted", type: "UInt8" };
187
+ export function engineReview(input) {
188
+ const evidence = [...(input.facts ?? [])];
189
+ const unique = input.uniqueKey && input.uniqueKey.length > 0 ? list(input.uniqueKey) : undefined;
190
+ if (input.mode === "cdc") {
191
+ evidence.push(`the table is mirrored from a source that updates rows in place${unique ? `, keyed on (${unique})` : ""}`);
192
+ const version = input.cdcColumns?.version ?? CDC_VERSION_COLUMN.name;
193
+ const deleted = input.cdcColumns?.deleted ?? CDC_DELETED_COLUMN.name;
194
+ return {
195
+ engine: `ReplacingMergeTree(${version}, ${deleted})`,
196
+ extraColumns: [
197
+ { name: version, type: CDC_VERSION_COLUMN.type },
198
+ { name: deleted, type: CDC_DELETED_COLUMN.type },
199
+ ],
200
+ finding: {
201
+ ruleId: "SQLRV002",
202
+ severity: "warning",
203
+ object: input.object,
204
+ message: `ReplacingMergeTree(${version}, ${deleted}) chosen for a mirror; it adds the columns ${version} and ${deleted}.`,
205
+ evidence,
206
+ suggestion: `The sort key must be the source key, because rows with an equal sort key collapse to the highest ${version} on merge. Read with FINAL, or filter on ${deleted}, to see the collapsed rows before a merge.`,
207
+ ...(input.at ? { at: input.at } : {}),
208
+ },
209
+ };
210
+ }
211
+ if (unique)
212
+ evidence.push(`the source enforces uniqueness on (${unique}); MergeTree does not`);
213
+ return {
214
+ engine: "MergeTree",
215
+ extraColumns: [],
216
+ finding: {
217
+ ruleId: "SQLRV002",
218
+ severity: "warning",
219
+ object: input.object,
220
+ message: "MergeTree chosen; the source has no engine to carry over.",
221
+ evidence,
222
+ suggestion: unique
223
+ ? "If rows can arrive twice, ReplacingMergeTree collapses duplicates of the sort key on merge, not on insert."
224
+ : "Pick another MergeTree variant for pre-aggregation (SummingMergeTree, AggregatingMergeTree) when the table is a rollup.",
225
+ ...(input.at ? { at: input.at } : {}),
226
+ },
227
+ };
228
+ }
229
+ export function nullableReview(input) {
230
+ if (!input.sourceNullable)
231
+ return { type: input.type };
232
+ const evidence = [`${input.column} allows NULL in the source`];
233
+ let suggestion;
234
+ if (input.defaultExpr !== undefined) {
235
+ evidence.push(`it has the default ${input.defaultExpr}`);
236
+ suggestion = `If NULL is never stored on purpose, declare ${input.type} DEFAULT ${input.defaultExpr} and load the default instead of NULL.`;
237
+ }
238
+ else {
239
+ evidence.push("it has no default");
240
+ suggestion = `If a sentinel value can stand for missing, declare ${input.type} DEFAULT <sentinel>; a Nullable column keeps a separate null mask.`;
241
+ }
242
+ return {
243
+ type: `Nullable(${input.type})`,
244
+ finding: {
245
+ ruleId: "SQLRV003",
246
+ severity: "warning",
247
+ object: input.object,
248
+ column: input.column,
249
+ message: `Kept as Nullable(${input.type}) so no stored NULL is lost.`,
250
+ evidence,
251
+ suggestion,
252
+ ...(input.at ? { at: input.at } : {}),
253
+ },
254
+ };
255
+ }
256
+ // --- LowCardinality -------------------------------------------------------
257
+ /** Last words of a column name that usually mean a small set of values. */
258
+ const LOW_CARDINALITY_WORDS = new Set("status state type kind category country currency region level channel gender lang language locale unit code flag method mode grade tier priority".split(" "));
259
+ /** A column name's last word: `order_status` and `OrderStatus` both give `status`. */
260
+ function lastWord(name) {
261
+ const words = name.replace(/([a-z0-9])([A-Z])/g, "$1_$2").split(/[^A-Za-z0-9]+/).filter(Boolean);
262
+ return (words[words.length - 1] ?? "").toLowerCase();
263
+ }
264
+ /** The longest declared length that still counts as supporting evidence. */
265
+ export const LOW_CARDINALITY_MAX_LENGTH = 50;
266
+ export function lowCardinalityReview(input) {
267
+ if (input.type !== "String" && input.type !== "Nullable(String)")
268
+ return undefined;
269
+ if (!LOW_CARDINALITY_WORDS.has(lastWord(input.column)))
270
+ return undefined;
271
+ const evidence = [`the name ${input.column} ends in a word that usually names a small set of values`, `the type is ${input.type}`];
272
+ if (input.maxLength !== undefined && input.maxLength <= LOW_CARDINALITY_MAX_LENGTH)
273
+ evidence.push(`the declared length is ${String(input.maxLength)}`);
274
+ evidence.push("no data was read, so the distinct count is unknown");
275
+ const wrapped = input.type.startsWith("Nullable(") ? "LowCardinality(Nullable(String))" : "LowCardinality(String)";
276
+ return {
277
+ ruleId: "SQLRV004",
278
+ severity: "warning",
279
+ object: input.object,
280
+ column: input.column,
281
+ message: `${input.column} is a LowCardinality candidate and stays ${input.type}.`,
282
+ evidence,
283
+ suggestion: `ClickHouse documents ${wrapped} as helpful below roughly ten thousand distinct values; count them with uniqExact(${q(input.column)}) before changing the type.`,
284
+ ...(input.at ? { at: input.at } : {}),
285
+ };
286
+ }
287
+ const oneLine = (s) => s.replace(/\s+/g, " ").trim();
288
+ export function constraintReview(input) {
289
+ const comments = [];
290
+ const findings = [];
291
+ for (const c of input.constraints) {
292
+ const label = c.name ? ` ${c.name}` : "";
293
+ let text;
294
+ let message;
295
+ let suggestion;
296
+ if (c.kind === "foreign-key") {
297
+ const target = c.references ? `${c.references.table} (${list(c.references.columns)})` : "an unknown table";
298
+ text = `FOREIGN KEY${label} (${list(c.columns ?? [])}) REFERENCES ${target}`;
299
+ message = `Foreign key${label} is not enforced by ClickHouse and is kept as a comment.`;
300
+ suggestion = "Check referential integrity in the load pipeline, or join on the column and accept orphan rows.";
301
+ }
302
+ else if (c.kind === "unique") {
303
+ text = `UNIQUE${label} (${list(c.columns ?? [])})`;
304
+ message = `Unique constraint${label} is not enforced by ClickHouse and is kept as a comment.`;
305
+ suggestion = "A MergeTree sort key does not make rows unique. ReplacingMergeTree collapses duplicates on merge only.";
306
+ }
307
+ else if (c.kind === "exclusion") {
308
+ text = `EXCLUDE${label} ${oneLine(c.expression ?? "")}`;
309
+ message = `Exclusion constraint${label} is not enforced by ClickHouse and is kept as a comment.`;
310
+ suggestion = "ClickHouse has no constraint that rejects overlapping rows. Check for overlaps in the load, or in a query.";
311
+ }
312
+ else {
313
+ text = `CHECK${label} ${oneLine(c.expression ?? "")}`;
314
+ message = `Check constraint${label} is not translated and is kept as a comment.`;
315
+ suggestion = "ClickHouse has CONSTRAINT name CHECK expr, enforced on INSERT. Rewrite the expression in ClickHouse SQL to use it.";
316
+ }
317
+ comments.push(`-- ${oneLine(text)}`);
318
+ findings.push({
319
+ ruleId: "SQLRV005",
320
+ severity: "warning",
321
+ object: input.object,
322
+ ...(c.kind !== "check" && c.kind !== "exclusion" && c.columns && c.columns.length === 1 ? { column: c.columns[0] } : {}),
323
+ message,
324
+ evidence: [oneLine(text)],
325
+ suggestion,
326
+ ...(c.at ? { at: c.at } : {}),
327
+ });
328
+ }
329
+ return { comments, findings };
330
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"classifier-page.d.ts","sourceRoot":"","sources":["../../src/codegen/classifier-page.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAcH,wBAAgB,oBAAoB,IAAI,MAAM,CAiF7C"}
1
+ {"version":3,"file":"classifier-page.d.ts","sourceRoot":"","sources":["../../src/codegen/classifier-page.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAeH,wBAAgB,oBAAoB,IAAI,MAAM,CAiG7C"}
@@ -8,6 +8,7 @@ const LABEL = {
8
8
  drop: "drop",
9
9
  metadata: "metadata only",
10
10
  rewrite: "background rewrite",
11
+ replace: "replace table",
11
12
  rebuild: "rebuild",
12
13
  };
13
14
  const cell = (s) => s.replace(/\|/g, "\\|");
@@ -16,7 +17,7 @@ export function renderClassifierPage() {
16
17
  return `---
17
18
  title: "Planning ClickHouse Changes"
18
19
  label: "Planning and the Change Classifier"
19
- description: "How a ClickHouse schema change is classified as metadata only, a background rewrite or a rebuild, each with the ALTER restriction behind it"
20
+ description: "How a ClickHouse schema change is classified as metadata only, a background rewrite, a replacement or a rebuild, each with the ALTER restriction behind it"
20
21
  diataxis: reference
21
22
  group: "ClickHouse"
22
23
  order: 1
@@ -30,9 +31,10 @@ Every change between two ClickHouse schemas is classified before anything runs:
30
31
  |---|---|
31
32
  | metadata only | the server records the change and touches no existing data |
32
33
  | background rewrite | a mutation rewrites existing parts in the background, with no rollback |
34
+ | replace table | ClickHouse cannot alter a stream-engine table, and it stores no rows, so the applier drops and creates it around the views that read it |
33
35
  | rebuild | ClickHouse cannot make the change to the existing table, and the data has to be copied into a new one; a plan refuses to make it in place |
34
36
 
35
- Two commands report the classification, and \`chant lifecycle plan\` reports it as each update's disruption (metadata only is \`in-place\`, a rewrite \`rolling\`, a rebuild \`replace\`):
37
+ Two commands report the classification, and \`chant lifecycle plan\` reports it as each update's disruption (metadata only is \`in-place\`, a rewrite \`rolling\`, a replacement or a rebuild \`replace\`):
36
38
 
37
39
  \`\`\`bash
38
40
  chant sql diff base.json head.json # two chant build outputs, offline
@@ -41,13 +43,28 @@ chant sql plan prod schema.json # a build output against the prod server
41
43
 
42
44
  Both exit 2 when a change needs a rebuild. \`chant sql diff\` compares a pull request's base and head builds with no server. \`chant sql plan\` reads the server \`sql.profiles.<env>\` binds, and asks that server's formatter about any expression the normalization rules leave different, so the server's own rewriting (\`INTERVAL 1 DAY\` as \`toIntervalDay(1)\`, \`a+b*2\` as \`a + (b * 2)\`) is not reported as a change.
43
45
 
44
- \`chant sql plan\` also exits 2 when a declared database holds an object whose definition it cannot read. It names each one under \`Refused\` (\`unreadable\` in \`--json\`) instead of leaving it out. Dictionaries are read and planned like the other objects: any change but a comment replaces one (SQLCH245).
46
+ \`chant sql plan\` also exits 2 when a declared database holds an object whose definition it cannot read. It names each one under \`Refused\` (\`unreadable\` in \`--json\`) instead of leaving it out. It exits 2 as well when the build names a named collection the server doesn't have, naming each under \`Refused\` (\`namedCollections.missing\` in \`--json\`); see [Named collections](../clickhouse-ddl/#named-collections). Dictionaries are read and planned like the other objects: any change but a comment replaces one (SQLCH245).
45
47
 
46
48
  A clause chant's parser does not know ([Plain .sql Files](../sql-files/#clauses-chant-does-not-read)) is compared as text, and the rest of its object is planned as usual. A change to one is SQLCH290, refused for review with no rebuild Op suggested, since chant cannot tell what the change takes. A clause only the server prints is a hint, not a change: a newer server printing a clause with its default looks the same as a clause removed from the declaration.
47
49
 
50
+ ## Stream tables
51
+
52
+ A table on Kafka, S3Queue, AzureQueue, RabbitMQ, NATS or FileLog stores no rows. It is the consumer that a materialized view reads through, and the position it has reached lives in the broker's committed offsets or in Keeper. There is no \`ALTER\` for its engine arguments, settings or columns, and there is nothing to copy, so a change to one is neither metadata nor a rebuild. It is SQLCH225, in the replace class (\`diffStreamTable\` in \`src/clickhouse/plan/diff.ts\`). The plan refuses nothing for it.
53
+
54
+ The applier makes the change in place, in this order (\`replaceStreamSteps\` in \`src/clickhouse/apply/statements.ts\`): \`DETACH TABLE\` for each materialized view on the server that reads the table, \`DROP TABLE ... SYNC\`, the declared \`CREATE TABLE\`, then \`ATTACH TABLE\` for the same views. The plan names the views in a hint. Messages wait in the broker, and files wait in the bucket, while the views are detached. A change that moves a table to or from a stream engine is still SQLCH223, a rebuild, and \`ClickHouseRebuildOp\` refuses a stream-engine table by name (\`streamRefusal\` in \`src/clickhouse/rebuild/observe.ts\`).
55
+
56
+ Two replacements lose the table's position, and the change carries a note saying so (\`positionWarnings\` in \`src/clickhouse/plan/stream.ts\`):
57
+
58
+ - A different \`kafka_group_name\`, as a setting or as the third engine argument, is a different consumer group. It starts from its own committed offsets, or from the start of the topic when it has none.
59
+ - A different S3Queue \`keeper_path\` is a different record of processed files. Every file already seen is processed again.
60
+
61
+ An apply killed between the detach and the attach leaves the views detached, and a detached view is not in \`system.tables\`. Nothing re-attaches it: run \`ATTACH TABLE\` for each view by hand, then plan again. This has not been run against a server.
62
+
63
+ The \`StreamIngest\` composite declares the stream table, the view and the MergeTree target together: see [Composites](../composites/#streamingest).
64
+
48
65
  ## After the plan
49
66
 
50
- The plan only reports. [\`clickhouseApply\`](../applying/) makes the metadata-only and background-rewrite changes, and refuses a rebuild the same way the plan does, sending nothing for that object. A rebuild runs as \`ClickHouseRebuildOp\`, a gated migration Op that creates the new table, backfills it, verifies it and swaps it in: see [Rebuilding a Table](../rebuild/). Both commands print the Op declaration to start from for each refused table.
67
+ The plan only reports. [\`clickhouseApply\`](../applying/) makes the metadata-only, background-rewrite and stream-table changes, and refuses a rebuild the same way the plan does, sending nothing for that object. A rebuild runs as \`ClickHouseRebuildOp\`, a gated migration Op that creates the new table, backfills it, verifies it and swaps it in: see [Rebuilding a Table](../rebuild/). Both commands print the Op declaration to start from for each refused table.
51
68
 
52
69
  \`chant migrate\` plays no part in any of this. It translates a file from one lexicon's format into another's, such as a GitHub Actions workflow into GitLab CI, and does not run schema migrations.
53
70
 
@@ -1 +1 @@
1
- {"version":3,"file":"clickhouse-module.d.ts","sourceRoot":"","sources":["../../src/codegen/clickhouse-module.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAc,MAAM,iBAAiB,CAAC;AA6BrE,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAElD;AAmED,MAAM,WAAW,cAAc;IAC7B,0GAA0G;IAC1G,YAAY,EAAE,MAAM,CAAC;IACrB,0EAA0E;IAC1E,MAAM,EAAE,MAAM,CAAC;IACf,qDAAqD;IACrD,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,iBAAiB,GAAG,cAAc,CAmKjF"}
1
+ {"version":3,"file":"clickhouse-module.d.ts","sourceRoot":"","sources":["../../src/codegen/clickhouse-module.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAc,MAAM,iBAAiB,CAAC;AA6BrE,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAElD;AAmED,MAAM,WAAW,cAAc;IAC7B,0GAA0G;IAC1G,YAAY,EAAE,MAAM,CAAC;IACrB,0EAA0E;IAC1E,MAAM,EAAE,MAAM,CAAC;IACf,qDAAqD;IACrD,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,iBAAiB,GAAG,cAAc,CAsKjF"}
@@ -236,6 +236,9 @@ export function renderClickHouseModule(catalog) {
236
236
  `/** The table functions (\`system.table_functions\`): \`numbers\`, \`remote\`, \`s3\`. */`,
237
237
  `export const TABLE_FUNCTIONS: readonly string[] = ${JSON.stringify(catalog.tableFunctions)};`,
238
238
  "",
239
+ `/** The input and output formats (\`system.formats\`): \`Parquet\`, \`JSONEachRow\`. */`,
240
+ `export const FORMATS: readonly string[] = ${JSON.stringify(catalog.formats.map((f) => f.name))};`,
241
+ "",
239
242
  `export const SKIP_INDEX_TYPES: Readonly<Record<SkipIndexType, SkipIndexSpec>> = {`,
240
243
  ...indexLines,
241
244
  "};",
@@ -1 +1 @@
1
- {"version":3,"file":"coverage-page.d.ts","sourceRoot":"","sources":["../../src/codegen/coverage-page.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AA4BH,wBAAgB,kBAAkB,IAAI,MAAM,CA4C3C"}
1
+ {"version":3,"file":"coverage-page.d.ts","sourceRoot":"","sources":["../../src/codegen/coverage-page.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AA6BH,wBAAgB,kBAAkB,IAAI,MAAM,CA6C3C"}
@@ -5,7 +5,7 @@
5
5
  */
6
6
  import { KIND_COVERAGE, PINNED_COMMANDS } from "../coverage.js";
7
7
  const cell = (s) => s.replace(/\|/g, "\\|").replace(/[{}<>]/g, (c) => `\\${c}`);
8
- const STATUS = { declared: "declared", refused: "refused", "out-of-scope": "out of scope" };
8
+ const STATUS = { declared: "declared", referenced: "referenced", refused: "refused", "out-of-scope": "out of scope" };
9
9
  function table(dialect) {
10
10
  const rows = [...KIND_COVERAGE[dialect]].sort((a, b) => (a.command < b.command ? -1 : a.command > b.command ? 1 : 0));
11
11
  return [
@@ -21,7 +21,8 @@ function table(dialect) {
21
21
  function counts(dialect) {
22
22
  const rows = KIND_COVERAGE[dialect];
23
23
  const n = (s) => rows.filter((r) => r.status === s).length;
24
- return `${n("declared")} declared, ${n("refused")} refused, ${n("out-of-scope")} out of scope`;
24
+ const referenced = n("referenced") > 0 ? `, ${n("referenced")} referenced` : "";
25
+ return `${n("declared")} declared${referenced}, ${n("refused")} refused, ${n("out-of-scope")} out of scope`;
25
26
  }
26
27
  export function renderCoveragePage() {
27
28
  const pg = PINNED_COMMANDS.postgres.map((p) => p.version).join(", ");
@@ -29,7 +30,7 @@ export function renderCoveragePage() {
29
30
  return `---
30
31
  title: "Object Coverage"
31
32
  label: "Object Coverage"
32
- description: "Every kind of object each pinned Postgres and ClickHouse server can create, marked declared, refused with a reason, or out of scope, and what import does with each"
33
+ description: "Every kind of object each pinned Postgres and ClickHouse server can create, marked declared, referenced, refused with a reason, or out of scope, and what import does with each"
33
34
  diataxis: reference
34
35
  order: 3
35
36
  ---
@@ -39,6 +40,7 @@ order: 3
39
40
  Each row is a \`CREATE\` command a pinned server has, or one form of a command where chant treats the forms apart (\`CREATE TYPE ... AS ENUM\` is declared, \`CREATE TYPE ... AS RANGE\` is not). The commands come from the servers' own sources at each pinned version (\`scripts/sql-create-commands.ts\`), and a test fails when a pinned server has a command with no row here, so a new server release cannot add a kind nobody looked at.
40
41
 
41
42
  - **declared**: a tag declares it, and import writes it as that declaration.
43
+ - **referenced**: the environment's, and never declared: a declaration names one, and chant never reads its values. A ClickHouse named collection is one ([#4395](https://github.com/INTENTIUS/chant/issues/4395)): \`ENGINE = S3(lake_creds, format = 'Parquet')\` names \`lake_creds\`, the build records the name, and \`chant sql plan\` fails when the server has no collection of that name. \`chant import --from <env>\` lists the server's SQL-defined collections as prerequisites and imports the rest. See [Named collections](../clickhouse-ddl/#named-collections).
42
44
  - **refused**: no declaration holds it yet. \`chant import --from <env>\` fails when the server has one, naming every such object (kind, schema, name) at once, and \`chant import schema.sql\` fails on the statement. Nothing is left out without a word.
43
45
  - **out of scope**: the environment's, not a schema's: import never reads it.
44
46
 
@@ -120,7 +120,7 @@ Postgres:
120
120
  - [Getting Started with Postgres](./postgres-getting-started/): declare a
121
121
  schema, apply it to a local server, add a column and an index, and see a
122
122
  rename refused.
123
- - [Declaring Postgres Objects](./postgres-ddl/): the eight tags,
123
+ - [Declaring Postgres Objects](./postgres-ddl/): the tags for every schema-level kind,
124
124
  constraints, \`nextval(\${seq})\`, \`COMMENT ON\` and \`literal()\`.
125
125
  - [Importing a Postgres Server](./postgres-importing/): canonical text from
126
126
  the catalog's printers, and the objects that belong to someone else.
@@ -67,7 +67,7 @@ Two rules change class across the supported majors: a STORED generated column's
67
67
 
68
68
  ## Identity and renames
69
69
 
70
- An object is identified by its export name between two builds, and by its schema-qualified name against a server, which has no export names. Tables, views, materialized views, sequences and indexes share one namespace per schema, types and domains another, and schemas and extensions are matched by name. Functions, procedures and aggregates share a namespace of their own and are told apart by their input parameter types, so an overload is another object; composite and range types share the types' namespace, collations have one of their own, a cast is named by its two types and an event trigger by its name in the database; a trigger is matched by its name on its table.
70
+ An object is identified by its export name between two builds, and by its schema-qualified name against a server, which has no export names. Tables, views, materialized views, sequences and indexes share one namespace per schema, types and domains another, and schemas and extensions are matched by name. Functions, procedures and aggregates share a namespace of their own and are told apart by their input parameter types, so an overload is another object; composite and range types share the types' namespace, collations have one of their own, extended statistics another, an operator by its symbol and operand types, a cast by its two types and an event trigger, a foreign data wrapper, a foreign server and a publication by their names in the database; a trigger is matched by its name on its table.
71
71
 
72
72
  A rename is declared where it happens. Before a CREATE, \`-- previously: <old name>\` says the object had another name; on a column's line, it says the column did:
73
73
 
@@ -1 +1 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/codegen/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AA0CH,wBAAgB,aAAa,IAAI,MAAM,CAKtC"}
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/codegen/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AA+CH,wBAAgB,aAAa,IAAI,MAAM,CAKtC"}
@@ -37,6 +37,11 @@ const KINDS = {
37
37
  PostgresCollation: POSTGRES_ENTITY_TYPES.collation,
38
38
  PostgresCast: POSTGRES_ENTITY_TYPES.cast,
39
39
  PostgresEventTrigger: POSTGRES_ENTITY_TYPES.eventTrigger,
40
+ PostgresOperator: POSTGRES_ENTITY_TYPES.operator,
41
+ PostgresStatistics: POSTGRES_ENTITY_TYPES.statistics,
42
+ PostgresForeignDataWrapper: POSTGRES_ENTITY_TYPES.foreignDataWrapper,
43
+ PostgresForeignServer: POSTGRES_ENTITY_TYPES.foreignServer,
44
+ PostgresPublication: POSTGRES_ENTITY_TYPES.publication,
40
45
  PostgresExtension: POSTGRES_ENTITY_TYPES.extension,
41
46
  PostgresFunction: POSTGRES_ENTITY_TYPES.function,
42
47
  PostgresProcedure: POSTGRES_ENTITY_TYPES.procedure,
@@ -1 +1 @@
1
- {"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../src/composites/catalog.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE/D,eAAO,MAAM,gBAAgB,EAAE,cAAc,EA2gB5C,CAAC"}
1
+ {"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../src/composites/catalog.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE/D,eAAO,MAAM,gBAAgB,EAAE,cAAc,EA+mB5C,CAAC"}
@@ -210,6 +210,41 @@ export const compositeCatalog = [
210
210
  }
211
211
  ]
212
212
  },
213
+ {
214
+ "name": "OtelTables",
215
+ "lexicon": "sql",
216
+ "description": "The logs, traces and metrics tables the OpenTelemetry Collector's clickhouse exporter writes, as it creates them at v0.130.0.",
217
+ "bundles": [
218
+ "ClickHouseTable",
219
+ "ClickHouseView"
220
+ ],
221
+ "params": [
222
+ {
223
+ "name": "database",
224
+ "type": "string",
225
+ "required": false,
226
+ "description": "The database the tables are created in, the exporter's `database`."
227
+ },
228
+ {
229
+ "name": "ttl",
230
+ "type": "string",
231
+ "required": false,
232
+ "description": "How long rows are kept, as the exporter's `ttl` takes it: a Go duration such as `72h` or `30m`."
233
+ },
234
+ {
235
+ "name": "tables",
236
+ "type": "OtelTableNames",
237
+ "required": false,
238
+ "description": "Table names other than the exporter's defaults, as set on the exporter."
239
+ },
240
+ {
241
+ "name": "traceIdLookup",
242
+ "type": "boolean",
243
+ "required": false,
244
+ "description": "Declare the trace-id lookup table and its materialized view (default true)."
245
+ }
246
+ ]
247
+ },
213
248
  {
214
249
  "name": "RefreshedView",
215
250
  "lexicon": "sql",
@@ -468,6 +503,71 @@ export const compositeCatalog = [
468
503
  }
469
504
  ]
470
505
  },
506
+ {
507
+ "name": "StreamIngest",
508
+ "lexicon": "sql",
509
+ "description": "A stream table, the materialized view that reads it, and the MergeTree target the view writes.",
510
+ "bundles": [
511
+ "ClickHouseTable",
512
+ "ClickHouseView"
513
+ ],
514
+ "params": [
515
+ {
516
+ "name": "name",
517
+ "type": "string",
518
+ "required": true,
519
+ "description": "The target table's name."
520
+ },
521
+ {
522
+ "name": "columns",
523
+ "type": "string",
524
+ "required": true,
525
+ "description": "The target's columns, as SQL: `ts DateTime, user_id UInt64, kind LowCardinality(String)`."
526
+ },
527
+ {
528
+ "name": "engine",
529
+ "type": "string",
530
+ "required": true,
531
+ "description": "The stream table's engine, with a named collection as its first argument rather than inline credentials: `Kafka(kafka_creds)`, `S3Queue(lake_creds)`."
532
+ },
533
+ {
534
+ "name": "settings",
535
+ "type": "string",
536
+ "required": false,
537
+ "description": "The engine's settings, the body of a `SETTINGS` clause: `kafka_topic_list = 'events', kafka_group_name = 'ingest', kafka_format = 'JSONEachRow'`."
538
+ },
539
+ {
540
+ "name": "streamColumns",
541
+ "type": "string",
542
+ "required": false,
543
+ "description": "The stream table's columns when they differ from the target's: the message as it arrives."
544
+ },
545
+ {
546
+ "name": "select",
547
+ "type": "string",
548
+ "required": false,
549
+ "description": "The view's select list over the stream table, each item aliased to a target column."
550
+ },
551
+ {
552
+ "name": "orderBy",
553
+ "type": "string",
554
+ "required": true,
555
+ "description": "The target's sort key (a column list or an expression)."
556
+ },
557
+ {
558
+ "name": "targetEngine",
559
+ "type": "string",
560
+ "required": false,
561
+ "description": "The target's engine (default `MergeTree`)."
562
+ },
563
+ {
564
+ "name": "partitionBy",
565
+ "type": "string",
566
+ "required": false,
567
+ "description": "The target's partition key."
568
+ }
569
+ ]
570
+ },
471
571
  {
472
572
  "name": "TenantTable",
473
573
  "lexicon": "sql",
@@ -4,4 +4,6 @@ export { EventsTable, type EventsTableProps, type EventsTableMembers } from "./e
4
4
  export { RollupView, type RollupViewProps, type RollupViewMembers } from "./rollup-view.js";
5
5
  export { CdcMirror, type CdcMirrorProps, type CdcMirrorMembers } from "./cdc-mirror.js";
6
6
  export { ShardedTable, type ShardedTableProps, type ShardedTableMembers } from "./sharded-table.js";
7
+ export { OtelTables, OTEL_EXPORTER_DEFAULT_TABLES, otelTtlClause, type OtelTablesProps, type OtelTablesMembers, type OtelTableNames } from "./otel-tables.js";
8
+ export { StreamIngest, type StreamIngestProps, type StreamIngestMembers } from "./stream-ingest.js";
7
9
  //# sourceMappingURL=clickhouse.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"clickhouse.d.ts","sourceRoot":"","sources":["../../src/composites/clickhouse.ts"],"names":[],"mappings":"AAAA,wFAAwF;AAExF,OAAO,EAAE,cAAc,EAAE,KAAK,mBAAmB,EAAE,KAAK,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AACzG,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,KAAK,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAC7F,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,KAAK,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACzF,OAAO,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,KAAK,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrF,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,KAAK,mBAAmB,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"clickhouse.d.ts","sourceRoot":"","sources":["../../src/composites/clickhouse.ts"],"names":[],"mappings":"AAAA,wFAAwF;AAExF,OAAO,EAAE,cAAc,EAAE,KAAK,mBAAmB,EAAE,KAAK,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AACzG,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,KAAK,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAC7F,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,KAAK,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACzF,OAAO,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,KAAK,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrF,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,KAAK,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACjG,OAAO,EAAE,UAAU,EAAE,4BAA4B,EAAE,aAAa,EAAE,KAAK,eAAe,EAAE,KAAK,iBAAiB,EAAE,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;AAC3J,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,KAAK,mBAAmB,EAAE,MAAM,iBAAiB,CAAC"}
@@ -4,3 +4,5 @@ export { EventsTable } from "./events-table.js";
4
4
  export { RollupView } from "./rollup-view.js";
5
5
  export { CdcMirror } from "./cdc-mirror.js";
6
6
  export { ShardedTable } from "./sharded-table.js";
7
+ export { OtelTables, OTEL_EXPORTER_DEFAULT_TABLES, otelTtlClause } from "./otel-tables.js";
8
+ export { StreamIngest } from "./stream-ingest.js";