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.

Developer's monitor showing C code that includes clickhouse.h beside a terminal running a clickhouse local queryTECHNOLOGY

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.

Sources and further readingGitHub - ClickHouse/clickhouse-c: minimalist header-only library for embedded contexts ↗
ABOUT THE DESK

Harsh DV

IntraGoals reports on important changes in technology and work. We check each story for clear writing, trusted sources and useful information before it is published.

KEEP READING

Latest from IntraGoals.

All latest stories ↗