db: prepare client manager queries

This commit is contained in:
server
2026-04-13 22:55:56 +02:00
parent fd3d8c0746
commit fce6268129

View File

@@ -40,19 +40,39 @@ int g_query_count[2];
namespace
{
bool PrepareClientPlayerStmt(CStmt& stmt, const std::string& query)
bool PrepareClientStmt(CStmt& stmt, const std::string& query, int slot)
{
CAsyncSQL* sql = CDBManager::instance().GetDirectSQL(SQL_PLAYER);
CAsyncSQL* sql = CDBManager::instance().GetDirectSQL(slot);
if (!sql)
{
sys_err("player SQL handle is not initialized");
sys_err("SQL handle is not initialized for slot %d", slot);
return false;
}
return stmt.Prepare(sql, query.c_str());
}
bool PrepareClientPlayerStmt(CStmt& stmt, const std::string& query)
{
return PrepareClientStmt(stmt, query, SQL_PLAYER);
}
bool PrepareClientCommonStmt(CStmt& stmt, const std::string& query)
{
return PrepareClientStmt(stmt, query, SQL_COMMON);
}
template <size_t N>
void NullTerminateClientResult(char (&buffer)[N], unsigned long length)
{
size_t finalLength = length;
if (finalLength >= N)
finalLength = N - 1;
buffer[finalLength] = '\0';
}
bool LoadSafeboxPassword(uint32_t accountId, char* password, size_t passwordSize, bool* foundRow)
{
CStmt stmt;
@@ -711,8 +731,10 @@ void CClientManager::RESULT_SAFEBOX_LOAD(CPeer * pkPeer, SQLMsg * msg)
std::vector<std::pair<DWORD, DWORD> > vec_dwFinishedAwardID;
__typeof(pSet->begin()) it = pSet->begin();
char szQuery[512];
const char* itemWindowName = pi->ip[0] == 0 ? "SAFEBOX" : "MALL";
const std::string insertAwardItemQuery = std::string(
"INSERT INTO item") + GetTablePostfix()
+ " (id, owner_id, window, pos, vnum, count, socket0, socket1, socket2) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)";
while (it != pSet->end())
{
@@ -841,25 +863,37 @@ void CClientManager::RESULT_SAFEBOX_LOAD(CPeer * pkPeer, SQLMsg * msg)
}
}
snprintf(szQuery, sizeof(szQuery),
"INSERT INTO item%s (id, owner_id, window, pos, vnum, count, socket0, socket1, socket2) "
"VALUES(%u, %u, '%s', %d, %u, %u, %u, %u, %u)",
GetTablePostfix(),
GainItemID(),
pi->account_id,
pi->ip[0] == 0 ? "SAFEBOX" : "MALL",
iPos,
pItemAward->dwVnum, pItemAward->dwCount, pItemAward->dwSocket0, pItemAward->dwSocket1, dwSocket2);
uint32_t itemId = GainItemID();
int32_t pos = iPos;
uint32_t ownerId = pi->account_id;
uint32_t vnum = pItemAward->dwVnum;
uint32_t count = pItemAward->dwCount;
uint32_t socket0 = pItemAward->dwSocket0;
uint32_t socket1 = pItemAward->dwSocket1;
uint32_t socket2 = dwSocket2;
CStmt insertAwardItemStmt;
if (!PrepareClientPlayerStmt(insertAwardItemStmt, insertAwardItemQuery)
|| !insertAwardItemStmt.BindParam(MYSQL_TYPE_LONG, &itemId)
|| !insertAwardItemStmt.BindParam(MYSQL_TYPE_LONG, &ownerId)
|| !insertAwardItemStmt.BindParam(MYSQL_TYPE_STRING, const_cast<char*>(itemWindowName), static_cast<int>(strlen(itemWindowName)))
|| !insertAwardItemStmt.BindParam(MYSQL_TYPE_LONG, &pos)
|| !insertAwardItemStmt.BindParam(MYSQL_TYPE_LONG, &vnum)
|| !insertAwardItemStmt.BindParam(MYSQL_TYPE_LONG, &count)
|| !insertAwardItemStmt.BindParam(MYSQL_TYPE_LONG, &socket0)
|| !insertAwardItemStmt.BindParam(MYSQL_TYPE_LONG, &socket1)
|| !insertAwardItemStmt.BindParam(MYSQL_TYPE_LONG, &socket2)
|| !insertAwardItemStmt.Execute())
{
break;
}
sys_log(0, "SAFEBOX insert: owner=%u window=%s pos=%d vnum=%u count=%u id=%u",
ownerId, itemWindowName, pos, vnum, count, itemId);
item.id = itemId;
}
auto pmsg = CDBManager::instance().DirectQuery(szQuery);
SQLResult * pRes = pmsg->Get();
sys_log(0, "SAFEBOX Query : [%s]", szQuery);
if (pRes->uiAffectedRows == 0 || pRes->uiInsertID == 0 || pRes->uiAffectedRows == (uint32_t)-1)
break;
item.id = pmsg->Get()->uiInsertID;
item.window = pi->ip[0] == 0 ? SAFEBOX : MALL,
item.pos = iPos;
item.count = pItemAward->dwCount;
@@ -1100,7 +1134,6 @@ void CClientManager::QUERY_EMPIRE_SELECT(CPeer * pkPeer, DWORD dwHandle, TEmpire
}
else if (playerIndexStmt.iRows && playerIndexStmt.Fetch())
{
CStmt moveEmpirePlayerStmt;
const std::string moveEmpirePlayerQuery = std::string("UPDATE player") + GetTablePostfix()
+ " SET map_index=?,x=?,y=? WHERE id=?";
@@ -1121,11 +1154,7 @@ void CClientManager::QUERY_EMPIRE_SELECT(CPeer * pkPeer, DWORD dwHandle, TEmpire
{ 969600, 278400 } // 진노국
};
if (!PrepareClientPlayerStmt(moveEmpirePlayerStmt, moveEmpirePlayerQuery))
{
sys_err("EmpireSelect: failed to prepare player move query");
}
else for (int i = 0; i < 3; ++i)
for (int i = 0; i < 3; ++i)
{
sys_log(0, "EMPIRE PIDS[%u]", pids[i]);
@@ -1138,8 +1167,10 @@ void CClientManager::QUERY_EMPIRE_SELECT(CPeer * pkPeer, DWORD dwHandle, TEmpire
uint32_t x = g_start_position[p->bEmpire][0];
uint32_t y = g_start_position[p->bEmpire][1];
uint32_t playerId = pids[i];
CStmt moveEmpirePlayerStmt;
if (!moveEmpirePlayerStmt.BindParam(MYSQL_TYPE_LONG, &mapIndex)
if (!PrepareClientPlayerStmt(moveEmpirePlayerStmt, moveEmpirePlayerQuery)
|| !moveEmpirePlayerStmt.BindParam(MYSQL_TYPE_LONG, &mapIndex)
|| !moveEmpirePlayerStmt.BindParam(MYSQL_TYPE_LONG, &x)
|| !moveEmpirePlayerStmt.BindParam(MYSQL_TYPE_LONG, &y)
|| !moveEmpirePlayerStmt.BindParam(MYSQL_TYPE_LONG, &playerId)
@@ -1883,15 +1914,21 @@ void CClientManager::CreateObject(TPacketGDCreateObject * p)
{
using namespace building;
char szQuery[512];
CStmt stmt;
const std::string query = std::string("INSERT INTO object") + GetTablePostfix()
+ " (land_id, vnum, map_index, x, y, x_rot, y_rot, z_rot) VALUES(?, ?, ?, ?, ?, ?, ?, ?)";
snprintf(szQuery, sizeof(szQuery),
"INSERT INTO object%s (land_id, vnum, map_index, x, y, x_rot, y_rot, z_rot) VALUES(%u, %u, %d, %d, %d, %f, %f, %f)",
GetTablePostfix(), p->dwLandID, p->dwVnum, p->lMapIndex, p->x, p->y, p->xRot, p->yRot, p->zRot);
auto pmsg = CDBManager::instance().DirectQuery(szQuery);
if (pmsg->Get()->uiInsertID == 0)
if (!PrepareClientPlayerStmt(stmt, query)
|| !stmt.BindParam(MYSQL_TYPE_LONG, &p->dwLandID)
|| !stmt.BindParam(MYSQL_TYPE_LONG, &p->dwVnum)
|| !stmt.BindParam(MYSQL_TYPE_LONG, &p->lMapIndex)
|| !stmt.BindParam(MYSQL_TYPE_LONG, &p->x)
|| !stmt.BindParam(MYSQL_TYPE_LONG, &p->y)
|| !stmt.BindParam(MYSQL_TYPE_FLOAT, &p->xRot)
|| !stmt.BindParam(MYSQL_TYPE_FLOAT, &p->yRot)
|| !stmt.BindParam(MYSQL_TYPE_FLOAT, &p->zRot)
|| !stmt.Execute()
|| stmt.GetInsertId() == 0)
{
sys_err("cannot insert object");
return;
@@ -1901,7 +1938,7 @@ void CClientManager::CreateObject(TPacketGDCreateObject * p)
memset(pkObj, 0, sizeof(TObject));
pkObj->dwID = pmsg->Get()->uiInsertID;
pkObj->dwID = static_cast<uint32_t>(stmt.GetInsertId());
pkObj->dwVnum = p->dwVnum;
pkObj->dwLandID = p->dwLandID;
pkObj->lMapIndex = p->lMapIndex;
@@ -1919,13 +1956,14 @@ void CClientManager::CreateObject(TPacketGDCreateObject * p)
void CClientManager::DeleteObject(DWORD dwID)
{
char szQuery[128];
CStmt stmt;
const std::string query = std::string("DELETE FROM object") + GetTablePostfix() + " WHERE id=?";
snprintf(szQuery, sizeof(szQuery), "DELETE FROM object%s WHERE id=%u", GetTablePostfix(), dwID);
auto pmsg = CDBManager::instance().DirectQuery(szQuery);
if (pmsg->Get()->uiAffectedRows == 0 || pmsg->Get()->uiAffectedRows == (uint32_t)-1)
if (!PrepareClientPlayerStmt(stmt, query)
|| !stmt.BindParam(MYSQL_TYPE_LONG, &dwID)
|| !stmt.Execute()
|| stmt.GetAffectedRows() == 0
|| stmt.GetAffectedRows() == static_cast<unsigned long long>(-1))
{
sys_err("no object by id %u", dwID);
return;
@@ -3067,29 +3105,31 @@ DWORD CClientManager::GetItemID()
bool CClientManager::InitializeLocalization()
{
char szQuery[512];
snprintf(szQuery, sizeof(szQuery), "SELECT mValue, mKey FROM locale");
auto pMsg = CDBManager::instance().DirectQuery(szQuery, SQL_COMMON);
CStmt stmt;
tLocale locale;
const std::string query = "SELECT COALESCE(mValue, ''), COALESCE(mKey, '') FROM locale";
if (pMsg->Get()->uiNumRows == 0)
memset(&locale, 0, sizeof(locale));
if (!PrepareClientCommonStmt(stmt, query)
|| !stmt.BindResult(MYSQL_TYPE_STRING, locale.szValue, sizeof(locale.szValue))
|| !stmt.BindResult(MYSQL_TYPE_STRING, locale.szKey, sizeof(locale.szKey))
|| !stmt.Execute()
|| stmt.iRows == 0)
{
sys_err("InitializeLocalization() ==> DirectQuery failed(%s)", szQuery);
sys_err("InitializeLocalization() ==> DirectQuery failed(%s)", query.c_str());
return false;
}
sys_log(0, "InitializeLocalization() - LoadLocaleTable(count:%d)", pMsg->Get()->uiNumRows);
sys_log(0, "InitializeLocalization() - LoadLocaleTable(count:%d)", stmt.iRows);
m_vec_Locale.clear();
m_vec_Locale.reserve(stmt.iRows);
MYSQL_ROW row = NULL;
for (int n = 0; (row = mysql_fetch_row(pMsg->Get()->pSQLResult)) != NULL; ++n)
while (stmt.Fetch())
{
int col = 0;
tLocale locale;
strlcpy(locale.szValue, row[col++], sizeof(locale.szValue));
strlcpy(locale.szKey, row[col++], sizeof(locale.szKey));
NullTerminateClientResult(locale.szValue, stmt.GetResultLength(0));
NullTerminateClientResult(locale.szKey, stmt.GetResultLength(1));
//DB_NAME_COLUMN Setting
if (strcmp(locale.szKey, "LOCALE") == 0)
@@ -3450,7 +3490,9 @@ bool CClientManager::InitializeLocalization()
{
sys_log(0, "locale[UNKNOWN_KEY(%s)] = %s", locale.szKey, locale.szValue);
}
m_vec_Locale.push_back(locale);
memset(&locale, 0, sizeof(locale));
}
return true;
@@ -3461,33 +3503,52 @@ bool CClientManager::InitializeLocalization()
bool CClientManager::__GetAdminInfo(const char *szIP, std::vector<tAdminInfo> & rAdminVec)
{
//szIP == NULL 일경우 모든서버에 운영자 권한을 갖는다.
char szQuery[512];
snprintf(szQuery, sizeof(szQuery),
"SELECT mID,mAccount,mName,mContactIP,mServerIP,mAuthority FROM gmlist WHERE mServerIP='ALL' or mServerIP='%s'",
szIP ? szIP : "ALL");
CStmt stmt;
int32_t adminId = 0;
char account[sizeof(tAdminInfo::m_szAccount)] = {};
char name[sizeof(tAdminInfo::m_szName)] = {};
char contactIP[sizeof(tAdminInfo::m_szContactIP)] = {};
char serverIP[sizeof(tAdminInfo::m_szServerIP)] = {};
char authority[32] = {};
const char* requestedServerIp = szIP ? szIP : "ALL";
const std::string query =
"SELECT mID, COALESCE(mAccount, ''), COALESCE(mName, ''), COALESCE(mContactIP, ''), COALESCE(mServerIP, ''), COALESCE(mAuthority, '') "
"FROM gmlist WHERE mServerIP='ALL' or mServerIP=?";
auto pMsg = CDBManager::instance().DirectQuery(szQuery, SQL_COMMON);
if (pMsg->Get()->uiNumRows == 0)
if (!PrepareClientCommonStmt(stmt, query)
|| !stmt.BindParam(MYSQL_TYPE_STRING, const_cast<char*>(requestedServerIp), static_cast<int>(strlen(requestedServerIp)))
|| !stmt.BindResult(MYSQL_TYPE_LONG, &adminId)
|| !stmt.BindResult(MYSQL_TYPE_STRING, account, sizeof(account))
|| !stmt.BindResult(MYSQL_TYPE_STRING, name, sizeof(name))
|| !stmt.BindResult(MYSQL_TYPE_STRING, contactIP, sizeof(contactIP))
|| !stmt.BindResult(MYSQL_TYPE_STRING, serverIP, sizeof(serverIP))
|| !stmt.BindResult(MYSQL_TYPE_STRING, authority, sizeof(authority))
|| !stmt.Execute()
|| stmt.iRows == 0)
{
sys_err("__GetAdminInfo() ==> DirectQuery failed(%s)", szQuery);
sys_err("__GetAdminInfo() ==> DirectQuery failed(%s)", query.c_str());
return false;
}
MYSQL_ROW row;
rAdminVec.reserve(pMsg->Get()->uiNumRows);
rAdminVec.reserve(stmt.iRows);
while ((row = mysql_fetch_row(pMsg->Get()->pSQLResult)))
while (stmt.Fetch())
{
int idx = 0;
tAdminInfo Info;
memset(&Info, 0, sizeof(Info));
str_to_number(Info.m_ID, row[idx++]);
trim_and_lower(row[idx++], Info.m_szAccount, sizeof(Info.m_szAccount));
strlcpy(Info.m_szName, row[idx++], sizeof(Info.m_szName));
strlcpy(Info.m_szContactIP, row[idx++], sizeof(Info.m_szContactIP));
strlcpy(Info.m_szServerIP, row[idx++], sizeof(Info.m_szServerIP));
std::string stAuth = row[idx++];
NullTerminateClientResult(account, stmt.GetResultLength(1));
NullTerminateClientResult(name, stmt.GetResultLength(2));
NullTerminateClientResult(contactIP, stmt.GetResultLength(3));
NullTerminateClientResult(serverIP, stmt.GetResultLength(4));
NullTerminateClientResult(authority, stmt.GetResultLength(5));
Info.m_ID = adminId;
trim_and_lower(account, Info.m_szAccount, sizeof(Info.m_szAccount));
strlcpy(Info.m_szName, name, sizeof(Info.m_szName));
strlcpy(Info.m_szContactIP, contactIP, sizeof(Info.m_szContactIP));
strlcpy(Info.m_szServerIP, serverIP, sizeof(Info.m_szServerIP));
std::string stAuth = authority;
if (!stAuth.compare("IMPLEMENTOR"))
Info.m_Authority = GM_IMPLEMENTOR;
@@ -3506,6 +3567,12 @@ bool CClientManager::__GetAdminInfo(const char *szIP, std::vector<tAdminInfo> &
sys_log(0, "GM: PID %u Login %s Character %s ContactIP %s ServerIP %s Authority %d[%s]",
Info.m_ID, Info.m_szAccount, Info.m_szName, Info.m_szContactIP, Info.m_szServerIP, Info.m_Authority, stAuth.c_str());
memset(account, 0, sizeof(account));
memset(name, 0, sizeof(name));
memset(contactIP, 0, sizeof(contactIP));
memset(serverIP, 0, sizeof(serverIP));
memset(authority, 0, sizeof(authority));
}
return true;
@@ -3513,27 +3580,32 @@ bool CClientManager::__GetAdminInfo(const char *szIP, std::vector<tAdminInfo> &
bool CClientManager::__GetHostInfo(std::vector<std::string> & rIPVec)
{
char szQuery[512];
snprintf(szQuery, sizeof(szQuery), "SELECT mIP FROM gmhost");
auto pMsg = CDBManager::instance().DirectQuery(szQuery, SQL_COMMON);
CStmt stmt;
char hostIP[16] = {};
const std::string query = "SELECT COALESCE(mIP, '') FROM gmhost";
if (pMsg->Get()->uiNumRows == 0)
if (!PrepareClientCommonStmt(stmt, query)
|| !stmt.BindResult(MYSQL_TYPE_STRING, hostIP, sizeof(hostIP))
|| !stmt.Execute()
|| stmt.iRows == 0)
{
sys_err("__GetHostInfo() ==> DirectQuery failed(%s)", szQuery);
sys_err("__GetHostInfo() ==> DirectQuery failed(%s)", query.c_str());
return false;
}
rIPVec.reserve(pMsg->Get()->uiNumRows);
rIPVec.reserve(stmt.iRows);
MYSQL_ROW row;
while ((row = mysql_fetch_row(pMsg->Get()->pSQLResult)))
while (stmt.Fetch())
{
if (row[0] && *row[0])
NullTerminateClientResult(hostIP, stmt.GetResultLength(0));
if (hostIP[0])
{
rIPVec.push_back(row[0]);
sys_log(0, "GMHOST: %s", row[0]);
rIPVec.push_back(hostIP);
sys_log(0, "GMHOST: %s", hostIP);
}
memset(hostIP, 0, sizeof(hostIP));
}
return true;