clickhouse-java v0.11.0
clickhouse-java v0.11.0
Breaking changes
-
[client-v2, jdbc-v2] The socket buffer options
socket_rcvbufandsocket_sndbufhave no default value anymore. Now the options are applied only when the application sets them (Client.Builder#setSocketRcvbuf,Client.Builder#setSocketSndbuf, or the properties of the same name). This is done to let OS TCP Stack auto-tune values. Do not set them until absolutely needed. (https://github.com/ClickHouse/clickhouse-java/issues/3121) -
[client-v2, jdbc-v2] Server error
159(TIMEOUT_EXCEEDED) is not retried by default anymore. It has its own retry cause,ClientFaultCause.ServerTimeoutExceeded, whichServerRetryabledoes not include and which is not in the defaultclient_retry_on_failureslist. AddServerTimeoutExceededto the list to retry this error. (https://github.com/ClickHouse/clickhouse-java/issues/3072) -
[r2dbc] Pre
1.0.0artifact is not supported anymore because R2DBC API reached stable1.0.0version. -
[jdbc-v2]
DatabaseMetaData#getTablesnow returnsnullinREMARKS(table comment) andTYPE_SCHEMby default, because metadata is read withSHOWstatements (see thejdbc_metadata_use_show_statementsentry in New Features). Setjdbc_metadata_use_show_statements=falseto get the table comments. (https://github.com/ClickHouse/clickhouse-java/issues/2907) -
[client-v2,jdbc-v2] Added ZSTD compression support for Block compression stream and used by default not to compress client requests. Previously only LZ4 was supported in this case. Note: Added ZSTD library and native libraries to
-allJDBC package because it is now required to work with server. (https://github.com/ClickHouse/clickhouse-java/issues/3105). -
[client-v2, jdbc-v2] The
User-Agentheader now uses the standard ClickHouse client format,<client name> clickhouse-java-v2/<version> (lv:java/<java.version>; os:<os.name>; hc:ahc_<version>):jvm:<version>is nowlv:java/<version>, the OS is theos:entry, and the trailingApache-HttpClient/<version>is replaced by thehc:ahc_<version>entry (the Apache HttpClient version that the client is built with). AddedClient.Builder#setClientName(String, Map)(propertyclient_id_metadata) to add key/value pairs to the comment group. The pairs can setlv,osandhcto replace the values of the client. Leading and trailing whitespace is removed from the client name and from a customUser-Agentvalue. A blank value set for one operation counts as not set. The client logs a warning if theUser-Agentvalue of the client configuration is longer than 200 characters. Queries that parsehttp_user_agentinsystem.query_logmust use the new format. (https://github.com/ClickHouse/clickhouse-java/issues/3202)
Important Changes
-
[client-v2]
com.clickhouse.client.api.observability.SpanSupportnow usesQUERYandINSERToperation constants (QUERY <database>andINSERT <database>.<table>span names).db.operation.nameattribute is set toINSERTfor insert operations and left unset for queries because SQL statements are not parsed on the client. -
[client-v2]
com.clickhouse.client.api.metrics.OperationMetricsnow has a single constructor,OperationMetrics(ClientStatisticsHolder, OperationType); the constructor without an operation type was removed. Metrics are created by the client, which always knows the kind of the operation it runs, and the constructor takes an internal type (com.clickhouse.client.api.internal.ClientStatisticsHolder), so application code is not expected to call it. (https://github.com/ClickHouse/clickhouse-java/issues/2974)
New Features
Data Types
-
[client-v2, jdbc-v2] Added support for the
MultiPointgeo data type (ClickHouse26.8+). Previously the type was unknown to the client, so reading or writing aMultiPointcolumn failed withUnknown data type: MultiPoint, and aMultiPointvalue inside aGeometrycolumn failed with an out-of-range variant discriminator.MultiPointisArray(Point)on the wire, exactly likeRingandLineString, so it is read and written asdouble[][]through generic records, binary readers, POJO binding, and SQL parameter formatting, and is read fromDynamiccolumns. In the JDBC driver (jdbc-v2)MultiPointmaps tojava.sql.Types.ARRAY, is returned asdouble[][]fromgetObjectand as ajava.sql.ArrayfromgetArray, and is reported byResultSetMetaDataandDatabaseMetaData. ClickHouse26.8also addsMultiPointto theGeometryvariant; the server appends it after the existing six variants instead of ordering it by type name, so the client now keeps that order and decodes aMultiPointheld in aGeometrycolumn. BecauseMultiPointshares its Java representation (double[][]) withRingandLineString, it is not selectable through the shape-basedGeometrywrite path — a 2D value keeps resolving toRingas before, and writingMultiPointrequires a concreteMultiPointcolumn. (https://github.com/ClickHouse/clickhouse-java/issues/3048) -
[client-v2, jdbc-v2] Added support for the
BFloat16data type (ClickHouse24.11+).BFloat16columns are read as Javafloatvalues (widening is lossless) and written fromfloat/Floatvalues, including through generic records, POJO binding,Nullable(BFloat16), andBFloat16values held inDynamic/Variantcolumns. On write the client keeps the high 16 bits of thefloat, matching the ClickHouse server’s ownFloat32→BFloat16conversion. In the JDBC driver (jdbc-v2)BFloat16maps tojava.sql.Types.FLOAT/java.lang.Floatand is read and written through the standardgetFloat/setFloatandgetObjectaccessors, and reported as such byResultSetMetaDataandDatabaseMetaData. Previously reading or writing aBFloat16column failed with an unsupported-data-type error. (https://github.com/ClickHouse/clickhouse-java/issues/2279) -
[client-v2, jdbc-v2] Added support for the experimental
QBit(element_type, dimension[, stride])vector data type (ClickHouse25.10+; theallow_experimental_qbit_typeserver setting is required to create a column). The type-name parser accepts two or three parameters (the optional third is the stride) and recognizes the documented element typesInt8,BFloat16,Float32, andFloat64; an element type outside that set is parsed with a warning rather than rejected, so a newer server-side element type keeps parsing. AQBitvalue is transmitted overRowBinaryexactly likeArray(element_type), so it is read and written as a Java array of the element type (float[]forBFloat16/Float32,double[]forFloat64) through generic records, binary readers, and POJO binding, via a dedicatedQBitread/serialize path. AQBitheld inside aDynamic/Variant/JSONcolumn is also decoded (its binary type encoding is read back to the concreteQBit(...)type). In the JDBC driver (jdbc-v2)QBitmaps tojava.sql.Types.ARRAYand is returned as ajava.sql.ArrayfromgetObject/getArray. PreviouslyQBitwas an unimplemented type constant and reading or writing such a column failed. A plain top-levelQBitcolumn with aFloat32,Float64, orBFloat16element type is also read through theNativeoutput format: there the server transmits it using its internal bit-plane-transposedTuple(FixedString(...))layout, and the client reverses that transposition to reconstruct the samefloat[]/double[]vector asRowBinary. AQBitthat is strided (QBit(element_type, dimension, stride)), wrapped inNullable/LowCardinality, nested inside another type (e.g.Array/Tuple/Map(String, QBit(...))), or carrying any other element type is not yet decoded overNativeand fails fast with a clear error directing you to aRowBinaryformat such asRowBinaryWithNamesAndTypes. (https://github.com/ClickHouse/clickhouse-java/issues/2610)
Observability
-
[client-v2, jdbc-v2] Added a Micrometer implementation of the metrics SPI.
Client.Builder.setMetricsRecorder(new MicrometerMetricsRecorder(meterRegistry))reports the metrics of every client operation to a MicrometerMeterRegistry: a timerdb.client.operation.durationper completed operation, a timerclickhouse.client.operation.serialization.durationwhen the client measured the serialization step, a counterclickhouse.client.operation.countper completed operation, and a counterclickhouse.client.operation.retriesper retried attempt. Previously the client could bind only its connection-pool gauges to Micrometer, so exporting the metrics of the operations themselves was left to the application. Meter names, units, descriptions and tag keys are the standard ones of the SPI - the recorder derives them throughMetricsSupport, so they are the names ofMetricNameand the keys ofMetricAttributeand mean the same as for every other recorder. A successful operation carries noerror.typetag and a failed one does, so the outcomes are separate time series of the same meter and a failure the server reported also carriesdb.response.status_code; a duration the client did not measure is not recorded, so no operation is reported with a made-up duration. The seconds of the SPI are handed to the registry as nanoseconds, because a Micrometer timer keeps its own time unit, so a backend publishes the duration in the unit it expects. The no-argument constructor reports toMetrics.globalRegistry, which is what the jdbc-v2jdbc_metrics_recorderproperty needs, so a JDBC connection exports its metrics to Micrometer by naming the class -jdbc_metrics_recorder=com.clickhouse.client.api.observability.micrometer.MicrometerMetricsRecorder- without application code.micrometer-corestays an optional dependency ofclient-v2and is not shaded into theallartifacts, so a client that does not use this recorder needs no Micrometer on the classpath. (https://github.com/ClickHouse/clickhouse-java/issues/2975) -
[client-v2, jdbc-v2] Added a metrics SPI that lets an application export the metrics of client operations to any metrics backend.
Client.Builder.setMetricsRecorder(MetricsRecorder)registers a backend-agnostic recorder from thecom.clickhouse.client.api.observabilitypackage, and the jdbc-v2 propertyjdbc_metrics_recordernames the recorder class a connection registers with its own client. Previously the client collected operation metrics but only returned them to the caller, so exporting them was left to the application. Each completed operation reports exactly one success or one failure event, and each retried attempt reports a retry event, which gives the operation duration, the serialization duration, the number of operations by outcome and the number of retries. The SPI follows the pattern of the span SPI: an implementation extends theDefaultMetricsRecorderbase class and overrides only what it cares about, so it keeps working when the client starts reporting an event it does not know about, and the reusableMetricsSupportclass derives the standard values from the same structures, so its logic is opt-in and overridable. Metric names, units and attribute keys follow the OpenTelemetry semantic conventions for database clients where a convention exists and are placed underclickhouse.where it does not; they are defined by theMetricNameandMetricAttributeenums, durations are reported in seconds, and a duration the client did not measure is reported asMetricsSupport.DURATION_UNKNOWNinstead of a made-up value. The metric attributes are deliberately a smaller set than the span attributes, because an attribute of a metric becomes a time series: the statement text, the query id and the statement parameters stay on spans. Nothing is recorded and no metrics-related work is done when no recorder is registered. (https://github.com/ClickHouse/clickhouse-java/issues/2975) -
[client-v2] Added an OpenTelemetry implementation of the observability SPI.
Client.Builder.setSpanRecorder(new OpenTelemetrySpanRecorder(openTelemetry))reports every client operation and every transport request as an OpenTelemetryCLIENTspan: an operation span is started as a child of the current OpenTelemetry context, so it joins the application’s own trace, and each request span - including one per retry - is a child of its operation span. Span names and attribute keys are the standard ones of the SPI (the recorder derives them throughSpanSupport), every value is recorded with the OpenTelemetry attribute type that matches it, and a failure sets the span status toERRORand is recorded as an OpenTelemetry exception event next to theerror.typeanddb.response.status_codeattributes. The recorder reports to a suppliedOpenTelemetryinstance, to aTracergiven tonew OpenTelemetrySpanRecorder(Tracer), or toGlobalOpenTelemetry- read when a span is started - when constructed without arguments. Previously an application that wanted OpenTelemetry spans had to write that mapping itself. The OpenTelemetry API is a compile-only dependency ofclient-v2: the recorder is used only by an application that already providesopentelemetry-apiat runtime, so nothing is added to the classpath of a client that does not use it. (https://github.com/ClickHouse/clickhouse-java/issues/2974) -
[client-v2] Added an observability SPI that lets an application observe client operations as spans.
Client.Builder.setSpanRecorder(SpanRecorder)registers a backend-agnostic recorder from the newcom.clickhouse.client.api.observabilitypackage: each operation (a query, a command or an insert - including thepingandgetTableSchemacalls, which run a query) starts one operation span, and every transport request made for it - including each retry - starts a child request span.SpanRecorderandSpanare plain interfaces; an implementation extends theDefaultSpanRecorderbase class and overrides only what it cares about, so it keeps working when the client starts a kind of span it does not know about. The registered recorder is called first and receives everything the client knows about the operation (itsQuerySettings/InsertSettings, the statement, the target table, the batch size, the endpoint, the metrics of the completed operation and the failure), so it is free to record whatever it needs and in whatever form; the reusableSpanSupportclass derives the standard span names and attribute values from those same structures and is called by a recorder implementation that wants them, so its logic is opt-in and overridable. Span names and attribute keys follow the OpenTelemetry semantic conventions for database and HTTP client spans; the keys are defined by theSpanAttributeenum and the values are derived bySpanSupport, so all recorders that use it report the same information (statement text, target database and table, query id, statement parameters, batch size, the first configured endpoint on the operation span and the per-attempt server address and port on the request spans, HTTP status, returned rows, and the error type and ClickHouse error code on failure). The outcome of a completed operation is reported per operation kind -recordQuerySuccessfor a read andrecordInsertSuccessfor an insert - because the metrics that describe a read are not the ones that describe a write: a query reportsdb.response.returned_rows,clickhouse.response.read_rowsandclickhouse.response.read_bytes, an insert reportsclickhouse.response.written_rowsandclickhouse.response.written_bytes. The same distinction is available on the metrics themselves through the newOperationMetrics#getOperationType(), which returns the newcom.clickhouse.client.api.metrics.OperationType- the kind of the call the application made, so a command that writes is reported as a query. An operation span is started on the calling thread, so it joins the caller’s ambient trace even when the operation runs on the client’s executor, and it is ended exactly once for every operation that starts. Previously the client exposed no hook for tracing, so an application could not attribute a query or a retried request to its own trace. When no recorder is registered nothing is recorded and no span-related work is done, so the default path is unchanged. An OpenTelemetry implementation of the SPI is available asOpenTelemetrySpanRecorder. (https://github.com/ClickHouse/clickhouse-java/issues/2974)
Improvements
-
[migration-helpers] Added
migration-helpersmodule containingConfigurationMigrationHelperandConfigPropertyCacheto convert configuration properties and connection URLs from v1 (0.7.1) format to v2 (0.9.8+) format (automatically prefixing ClickHouse server settings withclickhouse_setting_, custom headers withhttp_header_, and mapping renamed property keys). -
[client-v2, jdbc-v2] Added TLS cipher suite selection.
Client.Builder.setSSLCipherSuites(String...)(client-v2) and the comma-separatedssl_cipher_suitesconnection property (client-v2 and jdbc-v2) restrict the cipher suites enabled on secure connections; when unset, the transport defaults are used. Cipher-suite selection is independent of the trust configuration andssl_mode. (https://github.com/ClickHouse/clickhouse-java/issues/2882) -
[client-v2, jdbc-v2] Added support for un-flattened
Nested(...)columns (tables created withflatten_nested = 0). Previously theRowBinarywriter threwUnsupportedOperationException: Unsupported data type: Nestedwhen inserting such a column.client-v2now serializes aNested(f1 T1, ..., fN TN)column the same way it is read — identically toArray(Tuple(T1, ..., TN))(a var-uint row count followed by one tuple per nested row) — so it can be written through the insert path /RowBinaryFormatWriter. Injdbc-v2an un-flattenedNested(...)column is exposed as a JDBCARRAYwhose element type isTuple(f1 T1, ..., fN TN): it can be inserted throughConnection#createArrayOf/setArrayorsetObjectand read back throughgetArray/getObject, andjava.sql.Array#getResultSet()iterates the nested rows as(INDEX, VALUE)pairs where eachVALUEis the tuple. (https://github.com/ClickHouse/clickhouse-java/issues/2477) -
[client-v2, jdbc-v2] Added logging on previously-silent error and diagnostic paths (no functional or public-API change). (https://github.com/ClickHouse/clickhouse-java/issues/2969)
-
[jdbc-v2]
DatabaseMetaData#getSchemas,#getTablesand#getColumnsnow read metadata withSHOW DATABASES,SHOW TABLESandDESCRIBE TABLEinstead of thesystem.databases,system.tablesandsystem.columnstables. The server does not show some tables in the system tables by default (for example, tables ofDataLakeCatalogdatabases), so tools that useDatabaseMetaDatadid not find them. The new driver propertyjdbc_metadata_use_show_statements(defaulttrue) selects the implementation; set it tofalseto use the system tables. With theSHOWstatements,getTables()returnsnullinREMARKS(table comment) andTYPE_SCHEM;getColumns()sends oneDESCRIBE TABLEquery for each table that matches and skips a table that was dropped meanwhile, that the user cannot describe, or whose data lake metadata cannot be read. All other columns and values are the same. (https://github.com/ClickHouse/clickhouse-java/issues/2907)
Bug Fixes
-
[jdbc-v2] Fixed an
INSERT ... VALUESstatement whose values list holds a literal, an expression (e.g.? + 1) or, with theJAVACCparser, a JDBC escape sequence or a query parameter, being written with the RowBinary writer whenbeta.row_binary_for_simple_insertis enabled. The writer takes one bound value per column, so the bound values were shifted to other columns: the statement failed with a misleading error, or stored wrong data with no error. The parsers did not report such values: theJAVACCparser discarded the result of its values-list check, and theANTLR4parsers reported only function calls. Now the writer is used only for a values list of?placeholders, and other statements use the standardPreparedStatementpath. (https://github.com/ClickHouse/clickhouse-java/issues/3083) -
[client-v2,jdbc-v2] - Replaced slow HTTP LZ4 compression with compressing stream from
lz4-javalibrary. Client uses Apache Compress to handle HTTP compression (because it has convenient factory for many compressions methods. However, Apache Compress uses slow LZ4 implementation what causes very slow inserts. Nowlz4-javaused for insert. Query still slow but will be fix in future releases (need refactoring and custom implementation to solve it). UsingZSTDfor queries should solve the issue. (https://github.com/ClickHouse/clickhouse-java/issues/2273). -
[client-v2] Fixed writing a
Stringvalue into aUUIDcolumn (also as anArray/Tupleelement or aMapkey) failing withClassCastException. The string is now parsed withUUID.fromString; a string it cannot parse is rejected on the client with anIllegalArgumentException. (https://github.com/ClickHouse/clickhouse-java/issues/3132) -
[client-v2] Fixed reading a
Nullablecolumn in theNativeformat failing withFailed to read block ... End of stream reached before reading all data, or returning values of the wrong rows. The reader consumed a null marker before every value, which is the RowBinary layout.Nativeis columnar: it stores a null map of one byte per row before the values of the whole column, and a null row still has a placeholder value. The markers were therefore taken from the value bytes and the column was read out of alignment. The null map is now read as a block. (https://github.com/ClickHouse/clickhouse-java/issues/3137) -
[client-v2] Fixed geo columns (
Point,Ring,LineString,MultiPoint,Polygon,MultiLineString,MultiPolygon) being misread from theNativeformat. The reader decoded a geo column row by row with the RowBinary decoders, whileNativewrites it column-major: aPointblock came back with its coordinates scrambled across rows and no error, and every other geo type desynchronized the block and failed withNon-empty typeName is required. A geo column is now decoded from the Native layout - the twoFloat64sub-columns of a point, and cumulative offsets plus the flattened elements for the array levels - and returns the same values asRowBinaryWithNamesAndTypes, which is unchanged. (https://github.com/ClickHouse/clickhouse-java/issues/3088) -
[client-v2, jdbc-v2] Fixed a column type with a
JSONelement that is followed by a parameterized type, for exampleTuple(JSON, FixedString(3)), being parsed wrongly.JSONis valid with and without a parameter list, and the parser looked for the opening bracket of that list anywhere after the keyword, so it took the brackets of the next element for the parameters of theJSONelement. Everything up to those brackets was consumed, which dropped the elements between them, or failed withUnknown data type: <parameter>when the following type had more than one parameter, for exampleTuple(JSON, Decimal(10, 2)). Reading such a column, andClient#getTableSchemaof a table that has one, failed or returned an incomplete type. A parameter list is now recognized only when it immediately follows theJSONkeyword. (https://github.com/ClickHouse/clickhouse-java/issues/3098) -
[jdbc-v1] Fixed
WITH RECURSIVE <name> AS (...)failing to parse. The JavaCC grammar did not know theRECURSIVEkeyword, so it was taken for the name of the first common table expression and the statement was rejected. The query itself still ran, because the driver falls back to sending the original SQL, but everycreateStatement/prepareStatementcall logged aWARNparse failure and the statement was classified as unknown.RECURSIVEis now accepted afterWITHand stays usable as an ordinary identifier (column, alias, table or CTE name). (https://github.com/ClickHouse/clickhouse-java/issues/3122) -
[jdbc-v2] Fixed
WITH RECURSIVE <name> AS (...)failing to parse. Neither SQL grammar knew theRECURSIVEkeyword, so it was taken for the name of the first common table expression and the statement was rejected. The query itself still ran, because the driver falls back to sending the original SQL, but everycreateStatement/prepareStatementcall logged a parse failure (WARNwith the JavaCC backend) and the statement was classified as unknown.RECURSIVEis now accepted afterWITHby both the JavaCC and the ANTLR4 grammars, and stays usable as an ordinary identifier (column, alias, table or CTE name). (https://github.com/ClickHouse/clickhouse-java/issues/3122) -
[jdbc-v2] Fixed
ArrayResultSet#next()leaving the cursor before-first for empty arrays or on the last row for non-empty arrays after exhaustion. The cursor now moves to the after-last state whennext()returnsfalse. -
[jdbc-v2] Added the non-reserved keywords
AGGREGATE,BOUNDED,EXTEND,HANDLER,IDLE,PROTOCOL,RECENT,TIMEOUTandUNORDERED(ClickHouse26.8+;IDLE,TIMEOUTandRECENTcome from the multi-word keywordsIDLE TIMEOUTandRECENT SAMPLES) to the list of keywords allowed in identifier positions. The server accepts all of them as a column or table alias, so a query using one of them as an identifier must parse. (https://github.com/ClickHouse/clickhouse-java/issues/3113) -
[client-v2] Fixed a query with statement parameters sent in the request body (
client.http.use_form_request_for_query=true) failing withLZ4 decompression failed ... (LZ4_DECODER_FAILED)when client request compression and HTTP compression were both enabled. The multipart body is always sent uncompressed, but the request still declaredContent-Encoding: lz4; ClickHouse26.8+honours that header for multipart requests and tried to decompress a plain body. The header is now omitted for multipart requests, like thedecompressquery parameter already was. Response compression (Accept-Encoding,enable_http_compression) is unchanged. (https://github.com/ClickHouse/clickhouse-java/issues/3075) -
[client-v1] Fixed the
DateTime64case oftestReadWriteSimpleTypesfailing against ClickHouse 26.8. From 26.8 an unquoted number written to aDateTime64column in theValues/QuotedandJSONpaths is a Unix timestamp in seconds instead of the raw scaled value - the server settinginput_format_read_datetime_number_as_raw_valuechanged its default from1to0- so theinsert into ... values(1)of the test stored1970-01-01 00:00:01instead of the expected1970-01-01 00:00:00.001. The test now writes a quoted date-time literal forDateTime64, as it already does forFixedStringandUUID, so the written value means the same on every server version and the sub-second round-trip stays covered. No client code is affected: both clients quote a date-time value in a text statement or send it inRowBinary. (https://github.com/ClickHouse/clickhouse-java/issues/3114) -
[jdbc-v2, client-v2] Fixes issue with
FORMATin query unable to override format set by client when used with ClickHouse 26.8+. Default format isRowBinaryWithNamesAndTypesset at client level. For JDBC, recommend usingformat=JSONEachRowto query JSON. Settingformat=(empty ornull) omits the format request header so explicit queryFORMATclauses take effect; note that on JDBC any statement without aFORMATclause will fail because the server falls back todefault_format(TabSeparated).DatabaseMetaDatais unaffected: every statement it runs internally pinsRowBinaryWithNamesAndTypesin its own settings, so metadata keeps working regardless of the connection’sformatproperty. (https://github.com/ClickHouse/clickhouse-java/issues/3086) -
[jdbc-v2] Fixed
Connection#prepareStatementandPreparedStatement#addBatchthrowingStringIndexOutOfBoundsExceptionfor anINSERT ... VALUES (...)statement containing a JDBC escape sequence ({d '...'},{ts '...'}, …) or a ClickHouse query parameter whose name starts withd/t(e.g.{d:Int32}). The defaultJAVACCparser records the values list positions as offsets into the SQL it rebuilds from the token stream, where such sequences are rewritten or dropped, while the driver slices the original SQL with them — so the slice was taken at the wrong offsets or past the end of the statement. The positions are now checked against the original SQL and discarded when they do not address its values list, in which case the driver falls back to its generic parameter substitution path. Such a statement is now prepared without error; the escape sequence itself is still sent to the server unchanged. TheANTLR4parser backends were not affected. (https://github.com/ClickHouse/clickhouse-java/issues/3017) -
[jdbc-v2] Fixed a
?inside a//line comment or inside a heredoc (dollar quoted string, e.g.$$...$$or$tag$...$tag$) being counted as aPreparedStatementparameter. Such a statement expected a value the application could not supply, soexecuteQuery()failed withParameter at position 'N' is not setfor a query the server executes fine. The placeholder scan now skips both token kinds, like the server lexer does; a$that does not open a heredoc is still treated as an ordinary character (it is a valid identifier character). (https://github.com/ClickHouse/clickhouse-java/issues/3009) -
[jdbc-v2] Fixed
INSERT INTO [TABLE] FUNCTION f(...) VALUES (?)failing withCode: 60 ... does not exist. (UNKNOWN_TABLE)when thebeta.row_binary_for_simple_insertfeature was enabled. Neither SQL parser reported a table-function insert target as a function, so the statement was routed to theRowBinarywriter, which looked the function name (or a placeholder such asunknown) up as a table. Both parsers now report such a statement as using a function, so it stays on the regular SQL path; additionally the JavaCC grammar no longer mis-parsesINSERT INTO TABLE FUNCTION f(...)by consumingFUNCTIONas the table name. Inserts into a plain table are unaffected and still use theRowBinarywriter. (https://github.com/ClickHouse/clickhouse-java/issues/3015) -
[jdbc-v2] Fixed
Connection#prepareStatementthrowing aNullPointerExceptionfor anINSERT ... VALUES (...)statement whose values list the default JavaCC parser cannot parse — most commonly one containing a heredoc string ($$...$$), which the grammar has no token for, but also any other unparsable token inside the list. The parser’s error recovery left the values list’s start position recorded without its matching end position, which was then unboxed unguarded. Both positions are now dropped together, so the driver falls back to its generic parameter-substitution path and such statements are prepared and executed successfully. TheANTLR4parser backends were not affected. (https://github.com/ClickHouse/clickhouse-java/issues/3013) -
[client-v2] Fixed reading a
JSONor namedTuplevalue nested in aDynamiccolumn when a typed path or element name requires quoting (it contains a space, a comma or a bracket). Names read from the binary type encoding were appended to the reconstructed type name unquoted, so e.g.JSON(`a b` Int64)inside aDynamiccolumn produced a malformed type name and the whole query failed withIllegalArgumentException: Unknown data type: b Int64. Such names are now back-quoted (with inner back-quotes escaped) exactly as the server renders them, andJSONskip paths and path regexps are emitted with theirSKIP/SKIP REGEXPmarkers. Names that need no quoting are rendered as before. Top-levelJSONcolumns andJSONnested inMap/Tuple/Arraywere not affected — their type comes from theRowBinaryWithNamesAndTypesheader, which the server already quotes. (https://github.com/ClickHouse/clickhouse-java/issues/3001) -
[client-v2] Fixed reading a
Variant,Nested,DecimalorEnumvalue held in aDynamiccolumn. The concrete type rebuilt from the binary type encoding did not match what the server encoded:Variantwas wrapped twice (so the discriminator selected the wrong element),Nestedread only the element names and left the element type encodings in the stream, andDecimal/Enumlost their precision and scale / their constants whenever the value sat inside another type, so a decimal read back unscaled (1.2500as12500) and every enum value read back as<unknown>. The constant width of an enum is now taken from the type tag rather than from the number of constants, which also fixes reading anEnum16with fewer than 128 constants and negativeEnum8constants. (https://github.com/ClickHouse/clickhouse-java/issues/3003) -
[client-v2] Fixed a
Nullable(T)column bound to a primitive POJO field silently corrupting a row on the POJO read path. The compiled setter went straight to a primitive read method without consuming theNullablenull-marker byte, which is on the wire for every value of a nullable column regardless of the value, so the stream stayed shifted by one byte per row and the nullable column and every column after it decoded from the wrong offset without any error being raised. The generated setter now consumes the marker; a value that is actuallyNULLcannot be held by a primitive field and is reported with aNullValueException. Boxed POJO fields are unaffected. (https://github.com/ClickHouse/clickhouse-java/issues/2993) -
[client-v2] Fixed the
Nativeformat reader (NativeFormatReader) misreadingArraycolumns in multi-row results whose rows have different lengths. Native encodes an array column as cumulative row offsets followed by the flattened elements, but the reader used the first row’s offset as the element count for every row — truncating later rows and desyncing the columns that follow the array in the same block. Each row’s length is now derived from the difference between consecutive offsets, and empty array rows (len == 0) no longer read a phantom element. Results with uniform array lengths were unaffected. (https://github.com/ClickHouse/clickhouse-java/issues/2955) -
[jdbc-v2] Fixed
SQLException#getSQLState()returning the generic data-exception state22000when ClickHouse reports an unknown table. The driver now returns42S02(base table or view not found) while preserving the ClickHouse error code and original exception. (https://github.com/ClickHouse/clickhouse-java/issues/3104) -
[client-v2] Fixed truncated LZ4 stream errors reporting literal
{0}and{1}placeholders instead of the number of bytes read and expected. (https://github.com/ClickHouse/clickhouse-java/issues/3108) -
[jdbc-v2] Fixed
DatabaseMetaData#getTablesreportingTABLE_TYPE = TABLEfor a table with theBigQueryengine (present insystem.table_enginessince ClickHouse26.8). The engine was missing from the engine-to-table-type mapping, so it fell back to the defaultTABLE, andgetTables(..., types = {"REMOTE TABLE"})returned no row for such a table.BigQueryis now mapped toREMOTE TABLE, like the other external-storage engines. (https://github.com/ClickHouse/clickhouse-java/issues/3049) -
[jdbc-v2] Fixed
PreparedStatement.getMetaData()losing the result-set schema for a statement whose SQL contains a comment. TheDESCRIBEquery used to resolve the metadata was built by re-scanning the SQL with a regex that knew only quoted tokens, so a?inside a--/#//* */comment was rewritten toNULLand an odd'inside a comment mis-paired the quote alternative, leaving a real placeholder unreplaced — theDESCRIBEthen failed and the driver silently returned untyped metadata. The metadata query is now built from the placeholder positions the statement parser already computed, so it always matches the SQL that a parameterized execution produces. (https://github.com/ClickHouse/clickhouse-java/issues/3011) -
[client-v2] Fixed reading a
UInt64column into a primitive POJO field (e.g.long) always failing withClassCastException: BinaryStreamReader cannot be cast to java.math.BigInteger. The compiled setter for that combination never emitted a read call, so it cast the reader itself instead of a value and consumed nothing from the stream, which made every primitive field bound to aUInt64column unusable. The value is now read and converted to the target primitive with the matchingNumberaccessor, which narrows a value that does not fit the same way a Java narrowing conversion does (alongholds everyUInt64value bit-for-bit and can be read back withLong.toUnsignedString(long); abooleanistruefor any non-zero value). Boxed fields (BigInteger,Long) are unaffected. (https://github.com/ClickHouse/clickhouse-java/issues/2996) -
[jdbc-v2] Fixed
ResultSetMetaData.getPrecision()andgetScale()returning0for columns wrapped inSimpleAggregateFunction(func, T). The wrapper is transparent on the read path (values are read as plainT), but both accessors described the wrapper itself, which carries no precision or scale — so aSimpleAggregateFunction(sum, Decimal(18, 4))column looked like a scale-0 value andSimpleAggregateFunction(any, DateTime64(3, tz))looked like second precision. They now describe the nested type.AggregateFunctioncolumns are unchanged, since their values are aggregation states rather than values of the nested type. (https://github.com/ClickHouse/clickhouse-java/issues/3042) -
[clickhouse-jdbc] Fixed
Connection#prepareStatementthrowing aNullPointerExceptionfor anINSERT ... VALUES (...)statement whose values list the JavaCC parser cannot parse — most commonly one containing a heredoc string ($$...$$), which the grammar has no token for, but also any other unparsable token inside the list. The parser’s error recovery left the values list’s start position recorded without its matching end position, which was then unboxed unguarded. Both positions are now dropped together, so the driver falls back to its generic parameter-substitution path instead of failing, and a statement such asinsert into t values ($$a@b$$, ?)is prepared and executed successfully. (https://github.com/ClickHouse/clickhouse-java/issues/3033) -
[jdbc-v2] Fixed the ANTLR4 lexer not nesting
/* */block comments. ClickHouse (and the JavaCC parser backend) raise the nesting level on an inner/*and close the comment only at the matching*/, while the ANTLR4 lexer ended the comment at the first*/and lexed the rest of it as SQL. With theANTLR4/ANTLR4_PARAMS_PARSERbackends this made statements the server accepts (e.g.SELECT 1 /* ) /* ) */ ) */, 2) report syntax errors, and madeANTLR4_PARAMS_PARSERcount a?inside the nested part of a comment as a bind parameter. Comments that do not nest are unaffected; an unterminated block comment is now skipped to the end of the statement instead of being lexed as stray tokens. (https://github.com/ClickHouse/clickhouse-java/issues/3021) -
[client-v2] Fixed reading a
SimpleAggregateFunction(func, T)value held in aDynamiccolumn. The binary type encoding of such a value (0x2E <function_name> <parameters> <arguments> <argument_type_encodings>) was not consumed at all, so the read failed withIndexOutOfBoundsException, and the unconsumed encoding bytes would otherwise have been interpreted as row data and desynchronized the rest of theRowBinarystream. The concrete type is now reconstructed from the encoding and the value is read as its argument typeT, so it reads exactly like the same value in a plainSimpleAggregateFunctioncolumn. (https://github.com/ClickHouse/clickhouse-java/issues/3005) -
[jdbc-v2] Fixed
PreparedStatement#executeBatchsending a syntactically brokenINSERTwhen anANTLR4parser backend is selected (jdbc_sql_parser=ANTLR4/ANTLR4_PARAMS_PARSER) and the values list contains a value expression the bundled grammar cannot parse - a JDBC escape sequence ({d '...'}), or valid ClickHouse syntax the grammar does not cover such as a hex string literal (hex(x'AB')). Such a statement is still given a parse tree, completed by error recovery, and the values list positions and the value group count were read from it: the values list was reported to stop at the closing parenthesis of a nested function call, so the batch template lost its own closing parenthesis, and a two-group values list could be reported as a single group. Both are now discarded when the statement could not be parsed without errors, so the driver uses its generic parameter substitution path instead - and, with the betaRowBinarywriter enabled, such a statement is no longer routed to it. The defaultJAVACCbackend is not affected by this. (https://github.com/ClickHouse/clickhouse-java/issues/3019) -
[jdbc-v2] Fixed the ANTLR4 lexer rejecting
//line comments, which the ClickHouse server and the driver’s JavaCC grammar both accept. Because/is also the division operator,// commentwas lexed as two operator tokens, so a statement containing a//comment was reported as a syntax error by the ANTLR4-based parser backends (ANTLR4,ANTLR4_PARAMS_PARSER), and anINSERTpreceded by such a comment was misclassified as a statement with a result set.//is now skipped like--,#and#!; a single/and//inside a string literal or a quoted identifier are unaffected. Placeholder counting inside//comments for the backends that scan the raw SQL separately (JAVACC,ANTLR4) is fixed by https://github.com/ClickHouse/clickhouse-java/issues/3009. (https://github.com/ClickHouse/clickhouse-java/issues/3023) -
[jdbc-v2] Fixed
?parameter placeholders being lost whenjdbc_sql_parser=ANTLR4_PARAMS_PARSERis selected and the bundled grammar cannot match part of the statement - a JDBC escape sequence ({d '...'}), or valid ClickHouse syntax the grammar does not cover such as a hex string literal (hex(x'AB')). That backend read the placeholders only from the parse tree, and the tokens error recovery skips are not part of it, so a placeholder inside such an expression was dropped:getParameterMetaData().getParameterCount()was too low,setXxxfor a dropped placeholder failed, and the remaining values were substituted at the wrong offsets. The placeholders are now re-derived from the original SQL when the statement could not be parsed without errors, as the other two backends always do. (https://github.com/ClickHouse/clickhouse-java/issues/3025) -
[client-v2, jdbc-v2] Fixed
Client.getTableSchema(...),Client.getTableSchemaFromQuery(...)andping()failing against ClickHouse26.8+, where theX-ClickHouse-Formatheader the client sends wins over aFORMATclause in the query. These internal queries now set their format in the settings instead of aFORMATclause. (https://github.com/ClickHouse/clickhouse-java/issues/3068) -
[jdbc-v2] Fixed an
INSERTwhose values list holds a function call the bundledANTLR4grammar cannot match - such ashex(x'AB'), valid ClickHouse the grammar has no hex string literal for - being reported to hold no function call when anANTLR4parser backend is selected (jdbc_sql_parser=ANTLR4/ANTLR4_PARAMS_PARSER). Function calls in a values list are reported by a callback on the parse tree, and such a statement is still given a parse tree, completed by error recovery, which skips the tokens the parser recovered on - the function call among them. With the betaRowBinarywriter enabled (beta.row_binary_for_simple_insert=true) the statement was then routed to it, where a literal function-call column cannot be written; it now takes the generic parameter substitution path, as it already did for a function call the grammar matches. Since such a parse tree cannot tell, any insert that could not be parsed without errors is now assumed to hold a function call in its values list, so none of them is written with theRowBinarywriter. The defaultJAVACCbackend is not affected by this. (https://github.com/ClickHouse/clickhouse-java/issues/3027) -
[clickhouse-client] Fixed JPMS/module-path service loading for
ClickHouseRequestManagerby loading client services from thecom.clickhouse.clientmodule, which declares the requiredusesdirectives. This avoidsServiceConfigurationErrorfailures fromcom.clickhouse.datawhen applications run on the module path. (https://github.com/ClickHouse/clickhouse-java/issues/2669) -
[client-v2] Fixed
Client.cancelTransportRequest(queryId)being silently dropped when it landed between two attempts of a retried operation (query, POJO insert and stream insert): the operation issued the next attempt anyway and could complete successfully. The request of an attempt now stays registered until the whole operation is over, and the cancellation is checked before every attempt, so a cancelled operation stops instead of sending another request. (https://github.com/ClickHouse/clickhouse-java/issues/2989) -
[client-v1] Fixed
BlockingPipedOutputStream.close()not being idempotent under concurrency: the check of theclosedflag and the closing handshake were not atomic, so two threads closing the same stream (e.g. a writer thread and a try-with-resources block) could both put the end-of-stream marker into the queue, and the second one failed withClose stream timed out after <n> msonce the reader had stopped consuming. Exactly one caller now performs the handshake and runs the post-close action; a concurrent or repeatedclose()returns immediately. Aclose()which fails while flushing the remaining data also marks the stream closed and runs the post-close action, so the stream cannot stay half-closed. (https://github.com/ClickHouse/clickhouse-java/issues/3055) -
[client-v1] Fixed
NonBlockingPipedOutputStream.close()not being idempotent under concurrency. Two threads could both flush and mutate the same pending buffer before the reader consumed it, silently replacing the payload with an empty buffer and running the post-close action twice. Exactly one caller now flushes the pending data, enqueues the end-of-stream marker, and runs the post-close action; concurrent or repeatedclose()calls return immediately. (https://github.com/ClickHouse/clickhouse-java/issues/3057) -
[jdbc-v2] Fixed JDBC escape processing rewriting text inside string literals and quoted identifiers. Because
PreparedStatementinlines bound parameters into the statement text, a bound value containing{fn(or{d '...'}/{ts '...'}) was re-read as SQL syntax: the{fnwas removed together with the next}found anywhere in the statement — usually the closing brace of an unrelatedMap/Tupleliteral in another value or row — corrupting the inserted data or failing with a server-sideSYNTAX_ERROR. Escape sequences are now recognized only outside of quoted text, and a{fn ...}escape is unwrapped at its matching closing brace, so nested braces (e.g. a{name:Type}query parameter or a nested escape) stay balanced. (https://github.com/ClickHouse/clickhouse-java/issues/2995) -
[jdbc-v2] Fixed prepared statements losing parameter markers after an empty
--comment line or afterSELECT * EXCEPT (...), which caused parameter binding to fail withArrayIndexOutOfBoundsExceptionfor the affected SQL parser backends. (https://github.com/ClickHouse/clickhouse-java/issues/3052) -
[client-v2] Fixed LZ4 input streams not closing their underlying HTTP response stream. Closing an LZ4 stream returned by
QueryResponse.getInputStream()now releases the wrapped transport stream, including after a partial read. (https://github.com/ClickHouse/clickhouse-java/issues/2985) -
[jdbc-v2] Fixed the default JavaCC SQL parser aborting on a heredoc string (
$$body$$,$tag$body$tag$) whose body contains a character that is not a valid SQL token on its own, such as!,&,|or~. The lexer had no heredoc token, so such a body raised a lexer error that left the statement classified asUNKNOWN— an INSERT was reported as a result-set-bearing statement with no table name and no values-list positions, which disables the batch values template and the table-name based paths. A heredoc is now lexed as a single string literal. (https://github.com/ClickHouse/clickhouse-java/issues/3029) -
[client-v2, jdbc-v2] Reduced noisy and potentially sensitive logging; SQL that fails to parse is no longer logged at
WARN(it could contain credentials/PII). (https://github.com/ClickHouse/clickhouse-java/issues/2970) -
[client-v2] Fixed
BigDecimalvalues written into aDynamiccolumn being silently truncated when the value’s scale exceeded the inferred width’s maximum scale, and throwing an overflow error when the value carried an integer part (e.g.19.99). TheDynamictype inference now sizes theDecimalwidth to hold both the integer digits and the value’s scale, keeps the scale as wide as the width allows without stealing room from the integer part, and writes the actual column scale into theDynamictype tag. Values that already round-tripped losslessly are unchanged. (https://github.com/ClickHouse/clickhouse-java/issues/2966) -
[client-v2] Fixed the
RowBinarywriter throwingUnsupportedOperationException: Unsupported data type: SimpleAggregateFunctionwhen inserting into aSimpleAggregateFunction(func, T)column (the reader already supported these columns). The value is now serialized identically to its underlying typeT, writing theNullablenull-marker byte when the underlying type is nullable (e.g.SimpleAggregateFunction(anyLast, Nullable(String))), mirroring the read path. (https://github.com/ClickHouse/clickhouse-java/issues/2477) -
[client-v2] Fixed the
Dynamictype tag for aSimpleAggregateFunctiontype being written as a bare0x2Ebyte. The binary type encoding also carries the function name, its parameters and its argument types, so the server read the function name out of the value bytes that followed and failed withATTEMPT_TO_READ_AFTER_EOF. Since the client never infers aSimpleAggregateFunctionfrom a Java value and the reader cannot read one back out of aDynamiccolumn, this now fails fast with a clearClientExceptioninstead of producing a corruptRowBinarystream (the same treatmentQBitalready gets). (https://github.com/ClickHouse/clickhouse-java/issues/3007) -
[client-v2, jdbc-v2] Fixed several logging-layer defects. In
client-v2,HttpAPIClientHelper.shouldRetrythrew aClassCastExceptionwhen a retryableServerExceptionwas wrapped as the cause of another exception (the branch matched on the cause but the cast used the outer exception); the retry decision is now taken from whichever exception is theServerException. Also inclient-v2, a failure to build the HTTP client version string is now logged atWARNwith the throwable attached instead of a bareINFOmessage that discarded the cause. Injdbc-v2, a failure to close the response after a query error now logs the close failure itself instead of the already-propagated outer exception. (https://github.com/ClickHouse/clickhouse-java/issues/2968) -
[client-v2] Fixed scalar
Stringquery parameters containing a tab (0x09), newline (0x0a) or backslash being mishandled through the server’sparam_<name>interface. A{name:String}parameter value is parsed by the server withdeserializeTextEscaped, which treated a raw tab or newline as a field delimiter (failing the query withBAD_QUERY_PARAMETER: ... isn't parsed completely) and a raw backslash as the start of an escape sequence (silently corrupting the value, e.g.C:\tempbecameC:<tab>emp).Client.query(sql, params, ...)now escapes the backslash, tab and newline in a scalarStringparameter so any value round-trips; every other character the server reads verbatim — including the single quote and carriage return — is left unchanged, soIdentifiervalues and pre-formattedArray/Mapliterals passed as aStringstill round-trip. The JDBC driver (jdbc-v2), which inlines parameters as SQL literals and already escaped the backslash and single quote, is unchanged and covered by a new regression test. (https://github.com/ClickHouse/clickhouse-java/issues/2781) -
[client-v2] Fixed a
nullquery-parameter value being sent as the literal string"null", soClient.query(sql, params, ...)binding a Javanullto a scalar placeholder such as{x:Nullable(Decimal128(8))}was rejected by the server withBAD_QUERY_PARAMETER(Value null cannot be parsed as Nullable(...)). A top-level scalarnullis now sent as the ClickHouse\NNULL sentinel so it binds SQLNULL; anullnested inside anArray/Mapparameter value continues to render as the SQLNULLkeyword. (https://github.com/ClickHouse/clickhouse-java/issues/2977) -
[client-v2] Fixed binary array decoding for nullable element types so
Array(Nullable(Float64))and similar columns now return boxed arrays such asDouble[]instead ofObject[]. This keeps null-supporting arrays aligned with their element type while preserving the existingObject[]fallback for Variant/Dynamic/Geometry arrays. (https://github.com/ClickHouse/clickhouse-java/issues/2846) -
[client-v2] Fixed
Float32/Float64columns throwingClassCastExceptionwhen a value of a non-matching boxed numeric type was supplied through theObject-typed insert surface — for example aDouble(the natural type of Java literal like1.5) for aFloat32column, or aFloatfor aFloat64column. TheRowBinaryserializer now narrows anyNumber(and, like theInt*columns, aString/Boolean) throughNumber#floatValue()/Number#doubleValue(), so the float columns accept the same value types the integer columns already did. (https://github.com/ClickHouse/clickhouse-java/issues/2930) -
[client-v2] Fixed a
NullPointerExceptionwhen serializing anullvalue into a non-nullableEnum8/Enum16column.SerializerUtils.serializeEnumDatahad nonullguard, so anullin a non-nullable enum column reachedvalue.getClass()and failed the RowBinary insert path with a confusing NPE instead of a clear error. It now throwsIllegalArgumentExceptionnaming the column, consistent with the existingIllegalArgumentExceptionfor other unsupported enum values. Nullable enum columns are unaffected. (https://github.com/ClickHouse/clickhouse-java/issues/2931) -
[client-v2] Fixed silent data corruption when serializing a Java
nullinto a non-nullableArray(...)column viaRowBinaryFormatWriter.RowBinaryFormatSerializer.writeValuePreamblespecial-casedArray, emitting a stray marker byte on top of the array length; the server read the extra byte as a phantom extra row (single-column inserts) or as a column shift that failed the insert withCANNOT_READ_ALL_DATA(multi-column inserts). A non-nullableArraycannot represent anull, so it now throwsIllegalArgumentExceptionnaming the column — consistent with every other non-nullable type — in both theRowBinaryandRowBinaryWithDefaultspaths. Empty arrays ([]) still serialize correctly, andDynamiccolumns, which can hold anullas the implicitNothingtype, are unaffected. (https://github.com/ClickHouse/clickhouse-java/issues/2938) -
[client-v2] Fixed POJO insert error classification so transport write failures such as java.net.SocketException: Broken pipe (Write failed) are now surfaced as transfer/network errors instead of being wrapped as DataSerializationException. This only changes the exception type reported for request-body transport failures during
Client.insert (...);actual POJO reflection/serialization failures are still reported as DataSerializationException. (https://github.com/ClickHouse/clickhouse-java/issues/2729) -
[client-v2] Fixed binary varint decoding for length and count fields so overflowing or overlong values fail with an
IOExceptioninstead of being decoded into corrupted or negativeintvalues. (https://github.com/ClickHouse/clickhouse-java/issues/2902) -
[client-v2] Fixed container query parameters being sent unquoted, so
Client.query(sql, params, settings)binding aList<LocalDate>(or an array/Map) to a placeholder like{ids:Array(Date)}was rejected by the server withCANNOT_PARSE_INPUT_ASSERTION_FAILED. Parameter values are now formatted byDataTypeConverter#convertParameterToString(Object)before being sent: pass the raw Java value and the client renders it into the text the server’sparam_<name>interface expects — aCollection, array (object or primitive), orMapbecomes ClickHouseArray(['2026-05-13']) /Map({'k':'v'}) text withString/temporal leaves single-quoted and numeric/boolean leaves left unquoted, while a scalar is passed through unquoted as before. No manual pre-formatting of container parameters is needed. (https://github.com/ClickHouse/clickhouse-java/issues/2897) -
[client-v2] Fixed
DateTime/DateTime64columns declared with a synthetic fixed-offset timezone name (Fixed/UTC±HH:MM:SS, e.g.Fixed/UTC+05:30:00) being silently read in UTC instead of the declared offset. TheRowBinaryreader now recovers the offset from the column’s declared type. (https://github.com/ClickHouse/clickhouse-java/issues/2876) -
[jdbc-v2] Fixed the ANTLR4 SQL parser backends (
jdbc_sql_parser=ANTLR4andANTLR4_PARAMS_PARSER) lexing the body of a heredoc string ($$body$$,$tag$body$tag$) as ordinary SQL. The lexer had no heredoc token, so every$was dropped as an unrecognized character and the body was parsed as identifiers, operators and statement separators: a body that still looked like valid SQL was silently mis-parsed (wrong table name and VALUES-list positions), and a body containing;— as well as the empty heredoc$$$$— was reported as a parse error, which classifies an INSERT as a result-set-bearing statement with no values-list positions. A heredoc is now lexed as a single string literal and accepted as a literal value (INSERT ... VALUESlists, column expressions, settings), and a$inside an identifier (a$b, or an unterminated tag such as$foo$bar) is part of the identifier, as the server reads it. (https://github.com/ClickHouse/clickhouse-java/issues/3031) -
[jdbc-v2] Fixed the beta RowBinary writer (
DriverProperties.BETA_ROW_BINARY_WRITER) throwingNoSuchColumnExceptionforINSERTstatements whose column names are backtick-quoted, in particular the canonicalNestedsub-column wire form`directory`.`id`. The SQL parser now unescapes each backtick-quotedINSERTcolumn-name component before the by-name server-schema lookup, matching how the table and database identifiers are already handled. (https://github.com/ClickHouse/clickhouse-java/issues/2896) -
[client-v2, jdbc-v2] Fixed
ResultSet#close(),QueryResponse#close(), and closing a reader or the response stream when the result was not read to the end, which could fail withPremature end of chunk coded message body: closing chunk expected. To close a partly read response, the HTTP client reads and discards the rest of the body. When a query fails after the response started, the server ends the body early, and that read failed. When the result stream was opened, this failure on close is now logged atDEBUGand not thrown. Errors while the response is read are not changed, and a command or update that does not read the result (Client#execute,Statement#executeUpdate) still reports the failure. (https://github.com/ClickHouse/clickhouse-java/issues/3203)
Documentation
- [examples] - New
demo-spring-serviceadded to demonstrate usage of observability SPI.
Dependencies
-
[client-v1,client-v2] Upgraded
org.apache.httpcomponents.client5:httpclient5from5.4.4to5.6.4inclient-v2andclickhouse-http-clientto pick up the fixes of the newer 5.x releases, including known vulnerabilities. (https://github.com/ClickHouse/clickhouse-java/issues/3078) -
[client-v2] Upgraded
org.bouncycastle:bcprov-jdk18onfrom1.84to1.85inclient-v2(https://github.com/ClickHouse/clickhouse-java/pull/3141).
Source ClickHouse/clickhouse-java ·
v0.11.0· 2026-10-21 · upstream release
Mirrored verbatim for indexing. All rights belong to the upstream project.
Release notes are published by the upstream project and mirrored here for indexing. All rights belong to their authors.