#pragma once #include "sqlite3.h" #include #include class SQLiteException : public std::runtime_error { public: explicit SQLiteException(const char* msg) : std::runtime_error(msg) {} }; class SQLiteConnection; class SQLitePreparedStatement { public: SQLitePreparedStatement() = default; SQLitePreparedStatement(const SQLitePreparedStatement &) = delete; SQLitePreparedStatement(SQLitePreparedStatement&& rhs); SQLitePreparedStatement &operator=(SQLitePreparedStatement&& rhs); ~SQLitePreparedStatement(); void Open(SQLiteConnection &db, const char *query); void Open(SQLiteConnection &db, const QString &query); void Bind(int index, const char *s, int length = 0); void Bind(int index, const QString &s); void Bind(int index, int v); const char* ColumnCharPtr(int col); QString ColumnText(int col); int ColumnInteger(int col); bool Step(); void Reset() { sqlite3_reset(pStatement); } private: sqlite3_stmt *pStatement = nullptr; void Free() { if (pStatement != nullptr) { sqlite3_finalize(pStatement); pStatement = nullptr; } } }; class SQLiteTransaction { public: explicit SQLiteTransaction(SQLiteConnection &db); SQLiteTransaction(const SQLiteTransaction&&) = delete; ~SQLiteTransaction(); void Commit(); void Rollback(); private: SQLiteConnection &db; bool inTransaction = false; void UncheckedRollback(); }; class SQLiteConnection { public: SQLiteConnection() = default; SQLiteConnection(const SQLiteConnection&) = delete; SQLiteConnection(SQLiteConnection&& rhs); SQLiteConnection& operator=(const SQLiteConnection &) = delete; SQLiteConnection& operator=(SQLiteConnection && rhs); ~SQLiteConnection() { if (pDb) { sqlite3_close(pDb); } } void Open(const char *filename) { int result = sqlite3_open(filename, &pDb); CheckResult(result); } void Open(QString filename) { int result = sqlite3_open16((void*)filename.data(), &pDb); CheckResult(result); } void CheckResult(int result) { if (result == SQLITE_OK) return; if (pDb == nullptr) { const char * msg = sqlite3_errstr(result); throw SQLiteException(msg); } const char * msg = sqlite3_errmsg(pDb); throw SQLiteException(msg); } SQLitePreparedStatement Prepare(const char* query) { SQLitePreparedStatement stmt; stmt.Open(*this, query); return stmt; } SQLitePreparedStatement Prepare(const QString &query) { SQLitePreparedStatement stmt; stmt.Open(*this, query); return stmt; } void Exec(const char* query) { SQLitePreparedStatement stmt = Prepare(query); stmt.Step(); } void Exec(QString query) { SQLitePreparedStatement stmt = Prepare(query.toUtf8().constData()); stmt.Step(); } int64_t LastInsertRowId() { return sqlite3_last_insert_rowid(pDb); } private: sqlite3 *pDb = nullptr; friend class SQLitePreparedStatement; };