Skip to content

Commit

Permalink
[core, db] Add templates for db::preparedStmt and db::binder
Browse files Browse the repository at this point in the history
  • Loading branch information
zach2good committed Dec 18, 2023
1 parent e37b420 commit 6c5bca6
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 31 deletions.
33 changes: 5 additions & 28 deletions src/common/database.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ namespace
std::unordered_map<PreparedStatement, std::pair<std::string, std::unique_ptr<sql::PreparedStatement>>> preparedStatements;
} // namespace

std::unordered_map<PreparedStatement, std::pair<std::string, std::unique_ptr<sql::PreparedStatement>>>& db::getPreparedStatements()
{
return preparedStatements;
}

void db::populatePreparedStatements(std::unique_ptr<sql::Connection>& conn)
{
TracyZoneScoped;
Expand Down Expand Up @@ -94,31 +99,3 @@ std::unique_ptr<sql::ResultSet> db::query(std::string_view query)
return nullptr;
}
}

std::unique_ptr<sql::ResultSet> db::preparedStmt(PreparedStatement preparedStmt, uint32 id)
{
TracyZoneScoped;

// TODO: Check this is pooled. If not; make it pooled.
static thread_local auto conn = getConnection();

if (preparedStatements.find(preparedStmt) == preparedStatements.end())
{
ShowError("Bad prepared stmt");
return nullptr;
}

auto& stmt = preparedStatements[preparedStmt].second;
try
{
// NOTE: 1-indexed!
stmt->setUInt(1, id);
return std::unique_ptr<sql::ResultSet>(stmt->executeQuery());
}
catch (const std::exception& e)
{
ShowError("Query Failed: %s", str(preparedStatements[preparedStmt].first.c_str()));
ShowError(e.what());
return nullptr;
}
}
86 changes: 83 additions & 3 deletions src/common/database.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,94 @@ enum class PreparedStatement
// will be clearer if we use it too.
namespace db
{
std::unordered_map<PreparedStatement, std::pair<std::string, std::unique_ptr<sql::PreparedStatement>>>& getPreparedStatements();

void populatePreparedStatements(std::unique_ptr<sql::Connection>& conn);

auto getConnection() -> std::unique_ptr<sql::Connection>;

// WARNING: Everything in database-land is 1-indexed, not 0-indexed.
auto query(std::string_view query) -> std::unique_ptr<sql::ResultSet>;

// TODO: Template voodoo
// WARNING: Everything in database-land is 1-indexed, not 0-indexed.
auto preparedStmt(PreparedStatement preparedStmt, uint32 id) -> std::unique_ptr<sql::ResultSet>;
// Base case
inline void binder(std::unique_ptr<sql::PreparedStatement>&, int&)
{
}

template <typename T, typename... Args>
void binder(std::unique_ptr<sql::PreparedStatement>& stmt, int& counter, const T& first, const Args&&... rest)
{
if constexpr (std::is_same_v<std::decay_t<T>, signed int>)
{
stmt->setInt(counter, first);
}
else if constexpr (std::is_same_v<std::decay_t<T>, unsigned int>)
{
stmt->setUInt(counter, first);
}
else if constexpr (std::is_same_v<T, signed short>)
{
stmt->setShort(counter, first);
}
else if constexpr (std::is_same_v<T, int8>)
{
stmt->setByte(counter, first);
}
else if constexpr (std::is_same_v<std::decay_t<T>, std::string>)
{
stmt->setString(counter, first);
}
else if constexpr (std::is_same_v<T, bool>)
{
stmt->setBoolean(counter, first);
}
else if constexpr (std::is_same_v<T, double>)
{
stmt->setBoolean(counter, first);
}
else if constexpr (std::is_same_v<T, float>)
{
stmt->setBoolean(counter, first);
}
else if constexpr (std::is_convertible_v<T, const char*>)
{
stmt->setString(counter, first);
}

++counter;

binder(stmt, counter, rest...);
}

template <typename... Args>
std::unique_ptr<sql::ResultSet> preparedStmt(PreparedStatement preparedStmt, Args&&... args)
{
TracyZoneScoped;

// TODO: Check this is pooled. If not; make it pooled.
static thread_local auto conn = getConnection();

auto& preparedStatements = getPreparedStatements();

if (preparedStatements.find(preparedStmt) == preparedStatements.end())
{
ShowError("Bad prepared stmt");
return nullptr;
}

auto& stmt = preparedStatements[preparedStmt].second;
try
{
// NOTE: 1-indexed!
auto counter = 1;
binder(stmt, counter, std::forward<Args>(args)...);
return std::unique_ptr<sql::ResultSet>(stmt->executeQuery());
}
catch (const std::exception& e)
{
ShowError("Query Failed: %s", str(preparedStatements[preparedStmt].first.c_str()));
ShowError(e.what());
return nullptr;
}
}
} // namespace db

0 comments on commit 6c5bca6

Please sign in to comment.