OceanBase CE into Apache Arrow with ADBC
OceanBase CE 4.4.2 (MySQL 5.7.25 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
PASS
PASS (OceanBase CE, MySQL wire 5.7.25) — MODE=SLIM, boots in 40 s, 4.3 GiB peak
PASS (OceanBase CE, MySQL wire 5.7.25, MODE=SLIM, boots in ~60 s under a 6 GB cap; MySQL Connector/ODBC 26.7.1, user root@test) — needs NO_SSPS=1 on Windows: the entry's connection string carries no {no_ssps}, and without it every bound parameter fails No data supplied for parameters in prepared statement (pyodbc identical); run with an OCEANBASE_CONN override that adds it — a one-token patch to the entry
Driver and connection string
- ODBC driver
- MySQL Connector/ODBC 9.4 (MySQL wire)
- Wire
- MySQL wire
- adbcBridge
- 0.1.1 (release)
The connection string the matrix used, as the connection strings reference records it (MySQL 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=12881;Database=adbc;User=root@test;Password=adbc;{plugin_dir}
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=12881;Database=adbc;User=root@test;Password=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 OceanBase CE 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
no driver quirks and no tolerance flag the mysql entry does not already have (TINYINT(1) booleans, ANSI_QUOTES) — a distributed HTAP engine whose MySQL mode takes that entry's types unchanged; multi-tenant, so the login name carries the tenant (User=root@test), and mysql_native_password only, so run from the tarball the connector needs PLUGIN_DIR=; the container must boot with MODE=SLIM, which starts a prebuilt cluster — the default MODE=MINI builds its tenant from scratch and times out loading the timezone tables (117,043 rows in mysql.time_zone_transition), and is also the only path on which obd's open-files precheck (OBD-1007, nofile below 20000) fires; the SLIM path boots under Docker's default 1024, and the compose file raises nofile to 20000 anyway because at 1024 the observer quietly stops accepting connections once ~780 are open; ingest 105k rows/s at 20,000 rows (12.2k with adbc.odbc.rows_per_insert=1; adbc.odbc.array_binding changes nothing here -- Connector/ODBC walks a parameter array row by row, so the multi-row INSERT stays ahead and ingest takes it either way); fetch 1.32M rows/s.
What this stack needed
- One thing to know when writing NULLs here: on a server-side prepared INSERT the connector sends a NULL as
MYSQL_TYPE_NULLuntil a non-NULL execute has fixed that parameter's type, and OceanBase refuses that execute withObject type error(4001) -- the NULL-carrying execute itself, not the ones after it; once a value has gone through on that statement, later NULLs are accepted, and a fresh statement starts over. NO_SSPS=1avoids it entirely; MySQL itself is happy with the same sequence.- Bulk ingest is where it shows: a multi-row
INSERTwhose first execute carries a NULL is refused, the ingest falls back to a parameter array, and Connector/ODBC answersSQL_PARAM_ERRORfor the sets the server rejected -- adbcBridge re-runs those rows one at a time after the batch, by which point the types are fixed, so every row lands (0.1.0 dropped them silently and under-reported the count; a column that is NULL in every row raises the server's error)
Native ADBC driver, compared
OceanBase CE speaks the MySQL wire protocol, so the ADBC Driver Foundry's native MySQL ADBC driver (0.6.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:
| Path | Result | First error |
|---|---|---|
| Native ADBC driver | ✓ all seven steps | |
| adbcBridge over ODBC | ✓ all seven steps |
Where the native driver stops it is by design of that driver, not a defect of OceanBase CE; the full table for all 28 wire-compatible databases, with each first error, is in the note.