ChDriver.Types.Registry (ch_driver v0.1.0)

Copy Markdown

The scalar/fixed-width type codec table (column_codec/1) plus the primitive wire readers it hands out: decode_fixed_width/4 (fixed-width binary chunks, one per row, each run through a per-type unpack function) and decode_strings/3 (ClickHouse's length-prefixed String encoding).

A pragmatic subset of ClickHouse's type system: fixed-width integer and float types (by exact name), String, and a handful of common types (DateTime, Enum8/Enum16, UUID, IPv4, IPv6) that show up in ClickHouse's own ProfileEvents packets sent alongside every query result, or that this driver otherwise supports end to end. Not a general type system -- see ChDriver.Protocol.NativeBlock's moduledoc for the full list of what this driver supports and where each piece lives. Adding a new scalar ClickHouse type is a one-line addition to column_codec/1 here.

UUID's wire format: 16 bytes, laid out as the UUID's standard 16 text-representation bytes with each 8-byte half byte-reversed independently -- i.e. NOT the naive byte order, and NOT a swap of the two halves either. Concretely, for UUID 61f0c404-5cb3-11e7-907b-a6006ad3dba0 (standard bytes 61 f0 c4 04 5c b3 11 e7 90 7b a6 00 6a d3 db a0), ClickHouse's raw in-memory/wire bytes are e7 11 b3 5c 04 c4 f0 61 a0 db d3 6a 00 a6 7b 90 -- reversing bytes 0..7 and, separately, bytes 8..15 of the wire form recovers the standard form byte-for-byte.

IPv4's wire format (hex(reinterpretAsFixedString( toIPv4('192.168.1.1'))) -> 0101A8C0, i.e. the same little-endian UInt32 encoding as every other ClickHouse integer type -- 192.168.1.1 is 0xC0A80101 as a plain big-endian-read integer, and the wire bytes 01 01 A8 C0 are exactly that value's little-endian byte order): decoded to the dotted-quad text form (matching this module's UUID decode-to-text convention) by re-reading the same 4 bytes as a big-endian UInt32 and splitting into octets.

IPv6's wire format (hex(reinterpretAsFixedString( toIPv6('2001:db8::1'))) -> 20010DB8000000000000000000000001, and hex(reinterpretAsFixedString(toIPv6('::ffff:192.168.1.1'))) -> 00000000000000000000FFFFC0A80101): a plain 16-byte value in standard network byte order -- i.e. byte-for-byte identical to the address's normal text-form byte layout, with no reversal of any kind (unlike UUID, whose wire form independently byte-reverses each 8-byte half). Decoded to the standard colon-hex text form via :inet.ntoa/1 on the 8 big-endian 16-bit groups.

FixedString(N)'s wire format (hex(toFixedString('ab', 5)) -> 6162000000; matches DataTypeFixedString.cpp's deserializeBinaryBulk): exactly N raw bytes per row, right-padded with 0x00 up to N if the value is shorter -- unlike String, there is no length-prefix varint at all, and unlike String's own null-termination-free encoding, the padding bytes are real wire content. ClickHouse does not trim the padding back out on SELECT -- the padded value is the column's actual value -- so this decodes to the raw N-byte binary verbatim, trailing NULs included, via decode_fixed_width/4 with an identity unpack function (see ChDriver.Types.parse_fixed_string/1's call site in ChDriver.Protocol.NativeBlock's decode_column_data/3).

Summary

Functions

Looks up the fixed-width/string codec for a scalar ClickHouse type name. Returns {:fixed, byte_size, unpack_fun}, :string, or :unsupported.

Reads num_rows fixed-width byte_size-byte chunks from binary, running each through unpack (e.g. fn <<v::unsigned-little-32>> -> v end). Returns {:ok, values, rest} or {:incomplete, binary} if fewer than num_rows * byte_size bytes are available.

Reads remaining ClickHouse String values (varint length prefix + bytes) from binary. Returns {:ok, values, rest} or {:incomplete, binary}.

Functions

column_codec(arg1)

Looks up the fixed-width/string codec for a scalar ClickHouse type name. Returns {:fixed, byte_size, unpack_fun}, :string, or :unsupported.

decode_fixed_width(binary, num_rows, byte_size, unpack)

Reads num_rows fixed-width byte_size-byte chunks from binary, running each through unpack (e.g. fn <<v::unsigned-little-32>> -> v end). Returns {:ok, values, rest} or {:incomplete, binary} if fewer than num_rows * byte_size bytes are available.

decode_strings(binary, remaining, acc)

Reads remaining ClickHouse String values (varint length prefix + bytes) from binary. Returns {:ok, values, rest} or {:incomplete, binary}.