2011-08-28 00:31:30 +00:00
|
|
|
#pragma once
|
2010-03-01 16:59:51 +00:00
|
|
|
|
2019-09-27 14:49:03 +00:00
|
|
|
#include <cassert>
|
2010-03-01 16:59:51 +00:00
|
|
|
#include <vector>
|
2016-05-28 14:14:18 +00:00
|
|
|
#include <algorithm>
|
2014-01-08 16:33:28 +00:00
|
|
|
#include <type_traits>
|
|
|
|
#include <functional>
|
2010-03-01 16:59:51 +00:00
|
|
|
|
2017-04-01 09:19:00 +00:00
|
|
|
#include <Common/Exception.h>
|
2021-03-31 03:19:34 +00:00
|
|
|
#include <Common/AllocatorWithMemoryTracking.h>
|
2017-04-01 09:19:00 +00:00
|
|
|
#include <Core/Types.h>
|
2017-12-14 03:56:56 +00:00
|
|
|
#include <Core/Defines.h>
|
2020-08-19 11:52:17 +00:00
|
|
|
#include <Core/DecimalFunctions.h>
|
2018-10-22 08:54:54 +00:00
|
|
|
#include <Core/UUID.h>
|
2021-10-02 07:13:14 +00:00
|
|
|
#include <base/DayNum.h>
|
|
|
|
#include <base/strong_typedef.h>
|
|
|
|
#include <base/EnumReflection.h>
|
2014-12-09 12:07:27 +00:00
|
|
|
|
2013-10-11 11:43:50 +00:00
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
2016-01-11 21:46:36 +00:00
|
|
|
namespace ErrorCodes
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
extern const int BAD_TYPE_OF_FIELD;
|
|
|
|
extern const int BAD_GET;
|
|
|
|
extern const int NOT_IMPLEMENTED;
|
2018-08-23 19:11:31 +00:00
|
|
|
extern const int LOGICAL_ERROR;
|
2019-02-11 13:11:52 +00:00
|
|
|
extern const int ILLEGAL_TYPE_OF_ARGUMENT;
|
2016-01-11 21:46:36 +00:00
|
|
|
}
|
|
|
|
|
2021-08-29 19:00:00 +00:00
|
|
|
constexpr Null NEGATIVE_INFINITY{Null::Value::NegativeInfinity};
|
|
|
|
constexpr Null POSITIVE_INFINITY{Null::Value::PositiveInfinity};
|
2021-08-27 14:09:15 +00:00
|
|
|
|
2013-11-02 22:20:58 +00:00
|
|
|
class Field;
|
2021-03-31 03:19:34 +00:00
|
|
|
using FieldVector = std::vector<Field, AllocatorWithMemoryTracking<Field>>;
|
2019-10-18 15:57:05 +00:00
|
|
|
|
|
|
|
/// Array and Tuple use the same storage type -- FieldVector, but we declare
|
|
|
|
/// distinct types for them, so that the caller can choose whether it wants to
|
|
|
|
/// construct a Field of Array or a Tuple type. An alternative approach would be
|
|
|
|
/// to construct both of these types from FieldVector, and have the caller
|
|
|
|
/// specify the desired Field type explicitly.
|
|
|
|
#define DEFINE_FIELD_VECTOR(X) \
|
|
|
|
struct X : public FieldVector \
|
|
|
|
{ \
|
|
|
|
using FieldVector::FieldVector; \
|
|
|
|
}
|
|
|
|
|
|
|
|
DEFINE_FIELD_VECTOR(Array);
|
|
|
|
DEFINE_FIELD_VECTOR(Tuple);
|
2020-12-15 22:22:21 +00:00
|
|
|
|
|
|
|
/// An array with the following structure: [(key1, value1), (key2, value2), ...]
|
2020-10-10 06:49:03 +00:00
|
|
|
DEFINE_FIELD_VECTOR(Map);
|
2019-10-18 15:57:05 +00:00
|
|
|
|
|
|
|
#undef DEFINE_FIELD_VECTOR
|
2013-10-11 11:43:50 +00:00
|
|
|
|
2019-02-11 13:11:52 +00:00
|
|
|
struct AggregateFunctionStateData
|
|
|
|
{
|
|
|
|
String name; /// Name with arguments.
|
|
|
|
String data;
|
|
|
|
|
|
|
|
bool operator < (const AggregateFunctionStateData &) const
|
|
|
|
{
|
|
|
|
throw Exception("Operator < is not implemented for AggregateFunctionStateData.", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator <= (const AggregateFunctionStateData &) const
|
|
|
|
{
|
|
|
|
throw Exception("Operator <= is not implemented for AggregateFunctionStateData.", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator > (const AggregateFunctionStateData &) const
|
|
|
|
{
|
|
|
|
throw Exception("Operator > is not implemented for AggregateFunctionStateData.", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator >= (const AggregateFunctionStateData &) const
|
|
|
|
{
|
|
|
|
throw Exception("Operator >= is not implemented for AggregateFunctionStateData.", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator == (const AggregateFunctionStateData & rhs) const
|
|
|
|
{
|
|
|
|
if (name != rhs.name)
|
|
|
|
throw Exception("Comparing aggregate functions with different types: " + name + " and " + rhs.name,
|
|
|
|
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
|
|
|
|
|
|
|
return data == rhs.data;
|
|
|
|
}
|
|
|
|
};
|
2019-02-11 11:19:56 +00:00
|
|
|
|
2018-08-23 14:03:37 +00:00
|
|
|
template <typename T> bool decimalEqual(T x, T y, UInt32 x_scale, UInt32 y_scale);
|
|
|
|
template <typename T> bool decimalLess(T x, T y, UInt32 x_scale, UInt32 y_scale);
|
|
|
|
template <typename T> bool decimalLessOrEqual(T x, T y, UInt32 x_scale, UInt32 y_scale);
|
2010-03-01 16:59:51 +00:00
|
|
|
|
2021-04-18 09:17:02 +00:00
|
|
|
#if !defined(__clang__)
|
2020-08-19 11:52:17 +00:00
|
|
|
#pragma GCC diagnostic push
|
|
|
|
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
|
|
|
|
#endif
|
2018-08-23 14:03:37 +00:00
|
|
|
template <typename T>
|
2018-08-21 04:31:35 +00:00
|
|
|
class DecimalField
|
2018-08-09 16:32:01 +00:00
|
|
|
{
|
|
|
|
public:
|
2020-08-19 11:52:17 +00:00
|
|
|
DecimalField(T value = {}, UInt32 scale_ = 0)
|
2018-08-09 16:32:01 +00:00
|
|
|
: dec(value),
|
|
|
|
scale(scale_)
|
|
|
|
{}
|
|
|
|
|
2018-08-23 14:03:37 +00:00
|
|
|
operator T() const { return dec; }
|
2018-08-23 19:11:31 +00:00
|
|
|
T getValue() const { return dec; }
|
2020-08-19 11:52:17 +00:00
|
|
|
T getScaleMultiplier() const { return DecimalUtils::scaleMultiplier<T>(scale); }
|
2018-08-09 16:32:01 +00:00
|
|
|
UInt32 getScale() const { return scale; }
|
|
|
|
|
2018-08-23 14:03:37 +00:00
|
|
|
template <typename U>
|
|
|
|
bool operator < (const DecimalField<U> & r) const
|
|
|
|
{
|
|
|
|
using MaxType = std::conditional_t<(sizeof(T) > sizeof(U)), T, U>;
|
2018-08-23 19:11:31 +00:00
|
|
|
return decimalLess<MaxType>(dec, r.getValue(), scale, r.getScale());
|
2018-08-23 14:03:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <typename U>
|
|
|
|
bool operator <= (const DecimalField<U> & r) const
|
|
|
|
{
|
|
|
|
using MaxType = std::conditional_t<(sizeof(T) > sizeof(U)), T, U>;
|
2018-08-23 19:11:31 +00:00
|
|
|
return decimalLessOrEqual<MaxType>(dec, r.getValue(), scale, r.getScale());
|
2018-08-23 14:03:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <typename U>
|
|
|
|
bool operator == (const DecimalField<U> & r) const
|
|
|
|
{
|
|
|
|
using MaxType = std::conditional_t<(sizeof(T) > sizeof(U)), T, U>;
|
2018-08-23 19:11:31 +00:00
|
|
|
return decimalEqual<MaxType>(dec, r.getValue(), scale, r.getScale());
|
2018-08-23 14:03:37 +00:00
|
|
|
}
|
2018-08-09 16:32:01 +00:00
|
|
|
|
2018-08-23 14:03:37 +00:00
|
|
|
template <typename U> bool operator > (const DecimalField<U> & r) const { return r < *this; }
|
|
|
|
template <typename U> bool operator >= (const DecimalField<U> & r) const { return r <= * this; }
|
|
|
|
template <typename U> bool operator != (const DecimalField<U> & r) const { return !(*this == r); }
|
2018-08-09 16:32:01 +00:00
|
|
|
|
2018-08-23 19:11:31 +00:00
|
|
|
const DecimalField<T> & operator += (const DecimalField<T> & r)
|
|
|
|
{
|
|
|
|
if (scale != r.getScale())
|
|
|
|
throw Exception("Add different decimal fields", ErrorCodes::LOGICAL_ERROR);
|
|
|
|
dec += r.getValue();
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
const DecimalField<T> & operator -= (const DecimalField<T> & r)
|
|
|
|
{
|
|
|
|
if (scale != r.getScale())
|
|
|
|
throw Exception("Sub different decimal fields", ErrorCodes::LOGICAL_ERROR);
|
|
|
|
dec -= r.getValue();
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2018-08-09 16:32:01 +00:00
|
|
|
private:
|
2018-08-23 14:03:37 +00:00
|
|
|
T dec;
|
2018-08-09 16:32:01 +00:00
|
|
|
UInt32 scale;
|
|
|
|
};
|
2021-04-18 09:17:02 +00:00
|
|
|
#if !defined(__clang__)
|
2020-08-19 11:52:17 +00:00
|
|
|
#pragma GCC diagnostic pop
|
|
|
|
#endif
|
2018-08-09 16:32:01 +00:00
|
|
|
|
2021-06-14 03:05:27 +00:00
|
|
|
template <typename T> constexpr bool is_decimal_field = false;
|
2021-06-14 04:13:35 +00:00
|
|
|
template <> constexpr inline bool is_decimal_field<DecimalField<Decimal32>> = true;
|
|
|
|
template <> constexpr inline bool is_decimal_field<DecimalField<Decimal64>> = true;
|
|
|
|
template <> constexpr inline bool is_decimal_field<DecimalField<Decimal128>> = true;
|
|
|
|
template <> constexpr inline bool is_decimal_field<DecimalField<Decimal256>> = true;
|
2021-06-14 03:05:27 +00:00
|
|
|
|
2021-08-24 05:53:21 +00:00
|
|
|
template <typename T, typename SFINAE = void>
|
|
|
|
struct NearestFieldTypeImpl;
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
using NearestFieldType = typename NearestFieldTypeImpl<T>::Type;
|
|
|
|
|
2019-12-10 13:40:45 +00:00
|
|
|
/// char may be signed or unsigned, and behave identically to signed char or unsigned char,
|
|
|
|
/// but they are always three different types.
|
|
|
|
/// signedness of char is different in Linux on x86 and Linux on ARM.
|
|
|
|
template <> struct NearestFieldTypeImpl<char> { using Type = std::conditional_t<is_signed_v<char>, Int64, UInt64>; };
|
|
|
|
template <> struct NearestFieldTypeImpl<signed char> { using Type = Int64; };
|
|
|
|
template <> struct NearestFieldTypeImpl<unsigned char> { using Type = UInt64; };
|
2020-12-01 14:06:41 +00:00
|
|
|
#ifdef __cpp_char8_t
|
2020-01-03 14:29:31 +00:00
|
|
|
template <> struct NearestFieldTypeImpl<char8_t> { using Type = UInt64; };
|
2020-04-16 12:31:57 +00:00
|
|
|
#endif
|
2019-12-10 13:40:45 +00:00
|
|
|
|
|
|
|
template <> struct NearestFieldTypeImpl<UInt16> { using Type = UInt64; };
|
|
|
|
template <> struct NearestFieldTypeImpl<UInt32> { using Type = UInt64; };
|
|
|
|
|
|
|
|
template <> struct NearestFieldTypeImpl<DayNum> { using Type = UInt64; };
|
2021-05-03 22:46:51 +00:00
|
|
|
template <> struct NearestFieldTypeImpl<UUID> { using Type = UUID; };
|
2019-12-10 13:40:45 +00:00
|
|
|
template <> struct NearestFieldTypeImpl<Int16> { using Type = Int64; };
|
|
|
|
template <> struct NearestFieldTypeImpl<Int32> { using Type = Int64; };
|
|
|
|
|
|
|
|
/// long and long long are always different types that may behave identically or not.
|
|
|
|
/// This is different on Linux and Mac.
|
|
|
|
template <> struct NearestFieldTypeImpl<long> { using Type = Int64; };
|
|
|
|
template <> struct NearestFieldTypeImpl<long long> { using Type = Int64; };
|
|
|
|
template <> struct NearestFieldTypeImpl<unsigned long> { using Type = UInt64; };
|
|
|
|
template <> struct NearestFieldTypeImpl<unsigned long long> { using Type = UInt64; };
|
|
|
|
|
2020-09-01 09:54:50 +00:00
|
|
|
template <> struct NearestFieldTypeImpl<UInt256> { using Type = UInt256; };
|
|
|
|
template <> struct NearestFieldTypeImpl<Int256> { using Type = Int256; };
|
2021-01-27 00:54:57 +00:00
|
|
|
template <> struct NearestFieldTypeImpl<UInt128> { using Type = UInt128; };
|
2019-12-10 13:40:45 +00:00
|
|
|
template <> struct NearestFieldTypeImpl<Int128> { using Type = Int128; };
|
2021-01-27 00:54:57 +00:00
|
|
|
|
2019-12-10 13:40:45 +00:00
|
|
|
template <> struct NearestFieldTypeImpl<Decimal32> { using Type = DecimalField<Decimal32>; };
|
|
|
|
template <> struct NearestFieldTypeImpl<Decimal64> { using Type = DecimalField<Decimal64>; };
|
|
|
|
template <> struct NearestFieldTypeImpl<Decimal128> { using Type = DecimalField<Decimal128>; };
|
2020-08-19 11:52:17 +00:00
|
|
|
template <> struct NearestFieldTypeImpl<Decimal256> { using Type = DecimalField<Decimal256>; };
|
2020-11-12 20:23:26 +00:00
|
|
|
template <> struct NearestFieldTypeImpl<DateTime64> { using Type = DecimalField<DateTime64>; };
|
2019-12-10 13:40:45 +00:00
|
|
|
template <> struct NearestFieldTypeImpl<DecimalField<Decimal32>> { using Type = DecimalField<Decimal32>; };
|
|
|
|
template <> struct NearestFieldTypeImpl<DecimalField<Decimal64>> { using Type = DecimalField<Decimal64>; };
|
|
|
|
template <> struct NearestFieldTypeImpl<DecimalField<Decimal128>> { using Type = DecimalField<Decimal128>; };
|
2020-08-19 11:52:17 +00:00
|
|
|
template <> struct NearestFieldTypeImpl<DecimalField<Decimal256>> { using Type = DecimalField<Decimal256>; };
|
2020-11-12 20:23:26 +00:00
|
|
|
template <> struct NearestFieldTypeImpl<DecimalField<DateTime64>> { using Type = DecimalField<DateTime64>; };
|
2019-12-10 13:40:45 +00:00
|
|
|
template <> struct NearestFieldTypeImpl<Float32> { using Type = Float64; };
|
|
|
|
template <> struct NearestFieldTypeImpl<Float64> { using Type = Float64; };
|
|
|
|
template <> struct NearestFieldTypeImpl<const char *> { using Type = String; };
|
2020-07-26 21:41:27 +00:00
|
|
|
template <> struct NearestFieldTypeImpl<std::string_view> { using Type = String; };
|
2019-12-10 13:40:45 +00:00
|
|
|
template <> struct NearestFieldTypeImpl<String> { using Type = String; };
|
|
|
|
template <> struct NearestFieldTypeImpl<Array> { using Type = Array; };
|
|
|
|
template <> struct NearestFieldTypeImpl<Tuple> { using Type = Tuple; };
|
2020-10-10 06:49:03 +00:00
|
|
|
template <> struct NearestFieldTypeImpl<Map> { using Type = Map; };
|
2019-12-10 13:40:45 +00:00
|
|
|
template <> struct NearestFieldTypeImpl<bool> { using Type = UInt64; };
|
|
|
|
template <> struct NearestFieldTypeImpl<Null> { using Type = Null; };
|
|
|
|
|
|
|
|
template <> struct NearestFieldTypeImpl<AggregateFunctionStateData> { using Type = AggregateFunctionStateData; };
|
|
|
|
|
|
|
|
// For enum types, use the field type that corresponds to their underlying type.
|
|
|
|
template <typename T>
|
|
|
|
struct NearestFieldTypeImpl<T, std::enable_if_t<std::is_enum_v<T>>>
|
|
|
|
{
|
|
|
|
using Type = NearestFieldType<std::underlying_type_t<T>>;
|
|
|
|
};
|
|
|
|
|
2021-08-24 05:53:21 +00:00
|
|
|
template <typename T>
|
|
|
|
decltype(auto) castToNearestFieldType(T && x)
|
|
|
|
{
|
|
|
|
using U = NearestFieldType<std::decay_t<T>>;
|
|
|
|
if constexpr (std::is_same_v<std::decay_t<T>, U>)
|
|
|
|
return std::forward<T>(x);
|
|
|
|
else
|
|
|
|
return U(x);
|
|
|
|
}
|
|
|
|
|
2017-01-06 17:41:19 +00:00
|
|
|
/** 32 is enough. Round number is used for alignment and for better arithmetic inside std::vector.
|
2018-02-18 02:22:32 +00:00
|
|
|
* NOTE: Actually, sizeof(std::string) is 32 when using libc++, so Field is 40 bytes.
|
2013-01-08 21:32:16 +00:00
|
|
|
*/
|
2016-01-14 01:43:14 +00:00
|
|
|
#define DBMS_MIN_FIELD_SIZE 32
|
2013-01-08 21:32:16 +00:00
|
|
|
|
2013-01-05 20:03:19 +00:00
|
|
|
|
2017-04-30 13:50:16 +00:00
|
|
|
/** Discriminated union of several types.
|
|
|
|
* Made for replacement of `boost::variant`
|
|
|
|
* is not generalized,
|
|
|
|
* but somewhat more efficient, and simpler.
|
2013-01-05 20:03:19 +00:00
|
|
|
*
|
2017-08-29 19:07:54 +00:00
|
|
|
* Used to represent a single value of one of several types in memory.
|
2021-05-03 22:46:51 +00:00
|
|
|
* Warning! Prefer to use chunks of columns instead of single values. See IColumn.h
|
2010-03-01 16:59:51 +00:00
|
|
|
*/
|
2016-01-14 01:43:14 +00:00
|
|
|
class Field
|
2013-01-05 20:03:19 +00:00
|
|
|
{
|
|
|
|
public:
|
2017-04-01 07:20:54 +00:00
|
|
|
struct Types
|
|
|
|
{
|
|
|
|
/// Type tag.
|
|
|
|
enum Which
|
|
|
|
{
|
2017-05-11 19:48:46 +00:00
|
|
|
Null = 0,
|
2021-06-19 06:41:37 +00:00
|
|
|
UInt64 = 1,
|
|
|
|
Int64 = 2,
|
|
|
|
Float64 = 3,
|
|
|
|
UInt128 = 4,
|
|
|
|
Int128 = 5,
|
2017-04-01 07:20:54 +00:00
|
|
|
|
2017-05-11 19:48:46 +00:00
|
|
|
String = 16,
|
|
|
|
Array = 17,
|
|
|
|
Tuple = 18,
|
2018-08-23 14:03:37 +00:00
|
|
|
Decimal32 = 19,
|
|
|
|
Decimal64 = 20,
|
|
|
|
Decimal128 = 21,
|
2019-02-11 11:19:56 +00:00
|
|
|
AggregateFunctionState = 22,
|
2020-08-19 11:52:17 +00:00
|
|
|
Decimal256 = 23,
|
2020-09-01 09:54:50 +00:00
|
|
|
UInt256 = 24,
|
|
|
|
Int256 = 25,
|
2020-10-10 06:49:03 +00:00
|
|
|
Map = 26,
|
2021-05-03 22:46:51 +00:00
|
|
|
UUID = 27,
|
2022-01-18 11:52:27 +00:00
|
|
|
Bool = 28,
|
2017-04-01 07:20:54 +00:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2017-04-30 13:50:16 +00:00
|
|
|
/// Returns an identifier for the type or vice versa.
|
2017-04-01 07:20:54 +00:00
|
|
|
template <typename T> struct TypeToEnum;
|
|
|
|
template <Types::Which which> struct EnumToType;
|
|
|
|
|
2020-08-19 11:52:17 +00:00
|
|
|
static bool IsDecimal(Types::Which which)
|
|
|
|
{
|
2021-05-03 22:46:51 +00:00
|
|
|
return which == Types::Decimal32
|
|
|
|
|| which == Types::Decimal64
|
|
|
|
|| which == Types::Decimal128
|
|
|
|
|| which == Types::Decimal256;
|
2020-08-19 11:52:17 +00:00
|
|
|
}
|
2020-07-26 21:41:27 +00:00
|
|
|
|
|
|
|
/// Templates to avoid ambiguity.
|
|
|
|
template <typename T, typename Z = void *>
|
2021-08-23 05:33:16 +00:00
|
|
|
using enable_if_not_field_or_bool_or_stringlike_t = std::enable_if_t<
|
|
|
|
!std::is_same_v<std::decay_t<T>, Field> &&
|
|
|
|
!std::is_same_v<std::decay_t<T>, bool> &&
|
|
|
|
!std::is_same_v<NearestFieldType<std::decay_t<T>>, String>, Z>;
|
2017-04-01 07:20:54 +00:00
|
|
|
|
2021-08-27 14:09:15 +00:00
|
|
|
Field() : Field(Null{}) {}
|
2017-04-01 07:20:54 +00:00
|
|
|
|
2017-04-30 13:50:16 +00:00
|
|
|
/** Despite the presence of a template constructor, this constructor is still needed,
|
|
|
|
* since, in its absence, the compiler will still generate the default constructor.
|
2017-04-01 07:20:54 +00:00
|
|
|
*/
|
|
|
|
Field(const Field & rhs)
|
|
|
|
{
|
|
|
|
create(rhs);
|
|
|
|
}
|
|
|
|
|
|
|
|
Field(Field && rhs)
|
|
|
|
{
|
|
|
|
create(std::move(rhs));
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
2021-08-23 05:33:16 +00:00
|
|
|
Field(T && rhs, enable_if_not_field_or_bool_or_stringlike_t<T> = nullptr);
|
|
|
|
|
2022-01-18 11:52:27 +00:00
|
|
|
Field(bool rhs) : Field(castToNearestFieldType(rhs))
|
|
|
|
{
|
|
|
|
which = Types::Bool;
|
|
|
|
}
|
2017-04-01 07:20:54 +00:00
|
|
|
|
2017-04-30 13:50:16 +00:00
|
|
|
/// Create a string inplace.
|
2020-07-26 21:41:27 +00:00
|
|
|
Field(const std::string_view & str) { create(str.data(), str.size()); }
|
|
|
|
Field(const String & str) { create(std::string_view{str}); }
|
|
|
|
Field(String && str) { create(std::move(str)); }
|
|
|
|
Field(const char * str) { create(std::string_view{str}); }
|
2017-04-01 07:20:54 +00:00
|
|
|
|
2020-01-03 14:29:31 +00:00
|
|
|
template <typename CharT>
|
2020-07-26 21:41:27 +00:00
|
|
|
Field(const CharT * data, size_t size)
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
|
|
|
create(data, size);
|
|
|
|
}
|
|
|
|
|
|
|
|
Field & operator= (const Field & rhs)
|
|
|
|
{
|
|
|
|
if (this != &rhs)
|
|
|
|
{
|
|
|
|
if (which != rhs.which)
|
|
|
|
{
|
|
|
|
destroy();
|
|
|
|
create(rhs);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
assign(rhs); /// This assigns string or vector without deallocation of existing buffer.
|
|
|
|
}
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
Field & operator= (Field && rhs)
|
|
|
|
{
|
|
|
|
if (this != &rhs)
|
|
|
|
{
|
|
|
|
if (which != rhs.which)
|
|
|
|
{
|
|
|
|
destroy();
|
|
|
|
create(std::move(rhs));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
assign(std::move(rhs));
|
|
|
|
}
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2020-07-26 21:41:27 +00:00
|
|
|
/// Allows expressions like
|
|
|
|
/// Field f = 1;
|
|
|
|
/// Things to note:
|
|
|
|
/// 1. float <--> int needs explicit cast
|
|
|
|
/// 2. customized types needs explicit cast
|
2017-04-01 07:20:54 +00:00
|
|
|
template <typename T>
|
2021-08-23 05:33:16 +00:00
|
|
|
enable_if_not_field_or_bool_or_stringlike_t<T, Field> &
|
2020-07-26 21:41:27 +00:00
|
|
|
operator=(T && rhs);
|
|
|
|
|
2022-01-18 11:52:27 +00:00
|
|
|
Field & operator= (bool rhs)
|
|
|
|
{
|
|
|
|
*this = castToNearestFieldType(rhs);
|
|
|
|
which = Types::Bool;
|
|
|
|
return *this;
|
|
|
|
}
|
2021-08-23 05:33:16 +00:00
|
|
|
|
2021-05-03 22:46:51 +00:00
|
|
|
Field & operator= (const std::string_view & str);
|
|
|
|
Field & operator= (const String & str) { return *this = std::string_view{str}; }
|
|
|
|
Field & operator= (String && str);
|
|
|
|
Field & operator= (const char * str) { return *this = std::string_view{str}; }
|
2017-04-01 07:20:54 +00:00
|
|
|
|
|
|
|
~Field()
|
|
|
|
{
|
|
|
|
destroy();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Types::Which getType() const { return which; }
|
2021-09-06 14:24:03 +00:00
|
|
|
|
2021-09-06 15:59:46 +00:00
|
|
|
constexpr std::string_view getTypeName() const { return magic_enum::enum_name(which); }
|
2017-04-01 07:20:54 +00:00
|
|
|
|
2021-08-27 14:09:15 +00:00
|
|
|
bool isNull() const { return which == Types::Null; }
|
2019-12-10 13:40:45 +00:00
|
|
|
template <typename T>
|
2021-03-22 20:23:44 +00:00
|
|
|
NearestFieldType<std::decay_t<T>> & get();
|
2019-12-10 13:40:45 +00:00
|
|
|
|
|
|
|
template <typename T>
|
2021-03-22 20:23:44 +00:00
|
|
|
const auto & get() const
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
2019-12-10 13:40:45 +00:00
|
|
|
auto mutable_this = const_cast<std::decay_t<decltype(*this)> *>(this);
|
|
|
|
return mutable_this->get<T>();
|
2018-06-03 16:51:31 +00:00
|
|
|
}
|
2017-04-01 07:20:54 +00:00
|
|
|
|
2021-08-29 19:00:00 +00:00
|
|
|
bool isNegativeInfinity() const { return which == Types::Null && get<Null>().isNegativeInfinity(); }
|
|
|
|
bool isPositiveInfinity() const { return which == Types::Null && get<Null>().isPositiveInfinity(); }
|
2021-08-27 14:09:15 +00:00
|
|
|
|
2019-12-10 13:40:45 +00:00
|
|
|
template <typename T>
|
|
|
|
T & reinterpret();
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
const T & reinterpret() const
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
2019-12-10 13:40:45 +00:00
|
|
|
auto mutable_this = const_cast<std::decay_t<decltype(*this)> *>(this);
|
|
|
|
return mutable_this->reinterpret<T>();
|
2018-06-03 16:51:31 +00:00
|
|
|
}
|
2017-04-01 07:20:54 +00:00
|
|
|
|
2017-06-28 21:45:15 +00:00
|
|
|
template <typename T> bool tryGet(T & result)
|
|
|
|
{
|
2017-12-25 04:01:46 +00:00
|
|
|
const Types::Which requested = TypeToEnum<std::decay_t<T>>::value;
|
2017-06-28 21:45:15 +00:00
|
|
|
if (which != requested)
|
|
|
|
return false;
|
|
|
|
result = get<T>();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T> bool tryGet(T & result) const
|
|
|
|
{
|
2017-12-25 04:01:46 +00:00
|
|
|
const Types::Which requested = TypeToEnum<std::decay_t<T>>::value;
|
2017-06-28 21:45:15 +00:00
|
|
|
if (which != requested)
|
|
|
|
return false;
|
|
|
|
result = get<T>();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-03-22 20:23:44 +00:00
|
|
|
template <typename T> auto & safeGet() const
|
|
|
|
{ return const_cast<Field *>(this)->safeGet<T>(); }
|
2017-04-01 07:20:54 +00:00
|
|
|
|
2021-03-22 20:23:44 +00:00
|
|
|
template <typename T> auto & safeGet();
|
2017-04-01 07:20:54 +00:00
|
|
|
|
|
|
|
bool operator< (const Field & rhs) const
|
|
|
|
{
|
|
|
|
if (which < rhs.which)
|
|
|
|
return true;
|
|
|
|
if (which > rhs.which)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
switch (which)
|
|
|
|
{
|
2021-08-27 14:09:15 +00:00
|
|
|
case Types::Null: return false;
|
2022-01-18 11:52:27 +00:00
|
|
|
case Types::Bool: [[fallthrough]];
|
2017-05-11 19:48:46 +00:00
|
|
|
case Types::UInt64: return get<UInt64>() < rhs.get<UInt64>();
|
2017-07-06 14:42:27 +00:00
|
|
|
case Types::UInt128: return get<UInt128>() < rhs.get<UInt128>();
|
2021-05-03 16:12:28 +00:00
|
|
|
case Types::UInt256: return get<UInt256>() < rhs.get<UInt256>();
|
2017-05-11 19:48:46 +00:00
|
|
|
case Types::Int64: return get<Int64>() < rhs.get<Int64>();
|
2018-07-20 19:05:07 +00:00
|
|
|
case Types::Int128: return get<Int128>() < rhs.get<Int128>();
|
2021-05-03 22:46:51 +00:00
|
|
|
case Types::Int256: return get<Int256>() < rhs.get<Int256>();
|
|
|
|
case Types::UUID: return get<UUID>() < rhs.get<UUID>();
|
2017-05-11 19:48:46 +00:00
|
|
|
case Types::Float64: return get<Float64>() < rhs.get<Float64>();
|
|
|
|
case Types::String: return get<String>() < rhs.get<String>();
|
|
|
|
case Types::Array: return get<Array>() < rhs.get<Array>();
|
|
|
|
case Types::Tuple: return get<Tuple>() < rhs.get<Tuple>();
|
2020-10-10 06:49:03 +00:00
|
|
|
case Types::Map: return get<Map>() < rhs.get<Map>();
|
2018-08-23 14:03:37 +00:00
|
|
|
case Types::Decimal32: return get<DecimalField<Decimal32>>() < rhs.get<DecimalField<Decimal32>>();
|
|
|
|
case Types::Decimal64: return get<DecimalField<Decimal64>>() < rhs.get<DecimalField<Decimal64>>();
|
|
|
|
case Types::Decimal128: return get<DecimalField<Decimal128>>() < rhs.get<DecimalField<Decimal128>>();
|
2020-08-19 11:52:17 +00:00
|
|
|
case Types::Decimal256: return get<DecimalField<Decimal256>>() < rhs.get<DecimalField<Decimal256>>();
|
2019-02-11 11:19:56 +00:00
|
|
|
case Types::AggregateFunctionState: return get<AggregateFunctionStateData>() < rhs.get<AggregateFunctionStateData>();
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
2018-08-09 16:32:01 +00:00
|
|
|
|
|
|
|
throw Exception("Bad type of Field", ErrorCodes::BAD_TYPE_OF_FIELD);
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool operator> (const Field & rhs) const
|
|
|
|
{
|
|
|
|
return rhs < *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator<= (const Field & rhs) const
|
|
|
|
{
|
|
|
|
if (which < rhs.which)
|
|
|
|
return true;
|
|
|
|
if (which > rhs.which)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
switch (which)
|
|
|
|
{
|
2021-08-27 14:09:15 +00:00
|
|
|
case Types::Null: return true;
|
2022-01-18 11:52:27 +00:00
|
|
|
case Types::Bool: [[fallthrough]];
|
2017-05-11 19:48:46 +00:00
|
|
|
case Types::UInt64: return get<UInt64>() <= rhs.get<UInt64>();
|
2017-07-06 14:42:27 +00:00
|
|
|
case Types::UInt128: return get<UInt128>() <= rhs.get<UInt128>();
|
2021-05-03 16:12:28 +00:00
|
|
|
case Types::UInt256: return get<UInt256>() <= rhs.get<UInt256>();
|
2017-05-11 19:48:46 +00:00
|
|
|
case Types::Int64: return get<Int64>() <= rhs.get<Int64>();
|
2018-07-20 19:05:07 +00:00
|
|
|
case Types::Int128: return get<Int128>() <= rhs.get<Int128>();
|
2021-05-03 22:46:51 +00:00
|
|
|
case Types::Int256: return get<Int256>() <= rhs.get<Int256>();
|
|
|
|
case Types::UUID: return get<UUID>().toUnderType() <= rhs.get<UUID>().toUnderType();
|
2017-05-11 19:48:46 +00:00
|
|
|
case Types::Float64: return get<Float64>() <= rhs.get<Float64>();
|
|
|
|
case Types::String: return get<String>() <= rhs.get<String>();
|
|
|
|
case Types::Array: return get<Array>() <= rhs.get<Array>();
|
|
|
|
case Types::Tuple: return get<Tuple>() <= rhs.get<Tuple>();
|
2020-10-10 06:49:03 +00:00
|
|
|
case Types::Map: return get<Map>() <= rhs.get<Map>();
|
2018-08-23 14:03:37 +00:00
|
|
|
case Types::Decimal32: return get<DecimalField<Decimal32>>() <= rhs.get<DecimalField<Decimal32>>();
|
|
|
|
case Types::Decimal64: return get<DecimalField<Decimal64>>() <= rhs.get<DecimalField<Decimal64>>();
|
|
|
|
case Types::Decimal128: return get<DecimalField<Decimal128>>() <= rhs.get<DecimalField<Decimal128>>();
|
2020-08-19 11:52:17 +00:00
|
|
|
case Types::Decimal256: return get<DecimalField<Decimal256>>() <= rhs.get<DecimalField<Decimal256>>();
|
2019-02-11 11:19:56 +00:00
|
|
|
case Types::AggregateFunctionState: return get<AggregateFunctionStateData>() <= rhs.get<AggregateFunctionStateData>();
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
2018-08-09 16:32:01 +00:00
|
|
|
|
|
|
|
throw Exception("Bad type of Field", ErrorCodes::BAD_TYPE_OF_FIELD);
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool operator>= (const Field & rhs) const
|
|
|
|
{
|
|
|
|
return rhs <= *this;
|
|
|
|
}
|
|
|
|
|
2019-12-10 13:40:45 +00:00
|
|
|
// More like bitwise equality as opposed to semantic equality:
|
|
|
|
// Null equals Null and NaN equals NaN.
|
2017-04-01 07:20:54 +00:00
|
|
|
bool operator== (const Field & rhs) const
|
|
|
|
{
|
|
|
|
if (which != rhs.which)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
switch (which)
|
|
|
|
{
|
2021-08-27 14:09:15 +00:00
|
|
|
case Types::Null: return true;
|
2022-01-18 11:52:27 +00:00
|
|
|
case Types::Bool: [[fallthrough]];
|
2021-01-02 09:47:38 +00:00
|
|
|
case Types::UInt64: return get<UInt64>() == rhs.get<UInt64>();
|
2019-12-10 13:40:45 +00:00
|
|
|
case Types::Int64: return get<Int64>() == rhs.get<Int64>();
|
|
|
|
case Types::Float64:
|
|
|
|
{
|
|
|
|
// Compare as UInt64 so that NaNs compare as equal.
|
|
|
|
return reinterpret<UInt64>() == rhs.reinterpret<UInt64>();
|
|
|
|
}
|
2021-05-03 22:46:51 +00:00
|
|
|
case Types::UUID: return get<UUID>() == rhs.get<UUID>();
|
2017-07-04 10:42:53 +00:00
|
|
|
case Types::String: return get<String>() == rhs.get<String>();
|
|
|
|
case Types::Array: return get<Array>() == rhs.get<Array>();
|
|
|
|
case Types::Tuple: return get<Tuple>() == rhs.get<Tuple>();
|
2020-10-10 06:49:03 +00:00
|
|
|
case Types::Map: return get<Map>() == rhs.get<Map>();
|
2017-07-04 10:42:53 +00:00
|
|
|
case Types::UInt128: return get<UInt128>() == rhs.get<UInt128>();
|
2021-05-03 16:12:28 +00:00
|
|
|
case Types::UInt256: return get<UInt256>() == rhs.get<UInt256>();
|
2018-07-20 19:05:07 +00:00
|
|
|
case Types::Int128: return get<Int128>() == rhs.get<Int128>();
|
2021-05-03 16:12:28 +00:00
|
|
|
case Types::Int256: return get<Int256>() == rhs.get<Int256>();
|
2018-08-23 14:03:37 +00:00
|
|
|
case Types::Decimal32: return get<DecimalField<Decimal32>>() == rhs.get<DecimalField<Decimal32>>();
|
|
|
|
case Types::Decimal64: return get<DecimalField<Decimal64>>() == rhs.get<DecimalField<Decimal64>>();
|
|
|
|
case Types::Decimal128: return get<DecimalField<Decimal128>>() == rhs.get<DecimalField<Decimal128>>();
|
2020-08-19 11:52:17 +00:00
|
|
|
case Types::Decimal256: return get<DecimalField<Decimal256>>() == rhs.get<DecimalField<Decimal256>>();
|
2019-02-11 11:19:56 +00:00
|
|
|
case Types::AggregateFunctionState: return get<AggregateFunctionStateData>() == rhs.get<AggregateFunctionStateData>();
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
2018-08-09 16:32:01 +00:00
|
|
|
|
|
|
|
throw Exception("Bad type of Field", ErrorCodes::BAD_TYPE_OF_FIELD);
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool operator!= (const Field & rhs) const
|
|
|
|
{
|
|
|
|
return !(*this == rhs);
|
|
|
|
}
|
2013-01-05 20:03:19 +00:00
|
|
|
|
2019-12-10 13:40:45 +00:00
|
|
|
/// Field is template parameter, to allow universal reference for field,
|
|
|
|
/// that is useful for const and non-const .
|
|
|
|
template <typename F, typename FieldRef>
|
|
|
|
static auto dispatch(F && f, FieldRef && field)
|
|
|
|
{
|
|
|
|
switch (field.which)
|
|
|
|
{
|
|
|
|
case Types::Null: return f(field.template get<Null>());
|
2019-12-13 11:18:09 +00:00
|
|
|
// gcc 8.2.1
|
2021-04-18 09:17:02 +00:00
|
|
|
#if !defined(__clang__)
|
2019-12-13 11:18:09 +00:00
|
|
|
#pragma GCC diagnostic push
|
|
|
|
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
|
|
|
|
#endif
|
2019-12-10 13:40:45 +00:00
|
|
|
case Types::UInt64: return f(field.template get<UInt64>());
|
|
|
|
case Types::UInt128: return f(field.template get<UInt128>());
|
2021-05-03 16:12:28 +00:00
|
|
|
case Types::UInt256: return f(field.template get<UInt256>());
|
2019-12-10 13:40:45 +00:00
|
|
|
case Types::Int64: return f(field.template get<Int64>());
|
2021-05-03 22:46:51 +00:00
|
|
|
case Types::Int128: return f(field.template get<Int128>());
|
|
|
|
case Types::Int256: return f(field.template get<Int256>());
|
|
|
|
case Types::UUID: return f(field.template get<UUID>());
|
2019-12-10 13:40:45 +00:00
|
|
|
case Types::Float64: return f(field.template get<Float64>());
|
|
|
|
case Types::String: return f(field.template get<String>());
|
|
|
|
case Types::Array: return f(field.template get<Array>());
|
|
|
|
case Types::Tuple: return f(field.template get<Tuple>());
|
2020-10-10 06:49:03 +00:00
|
|
|
case Types::Map: return f(field.template get<Map>());
|
2022-01-18 11:52:27 +00:00
|
|
|
case Types::Bool:
|
|
|
|
{
|
|
|
|
bool value = bool(field.template get<UInt64>());
|
|
|
|
return f(value);
|
|
|
|
}
|
2019-12-10 13:40:45 +00:00
|
|
|
case Types::Decimal32: return f(field.template get<DecimalField<Decimal32>>());
|
|
|
|
case Types::Decimal64: return f(field.template get<DecimalField<Decimal64>>());
|
|
|
|
case Types::Decimal128: return f(field.template get<DecimalField<Decimal128>>());
|
2020-08-19 11:52:17 +00:00
|
|
|
case Types::Decimal256: return f(field.template get<DecimalField<Decimal256>>());
|
2019-12-10 13:40:45 +00:00
|
|
|
case Types::AggregateFunctionState: return f(field.template get<AggregateFunctionStateData>());
|
2021-04-18 09:17:02 +00:00
|
|
|
#if !defined(__clang__)
|
2020-08-19 11:52:17 +00:00
|
|
|
#pragma GCC diagnostic pop
|
|
|
|
#endif
|
2019-12-10 13:40:45 +00:00
|
|
|
}
|
|
|
|
|
2021-05-03 22:46:51 +00:00
|
|
|
__builtin_unreachable();
|
2019-12-10 13:40:45 +00:00
|
|
|
}
|
|
|
|
|
2020-07-28 12:37:44 +00:00
|
|
|
String dump() const;
|
|
|
|
static Field restoreFromDump(const std::string_view & dump_);
|
2019-12-10 13:40:45 +00:00
|
|
|
|
2013-01-05 20:03:19 +00:00
|
|
|
private:
|
2017-12-25 04:01:46 +00:00
|
|
|
std::aligned_union_t<DBMS_MIN_FIELD_SIZE - sizeof(Types::Which),
|
2021-05-03 22:46:51 +00:00
|
|
|
Null, UInt64, UInt128, UInt256, Int64, Int128, Int256, UUID, Float64, String, Array, Tuple, Map,
|
2020-08-19 11:52:17 +00:00
|
|
|
DecimalField<Decimal32>, DecimalField<Decimal64>, DecimalField<Decimal128>, DecimalField<Decimal256>,
|
2021-05-03 16:12:28 +00:00
|
|
|
AggregateFunctionStateData
|
2017-12-25 04:01:46 +00:00
|
|
|
> storage;
|
2017-04-01 07:20:54 +00:00
|
|
|
|
|
|
|
Types::Which which;
|
|
|
|
|
|
|
|
|
|
|
|
/// Assuming there was no allocated state or it was deallocated (see destroy).
|
|
|
|
template <typename T>
|
|
|
|
void createConcrete(T && x)
|
|
|
|
{
|
2019-09-27 14:49:03 +00:00
|
|
|
using UnqualifiedType = std::decay_t<T>;
|
|
|
|
|
|
|
|
// In both Field and PODArray, small types may be stored as wider types,
|
|
|
|
// e.g. char is stored as UInt64. Field can return this extended value
|
|
|
|
// with get<StorageType>(). To avoid uninitialized results from get(),
|
|
|
|
// we must initialize the entire wide stored type, and not just the
|
|
|
|
// nominal type.
|
|
|
|
using StorageType = NearestFieldType<UnqualifiedType>;
|
|
|
|
new (&storage) StorageType(std::forward<T>(x));
|
2019-10-17 20:30:33 +00:00
|
|
|
which = TypeToEnum<UnqualifiedType>::value;
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Assuming same types.
|
|
|
|
template <typename T>
|
|
|
|
void assignConcrete(T && x)
|
|
|
|
{
|
2017-12-25 04:01:46 +00:00
|
|
|
using JustT = std::decay_t<T>;
|
2019-09-27 14:49:03 +00:00
|
|
|
assert(which == TypeToEnum<JustT>::value);
|
2018-03-23 16:05:14 +00:00
|
|
|
JustT * MAY_ALIAS ptr = reinterpret_cast<JustT *>(&storage);
|
2017-04-01 07:20:54 +00:00
|
|
|
*ptr = std::forward<T>(x);
|
|
|
|
}
|
|
|
|
|
2020-07-26 21:41:27 +00:00
|
|
|
template <typename CharT>
|
|
|
|
std::enable_if_t<sizeof(CharT) == 1> assignString(const CharT * data, size_t size)
|
|
|
|
{
|
|
|
|
assert(which == Types::String);
|
|
|
|
String * ptr = reinterpret_cast<String *>(&storage);
|
|
|
|
ptr->assign(reinterpret_cast<const char *>(data), size);
|
|
|
|
}
|
|
|
|
|
|
|
|
void assignString(String && str)
|
|
|
|
{
|
|
|
|
assert(which == Types::String);
|
|
|
|
String * ptr = reinterpret_cast<String *>(&storage);
|
|
|
|
ptr->assign(std::move(str));
|
|
|
|
}
|
2017-04-01 07:20:54 +00:00
|
|
|
|
|
|
|
void create(const Field & x)
|
|
|
|
{
|
|
|
|
dispatch([this] (auto & value) { createConcrete(value); }, x);
|
|
|
|
}
|
|
|
|
|
|
|
|
void create(Field && x)
|
|
|
|
{
|
|
|
|
dispatch([this] (auto & value) { createConcrete(std::move(value)); }, x);
|
|
|
|
}
|
|
|
|
|
|
|
|
void assign(const Field & x)
|
|
|
|
{
|
|
|
|
dispatch([this] (auto & value) { assignConcrete(value); }, x);
|
|
|
|
}
|
|
|
|
|
|
|
|
void assign(Field && x)
|
|
|
|
{
|
|
|
|
dispatch([this] (auto & value) { assignConcrete(std::move(value)); }, x);
|
|
|
|
}
|
|
|
|
|
2020-01-03 14:29:31 +00:00
|
|
|
template <typename CharT>
|
|
|
|
std::enable_if_t<sizeof(CharT) == 1> create(const CharT * data, size_t size)
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
2020-01-03 14:29:31 +00:00
|
|
|
new (&storage) String(reinterpret_cast<const char *>(data), size);
|
2017-04-01 07:20:54 +00:00
|
|
|
which = Types::String;
|
|
|
|
}
|
|
|
|
|
2020-07-26 21:41:27 +00:00
|
|
|
void create(String && str)
|
|
|
|
{
|
|
|
|
new (&storage) String(std::move(str));
|
|
|
|
which = Types::String;
|
|
|
|
}
|
|
|
|
|
2017-12-14 03:56:56 +00:00
|
|
|
ALWAYS_INLINE void destroy()
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
|
|
|
switch (which)
|
|
|
|
{
|
|
|
|
case Types::String:
|
|
|
|
destroy<String>();
|
|
|
|
break;
|
|
|
|
case Types::Array:
|
|
|
|
destroy<Array>();
|
|
|
|
break;
|
|
|
|
case Types::Tuple:
|
|
|
|
destroy<Tuple>();
|
|
|
|
break;
|
2020-10-10 06:49:03 +00:00
|
|
|
case Types::Map:
|
|
|
|
destroy<Map>();
|
|
|
|
break;
|
2019-02-11 11:19:56 +00:00
|
|
|
case Types::AggregateFunctionState:
|
|
|
|
destroy<AggregateFunctionStateData>();
|
|
|
|
break;
|
2017-04-01 07:20:54 +00:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
which = Types::Null; /// for exception safety in subsequent calls to destroy and create, when create fails.
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
void destroy()
|
|
|
|
{
|
2018-03-23 16:05:14 +00:00
|
|
|
T * MAY_ALIAS ptr = reinterpret_cast<T*>(&storage);
|
2017-04-01 07:20:54 +00:00
|
|
|
ptr->~T();
|
|
|
|
}
|
2013-01-05 20:03:19 +00:00
|
|
|
};
|
|
|
|
|
2016-01-14 01:43:14 +00:00
|
|
|
#undef DBMS_MIN_FIELD_SIZE
|
2015-10-12 07:05:54 +00:00
|
|
|
|
2014-05-12 00:45:50 +00:00
|
|
|
|
2021-05-21 01:17:18 +00:00
|
|
|
using Row = std::vector<Field>;
|
|
|
|
|
|
|
|
|
2021-08-27 14:09:15 +00:00
|
|
|
template <> struct Field::TypeToEnum<Null> { static const Types::Which value = Types::Null; };
|
2017-05-11 19:48:46 +00:00
|
|
|
template <> struct Field::TypeToEnum<UInt64> { static const Types::Which value = Types::UInt64; };
|
2017-07-06 14:42:27 +00:00
|
|
|
template <> struct Field::TypeToEnum<UInt128> { static const Types::Which value = Types::UInt128; };
|
2021-05-03 16:12:28 +00:00
|
|
|
template <> struct Field::TypeToEnum<UInt256> { static const Types::Which value = Types::UInt256; };
|
2017-05-11 19:48:46 +00:00
|
|
|
template <> struct Field::TypeToEnum<Int64> { static const Types::Which value = Types::Int64; };
|
2018-07-20 19:05:07 +00:00
|
|
|
template <> struct Field::TypeToEnum<Int128> { static const Types::Which value = Types::Int128; };
|
2021-05-03 22:46:51 +00:00
|
|
|
template <> struct Field::TypeToEnum<Int256> { static const Types::Which value = Types::Int256; };
|
|
|
|
template <> struct Field::TypeToEnum<UUID> { static const Types::Which value = Types::UUID; };
|
2017-05-11 19:48:46 +00:00
|
|
|
template <> struct Field::TypeToEnum<Float64> { static const Types::Which value = Types::Float64; };
|
|
|
|
template <> struct Field::TypeToEnum<String> { static const Types::Which value = Types::String; };
|
|
|
|
template <> struct Field::TypeToEnum<Array> { static const Types::Which value = Types::Array; };
|
|
|
|
template <> struct Field::TypeToEnum<Tuple> { static const Types::Which value = Types::Tuple; };
|
2020-10-10 06:49:03 +00:00
|
|
|
template <> struct Field::TypeToEnum<Map> { static const Types::Which value = Types::Map; };
|
2018-08-23 14:03:37 +00:00
|
|
|
template <> struct Field::TypeToEnum<DecimalField<Decimal32>>{ static const Types::Which value = Types::Decimal32; };
|
|
|
|
template <> struct Field::TypeToEnum<DecimalField<Decimal64>>{ static const Types::Which value = Types::Decimal64; };
|
|
|
|
template <> struct Field::TypeToEnum<DecimalField<Decimal128>>{ static const Types::Which value = Types::Decimal128; };
|
2020-08-19 11:52:17 +00:00
|
|
|
template <> struct Field::TypeToEnum<DecimalField<Decimal256>>{ static const Types::Which value = Types::Decimal256; };
|
2020-11-12 20:23:26 +00:00
|
|
|
template <> struct Field::TypeToEnum<DecimalField<DateTime64>>{ static const Types::Which value = Types::Decimal64; };
|
2019-02-11 11:19:56 +00:00
|
|
|
template <> struct Field::TypeToEnum<AggregateFunctionStateData>{ static const Types::Which value = Types::AggregateFunctionState; };
|
2022-01-18 11:52:27 +00:00
|
|
|
template <> struct Field::TypeToEnum<bool>{ static const Types::Which value = Types::Bool; };
|
2013-01-05 20:03:19 +00:00
|
|
|
|
2017-05-11 19:48:46 +00:00
|
|
|
template <> struct Field::EnumToType<Field::Types::Null> { using Type = Null; };
|
|
|
|
template <> struct Field::EnumToType<Field::Types::UInt64> { using Type = UInt64; };
|
2017-07-06 14:42:27 +00:00
|
|
|
template <> struct Field::EnumToType<Field::Types::UInt128> { using Type = UInt128; };
|
2021-05-03 16:12:28 +00:00
|
|
|
template <> struct Field::EnumToType<Field::Types::UInt256> { using Type = UInt256; };
|
2017-05-11 19:48:46 +00:00
|
|
|
template <> struct Field::EnumToType<Field::Types::Int64> { using Type = Int64; };
|
2018-07-20 19:05:07 +00:00
|
|
|
template <> struct Field::EnumToType<Field::Types::Int128> { using Type = Int128; };
|
2021-05-03 16:12:28 +00:00
|
|
|
template <> struct Field::EnumToType<Field::Types::Int256> { using Type = Int256; };
|
2021-05-03 22:46:51 +00:00
|
|
|
template <> struct Field::EnumToType<Field::Types::UUID> { using Type = UUID; };
|
2017-05-11 19:48:46 +00:00
|
|
|
template <> struct Field::EnumToType<Field::Types::Float64> { using Type = Float64; };
|
|
|
|
template <> struct Field::EnumToType<Field::Types::String> { using Type = String; };
|
|
|
|
template <> struct Field::EnumToType<Field::Types::Array> { using Type = Array; };
|
|
|
|
template <> struct Field::EnumToType<Field::Types::Tuple> { using Type = Tuple; };
|
2020-10-10 06:49:03 +00:00
|
|
|
template <> struct Field::EnumToType<Field::Types::Map> { using Type = Map; };
|
2018-08-23 14:03:37 +00:00
|
|
|
template <> struct Field::EnumToType<Field::Types::Decimal32> { using Type = DecimalField<Decimal32>; };
|
|
|
|
template <> struct Field::EnumToType<Field::Types::Decimal64> { using Type = DecimalField<Decimal64>; };
|
|
|
|
template <> struct Field::EnumToType<Field::Types::Decimal128> { using Type = DecimalField<Decimal128>; };
|
2020-08-19 11:52:17 +00:00
|
|
|
template <> struct Field::EnumToType<Field::Types::Decimal256> { using Type = DecimalField<Decimal256>; };
|
2019-02-11 11:19:56 +00:00
|
|
|
template <> struct Field::EnumToType<Field::Types::AggregateFunctionState> { using Type = DecimalField<AggregateFunctionStateData>; };
|
2022-01-18 11:52:27 +00:00
|
|
|
template <> struct Field::EnumToType<Field::Types::Bool> { using Type = UInt64; };
|
2013-01-05 20:03:19 +00:00
|
|
|
|
2021-05-03 22:46:51 +00:00
|
|
|
inline constexpr bool isInt64OrUInt64FieldType(Field::Types::Which t)
|
2019-12-17 20:48:33 +00:00
|
|
|
{
|
|
|
|
return t == Field::Types::Int64
|
|
|
|
|| t == Field::Types::UInt64;
|
|
|
|
}
|
|
|
|
|
2022-01-18 11:52:27 +00:00
|
|
|
inline constexpr bool isInt64OrUInt64orBoolFieldType(Field::Types::Which t)
|
|
|
|
{
|
|
|
|
return t == Field::Types::Int64
|
|
|
|
|| t == Field::Types::UInt64
|
|
|
|
|| t == Field::Types::Bool;
|
|
|
|
}
|
|
|
|
|
2019-12-17 20:48:33 +00:00
|
|
|
// Field value getter with type checking in debug builds.
|
2019-12-10 13:40:45 +00:00
|
|
|
template <typename T>
|
2021-03-22 20:23:44 +00:00
|
|
|
NearestFieldType<std::decay_t<T>> & Field::get()
|
2019-12-10 13:40:45 +00:00
|
|
|
{
|
2021-03-22 20:23:44 +00:00
|
|
|
// Before storing the value in the Field, we static_cast it to the field
|
|
|
|
// storage type, so here we return the value of storage type as well.
|
|
|
|
// Otherwise, it is easy to make a mistake of reinterpret_casting the stored
|
|
|
|
// value to a different and incompatible type.
|
|
|
|
// For example, a Float32 value is stored as Float64, and it is incorrect to
|
|
|
|
// return a reference to this value as Float32.
|
|
|
|
using StoredType = NearestFieldType<std::decay_t<T>>;
|
2019-12-17 20:48:33 +00:00
|
|
|
|
|
|
|
#ifndef NDEBUG
|
|
|
|
// Disregard signedness when converting between int64 types.
|
2021-03-22 20:23:44 +00:00
|
|
|
constexpr Field::Types::Which target = TypeToEnum<StoredType>::value;
|
2020-11-02 11:39:27 +00:00
|
|
|
if (target != which
|
2022-01-18 11:52:27 +00:00
|
|
|
&& (!isInt64OrUInt64orBoolFieldType(target) || !isInt64OrUInt64orBoolFieldType(which)))
|
2021-09-06 15:59:46 +00:00
|
|
|
throw Exception(ErrorCodes::LOGICAL_ERROR,
|
2021-09-06 14:24:03 +00:00
|
|
|
"Invalid Field get from type {} to type {}", which, target);
|
2019-12-17 20:48:33 +00:00
|
|
|
#endif
|
|
|
|
|
2021-03-22 20:23:44 +00:00
|
|
|
StoredType * MAY_ALIAS ptr = reinterpret_cast<StoredType *>(&storage);
|
|
|
|
|
2019-12-10 13:40:45 +00:00
|
|
|
return *ptr;
|
|
|
|
}
|
|
|
|
|
2021-03-22 20:23:44 +00:00
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
auto & Field::safeGet()
|
|
|
|
{
|
|
|
|
const Types::Which requested = TypeToEnum<NearestFieldType<std::decay_t<T>>>::value;
|
2021-09-06 14:24:03 +00:00
|
|
|
|
2021-03-22 20:23:44 +00:00
|
|
|
if (which != requested)
|
2021-09-06 15:59:46 +00:00
|
|
|
throw Exception(ErrorCodes::BAD_GET,
|
2021-09-06 14:24:03 +00:00
|
|
|
"Bad get: has {}, requested {}", getTypeName(), requested);
|
|
|
|
|
2021-03-22 20:23:44 +00:00
|
|
|
return get<T>();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-12-10 13:40:45 +00:00
|
|
|
template <typename T>
|
|
|
|
T & Field::reinterpret()
|
|
|
|
{
|
2021-12-01 13:14:28 +00:00
|
|
|
assert(which != Types::String); // See specialization for char
|
2019-12-10 13:40:45 +00:00
|
|
|
using ValueType = std::decay_t<T>;
|
|
|
|
ValueType * MAY_ALIAS ptr = reinterpret_cast<ValueType *>(&storage);
|
|
|
|
return *ptr;
|
|
|
|
}
|
2013-01-05 20:03:19 +00:00
|
|
|
|
2021-12-01 13:14:28 +00:00
|
|
|
// Specialize reinterpreting to char (used in ColumnUnique) to make sure Strings are reinterpreted correctly
|
|
|
|
// inline to avoid multiple definitions
|
|
|
|
template <>
|
|
|
|
inline char & Field::reinterpret<char>()
|
|
|
|
{
|
|
|
|
if (which == Types::String)
|
|
|
|
{
|
|
|
|
// For String we want to return a pointer to the data, not the start of the class
|
|
|
|
// as the layout of std::string depends on the STD version and options
|
2021-12-24 00:26:31 +00:00
|
|
|
char * ptr = reinterpret_cast<String *>(&storage)->data();
|
2021-12-01 13:14:28 +00:00
|
|
|
return *ptr;
|
|
|
|
}
|
2021-12-23 10:56:07 +00:00
|
|
|
return *reinterpret_cast<char *>(&storage);
|
2021-12-01 13:14:28 +00:00
|
|
|
}
|
|
|
|
|
2013-01-05 20:03:19 +00:00
|
|
|
template <typename T>
|
|
|
|
T get(const Field & field)
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
return field.template get<T>();
|
2010-03-01 16:59:51 +00:00
|
|
|
}
|
|
|
|
|
2013-01-05 20:03:19 +00:00
|
|
|
template <typename T>
|
|
|
|
T get(Field & field)
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
return field.template get<T>();
|
2013-01-05 20:03:19 +00:00
|
|
|
}
|
2010-03-01 16:59:51 +00:00
|
|
|
|
2013-01-05 20:03:19 +00:00
|
|
|
template <typename T>
|
|
|
|
T safeGet(const Field & field)
|
2010-03-01 16:59:51 +00:00
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
return field.template safeGet<T>();
|
2013-01-05 20:03:19 +00:00
|
|
|
}
|
2010-03-01 16:59:51 +00:00
|
|
|
|
2013-01-05 20:03:19 +00:00
|
|
|
template <typename T>
|
|
|
|
T safeGet(Field & field)
|
2010-03-01 16:59:51 +00:00
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
return field.template safeGet<T>();
|
2013-01-05 20:03:19 +00:00
|
|
|
}
|
|
|
|
|
2018-10-22 08:54:54 +00:00
|
|
|
template <typename T>
|
2021-08-23 05:33:16 +00:00
|
|
|
Field::Field(T && rhs, enable_if_not_field_or_bool_or_stringlike_t<T>) //-V730
|
2018-10-22 08:54:54 +00:00
|
|
|
{
|
2019-09-27 13:44:33 +00:00
|
|
|
auto && val = castToNearestFieldType(std::forward<T>(rhs));
|
2018-10-22 08:54:54 +00:00
|
|
|
createConcrete(std::forward<decltype(val)>(val));
|
|
|
|
}
|
2013-10-04 20:15:42 +00:00
|
|
|
|
|
|
|
template <typename T>
|
2021-08-23 05:33:16 +00:00
|
|
|
Field::enable_if_not_field_or_bool_or_stringlike_t<T, Field> &
|
2020-07-26 21:41:27 +00:00
|
|
|
Field::operator=(T && rhs)
|
2013-10-04 20:15:42 +00:00
|
|
|
{
|
2019-09-27 13:44:33 +00:00
|
|
|
auto && val = castToNearestFieldType(std::forward<T>(rhs));
|
2018-10-22 08:54:54 +00:00
|
|
|
using U = decltype(val);
|
|
|
|
if (which != TypeToEnum<std::decay_t<U>>::value)
|
|
|
|
{
|
|
|
|
destroy();
|
|
|
|
createConcrete(std::forward<U>(val));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
assignConcrete(std::forward<U>(val));
|
2020-07-26 21:41:27 +00:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline Field & Field::operator=(const std::string_view & str)
|
|
|
|
{
|
|
|
|
if (which != Types::String)
|
|
|
|
{
|
|
|
|
destroy();
|
|
|
|
create(str.data(), str.size());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
assignString(str.data(), str.size());
|
2018-10-22 08:54:54 +00:00
|
|
|
return *this;
|
2013-10-04 20:15:42 +00:00
|
|
|
}
|
|
|
|
|
2020-07-26 21:41:27 +00:00
|
|
|
inline Field & Field::operator=(String && str)
|
|
|
|
{
|
|
|
|
if (which != Types::String)
|
|
|
|
{
|
|
|
|
destroy();
|
|
|
|
create(std::move(str));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
assignString(std::move(str));
|
|
|
|
return *this;
|
|
|
|
}
|
2012-09-05 19:51:09 +00:00
|
|
|
|
2017-01-21 04:24:28 +00:00
|
|
|
class ReadBuffer;
|
|
|
|
class WriteBuffer;
|
2015-10-12 07:05:54 +00:00
|
|
|
|
2017-04-30 13:50:16 +00:00
|
|
|
/// It is assumed that all elements of the array have the same type.
|
2017-01-21 04:24:28 +00:00
|
|
|
void readBinary(Array & x, ReadBuffer & buf);
|
2012-09-05 19:51:09 +00:00
|
|
|
|
2019-07-08 00:16:39 +00:00
|
|
|
[[noreturn]] inline void readText(Array &, ReadBuffer &) { throw Exception("Cannot read Array.", ErrorCodes::NOT_IMPLEMENTED); }
|
|
|
|
[[noreturn]] inline void readQuoted(Array &, ReadBuffer &) { throw Exception("Cannot read Array.", ErrorCodes::NOT_IMPLEMENTED); }
|
2012-09-05 19:51:09 +00:00
|
|
|
|
2017-04-30 13:50:16 +00:00
|
|
|
/// It is assumed that all elements of the array have the same type.
|
2019-06-18 12:54:27 +00:00
|
|
|
/// Also write size and type into buf. UInt64 and Int64 is written in variadic size form
|
2017-01-21 04:24:28 +00:00
|
|
|
void writeBinary(const Array & x, WriteBuffer & buf);
|
2014-08-09 22:36:07 +00:00
|
|
|
|
2017-01-21 04:24:28 +00:00
|
|
|
void writeText(const Array & x, WriteBuffer & buf);
|
2014-08-09 22:36:07 +00:00
|
|
|
|
2019-07-08 00:16:39 +00:00
|
|
|
[[noreturn]] inline void writeQuoted(const Array &, WriteBuffer &) { throw Exception("Cannot write Array quoted.", ErrorCodes::NOT_IMPLEMENTED); }
|
2012-09-05 19:51:09 +00:00
|
|
|
|
2017-01-21 04:24:28 +00:00
|
|
|
void readBinary(Tuple & x, ReadBuffer & buf);
|
2014-08-09 22:36:07 +00:00
|
|
|
|
2019-07-08 00:16:39 +00:00
|
|
|
[[noreturn]] inline void readText(Tuple &, ReadBuffer &) { throw Exception("Cannot read Tuple.", ErrorCodes::NOT_IMPLEMENTED); }
|
|
|
|
[[noreturn]] inline void readQuoted(Tuple &, ReadBuffer &) { throw Exception("Cannot read Tuple.", ErrorCodes::NOT_IMPLEMENTED); }
|
2015-12-24 14:31:41 +00:00
|
|
|
|
2017-01-21 04:24:28 +00:00
|
|
|
void writeBinary(const Tuple & x, WriteBuffer & buf);
|
2015-12-24 14:31:41 +00:00
|
|
|
|
2017-01-21 04:24:28 +00:00
|
|
|
void writeText(const Tuple & x, WriteBuffer & buf);
|
2015-12-24 14:31:41 +00:00
|
|
|
|
2020-10-10 06:49:03 +00:00
|
|
|
void readBinary(Map & x, ReadBuffer & buf);
|
|
|
|
[[noreturn]] inline void readText(Map &, ReadBuffer &) { throw Exception("Cannot read Map.", ErrorCodes::NOT_IMPLEMENTED); }
|
|
|
|
[[noreturn]] inline void readQuoted(Map &, ReadBuffer &) { throw Exception("Cannot read Map.", ErrorCodes::NOT_IMPLEMENTED); }
|
|
|
|
void writeBinary(const Map & x, WriteBuffer & buf);
|
|
|
|
void writeText(const Map & x, WriteBuffer & buf);
|
|
|
|
[[noreturn]] inline void writeQuoted(const Map &, WriteBuffer &) { throw Exception("Cannot write Map quoted.", ErrorCodes::NOT_IMPLEMENTED); }
|
2020-08-05 02:21:33 +00:00
|
|
|
|
|
|
|
__attribute__ ((noreturn)) inline void writeText(const AggregateFunctionStateData &, WriteBuffer &)
|
|
|
|
{
|
|
|
|
// This probably doesn't make any sense, but we have to have it for
|
|
|
|
// completeness, so that we can use toString(field_value) in field visitors.
|
|
|
|
throw Exception(ErrorCodes::LOGICAL_ERROR, "Cannot convert a Field of type AggregateFunctionStateData to human-readable text");
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
2021-08-16 08:03:23 +00:00
|
|
|
inline void writeText(const DecimalField<T> & value, WriteBuffer & buf, bool trailing_zeros = false)
|
2020-08-05 02:21:33 +00:00
|
|
|
{
|
2021-08-16 08:03:23 +00:00
|
|
|
writeText(value.getValue(), value.getScale(), buf, trailing_zeros);
|
2020-08-05 02:21:33 +00:00
|
|
|
}
|
|
|
|
|
2020-07-28 12:37:44 +00:00
|
|
|
template <typename T>
|
|
|
|
void readQuoted(DecimalField<T> & x, ReadBuffer & buf);
|
|
|
|
|
2019-10-18 15:57:05 +00:00
|
|
|
void writeFieldText(const Field & x, WriteBuffer & buf);
|
|
|
|
|
2019-07-08 00:16:39 +00:00
|
|
|
[[noreturn]] inline void writeQuoted(const Tuple &, WriteBuffer &) { throw Exception("Cannot write Tuple quoted.", ErrorCodes::NOT_IMPLEMENTED); }
|
2020-08-05 02:21:33 +00:00
|
|
|
|
2020-08-05 15:45:44 +00:00
|
|
|
String toString(const Field & x);
|
2020-08-05 02:21:33 +00:00
|
|
|
|
2015-12-24 14:31:41 +00:00
|
|
|
}
|
2021-03-18 23:05:43 +00:00
|
|
|
|
|
|
|
template <>
|
|
|
|
struct fmt::formatter<DB::Field>
|
|
|
|
{
|
|
|
|
constexpr auto parse(format_parse_context & ctx)
|
|
|
|
{
|
|
|
|
auto it = ctx.begin();
|
|
|
|
auto end = ctx.end();
|
|
|
|
|
|
|
|
/// Only support {}.
|
|
|
|
if (it != end && *it != '}')
|
2021-05-03 22:46:51 +00:00
|
|
|
throw format_error("Invalid format");
|
2021-03-18 23:05:43 +00:00
|
|
|
|
|
|
|
return it;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename FormatContext>
|
|
|
|
auto format(const DB::Field & x, FormatContext & ctx)
|
|
|
|
{
|
|
|
|
return format_to(ctx.out(), "{}", toString(x));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|