From 355c6fccd31aae80714bc7a8d0d121d98c209304 Mon Sep 17 00:00:00 2001 From: heinrich5991 Date: Wed, 21 Apr 2021 13:21:25 +0200 Subject: [PATCH] Add sqlite3 to the client --- CMakeLists.txt | 5 ++- src/engine/client/sqlite.cpp | 60 ++++++++++++++++++++++++++++++++++++ src/engine/sqlite.h | 28 +++++++++++++++++ 3 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 src/engine/client/sqlite.cpp create mode 100644 src/engine/sqlite.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 3b80bf736..58abbcdde 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1508,6 +1508,7 @@ set_src(ENGINE_INTERFACE GLOB src/engine server.h serverbrowser.h sound.h + sqlite.h steam.h storage.h textrender.h @@ -1646,6 +1647,7 @@ set(DEPS ${DEP_JSON} ${DEP_MD5} ${ZLIB_DEP}) # Libraries set(LIBS ${CRYPTO_LIBRARIES} + ${SQLite3_LIBRARIES} ${WEBSOCKETS_LIBRARIES} ${ZLIB_LIBRARIES} ${PLATFORM_LIBS} @@ -1734,6 +1736,7 @@ if(CLIENT) serverbrowser_http.h sound.cpp sound.h + sqlite.cpp steam.cpp text.cpp updater.cpp @@ -2080,7 +2083,6 @@ endif() set(LIBS_SERVER ${LIBS} ${MYSQL_LIBRARIES} - ${SQLite3_LIBRARIES} ${TARGET_ANTIBOT} ${MINIUPNPC_LIBRARIES} # Add pthreads (on non-Windows) at the end, so that other libraries can depend @@ -2227,6 +2229,7 @@ if(GTEST_FOUND OR DOWNLOAD_GTEST) src/engine/client/serverbrowser.h src/engine/client/serverbrowser_http.cpp src/engine/client/serverbrowser_http.h + src/engine/client/sqlite.cpp src/engine/server/name_ban.cpp src/engine/server/name_ban.h src/game/server/teehistorian.cpp diff --git a/src/engine/client/sqlite.cpp b/src/engine/client/sqlite.cpp new file mode 100644 index 000000000..a6bb6f8b4 --- /dev/null +++ b/src/engine/client/sqlite.cpp @@ -0,0 +1,60 @@ +#include +#include +#include + +#include + +void CSqliteDeleter::operator()(sqlite3 *pSqlite) +{ + sqlite3_close(pSqlite); +} + +void CSqliteStmtDeleter::operator()(sqlite3_stmt *pStmt) +{ + sqlite3_finalize(pStmt); +} + +int SqliteHandleError(IConsole *pConsole, int Error, sqlite3 *pSqlite, const char *pContext) +{ + if(Error != SQLITE_OK && Error != SQLITE_DONE && Error != SQLITE_ROW) + { + char aBuf[512]; + str_format(aBuf, sizeof(aBuf), "%s at %s", sqlite3_errmsg(pSqlite), pContext); + pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "sqlite3", aBuf); + } + return Error; +} + +CSqlite SqliteOpen(IConsole *pConsole, IStorage *pStorage, const char *pPath) +{ + char aFullPath[MAX_PATH_LENGTH]; + pStorage->GetCompletePath(IStorage::TYPE_SAVE, pPath, aFullPath, sizeof(aFullPath)); + sqlite3 *pSqlite = nullptr; + bool ErrorOpening = SQLITE_HANDLE_ERROR(sqlite3_open(aFullPath, &pSqlite)) != SQLITE_OK; + // Even on error, the database is initialized and needs to be freed. + // Except on allocation failure, but then it'll be nullptr which is + // also fine. + CSqlite pResult{pSqlite}; + if(ErrorOpening) + { + return nullptr; + } + bool Error = false; + Error = Error || SQLITE_HANDLE_ERROR(sqlite3_exec(pSqlite, "PRAGMA journal_mode = WAL", nullptr, nullptr, nullptr)); + Error = Error || SQLITE_HANDLE_ERROR(sqlite3_exec(pSqlite, "PRAGMA synchronous = NORMAL", nullptr, nullptr, nullptr)); + if(Error) + { + return nullptr; + } + return pResult; +} + +CSqliteStmt SqlitePrepare(IConsole *pConsole, sqlite3 *pSqlite, const char *pStatement) +{ + sqlite3_stmt *pTemp; + if(SQLITE_HANDLE_ERROR(sqlite3_prepare_v2(pSqlite, pStatement, -1, &pTemp, nullptr))) + { + return nullptr; + } + return CSqliteStmt{pTemp}; +} diff --git a/src/engine/sqlite.h b/src/engine/sqlite.h new file mode 100644 index 000000000..562e8d436 --- /dev/null +++ b/src/engine/sqlite.h @@ -0,0 +1,28 @@ +#ifndef ENGINE_SQLITE_H +#define ENGINE_SQLITE_H +#include + +typedef struct sqlite3 sqlite3; +typedef struct sqlite3_stmt sqlite3_stmt; +class IConsole; +class IStorage; + +class CSqliteDeleter +{ +public: + void operator()(sqlite3 *pSqlite); +}; +class CSqliteStmtDeleter +{ +public: + void operator()(sqlite3_stmt *pStmt); +}; +typedef std::unique_ptr CSqlite; +typedef std::unique_ptr CSqliteStmt; + +int SqliteHandleError(IConsole *pConsole, int Error, sqlite3 *pSqlite, const char *pContext); +#define SQLITE_HANDLE_ERROR(x) SqliteHandleError(pConsole, x, &*pSqlite, #x) + +CSqlite SqliteOpen(IConsole *pConsole, IStorage *pStorage, const char *pPath); +CSqliteStmt SqlitePrepare(IConsole *pConsole, sqlite3 *pSqlite, const char *pStatement); +#endif // ENGINE_SQLITE_H