Allow specifying transaction behaviors DEFERRED, IMMEDIATE, and EXCLUSIVE

This commit is contained in:
John Jenkins 2021-10-04 16:21:31 -05:00
parent c7909ee9c1
commit abd139c597
3 changed files with 59 additions and 2 deletions

View File

@ -20,6 +20,16 @@ namespace SQLite
// Forward declaration
class Database;
/**
* @brief Transaction behaviors when opening an SQLite transaction.
* Names correspond directly to the behavior.
*/
enum class TransactionBehavior {
DEFERRED,
IMMEDIATE,
EXCLUSIVE,
};
/**
* @brief RAII encapsulation of a SQLite Transaction.
*
@ -44,7 +54,7 @@ class Transaction
{
public:
/**
* @brief Begins the SQLite transaction
* @brief Begins the SQLite transaction using the default transaction behavior.
*
* @param[in] aDatabase the SQLite Database Connection
*
@ -52,6 +62,16 @@ public:
*/
explicit Transaction(Database& aDatabase);
/**
* @brief Begins the SQLite transaction with the specified behavior.
*
* @param[in] aDatabase the SQLite Database Connection
* @param[in] behavior the requested transaction behavior
*
* Exception is thrown in case of error, then the Transaction is NOT initiated.
*/
explicit Transaction(Database& aDatabase, TransactionBehavior behavior);
// Transaction is non-copyable
Transaction(const Transaction&) = delete;
Transaction& operator=(const Transaction&) = delete;

View File

@ -13,13 +13,36 @@
#include <SQLiteCpp/Database.h>
#include <SQLiteCpp/Assertion.h>
#include <sqlite3.h>
namespace SQLite
{
// Begins the SQLite transaction
Transaction::Transaction(Database& aDatabase) :
Transaction::Transaction(Database& aDatabase, TransactionBehavior behavior) :
mDatabase(aDatabase),
mbCommited(false)
{
const char *stmt;
switch (behavior) {
case TransactionBehavior::DEFERRED:
stmt = "BEGIN DEFERRED";
break;
case TransactionBehavior::IMMEDIATE:
stmt = "BEGIN IMMEDIATE";
break;
case TransactionBehavior::EXCLUSIVE:
stmt = "BEGIN EXCLUSIVE";
break;
default:
throw SQLite::Exception("invalid/unknown transaction behavior", SQLITE_ERROR);
}
mDatabase.exec(stmt);
}
// Begins the SQLite transaction
Transaction::Transaction(Database &aDatabase) :
mDatabase(aDatabase),
mbCommited(false)
{

View File

@ -42,6 +42,20 @@ TEST(Transaction, commitRollback)
EXPECT_THROW(transaction.commit(), SQLite::Exception);
}
// ensure transactions with different types are well-formed
{
for (auto behavior : {
SQLite::TransactionBehavior::DEFERRED,
SQLite::TransactionBehavior::IMMEDIATE,
SQLite::TransactionBehavior::EXCLUSIVE })
{
SQLite::Transaction transaction(db, behavior);
transaction.commit();
}
EXPECT_THROW(SQLite::Transaction(db, static_cast<SQLite::TransactionBehavior>(-1)), SQLite::Exception);
}
// Auto rollback if no commit() before the end of scope
{
// Begin transaction