@intentius/chant-lexicon-sql 0.124.31 → 0.124.33

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 (322) hide show
  1. package/dist/change-set.js +250 -0
  2. package/dist/clickhouse/access.js +722 -0
  3. package/dist/clickhouse/apply/apply.js +243 -0
  4. package/dist/clickhouse/apply/mutations.js +66 -0
  5. package/dist/clickhouse/apply/statements.js +545 -0
  6. package/dist/clickhouse/catalog-types.js +7 -0
  7. package/dist/clickhouse/container.js +152 -0
  8. package/dist/clickhouse/engine-syntax.js +159 -0
  9. package/dist/clickhouse/entities.js +593 -0
  10. package/dist/clickhouse/expressions.js +107 -0
  11. package/dist/clickhouse/http.js +55 -0
  12. package/dist/clickhouse/import/generator.js +192 -0
  13. package/dist/clickhouse/import/inlined.js +207 -0
  14. package/dist/clickhouse/import/ir.js +160 -0
  15. package/dist/clickhouse/import/live-export.js +131 -0
  16. package/dist/clickhouse/import/parser.js +17 -0
  17. package/dist/clickhouse/live/bind.js +116 -0
  18. package/dist/clickhouse/live/catalog.js +223 -0
  19. package/dist/clickhouse/live/describe-resources.js +91 -0
  20. package/dist/clickhouse/live/undeclarable.js +59 -0
  21. package/dist/clickhouse/overlays/codecs.js +57 -0
  22. package/dist/clickhouse/overlays/engines.js +101 -0
  23. package/dist/clickhouse/overlays/kinds.js +1 -0
  24. package/dist/clickhouse/overlays/projections.js +26 -0
  25. package/dist/clickhouse/overlays/skip-indexes.js +40 -0
  26. package/dist/clickhouse/overlays/ttl.js +34 -0
  27. package/dist/clickhouse/overlays/types.js +59 -0
  28. package/dist/clickhouse/ownership.js +83 -0
  29. package/dist/clickhouse/parser.js +674 -0
  30. package/dist/clickhouse/plan/commands.js +159 -0
  31. package/dist/clickhouse/plan/deep.js +345 -0
  32. package/dist/clickhouse/plan/diff.js +312 -0
  33. package/dist/clickhouse/plan/disruption.js +73 -0
  34. package/dist/clickhouse/plan/normalize.js +545 -0
  35. package/dist/clickhouse/plan/rebuild-handoff.js +57 -0
  36. package/dist/clickhouse/plan/report.js +26 -0
  37. package/dist/clickhouse/plan/rules.js +72 -0
  38. package/dist/clickhouse/plan/schema.js +67 -0
  39. package/dist/clickhouse/plan/server-format.js +35 -0
  40. package/dist/clickhouse/rebuild/backfill.js +265 -0
  41. package/dist/clickhouse/rebuild/engines.js +146 -0
  42. package/dist/clickhouse/rebuild/observe.js +260 -0
  43. package/dist/clickhouse/rebuild/op.js +152 -0
  44. package/dist/clickhouse/rebuild/partitions.js +65 -0
  45. package/dist/clickhouse/rebuild/receipts.js +120 -0
  46. package/dist/clickhouse/rebuild/replicas.js +121 -0
  47. package/dist/clickhouse/rebuild/shards.js +76 -0
  48. package/dist/clickhouse/rebuild/steps.js +383 -0
  49. package/dist/clickhouse/rebuild/verify.js +279 -0
  50. package/dist/clickhouse/row-types.js +151 -0
  51. package/dist/clickhouse/testing/fake-server.js +47 -0
  52. package/dist/clickhouse/testing/roundtrip-schema.js +25 -0
  53. package/dist/clickhouse/testing/writable-server.js +123 -0
  54. package/dist/clickhouse/tokens.js +23 -0
  55. package/dist/clickhouse/topology.js +463 -0
  56. package/dist/clickhouse/type-syntax.js +73 -0
  57. package/dist/clickhouse.js +25 -0
  58. package/dist/codegen/classifier-page.js +93 -0
  59. package/dist/codegen/clickhouse-module.js +249 -0
  60. package/dist/codegen/coverage-page.js +70 -0
  61. package/dist/codegen/docs-cli.js +3 -0
  62. package/dist/codegen/docs.js +222 -0
  63. package/dist/codegen/generate-cli.js +13 -0
  64. package/dist/codegen/generate.js +97 -0
  65. package/dist/codegen/package.js +28 -0
  66. package/dist/codegen/postgres-classifier-page.js +95 -0
  67. package/dist/codegen/postgres-module.js +418 -0
  68. package/dist/codegen/registry.js +52 -0
  69. package/dist/composites/audit-log-table.js +35 -0
  70. package/dist/composites/catalog.js +524 -0
  71. package/dist/composites/cdc-mirror.js +32 -0
  72. package/dist/composites/clickhouse.js +6 -0
  73. package/dist/composites/events-table.js +26 -0
  74. package/dist/composites/index.js +8 -0
  75. package/dist/composites/join-table.js +25 -0
  76. package/dist/composites/postgres.js +6 -0
  77. package/dist/composites/refreshed-view.js +24 -0
  78. package/dist/composites/replacing-table.js +28 -0
  79. package/dist/composites/rollup-view.js +29 -0
  80. package/dist/composites/sharded-table.js +27 -0
  81. package/dist/composites/soft-delete-table.js +34 -0
  82. package/dist/composites/tenant-table.js +26 -0
  83. package/dist/composites/typed.js +8 -0
  84. package/dist/config.js +206 -0
  85. package/dist/core/apply.js +93 -0
  86. package/dist/core/classifier.js +115 -0
  87. package/dist/core/container.js +69 -0
  88. package/dist/core/cursor.js +261 -0
  89. package/dist/core/diff.js +48 -0
  90. package/dist/core/entity.js +58 -0
  91. package/dist/core/find-templates.js +118 -0
  92. package/dist/core/foreign-tables.js +27 -0
  93. package/dist/core/handoff.js +32 -0
  94. package/dist/core/index.js +64 -0
  95. package/dist/core/interpolation.js +191 -0
  96. package/dist/core/normalize.js +43 -0
  97. package/dist/core/ownership.js +119 -0
  98. package/dist/core/receipts.js +22 -0
  99. package/dist/core/references.js +61 -0
  100. package/dist/core/statements.js +42 -0
  101. package/dist/core/template.js +79 -0
  102. package/dist/core/testing/http-stub.js +21 -0
  103. package/dist/core/tokens.js +202 -0
  104. package/dist/core/typed.js +40 -0
  105. package/dist/core/undeclarable.js +46 -0
  106. package/dist/coverage.js +161 -0
  107. package/dist/detect.js +32 -0
  108. package/dist/dialects.js +18 -0
  109. package/dist/files/build-root.js +72 -0
  110. package/dist/files/clickhouse.js +138 -0
  111. package/dist/files/common.js +58 -0
  112. package/dist/files/postgres.js +389 -0
  113. package/dist/generated/clickhouse-types.js +5 -0
  114. package/dist/generated/clickhouse.js +4361 -0
  115. package/dist/generated/postgres-types.js +227 -0
  116. package/dist/generated/postgres.js +3667 -0
  117. package/dist/import-generator.js +14 -0
  118. package/dist/import-parser.js +71 -0
  119. package/dist/index.js +24 -0
  120. package/dist/init-templates.js +290 -0
  121. package/dist/integrity.json +2 -2
  122. package/dist/lint/audit-catalog.js +31 -0
  123. package/dist/lint/audit-lineage.js +22 -0
  124. package/dist/lint/post-synth/audit-entries.js +34 -0
  125. package/dist/lint/post-synth/clickhouse-helpers.js +79 -0
  126. package/dist/lint/post-synth/clickhouse-type-check.js +162 -0
  127. package/dist/lint/post-synth/index.js +112 -0
  128. package/dist/lint/post-synth/postgres-audit-entries.js +35 -0
  129. package/dist/lint/post-synth/postgres-helpers.js +65 -0
  130. package/dist/lint/post-synth/postgres-names.js +507 -0
  131. package/dist/lint/post-synth/sql-helpers.js +23 -0
  132. package/dist/lint/post-synth/sql101.js +59 -0
  133. package/dist/lint/post-synth/sql102.js +34 -0
  134. package/dist/lint/post-synth/sqlch101.js +34 -0
  135. package/dist/lint/post-synth/sqlch102.js +23 -0
  136. package/dist/lint/post-synth/sqlch103.js +45 -0
  137. package/dist/lint/post-synth/sqlch104.js +41 -0
  138. package/dist/lint/post-synth/sqlch105.js +36 -0
  139. package/dist/lint/post-synth/sqlch106.js +27 -0
  140. package/dist/lint/post-synth/sqlch107.js +39 -0
  141. package/dist/lint/post-synth/sqlch108.js +28 -0
  142. package/dist/lint/post-synth/sqlch109.js +21 -0
  143. package/dist/lint/post-synth/sqlch110.js +31 -0
  144. package/dist/lint/post-synth/sqlch111.js +41 -0
  145. package/dist/lint/post-synth/sqlch112.js +28 -0
  146. package/dist/lint/post-synth/sqlch113.js +19 -0
  147. package/dist/lint/post-synth/sqlch114.js +26 -0
  148. package/dist/lint/post-synth/sqlch115.js +30 -0
  149. package/dist/lint/post-synth/sqlch116.js +22 -0
  150. package/dist/lint/post-synth/sqlch117.js +26 -0
  151. package/dist/lint/post-synth/sqlch118.js +27 -0
  152. package/dist/lint/post-synth/sqlch119.js +32 -0
  153. package/dist/lint/post-synth/sqlch120.js +20 -0
  154. package/dist/lint/post-synth/sqlch121.js +11 -0
  155. package/dist/lint/post-synth/sqlch122.js +11 -0
  156. package/dist/lint/post-synth/sqlch123.js +10 -0
  157. package/dist/lint/post-synth/sqlch124.js +21 -0
  158. package/dist/lint/post-synth/sqlch125.js +55 -0
  159. package/dist/lint/post-synth/sqlch126.js +62 -0
  160. package/dist/lint/post-synth/sqlch127.js +132 -0
  161. package/dist/lint/post-synth/sqlpg101.js +25 -0
  162. package/dist/lint/post-synth/sqlpg102.js +35 -0
  163. package/dist/lint/post-synth/sqlpg103.js +23 -0
  164. package/dist/lint/post-synth/sqlpg104.js +23 -0
  165. package/dist/lint/post-synth/sqlpg105.js +22 -0
  166. package/dist/lint/post-synth/sqlpg106.js +22 -0
  167. package/dist/lint/post-synth/sqlpg107.js +22 -0
  168. package/dist/lint/post-synth/sqlpg108.js +28 -0
  169. package/dist/lint/post-synth/sqlpg109.js +39 -0
  170. package/dist/lint/post-synth/sqlpg110.js +38 -0
  171. package/dist/lint/post-synth/sqlpg111.js +23 -0
  172. package/dist/lint/post-synth/sqlpg112.js +25 -0
  173. package/dist/lint/post-synth/sqlpg113.js +29 -0
  174. package/dist/lint/post-synth/sqlpg114.js +39 -0
  175. package/dist/lint/post-synth/sqlpg115.js +48 -0
  176. package/dist/lint/post-synth/sqlpg116.js +26 -0
  177. package/dist/lint/post-synth/sqlpg117.js +24 -0
  178. package/dist/lint/post-synth/sqlpg118.js +22 -0
  179. package/dist/lint/post-synth/sqlpg119.js +41 -0
  180. package/dist/lint/post-synth/sqlpg120.js +83 -0
  181. package/dist/lint/post-synth/sqlpg121.js +33 -0
  182. package/dist/lint/post-synth/sqlpg122.js +27 -0
  183. package/dist/lint/post-synth/sqlpg123.js +69 -0
  184. package/dist/lint/post-synth/sqlpg124.js +50 -0
  185. package/dist/lint/post-synth/sqlpg125.js +41 -0
  186. package/dist/lint/post-synth/sqlpg126.js +38 -0
  187. package/dist/lint/rules/index.js +12 -0
  188. package/dist/lint/rules/postgres-templates.js +27 -0
  189. package/dist/lint/rules/sqlch001.js +79 -0
  190. package/dist/lint/rules/sqlch002.js +124 -0
  191. package/dist/lint/rules/sqlch003.js +69 -0
  192. package/dist/lint/rules/sqlch004.js +83 -0
  193. package/dist/lint/rules/sqlpg001.js +68 -0
  194. package/dist/lint/rules/sqlpg002.js +69 -0
  195. package/dist/lint/rules/sqlpg003.js +58 -0
  196. package/dist/lint/rules/sqlpg004.js +77 -0
  197. package/dist/lint/rules/sqlpg005.js +86 -0
  198. package/dist/lint/rules/templates.js +25 -0
  199. package/dist/lint/rules/typed-names.js +132 -0
  200. package/dist/live-dialect.js +32 -0
  201. package/dist/lsp/catalog.js +44 -0
  202. package/dist/lsp/completions.js +136 -0
  203. package/dist/lsp/hover.js +115 -0
  204. package/dist/lsp/postgres-catalog.js +176 -0
  205. package/dist/lsp/postgres-template.js +171 -0
  206. package/dist/lsp/postgres.js +266 -0
  207. package/dist/lsp/refs.js +60 -0
  208. package/dist/lsp/registry.d.ts.map +1 -1
  209. package/dist/lsp/registry.js +19 -0
  210. package/dist/lsp/template.js +143 -0
  211. package/dist/manifest.json +1 -1
  212. package/dist/mcp/index.d.ts.map +1 -1
  213. package/dist/mcp/index.js +293 -0
  214. package/dist/mcp/postgres.js +117 -0
  215. package/dist/migration-statements.js +243 -0
  216. package/dist/op/activities/clickhouse-apply.js +83 -0
  217. package/dist/op/activities/clickhouse-emulator.js +53 -0
  218. package/dist/op/activities/clickhouse-rebuild.js +119 -0
  219. package/dist/op/activities/index.js +26 -0
  220. package/dist/op/activities/postgres-apply.js +126 -0
  221. package/dist/op/activities/postgres-emulator.js +70 -0
  222. package/dist/op/activities/postgres-migration.js +156 -0
  223. package/dist/op/activities/sql-exec.js +57 -0
  224. package/dist/op/activity-contracts.js +103 -0
  225. package/dist/package-cli.js +14 -0
  226. package/dist/plugin.js +259 -0
  227. package/dist/postgres/access/acl.js +344 -0
  228. package/dist/postgres/access/changes.js +30 -0
  229. package/dist/postgres/access/import.js +61 -0
  230. package/dist/postgres/access/live.js +96 -0
  231. package/dist/postgres/apply/apply.js +557 -0
  232. package/dist/postgres/apply/statements.js +882 -0
  233. package/dist/postgres/catalog-types.js +18 -0
  234. package/dist/postgres/container.js +58 -0
  235. package/dist/postgres/entities.js +1390 -0
  236. package/dist/postgres/entity-types.js +28 -0
  237. package/dist/postgres/import/generator.js +283 -0
  238. package/dist/postgres/import/ir.js +53 -0
  239. package/dist/postgres/import/live-export.js +83 -0
  240. package/dist/postgres/keywords.js +32 -0
  241. package/dist/postgres/live/bind.js +130 -0
  242. package/dist/postgres/live/catalog-kinds.js +301 -0
  243. package/dist/postgres/live/catalog.js +644 -0
  244. package/dist/postgres/live/client.js +151 -0
  245. package/dist/postgres/live/describe-resources.js +135 -0
  246. package/dist/postgres/live/undeclarable.js +111 -0
  247. package/dist/postgres/migrate/backfill.js +170 -0
  248. package/dist/postgres/migrate/batches.js +122 -0
  249. package/dist/postgres/migrate/carry.js +518 -0
  250. package/dist/postgres/migrate/handoff.js +59 -0
  251. package/dist/postgres/migrate/names.js +61 -0
  252. package/dist/postgres/migrate/observe.js +360 -0
  253. package/dist/postgres/migrate/op.js +178 -0
  254. package/dist/postgres/migrate/receipts.js +117 -0
  255. package/dist/postgres/migrate/replication.js +106 -0
  256. package/dist/postgres/migrate/steps.js +514 -0
  257. package/dist/postgres/overlays/columns.js +31 -0
  258. package/dist/postgres/overlays/constraints.js +52 -0
  259. package/dist/postgres/overlays/extension-objects.js +88 -0
  260. package/dist/postgres/overlays/indexes.js +25 -0
  261. package/dist/postgres/overlays/kinds.js +2 -0
  262. package/dist/postgres/overlays/partitioning.js +23 -0
  263. package/dist/postgres/overlays/relations.js +25 -0
  264. package/dist/postgres/overlays/storage.js +65 -0
  265. package/dist/postgres/overlays/type-ddl.js +36 -0
  266. package/dist/postgres/overlays/types.js +74 -0
  267. package/dist/postgres/parser.js +1824 -0
  268. package/dist/postgres/plan/commands.js +137 -0
  269. package/dist/postgres/plan/deep.js +324 -0
  270. package/dist/postgres/plan/diff.js +499 -0
  271. package/dist/postgres/plan/disruption.js +64 -0
  272. package/dist/postgres/plan/normalize.js +889 -0
  273. package/dist/postgres/plan/report.js +21 -0
  274. package/dist/postgres/plan/rules.js +115 -0
  275. package/dist/postgres/plan/schema.js +105 -0
  276. package/dist/postgres/plan/server-normalize.js +166 -0
  277. package/dist/postgres/providers/aurora.js +44 -0
  278. package/dist/postgres/providers/azure.js +53 -0
  279. package/dist/postgres/providers/cloud-sql.js +41 -0
  280. package/dist/postgres/providers/index.js +73 -0
  281. package/dist/postgres/providers/neon.js +44 -0
  282. package/dist/postgres/providers/rds.js +47 -0
  283. package/dist/postgres/providers/supabase.js +45 -0
  284. package/dist/postgres/providers/types.js +21 -0
  285. package/dist/postgres/row-types.js +107 -0
  286. package/dist/postgres/testing/fake-client.js +34 -0
  287. package/dist/postgres/testing/migration.js +48 -0
  288. package/dist/postgres/testing/roundtrip-schema.js +64 -0
  289. package/dist/postgres/testing/server.js +47 -0
  290. package/dist/postgres/testing/writable-server.js +160 -0
  291. package/dist/postgres/tokens.js +41 -0
  292. package/dist/postgres.js +15 -0
  293. package/dist/read/clickhouse.js +82 -0
  294. package/dist/read/objects.js +44 -0
  295. package/dist/read/postgres.js +104 -0
  296. package/dist/read.js +52 -0
  297. package/dist/receipts.js +207 -0
  298. package/dist/serializer.js +172 -0
  299. package/dist/skill-defs.js +93 -0
  300. package/dist/spec/catalog.js +191 -0
  301. package/dist/spec/fetch.d.ts.map +1 -1
  302. package/dist/spec/fetch.js +90 -0
  303. package/dist/spec/pin.js +42 -0
  304. package/dist/spec/postgres-catalog.js +171 -0
  305. package/dist/spec/postgres-fetch.js +91 -0
  306. package/dist/spec/postgres-pin.js +82 -0
  307. package/dist/sql-files.js +206 -0
  308. package/dist/sql-types-command.js +97 -0
  309. package/dist/sql-types.js +323 -0
  310. package/dist/token-source.js +156 -0
  311. package/dist/validate-cli.js +5 -0
  312. package/dist/validate.js +151 -0
  313. package/dist/workspace-outputs.js +191 -0
  314. package/package.json +7 -7
  315. package/src/codegen/package.ts +2 -2
  316. package/src/lint/rules/typescript-7.test.ts +2 -1
  317. package/src/lsp/catalog.ts +2 -2
  318. package/src/lsp/postgres-catalog.ts +2 -2
  319. package/src/lsp/registry.ts +2 -1
  320. package/src/mcp/index.ts +4 -2
  321. package/src/spec/fetch.ts +2 -2
  322. package/src/spec/postgres-fetch.ts +2 -2
