db: prepare marriage queries

This commit is contained in:
server
2026-04-13 22:09:42 +02:00
parent 063d92f876
commit 4b1cdbf134

View File

@@ -3,9 +3,177 @@
#include "Main.h"
#include "DBManager.h"
#include "ClientManager.h"
#include "libsql/Statement.h"
#include <string>
#include <vector>
namespace marriage
{
namespace
{
struct MarriageRow
{
DWORD pid1 = 0;
DWORD pid2 = 0;
int lovePoint = 0;
DWORD time = 0;
BYTE isMarried = 0;
char name1[CHARACTER_NAME_MAX_LEN + 1] = {};
char name2[CHARACTER_NAME_MAX_LEN + 1] = {};
};
bool PrepareMarriageStmt(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 PurgePendingMarriages()
{
CStmt stmt;
const std::string query = "DELETE FROM marriage WHERE is_married = 0";
if (!PrepareMarriageStmt(stmt, query))
return false;
return stmt.Execute();
}
bool LoadMarriageRows(std::vector<MarriageRow>& rows)
{
CStmt stmt;
MarriageRow row = {};
const std::string query = std::string("SELECT pid1, pid2, love_point, time, is_married, p1.name, p2.name FROM marriage, player")
+ GetTablePostfix() + " as p1, player" + GetTablePostfix() + " as p2 WHERE p1.id = pid1 AND p2.id = pid2";
rows.clear();
if (!PrepareMarriageStmt(stmt, query))
return false;
if (!stmt.BindResult(MYSQL_TYPE_LONG, &row.pid1)
|| !stmt.BindResult(MYSQL_TYPE_LONG, &row.pid2)
|| !stmt.BindResult(MYSQL_TYPE_LONG, &row.lovePoint)
|| !stmt.BindResult(MYSQL_TYPE_LONG, &row.time)
|| !stmt.BindResult(MYSQL_TYPE_TINY, &row.isMarried)
|| !stmt.BindResult(MYSQL_TYPE_STRING, row.name1, sizeof(row.name1))
|| !stmt.BindResult(MYSQL_TYPE_STRING, row.name2, sizeof(row.name2)))
{
return false;
}
if (!stmt.Execute())
return false;
rows.reserve(stmt.iRows);
for (int i = 0; i < stmt.iRows; ++i)
{
row = {};
if (!stmt.Fetch())
return false;
size_t name1Len = stmt.GetResultLength(5);
if (name1Len >= sizeof(row.name1))
name1Len = sizeof(row.name1) - 1;
row.name1[name1Len] = '\0';
size_t name2Len = stmt.GetResultLength(6);
if (name2Len >= sizeof(row.name2))
name2Len = sizeof(row.name2) - 1;
row.name2[name2Len] = '\0';
rows.push_back(row);
}
return true;
}
bool AddMarriageRow(DWORD pid1, DWORD pid2, DWORD time)
{
CStmt stmt;
const std::string query = "INSERT INTO marriage(pid1, pid2, love_point, time) VALUES (?, ?, 0, ?)";
if (!PrepareMarriageStmt(stmt, query))
return false;
if (!stmt.BindParam(MYSQL_TYPE_LONG, &pid1)
|| !stmt.BindParam(MYSQL_TYPE_LONG, &pid2)
|| !stmt.BindParam(MYSQL_TYPE_LONG, &time)
|| !stmt.Execute())
{
return false;
}
return stmt.GetAffectedRows() != 0 && stmt.GetAffectedRows() != static_cast<unsigned long long>(-1);
}
bool UpdateMarriageRow(DWORD pid1, DWORD pid2, int lovePoint, BYTE isMarried)
{
CStmt stmt;
const std::string query = "UPDATE marriage SET love_point = ?, is_married = ? WHERE pid1 = ? AND pid2 = ?";
if (!PrepareMarriageStmt(stmt, query))
return false;
if (!stmt.BindParam(MYSQL_TYPE_LONG, &lovePoint)
|| !stmt.BindParam(MYSQL_TYPE_TINY, &isMarried)
|| !stmt.BindParam(MYSQL_TYPE_LONG, &pid1)
|| !stmt.BindParam(MYSQL_TYPE_LONG, &pid2)
|| !stmt.Execute())
{
return false;
}
return stmt.GetAffectedRows() != 0 && stmt.GetAffectedRows() != static_cast<unsigned long long>(-1);
}
bool RemoveMarriageRow(DWORD pid1, DWORD pid2)
{
CStmt stmt;
const std::string query = "DELETE FROM marriage WHERE pid1 = ? AND pid2 = ?";
if (!PrepareMarriageStmt(stmt, query))
return false;
if (!stmt.BindParam(MYSQL_TYPE_LONG, &pid1)
|| !stmt.BindParam(MYSQL_TYPE_LONG, &pid2)
|| !stmt.Execute())
{
return false;
}
return stmt.GetAffectedRows() != 0 && stmt.GetAffectedRows() != static_cast<unsigned long long>(-1);
}
bool MarkMarriageAsMarried(DWORD pid1, DWORD pid2)
{
CStmt stmt;
const std::string query = "UPDATE marriage SET is_married = 1 WHERE pid1 = ? AND pid2 = ?";
if (!PrepareMarriageStmt(stmt, query))
return false;
if (!stmt.BindParam(MYSQL_TYPE_LONG, &pid1)
|| !stmt.BindParam(MYSQL_TYPE_LONG, &pid2)
|| !stmt.Execute())
{
return false;
}
return stmt.GetAffectedRows() != 0 && stmt.GetAffectedRows() != static_cast<unsigned long long>(-1);
}
}
const DWORD WEDDING_LENGTH = 60 * 60; // sec
bool operator < (const TWedding& lhs, const TWedding& rhs)
{
@@ -34,38 +202,29 @@ namespace marriage
bool CManager::Initialize()
{
char szQuery[1024];
std::vector<MarriageRow> rows;
snprintf(szQuery, sizeof(szQuery),
"SELECT pid1, pid2, love_point, time, is_married, p1.name, p2.name FROM marriage, player%s as p1, player%s as p2 WHERE p1.id = pid1 AND p2.id = pid2",
GetTablePostfix(), GetTablePostfix());
if (!PurgePendingMarriages())
sys_err("failed to purge pending marriages");
CDBManager::instance().DirectQuery("DELETE FROM marriage WHERE is_married = 0");
auto pmsg = CDBManager::instance().DirectQuery(szQuery);
SQLResult * pRes = pmsg->Get();
sys_log(0, "MarriageList(size=%lu)", pRes->uiNumRows);
if (!LoadMarriageRows(rows))
return false;
if (pRes->uiNumRows > 0)
sys_log(0, "MarriageList(size=%lu)", rows.size());
if (!rows.empty())
{
for (uint uiRow = 0; uiRow != pRes->uiNumRows; ++uiRow)
for (size_t uiRow = 0; uiRow != rows.size(); ++uiRow)
{
MYSQL_ROW row = mysql_fetch_row(pRes->pSQLResult);
const auto& row = rows[uiRow];
DWORD pid1 = 0; str_to_number(pid1, row[0]);
DWORD pid2 = 0; str_to_number(pid2, row[1]);
int love_point = 0; str_to_number(love_point, row[2]);
DWORD time = 0; str_to_number(time, row[3]);
BYTE is_married = 0; str_to_number(is_married, row[4]);
const char* name1 = row[5];
const char* name2 = row[6];
TMarriage* pMarriage = new TMarriage(pid1, pid2, love_point, time, is_married, name1, name2);
TMarriage* pMarriage = new TMarriage(row.pid1, row.pid2, row.lovePoint, row.time, row.isMarried, row.name1, row.name2);
m_Marriages.insert(pMarriage);
m_MarriageByPID.insert(make_pair(pid1, pMarriage));
m_MarriageByPID.insert(make_pair(pid2, pMarriage));
m_MarriageByPID.insert(make_pair(row.pid1, pMarriage));
m_MarriageByPID.insert(make_pair(row.pid2, pMarriage));
sys_log(0, "Marriage %lu: LP:%d TM:%u ST:%d %10lu:%16s %10lu:%16s ", uiRow, love_point, time, is_married, pid1, name1, pid2, name2);
sys_log(0, "Marriage %lu: LP:%d TM:%u ST:%d %10lu:%16s %10lu:%16s ",
static_cast<unsigned long>(uiRow), row.lovePoint, row.time, row.isMarried, row.pid1, row.name1, row.pid2, row.name2);
}
}
return true;
@@ -98,13 +257,7 @@ namespace marriage
Align(dwPID1, dwPID2);
char szQuery[512];
snprintf(szQuery, sizeof(szQuery), "INSERT INTO marriage(pid1, pid2, love_point, time) VALUES (%u, %u, 0, %u)", dwPID1, dwPID2, now);
auto pmsg = CDBManager::instance().DirectQuery(szQuery);
SQLResult* res = pmsg->Get();
if (res->uiAffectedRows == 0 || res->uiAffectedRows == (uint32_t)-1)
if (!AddMarriageRow(dwPID1, dwPID2, now))
{
sys_err("cannot insert marriage");
return;
@@ -137,14 +290,7 @@ namespace marriage
Align(dwPID1, dwPID2);
char szQuery[512];
snprintf(szQuery, sizeof(szQuery), "UPDATE marriage SET love_point = %d, is_married = %d WHERE pid1 = %u AND pid2 = %u",
iLovePoint, byMarried, pMarriage->pid1, pMarriage->pid2);
auto pmsg = CDBManager::instance().DirectQuery(szQuery);
SQLResult* res = pmsg->Get();
if (res->uiAffectedRows == 0 || res->uiAffectedRows == (uint32_t)-1)
if (!UpdateMarriageRow(pMarriage->pid1, pMarriage->pid2, iLovePoint, byMarried))
{
sys_err("cannot update marriage : PID:%u %u", dwPID1, dwPID2);
return;
@@ -184,13 +330,7 @@ namespace marriage
Align(dwPID1, dwPID2);
char szQuery[512];
snprintf(szQuery, sizeof(szQuery), "DELETE FROM marriage WHERE pid1 = %u AND pid2 = %u", dwPID1, dwPID2);
auto pmsg = CDBManager::instance().DirectQuery(szQuery);
SQLResult* res = pmsg->Get();
if (res->uiAffectedRows == 0 || res->uiAffectedRows == (uint32_t)-1)
if (!RemoveMarriageRow(dwPID1, dwPID2))
{
sys_err("cannot delete marriage : PID:%u %u", dwPID1, dwPID2);
return;
@@ -227,14 +367,7 @@ namespace marriage
Align(dwPID1, dwPID2);
char szQuery[512];
snprintf(szQuery, sizeof(szQuery), "UPDATE marriage SET is_married = 1 WHERE pid1 = %u AND pid2 = %u",
pMarriage->pid1, pMarriage->pid2);
auto pmsg = CDBManager::instance().DirectQuery(szQuery);
SQLResult* res = pmsg->Get();
if (res->uiAffectedRows == 0 || res->uiAffectedRows == (uint32_t)-1)
if (!MarkMarriageAsMarried(pMarriage->pid1, pMarriage->pid2))
{
sys_err("cannot change engage to marriage : PID:%u %u", dwPID1, dwPID2);
return;