Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions sqlwriter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -225,12 +225,10 @@ void MiniSQLite::execPrep(const std::string& table, std::vector<std::unordered_m

void MiniSQLite::begin()
{
d_intransaction=true;
exec("begin");
}
void MiniSQLite::commit()
{
d_intransaction=false;
exec("commit");
}

Expand All @@ -239,6 +237,11 @@ void MiniSQLite::cycle()
exec("commit;begin");
}

bool MiniSQLite::inTransaction()
{
return sqlite3_get_autocommit(d_sqlite) == 0;
}

bool MiniSQLite::haveTable(const string& table)
{
return !getSchema(table).empty();
Expand Down Expand Up @@ -437,8 +440,14 @@ vector<std::unordered_map<string, MiniSQLite::outvar_t>> 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)
Expand Down
2 changes: 1 addition & 1 deletion sqlwriter.hh
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ private:
std::unordered_map<std::string, sqlite3_stmt*> d_stmts;
std::vector<std::vector<std::string>> 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);
};

Expand Down
56 changes: 56 additions & 0 deletions testrunner.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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");
{
Expand Down