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 "Database.h"
|
||||||
#include "Statement.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++/Database.h"
|
||||||
#include "../SQLiteC++/Statement.h"
|
#include "../SQLiteC++/Statement.h"
|
||||||
|
#include "../SQLiteC++/Transaction.h"
|
||||||
|
|
||||||
|
|
||||||
/// Object Oriented Basic example
|
/// Object Oriented Basic example
|
||||||
@ -56,7 +57,7 @@ private:
|
|||||||
|
|
||||||
int main (void)
|
int main (void)
|
||||||
{
|
{
|
||||||
// Basic example (1/3) :
|
// Basic example (1/4) :
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Open a database file
|
// Open a database file
|
||||||
@ -64,7 +65,7 @@ int main (void)
|
|||||||
std::cout << "SQLite database file '" << db.getFilename().c_str() << "' opened successfully\n";
|
std::cout << "SQLite database file '" << db.getFilename().c_str() << "' opened successfully\n";
|
||||||
|
|
||||||
// Compile a SQL query, containing one parameter (index 1)
|
// 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";
|
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
|
// Bind the integer value 6 to the first parameter of the SQL query
|
||||||
query.bind(1, 6);
|
query.bind(1, 6);
|
||||||
@ -99,7 +100,7 @@ int main (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
// Object Oriented Basic example (2/3) :
|
// Object Oriented Basic example (2/4) :
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Open the database and compile the query
|
// 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
|
try
|
||||||
{
|
{
|
||||||
// Open a database file
|
// Open a database file
|
||||||
@ -138,5 +139,69 @@ int main (void)
|
|||||||
}
|
}
|
||||||
remove("test.db3");
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user