[Database] Fix multi-statement error reporting (#3425)

This commit is contained in:
Chris Miles 2023-06-19 11:55:32 -05:00 committed by GitHub
parent 66e377fd4a
commit 6d7beb1796
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 83 additions and 12 deletions

View File

@ -183,7 +183,7 @@ bool DatabaseUpdate::UpdateManifest(
// ignore empty query result "errors" // ignore empty query result "errors"
if (r.ErrorNumber() != 1065 && !r.ErrorMessage().empty()) { if (r.ErrorNumber() != 1065 && !r.ErrorMessage().empty()) {
LogError("[{}]", r.ErrorMessage()); LogError("(#{}) [{}]", r.ErrorNumber(), r.ErrorMessage());
errored_migration = true; errored_migration = true;
LogInfo("Required database update failed. This could be a problem"); LogInfo("Required database update failed. This could be a problem");

View File

@ -323,8 +323,11 @@ MySQLRequestResult DBcore::QueryDatabaseMulti(const std::string &query)
if (pStatus != Connected) { if (pStatus != Connected) {
Open(); Open();
} }
auto r = MySQLRequestResult{};
int status = mysql_real_query(mysql, query.c_str(), query.length()); int status = mysql_real_query(mysql, query.c_str(), query.length());
// process single result
if (status != 0) { if (status != 0) {
unsigned int error_number = mysql_errno(mysql); unsigned int error_number = mysql_errno(mysql);
@ -337,11 +340,35 @@ MySQLRequestResult DBcore::QueryDatabaseMulti(const std::string &query)
std::string error_raw = fmt::format("{}", mysql_error(mysql)); std::string error_raw = fmt::format("{}", mysql_error(mysql));
std::string mysql_err = Strings::Trim(error_raw); std::string mysql_err = Strings::Trim(error_raw);
std::string clean_query = Strings::Replace(query, "\n", ""); std::string clean_query = Strings::Replace(query, "\n", "");
LogMySQLQuery("[{}] ({}) query [{}]", mysql_err, mysql_errno(mysql), clean_query); LogMySQLError("[{}] ({}) query [{}]", mysql_err, mysql_errno(mysql), clean_query);
MYSQL_RES *res = mysql_store_result(mysql);
uint32 row_count = 0;
if (res) {
row_count = (uint32) mysql_num_rows(res);
}
r = MySQLRequestResult(
res,
(uint32) mysql_affected_rows(mysql),
row_count,
(uint32) mysql_field_count(mysql),
(uint32) mysql_insert_id(mysql)
);
std::string error_message = mysql_error(mysql);
r.SetErrorMessage(error_message);
r.SetErrorNumber(mysql_errno(mysql));
if (res) {
mysql_free_result(res);
}
return r;
} }
} }
auto result = MySQLRequestResult{};
int index = 0; int index = 0;
@ -355,7 +382,7 @@ MySQLRequestResult DBcore::QueryDatabaseMulti(const std::string &query)
uint32 row_count = 0; uint32 row_count = 0;
MYSQL_RES *res = mysql_store_result(mysql); MYSQL_RES *res = mysql_store_result(mysql);
result = MySQLRequestResult( r = MySQLRequestResult(
res, res,
(uint32) mysql_affected_rows(mysql), (uint32) mysql_affected_rows(mysql),
row_count, row_count,
@ -368,15 +395,14 @@ MySQLRequestResult DBcore::QueryDatabaseMulti(const std::string &query)
LogMySQLQuery( LogMySQLQuery(
"{} -- ({} row{} affected) ({}s)", "{} -- ({} row{} affected) ({}s)",
piece, piece,
result.RowsAffected(), r.RowsAffected(),
result.RowsAffected() == 1 ? "" : "s", r.RowsAffected() == 1 ? "" : "s",
std::to_string(timer.elapsed()) std::to_string(timer.elapsed())
); );
} }
if (res) { if (res) {
row_count = (uint32) mysql_num_rows(res); row_count = (uint32) mysql_num_rows(res);
mysql_free_result(res);
} }
// more results? -1 = no, >0 = error, 0 = yes (keep looping) // more results? -1 = no, >0 = error, 0 = yes (keep looping)
@ -385,13 +411,25 @@ MySQLRequestResult DBcore::QueryDatabaseMulti(const std::string &query)
LogMySQLError("[{}] [{}]", mysql_errno(mysql), mysql_error(mysql)); LogMySQLError("[{}] [{}]", mysql_errno(mysql), mysql_error(mysql));
} }
mysql_free_result(res);
// error logging
std::string error_message = mysql_error(mysql);
r.SetErrorMessage(error_message);
r.SetErrorNumber(mysql_errno(mysql));
// we handle errors elsewhere // we handle errors elsewhere
return result; return r;
} }
if (res) {
mysql_free_result(res);
}
index++; index++;
} while (status == 0); } while (status == 0);
SetMultiStatementsOff(); SetMultiStatementsOff();
return result; return r;
} }

