Add ClickHouse server-version detection#293
Conversation
Expose the ClickHouse server version at any time, including during query
planning, via chfdw_get_server_version(UserMapping*), with a
chfdw_version_ge() comparison helper. This is the reusable plumbing that
lets a later change gate subquery pushdown on the server version so that
older ClickHouse releases fall back gracefully instead of erroring.
- New server_version method on the libclickhouse_methods vtable.
- Binary driver reads the version captured during the native-protocol
handshake (chc_client_server_info).
- HTTP driver fetches it lazily via SELECT version() and caches it on
the connection.
- New clickhouse_server_version(text) SQL function returning
"major.minor.patch" exercises both drivers, covered by the new
server_version regression test.
No behavior change to existing flows: nothing calls the getter at plan
time yet, so planning still opens no connection.
| /* | ||
| * Build the query directly rather than via new_query(): this file does | ||
| * not include fdw.h (which declares chfdw_get_session_settings), and the | ||
| * version probe needs no session settings. | ||
| */ |
There was a problem hiding this comment.
| /* | |
| * Build the query directly rather than via new_query(): this file does | |
| * not include fdw.h (which declares chfdw_get_session_settings), and the | |
| * version probe needs no session settings. | |
| */ |
theory
left a comment
There was a problem hiding this comment.
Will read carefully tomorrow, but just to note here, if we're adding a new SQL function, we need to increment to v0.4.0 and add an upgrade script, sql/pg_clickhouse--0.3--0.4.sql. See #196 for a pervious such change to the extension's catalog.
|
Simpler example of incrementing the version and adding an upgrade script in ClickHouse/pg_re2#22 |
theory
left a comment
There was a problem hiding this comment.
This looks good, though it doesn't look like the http connection caches the version info to allow multiple calls with the same connection without each resulting in an HTTP request.
Please add the new function to pg_clickhouse.md and an item to CHANGELOG.md, as well as the aforementioned migration script and version increments.
Also I thought ClickHouse returned a header with the version, but apparently not:
❯ curl -iX POST 'http://localhost:8123/' -d 'SELECT 1'
HTTP/1.1 200 OK
X-ClickHouse-Summary: {"read_rows":"1","read_bytes":"1","written_rows":"0","written_bytes":"0","total_rows_to_read":"1","result_rows":"0","result_bytes":"0","elapsed_ns":"5185292"}
Date: Wed, 24 Jun 2026 19:58:06 GMT
Connection: Keep-Alive
Content-Type: text/tab-separated-values; charset=UTF-8
Access-Control-Expose-Headers: X-ClickHouse-Query-Id,X-ClickHouse-Summary,X-ClickHouse-Server-Display-Name,X-ClickHouse-Format,X-ClickHouse-Timezone,X-ClickHouse-Exception-Code
X-ClickHouse-Server-Display-Name: clickhouse01
Transfer-Encoding: chunked
X-ClickHouse-Query-Id: 93bf9289-6dbf-4621-a5d9-9c183e8d8484
X-ClickHouse-Format: TabSeparated
X-ClickHouse-Timezone: UTC
Keep-Alive: timeout=3, max=9999| return s ? s->broken : false; | ||
| } | ||
|
|
||
| void |
| static inline bool | ||
| chfdw_version_ge(ch_server_version v, int major, int minor) { | ||
| return v.major > major || (v.major == major && v.minor >= minor); | ||
| } |
There was a problem hiding this comment.
Maybe this should live in server_version.h?
| ch_query query = { "SELECT version()", 0, NULL, NULL, NULL, NULL }; | ||
| ch_http_response_t* resp = ch_http_simple_query(conn, &query); | ||
|
|
||
| if (resp != NULL) { |
There was a problem hiding this comment.
We should log an error if the response is an error.
| return; | ||
| } | ||
|
|
||
| if (conn->version.major == 0) { |
There was a problem hiding this comment.
Do we know for sure that major was allocated with all memory set to 0?
|
|
||
| SELECT clickhouse_server_version('srv_ver_binary') ~ '^[0-9]+\.[0-9]+\.[0-9]+$' | ||
| AS binary_well_formed, | ||
| split_part(clickhouse_server_version('srv_ver_binary'), '.', 1)::int >= 1 |
There was a problem hiding this comment.
This seems redundant, the regex test covers it.
Exposes the ClickHouse server version to the planner via
chfdw_get_server_version(UserMapping*), with achfdw_version_ge()comparison helper. This is the reusable plumbing a follow-up will use to gate
subquery pushdown on the server version, so older ClickHouse releases degrade
gracefully instead of erroring on SQL their analyzer cannot handle.
What's here
server_versionmethod on thelibclickhouse_methodsvtable, backed by asmall dependency-free
ch_server_versionstruct (shared between thePostgres-free driver internals and the FDW layer).
handshake (
chc_client_server_info) — free once the connection exists.and the "connection" is just a curl handle with no server round-trip), so it
fetches
SELECT version()once and caches it on the connection.clickhouse_server_version(text)SQL function returningmajor.minor.patch, which exercises both drivers and is covered by the newserver_versionregression test.Notes
yet, so planning still opens no connection. The (amortized, once-per-session)
plan-time connect arrives with the gate in the follow-up PR.
🤖 Generated with Claude Code