mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-15 12:31:31 +00:00
Database interface improvement with stl style iterators
This commit is contained in:
parent
b3292e1d22
commit
3054a4c307
@ -39,6 +39,8 @@ SET(common_sources
|
|||||||
MiscFunctions.cpp
|
MiscFunctions.cpp
|
||||||
moremath.cpp
|
moremath.cpp
|
||||||
Mutex.cpp
|
Mutex.cpp
|
||||||
|
MySQLRequestResult.cpp
|
||||||
|
MySQLRequestRow.cpp
|
||||||
opcode_map.cpp
|
opcode_map.cpp
|
||||||
opcodemgr.cpp
|
opcodemgr.cpp
|
||||||
packet_dump.cpp
|
packet_dump.cpp
|
||||||
@ -149,6 +151,8 @@ SET(common_headers
|
|||||||
MiscFunctions.h
|
MiscFunctions.h
|
||||||
moremath.h
|
moremath.h
|
||||||
Mutex.h
|
Mutex.h
|
||||||
|
MySQLRequestResult.h
|
||||||
|
MySQLRequestRow.h
|
||||||
op_codes.h
|
op_codes.h
|
||||||
opcode_dispatch.h
|
opcode_dispatch.h
|
||||||
opcodemgr.h
|
opcodemgr.h
|
||||||
|
|||||||
103
common/MySQLRequestResult.cpp
Normal file
103
common/MySQLRequestResult.cpp
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
#include "MySQLRequestResult.h"
|
||||||
|
|
||||||
|
|
||||||
|
MySQLRequestResult::MySQLRequestResult()
|
||||||
|
: m_CurrentRow(), m_OneBeyondRow()
|
||||||
|
{
|
||||||
|
ZeroOut();
|
||||||
|
}
|
||||||
|
|
||||||
|
MySQLRequestResult::MySQLRequestResult(MYSQL_RES* result, uint32 rowsAffected, uint32 rowCount, uint32 columnCount, uint32 lastInsertedID, uint32 errorNumber, char *errorBuffer)
|
||||||
|
: m_CurrentRow(result), m_OneBeyondRow()
|
||||||
|
{
|
||||||
|
if (errorBuffer != nullptr)
|
||||||
|
m_Success = false;
|
||||||
|
else if (errorBuffer == nullptr && result == nullptr)
|
||||||
|
{
|
||||||
|
m_Success = false;
|
||||||
|
|
||||||
|
#ifdef _EQDEBUG
|
||||||
|
std::cout << "DB Query Error: No Result" << std::endl;
|
||||||
|
#endif
|
||||||
|
m_ErrorNumber = UINT_MAX;
|
||||||
|
m_ErrorBuffer = new char[MYSQL_ERRMSG_SIZE];
|
||||||
|
|
||||||
|
strcpy(m_ErrorBuffer, "DBcore::RunQuery: No Result");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_Success = true;
|
||||||
|
|
||||||
|
m_Result = result;
|
||||||
|
m_ErrorBuffer = errorBuffer;
|
||||||
|
m_RowsAffected = rowsAffected;
|
||||||
|
m_RowCount = rowCount;
|
||||||
|
m_ColumnCount = columnCount;
|
||||||
|
m_LastInsertedID = lastInsertedID;
|
||||||
|
m_ErrorNumber = errorNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MySQLRequestResult::FreeInternals()
|
||||||
|
{
|
||||||
|
safe_delete_array(m_ErrorBuffer);
|
||||||
|
|
||||||
|
if (m_Result != nullptr)
|
||||||
|
mysql_free_result(m_Result);
|
||||||
|
|
||||||
|
ZeroOut();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MySQLRequestResult::ZeroOut()
|
||||||
|
{
|
||||||
|
m_Success = false;
|
||||||
|
m_Result = nullptr;
|
||||||
|
m_ErrorBuffer = nullptr;
|
||||||
|
m_RowCount = 0;
|
||||||
|
m_RowsAffected = 0;
|
||||||
|
m_LastInsertedID = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
MySQLRequestResult::~MySQLRequestResult()
|
||||||
|
{
|
||||||
|
FreeInternals();
|
||||||
|
}
|
||||||
|
|
||||||
|
MySQLRequestResult::MySQLRequestResult(MySQLRequestResult&& moveItem)
|
||||||
|
: m_CurrentRow(moveItem.m_CurrentRow), m_OneBeyondRow()
|
||||||
|
{
|
||||||
|
m_Result = moveItem.m_Result;
|
||||||
|
m_ErrorBuffer = moveItem.m_ErrorBuffer;
|
||||||
|
m_Success = moveItem.m_Success;
|
||||||
|
m_RowCount = moveItem.m_RowCount;
|
||||||
|
m_RowsAffected = moveItem.m_RowsAffected;
|
||||||
|
m_LastInsertedID = moveItem.m_LastInsertedID;
|
||||||
|
|
||||||
|
// Keeps deconstructor from double freeing
|
||||||
|
// pre move instance.
|
||||||
|
moveItem.ZeroOut();
|
||||||
|
}
|
||||||
|
|
||||||
|
MySQLRequestResult& MySQLRequestResult::operator=(MySQLRequestResult&& other)
|
||||||
|
{
|
||||||
|
// Assigning something to itself?
|
||||||
|
// Silly! (but happens)
|
||||||
|
if (this == &other)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
FreeInternals();
|
||||||
|
|
||||||
|
m_Success = other.m_Success;
|
||||||
|
|
||||||
|
m_Result = other.m_Result;
|
||||||
|
m_ErrorBuffer = other.m_ErrorBuffer;
|
||||||
|
|
||||||
|
m_RowCount = other.m_RowCount;
|
||||||
|
m_RowsAffected = other.m_RowsAffected;
|
||||||
|
m_LastInsertedID = other.m_LastInsertedID;
|
||||||
|
m_CurrentRow = other.m_CurrentRow;
|
||||||
|
m_OneBeyondRow = other.m_OneBeyondRow;
|
||||||
|
|
||||||
|
// Keeps deconstructor from double freeing
|
||||||
|
// pre move instance.
|
||||||
|
other.ZeroOut();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
54
common/MySQLRequestResult.h
Normal file
54
common/MySQLRequestResult.h
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
#ifndef MYSQL_REQUEST_RESULT_H
|
||||||
|
#define MYSQL_REQUEST_RESULT_H
|
||||||
|
|
||||||
|
#ifdef _WINDOWS
|
||||||
|
#include <winsock.h>
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <mysql.h>
|
||||||
|
#include <../common/types.h>
|
||||||
|
#include <../common/MySQLRequestRow.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class MySQLRequestResult {
|
||||||
|
private:
|
||||||
|
MYSQL_RES* m_Result;
|
||||||
|
char* m_ErrorBuffer;
|
||||||
|
MySQLRequestRow m_CurrentRow;
|
||||||
|
MySQLRequestRow m_OneBeyondRow;
|
||||||
|
|
||||||
|
bool m_Success;
|
||||||
|
uint32 m_RowsAffected;
|
||||||
|
uint32 m_RowCount;
|
||||||
|
uint32 m_ColumnCount;
|
||||||
|
uint32 m_LastInsertedID;
|
||||||
|
uint32 m_ErrorNumber;
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
MySQLRequestResult(MYSQL_RES* result, uint32 rowsAffected = 0, uint32 rowCount = 0, uint32 columnCount = 0, uint32 lastInsertedID = 0, uint32 errorNumber = 0, char *errorBuffer = nullptr);
|
||||||
|
MySQLRequestResult();
|
||||||
|
MySQLRequestResult(MySQLRequestResult&& moveItem);
|
||||||
|
~MySQLRequestResult();
|
||||||
|
|
||||||
|
MySQLRequestResult& operator=(MySQLRequestResult&& other);
|
||||||
|
|
||||||
|
bool Success() const { return m_Success;}
|
||||||
|
std::string ErrorMessage() const {return std::string(m_ErrorBuffer);}
|
||||||
|
uint32 ErrorNumber() const {return m_ErrorNumber;}
|
||||||
|
uint32 RowsAffected() const {return m_RowsAffected;}
|
||||||
|
uint32 RowCount() const {return m_RowCount;}
|
||||||
|
uint32 ColumnCount() const {return m_ColumnCount;}
|
||||||
|
|
||||||
|
MySQLRequestRow& begin() { return m_CurrentRow; }
|
||||||
|
MySQLRequestRow& end() { return m_OneBeyondRow;}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void FreeInternals();
|
||||||
|
void ZeroOut();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
54
common/MySQLRequestRow.cpp
Normal file
54
common/MySQLRequestRow.cpp
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
#include "MySQLRequestRow.h"
|
||||||
|
|
||||||
|
MySQLRequestRow::MySQLRequestRow(const MySQLRequestRow& row)
|
||||||
|
: m_Result(row.m_Result), m_MySQLRow(row.m_MySQLRow)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
MySQLRequestRow::MySQLRequestRow()
|
||||||
|
: m_Result(nullptr), m_MySQLRow(nullptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
MySQLRequestRow::MySQLRequestRow(MySQLRequestRow&& moveItem)
|
||||||
|
{
|
||||||
|
m_Result = moveItem.m_Result;
|
||||||
|
m_MySQLRow = moveItem.m_MySQLRow;
|
||||||
|
|
||||||
|
moveItem.m_Result = nullptr;
|
||||||
|
moveItem.m_MySQLRow = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
MySQLRequestRow::MySQLRequestRow(MYSQL_RES *result)
|
||||||
|
: m_Result(result), m_MySQLRow(mysql_fetch_row(m_Result))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
MySQLRequestRow& MySQLRequestRow::operator++()
|
||||||
|
{
|
||||||
|
m_MySQLRow = mysql_fetch_row(m_Result);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
MySQLRequestRow MySQLRequestRow::operator++(int)
|
||||||
|
{
|
||||||
|
MySQLRequestRow tmp(*this);
|
||||||
|
operator++();
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MySQLRequestRow::operator==(const MySQLRequestRow& rhs)
|
||||||
|
{
|
||||||
|
return m_MySQLRow == rhs.m_MySQLRow;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MySQLRequestRow::operator!=(const MySQLRequestRow& rhs)
|
||||||
|
{
|
||||||
|
return m_MySQLRow != rhs.m_MySQLRow;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* MySQLRequestRow::operator[](int index)
|
||||||
|
{
|
||||||
|
|
||||||
|
return m_MySQLRow[index];
|
||||||
|
}
|
||||||
37
common/MySQLRequestRow.h
Normal file
37
common/MySQLRequestRow.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#ifndef MYSQL_REQUEST_ROW_H
|
||||||
|
#define MYSQL_REQUEST_ROW_H
|
||||||
|
|
||||||
|
#ifdef _WINDOWS
|
||||||
|
#include <winsock.h>
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <mysql.h>
|
||||||
|
#include <iterator>
|
||||||
|
#include <../common/types.h>
|
||||||
|
|
||||||
|
class MySQLRequestRow : public std::iterator<std::input_iterator_tag, MYSQL_ROW>
|
||||||
|
{
|
||||||
|
|
||||||
|
private:
|
||||||
|
MYSQL_RES* m_Result;
|
||||||
|
MYSQL_ROW m_MySQLRow;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
MySQLRequestRow();
|
||||||
|
MySQLRequestRow(MYSQL_RES *result);
|
||||||
|
MySQLRequestRow(const MySQLRequestRow& row);
|
||||||
|
MySQLRequestRow(MySQLRequestRow&& moveItem);
|
||||||
|
MySQLRequestRow& operator++();
|
||||||
|
MySQLRequestRow operator++(int);
|
||||||
|
bool operator==(const MySQLRequestRow& rhs);
|
||||||
|
bool operator!=(const MySQLRequestRow& rhs);
|
||||||
|
|
||||||
|
char* operator[](int index);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -58,6 +58,83 @@ void DBcore::ping() {
|
|||||||
MDatabase.unlock();
|
MDatabase.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MySQLRequestResult DBcore::QueryDatabase(const char* query, uint32 querylen, bool retryOnFailureOnce)
|
||||||
|
{
|
||||||
|
LockMutex lock(&MDatabase);
|
||||||
|
|
||||||
|
// Reconnect if we are not connected before hand.
|
||||||
|
if (pStatus != Connected)
|
||||||
|
Open();
|
||||||
|
|
||||||
|
// request query. != 0 indicates some kind of error.
|
||||||
|
if (mysql_real_query(&mysql, query, querylen) != 0)
|
||||||
|
{
|
||||||
|
unsigned int errorNumber = mysql_errno(&mysql);
|
||||||
|
|
||||||
|
if (errorNumber == CR_SERVER_GONE_ERROR)
|
||||||
|
pStatus = Error;
|
||||||
|
|
||||||
|
// error appears to be a disconnect error, may need to try again.
|
||||||
|
if (errorNumber == CR_SERVER_LOST || errorNumber == CR_SERVER_GONE_ERROR)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (retryOnFailureOnce)
|
||||||
|
{
|
||||||
|
std::cout << "Database Error: Lost connection, attempting to recover...." << std::endl;
|
||||||
|
MySQLRequestResult requestResult = QueryDatabase(query, querylen, false);
|
||||||
|
|
||||||
|
if (requestResult.Success())
|
||||||
|
{
|
||||||
|
std::cout << "Reconnection to database successful." << std::endl;
|
||||||
|
return requestResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
pStatus = Error;
|
||||||
|
|
||||||
|
char *errorBuffer = new char[MYSQL_ERRMSG_SIZE];
|
||||||
|
|
||||||
|
snprintf(errorBuffer, MYSQL_ERRMSG_SIZE, "#%i: %s", mysql_errno(&mysql), mysql_error(&mysql));
|
||||||
|
|
||||||
|
std::cout << "DB Query Error #" << mysql_errno(&mysql) << ": " << mysql_error(&mysql) << std::endl;
|
||||||
|
|
||||||
|
return MySQLRequestResult(nullptr, 0, 0, 0, 0, (uint32)mysql_errno(&mysql), errorBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *errorBuffer = new char[MYSQL_ERRMSG_SIZE];
|
||||||
|
snprintf(errorBuffer, MYSQL_ERRMSG_SIZE, "#%i: %s", mysql_errno(&mysql), mysql_error(&mysql));
|
||||||
|
|
||||||
|
#ifdef _EQDEBUG
|
||||||
|
std::cout << "DB Query Error #" << mysql_errno(&mysql) << ": " << mysql_error(&mysql) << std::endl;
|
||||||
|
#endif
|
||||||
|
return MySQLRequestResult(nullptr, 0, 0, 0, 0, mysql_errno(&mysql),errorBuffer);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// successful query. get results.
|
||||||
|
MYSQL_RES* res = mysql_store_result(&mysql);
|
||||||
|
MySQLRequestResult requestResult(res, (uint32)mysql_affected_rows(&mysql), (uint32)mysql_num_rows(res), (uint32)mysql_field_count(&mysql), (uint32)mysql_insert_id(&mysql));
|
||||||
|
|
||||||
|
|
||||||
|
#if DEBUG_MYSQL_QUERIES >= 1
|
||||||
|
if (requestResult.Success())
|
||||||
|
{
|
||||||
|
std::cout << "query successful";
|
||||||
|
if (requestResult.Result())
|
||||||
|
std::cout << ", " << (int) mysql_num_rows(requestResult.Result()) << " rows returned";
|
||||||
|
|
||||||
|
std::cout << ", " << requestResult.RowCount() << " rows affected";
|
||||||
|
std::cout<< std::endl;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
std::cout << "QUERY: query FAILED" << std::endl;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return requestResult;
|
||||||
|
}
|
||||||
|
|
||||||
bool DBcore::RunQuery(const char* query, uint32 querylen, char* errbuf, MYSQL_RES** result, uint32* affected_rows, uint32* last_insert_id, uint32* errnum, bool retry) {
|
bool DBcore::RunQuery(const char* query, uint32 querylen, char* errbuf, MYSQL_RES** result, uint32* affected_rows, uint32* last_insert_id, uint32* errnum, bool retry) {
|
||||||
if (errnum)
|
if (errnum)
|
||||||
*errnum = 0;
|
*errnum = 0;
|
||||||
@ -111,7 +188,7 @@ bool DBcore::RunQuery(const char* query, uint32 querylen, char* errbuf, MYSQL_RE
|
|||||||
if (affected_rows)
|
if (affected_rows)
|
||||||
*affected_rows = mysql_affected_rows(&mysql);
|
*affected_rows = mysql_affected_rows(&mysql);
|
||||||
if (last_insert_id)
|
if (last_insert_id)
|
||||||
*last_insert_id = mysql_insert_id(&mysql);
|
*last_insert_id = (uint32)mysql_insert_id(&mysql);
|
||||||
if (result) {
|
if (result) {
|
||||||
if (*result) {
|
if (*result) {
|
||||||
ret = true;
|
ret = true;
|
||||||
|
|||||||
@ -4,8 +4,8 @@
|
|||||||
#ifdef _WINDOWS
|
#ifdef _WINDOWS
|
||||||
#include <winsock.h>
|
#include <winsock.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
//#include <winsock.h>
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <mysql.h>
|
#include <mysql.h>
|
||||||
#include "../common/types.h"
|
#include "../common/types.h"
|
||||||
#include "../common/Mutex.h"
|
#include "../common/Mutex.h"
|
||||||
@ -13,6 +13,7 @@
|
|||||||
#include "../common/queue.h"
|
#include "../common/queue.h"
|
||||||
#include "../common/timer.h"
|
#include "../common/timer.h"
|
||||||
#include "../common/Condition.h"
|
#include "../common/Condition.h"
|
||||||
|
#include "../common/MySQLRequestResult.h"
|
||||||
|
|
||||||
class DBcore {
|
class DBcore {
|
||||||
public:
|
public:
|
||||||
@ -22,6 +23,7 @@ public:
|
|||||||
~DBcore();
|
~DBcore();
|
||||||
eStatus GetStatus() { return pStatus; }
|
eStatus GetStatus() { return pStatus; }
|
||||||
bool RunQuery(const char* query, uint32 querylen, char* errbuf = 0, MYSQL_RES** result = 0, uint32* affected_rows = 0, uint32* last_insert_id = 0, uint32* errnum = 0, bool retry = true);
|
bool RunQuery(const char* query, uint32 querylen, char* errbuf = 0, MYSQL_RES** result = 0, uint32* affected_rows = 0, uint32* last_insert_id = 0, uint32* errnum = 0, bool retry = true);
|
||||||
|
MySQLRequestResult QueryDatabase(const char* query, uint32 querylen, bool retryOnFailureOnce = true);
|
||||||
uint32 DoEscapeString(char* tobuf, const char* frombuf, uint32 fromlen);
|
uint32 DoEscapeString(char* tobuf, const char* frombuf, uint32 fromlen);
|
||||||
void ping();
|
void ping();
|
||||||
MYSQL* getMySQL(){ return &mysql; }
|
MYSQL* getMySQL(){ return &mysql; }
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user