Support JSON columns (read and insert) - #6
Merged
Conversation
Bump vendored clickhouse-cpp v2.6.1 -> v2.6.2, which adds a string-backed
ColumnJSON, and wire it through the type codec:
- decode a JSON column to a parsed Ruby Hash (like Map -> Hash)
- encode a Hash/Array via #to_json, or a String verbatim; nil becomes
"{}" (CH rejects empty strings) / SQL NULL on Nullable(JSON)
- auto-inject output_format_native_write_json_as_string on the read
paths so JSON reads just work; the setting is sent non-important so
servers that don't know it ignore it rather than erroring
- pin CH_MAP_BOOL_TO_UINT8=ON: v2.6.2 adds a distinct Bool column, and
the gem relies on Bool normalising to UInt8
JSON's string wire format requires ClickHouse 25.x+; specs are gated via
a min_ch_major tag and skip cleanly on older servers.
KirIgor
approved these changes
Jun 22, 2026
Bundler git: dependencies don't fetch submodules unless the Gemfile sets submodules: true, leaving vendor/clickhouse-cpp empty and aborting the build. When running inside a git checkout, fetch it ourselves before giving up. No-op for released gems and submodules:recursive checkouts. Also document the submodules: true Gemfile flag.
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
Adds support for ClickHouse
JSONcolumns — both decoding (read) and inserting.How
clickhouse-cppv2.6.1 → v2.6.2, which adds a string-backedColumnJSON. The in-tree declared-type patch still applies cleanly (the changed files don't touch the patched regions).value_at): aJSONcolumn is parsed into a RubyHash, consistent with howMapdecodes toHashandDecimal/Date/Timedecode to rich types.append_value): aHash/Arrayis serialized with#to_json; aStringis sent verbatim as JSON text.nilbecomes{}(ClickHouse rejects empty strings) on a plain column, or SQLNULLonNullable(JSON)via the existingNullablepath + a newappend_defaultarm.output_format_native_write_json_as_string=1is injected on every read path (query/query_value/query_each). It's sent with the non-important flag, so servers that don't know the setting silently ignore it instead of erroring; user-suppliedsettings:still override it.CH_MAP_BOOL_TO_UINT8=ONinextconf.rb: v2.6.2 introduces a distinctBoolcolumn, and the gem relies onBoolnormalising toUInt8(see the declared-type handling inclient.cpp). The upstream default is alreadyON; pinning it guards against a future flip.Drive-by fixes
extconf.rbself-heals git installs. Bundler doesn't fetch submodules forgit:dependencies unless the Gemfile setssubmodules: true, which leftvendor/clickhouse-cppempty and aborted the build.extconf.rbnow runsgit submodule update --init --recursiveitself when the vendored tree is missing and it's inside a git checkout (no-op for released gems andsubmodules: recursiveCI checkouts). The README also documents thesubmodules: trueflag. Verified end-to-end with a fresh no-submodule clone built viarake compile.Mapinserts aren't supported — they are (there's aMaparm inappend_valueand round-trip specs).Behaviour notes
ColumnJSONrelies on doesn't exist on 24.x, and 24.x's experimental JSON uses an incompatible on-wire serialization. Specs are gated with amin_ch_major: 25tag and skip cleanly on older servers (verified against a real 24.8 — 3 pending, 0 failures).1round-trips as"1", while booleans/nulls stay native and explicitly typed paths (e.g.JSON(a UInt32)) keep their type. This mirrorstoJSONString(col)server-side; the specs assert the real round-trip.Testing
rspecgreen on 25.3 (JSON specs run) and 24.8 (JSON specs skip) — 72 examples, 0 failures on both. CI passes the full matrix (ruby 3.3/3.4/4.0 × ch 24.8/25.3) plus macOS compile.rubocopclean.JSON, parametrizedJSON(max_dynamic_paths=N, a UInt32), andNullable(JSON)all verified round-tripping.rake compileauto-fetches clickhouse-cpp and builds throughjson.cpp; the resulting extension loads and round-trips JSON.🤖 Generated with Claude Code