← All databases

Database · PostgreSQL wire

YDB into Apache Arrow with ADBC

YDB 23.4 (PostgreSQL wire), 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 with psqlodbc 16.00.0005 built from REL-16_00_0005 (YDB, PostgreSQL wire 14.0.5); FAIL with psqlodbc 18.00.0002: psqlodbc 18.00.0002 sends SHOW DateStyle; at connect (connection.c:1109) and YDB's PostgreSQL layer answers unrecognized configuration parameter "datestyle" — a driver-version incompatibility; psqlodbc 16 (Linux) does not issue it

Windows x64✓ pass

PASS (ydbplatform/local-ydb, PostgreSQL wire 14.0.5; psqlodbc 16.00.0007 PostgreSQL Unicode 16(x64) as on Linux, admin-extracted from psqlodbc16_x64.msi since 18 and 16 cannot coexist through the installer; adbcuser + GRANT ALL provisioned per the README after every container recreate) — the first run hung for 7 min inside the workload while the container's own health check sat at OVERLOADED (.sys_health/test "path exists but creating right now"); recreated fresh, it passes in 4 s

Driver and connection string

ODBC driver
psqlodbc 16 (PG wire)
Wire
PostgreSQL wire
adbcBridge
0.1.1 (release)

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

Driver={drv};Server=127.0.0.1;Port=15444;Database=local;Uid=adbcuser;Pwd=Ydb!Bridge2026;BoolsAsChar=0;UseServerSidePrepare=0;

Python

import adbcbridge

# {drv}: the ODBC driver library (path), or its name from odbcinst.ini
conn = adbcbridge.connect(uri="Driver={drv};Server=127.0.0.1;Port=15444;Database=local;Uid=adbcuser;Pwd=Ydb!Bridge2026;BoolsAsChar=0;UseServerSidePrepare=0;")
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 YDB 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

distributed HTAP store behind a PostgreSQL-compatible wire; version() names it PostgreSQL 16, so the two quirks are keyed on the one thing that gives YDB away over ODBC — it answers SHOW server_version with that whole banner rather than a version number: every table needs a PRIMARY KEY, and no ingested column can be one (a YDB key is implicitly NOT NULL), so generated ingest DDL appends adbc_pk SERIAL PRIMARY KEY (ddl_extra_column), and pg_catalog.pg_attribute is empty, so psqlodbc's SQLColumns answers success with zero rows and GetObjects describes a zero-row SELECT instead (no_sql_columns).

What this stack needed

Native ADBC driver, compared

YDB speaks the PostgreSQL wire protocol, so Apache Arrow's native PostgreSQL ADBC driver (adbc-driver-postgresql 1.12.0) can be pointed at it too. On 2026-09-05 the same seven-step ADBC workload (connect, SELECT 1, DDL and inserts and a read, a 1,000-row adbc_ingest, table schema, catalog listing, read back) ran through both:

PathResultFirst error
Native ADBC driverfails at select1IO: [libpq] Failed to execute query: could not begin COPY: Status: GENERIC_ERROR
adbcBridge over ODBC✓ all seven steps

Where the native driver stops it is by design of that driver, not a defect of YDB; the full table for all 28 wire-compatible databases, with each first error, is in the note.

Read next