[Database] Add query multi statement execution support (#3414)

This commit is contained in:
Chris Miles
2023-06-17 18:20:13 -05:00
committed by GitHub
parent 3200145d01
commit b45e0e80b5
2 changed files with 104 additions and 1 deletions
+90
View File
@@ -13,6 +13,7 @@
#include <iostream>
#include <mysqld_error.h>
#include <string.h>
#include "strings.h"
#ifdef _WINDOWS
#define snprintf _snprintf
@@ -305,3 +306,92 @@ void DBcore::SetMutex(Mutex *mutex)
DBcore::m_mutex = mutex;
}
// executes multiple statements in one query
// do not use this in application logic
// this was built and maintained for database migrations only
MySQLRequestResult DBcore::QueryDatabaseMulti(const std::string &query)
{
SetMultiStatementsOn();
BenchTimer timer;
timer.reset();
LockMutex lock(m_mutex);
// Reconnect if we are not connected before hand.
if (pStatus != Connected) {
Open();
}
int status = mysql_real_query(mysql, query.c_str(), query.length());
if (status != 0) {
unsigned int error_number = mysql_errno(mysql);
if (error_number == CR_SERVER_GONE_ERROR) {
pStatus = Error;
}
// error logging
if (mysql_errno(mysql) > 0 && query.length() > 0 && mysql_errno(mysql) != 1065) {
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);
}
}
auto result = MySQLRequestResult{};
int index = 0;
// there could be a query with a semicolon in the actual data, this is best effort for
// logging / display purposes
// rare that we see this when this is only used in DDL statements
auto pieces = Strings::Split(query, ";");
// process each statement result
do {
uint32 row_count = 0;
MYSQL_RES *res = mysql_store_result(mysql);
result = MySQLRequestResult(
res,
(uint32) mysql_affected_rows(mysql),
row_count,
(uint32) mysql_field_count(mysql),
(uint32) mysql_insert_id(mysql)
);
if (pieces.size() >= index) {
auto piece = pieces[index];
LogMySQLQuery(
"{} -- ({} row{} affected) ({}s)",
piece,
result.RowsAffected(),
result.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)
if ((status = mysql_next_result(mysql)) > 0) {
if (mysql_errno(mysql) > 0) {
LogMySQLError("[{}] [{}]", mysql_errno(mysql), mysql_error(mysql));
}
// we handle errors elsewhere
return result;
}
index++;
} while (status == 0);
SetMultiStatementsOff();
return result;
}