1.21.0
New features
-
The tracer API (unreleased, introduced in #776) now follows the OpenTelemetry database semantic conventions and matches the attribute vocabulary of the Rust client (clickhouse-rs); see
docs/howto/tracing.mdfor the documentation. In particular (#828):- Spans now carry
db.system.name(instead ofdb.system),server.address+server.port(instead of a combinedhost:port),clickhouse.request.query_id/clickhouse.request.session_id(instead ofclickhouse.query_id/clickhouse.session_id),clickhouse.response.formatonqueryandclickhouse.request.formatoninsert(instead ofclickhouse.format), anddb.operation.name+db.collection.nameoninsert(instead ofclickhouse.table). - The span status is left unset on success (per the OTEL spec recommendation for client spans, previously set to
OK); on failure, the span gets theerror.typeattribute (the error class name) and, for server-side errors,clickhouse.error.code(the numeric ClickHouse error code). - Spans record response-side attributes:
db.response.status_code(HTTP status) and, when theX-ClickHouse-Summaryheader is available,clickhouse.summary.*counters (read_rows,written_rows, etc.). query()now emits two spans:clickhouse.querycovers the HTTP request lifetime and ends as soon as the response headers are received; a childclickhouse.query.streamspan is handed to theResultSetand tracks the stream consumption, ending when the response is fully read, closed, or fails - with the finalclickhouse.response.decoded_bytesand (for row-streaming)db.response.returned_rowsmetrics. This separation makes it easy to distinguish the original request duration from a stream that may never end (e.g. tailing a live table).- Fixed a span leak in the Web
ResultSet.stream()path: if the underlying fetch response stream was aborted (e.g. due to a network error), theclickhouse.query.streamspan was never ended. The TransformStream now handles both source-stream aborts and consumer-side cancellations via acancelcallback. - The
insertspan recordsclickhouse.request.sent_rowsfor array-based inserts.
- Spans now carry
-
Added a
use_multipart_params_autoclient option (default:false). When enabled,query()automatically sendsquery_paramsasmultipart/form-databody parts (the same mechanism asuse_multipart_params) once their URL-encoded length exceeds 4096 characters, avoiding HTTP 414/400 errors from HTTP intermediaries (nginx, AWS ALB, CloudFront) caused by over-long URLs - for example, a largeINlist or a high-dimensional vector embedding. Smaller parameter payloads remain in the URL query string, so existing behavior is unchanged unless the threshold is crossed.use_multipart_params: truestill forces multipart for all queries regardless of size. This does not change the server's per-value size limit, which is governed byhttp_max_field_value_size. Supported on both@clickhouse/clientand@clickhouse/client-web, and overridable per request viause_multipart_params_autoonquery(). Ported from clickhouse-connect#789. (#827)
const client = createClient({ use_multipart_params_auto: true });
await client.query({
query: "SELECT * FROM events WHERE id IN {ids:Array(UInt64)}",
// Sent in the URL when small, auto-promoted to the multipart body when large
query_params: { ids: veryLargeArrayOfIds },
});- Added a
use_multipart_paramsclient option (default:false). When enabled,query()sendsquery_paramsasmultipart/form-databody parts (with the SQL moved into aquerypart) instead of URL query-string entries, avoiding HTTP 400 errors caused by over-long URLs when parameters contain large arrays (25K+ values). All other URL search params (database, query_id, settings, session_id, role) remain in the URL. Supported on both@clickhouse/clientand@clickhouse/client-web, and overridable per request viause_multipart_paramsonquery(). (#825)
const client = createClient({ use_multipart_params: true });
await client.query({
query: "SELECT * FROM events WHERE id IN {ids:Array(UInt64)}",
query_params: { ids: veryLargeArrayOfIds },
// Per-request override is also supported:
// use_multipart_params: false,
});Bug Fixes
- The client now checks the
X-ClickHouse-Exception-Coderesponse header to detect server errors even when the HTTP status code indicates success. In some scenarios (for example, when an exception occurs while streaming the response progress in headers, or with certain proxy setups), ClickHouse responds with HTTP 200 but sets theX-ClickHouse-Exception-Codeheader. Previously, such responses were treated as successful, and the exception text could surface as malformed response data; now the request is rejected with a parsedClickHouseError(with the propercodeandtype), consistent with non-2xx error responses. This applies to both the Node.js and Web clients. (#554, supersedes #350, related issue: #332)