/* * This file is part of the AzerothCore 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 Affero General Public License as published by the * Free Software Foundation; either version 3 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 Affero 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 . */ #ifndef _FIELD_H #define _FIELD_H #include "Define.h" #include "Duration.h" #include #include #include namespace Acore::Types { template using is_chrono_v = std::enable_if_t || std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v, T>; } using Binary = std::vector; enum class DatabaseFieldTypes : uint8 { Null, Int8, Int16, Int32, Int64, Float, Double, Decimal, Date, Binary }; struct QueryResultFieldMetadata { std::string TableName{}; std::string TableAlias{}; std::string Name{}; std::string Alias{}; std::string TypeName{}; uint32 Index = 0; DatabaseFieldTypes Type = DatabaseFieldTypes::Null; }; /** @class Field @brief Class used to access individual fields of database query result Guideline on field type matching: | MySQL type | method to use | |------------------------|-----------------------------------------| | TINYINT | Get, Get, Get | | SMALLINT | Get, Get | | MEDIUMINT, INT | Get, Get | | BIGINT | Get, Get | | FLOAT | Get | | DOUBLE, DECIMAL | Get | | CHAR, VARCHAR, | Get, Get | | TINYTEXT, MEDIUMTEXT, | Get, Get | | TEXT, LONGTEXT | Get, Get | | TINYBLOB, MEDIUMBLOB, | Get, Get | | BLOB, LONGBLOB | Get, Get | | BINARY, VARBINARY | Get | Return types of aggregate functions: | Function | Type | |----------|-------------------| | MIN, MAX | Same as the field | | SUM, AVG | DECIMAL | | COUNT | BIGINT | */ class AC_DATABASE_API Field { friend class ResultSet; friend class PreparedResultSet; public: Field(); ~Field() = default; [[nodiscard]] inline bool IsNull() const { return data.value == nullptr; } template inline std::enable_if_t, T> Get() const { return GetData(); } template inline std::enable_if_t, T> Get() const { return GetDataString(); } template inline std::enable_if_t, T> Get() const { return GetDataStringView(); } template inline std::enable_if_t, T> Get() const { return GetDataBinary(); } template inline std::enable_if_t, std::array> Get() const { std::array buf = {}; GetBinarySizeChecked(buf.data(), S); return buf; } template inline Acore::Types::is_chrono_v Get(bool convertToUin32 = true) const { return convertToUin32 ? T(GetData()) : T(GetData()); } DatabaseFieldTypes GetType() { return meta->Type; } 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); [[nodiscard]] bool IsType(DatabaseFieldTypes type) const; [[nodiscard]] bool IsNumeric() const; private: template T GetData() const; std::string GetDataString() const; std::string_view GetDataStringView() const; Binary GetDataBinary() const; QueryResultFieldMetadata const* meta; void LogWrongType(std::string_view getter, std::string_view typeName) const; void SetMetadata(QueryResultFieldMetadata const* fieldMeta); void GetBinarySizeChecked(uint8* buf, std::size_t size) const; }; #endif