Add ClickHouse and chDB readers - #535
Open
alexey-milovidov wants to merge 2 commits into
Open
Conversation
Two readers behind the new default-on `clickhouse` and `chdb` features, sharing one implementation (`ClickHouseSqlReader<T: Transport>`): - `clickhouse://[user[:password]@]host[:port][/database][?setting=…]` (`clickhouses://` for TLS) talks to a server's HTTP interface with plain requests and exchanges data as Arrow IPC streams, so no driver is needed. Unknown URI parameters are forwarded as ClickHouse settings; host, user and password fall back to CLICKHOUSE_HOST/USER/PASSWORD. - `chdb://[path]` runs the embedded chDB engine in-process. libchdb is loaded at runtime via libloading (same approach as the ODBC driver manager), so the build has no new native dependency. chDB is also a new `CacheBackend` (`chdb+<primary>://`, `--cache chdb`), so a ClickHouse setup needs no other engine. Type handling: every SELECT is DESCRIBEd first and, when ClickHouse's Arrow output would lose the type (DateTime → UInt32, Enum → codes, UUID/IP/wide integers → bytes, Decimal), wrapped in `SELECT * REPLACE (…)` converting those columns server-side; timestamps are normalized to naive microseconds. Read-only accounts (e.g. play.clickhouse.com) are detected on connect via a CREATE TEMPORARY TABLE probe; `reader_from_uri` then keeps the executor's intermediate tables in an embedded chDB cache automatically. Dialect: Nullable(…) cast targets, TEMPORARY temp tables, quantiles via quantileExactInclusive (inline, no correlated subquery), greatest/least cast to Float64 (no UInt64/Float64 supertype), Memory-engine memo table for the caching layer via new `cache_meta_*` SqlDialect hooks, and a new `sql_null_safe_equals` hook because older ClickHouse only accepts IS NOT DISTINCT FROM in JOIN ON. Portable fixes found along the way: the Vega-Lite writer rescaled timestamps that were already converted to microseconds (overflow for any non-microsecond source); density and boxplot stat SQL now alias qualified projections, which ClickHouse otherwise names `cte.col`. Also: CLI `--cache chdb`, Jupyter kernel connection names, Positron connection drivers for ClickHouse and chDB, docs and CHANGELOG. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Remove the `sql_null_safe_equals` dialect hook and the dialect threading it required in the density stat SQL: ClickHouse 26.8+ accepts `IS NOT DISTINCT FROM` in any clause and supports correlated subqueries, so no compatibility spelling is needed. Document the version requirement. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Reviewed and merged first in the ClickHouse fork (ClickHouse#2); this is the same change proposed upstream.
Integrates ggsql with ClickHouse. Two readers behind new default-on
clickhouseandchdbfeatures share one implementation (ClickHouseSqlReader<T: Transport>insrc/reader/clickhouse/):clickhouse://[user[:password]@]host[:port][/database][?setting=…](clickhouses://for TLS) talks to a server's HTTP interface with plain requests and exchanges data as Arrow IPC streams (FORMAT ArrowStream), so no driver is needed. Unknown URI parameters are forwarded as ClickHouse settings; host, user and password fall back toCLICKHOUSE_HOST/CLICKHOUSE_USER/CLICKHOUSE_PASSWORD.chdb://[path]runs the embedded chDB engine in-process. libchdb is loaded at runtime vialibloading(the same approach as the ODBC driver manager), so the build has no new native dependency and a binary works with or without the library installed. chDB is also a newCacheBackend(chdb+<primary>://,--cache chdb), so a ClickHouse setup never depends on DuckDB.Each reader owns one session, so the executor's temporary tables and
SETstatements persist across statements and stat transforms (binning, quantiles, KDE) run on the engine. A read-only account (e.g.play.clickhouse.com) is detected on connect with aCREATE TEMPORARY TABLEprobe;reader_from_urithen keeps intermediate tables in an embedded chDB cache automatically, so the plainclickhouse://URI just works there.Type handling
ClickHouse's Arrow output loses some of its own types (
DateTime→UInt32,Enum→ codes,UUID/IPv4/IPv6/wide integers → bytes,Decimal→ an Arrow decimal the pipeline does not consume). EverySELECT/WITHisDESCRIBEd first and, when needed, wrapped inSELECT * REPLACE (…)converting those columns server-side. Timestamps are normalized to naive microseconds. Arrow batches from ClickHouse are LZ4-compressed by default (a read-only account cannot change that), hencearrow/ipc_compression.Dialect
Nullable(…)cast targets (ClickHouse cannot cast NULL to a non-nullable type),TEMPORARYtemp tables, quantiles viaquantileExactInclusive(inline, no correlated subquery),greatest/leastarguments cast to Float64 (no UInt64/Float64 supertype), and aMemory-engine memo table for the caching layer through newcache_meta_*SqlDialecthooks. ClickHouse 26.8 or newer is assumed; there are deliberately no shims for older servers.Portable fixes found along the way
grid."g" AS "g"); ClickHouse otherwise names an unaliasedcte.colprojectioncte.col.Also
CLI
--cache chdb, Jupyter kernel connection display names, Positron connection drivers for ClickHouse and chDB, docs (doc/get_started/tooling/cli.qmd), CHANGELOG, CLAUDE.md notes.GGSQL_CLICKHOUSE_TRACE=1prints every statement sent.Testing
cargo test -p ggsql --lib: 1835 passed (withGGSQL_CLICKHOUSE_URIandGGSQL_CHDB_LIBRARYset, the 34 ClickHouse/chDB live tests run against a local ClickHouse 26.9 server and libchdb 26.7; without them they skip).cargo test -p ggsql-cli -p ggsql-jupyterpass.cargo +1.86 build -p ggsql(MSRV) passes.cargo fmt,cargo clippy --all-targetsclean for the new code (one pre-existing warning ingeographic.rstests untouched).npm run check-typespasses for the VS Code extension.chdb://memoryover a Parquet file (tile heatmap, grouped density, area), and 4 onclickhouses://explorer@play.clickhouse.com:443through the automatic chDB cache (github_events,uk_price_paid,hackernews,opensky).Notes for reviewers
chdb://readers on the same path share it, and the chDB tests are serialized on a mutex because the executor's temp-table names are per process.🤖 Generated with Claude Code