1#include <base/log.h>
2#include <base/str.h>
3#include <base/types.h>
4
5#include <engine/sqlite.h>
6#include <engine/storage.h>
7
8#include <sqlite3.h>
9
10void CSqliteDeleter::operator()(sqlite3 *pSqlite)
11{
12 sqlite3_close(pSqlite);
13}
14
15void CSqliteStmtDeleter::operator()(sqlite3_stmt *pStmt)
16{
17 sqlite3_finalize(pStmt);
18}
19
20int SqliteHandleError(int Error, sqlite3 *pSqlite, const char *pContext)
21{
22 if(Error != SQLITE_OK && Error != SQLITE_DONE && Error != SQLITE_ROW)
23 {
24 log_error("sqlite3", "%s at %s", sqlite3_errmsg(pSqlite), pContext);
25 }
26 return Error;
27}
28
29CSqlite SqliteOpen(IStorage *pStorage, const char *pPath)
30{
31 char aFullPath[IO_MAX_PATH_LENGTH];
32 pStorage->GetCompletePath(Type: IStorage::TYPE_SAVE, pDir: pPath, pBuffer: aFullPath, BufferSize: sizeof(aFullPath));
33 sqlite3 *pSqlite = nullptr;
34 const bool ErrorOpening = SQLITE_HANDLE_ERROR(sqlite3_open(aFullPath, &pSqlite)) != SQLITE_OK;
35 // Even on error, the database is initialized and needs to be freed.
36 // Except on allocation failure, but then it'll be nullptr which is
37 // also fine.
38 CSqlite pResult{pSqlite};
39 if(ErrorOpening)
40 {
41 return nullptr;
42 }
43 bool Error = false;
44 Error = Error || SQLITE_HANDLE_ERROR(sqlite3_exec(pSqlite, "PRAGMA journal_mode = WAL", nullptr, nullptr, nullptr));
45 Error = Error || SQLITE_HANDLE_ERROR(sqlite3_exec(pSqlite, "PRAGMA synchronous = NORMAL", nullptr, nullptr, nullptr));
46 if(Error)
47 {
48 return nullptr;
49 }
50 return pResult;
51}
52
53CSqliteStmt SqlitePrepare(sqlite3 *pSqlite, const char *pStatement)
54{
55 sqlite3_stmt *pTemp;
56 if(SQLITE_HANDLE_ERROR(sqlite3_prepare_v2(pSqlite, pStatement, -1, &pTemp, nullptr)))
57 {
58 return nullptr;
59 }
60 return CSqliteStmt{pTemp};
61}
62