Notes · 2026-09-03

Which older engine releases pass the matrix entry unchanged

A sweep of older SQL Server, PostgreSQL, MariaDB and Firebird releases through the same driver and the same unmodified matrix entry, with only the port changed.

A compatibility matrix is usually written against whatever the vendor ships today, which leaves a question it never answers: does any of this hold on the release you are actually running? A sweep took a set of older releases of engines already in the matrix and ran each one through the stock entry with only the port changed — same driver where the platform allows it, same DDL, same workload, same assertions, nothing tuned.

The rule for what gets published is deliberately narrow: a release is listed only when the entry passed as it is. No adjusted tolerances, no extra quirk flags, no "passes if you skip the timestamp check". A release that needed any of that is not in the table. These rows also add no database to the compatibility count — they are the same engine, re-run.

What passed

SQL Server 2017 (14.0.3540) and 2019 (15.0.4480), through msodbcsql 18.6 on Linux. Both show the same NVARCHAR(MAX) chunked-read and SQL_GD_BLOCK-only behaviour as the 2022 row above them, which is the interesting part: the driver's handling of a wide unbounded column is a property of msodbcsql, not of the server generation behind it. 2017 reads at 2.27M rows/s and writes at 101k; 2019 at 2.43M and 106k. Neither was run on macOS.

PostgreSQL 9.6.24, 10.21 and 12.22, through psqlodbc 16 on Linux and psqlodbc 18 on macOS, all six cells PASS. The unnest array-ingest fast path — the bulk-write shape the entry uses against PostgreSQL — applies unchanged on all three. Linux fetch runs 1.58M / 1.70M / 2.13M rows/s and ingest 511k / 535k / 546k; macOS fetch 993k / 1.00M / 1.17M and ingest 555k / 423k / 640k. The oldest of the three takes the same write path as a current one.

MariaDB 10.6.28, entry unchanged, PASS on both platforms — MariaDB Connector/ODBC 3.1 on Linux, 3.2.9 on macOS. Linux fetch 2.80M rows/s, ingest 104k. The macOS fetch figure, 57k against 237k ingest, is not the server: every MySQL-wire database read through MariaDB Connector/ODBC 3.2.9 on macOS arm64 lands in the same 39–47k band, in five languages and in pyodbc alike, which puts the ceiling in the connector's fetch path on that platform.

Firebird 3.0.14, through Firebird ODBC 3.5.0-rc1, PASS on Linux; the macOS cell is "driver unavailable", exactly as the Firebird 5 row is, because there is no macOS build of that driver. Every Firebird 5.0 quirk in the entry holds identically on 3.0 — the parameter-array stride defect, the NULL-then-SQL_C_SBIGINT rebind, the discarded SQL_ATTR_ROWS_FETCHED_PTR — and the three driver reports filed for them each reproduce on driver 3.0.1 as well as on 3.5.0-rc1. Fetch 231k rows/s, ingest 24k.

Related: Three ways Firebird's ODBC driver loses your parameters without saying so

Why the driver, not the server, usually decides

The pattern across all seven rows is that what changes between releases is rarely what the matrix is testing. The entry's tolerances describe how a driver answers SQLGetTypeInfo, how it sizes a bound column, whether its parameter arrays step correctly — and a server upgrade moves none of that. Where a server generation does matter, it tends to matter in the SQL dialect rather than in the ODBC surface.

Oracle is the clean example of that, and the reason its bulk-write path is written the way it is. The bridge carries an INSERT ALL … SELECT 1 FROM dual fallback for Oracle releases with no multi-row VALUES clause, but it is consulted only after the standard multi-row form has actually been refused — it is a probe, not a version check. Oracle 23.26 takes the plain VALUES (…),(…) form, so the verified row never reaches that fallback at all. The code path that exists for older Oracle is therefore live but untaken on the release in the table, which is a different thing from a release having been tested.

That is the boundary this table respects. A version listed here was run; a version not listed here was not published, and the absence is not a claim in either direction.

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/#mssql, and the finding is on file with its reproduction in docs/UPSTREAM.md of the repository.