Source branch: v5-pr (PR #283 — RFC only, DO NOT MERGE)
Target branch: master (official)
Reference: Docs/FIREBIRD_ODBC_MASTER_PLAN.original.md (v5-pr branch)
Last updated: April 6, 2026
Legend:
| Status |
Meaning |
| ✅ RESOLVED |
Fix implemented and tested in master |
| 🔧 IN PROGRESS |
Partially implemented or PR under review |
| ❌ OPEN |
Not yet addressed |
| ⏯️ DEFERRED |
delayed or put on hold until another task is finished |
Already Merged to Master
These PRs have been completed and form the foundation for all subsequent work.
| # |
Description |
PR |
Status |
| F-1 |
Google Test suite — 375 tests (230 pass, 145 skip), regression testing baseline |
#276 |
✅ RESOLVED |
| F-2 |
CMake build system — Replaced 14 obsolete build configs, vendored headers fetched at build time, cross-platform (Windows + Linux + ARM64) |
#281 |
✅ RESOLVED |
| F-3 |
GitHub Actions CI — Build-and-test workflow (Windows + Linux), Firebird 5.0.2 via PSFirebird, 3 charset configurations, Invoke-Build script |
#282 |
✅ RESOLVED |
| F-4 |
Array binding fix — sizeof(SQLINTEGER) → sizeof(SQLLEN) indicator stride in OdbcStatement.cpp (fixes segfault on Linux) |
#279 |
✅ RESOLVED |
| F-5 |
MSI installer, semantic versioning, GitHub Releases — WiX v4 MSI replaces InnoSetup, release.yml workflow, version from git tags, removes old VS solution |
#286 |
✅ RESOLVED |
In Progress
| # |
Description |
PR |
Status |
| F-6 |
Add ASAN and Valgrind integration for CI test suite — Integrate AddressSanitizer (ASAN) and Valgrind into the CI test pipeline so that memory bugs (buffer overflows, use-after-free, leaks, etc.) are caught automatically on every PR. |
#289 |
🔧 IN PROGRESS |
Migration Tasks
Tasks are organized by priority and dependency order. Each task maps to one or more phases from the v5-pr master plan and should result in a single, reviewable PR.
Tier 1: Critical — Crash Fixes & Safety (Phase 0 + Phase 2)
These fixes prevent crashes and data corruption. They should be ported first because they affect every ODBC application using the driver.
| # |
Task |
v5-pr Phase |
v5-pr Issues |
PR |
Status |
| T1-1 |
Fix GUARD_ macros* — Add NULL_CHECK macro to all GUARD_HSTMT/GUARD_HDBC/GUARD_HENV/GUARD_HDESC macros in Main.h so null handles return SQL_INVALID_HANDLE instead of crashing |
Phase 0 (0.1–0.2) |
C-1, C-2, C-3 |
|
❌ OPEN |
| T1-2 |
Fix postError buffer overflow — Replace sprintf with snprintf in OdbcConnection.cpp, increase buffer to 512 bytes |
Phase 0 (0.3) |
C-6 |
|
❌ OPEN |
| T1-3 |
Replace unsafe exception downcasts — Replace 64 (SQLException&)ex C-style casts across 12 files with direct catch (SQLException& exception) blocks |
Phase 0 (0.4) |
C-7 |
|
❌ OPEN |
| T1-4 |
Harden entry points — Add try/catch to 9 inner methods missing exception handling (sqlPutData, sqlSetPos, sqlFetch, sqlGetData, sqlSetDescField, sqlGetConnectAttr, sqlGetInfo, sqlSetConnectAttr, sqlGetFunctions), add clearErrors() where missing |
Phase 2 (2.1–2.2) |
C-3 |
|
❌ OPEN |
| T1-5 |
Remove DRIVER_LOCKED_LEVEL_NONE — Thread safety always enabled; remove no-locking fallback from Main.h, add compile-time #error guard |
Phase 2 (2.4) |
L-5 |
|
❌ OPEN |
Impact: After T1-1 through T1-5, the driver never crashes on invalid input. Returns SQL_INVALID_HANDLE or SQL_ERROR instead. Unlocks 65 test_null_handles.cpp tests currently skipped.
Tier 2: High — ODBC Spec Compliance (Phase 1)
These fix incorrect behavior that affects every ODBC application. Many test SKIPs in the current test suite depend on these fixes.
| # |
Task |
v5-pr Phase |
v5-pr Issues |
PR |
Status |
| T2-1 |
Comprehensive ISC→SQLSTATE mapping — Add OdbcSqlState.h with 121 SQLSTATE entries, 100+ ISC mappings, 130+ SQL code mappings; dual ODBC 2.x/3.x SQLSTATE support via getVersionedSqlState() |
Phase 1 (1.1–1.2) |
H-2, H-3, H-15 |
|
❌ OPEN |
| T2-2 |
Fix SQLCloseCursor cursor state check — Return SQLSTATE 24000 when no cursor is open instead of SQL_SUCCESS |
Phase 1 (1.10) |
H-1 |
|
❌ OPEN |
| T2-3 |
Fix SQL_ATTR_ODBC_VERSION handling — SQLGetEnvAttr now returns the value actually set by the application, not hardcoded SQL_OV_ODBC3 |
Phase 1 (1.5) |
H-4 |
|
❌ OPEN |
| T2-4 |
Fix SQLSetConnectAttr default path — Return HY092/HYC00 for unsupported attributes instead of silent success |
Phase 1 (1.6) |
H-5 |
|
❌ OPEN |
| T2-5 |
Fix SQLGetConnectAttr StringLengthPtr — Pass through caller's StringLengthPtr instead of overwriting with local pointer |
Phase 1 (1.7) |
H-6 |
|
❌ OPEN |
| T2-6 |
Fix SQLGetInfo numeric/NULL handling — Fix NULL pointer checks, remove incorrect BufferLength heuristic for infoLong |
Phase 1 (1.8, 1.13) |
H-7, H-13 |
|
❌ OPEN |
| T2-7 |
Fix SQL_SCHEMA_USAGE — Use schema check instead of supportsCatalogsInIndexDefinitions() |
Phase 1 (1.9) |
H-8 |
|
❌ OPEN |
| T2-8 |
Fix diagnostics — SQLGetDiagRec returns SQL_NO_DATA (3.x) not SQL_NO_DATA_FOUND (2.x); SQLGetDiagField null-checks StringLengthPtr |
Phase 1 (1.3–1.4) |
H-9, H-10 |
|
❌ OPEN |
| T2-9 |
Fix SQLSetStmtAttr cursor-state validations — Enforce 24000/HY011 when cursor is open |
Phase 1 (1.11) |
H-11 |
|
❌ OPEN |
| T2-10 |
Fix Unicode W-API BufferLength validation — Return HY090 when BufferLength is odd |
Phase 1 (1.12) |
H-12 |
|
❌ OPEN |
| T2-11 |
Fix SQLDescribeColW return types — Map SQL_CHAR→SQL_WCHAR, SQL_VARCHAR→SQL_WVARCHAR, SQL_LONGVARCHAR→SQL_WLONGVARCHAR |
Phase 1 (1.13) |
H-14 |
|
❌ OPEN |
Note: Tasks T2-1 through T2-11 could be grouped into 2–3 PRs (e.g., error mapping + diagnostics in one PR, getter/setter fixes in another) for manageable review sizes.
Tier 3: High — Feature Completeness (Phase 4)
Features that enable previously-broken or missing functionality. Prioritized by impact on existing test suite.
| # |
Task |
v5-pr Phase |
v5-pr Issues |
PR |
Status |
| T3-1 |
Savepoint/rollback isolation — Implement SAVEPOINT/RELEASE SAVEPOINT/ROLLBACK TO SAVEPOINT in IscConnection; wrap IscStatement::execute() and executeProcedure() with savepoint isolation when autoCommit=OFF |
Phase 2 (2.3) |
M-1 |
|
❌ OPEN |
| T3-2 |
Server version feature-flagging — Add getServerMajorVersion()/getServerMinorVersion() to Connection interface; implement in IscConnection via Attachment version parsing |
Phase 4 (4.2) |
M-3 |
|
❌ OPEN |
| T3-3 |
Complete SQLGetTypeInfo for Firebird types — Add INT128, DECFLOAT, TIME WITH TIME ZONE, TIMESTAMP WITH TIME ZONE to TypesResultSet; version-gate to FB4+; add BLR handler safety net in IscSqlType::buildType |
Phase 4 (4.4) |
M-8 |
|
❌ OPEN |
| T3-4 |
ConnSettings connection string parameter — Execute SQL statements via PreparedStatement after connection open; semicolons split multiple statements |
Phase 4 (4.6) |
M-5 |
|
❌ OPEN |
| T3-5 |
Full batch parameter execution — Fix column-wise binding (sizeColumnExtendedFetch for fixed-size types), row-wise binding, SQL_ATTR_PARAM_OPERATION_PTR skip rows, per-row error handling, execute-time PARAMSET_SIZE routing |
Phase 4 (4.3) |
M-7 |
|
❌ OPEN |
| T3-6 |
Scrollable cursor verification — Verify static scrollable cursors work with all fetch orientations (FIRST, LAST, PRIOR, ABSOLUTE, RELATIVE, NEXT) |
Phase 4 (4.7) |
M-2 |
|
❌ OPEN |
Impact: After Tier 3, most of the 145 currently-skipped tests should become active and passing.
Tier 4: Medium — ODBC Crusher Fixes (Phase 7)
Issues discovered by ODBC Crusher v0.3.1 analysis. Targeted fixes with clear reproduction cases.
| # |
Task |
v5-pr Phase |
v5-pr Issues |
PR |
Status |
| T4-1 |
Fix SQLCopyDesc crash — Add null guard for sour.records and early return when sour.headCount == 0 in OdbcDesc::operator=; also fix SQLSetDescField(SQL_DESC_COUNT) to allocate records array |
Phase 7 (7.1, 7.6) |
OC-1 |
|
❌ OPEN |
| T4-2 |
Populate SQL_DIAG_ROW_COUNT — Add setDiagRowCount() setter; populate in executeStatement(), executeStatementParamArray(), executeProcedure(); fix sqlGetDiagField to write as SQLLEN* |
Phase 7 (7.2) |
OC-2 |
|
❌ OPEN |
| T4-3 |
Implement SQL_ATTR_CONNECTION_TIMEOUT — Add to both sqlGetConnectAttr and sqlSetConnectAttr; also fix SQL_LOGIN_TIMEOUT getter |
Phase 7 (7.3) |
OC-3 |
|
❌ OPEN |
| T4-4 |
Fix SQL_ATTR_ASYNC_ENABLE — Reject SQL_ASYNC_ENABLE_ON with HYC00 at both connection and statement level; getters return SQL_ASYNC_ENABLE_OFF |
Phase 7 (7.4) |
OC-4 |
|
❌ OPEN |
| T4-5 |
Fix returnStringInfo() truncation — Preserve full string length on truncation instead of overwriting with buffer size; add NULL guard to SQLINTEGER* overload |
Phase 7 (7.5) |
OC-5 |
|
❌ OPEN |
Tier 5: Medium — ODBC 3.8 Compliance & SQL_GUID (Phase 8)
Brings the driver up to ODBC 3.8 specification and adds SQL_GUID type support.
| # |
Task |
v5-pr Phase |
v5-pr Issues |
PR |
Status |
| T5-1 |
Accept SQL_OV_ODBC3_80 — Validate 380 as valid SQL_ATTR_ODBC_VERSION value in OdbcEnv::sqlSetEnvAttr |
Phase 8 (8.1) |
— |
|
❌ OPEN |
| T5-2 |
Update SQL_DRIVER_ODBC_VER — Change from "03.51" to "03.80" |
Phase 8 (8.2) |
— |
|
❌ OPEN |
| T5-3 |
SQL_ATTR_RESET_CONNECTION — Reset autocommit, access mode, transaction isolation, connection timeout to defaults |
Phase 8 (8.3) |
— |
|
❌ OPEN |
| T5-4 |
ODBC 3.8 info types — Add SQL_GD_OUTPUT_PARAMS to SQL_GETDATA_EXTENSIONS; add SQL_ASYNC_DBC_FUNCTIONS returning NOT_CAPABLE |
Phase 8 (8.4–8.5) |
— |
|
❌ OPEN |
| T5-5 |
SQL_GUID type mapping — Detect CHAR(16) CHARACTER SET OCTETS (FB3) and BINARY(16) (FB4+) as SQL_GUID; add GUID conversion methods (GUID↔string, GUID↔binary) |
Phase 8 (8.7–8.8) |
— |
|
❌ OPEN |
| T5-6 |
BINARY/VARBINARY types — Add to TypesResultSet for Firebird 4+; fix ODBC 3.8 version check |
Phase 8 (8.9–8.10) |
— |
|
❌ OPEN |
Tier 6: Medium — Code Quality & Maintainability (Phase 5)
Modernize internal code to reduce maintenance burden. Low risk, incremental changes.
| # |
Task |
v5-pr Phase |
v5-pr Issues |
PR |
Status |
| T6-1 |
Smart pointers for OdbcError — Convert OdbcError chain from raw OdbcError* linked list to std::vector<std::unique_ptr<OdbcError>> |
Phase 5 (5.1) |
L-2 |
|
❌ OPEN |
| T6-2 |
Class visibility — Add private/protected to OdbcObject, OdbcError, OdbcEnv; add getOdbcIniFileName() accessor |
Phase 5 (5.2) |
L-1 |
|
❌ OPEN |
| T6-3 |
Replace linked lists — Replace LinkedList with std::vector<T*> in IscConnection::statements, IscStatement::resultSets, IscResultSet::blobs |
Phase 5 (5.5) |
L-6 |
|
❌ OPEN |
| T6-4 |
Fix returnStringInfo duplication — SQLINTEGER* overload delegates to SQLSMALLINT* overload |
Phase 5 (5.6) |
L-7 |
|
❌ OPEN |
| T6-5 |
Fix EnvShare static init order — Replace global EnvShare environmentShare with Meyer's Singleton (getEnvironmentShareInstance()) |
Phase 5 (5.7) |
L-8 |
|
❌ OPEN |
| T6-6 |
Fix snprintf macro conflict — Guard #define snprintf _snprintf behind _MSC_VER < 1900 |
Phase 5 (5.8) |
L-9 |
|
❌ OPEN |
| T6-7 |
Add .clang-format — Configuration matching existing codebase conventions; apply to new/modified code only |
Phase 5 (5.4) |
L-4 |
|
❌ OPEN |
Tier 7: Medium — SQLGetTypeInfo, Query Timeout, Connection Pool (Phase 11)
Functional improvements that affect ORM frameworks and connection pool managers.
| # |
Task |
v5-pr Phase |
v5-pr Issues |
PR |
Status |
| T7-1 |
Fix SQLGetTypeInfo thread-safety — Copy static alphaV[] array to per-instance std::vector before mutation |
Phase 11 (11.1.1) |
— |
|
❌ OPEN |
| T7-2 |
Fix SQLGetTypeInfo spec compliance — Sort result set by DATA_TYPE ascending; return all matching rows (not just first); remove duplicate BINARY/VARBINARY on FB4+; fix SQL_GUID metadata |
Phase 11 (11.1.2–11.1.5) |
— |
|
❌ OPEN |
| T7-3 |
Fix SQL_ASYNC_MODE misreport — Change from SQL_AM_STATEMENT to SQL_AM_NONE |
Phase 11 (11.1.6) |
— |
|
❌ OPEN |
| T7-4 |
Implement SQL_ATTR_QUERY_TIMEOUT — Timer-based cancellation using IAttachment::cancelOperation(fb_cancel_raise); maps isc_cancelled to SQLSTATE HYT00 |
Phase 11 (11.2.1–11.2.3) |
— |
|
❌ OPEN |
| T7-5 |
Implement SQLCancel — Call IAttachment::cancelOperation(fb_cancel_raise) to actually cancel in-flight statements |
Phase 11 (11.2.4) |
— |
|
❌ OPEN |
| T7-6 |
Improve SQL_ATTR_RESET_CONNECTION — Roll back pending transactions, close open cursors/statements, reset child statement timeouts |
Phase 11 (11.3.1–11.3.3) |
— |
|
❌ OPEN |
Tier 8: Medium — Performance (Phase 10)
Performance improvements. Should be ported after correctness/compliance fixes are stable.
| # |
Task |
v5-pr Phase |
v5-pr Issues |
PR |
Status |
| T8-1 |
Replace Win32 Mutex with SRWLOCK — User-mode-only, ~20ns uncontended; Linux pthread_mutex_t unchanged |
Phase 10 (10.1.1) |
— |
|
❌ OPEN |
| T8-2 |
Eliminate global env-level lock for statement ops — Statement/descriptor ops use per-connection lock; global lock only for env ops |
Phase 10 (10.1.2) |
— |
|
❌ OPEN |
| T8-3 |
Per-row allocation elimination — Hoist conversions array to result-set lifetime; pool BLOB objects; reuse Value::getString() buffers; [[likely]] early-return in clearErrors() |
Phase 10 (10.2.1–10.2.4) |
— |
|
❌ OPEN |
| T8-4 |
64-row prefetch buffer — IscResultSet::nextFetch() fills a 64-row buffer in batches, then serves rows from the buffer |
Phase 10 (10.5.1) |
— |
|
❌ OPEN |
| T8-5 |
Stack-buffer Unicode fast path — 512-byte stack buffer in ConvertingString; single-pass W→A conversion on Windows |
Phase 10 (10.6.1–10.6.2) |
— |
|
❌ OPEN |
| T8-6 |
Enable LTO for Release builds — check_ipo_supported() + CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE; ODBC_FORCEINLINE on 6 hot functions |
Phase 10 (10.7.1, 10.7.3) |
— |
|
❌ OPEN |
| T8-7 |
std::to_chars for float→string — Replace repeated fmod() calls in convFloatToString/convDoubleToString |
Phase 10 (10.4.6) |
— |
|
❌ OPEN |
| T8-8 |
Cache-aligned Sqlda buffer — alignas(64) via AlignedAllocator; /favor:AMD64 and -march=native for release builds |
Phase 10 (10.8.2, 10.7.5) |
— |
|
❌ OPEN |
| T8-9 |
Micro-benchmark harness — tests/bench_fetch.cpp using Google Benchmark; baseline perf numbers documented |
Phase 10 (10.0.1–10.0.4) |
— |
|
❌ OPEN |
Tier 9: Medium — Unicode / String Conversion (Phase 12)
Fixes data corruption on Linux/macOS and eliminates redundant encoding conversions.
| # |
Task |
v5-pr Phase |
v5-pr Issues |
PR |
Status |
| T9-1 |
Fix wchar_t vs SQLWCHAR confusion — Introduce ODBC_SQLWCHAR typedef (always 16-bit); all *ToStringW functions use SQLWCHAR* directly; fixes silent data corruption on Linux where wchar_t is 4 bytes |
Phase 12 (12.1.4) |
C-4 |
|
❌ OPEN |
| T9-2 |
Fix locale-dependent mbstowcs usage — Replace mbstowcs() with Utf8ToUtf16() in convVarStringSystemToStringW; use trivial ASCII widening in integer→StringW formatters |
Phase 12 (12.1.2–12.1.3) |
C-5 |
|
❌ OPEN |
| T9-3 |
Unify UTF-8 codecs — Single Utf16Convert.h/cpp implementation; update MultibyteConvert codecs to use ODBC_SQLWCHAR*; Linux CHARSET=NONE uses UTF-8 codec |
Phase 12 (12.1.1, 12.1.5–12.1.6) |
— |
|
❌ OPEN |
| T9-4 |
Default CHARSET=UTF8 — When CHARSET not specified in connection string, default to UTF8 instead of NONE |
Phase 12 (12.4.1–12.4.2) |
— |
|
❌ OPEN |
| T9-5 |
OdbcString UTF-16 metadata cache — Introduce OdbcString class; cache column/table names as UTF-16 in DescRecord (11 fields); direct UTF-16 output for SQLDescribeColW, SQLColAttributeW, SQLGetDescFieldW, SQLGetDescRecW, SQLGetDiagRecW, SQLGetDiagFieldW |
Phase 12 (12.2.1–12.2.8) |
— |
|
❌ OPEN |
| T9-6 |
Merge conversion variants — Remove convVarStringSystemToString* variants; unify convStringToStringW/convVarStringToStringW via shared helper; document conversion matrix |
Phase 12 (12.3.1–12.3.4) |
— |
|
❌ OPEN |
Tier 10: Medium — Firebird OO API Alignment (Phase 9)
Leverage the modern Firebird OO API; biggest win is IBatch for array execution.
| # |
Task |
v5-pr Phase |
v5-pr Issues |
PR |
Status |
| T10-1 |
Implement IBatch for array parameter execution — Single server roundtrip for N rows on FB4+; falls back to row-by-row for FB3; inline BLOB support via BLOB_ID_ENGINE policy |
Phase 9 (9.1–9.2) |
— |
|
❌ OPEN |
| T10-2 |
Remove ~35 dead ISC function pointers — Keep only array functions + bridge; remove _dsql_*, _attach_database, etc. |
Phase 9 (9.3) |
— |
|
❌ OPEN |
| T10-3 |
Migrate IscUserEvents to OO API — Replace isc_que_events() with IAttachment::queEvents() via FbEventCallback class |
Phase 9 (9.4) |
— |
|
❌ OPEN |
| T10-4 |
Migrate TPB construction to IXpbBuilder — Replace raw byte-stuffing in buildParamTransaction() |
Phase 9 (9.5) |
— |
|
❌ OPEN |
| T10-5 |
Replace manual date/time math — Shared FbDateConvert.h helpers replace ~150 lines of duplicated Julian-day arithmetic; remove dead OdbcDateTime class |
Phase 9 (9.6) |
— |
|
❌ OPEN |
| T10-6 |
Unify error handling — Add getIscStatusTextFromVector() using IUtil::formatStatus(); remove legacy fb_interpret path |
Phase 9 (9.7) |
— |
|
❌ OPEN |
| T10-7 |
Optimize Sqlda re-execute — Skip metadata rebuild when unchanged; replace isc_vax_integer with inline helper; mark concrete IscDbc classes final |
Phase 9 (9.8–9.11) |
— |
|
❌ OPEN |
Tier 11: Low — Dead Code Removal (Phase 13)
Cleanup after features are ported. Best done as the last code-only change before any architectural migration.
| # |
Task |
v5-pr Phase |
v5-pr Issues |
PR |
Status |
| T11-1 |
Delete dead source files — LinkedList.*, Lock.*, ServiceManager.*, SupportFunctions.*, OdbcDateTime.*, Engine.h, WriteBuildNo.h, IscDbc.def, IscDbc.exp, OdbcJdbcMinGw.def, OdbcJdbc.dll.manifest, makefile.in (×2) |
Phase 13 (13.1) |
— |
|
❌ OPEN |
| T11-2 |
Add missing headers to CMakeLists.txt — OdbcSqlState.h, OdbcUserEvents.h, FbDateConvert.h and any new headers from previous tiers |
Phase 13 (13.2) |
— |
|
❌ OPEN |
| T11-3 |
Build system simplification — Remove redundant if/else in .def file assignment; remove BUILD_SETUP option |
Phase 13 (13.3) |
— |
|
❌ OPEN |
| T11-4 |
Test suite consolidation — Remove duplicate test files (test_catalog.cpp, test_batch_params.cpp, test_connection.cpp, test_cursor.cpp, test_bind_cycle.cpp); redistribute phase-named tests to topic-named files |
Phase 13 (13.4) |
— |
|
❌ OPEN |
Tier 12: Low — Source Reorganization
Move source files into src/ subdirectory. This is a large, disruptive change that should be done as a single PR when the codebase is stable.
| # |
Task |
v5-pr Phase |
v5-pr Issues |
PR |
Status |
| T12-1 |
Move all source to src/ — Move .cpp/.h from root to src/, move IscDbc/ to src/IscDbc/, move .def/.rc/.manifest to src/; update CMakeLists.txt |
Build Infra |
— |
|
❌ OPEN |
| T12-2 |
Remove i18n code — Delete Res/ directory (5 locale resource files); simplify _TR() macro to always return English; remove initCodePageTranslate call from DllMain |
Build Infra |
— |
|
❌ OPEN |
Tier 13: Future — fb-cpp Adoption (Phase 14)
The largest architectural change. Requires vcpkg infrastructure and the fb-cpp library. Should be done incrementally, after all correctness/performance work is stable.
| # |
Task |
v5-pr Phase |
v5-pr Issues |
PR |
Status |
| T13-1 |
vcpkg infrastructure — Add vcpkg.json manifest, vcpkg-configuration.json with custom Firebird registry; update CI for vcpkg; add vcpkg as git submodule |
Phase 14 (14.1) + Phase 15 |
— |
|
❌ OPEN |
| T13-2 |
Replace CFbDll with FbClient singleton — Use fbcpp::FbApiHandle for fbclient loading; replace Attachment class with fbcpp::Attachment |
Phase 14 (14.2) |
— |
|
❌ OPEN |
| T13-3 |
Migrate transactions — Replace InfoTransaction with fbcpp::Transaction; map transaction isolation levels; migrate auto-commit and savepoints |
Phase 14 (14.3) |
— |
|
❌ OPEN |
| T13-4 |
Migrate statements & result sets — Replace IscStatement handle management with fbcpp::Statement; remap Sqlda buffers to fbcpp message buffers; migrate batch execution to fbcpp::Batch |
Phase 14 (14.4) |
— |
|
❌ OPEN |
| T13-5 |
Migrate blobs & events — Replace IscBlob internals with fbcpp::Blob; replace IscUserEvents internals with fbcpp::EventListener |
Phase 14 (14.5–14.6) |
— |
|
❌ OPEN |
| T13-6 |
Error bridging & utilities — SQLError::fromDatabaseException(); consolidate date/time types into FbDateConvert.h PODs; replace JString with std::string across all headers |
Phase 14 (14.7) |
— |
|
❌ OPEN |
| T13-7 |
Final cleanup — Delete dead code from migration; rename src/IscDbc/ to src/core/; decompose Sqlda into data struct |
Phase 14 (14.8) |
— |
|
❌ OPEN |
Note: fb-cpp v0.0.4 is required for full Statement/Batch/RowSet support. The vcpkg custom registry provides this version.
Items Explicitly Excluded (WONTFIX)
These items were evaluated in v5-pr and deliberately excluded:
| Item |
v5-pr Issue |
Reason |
ODBC escape sequence parsing ({fn}, {d}, {ts}, {oj}) |
M-4 |
Acknowledged mistake from v4 — Must be restored, not removed. This is tracked separately and is NOT part of this migration plan. See PR #283 notes. |
| ATL/DTC distributed transaction support |
M-6 |
Unnecessary complexity; not needed by Firebird users |
Split large files (OdbcConvert.cpp, OdbcStatement.cpp) |
L-3 |
Heavily macro-driven; splitting carries high regression risk for marginal benefit |
True async execution (SQL_ASYNC_ENABLE_ON) |
Phase 11.5 |
Firebird OO API is entirely synchronous; no non-blocking calls exist |
| Driver-aware connection pool SPI (7 functions) |
Phase 11.4 |
Large undertaking; deferred until basic reset is solid |
Known Gaps / Future Work
Items identified in v5-pr that are explicitly deferred or still open:
| Item |
v5-pr Reference |
Notes |
| Unit tests for IscDbc layer |
T-3 |
Only ODBC API-level integration tests exist |
| Data conversion unit tests for OdbcConvert |
T-4 |
~150 conversion methods, no unit tests |
| Firebird version matrix in CI (3.0, 4.0, 5.0) |
T-7 |
Currently hardcoded to 5.0.2 |
| Performance/stress tests |
T-8 |
Phase 10 benchmarks exist in v5-pr; not ported yet |
Descriptor tests (SQLGetDescRec, SQLSetDescRec, SQLCopyDesc) |
T-10 |
Some tests exist but depend on T4-1 |
| Multi-statement handle interleaving tests |
T-11 |
psqlodbc tests 100 simultaneous handles |
| ODBC escape sequences restoration |
PR #283 notes |
Removed in v4; acknowledged as a mistake; needs separate plan |
| Windows ODBC Administrator UI (OdbcJdbcSetup) |
PR #283 notes |
Removed in v4; acknowledged as a mistake; needs separate plan |
| WiX installer for ARM64/x86 |
— |
Currently x64-only; ARM64 could be added if needed |
Test Suite Status After Each Tier
| After Tier |
Expected Passing |
Expected Skipped |
Notes |
| Current (master) |
230 |
145 |
Baseline from PR #276 |
| Tier 1 (Crash fixes) |
~295 |
~80 |
+65 null-handle tests unlocked |
| Tier 2 (Spec compliance) |
~320 |
~55 |
Error/diagnostic/attribute tests pass |
| Tier 3 (Features) |
~350 |
~25 |
Savepoint, batch, scrollable, ConnSettings tests pass |
| Tier 4 (Crusher fixes) |
~360 |
~15 |
Descriptor/truncation/diag-row-count tests pass |
| Tier 5 (ODBC 3.8) |
~370 |
~5 |
ODBC 3.8, GUID, binary type tests pass |
| All tiers |
~375 |
0 |
Full test suite green |
Source branch:
v5-pr(PR #283 — RFC only, DO NOT MERGE)Target branch:
master(official)Reference:
Docs/FIREBIRD_ODBC_MASTER_PLAN.original.md(v5-pr branch)Last updated: April 6, 2026
Legend:
masterAlready Merged to Master
These PRs have been completed and form the foundation for all subsequent work.
sizeof(SQLINTEGER)→sizeof(SQLLEN)indicator stride in OdbcStatement.cpp (fixes segfault on Linux)release.ymlworkflow, version from git tags, removes old VS solutionIn Progress
Migration Tasks
Tasks are organized by priority and dependency order. Each task maps to one or more phases from the v5-pr master plan and should result in a single, reviewable PR.
Tier 1: Critical — Crash Fixes & Safety (Phase 0 + Phase 2)
These fixes prevent crashes and data corruption. They should be ported first because they affect every ODBC application using the driver.
NULL_CHECKmacro to allGUARD_HSTMT/GUARD_HDBC/GUARD_HENV/GUARD_HDESCmacros inMain.hso null handles returnSQL_INVALID_HANDLEinstead of crashingpostErrorbuffer overflow — ReplacesprintfwithsnprintfinOdbcConnection.cpp, increase buffer to 512 bytes(SQLException&)exC-style casts across 12 files with directcatch (SQLException& exception)blockssqlPutData,sqlSetPos,sqlFetch,sqlGetData,sqlSetDescField,sqlGetConnectAttr,sqlGetInfo,sqlSetConnectAttr,sqlGetFunctions), addclearErrors()where missingDRIVER_LOCKED_LEVEL_NONE— Thread safety always enabled; remove no-locking fallback fromMain.h, add compile-time#errorguardTier 2: High — ODBC Spec Compliance (Phase 1)
These fix incorrect behavior that affects every ODBC application. Many test SKIPs in the current test suite depend on these fixes.
OdbcSqlState.hwith 121 SQLSTATE entries, 100+ ISC mappings, 130+ SQL code mappings; dual ODBC 2.x/3.x SQLSTATE support viagetVersionedSqlState()SQLCloseCursorcursor state check — Return SQLSTATE 24000 when no cursor is open instead ofSQL_SUCCESSSQL_ATTR_ODBC_VERSIONhandling —SQLGetEnvAttrnow returns the value actually set by the application, not hardcodedSQL_OV_ODBC3SQLSetConnectAttrdefault path — ReturnHY092/HYC00for unsupported attributes instead of silent successSQLGetConnectAttrStringLengthPtr — Pass through caller'sStringLengthPtrinstead of overwriting with local pointerSQLGetInfonumeric/NULL handling — Fix NULL pointer checks, remove incorrectBufferLengthheuristic forinfoLongSQL_SCHEMA_USAGE— Use schema check instead ofsupportsCatalogsInIndexDefinitions()SQLGetDiagRecreturnsSQL_NO_DATA(3.x) notSQL_NO_DATA_FOUND(2.x);SQLGetDiagFieldnull-checksStringLengthPtrSQLSetStmtAttrcursor-state validations — Enforce 24000/HY011 when cursor is openBufferLengthvalidation — Return HY090 whenBufferLengthis oddSQLDescribeColWreturn types — MapSQL_CHAR→SQL_WCHAR,SQL_VARCHAR→SQL_WVARCHAR,SQL_LONGVARCHAR→SQL_WLONGVARCHARTier 3: High — Feature Completeness (Phase 4)
Features that enable previously-broken or missing functionality. Prioritized by impact on existing test suite.
SAVEPOINT/RELEASE SAVEPOINT/ROLLBACK TO SAVEPOINTinIscConnection; wrapIscStatement::execute()andexecuteProcedure()with savepoint isolation whenautoCommit=OFFgetServerMajorVersion()/getServerMinorVersion()toConnectioninterface; implement inIscConnectionvia Attachment version parsingSQLGetTypeInfofor Firebird types — Add INT128, DECFLOAT, TIME WITH TIME ZONE, TIMESTAMP WITH TIME ZONE toTypesResultSet; version-gate to FB4+; add BLR handler safety net inIscSqlType::buildTypeConnSettingsconnection string parameter — Execute SQL statements viaPreparedStatementafter connection open; semicolons split multiple statementssizeColumnExtendedFetchfor fixed-size types), row-wise binding,SQL_ATTR_PARAM_OPERATION_PTRskip rows, per-row error handling, execute-timePARAMSET_SIZEroutingTier 4: Medium — ODBC Crusher Fixes (Phase 7)
Issues discovered by ODBC Crusher v0.3.1 analysis. Targeted fixes with clear reproduction cases.
SQLCopyDesccrash — Add null guard forsour.recordsand early return whensour.headCount == 0inOdbcDesc::operator=; also fixSQLSetDescField(SQL_DESC_COUNT)to allocate records arraySQL_DIAG_ROW_COUNT— AddsetDiagRowCount()setter; populate inexecuteStatement(),executeStatementParamArray(),executeProcedure(); fixsqlGetDiagFieldto write asSQLLEN*SQL_ATTR_CONNECTION_TIMEOUT— Add to bothsqlGetConnectAttrandsqlSetConnectAttr; also fixSQL_LOGIN_TIMEOUTgetterSQL_ATTR_ASYNC_ENABLE— RejectSQL_ASYNC_ENABLE_ONwith HYC00 at both connection and statement level; getters returnSQL_ASYNC_ENABLE_OFFreturnStringInfo()truncation — Preserve full string length on truncation instead of overwriting with buffer size; add NULL guard toSQLINTEGER*overloadTier 5: Medium — ODBC 3.8 Compliance & SQL_GUID (Phase 8)
Brings the driver up to ODBC 3.8 specification and adds SQL_GUID type support.
SQL_OV_ODBC3_80— Validate 380 as validSQL_ATTR_ODBC_VERSIONvalue inOdbcEnv::sqlSetEnvAttrSQL_DRIVER_ODBC_VER— Change from"03.51"to"03.80"SQL_ATTR_RESET_CONNECTION— Reset autocommit, access mode, transaction isolation, connection timeout to defaultsSQL_GD_OUTPUT_PARAMStoSQL_GETDATA_EXTENSIONS; addSQL_ASYNC_DBC_FUNCTIONSreturningNOT_CAPABLECHAR(16) CHARACTER SET OCTETS(FB3) andBINARY(16)(FB4+) as SQL_GUID; add GUID conversion methods (GUID↔string, GUID↔binary)BINARY/VARBINARYtypes — Add toTypesResultSetfor Firebird 4+; fix ODBC 3.8 version checkTier 6: Medium — Code Quality & Maintainability (Phase 5)
Modernize internal code to reduce maintenance burden. Low risk, incremental changes.
OdbcError*linked list tostd::vector<std::unique_ptr<OdbcError>>private/protectedtoOdbcObject,OdbcError,OdbcEnv; addgetOdbcIniFileName()accessorLinkedListwithstd::vector<T*>inIscConnection::statements,IscStatement::resultSets,IscResultSet::blobsreturnStringInfoduplication —SQLINTEGER*overload delegates toSQLSMALLINT*overloadEnvSharestatic init order — Replace globalEnvShare environmentSharewith Meyer's Singleton (getEnvironmentShareInstance())snprintfmacro conflict — Guard#define snprintf _snprintfbehind_MSC_VER < 1900.clang-format— Configuration matching existing codebase conventions; apply to new/modified code onlyTier 7: Medium — SQLGetTypeInfo, Query Timeout, Connection Pool (Phase 11)
Functional improvements that affect ORM frameworks and connection pool managers.
SQLGetTypeInfothread-safety — Copy staticalphaV[]array to per-instancestd::vectorbefore mutationSQLGetTypeInfospec compliance — Sort result set byDATA_TYPEascending; return all matching rows (not just first); remove duplicate BINARY/VARBINARY on FB4+; fix SQL_GUID metadataSQL_ASYNC_MODEmisreport — Change fromSQL_AM_STATEMENTtoSQL_AM_NONESQL_ATTR_QUERY_TIMEOUT— Timer-based cancellation usingIAttachment::cancelOperation(fb_cancel_raise); mapsisc_cancelledto SQLSTATE HYT00SQLCancel— CallIAttachment::cancelOperation(fb_cancel_raise)to actually cancel in-flight statementsSQL_ATTR_RESET_CONNECTION— Roll back pending transactions, close open cursors/statements, reset child statement timeoutsTier 8: Medium — Performance (Phase 10)
Performance improvements. Should be ported after correctness/compliance fixes are stable.
MutexwithSRWLOCK— User-mode-only, ~20ns uncontended; Linuxpthread_mutex_tunchangedconversionsarray to result-set lifetime; pool BLOB objects; reuseValue::getString()buffers;[[likely]]early-return inclearErrors()IscResultSet::nextFetch()fills a 64-row buffer in batches, then serves rows from the bufferConvertingString; single-pass W→A conversion on Windowscheck_ipo_supported()+CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE;ODBC_FORCEINLINEon 6 hot functionsstd::to_charsfor float→string — Replace repeatedfmod()calls inconvFloatToString/convDoubleToStringalignas(64)viaAlignedAllocator;/favor:AMD64and-march=nativefor release buildstests/bench_fetch.cppusing Google Benchmark; baseline perf numbers documentedTier 9: Medium — Unicode / String Conversion (Phase 12)
Fixes data corruption on Linux/macOS and eliminates redundant encoding conversions.
wchar_tvsSQLWCHARconfusion — IntroduceODBC_SQLWCHARtypedef (always 16-bit); all*ToStringWfunctions useSQLWCHAR*directly; fixes silent data corruption on Linux wherewchar_tis 4 bytesmbstowcsusage — Replacembstowcs()withUtf8ToUtf16()inconvVarStringSystemToStringW; use trivial ASCII widening in integer→StringW formattersUtf16Convert.h/cppimplementation; update MultibyteConvert codecs to useODBC_SQLWCHAR*; LinuxCHARSET=NONEuses UTF-8 codecCHARSET=UTF8— WhenCHARSETnot specified in connection string, default toUTF8instead ofNONEOdbcStringUTF-16 metadata cache — IntroduceOdbcStringclass; cache column/table names as UTF-16 inDescRecord(11 fields); direct UTF-16 output forSQLDescribeColW,SQLColAttributeW,SQLGetDescFieldW,SQLGetDescRecW,SQLGetDiagRecW,SQLGetDiagFieldWconvVarStringSystemToString*variants; unifyconvStringToStringW/convVarStringToStringWvia shared helper; document conversion matrixTier 10: Medium — Firebird OO API Alignment (Phase 9)
Leverage the modern Firebird OO API; biggest win is IBatch for array execution.
IBatchfor array parameter execution — Single server roundtrip for N rows on FB4+; falls back to row-by-row for FB3; inline BLOB support viaBLOB_ID_ENGINEpolicy_dsql_*,_attach_database, etc.IscUserEventsto OO API — Replaceisc_que_events()withIAttachment::queEvents()viaFbEventCallbackclassIXpbBuilder— Replace raw byte-stuffing inbuildParamTransaction()FbDateConvert.hhelpers replace ~150 lines of duplicated Julian-day arithmetic; remove deadOdbcDateTimeclassgetIscStatusTextFromVector()usingIUtil::formatStatus(); remove legacyfb_interpretpathisc_vax_integerwith inline helper; mark concrete IscDbc classesfinalTier 11: Low — Dead Code Removal (Phase 13)
Cleanup after features are ported. Best done as the last code-only change before any architectural migration.
LinkedList.*,Lock.*,ServiceManager.*,SupportFunctions.*,OdbcDateTime.*,Engine.h,WriteBuildNo.h,IscDbc.def,IscDbc.exp,OdbcJdbcMinGw.def,OdbcJdbc.dll.manifest,makefile.in(×2)OdbcSqlState.h,OdbcUserEvents.h,FbDateConvert.hand any new headers from previous tiers.deffile assignment; removeBUILD_SETUPoptiontest_catalog.cpp,test_batch_params.cpp,test_connection.cpp,test_cursor.cpp,test_bind_cycle.cpp); redistribute phase-named tests to topic-named filesTier 12: Low — Source Reorganization
Move source files into
src/subdirectory. This is a large, disruptive change that should be done as a single PR when the codebase is stable.src/— Move.cpp/.hfrom root tosrc/, moveIscDbc/tosrc/IscDbc/, move.def/.rc/.manifesttosrc/; updateCMakeLists.txtRes/directory (5 locale resource files); simplify_TR()macro to always return English; removeinitCodePageTranslatecall fromDllMainTier 13: Future — fb-cpp Adoption (Phase 14)
The largest architectural change. Requires vcpkg infrastructure and the fb-cpp library. Should be done incrementally, after all correctness/performance work is stable.
vcpkg.jsonmanifest,vcpkg-configuration.jsonwith custom Firebird registry; update CI for vcpkg; add vcpkg as git submoduleCFbDllwithFbClientsingleton — Usefbcpp::FbApiHandlefor fbclient loading; replaceAttachmentclass withfbcpp::AttachmentInfoTransactionwithfbcpp::Transaction; map transaction isolation levels; migrate auto-commit and savepointsIscStatementhandle management withfbcpp::Statement; remap Sqlda buffers to fbcpp message buffers; migrate batch execution tofbcpp::BatchIscBlobinternals withfbcpp::Blob; replaceIscUserEventsinternals withfbcpp::EventListenerSQLError::fromDatabaseException(); consolidate date/time types intoFbDateConvert.hPODs; replaceJStringwithstd::stringacross all headerssrc/IscDbc/tosrc/core/; decompose Sqlda into data structItems Explicitly Excluded (WONTFIX)
These items were evaluated in v5-pr and deliberately excluded:
{fn},{d},{ts},{oj})OdbcConvert.cpp,OdbcStatement.cpp)SQL_ASYNC_ENABLE_ON)Known Gaps / Future Work
Items identified in v5-pr that are explicitly deferred or still open:
SQLGetDescRec,SQLSetDescRec,SQLCopyDesc)Test Suite Status After Each Tier