diff options
Diffstat (limited to 'src/server/database/Database/Field.h')
-rw-r--r-- | src/server/database/Database/Field.h | 394 |
1 files changed, 394 insertions, 0 deletions
diff --git a/src/server/database/Database/Field.h b/src/server/database/Database/Field.h new file mode 100644 index 00000000000..65d1c131e32 --- /dev/null +++ b/src/server/database/Database/Field.h @@ -0,0 +1,394 @@ +/* + * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> + * + * This program 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 2 of the License, or (at your + * option) any later version. + * + * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _FIELD_H +#define _FIELD_H + +#include "Common.h" +#include "Log.h" + +#include <mysql.h> + +class Field +{ + friend class ResultSet; + friend class PreparedResultSet; + + public: + + bool GetBool() const // Wrapper, actually gets integer + { + return GetUInt8() == 1 ? true : false; + } + + uint8 GetUInt8() const + { + if (!data.value) + return 0; + + #ifdef TRINITY_DEBUG + if (!IsType(MYSQL_TYPE_TINY)) + { + TC_LOG_WARN("sql.sql", "Warning: GetUInt8() on non-tinyint field. Using type: %s.", FieldTypeToString(data.type)); + return 0; + } + #endif + + if (data.raw) + return *reinterpret_cast<uint8*>(data.value); + return static_cast<uint8>(strtoul((char*)data.value, nullptr, 10)); + } + + int8 GetInt8() const + { + if (!data.value) + return 0; + + #ifdef TRINITY_DEBUG + if (!IsType(MYSQL_TYPE_TINY)) + { + TC_LOG_WARN("sql.sql", "Warning: GetInt8() on non-tinyint field. Using type: %s.", FieldTypeToString(data.type)); + return 0; + } + #endif + + if (data.raw) + return *reinterpret_cast<int8*>(data.value); + return static_cast<int8>(strtol((char*)data.value, NULL, 10)); + } + + uint16 GetUInt16() const + { + if (!data.value) + return 0; + + #ifdef TRINITY_DEBUG + if (!IsType(MYSQL_TYPE_SHORT) && !IsType(MYSQL_TYPE_YEAR)) + { + TC_LOG_WARN("sql.sql", "Warning: GetUInt16() on non-smallint field. Using type: %s.", FieldTypeToString(data.type)); + return 0; + } + #endif + + if (data.raw) + return *reinterpret_cast<uint16*>(data.value); + return static_cast<uint16>(strtoul((char*)data.value, nullptr, 10)); + } + + int16 GetInt16() const + { + if (!data.value) + return 0; + + #ifdef TRINITY_DEBUG + if (!IsType(MYSQL_TYPE_SHORT) && !IsType(MYSQL_TYPE_YEAR)) + { + TC_LOG_WARN("sql.sql", "Warning: GetInt16() on non-smallint field. Using type: %s.", FieldTypeToString(data.type)); + return 0; + } + #endif + + if (data.raw) + return *reinterpret_cast<int16*>(data.value); + return static_cast<int16>(strtol((char*)data.value, NULL, 10)); + } + + uint32 GetUInt32() const + { + if (!data.value) + return 0; + + #ifdef TRINITY_DEBUG + if (!IsType(MYSQL_TYPE_INT24) && !IsType(MYSQL_TYPE_LONG)) + { + TC_LOG_WARN("sql.sql", "Warning: GetUInt32() on non-(medium)int field. Using type: %s.", FieldTypeToString(data.type)); + return 0; + } + #endif + + if (data.raw) + return *reinterpret_cast<uint32*>(data.value); + return static_cast<uint32>(strtoul((char*)data.value, nullptr, 10)); + } + + int32 GetInt32() const + { + if (!data.value) + return 0; + + #ifdef TRINITY_DEBUG + if (!IsType(MYSQL_TYPE_INT24) && !IsType(MYSQL_TYPE_LONG)) + { + TC_LOG_WARN("sql.sql", "Warning: GetInt32() on non-(medium)int field. Using type: %s.", FieldTypeToString(data.type)); + return 0; + } + #endif + + if (data.raw) + return *reinterpret_cast<int32*>(data.value); + return static_cast<int32>(strtol((char*)data.value, NULL, 10)); + } + + uint64 GetUInt64() const + { + if (!data.value) + return 0; + + #ifdef TRINITY_DEBUG + if (!IsType(MYSQL_TYPE_LONGLONG) && !IsType(MYSQL_TYPE_BIT)) + { + TC_LOG_WARN("sql.sql", "Warning: GetUInt64() on non-bigint field. Using type: %s.", FieldTypeToString(data.type)); + return 0; + } + #endif + + if (data.raw) + return *reinterpret_cast<uint64*>(data.value); + return static_cast<uint64>(strtoull((char*)data.value, nullptr, 10)); + } + + int64 GetInt64() const + { + if (!data.value) + return 0; + + #ifdef TRINITY_DEBUG + if (!IsType(MYSQL_TYPE_LONGLONG) && !IsType(MYSQL_TYPE_BIT)) + { + TC_LOG_WARN("sql.sql", "Warning: GetInt64() on non-bigint field. Using type: %s.", FieldTypeToString(data.type)); + return 0; + } + #endif + + if (data.raw) + return *reinterpret_cast<int64*>(data.value); + return static_cast<int64>(strtoll((char*)data.value, NULL, 10)); + } + + float GetFloat() const + { + if (!data.value) + return 0.0f; + + #ifdef TRINITY_DEBUG + if (!IsType(MYSQL_TYPE_FLOAT)) + { + TC_LOG_WARN("sql.sql", "Warning: GetFloat() on non-float field. Using type: %s.", FieldTypeToString(data.type)); + return 0.0f; + } + #endif + + if (data.raw) + return *reinterpret_cast<float*>(data.value); + return static_cast<float>(atof((char*)data.value)); + } + + double GetDouble() const + { + if (!data.value) + return 0.0f; + + #ifdef TRINITY_DEBUG + if (!IsType(MYSQL_TYPE_DOUBLE)) + { + TC_LOG_WARN("sql.sql", "Warning: GetDouble() on non-double field. Using type: %s.", FieldTypeToString(data.type)); + return 0.0f; + } + #endif + + if (data.raw) + return *reinterpret_cast<double*>(data.value); + return static_cast<double>(atof((char*)data.value)); + } + + char const* GetCString() const + { + if (!data.value) + return NULL; + + #ifdef TRINITY_DEBUG + if (IsNumeric()) + { + TC_LOG_WARN("sql.sql", "Error: GetCString() on numeric field. Using type: %s.", FieldTypeToString(data.type)); + return NULL; + } + #endif + return static_cast<char const*>(data.value); + } + + std::string GetString() const + { + if (!data.value) + return ""; + + if (data.raw) + { + char const* string = GetCString(); + if (!string) + return ""; + + return std::string(string, data.length); + } + + return std::string((char*)data.value, data.length); + } + + std::vector<uint8> GetBinary() const + { + std::vector<uint8> result; + if (!data.value || !data.length) + return result; + + result.resize(data.length); + memcpy(result.data(), data.value, data.length); + return result; + } + + bool IsNull() const + { + return data.value == NULL; + } + + protected: + Field(); + ~Field(); + + #pragma pack(push, 1) + struct + { + uint32 length; // Length (prepared strings only) + void* value; // Actual data in memory + enum_field_types type; // Field type + bool raw; // Raw bytes? (Prepared statement or ad hoc) + } data; + #pragma pack(pop) + + void SetByteValue(void const* newValue, size_t const newSize, enum_field_types newType, uint32 length); + void SetStructuredValue(char* newValue, enum_field_types newType, uint32 length); + + void CleanUp() + { + delete[] ((char*)data.value); + data.value = NULL; + } + + static size_t SizeForType(MYSQL_FIELD* field) + { + switch (field->type) + { + case MYSQL_TYPE_NULL: + return 0; + case MYSQL_TYPE_TINY: + return 1; + case MYSQL_TYPE_YEAR: + case MYSQL_TYPE_SHORT: + return 2; + case MYSQL_TYPE_INT24: + case MYSQL_TYPE_LONG: + case MYSQL_TYPE_FLOAT: + return 4; + case MYSQL_TYPE_DOUBLE: + case MYSQL_TYPE_LONGLONG: + case MYSQL_TYPE_BIT: + return 8; + + case MYSQL_TYPE_TIMESTAMP: + case MYSQL_TYPE_DATE: + case MYSQL_TYPE_TIME: + case MYSQL_TYPE_DATETIME: + return sizeof(MYSQL_TIME); + + case MYSQL_TYPE_TINY_BLOB: + case MYSQL_TYPE_MEDIUM_BLOB: + case MYSQL_TYPE_LONG_BLOB: + case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_STRING: + case MYSQL_TYPE_VAR_STRING: + return field->max_length + 1; + + case MYSQL_TYPE_DECIMAL: + case MYSQL_TYPE_NEWDECIMAL: + return 64; + + case MYSQL_TYPE_GEOMETRY: + /* + Following types are not sent over the wire: + MYSQL_TYPE_ENUM: + MYSQL_TYPE_SET: + */ + default: + TC_LOG_WARN("sql.sql", "SQL::SizeForType(): invalid field type %u", uint32(field->type)); + return 0; + } + } + + bool IsType(enum_field_types type) const + { + return data.type == type; + } + + bool IsNumeric() const + { + return (data.type == MYSQL_TYPE_TINY || + data.type == MYSQL_TYPE_SHORT || + data.type == MYSQL_TYPE_INT24 || + data.type == MYSQL_TYPE_LONG || + data.type == MYSQL_TYPE_FLOAT || + data.type == MYSQL_TYPE_DOUBLE || + data.type == MYSQL_TYPE_LONGLONG ); + } + + private: + #ifdef TRINITY_DEBUG + static char const* FieldTypeToString(enum_field_types type) + { + switch (type) + { + case MYSQL_TYPE_BIT: return "BIT"; + case MYSQL_TYPE_BLOB: return "BLOB"; + case MYSQL_TYPE_DATE: return "DATE"; + case MYSQL_TYPE_DATETIME: return "DATETIME"; + case MYSQL_TYPE_NEWDECIMAL: return "NEWDECIMAL"; + case MYSQL_TYPE_DECIMAL: return "DECIMAL"; + case MYSQL_TYPE_DOUBLE: return "DOUBLE"; + case MYSQL_TYPE_ENUM: return "ENUM"; + case MYSQL_TYPE_FLOAT: return "FLOAT"; + case MYSQL_TYPE_GEOMETRY: return "GEOMETRY"; + case MYSQL_TYPE_INT24: return "INT24"; + case MYSQL_TYPE_LONG: return "LONG"; + case MYSQL_TYPE_LONGLONG: return "LONGLONG"; + case MYSQL_TYPE_LONG_BLOB: return "LONG_BLOB"; + case MYSQL_TYPE_MEDIUM_BLOB: return "MEDIUM_BLOB"; + case MYSQL_TYPE_NEWDATE: return "NEWDATE"; + case MYSQL_TYPE_NULL: return "NULL"; + case MYSQL_TYPE_SET: return "SET"; + case MYSQL_TYPE_SHORT: return "SHORT"; + case MYSQL_TYPE_STRING: return "STRING"; + case MYSQL_TYPE_TIME: return "TIME"; + case MYSQL_TYPE_TIMESTAMP: return "TIMESTAMP"; + case MYSQL_TYPE_TINY: return "TINY"; + case MYSQL_TYPE_TINY_BLOB: return "TINY_BLOB"; + case MYSQL_TYPE_VAR_STRING: return "VAR_STRING"; + case MYSQL_TYPE_YEAR: return "YEAR"; + default: return "-Unknown-"; + } + } + #endif +}; + +#endif + |