/* EQ2Emulator: Everquest II Server Emulator Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net) This file is part of EQ2Emulator. EQ2Emulator is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. EQ2Emulator is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with EQ2Emulator. If not, see . */ #include #include #include "Log.h" #include "DatabaseResult.h" //enforced by MySQL...couldn't find a #define in their headers though #define FIELD_NAME_MAX 64 //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() { unsigned int i; 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); } } bool DatabaseResult::StoreResult(MYSQL_RES *res) { unsigned int i, j; MYSQL_FIELD *field; //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); } //store the new result result = res; num_fields = mysql_num_fields(res); //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); 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++; } return true; } const char * DatabaseResult::GetFieldValue(unsigned int index) { if (index >= num_fields) { LogWrite(DATABASE__ERROR, 0, "Database Result", "Attempt to access field at index %u but there %s only %u field%s", index, num_fields == 1 ? "is" : "are", num_fields, num_fields == 1 ? "" : "s"); return NULL; } return row[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]; } LogWrite(DATABASE__ERROR, 0, "Database Result", "Unknown field name '%s'", field_name); return NULL; } bool DatabaseResult::Next() { return (result != NULL && (row = mysql_fetch_row(result)) != NULL); } bool DatabaseResult::IsNull(unsigned int index) { const char *value = GetFieldValue(index); return value == NULL; } bool DatabaseResult::IsNullStr(const char *field_name) { const char *value = GetFieldValueStr(field_name); return value == NULL; } int8 DatabaseResult::GetInt8(unsigned int index) { const char *value = GetFieldValue(index); return value == NULL ? 0 : atoi(value); } int8 DatabaseResult::GetInt8Str(const char *field_name) { const char *value = GetFieldValueStr(field_name); return value == NULL ? 0 : atoi(value); } sint8 DatabaseResult::GetSInt8(unsigned int index) { const char *value = GetFieldValue(index); return value == NULL ? 0 : atoi(value); } sint8 DatabaseResult::GetSInt8Str(const char *field_name) { const char *value = GetFieldValueStr(field_name); return value == NULL ? 0 : atoi(value); } int16 DatabaseResult::GetInt16(unsigned int index) { const char *value = GetFieldValue(index); return value == NULL ? 0 : atoi(value); } int16 DatabaseResult::GetInt16Str(const char *field_name) { const char *value = GetFieldValueStr(field_name); return value == NULL ? 0 : atoi(value); } sint16 DatabaseResult::GetSInt16(unsigned int index) { const char *value = GetFieldValue(index); return value == NULL ? 0 : atoi(value); } sint16 DatabaseResult::GetSInt16Str(const char *field_name) { const char *value = GetFieldValueStr(field_name); return value == NULL ? 0 : atoi(value); } int32 DatabaseResult::GetInt32(unsigned int index) { const char *value = GetFieldValue(index); return value == NULL ? 0U : strtoul(value, NULL, 10); } int32 DatabaseResult::GetInt32Str(const char *field_name) { const char *value = GetFieldValueStr(field_name); return value == NULL ? 0U : strtoul(value, NULL, 10); } sint32 DatabaseResult::GetSInt32(unsigned int index) { const char *value = GetFieldValue(index); return value == NULL ? 0 : atoi(value); } sint32 DatabaseResult::GetSInt32Str(const char *field_name) { const char *value = GetFieldValueStr(field_name); return value == NULL ? 0 : atoi(value); } uint64 DatabaseResult::GetInt64(unsigned int index) { const char *value = GetFieldValue(index); #ifdef _WIN32 return value == NULL ? 0UL : _strtoui64(value, NULL, 10); #else return value == NULL ? 0UL : strtoull(value, NULL, 10); #endif } uint64 DatabaseResult::GetInt64Str(const char *field_name) { const char *value = GetFieldValueStr(field_name); #ifdef _WIN32 return value == NULL ? 0UL : _strtoui64(value, NULL, 10); #else return value == NULL ? 0UL : strtoull(value, NULL, 10); #endif } sint64 DatabaseResult::GetSInt64(unsigned int index) { const char *value = GetFieldValue(index); #ifdef _WIN32 return value == NULL ? 0L : _strtoi64(value, NULL, 10); #else return value == NULL ? 0L : strtoll(value, NULL, 10); #endif } sint64 DatabaseResult::GetSInt64Str(const char *field_name) { const char *value = GetFieldValueStr(field_name); #ifdef _WIN32 return value == NULL ? 0L : _strtoi64(value, NULL, 10); #else return value == NULL ? 0L : strtoll(value, NULL, 10); #endif } float DatabaseResult::GetFloat(unsigned int index) { const char *value = GetFieldValue(index); return value == NULL ? 0.0F : atof(value); } float DatabaseResult::GetFloatStr(const char *field_name) { const char *value = GetFieldValueStr(field_name); return value == NULL ? 0.0F : atof(value); } char DatabaseResult::GetChar(unsigned int index) { const char *value = GetFieldValue(index); return value == NULL ? '\0' : value[0]; } char DatabaseResult::GetCharStr(const char *field_name) { const char *value = GetFieldValueStr(field_name); return value == NULL ? '\0' : value[0]; } const char * DatabaseResult::GetString(unsigned int index) { const char *value = GetFieldValue(index); return value == NULL ? empty_str : value; } const char * DatabaseResult::GetStringStr(const char *field_name) { const char *value = GetFieldValueStr(field_name); return value == NULL ? empty_str : value; }