Skip to content

Commit

Permalink
[core] Add db::lazyPreparedStmt and db::extractBlob
Browse files Browse the repository at this point in the history
  • Loading branch information
zach2good committed Dec 19, 2023
1 parent f898701 commit 3bca4a1
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 26 deletions.
6 changes: 6 additions & 0 deletions src/common/database.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,19 @@
namespace
{
std::unordered_map<PreparedStatement, std::pair<std::string, std::unique_ptr<sql::PreparedStatement>>> preparedStatements;
std::unordered_map<std::string, std::unique_ptr<sql::PreparedStatement>> lazyPreparedStatements;
} // namespace

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

std::unordered_map<std::string, std::unique_ptr<sql::PreparedStatement>>& db::getLazyPreparedStatements()
{
return lazyPreparedStatements;
}

void db::populatePreparedStatements(std::unique_ptr<sql::Connection>& conn)
{
TracyZoneScoped;
Expand Down
56 changes: 56 additions & 0 deletions src/common/database.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ enum class PreparedStatement
namespace db
{
std::unordered_map<PreparedStatement, std::pair<std::string, std::unique_ptr<sql::PreparedStatement>>>& getPreparedStatements();
std::unordered_map<std::string, std::unique_ptr<sql::PreparedStatement>>& getLazyPreparedStatements();

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

Expand Down Expand Up @@ -128,4 +129,59 @@ namespace db
return nullptr;
}
}

template <typename... Args>
std::unique_ptr<sql::ResultSet> lazyPreparedStmt(std::string const& query, Args&&... args)
{
TracyZoneScoped;

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

auto& lazyPreparedStatements = getLazyPreparedStatements();

// If we don't have it, lazily make it
if (lazyPreparedStatements.find(query) == lazyPreparedStatements.end())
{
try
{
lazyPreparedStatements[query] = std::unique_ptr<sql::PreparedStatement>(conn->prepareStatement(query.c_str()));
}
catch (const std::exception& e)
{
ShowError("Failed to lazy prepare query: %s", str(query.c_str()));
ShowError(e.what());
return nullptr;
}
}

auto& stmt = lazyPreparedStatements[query];
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(query.c_str()));
ShowError(e.what());
return nullptr;
}
}

template <typename T>
void extractBlob(std::unique_ptr<sql::ResultSet>& rset, std::string const& blobKey, T* destination)
{
std::unique_ptr<std::istream> inStr(rset->getBlob(blobKey.c_str()));

char buff[sizeof(T)];
while (!inStr->eof())
{
inStr->read(buff, sizeof(buff));
}

std::memcpy(destination, buff, sizeof(T));
}
} // namespace db
51 changes: 25 additions & 26 deletions src/map/utils/charutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,8 @@ namespace charutils

void LoadChar(CCharEntity* PChar)
{
TracyZoneScoped;

uint8 meritPoints = 0;
uint16 limitPoints = 0;
int32 HP = 0;
Expand Down Expand Up @@ -955,37 +957,34 @@ namespace charutils

void LoadInventory(CCharEntity* PChar)
{
const char* Query = "SELECT "
"itemid," // 0
"location," // 1
"slot," // 2
"quantity," // 3
"bazaar," // 4
"signature, " // 5
"extra " // 6
"FROM char_inventory "
"WHERE charid = %u "
"ORDER BY FIELD(location,0,1,9,2,3,4,5,6,7,8,10,11,12)";
TracyZoneScoped;

int32 ret = _sql->Query(Query, PChar->id);
const char* query = "SELECT "
"itemid, "
"location, "
"slot, "
"quantity, "
"bazaar, "
"signature, "
"extra "
"FROM char_inventory "
"WHERE charid = (?) "
"ORDER BY FIELD(location,0,1,9,2,3,4,5,6,7,8,10,11,12);";

if (ret != SQL_ERROR && _sql->NumRows() != 0)
auto rset = db::lazyPreparedStmt(query, PChar->id);
if (rset && rset->rowsCount())
{
while (_sql->NextRow() == SQL_SUCCESS)
while (rset->next())
{
CItem* PItem = itemutils::GetItem(_sql->GetIntData(0));

CItem* PItem = itemutils::GetItem(rset->getInt("itemid"));
if (PItem != nullptr)
{
PItem->setLocationID((uint8)_sql->GetUIntData(1));
PItem->setSlotID(_sql->GetUIntData(2));
PItem->setQuantity(_sql->GetUIntData(3));
PItem->setCharPrice(_sql->GetUIntData(4));
PItem->setLocationID((uint8)rset->getUInt("location"));
PItem->setSlotID(rset->getUInt("slot"));
PItem->setQuantity(rset->getUInt("quantity"));
PItem->setCharPrice(rset->getUInt("bazaar"));

size_t length = 0;
char* extra = nullptr;
_sql->GetData(6, &extra, &length);
memcpy(PItem->m_extra, extra, (length > sizeof(PItem->m_extra) ? sizeof(PItem->m_extra) : length));
db::extractBlob(rset, "extra", PItem->m_extra);

if (PItem->getCharPrice() != 0)
{
Expand All @@ -999,13 +998,13 @@ namespace charutils
static_cast<CItemLinkshell*>(PItem)->SetLSType((LSTYPE)(PItem->getID() - 0x200));
}
char EncodedString[LinkshellStringLength] = {};
EncodeStringLinkshell(_sql->GetStringData(5).c_str(), EncodedString);
EncodeStringLinkshell(rset->getString("signature").c_str(), EncodedString);
PItem->setSignature(EncodedString);
}
else if (PItem->getFlag() & (ITEM_FLAG_INSCRIBABLE))
{
char EncodedString[SignatureStringLength] = {};
EncodeStringSignature(_sql->GetStringData(5).c_str(), EncodedString);
EncodeStringSignature(rset->getString("signature").c_str(), EncodedString);
PItem->setSignature(EncodedString);
}

Expand Down

0 comments on commit 3bca4a1

Please sign in to comment.