ODBC backend — verified live targets
The ODBC Plus backend (odbc://) is data-source agnostic: it reaches any
engine through its ODBC driver using only standard catalog calls
(SQLPrimaryKeys / SQLStatistics / SQLColumns) and portable SQL. No
per-dialect code lives in the backend.
The same ABI test cases (--test-case=*odbc*) run against any target by
pointing OPENADS_TEST_ODBC_CONNSTR at it. Two reproducible harnesses ship:
| Target | Harness | Notes |
|---|---|---|
Microsoft Access (.accdb) |
tools/scripts/run_odbc_tests.ps1 |
Zero-server; ADOX fixture, available out of the box on Windows. |
| SQL Server / PostgreSQL / MariaDB / Firebird | tools/scripts/run_odbc_tests_live.ps1 -ConnStr '...' |
Connection-string driven; seeds the clientes fixture over ODBC. |
Verified
- Microsoft Access — 5 cases / 83 assertions (CI fixture).
- SQL Server 2022 — 5 cases / 83 assertions, via the ODBC Driver 18 for
SQL Server. The unmodified backend (same binary that passes against
Access) navigates a
dbo.clientestable by primary key with no dialect-specific changes:SQLPrimaryKeysis honoured, the identifier quote character is discovered viaSQLGetInfo, and numeric literals are emitted type-aware.
Both read navigation (GO TOP / SKIP / SEEK) and navigational write
(AdsAppendRecord → AdsSetString/AdsSetDouble → AdsWriteRecord,
plus AdsDeleteRecord) are exercised against the same fixture on both
drivers. Write stages field values and flushes one INSERT (append) or
UPDATE (positioned edit) per record; AdsDeleteRecord issues a DELETE
by primary key. v1 expects the caller to supply the primary key on append
(no IDENTITY round-trip yet) and emits SQL literals (parameter binding is a
later hardening slice).
When OPENADS_TEST_ODBC_CONNSTR is unset, the live cases skip (the backend
is still exercised by the URI-parsing unit tests), so the suite stays green
on machines without a configured data source.
Driver compatibility matrix (verified 2026-06-23)
Suite binary: build/odbc-verify/tests/openads_unit_tests.exe (--test-case=*odbc*)
Harness: tools/scripts/run_odbc_tests.ps1 (Access) · run_odbc_tests_live.ps1 -ConnStr ... (others)
Total test cases in filter: 10 (4 unit-only always run; 6 live, skip when OPENADS_TEST_ODBC_CONNSTR unset)
| Driver | PK discovery | Quote char | Read/nav | Seek | Write | NULL/empty | Composite+date+decimal |
|---|---|---|---|---|---|---|---|
| Microsoft Access Driver (*.mdb, *.accdb) | SQLStatistics | ` |
✅ | ✅ | ✅ | ⚠️ | ⚠️ |
| ODBC Driver 18 for SQL Server | SQLPrimaryKeys | " |
✅ | ✅ | ✅ | ✅ | ✅ |
| Firebird ODBC Driver | SQLPrimaryKeys | " |
✅ | ✅ | ✅ | ✅ | ✅ |
| PostgreSQL Unicode | — | — | — | — | — | — | — |
| MariaDB ODBC | — | — | — | — | — | — | — |
Legend: ✅ pass · ⚠️ pass-with-note (see below) · ❌ fail · — not verified (driver absent or not tested)
Assertion counts per run:
| Driver | Total assertions | Of which live | Pedidos seeded |
|---|---|---|---|
| Microsoft Access | 134 / 134 | 114 | No (ADOX composite-PK skip) |
| SQL Server (LocalDB DEVAI, v16) | 145 / 145 | 125 | Yes |
| Firebird 4.0 (portable embedded+server) | 145 / 145 | 125 | Yes |
Notes on ⚠️ cells:
-
Access — NULL/empty (⚠️): The backend correctly binds an empty numeric value as SQL
NULLviaSQLBindParameterwithSQL_NULL_DATA. Access/Jet coerces empty strings toNULLonDOUBLEcolumns regardless of how the driver submits them, so the test passes but does not distinguish whether the fix (bound-parameterNULLvs literalNULL) is exercised — the column type coercion masks both paths. SQL Server, which enforces strict typing, proves the binding fix conclusively. -
Access — Composite+date+decimal (⚠️): The ADOX
Key.Appendcall for the composite-PKpedidosfixture fails with"item not found in collection"on the installed ACE 16 version. The harness (run_odbc_tests.ps1) catches this and warns; the test binary opens the table, finds it absent, and logs"pedidos fixture absent; skipping". The test case is counted as passed (early-return pattern, no assertions executed). The composite-PK code path in the backend is exercised by SQL Server and Firebird. -
Access — PK discovery via SQLStatistics: The Access/Jet ODBC driver returns an empty result set for
SQLPrimaryKeys(not an error, just no rows). The backend falls through toSQLStatisticsand picks up thePRIMARY KEYunique index created byCONSTRAINT pk PRIMARY KEYin the DDL. Navigation is fully correct; only the discovery route differs.
Absent drivers:
- PostgreSQL Unicode — driver not installed on this machine; system-level installation requires owner authorisation. Record: not verified (driver absent).
- MariaDB ODBC — driver not installed on this machine; system-level installation requires owner authorisation. Record: not verified (driver absent).