#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; }