diff --git a/sqlwriter.cc b/sqlwriter.cc index aacde15..08a6105 100644 --- a/sqlwriter.cc +++ b/sqlwriter.cc @@ -225,12 +225,10 @@ void MiniSQLite::execPrep(const std::string& table, std::vector> SQLiteWriter::queryGen( MiniSQLite::~MiniSQLite() { // needs to close down d_sqlite3 - if(d_intransaction) - commit(); + if(inTransaction()) { + try { + commit(); + } catch (std::runtime_error &e) { + // don't have a good way to report e + // transaction will be rolled back instead + } + } for(auto& stmt: d_stmts) if(stmt.second) diff --git a/sqlwriter.hh b/sqlwriter.hh index a0b062b..0d3f74f 100644 --- a/sqlwriter.hh +++ b/sqlwriter.hh @@ -55,7 +55,7 @@ private: std::unordered_map d_stmts; std::vector> d_rows; // for exec() static int helperFunc(void* ptr, int cols, char** colvals, char** colnames); - bool d_intransaction{false}; + bool inTransaction(); bool haveTable(const std::string& table); }; diff --git a/testrunner.cc b/testrunner.cc index f6ef378..ea9bf7b 100644 --- a/testrunner.cc +++ b/testrunner.cc @@ -349,6 +349,62 @@ TEST_CASE("readonly test") { unlink(fname.c_str()); } +TEST_CASE("MiniSQLite destructor commits") { + const char* name = "testrunner-dtor.sqlite3"; + + unlink(name); + + { + MiniSQLite ms(name); + ms.begin(); + ms.exec("create table top (role, playing, game)"); + ms.exec("insert into top values ('d', '&', 'd')"); + } + + { + MiniSQLite ms(name); + CHECK(ms.exec("select count(*) from top").at(0).at(0) == "1"); + } + + unlink(name); +} + +TEST_CASE("MiniSQLite destructor commit failure is ignored") { + const char* name = "testrunner-dtor.sqlite3"; + + unlink(name); + + { + MiniSQLite ms(name); + ms.begin(); + unlink(name); + } + + unlink(name); +} + +TEST_CASE("MiniSQLite destructor is not confused by rollback query") { + CHECK_NOTHROW([](){ + MiniSQLite ms(":memory:"); + + ms.begin(); + ms.exec("rollback"); + }()); +} + +TEST_CASE("MiniSQLite destructor is not confused by rollback caused by error") { + CHECK_THROWS([](){ + MiniSQLite ms(":memory:"); + + ms.begin(); + ms.exec("create table foo (bar)"); + ms.exec("pragma max_page_count=5"); + + // error happens here: 'database or disk is full' + ms.exec("insert into foo values (zeroblob(1000000))"); + }()); +} + TEST_CASE("test scale") { unlink("testrunner-example.sqlite3"); {