Merge branch 'nellag/database-result-optimisations' of devn00b/EQ2EMu into master

Thanks for the great addition!
This commit is contained in:
image 2024-04-02 11:15:26 +00:00 committed by Gogs
commit 5a791384a9
3 changed files with 33 additions and 50 deletions

View file

@ -233,7 +233,13 @@ bool DatabaseNew::Select(DatabaseResult *result, const char *query, ...) {
res = mysql_store_result(&mysql);
if (res != NULL)
ret = result->StoreResult(res);
{
// Grab number of rows and number of fields from the query
uint8 num_rows = mysql_affected_rows(&mysql);
uint8 num_fields = mysql_field_count(&mysql);
ret = result->StoreResult(res, num_fields, num_rows);
}
else {
LogWrite(DATABASE__ERROR, 0, "Database", "Error storing MySql query result (%d): %s\n%s", mysql_errno(&mysql), mysql_error(&mysql), buf);
ret = false;

View file

@ -28,11 +28,7 @@
//return this instead of NULL for certain functions to prevent crashes from coding errors
static const char *empty_str = "";
DatabaseResult::DatabaseResult() {
result = NULL;
field_names = NULL;
num_fields = 0;
row = 0;
DatabaseResult::DatabaseResult(): field_map(), result(0), num_fields(0), row(0) {
}
DatabaseResult::~DatabaseResult() {
@ -41,58 +37,38 @@ DatabaseResult::~DatabaseResult() {
if (result != NULL)
mysql_free_result(result);
if (field_names != NULL) {
for (i = 0; i < num_fields; i++)
free(field_names[i]);
free(field_names);
if (field_map.size()) {
field_map.clear();
}
}
bool DatabaseResult::StoreResult(MYSQL_RES *res) {
unsigned int i, j;
MYSQL_FIELD *field;
bool DatabaseResult::StoreResult(MYSQL_RES* res, uint8 field_count, uint8 row_count) {
//clear any previously stored result
if (result != NULL)
mysql_free_result(result);
//clear any field names from a previous result
if (field_names != NULL) {
for (i = 0; i < num_fields; i++)
free(field_names[i]);
free(field_names);
if (field_map.size()) {
field_map.clear();
}
//store the new result
result = res;
num_fields = mysql_num_fields(res);
num_rows = row_count;
num_fields = field_count;
//allocate enough space for each field's name
if ((field_names = (char **)malloc(sizeof(char *) * num_fields)) == NULL) {
LogWrite(DATABASE__ERROR, 0, "Database Result", "Unable to allocate %u bytes when storing database result and fetching field names\nNumber of fields=%u\n", sizeof(char *) * num_fields, num_fields);
mysql_free_result(result);
// No rows or fields then we don't care
if (!num_rows || !num_fields) {
mysql_free_result(res);
result = NULL;
num_fields = 0;
return false;
}
//store each field's name
i = 0;
while ((field = mysql_fetch_field(result)) != NULL) {
if ((field_names[i] = (char *)calloc(field->name_length + 1, sizeof(char))) == NULL) {
LogWrite(DATABASE__ERROR, 0, "Database Result", "Unable to allocate %u bytes when storing databse result and copying field name %s\n", field->name_length + 1, field->name);
mysql_free_result(result);
result = NULL;
for (j = 0; j < i; j++)
free(field_names[j]);
free(field_names);
field_names = NULL;
num_fields = 0;
return false;
}
strncpy(field_names[i], field->name, field->name_length);
i++;
const MYSQL_FIELD* fields = mysql_fetch_fields(result);
for (uint8 i = 0; i < num_fields; ++i) {
field_map.emplace(std::make_pair(std::string_view(fields[i].name), i));
}
return true;
@ -108,11 +84,9 @@ const char * DatabaseResult::GetFieldValue(unsigned int index) {
}
const char * DatabaseResult::GetFieldValueStr(const char *field_name) {
unsigned int i;
for (i = 0; i < num_fields; i++) {
if (strncmp(field_name, field_names[i], FIELD_NAME_MAX) == 0)
return row[i];
const auto& map_iterator = field_map.find(std::string_view(field_name));
if (map_iterator != field_map.end()) {
return row[map_iterator->second];
}
LogWrite(DATABASE__ERROR, 0, "Database Result", "Unknown field name '%s'", field_name);

View file

@ -6,13 +6,14 @@
#include <WinSock2.h> //#include <my_global.h> when we/if we go to winsock2 :/
#endif
#include <mysql.h>
#include <map>
class DatabaseResult {
public:
DatabaseResult();
virtual ~DatabaseResult();
bool StoreResult(MYSQL_RES *res);
bool StoreResult(MYSQL_RES* result, uint8 field_count, uint8 row_count);
bool Next();
bool IsNull(unsigned int index);
@ -40,15 +41,17 @@ public:
const char * GetString(unsigned int index);
const char * GetStringStr(const char *field_name);
unsigned int GetNumRows() {return result == NULL ? 0 : (unsigned int)mysql_num_rows(result);}
const unsigned int GetNumRows() { return num_rows; }
const char * GetFieldValue(unsigned int index);
const char * GetFieldValueStr(const char *field_name);
private:
MYSQL_RES *result;
MYSQL_ROW row;
char **field_names;
unsigned int num_rows;
unsigned int num_fields;
std::map<std::string_view,uint8> field_map;
};
#endif