Skip to content

Add ClickHouse server-version detection#293

Open
JoshDreamland wants to merge 1 commit into
mainfrom
ch-server-version
Open

Add ClickHouse server-version detection#293
JoshDreamland wants to merge 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

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

@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
return s ? s->broken : false;
}

void

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.

Please add a doc comment.

Comment thread src/include/fdw.h
Comment on lines +126 to +129
static inline bool
chfdw_version_ge(ch_server_version v, int major, int minor) {
return v.major > major || (v.major == major && v.minor >= minor);
}

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.

Maybe this should live in server_version.h?

Comment thread src/http.c
ch_query query = { "SELECT version()", 0, NULL, NULL, NULL, NULL };
ch_http_response_t* resp = ch_http_simple_query(conn, &query);

if (resp != NULL) {

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.

We should log an error if the response is an error.

Comment thread src/http.c
return;
}

if (conn->version.major == 0) {

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.

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

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 seems redundant, the regex test covers it.

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