@@ -0,0 +1,249 @@
1
+ /**
2
+ * Render `src/generated/clickhouse.ts`, the ClickHouse dialect's generated
3
+ * surface: string-literal unions for every named thing in the catalog, the two
4
+ * settings interfaces, and the tables lint and the LSP read (engines with
5
+ * their typed arguments, type families, codecs, skip index types, settings).
6
+ *
7
+ * The overlays are merged here, and checked against the catalog in both
8
+ * directions. An overlay key the pinned server does not have, or a codec at
9
+ * the pin with no overlay entry, is an error: a pin move that changes the
10
+ * grammar has to change the overlay in the same commit.
11
+ */
12
+ import { parseEngineSyntax } from "../clickhouse/engine-syntax.js";
13
+ import { ENGINE_ARGUMENTS } from "../clickhouse/overlays/engines.js";
14
+ import { SKIP_INDEX_PARAMETERS } from "../clickhouse/overlays/skip-indexes.js";
15
+ import { CODEC_OVERLAY } from "../clickhouse/overlays/codecs.js";
16
+ import { TYPE_PARAMETERS } from "../clickhouse/overlays/types.js";
17
+ import { TTL_SETTINGS } from "../clickhouse/overlays/ttl.js";
18
+ import { PROJECTION_SETTINGS } from "../clickhouse/overlays/projections.js";
19
+ /** Setting types with a TypeScript form; every enum-typed setting (no member list in the catalog) is `string`. */
20
+ const SETTING_TS_TYPES = {
21
+ Bool: "boolean",
22
+ BoolAuto: 'boolean | "auto"',
23
+ UInt64: "number",
24
+ Int64: "number",
25
+ UInt32: "number",
26
+ Int32: "number",
27
+ Float: "number",
28
+ Double: "number",
29
+ Seconds: "number",
30
+ Milliseconds: "number",
31
+ NonZeroUInt64: "number",
32
+ MaxThreads: 'number | "auto"',
33
+ UInt64Auto: 'number | "auto"',
34
+ FloatAuto: 'number | "auto"',
35
+ };
36
+ export function settingTsType(type) {
37
+ return SETTING_TS_TYPES[type] ?? "string";
38
+ }
39
+ const lit = (names) => names.length > 0 ? names.map((n) => JSON.stringify(n)).join(" | ") : "never";
40
+ const key = (name) => (/^[A-Za-z_$][\w$]*$/.test(name) ? name : JSON.stringify(name));
41
+ /** A JSDoc line cannot contain `*\/`. */
42
+ const doc = (text) => text.replace(/\*\//g, "*\\/");
43
+ function mergeArguments(owner, parsed, overlay, errors) {
44
+ if (!parsed) {
45
+ if (overlay)
46
+ errors.push(`${owner}: the overlay types arguments, but the syntax line is not readable`);
47
+ return { typed: false };
48
+ }
49
+ const names = new Set(parsed.args.map((a) => a.name));
50
+ for (const name of Object.keys(overlay ?? {})) {
51
+ if (!names.has(name))
52
+ errors.push(`${owner}: overlay argument "${name}" is not in the syntax line at this pin`);
53
+ }
54
+ const args = parsed.args.map((a) => {
55
+ const o = overlay?.[a.name];
56
+ return {
57
+ name: a.name,
58
+ position: a.position,
59
+ optional: o?.optional ?? a.optional,
60
+ repeated: a.repeated,
61
+ named: a.named,
62
+ kind: o?.kind ?? (a.quoted ? "string" : "unknown"),
63
+ ...(o?.values ? { values: o.values } : {}),
64
+ ...(o?.range ? { range: o.range } : {}),
65
+ ...(o?.note ? { note: o.note } : {}),
66
+ };
67
+ });
68
+ return { args, typed: args.every((a) => a.kind !== "unknown") };
69
+ }
70
+ function settingsInterface(name, rows) {
71
+ const lines = [`export interface ${name} {`];
72
+ for (const r of rows) {
73
+ const tags = [doc(r.summary)];
74
+ if (r.obsolete || r.tier === "Obsolete")
75
+ tags.push("@deprecated obsolete at this pin");
76
+ if (r.tier === "Experimental" || r.tier === "Beta")
77
+ tags.push(`@tier ${r.tier}`);
78
+ if (r.aliasFor)
79
+ tags.push(`@alias ${r.aliasFor}`);
80
+ tags.push(`@default ${doc(JSON.stringify(r.default))}`);
81
+ lines.push(` /** ${tags.filter(Boolean).join(" | ")} */`);
82
+ lines.push(` ${key(r.name)}?: ${settingTsType(r.type)};`);
83
+ }
84
+ lines.push("}");
85
+ return lines.join("\n");
86
+ }
87
+ function settingsTable(name, keyType, rows) {
88
+ const lines = [`export const ${name}: Readonly<Record<${keyType}, SettingSpec>> = {`];
89
+ for (const r of rows) {
90
+ lines.push(` ${key(r.name)}: ${JSON.stringify({ type: r.type, default: r.default, tier: r.tier, obsolete: r.obsolete, readonly: r.readonly })},`);
91
+ }
92
+ lines.push("};");
93
+ return lines.join("\n");
94
+ }
95
+ export function renderClickHouseModule(catalog) {
96
+ const errors = [];
97
+ const notes = [];
98
+ // ── Cross-checks of the overlays against the catalog ──────────────
99
+ const engineNames = new Set(catalog.tableEngines.map((e) => e.name));
100
+ for (const name of Object.keys(ENGINE_ARGUMENTS)) {
101
+ if (!engineNames.has(name))
102
+ errors.push(`overlays/engines.ts: engine ${name} is not in the catalog at ${catalog.version}`);
103
+ }
104
+ const indexNames = new Set(catalog.skipIndexTypes.map((e) => e.name));
105
+ for (const name of Object.keys(SKIP_INDEX_PARAMETERS)) {
106
+ if (!indexNames.has(name))
107
+ errors.push(`overlays/skip-indexes.ts: index type ${name} is not in the catalog`);
108
+ }
109
+ const codecNames = new Set(catalog.codecs.map((c) => c.name));
110
+ for (const name of Object.keys(CODEC_OVERLAY)) {
111
+ if (!codecNames.has(name))
112
+ errors.push(`overlays/codecs.ts: codec ${name} is not in the catalog`);
113
+ }
114
+ for (const name of codecNames) {
115
+ if (!CODEC_OVERLAY[name])
116
+ errors.push(`overlays/codecs.ts: codec ${name} at ${catalog.version} has no entry`);
117
+ }
118
+ const families = new Set(catalog.typeFamilies.filter((t) => !t.aliasOf).map((t) => t.name));
119
+ for (const name of Object.keys(TYPE_PARAMETERS)) {
120
+ if (!families.has(name))
121
+ errors.push(`overlays/types.ts: type family ${name} is not in the catalog`);
122
+ }
123
+ const mtSettings = new Set(catalog.mergeTreeSettings.map((s) => s.name));
124
+ for (const name of [...TTL_SETTINGS, ...PROJECTION_SETTINGS]) {
125
+ if (!mtSettings.has(name))
126
+ errors.push(`overlays: MergeTree setting ${name} is not in the catalog`);
127
+ }
128
+ // ── Engines ────────────────────────────────────────────────────────
129
+ const engineLines = [];
130
+ for (const e of catalog.tableEngines) {
131
+ const parsed = parseEngineSyntax(e.syntax);
132
+ const { args, typed } = mergeArguments(`engine ${e.name}`, parsed, ENGINE_ARGUMENTS[e.name], errors);
133
+ const mergeTree = /MergeTree$/.test(e.name);
134
+ const replicates = /^Replicated.+MergeTree$/.test(e.name) ? e.name.slice("Replicated".length) : undefined;
135
+ if (mergeTree && !typed)
136
+ notes.push(`engine ${e.name}: arguments not fully typed`);
137
+ const spec = {
138
+ capabilities: e.capabilities,
139
+ syntax: e.syntax,
140
+ ...(args ? { args } : {}),
141
+ typed,
142
+ mergeTree,
143
+ ...(replicates ? { replicates } : {}),
144
+ summary: e.summary,
145
+ };
146
+ engineLines.push(` ${key(e.name)}: ${JSON.stringify(spec)},`);
147
+ }
148
+ const indexLines = [];
149
+ for (const t of catalog.skipIndexTypes) {
150
+ const { args } = mergeArguments(`index ${t.name}`, parseEngineSyntax(t.syntax), SKIP_INDEX_PARAMETERS[t.name], errors);
151
+ indexLines.push(` ${key(t.name)}: ${JSON.stringify({ syntax: t.syntax, ...(args ? { args } : {}), summary: t.summary })},`);
152
+ }
153
+ if (errors.length > 0) {
154
+ throw new Error(`The ClickHouse overlays disagree with the catalog at ${catalog.version}:\n ${errors.join("\n ")}\n` +
155
+ "Update src/clickhouse/overlays/ for this pin.");
156
+ }
157
+ const canonical = catalog.typeFamilies.filter((t) => !t.aliasOf);
158
+ const aliases = catalog.typeFamilies.filter((t) => t.aliasOf);
159
+ const mergeTreeEngines = catalog.tableEngines.filter((e) => /MergeTree$/.test(e.name));
160
+ const header = (what) => [
161
+ `// Generated by \`npm run generate\` from the ClickHouse catalog at ${catalog.version}`,
162
+ `// (src/spec/clickhouse-catalog.snapshot.json) and the overlays in src/clickhouse/overlays/. Do not edit.`,
163
+ `// ${what}`,
164
+ "",
165
+ ];
166
+ const declarations = [
167
+ ...header("The type surface: unions of every named thing in the catalog, and the two settings interfaces."),
168
+ `/** The ClickHouse release these types were read from. */`,
169
+ `export const CLICKHOUSE_VERSION = ${JSON.stringify(catalog.version)};`,
170
+ "",
171
+ `export type TableEngineName = ${lit(catalog.tableEngines.map((e) => e.name))};`,
172
+ `export type MergeTreeEngineName = ${lit(mergeTreeEngines.map((e) => e.name))};`,
173
+ `export type DatabaseEngineName = ${lit(catalog.databaseEngines.map((e) => e.name))};`,
174
+ `export type ColumnTypeFamily = ${lit(canonical.map((t) => t.name))};`,
175
+ `export type ColumnTypeAlias = ${lit(aliases.map((t) => t.name))};`,
176
+ `export type ColumnTypeName = ColumnTypeFamily | ColumnTypeAlias;`,
177
+ `export type CodecName = ${lit(catalog.codecs.map((c) => c.name))};`,
178
+ `export type SkipIndexType = ${lit(catalog.skipIndexTypes.map((c) => c.name))};`,
179
+ `export type AggregateCombinator = ${lit(catalog.aggregateCombinators.filter((c) => !c.internal).map((c) => c.name))};`,
180
+ `export type TableFunctionName = ${lit(catalog.tableFunctions)};`,
181
+ `export type FormatName = ${lit(catalog.formats.map((f) => f.name))};`,
182
+ `export type InputFormatName = ${lit(catalog.formats.filter((f) => f.input).map((f) => f.name))};`,
183
+ `export type OutputFormatName = ${lit(catalog.formats.filter((f) => f.output).map((f) => f.name))};`,
184
+ `export type AggregateFunctionName = ${lit(catalog.functions.filter((f) => f.aggregate).map((f) => f.name))};`,
185
+ `export type ScalarFunctionName = ${lit(catalog.functions.filter((f) => !f.aggregate).map((f) => f.name))};`,
186
+ "",
187
+ settingsInterface("MergeTreeSettings", catalog.mergeTreeSettings),
188
+ "",
189
+ settingsInterface("QuerySettings", catalog.querySettings),
190
+ "",
191
+ ].join("\n");
192
+ const tables = [
193
+ ...header("The tables lint and the LSP read, typed by ./clickhouse-types."),
194
+ `import type { CodecSpec, DatabaseEngineSpec, FunctionSpec, SettingSpec, SkipIndexSpec, TableEngineSpec, TypeFamilySpec } from "../clickhouse/catalog-types.js";`,
195
+ `import type { CodecName, ColumnTypeName, DatabaseEngineName, MergeTreeSettings, QuerySettings, SkipIndexType, TableEngineName } from "./clickhouse-types";`,
196
+ "",
197
+ `export * from "./clickhouse-types";`,
198
+ "",
199
+ `export const TABLE_ENGINES: Readonly<Record<TableEngineName, TableEngineSpec>> = {`,
200
+ ...engineLines,
201
+ "};",
202
+ "",
203
+ `export const DATABASE_ENGINES: Readonly<Record<DatabaseEngineName, DatabaseEngineSpec>> = {`,
204
+ ...catalog.databaseEngines.map((e) => ` ${key(e.name)}: ${JSON.stringify({ syntax: e.syntax, summary: e.summary })},`),
205
+ "};",
206
+ "",
207
+ `export const TYPE_FAMILIES: Readonly<Record<ColumnTypeName, TypeFamilySpec>> = {`,
208
+ ...catalog.typeFamilies.map((t) => ` ${key(t.name)}: ${JSON.stringify({ canonical: t.aliasOf ?? t.name, caseInsensitive: t.caseInsensitive })},`),
209
+ "};",
210
+ "",
211
+ `export const CODECS: Readonly<Record<CodecName, CodecSpec>> = {`,
212
+ ...catalog.codecs.map((c) => {
213
+ const o = CODEC_OVERLAY[c.name];
214
+ const spec = {
215
+ compression: c.compression,
216
+ generic: c.generic,
217
+ encryption: c.encryption,
218
+ timeseries: c.timeseries,
219
+ experimental: c.experimental,
220
+ role: o.role,
221
+ parameters: o.parameters,
222
+ summary: c.summary,
223
+ };
224
+ return ` ${key(c.name)}: ${JSON.stringify(spec)},`;
225
+ }),
226
+ "};",
227
+ "",
228
+ `/** Every function the server has (\`system.functions\`, origin System), aliases included. */`,
229
+ `export const FUNCTIONS: Readonly<Record<string, FunctionSpec>> = {`,
230
+ ...catalog.functions.map((f) => ` ${key(f.name)}: ${JSON.stringify({ aggregate: f.aggregate, caseInsensitive: f.caseInsensitive, ...(f.aliasOf ? { aliasOf: f.aliasOf } : {}) })},`),
231
+ "};",
232
+ "",
233
+ `/** The aggregate function combinators (\`system.aggregate_function_combinators\`): the suffixes of \`countIf\`, \`sumState\`. */`,
234
+ `export const AGGREGATE_COMBINATORS: readonly string[] = ${JSON.stringify(catalog.aggregateCombinators.map((c) => c.name))};`,
235
+ "",
236
+ `/** The table functions (\`system.table_functions\`): \`numbers\`, \`remote\`, \`s3\`. */`,
237
+ `export const TABLE_FUNCTIONS: readonly string[] = ${JSON.stringify(catalog.tableFunctions)};`,
238
+ "",
239
+ `export const SKIP_INDEX_TYPES: Readonly<Record<SkipIndexType, SkipIndexSpec>> = {`,
240
+ ...indexLines,
241
+ "};",
242
+ "",
243
+ settingsTable("MERGE_TREE_SETTINGS", "keyof MergeTreeSettings", catalog.mergeTreeSettings),
244
+ "",
245
+ settingsTable("QUERY_SETTINGS", "keyof QuerySettings", catalog.querySettings),
246
+ "",
247
+ ].join("\n");
248
+ return { declarations, tables, notes };
249
+ }
@@ -0,0 +1,70 @@
1
+ /**
2
+ * `docs/pages/object-coverage.mdx`, written from the coverage tables
3
+ * (`../coverage/<dialect>.json`) by `npm run docs`, so the page cannot
4
+ * disagree with what import refuses.
5
+ */
6
+ import { KIND_COVERAGE, PINNED_COMMANDS } from "../coverage.js";
7
+ const cell = (s) => s.replace(/\|/g, "\\|").replace(/[{}<>]/g, (c) => `\\${c}`);
8
+ const STATUS = { declared: "declared", refused: "refused", "out-of-scope": "out of scope" };
9
+ function table(dialect) {
10
+ const rows = [...KIND_COVERAGE[dialect]].sort((a, b) => (a.command < b.command ? -1 : a.command > b.command ? 1 : 0));
11
+ return [
12
+ "| Command | Kind | Status | Declared by, or why not |",
13
+ "|---|---|---|---|",
14
+ ...rows.map((r) => {
15
+ const command = `\`${r.command}\`${r.form ? ` (${cell(r.form)})` : ""}`;
16
+ const why = r.status === "declared" ? `\`${r.entity}\`${r.note ? `: ${cell(r.note)}` : ""}` : cell(r.reason ?? "");
17
+ return `| ${command} | ${cell(r.kind)} | ${STATUS[r.status]} | ${why} |`;
18
+ }),
19
+ ].join("\n");
20
+ }
21
+ function counts(dialect) {
22
+ const rows = KIND_COVERAGE[dialect];
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`;
25
+ }
26
+ export function renderCoveragePage() {
27
+ const pg = PINNED_COMMANDS.postgres.map((p) => p.version).join(", ");
28
+ const ch = PINNED_COMMANDS.clickhouse.map((p) => p.version).join(", ");
29
+ return `---
30
+ title: "Object Coverage"
31
+ 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
+ diataxis: reference
34
+ order: 3
35
+ ---
36
+
37
+ {/* Written by src/codegen/coverage-page.ts from src/coverage/postgres.json and src/coverage/clickhouse.json. Edit the tables, then run npm run docs. */}
38
+
39
+ 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
+ - **declared**: a tag declares it, and import writes it as that declaration.
42
+ - **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
+ - **out of scope**: the environment's, not a schema's: import never reads it.
44
+
45
+ \`--skip-undeclarable\` (\`--parser-option skipUndeclarable\` for a file) imports everything else and lists the refused objects as warnings, for an adopter who keeps those objects by hand for now:
46
+
47
+ \`\`\`bash
48
+ chant import --from prod --skip-undeclarable
49
+ chant import schema.sql --parser-option skipUndeclarable
50
+ \`\`\`
51
+
52
+ What a managed provider, an extension or the server's configuration files define is never refused: an extension's aggregates and casts are the extension's, declared with it, and a quota from \`users.xml\` is the server's. An import with \`--type\`, \`--name\` or \`--owned\` asks only for objects chant can hold, and does not look for the rest.
53
+
54
+ ## Postgres
55
+
56
+ Pinned majors: ${pg}. ${counts("postgres")}.
57
+
58
+ ${table("postgres")}
59
+
60
+ ## ClickHouse
61
+
62
+ Pinned release: ${ch}. ${counts("clickhouse")}.
63
+
64
+ ${table("clickhouse")}
65
+
66
+ ## Declaring a refused kind
67
+
68
+ A kind becomes declarable in three steps: a tag that declares it, the catalog reader reading it (\`src/postgres/live/catalog.ts\`, \`src/clickhouse/live/catalog.ts\`), and its row flipped to \`declared\` with the entity type, its reason taken out. The row's flip is what stops import refusing the kind. After moving a pin, run \`npx tsx scripts/sql-create-commands.ts\` and give each new command a row.
69
+ `;
70
+ }
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env tsx
2
+ import { generateDocs } from "./docs.js";
3
+ await generateDocs({ verbose: true });
@@ -0,0 +1,222 @@
1
+ /**
2
+ * Documentation generation for the sql lexicon: the generated reference pages
3
+ * from the core docs pipeline, plus the authored pages in docs/pages/.
4
+ */
5
+ import { dirname, join } from "path";
6
+ import { fileURLToPath } from "url";
7
+ import { writeFileSync } from "fs";
8
+ import { docsPipeline, writeDocsSite } from "@intentius/chant/codegen/docs";
9
+ import { renderClassifierPage } from "./classifier-page.js";
10
+ import { renderPostgresClassifierPage } from "./postgres-classifier-page.js";
11
+ import { renderCoveragePage } from "./coverage-page.js";
12
+ const overview = `The sql lexicon declares database schema in TypeScript. It has two dialects,
13
+ each a subpath of the one package: ClickHouse at
14
+ \`@intentius/chant-lexicon-sql/clickhouse\` and Postgres at
15
+ \`@intentius/chant-lexicon-sql/postgres\`. A declaration is the database's own
16
+ \`CREATE\` statement in a tagged template, and an interpolated object or
17
+ column stays a reference. Install it with
18
+ \`npm install --save-dev @intentius/chant @intentius/chant-lexicon-sql\`; each
19
+ dialect's Getting Started page runs the example the lexicon ships.
20
+
21
+ \`\`\`ts
22
+ import { database, table, view } from "@intentius/chant-lexicon-sql/clickhouse";
23
+
24
+ export const analytics = database\`CREATE DATABASE analytics ENGINE = Atomic\`;
25
+
26
+ export const events = table\`
27
+ CREATE TABLE \${analytics}.events (
28
+ user_id UUID,
29
+ kind LowCardinality(String),
30
+ ts DateTime
31
+ )
32
+ ENGINE = MergeTree
33
+ ORDER BY (user_id, kind, ts)\`;
34
+ \`\`\`
35
+
36
+ \`\`\`ts
37
+ import { schema, table, index } from "@intentius/chant-lexicon-sql/postgres";
38
+
39
+ export const app = schema\`CREATE SCHEMA app\`;
40
+
41
+ export const users = table\`
42
+ CREATE TABLE \${app}.users (
43
+ id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
44
+ email text NOT NULL UNIQUE
45
+ )\`;
46
+
47
+ export const usersEmail = index\`
48
+ CREATE INDEX CONCURRENTLY users_email_lower_idx ON \${users} (lower(\${users.columns.email}))\`;
49
+ \`\`\`
50
+
51
+ ## Spec-true per dialect
52
+
53
+ Each dialect is true to its own database. For SQL the spec is the database's
54
+ own DDL, so a ClickHouse declaration is a ClickHouse \`CREATE\` statement and a
55
+ Postgres declaration a Postgres one. The names a declaration can use (engines,
56
+ codecs and settings for ClickHouse; types, access methods, storage parameters
57
+ and extensions for Postgres) are generated from a pinned server's own catalog:
58
+ ClickHouse's \`system.*\` tables, and Postgres's \`pg_catalog\` at one pinned
59
+ release of each supported major. There is no neutral schema model that the
60
+ dialects are translated from.
61
+
62
+ The reason is that the databases differ exactly where a schema tool does its
63
+ work. ClickHouse has no foreign keys and no transactional DDL, and it cannot
64
+ change a table's sort key, partition key or engine in place: the rows have to
65
+ be copied into a new table. Postgres makes most changes in place and inside a
66
+ transaction, and what a change costs there is the lock it takes: adding a
67
+ column with a constant default is a catalog change, a type change that
68
+ rewrites the table blocks every reader until it finishes, and an index built
69
+ without \`CONCURRENTLY\` blocks every writer. A neutral model would have to hide
70
+ those differences, so a plan could not say what a change will cost, or carry
71
+ every dialect's features and check each one against the target anyway.
72
+
73
+ So each dialect has its own types, parser, lint rules and post-synth checks,
74
+ change classifier, applier, migration Op, composites and skills. What the two
75
+ share is the way of working:
76
+
77
+ | | ClickHouse | Postgres |
78
+ |---|---|---|
79
+ | Declaring | \`database\`, \`table\`, \`view\` | \`schema\`, \`table\`, \`index\`, \`view\`, \`sequence\`, \`type\`, \`domain\`, \`extension\` |
80
+ | Types from | one pinned \`clickhouse-server\` release | one pinned \`postgres\` release per major, 14 to 18 |
81
+ | Rule ids | SQLCH001-003, SQLCH101-120, SQLCH200-250 | SQLPG001-004, SQLPG101-118, SQLPG200-270 |
82
+ | Change classes | metadata only, background rewrite, rebuild | metadata only, validates under a weaker lock, needs \`CONCURRENTLY\`, \`ACCESS EXCLUSIVE\` rewrite or scan, expand and contract |
83
+ | Applier (\`ApplyOp\` target) | \`clickhouseApply\` (\`clickhouse\`) | \`postgresApply\` (\`postgres\`) |
84
+ | What a plan refuses runs as | \`ClickHouseRebuildOp\` | \`PostgresMigrationOp\` |
85
+ | Ownership marker | a trailer on the object's comment | a trailer on the object's comment |
86
+
87
+ References, dependency order and column lineage work the same way in both, as
88
+ do \`chant sql diff\` and \`chant sql plan\` (they read the build's
89
+ \`dialect\`), import with \`chant import --from <env>\`, the \`-- previously:\`
90
+ rename hint, and the comment trailer that marks what chant owns.
91
+
92
+ One build holds one dialect. A project that declares both ClickHouse and
93
+ Postgres objects fails the build naming one of each; a Postgres database and
94
+ a ClickHouse database are two projects, which a workspace can hold as two
95
+ members. \`sql.dialect\` in \`chant.config.ts\` says which dialect a project is
96
+ when nothing declared says so, as for an import into an empty project.
97
+
98
+ ## Pages
99
+
100
+ ClickHouse:
101
+
102
+ - [Getting Started with ClickHouse](./getting-started/): declare a schema,
103
+ build it, apply it to a local server and plan a change against it.
104
+ - [Declaring ClickHouse Tables and Views](./clickhouse-ddl/): databases,
105
+ tables, views and materialized views, and what each kind of interpolation
106
+ means.
107
+ - [Importing a ClickHouse Server](./importing/): \`chant import --from <env>\`
108
+ from \`SHOW CREATE\`.
109
+ - [Planning and the Change Classifier](./change-classifier/): every change
110
+ classified as metadata only, a background rewrite or a rebuild.
111
+ - [Applying to a ClickHouse Server](./applying/): \`clickhouseApply\`, the
112
+ ownership marker, prune and the local server.
113
+ - [Rebuilding a Table](./rebuild/): \`ClickHouseRebuildOp\` for the changes
114
+ ClickHouse cannot make in place.
115
+ - [Where the ClickHouse Types Come From](./clickhouse-catalog/): the pinned
116
+ server and how to move the pin.
117
+
118
+ Postgres:
119
+
120
+ - [Getting Started with Postgres](./postgres-getting-started/): declare a
121
+ schema, apply it to a local server, add a column and an index, and see a
122
+ rename refused.
123
+ - [Declaring Postgres Objects](./postgres-ddl/): the eight tags,
124
+ constraints, \`nextval(\${seq})\`, \`COMMENT ON\` and \`literal()\`.
125
+ - [Importing a Postgres Server](./postgres-importing/): canonical text from
126
+ the catalog's printers, and the objects that belong to someone else.
127
+ - [Postgres Locks and the Change Classifier](./postgres-change-classifier/):
128
+ every change classified by the lock it takes.
129
+ - [Applying to a Postgres Server](./postgres-applying/): transactions,
130
+ \`CONCURRENTLY\`, timeouts, ownership, prune and the local server.
131
+ - [Migrating a Column](./postgres-migration/): \`PostgresMigrationOp\`, the
132
+ expand-and-contract Op for a column rename or type change.
133
+ - [Managed Providers](./postgres-providers/): \`sql.provider\`, SQLPG004, and
134
+ what each provider's data has not verified.
135
+ - [The Postgres Pin and Supported Majors](./postgres-majors/): one pin per
136
+ major, \`sql.postgresMajor\`, and moving a pin.
137
+
138
+ Both dialects:
139
+
140
+ - [References and Lineage](./references-and-lineage/): how references become
141
+ dependency order and column-level lineage.
142
+ - [Composites](./composites/): five ClickHouse and five Postgres composites.
143
+ - [Lint Rules and Checks](./lint-rules/): every lint rule and post-synth
144
+ check.
145
+ - [Object Coverage](./object-coverage/): every kind of object the pinned
146
+ servers can create, declared, refused or out of scope, and what import
147
+ does with each.
148
+
149
+ ## Schema changes and \`chant migrate\`
150
+
151
+ \`chant migrate\` translates a file from one lexicon's format into another's,
152
+ such as a GitHub Actions workflow into GitLab CI. It does not run schema
153
+ migrations, and the sql lexicon registers nothing for it. A schema change is a
154
+ change to the declarations: \`chant sql diff\` or \`chant sql plan\` classifies
155
+ it, the dialect's applier makes the changes it can make in place, and a change
156
+ it cannot make runs as a gated migration Op: \`ClickHouseRebuildOp\` (see
157
+ [Rebuilding a Table](./rebuild/)) or \`PostgresMigrationOp\` (see
158
+ [Migrating a Column](./postgres-migration/)).
159
+ `;
160
+ const outputFormat = `A build writes two files, beside each other. Which pair depends on the
161
+ dialect the project declares.
162
+
163
+ - The primary output (the \`-o\` file, \`dist/schema.json\` by convention), one
164
+ JSON document. \`dialect\` is \`clickhouse\` or \`postgres\`. \`applyOrder\`
165
+ lists the export names in the order the objects have to be created.
166
+ \`objects\` holds one entry per declared object, in that order: its export
167
+ name (\`export\`), its type, its SQL name (\`sqlName\`), its parsed
168
+ definition, \`dependsOn\`, and its \`ddl\`. References are written as export
169
+ names and lineage as \`export.column\`.
170
+ - ClickHouse: the types are \`ClickHouse::Database\`, \`::Table\`, \`::View\`
171
+ and \`::MaterializedView\`, and the definition holds columns, engine, keys,
172
+ TTL, settings, indexes, projections and constraints, and for a view its
173
+ \`select\`, \`reads\`, \`to\` and \`lineage\`.
174
+ - Postgres: the document also carries \`postgresMajor\`, the major the
175
+ project targets (\`sql.postgresMajor\`, else 18, the newest pinned). The
176
+ types are \`Postgres::Schema\`, \`::Table\`, \`::Index\`, \`::View\`,
177
+ \`::MaterializedView\`, \`::Sequence\`, \`::Enum\`, \`::Domain\` and
178
+ \`::Extension\`. A table's definition holds its columns, primary key,
179
+ uniques, checks, foreign keys, exclusions and the rest of its clauses; a
180
+ view's its \`query\`, \`reads\` and \`lineage\`; an index's its table,
181
+ method and elements. \`dependsOn\` names the objects and the columns the
182
+ statement references.
183
+ - \`clickhouse.sql\` or \`postgres.sql\`: every statement in \`applyOrder\`, each
184
+ ending in \`;\`, written byte for byte as declared, with a Postgres
185
+ template's \`COMMENT ON\` statements after its \`CREATE\`.
186
+
187
+ The order follows the references: a table after its database or schema and the
188
+ types and sequences it uses, a view after the tables it reads, an index after
189
+ its table, a materialized view after its \`TO\` target. Ties go by export name,
190
+ so the output does not depend on the order files were found in. A reference
191
+ cycle fails the build and names the cycle.
192
+
193
+ \`chant sql diff\`, \`chant sql plan\`, the post-synth checks and the appliers
194
+ read the JSON document. Neither file carries chant's ownership marker: the
195
+ applier adds it to each object's comment when it creates the object (see
196
+ [Applying to a ClickHouse Server](../applying/) and
197
+ [Applying to a Postgres Server](../postgres-applying/)).
198
+ `;
199
+ export async function generateDocs(opts) {
200
+ const pkgDir = dirname(dirname(dirname(fileURLToPath(import.meta.url))));
201
+ writeFileSync(join(pkgDir, "docs", "pages", "change-classifier.mdx"), renderClassifierPage());
202
+ writeFileSync(join(pkgDir, "docs", "pages", "postgres-change-classifier.mdx"), renderPostgresClassifierPage());
203
+ writeFileSync(join(pkgDir, "docs", "pages", "object-coverage.mdx"), renderCoveragePage());
204
+ const config = {
205
+ name: "sql",
206
+ displayName: "SQL",
207
+ description: "Database schema as typed declarations in each database's own DDL: ClickHouse and Postgres",
208
+ distDir: join(pkgDir, "dist"),
209
+ outDir: join(pkgDir, "docs"),
210
+ basePath: process.env.DOCS_BASE_PATH ?? "/chant/lexicons/sql/",
211
+ overview,
212
+ outputFormat,
213
+ serviceFromType: (type) => type.split("::")[0] ?? "SQL",
214
+ srcDir: join(pkgDir, "src"),
215
+ examplesDir: join(pkgDir, "examples"),
216
+ };
217
+ const result = docsPipeline(config);
218
+ writeDocsSite(config, result);
219
+ if (opts?.verbose) {
220
+ console.error(`Generated ${result.pages.size} documentation pages`);
221
+ }
222
+ }
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env tsx
2
+ import { generate, generatePostgres, writeGeneratedFiles } from "./generate.js";
3
+ // `npm run generate -- --force` reads the pinned servers even when the snapshots match the pins;
4
+ // `--major=18` limits the Postgres read to one major.
5
+ const force = process.argv.includes("--force");
6
+ const majors = process.argv
7
+ .filter((a) => a.startsWith("--major="))
8
+ .map((a) => Number.parseInt(a.slice("--major=".length), 10));
9
+ const result = await generate({ verbose: true, force });
10
+ const postgres = await generatePostgres({ force, ...(majors.length > 0 ? { majors } : {}) });
11
+ for (const note of postgres.notes)
12
+ console.error(`[sql] ${note}`);
13
+ writeGeneratedFiles(result, undefined, postgres);
@@ -0,0 +1,97 @@
1
+ /**
2
+ * The sql lexicon's generation pipeline.
3
+ *
4
+ * Two dialects. ClickHouse's "schema" is the catalog a pinned
5
+ * `clickhouse-server` reports from `system.*`, committed as
6
+ * `src/spec/clickhouse-catalog.snapshot.json` (chant #3195). `fetchSchemas`
7
+ * reads that snapshot, and starts the pinned server only on a pin move; see
8
+ * `src/spec/fetch.ts`.
9
+ *
10
+ * Outputs, under `src/generated/`:
11
+ *
12
+ * - `clickhouse-types.ts` (and `index.d.ts`, the packaged copy): unions of every
13
+ * engine, type family, codec, skip index type, format and function name, and
14
+ * the `MergeTreeSettings` / `QuerySettings` interfaces.
15
+ * - `clickhouse.ts`: the tables lint and the LSP read, with the hand-written
16
+ * overlays (engine argument kinds, codec parameters) merged in.
17
+ * - `lexicon-sql.json`: the entity registry.
18
+ */
19
+ import { generatePipeline, writeGeneratedArtifacts, } from "@intentius/chant/codegen/generate";
20
+ import { NamingStrategy } from "@intentius/chant/codegen/naming";
21
+ import { dirname } from "path";
22
+ import { fileURLToPath } from "url";
23
+ import { CATALOG_KEY, fetchSchemas } from "../spec/fetch.js";
24
+ import { parseCatalog } from "../spec/catalog.js";
25
+ import { renderClickHouseModule } from "./clickhouse-module.js";
26
+ import { buildRegistry } from "./registry.js";
27
+ import { fetchCatalogs } from "../spec/postgres-fetch.js";
28
+ import { renderPostgresModule } from "./postgres-module.js";
29
+ export async function generate(opts = {}) {
30
+ let notes = [];
31
+ let tables = "";
32
+ const result = await generatePipeline({
33
+ fetchSchemas: (fetchOpts) => fetchSchemas({ force: fetchOpts.force }),
34
+ parseSchema: (typeName, data) => {
35
+ if (typeName !== CATALOG_KEY)
36
+ return null;
37
+ const catalog = parseCatalog(data.toString("utf-8"));
38
+ return {
39
+ typeName,
40
+ catalog,
41
+ propertyTypes: [{ name: "MergeTreeSettings" }, { name: "QuerySettings" }],
42
+ enums: [],
43
+ };
44
+ },
45
+ createNaming: (results) => new NamingStrategy(results.map((r) => ({ typeName: r.typeName, propertyTypes: r.propertyTypes })), {
46
+ priorityNames: {},
47
+ priorityAliases: {},
48
+ priorityPropertyAliases: {},
49
+ serviceAbbreviations: {},
50
+ shortName: (t) => t.split("::").pop(),
51
+ serviceName: (t) => t.split("::")[0] ?? t,
52
+ }),
53
+ generateRegistry: () => buildRegistry(),
54
+ generateTypes: (results) => {
55
+ const catalog = results.find((r) => r.typeName === CATALOG_KEY)?.catalog;
56
+ if (!catalog)
57
+ throw new Error("no ClickHouse catalog was parsed");
58
+ const rendered = renderClickHouseModule(catalog);
59
+ notes = rendered.notes;
60
+ tables = rendered.tables;
61
+ return rendered.declarations;
62
+ },
63
+ generateRuntimeIndex: () => tables,
64
+ }, opts);
65
+ if (result.warnings.length > 0) {
66
+ throw new Error(`sql generation failed:\n ${result.warnings.map((w) => `${w.file}: ${w.error}`).join("\n ")}`);
67
+ }
68
+ if (opts.verbose)
69
+ for (const note of notes)
70
+ console.error(`[sql] ${note}`);
71
+ return result;
72
+ }
73
+ /**
74
+ * Generate the Postgres types: the union of the catalogs of every supported
75
+ * major (`src/spec/postgres-catalog-<major>.snapshot.json`), rendered with the
76
+ * overlays. A server is started only for a major whose pin moved, or with
77
+ * `force`; see `src/spec/postgres-fetch.ts`. The types stay internal to the
78
+ * package until the `/postgres` subpath has entities to export with them.
79
+ */
80
+ export async function generatePostgres(opts = {}) {
81
+ const catalogs = await fetchCatalogs(opts);
82
+ return renderPostgresModule(catalogs);
83
+ }
84
+ /** Write the generated files under `src/generated/`. */
85
+ export function writeGeneratedFiles(result, pkgDir, postgres) {
86
+ const baseDir = pkgDir ?? dirname(dirname(dirname(fileURLToPath(import.meta.url))));
87
+ writeGeneratedArtifacts({
88
+ baseDir,
89
+ files: {
90
+ "lexicon-sql.json": result.lexiconJSON,
91
+ "index.d.ts": result.typesDTS,
92
+ "clickhouse-types.ts": result.typesDTS,
93
+ "clickhouse.ts": result.indexTS,
94
+ ...(postgres ? { "postgres-types.ts": postgres.declarations, "postgres.ts": postgres.tables } : {}),
95
+ },
96
+ });
97
+ }