1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-06-15 15:49:36 +02:00

Cut and paste TransactionScope into DBConnection.* files

This commit is contained in:
Paul Licameli 2020-09-02 15:17:51 -04:00
parent ddc2593282
commit e7b3c2b99f
6 changed files with 125 additions and 124 deletions

View File

@ -337,6 +337,107 @@ int DBConnection::CheckpointHook(void *data, sqlite3 *db, const char *schema, in
return SQLITE_OK;
}
bool TransactionScope::TransactionStart(const wxString &name)
{
char *errmsg = nullptr;
int rc = sqlite3_exec(mConnection.DB(),
wxT("SAVEPOINT ") + name + wxT(";"),
nullptr,
nullptr,
&errmsg);
if (errmsg)
{
mConnection.SetDBError(
XO("Failed to create savepoint:\n\n%s").Format(name)
);
sqlite3_free(errmsg);
}
return rc == SQLITE_OK;
}
bool TransactionScope::TransactionCommit(const wxString &name)
{
char *errmsg = nullptr;
int rc = sqlite3_exec(mConnection.DB(),
wxT("RELEASE ") + name + wxT(";"),
nullptr,
nullptr,
&errmsg);
if (errmsg)
{
mConnection.SetDBError(
XO("Failed to release savepoint:\n\n%s").Format(name)
);
sqlite3_free(errmsg);
}
return rc == SQLITE_OK;
}
bool TransactionScope::TransactionRollback(const wxString &name)
{
char *errmsg = nullptr;
int rc = sqlite3_exec(mConnection.DB(),
wxT("ROLLBACK TO ") + name + wxT(";"),
nullptr,
nullptr,
&errmsg);
if (errmsg)
{
mConnection.SetDBError(
XO("Failed to release savepoint:\n\n%s").Format(name)
);
sqlite3_free(errmsg);
}
return rc == SQLITE_OK;
}
TransactionScope::TransactionScope(
DBConnection &connection, const char *name)
: mConnection(connection),
mName(name)
{
mInTrans = TransactionStart(mName);
if ( !mInTrans )
// To do, improve the message
throw SimpleMessageBoxException( XO("Database error") );
}
TransactionScope::~TransactionScope()
{
if (mInTrans)
{
// Rollback AND REMOVE the transaction
// -- must do both; rolling back a savepoint only rewinds it
// without removing it, unlike the ROLLBACK command
if (!(TransactionRollback(mName) &&
TransactionCommit(mName) ) )
{
// Do not throw from a destructor!
// This has to be a no-fail cleanup that does the best that it can.
}
}
}
bool TransactionScope::Commit()
{
if ( !mInTrans )
// Misuse of this class
THROW_INCONSISTENCY_EXCEPTION;
mInTrans = !TransactionCommit(mName);
return mInTrans;
}
ConnectionPtr::~ConnectionPtr()
{
wxASSERT_MSG(!mpConnection, wxT("Project file was not closed at shutdown"));

View File

@ -110,6 +110,28 @@ private:
bool mBypass;
};
// Make a savepoint (a transaction, possibly nested) with the given name;
// roll it back at destruction time, unless an explicit Commit() happened first.
// Commit() must not be called again after one successful call.
// An exception is thrown from the constructor if the transaction cannot open.
class TransactionScope
{
public:
TransactionScope(DBConnection &connection, const char *name);
~TransactionScope();
bool Commit();
private:
bool TransactionStart(const wxString &name);
bool TransactionCommit(const wxString &name);
bool TransactionRollback(const wxString &name);
DBConnection &mConnection;
bool mInTrans;
wxString mName;
};
using Connection = std::unique_ptr<DBConnection>;
// This object attached to the project simply holds the pointer to the

View File

