mirror of
https://github.com/cuberite/SQLiteCpp.git
synced 2025-08-04 09:46:02 -04:00
Added a simple RAII Transaction class
This commit is contained in:
parent
acf27fd052
commit
c4f041cb46
@ -11,3 +11,4 @@
|
||||
|
||||
#include "Database.h"
|
||||
#include "Statement.h"
|
||||
#include "Transaction.h"
|
||||
|
49
src/SQLiteC++/Transaction.cpp
Normal file
49
src/SQLiteC++/Transaction.cpp
Normal file
@ -0,0 +1,49 @@
|
||||
/**
|
||||
* @file Transaction.cpp
|
||||
* @brief A prepared SQLite Transaction is a compiled SQL query ready to be executed.
|
||||
*
|
||||
* Copyright (c) 2012 Sebastien Rombauts (sebastien dot rombauts at gmail dot com)
|
||||
*
|
||||
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
|
||||
* or copy at http://opensource.org/licenses/MIT)
|
||||
*/
|
||||
#include "Transaction.h"
|
||||
|
||||
#include "Database.h"
|
||||
|
||||
namespace SQLite
|
||||
{
|
||||
|
||||
// Compile and register the SQL query for the provided SQLite Database Connection
|
||||
Transaction::Transaction(Database &aDatabase) : // throw(SQLite::Exception)
|
||||
mDatabase(aDatabase),
|
||||
mbCommited(false)
|
||||
{
|
||||
mDatabase.exec("BEGIN");
|
||||
}
|
||||
|
||||
// Finalize and unregister the SQL query from the SQLite Database Connection.
|
||||
Transaction::~Transaction(void) throw() // nothrow
|
||||
{
|
||||
if (false == mbCommited)
|
||||
{
|
||||
mDatabase.exec("ROLLBACK");
|
||||
}
|
||||
}
|
||||
|
||||
// Commit the transaction.
|
||||
void Transaction::commit(void) // throw(SQLite::Exception)
|
||||
{
|
||||
if (false == mbCommited)
|
||||
{
|
||||
mDatabase.exec("COMMIT");
|
||||
mbCommited = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw SQLite::Exception("Transaction already commited");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}; // namespace SQLite
|
64
src/SQLiteC++/Transaction.h
Normal file
64
src/SQLiteC++/Transaction.h
Normal file
@ -0,0 +1,64 @@
|
||||
/**
|
||||
* @file Transaction.h
|
||||
* @brief A Transaction is way to group multiple SQL statements into an atomic secured operation.
|
||||
*
|
||||
* Copyright (c) 2012 Sebastien Rombauts (sebastien dot rombauts at gmail dot com)
|
||||
*
|
||||
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
|
||||
* or copy at http://opensource.org/licenses/MIT)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <sqlite3.h>
|
||||
#include "Exception.h"
|
||||
|
||||
namespace SQLite
|
||||
{
|
||||
|
||||
// Forward declaration
|
||||
class Database;
|
||||
|
||||
/**
|
||||
* @brief RAII encapsulation of a SQLite Transaction.
|
||||
*
|
||||
* A Transaction is a way to group multiple SQL statements into an atomic secured operation;
|
||||
* either it succeeds, with all the changes commited to the database file,
|
||||
* or if it fails, all the changes are rolled back to the initial state.
|
||||
*
|
||||
* Resource Acquisition Is Initialization (RAII) means that the Transaction
|
||||
* begins in the constructor and is rollbacked in the destructor, so that there is
|
||||
* no need to worry about memory management or the validity of the underlying SQLite Connection.
|
||||
*/
|
||||
class Transaction
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Begins the SQLite transaction
|
||||
*
|
||||
* Exception is thrown in case of error, then the Transaction is NOT initiated.
|
||||
*/
|
||||
explicit Transaction(Database &aDatabase); // throw(SQLite::Exception);
|
||||
|
||||
/**
|
||||
* @brief Safely rollback the transaction if it has not been commited.
|
||||
*/
|
||||
virtual ~Transaction(void) throw(); // nothrow
|
||||
|
||||
/**
|
||||
* @brief Commit the transaction.
|
||||
*/
|
||||
void commit(void); // throw(SQLite::Exception);
|
||||
|
||||
private:
|
||||
// Transaction must not be copyable
|
||||
Transaction(void);
|
||||
Transaction(const Transaction&);
|
||||
Transaction& operator=(const Transaction&);
|
||||
|
||||
private:
|
||||
Database& mDatabase; //!< Reference to the SQLite Database Connection
|
||||
bool mbCommited; //!< True when the last executeStep() had no more row to fetch
|
||||
};
|
||||
|
||||
|
||||
}; // namespace SQLite
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include "../SQLiteC++/Database.h"
|
||||
#include "../SQLiteC++/Statement.h"
|
||||
#include "../SQLiteC++/Transaction.h"
|
||||
|
||||
|
||||
/// Object Oriented Basic example
|
||||
@ -56,7 +57,7 @@ private:
|
||||
|
||||
int main (void)
|
||||
{
|
||||
// Basic example (1/3) :
|
||||
// Basic example (1/4) :
|
||||
try
|
||||
{
|
||||
// Open a database file
|
||||
@ -64,7 +65,7 @@ int main (void)
|
||||
std::cout << "SQLite database file '" << db.getFilename().c_str() << "' opened successfully\n";
|
||||
|
||||
// Compile a SQL query, containing one parameter (index 1)
|
||||
SQLite::Statement query(db, "SELECT * FROM test WHERE size > ?;SELECT id FROM test");
|
||||
SQLite::Statement query(db, "SELECT * FROM test WHERE size > ?");
|
||||
std::cout << "SQLite statement '" << query.getQuery().c_str() << "' compiled (" << query.getColumnCount () << " columns in the result)\n";
|
||||
// Bind the integer value 6 to the first parameter of the SQL query
|
||||
query.bind(1, 6);
|
||||
@ -99,7 +100,7 @@ int main (void)
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Object Oriented Basic example (2/3) :
|
||||
// Object Oriented Basic example (2/4) :
|
||||
try
|
||||
{
|
||||
// Open the database and compile the query
|
||||
@ -116,7 +117,7 @@ int main (void)
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Simple batch queries example (3/3) :
|
||||
// Simple batch queries example (3/4) :
|
||||
try
|
||||
{
|
||||
// Open a database file
|
||||
@ -138,5 +139,69 @@ int main (void)
|
||||
}
|
||||
remove("test.db3");
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// RAII transaction example (4/4) :
|
||||
try
|
||||
{
|
||||
// Open a database file
|
||||
SQLite::Database db("transaction.db3", SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
|
||||
std::cout << "SQLite database file '" << db.getFilename().c_str() << "' opened successfully\n";
|
||||
|
||||
db.exec("DROP TABLE IF EXISTS test");
|
||||
|
||||
// Exemple of a successful transaction :
|
||||
try
|
||||
{
|
||||
// Begin transaction
|
||||
SQLite::Transaction transaction(db);
|
||||
|
||||
db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)");
|
||||
|
||||
int nb = db.exec("INSERT INTO test VALUES (NULL, \"test\")");
|
||||
std::cout << "INSERT INTO test VALUES (NULL, \"test\")\", returned " << nb << std::endl;
|
||||
|
||||
// Commit transaction
|
||||
transaction.commit();
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::cout << "SQLite exception: " << e.what() << std::endl;
|
||||
}
|
||||
|
||||
// Exemple of a rollbacked transaction :
|
||||
try
|
||||
{
|
||||
// Begin transaction
|
||||
SQLite::Transaction transaction(db);
|
||||
|
||||
int nb = db.exec("INSERT INTO test VALUES (NULL, \"second\")");
|
||||
std::cout << "INSERT INTO test VALUES (NULL, \"second\")\", returned " << nb << std::endl;
|
||||
|
||||
nb = db.exec("INSERT INTO test \"error\"");
|
||||
std::cout << "INSERT INTO test \"error\"\", returned " << nb << std::endl;
|
||||
|
||||
// Commit transaction
|
||||
transaction.commit();
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::cout << "SQLite exception: " << e.what() << std::endl;
|
||||
}
|
||||
|
||||
// Check the results
|
||||
SQLite::Statement query(db, "SELECT * FROM test");
|
||||
std::cout << "SELECT * FROM test :\n";
|
||||
while (query.executeStep())
|
||||
{
|
||||
std::cout << "row : (" << query.getColumn(0) << ", " << query.getColumn(1) << ")\n";
|
||||
}
|
||||
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::cout << "SQLite exception: " << e.what() << std::endl;
|
||||
}
|
||||
remove("transaction.db3");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user