#include "pch.h" #include "CSQLite/CSQLite.h" #include "aLog.h" int CSQLiteDB::open(const char* apFilename, const int aFlags) noexcept { mFilename = apFilename; dbErrCode = sqlite3_open_v2(apFilename, &mpSQLite, aFlags, nullptr); if (SQLITE_OK != dbErrCode) { dbErrMsg = sqlite3_errmsg(mpSQLite); sqlite3_close(mpSQLite); // close is required even in case of error on opening mpSQLite = nullptr; } return dbErrCode; } int CSQLiteDB::open(const std::string &apFilename, const int aFlags) noexcept { mFilename = apFilename; dbErrCode = sqlite3_open_v2(apFilename.c_str(), &mpSQLite, aFlags, nullptr); if (SQLITE_OK != dbErrCode) { dbErrMsg = sqlite3_errmsg(mpSQLite); sqlite3_close(mpSQLite); // close is required even in case of error on opening mpSQLite = nullptr; } return dbErrCode; } int CSQLiteDB::openInRam(const char* apFilename) { UNUSED(apFilename); return dbErrCode; } int CSQLiteDB::close() { if(bInTransaction) { // 没有主动Commit,就Rollback(); Rollback(); } bInTransaction = false; int ret =0; if(mpSQLite){ ret = sqlite3_close(mpSQLite); if(SQLITE_OK != ret){ switch (ret) { case SQLITE_MISUSE: alog->error("CSQLiteDB::close(): Library used incorrectly {}, {}", ret, mFilename); break; case SQLITE_BUSY: alog->error("CSQLiteDB::close(): database is locked {}, {}", ret, mFilename); break; default: alog->error("CSQLiteDB::close(): database close error {}, {}", ret, mFilename); break; } } mpSQLite = nullptr; } return ret; } /** * @brief Set a busy handler that sleeps for a specified amount of time when a table is locked. * * This is useful in multithreaded program to handle case where a table is locked for writting by a thread. * Any other thread cannot access the table and will receive a SQLITE_BUSY error: * setting a timeout will wait and retry up to the time specified before returning this SQLITE_BUSY error. * Reading the value of timeout for current connection can be done with SQL query "PRAGMA busy_timeout;". * Default busy timeout is 0ms. * * @param[in] aBusyTimeoutMs Amount of milliseconds to wait before returning SQLITE_BUSY * * @throw SQLite::Exception in case of error */ void CSQLiteDB::setBusyTimeout(const int aBusyTimeoutMs) { const int ret = sqlite3_busy_timeout(mpSQLite, aBusyTimeoutMs); check(ret); } // Shortcut to execute one or multiple SQL statements without results (UPDATE, INSERT, ALTER, COMMIT, CREATE...). int CSQLiteDB::exec(const char* apQueries) { const int ret = sqlite3_exec(mpSQLite, apQueries, nullptr, nullptr, nullptr); check(ret); // Return the number of rows modified by those SQL statements (INSERT, UPDATE or DELETE only) return sqlite3_changes(mpSQLite); } // Shortcut to test if a table exists. bool CSQLiteDB::tableExists(const char* apTableName) { CSQLiteStatement query(*this, "SELECT count(*) FROM sqlite_master WHERE type='table' AND name=?"); query.bind(1, apTableName); (void)query.executeStep(); // Cannot return false, as the above query always return a result return (1 == query.getColumn(0).getInt()); }