db: prepare guild war and backup queries

This commit is contained in:
server
2026-04-13 22:15:59 +02:00
parent 4b1cdbf134
commit 08badc3c7a
3 changed files with 426 additions and 150 deletions

View File

@@ -4,7 +4,11 @@
#include "ClientManager.h"
#include "QID.h"
#include "Config.h"
#include "libsql/Statement.h"
#include <math.h>
#include <string>
#include <vector>
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<GuildRow>& 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<DWORD*>(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<GuildRow>& 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<TGuildWarReserve>& 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<int>(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<unsigned long long>(-1))
return false;
reservationId = static_cast<DWORD>(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<GuildWarBetRow>& 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<char*>(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<unsigned long long>(-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<GuildRow> 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<GuildRow> 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<TGuildWarReserve> 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<int>(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<long>(p->lWarPrice), static_cast<long>(p->lInitialScore), static_cast<long>(t.lPowerFrom), static_cast<long>(t.lPowerTo), static_cast<long>(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<GuildWarBetRow> 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;
}
}

View File

@@ -215,8 +215,6 @@ class CGuildManager : public singleton<CGuildManager>
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);

View File

@@ -2,8 +2,66 @@
#include "HB.h"
#include "Main.h"
#include "DBManager.h"
#include "libsql/Statement.h"
#include <memory>
#include <string>
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;
}