ClickHouse C – 使用原生二进制协议与 ClickHouse 交互
仅包含头文件的 C 客户端,用于 ClickHouse 原生线格式 — 通过 TCP 传输原生格式块的原生协议。一个核心头部,加上可选的后续头部,用于 TCP、压缩、编解码器和 I/O 后端。旨在嵌入 PostgreSQL 扩展中(palloc 区域,longjmp),但没有 PG 特定代码。只需包含 clickhouse.h 就可以提供一个纯粹的块解码器,基于调用方提供的 chc_io,用于从管道中读取 clickhouse-local 的 FORMAT 原生,无需 TCP,无需压缩,除了 libc 之外没有链接时依赖。快速入门 无需 TCP 或压缩地解码 clickhouse local 查询。 /* demo.c — cc -std=c11 -O2 -I. demo.c -o demo */ #define CHC_PROVIDE_STDLIB_ALLOC #define CHC_IMPLEMENTATION #include "clickhouse.h" #include "clickhouse-posix-io.h" #include <stdio.h> #include <unistd.h> int main ( void ) { /* 生成 `clickhouse local --format Native -q "..."` 并通过管道读取其标准输出;请参见 examples/minimal_decode.c 了解完整的实现。 */ int fd = /* 从子进程读取管道的末尾 */ ; chc_alloc al = chc_alloc_stdlib (); chc_posix_io state ; chc_io io ; chc_posix_io_init ( & state , & io , fd , NULL , NULL ); chc_block_opts opts = {}; /* clickhouse-local: 无 BlockInfo,无自定义序列化 */ /* 整个流的一个持久读者:chc_block_read 保持已读取字节的缓存,直到下一个块边界。 */ chc_err ierr = {}; chc_in in ; if ( chc_in_init ( & in , & io , & al , opts . read_buffer_bytes , & ierr ) != CHC_OK ) { fprintf ( stderr , "init: %s " , ierr . msg ); return 1 ; } for (;;) { chc_block * block = NULL ; chc_err err = {}; if ( chc_block_read ( & in , & al , & opts , & block , & err ) != CHC_OK ) { fprintf ( stderr , "decode: %s " , err . msg ); return 1 ; } if (! block ) break ; for ( size_t r = 0 ; r < chc_block_n_rows ( block ); r ++ ) for ( size_t c = 0 ; c < chc_block_n_columns ( block ); c ++ ) /* 根据 chc_column_layout(chc_block_column(block, c)) 分派 */ ; chc_block_destroy ( block , & al ); } chc_in_free ( & in ); } 完整的端到端版本:examples/minimal_decode.c。所需的服务器设置(TCP 的查询包,clickhouse local 的标志): output_format_native_encode_types_in_binary_format = 0 否则,服务器将发出二进制类型标签,chc_block_read 返回 CHC_ERR_TYPE。集成 clickhouse-c 作为一组平面的头文件分发:每个头文件都包含声明和实现,由哨兵宏保护。每个消费者正好有一个翻译单元定义实现宏并包含头文件;其他人只包含声明。/* consumer/src/clickhouse.c — 唯一链接库的一个 TU */ #define CHC_IMPLEMENTATION #include "clickhouse.h" #include "clickhouse-posix-io.h" /* …在此处包含 clickhouse-client.h、clickhouse-compression.h 以使用所需的功能。 */ 其他 TU 仅包含公共声明:#include "clickhouse.h" #include "clickhouse-posix-io.h" /* 不在此处定义 CHC_IMPLEMENTATION */ 一个 stdlib malloc / realloc / free 帮助器可在包含 clickhouse.h 之前定义 #define CHC_PROVIDE_STDLIB_ALLOC 。有关在真实 PostgreSQL 扩展中内部使用 palloc / repalloc / pfree 的 wiring,请参见 pg_clickhouse 或 pg_stat_ch 。头文件 头部 目的 链接 clickhouse.h 核心:类型、错误、chc_alloc、chc_io、类型名称解析器、块读写器 — clickhouse-client.h TCP 数据包循环:Hello / Query / Data / EOS / Exception / Progress / Pong — clickhouse-async.h 无 I/O 客户端:由调用者字节提交驱动的相同数据包循环,无 socket — clickhouse-compression.h 压缩帧布局、CityHash128、chc_codec 调度、LZ4 和 ZSTD 适配器(可通过 CHC_NO_LZ4 / CHC_NO_ZSTD 选择退出) -llz4 -lzstd clickhouse-posix-io.h 基于阻塞 read(2) / write(2) 的 chc_io,使用 EINTR 循环和取消钩子 — clickhouse-openssl.h 基于 SSL_read / SSL_write 的 chc_io -lssl -lcrypto 每个后续头文件都是独立的;选择适合您构建需要的内容。clickhouse-client.h 支持 ClickHouse 23.3 及更高版本。每个头文件的参考在 doc/;头文件本身内联声明和注释。完整示例在 examples/ 中。测试 使用 test.sh 运行测试:./test.sh 如果错误报告缺少头文件或链接器错误,请使用 CFLAGS 和 LDFLAGS 指向适当的目录,例如,使用 Homebrew:CFLAGS=-I/opt/homebrew/include LDFLAGS=-L/opt/homebrew/lib ./test.sh 该脚本在测试中运行单个测试。要运行单个测试,请将其基本名称(不带结尾的 .c)作为参数传递:./test.sh test_cancel test_block_decode test_client_tcp 从 PATH 启动 clickhouse 服务器。将 CHC_TEST_PORT 设置为针对正在运行的服务器进行测试,例如在 docker 中的旧版本:docker run -d -p 127.0.0.1:19233:9000 clickhouse/clickhouse-server:23.3.22.3 CHC_TEST_PORT=19233 ./test.sh client_tcp tools/capture.py 代理这样的服务器以记录重放固定,如 test/ch23_3_sparse.bin 。非目标 HTTP 协议 — 直接包装 libcurl。DNS、端点轮询、连接池、重试/退避。SSL/TLS 上下文生命周期
本站免费、广告极少。如果觉得有帮助,可以请我们喝杯咖啡 —— 任何金额都对持续运营有实际帮助。
☕请我喝杯咖啡