Add migration for the sqlite database. Because the Qt SQL library is a bit hard to work with use sqlite through custom wrapper.
159 lines
3.4 KiB
C++
159 lines
3.4 KiB
C++
#include "SQLiteConnection.h"
|
|
|
|
|
|
|
|
SQLitePreparedStatement::SQLitePreparedStatement(SQLitePreparedStatement &&rhs)
|
|
: pStatement(rhs.pStatement)
|
|
{
|
|
rhs.pStatement = nullptr;
|
|
}
|
|
|
|
SQLitePreparedStatement &SQLitePreparedStatement::operator=(SQLitePreparedStatement &&rhs)
|
|
{
|
|
Free();
|
|
pStatement = rhs.pStatement;
|
|
rhs.pStatement = nullptr;
|
|
return *this;
|
|
}
|
|
|
|
SQLitePreparedStatement::~SQLitePreparedStatement()
|
|
{
|
|
Free();
|
|
}
|
|
|
|
void SQLitePreparedStatement::Open(SQLiteConnection &db, const char *query)
|
|
{
|
|
int result = sqlite3_prepare_v2(
|
|
db.pDb,
|
|
query,
|
|
-1,
|
|
&pStatement,
|
|
nullptr);
|
|
db.CheckResult(result);
|
|
}
|
|
|
|
void SQLitePreparedStatement::Open(SQLiteConnection &db, const QString &query)
|
|
{
|
|
Open(db, query.toUtf8().constData());
|
|
}
|
|
|
|
void SQLitePreparedStatement::Bind(int index, const char *s, int length)
|
|
{
|
|
int result = sqlite3_bind_text(pStatement, index, s, length, SQLITE_STATIC);
|
|
if (result != SQLITE_OK)
|
|
throw SQLiteException("failed to bind");
|
|
}
|
|
|
|
void SQLitePreparedStatement::Bind(int index, const QString &s)
|
|
{
|
|
int result = sqlite3_bind_text16(pStatement, index, s.constData(), -1, SQLITE_TRANSIENT);
|
|
if (result != SQLITE_OK)
|
|
throw SQLiteException("failed to bind");
|
|
}
|
|
|
|
void SQLitePreparedStatement::Bind(int index, int v)
|
|
{
|
|
int result = sqlite3_bind_int(pStatement, index, v);
|
|
if (result != SQLITE_OK)
|
|
throw SQLiteException("failed to bind");
|
|
}
|
|
|
|
const char *SQLitePreparedStatement::ColumnCharPtr(int col)
|
|
{
|
|
return (const char*)sqlite3_column_text(pStatement, col);
|
|
}
|
|
|
|
QString SQLitePreparedStatement::ColumnText(int col)
|
|
{
|
|
const unsigned char *val = sqlite3_column_text(pStatement, col);
|
|
if (val != nullptr)
|
|
{
|
|
return QString::fromUtf8(val);
|
|
}
|
|
return {};
|
|
}
|
|
|
|
int SQLitePreparedStatement::ColumnInteger(int col)
|
|
{
|
|
return sqlite3_column_int(pStatement, col);
|
|
}
|
|
|
|
bool SQLitePreparedStatement::Step()
|
|
{
|
|
int result = sqlite3_step(pStatement);
|
|
switch (result)
|
|
{
|
|
case SQLITE_ROW:
|
|
return true;
|
|
case SQLITE_DONE:
|
|
return false;
|
|
default:
|
|
throw std::runtime_error("Error in step");
|
|
}
|
|
}
|
|
|
|
SQLiteConnection::SQLiteConnection(SQLiteConnection &&rhs)
|
|
: pDb(rhs.pDb)
|
|
{
|
|
rhs.pDb = nullptr;
|
|
}
|
|
|
|
SQLiteConnection &SQLiteConnection::operator=(SQLiteConnection &&rhs)
|
|
{
|
|
if (pDb != nullptr)
|
|
{
|
|
sqlite3_close(pDb);
|
|
}
|
|
pDb = rhs.pDb;
|
|
rhs.pDb = nullptr;
|
|
return *this;
|
|
}
|
|
|
|
SQLiteTransaction::SQLiteTransaction(SQLiteConnection &db)
|
|
: db(db)
|
|
{
|
|
SQLitePreparedStatement stmt = db.Prepare("BEGIN TRANSACTION;");
|
|
stmt.Step();
|
|
inTransaction = true;
|
|
}
|
|
|
|
SQLiteTransaction::~SQLiteTransaction()
|
|
{
|
|
if (inTransaction)
|
|
{
|
|
UncheckedRollback();
|
|
}
|
|
}
|
|
|
|
void SQLiteTransaction::Commit()
|
|
{
|
|
if (inTransaction)
|
|
{
|
|
SQLitePreparedStatement stmt = db.Prepare("COMMIT TRANSACTION;");
|
|
stmt.Step();
|
|
inTransaction = false;
|
|
}
|
|
else
|
|
{
|
|
throw SQLiteException("Transaction already ended or never started");
|
|
}
|
|
}
|
|
|
|
void SQLiteTransaction::Rollback()
|
|
{
|
|
if (inTransaction)
|
|
{
|
|
UncheckedRollback();
|
|
}
|
|
else
|
|
{
|
|
throw SQLiteException("Transaction already ended or never started");
|
|
}
|
|
}
|
|
|
|
void SQLiteTransaction::UncheckedRollback()
|
|
{
|
|
SQLitePreparedStatement stmt = db.Prepare("ROLLBACK TRANSACTION;");
|
|
stmt.Step();
|
|
inTransaction = false;
|
|
}
|