View File

@ -51,6 +51,7 @@ void MySQLRequestResult::ZeroOut()
m_RowCount = 0; m_RowCount = 0;
m_RowsAffected = 0; m_RowsAffected = 0;
m_LastInsertedID = 0; m_LastInsertedID = 0;
m_error_message = "";
} }
MySQLRequestResult::~MySQLRequestResult() MySQLRequestResult::~MySQLRequestResult()
@ -137,3 +138,23 @@ MySQLRequestResult& MySQLRequestResult::operator=(MySQLRequestResult&& other)
other.ZeroOut(); other.ZeroOut();
return *this; return *this;
} }
uint32 MySQLRequestResult::GetErrorNumber() const
{
return m_ErrorNumber;
}
void MySQLRequestResult::SetErrorNumber(uint32 m_error_number)
{
m_ErrorNumber = m_error_number;
}
const std::string &MySQLRequestResult::GetErrorMessage() const
{
return m_error_message;
}
void MySQLRequestResult::SetErrorMessage(const std::string &m_error_message)
{
MySQLRequestResult::m_error_message = m_error_message;
}

View File

@ -33,6 +33,7 @@ private:
uint32 m_LastInsertedID; uint32 m_LastInsertedID;
uint32 m_ErrorNumber; uint32 m_ErrorNumber;
std::string m_error_message;
public: public:
@ -44,7 +45,13 @@ public:
MySQLRequestResult& operator=(MySQLRequestResult&& other); MySQLRequestResult& operator=(MySQLRequestResult&& other);
bool Success() const { return m_Success;} bool Success() const { return m_Success;}
std::string ErrorMessage() const {return m_ErrorBuffer ? std::string(m_ErrorBuffer) : std::string("");} std::string ErrorMessage() const {
if (!m_error_message.empty()) {
return m_error_message;
}
return m_ErrorBuffer ? std::string(m_ErrorBuffer) : std::string("");
}
uint32 ErrorNumber() const {return m_ErrorNumber;} uint32 ErrorNumber() const {return m_ErrorNumber;}
uint32 RowsAffected() const {return m_RowsAffected;} uint32 RowsAffected() const {return m_RowsAffected;}
uint32 RowCount() const {return m_RowCount;} uint32 RowCount() const {return m_RowCount;}
@ -57,6 +64,11 @@ public:
MySQLRequestRow& begin() { return m_CurrentRow; } MySQLRequestRow& begin() { return m_CurrentRow; }
MySQLRequestRow& end() { return m_OneBeyondRow; } MySQLRequestRow& end() { return m_OneBeyondRow; }
uint32 GetErrorNumber() const;
void SetErrorNumber(uint32 m_error_number);
const std::string &GetErrorMessage() const;
void SetErrorMessage(const std::string &m_error_message);
private: private:
void FreeInternals(); void FreeInternals();
void ZeroOut(); void ZeroOut();