From 08badc3c7a6dfa29239304e4564257952ddb66c7 Mon Sep 17 00:00:00 2001 From: server Date: Mon, 13 Apr 2026 22:15:59 +0200 Subject: [PATCH] db: prepare guild war and backup queries --- src/db/GuildManager.cpp | 503 +++++++++++++++++++++++++++++----------- src/db/GuildManager.h | 2 - src/db/HB.cpp | 71 +++++- 3 files changed, 426 insertions(+), 150 deletions(-) diff --git a/src/db/GuildManager.cpp b/src/db/GuildManager.cpp index b761fa9..4f509c1 100644 --- a/src/db/GuildManager.cpp +++ b/src/db/GuildManager.cpp @@ -4,7 +4,11 @@ #include "ClientManager.h" #include "QID.h" #include "Config.h" +#include "libsql/Statement.h" + #include +#include +#include extern std::string g_stLocale; @@ -50,6 +54,329 @@ DWORD GetGuildWarReserveSeconds() namespace { + struct GuildRow + { + DWORD id = 0; + char name[GUILD_NAME_MAX_LEN + 1] = {}; + int ladderPoint = 0; + int win = 0; + int draw = 0; + int loss = 0; + int gold = 0; + int level = 0; + }; + + struct GuildWarBetRow + { + char login[LOGIN_MAX_LEN + 1] = {}; + DWORD guild = 0; + DWORD gold = 0; + }; + + bool PrepareGuildStmt(CStmt& stmt, const std::string& query) + { + CAsyncSQL* sql = CDBManager::instance().GetDirectSQL(SQL_PLAYER); + + if (!sql) + { + sys_err("player SQL handle is not initialized"); + return false; + } + + return stmt.Prepare(sql, query.c_str()); + } + + bool LoadGuildRows(const DWORD* guildId, std::vector& rows) + { + CStmt stmt; + GuildRow row = {}; + std::string query = std::string("SELECT id, name, ladder_point, win, draw, loss, gold, level FROM guild") + GetTablePostfix(); + + rows.clear(); + + if (guildId) + query += " WHERE id=?"; + + if (!PrepareGuildStmt(stmt, query)) + return false; + + if (guildId && !stmt.BindParam(MYSQL_TYPE_LONG, const_cast(guildId))) + return false; + + if (!stmt.BindResult(MYSQL_TYPE_LONG, &row.id) + || !stmt.BindResult(MYSQL_TYPE_STRING, row.name, sizeof(row.name)) + || !stmt.BindResult(MYSQL_TYPE_LONG, &row.ladderPoint) + || !stmt.BindResult(MYSQL_TYPE_LONG, &row.win) + || !stmt.BindResult(MYSQL_TYPE_LONG, &row.draw) + || !stmt.BindResult(MYSQL_TYPE_LONG, &row.loss) + || !stmt.BindResult(MYSQL_TYPE_LONG, &row.gold) + || !stmt.BindResult(MYSQL_TYPE_LONG, &row.level) + || !stmt.Execute()) + { + return false; + } + + rows.reserve(stmt.iRows); + + for (int i = 0; i < stmt.iRows; ++i) + { + row = {}; + + if (!stmt.Fetch()) + return false; + + size_t nameLen = stmt.GetResultLength(1); + if (nameLen >= sizeof(row.name)) + nameLen = sizeof(row.name) - 1; + + row.name[nameLen] = '\0'; + rows.push_back(row); + } + + return true; + } + + void ApplyGuildRows(CGuildManager& manager, const std::vector& rows) + { + for (const auto& row : rows) + { + TGuild& guild = manager.TouchGuild(row.id); + + strlcpy(guild.szName, row.name, sizeof(guild.szName)); + guild.ladder_point = row.ladderPoint; + guild.win = row.win; + guild.draw = row.draw; + guild.loss = row.loss; + guild.gold = row.gold; + guild.level = row.level; + + sys_log(0, + "GuildWar: %-24s ladder %-5d win %-3d draw %-3d loss %-3d", + guild.szName, + guild.ladder_point, + guild.win, + guild.draw, + guild.loss); + } + } + + bool LoadWarReserveRows(const char* query, std::vector& rows) + { + CStmt stmt; + TGuildWarReserve row = {}; + + rows.clear(); + + if (!PrepareGuildStmt(stmt, query)) + return false; + + if (!stmt.BindResult(MYSQL_TYPE_LONG, &row.dwID) + || !stmt.BindResult(MYSQL_TYPE_LONG, &row.dwGuildFrom) + || !stmt.BindResult(MYSQL_TYPE_LONG, &row.dwGuildTo) + || !stmt.BindResult(MYSQL_TYPE_LONG, &row.dwTime) + || !stmt.BindResult(MYSQL_TYPE_TINY, &row.bType) + || !stmt.BindResult(MYSQL_TYPE_LONG, &row.lWarPrice) + || !stmt.BindResult(MYSQL_TYPE_LONG, &row.lInitialScore) + || !stmt.BindResult(MYSQL_TYPE_LONG, &row.dwBetFrom) + || !stmt.BindResult(MYSQL_TYPE_LONG, &row.dwBetTo) + || !stmt.BindResult(MYSQL_TYPE_LONG, &row.lPowerFrom) + || !stmt.BindResult(MYSQL_TYPE_LONG, &row.lPowerTo) + || !stmt.BindResult(MYSQL_TYPE_LONG, &row.lHandicap) + || !stmt.Execute()) + { + return false; + } + + rows.reserve(stmt.iRows); + + for (int i = 0; i < stmt.iRows; ++i) + { + row = {}; + + if (!stmt.Fetch()) + return false; + + row.bStarted = false; + rows.push_back(row); + } + + return true; + } + + bool LoadAverageGuildMemberLevel(DWORD guildId, int& averageLevel) + { + CStmt stmt; + double average = 0.0; + const std::string query = std::string("SELECT COALESCE(AVG(level), 0) FROM guild_member") + GetTablePostfix() + + ", player" + GetTablePostfix() + " AS p WHERE guild_id=? AND guild_member" + GetTablePostfix() + ".pid=p.id"; + + averageLevel = 0; + + if (!PrepareGuildStmt(stmt, query)) + return false; + + if (!stmt.BindParam(MYSQL_TYPE_LONG, &guildId) + || !stmt.BindResult(MYSQL_TYPE_DOUBLE, &average) + || !stmt.Execute() + || stmt.iRows == 0 + || !stmt.Fetch()) + { + return false; + } + + averageLevel = static_cast(average); + return true; + } + + bool LoadGuildMemberCount(DWORD guildId, DWORD& memberCount) + { + CStmt stmt; + const std::string query = std::string("SELECT COUNT(*) FROM guild_member") + GetTablePostfix() + " WHERE guild_id=?"; + + memberCount = 0; + + if (!PrepareGuildStmt(stmt, query)) + return false; + + if (!stmt.BindParam(MYSQL_TYPE_LONG, &guildId) + || !stmt.BindResult(MYSQL_TYPE_LONG, &memberCount) + || !stmt.Execute() + || stmt.iRows == 0 + || !stmt.Fetch()) + { + return false; + } + + return true; + } + + bool InsertWarReservation(DWORD guildFrom, DWORD guildTo, BYTE warType, int32_t warPrice, int32_t initialScore, int32_t powerFrom, int32_t powerTo, int32_t handicap, DWORD& reservationId) + { + CStmt stmt; + const std::string query = "INSERT INTO guild_war_reservation (guild1, guild2, time, type, warprice, initscore, power1, power2, handicap) " + "VALUES(?, ?, DATE_ADD(NOW(), INTERVAL 180 SECOND), ?, ?, ?, ?, ?, ?)"; + + reservationId = 0; + + if (!PrepareGuildStmt(stmt, query)) + return false; + + if (!stmt.BindParam(MYSQL_TYPE_LONG, &guildFrom) + || !stmt.BindParam(MYSQL_TYPE_LONG, &guildTo) + || !stmt.BindParam(MYSQL_TYPE_TINY, &warType) + || !stmt.BindParam(MYSQL_TYPE_LONG, &warPrice) + || !stmt.BindParam(MYSQL_TYPE_LONG, &initialScore) + || !stmt.BindParam(MYSQL_TYPE_LONG, &powerFrom) + || !stmt.BindParam(MYSQL_TYPE_LONG, &powerTo) + || !stmt.BindParam(MYSQL_TYPE_LONG, &handicap) + || !stmt.Execute()) + { + return false; + } + + if (stmt.GetAffectedRows() == 0 || stmt.GetAffectedRows() == static_cast(-1)) + return false; + + reservationId = static_cast(stmt.GetInsertId()); + return reservationId != 0; + } + + bool UpdateGuildMaster(DWORD guildId, DWORD masterId) + { + CStmt stmt; + const std::string query = std::string("UPDATE guild") + GetTablePostfix() + " SET master=? WHERE id=?"; + + if (!PrepareGuildStmt(stmt, query)) + return false; + + if (!stmt.BindParam(MYSQL_TYPE_LONG, &masterId) + || !stmt.BindParam(MYSQL_TYPE_LONG, &guildId) + || !stmt.Execute()) + { + return false; + } + + return true; + } + + bool UpdateGuildMemberGrade(DWORD playerId, DWORD grade) + { + CStmt stmt; + const std::string query = std::string("UPDATE guild_member") + GetTablePostfix() + " SET grade=? WHERE pid=?"; + + if (!PrepareGuildStmt(stmt, query)) + return false; + + if (!stmt.BindParam(MYSQL_TYPE_LONG, &grade) + || !stmt.BindParam(MYSQL_TYPE_LONG, &playerId) + || !stmt.Execute()) + { + return false; + } + + return true; + } + + bool LoadGuildWarBets(DWORD warId, std::vector& rows) + { + CStmt stmt; + GuildWarBetRow row = {}; + const std::string query = "SELECT login, guild, gold FROM guild_war_bet WHERE war_id=?"; + + rows.clear(); + + if (!PrepareGuildStmt(stmt, query)) + return false; + + if (!stmt.BindParam(MYSQL_TYPE_LONG, &warId) + || !stmt.BindResult(MYSQL_TYPE_STRING, row.login, sizeof(row.login)) + || !stmt.BindResult(MYSQL_TYPE_LONG, &row.guild) + || !stmt.BindResult(MYSQL_TYPE_LONG, &row.gold) + || !stmt.Execute()) + { + return false; + } + + rows.reserve(stmt.iRows); + + for (int i = 0; i < stmt.iRows; ++i) + { + row = {}; + + if (!stmt.Fetch()) + return false; + + size_t loginLen = stmt.GetResultLength(0); + if (loginLen >= sizeof(row.login)) + loginLen = sizeof(row.login) - 1; + + row.login[loginLen] = '\0'; + rows.push_back(row); + } + + return true; + } + + bool InsertGuildWarBet(DWORD warId, const char* login, DWORD gold, DWORD guildId) + { + CStmt stmt; + const std::string query = "INSERT INTO guild_war_bet (war_id, login, gold, guild) VALUES(?, ?, ?, ?)"; + + if (!PrepareGuildStmt(stmt, query)) + return false; + + if (!stmt.BindParam(MYSQL_TYPE_LONG, &warId) + || !stmt.BindParam(MYSQL_TYPE_STRING, const_cast(login)) + || !stmt.BindParam(MYSQL_TYPE_LONG, &gold) + || !stmt.BindParam(MYSQL_TYPE_LONG, &guildId) + || !stmt.Execute()) + { + return false; + } + + return stmt.GetAffectedRows() != 0 && stmt.GetAffectedRows() != static_cast(-1); + } + struct FSendPeerWar { FSendPeerWar(BYTE bType, BYTE bWar, DWORD GID1, DWORD GID2) @@ -127,42 +454,11 @@ TGuild & CGuildManager::TouchGuild(DWORD GID) return m_map_kGuild[GID]; } -void CGuildManager::ParseResult(SQLResult * pRes) -{ - MYSQL_ROW row; - - while ((row = mysql_fetch_row(pRes->pSQLResult))) - { - DWORD GID = strtoul(row[0], NULL, 10); - - TGuild & r_info = TouchGuild(GID); - - strlcpy(r_info.szName, row[1], sizeof(r_info.szName)); - str_to_number(r_info.ladder_point, row[2]); - str_to_number(r_info.win, row[3]); - str_to_number(r_info.draw, row[4]); - str_to_number(r_info.loss, row[5]); - str_to_number(r_info.gold, row[6]); - str_to_number(r_info.level, row[7]); - - sys_log(0, - "GuildWar: %-24s ladder %-5d win %-3d draw %-3d loss %-3d", - r_info.szName, - r_info.ladder_point, - r_info.win, - r_info.draw, - r_info.loss); - } -} - void CGuildManager::Initialize() { - char szQuery[1024]; - snprintf(szQuery, sizeof(szQuery), "SELECT id, name, ladder_point, win, draw, loss, gold, level FROM guild%s", GetTablePostfix()); - auto pmsg = CDBManager::instance().DirectQuery(szQuery); - - if (pmsg->Get()->uiNumRows) - ParseResult(pmsg->Get()); + std::vector guildRows; + if (LoadGuildRows(nullptr, guildRows) && !guildRows.empty()) + ApplyGuildRows(*this, guildRows); char str[128 + 1]; @@ -187,13 +483,9 @@ void CGuildManager::Initialize() void CGuildManager::Load(DWORD dwGuildID) { - char szQuery[1024]; - - snprintf(szQuery, sizeof(szQuery), "SELECT id, name, ladder_point, win, draw, loss, gold, level FROM guild%s WHERE id=%u", GetTablePostfix(), dwGuildID); - auto pmsg = CDBManager::instance().DirectQuery(szQuery); - - if (pmsg->Get()->uiNumRows) - ParseResult(pmsg->Get()); + std::vector guildRows; + if (LoadGuildRows(&dwGuildID, guildRows) && !guildRows.empty()) + ApplyGuildRows(*this, guildRows); } void CGuildManager::QueryRanking() @@ -901,33 +1193,12 @@ void CGuildManager::BootReserveWar() for (int i = 0; i < 2; ++i) { - auto pmsg = CDBManager::instance().DirectQuery(c_apszQuery[i]); - - if (pmsg->Get()->uiNumRows == 0) + std::vector reserveRows; + if (!LoadWarReserveRows(c_apszQuery[i], reserveRows) || reserveRows.empty()) continue; - MYSQL_ROW row; - - while ((row = mysql_fetch_row(pmsg->Get()->pSQLResult))) + for (const auto& t : reserveRows) { - int col = 0; - - TGuildWarReserve t; - - str_to_number(t.dwID, row[col++]); - str_to_number(t.dwGuildFrom, row[col++]); - str_to_number(t.dwGuildTo, row[col++]); - str_to_number(t.dwTime, row[col++]); - str_to_number(t.bType, row[col++]); - str_to_number(t.lWarPrice, row[col++]); - str_to_number(t.lInitialScore, row[col++]); - str_to_number(t.dwBetFrom, row[col++]); - str_to_number(t.dwBetTo, row[col++]); - str_to_number(t.lPowerFrom, row[col++]); - str_to_number(t.lPowerTo, row[col++]); - str_to_number(t.lHandicap, row[col++]); - t.bStarted = 0; - CGuildWarReserve * pkReserve = new CGuildWarReserve(t); char buf[512]; @@ -956,34 +1227,20 @@ void CGuildManager::BootReserveWar() int GetAverageGuildMemberLevel(DWORD dwGID) { - char szQuery[QUERY_MAX_LEN]; + int nAverageLevel = 0; + if (!LoadAverageGuildMemberLevel(dwGID, nAverageLevel)) + return 0; - snprintf(szQuery, sizeof(szQuery), - "SELECT AVG(level) FROM guild_member%s, player%s AS p WHERE guild_id=%u AND guild_member%s.pid=p.id", - GetTablePostfix(), GetTablePostfix(), dwGID, GetTablePostfix()); - - auto msg = CDBManager::instance().DirectQuery(szQuery); - - MYSQL_ROW row; - row = mysql_fetch_row(msg->Get()->pSQLResult); - - int nAverageLevel = 0; str_to_number(nAverageLevel, row[0]); return nAverageLevel; } int GetGuildMemberCount(DWORD dwGID) { - char szQuery[QUERY_MAX_LEN]; + DWORD dwCount = 0; + if (!LoadGuildMemberCount(dwGID, dwCount)) + return 0; - snprintf(szQuery, sizeof(szQuery), "SELECT COUNT(*) FROM guild_member%s WHERE guild_id=%u", GetTablePostfix(), dwGID); - - auto msg = CDBManager::instance().DirectQuery(szQuery); - - MYSQL_ROW row; - row = mysql_fetch_row(msg->Get()->pSQLResult); - - DWORD dwCount = 0; str_to_number(dwCount, row[0]); - return dwCount; + return static_cast(dwCount); } bool CGuildManager::ReserveWar(TPacketGuildWar * p) @@ -1058,23 +1315,21 @@ bool CGuildManager::ReserveWar(TPacketGuildWar * p) sys_log(0, "GuildWar: handicap %d", t.lHandicap); // 쿼리 - char szQuery[512]; - - snprintf(szQuery, sizeof(szQuery), - "INSERT INTO guild_war_reservation (guild1, guild2, time, type, warprice, initscore, power1, power2, handicap) " - "VALUES(%u, %u, DATE_ADD(NOW(), INTERVAL 180 SECOND), %u, %ld, %ld, %ld, %ld, %ld)", - GID1, GID2, p->bType, static_cast(p->lWarPrice), static_cast(p->lInitialScore), static_cast(t.lPowerFrom), static_cast(t.lPowerTo), static_cast(t.lHandicap)); - - auto pmsg = CDBManager::instance().DirectQuery(szQuery); - - if (pmsg->Get()->uiAffectedRows == 0 || pmsg->Get()->uiInsertID == 0 || pmsg->Get()->uiAffectedRows == (uint32_t)-1) + if (!InsertWarReservation( + GID1, + GID2, + p->bType, + p->lWarPrice, + p->lInitialScore, + t.lPowerFrom, + t.lPowerTo, + t.lHandicap, + t.dwID)) { sys_err("GuildWar: Cannot insert row"); return false; } - t.dwID = pmsg->Get()->uiInsertID; - m_map_kWarReserve.insert(std::make_pair(t.dwID, new CGuildWarReserve(t))); CClientManager::instance().ForwardPacket(DG::GUILD_WAR_RESERVE_ADD, &t, sizeof(TGuildWarReserve)); @@ -1184,16 +1439,12 @@ bool CGuildManager::ChangeMaster(DWORD dwGID, DWORD dwFrom, DWORD dwTo) if (iter == m_map_kGuild.end()) return false; - char szQuery[1024]; - - snprintf(szQuery, sizeof(szQuery), "UPDATE guild%s SET master=%u WHERE id=%u", GetTablePostfix(), dwTo, dwGID); - CDBManager::instance().DirectQuery(szQuery); - - snprintf(szQuery, sizeof(szQuery), "UPDATE guild_member%s SET grade=1 WHERE pid=%u", GetTablePostfix(), dwTo); - CDBManager::instance().DirectQuery(szQuery); - - snprintf(szQuery, sizeof(szQuery), "UPDATE guild_member%s SET grade=15 WHERE pid=%u", GetTablePostfix(), dwFrom); - CDBManager::instance().DirectQuery(szQuery); + if (!UpdateGuildMaster(dwGID, dwTo) + || !UpdateGuildMemberGrade(dwTo, 1) + || !UpdateGuildMemberGrade(dwFrom, 15)) + { + return false; + } return true; } @@ -1211,28 +1462,12 @@ CGuildWarReserve::CGuildWarReserve(const TGuildWarReserve & rTable) void CGuildWarReserve::Initialize() { - char szQuery[256]; - snprintf(szQuery, sizeof(szQuery), "SELECT login, guild, gold FROM guild_war_bet WHERE war_id=%u", m_data.dwID); - - auto msgbet = CDBManager::instance().DirectQuery(szQuery); - - if (msgbet->Get()->uiNumRows) + std::vector betRows; + if (LoadGuildWarBets(m_data.dwID, betRows) && !betRows.empty()) { - MYSQL_RES * res = msgbet->Get()->pSQLResult; - MYSQL_ROW row; - - char szLogin[LOGIN_MAX_LEN+1]; - DWORD dwGuild; - DWORD dwGold; - - while ((row = mysql_fetch_row(res))) + for (const auto& row : betRows) { - dwGuild = dwGold = 0; - strlcpy(szLogin, row[0], sizeof(szLogin)); - str_to_number(dwGuild, row[1]); - str_to_number(dwGold, row[2]); - - mapBet.insert(std::make_pair(szLogin, std::make_pair(dwGuild, dwGold))); + mapBet.insert(std::make_pair(row.login, std::make_pair(row.guild, row.gold))); } } } @@ -1267,8 +1502,6 @@ void CGuildWarReserve::OnSetup(CPeer * peer) bool CGuildWarReserve::Bet(const char * pszLogin, DWORD dwGold, DWORD dwGuild) { - char szQuery[1024]; - if (m_data.dwGuildFrom != dwGuild && m_data.dwGuildTo != dwGuild) { sys_log(0, "GuildWarReserve::Bet: invalid guild id"); @@ -1287,18 +1520,13 @@ bool CGuildWarReserve::Bet(const char * pszLogin, DWORD dwGold, DWORD dwGuild) return false; } - snprintf(szQuery, sizeof(szQuery), - "INSERT INTO guild_war_bet (war_id, login, gold, guild) VALUES(%u, '%s', %u, %u)", - m_data.dwID, pszLogin, dwGold, dwGuild); - - auto pmsg = CDBManager::instance().DirectQuery(szQuery); - - if (pmsg->Get()->uiAffectedRows == 0 || pmsg->Get()->uiAffectedRows == (uint32_t)-1) + if (!InsertGuildWarBet(m_data.dwID, pszLogin, dwGold, dwGuild)) { sys_log(0, "GuildWarReserve::Bet: failed. cannot insert row to guild_war_bet table"); return false; } + char szQuery[1024]; if (m_data.dwGuildFrom == dwGuild) m_data.dwBetFrom += dwGold; else @@ -1488,4 +1716,3 @@ void CGuildWarReserve::End(int iScoreFrom, int iScoreTo) break; } } - diff --git a/src/db/GuildManager.h b/src/db/GuildManager.h index 9083870..3ec9cdd 100644 --- a/src/db/GuildManager.h +++ b/src/db/GuildManager.h @@ -215,8 +215,6 @@ class CGuildManager : public singleton bool ChangeMaster(DWORD dwGID, DWORD dwFrom, DWORD dwTo); private: - void ParseResult(SQLResult * pRes); - void RemoveWar(DWORD GID1, DWORD GID2); // erase war from m_WarMap and set end on priority queue void WarEnd(DWORD GID1, DWORD GID2, bool bDraw = false); diff --git a/src/db/HB.cpp b/src/db/HB.cpp index 3e3db88..88f709d 100644 --- a/src/db/HB.cpp +++ b/src/db/HB.cpp @@ -2,8 +2,66 @@ #include "HB.h" #include "Main.h" #include "DBManager.h" +#include "libsql/Statement.h" #include +#include + +namespace +{ + bool PrepareHBStmt(CStmt& stmt, int slot, const std::string& query) + { + CAsyncSQL* sql = CDBManager::instance().GetDirectSQL(slot); + + if (!sql) + { + sys_err("SQL handle is not initialized for slot %d", slot); + return false; + } + + return stmt.Prepare(sql, query.c_str()); + } + + bool LoadPlayerCreateTableQuery(std::string& createTableQuery) + { + CStmt stmt; + char tableName[128] = {}; + char createStatement[QUERY_MAX_LEN] = {}; + const std::string query = std::string("SHOW CREATE TABLE player") + GetTablePostfix(); + + createTableQuery.clear(); + + if (!PrepareHBStmt(stmt, SQL_PLAYER, query)) + return false; + + if (!stmt.BindResult(MYSQL_TYPE_STRING, tableName, sizeof(tableName)) + || !stmt.BindResult(MYSQL_TYPE_STRING, createStatement, sizeof(createStatement)) + || !stmt.Execute() + || stmt.iRows == 0 + || !stmt.Fetch()) + { + return false; + } + + size_t createLen = stmt.GetResultLength(1); + if (createLen >= sizeof(createStatement)) + createLen = sizeof(createStatement) - 1; + + createStatement[createLen] = '\0'; + createTableQuery = createStatement; + return true; + } + + bool EnsureHotbackupTable(const std::string& query) + { + CStmt stmt; + + if (!PrepareHBStmt(stmt, SQL_HOTBACKUP, query)) + return false; + + return stmt.Execute(); + } +} PlayerHB::PlayerHB() { @@ -16,16 +74,9 @@ PlayerHB::~PlayerHB() bool PlayerHB::Initialize() { - char szQuery[128]; - snprintf(szQuery, sizeof(szQuery), "SHOW CREATE TABLE player%s", GetTablePostfix()); - - auto pMsg = CDBManager::instance().DirectQuery(szQuery); - - if (pMsg->Get()->uiNumRows == 0) + if (!LoadPlayerCreateTableQuery(m_stCreateTableQuery)) return false; - MYSQL_ROW row = mysql_fetch_row(pMsg->Get()->pSQLResult); - m_stCreateTableQuery = row[1]; return true; } @@ -75,7 +126,8 @@ bool PlayerHB::Query(DWORD id) snprintf(szQuery, sizeof(szQuery), "CREATE TABLE IF NOT EXISTS %s%s", szTableName, m_stCreateTableQuery.c_str() + strlen(szFind)); // sys_log(0, "%s", szQuery); - auto pMsg = CDBManager::instance().DirectQuery(szQuery, SQL_HOTBACKUP); + if (!EnsureHotbackupTable(szQuery)) + return false; m_stTableName = szTableName; } @@ -83,4 +135,3 @@ bool PlayerHB::Query(DWORD id) CDBManager::instance().AsyncQuery(szQuery, SQL_HOTBACKUP); return true; } -