@ -423,69 +423,6 @@ void ProjectFileIO::UseConnection(Connection &&conn, const FilePath &filePath)
SetFileName(filePath);
}
bool TransactionScope::TransactionStart(const wxString &name)
{
char *errmsg = nullptr;
int rc = sqlite3_exec(mConnection.DB(),
wxT("SAVEPOINT ") + name + wxT(";"),
nullptr,
nullptr,
&errmsg);
if (errmsg)
{
mConnection.SetDBError(
XO("Failed to create savepoint:\n\n%s").Format(name)
);
sqlite3_free(errmsg);
}
return rc == SQLITE_OK;
}
bool TransactionScope::TransactionCommit(const wxString &name)
{
char *errmsg = nullptr;
int rc = sqlite3_exec(mConnection.DB(),
wxT("RELEASE ") + name + wxT(";"),
nullptr,
nullptr,
&errmsg);
if (errmsg)
{
mConnection.SetDBError(
XO("Failed to release savepoint:\n\n%s").Format(name)
);
sqlite3_free(errmsg);
}
return rc == SQLITE_OK;
}
bool TransactionScope::TransactionRollback(const wxString &name)
{
char *errmsg = nullptr;
int rc = sqlite3_exec(mConnection.DB(),
wxT("ROLLBACK TO ") + name + wxT(";"),
nullptr,
nullptr,
&errmsg);
if (errmsg)
{
mConnection.SetDBError(
XO("Failed to release savepoint:\n\n%s").Format(name)
);
sqlite3_free(errmsg);
}
return rc == SQLITE_OK;
}
static int ExecCallback(void *data, int cols, char **vals, char **names)
{
auto &cb = *static_cast<const ProjectFileIO::ExecCB *>(data);
@ -2448,41 +2385,3 @@ int ProjectFileIO::get_varint(const unsigned char *ptr, int64_t *out)
return 9;
}
TransactionScope::TransactionScope(
DBConnection &connection, const char *name)
: mConnection(connection),
mName(name)
{
mInTrans = TransactionStart(mName);
if ( !mInTrans )
// To do, improve the message
throw SimpleMessageBoxException( XO("Database error") );
}
TransactionScope::~TransactionScope()
{
if (mInTrans)
{
// Rollback AND REMOVE the transaction
// -- must do both; rolling back a savepoint only rewinds it
// without removing it, unlike the ROLLBACK command
if (!(TransactionRollback(mName) &&
TransactionCommit(mName) ) )
{
// Do not throw from a destructor!
// This has to be a no-fail cleanup that does the best that it can.
}
}
}
bool TransactionScope::Commit()
{
if ( !mInTrans )
// Misuse of this class
THROW_INCONSISTENCY_EXCEPTION;
mInTrans = !TransactionCommit(mName);
return mInTrans;
}

View File

@ -24,7 +24,6 @@ struct sqlite3_stmt;
struct sqlite3_value;
class AudacityProject;
class TransactionScope;
class DBConnection;
class ProjectSerializer;
class SqliteSampleBlock;
@ -239,28 +238,6 @@ private:
bool mPrevTemporary;
};
// Make a savepoint (a transaction, possibly nested) with the given name;
// roll it back at destruction time, unless an explicit Commit() happened first.
// Commit() must not be called again after one successful call.
// An exception is thrown from the constructor if the transaction cannot open.
class TransactionScope
{
public:
TransactionScope(DBConnection &connection, const char *name);
~TransactionScope();
bool Commit();
private:
bool TransactionStart(const wxString &name);
bool TransactionCommit(const wxString &name);
bool TransactionRollback(const wxString &name);
DBConnection &mConnection;
bool mInTrans;
wxString mName;
};
class wxTopLevelWindow;
// TitleRestorer restores project window titles to what they were, in its destructor.

View File

@ -15,6 +15,7 @@ Paul Licameli split from AudacityProject.cpp
#include "AdornedRulerPanel.h"
#include "AudioIO.h"
#include "Clipboard.h"
#include "DBConnection.h"
#include "FileNames.h"
#include "Menus.h"
#include "ModuleManager.h"

View File

@ -27,6 +27,7 @@
#include <wx/tokenzr.h>
#include "../AudioIO.h"
#include "../DBConnection.h"
#include "../LabelTrack.h"
#include "../Mix.h"
#include "../PluginManager.h"