Bind types

FossilOrigin-Name: 8881ec4fc258c93b327f367bf0a7da27460d6347b322b4b9ebd7c85e07a3c30a
This commit is contained in:
nekobit 2022-10-08 05:43:17 +00:00
parent 42d243674c
commit 620e246d42
2 changed files with 72 additions and 11 deletions

View file

@ -21,6 +21,7 @@
#include <utility>
#include "sqlite.h"
#include <logger.h>
#include <variant>
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<SQLiteBindType_t> keys,
std::function<void(sqlite3_stmt*)> 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<T, int>)
code = sqlite3_bind_int(stmt, key_i, arg);
else if constexpr (std::is_same_v<T, unsigned long>)
code = sqlite3_bind_int64(stmt, key_i, static_cast<unsigned long>(arg));
else if constexpr (std::is_same_v<T, double>)
code = sqlite3_bind_double(stmt, key_i, arg);
else if constexpr (std::is_same_v<T, std::string>)
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<const char*>(sqlite3_column_text(stmt, 0));
});
return luser;
}

View file

@ -19,6 +19,9 @@
#pragma once
#include <array>
#include <functional>
#include <initializer_list>
#include <utility>
#include <variant>
#include <filesystem>
#include <memory>
#include <sqlite3.h>
@ -27,6 +30,11 @@
namespace DB
{
using SQLiteBindType_t = std::variant<double,
int,
unsigned long,
std::string>;
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<void(sqlite3_stmt*)> func);
void sqlite_exec(SQLiteCacheIndex idx,
std::initializer_list<SQLiteBindType_t> keys,
std::function<void(sqlite3_stmt*)> func);
SQLiteCacheIndex sqlite_compile_to_cache(SQLiteCacheIndex idx, std::string_view sql);
std::array<sqlite3_stmt*, SQLiteCacheIndex::COUNT> sql_cache;