Bind Tuple parameters and integer Map keys, matching @clickhouse/client#75
Open
dfrankland wants to merge 1 commit into
Open
Bind Tuple parameters and integer Map keys, matching @clickhouse/client#75dfrankland wants to merge 1 commit into
dfrankland wants to merge 1 commit into
Conversation
`serializeValue` (the JS-value serializer behind `formatParamValue`, used by
the `queryBindAsync` server-side binding path) mishandled two compound-type
parameter shapes, so `@clickhouse/client` code passing them through
`ChdbConnection` failed with engine parse errors:
- A `@clickhouse/client-common` `TupleParam` fell through to the generic-object
branch and serialized as the map literal `{'values':[...]}`, which the engine
rejects for a `Tuple(...)` param. It now serializes as the positional tuple
literal `(a,b,c)`. Detected by shape (constructor name + `values` array)
rather than `instanceof`: the instance a caller passes comes from their own
`@clickhouse/client(-common)` copy, which under pnpm/nested installs may be a
different module instance than ours, so `instanceof` would spuriously miss it.
- `Map` keys were force-stringified and quoted (`{'42':...}`), which the engine
rejects for `Map(Int32, ...)`. Keys are now serialized by their JS type
(numeric keys unquoted, string keys quoted), matching
`@clickhouse/client-common`'s formatter.
Verified against the real engine: added unit + `queryBind` round-trip tests,
and confirmed the upstream `select_query_binding.test.ts` tuple/map cases now
pass, so their entries are removed from the clickhouse-js parity skip list.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
serializeValue(the JS-value serializer behindformatParamValue, used by thequeryBindAsync{name:Type}server-side binding path) mishandled two compound-type parameter shapes, so@clickhouse/clientcode passing them throughChdbConnectionfailed with engine parse errors:@clickhouse/client-commonTupleParamfell through to the generic-object branch and serialized as the map literal{'values':[...]}, which the engine rejects for aTuple(...)param.Mapkeys were force-stringified and quoted ({'42':...}), which the engine rejects forMap(Int32, ...).Why
chdb-node is a byte-compatible
@clickhouse/clientfaçade. The reference client serializes aTupleParamas the positional form(v1, v2, …)and aMapkey by its JS type (numbers unquoted); chdb-node's divergent output was a serialization bug, not an engine limitation. These are exactly the compound-type divergences called out as out-of-scope in #68's "Scope / non-goals".The diff
TupleParamis detected by shape (constructor name +valuesarray), notinstanceof: the instance a caller passes originates from their@clickhouse/client(-common)copy, which under pnpm/nested installs may resolve to a different module instance than ours, soinstanceofagainst our imported class would spuriously miss it. Both fixes live inserializeValue, so they apply at any nesting depth (Array(Tuple(...)),Map(K, Tuple(...))), mirroring the reference client's recursion.Verification
Confirmed end-to-end against the native
chdb_query_with_paramspath:new TupleParam(['main*','^main.*$'])Tuple(String, String)('main*','^main.*$')[TupleParam, TupleParam]Array(Tuple(String, String))new Map([[42, 'v']])Map(Int32, String){42:'v'}(was{'42':'v'}→ rejected)Parity suite
Removes the 7 tuple/map entries from
tests/clickhouse-js/skip_list.json. Verified against the upstreamselect_query_binding.test.ts(@clickhouse/clientclient-1.23.0,ChdbConnectioninjected,:memory:) — all 7 previously-skipped cases now pass:Tests
test/v3/serialize.test.ts: tuple literal,Array(Tuple), numeric-keyMap, and a guard that a plain{ values: [...] }object still serializes as a map.test/v3/querybind.test.ts: real-engine round-trips forTuple(String, String)andArray(Tuple(String, String)).test/v3suite green: 454 passed, 11 skipped.🤖 Generated with Claude Code
Note
Bind Tuple parameters and integer Map keys in query serialization, matching @clickhouse/client
TupleParamsupport toserializeValuein serialize.ts: objects matching theTupleParamshape (constructor name'TupleParam'with an array.values) are rendered as SQL tuple literals, e.g.('a','b').serializeValue(k)instead of always quoting keys as strings, so numeric keys render unquoted.Macroscope summarized a0e5360.