Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rename Savepoint RollbackTo() and fix class comments and formatting #396

Merged
merged 2 commits into from
Dec 15, 2022
Merged
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
58 changes: 30 additions & 28 deletions include/SQLiteCpp/Savepoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,49 +14,48 @@

#include <SQLiteCpp/Exception.h>

namespace SQLite {
namespace SQLite
{

// Foward declaration
// Forward declaration
class Database;

/**
* @brief RAII encapsulation of a SQLite Savepoint.
*
* A Savepoint is a way to group multiple SQL statements into an atomic
* secure operation; either it succeeds, with all the changes committed to the
* database file, or if it fails, all the changes are rolled back to the initial
* state at the start of the savepoint.
* SAVEPOINTs are a method of creating Transactions, similar to BEGIN and COMMIT,
* except that the SAVEPOINT and RELEASE commands are named and may be nested..
*
* Resource Acquisition Is Initialization (RAII) means that the Savepoint
* begins in the constructor and is rolled back in the destructor (unless committed before), so that there is
* no need to worry about memory management or the validity of the underlying SQLite Connection.
*
* This method also offers big performances improvements compared to
* individually executed statements.
*
* Caveats:
*
* 1) Calling COMMIT or commiting a parent transaction or RELEASE on a parent
* 1) Calling COMMIT or committing a parent transaction or RELEASE on a parent
* savepoint will cause this savepoint to be released.
*
* 2) Calling ROLLBACK or rolling back a parent savepoint will cause this
* 2) Calling ROLLBACK TO or rolling back a parent savepoint will cause this
* savepoint to be rolled back.
*
* 3) This savepoint is not saved to the database until this and all savepoints
* or transaction in the savepoint stack have been released or committed.
*
* See also: https://sqlite.org/lang_savepoint.html
*
* Thread-safety: a Transaction object shall not be shared by multiple threads,
* because:
*
* 1) in the SQLite "Thread Safe" mode, "SQLite can be safely used by multiple
* threads provided that no single database connection is used simultaneously in
* two or more threads."
*
* 2) the SQLite "Serialized" mode is not supported by SQLiteC++, because of the
* way it shares the underling SQLite precompiled statement in a custom shared
* pointer (See the inner class "Statement::Ptr").
* Thread-safety: a Savepoint object shall not be shared by multiple threads, because:
* 1) in the SQLite "Thread Safe" mode, "SQLite can be safely used by multiple threads
* provided that no single database connection is used simultaneously in two or more threads."
* 2) the SQLite "Serialized" mode is not supported by SQLiteC++,
* because of the way it shares the underling SQLite precompiled statement
* in a custom shared pointer (See the inner class "Statement::Ptr").
*/

class Savepoint {
public:
class Savepoint
{
public:
/**
* @brief Begins the SQLite savepoint
*
Expand All @@ -73,7 +72,7 @@ class Savepoint {
Savepoint& operator=(const Savepoint&) = delete;

/**
* @brief Safely rollback the savepoint if it has not been commited.
* @brief Safely rollback the savepoint if it has not been committed.
*/
~Savepoint();

Expand All @@ -83,13 +82,16 @@ class Savepoint {
void release();

/**
* @brief Rollback the savepoint
* @brief Rollback to the savepoint, but don't release it.
*/
void rollback();
void rollbackTo();
// @deprecated same as rollbackTo();
void rollback() { rollbackTo(); }

private:
Database& mDatabase; ///< Reference to the SQLite Database Connection
std::string msName; ///< Name of the Savepoint
bool mbReleased = false; ///< True when release has been called
private:
Database& mDatabase; ///< Reference to the SQLite Database Connection
std::string msName; ///< Name of the Savepoint
bool mbReleased = false; ///< True when release has been called
};

} // namespace SQLite
45 changes: 30 additions & 15 deletions src/Savepoint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@
#include <SQLiteCpp/Savepoint.h>
#include <SQLiteCpp/Statement.h>

namespace SQLite {
namespace SQLite
{

// Begins the SQLite savepoint
Savepoint::Savepoint(Database& aDatabase, const std::string& aName)
: mDatabase(aDatabase), msName(aName) {
: mDatabase(aDatabase), msName(aName)
{
// workaround because you cannot bind to SAVEPOINT
// escape name for use in query
Statement stmt(mDatabase, "SELECT quote(?)");
Expand All @@ -32,33 +34,46 @@ Savepoint::Savepoint(Database& aDatabase, const std::string& aName)
}

// Safely rollback the savepoint if it has not been committed.
Savepoint::~Savepoint() {
if (!mbReleased) {
try {
Savepoint::~Savepoint()
{
if (!mbReleased)
{
try
{
rollback();
release();
} catch (SQLite::Exception&) {
// Never throw an exception in a destructor: error if already rolled
// back or released, but no harm is caused by this.
}
catch (SQLite::Exception&)
{
// Never throw an exception in a destructor: error if already released,
// but no harm is caused by this.
}
}
}

// Release the savepoint and commit
void Savepoint::release() {
if (!mbReleased) {
void Savepoint::release()
{
if (!mbReleased)
{
mDatabase.exec(std::string("RELEASE SAVEPOINT ") + msName);
mbReleased = true;
} else {
}
else
{
throw SQLite::Exception("Savepoint already released.");
}
}

// Rollback the savepoint
void Savepoint::rollback() {
if (!mbReleased) {
// Rollback to the savepoint, but don't release it
void Savepoint::rollbackTo()
{
if (!mbReleased)
{
mDatabase.exec(std::string("ROLLBACK TO SAVEPOINT ") + msName);
} else {
}
else
{
throw SQLite::Exception("Savepoint already released.");
}
}
Expand Down