From d514eef59b8906a176f59822a2f67cf127762899 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sat, 5 Jul 2014 10:10:55 -0700 Subject: [PATCH 1/3] Added LengthOfColumn method because of stupid BLOBs --- common/MySQLRequestResult.cpp | 29 +++++++++++++++++++++++++++++ common/MySQLRequestResult.h | 3 +++ 2 files changed, 32 insertions(+) diff --git a/common/MySQLRequestResult.cpp b/common/MySQLRequestResult.cpp index 16d7fe9a0..8fc47cfca 100644 --- a/common/MySQLRequestResult.cpp +++ b/common/MySQLRequestResult.cpp @@ -32,6 +32,10 @@ MySQLRequestResult::MySQLRequestResult(MYSQL_RES* result, uint32 rowsAffected, u m_RowsAffected = rowsAffected; m_RowCount = rowCount; m_ColumnCount = columnCount; + // If we actually need the column length 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_LastInsertedID = lastInsertedID; m_ErrorNumber = errorNumber; } @@ -51,6 +55,7 @@ void MySQLRequestResult::ZeroOut() m_Success = false; m_Result = nullptr; m_ErrorBuffer = nullptr; + m_ColumnLengths = nullptr; m_RowCount = 0; m_RowsAffected = 0; m_LastInsertedID = 0; @@ -61,6 +66,28 @@ 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]; +} + MySQLRequestResult::MySQLRequestResult(MySQLRequestResult&& moveItem) : m_CurrentRow(moveItem.m_CurrentRow), m_OneBeyondRow() { @@ -70,6 +97,7 @@ MySQLRequestResult::MySQLRequestResult(MySQLRequestResult&& moveItem) m_RowCount = moveItem.m_RowCount; m_RowsAffected = moveItem.m_RowsAffected; m_LastInsertedID = moveItem.m_LastInsertedID; + m_ColumnLengths = moveItem.m_ColumnLengths; // Keeps deconstructor from double freeing // pre move instance. @@ -95,6 +123,7 @@ 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; // Keeps deconstructor from double freeing // pre move instance. diff --git a/common/MySQLRequestResult.h b/common/MySQLRequestResult.h index 05f363722..4859a625f 100644 --- a/common/MySQLRequestResult.h +++ b/common/MySQLRequestResult.h @@ -17,6 +17,7 @@ class MySQLRequestResult { private: MYSQL_RES* m_Result; char* m_ErrorBuffer; + unsigned long* m_ColumnLengths; MySQLRequestRow m_CurrentRow; MySQLRequestRow m_OneBeyondRow; @@ -44,6 +45,8 @@ 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); MySQLRequestRow& begin() { return m_CurrentRow; } MySQLRequestRow& end() { return m_OneBeyondRow;} From 923adc3ea5c747849bf6dd953cdfaedbd3229817 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sun, 6 Jul 2014 16:01:10 -0700 Subject: [PATCH 2/3] Added FieldName for column name requests --- common/MySQLRequestResult.cpp | 21 ++++++++++++++++++--- common/MySQLRequestResult.h | 2 ++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/common/MySQLRequestResult.cpp b/common/MySQLRequestResult.cpp index 8fc47cfca..56e62ae37 100644 --- a/common/MySQLRequestResult.cpp +++ b/common/MySQLRequestResult.cpp @@ -32,10 +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 it will be requested - // at that time, no need to pull it in just to cache it. + // 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; } @@ -56,6 +57,7 @@ void MySQLRequestResult::ZeroOut() m_Result = nullptr; m_ErrorBuffer = nullptr; m_ColumnLengths = nullptr; + m_Fields = nullptr; m_RowCount = 0; m_RowsAffected = 0; m_LastInsertedID = 0; @@ -88,6 +90,17 @@ uint32 MySQLRequestResult::LengthOfColumn(int columnIndex) 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() { @@ -98,6 +111,7 @@ MySQLRequestResult::MySQLRequestResult(MySQLRequestResult&& moveItem) 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. @@ -124,7 +138,8 @@ MySQLRequestResult& MySQLRequestResult::operator=(MySQLRequestResult&& other) 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 4859a625f..6cb110b1d 100644 --- a/common/MySQLRequestResult.h +++ b/common/MySQLRequestResult.h @@ -16,6 +16,7 @@ class MySQLRequestResult { private: MYSQL_RES* m_Result; + MYSQL_FIELD* m_Fields; char* m_ErrorBuffer; unsigned long* m_ColumnLengths; MySQLRequestRow m_CurrentRow; @@ -47,6 +48,7 @@ public: 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;} From c175369ff65242a96e4e3f50c3d9e9cefe920f12 Mon Sep 17 00:00:00 2001 From: Arthur Ice Date: Sun, 6 Jul 2014 16:15:54 -0700 Subject: [PATCH 3/3] string based QueryDatabase --- common/dbcore.cpp | 5 +++++ common/dbcore.h | 2 ++ 2 files changed, 7 insertions(+) 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; }