diff --git a/common/MySQLRequestResult.cpp b/common/MySQLRequestResult.cpp index 16d7fe9a0..56e62ae37 100644 --- a/common/MySQLRequestResult.cpp +++ b/common/MySQLRequestResult.cpp @@ -32,6 +32,11 @@ MySQLRequestResult::MySQLRequestResult(MYSQL_RES* result, uint32 rowsAffected, u m_RowsAffected = rowsAffected; m_RowCount = rowCount; m_ColumnCount = columnCount; + // If we actually need the column length / fields it will be + // requested at that time, no need to pull it in just to cache it. + // Normal usage would have it as nullptr most likely anyways. + m_ColumnLengths = nullptr; + m_Fields = nullptr; m_LastInsertedID = lastInsertedID; m_ErrorNumber = errorNumber; } @@ -51,6 +56,8 @@ void MySQLRequestResult::ZeroOut() m_Success = false; m_Result = nullptr; m_ErrorBuffer = nullptr; + m_ColumnLengths = nullptr; + m_Fields = nullptr; m_RowCount = 0; m_RowsAffected = 0; m_LastInsertedID = 0; @@ -61,6 +68,39 @@ MySQLRequestResult::~MySQLRequestResult() FreeInternals(); } +uint32 MySQLRequestResult::LengthOfColumn(int columnIndex) +{ + if (m_ColumnLengths == nullptr && m_Result != nullptr) + m_ColumnLengths = mysql_fetch_lengths(m_Result); + + // If someone screws up and tries to get the length of a + // column when no result occured (check Success! argh!) + // then we always return 0. Also applies if mysql screws + // up and can't get the column lengths for whatever reason. + if (m_ColumnLengths == nullptr) + return 0; + + // Want to index check to be sure we don't read passed + // the end of the array. Just default to 0 in that case. + // We *shouldn't* need this or the previous checks if all + // interface code is correctly written. + if (columnIndex >= m_ColumnCount) + return 0; + + return m_ColumnLengths[columnIndex]; +} + +const std::string MySQLRequestResult::FieldName(int columnIndex) +{ + if (columnIndex >= m_ColumnCount || m_Result == nullptr) + return std::string(); + + if (m_Fields == nullptr) + m_Fields = mysql_fetch_fields(m_Result); + + return std::string(m_Fields[columnIndex].name); +} + MySQLRequestResult::MySQLRequestResult(MySQLRequestResult&& moveItem) : m_CurrentRow(moveItem.m_CurrentRow), m_OneBeyondRow() { @@ -70,6 +110,8 @@ MySQLRequestResult::MySQLRequestResult(MySQLRequestResult&& moveItem) m_RowCount = moveItem.m_RowCount; m_RowsAffected = moveItem.m_RowsAffected; m_LastInsertedID = moveItem.m_LastInsertedID; + m_ColumnLengths = moveItem.m_ColumnLengths; + m_Fields = moveItem.m_Fields; // Keeps deconstructor from double freeing // pre move instance. @@ -95,7 +137,9 @@ MySQLRequestResult& MySQLRequestResult::operator=(MySQLRequestResult&& other) m_LastInsertedID = other.m_LastInsertedID; m_CurrentRow = other.m_CurrentRow; m_OneBeyondRow = other.m_OneBeyondRow; - + m_ColumnLengths = other.m_ColumnLengths; + m_Fields = other.m_Fields; + // Keeps deconstructor from double freeing // pre move instance. other.ZeroOut(); diff --git a/common/MySQLRequestResult.h b/common/MySQLRequestResult.h index 0bf644c98..0f6cac40e 100644 --- a/common/MySQLRequestResult.h +++ b/common/MySQLRequestResult.h @@ -16,7 +16,9 @@ class MySQLRequestResult { private: MYSQL_RES* m_Result; + MYSQL_FIELD* m_Fields; char* m_ErrorBuffer; + unsigned long* m_ColumnLengths; MySQLRequestRow m_CurrentRow; MySQLRequestRow m_OneBeyondRow; @@ -44,6 +46,9 @@ public: uint32 RowCount() const {return m_RowCount;} uint32 ColumnCount() const {return m_ColumnCount;} uint32 LastInsertedID() const {return m_LastInsertedID;} + // default to 0 index since we mostly use it that way anyways. + uint32 LengthOfColumn(int columnIndex = 0); + const std::string FieldName(int columnIndex); MySQLRequestRow& begin() { return m_CurrentRow; } MySQLRequestRow& end() { return m_OneBeyondRow;} diff --git a/common/dbcore.cpp b/common/dbcore.cpp index ce1b41bdc..9b6236e5a 100644 --- a/common/dbcore.cpp +++ b/common/dbcore.cpp @@ -58,6 +58,11 @@ void DBcore::ping() { MDatabase.unlock(); } +MySQLRequestResult DBcore::QueryDatabase(std::string query, bool retryOnFailureOnce) +{ + return QueryDatabase(query.c_str(), query.length(), retryOnFailureOnce); +} + MySQLRequestResult DBcore::QueryDatabase(const char* query, uint32 querylen, bool retryOnFailureOnce) { LockMutex lock(&MDatabase); diff --git a/common/dbcore.h b/common/dbcore.h index 13a395eac..2c3602a81 100644 --- a/common/dbcore.h +++ b/common/dbcore.h @@ -7,6 +7,7 @@ #endif #include +#include #include "../common/types.h" #include "../common/Mutex.h" #include "../common/linked_list.h" @@ -24,6 +25,7 @@ public: 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); MySQLRequestResult QueryDatabase(const char* query, uint32 querylen, bool retryOnFailureOnce = true); + MySQLRequestResult QueryDatabase(std::string query, bool retryOnFailureOnce = true); uint32 DoEscapeString(char* tobuf, const char* frombuf, uint32 fromlen); void ping(); MYSQL* getMySQL(){ return &mysql; }