Skip to content

Commit

Permalink
[Database] Fix multi-statement error reporting (#3425)
Browse files Browse the repository at this point in the history
  • Loading branch information
Akkadius authored Jun 19, 2023
1 parent 66e377f commit 6d7beb1
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 12 deletions.
2 changes: 1 addition & 1 deletion common/database/database_update.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ bool DatabaseUpdate::UpdateManifest(

// ignore empty query result "errors"
if (r.ErrorNumber() != 1065 && !r.ErrorMessage().empty()) {
LogError("[{}]", r.ErrorMessage());
LogError("(#{}) [{}]", r.ErrorNumber(), r.ErrorMessage());
errored_migration = true;

LogInfo("Required database update failed. This could be a problem");
Expand Down
54 changes: 46 additions & 8 deletions common/dbcore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -323,8 +323,11 @@ MySQLRequestResult DBcore::QueryDatabaseMulti(const std::string &query)
if (pStatus != Connected) {
Open();
}
auto r = MySQLRequestResult{};

int status = mysql_real_query(mysql, query.c_str(), query.length());

// process single result
if (status != 0) {
unsigned int error_number = mysql_errno(mysql);

Expand All @@ -337,11 +340,35 @@ MySQLRequestResult DBcore::QueryDatabaseMulti(const std::string &query)
std::string error_raw = fmt::format("{}", mysql_error(mysql));
std::string mysql_err = Strings::Trim(error_raw);
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;

Expand All @@ -355,7 +382,7 @@ MySQLRequestResult DBcore::QueryDatabaseMulti(const std::string &query)
uint32 row_count = 0;
MYSQL_RES *res = mysql_store_result(mysql);

result = MySQLRequestResult(
r = MySQLRequestResult(
res,
(uint32) mysql_affected_rows(mysql),
row_count,
Expand All @@ -368,15 +395,14 @@ MySQLRequestResult DBcore::QueryDatabaseMulti(const std::string &query)
LogMySQLQuery(
"{} -- ({} row{} affected) ({}s)",
piece,
result.RowsAffected(),
result.RowsAffected() == 1 ? "" : "s",
r.RowsAffected(),
r.RowsAffected() == 1 ? "" : "s",
std::to_string(timer.elapsed())
);
}

if (res) {
row_count = (uint32) mysql_num_rows(res);
mysql_free_result(res);
}

// more results? -1 = no, >0 = error, 0 = yes (keep looping)
Expand All @@ -385,13 +411,25 @@ MySQLRequestResult DBcore::QueryDatabaseMulti(const std::string &query)
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
return result;
return r;
}

if (res) {
mysql_free_result(res);
}

index++;
} while (status == 0);

SetMultiStatementsOff();

return result;
return r;
}
21 changes: 21 additions & 0 deletions common/mysql_request_result.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ void MySQLRequestResult::ZeroOut()
m_RowCount = 0;
m_RowsAffected = 0;
m_LastInsertedID = 0;
m_error_message = "";
}

MySQLRequestResult::~MySQLRequestResult()
Expand Down Expand Up @@ -137,3 +138,23 @@ MySQLRequestResult& MySQLRequestResult::operator=(MySQLRequestResult&& other)
other.ZeroOut();
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;
}
18 changes: 15 additions & 3 deletions common/mysql_request_result.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,30 +33,42 @@ class MySQLRequestResult {
uint32 m_LastInsertedID;
uint32 m_ErrorNumber;

std::string m_error_message;

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(MySQLRequestResult&& moveItem);
~MySQLRequestResult();

MySQLRequestResult& operator=(MySQLRequestResult&& other);

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 RowsAffected() const {return m_RowsAffected;}
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);
uint32 LengthOfColumn(int columnIndex = 0);
const std::string FieldName(int columnIndex);

MySQLRequestRow& begin() { return m_CurrentRow; }
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:
void FreeInternals();
void ZeroOut();
Expand Down

0 comments on commit 6d7beb1

Please sign in to comment.