What the Arrow Flight SQL ODBC driver claims, and what it does
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.