Commit 76e9c07
feat: add ClickHouse warehouse driver (#574)
* feat: add ClickHouse warehouse driver with full integration
Add first-class ClickHouse support as the 12th database driver:
**Driver (`packages/drivers/src/clickhouse.ts`):**
- Official `@clickhouse/client` over HTTP(S)
- Supports ClickHouse server 23.3+ (all non-EOL versions)
- Password, connection string, and TLS/mTLS auth
- ClickHouse Cloud and self-hosted compatible
- Parameterized queries for SQL injection prevention
- DML-aware LIMIT injection (won't break `WITH...INSERT`)
**Integration (23 touchpoints):**
- Registry: `DRIVER_MAP`, import switch, `PASSWORD_DRIVERS`
- Discovery: Docker containers, env vars (`CLICKHOUSE_HOST`/`CLICKHOUSE_URL`),
dbt profiles (`ADAPTER_TYPE_MAP`), dbt lineage dialect
- FinOps: `system.query_log` query history template
- Normalization: aliases for `connectionString`, `requestTimeout`, TLS fields
- Publish: `@clickhouse/client` in `peerDependencies`
**Tests:**
- 30+ E2E tests across 5 suites (latest, LTS 23.8, 24.3, 24.8, connection string)
- 14 config normalization tests for all ClickHouse aliases
- MergeTree variants, materialized views, Nullable columns, Array/Map/IPv4 types
**Documentation:**
- Full config section in `warehouses.md` (standard, Cloud, connection string)
- Support matrix entry in `drivers.md` with auth methods
- Dedicated guide (`guides/clickhouse.md`): MergeTree optimization, materialized
view pipelines, dialect translation, LowCardinality tips, dbt integration
- Updated README, getting-started, warehouse-tools docs
**Engineering:**
- `packages/drivers/ADDING_A_DRIVER.md` — 23-point checklist for adding future drivers
- `.claude/commands/add-database-driver.md` — Claude skill to automate the process
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: use `client.command()` for ClickHouse DDL/DML, fix E2E test auth
- `execute()` now uses `client.command()` for INSERT/CREATE/DROP/ALTER
queries instead of `client.query()` with JSONEachRow format, which
caused parse errors on INSERT VALUES
- Add `CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT=1` to all LTS Docker
containers (required for passwordless default user)
- Fix UInt64 assertion to handle both string and number JSON encoding
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* ci: add ClickHouse E2E tests to driver-e2e CI job
- Add `clickhouse/clickhouse-server:latest` as a GitHub Actions service
- Add test step running `drivers-clickhouse-e2e.test.ts` with CI env vars
- Add test file to change detection paths for the `drivers` filter
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: 3 driver bugs found by adversarial testing (167 tests, 3 real failures)
Ran 167 adversarial tests against real ClickHouse Docker containers
covering SQL injection, unicode, NULLs, LIMIT edge cases, exotic types,
error handling, large data, MergeTree variants, views, system tables,
concurrent operations, and return value edge cases.
**Bugs found and fixed:**
1. **DESCRIBE/EXISTS get LIMIT appended** — `isSelectLike` regex matched
DESCRIBE/EXISTS but ClickHouse doesn't support LIMIT on these statements.
Fix: narrowed `supportsLimit` to only `SELECT` and `WITH` queries.
2. **`limit=0` returns 0 rows** — truncation check `rows.length > 0` was
always true, causing `slice(0, 0)` to return empty array.
Fix: guard with `effectiveLimit > 0 &&` before truncation check.
3. **`limit=0` treated as `limit=1000`** — `0 ?? 1000` returns 0 (correct)
but `limit === undefined ? 1000 : limit` properly distinguishes "not
provided" from "explicitly zero". Changed from `??` to explicit check.
**Regression tests added (5 tests in main E2E suite):**
- DESCRIBE TABLE without LIMIT error
- EXISTS TABLE without LIMIT error
- limit=0 returns all rows without truncation
- INSERT uses `client.command()` not `client.query()`
- WITH...INSERT does not get LIMIT appended
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: address CodeRabbit review findings for ClickHouse driver PR
- Remove stale ClickHouse entry from "Unsupported Databases" doc section
- Add ClickHouse to Docker auto-discovery description in docs
- Add blank line around ClickHouse auth table for markdownlint MD058
- Add `text` language tag to fenced code block for markdownlint MD040
- Fail fast when `binds` passed to ClickHouse `execute()` instead of ignoring
- Add `tls_key`, `tls_cert`, `tls_ca_cert` to SENSITIVE_FIELDS in credential store
- Clamp `days`/`limit` values in ClickHouse query history SQL builder
- Add `clickhouse`, `clickhouse+http`, `clickhouse+https` to DATABASE_URL scheme map
- Make `waitForPort` accept configurable host in E2E tests
- Close failed connectors during `waitForDbReady` retries in E2E tests
- Add missing TLS alias tests: `ca_cert`, `ssl_cert`, `ssl_key`
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>1 parent 75b077f commit 76e9c07
File tree
29 files changed
+1937
-130
lines changed- .claude/commands
- .github
- meta
- workflows
- docs
- docs
- configure
- data-engineering
- guides
- tools
- getting-started
- packages
- drivers
- src
- opencode
- .github/meta
- script
- src/altimate
- native
- connections
- dbt
- finops
- tools
- test/altimate
29 files changed
+1937
-130
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
2 | | - | |
3 | | - | |
4 | | - | |
5 | | - | |
6 | | - | |
7 | | - | |
8 | | - | |
9 | | - | |
10 | | - | |
11 | | - | |
12 | | - | |
13 | | - | |
14 | | - | |
15 | | - | |
16 | | - | |
17 | | - | |
18 | | - | |
19 | | - | |
20 | | - | |
21 | | - | |
22 | | - | |
23 | | - | |
24 | | - | |
25 | | - | |
26 | | - | |
27 | | - | |
28 | | - | |
29 | | - | |
| 1 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
46 | 46 | | |
47 | 47 | | |
48 | 48 | | |
| 49 | + | |
49 | 50 | | |
50 | 51 | | |
51 | 52 | | |
| |||
198 | 199 | | |
199 | 200 | | |
200 | 201 | | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
201 | 215 | | |
202 | 216 | | |
203 | 217 | | |
| |||
245 | 259 | | |
246 | 260 | | |
247 | 261 | | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
248 | 269 | | |
249 | 270 | | |
250 | 271 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
151 | 151 | | |
152 | 152 | | |
153 | 153 | | |
154 | | - | |
| 154 | + | |
155 | 155 | | |
156 | 156 | | |
157 | 157 | | |
| |||
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | | - | |
| 3 | + | |
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
| |||
288 | 288 | | |
289 | 289 | | |
290 | 290 | | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
291 | 351 | | |
292 | 352 | | |
293 | 353 | | |
| |||
320 | 380 | | |
321 | 381 | | |
322 | 382 | | |
323 | | - | |
324 | 383 | | |
325 | 384 | | |
326 | 385 | | |
| |||
362 | 421 | | |
363 | 422 | | |
364 | 423 | | |
365 | | - | |
| 424 | + | |
366 | 425 | | |
367 | 426 | | |
368 | 427 | | |
| |||
0 commit comments