2011-08-28 00:31:30 +00:00
|
|
|
#pragma once
|
2010-03-01 16:59:51 +00:00
|
|
|
|
2019-05-22 19:38:43 +00:00
|
|
|
#include <cstdint>
|
2010-03-01 16:59:51 +00:00
|
|
|
#include <string>
|
2012-10-24 18:14:36 +00:00
|
|
|
#include <vector>
|
2019-11-02 05:55:06 +00:00
|
|
|
#include <common/Types.h>
|
2010-03-01 16:59:51 +00:00
|
|
|
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
2017-12-09 07:32:32 +00:00
|
|
|
/// Data types for representing elementary values from a database in RAM.
|
2010-03-01 16:59:51 +00:00
|
|
|
|
2017-12-09 07:32:32 +00:00
|
|
|
struct Null {};
|
2010-03-01 16:59:51 +00:00
|
|
|
|
2019-08-03 11:02:40 +00:00
|
|
|
enum class TypeIndex
|
|
|
|
{
|
|
|
|
Nothing = 0,
|
|
|
|
UInt8,
|
|
|
|
UInt16,
|
|
|
|
UInt32,
|
|
|
|
UInt64,
|
|
|
|
UInt128,
|
|
|
|
Int8,
|
|
|
|
Int16,
|
|
|
|
Int32,
|
|
|
|
Int64,
|
|
|
|
Int128,
|
|
|
|
Float32,
|
|
|
|
Float64,
|
|
|
|
Date,
|
|
|
|
DateTime,
|
|
|
|
String,
|
|
|
|
FixedString,
|
|
|
|
Enum8,
|
|
|
|
Enum16,
|
|
|
|
Decimal32,
|
|
|
|
Decimal64,
|
|
|
|
Decimal128,
|
|
|
|
UUID,
|
|
|
|
Array,
|
|
|
|
Tuple,
|
|
|
|
Set,
|
|
|
|
Interval,
|
|
|
|
Nullable,
|
|
|
|
Function,
|
|
|
|
AggregateFunction,
|
|
|
|
LowCardinality,
|
|
|
|
};
|
|
|
|
|
2018-07-20 19:05:07 +00:00
|
|
|
using UInt8 = uint8_t;
|
|
|
|
using UInt16 = uint16_t;
|
|
|
|
using UInt32 = uint32_t;
|
|
|
|
using UInt64 = uint64_t;
|
2010-03-01 16:59:51 +00:00
|
|
|
|
2018-07-20 19:05:07 +00:00
|
|
|
using Int8 = int8_t;
|
|
|
|
using Int16 = int16_t;
|
|
|
|
using Int32 = int32_t;
|
|
|
|
using Int64 = int64_t;
|
2010-03-01 16:59:51 +00:00
|
|
|
|
2016-05-28 10:35:44 +00:00
|
|
|
using Float32 = float;
|
|
|
|
using Float64 = double;
|
2010-03-01 16:59:51 +00:00
|
|
|
|
2016-05-28 10:35:44 +00:00
|
|
|
using String = std::string;
|
2016-08-04 15:06:27 +00:00
|
|
|
|
2011-08-28 00:31:30 +00:00
|
|
|
|
2017-12-09 07:32:32 +00:00
|
|
|
/** Note that for types not used in DB, IsNumber is false.
|
|
|
|
*/
|
2017-12-09 10:19:02 +00:00
|
|
|
template <typename T> constexpr bool IsNumber = false;
|
|
|
|
|
2019-05-30 08:23:20 +00:00
|
|
|
template <> inline constexpr bool IsNumber<UInt8> = true;
|
|
|
|
template <> inline constexpr bool IsNumber<UInt16> = true;
|
|
|
|
template <> inline constexpr bool IsNumber<UInt32> = true;
|
|
|
|
template <> inline constexpr bool IsNumber<UInt64> = true;
|
|
|
|
template <> inline constexpr bool IsNumber<Int8> = true;
|
|
|
|
template <> inline constexpr bool IsNumber<Int16> = true;
|
|
|
|
template <> inline constexpr bool IsNumber<Int32> = true;
|
|
|
|
template <> inline constexpr bool IsNumber<Int64> = true;
|
|
|
|
template <> inline constexpr bool IsNumber<Float32> = true;
|
|
|
|
template <> inline constexpr bool IsNumber<Float64> = true;
|
2011-08-28 00:31:30 +00:00
|
|
|
|
|
|
|
template <typename T> struct TypeName;
|
|
|
|
|
2017-07-16 03:05:40 +00:00
|
|
|
template <> struct TypeName<UInt8> { static const char * get() { return "UInt8"; } };
|
|
|
|
template <> struct TypeName<UInt16> { static const char * get() { return "UInt16"; } };
|
|
|
|
template <> struct TypeName<UInt32> { static const char * get() { return "UInt32"; } };
|
|
|
|
template <> struct TypeName<UInt64> { static const char * get() { return "UInt64"; } };
|
|
|
|
template <> struct TypeName<Int8> { static const char * get() { return "Int8"; } };
|
|
|
|
template <> struct TypeName<Int16> { static const char * get() { return "Int16"; } };
|
|
|
|
template <> struct TypeName<Int32> { static const char * get() { return "Int32"; } };
|
|
|
|
template <> struct TypeName<Int64> { static const char * get() { return "Int64"; } };
|
|
|
|
template <> struct TypeName<Float32> { static const char * get() { return "Float32"; } };
|
|
|
|
template <> struct TypeName<Float64> { static const char * get() { return "Float64"; } };
|
|
|
|
template <> struct TypeName<String> { static const char * get() { return "String"; } };
|
2015-11-29 08:06:29 +00:00
|
|
|
|
2018-08-20 15:17:55 +00:00
|
|
|
template <typename T> struct TypeId;
|
|
|
|
template <> struct TypeId<UInt8> { static constexpr const TypeIndex value = TypeIndex::UInt8; };
|
|
|
|
template <> struct TypeId<UInt16> { static constexpr const TypeIndex value = TypeIndex::UInt16; };
|
|
|
|
template <> struct TypeId<UInt32> { static constexpr const TypeIndex value = TypeIndex::UInt32; };
|
|
|
|
template <> struct TypeId<UInt64> { static constexpr const TypeIndex value = TypeIndex::UInt64; };
|
|
|
|
template <> struct TypeId<Int8> { static constexpr const TypeIndex value = TypeIndex::Int8; };
|
|
|
|
template <> struct TypeId<Int16> { static constexpr const TypeIndex value = TypeIndex::Int16; };
|
|
|
|
template <> struct TypeId<Int32> { static constexpr const TypeIndex value = TypeIndex::Int32; };
|
|
|
|
template <> struct TypeId<Int64> { static constexpr const TypeIndex value = TypeIndex::Int64; };
|
|
|
|
template <> struct TypeId<Float32> { static constexpr const TypeIndex value = TypeIndex::Float32; };
|
|
|
|
template <> struct TypeId<Float64> { static constexpr const TypeIndex value = TypeIndex::Float64; };
|
2017-10-14 04:39:14 +00:00
|
|
|
|
2017-12-09 07:32:32 +00:00
|
|
|
/// Not a data type in database, defined just for convenience.
|
|
|
|
using Strings = std::vector<String>;
|
|
|
|
|
2018-07-25 19:38:21 +00:00
|
|
|
|
|
|
|
using Int128 = __int128;
|
2019-05-30 08:23:20 +00:00
|
|
|
template <> inline constexpr bool IsNumber<Int128> = true;
|
|
|
|
template <> struct TypeName<Int128> { static const char * get() { return "Int128"; } };
|
2018-08-20 15:17:55 +00:00
|
|
|
template <> struct TypeId<Int128> { static constexpr const TypeIndex value = TypeIndex::Int128; };
|
2018-07-25 19:38:21 +00:00
|
|
|
|
2018-08-31 17:36:27 +00:00
|
|
|
/// Own FieldType for Decimal.
|
|
|
|
/// It is only a "storage" for decimal. To perform operations, you also have to provide a scale (number of digits after point).
|
|
|
|
template <typename T>
|
|
|
|
struct Decimal
|
2018-07-25 19:38:21 +00:00
|
|
|
{
|
2018-08-31 17:36:27 +00:00
|
|
|
using NativeType = T;
|
2018-07-25 19:38:21 +00:00
|
|
|
|
2018-08-31 17:36:27 +00:00
|
|
|
Decimal() = default;
|
|
|
|
Decimal(Decimal<T> &&) = default;
|
|
|
|
Decimal(const Decimal<T> &) = default;
|
2018-07-25 19:38:21 +00:00
|
|
|
|
2018-08-31 17:36:27 +00:00
|
|
|
Decimal(const T & value_)
|
|
|
|
: value(value_)
|
|
|
|
{}
|
2018-07-25 19:38:21 +00:00
|
|
|
|
2018-08-31 17:36:27 +00:00
|
|
|
template <typename U>
|
|
|
|
Decimal(const Decimal<U> & x)
|
|
|
|
: value(x)
|
|
|
|
{}
|
2018-07-25 19:38:21 +00:00
|
|
|
|
2018-08-31 17:36:27 +00:00
|
|
|
constexpr Decimal<T> & operator = (Decimal<T> &&) = default;
|
|
|
|
constexpr Decimal<T> & operator = (const Decimal<T> &) = default;
|
|
|
|
|
|
|
|
operator T () const { return value; }
|
|
|
|
|
|
|
|
const Decimal<T> & operator += (const T & x) { value += x; return *this; }
|
|
|
|
const Decimal<T> & operator -= (const T & x) { value -= x; return *this; }
|
|
|
|
const Decimal<T> & operator *= (const T & x) { value *= x; return *this; }
|
|
|
|
const Decimal<T> & operator /= (const T & x) { value /= x; return *this; }
|
|
|
|
const Decimal<T> & operator %= (const T & x) { value %= x; return *this; }
|
|
|
|
|
|
|
|
T value;
|
2018-07-25 19:38:21 +00:00
|
|
|
};
|
|
|
|
|
2018-08-31 17:36:27 +00:00
|
|
|
using Decimal32 = Decimal<Int32>;
|
|
|
|
using Decimal64 = Decimal<Int64>;
|
|
|
|
using Decimal128 = Decimal<Int128>;
|
2018-08-07 13:57:28 +00:00
|
|
|
|
2018-08-31 17:36:27 +00:00
|
|
|
template <> struct TypeName<Decimal32> { static const char * get() { return "Decimal32"; } };
|
|
|
|
template <> struct TypeName<Decimal64> { static const char * get() { return "Decimal64"; } };
|
|
|
|
template <> struct TypeName<Decimal128> { static const char * get() { return "Decimal128"; } };
|
|
|
|
|
|
|
|
template <> struct TypeId<Decimal32> { static constexpr const TypeIndex value = TypeIndex::Decimal32; };
|
|
|
|
template <> struct TypeId<Decimal64> { static constexpr const TypeIndex value = TypeIndex::Decimal64; };
|
|
|
|
template <> struct TypeId<Decimal128> { static constexpr const TypeIndex value = TypeIndex::Decimal128; };
|
|
|
|
|
2019-05-30 08:23:20 +00:00
|
|
|
template <typename T> constexpr bool IsDecimalNumber = false;
|
|
|
|
template <> inline constexpr bool IsDecimalNumber<Decimal32> = true;
|
|
|
|
template <> inline constexpr bool IsDecimalNumber<Decimal64> = true;
|
|
|
|
template <> inline constexpr bool IsDecimalNumber<Decimal128> = true;
|
2018-08-07 13:57:28 +00:00
|
|
|
|
2019-05-16 14:33:13 +00:00
|
|
|
template <typename T> struct NativeType { using Type = T; };
|
|
|
|
template <> struct NativeType<Decimal32> { using Type = Int32; };
|
|
|
|
template <> struct NativeType<Decimal64> { using Type = Int64; };
|
|
|
|
template <> struct NativeType<Decimal128> { using Type = Int128; };
|
|
|
|
|
2019-05-23 14:04:33 +00:00
|
|
|
inline const char * getTypeName(TypeIndex idx)
|
|
|
|
{
|
|
|
|
switch (idx)
|
|
|
|
{
|
|
|
|
case TypeIndex::Nothing: return "Nothing";
|
|
|
|
case TypeIndex::UInt8: return TypeName<UInt8>::get();
|
|
|
|
case TypeIndex::UInt16: return TypeName<UInt16>::get();
|
|
|
|
case TypeIndex::UInt32: return TypeName<UInt32>::get();
|
|
|
|
case TypeIndex::UInt64: return TypeName<UInt64>::get();
|
|
|
|
case TypeIndex::UInt128: return "UInt128";
|
|
|
|
case TypeIndex::Int8: return TypeName<Int8>::get();
|
|
|
|
case TypeIndex::Int16: return TypeName<Int16>::get();
|
|
|
|
case TypeIndex::Int32: return TypeName<Int32>::get();
|
|
|
|
case TypeIndex::Int64: return TypeName<Int64>::get();
|
|
|
|
case TypeIndex::Int128: return TypeName<Int128>::get();
|
|
|
|
case TypeIndex::Float32: return TypeName<Float32>::get();
|
|
|
|
case TypeIndex::Float64: return TypeName<Float64>::get();
|
|
|
|
case TypeIndex::Date: return "Date";
|
|
|
|
case TypeIndex::DateTime: return "DateTime";
|
|
|
|
case TypeIndex::String: return TypeName<String>::get();
|
|
|
|
case TypeIndex::FixedString: return "FixedString";
|
|
|
|
case TypeIndex::Enum8: return "Enum8";
|
|
|
|
case TypeIndex::Enum16: return "Enum16";
|
|
|
|
case TypeIndex::Decimal32: return TypeName<Decimal32>::get();
|
|
|
|
case TypeIndex::Decimal64: return TypeName<Decimal64>::get();
|
|
|
|
case TypeIndex::Decimal128: return TypeName<Decimal128>::get();
|
|
|
|
case TypeIndex::UUID: return "UUID";
|
|
|
|
case TypeIndex::Array: return "Array";
|
|
|
|
case TypeIndex::Tuple: return "Tuple";
|
|
|
|
case TypeIndex::Set: return "Set";
|
|
|
|
case TypeIndex::Interval: return "Interval";
|
|
|
|
case TypeIndex::Nullable: return "Nullable";
|
|
|
|
case TypeIndex::Function: return "Function";
|
|
|
|
case TypeIndex::AggregateFunction: return "AggregateFunction";
|
|
|
|
case TypeIndex::LowCardinality: return "LowCardinality";
|
|
|
|
}
|
|
|
|
|
|
|
|
__builtin_unreachable();
|
|
|
|
}
|
|
|
|
|
2018-08-07 13:57:28 +00:00
|
|
|
}
|
2019-01-24 12:31:33 +00:00
|
|
|
|
|
|
|
/// Specialization of `std::hash` for the Decimal<T> types.
|
|
|
|
namespace std
|
|
|
|
{
|
|
|
|
template <typename T>
|
|
|
|
struct hash<DB::Decimal<T>> { size_t operator()(const DB::Decimal<T> & x) const { return hash<T>()(x.value); } };
|
|
|
|
|
|
|
|
template <>
|
|
|
|
struct hash<DB::Decimal128>
|
|
|
|
{
|
|
|
|
size_t operator()(const DB::Decimal128 & x) const
|
|
|
|
{
|
|
|
|
return std::hash<DB::Int64>()(x.value >> 64)
|
|
|
|
^ std::hash<DB::Int64>()(x.value & std::numeric_limits<DB::UInt64>::max());
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|