OpenSearch into Apache Arrow with ADBC
OpenSearch 3.8 (SQL plugin), read and written through adbcBridge — the ADBC driver that loads the database's ODBC driver — read-only on Linux and Windows x64. Everything below is the compatibility matrix's record for this row.
Status
PASS
driver unavailable: the project's macOS pkg is x86_64-only (Intel Macs not targeted)
PASS (OpenSearch 3.8.0, DISABLE_SECURITY_PLUGIN=true; OpenSearch SQL ODBC Driver 1.5.0.0 — the release's opensearch-sql-odbc-artifacts.tar.gz holds a 64-bit Windows MSI; read-only entry, fixtures from load_opensearch.py)
Driver and connection string
- ODBC driver
- OpenSearch SQL ODBC (built from source)
- 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};host=127.0.0.1;port=19200;auth=NONE;useSSL=0;
Python
import adbcbridge
# {drv}: the ODBC driver library (path), or its name from odbcinst.ini
conn = adbcbridge.connect(uri="Driver={drv};host=127.0.0.1;port=19200;auth=NONE;useSSL=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 OpenSearch 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
search engine reached through its bundled SQL plugin (/_plugins/_sql); the project publishes the driver for Windows and macOS only, so it is built for Linux — its never-compiled POSIX branch needed three source fixes: two compile fixes plus a sem_init() given capacity where WIN32/APPLE use initial (the pop semaphore starts full, so pop() corrupts an empty queue and clear() segfaults on close).
What this stack needed
- Driver quirk handled: its ANSI
SQLDriverConnectcannot connect at all —CC_connect()asks for theSQL_ASCIIclient encoding, which it does not support, unlessSQLDriverConnectWset the unicode-driver flag first — and returnsSQL_ERRORwith an empty diagnostic queue, so adbcBridge retries a connect that failed without saying why throughSQLDriverConnectW; one that reported a real error, bad credentials say, is left alone — though through unixODBC no other failed connect ever returns: the driver exportsSQLErrorWand hands back the same record on every call, and the driver manager, which prefersSQLErrorfor collecting a failed connect's diagnostics, loops on it forever (opensearch-project/sql-odbc#102).
CREATE TABLE, no INSERT) and the driver answers SQLBindParameter with "OpenSearch does not support parameters" — so the indices are written over the REST _bulk API; backtick identifiers, no DECIMAL or binary type, and the driver's result-set type map has no timestamp entry so ts is described SQL_WVARCHAR and arrives as text (its SQLColumns and SQLGetTypeInfo tables do map timestamp, so the two metadata paths disagree about the same column); also runs MATCH/MATCH_QUERY full-text predicates; fetch ~120k rows/s