/*
* 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