[jdbc-v2,client-v2] Fix format selection and document how to - #3101
[jdbc-v2,client-v2] Fix format selection and document how to #3101chernser wants to merge 4 commits into
Conversation
TriageCategory: Summary What this impacts
Concerns
Required reviewer action
|
|
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 503def4. Configure here.
Client V2 CoverageCoverage Report
Class Coverage
|
|
JDBC V2 CoverageCoverage Report
Class Coverage
|
JDBC V1 CoverageCoverage Report
Class Coverage
|
Client V1 CoverageCoverage Report
Class Coverage
|
| **Important for ClickHouse 26.8+:** | ||
| - On ClickHouse 26.8+, the request format header sent by the driver (`X-ClickHouse-Format`) takes priority over a `FORMAT` clause written in the SQL query string. | ||
| - By default, the driver sends `format=RowBinaryWithNamesAndTypes`. | ||
| - To use a SQL `FORMAT` clause (such as `SELECT ... FORMAT JSONEachRow`) with ClickHouse 26.8+, set `format=JSONEachRow` in connection properties or set `format=` (to `""` empty string) so the default binary format header is omitted and ClickHouse honors the query's `FORMAT` clause. |
There was a problem hiding this comment.
Recommending format= (empty) for a JDBC connection has a wider effect than this bullet says. With no header the server falls back to default_format (TabSeparated) for every statement that has no FORMAT clause, and StatementImpl rejects text formats. Verified on 26.8.1 with a scratch test on a connection configured with format=:
execute/executeUpdatefor DDL andINSERT ... VALUES: workexecuteQuery("SELECT 1")andexecute("SELECT 1"):SQLException: Only RowBinaryWithNameAndTypes and JSONEachRow are supported for output formatDatabaseMetaData.getTables/getColumns/getSchemas: sameSQLException
So a connection configured this way only works for statements that carry an explicit FORMAT clause, and any tool that touches metadata breaks. Suggest either stating this explicitly here (and in docs/features.md line 110 and the CHANGELOG entry), or recommending format=JSONEachRow as the JDBC way to read JSON and treating format= as an expert-only setting.
Related: the "Export to a file format" row at line 473 has the same issue. Only RowBinaryWithNamesAndTypes and JSONEachRow are consumable by a ResultSet; format=CSV makes every query fail, which testUnsupportedFormat shows. A small follow-up that would make this failure self-explanatory: have the StatementImpl error name the format actually received and point at the format property.
| * @param format - valid ClickHouse format | ||
| * @return this instance of builder | ||
| */ | ||
| public Builder queryFormat(String format) { |
There was a problem hiding this comment.
Since this becomes permanent public API in 0.11.0, I'd settle its shape before merging:
ClickHouseFormat.valueOfis case-sensitive, soqueryFormat("csv")throws whilesetOption("format", "csv")now succeeds thanks to the case-insensitive parsing added in this PR.nullthrows an NPE, so the method cannot express the new "send no format header" mode this PR introduces; callers have to fall back tosetOption(INPUT_OUTPUT_FORMAT.getKey(), null).- An invalid name surfaces the raw
No enum constant ...message rather than aClientMisconfigurationException.
Suggestion: take ClickHouseFormat instead of String, with null meaning "no header", e.g. queryFormat(ClickHouseFormat format) storing format == null ? null : format.name(). Alternatively route the string through INPUT_OUTPUT_FORMAT.parseValue(...) so both entry points agree. Either way a test for null and for an invalid value would be good; the only coverage today is the CSV happy path in ClientTests.testDefaultSettings.


Summary
Closes: #3086
Checklist
Delete items not relevant to your PR: