aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/database/Database/Field.cpp217
-rw-r--r--src/server/database/Database/Field.h37
-rw-r--r--src/server/database/Database/FieldValueConverter.cpp48
-rw-r--r--src/server/database/Database/FieldValueConverter.h50
-rw-r--r--src/server/database/Database/FieldValueConverters.h112
-rw-r--r--src/server/database/Database/QueryResult.cpp76
6 files changed, 321 insertions, 219 deletions
diff --git a/src/server/database/Database/Field.cpp b/src/server/database/Database/Field.cpp
index cdcb32c6508..6957cec00ad 100644
--- a/src/server/database/Database/Field.cpp
+++ b/src/server/database/Database/Field.cpp
@@ -17,294 +17,153 @@
#include "Field.h"
#include "Errors.h"
+#include "FieldValueConverter.h"
#include "Log.h"
-#include "StringConvert.h"
#include <cstring>
-Field::Field()
+Field::Field() : _value(nullptr), _length(0), _meta(nullptr)
{
- data.value = nullptr;
- data.length = 0;
- data.raw = false;
- meta = nullptr;
}
Field::~Field() = default;
uint8 Field::GetUInt8() const
{
- if (!data.value)
+ if (!_value)
return 0;
-#ifdef TRINITY_STRICT_DATABASE_TYPE_CHECKS
- if (!IsType(DatabaseFieldTypes::Int8))
- {
- LogWrongType(__FUNCTION__);
- return 0;
- }
-#endif
-
- if (data.raw)
- return *reinterpret_cast<uint8 const*>(data.value);
- return Trinity::StringTo<uint8>(data.value, 10).value_or(0);
+ return _meta->Converter->GetUInt8(_value, _length, _meta);
}
int8 Field::GetInt8() const
{
- if (!data.value)
+ if (!_value)
return 0;
-#ifdef TRINITY_STRICT_DATABASE_TYPE_CHECKS
- if (!IsType(DatabaseFieldTypes::Int8))
- {
- LogWrongType(__FUNCTION__);
- return 0;
- }
-#endif
-
- if (data.raw)
- return *reinterpret_cast<int8 const*>(data.value);
- return Trinity::StringTo<int8>(data.value, 10).value_or(0);
+ return _meta->Converter->GetInt8(_value, _length, _meta);
}
uint16 Field::GetUInt16() const
{
- if (!data.value)
+ if (!_value)
return 0;
-#ifdef TRINITY_STRICT_DATABASE_TYPE_CHECKS
- if (!IsType(DatabaseFieldTypes::Int16))
- {
- LogWrongType(__FUNCTION__);
- return 0;
- }
-#endif
-
- if (data.raw)
- return *reinterpret_cast<uint16 const*>(data.value);
- return Trinity::StringTo<uint16>(data.value, 10).value_or(0);
+ return _meta->Converter->GetUInt16(_value, _length, _meta);
}
int16 Field::GetInt16() const
{
- if (!data.value)
- return 0;
-
-#ifdef TRINITY_STRICT_DATABASE_TYPE_CHECKS
- if (!IsType(DatabaseFieldTypes::Int16))
- {
- LogWrongType(__FUNCTION__);
+ if (!_value)
return 0;
- }
-#endif
- if (data.raw)
- return *reinterpret_cast<int16 const*>(data.value);
- return Trinity::StringTo<int16>(data.value, 10).value_or(0);
+ return _meta->Converter->GetInt16(_value, _length, _meta);
}
uint32 Field::GetUInt32() const
{
- if (!data.value)
+ if (!_value)
return 0;
-#ifdef TRINITY_STRICT_DATABASE_TYPE_CHECKS
- if (!IsType(DatabaseFieldTypes::Int32))
- {
- LogWrongType(__FUNCTION__);
- return 0;
- }
-#endif
-
- if (data.raw)
- return *reinterpret_cast<uint32 const*>(data.value);
- return Trinity::StringTo<uint32>(data.value, 10).value_or(0);
+ return _meta->Converter->GetUInt32(_value, _length, _meta);
}
int32 Field::GetInt32() const
{
- if (!data.value)
- return 0;
-
-#ifdef TRINITY_STRICT_DATABASE_TYPE_CHECKS
- if (!IsType(DatabaseFieldTypes::Int32))
- {
- LogWrongType(__FUNCTION__);
+ if (!_value)
return 0;
- }
-#endif
- if (data.raw)
- return *reinterpret_cast<int32 const*>(data.value);
- return Trinity::StringTo<int32>(data.value, 10).value_or(0);
+ return _meta->Converter->GetInt32(_value, _length, _meta);
}
uint64 Field::GetUInt64() const
{
- if (!data.value)
- return 0;
-
-#ifdef TRINITY_STRICT_DATABASE_TYPE_CHECKS
- if (!IsType(DatabaseFieldTypes::Int64))
- {
- LogWrongType(__FUNCTION__);
+ if (!_value)
return 0;
- }
-#endif
- if (data.raw)
- return *reinterpret_cast<uint64 const*>(data.value);
- return Trinity::StringTo<uint64>(data.value, 10).value_or(0);
+ return _meta->Converter->GetUInt64(_value, _length, _meta);
}
int64 Field::GetInt64() const
{
- if (!data.value)
- return 0;
-
-#ifdef TRINITY_STRICT_DATABASE_TYPE_CHECKS
- if (!IsType(DatabaseFieldTypes::Int64))
- {
- LogWrongType(__FUNCTION__);
+ if (!_value)
return 0;
- }
-#endif
- if (data.raw)
- return *reinterpret_cast<int64 const*>(data.value);
- return Trinity::StringTo<int64>(data.value, 10).value_or(0);
+ return _meta->Converter->GetInt64(_value, _length, _meta);
}
float Field::GetFloat() const
{
- if (!data.value)
+ if (!_value)
return 0.0f;
-#ifdef TRINITY_STRICT_DATABASE_TYPE_CHECKS
- if (!IsType(DatabaseFieldTypes::Float))
- {
- LogWrongType(__FUNCTION__);
- return 0.0f;
- }
-#endif
-
- if (data.raw)
- return *reinterpret_cast<float const*>(data.value);
- return Trinity::StringTo<float>(data.value, 10).value_or(0);
+ return _meta->Converter->GetFloat(_value, _length, _meta);
}
double Field::GetDouble() const
{
- if (!data.value)
- return 0.0;
-
-#ifdef TRINITY_STRICT_DATABASE_TYPE_CHECKS
- if (!IsType(DatabaseFieldTypes::Double) && !IsType(DatabaseFieldTypes::Decimal))
- {
- LogWrongType(__FUNCTION__);
+ if (!_value)
return 0.0;
- }
-#endif
- if (data.raw && !IsType(DatabaseFieldTypes::Decimal))
- return *reinterpret_cast<double const*>(data.value);
- return Trinity::StringTo<double>(data.value, 10).value_or(0);
+ return _meta->Converter->GetDouble(_value, _length, _meta);
}
char const* Field::GetCString() const
{
- if (!data.value)
+ if (!_value)
return nullptr;
-#ifdef TRINITY_STRICT_DATABASE_TYPE_CHECKS
- if (IsNumeric() && data.raw)
- {
- LogWrongType(__FUNCTION__);
- return nullptr;
- }
-#endif
- return static_cast<char const*>(data.value);
+ return _meta->Converter->GetCString(_value, _length, _meta);
}
std::string Field::GetString() const
{
- if (!data.value)
+ if (!_value)
return "";
char const* string = GetCString();
if (!string)
return "";
- return std::string(string, data.length);
+ return std::string(string, _length);
}
std::string_view Field::GetStringView() const
{
- if (!data.value)
+ if (!_value)
return {};
char const* const string = GetCString();
if (!string)
return {};
- return { string, data.length };
+ return { string, _length };
}
std::vector<uint8> Field::GetBinary() const
{
std::vector<uint8> result;
- if (!data.value || !data.length)
+ if (!_value || !_length)
return result;
- result.resize(data.length);
- memcpy(result.data(), data.value, data.length);
+ result.resize(_length);
+ memcpy(result.data(), _value, _length);
return result;
}
void Field::GetBinarySizeChecked(uint8* buf, size_t length) const
{
- ASSERT(data.value && (data.length == length), "Expected %zu-byte binary blob, got %sdata (%u bytes) instead", length, data.value ? "" : "no ", data.length);
- memcpy(buf, data.value, length);
+ ASSERT(_value && (_length == length), "Expected %zu-byte binary blob, got %sdata (%u bytes) instead", length, _value ? "" : "no ", _length);
+ memcpy(buf, _value, length);
}
-void Field::SetByteValue(char const* newValue, uint32 length)
+void Field::SetValue(char const* newValue, uint32 length)
{
// This value stores raw bytes that have to be explicitly cast later
- data.value = newValue;
- data.length = length;
- data.raw = true;
-}
-
-void Field::SetStructuredValue(char const* newValue, uint32 length)
-{
- // This value stores somewhat structured data that needs function style casting
- data.value = newValue;
- data.length = length;
- data.raw = false;
-}
-
-bool Field::IsType(DatabaseFieldTypes type) const
-{
- return meta->Type == type;
-}
-
-bool Field::IsNumeric() const
-{
- return (meta->Type == DatabaseFieldTypes::Int8 ||
- meta->Type == DatabaseFieldTypes::Int16 ||
- meta->Type == DatabaseFieldTypes::Int32 ||
- meta->Type == DatabaseFieldTypes::Int64 ||
- meta->Type == DatabaseFieldTypes::Float ||
- meta->Type == DatabaseFieldTypes::Double);
-}
-
-void Field::LogWrongType(char const* getter) const
-{
- TC_LOG_WARN("sql.sql", "Warning: {} on {} field {}.{} ({}.{}) at index {}.",
- getter, meta->TypeName, meta->TableAlias, meta->Alias, meta->TableName, meta->Name, meta->Index);
+ _value = newValue;
+ _length = length;
}
-void Field::SetMetadata(QueryResultFieldMetadata const* fieldMeta)
+void Field::SetMetadata(QueryResultFieldMetadata const* meta)
{
- meta = fieldMeta;
+ _meta = meta;
}
diff --git a/src/server/database/Database/Field.h b/src/server/database/Database/Field.h
index 0229c852647..d0613a3a94f 100644
--- a/src/server/database/Database/Field.h
+++ b/src/server/database/Database/Field.h
@@ -15,22 +15,27 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _FIELD_H
-#define _FIELD_H
+#ifndef TRINITY_DATABASE_FIELD_H
+#define TRINITY_DATABASE_FIELD_H
#include "Define.h"
-#include "DatabaseEnvFwd.h"
#include <array>
#include <string>
#include <string_view>
#include <vector>
+class BaseDatabaseResultValueConverter;
+
enum class DatabaseFieldTypes : uint8
{
Null,
+ UInt8,
Int8,
+ UInt16,
Int16,
+ UInt32,
Int32,
+ UInt64,
Int64,
Float,
Double,
@@ -48,6 +53,7 @@ struct QueryResultFieldMetadata
char const* TypeName = nullptr;
uint32 Index = 0;
DatabaseFieldTypes Type = DatabaseFieldTypes::Null;
+ BaseDatabaseResultValueConverter const* Converter = nullptr;
};
/**
@@ -118,28 +124,17 @@ class TC_DATABASE_API Field
bool IsNull() const
{
- return data.value == nullptr;
+ return _value == nullptr;
}
- protected:
- struct
- {
- char const* value; // Actual data in memory
- uint32 length; // Length
- bool raw; // Raw bytes? (Prepared statement or ad hoc)
- } data;
-
- void SetByteValue(char const* newValue, uint32 length);
- void SetStructuredValue(char const* newValue, uint32 length);
-
- bool IsType(DatabaseFieldTypes type) const;
+ private:
+ char const* _value; // Actual data in memory
+ uint32 _length; // Length
- bool IsNumeric() const;
+ void SetValue(char const* newValue, uint32 length);
- private:
- QueryResultFieldMetadata const* meta;
- void LogWrongType(char const* getter) const;
- void SetMetadata(QueryResultFieldMetadata const* fieldMeta);
+ QueryResultFieldMetadata const* _meta;
+ void SetMetadata(QueryResultFieldMetadata const* meta);
void GetBinarySizeChecked(uint8* buf, size_t size) const;
};
diff --git a/src/server/database/Database/FieldValueConverter.cpp b/src/server/database/Database/FieldValueConverter.cpp
new file mode 100644
index 00000000000..589d33c8850
--- /dev/null
+++ b/src/server/database/Database/FieldValueConverter.cpp
@@ -0,0 +1,48 @@
+/*
+ * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
+ *
+ * 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/>.
+ */
+
+#include "FieldValueConverter.h"
+#include "Errors.h"
+#include "Field.h"
+
+BaseDatabaseResultValueConverter::BaseDatabaseResultValueConverter() = default;
+BaseDatabaseResultValueConverter::~BaseDatabaseResultValueConverter() = default;
+
+void BaseDatabaseResultValueConverter::LogTruncation(char const* getter, QueryResultFieldMetadata const* meta)
+{
+ char const* expectedAccessor = "";
+ switch (meta->Type)
+ {
+ case DatabaseFieldTypes::UInt8: expectedAccessor = "Field::GetUInt8"; break;
+ case DatabaseFieldTypes::Int8: expectedAccessor = "Field::GetInt8"; break;
+ case DatabaseFieldTypes::UInt16: expectedAccessor = "Field::GetUInt16"; break;
+ case DatabaseFieldTypes::Int16: expectedAccessor = "Field::GetInt16"; break;
+ case DatabaseFieldTypes::UInt32: expectedAccessor = "Field::GetUIn32"; break;
+ case DatabaseFieldTypes::Int32: expectedAccessor = "Field::GetInt32"; break;
+ case DatabaseFieldTypes::UInt64: expectedAccessor = "Field::GetUIn64"; break;
+ case DatabaseFieldTypes::Int64: expectedAccessor = "Field::GetInt64"; break;
+ case DatabaseFieldTypes::Float: expectedAccessor = "Field::GetFloat"; break;
+ case DatabaseFieldTypes::Double: expectedAccessor = "Field::GetDouble"; break;
+ case DatabaseFieldTypes::Decimal: expectedAccessor = "Field::GetDouble or Field::GetString"; break;
+ case DatabaseFieldTypes::Binary: expectedAccessor = "Field::GetString or Field::GetBinary"; break;
+ default:
+ break;
+ }
+
+ ASSERT(false, "%s on %s field %s.%s (%s.%s) at index %u caused value to be truncated. Use %s instead.",
+ getter, meta->TypeName, meta->TableAlias, meta->Alias, meta->TableName, meta->Name, meta->Index, expectedAccessor);
+}
diff --git a/src/server/database/Database/FieldValueConverter.h b/src/server/database/Database/FieldValueConverter.h
new file mode 100644
index 00000000000..15e65b0fa33
--- /dev/null
+++ b/src/server/database/Database/FieldValueConverter.h
@@ -0,0 +1,50 @@
+/*
+ * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
+ *
+ * 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 TRINITY_FIELD_VALUE_CONVERTER_H
+#define TRINITY_FIELD_VALUE_CONVERTER_H
+
+#include "Define.h"
+
+struct QueryResultFieldMetadata;
+
+class BaseDatabaseResultValueConverter
+{
+public:
+ BaseDatabaseResultValueConverter();
+ BaseDatabaseResultValueConverter(BaseDatabaseResultValueConverter const&) = delete;
+ BaseDatabaseResultValueConverter(BaseDatabaseResultValueConverter&&) = delete;
+ BaseDatabaseResultValueConverter& operator=(BaseDatabaseResultValueConverter const&) = delete;
+ BaseDatabaseResultValueConverter& operator=(BaseDatabaseResultValueConverter&&) = delete;
+ virtual ~BaseDatabaseResultValueConverter();
+
+ virtual uint8 GetUInt8(char const* data, uint32 size, QueryResultFieldMetadata const* meta) const = 0;
+ virtual int8 GetInt8(char const* data, uint32 size, QueryResultFieldMetadata const* meta) const = 0;
+ virtual uint16 GetUInt16(char const* data, uint32 size, QueryResultFieldMetadata const* meta) const = 0;
+ virtual int16 GetInt16(char const* data, uint32 size, QueryResultFieldMetadata const* meta) const = 0;
+ virtual uint32 GetUInt32(char const* data, uint32 size, QueryResultFieldMetadata const* meta) const = 0;
+ virtual int32 GetInt32(char const* data, uint32 size, QueryResultFieldMetadata const* meta) const = 0;
+ virtual uint64 GetUInt64(char const* data, uint32 size, QueryResultFieldMetadata const* meta) const = 0;
+ virtual int64 GetInt64(char const* data, uint32 size, QueryResultFieldMetadata const* meta) const = 0;
+ virtual float GetFloat(char const* data, uint32 size, QueryResultFieldMetadata const* meta) const = 0;
+ virtual double GetDouble(char const* data, uint32 size, QueryResultFieldMetadata const* meta) const = 0;
+ virtual char const* GetCString(char const* data, uint32 size, QueryResultFieldMetadata const* meta) const = 0;
+
+ static void LogTruncation(char const* getter, QueryResultFieldMetadata const* meta);
+};
+
+#endif // TRINITY_FIELD_VALUE_CONVERTER_H
diff --git a/src/server/database/Database/FieldValueConverters.h b/src/server/database/Database/FieldValueConverters.h
new file mode 100644
index 00000000000..e050d8052ca
--- /dev/null
+++ b/src/server/database/Database/FieldValueConverters.h
@@ -0,0 +1,112 @@
+/*
+ * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
+ *
+ * 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 TRINITY_FIELD_VALUE_CONVERTERS_H
+#define TRINITY_FIELD_VALUE_CONVERTERS_H
+
+#include "FieldValueConverter.h"
+#include "StringConvert.h"
+
+// converts string value returned from query to type specified in column metadata
+template<typename DatabaseType>
+class FromStringToDatabaseTypeConverter : public BaseDatabaseResultValueConverter
+{
+public:
+ static DatabaseType GetDatabaseValue(char const* data, uint32 size)
+ {
+ return Trinity::StringTo<DatabaseType>({ data, size }).template value_or<DatabaseType>(0);
+ }
+
+ static char const* GetStringValue(char const* data)
+ {
+ return data;
+ }
+};
+
+// converts binary value returned from query to type specified in column metadata
+template<typename DatabaseType>
+class FromBinaryToDatabaseTypeConverter : public BaseDatabaseResultValueConverter
+{
+public:
+ static DatabaseType GetDatabaseValue(char const* data, uint32 /*size*/)
+ {
+ return *reinterpret_cast<DatabaseType const*>(data);
+ }
+
+ static char const* GetStringValue(char const* /*data*/)
+ {
+ return nullptr;
+ }
+};
+
+// converts column value from type specified in column metadata to type requested by Field::Get* function
+template<typename DatabaseType, template<typename...> typename ToDatabaseTypeConverter>
+class PrimitiveResultValueConverter : public BaseDatabaseResultValueConverter
+{
+public:
+ template<typename T>
+ static T GetNumericValue(char const* data, uint32 size, QueryResultFieldMetadata const* meta, char const* func)
+ {
+ DatabaseType source = ToDatabaseTypeConverter<DatabaseType>::GetDatabaseValue(data, size);
+ T result = static_cast<T>(source);
+ if (static_cast<DatabaseType>(result) != source)
+ {
+ LogTruncation(func, meta);
+ return T();
+ }
+ return result;
+ }
+
+ uint8 GetUInt8(char const* data, uint32 size, QueryResultFieldMetadata const* meta) const override { return GetNumericValue<uint8>(data, size, meta, "Field::GetUInt8"); }
+ int8 GetInt8(char const* data, uint32 size, QueryResultFieldMetadata const* meta) const override { return GetNumericValue<int8>(data, size, meta, "Field::GetInt8"); }
+ uint16 GetUInt16(char const* data, uint32 size, QueryResultFieldMetadata const* meta) const override { return GetNumericValue<uint16>(data, size, meta, "Field::GetUInt16"); }
+ int16 GetInt16(char const* data, uint32 size, QueryResultFieldMetadata const* meta) const override { return GetNumericValue<int16>(data, size, meta, "Field::GetInt16"); }
+ uint32 GetUInt32(char const* data, uint32 size, QueryResultFieldMetadata const* meta) const override { return GetNumericValue<uint32>(data, size, meta, "Field::GetUInt32"); }
+ int32 GetInt32(char const* data, uint32 size, QueryResultFieldMetadata const* meta) const override { return GetNumericValue<int32>(data, size, meta, "Field::GetInt32"); }
+ uint64 GetUInt64(char const* data, uint32 size, QueryResultFieldMetadata const* meta) const override { return GetNumericValue<uint64>(data, size, meta, "Field::GetUInt64"); }
+ int64 GetInt64(char const* data, uint32 size, QueryResultFieldMetadata const* meta) const override { return GetNumericValue<int64>(data, size, meta, "Field::GetInt64"); }
+ float GetFloat(char const* data, uint32 size, QueryResultFieldMetadata const* meta) const override { return GetNumericValue<float>(data, size, meta, "Field::GetFloat"); }
+ double GetDouble(char const* data, uint32 size, QueryResultFieldMetadata const* meta) const override { return GetNumericValue<double>(data, size, meta, "Field::GetDouble"); }
+ char const* GetCString(char const* data, uint32 /*size*/, QueryResultFieldMetadata const* meta) const override
+ {
+ char const* result = ToDatabaseTypeConverter<DatabaseType>::GetStringValue(data);
+ if (data && !result)
+ LogTruncation("Field::GetCString", meta);
+ return result;
+ }
+};
+
+template<>
+class PrimitiveResultValueConverter<char const*, std::void_t> : public BaseDatabaseResultValueConverter
+{
+public:
+ uint8 GetUInt8(char const* /*data*/, uint32 /*size*/, QueryResultFieldMetadata const* meta) const override { LogTruncation("Field::GetUInt8", meta); return 0; }
+ int8 GetInt8(char const* /*data*/, uint32 /*size*/, QueryResultFieldMetadata const* meta) const override { LogTruncation("Field::GetInt8", meta); return 0; }
+ uint16 GetUInt16(char const* /*data*/, uint32 /*size*/, QueryResultFieldMetadata const* meta) const override { LogTruncation("Field::GetUInt16", meta); return 0; }
+ int16 GetInt16(char const* /*data*/, uint32 /*size*/, QueryResultFieldMetadata const* meta) const override { LogTruncation("Field::GetInt16", meta); return 0; }
+ uint32 GetUInt32(char const* /*data*/, uint32 /*size*/, QueryResultFieldMetadata const* meta) const override { LogTruncation("Field::GetUInt32", meta); return 0; }
+ int32 GetInt32(char const* /*data*/, uint32 /*size*/, QueryResultFieldMetadata const* meta) const override { LogTruncation("Field::GetInt32", meta); return 0; }
+ uint64 GetUInt64(char const* /*data*/, uint32 /*size*/, QueryResultFieldMetadata const* meta) const override { LogTruncation("Field::GetUInt64", meta); return 0; }
+ int64 GetInt64(char const* /*data*/, uint32 /*size*/, QueryResultFieldMetadata const* meta) const override { LogTruncation("Field::GetInt64", meta); return 0; }
+ float GetFloat(char const* /*data*/, uint32 /*size*/, QueryResultFieldMetadata const* meta) const override { LogTruncation("Field::GetFloat", meta); return 0.0f; }
+ double GetDouble(char const* /*data*/, uint32 /*size*/, QueryResultFieldMetadata const* meta) const override { LogTruncation("Field::GetDouble", meta); return 0.0; }
+ char const* GetCString(char const* data, uint32 /*size*/, QueryResultFieldMetadata const* /*meta*/) const override { return data; }
+};
+
+using StringResultValueConverter = PrimitiveResultValueConverter<char const*, std::void_t>;
+
+#endif // TRINITY_FIELD_VALUE_CONVERTERS_H
diff --git a/src/server/database/Database/QueryResult.cpp b/src/server/database/Database/QueryResult.cpp
index 2ab20f392f2..e15826729f4 100644
--- a/src/server/database/Database/QueryResult.cpp
+++ b/src/server/database/Database/QueryResult.cpp
@@ -18,6 +18,7 @@
#include "QueryResult.h"
#include "Errors.h"
#include "Field.h"
+#include "FieldValueConverters.h"
#include "Log.h"
#include "MySQLHacks.h"
#include "MySQLWorkaround.h"
@@ -74,23 +75,23 @@ static uint32 SizeForType(MYSQL_FIELD* field)
}
}
-DatabaseFieldTypes MysqlTypeToFieldType(enum_field_types type)
+DatabaseFieldTypes MysqlTypeToFieldType(enum_field_types type, uint32 flags)
{
switch (type)
{
case MYSQL_TYPE_NULL:
return DatabaseFieldTypes::Null;
case MYSQL_TYPE_TINY:
- return DatabaseFieldTypes::Int8;
+ return (flags & UNSIGNED_FLAG) ? DatabaseFieldTypes::UInt8 : DatabaseFieldTypes::Int8;
case MYSQL_TYPE_YEAR:
case MYSQL_TYPE_SHORT:
- return DatabaseFieldTypes::Int16;
+ return (flags & UNSIGNED_FLAG) ? DatabaseFieldTypes::UInt16 : DatabaseFieldTypes::Int16;
case MYSQL_TYPE_INT24:
case MYSQL_TYPE_LONG:
- return DatabaseFieldTypes::Int32;
+ return (flags & UNSIGNED_FLAG) ? DatabaseFieldTypes::UInt32 : DatabaseFieldTypes::Int32;
case MYSQL_TYPE_LONGLONG:
case MYSQL_TYPE_BIT:
- return DatabaseFieldTypes::Int64;
+ return (flags & UNSIGNED_FLAG) ? DatabaseFieldTypes::UInt64 : DatabaseFieldTypes::Int64;
case MYSQL_TYPE_FLOAT:
return DatabaseFieldTypes::Float;
case MYSQL_TYPE_DOUBLE:
@@ -118,7 +119,7 @@ DatabaseFieldTypes MysqlTypeToFieldType(enum_field_types type)
return DatabaseFieldTypes::Null;
}
-static char const* FieldTypeToString(enum_field_types type)
+static char const* FieldTypeToString(enum_field_types type, uint32 flags)
{
switch (type)
{
@@ -132,19 +133,19 @@ static char const* FieldTypeToString(enum_field_types type)
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_INT24: return (flags & UNSIGNED_FLAG) ? "UNSIGNED INT24" : "INT24";
+ case MYSQL_TYPE_LONG: return (flags & UNSIGNED_FLAG) ? "UNSIGNED LONG" : "LONG";
+ case MYSQL_TYPE_LONGLONG: return (flags & UNSIGNED_FLAG) ? "UNSIGNED LONGLONG" : "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_SHORT: return (flags & UNSIGNED_FLAG) ? "UNSIGNED SHORT" : "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: return (flags & UNSIGNED_FLAG) ? "UNSIGNED TINY" : "TINY";
case MYSQL_TYPE_TINY_BLOB: return "TINY_BLOB";
case MYSQL_TYPE_VAR_STRING: return "VAR_STRING";
case MYSQL_TYPE_YEAR: return "YEAR";
@@ -152,15 +153,52 @@ static char const* FieldTypeToString(enum_field_types type)
}
}
-void InitializeDatabaseFieldMetadata(QueryResultFieldMetadata* meta, MySQLField const* field, uint32 fieldIndex)
+std::unique_ptr<BaseDatabaseResultValueConverter> FromStringValueConverters[14] =
+{
+ nullptr,
+ std::make_unique<PrimitiveResultValueConverter<uint8, FromStringToDatabaseTypeConverter>>(),
+ std::make_unique<PrimitiveResultValueConverter<int8, FromStringToDatabaseTypeConverter>>(),
+ std::make_unique<PrimitiveResultValueConverter<uint16, FromStringToDatabaseTypeConverter>>(),
+ std::make_unique<PrimitiveResultValueConverter<int16, FromStringToDatabaseTypeConverter>>(),
+ std::make_unique<PrimitiveResultValueConverter<uint32, FromStringToDatabaseTypeConverter>>(),
+ std::make_unique<PrimitiveResultValueConverter<int32, FromStringToDatabaseTypeConverter>>(),
+ std::make_unique<PrimitiveResultValueConverter<uint64, FromStringToDatabaseTypeConverter>>(),
+ std::make_unique<PrimitiveResultValueConverter<int64, FromStringToDatabaseTypeConverter>>(),
+ std::make_unique<PrimitiveResultValueConverter<float, FromStringToDatabaseTypeConverter>>(),
+ std::make_unique<PrimitiveResultValueConverter<double, FromStringToDatabaseTypeConverter>>(),
+ std::make_unique<PrimitiveResultValueConverter<double, FromStringToDatabaseTypeConverter>>(),
+ nullptr,
+ std::make_unique<StringResultValueConverter>()
+};
+
+std::unique_ptr<BaseDatabaseResultValueConverter> BinaryValueConverters[14] =
+{
+ nullptr,
+ std::make_unique<PrimitiveResultValueConverter<uint8, FromBinaryToDatabaseTypeConverter>>(),
+ std::make_unique<PrimitiveResultValueConverter<int8, FromBinaryToDatabaseTypeConverter>>(),
+ std::make_unique<PrimitiveResultValueConverter<uint16, FromBinaryToDatabaseTypeConverter>>(),
+ std::make_unique<PrimitiveResultValueConverter<int16, FromBinaryToDatabaseTypeConverter>>(),
+ std::make_unique<PrimitiveResultValueConverter<uint32, FromBinaryToDatabaseTypeConverter>>(),
+ std::make_unique<PrimitiveResultValueConverter<int32, FromBinaryToDatabaseTypeConverter>>(),
+ std::make_unique<PrimitiveResultValueConverter<uint64, FromBinaryToDatabaseTypeConverter>>(),
+ std::make_unique<PrimitiveResultValueConverter<int64, FromBinaryToDatabaseTypeConverter>>(),
+ std::make_unique<PrimitiveResultValueConverter<float, FromBinaryToDatabaseTypeConverter>>(),
+ std::make_unique<PrimitiveResultValueConverter<double, FromBinaryToDatabaseTypeConverter>>(),
+ std::make_unique<PrimitiveResultValueConverter<double, FromStringToDatabaseTypeConverter>>(), // always sent as string
+ nullptr,
+ std::make_unique<StringResultValueConverter>()
+};
+
+void InitializeDatabaseFieldMetadata(QueryResultFieldMetadata* meta, MySQLField const* field, uint32 fieldIndex, bool binaryProtocol)
{
meta->TableName = field->org_table;
meta->TableAlias = field->table;
meta->Name = field->org_name;
meta->Alias = field->name;
- meta->TypeName = FieldTypeToString(field->type);
+ meta->TypeName = FieldTypeToString(field->type, field->flags);
meta->Index = fieldIndex;
- meta->Type = MysqlTypeToFieldType(field->type);
+ meta->Type = MysqlTypeToFieldType(field->type, field->flags);
+ meta->Converter = binaryProtocol ? BinaryValueConverters[AsUnderlyingType(meta->Type)].get() : FromStringValueConverters[AsUnderlyingType(meta->Type)].get();
}
}
@@ -174,7 +212,7 @@ _fields(fields)
_currentRow = new Field[_fieldCount];
for (uint32 i = 0; i < _fieldCount; i++)
{
- InitializeDatabaseFieldMetadata(&_fieldMetadata[i], &_fields[i], i);
+ InitializeDatabaseFieldMetadata(&_fieldMetadata[i], &_fields[i], i, false);
_currentRow[i].SetMetadata(&_fieldMetadata[i]);
}
}
@@ -229,7 +267,7 @@ m_metadataResult(result)
uint32 size = SizeForType(&field[i]);
rowSize += size;
- InitializeDatabaseFieldMetadata(&m_fieldMetadata[i], &field[i], i);
+ InitializeDatabaseFieldMetadata(&m_fieldMetadata[i], &field[i], i, true);
m_rBind[i].buffer_type = field[i].type;
m_rBind[i].buffer_length = size;
@@ -289,7 +327,7 @@ m_metadataResult(result)
break;
}
- m_rows[uint32(m_rowPosition) * m_fieldCount + fIndex].SetByteValue(
+ m_rows[uint32(m_rowPosition) * m_fieldCount + fIndex].SetValue(
(char const*)buffer,
fetched_length);
@@ -298,7 +336,7 @@ m_metadataResult(result)
}
else
{
- m_rows[uint32(m_rowPosition) * m_fieldCount + fIndex].SetByteValue(
+ m_rows[uint32(m_rowPosition) * m_fieldCount + fIndex].SetValue(
nullptr,
*m_rBind[fIndex].length);
}
@@ -344,7 +382,7 @@ bool ResultSet::NextRow()
}
for (uint32 i = 0; i < _fieldCount; i++)
- _currentRow[i].SetStructuredValue(row[i], lengths[i]);
+ _currentRow[i].SetValue(row[i], lengths[i]);
return true;
}