Search code examples
c++sqlitetransactionsraii

Clear any transactions


I'm writing some C++ software that works with a SQLite database.

I have one section of my code that has a lot of potential branches and errors. I'm having trouble ensuring that my transactions are always either committed or rolledback.

I was just wondering if there is any way to say "If there's a transaction underway, roll it back." Or perhaps there is a test I can make to determine if a transaction is in effect?

I don't see any way to do that, and I confirmed that executing ROLLBACK when no transaction is in effect causes an error. But I just thought I'd ask.


Solution

  • Many languages have a try/finally construct. C++ has not, you have to use RAII with an object with a constructor/destructor instead:

    class Transaction {
        sqlite3* db;
        public Transaction(sqlite3* db): db(db)
        {
            sqlite3_exec(db, "BEGIN");
        }
        public ~Transaction()
        {
            if (success)
                sqlite3_exec(db, "COMMIT");
            else
                sqlite3_exec(db, "ROLLBACK");
        }
    };
    

    To determine if the transaction is successful, you could use a function like Android's setTransactionSuccessful() (see also beginTransaction()).

    And a little bit of error handling would be useful (especially SQLITE_BUSY when you try to COMMIT).

    (To actually check whether an explicit transaction is active, you could test for auto-commit mode, but you should not do this if you have a better method to ensure that transactions are properly handled.)