← All databases

Database · native ODBC

ClickHouse into Apache Arrow with ADBC

ClickHouse 26, read and written through adbcBridge — the ADBC driver that loads the database's ODBC driver — verified on Linux, macOS arm64 and Windows x64. Everything below is the compatibility matrix's record for this row.

Status

Linux✓ pass

PASS

macOS arm64✓ pass

PASS (ClickHouse 26.7.5.10, clickhouse-odbc 1.5.5 macOS zip, arm64)

Windows x64✓ pass

PASS (ClickHouse 26.7.5.10; clickhouse-odbc 1.5.5 Unicode from the GitHub MSI)

Driver and connection string

ODBC driver
clickhouse-odbc 1.5
Wire
native ODBC
adbcBridge
0.1.1 (release)

The connection string the matrix used, as the connection strings reference records it (Databases with their own native protocol and ODBC driver); {drv} is the driver library or its name from odbcinst.ini, and the host, port and credentials are the test server's.

Driver={drv};Url=http://127.0.0.1:18123;Database=adbc;UID=adbc;PWD=adbc;

Python

import adbcbridge

# {drv}: the ODBC driver library (path), or its name from odbcinst.ini
conn = adbcbridge.connect(uri="Driver={drv};Url=http://127.0.0.1:18123;Database=adbc;UID=adbc;PWD=adbc;")
with conn.cursor() as cur:
    cur.execute("SELECT * FROM my_table")
    table = cur.fetch_arrow_table()      # pyarrow.Table

Polars and pandas

import polars as pl, pandas as pd

df = pl.read_database("SELECT * FROM my_table", connection=conn)   # Polars, Arrow-native
pdf = pd.read_sql("SELECT * FROM my_table", conn)                   # pandas 2.2+, ADBC connection

pip install adbcbridge brings the driver library; the ClickHouse ODBC driver is installed the way its vendor documents, then named in Driver=. Rust, Go, C# and Java use the same connection string through their ADBC driver managers — see the docs.

What the matrix recorded

a NULL parameter must be bound with a NULL value pointer — with a value buffer bound the driver ignores SQL_NULL_DATA and sends the parameter empty, which the server rejects for Int32/Float64/Date/Decimal/Bool and silently stores as '' in String and as the epoch in DateTime64 (SQL_DESCRIBE_PARAMETER is N; SQLDescribeParam answers SQL_UNKNOWN_TYPE); no affected-row counts (SQLRowCount answers 0 for every write); Nullable() DDL wrapper on ingest; parameter arrays are the driver's own protocol — SQLExecute sends set 0 and each SQLMoreResults the next set (clickhouse-odbc#324) — and on 1.5.5 the first SQLMoreResults sends set 1 but answers SQL_NO_DATA, after which nothing advances: a 5-set array lands 2 rows under SQL_SUCCESS/SQL_NO_DATA (clickhouse-odbc#582), and a spec-conforming single SQLExecute lands 1; one HTTP request per execute — ~16 rows/s one row at a time, ~1k rows/s through the K-row INSERT ingest uses, with K bounded by the server's 1,000-field HTTP form limit

Read next