ClickHouse / ClickHouse/dbt-clickhouse

dbt Core 2.0 parity: General adapter behaviour

Open
#712 0 comments 0 reactions 0 assignees View on GitHub
enhancement
Dominant language
Python
Stars
362
Forks
177
Avg merge
2d 10h
Merged PRs (30d)
8

Description

Sub-issue of #660 — feature-parity tracking for the ClickHouse adapter in dbt Core 2.0 / Fusion versus the Python `dbt-clickhouse` adapter.

Covers adapter-wide behaviour: capability probes (EXCHANGE, lightweight deletes), server version checks, column schema introspection, macro sync with upstream, S3 source support, connection-level behaviour and usage tracking. Metadata-based source freshness is a dbt Core 2.0-only capability and is tracked in #736.

**Status legend:** ✅ implemented — merged and working on dbt-core 2.0 `origin/main` · 🟡 partial — partly working on `origin/main` (Notes say what works vs fails) · 🚧 in progress — implemented in an open PR (linked in Notes) · 🔴 not started — not working anywhere · ⚪️ future work — explicitly deferred, not being solved now (also listed in the future-work sub-issue) · Combined status "A-🚧->B": the feature is at A on origin/main today; an open PR is driving it to B (🟡 partially working / ✅ fully working)

| Feature | Subfeatures / details | Status | Notes (PR) |
| --------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **General adapter behaviour** | *(overall)* | 🟡 | Merged: version probe, DESCRIBE introspection, TLS, non-experimental registration, S3 (dbt-labs/dbt-core#16082), lw-delete probe (dbt-labs/dbt-core#16090), EXCHANGE probe (dbt-labs/dbt-core#16200), 0.1.1 driver (dbt-labs/dbt-core#16185), `dbt/` User-Agent (dbt-labs/dbt-core#16156). Missing: usage tracking (dbt first in the User-Agent), query comment, `query_id`, view replace fallback without `renameat2` |
| Server version checks | `SELECT version()` probe + `adapter.is_before_version` / `is_at_or_after_version` | ✅ | dbt-labs/dbt-core#16079: once-per-process probe, `compare_versions` mirrors util.py; used by the 26.6 `insert_overwrite` gate |
| `adapter.format_columns` / `get_column_schema_from_query` | `DESCRIBE TABLE (sql)` with the model's `query_settings`; ADBC/Arrow reports all columns Nullable, so the server-typed schema replaces the driver schema | ✅ | dbt-labs/dbt-core#16079 (fixes dbt-labs/dbt-core#14581) |
| TLS / secure connections | `secure` profile flag, HTTPS/TLS driver support | ✅ | Driver 0.1.0-a2 for TLS (dbt-labs/dbt-core#10391); `secure` registered with port/scheme autodetection |
| Adapter registration / onboarding | ClickHouse listed as a non-experimental adapter; `dbt init` flow | ✅ | Non-experimental (closes dbt-labs/dbt-core#15410); `dbt init` improvements (dbt-labs/dbt-core#10558) |
| Lightweight-delete capability probe | `use_lw_deletes` profile flag + settings/permission checks | ✅ | Probe in dbt-labs/dbt-core#16090; `allow_nondeterministic_mutations` sent for the disabled-but-changeable case in dbt-labs/dbt-core#16156 (adbc_clickhouse#70) |
| ADBC driver: literal `?` in SQL | A literal `?` must reach the server verbatim (the 0.1.0 driver treated it as a bind param, forcing `\x3F`/`??` escapes into seed.sql, adapters.sql and materialized_view.sql) | ✅ | adbc_clickhouse 0.1.1 (adbc_clickhouse#53) via dbt-labs/dbt-core#16185 sends a literal `?` verbatim; dbt-labs/dbt-core#16156 retired seed.sql's `??` escape. The `\x3F` regex escapes in adapters.sql/materialized_view.sql are harmless server-side escapes and stay until retired together with the v1 macro tree |
| S3 table function | `adapter.s3source_clause` (`clickhouse_s3source(...)` via project vars), incl. `external_id`/`role_arn` extra credentials | ✅ | dbt-labs/dbt-core#16082 with impl.py parity |
| UUID support in ADBC / Arrow | Driver-side: ADBC driver 0.1.0 (adbc_clickhouse#63); server-side: Arrow output of `UUID` columns requires ClickHouse 26.7+ | ✅ | Driver fix released (adbc_clickhouse#63). The server-side 26.7+ requirement is a Known limitation in #660; no adapter work |
| EXCHANGE capability check | Probe once per process: db-engine check + real `CREATE`/`EXCHANGE`/`DROP` scratch test; `check_exchange: false` skips; `relation.can_exchange` stamped on cached relations and used by the table / incremental / snapshot / materialized-view swaps | ✅ | dbt-labs/dbt-core#16200. Rebuilds and full refreshes of tables, incremental swaps, snapshot upserts and MV target rebuilds run `EXCHANGE TABLES` on Atomic/Replicated/Shared databases and fall back to rename elsewhere |
| Macro sync to upstream | Byte-identical macros; only documented Fusion divergences allowed | 🟡 | Most of the tree is byte-identical (dbt-labs/dbt-core#16023, #16079, #16082, #16200, #16153). Still differing on main: adapters.sql, persist_docs.sql (extra `validate_doc_columns` call), view.sql (no `supports_atomic_exchange` fallback), seed/distributed_table/incremental/distributed_incremental/schema_changes. Missing entirely: `macros/adapters/` (apply_grants.sql, relation.sql), `materializations/clone.sql`, `utils/datatypes.sql`. Deliberate divergences: adapters.sql `clickhouse__check_schema_exists`, seed.sql's literal-VALUES insert (the `format CSV` path is deferred, #731) |
| Connection profile keys parity | `cluster`, `cluster_mode`, `use_lw_deletes`, `check_exchange`, `local_suffix`, `local_db_prefix`, `allow_automatic_deduplication`, `custom_settings`, `database_engine`, `sync_request_timeout`, `compress_block_size`, `secure`, … | 🟡 | Consumed on main: `secure`, `custom_settings` (driver options, dbt-labs/dbt-core#16156), `check_exchange` (EXCHANGE probe, dbt-labs/dbt-core#16200), `use_lw_deletes` (lw-deletes probe, dbt-labs/dbt-core#16090), `allow_automatic_deduplication` (dedup default, dbt-labs/dbt-core#16079), `database_engine`/`cluster_mode` (connection settings + DDL), `local_suffix`/`local_db_prefix` (distributed macros). Missing: `cluster` is not consumed yet; the HTTP-client keys `verify`, `client_cert`/`client_cert_key`, `connect_timeout`, `send_receive_timeout`, `sync_request_timeout`, `compress_block_size` parse but are inert — the ADBC driver exposes no TLS-verification, client-certificate, timeout or compression options, so these need driver work first |
| Usage tracking | dbt identifies itself first in the HTTP `User-Agent` (`system.query_log.http_user_agent`), as `dbt/ …` | 🟡 | v1 sends `dbt-adapters/x dbt-clickhouse/y clickhouse-connect/z (lv:py/…; os:…; os_user:…)`. Merged (dbt-labs/dbt-core#16156): `dbt/` via the driver's `clickhouse.client.product_info` option — DDL/INSERT statements log `dbt/2.0.0-rc.1 adbc_clickhouse/0.1.1 clickhouse-rs/0.15.2 (…)`, but Arrow reads (SELECT/DESCRIBE) log `clickhouse-ext-arrow/0.1.0 dbt/2.0.0-rc.1 …` because clickhouse-ext-arrow tags the query last and clickhouse-rs prints the last-added product first. Missing: `dbt/…` always first — reported as ClickHouse/clickhouse-rs#469; the fix has to land there, then ship in a clickhouse-rs release, then in an adbc_clickhouse release, and only then can dbt Core 2.0 bump its driver pin (no dbt-side code change expected). Extra key/value pairs in the parenthesised comment are not possible either (clickhouse-rs hardcodes that section) |
| View replace fallback without `renameat2` | `adapter.supports_atomic_exchange()`; view.sql falls back to drop + create when the filesystem lacks `renameat2` (NFS), upstream #684 | 🔴 | Only the method name is registered on main (no implementation) and view.sql has no fallback, so `CREATE OR REPLACE VIEW` fails with `UNSUPPORTED_METHOD` on such filesystems (`test_view_no_renameat2`) |
| Query comment handling | `query-comment: null` honored; rendered macro comments re-validated | 🔴 | 2 integration tests fail (NullQueryComments, MacroInvalidQueryComments). Engine-generic fix |
| `adapter_response.query_id` | Engine-assigned `clickhouse.client.query_id` surfaced into run results/logs | 🔴 | 1 integration test fails |
| `dbt debug` target handling | Bad target should surface a connection-failure report, not a profile-resolution error | ⚪️ | Deferred (#731). An unknown `--target` errors out before the `dbt debug` report is printed |
| `dbt run --sample` (sample mode) | Models' inputs filtered by the `--sample` window | ⚪️ | Deferred (#731). A sampled model returns 0 rows on ClickHouse |
| Duplicate hook definitions | A node defining both `post-hook` and `post_hook` (or the `pre-` pair) must fail compilation | ⚪️ | Deferred (#731). v2 keeps one of the two hooks silently instead of failing |
| Port dbt-clickhouse 1.10.1 features | Bring the features added in v1 1.10.1 to 2.X | ⚪️ | Deferred (#731); not itemized yet |
| Port dbt-clickhouse 1.10.2 features | Bring the features added in v1 1.10.2 to 2.X | ⚪️ | Deferred (#731); not itemized yet |

Contributor guide

Open the contributing guide

Research direction

Start by reading the remaining-status rows and comparing the listed macro paths—macros/adapters/, materializations/clone.sql, utils/datatypes.sql, and the differing adapter, view, seed, incremental, and schema-change macros—with upstream dbt Core. Review the notes for usage tracking, query comments, query_id, and view replacement fallback. Done means the remaining parity items are implemented or explicitly tracked as deferred.

Written by the indexing model from the issue text.

Assessment

Tech stack
clickhouse, python
Domain
databases
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.