Notes · 2026-08-25

What the Arrow Flight SQL ODBC driver claims, and what it does

Arrow Flight SQL ODBC 0.9.7, the driver Dremio publishes, advertises SQLBindParameter while answering HYC00, segfaults in SQLColumns without field metadata, and is iODBC-width on Apple Silicon.

Arrow Flight SQL is a wire protocol, not a database, and the one ODBC driver for it is the one Dremio publishes as arrow-flight-sql-odbc-driver. The same library file drives three very different servers in the compatibility matrix — sqlflite over DuckDB, InfluxDB 3 Core and Dremio 26 — so everything below is the driver's, not any one server's, and where a server does change the outcome that is said explicitly.

SQLGetFunctions says yes; the call says HYC00

The driver reports SQLBindParameter and SQLNumParams as supported. SQLBindParameter always answers HYC00, on a virgin statement handle, before any SQL has been seen:

SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt);
SQLINTEGER v = 42; SQLLEN ind = 4;
SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &v, 0, &ind);
/* SQL_ERROR, HYC00 [Apache Arrow][Flight SQL] (100) Unsupported function. */

Only SQLDescribeParam tells the truth, reporting 0. SQLPrepare succeeds on a statement containing ? and SQLNumParams then reports 0 markers, so there is no way to supply a value. SQLGetFunctions makes the same false claim for SQLStatistics, which also answers HYC00. Parameter binding is the write path, so nothing that binds a parameter can run: the matrix entries for all three servers are read-only, their tables built from literal SQLExecDirect statements. SQLRowCount returns -1 after a literal INSERT, so there would be no affected-row count either.

SQL_ATTR_AUTOCOMMIT = OFF is refused

HYC00 Optional feature not implemented. There is no transaction control through this driver at all.

SQLColumns segfaults on the first fetch

SQLColumns returns SQL_SUCCESS and describes all 18 result columns; the first SQLFetch on that cursor segfaults inside the driver, with no bound columns at all:

SQLColumns(stmt, NULL, 0, NULL, 0, (SQLCHAR*)"adbc_t", SQL_NTS, NULL, 0);  /* SQL_SUCCESS */
SQLNumResultCols(stmt, &n);                                               /* n == 18 */
SQLFetch(stmt);                                                           /* SIGSEGV */

The root cause, found later against InfluxDB 3: arrow::KeyValueMetadata::Get is called on a null pointer from GetColumns_Transformer::Transform, for any table whose Flight SQL schema carries no per-field key-value metadata. Against sqlflite that is every table, including the server's own TPC-H tables. Against InfluxDB 3 it is twelve of the seventeen tables SQLTables lists — all seven information_schema views and five of the eight system tables — while its iox tables fetch cleanly; a request spanning one bad table loses the good rows with it, and three system tables answer SQL_SUCCESS with zero rows for tables that do have columns. Against Dremio 26 the call fetches normally, unbound, bound, through SQLColumnsW, in an ODBC 2 environment and for every table the server has — so this half is the server's schema meeting the driver's assumption.

A crash leaves no return code to fall back on, so the call has to be skipped outright rather than tried and recovered from: read a table's columns off the result-set metadata of SELECT * FROM <table> WHERE 1=0 instead. Passing a catalog that matches nothing returns an empty result set that fetches without crashing — the crash is in producing the first row.

Apple Silicon: the build is iODBC-width, and nothing says so

The 0.9.7 armv8 build defines SQLWCHAR as wchar_t, four bytes. Under unixODBC, whose SQLWCHAR is two bytes, the first statement that fails on the server kills the process; the same driver through iODBC 3.52.16 returns the diagnostic intact ([HY000] (100) [Apache Arrow][Flight SQL] … Catalog Error: Table with name no_such_table_xyz does not exist!). The Linux x86_64 build of the same version is two-byte, exports the …W entry points and behaves correctly under unixODBC 2.3.12 — the abort is the Apple Silicon build's alone. Two more things that build does: LogEnabled=true with a real LogPath makes SQLAllocHandle(ENV) fail with IM004, an uncaught spdlog::rotating_file_sink exception inside the logger's init; and the pkg ships arrow-odbc.ini.orig but no arrow-odbc.ini.

Related: Vendor macOS drivers are built for iODBC's four-byte SQLWCHAR

Windows: a non-BMP character loses its high bits

The Windows build (LATEST-win64, 00.09.0007) returns a character outside the BMP through SQL_C_WCHAR as its low 16 bits — U+1F680 reads back as U+F680 — and through SQL_C_CHAR as the ANSI code page's ?, on a literal and on stored data, through pyodbc and the bridge identically. Its SQL_C_BINARY conversion of a text column hands the server's UTF-8 through byte-exact, which is the way out: reading text columns as binary passes the astral check for all three entries and is faster than the wide read. On Linux the wide path throws on anything outside the BMP instead — HY000 wstring_convert::from_bytes — while the narrow path is correct UTF-8.

Related: Five Windows-only ODBC failures are one thing wearing different clothes

Upstream

The Apple Silicon width, the IM004 logger failure, the missing arrow-odbc.ini and the docs contradicting themselves on Apple Silicon support were reported on 2026-08-25 as dremio/warpdrive#16, open. The driver-manager half of that abort is lurcher/unixODBC#239. The SQLGetFunctions claims, the autocommit refusal, the SQLColumns crash and its root cause, and the Windows truncation are recorded with their reproductions but not yet filed.

Where this comes from: the adbcBridge compatibility matrix runs one workload through every database's ODBC driver on Linux, macOS and Windows and records each failure with its first error; the row for this database is at https://adbcbridge.org/matrix/#flightsql, and the finding is on file with its reproduction in docs/UPSTREAM.md of the repository.