TECHNOLOGY
ClickHouse releases header-only C library for reading its native protocol in embedded code
A new open-source project, clickhouse-c, lets C programs talk to ClickHouse using its native binary format. It is built for embedding, including inside PostgreSQL extensions, and its core needs nothing beyond libc.
Image: IntraGoals Media
ClickHouse has published clickhouse-c, a header-only C client for the ClickHouse Native wire format. That is the Native Protocol over TCP, which carries data in Native Format blocks.
"Header-only" means the code ships as header files that you include in your own project, instead of a separate library you build and link. The core is one header, clickhouse.h. Other headers are optional and add TCP, compression, codecs and different I/O backends.
The project is designed for embedding inside PostgreSQL extensions, where code uses PostgreSQL's palloc memory arena and longjmp for error handling. It contains no PostgreSQL-specific code, though. For real PostgreSQL wiring, the page points to pg_clickhouse and pg_stat_ch.
Including clickhouse.h alone gives you a pure block decoder. It reads from an I/O object that the caller supplies, called chc_io. One use is reading the FORMAT Native output of clickhouse-local from a pipe. That needs no TCP, no compression and no link-time dependencies beyond libc, the standard C library.
The quickstart shows this case. A program starts clickhouse local with the Native format, reads its output through a pipe, and loops over the blocks it decodes. It then goes through each block's rows and columns. The page also links to a full runnable version, examples/minimal_decode.c.
One server setting is required. output_format_native_encode_types_in_binary_format must be set to 0, either in the Query packet over TCP or as a flag for clickhouse local. Without it, the server sends binary type tags and chc_block_read returns CHC_ERR_TYPE.
On integration, each header holds both declarations and implementation, guarded by a macro. Exactly one translation unit, meaning one C source file, defines CHC_IMPLEMENTATION and includes the headers. Every other file includes them for declarations only. A standard malloc, realloc and free helper is available by defining CHC_PROVIDE_STDLIB_ALLOC before including clickhouse.h.
The other headers each have a job. clickhouse-client.h runs the TCP packet loop: Hello, Query, Data, end of stream, Exception, Progress and Pong. clickhouse-async.h does the same without a socket, with the caller feeding in bytes. clickhouse-compression.h covers compressed frames, CityHash128, and LZ4 and ZSTD adapters, which can be turned off with CHC_NO_LZ4 or CHC_NO_ZSTD. It links with -llz4 and -lzstd.
Two more headers handle I/O. clickhouse-posix-io.h wraps blocking read and write calls, with an EINTR retry loop and a cancel hook. clickhouse-openssl.h wraps SSL_read and SSL_write and links with -lssl and -lcrypto. Each follow-up header is independent, so you only pull in what your build needs. clickhouse-client.h supports ClickHouse 23.3 and newer.