Skip to content

Add ClickHouse server-version detection - #293

Merged
JoshDreamland merged 1 commit into
mainfrom
ch-server-version
Jun 30, 2026
Merged

Add ClickHouse server-version detection#293
JoshDreamland merged 1 commit into
mainfrom
ch-server-version

Conversation

@JoshDreamland

Copy link
Copy Markdown
Contributor

Exposes the ClickHouse server version to the planner via
chfdw_get_server_version(UserMapping*), with a chfdw_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

  • A server_version method on the libclickhouse_methods vtable, backed by a
    small dependency-free ch_server_version struct (shared between the
    Postgres-free driver internals and the FDW layer).
  • Binary driver: reads the version straight from the native-protocol
    handshake (chc_client_server_info) — free once the connection exists.
  • HTTP driver: ClickHouse exposes no version over HTTP (no response header,
    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.
  • A clickhouse_server_version(text) SQL function returning
    major.minor.patch, which exercises both drivers and is covered by the new
    server_version regression test.

Notes

  • No behavior change to existing flows: nothing calls the getter at plan time
    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

@JoshDreamland
JoshDreamland requested review from Copilot, serprex and theory and removed request for theory June 23, 2026 17:19

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review any files in this pull request.

@serprex serprex left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

needs CHANGELOG entry

Comment thread src/http.c Outdated
Comment on lines +233 to +237
/*
* 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.
*/

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/*
* 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.
*/

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deleted.

@theory theory left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@theory
theory self-requested a review June 23, 2026 21:57
@theory

theory commented Jun 24, 2026

Copy link
Copy Markdown
Collaborator

Simpler example of incrementing the version and adding an upgrade script in ClickHouse/pg_re2#22

@theory theory assigned theory and JoshDreamland and unassigned theory Jun 24, 2026
@theory theory added enhancement New feature or request functions Improve function pushdown drivers Improve binary and/or http driver support labels Jun 24, 2026

@theory theory left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Comment thread src/binary/connection.c
Comment thread src/include/fdw.h Outdated
Comment thread src/http.c
Comment thread src/http.c
Comment thread test/sql/server_version.sql Outdated
@JoshDreamland
JoshDreamland force-pushed the ch-server-version branch 2 times, most recently from 52297d2 to 43cfc72 Compare June 29, 2026 17:38
Comment thread doc/pg_clickhouse.md Outdated
Comment on lines +1063 to +1065
The version is read from the connection — over the native protocol it comes
from the handshake, and over the HTTP interface it is obtained with a single
`SELECT version()` and cached for the life of the connection.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fuck the passive voice.

Suggested change
The version is read from the connection — over the native protocol it comes
from the handshake, and over the HTTP interface it is obtained with a single
`SELECT version()` and cached for the life of the connection.
Reads the version from the native protocol connection handshake or from a
single `SELECT version()` http query and cached for the life of the
connection.

Comment thread src/binary/connection.c Outdated
/*
* Report the ClickHouse server version (major.minor.patch) for a binary
* connection. The native protocol reports the server version during the
* handshake, so this reads the cached handshake info rather than issuing a

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* handshake, so this reads the cached handshake info rather than issuing a
* handshake, so read the cached handshake info rather than issuing a

Comment thread src/http.c Outdated
Comment on lines +222 to +223
* to all out-params when the version cannot be determined. The result is cached
* on the connection, so only the first call issues a query.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* to all out-params when the version cannot be determined. The result is cached
* on the connection, so only the first call issues a query.
* to all out-params when the version cannot be determined. Caches the result
* on the connection, so only the first call issues a query.

Comment thread CHANGELOG.md Outdated

### ⚡ Improvements

* Added a `clickhouse_server_version(server)` function reporting the

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* Added a `clickhouse_server_version(server)` function reporting the
* Added the `clickhouse_server_version(server)` function, which reports the

@JoshDreamland JoshDreamland left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re:caching: this info lives on the connection itself (conn->version), yes, but specifically in the long-lived "gate" connection that all our scans use. So it's only re-fetched when a connection is re-made, which is the right behavior anyway or we could be connecting to a different version without knowing. You don't have to worry about it querying the version for each scan, though.

Comment thread src/http.c
Comment thread src/binary/connection.c
Comment thread src/http.c Outdated
Comment on lines +233 to +237
/*
* 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.
*/

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deleted.

Comment thread src/http.c
@JoshDreamland

Copy link
Copy Markdown
Contributor Author

Comments updated; active voice, present indicative.

@theory theory left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Brilliant!

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.
@JoshDreamland
JoshDreamland merged commit 542e277 into main Jun 30, 2026
23 checks passed
@JoshDreamland
JoshDreamland deleted the ch-server-version branch June 30, 2026 00:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

drivers Improve binary and/or http driver support enhancement New feature or request functions Improve function pushdown

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants