You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Fix Savepoint destructor exception-safety and rollback bookkeeping (#559)
## Summary
Fixes two findings from the deep code review (SP-03, SP-02) in the
`Savepoint` destructor. The documented auto-rollback-on-scope-exit
semantics are unchanged.
### SP-03 — destructor could call `std::terminate`
`~Savepoint()` caught only `SQLite::Exception`. Building the `"ROLLBACK
TO SAVEPOINT " + msName` / `"RELEASE SAVEPOINT " + msName` strings can
throw `std::bad_alloc`, and any non-`SQLite::Exception` thrown during
cleanup would escape the implicitly `noexcept` destructor and terminate
the process. The handler is now `catch (...)`, matching the stated
intent ("Never throw an exception in a destructor").
### SP-02 — no rolled-back state, fragile double-rollback
There was a single `mbReleased` flag and no notion of "already rolled
back", so after a manual `rollbackTo()` (or on the normal scope-exit
path) the destructor issued a `ROLLBACK TO` and then a `RELEASE`,
relying on SQLite tolerating a repeated `ROLLBACK TO`. A new
`mbRolledBack` flag (set in `rollbackTo()`) lets the destructor do the
minimum: skip the redundant `ROLLBACK TO` and just `RELEASE`.
## Test plan
- Added `Savepoint.rollbackToThenRelease` covering a manual
`rollbackTo()` followed by `release()` and a clean scope exit.
- Built `SQLiteCpp_tests` (MSVC, Debug); `ctest -C Debug` 100% passed,
including the existing `Savepoint.commitRollback` and
`Savepoint.destructorSwallowsException` tests.
No public API or behavioural change on the happy path; only the
(previously UB-on-OOM) destructor error handling and the
redundant-command path change.
0 commit comments