ChDriver.Protocol.Block.Wrappers (ch_driver v0.3.0)

Copy Markdown

Decoders for ClickHouse's wrapper and compound column types: Nullable(T), Array(T), Map(K, V), LowCardinality(T), Variant(T1, ..., Tn), and Decimal(P, S).

Dispatched from ChDriver.Protocol.NativeBlock's decode_column_data/3, which these functions recurse back into for their inner type(s) — that's what lets deeply nested types like Array(Nullable(String)) or Map(String, Array(UInt32)) decode correctly without any special-casing.

Map(K, V) values decode to plain Elixir maps; Array(T) and LowCardinality(T) decode to lists; Nullable(T) decodes to the inner value or nil; Variant(...) decodes to whichever alternative each row selected (or nil); Decimal(P, S) decodes to a Decimal.t(). See ARCHITECTURE.md for the wire-level byte layouts.

Each decoder takes and returns the hoisted serialization-prefix list — see ChDriver.Protocol.NativeBlock's moduledoc for why prefixes are read up front rather than inline.

Summary

Functions

Decodes a Variant(T1, ..., Tn) column: one discriminator byte per row (the 0-based index of the alternative that row holds, in the type name's order, or 255 for no value), followed by one contiguous sub-column per alternative, in alternative order, holding only the rows that selected it.

Splits values (the flattened element array) back into per-row lists using Array(T)'s cumulative offsets, e.g. values = [1, 2, 3, 4, 5] and offsets = [2, 2, 5] (row 0 has 2 elements, row 1 has 0, row 2 has

Functions

decode_variant(alternatives, num_rows, binary, prefixes)

Decodes a Variant(T1, ..., Tn) column: one discriminator byte per row (the 0-based index of the alternative that row holds, in the type name's order, or 255 for no value), followed by one contiguous sub-column per alternative, in alternative order, holding only the rows that selected it.

An alternative no row selected contributes zero bytes, so the discriminators have to be counted before any sub-column can be read — which is exactly why this can't be a streaming per-row decode.

Variant's own 8-byte discriminator-mode prefix was already consumed by ChDriver.Protocol.NativeBlock.decode_prefixes/2, so it's popped off prefixes here rather than read from binary.

split_by_offsets(values, offsets)

Splits values (the flattened element array) back into per-row lists using Array(T)'s cumulative offsets, e.g. values = [1, 2, 3, 4, 5] and offsets = [2, 2, 5] (row 0 has 2 elements, row 1 has 0, row 2 has

  1. splits into [[1, 2], [], [3, 4, 5]].