From 620e246d42910041dd5a9eae11f03aebc3bd38d3 Mon Sep 17 00:00:00 2001 From: nekobit Date: Sat, 8 Oct 2022 05:43:17 +0000 Subject: [PATCH] Bind types FossilOrigin-Name: 8881ec4fc258c93b327f367bf0a7da27460d6347b322b4b9ebd7c85e07a3c30a --- src/database/sqlite/sqlite.cpp | 71 +++++++++++++++++++++++++++++----- src/database/sqlite/sqlite.h | 12 +++++- 2 files changed, 72 insertions(+), 11 deletions(-) diff --git a/src/database/sqlite/sqlite.cpp b/src/database/sqlite/sqlite.cpp index 277ee15..609d980 100644 --- a/src/database/sqlite/sqlite.cpp +++ b/src/database/sqlite/sqlite.cpp @@ -21,6 +21,7 @@ #include #include "sqlite.h" #include +#include using namespace DB; @@ -28,7 +29,7 @@ SQLite::SQLite(std::filesystem::path path) : DB::Database(), path{std::move(path)}, db{nullptr}, - sql_cache(), + sql_cache() { using namespace std::string_literals; if (sqlite3_open(this->path.c_str(), &db)) @@ -46,14 +47,65 @@ SQLite::~SQLite() sqlite3_close(db); } -void SQLite::sqlite_exec(SQLiteCacheIndex idx) +void SQLite::sqlite_exec(SQLiteCacheIndex idx, + std::initializer_list keys, + std::function func) { + using namespace std::string_literals; + + int code; sqlite3_stmt* stmt = sql_cache[idx]; - while () - {} + Logger::instance().log("Executing query: "s + sqlite3_sql(stmt), Logger::Level::DEBUG); + + int key_i = 1; + for (auto& key: keys) + { + std::visit([&code, stmt, key_i](auto&& arg) { + using T = decltype(arg); + if constexpr (std::is_same_v) + code = sqlite3_bind_int(stmt, key_i, arg); + else if constexpr (std::is_same_v) + code = sqlite3_bind_int64(stmt, key_i, static_cast(arg)); + else if constexpr (std::is_same_v) + code = sqlite3_bind_double(stmt, key_i, arg); + else if constexpr (std::is_same_v) + code = sqlite3_bind_text(stmt, key_i, arg.c_str()); + }, key); + + if (code != SQLITE_OK) + { + const std::string err_msg = "Couldn't bind argument: "s + std::string(sqlite3_errmsg(db)); + sqlite3_reset(stmt); + throw std::runtime_error(err_msg); + } + + ++key_i; + } + + while ((code = sqlite3_step(stmt)) == SQLITE_ROW) + { + func(stmt); + } + + switch (code) + { + case SQLITE_BUSY: + Logger::instance().log("SQLite database is busy!", Logger::Level::DEBUG); + break; + case SQLITE_ERROR: + case SQLITE_MISUSE: + { + const std::string err_msg = "Couldn't exec query: "s + std::string(sqlite3_errmsg(db)); + sqlite3_reset(stmt); + throw std::runtime_error(err_msg); + } + case SQLITE_DONE: + default: + break; + } - if (code == SQLITE_DONE) sqlite3_reset(stmt); + sqlite3_reset(stmt); } SQLiteCacheIndex SQLite::sqlite_compile_to_cache(SQLiteCacheIndex idx, std::string_view sql) @@ -74,17 +126,16 @@ SQLiteCacheIndex SQLite::sqlite_compile_to_cache(SQLiteCacheIndex idx, std::stri Types::User SQLite::get_user(unsigned long id) { - Types::User luser{id, {}, false, {}, {}, {}}; - int code = 0; // Setup function - sqlite_compile_to_cache("SELECT acct FROM users WHERE id=?1"); + sqlite_compile_to_cache(GET_USER_BY_ID, "SELECT acct FROM users WHERE id=?1"); - sqlite_exec({id}, [luser](){ + sqlite_exec(GET_USER_BY_ID, + {id}, + [&luser](sqlite3_stmt* stmt){ luser.acct = reinterpret_cast(sqlite3_column_text(stmt, 0)); }); - return luser; } diff --git a/src/database/sqlite/sqlite.h b/src/database/sqlite/sqlite.h index 95e80b5..b88c7de 100644 --- a/src/database/sqlite/sqlite.h +++ b/src/database/sqlite/sqlite.h @@ -19,6 +19,9 @@ #pragma once #include #include +#include +#include +#include #include #include #include @@ -27,6 +30,11 @@ namespace DB { + using SQLiteBindType_t = std::variant; + enum SQLiteCacheIndex { GET_USER_BY_ID, GET_USER_BY_ACCT, @@ -43,7 +51,9 @@ namespace DB virtual Types::User get_user(unsigned long id) override; virtual Types::User get_user(const std::string& acct) override; private: - void sqlite_exec(SQLiteCacheIndex idx, std::function func); + void sqlite_exec(SQLiteCacheIndex idx, + std::initializer_list keys, + std::function func); SQLiteCacheIndex sqlite_compile_to_cache(SQLiteCacheIndex idx, std::string_view sql); std::array sql_cache;