mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-25 09:02:00 +00:00
Merge pull request #28659 from myrrc/improvement/tostring_to_magic_enum
Improving CH type system with concepts
This commit is contained in:
commit
ea13a8b562
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -246,3 +246,6 @@
|
|||||||
[submodule "contrib/bzip2"]
|
[submodule "contrib/bzip2"]
|
||||||
path = contrib/bzip2
|
path = contrib/bzip2
|
||||||
url = https://github.com/ClickHouse-Extras/bzip2.git
|
url = https://github.com/ClickHouse-Extras/bzip2.git
|
||||||
|
[submodule "contrib/magic_enum"]
|
||||||
|
path = contrib/magic_enum
|
||||||
|
url = https://github.com/Neargye/magic_enum
|
||||||
|
@ -85,6 +85,7 @@ target_link_libraries (common
|
|||||||
replxx
|
replxx
|
||||||
cctz
|
cctz
|
||||||
fmt
|
fmt
|
||||||
|
magic_enum
|
||||||
)
|
)
|
||||||
|
|
||||||
if (ENABLE_TESTS)
|
if (ENABLE_TESTS)
|
||||||
|
157
base/common/Decimal.h
Normal file
157
base/common/Decimal.h
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "common/extended_types.h"
|
||||||
|
|
||||||
|
#if !defined(NO_SANITIZE_UNDEFINED)
|
||||||
|
#if defined(__clang__)
|
||||||
|
#define NO_SANITIZE_UNDEFINED __attribute__((__no_sanitize__("undefined")))
|
||||||
|
#else
|
||||||
|
#define NO_SANITIZE_UNDEFINED
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
template <class> struct Decimal;
|
||||||
|
class DateTime64;
|
||||||
|
|
||||||
|
using Decimal32 = Decimal<Int32>;
|
||||||
|
using Decimal64 = Decimal<Int64>;
|
||||||
|
using Decimal128 = Decimal<Int128>;
|
||||||
|
using Decimal256 = Decimal<Int256>;
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
concept is_decimal =
|
||||||
|
std::is_same_v<T, Decimal32>
|
||||||
|
|| std::is_same_v<T, Decimal64>
|
||||||
|
|| std::is_same_v<T, Decimal128>
|
||||||
|
|| std::is_same_v<T, Decimal256>
|
||||||
|
|| std::is_same_v<T, DateTime64>;
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
concept is_over_big_int =
|
||||||
|
std::is_same_v<T, Int128>
|
||||||
|
|| std::is_same_v<T, UInt128>
|
||||||
|
|| std::is_same_v<T, Int256>
|
||||||
|
|| std::is_same_v<T, UInt256>
|
||||||
|
|| std::is_same_v<T, Decimal128>
|
||||||
|
|| std::is_same_v<T, Decimal256>;
|
||||||
|
|
||||||
|
template <class T> struct NativeTypeT { using Type = T; };
|
||||||
|
template <is_decimal T> struct NativeTypeT<T> { using Type = typename T::NativeType; };
|
||||||
|
template <class T> using NativeType = typename NativeTypeT<T>::Type;
|
||||||
|
|
||||||
|
/// 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
|
||||||
|
{
|
||||||
|
using NativeType = T;
|
||||||
|
|
||||||
|
constexpr Decimal() = default;
|
||||||
|
constexpr Decimal(Decimal<T> &&) = default;
|
||||||
|
constexpr Decimal(const Decimal<T> &) = default;
|
||||||
|
|
||||||
|
constexpr Decimal(const T & value_): value(value_) {}
|
||||||
|
|
||||||
|
template <typename U>
|
||||||
|
constexpr Decimal(const Decimal<U> & x): value(x.value) {}
|
||||||
|
|
||||||
|
constexpr Decimal<T> & operator = (Decimal<T> &&) = default;
|
||||||
|
constexpr Decimal<T> & operator = (const Decimal<T> &) = default;
|
||||||
|
|
||||||
|
constexpr operator T () const { return value; }
|
||||||
|
|
||||||
|
template <typename U>
|
||||||
|
constexpr U convertTo() const
|
||||||
|
{
|
||||||
|
if constexpr (is_decimal<U>)
|
||||||
|
return convertTo<typename U::NativeType>();
|
||||||
|
else
|
||||||
|
return static_cast<U>(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; }
|
||||||
|
|
||||||
|
template <typename U> const Decimal<T> & operator += (const Decimal<U> & x) { value += x.value; return *this; }
|
||||||
|
template <typename U> const Decimal<T> & operator -= (const Decimal<U> & x) { value -= x.value; return *this; }
|
||||||
|
template <typename U> const Decimal<T> & operator *= (const Decimal<U> & x) { value *= x.value; return *this; }
|
||||||
|
template <typename U> const Decimal<T> & operator /= (const Decimal<U> & x) { value /= x.value; return *this; }
|
||||||
|
template <typename U> const Decimal<T> & operator %= (const Decimal<U> & x) { value %= x.value; return *this; }
|
||||||
|
|
||||||
|
/// This is to avoid UB for sumWithOverflow()
|
||||||
|
void NO_SANITIZE_UNDEFINED addOverflow(const T & x) { value += x; }
|
||||||
|
|
||||||
|
T value;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T> inline bool operator< (const Decimal<T> & x, const Decimal<T> & y) { return x.value < y.value; }
|
||||||
|
template <typename T> inline bool operator> (const Decimal<T> & x, const Decimal<T> & y) { return x.value > y.value; }
|
||||||
|
template <typename T> inline bool operator<= (const Decimal<T> & x, const Decimal<T> & y) { return x.value <= y.value; }
|
||||||
|
template <typename T> inline bool operator>= (const Decimal<T> & x, const Decimal<T> & y) { return x.value >= y.value; }
|
||||||
|
template <typename T> inline bool operator== (const Decimal<T> & x, const Decimal<T> & y) { return x.value == y.value; }
|
||||||
|
template <typename T> inline bool operator!= (const Decimal<T> & x, const Decimal<T> & y) { return x.value != y.value; }
|
||||||
|
|
||||||
|
template <typename T> inline Decimal<T> operator+ (const Decimal<T> & x, const Decimal<T> & y) { return x.value + y.value; }
|
||||||
|
template <typename T> inline Decimal<T> operator- (const Decimal<T> & x, const Decimal<T> & y) { return x.value - y.value; }
|
||||||
|
template <typename T> inline Decimal<T> operator* (const Decimal<T> & x, const Decimal<T> & y) { return x.value * y.value; }
|
||||||
|
template <typename T> inline Decimal<T> operator/ (const Decimal<T> & x, const Decimal<T> & y) { return x.value / y.value; }
|
||||||
|
template <typename T> inline Decimal<T> operator- (const Decimal<T> & x) { return -x.value; }
|
||||||
|
|
||||||
|
/// Distinguishable type to allow function resolution/deduction based on value type,
|
||||||
|
/// but also relatively easy to convert to/from Decimal64.
|
||||||
|
class DateTime64 : public Decimal64
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using Base = Decimal64;
|
||||||
|
using Base::Base;
|
||||||
|
using NativeType = Base::NativeType;
|
||||||
|
|
||||||
|
constexpr DateTime64(const Base & v): Base(v) {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr DB::UInt64 max_uint_mask = std::numeric_limits<DB::UInt64>::max();
|
||||||
|
|
||||||
|
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 & max_uint_mask);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct hash<DB::DateTime64>
|
||||||
|
{
|
||||||
|
size_t operator()(const DB::DateTime64 & x) const
|
||||||
|
{
|
||||||
|
return std::hash<DB::DateTime64::NativeType>()(x);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct hash<DB::Decimal256>
|
||||||
|
{
|
||||||
|
size_t operator()(const DB::Decimal256 & x) const
|
||||||
|
{
|
||||||
|
// FIXME temp solution
|
||||||
|
return std::hash<DB::Int64>()(static_cast<DB::Int64>(x.value >> 64 & max_uint_mask))
|
||||||
|
^ std::hash<DB::Int64>()(static_cast<DB::Int64>(x.value & max_uint_mask));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
38
base/common/EnumReflection.h
Normal file
38
base/common/EnumReflection.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <magic_enum.hpp>
|
||||||
|
#include <fmt/format.h>
|
||||||
|
|
||||||
|
template <class T> concept is_enum = std::is_enum_v<T>;
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
template <is_enum E, class F, size_t ...I>
|
||||||
|
constexpr void static_for(F && f, std::index_sequence<I...>)
|
||||||
|
{
|
||||||
|
(std::forward<F>(f)(std::integral_constant<E, magic_enum::enum_value<E>(I)>()) , ...);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterate over enum values in compile-time (compile-time switch/case, loop unrolling).
|
||||||
|
*
|
||||||
|
* @example static_for<E>([](auto enum_value) { return template_func<enum_value>(); }
|
||||||
|
* ^ enum_value can be used as a template parameter
|
||||||
|
*/
|
||||||
|
template <is_enum E, class F>
|
||||||
|
constexpr void static_for(F && f)
|
||||||
|
{
|
||||||
|
constexpr size_t count = magic_enum::enum_count<E>();
|
||||||
|
detail::static_for<E>(std::forward<F>(f), std::make_index_sequence<count>());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Enable printing enum values as strings via fmt + magic_enum
|
||||||
|
template <is_enum T>
|
||||||
|
struct fmt::formatter<T> : fmt::formatter<std::string_view>
|
||||||
|
{
|
||||||
|
constexpr auto format(T value, auto& format_context)
|
||||||
|
{
|
||||||
|
return formatter<string_view>::format(magic_enum::enum_name(value), format_context);
|
||||||
|
}
|
||||||
|
};
|
@ -41,22 +41,14 @@ template <> struct is_unsigned<UInt256> { static constexpr bool value = true; };
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
inline constexpr bool is_unsigned_v = is_unsigned<T>::value;
|
inline constexpr bool is_unsigned_v = is_unsigned<T>::value;
|
||||||
|
|
||||||
|
template <class T> concept is_integer =
|
||||||
|
std::is_integral_v<T>
|
||||||
|
|| std::is_same_v<T, Int128>
|
||||||
|
|| std::is_same_v<T, UInt128>
|
||||||
|
|| std::is_same_v<T, Int256>
|
||||||
|
|| std::is_same_v<T, UInt256>;
|
||||||
|
|
||||||
/// TODO: is_integral includes char, char8_t and wchar_t.
|
template <class T> concept is_floating_point = std::is_floating_point_v<T>;
|
||||||
template <typename T>
|
|
||||||
struct is_integer
|
|
||||||
{
|
|
||||||
static constexpr bool value = std::is_integral_v<T>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <> struct is_integer<Int128> { static constexpr bool value = true; };
|
|
||||||
template <> struct is_integer<UInt128> { static constexpr bool value = true; };
|
|
||||||
template <> struct is_integer<Int256> { static constexpr bool value = true; };
|
|
||||||
template <> struct is_integer<UInt256> { static constexpr bool value = true; };
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
inline constexpr bool is_integer_v = is_integer<T>::value;
|
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct is_arithmetic
|
struct is_arithmetic
|
||||||
|
@ -36,18 +36,7 @@
|
|||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
|
template <char ...chars> constexpr bool is_in(char x) { return ((x == chars) || ...); }
|
||||||
template <char s0>
|
|
||||||
inline bool is_in(char x)
|
|
||||||
{
|
|
||||||
return x == s0;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <char s0, char s1, char... tail>
|
|
||||||
inline bool is_in(char x)
|
|
||||||
{
|
|
||||||
return x == s0 || is_in<s1, tail...>(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(__SSE2__)
|
#if defined(__SSE2__)
|
||||||
template <char s0>
|
template <char s0>
|
||||||
@ -67,16 +56,10 @@ inline __m128i mm_is_in(__m128i bytes)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <bool positive>
|
template <bool positive>
|
||||||
bool maybe_negate(bool x)
|
constexpr bool maybe_negate(bool x) { return x == positive; }
|
||||||
{
|
|
||||||
if constexpr (positive)
|
|
||||||
return x;
|
|
||||||
else
|
|
||||||
return !x;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <bool positive>
|
template <bool positive>
|
||||||
uint16_t maybe_negate(uint16_t x)
|
constexpr uint16_t maybe_negate(uint16_t x)
|
||||||
{
|
{
|
||||||
if constexpr (positive)
|
if constexpr (positive)
|
||||||
return x;
|
return x;
|
||||||
@ -149,12 +132,13 @@ template <bool positive, ReturnMode return_mode, size_t num_chars,
|
|||||||
char c05 = 0, char c06 = 0, char c07 = 0, char c08 = 0,
|
char c05 = 0, char c06 = 0, char c07 = 0, char c08 = 0,
|
||||||
char c09 = 0, char c10 = 0, char c11 = 0, char c12 = 0,
|
char c09 = 0, char c10 = 0, char c11 = 0, char c12 = 0,
|
||||||
char c13 = 0, char c14 = 0, char c15 = 0, char c16 = 0>
|
char c13 = 0, char c14 = 0, char c15 = 0, char c16 = 0>
|
||||||
inline const char * find_first_symbols_sse42_impl(const char * const begin, const char * const end)
|
inline const char * find_first_symbols_sse42(const char * const begin, const char * const end)
|
||||||
{
|
{
|
||||||
const char * pos = begin;
|
const char * pos = begin;
|
||||||
|
|
||||||
#if defined(__SSE4_2__)
|
#if defined(__SSE4_2__)
|
||||||
#define MODE (_SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_LEAST_SIGNIFICANT)
|
constexpr int mode = _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_LEAST_SIGNIFICANT;
|
||||||
|
|
||||||
__m128i set = _mm_setr_epi8(c01, c02, c03, c04, c05, c06, c07, c08, c09, c10, c11, c12, c13, c14, c15, c16);
|
__m128i set = _mm_setr_epi8(c01, c02, c03, c04, c05, c06, c07, c08, c09, c10, c11, c12, c13, c14, c15, c16);
|
||||||
|
|
||||||
for (; pos + 15 < end; pos += 16)
|
for (; pos + 15 < end; pos += 16)
|
||||||
@ -163,16 +147,15 @@ inline const char * find_first_symbols_sse42_impl(const char * const begin, cons
|
|||||||
|
|
||||||
if constexpr (positive)
|
if constexpr (positive)
|
||||||
{
|
{
|
||||||
if (_mm_cmpestrc(set, num_chars, bytes, 16, MODE))
|
if (_mm_cmpestrc(set, num_chars, bytes, 16, mode))
|
||||||
return pos + _mm_cmpestri(set, num_chars, bytes, 16, MODE);
|
return pos + _mm_cmpestri(set, num_chars, bytes, 16, mode);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (_mm_cmpestrc(set, num_chars, bytes, 16, MODE | _SIDD_NEGATIVE_POLARITY))
|
if (_mm_cmpestrc(set, num_chars, bytes, 16, mode | _SIDD_NEGATIVE_POLARITY))
|
||||||
return pos + _mm_cmpestri(set, num_chars, bytes, 16, MODE | _SIDD_NEGATIVE_POLARITY);
|
return pos + _mm_cmpestri(set, num_chars, bytes, 16, mode | _SIDD_NEGATIVE_POLARITY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#undef MODE
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (; pos < end; ++pos)
|
for (; pos < end; ++pos)
|
||||||
@ -197,20 +180,15 @@ inline const char * find_first_symbols_sse42_impl(const char * const begin, cons
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <bool positive, ReturnMode return_mode, char... symbols>
|
|
||||||
inline const char * find_first_symbols_sse42(const char * begin, const char * end)
|
|
||||||
{
|
|
||||||
return find_first_symbols_sse42_impl<positive, return_mode, sizeof...(symbols), symbols...>(begin, end);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// NOTE No SSE 4.2 implementation for find_last_symbols_or_null. Not worth to do.
|
/// NOTE No SSE 4.2 implementation for find_last_symbols_or_null. Not worth to do.
|
||||||
|
|
||||||
template <bool positive, ReturnMode return_mode, char... symbols>
|
template <bool positive, ReturnMode return_mode, char... symbols>
|
||||||
inline const char * find_first_symbols_dispatch(const char * begin, const char * end)
|
inline const char * find_first_symbols_dispatch(const char * begin, const char * end)
|
||||||
|
requires(0 <= sizeof...(symbols) && sizeof...(symbols) <= 16)
|
||||||
{
|
{
|
||||||
#if defined(__SSE4_2__)
|
#if defined(__SSE4_2__)
|
||||||
if (sizeof...(symbols) >= 5)
|
if (sizeof...(symbols) >= 5)
|
||||||
return find_first_symbols_sse42<positive, return_mode, symbols...>(begin, end);
|
return find_first_symbols_sse42<positive, return_mode, sizeof...(symbols), symbols...>(begin, end);
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
return find_first_symbols_sse2<positive, return_mode, symbols...>(begin, end);
|
return find_first_symbols_sse2<positive, return_mode, symbols...>(begin, end);
|
||||||
|
@ -15,15 +15,15 @@ private:
|
|||||||
public:
|
public:
|
||||||
using UnderlyingType = T;
|
using UnderlyingType = T;
|
||||||
template <class Enable = typename std::is_copy_constructible<T>::type>
|
template <class Enable = typename std::is_copy_constructible<T>::type>
|
||||||
explicit StrongTypedef(const T & t_) : t(t_) {}
|
constexpr explicit StrongTypedef(const T & t_) : t(t_) {}
|
||||||
template <class Enable = typename std::is_move_constructible<T>::type>
|
template <class Enable = typename std::is_move_constructible<T>::type>
|
||||||
explicit StrongTypedef(T && t_) : t(std::move(t_)) {}
|
constexpr explicit StrongTypedef(T && t_) : t(std::move(t_)) {}
|
||||||
|
|
||||||
template <class Enable = typename std::is_default_constructible<T>::type>
|
template <class Enable = typename std::is_default_constructible<T>::type>
|
||||||
StrongTypedef(): t() {}
|
constexpr StrongTypedef(): t() {}
|
||||||
|
|
||||||
StrongTypedef(const Self &) = default;
|
constexpr StrongTypedef(const Self &) = default;
|
||||||
StrongTypedef(Self &&) = default;
|
constexpr StrongTypedef(Self &&) = default;
|
||||||
|
|
||||||
Self & operator=(const Self &) = default;
|
Self & operator=(const Self &) = default;
|
||||||
Self & operator=(Self &&) = default;
|
Self & operator=(Self &&) = default;
|
||||||
|
1
contrib/CMakeLists.txt
vendored
1
contrib/CMakeLists.txt
vendored
@ -33,6 +33,7 @@ endif()
|
|||||||
set_property(DIRECTORY PROPERTY EXCLUDE_FROM_ALL 1)
|
set_property(DIRECTORY PROPERTY EXCLUDE_FROM_ALL 1)
|
||||||
|
|
||||||
add_subdirectory (abseil-cpp-cmake)
|
add_subdirectory (abseil-cpp-cmake)
|
||||||
|
add_subdirectory (magic-enum-cmake)
|
||||||
add_subdirectory (boost-cmake)
|
add_subdirectory (boost-cmake)
|
||||||
add_subdirectory (cctz-cmake)
|
add_subdirectory (cctz-cmake)
|
||||||
add_subdirectory (consistent-hashing)
|
add_subdirectory (consistent-hashing)
|
||||||
|
3
contrib/magic-enum-cmake/CMakeLists.txt
Normal file
3
contrib/magic-enum-cmake/CMakeLists.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
set (LIBRARY_DIR "${ClickHouse_SOURCE_DIR}/contrib/magic_enum")
|
||||||
|
add_library (magic_enum INTERFACE)
|
||||||
|
target_include_directories(magic_enum INTERFACE ${LIBRARY_DIR}/include)
|
1
contrib/magic_enum
vendored
Submodule
1
contrib/magic_enum
vendored
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 38f86e4d093cfc9034a140d37de2168e3951bef3
|
@ -159,6 +159,7 @@ function clone_submodules
|
|||||||
cd "$FASTTEST_SOURCE"
|
cd "$FASTTEST_SOURCE"
|
||||||
|
|
||||||
SUBMODULES_TO_UPDATE=(
|
SUBMODULES_TO_UPDATE=(
|
||||||
|
contrib/magic_enum
|
||||||
contrib/abseil-cpp
|
contrib/abseil-cpp
|
||||||
contrib/boost
|
contrib/boost
|
||||||
contrib/zlib-ng
|
contrib/zlib-ng
|
||||||
|
@ -21,11 +21,9 @@
|
|||||||
namespace DB
|
namespace DB
|
||||||
{
|
{
|
||||||
struct Settings;
|
struct Settings;
|
||||||
template <typename T>
|
|
||||||
using DecimalOrVectorCol = std::conditional_t<IsDecimalNumber<T>, ColumnDecimal<T>, ColumnVector<T>>;
|
|
||||||
|
|
||||||
template <typename T> constexpr bool DecimalOrExtendedInt =
|
template <typename T> constexpr bool DecimalOrExtendedInt =
|
||||||
IsDecimalNumber<T>
|
is_decimal<T>
|
||||||
|| std::is_same_v<T, Int128>
|
|| std::is_same_v<T, Int128>
|
||||||
|| std::is_same_v<T, Int256>
|
|| std::is_same_v<T, Int256>
|
||||||
|| std::is_same_v<T, UInt128>
|
|| std::is_same_v<T, UInt128>
|
||||||
@ -44,7 +42,7 @@ struct AvgFraction
|
|||||||
/// Invoked only is either Numerator or Denominator are Decimal.
|
/// Invoked only is either Numerator or Denominator are Decimal.
|
||||||
Float64 NO_SANITIZE_UNDEFINED divideIfAnyDecimal(UInt32 num_scale, UInt32 denom_scale [[maybe_unused]]) const
|
Float64 NO_SANITIZE_UNDEFINED divideIfAnyDecimal(UInt32 num_scale, UInt32 denom_scale [[maybe_unused]]) const
|
||||||
{
|
{
|
||||||
if constexpr (IsDecimalNumber<Numerator> && IsDecimalNumber<Denominator>)
|
if constexpr (is_decimal<Numerator> && is_decimal<Denominator>)
|
||||||
{
|
{
|
||||||
// According to the docs, num(S1) / denom(S2) would have scale S1
|
// According to the docs, num(S1) / denom(S2) would have scale S1
|
||||||
|
|
||||||
@ -60,7 +58,7 @@ struct AvgFraction
|
|||||||
/// Numerator is always casted to Float64 to divide correctly if the denominator is not Float64.
|
/// Numerator is always casted to Float64 to divide correctly if the denominator is not Float64.
|
||||||
Float64 num_converted;
|
Float64 num_converted;
|
||||||
|
|
||||||
if constexpr (IsDecimalNumber<Numerator>)
|
if constexpr (is_decimal<Numerator>)
|
||||||
num_converted = DecimalUtils::convertTo<Float64>(numerator, num_scale);
|
num_converted = DecimalUtils::convertTo<Float64>(numerator, num_scale);
|
||||||
else
|
else
|
||||||
num_converted = static_cast<Float64>(numerator); /// all other types, including extended integral.
|
num_converted = static_cast<Float64>(numerator); /// all other types, including extended integral.
|
||||||
@ -68,7 +66,7 @@ struct AvgFraction
|
|||||||
std::conditional_t<DecimalOrExtendedInt<Denominator>,
|
std::conditional_t<DecimalOrExtendedInt<Denominator>,
|
||||||
Float64, Denominator> denom_converted;
|
Float64, Denominator> denom_converted;
|
||||||
|
|
||||||
if constexpr (IsDecimalNumber<Denominator>)
|
if constexpr (is_decimal<Denominator>)
|
||||||
denom_converted = DecimalUtils::convertTo<Float64>(denominator, denom_scale);
|
denom_converted = DecimalUtils::convertTo<Float64>(denominator, denom_scale);
|
||||||
else if constexpr (DecimalOrExtendedInt<Denominator>)
|
else if constexpr (DecimalOrExtendedInt<Denominator>)
|
||||||
/// no way to divide Float64 and extended integral type without an explicit cast.
|
/// no way to divide Float64 and extended integral type without an explicit cast.
|
||||||
@ -139,7 +137,7 @@ public:
|
|||||||
|
|
||||||
void insertResultInto(AggregateDataPtr __restrict place, IColumn & to, Arena *) const override
|
void insertResultInto(AggregateDataPtr __restrict place, IColumn & to, Arena *) const override
|
||||||
{
|
{
|
||||||
if constexpr (IsDecimalNumber<Numerator> || IsDecimalNumber<Denominator>)
|
if constexpr (is_decimal<Numerator> || is_decimal<Denominator>)
|
||||||
assert_cast<ColumnVector<Float64> &>(to).getData().push_back(
|
assert_cast<ColumnVector<Float64> &>(to).getData().push_back(
|
||||||
this->data(place).divideIfAnyDecimal(num_scale, denom_scale));
|
this->data(place).divideIfAnyDecimal(num_scale, denom_scale));
|
||||||
else
|
else
|
||||||
@ -222,7 +220,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using AvgFieldType = std::conditional_t<IsDecimalNumber<T>,
|
using AvgFieldType = std::conditional_t<is_decimal<T>,
|
||||||
std::conditional_t<std::is_same_v<T, Decimal256>, Decimal256, Decimal128>,
|
std::conditional_t<std::is_same_v<T, Decimal256>, Decimal256, Decimal128>,
|
||||||
NearestFieldType<T>>;
|
NearestFieldType<T>>;
|
||||||
|
|
||||||
@ -239,7 +237,7 @@ public:
|
|||||||
|
|
||||||
void NO_SANITIZE_UNDEFINED add(AggregateDataPtr __restrict place, const IColumn ** columns, size_t row_num, Arena *) const final
|
void NO_SANITIZE_UNDEFINED add(AggregateDataPtr __restrict place, const IColumn ** columns, size_t row_num, Arena *) const final
|
||||||
{
|
{
|
||||||
this->data(place).numerator += static_cast<const DecimalOrVectorCol<T> &>(*columns[0]).getData()[row_num];
|
this->data(place).numerator += static_cast<const ColumnVectorOrDecimal<T> &>(*columns[0]).getData()[row_num];
|
||||||
++this->data(place).denominator;
|
++this->data(place).denominator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ namespace DB
|
|||||||
struct Settings;
|
struct Settings;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using AvgWeightedFieldType = std::conditional_t<IsDecimalNumber<T>,
|
using AvgWeightedFieldType = std::conditional_t<is_decimal<T>,
|
||||||
std::conditional_t<std::is_same_v<T, Decimal256>, Decimal256, Decimal128>,
|
std::conditional_t<std::is_same_v<T, Decimal256>, Decimal256, Decimal128>,
|
||||||
std::conditional_t<DecimalOrExtendedInt<T>,
|
std::conditional_t<DecimalOrExtendedInt<T>,
|
||||||
Float64, // no way to do UInt128 * UInt128, better cast to Float64
|
Float64, // no way to do UInt128 * UInt128, better cast to Float64
|
||||||
@ -34,10 +34,10 @@ public:
|
|||||||
|
|
||||||
void NO_SANITIZE_UNDEFINED add(AggregateDataPtr __restrict place, const IColumn ** columns, size_t row_num, Arena *) const override
|
void NO_SANITIZE_UNDEFINED add(AggregateDataPtr __restrict place, const IColumn ** columns, size_t row_num, Arena *) const override
|
||||||
{
|
{
|
||||||
const auto& weights = static_cast<const DecimalOrVectorCol<Weight> &>(*columns[1]);
|
const auto& weights = static_cast<const ColumnVectorOrDecimal<Weight> &>(*columns[1]);
|
||||||
|
|
||||||
this->data(place).numerator += static_cast<Numerator>(
|
this->data(place).numerator += static_cast<Numerator>(
|
||||||
static_cast<const DecimalOrVectorCol<Value> &>(*columns[0]).getData()[row_num]) *
|
static_cast<const ColumnVectorOrDecimal<Value> &>(*columns[0]).getData()[row_num]) *
|
||||||
static_cast<Numerator>(weights.getData()[row_num]);
|
static_cast<Numerator>(weights.getData()[row_num]);
|
||||||
|
|
||||||
this->data(place).denominator += static_cast<Denominator>(weights.getData()[row_num]);
|
this->data(place).denominator += static_cast<Denominator>(weights.getData()[row_num]);
|
||||||
|
@ -25,14 +25,14 @@ namespace
|
|||||||
template <typename T, typename LimitNumberOfElements>
|
template <typename T, typename LimitNumberOfElements>
|
||||||
struct MovingSum
|
struct MovingSum
|
||||||
{
|
{
|
||||||
using Data = MovingSumData<std::conditional_t<IsDecimalNumber<T>, Decimal128, NearestFieldType<T>>>;
|
using Data = MovingSumData<std::conditional_t<is_decimal<T>, Decimal128, NearestFieldType<T>>>;
|
||||||
using Function = MovingImpl<T, LimitNumberOfElements, Data>;
|
using Function = MovingImpl<T, LimitNumberOfElements, Data>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, typename LimitNumberOfElements>
|
template <typename T, typename LimitNumberOfElements>
|
||||||
struct MovingAvg
|
struct MovingAvg
|
||||||
{
|
{
|
||||||
using Data = MovingAvgData<std::conditional_t<IsDecimalNumber<T>, Decimal128, Float64>>;
|
using Data = MovingAvgData<std::conditional_t<is_decimal<T>, Decimal128, Float64>>;
|
||||||
using Function = MovingImpl<T, LimitNumberOfElements, Data>;
|
using Function = MovingImpl<T, LimitNumberOfElements, Data>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -87,18 +87,10 @@ class MovingImpl final
|
|||||||
public:
|
public:
|
||||||
using ResultT = typename Data::Accumulator;
|
using ResultT = typename Data::Accumulator;
|
||||||
|
|
||||||
using ColumnSource = std::conditional_t<IsDecimalNumber<T>,
|
using ColumnSource = ColumnVectorOrDecimal<T>;
|
||||||
ColumnDecimal<T>,
|
|
||||||
ColumnVector<T>>;
|
|
||||||
|
|
||||||
/// Probably for overflow function in the future.
|
/// Probably for overflow function in the future.
|
||||||
using ColumnResult = std::conditional_t<IsDecimalNumber<ResultT>,
|
using ColumnResult = ColumnVectorOrDecimal<ResultT>;
|
||||||
ColumnDecimal<ResultT>,
|
|
||||||
ColumnVector<ResultT>>;
|
|
||||||
|
|
||||||
using DataTypeResult = std::conditional_t<IsDecimalNumber<ResultT>,
|
|
||||||
DataTypeDecimal<ResultT>,
|
|
||||||
DataTypeNumber<ResultT>>;
|
|
||||||
|
|
||||||
explicit MovingImpl(const DataTypePtr & data_type_, UInt64 window_size_ = std::numeric_limits<UInt64>::max())
|
explicit MovingImpl(const DataTypePtr & data_type_, UInt64 window_size_ = std::numeric_limits<UInt64>::max())
|
||||||
: IAggregateFunctionDataHelper<Data, MovingImpl<T, Tlimit_num_elems, Data>>({data_type_}, {})
|
: IAggregateFunctionDataHelper<Data, MovingImpl<T, Tlimit_num_elems, Data>>({data_type_}, {})
|
||||||
@ -106,14 +98,7 @@ public:
|
|||||||
|
|
||||||
String getName() const override { return Data::name; }
|
String getName() const override { return Data::name; }
|
||||||
|
|
||||||
DataTypePtr getReturnType() const override
|
DataTypePtr getReturnType() const override { return std::make_shared<DataTypeArray>(getReturnTypeElement()); }
|
||||||
{
|
|
||||||
if constexpr (IsDecimalNumber<ResultT>)
|
|
||||||
return std::make_shared<DataTypeArray>(std::make_shared<DataTypeResult>(
|
|
||||||
DataTypeResult::maxPrecision(), getDecimalScale(*this->argument_types.at(0))));
|
|
||||||
else
|
|
||||||
return std::make_shared<DataTypeArray>(std::make_shared<DataTypeResult>());
|
|
||||||
}
|
|
||||||
|
|
||||||
void NO_SANITIZE_UNDEFINED add(AggregateDataPtr __restrict place, const IColumn ** columns, size_t row_num, Arena * arena) const override
|
void NO_SANITIZE_UNDEFINED add(AggregateDataPtr __restrict place, const IColumn ** columns, size_t row_num, Arena * arena) const override
|
||||||
{
|
{
|
||||||
@ -196,6 +181,18 @@ public:
|
|||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
auto getReturnTypeElement() const
|
||||||
|
{
|
||||||
|
if constexpr (!is_decimal<ResultT>)
|
||||||
|
return std::make_shared<DataTypeNumber<ResultT>>();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
using Res = DataTypeDecimal<ResultT>;
|
||||||
|
return std::make_shared<Res>(Res::maxPrecision(), getDecimalScale(*this->argument_types.at(0)));
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#undef AGGREGATE_FUNCTION_MOVING_MAX_ARRAY_SIZE
|
#undef AGGREGATE_FUNCTION_MOVING_MAX_ARRAY_SIZE
|
||||||
|
@ -44,7 +44,7 @@ struct SingleValueDataFixed
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
using Self = SingleValueDataFixed;
|
using Self = SingleValueDataFixed;
|
||||||
using ColVecType = std::conditional_t<IsDecimalNumber<T>, ColumnDecimal<T>, ColumnVector<T>>;
|
using ColVecType = ColumnVectorOrDecimal<T>;
|
||||||
|
|
||||||
bool has_value = false; /// We need to remember if at least one value has been passed. This is necessary for AggregateFunctionIf.
|
bool has_value = false; /// We need to remember if at least one value has been passed. This is necessary for AggregateFunctionIf.
|
||||||
T value;
|
T value;
|
||||||
|
@ -67,10 +67,10 @@ class AggregateFunctionQuantile final : public IAggregateFunctionDataHelper<Data
|
|||||||
AggregateFunctionQuantile<Value, Data, Name, has_second_arg, FloatReturnType, returns_many>>
|
AggregateFunctionQuantile<Value, Data, Name, has_second_arg, FloatReturnType, returns_many>>
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
using ColVecType = std::conditional_t<IsDecimalNumber<Value>, ColumnDecimal<Value>, ColumnVector<Value>>;
|
using ColVecType = ColumnVectorOrDecimal<Value>;
|
||||||
|
|
||||||
static constexpr bool returns_float = !(std::is_same_v<FloatReturnType, void>);
|
static constexpr bool returns_float = !(std::is_same_v<FloatReturnType, void>);
|
||||||
static_assert(!IsDecimalNumber<Value> || !returns_float);
|
static_assert(!is_decimal<Value> || !returns_float);
|
||||||
|
|
||||||
QuantileLevels<Float64> levels;
|
QuantileLevels<Float64> levels;
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ struct StatFuncOneArg
|
|||||||
using Type1 = T;
|
using Type1 = T;
|
||||||
using Type2 = T;
|
using Type2 = T;
|
||||||
using ResultType = std::conditional_t<std::is_same_v<T, Float32>, Float32, Float64>;
|
using ResultType = std::conditional_t<std::is_same_v<T, Float32>, Float32, Float64>;
|
||||||
using Data = std::conditional_t<IsDecimalNumber<T>, VarMomentsDecimal<Decimal128, _level>, VarMoments<ResultType, _level>>;
|
using Data = std::conditional_t<is_decimal<T>, VarMomentsDecimal<Decimal128, _level>, VarMoments<ResultType, _level>>;
|
||||||
|
|
||||||
static constexpr StatisticsFunctionKind kind = _kind;
|
static constexpr StatisticsFunctionKind kind = _kind;
|
||||||
static constexpr UInt32 num_args = 1;
|
static constexpr UInt32 num_args = 1;
|
||||||
@ -75,8 +75,8 @@ class AggregateFunctionVarianceSimple final
|
|||||||
public:
|
public:
|
||||||
using T1 = typename StatFunc::Type1;
|
using T1 = typename StatFunc::Type1;
|
||||||
using T2 = typename StatFunc::Type2;
|
using T2 = typename StatFunc::Type2;
|
||||||
using ColVecT1 = std::conditional_t<IsDecimalNumber<T1>, ColumnDecimal<T1>, ColumnVector<T1>>;
|
using ColVecT1 = ColumnVectorOrDecimal<T1>;
|
||||||
using ColVecT2 = std::conditional_t<IsDecimalNumber<T2>, ColumnDecimal<T2>, ColumnVector<T2>>;
|
using ColVecT2 = ColumnVectorOrDecimal<T2>;
|
||||||
using ResultType = typename StatFunc::ResultType;
|
using ResultType = typename StatFunc::ResultType;
|
||||||
using ColVecResult = ColumnVector<ResultType>;
|
using ColVecResult = ColumnVector<ResultType>;
|
||||||
|
|
||||||
@ -132,7 +132,7 @@ public:
|
|||||||
static_cast<ResultType>(static_cast<const ColVecT2 &>(*columns[1]).getData()[row_num]));
|
static_cast<ResultType>(static_cast<const ColVecT2 &>(*columns[1]).getData()[row_num]));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if constexpr (IsDecimalNumber<T1>)
|
if constexpr (is_decimal<T1>)
|
||||||
{
|
{
|
||||||
this->data(place).add(static_cast<ResultType>(
|
this->data(place).add(static_cast<ResultType>(
|
||||||
static_cast<const ColVecT1 &>(*columns[0]).getData()[row_num].value));
|
static_cast<const ColVecT1 &>(*columns[0]).getData()[row_num].value));
|
||||||
@ -163,7 +163,7 @@ public:
|
|||||||
const auto & data = this->data(place);
|
const auto & data = this->data(place);
|
||||||
auto & dst = static_cast<ColVecResult &>(to).getData();
|
auto & dst = static_cast<ColVecResult &>(to).getData();
|
||||||
|
|
||||||
if constexpr (IsDecimalNumber<T1>)
|
if constexpr (is_decimal<T1>)
|
||||||
{
|
{
|
||||||
if constexpr (StatFunc::kind == StatisticsFunctionKind::varPop)
|
if constexpr (StatFunc::kind == StatisticsFunctionKind::varPop)
|
||||||
dst.push_back(data.getPopulation(src_scale * 2));
|
dst.push_back(data.getPopulation(src_scale * 2));
|
||||||
|
@ -20,10 +20,9 @@ template <typename T>
|
|||||||
struct SumSimple
|
struct SumSimple
|
||||||
{
|
{
|
||||||
/// @note It uses slow Decimal128 (cause we need such a variant). sumWithOverflow is faster for Decimal32/64
|
/// @note It uses slow Decimal128 (cause we need such a variant). sumWithOverflow is faster for Decimal32/64
|
||||||
using ResultType = std::conditional_t<IsDecimalNumber<T>,
|
using ResultType = std::conditional_t<is_decimal<T>,
|
||||||
std::conditional_t<std::is_same_v<T, Decimal256>, Decimal256, Decimal128>,
|
std::conditional_t<std::is_same_v<T, Decimal256>, Decimal256, Decimal128>,
|
||||||
NearestFieldType<T>>;
|
NearestFieldType<T>>;
|
||||||
// using ResultType = std::conditional_t<IsDecimalNumber<T>, Decimal128, NearestFieldType<T>>;
|
|
||||||
using AggregateDataType = AggregateFunctionSumData<ResultType>;
|
using AggregateDataType = AggregateFunctionSumData<ResultType>;
|
||||||
using Function = AggregateFunctionSum<T, ResultType, AggregateDataType, AggregateFunctionTypeSum>;
|
using Function = AggregateFunctionSum<T, ResultType, AggregateDataType, AggregateFunctionTypeSum>;
|
||||||
};
|
};
|
||||||
@ -47,7 +46,7 @@ struct SumKahan
|
|||||||
template <typename T> using AggregateFunctionSumSimple = typename SumSimple<T>::Function;
|
template <typename T> using AggregateFunctionSumSimple = typename SumSimple<T>::Function;
|
||||||
template <typename T> using AggregateFunctionSumWithOverflow = typename SumSameType<T>::Function;
|
template <typename T> using AggregateFunctionSumWithOverflow = typename SumSameType<T>::Function;
|
||||||
template <typename T> using AggregateFunctionSumKahan =
|
template <typename T> using AggregateFunctionSumKahan =
|
||||||
std::conditional_t<IsDecimalNumber<T>, typename SumSimple<T>::Function, typename SumKahan<T>::Function>;
|
std::conditional_t<is_decimal<T>, typename SumSimple<T>::Function, typename SumKahan<T>::Function>;
|
||||||
|
|
||||||
|
|
||||||
template <template <typename> class Function>
|
template <template <typename> class Function>
|
||||||
|
@ -104,8 +104,8 @@ struct AggregateFunctionSumData
|
|||||||
const auto * end = ptr + count;
|
const auto * end = ptr + count;
|
||||||
|
|
||||||
if constexpr (
|
if constexpr (
|
||||||
(is_integer_v<T> && !is_big_int_v<T>)
|
(is_integer<T> && !is_big_int_v<T>)
|
||||||
|| (IsDecimalNumber<T> && !std::is_same_v<T, Decimal256> && !std::is_same_v<T, Decimal128>))
|
|| (is_decimal<T> && !std::is_same_v<T, Decimal256> && !std::is_same_v<T, Decimal128>))
|
||||||
{
|
{
|
||||||
/// For integers we can vectorize the operation if we replace the null check using a multiplication (by 0 for null, 1 for not null)
|
/// For integers we can vectorize the operation if we replace the null check using a multiplication (by 0 for null, 1 for not null)
|
||||||
/// https://quick-bench.com/q/MLTnfTvwC2qZFVeWHfOBR3U7a8I
|
/// https://quick-bench.com/q/MLTnfTvwC2qZFVeWHfOBR3U7a8I
|
||||||
@ -334,9 +334,7 @@ class AggregateFunctionSum final : public IAggregateFunctionDataHelper<Data, Agg
|
|||||||
public:
|
public:
|
||||||
static constexpr bool DateTime64Supported = false;
|
static constexpr bool DateTime64Supported = false;
|
||||||
|
|
||||||
using ResultDataType = std::conditional_t<IsDecimalNumber<T>, DataTypeDecimal<TResult>, DataTypeNumber<TResult>>;
|
using ColVecType = ColumnVectorOrDecimal<T>;
|
||||||
using ColVecType = std::conditional_t<IsDecimalNumber<T>, ColumnDecimal<T>, ColumnVector<T>>;
|
|
||||||
using ColVecResult = std::conditional_t<IsDecimalNumber<T>, ColumnDecimal<TResult>, ColumnVector<TResult>>;
|
|
||||||
|
|
||||||
String getName() const override
|
String getName() const override
|
||||||
{
|
{
|
||||||
@ -361,10 +359,13 @@ public:
|
|||||||
|
|
||||||
DataTypePtr getReturnType() const override
|
DataTypePtr getReturnType() const override
|
||||||
{
|
{
|
||||||
if constexpr (IsDecimalNumber<T>)
|
if constexpr (!is_decimal<T>)
|
||||||
return std::make_shared<ResultDataType>(ResultDataType::maxPrecision(), scale);
|
return std::make_shared<DataTypeNumber<TResult>>();
|
||||||
else
|
else
|
||||||
return std::make_shared<ResultDataType>();
|
{
|
||||||
|
using DataType = DataTypeDecimal<TResult>;
|
||||||
|
return std::make_shared<DataType>(DataType::maxPrecision(), scale);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool allocatesMemoryInArena() const override { return false; }
|
bool allocatesMemoryInArena() const override { return false; }
|
||||||
@ -431,8 +432,7 @@ public:
|
|||||||
|
|
||||||
void insertResultInto(AggregateDataPtr __restrict place, IColumn & to, Arena *) const override
|
void insertResultInto(AggregateDataPtr __restrict place, IColumn & to, Arena *) const override
|
||||||
{
|
{
|
||||||
auto & column = assert_cast<ColVecResult &>(to);
|
castColumnToResult(to).getData().push_back(this->data(place).get());
|
||||||
column.getData().push_back(this->data(place).get());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if USE_EMBEDDED_COMPILER
|
#if USE_EMBEDDED_COMPILER
|
||||||
@ -511,6 +511,14 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
UInt32 scale;
|
UInt32 scale;
|
||||||
|
|
||||||
|
static constexpr auto & castColumnToResult(IColumn & to)
|
||||||
|
{
|
||||||
|
if constexpr (is_decimal<T>)
|
||||||
|
return assert_cast<ColumnDecimal<TResult> &>(to);
|
||||||
|
else
|
||||||
|
return assert_cast<ColumnVector<TResult> &>(to);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -8,8 +8,6 @@
|
|||||||
namespace DB
|
namespace DB
|
||||||
{
|
{
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using DecimalOrNumberDataType = std::conditional_t<IsDecimalNumber<T>, DataTypeDecimal<AvgFieldType<T>>, DataTypeNumber<AvgFieldType<T>>>;
|
|
||||||
template <typename T>
|
|
||||||
class AggregateFunctionSumCount final : public AggregateFunctionAvgBase<AvgFieldType<T>, UInt64, AggregateFunctionSumCount<T>>
|
class AggregateFunctionSumCount final : public AggregateFunctionAvgBase<AvgFieldType<T>, UInt64, AggregateFunctionSumCount<T>>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -20,20 +18,13 @@ public:
|
|||||||
|
|
||||||
DataTypePtr getReturnType() const override
|
DataTypePtr getReturnType() const override
|
||||||
{
|
{
|
||||||
DataTypes types;
|
auto second_elem = std::make_shared<DataTypeUInt64>();
|
||||||
if constexpr (IsDecimalNumber<T>)
|
return std::make_shared<DataTypeTuple>(DataTypes{getReturnTypeFirstElement(), std::move(second_elem)});
|
||||||
types.emplace_back(std::make_shared<DecimalOrNumberDataType<T>>(DecimalOrNumberDataType<T>::maxPrecision(), scale));
|
|
||||||
else
|
|
||||||
types.emplace_back(std::make_shared<DecimalOrNumberDataType<T>>());
|
|
||||||
|
|
||||||
types.emplace_back(std::make_shared<DataTypeUInt64>());
|
|
||||||
|
|
||||||
return std::make_shared<DataTypeTuple>(types);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void insertResultInto(AggregateDataPtr __restrict place, IColumn & to, Arena *) const final
|
void insertResultInto(AggregateDataPtr __restrict place, IColumn & to, Arena *) const final
|
||||||
{
|
{
|
||||||
assert_cast<DecimalOrVectorCol<AvgFieldType<T>> &>((assert_cast<ColumnTuple &>(to)).getColumn(0)).getData().push_back(
|
assert_cast<ColumnVectorOrDecimal<AvgFieldType<T>> &>((assert_cast<ColumnTuple &>(to)).getColumn(0)).getData().push_back(
|
||||||
this->data(place).numerator);
|
this->data(place).numerator);
|
||||||
|
|
||||||
assert_cast<ColumnUInt64 &>((assert_cast<ColumnTuple &>(to)).getColumn(1)).getData().push_back(
|
assert_cast<ColumnUInt64 &>((assert_cast<ColumnTuple &>(to)).getColumn(1)).getData().push_back(
|
||||||
@ -42,7 +33,7 @@ public:
|
|||||||
|
|
||||||
void NO_SANITIZE_UNDEFINED add(AggregateDataPtr __restrict place, const IColumn ** columns, size_t row_num, Arena *) const final
|
void NO_SANITIZE_UNDEFINED add(AggregateDataPtr __restrict place, const IColumn ** columns, size_t row_num, Arena *) const final
|
||||||
{
|
{
|
||||||
this->data(place).numerator += static_cast<const DecimalOrVectorCol<T> &>(*columns[0]).getData()[row_num];
|
this->data(place).numerator += static_cast<const ColumnVectorOrDecimal<T> &>(*columns[0]).getData()[row_num];
|
||||||
++this->data(place).denominator;
|
++this->data(place).denominator;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,6 +50,19 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
UInt32 scale;
|
UInt32 scale;
|
||||||
|
|
||||||
|
auto getReturnTypeFirstElement() const
|
||||||
|
{
|
||||||
|
using FieldType = AvgFieldType<T>;
|
||||||
|
|
||||||
|
if constexpr (!is_decimal<T>)
|
||||||
|
return std::make_shared<DataTypeNumber<FieldType>>();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
using DataType = DataTypeDecimal<FieldType>;
|
||||||
|
return std::make_shared<DataType>(DataType::maxPrecision(), scale);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -190,7 +190,7 @@ public:
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
decltype(merged_maps.begin()) it;
|
decltype(merged_maps.begin()) it;
|
||||||
if constexpr (IsDecimalNumber<T>)
|
if constexpr (is_decimal<T>)
|
||||||
{
|
{
|
||||||
// FIXME why is storing NearestFieldType not enough, and we
|
// FIXME why is storing NearestFieldType not enough, and we
|
||||||
// have to check for decimals again here?
|
// have to check for decimals again here?
|
||||||
@ -217,7 +217,7 @@ public:
|
|||||||
new_values.resize(size);
|
new_values.resize(size);
|
||||||
new_values[col] = value;
|
new_values[col] = value;
|
||||||
|
|
||||||
if constexpr (IsDecimalNumber<T>)
|
if constexpr (is_decimal<T>)
|
||||||
{
|
{
|
||||||
UInt32 scale = static_cast<const ColumnDecimal<T> &>(key_column).getData().getScale();
|
UInt32 scale = static_cast<const ColumnDecimal<T> &>(key_column).getData().getScale();
|
||||||
merged_maps.emplace(DecimalField<T>(key, scale), std::move(new_values));
|
merged_maps.emplace(DecimalField<T>(key, scale), std::move(new_values));
|
||||||
@ -280,7 +280,7 @@ public:
|
|||||||
for (size_t col = 0; col < values_types.size(); ++col)
|
for (size_t col = 0; col < values_types.size(); ++col)
|
||||||
values_serializations[col]->deserializeBinary(values[col], buf);
|
values_serializations[col]->deserializeBinary(values[col], buf);
|
||||||
|
|
||||||
if constexpr (IsDecimalNumber<T>)
|
if constexpr (is_decimal<T>)
|
||||||
merged_maps[key.get<DecimalField<T>>()] = values;
|
merged_maps[key.get<DecimalField<T>>()] = values;
|
||||||
else
|
else
|
||||||
merged_maps[key.get<T>()] = values;
|
merged_maps[key.get<T>()] = values;
|
||||||
@ -396,7 +396,7 @@ private:
|
|||||||
using Base = AggregateFunctionMapBase<T, Self, FieldVisitorSum, overflow, tuple_argument, true>;
|
using Base = AggregateFunctionMapBase<T, Self, FieldVisitorSum, overflow, tuple_argument, true>;
|
||||||
|
|
||||||
/// ARCADIA_BUILD disallow unordered_set for big ints for some reason
|
/// ARCADIA_BUILD disallow unordered_set for big ints for some reason
|
||||||
static constexpr const bool allow_hash = !OverBigInt<T>;
|
static constexpr const bool allow_hash = !is_over_big_int<T>;
|
||||||
using ContainerT = std::conditional_t<allow_hash, std::unordered_set<T>, std::set<T>>;
|
using ContainerT = std::conditional_t<allow_hash, std::unordered_set<T>, std::set<T>>;
|
||||||
|
|
||||||
ContainerT keys_to_keep;
|
ContainerT keys_to_keep;
|
||||||
|
@ -30,7 +30,7 @@ struct QuantileExactWeighted
|
|||||||
};
|
};
|
||||||
|
|
||||||
using Weight = UInt64;
|
using Weight = UInt64;
|
||||||
using UnderlyingType = typename NativeType<Value>::Type;
|
using UnderlyingType = NativeType<Value>;
|
||||||
using Hasher = std::conditional_t<std::is_same_v<Value, Decimal128>, Int128Hash, HashCRC32<UnderlyingType>>;
|
using Hasher = std::conditional_t<std::is_same_v<Value, Decimal128>, Int128Hash, HashCRC32<UnderlyingType>>;
|
||||||
|
|
||||||
/// When creating, the hash table must be small.
|
/// When creating, the hash table must be small.
|
||||||
|
@ -121,7 +121,7 @@ public:
|
|||||||
{
|
{
|
||||||
if (samples.empty())
|
if (samples.empty())
|
||||||
{
|
{
|
||||||
if (DB::IsDecimalNumber<T>)
|
if (DB::is_decimal<T>)
|
||||||
return 0;
|
return 0;
|
||||||
return onEmpty<double>();
|
return onEmpty<double>();
|
||||||
}
|
}
|
||||||
@ -134,7 +134,7 @@ public:
|
|||||||
size_t right_index = left_index + 1;
|
size_t right_index = left_index + 1;
|
||||||
if (right_index == samples.size())
|
if (right_index == samples.size())
|
||||||
{
|
{
|
||||||
if constexpr (DB::IsDecimalNumber<T>)
|
if constexpr (DB::is_decimal<T>)
|
||||||
return static_cast<double>(samples[left_index].value);
|
return static_cast<double>(samples[left_index].value);
|
||||||
else
|
else
|
||||||
return static_cast<double>(samples[left_index]);
|
return static_cast<double>(samples[left_index]);
|
||||||
@ -143,7 +143,7 @@ public:
|
|||||||
double left_coef = right_index - index;
|
double left_coef = right_index - index;
|
||||||
double right_coef = index - left_index;
|
double right_coef = index - left_index;
|
||||||
|
|
||||||
if constexpr (DB::IsDecimalNumber<T>)
|
if constexpr (DB::is_decimal<T>)
|
||||||
return static_cast<double>(samples[left_index].value) * left_coef + static_cast<double>(samples[right_index].value) * right_coef;
|
return static_cast<double>(samples[left_index].value) * left_coef + static_cast<double>(samples[right_index].value) * right_coef;
|
||||||
else
|
else
|
||||||
return static_cast<double>(samples[left_index]) * left_coef + static_cast<double>(samples[right_index]) * right_coef;
|
return static_cast<double>(samples[left_index]) * left_coef + static_cast<double>(samples[right_index]) * right_coef;
|
||||||
|
@ -506,8 +506,9 @@ static void pushBackAndCreateState(ColumnAggregateFunction::Container & data, Ar
|
|||||||
void ColumnAggregateFunction::insert(const Field & x)
|
void ColumnAggregateFunction::insert(const Field & x)
|
||||||
{
|
{
|
||||||
if (x.getType() != Field::Types::AggregateFunctionState)
|
if (x.getType() != Field::Types::AggregateFunctionState)
|
||||||
throw Exception(String("Inserting field of type ") + x.getTypeName() + " into ColumnAggregateFunction. "
|
throw Exception(ErrorCodes::LOGICAL_ERROR,
|
||||||
"Expected " + Field::Types::toString(Field::Types::AggregateFunctionState), ErrorCodes::LOGICAL_ERROR);
|
"Inserting field of type {} into ColumnAggregateFunction. Expected {}",
|
||||||
|
x.getTypeName(), Field::Types::AggregateFunctionState);
|
||||||
|
|
||||||
const auto & field_name = x.get<const AggregateFunctionStateData &>().name;
|
const auto & field_name = x.get<const AggregateFunctionStateData &>().name;
|
||||||
if (type_string != field_name)
|
if (type_string != field_name)
|
||||||
|
@ -38,7 +38,7 @@ template class DecimalPaddedPODArray<Decimal128>;
|
|||||||
template class DecimalPaddedPODArray<Decimal256>;
|
template class DecimalPaddedPODArray<Decimal256>;
|
||||||
template class DecimalPaddedPODArray<DateTime64>;
|
template class DecimalPaddedPODArray<DateTime64>;
|
||||||
|
|
||||||
template <typename T>
|
template <is_decimal T>
|
||||||
int ColumnDecimal<T>::compareAt(size_t n, size_t m, const IColumn & rhs_, int) const
|
int ColumnDecimal<T>::compareAt(size_t n, size_t m, const IColumn & rhs_, int) const
|
||||||
{
|
{
|
||||||
auto & other = static_cast<const Self &>(rhs_);
|
auto & other = static_cast<const Self &>(rhs_);
|
||||||
@ -50,7 +50,7 @@ int ColumnDecimal<T>::compareAt(size_t n, size_t m, const IColumn & rhs_, int) c
|
|||||||
return decimalLess<T>(b, a, other.scale, scale) ? 1 : (decimalLess<T>(a, b, scale, other.scale) ? -1 : 0);
|
return decimalLess<T>(b, a, other.scale, scale) ? 1 : (decimalLess<T>(a, b, scale, other.scale) ? -1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <is_decimal T>
|
||||||
void ColumnDecimal<T>::compareColumn(const IColumn & rhs, size_t rhs_row_num,
|
void ColumnDecimal<T>::compareColumn(const IColumn & rhs, size_t rhs_row_num,
|
||||||
PaddedPODArray<UInt64> * row_indexes, PaddedPODArray<Int8> & compare_results,
|
PaddedPODArray<UInt64> * row_indexes, PaddedPODArray<Int8> & compare_results,
|
||||||
int direction, int nan_direction_hint) const
|
int direction, int nan_direction_hint) const
|
||||||
@ -59,13 +59,13 @@ void ColumnDecimal<T>::compareColumn(const IColumn & rhs, size_t rhs_row_num,
|
|||||||
compare_results, direction, nan_direction_hint);
|
compare_results, direction, nan_direction_hint);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <is_decimal T>
|
||||||
bool ColumnDecimal<T>::hasEqualValues() const
|
bool ColumnDecimal<T>::hasEqualValues() const
|
||||||
{
|
{
|
||||||
return this->template hasEqualValuesImpl<ColumnDecimal<T>>();
|
return this->template hasEqualValuesImpl<ColumnDecimal<T>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <is_decimal T>
|
||||||
StringRef ColumnDecimal<T>::serializeValueIntoArena(size_t n, Arena & arena, char const *& begin) const
|
StringRef ColumnDecimal<T>::serializeValueIntoArena(size_t n, Arena & arena, char const *& begin) const
|
||||||
{
|
{
|
||||||
auto * pos = arena.allocContinue(sizeof(T), begin);
|
auto * pos = arena.allocContinue(sizeof(T), begin);
|
||||||
@ -73,20 +73,20 @@ StringRef ColumnDecimal<T>::serializeValueIntoArena(size_t n, Arena & arena, cha
|
|||||||
return StringRef(pos, sizeof(T));
|
return StringRef(pos, sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <is_decimal T>
|
||||||
const char * ColumnDecimal<T>::deserializeAndInsertFromArena(const char * pos)
|
const char * ColumnDecimal<T>::deserializeAndInsertFromArena(const char * pos)
|
||||||
{
|
{
|
||||||
data.push_back(unalignedLoad<T>(pos));
|
data.push_back(unalignedLoad<T>(pos));
|
||||||
return pos + sizeof(T);
|
return pos + sizeof(T);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <is_decimal T>
|
||||||
const char * ColumnDecimal<T>::skipSerializedInArena(const char * pos) const
|
const char * ColumnDecimal<T>::skipSerializedInArena(const char * pos) const
|
||||||
{
|
{
|
||||||
return pos + sizeof(T);
|
return pos + sizeof(T);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <is_decimal T>
|
||||||
UInt64 ColumnDecimal<T>::get64([[maybe_unused]] size_t n) const
|
UInt64 ColumnDecimal<T>::get64([[maybe_unused]] size_t n) const
|
||||||
{
|
{
|
||||||
if constexpr (sizeof(T) > sizeof(UInt64))
|
if constexpr (sizeof(T) > sizeof(UInt64))
|
||||||
@ -95,13 +95,13 @@ UInt64 ColumnDecimal<T>::get64([[maybe_unused]] size_t n) const
|
|||||||
return static_cast<NativeT>(data[n]);
|
return static_cast<NativeT>(data[n]);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <is_decimal T>
|
||||||
void ColumnDecimal<T>::updateHashWithValue(size_t n, SipHash & hash) const
|
void ColumnDecimal<T>::updateHashWithValue(size_t n, SipHash & hash) const
|
||||||
{
|
{
|
||||||
hash.update(data[n].value);
|
hash.update(data[n].value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <is_decimal T>
|
||||||
void ColumnDecimal<T>::updateWeakHash32(WeakHash32 & hash) const
|
void ColumnDecimal<T>::updateWeakHash32(WeakHash32 & hash) const
|
||||||
{
|
{
|
||||||
auto s = data.size();
|
auto s = data.size();
|
||||||
@ -122,13 +122,13 @@ void ColumnDecimal<T>::updateWeakHash32(WeakHash32 & hash) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <is_decimal T>
|
||||||
void ColumnDecimal<T>::updateHashFast(SipHash & hash) const
|
void ColumnDecimal<T>::updateHashFast(SipHash & hash) const
|
||||||
{
|
{
|
||||||
hash.update(reinterpret_cast<const char *>(data.data()), size() * sizeof(data[0]));
|
hash.update(reinterpret_cast<const char *>(data.data()), size() * sizeof(data[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <is_decimal T>
|
||||||
void ColumnDecimal<T>::getPermutation(bool reverse, size_t limit, int , IColumn::Permutation & res) const
|
void ColumnDecimal<T>::getPermutation(bool reverse, size_t limit, int , IColumn::Permutation & res) const
|
||||||
{
|
{
|
||||||
#if 1 /// TODO: perf test
|
#if 1 /// TODO: perf test
|
||||||
@ -147,7 +147,7 @@ void ColumnDecimal<T>::getPermutation(bool reverse, size_t limit, int , IColumn:
|
|||||||
permutation(reverse, limit, res);
|
permutation(reverse, limit, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <is_decimal T>
|
||||||
void ColumnDecimal<T>::updatePermutation(bool reverse, size_t limit, int, IColumn::Permutation & res, EqualRanges & equal_ranges) const
|
void ColumnDecimal<T>::updatePermutation(bool reverse, size_t limit, int, IColumn::Permutation & res, EqualRanges & equal_ranges) const
|
||||||
{
|
{
|
||||||
if (equal_ranges.empty())
|
if (equal_ranges.empty())
|
||||||
@ -228,7 +228,7 @@ void ColumnDecimal<T>::updatePermutation(bool reverse, size_t limit, int, IColum
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <is_decimal T>
|
||||||
ColumnPtr ColumnDecimal<T>::permute(const IColumn::Permutation & perm, size_t limit) const
|
ColumnPtr ColumnDecimal<T>::permute(const IColumn::Permutation & perm, size_t limit) const
|
||||||
{
|
{
|
||||||
size_t size = limit ? std::min(data.size(), limit) : data.size();
|
size_t size = limit ? std::min(data.size(), limit) : data.size();
|
||||||
@ -244,7 +244,7 @@ ColumnPtr ColumnDecimal<T>::permute(const IColumn::Permutation & perm, size_t li
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <is_decimal T>
|
||||||
MutableColumnPtr ColumnDecimal<T>::cloneResized(size_t size) const
|
MutableColumnPtr ColumnDecimal<T>::cloneResized(size_t size) const
|
||||||
{
|
{
|
||||||
auto res = this->create(0, scale);
|
auto res = this->create(0, scale);
|
||||||
@ -268,7 +268,7 @@ MutableColumnPtr ColumnDecimal<T>::cloneResized(size_t size) const
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <is_decimal T>
|
||||||
void ColumnDecimal<T>::insertData(const char * src, size_t /*length*/)
|
void ColumnDecimal<T>::insertData(const char * src, size_t /*length*/)
|
||||||
{
|
{
|
||||||
T tmp;
|
T tmp;
|
||||||
@ -276,7 +276,7 @@ void ColumnDecimal<T>::insertData(const char * src, size_t /*length*/)
|
|||||||
data.emplace_back(tmp);
|
data.emplace_back(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <is_decimal T>
|
||||||
void ColumnDecimal<T>::insertRangeFrom(const IColumn & src, size_t start, size_t length)
|
void ColumnDecimal<T>::insertRangeFrom(const IColumn & src, size_t start, size_t length)
|
||||||
{
|
{
|
||||||
const ColumnDecimal & src_vec = assert_cast<const ColumnDecimal &>(src);
|
const ColumnDecimal & src_vec = assert_cast<const ColumnDecimal &>(src);
|
||||||
@ -292,7 +292,7 @@ void ColumnDecimal<T>::insertRangeFrom(const IColumn & src, size_t start, size_t
|
|||||||
memcpy(data.data() + old_size, &src_vec.data[start], length * sizeof(data[0]));
|
memcpy(data.data() + old_size, &src_vec.data[start], length * sizeof(data[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <is_decimal T>
|
||||||
ColumnPtr ColumnDecimal<T>::filter(const IColumn::Filter & filt, ssize_t result_size_hint) const
|
ColumnPtr ColumnDecimal<T>::filter(const IColumn::Filter & filt, ssize_t result_size_hint) const
|
||||||
{
|
{
|
||||||
size_t size = data.size();
|
size_t size = data.size();
|
||||||
@ -321,19 +321,19 @@ ColumnPtr ColumnDecimal<T>::filter(const IColumn::Filter & filt, ssize_t result_
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <is_decimal T>
|
||||||
void ColumnDecimal<T>::expand(const IColumn::Filter & mask, bool inverted)
|
void ColumnDecimal<T>::expand(const IColumn::Filter & mask, bool inverted)
|
||||||
{
|
{
|
||||||
expandDataByMask<T>(data, mask, inverted);
|
expandDataByMask<T>(data, mask, inverted);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <is_decimal T>
|
||||||
ColumnPtr ColumnDecimal<T>::index(const IColumn & indexes, size_t limit) const
|
ColumnPtr ColumnDecimal<T>::index(const IColumn & indexes, size_t limit) const
|
||||||
{
|
{
|
||||||
return selectIndexImpl(*this, indexes, limit);
|
return selectIndexImpl(*this, indexes, limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <is_decimal T>
|
||||||
ColumnPtr ColumnDecimal<T>::replicate(const IColumn::Offsets & offsets) const
|
ColumnPtr ColumnDecimal<T>::replicate(const IColumn::Offsets & offsets) const
|
||||||
{
|
{
|
||||||
size_t size = data.size();
|
size_t size = data.size();
|
||||||
@ -360,13 +360,13 @@ ColumnPtr ColumnDecimal<T>::replicate(const IColumn::Offsets & offsets) const
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <is_decimal T>
|
||||||
void ColumnDecimal<T>::gather(ColumnGathererStream & gatherer)
|
void ColumnDecimal<T>::gather(ColumnGathererStream & gatherer)
|
||||||
{
|
{
|
||||||
gatherer.gather(*this);
|
gatherer.gather(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <is_decimal T>
|
||||||
ColumnPtr ColumnDecimal<T>::compress() const
|
ColumnPtr ColumnDecimal<T>::compress() const
|
||||||
{
|
{
|
||||||
size_t source_size = data.size() * sizeof(T);
|
size_t source_size = data.size() * sizeof(T);
|
||||||
@ -390,7 +390,7 @@ ColumnPtr ColumnDecimal<T>::compress() const
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <is_decimal T>
|
||||||
void ColumnDecimal<T>::getExtremes(Field & min, Field & max) const
|
void ColumnDecimal<T>::getExtremes(Field & min, Field & max) const
|
||||||
{
|
{
|
||||||
if (data.empty())
|
if (data.empty())
|
||||||
|
@ -7,6 +7,8 @@
|
|||||||
#include <Core/DecimalFunctions.h>
|
#include <Core/DecimalFunctions.h>
|
||||||
#include <Common/typeid_cast.h>
|
#include <Common/typeid_cast.h>
|
||||||
#include <common/sort.h>
|
#include <common/sort.h>
|
||||||
|
#include <Core/TypeId.h>
|
||||||
|
#include <Core/TypeName.h>
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
@ -59,11 +61,9 @@ extern template class DecimalPaddedPODArray<Decimal256>;
|
|||||||
extern template class DecimalPaddedPODArray<DateTime64>;
|
extern template class DecimalPaddedPODArray<DateTime64>;
|
||||||
|
|
||||||
/// A ColumnVector for Decimals
|
/// A ColumnVector for Decimals
|
||||||
template <typename T>
|
template <is_decimal T>
|
||||||
class ColumnDecimal final : public COWHelper<ColumnVectorHelper, ColumnDecimal<T>>
|
class ColumnDecimal final : public COWHelper<ColumnVectorHelper, ColumnDecimal<T>>
|
||||||
{
|
{
|
||||||
static_assert(IsDecimalNumber<T>);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using Self = ColumnDecimal;
|
using Self = ColumnDecimal;
|
||||||
friend class COWHelper<ColumnVectorHelper, Self>;
|
friend class COWHelper<ColumnVectorHelper, Self>;
|
||||||
@ -210,7 +210,12 @@ protected:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <class> class ColumnVector;
|
||||||
|
template <class T> struct ColumnVectorOrDecimalT { using Col = ColumnVector<T>; };
|
||||||
|
template <is_decimal T> struct ColumnVectorOrDecimalT<T> { using Col = ColumnDecimal<T>; };
|
||||||
|
template <class T> using ColumnVectorOrDecimal = typename ColumnVectorOrDecimalT<T>::Col;
|
||||||
|
|
||||||
|
template <is_decimal T>
|
||||||
template <typename Type>
|
template <typename Type>
|
||||||
ColumnPtr ColumnDecimal<T>::indexImpl(const PaddedPODArray<Type> & indexes, size_t limit) const
|
ColumnPtr ColumnDecimal<T>::indexImpl(const PaddedPODArray<Type> & indexes, size_t limit) const
|
||||||
{
|
{
|
||||||
|
@ -7,6 +7,8 @@
|
|||||||
#include <common/unaligned.h>
|
#include <common/unaligned.h>
|
||||||
#include <Core/Field.h>
|
#include <Core/Field.h>
|
||||||
#include <Common/assert_cast.h>
|
#include <Common/assert_cast.h>
|
||||||
|
#include <Core/TypeId.h>
|
||||||
|
#include <Core/TypeName.h>
|
||||||
|
|
||||||
|
|
||||||
namespace DB
|
namespace DB
|
||||||
@ -102,7 +104,7 @@ template <class U> struct CompareHelper<Float64, U> : public FloatCompareHelper<
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
class ColumnVector final : public COWHelper<ColumnVectorHelper, ColumnVector<T>>
|
class ColumnVector final : public COWHelper<ColumnVectorHelper, ColumnVector<T>>
|
||||||
{
|
{
|
||||||
static_assert(!IsDecimalNumber<T>);
|
static_assert(!is_decimal<T>);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using Self = ColumnVector;
|
using Self = ColumnVector;
|
||||||
|
@ -494,7 +494,6 @@
|
|||||||
M(523, UNKNOWN_ROW_POLICY) \
|
M(523, UNKNOWN_ROW_POLICY) \
|
||||||
M(524, ALTER_OF_COLUMN_IS_FORBIDDEN) \
|
M(524, ALTER_OF_COLUMN_IS_FORBIDDEN) \
|
||||||
M(525, INCORRECT_DISK_INDEX) \
|
M(525, INCORRECT_DISK_INDEX) \
|
||||||
M(526, UNKNOWN_VOLUME_TYPE) \
|
|
||||||
M(527, NO_SUITABLE_FUNCTION_IMPLEMENTATION) \
|
M(527, NO_SUITABLE_FUNCTION_IMPLEMENTATION) \
|
||||||
M(528, CASSANDRA_INTERNAL_ERROR) \
|
M(528, CASSANDRA_INTERNAL_ERROR) \
|
||||||
M(529, NOT_A_LEADER) \
|
M(529, NOT_A_LEADER) \
|
||||||
|
@ -1,39 +0,0 @@
|
|||||||
#include <Common/ExternalLoaderStatus.h>
|
|
||||||
|
|
||||||
namespace DB
|
|
||||||
{
|
|
||||||
String toString(ExternalLoaderStatus status)
|
|
||||||
{
|
|
||||||
using Status = ExternalLoaderStatus;
|
|
||||||
switch (status)
|
|
||||||
{
|
|
||||||
case Status::NOT_LOADED: return "NOT_LOADED";
|
|
||||||
case Status::LOADED: return "LOADED";
|
|
||||||
case Status::FAILED: return "FAILED";
|
|
||||||
case Status::LOADING: return "LOADING";
|
|
||||||
case Status::FAILED_AND_RELOADING: return "FAILED_AND_RELOADING";
|
|
||||||
case Status::LOADED_AND_RELOADING: return "LOADED_AND_RELOADING";
|
|
||||||
case Status::NOT_EXIST: return "NOT_EXIST";
|
|
||||||
}
|
|
||||||
__builtin_unreachable();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::pair<String, Int8>> getStatusEnumAllPossibleValues()
|
|
||||||
{
|
|
||||||
using Status = ExternalLoaderStatus;
|
|
||||||
return std::vector<std::pair<String, Int8>>{
|
|
||||||
{toString(Status::NOT_LOADED), static_cast<Int8>(Status::NOT_LOADED)},
|
|
||||||
{toString(Status::LOADED), static_cast<Int8>(Status::LOADED)},
|
|
||||||
{toString(Status::FAILED), static_cast<Int8>(Status::FAILED)},
|
|
||||||
{toString(Status::LOADING), static_cast<Int8>(Status::LOADING)},
|
|
||||||
{toString(Status::LOADED_AND_RELOADING), static_cast<Int8>(Status::LOADED_AND_RELOADING)},
|
|
||||||
{toString(Status::FAILED_AND_RELOADING), static_cast<Int8>(Status::FAILED_AND_RELOADING)},
|
|
||||||
{toString(Status::NOT_EXIST), static_cast<Int8>(Status::NOT_EXIST)},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
std::ostream & operator<<(std::ostream & out, ExternalLoaderStatus status)
|
|
||||||
{
|
|
||||||
return out << toString(status);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,13 +1,12 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <utility>
|
#include <common/EnumReflection.h>
|
||||||
#include <ostream>
|
|
||||||
#include <common/types.h>
|
#include <common/types.h>
|
||||||
|
|
||||||
namespace DB
|
namespace DB
|
||||||
{
|
{
|
||||||
enum class ExternalLoaderStatus
|
enum class ExternalLoaderStatus : Int8
|
||||||
{
|
{
|
||||||
NOT_LOADED, /// Object hasn't been tried to load. This is an initial state.
|
NOT_LOADED, /// Object hasn't been tried to load. This is an initial state.
|
||||||
LOADED, /// Object has been loaded successfully.
|
LOADED, /// Object has been loaded successfully.
|
||||||
@ -18,7 +17,14 @@ namespace DB
|
|||||||
NOT_EXIST, /// Object with this name wasn't found in the configuration.
|
NOT_EXIST, /// Object with this name wasn't found in the configuration.
|
||||||
};
|
};
|
||||||
|
|
||||||
String toString(ExternalLoaderStatus status);
|
inline std::vector<std::pair<String, Int8>> getStatusEnumAllPossibleValues()
|
||||||
std::vector<std::pair<String, Int8>> getStatusEnumAllPossibleValues();
|
{
|
||||||
std::ostream & operator<<(std::ostream & out, ExternalLoaderStatus status);
|
std::vector<std::pair<String, Int8>> out;
|
||||||
|
out.reserve(magic_enum::enum_count<ExternalLoaderStatus>());
|
||||||
|
|
||||||
|
for (const auto & [value, str] : magic_enum::enum_entries<ExternalLoaderStatus>())
|
||||||
|
out.emplace_back(std::string{str}, static_cast<Int8>(value));
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -116,7 +116,7 @@ public:
|
|||||||
template <typename U, typename = std::enable_if_t<is_big_int_v<U>> >
|
template <typename U, typename = std::enable_if_t<is_big_int_v<U>> >
|
||||||
T operator() (const U & x) const
|
T operator() (const U & x) const
|
||||||
{
|
{
|
||||||
if constexpr (IsDecimalNumber<T>)
|
if constexpr (is_decimal<T>)
|
||||||
return static_cast<T>(static_cast<typename T::NativeType>(x));
|
return static_cast<T>(static_cast<typename T::NativeType>(x));
|
||||||
else if constexpr (std::is_same_v<T, UInt128>)
|
else if constexpr (std::is_same_v<T, UInt128>)
|
||||||
throw Exception("No conversion to old UInt128 from " + demangle(typeid(U).name()), ErrorCodes::NOT_IMPLEMENTED);
|
throw Exception("No conversion to old UInt128 from " + demangle(typeid(U).name()), ErrorCodes::NOT_IMPLEMENTED);
|
||||||
|
@ -197,12 +197,8 @@ inline size_t DefaultHash64(std::enable_if_t<(sizeof(T) > sizeof(UInt64)), T> ke
|
|||||||
__builtin_unreachable();
|
__builtin_unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename T, typename Enable = void>
|
|
||||||
struct DefaultHash;
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct DefaultHash<T, std::enable_if_t<!DB::IsDecimalNumber<T>>>
|
struct DefaultHash
|
||||||
{
|
{
|
||||||
size_t operator() (T key) const
|
size_t operator() (T key) const
|
||||||
{
|
{
|
||||||
@ -210,8 +206,8 @@ struct DefaultHash<T, std::enable_if_t<!DB::IsDecimalNumber<T>>>
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <DB::is_decimal T>
|
||||||
struct DefaultHash<T, std::enable_if_t<DB::IsDecimalNumber<T>>>
|
struct DefaultHash<T>
|
||||||
{
|
{
|
||||||
size_t operator() (T key) const
|
size_t operator() (T key) const
|
||||||
{
|
{
|
||||||
|
@ -9,23 +9,6 @@ namespace ErrorCodes
|
|||||||
extern const int SYNTAX_ERROR;
|
extern const int SYNTAX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char * IntervalKind::toString() const
|
|
||||||
{
|
|
||||||
switch (kind)
|
|
||||||
{
|
|
||||||
case IntervalKind::Second: return "Second";
|
|
||||||
case IntervalKind::Minute: return "Minute";
|
|
||||||
case IntervalKind::Hour: return "Hour";
|
|
||||||
case IntervalKind::Day: return "Day";
|
|
||||||
case IntervalKind::Week: return "Week";
|
|
||||||
case IntervalKind::Month: return "Month";
|
|
||||||
case IntervalKind::Quarter: return "Quarter";
|
|
||||||
case IntervalKind::Year: return "Year";
|
|
||||||
}
|
|
||||||
__builtin_unreachable();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Int32 IntervalKind::toAvgSeconds() const
|
Int32 IntervalKind::toAvgSeconds() const
|
||||||
{
|
{
|
||||||
switch (kind)
|
switch (kind)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <common/types.h>
|
#include <common/types.h>
|
||||||
|
#include <common/EnumReflection.h>
|
||||||
|
|
||||||
namespace DB
|
namespace DB
|
||||||
{
|
{
|
||||||
@ -24,7 +24,7 @@ struct IntervalKind
|
|||||||
IntervalKind(Kind kind_ = Second) : kind(kind_) {}
|
IntervalKind(Kind kind_ = Second) : kind(kind_) {}
|
||||||
operator Kind() const { return kind; }
|
operator Kind() const { return kind; }
|
||||||
|
|
||||||
const char * toString() const;
|
constexpr std::string_view toString() const { return magic_enum::enum_name(kind); }
|
||||||
|
|
||||||
/// Returns number of seconds in one interval.
|
/// Returns number of seconds in one interval.
|
||||||
/// For `Month`, `Quarter` and `Year` the function returns an average number of seconds.
|
/// For `Month`, `Quarter` and `Year` the function returns an average number of seconds.
|
||||||
|
@ -33,7 +33,7 @@ using ItemPtr = std::unique_ptr<IItem>;
|
|||||||
class JSONString : public IItem
|
class JSONString : public IItem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit JSONString(std::string value_) : value(std::move(value_)) {}
|
JSONString(std::string_view value_) : value(value_) {}
|
||||||
void format(const FormatSettings & settings, FormatContext & context) override;
|
void format(const FormatSettings & settings, FormatContext & context) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -97,6 +97,7 @@ public:
|
|||||||
void add(std::string key, ItemPtr value) { values.emplace_back(Pair{.key = std::move(key), .value = std::move(value)}); }
|
void add(std::string key, ItemPtr value) { values.emplace_back(Pair{.key = std::move(key), .value = std::move(value)}); }
|
||||||
void add(std::string key, std::string value) { add(std::move(key), std::make_unique<JSONString>(std::move(value))); }
|
void add(std::string key, std::string value) { add(std::move(key), std::make_unique<JSONString>(std::move(value))); }
|
||||||
void add(std::string key, const char * value) { add(std::move(key), std::make_unique<JSONString>(value)); }
|
void add(std::string key, const char * value) { add(std::move(key), std::make_unique<JSONString>(value)); }
|
||||||
|
void add(std::string key, std::string_view value) { add(std::move(key), std::make_unique<JSONString>(value)); }
|
||||||
void add(std::string key, bool value) { add(std::move(key), std::make_unique<JSONBool>(std::move(value))); }
|
void add(std::string key, bool value) { add(std::move(key), std::make_unique<JSONBool>(std::move(value))); }
|
||||||
|
|
||||||
template <typename T, std::enable_if_t<std::is_arithmetic<T>::value, bool> = true>
|
template <typename T, std::enable_if_t<std::is_arithmetic<T>::value, bool> = true>
|
||||||
|
@ -187,7 +187,7 @@ struct RadixSortIntTraits
|
|||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using RadixSortNumTraits = std::conditional_t<
|
using RadixSortNumTraits = std::conditional_t<
|
||||||
is_integer_v<T>,
|
is_integer<T>,
|
||||||
std::conditional_t<is_unsigned_v<T>, RadixSortUIntTraits<T>, RadixSortIntTraits<T>>,
|
std::conditional_t<is_unsigned_v<T>, RadixSortUIntTraits<T>, RadixSortIntTraits<T>>,
|
||||||
RadixSortFloatTraits<T>>;
|
RadixSortFloatTraits<T>>;
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ std::pair<std::string, UInt16> parseAddress(const std::string & str, UInt16 defa
|
|||||||
|
|
||||||
UInt16 port_number;
|
UInt16 port_number;
|
||||||
ReadBufferFromMemory port_buf(port, end - port);
|
ReadBufferFromMemory port_buf(port, end - port);
|
||||||
if (!tryReadText<UInt16>(port_number, port_buf) || !port_buf.eof())
|
if (!tryReadText(port_number, port_buf) || !port_buf.eof())
|
||||||
{
|
{
|
||||||
throw Exception(ErrorCodes::BAD_ARGUMENTS,
|
throw Exception(ErrorCodes::BAD_ARGUMENTS,
|
||||||
"Illegal port passed to function parseAddress: {}", port);
|
"Illegal port passed to function parseAddress: {}", port);
|
||||||
|
@ -13,22 +13,22 @@
|
|||||||
|
|
||||||
static_assert(is_signed_v<Int128>);
|
static_assert(is_signed_v<Int128>);
|
||||||
static_assert(!is_unsigned_v<Int128>);
|
static_assert(!is_unsigned_v<Int128>);
|
||||||
static_assert(is_integer_v<Int128>);
|
static_assert(is_integer<Int128>);
|
||||||
static_assert(sizeof(Int128) == 16);
|
static_assert(sizeof(Int128) == 16);
|
||||||
|
|
||||||
static_assert(is_signed_v<Int256>);
|
static_assert(is_signed_v<Int256>);
|
||||||
static_assert(!is_unsigned_v<Int256>);
|
static_assert(!is_unsigned_v<Int256>);
|
||||||
static_assert(is_integer_v<Int256>);
|
static_assert(is_integer<Int256>);
|
||||||
static_assert(sizeof(Int256) == 32);
|
static_assert(sizeof(Int256) == 32);
|
||||||
|
|
||||||
static_assert(!is_signed_v<UInt128>);
|
static_assert(!is_signed_v<UInt128>);
|
||||||
static_assert(is_unsigned_v<UInt128>);
|
static_assert(is_unsigned_v<UInt128>);
|
||||||
static_assert(is_integer_v<UInt128>);
|
static_assert(is_integer<UInt128>);
|
||||||
static_assert(sizeof(UInt128) == 16);
|
static_assert(sizeof(UInt128) == 16);
|
||||||
|
|
||||||
static_assert(!is_signed_v<UInt256>);
|
static_assert(!is_signed_v<UInt256>);
|
||||||
static_assert(is_unsigned_v<UInt256>);
|
static_assert(is_unsigned_v<UInt256>);
|
||||||
static_assert(is_integer_v<UInt256>);
|
static_assert(is_integer<UInt256>);
|
||||||
static_assert(sizeof(UInt256) == 32);
|
static_assert(sizeof(UInt256) == 32);
|
||||||
|
|
||||||
|
|
||||||
|
@ -685,7 +685,7 @@ auto SequentialGenerator = [](auto stride = 1)
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
using uniform_distribution =
|
using uniform_distribution =
|
||||||
typename std::conditional_t<std::is_floating_point_v<T>, std::uniform_real_distribution<T>,
|
typename std::conditional_t<std::is_floating_point_v<T>, std::uniform_real_distribution<T>,
|
||||||
typename std::conditional_t<is_integer_v<T>, std::uniform_int_distribution<T>, void>>;
|
typename std::conditional_t<is_integer<T>, std::uniform_int_distribution<T>, void>>;
|
||||||
|
|
||||||
|
|
||||||
template <typename T = Int32>
|
template <typename T = Int32>
|
||||||
|
@ -33,7 +33,7 @@ bool lessOp(A a, B b)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
/// int vs int
|
/// int vs int
|
||||||
if constexpr (is_integer_v<A> && is_integer_v<B>)
|
if constexpr (is_integer<A> && is_integer<B>)
|
||||||
{
|
{
|
||||||
/// same signedness
|
/// same signedness
|
||||||
if constexpr (is_signed_v<A> == is_signed_v<B>)
|
if constexpr (is_signed_v<A> == is_signed_v<B>)
|
||||||
@ -49,7 +49,7 @@ bool lessOp(A a, B b)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// int vs float
|
/// int vs float
|
||||||
if constexpr (is_integer_v<A> && std::is_floating_point_v<B>)
|
if constexpr (is_integer<A> && std::is_floating_point_v<B>)
|
||||||
{
|
{
|
||||||
if constexpr (sizeof(A) <= 4)
|
if constexpr (sizeof(A) <= 4)
|
||||||
return static_cast<double>(a) < static_cast<double>(b);
|
return static_cast<double>(a) < static_cast<double>(b);
|
||||||
@ -57,7 +57,7 @@ bool lessOp(A a, B b)
|
|||||||
return DecomposedFloat<B>(b).greater(a);
|
return DecomposedFloat<B>(b).greater(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr (std::is_floating_point_v<A> && is_integer_v<B>)
|
if constexpr (std::is_floating_point_v<A> && is_integer<B>)
|
||||||
{
|
{
|
||||||
if constexpr (sizeof(B) <= 4)
|
if constexpr (sizeof(B) <= 4)
|
||||||
return static_cast<double>(a) < static_cast<double>(b);
|
return static_cast<double>(a) < static_cast<double>(b);
|
||||||
@ -65,8 +65,8 @@ bool lessOp(A a, B b)
|
|||||||
return DecomposedFloat<A>(a).less(b);
|
return DecomposedFloat<A>(a).less(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
static_assert(is_integer_v<A> || std::is_floating_point_v<A>);
|
static_assert(is_integer<A> || std::is_floating_point_v<A>);
|
||||||
static_assert(is_integer_v<B> || std::is_floating_point_v<B>);
|
static_assert(is_integer<B> || std::is_floating_point_v<B>);
|
||||||
__builtin_unreachable();
|
__builtin_unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,7 +109,7 @@ bool equalsOp(A a, B b)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
/// int vs int
|
/// int vs int
|
||||||
if constexpr (is_integer_v<A> && is_integer_v<B>)
|
if constexpr (is_integer<A> && is_integer<B>)
|
||||||
{
|
{
|
||||||
/// same signedness
|
/// same signedness
|
||||||
if constexpr (is_signed_v<A> == is_signed_v<B>)
|
if constexpr (is_signed_v<A> == is_signed_v<B>)
|
||||||
@ -125,7 +125,7 @@ bool equalsOp(A a, B b)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// int vs float
|
/// int vs float
|
||||||
if constexpr (is_integer_v<A> && std::is_floating_point_v<B>)
|
if constexpr (is_integer<A> && std::is_floating_point_v<B>)
|
||||||
{
|
{
|
||||||
if constexpr (sizeof(A) <= 4)
|
if constexpr (sizeof(A) <= 4)
|
||||||
return static_cast<double>(a) == static_cast<double>(b);
|
return static_cast<double>(a) == static_cast<double>(b);
|
||||||
@ -133,7 +133,7 @@ bool equalsOp(A a, B b)
|
|||||||
return DecomposedFloat<B>(b).equals(a);
|
return DecomposedFloat<B>(b).equals(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr (std::is_floating_point_v<A> && is_integer_v<B>)
|
if constexpr (std::is_floating_point_v<A> && is_integer<B>)
|
||||||
{
|
{
|
||||||
if constexpr (sizeof(B) <= 4)
|
if constexpr (sizeof(B) <= 4)
|
||||||
return static_cast<double>(a) == static_cast<double>(b);
|
return static_cast<double>(a) == static_cast<double>(b);
|
||||||
|
@ -47,21 +47,21 @@ template <> struct ConstructDecInt<32> { using Type = Int256; };
|
|||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
struct DecCompareInt
|
struct DecCompareInt
|
||||||
{
|
{
|
||||||
using Type = typename ConstructDecInt<(!IsDecimalNumber<U> || sizeof(T) > sizeof(U)) ? sizeof(T) : sizeof(U)>::Type;
|
using Type = typename ConstructDecInt<(!is_decimal<U> || sizeof(T) > sizeof(U)) ? sizeof(T) : sizeof(U)>::Type;
|
||||||
using TypeA = Type;
|
using TypeA = Type;
|
||||||
using TypeB = Type;
|
using TypeB = Type;
|
||||||
};
|
};
|
||||||
|
|
||||||
///
|
///
|
||||||
template <typename A, typename B, template <typename, typename> typename Operation, bool _check_overflow = true,
|
template <typename A, typename B, template <typename, typename> typename Operation, bool _check_overflow = true,
|
||||||
bool _actual = IsDecimalNumber<A> || IsDecimalNumber<B>>
|
bool _actual = is_decimal<A> || is_decimal<B>>
|
||||||
class DecimalComparison
|
class DecimalComparison
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using CompareInt = typename DecCompareInt<A, B>::Type;
|
using CompareInt = typename DecCompareInt<A, B>::Type;
|
||||||
using Op = Operation<CompareInt, CompareInt>;
|
using Op = Operation<CompareInt, CompareInt>;
|
||||||
using ColVecA = std::conditional_t<IsDecimalNumber<A>, ColumnDecimal<A>, ColumnVector<A>>;
|
using ColVecA = ColumnVectorOrDecimal<A>;
|
||||||
using ColVecB = std::conditional_t<IsDecimalNumber<B>, ColumnDecimal<B>, ColumnVector<B>>;
|
using ColVecB = ColumnVectorOrDecimal<B>;
|
||||||
|
|
||||||
using ArrayA = typename ColVecA::Container;
|
using ArrayA = typename ColVecA::Container;
|
||||||
using ArrayB = typename ColVecB::Container;
|
using ArrayB = typename ColVecB::Container;
|
||||||
@ -116,7 +116,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
static std::enable_if_t<IsDecimalNumber<T> && IsDecimalNumber<U>, Shift>
|
static std::enable_if_t<is_decimal<T> && is_decimal<U>, Shift>
|
||||||
getScales(const DataTypePtr & left_type, const DataTypePtr & right_type)
|
getScales(const DataTypePtr & left_type, const DataTypePtr & right_type)
|
||||||
{
|
{
|
||||||
const DataTypeDecimalBase<T> * decimal0 = checkDecimalBase<T>(*left_type);
|
const DataTypeDecimalBase<T> * decimal0 = checkDecimalBase<T>(*left_type);
|
||||||
@ -138,7 +138,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
static std::enable_if_t<IsDecimalNumber<T> && !IsDecimalNumber<U>, Shift>
|
static std::enable_if_t<is_decimal<T> && !is_decimal<U>, Shift>
|
||||||
getScales(const DataTypePtr & left_type, const DataTypePtr &)
|
getScales(const DataTypePtr & left_type, const DataTypePtr &)
|
||||||
{
|
{
|
||||||
Shift shift;
|
Shift shift;
|
||||||
@ -149,7 +149,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
static std::enable_if_t<!IsDecimalNumber<T> && IsDecimalNumber<U>, Shift>
|
static std::enable_if_t<!is_decimal<T> && is_decimal<U>, Shift>
|
||||||
getScales(const DataTypePtr &, const DataTypePtr & right_type)
|
getScales(const DataTypePtr &, const DataTypePtr & right_type)
|
||||||
{
|
{
|
||||||
Shift shift;
|
Shift shift;
|
||||||
@ -222,13 +222,13 @@ private:
|
|||||||
static NO_INLINE UInt8 apply(A a, B b, CompareInt scale [[maybe_unused]])
|
static NO_INLINE UInt8 apply(A a, B b, CompareInt scale [[maybe_unused]])
|
||||||
{
|
{
|
||||||
CompareInt x;
|
CompareInt x;
|
||||||
if constexpr (IsDecimalNumber<A>)
|
if constexpr (is_decimal<A>)
|
||||||
x = a.value;
|
x = a.value;
|
||||||
else
|
else
|
||||||
x = a;
|
x = a;
|
||||||
|
|
||||||
CompareInt y;
|
CompareInt y;
|
||||||
if constexpr (IsDecimalNumber<B>)
|
if constexpr (is_decimal<B>)
|
||||||
y = b.value;
|
y = b.value;
|
||||||
else
|
else
|
||||||
y = b;
|
y = b;
|
||||||
|
@ -223,16 +223,16 @@ inline typename DecimalType::NativeType getFractionalPart(const DecimalType & de
|
|||||||
template <typename To, typename DecimalType, typename ReturnType>
|
template <typename To, typename DecimalType, typename ReturnType>
|
||||||
ReturnType convertToImpl(const DecimalType & decimal, size_t scale, To & result)
|
ReturnType convertToImpl(const DecimalType & decimal, size_t scale, To & result)
|
||||||
{
|
{
|
||||||
using NativeT = typename DecimalType::NativeType;
|
using DecimalNativeType = typename DecimalType::NativeType;
|
||||||
static constexpr bool throw_exception = std::is_same_v<ReturnType, void>;
|
static constexpr bool throw_exception = std::is_void_v<ReturnType>;
|
||||||
|
|
||||||
if constexpr (std::is_floating_point_v<To>)
|
if constexpr (std::is_floating_point_v<To>)
|
||||||
{
|
{
|
||||||
result = static_cast<To>(decimal.value) / static_cast<To>(scaleMultiplier<NativeT>(scale));
|
result = static_cast<To>(decimal.value) / static_cast<To>(scaleMultiplier<DecimalNativeType>(scale));
|
||||||
}
|
}
|
||||||
else if constexpr (is_integer_v<To> && (sizeof(To) >= sizeof(NativeT)))
|
else if constexpr (is_integer<To> && (sizeof(To) >= sizeof(DecimalNativeType)))
|
||||||
{
|
{
|
||||||
NativeT whole = getWholePart(decimal, scale);
|
DecimalNativeType whole = getWholePart(decimal, scale);
|
||||||
|
|
||||||
if constexpr (is_unsigned_v<To>)
|
if constexpr (is_unsigned_v<To>)
|
||||||
{
|
{
|
||||||
@ -247,15 +247,14 @@ ReturnType convertToImpl(const DecimalType & decimal, size_t scale, To & result)
|
|||||||
|
|
||||||
result = static_cast<To>(whole);
|
result = static_cast<To>(whole);
|
||||||
}
|
}
|
||||||
else if constexpr (is_integer_v<To>)
|
else if constexpr (is_integer<To>)
|
||||||
{
|
{
|
||||||
using ToNativeT = typename NativeType<To>::Type;
|
using CastTo = std::conditional_t<(is_big_int_v<DecimalNativeType> && std::is_same_v<To, UInt8>), uint8_t, To>;
|
||||||
using CastTo = std::conditional_t<(is_big_int_v<NativeT> && std::is_same_v<ToNativeT, UInt8>), uint8_t, ToNativeT>;
|
|
||||||
|
|
||||||
const NativeT whole = getWholePart(decimal, scale);
|
const DecimalNativeType whole = getWholePart(decimal, scale);
|
||||||
|
|
||||||
static const constexpr CastTo min_to = std::numeric_limits<ToNativeT>::min();
|
static const constexpr CastTo min_to = std::numeric_limits<To>::min();
|
||||||
static const constexpr CastTo max_to = std::numeric_limits<ToNativeT>::max();
|
static const constexpr CastTo max_to = std::numeric_limits<To>::max();
|
||||||
|
|
||||||
if (whole < min_to || whole > max_to)
|
if (whole < min_to || whole > max_to)
|
||||||
{
|
{
|
||||||
|
@ -487,11 +487,11 @@ template bool decimalLessOrEqual<DateTime64>(DateTime64 x, DateTime64 y, UInt32
|
|||||||
inline void writeText(const Null & x, WriteBuffer & buf)
|
inline void writeText(const Null & x, WriteBuffer & buf)
|
||||||
{
|
{
|
||||||
if (x.isNegativeInfinity())
|
if (x.isNegativeInfinity())
|
||||||
writeText(std::string("-Inf"), buf);
|
writeText("-Inf", buf);
|
||||||
if (x.isPositiveInfinity())
|
if (x.isPositiveInfinity())
|
||||||
writeText(std::string("+Inf"), buf);
|
writeText("+Inf", buf);
|
||||||
else
|
else
|
||||||
writeText(std::string("NULL"), buf);
|
writeText("NULL", buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
String toString(const Field & x)
|
String toString(const Field & x)
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
#include <Core/UUID.h>
|
#include <Core/UUID.h>
|
||||||
#include <common/DayNum.h>
|
#include <common/DayNum.h>
|
||||||
#include <common/strong_typedef.h>
|
#include <common/strong_typedef.h>
|
||||||
|
#include <common/EnumReflection.h>
|
||||||
|
|
||||||
namespace DB
|
namespace DB
|
||||||
{
|
{
|
||||||
@ -283,33 +283,6 @@ public:
|
|||||||
Map = 26,
|
Map = 26,
|
||||||
UUID = 27,
|
UUID = 27,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char * toString(Which which)
|
|
||||||
{
|
|
||||||
switch (which)
|
|
||||||
{
|
|
||||||
case Null: return "Null";
|
|
||||||
case UInt64: return "UInt64";
|
|
||||||
case UInt128: return "UInt128";
|
|
||||||
case UInt256: return "UInt256";
|
|
||||||
case Int64: return "Int64";
|
|
||||||
case Int128: return "Int128";
|
|
||||||
case Int256: return "Int256";
|
|
||||||
case UUID: return "UUID";
|
|
||||||
case Float64: return "Float64";
|
|
||||||
case String: return "String";
|
|
||||||
case Array: return "Array";
|
|
||||||
case Tuple: return "Tuple";
|
|
||||||
case Map: return "Map";
|
|
||||||
case Decimal32: return "Decimal32";
|
|
||||||
case Decimal64: return "Decimal64";
|
|
||||||
case Decimal128: return "Decimal128";
|
|
||||||
case Decimal256: return "Decimal256";
|
|
||||||
case AggregateFunctionState: return "AggregateFunctionState";
|
|
||||||
}
|
|
||||||
|
|
||||||
throw Exception("Bad type of Field", ErrorCodes::BAD_TYPE_OF_FIELD);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -417,7 +390,8 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
Types::Which getType() const { return which; }
|
Types::Which getType() const { return which; }
|
||||||
const char * getTypeName() const { return Types::toString(which); }
|
|
||||||
|
constexpr std::string_view getTypeName() const { return magic_enum::enum_name(which); }
|
||||||
|
|
||||||
bool isNull() const { return which == Types::Null; }
|
bool isNull() const { return which == Types::Null; }
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -808,7 +782,8 @@ NearestFieldType<std::decay_t<T>> & Field::get()
|
|||||||
constexpr Field::Types::Which target = TypeToEnum<StoredType>::value;
|
constexpr Field::Types::Which target = TypeToEnum<StoredType>::value;
|
||||||
if (target != which
|
if (target != which
|
||||||
&& (!isInt64OrUInt64FieldType(target) || !isInt64OrUInt64FieldType(which)))
|
&& (!isInt64OrUInt64FieldType(target) || !isInt64OrUInt64FieldType(which)))
|
||||||
throw Exception(ErrorCodes::LOGICAL_ERROR, "Invalid Field get from type {} to type {}", Types::toString(which), Types::toString(target));
|
throw Exception(ErrorCodes::LOGICAL_ERROR,
|
||||||
|
"Invalid Field get from type {} to type {}", which, target);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
StoredType * MAY_ALIAS ptr = reinterpret_cast<StoredType *>(&storage);
|
StoredType * MAY_ALIAS ptr = reinterpret_cast<StoredType *>(&storage);
|
||||||
@ -821,8 +796,11 @@ template <typename T>
|
|||||||
auto & Field::safeGet()
|
auto & Field::safeGet()
|
||||||
{
|
{
|
||||||
const Types::Which requested = TypeToEnum<NearestFieldType<std::decay_t<T>>>::value;
|
const Types::Which requested = TypeToEnum<NearestFieldType<std::decay_t<T>>>::value;
|
||||||
|
|
||||||
if (which != requested)
|
if (which != requested)
|
||||||
throw Exception("Bad get: has " + std::string(getTypeName()) + ", requested " + std::string(Types::toString(requested)), ErrorCodes::BAD_GET);
|
throw Exception(ErrorCodes::BAD_GET,
|
||||||
|
"Bad get: has {}, requested {}", getTypeName(), requested);
|
||||||
|
|
||||||
return get<T>();
|
return get<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -859,12 +837,6 @@ T safeGet(Field & field)
|
|||||||
return field.template safeGet<T>();
|
return field.template safeGet<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <> inline constexpr const char * TypeName<Array> = "Array";
|
|
||||||
template <> inline constexpr const char * TypeName<Tuple> = "Tuple";
|
|
||||||
template <> inline constexpr const char * TypeName<Map> = "Map";
|
|
||||||
template <> inline constexpr const char * TypeName<AggregateFunctionStateData> = "AggregateFunctionState";
|
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
Field::Field(T && rhs, enable_if_not_field_or_bool_or_stringlike_t<T>) //-V730
|
Field::Field(T && rhs, enable_if_not_field_or_bool_or_stringlike_t<T>) //-V730
|
||||||
{
|
{
|
||||||
|
61
src/Core/TypeId.h
Normal file
61
src/Core/TypeId.h
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Core/Types.h>
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Obtain TypeIndex value from real type if possible.
|
||||||
|
*
|
||||||
|
* Returns TypeIndex::Nothing if type was not present in TypeIndex;
|
||||||
|
* Returns TypeIndex element otherwise.
|
||||||
|
*
|
||||||
|
* @example TypeId<UInt8> == TypeIndex::UInt8
|
||||||
|
* @example TypeId<MySuperType> == TypeIndex::Nothing
|
||||||
|
*/
|
||||||
|
template <class T> inline constexpr TypeIndex TypeId = TypeIndex::Nothing;
|
||||||
|
|
||||||
|
template <TypeIndex index> struct ReverseTypeIdT : std::false_type {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtain real type from TypeIndex if possible.
|
||||||
|
*
|
||||||
|
* Returns a type alias if is corresponds to TypeIndex value.
|
||||||
|
* Yields a compiler error otherwise.
|
||||||
|
*
|
||||||
|
* @example ReverseTypeId<TypeIndex::UInt8> == UInt8
|
||||||
|
*/
|
||||||
|
template <TypeIndex index> using ReverseTypeId = typename ReverseTypeIdT<index>::T;
|
||||||
|
template <TypeIndex index> constexpr bool HasReverseTypeId = ReverseTypeIdT<index>::value;
|
||||||
|
|
||||||
|
#define TYPEID_MAP(_A) \
|
||||||
|
template <> inline constexpr TypeIndex TypeId<_A> = TypeIndex::_A; \
|
||||||
|
template <> struct ReverseTypeIdT<TypeIndex::_A> : std::true_type { using T = _A; };
|
||||||
|
|
||||||
|
TYPEID_MAP(UInt8)
|
||||||
|
TYPEID_MAP(UInt16)
|
||||||
|
TYPEID_MAP(UInt32)
|
||||||
|
TYPEID_MAP(UInt64)
|
||||||
|
TYPEID_MAP(UInt128)
|
||||||
|
TYPEID_MAP(UInt256)
|
||||||
|
TYPEID_MAP(Int8)
|
||||||
|
TYPEID_MAP(Int16)
|
||||||
|
TYPEID_MAP(Int32)
|
||||||
|
TYPEID_MAP(Int64)
|
||||||
|
TYPEID_MAP(Int128)
|
||||||
|
TYPEID_MAP(Int256)
|
||||||
|
TYPEID_MAP(Float32)
|
||||||
|
TYPEID_MAP(Float64)
|
||||||
|
TYPEID_MAP(UUID)
|
||||||
|
|
||||||
|
TYPEID_MAP(Decimal32)
|
||||||
|
TYPEID_MAP(Decimal64)
|
||||||
|
TYPEID_MAP(Decimal128)
|
||||||
|
TYPEID_MAP(Decimal256)
|
||||||
|
TYPEID_MAP(DateTime64)
|
||||||
|
|
||||||
|
TYPEID_MAP(String)
|
||||||
|
|
||||||
|
struct Array;
|
||||||
|
TYPEID_MAP(Array)
|
||||||
|
}
|
39
src/Core/TypeName.h
Normal file
39
src/Core/TypeName.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Core/Types.h>
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
struct Array;
|
||||||
|
struct Tuple;
|
||||||
|
struct Map;
|
||||||
|
struct AggregateFunctionStateData;
|
||||||
|
|
||||||
|
template <class T> constexpr const char * TypeName = "";
|
||||||
|
|
||||||
|
template <> inline constexpr const char * TypeName<UInt8> = "UInt8";
|
||||||
|
template <> inline constexpr const char * TypeName<UInt16> = "UInt16";
|
||||||
|
template <> inline constexpr const char * TypeName<UInt32> = "UInt32";
|
||||||
|
template <> inline constexpr const char * TypeName<UInt64> = "UInt64";
|
||||||
|
template <> inline constexpr const char * TypeName<UInt128> = "UInt128";
|
||||||
|
template <> inline constexpr const char * TypeName<UInt256> = "UInt256";
|
||||||
|
template <> inline constexpr const char * TypeName<Int8> = "Int8";
|
||||||
|
template <> inline constexpr const char * TypeName<Int16> = "Int16";
|
||||||
|
template <> inline constexpr const char * TypeName<Int32> = "Int32";
|
||||||
|
template <> inline constexpr const char * TypeName<Int64> = "Int64";
|
||||||
|
template <> inline constexpr const char * TypeName<Int128> = "Int128";
|
||||||
|
template <> inline constexpr const char * TypeName<Int256> = "Int256";
|
||||||
|
template <> inline constexpr const char * TypeName<Float32> = "Float32";
|
||||||
|
template <> inline constexpr const char * TypeName<Float64> = "Float64";
|
||||||
|
template <> inline constexpr const char * TypeName<String> = "String";
|
||||||
|
template <> inline constexpr const char * TypeName<UUID> = "UUID";
|
||||||
|
template <> inline constexpr const char * TypeName<Decimal32> = "Decimal32";
|
||||||
|
template <> inline constexpr const char * TypeName<Decimal64> = "Decimal64";
|
||||||
|
template <> inline constexpr const char * TypeName<Decimal128> = "Decimal128";
|
||||||
|
template <> inline constexpr const char * TypeName<Decimal256> = "Decimal256";
|
||||||
|
template <> inline constexpr const char * TypeName<DateTime64> = "DateTime64";
|
||||||
|
template <> inline constexpr const char * TypeName<Array> = "Array";
|
||||||
|
template <> inline constexpr const char * TypeName<Tuple> = "Tuple";
|
||||||
|
template <> inline constexpr const char * TypeName<Map> = "Map";
|
||||||
|
template <> inline constexpr const char * TypeName<AggregateFunctionStateData> = "AggregateFunctionState";
|
||||||
|
}
|
250
src/Core/Types.h
250
src/Core/Types.h
@ -4,7 +4,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <common/strong_typedef.h>
|
#include <common/strong_typedef.h>
|
||||||
#include <common/extended_types.h>
|
#include <common/Decimal.h>
|
||||||
#include <common/defines.h>
|
#include <common/defines.h>
|
||||||
|
|
||||||
|
|
||||||
@ -99,254 +99,6 @@ using Int256 = ::Int256;
|
|||||||
|
|
||||||
STRONG_TYPEDEF(UInt128, UUID)
|
STRONG_TYPEDEF(UInt128, UUID)
|
||||||
|
|
||||||
|
|
||||||
template <typename T> constexpr const char * TypeName = "";
|
|
||||||
|
|
||||||
template <> inline constexpr const char * TypeName<UInt8> = "UInt8";
|
|
||||||
template <> inline constexpr const char * TypeName<UInt16> = "UInt16";
|
|
||||||
template <> inline constexpr const char * TypeName<UInt32> = "UInt32";
|
|
||||||
template <> inline constexpr const char * TypeName<UInt64> = "UInt64";
|
|
||||||
template <> inline constexpr const char * TypeName<UInt128> = "UInt128";
|
|
||||||
template <> inline constexpr const char * TypeName<UInt256> = "UInt256";
|
|
||||||
template <> inline constexpr const char * TypeName<Int8> = "Int8";
|
|
||||||
template <> inline constexpr const char * TypeName<Int16> = "Int16";
|
|
||||||
template <> inline constexpr const char * TypeName<Int32> = "Int32";
|
|
||||||
template <> inline constexpr const char * TypeName<Int64> = "Int64";
|
|
||||||
template <> inline constexpr const char * TypeName<Int128> = "Int128";
|
|
||||||
template <> inline constexpr const char * TypeName<Int256> = "Int256";
|
|
||||||
template <> inline constexpr const char * TypeName<Float32> = "Float32";
|
|
||||||
template <> inline constexpr const char * TypeName<Float64> = "Float64";
|
|
||||||
template <> inline constexpr const char * TypeName<String> = "String";
|
|
||||||
template <> inline constexpr const char * TypeName<UUID> = "UUID";
|
|
||||||
|
|
||||||
/// TODO Try to remove it.
|
|
||||||
template <typename T> constexpr TypeIndex TypeId = TypeIndex::Nothing;
|
|
||||||
template <> inline constexpr TypeIndex TypeId<UInt8> = TypeIndex::UInt8;
|
|
||||||
template <> inline constexpr TypeIndex TypeId<UInt16> = TypeIndex::UInt16;
|
|
||||||
template <> inline constexpr TypeIndex TypeId<UInt32> = TypeIndex::UInt32;
|
|
||||||
template <> inline constexpr TypeIndex TypeId<UInt64> = TypeIndex::UInt64;
|
|
||||||
template <> inline constexpr TypeIndex TypeId<UInt128> = TypeIndex::UInt128;
|
|
||||||
template <> inline constexpr TypeIndex TypeId<UInt256> = TypeIndex::UInt256;
|
|
||||||
template <> inline constexpr TypeIndex TypeId<Int8> = TypeIndex::Int8;
|
|
||||||
template <> inline constexpr TypeIndex TypeId<Int16> = TypeIndex::Int16;
|
|
||||||
template <> inline constexpr TypeIndex TypeId<Int32> = TypeIndex::Int32;
|
|
||||||
template <> inline constexpr TypeIndex TypeId<Int64> = TypeIndex::Int64;
|
|
||||||
template <> inline constexpr TypeIndex TypeId<Int128> = TypeIndex::Int128;
|
|
||||||
template <> inline constexpr TypeIndex TypeId<Int256> = TypeIndex::Int256;
|
|
||||||
template <> inline constexpr TypeIndex TypeId<Float32> = TypeIndex::Float32;
|
|
||||||
template <> inline constexpr TypeIndex TypeId<Float64> = TypeIndex::Float64;
|
|
||||||
template <> inline constexpr TypeIndex TypeId<UUID> = TypeIndex::UUID;
|
|
||||||
|
|
||||||
|
|
||||||
/// Not a data type in database, defined just for convenience.
|
/// Not a data type in database, defined just for convenience.
|
||||||
using Strings = std::vector<String>;
|
using Strings = std::vector<String>;
|
||||||
|
|
||||||
/// 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
|
|
||||||
{
|
|
||||||
using NativeType = T;
|
|
||||||
|
|
||||||
Decimal() = default;
|
|
||||||
Decimal(Decimal<T> &&) = default;
|
|
||||||
Decimal(const Decimal<T> &) = default;
|
|
||||||
|
|
||||||
Decimal(const T & value_)
|
|
||||||
: value(value_)
|
|
||||||
{}
|
|
||||||
|
|
||||||
template <typename U>
|
|
||||||
Decimal(const Decimal<U> & x)
|
|
||||||
: value(x.value)
|
|
||||||
{}
|
|
||||||
|
|
||||||
constexpr Decimal<T> & operator = (Decimal<T> &&) = default;
|
|
||||||
constexpr Decimal<T> & operator = (const Decimal<T> &) = default;
|
|
||||||
|
|
||||||
operator T () const { return value; }
|
|
||||||
|
|
||||||
template <typename U>
|
|
||||||
U convertTo() const
|
|
||||||
{
|
|
||||||
/// no IsDecimalNumber defined yet
|
|
||||||
if constexpr (std::is_same_v<U, Decimal<Int32>> ||
|
|
||||||
std::is_same_v<U, Decimal<Int64>> ||
|
|
||||||
std::is_same_v<U, Decimal<Int128>> ||
|
|
||||||
std::is_same_v<U, Decimal<Int256>>)
|
|
||||||
{
|
|
||||||
return convertTo<typename U::NativeType>();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return static_cast<U>(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; }
|
|
||||||
|
|
||||||
template <typename U> const Decimal<T> & operator += (const Decimal<U> & x) { value += x.value; return *this; }
|
|
||||||
template <typename U> const Decimal<T> & operator -= (const Decimal<U> & x) { value -= x.value; return *this; }
|
|
||||||
template <typename U> const Decimal<T> & operator *= (const Decimal<U> & x) { value *= x.value; return *this; }
|
|
||||||
template <typename U> const Decimal<T> & operator /= (const Decimal<U> & x) { value /= x.value; return *this; }
|
|
||||||
template <typename U> const Decimal<T> & operator %= (const Decimal<U> & x) { value %= x.value; return *this; }
|
|
||||||
|
|
||||||
/// This is to avoid UB for sumWithOverflow()
|
|
||||||
void NO_SANITIZE_UNDEFINED addOverflow(const T & x) { value += x; }
|
|
||||||
|
|
||||||
T value;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T> inline bool operator< (const Decimal<T> & x, const Decimal<T> & y) { return x.value < y.value; }
|
|
||||||
template <typename T> inline bool operator> (const Decimal<T> & x, const Decimal<T> & y) { return x.value > y.value; }
|
|
||||||
template <typename T> inline bool operator<= (const Decimal<T> & x, const Decimal<T> & y) { return x.value <= y.value; }
|
|
||||||
template <typename T> inline bool operator>= (const Decimal<T> & x, const Decimal<T> & y) { return x.value >= y.value; }
|
|
||||||
template <typename T> inline bool operator== (const Decimal<T> & x, const Decimal<T> & y) { return x.value == y.value; }
|
|
||||||
template <typename T> inline bool operator!= (const Decimal<T> & x, const Decimal<T> & y) { return x.value != y.value; }
|
|
||||||
|
|
||||||
template <typename T> inline Decimal<T> operator+ (const Decimal<T> & x, const Decimal<T> & y) { return x.value + y.value; }
|
|
||||||
template <typename T> inline Decimal<T> operator- (const Decimal<T> & x, const Decimal<T> & y) { return x.value - y.value; }
|
|
||||||
template <typename T> inline Decimal<T> operator* (const Decimal<T> & x, const Decimal<T> & y) { return x.value * y.value; }
|
|
||||||
template <typename T> inline Decimal<T> operator/ (const Decimal<T> & x, const Decimal<T> & y) { return x.value / y.value; }
|
|
||||||
template <typename T> inline Decimal<T> operator- (const Decimal<T> & x) { return -x.value; }
|
|
||||||
|
|
||||||
using Decimal32 = Decimal<Int32>;
|
|
||||||
using Decimal64 = Decimal<Int64>;
|
|
||||||
using Decimal128 = Decimal<Int128>;
|
|
||||||
using Decimal256 = Decimal<Int256>;
|
|
||||||
|
|
||||||
// Distinguishable type to allow function resolution/deduction based on value type,
|
|
||||||
// but also relatively easy to convert to/from Decimal64.
|
|
||||||
class DateTime64 : public Decimal64
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using Base = Decimal64;
|
|
||||||
using Base::Base;
|
|
||||||
|
|
||||||
DateTime64(const Base & v)
|
|
||||||
: Base(v)
|
|
||||||
{}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <> inline constexpr const char * TypeName<Decimal32> = "Decimal32";
|
|
||||||
template <> inline constexpr const char * TypeName<Decimal64> = "Decimal64";
|
|
||||||
template <> inline constexpr const char * TypeName<Decimal128> = "Decimal128";
|
|
||||||
template <> inline constexpr const char * TypeName<Decimal256> = "Decimal256";
|
|
||||||
template <> inline constexpr const char * TypeName<DateTime64> = "DateTime64";
|
|
||||||
|
|
||||||
template <> inline constexpr TypeIndex TypeId<Decimal32> = TypeIndex::Decimal32;
|
|
||||||
template <> inline constexpr TypeIndex TypeId<Decimal64> = TypeIndex::Decimal64;
|
|
||||||
template <> inline constexpr TypeIndex TypeId<Decimal128> = TypeIndex::Decimal128;
|
|
||||||
template <> inline constexpr TypeIndex TypeId<Decimal256> = TypeIndex::Decimal256;
|
|
||||||
template <> inline constexpr TypeIndex TypeId<DateTime64> = TypeIndex::DateTime64;
|
|
||||||
|
|
||||||
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;
|
|
||||||
template <> inline constexpr bool IsDecimalNumber<Decimal256> = true;
|
|
||||||
template <> inline constexpr bool IsDecimalNumber<DateTime64> = true;
|
|
||||||
|
|
||||||
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; };
|
|
||||||
template <> struct NativeType<Decimal256> { using Type = Int256; };
|
|
||||||
template <> struct NativeType<DateTime64> { using Type = Int64; };
|
|
||||||
|
|
||||||
template <typename T> constexpr bool OverBigInt = false;
|
|
||||||
template <> inline constexpr bool OverBigInt<Int128> = true;
|
|
||||||
template <> inline constexpr bool OverBigInt<UInt128> = true;
|
|
||||||
template <> inline constexpr bool OverBigInt<Int256> = true;
|
|
||||||
template <> inline constexpr bool OverBigInt<UInt256> = true;
|
|
||||||
template <> inline constexpr bool OverBigInt<Decimal128> = true;
|
|
||||||
template <> inline constexpr bool OverBigInt<Decimal256> = true;
|
|
||||||
|
|
||||||
inline constexpr const char * getTypeName(TypeIndex idx)
|
|
||||||
{
|
|
||||||
switch (idx)
|
|
||||||
{
|
|
||||||
case TypeIndex::Nothing: return "Nothing";
|
|
||||||
case TypeIndex::UInt8: return "UInt8";
|
|
||||||
case TypeIndex::UInt16: return "UInt16";
|
|
||||||
case TypeIndex::UInt32: return "UInt32";
|
|
||||||
case TypeIndex::UInt64: return "UInt64";
|
|
||||||
case TypeIndex::UInt128: return "UInt128";
|
|
||||||
case TypeIndex::UInt256: return "UInt256";
|
|
||||||
case TypeIndex::Int8: return "Int8";
|
|
||||||
case TypeIndex::Int16: return "Int16";
|
|
||||||
case TypeIndex::Int32: return "Int32";
|
|
||||||
case TypeIndex::Int64: return "Int64";
|
|
||||||
case TypeIndex::Int128: return "Int128";
|
|
||||||
case TypeIndex::Int256: return "Int256";
|
|
||||||
case TypeIndex::Float32: return "Float32";
|
|
||||||
case TypeIndex::Float64: return "Float64";
|
|
||||||
case TypeIndex::Date: return "Date";
|
|
||||||
case TypeIndex::Date32: return "Date32";
|
|
||||||
case TypeIndex::DateTime: return "DateTime";
|
|
||||||
case TypeIndex::DateTime64: return "DateTime64";
|
|
||||||
case TypeIndex::String: return "String";
|
|
||||||
case TypeIndex::FixedString: return "FixedString";
|
|
||||||
case TypeIndex::Enum8: return "Enum8";
|
|
||||||
case TypeIndex::Enum16: return "Enum16";
|
|
||||||
case TypeIndex::Decimal32: return "Decimal32";
|
|
||||||
case TypeIndex::Decimal64: return "Decimal64";
|
|
||||||
case TypeIndex::Decimal128: return "Decimal128";
|
|
||||||
case TypeIndex::Decimal256: return "Decimal256";
|
|
||||||
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";
|
|
||||||
case TypeIndex::Map: return "Map";
|
|
||||||
}
|
|
||||||
|
|
||||||
__builtin_unreachable();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
struct hash<DB::DateTime64>
|
|
||||||
{
|
|
||||||
size_t operator()(const DB::DateTime64 & x) const
|
|
||||||
{
|
|
||||||
return std::hash<std::decay_t<decltype(x)>::NativeType>()(x);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
template <>
|
|
||||||
struct hash<DB::Decimal256>
|
|
||||||
{
|
|
||||||
size_t operator()(const DB::Decimal256 & x) const
|
|
||||||
{
|
|
||||||
// temp solution
|
|
||||||
static constexpr DB::UInt64 max_uint_mask = std::numeric_limits<DB::UInt64>::max();
|
|
||||||
return std::hash<DB::Int64>()(static_cast<DB::Int64>(x.value >> 64 & max_uint_mask))
|
|
||||||
^ std::hash<DB::Int64>()(static_cast<DB::Int64>(x.value & max_uint_mask));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
@ -164,7 +164,7 @@ class DataTypeDateTime;
|
|||||||
class DataTypeDateTime64;
|
class DataTypeDateTime64;
|
||||||
template <typename T> class DataTypeEnum;
|
template <typename T> class DataTypeEnum;
|
||||||
template <typename T> class DataTypeNumber;
|
template <typename T> class DataTypeNumber;
|
||||||
template <typename T> class DataTypeDecimal;
|
template <is_decimal T> class DataTypeDecimal;
|
||||||
|
|
||||||
|
|
||||||
template <typename T, typename F, typename... ExtraArgs>
|
template <typename T, typename F, typename... ExtraArgs>
|
||||||
|
@ -28,19 +28,19 @@ bool decimalCheckArithmeticOverflow(ContextPtr context)
|
|||||||
return context->getSettingsRef().decimal_check_overflow;
|
return context->getSettingsRef().decimal_check_overflow;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <is_decimal T>
|
||||||
Field DataTypeDecimalBase<T>::getDefault() const
|
Field DataTypeDecimalBase<T>::getDefault() const
|
||||||
{
|
{
|
||||||
return DecimalField(T(0), scale);
|
return DecimalField(T(0), scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <is_decimal T>
|
||||||
MutableColumnPtr DataTypeDecimalBase<T>::createColumn() const
|
MutableColumnPtr DataTypeDecimalBase<T>::createColumn() const
|
||||||
{
|
{
|
||||||
return ColumnType::create(0, scale);
|
return ColumnType::create(0, scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <is_decimal T>
|
||||||
T DataTypeDecimalBase<T>::getScaleMultiplier(UInt32 scale_)
|
T DataTypeDecimalBase<T>::getScaleMultiplier(UInt32 scale_)
|
||||||
{
|
{
|
||||||
return DecimalUtils::scaleMultiplier<typename T::NativeType>(scale_);
|
return DecimalUtils::scaleMultiplier<typename T::NativeType>(scale_);
|
||||||
|
@ -53,11 +53,9 @@ inline UInt32 leastDecimalPrecisionFor(TypeIndex int_type)
|
|||||||
/// Operation between two decimals leads to Decimal(P, S), where
|
/// Operation between two decimals leads to Decimal(P, S), where
|
||||||
/// P is one of (9, 18, 38, 76); equals to the maximum precision for the biggest underlying type of operands.
|
/// P is one of (9, 18, 38, 76); equals to the maximum precision for the biggest underlying type of operands.
|
||||||
/// S is maximum scale of operands. The allowed valuas are [0, precision]
|
/// S is maximum scale of operands. The allowed valuas are [0, precision]
|
||||||
template <typename T>
|
template <is_decimal T>
|
||||||
class DataTypeDecimalBase : public IDataType
|
class DataTypeDecimalBase : public IDataType
|
||||||
{
|
{
|
||||||
static_assert(IsDecimalNumber<T>);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using FieldType = T;
|
using FieldType = T;
|
||||||
using ColumnType = ColumnDecimal<T>;
|
using ColumnType = ColumnDecimal<T>;
|
||||||
|
@ -134,7 +134,8 @@ Field DataTypeEnum<Type>::castToName(const Field & value_or_name) const
|
|||||||
return this->getNameForValue(static_cast<Type>(value)).toString();
|
return this->getNameForValue(static_cast<Type>(value)).toString();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw Exception(String("DataTypeEnum: Unsupported type of field ") + value_or_name.getTypeName(), ErrorCodes::BAD_TYPE_OF_FIELD);
|
throw Exception(ErrorCodes::BAD_TYPE_OF_FIELD,
|
||||||
|
"DataTypeEnum: Unsupported type of field {}", value_or_name.getTypeName());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Type>
|
template <typename Type>
|
||||||
@ -153,7 +154,8 @@ Field DataTypeEnum<Type>::castToValue(const Field & value_or_name) const
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw Exception(String("DataTypeEnum: Unsupported type of field ") + value_or_name.getTypeName(), ErrorCodes::BAD_TYPE_OF_FIELD);
|
throw Exception(ErrorCodes::BAD_TYPE_OF_FIELD,
|
||||||
|
"DataTypeEnum: Unsupported type of field {}", value_or_name.getTypeName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ public:
|
|||||||
|
|
||||||
DataTypeInterval(IntervalKind kind_) : kind(kind_) {}
|
DataTypeInterval(IntervalKind kind_) : kind(kind_) {}
|
||||||
|
|
||||||
std::string doGetName() const override { return std::string("Interval") + kind.toString(); }
|
std::string doGetName() const override { return fmt::format("Interval{}", kind.toString()); }
|
||||||
const char * getFamilyName() const override { return "Interval"; }
|
const char * getFamilyName() const override { return "Interval"; }
|
||||||
TypeIndex getTypeId() const override { return TypeIndex::Interval; }
|
TypeIndex getTypeId() const override { return TypeIndex::Interval; }
|
||||||
|
|
||||||
|
@ -28,13 +28,13 @@ MutableColumnPtr DataTypeNumberBase<T>::createColumn() const
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
bool DataTypeNumberBase<T>::isValueRepresentedByInteger() const
|
bool DataTypeNumberBase<T>::isValueRepresentedByInteger() const
|
||||||
{
|
{
|
||||||
return is_integer_v<T>;
|
return is_integer<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool DataTypeNumberBase<T>::isValueRepresentedByUnsignedInteger() const
|
bool DataTypeNumberBase<T>::isValueRepresentedByUnsignedInteger() const
|
||||||
{
|
{
|
||||||
return is_integer_v<T> && is_unsigned_v<T>;
|
return is_integer<T> && is_unsigned_v<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -25,14 +25,14 @@ namespace ErrorCodes
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <is_decimal T>
|
||||||
std::string DataTypeDecimal<T>::doGetName() const
|
std::string DataTypeDecimal<T>::doGetName() const
|
||||||
{
|
{
|
||||||
return fmt::format("Decimal({}, {})", this->precision, this->scale);
|
return fmt::format("Decimal({}, {})", this->precision, this->scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <is_decimal T>
|
||||||
bool DataTypeDecimal<T>::equals(const IDataType & rhs) const
|
bool DataTypeDecimal<T>::equals(const IDataType & rhs) const
|
||||||
{
|
{
|
||||||
if (auto * ptype = typeid_cast<const DataTypeDecimal<T> *>(&rhs))
|
if (auto * ptype = typeid_cast<const DataTypeDecimal<T> *>(&rhs))
|
||||||
@ -40,14 +40,14 @@ bool DataTypeDecimal<T>::equals(const IDataType & rhs) const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <is_decimal T>
|
||||||
DataTypePtr DataTypeDecimal<T>::promoteNumericType() const
|
DataTypePtr DataTypeDecimal<T>::promoteNumericType() const
|
||||||
{
|
{
|
||||||
using PromotedType = DataTypeDecimal<Decimal128>;
|
using PromotedType = DataTypeDecimal<Decimal128>;
|
||||||
return std::make_shared<PromotedType>(PromotedType::maxPrecision(), this->scale);
|
return std::make_shared<PromotedType>(PromotedType::maxPrecision(), this->scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <is_decimal T>
|
||||||
T DataTypeDecimal<T>::parseFromString(const String & str) const
|
T DataTypeDecimal<T>::parseFromString(const String & str) const
|
||||||
{
|
{
|
||||||
ReadBufferFromMemory buf(str.data(), str.size());
|
ReadBufferFromMemory buf(str.data(), str.size());
|
||||||
@ -61,7 +61,7 @@ T DataTypeDecimal<T>::parseFromString(const String & str) const
|
|||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <is_decimal T>
|
||||||
SerializationPtr DataTypeDecimal<T>::doGetDefaultSerialization() const
|
SerializationPtr DataTypeDecimal<T>::doGetDefaultSerialization() const
|
||||||
{
|
{
|
||||||
return std::make_shared<SerializationDecimal<T>>(this->precision, this->scale);
|
return std::make_shared<SerializationDecimal<T>>(this->precision, this->scale);
|
||||||
|
@ -24,11 +24,10 @@ namespace ErrorCodes
|
|||||||
/// Operation between two decimals leads to Decimal(P, S), where
|
/// Operation between two decimals leads to Decimal(P, S), where
|
||||||
/// P is one of (9, 18, 38, 76); equals to the maximum precision for the biggest underlying type of operands.
|
/// P is one of (9, 18, 38, 76); equals to the maximum precision for the biggest underlying type of operands.
|
||||||
/// S is maximum scale of operands. The allowed valuas are [0, precision]
|
/// S is maximum scale of operands. The allowed valuas are [0, precision]
|
||||||
template <typename T>
|
template <is_decimal T>
|
||||||
class DataTypeDecimal final : public DataTypeDecimalBase<T>
|
class DataTypeDecimal final : public DataTypeDecimalBase<T>
|
||||||
{
|
{
|
||||||
using Base = DataTypeDecimalBase<T>;
|
using Base = DataTypeDecimalBase<T>;
|
||||||
static_assert(IsDecimalNumber<T>);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using typename Base::FieldType;
|
using typename Base::FieldType;
|
||||||
@ -48,6 +47,11 @@ public:
|
|||||||
SerializationPtr doGetDefaultSerialization() const override;
|
SerializationPtr doGetDefaultSerialization() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using DataTypeDecimal32 = DataTypeDecimal<Decimal32>;
|
||||||
|
using DataTypeDecimal64 = DataTypeDecimal<Decimal64>;
|
||||||
|
using DataTypeDecimal128 = DataTypeDecimal<Decimal128>;
|
||||||
|
using DataTypeDecimal256 = DataTypeDecimal<Decimal256>;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline const DataTypeDecimal<T> * checkDecimal(const IDataType & data_type)
|
inline const DataTypeDecimal<T> * checkDecimal(const IDataType & data_type)
|
||||||
{
|
{
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
#include <Common/COW.h>
|
#include <Common/COW.h>
|
||||||
#include <boost/noncopyable.hpp>
|
#include <boost/noncopyable.hpp>
|
||||||
#include <Core/Names.h>
|
#include <Core/Names.h>
|
||||||
#include <Core/Types.h>
|
#include <Core/TypeId.h>
|
||||||
#include <DataTypes/DataTypeCustom.h>
|
#include <DataTypes/DataTypeCustom.h>
|
||||||
|
|
||||||
|
|
||||||
@ -490,7 +490,7 @@ template <typename DataType> constexpr bool IsDataTypeDateOrDateTime = false;
|
|||||||
|
|
||||||
template <typename DataType> constexpr bool IsDataTypeDecimalOrNumber = IsDataTypeDecimal<DataType> || IsDataTypeNumber<DataType>;
|
template <typename DataType> constexpr bool IsDataTypeDecimalOrNumber = IsDataTypeDecimal<DataType> || IsDataTypeNumber<DataType>;
|
||||||
|
|
||||||
template <typename T>
|
template <is_decimal T>
|
||||||
class DataTypeDecimal;
|
class DataTypeDecimal;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -501,7 +501,7 @@ class DataTypeDate32;
|
|||||||
class DataTypeDateTime;
|
class DataTypeDateTime;
|
||||||
class DataTypeDateTime64;
|
class DataTypeDateTime64;
|
||||||
|
|
||||||
template <typename T> constexpr bool IsDataTypeDecimal<DataTypeDecimal<T>> = true;
|
template <is_decimal T> constexpr bool IsDataTypeDecimal<DataTypeDecimal<T>> = true;
|
||||||
template <> inline constexpr bool IsDataTypeDecimal<DataTypeDateTime64> = true;
|
template <> inline constexpr bool IsDataTypeDecimal<DataTypeDateTime64> = true;
|
||||||
|
|
||||||
template <typename T> constexpr bool IsDataTypeNumber<DataTypeNumber<T>> = true;
|
template <typename T> constexpr bool IsDataTypeNumber<DataTypeNumber<T>> = true;
|
||||||
|
@ -172,14 +172,14 @@ template <typename A, typename B>
|
|||||||
struct ResultOfIf
|
struct ResultOfIf
|
||||||
{
|
{
|
||||||
static constexpr bool has_float = std::is_floating_point_v<A> || std::is_floating_point_v<B>;
|
static constexpr bool has_float = std::is_floating_point_v<A> || std::is_floating_point_v<B>;
|
||||||
static constexpr bool has_integer = is_integer_v<A> || is_integer_v<B>;
|
static constexpr bool has_integer = is_integer<A> || is_integer<B>;
|
||||||
static constexpr bool has_signed = is_signed_v<A> || is_signed_v<B>;
|
static constexpr bool has_signed = is_signed_v<A> || is_signed_v<B>;
|
||||||
static constexpr bool has_unsigned = !is_signed_v<A> || !is_signed_v<B>;
|
static constexpr bool has_unsigned = !is_signed_v<A> || !is_signed_v<B>;
|
||||||
static constexpr bool has_big_int = is_big_int_v<A> || is_big_int_v<B>;
|
static constexpr bool has_big_int = is_big_int_v<A> || is_big_int_v<B>;
|
||||||
|
|
||||||
static constexpr size_t max_size_of_unsigned_integer = max(is_signed_v<A> ? 0 : sizeof(A), is_signed_v<B> ? 0 : sizeof(B));
|
static constexpr size_t max_size_of_unsigned_integer = max(is_signed_v<A> ? 0 : sizeof(A), is_signed_v<B> ? 0 : sizeof(B));
|
||||||
static constexpr size_t max_size_of_signed_integer = max(is_signed_v<A> ? sizeof(A) : 0, is_signed_v<B> ? sizeof(B) : 0);
|
static constexpr size_t max_size_of_signed_integer = max(is_signed_v<A> ? sizeof(A) : 0, is_signed_v<B> ? sizeof(B) : 0);
|
||||||
static constexpr size_t max_size_of_integer = max(is_integer_v<A> ? sizeof(A) : 0, is_integer_v<B> ? sizeof(B) : 0);
|
static constexpr size_t max_size_of_integer = max(is_integer<A> ? sizeof(A) : 0, is_integer<B> ? sizeof(B) : 0);
|
||||||
static constexpr size_t max_size_of_float = max(std::is_floating_point_v<A> ? sizeof(A) : 0, std::is_floating_point_v<B> ? sizeof(B) : 0);
|
static constexpr size_t max_size_of_float = max(std::is_floating_point_v<A> ? sizeof(A) : 0, std::is_floating_point_v<B> ? sizeof(B) : 0);
|
||||||
|
|
||||||
using ConstructedType = typename Construct<has_signed, has_float,
|
using ConstructedType = typename Construct<has_signed, has_float,
|
||||||
@ -190,9 +190,9 @@ struct ResultOfIf
|
|||||||
|
|
||||||
using Type =
|
using Type =
|
||||||
std::conditional_t<std::is_same_v<A, B>, A,
|
std::conditional_t<std::is_same_v<A, B>, A,
|
||||||
std::conditional_t<IsDecimalNumber<A> && IsDecimalNumber<B>,
|
std::conditional_t<is_decimal<A> && is_decimal<B>,
|
||||||
std::conditional_t<(sizeof(A) > sizeof(B)), A, B>,
|
std::conditional_t<(sizeof(A) > sizeof(B)), A, B>,
|
||||||
std::conditional_t<!IsDecimalNumber<A> && !IsDecimalNumber<B>,
|
std::conditional_t<!is_decimal<A> && !is_decimal<B>,
|
||||||
ConstructedType, Error>>>;
|
ConstructedType, Error>>>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ void SerializationNumber<T>::deserializeText(IColumn & column, ReadBuffer & istr
|
|||||||
{
|
{
|
||||||
T x;
|
T x;
|
||||||
|
|
||||||
if constexpr (is_integer_v<T> && is_arithmetic_v<T>)
|
if constexpr (is_integer<T> && is_arithmetic_v<T>)
|
||||||
readIntTextUnsafe(x, istr);
|
readIntTextUnsafe(x, istr);
|
||||||
else
|
else
|
||||||
readText(x, istr);
|
readText(x, istr);
|
||||||
|
@ -26,10 +26,8 @@ String getExceptionMessage(
|
|||||||
const String & message, size_t argument_index, const char * argument_name,
|
const String & message, size_t argument_index, const char * argument_name,
|
||||||
const std::string & context_data_type_name, Field::Types::Which field_type)
|
const std::string & context_data_type_name, Field::Types::Which field_type)
|
||||||
{
|
{
|
||||||
return std::string("Parameter #") + std::to_string(argument_index) + " '"
|
return fmt::format("Parameter #{} '{}' for {}{}, expected {} literal",
|
||||||
+ argument_name + "' for " + context_data_type_name
|
argument_index, argument_name, context_data_type_name, message, field_type);
|
||||||
+ message
|
|
||||||
+ ", expected: " + Field::Types::toString(field_type) + " literal.";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, ArgumentKind Kind>
|
template <typename T, ArgumentKind Kind>
|
||||||
@ -49,7 +47,7 @@ getArgument(const ASTPtr & arguments, size_t argument_index, const char * argume
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (argument && argument->value.getType() != field_type)
|
if (argument && argument->value.getType() != field_type)
|
||||||
throw Exception(getExceptionMessage(String(" has wrong type: ") + argument->value.getTypeName(),
|
throw Exception(getExceptionMessage(fmt::format(" has wrong type: {}", argument->value.getTypeName()),
|
||||||
argument_index, argument_name, context_data_type_name, field_type), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
argument_index, argument_name, context_data_type_name, field_type), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||||
else
|
else
|
||||||
throw Exception(getExceptionMessage(" is missing", argument_index, argument_name, context_data_type_name, field_type),
|
throw Exception(getExceptionMessage(" is missing", argument_index, argument_name, context_data_type_name, field_type),
|
||||||
|
@ -240,8 +240,7 @@ public:
|
|||||||
using ColumnType =
|
using ColumnType =
|
||||||
std::conditional_t<std::is_same_v<DictionaryAttributeType, Array>, ColumnArray,
|
std::conditional_t<std::is_same_v<DictionaryAttributeType, Array>, ColumnArray,
|
||||||
std::conditional_t<std::is_same_v<DictionaryAttributeType, String>, ColumnString,
|
std::conditional_t<std::is_same_v<DictionaryAttributeType, String>, ColumnString,
|
||||||
std::conditional_t<IsDecimalNumber<DictionaryAttributeType>, ColumnDecimal<DictionaryAttributeType>,
|
ColumnVectorOrDecimal<DictionaryAttributeType>>>;
|
||||||
ColumnVector<DictionaryAttributeType>>>>;
|
|
||||||
|
|
||||||
using ColumnPtr = typename ColumnType::MutablePtr;
|
using ColumnPtr = typename ColumnType::MutablePtr;
|
||||||
|
|
||||||
@ -267,7 +266,7 @@ public:
|
|||||||
{
|
{
|
||||||
return ColumnType::create(size);
|
return ColumnType::create(size);
|
||||||
}
|
}
|
||||||
else if constexpr (IsDecimalNumber<DictionaryAttributeType>)
|
else if constexpr (is_decimal<DictionaryAttributeType>)
|
||||||
{
|
{
|
||||||
auto nested_type = removeNullable(dictionary_attribute.type);
|
auto nested_type = removeNullable(dictionary_attribute.type);
|
||||||
auto scale = getDecimalScale(*nested_type);
|
auto scale = getDecimalScale(*nested_type);
|
||||||
|
@ -19,16 +19,15 @@ namespace DB
|
|||||||
namespace ErrorCodes
|
namespace ErrorCodes
|
||||||
{
|
{
|
||||||
extern const int UNKNOWN_TYPE;
|
extern const int UNKNOWN_TYPE;
|
||||||
extern const int ARGUMENT_OUT_OF_BOUND;
|
|
||||||
extern const int TYPE_MISMATCH;
|
extern const int TYPE_MISMATCH;
|
||||||
extern const int BAD_ARGUMENTS;
|
extern const int BAD_ARGUMENTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
DictionaryTypedSpecialAttribute makeDictionaryTypedSpecialAttribute(
|
DictionaryTypedSpecialAttribute makeDictionaryTypedSpecialAttribute(
|
||||||
const Poco::Util::AbstractConfiguration & config, const std::string & config_prefix, const std::string & default_type)
|
const Poco::Util::AbstractConfiguration & config, const std::string & config_prefix, const std::string & default_type)
|
||||||
{
|
{
|
||||||
const auto name = config.getString(config_prefix + ".name", "");
|
const auto name = config.getString(config_prefix + ".name", "");
|
||||||
const auto expression = config.getString(config_prefix + ".expression", "");
|
const auto expression = config.getString(config_prefix + ".expression", "");
|
||||||
|
|
||||||
@ -37,66 +36,20 @@ namespace
|
|||||||
|
|
||||||
const auto type_name = config.getString(config_prefix + ".type", default_type);
|
const auto type_name = config.getString(config_prefix + ".type", default_type);
|
||||||
return DictionaryTypedSpecialAttribute{std::move(name), std::move(expression), DataTypeFactory::instance().get(type_name)};
|
return DictionaryTypedSpecialAttribute{std::move(name), std::move(expression), DataTypeFactory::instance().get(type_name)};
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<AttributeUnderlyingType> maybeGetAttributeUnderlyingType(TypeIndex index)
|
||||||
AttributeUnderlyingType getAttributeUnderlyingType(const DataTypePtr & type)
|
|
||||||
{
|
{
|
||||||
auto type_index = type->getTypeId();
|
switch (index) /// Special cases which do not map TypeIndex::T -> AttributeUnderlyingType::T
|
||||||
|
|
||||||
switch (type_index)
|
|
||||||
{
|
{
|
||||||
case TypeIndex::UInt8: return AttributeUnderlyingType::UInt8;
|
|
||||||
case TypeIndex::UInt16: return AttributeUnderlyingType::UInt16;
|
|
||||||
case TypeIndex::UInt32: return AttributeUnderlyingType::UInt32;
|
|
||||||
case TypeIndex::UInt64: return AttributeUnderlyingType::UInt64;
|
|
||||||
case TypeIndex::UInt128: return AttributeUnderlyingType::UInt128;
|
|
||||||
case TypeIndex::UInt256: return AttributeUnderlyingType::UInt256;
|
|
||||||
|
|
||||||
case TypeIndex::Int8: return AttributeUnderlyingType::Int8;
|
|
||||||
case TypeIndex::Int16: return AttributeUnderlyingType::Int16;
|
|
||||||
case TypeIndex::Int32: return AttributeUnderlyingType::Int32;
|
|
||||||
case TypeIndex::Int64: return AttributeUnderlyingType::Int64;
|
|
||||||
case TypeIndex::Int128: return AttributeUnderlyingType::Int128;
|
|
||||||
case TypeIndex::Int256: return AttributeUnderlyingType::Int256;
|
|
||||||
|
|
||||||
case TypeIndex::Float32: return AttributeUnderlyingType::Float32;
|
|
||||||
case TypeIndex::Float64: return AttributeUnderlyingType::Float64;
|
|
||||||
|
|
||||||
case TypeIndex::Decimal32: return AttributeUnderlyingType::Decimal32;
|
|
||||||
case TypeIndex::Decimal64: return AttributeUnderlyingType::Decimal64;
|
|
||||||
case TypeIndex::Decimal128: return AttributeUnderlyingType::Decimal128;
|
|
||||||
case TypeIndex::Decimal256: return AttributeUnderlyingType::Decimal256;
|
|
||||||
|
|
||||||
case TypeIndex::Date: return AttributeUnderlyingType::UInt16;
|
case TypeIndex::Date: return AttributeUnderlyingType::UInt16;
|
||||||
case TypeIndex::DateTime: return AttributeUnderlyingType::UInt32;
|
case TypeIndex::DateTime: return AttributeUnderlyingType::UInt32;
|
||||||
case TypeIndex::DateTime64: return AttributeUnderlyingType::UInt64;
|
case TypeIndex::DateTime64: return AttributeUnderlyingType::UInt64;
|
||||||
|
|
||||||
case TypeIndex::UUID: return AttributeUnderlyingType::UUID;
|
|
||||||
|
|
||||||
case TypeIndex::String: return AttributeUnderlyingType::String;
|
|
||||||
|
|
||||||
case TypeIndex::Array: return AttributeUnderlyingType::Array;
|
|
||||||
|
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw Exception(ErrorCodes::UNKNOWN_TYPE, "Unknown type {} for dictionary attribute", type->getName());
|
return magic_enum::enum_cast<AttributeUnderlyingType>(static_cast<TypeIndexUnderlying>(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string toString(AttributeUnderlyingType type)
|
|
||||||
{
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
#define M(TYPE) case AttributeUnderlyingType::TYPE: return #TYPE;
|
|
||||||
FOR_ATTRIBUTE_TYPES(M)
|
|
||||||
#undef M
|
|
||||||
}
|
|
||||||
|
|
||||||
throw Exception(ErrorCodes::ARGUMENT_OUT_OF_BOUND, "Unknown dictionary attribute type {}", toString(static_cast<int>(type)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -152,7 +105,7 @@ DictionaryStructure::DictionaryStructure(const Poco::Util::AbstractConfiguration
|
|||||||
if (id && attribute.underlying_type != AttributeUnderlyingType::UInt64)
|
if (id && attribute.underlying_type != AttributeUnderlyingType::UInt64)
|
||||||
throw Exception(ErrorCodes::TYPE_MISMATCH,
|
throw Exception(ErrorCodes::TYPE_MISMATCH,
|
||||||
"Hierarchical attribute type for dictionary with simple key must be UInt64. Actual {}",
|
"Hierarchical attribute type for dictionary with simple key must be UInt64. Actual {}",
|
||||||
toString(attribute.underlying_type));
|
attribute.underlying_type);
|
||||||
|
|
||||||
else if (key)
|
else if (key)
|
||||||
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Dictionary with complex key does not support hierarchy");
|
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Dictionary with complex key does not support hierarchy");
|
||||||
@ -342,7 +295,12 @@ std::vector<DictionaryAttribute> DictionaryStructure::getAttributes(
|
|||||||
bool is_nullable = initial_type->isNullable();
|
bool is_nullable = initial_type->isNullable();
|
||||||
|
|
||||||
auto non_nullable_type = removeNullable(initial_type);
|
auto non_nullable_type = removeNullable(initial_type);
|
||||||
const auto underlying_type = getAttributeUnderlyingType(non_nullable_type);
|
|
||||||
|
const auto underlying_type_opt = maybeGetAttributeUnderlyingType(non_nullable_type->getTypeId());
|
||||||
|
|
||||||
|
if (!underlying_type_opt)
|
||||||
|
throw Exception(ErrorCodes::UNKNOWN_TYPE,
|
||||||
|
"Unknown type {} for dictionary attribute", non_nullable_type->getName());
|
||||||
|
|
||||||
const auto expression = config.getString(prefix + "expression", "");
|
const auto expression = config.getString(prefix + "expression", "");
|
||||||
if (!expression.empty())
|
if (!expression.empty())
|
||||||
@ -391,7 +349,7 @@ std::vector<DictionaryAttribute> DictionaryStructure::getAttributes(
|
|||||||
|
|
||||||
res_attributes.emplace_back(DictionaryAttribute{
|
res_attributes.emplace_back(DictionaryAttribute{
|
||||||
name,
|
name,
|
||||||
underlying_type,
|
*underlying_type_opt,
|
||||||
initial_type,
|
initial_type,
|
||||||
initial_type_serialization,
|
initial_type_serialization,
|
||||||
expression,
|
expression,
|
||||||
|
@ -11,53 +11,37 @@
|
|||||||
#include <IO/ReadBufferFromString.h>
|
#include <IO/ReadBufferFromString.h>
|
||||||
#include <DataTypes/IDataType.h>
|
#include <DataTypes/IDataType.h>
|
||||||
#include <Interpreters/IExternalLoadable.h>
|
#include <Interpreters/IExternalLoadable.h>
|
||||||
|
#include <common/EnumReflection.h>
|
||||||
|
#include <Core/TypeId.h>
|
||||||
|
|
||||||
#if defined(__GNUC__)
|
#if defined(__GNUC__)
|
||||||
/// GCC mistakenly warns about the names in enum class.
|
/// GCC mistakenly warns about the names in enum class.
|
||||||
#pragma GCC diagnostic ignored "-Wshadow"
|
#pragma GCC diagnostic ignored "-Wshadow"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#define FOR_ATTRIBUTE_TYPES(M) \
|
|
||||||
M(UInt8) \
|
|
||||||
M(UInt16) \
|
|
||||||
M(UInt32) \
|
|
||||||
M(UInt64) \
|
|
||||||
M(UInt128) \
|
|
||||||
M(UInt256) \
|
|
||||||
M(Int8) \
|
|
||||||
M(Int16) \
|
|
||||||
M(Int32) \
|
|
||||||
M(Int64) \
|
|
||||||
M(Int128) \
|
|
||||||
M(Int256) \
|
|
||||||
M(Float32) \
|
|
||||||
M(Float64) \
|
|
||||||
M(Decimal32) \
|
|
||||||
M(Decimal64) \
|
|
||||||
M(Decimal128) \
|
|
||||||
M(Decimal256) \
|
|
||||||
M(UUID) \
|
|
||||||
M(String) \
|
|
||||||
M(Array) \
|
|
||||||
|
|
||||||
|
|
||||||
namespace DB
|
namespace DB
|
||||||
{
|
{
|
||||||
|
using TypeIndexUnderlying = magic_enum::underlying_type_t<TypeIndex>;
|
||||||
|
|
||||||
enum class AttributeUnderlyingType
|
// We need to be able to map TypeIndex -> AttributeUnderlyingType and AttributeUnderlyingType -> real type
|
||||||
|
// The first can be done by defining AttributeUnderlyingType enum values to TypeIndex values and then performing
|
||||||
|
// a enum_cast.
|
||||||
|
// The second can be achieved by using ReverseTypeId
|
||||||
|
#define map_item(__T) __T = static_cast<TypeIndexUnderlying>(TypeIndex::__T)
|
||||||
|
|
||||||
|
enum class AttributeUnderlyingType : TypeIndexUnderlying
|
||||||
{
|
{
|
||||||
#define M(TYPE) TYPE,
|
map_item(Int8), map_item(Int16), map_item(Int32), map_item(Int64), map_item(Int128), map_item(Int256),
|
||||||
FOR_ATTRIBUTE_TYPES(M)
|
map_item(UInt8), map_item(UInt16), map_item(UInt32), map_item(UInt64), map_item(UInt128), map_item(UInt256),
|
||||||
#undef M
|
map_item(Float32), map_item(Float64),
|
||||||
|
map_item(Decimal32), map_item(Decimal64), map_item(Decimal128), map_item(Decimal256),
|
||||||
|
|
||||||
|
map_item(UUID), map_item(String), map_item(Array)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#undef map_item
|
||||||
|
|
||||||
AttributeUnderlyingType getAttributeUnderlyingType(const std::string & type);
|
/// Min and max lifetimes for a dictionary or its entry
|
||||||
|
|
||||||
std::string toString(AttributeUnderlyingType type);
|
|
||||||
|
|
||||||
/// Min and max lifetimes for a dictionary or it's entry
|
|
||||||
using DictionaryLifetime = ExternalLoadableLifetime;
|
using DictionaryLifetime = ExternalLoadableLifetime;
|
||||||
|
|
||||||
/** Holds the description of a single dictionary attribute:
|
/** Holds the description of a single dictionary attribute:
|
||||||
@ -85,24 +69,23 @@ struct DictionaryAttribute final
|
|||||||
const bool is_nullable;
|
const bool is_nullable;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Type>
|
template <AttributeUnderlyingType type>
|
||||||
struct DictionaryAttributeType
|
struct DictionaryAttributeType
|
||||||
{
|
{
|
||||||
using AttributeType = Type;
|
/// Converts @c type to it underlying type e.g. AttributeUnderlyingType::UInt8 -> UInt8
|
||||||
|
using AttributeType = ReverseTypeId<
|
||||||
|
static_cast<TypeIndex>(
|
||||||
|
static_cast<TypeIndexUnderlying>(type))>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename F>
|
template <typename F>
|
||||||
void callOnDictionaryAttributeType(AttributeUnderlyingType type, F && func)
|
constexpr void callOnDictionaryAttributeType(AttributeUnderlyingType type, F && func)
|
||||||
{
|
{
|
||||||
switch (type)
|
static_for<AttributeUnderlyingType>([type, func = std::forward<F>(func)](auto other)
|
||||||
{
|
{
|
||||||
#define M(TYPE) \
|
if (type == other)
|
||||||
case AttributeUnderlyingType::TYPE: \
|
func(DictionaryAttributeType<other>{});
|
||||||
func(DictionaryAttributeType<TYPE>()); \
|
});
|
||||||
break;
|
|
||||||
FOR_ATTRIBUTE_TYPES(M)
|
|
||||||
#undef M
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DictionarySpecialAttribute final
|
struct DictionarySpecialAttribute final
|
||||||
|
@ -12,23 +12,6 @@ namespace ErrorCodes
|
|||||||
extern const int NO_ELEMENTS_IN_CONFIG;
|
extern const int NO_ELEMENTS_IN_CONFIG;
|
||||||
extern const int INCONSISTENT_RESERVATIONS;
|
extern const int INCONSISTENT_RESERVATIONS;
|
||||||
extern const int NO_RESERVATIONS_PROVIDED;
|
extern const int NO_RESERVATIONS_PROVIDED;
|
||||||
extern const int UNKNOWN_VOLUME_TYPE;
|
|
||||||
}
|
|
||||||
|
|
||||||
String volumeTypeToString(VolumeType type)
|
|
||||||
{
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case VolumeType::JBOD:
|
|
||||||
return "JBOD";
|
|
||||||
case VolumeType::RAID1:
|
|
||||||
return "RAID1";
|
|
||||||
case VolumeType::SINGLE_DISK:
|
|
||||||
return "SINGLE_DISK";
|
|
||||||
case VolumeType::UNKNOWN:
|
|
||||||
return "UNKNOWN";
|
|
||||||
}
|
|
||||||
throw Exception("Unknown volume type, please add it to DB::volumeTypeToString", ErrorCodes::UNKNOWN_VOLUME_TYPE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IVolume::IVolume(
|
IVolume::IVolume(
|
||||||
|
@ -16,8 +16,6 @@ enum class VolumeType
|
|||||||
UNKNOWN
|
UNKNOWN
|
||||||
};
|
};
|
||||||
|
|
||||||
String volumeTypeToString(VolumeType t);
|
|
||||||
|
|
||||||
class IVolume;
|
class IVolume;
|
||||||
using VolumePtr = std::shared_ptr<IVolume>;
|
using VolumePtr = std::shared_ptr<IVolume>;
|
||||||
using Volumes = std::vector<VolumePtr>;
|
using Volumes = std::vector<VolumePtr>;
|
||||||
|
@ -81,7 +81,7 @@ struct DivideIntegralImpl
|
|||||||
|
|
||||||
/// Otherwise overflow may occur due to integer promotion. Example: int8_t(-1) / uint64_t(2).
|
/// Otherwise overflow may occur due to integer promotion. Example: int8_t(-1) / uint64_t(2).
|
||||||
/// NOTE: overflow is still possible when dividing large signed number to large unsigned number or vice-versa. But it's less harmful.
|
/// NOTE: overflow is still possible when dividing large signed number to large unsigned number or vice-versa. But it's less harmful.
|
||||||
if constexpr (is_integer_v<A> && is_integer_v<B> && (is_signed_v<A> || is_signed_v<B>))
|
if constexpr (is_integer<A> && is_integer<B> && (is_signed_v<A> || is_signed_v<B>))
|
||||||
{
|
{
|
||||||
using SignedCastA = make_signed_t<CastA>;
|
using SignedCastA = make_signed_t<CastA>;
|
||||||
using SignedCastB = std::conditional_t<sizeof(A) <= sizeof(B), make_signed_t<CastB>, SignedCastA>;
|
using SignedCastB = std::conditional_t<sizeof(A) <= sizeof(B), make_signed_t<CastB>, SignedCastA>;
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include <Common/typeid_cast.h>
|
#include <Common/typeid_cast.h>
|
||||||
#include <Common/assert_cast.h>
|
#include <Common/assert_cast.h>
|
||||||
#include <Common/FieldVisitorsAccurateComparison.h>
|
#include <Common/FieldVisitorsAccurateComparison.h>
|
||||||
|
#include <Common/TypeList.h>
|
||||||
#include <common/map.h>
|
#include <common/map.h>
|
||||||
|
|
||||||
#if !defined(ARCADIA_BUILD)
|
#if !defined(ARCADIA_BUILD)
|
||||||
@ -183,14 +184,8 @@ namespace impl_
|
|||||||
|
|
||||||
enum class OpCase { Vector, LeftConstant, RightConstant };
|
enum class OpCase { Vector, LeftConstant, RightConstant };
|
||||||
|
|
||||||
template <class T>
|
constexpr const auto & undec(const auto & x) { return x; }
|
||||||
inline constexpr const auto & undec(const T & x)
|
constexpr const auto & undec(const is_decimal auto & x) { return x.value; }
|
||||||
{
|
|
||||||
if constexpr (IsDecimalNumber<T>)
|
|
||||||
return x.value;
|
|
||||||
else
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename A, typename B, typename Op, typename OpResultType = typename Op::ResultType>
|
template <typename A, typename B, typename Op, typename OpResultType = typename Op::ResultType>
|
||||||
struct BinaryOperation
|
struct BinaryOperation
|
||||||
@ -301,19 +296,17 @@ struct DecimalBinaryOperation
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
using ResultType = OpResultType; // e.g. Decimal32
|
using ResultType = OpResultType; // e.g. Decimal32
|
||||||
using NativeResultType = typename NativeType<ResultType>::Type; // e.g. UInt32 for Decimal32
|
using NativeResultType = NativeType<ResultType>; // e.g. UInt32 for Decimal32
|
||||||
|
|
||||||
using ResultContainerType = typename std::conditional_t<IsDecimalNumber<ResultType>,
|
using ResultContainerType = typename ColumnVectorOrDecimal<ResultType>::Container;
|
||||||
ColumnDecimal<ResultType>,
|
|
||||||
ColumnVector<ResultType>>::Container;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template <OpCase op_case, bool is_decimal_a, bool is_decimal_b, class A, class B>
|
template <OpCase op_case, bool is_decimal_a, bool is_decimal_b>
|
||||||
static void NO_INLINE process(const A & a, const B & b, ResultContainerType & c,
|
static void NO_INLINE process(const auto & a, const auto & b, ResultContainerType & c,
|
||||||
NativeResultType scale_a, NativeResultType scale_b)
|
NativeResultType scale_a, NativeResultType scale_b)
|
||||||
{
|
{
|
||||||
if constexpr (op_case == OpCase::LeftConstant) static_assert(!IsDecimalNumber<A>);
|
if constexpr (op_case == OpCase::LeftConstant) static_assert(!is_decimal<decltype(a)>);
|
||||||
if constexpr (op_case == OpCase::RightConstant) static_assert(!IsDecimalNumber<B>);
|
if constexpr (op_case == OpCase::RightConstant) static_assert(!is_decimal<decltype(b)>);
|
||||||
|
|
||||||
size_t size;
|
size_t size;
|
||||||
|
|
||||||
@ -383,10 +376,8 @@ public:
|
|||||||
|
|
||||||
template <bool is_decimal_a, bool is_decimal_b, class A, class B>
|
template <bool is_decimal_a, bool is_decimal_b, class A, class B>
|
||||||
static ResultType process(A a, B b, NativeResultType scale_a, NativeResultType scale_b)
|
static ResultType process(A a, B b, NativeResultType scale_a, NativeResultType scale_b)
|
||||||
|
requires(!is_decimal<A> && !is_decimal<B>)
|
||||||
{
|
{
|
||||||
static_assert(!IsDecimalNumber<A>);
|
|
||||||
static_assert(!IsDecimalNumber<B>);
|
|
||||||
|
|
||||||
if constexpr (is_division && is_decimal_b)
|
if constexpr (is_division && is_decimal_b)
|
||||||
return applyScaledDiv<is_decimal_a>(a, b, scale_a);
|
return applyScaledDiv<is_decimal_a>(a, b, scale_a);
|
||||||
else if constexpr (is_plus_minus_compare)
|
else if constexpr (is_plus_minus_compare)
|
||||||
@ -516,64 +507,26 @@ class FunctionBinaryArithmetic : public IFunction
|
|||||||
ContextPtr context;
|
ContextPtr context;
|
||||||
bool check_decimal_overflow = true;
|
bool check_decimal_overflow = true;
|
||||||
|
|
||||||
template <typename F>
|
static bool castType(const IDataType * type, auto && f)
|
||||||
static bool castType(const IDataType * type, F && f)
|
|
||||||
{
|
{
|
||||||
return castTypeToEither<
|
using Types = TypeList<
|
||||||
DataTypeUInt8,
|
DataTypeUInt8, DataTypeUInt16, DataTypeUInt32, DataTypeUInt64, DataTypeUInt128, DataTypeUInt256,
|
||||||
DataTypeUInt16,
|
DataTypeInt8, DataTypeInt16, DataTypeInt32, DataTypeInt64, DataTypeInt128, DataTypeInt256,
|
||||||
DataTypeUInt32,
|
DataTypeDecimal32, DataTypeDecimal64, DataTypeDecimal128, DataTypeDecimal256,
|
||||||
DataTypeUInt64,
|
DataTypeDate, DataTypeDateTime,
|
||||||
DataTypeUInt128,
|
DataTypeFixedString>;
|
||||||
DataTypeUInt256,
|
|
||||||
DataTypeInt8,
|
|
||||||
DataTypeInt16,
|
|
||||||
DataTypeInt32,
|
|
||||||
DataTypeInt64,
|
|
||||||
DataTypeInt128,
|
|
||||||
DataTypeInt256,
|
|
||||||
DataTypeFloat32,
|
|
||||||
DataTypeFloat64,
|
|
||||||
DataTypeDate,
|
|
||||||
DataTypeDateTime,
|
|
||||||
DataTypeDecimal<Decimal32>,
|
|
||||||
DataTypeDecimal<Decimal64>,
|
|
||||||
DataTypeDecimal<Decimal128>,
|
|
||||||
DataTypeDecimal<Decimal256>,
|
|
||||||
DataTypeFixedString
|
|
||||||
>(type, std::forward<F>(f));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename F>
|
using Floats = TypeList<DataTypeFloat32, DataTypeFloat64>;
|
||||||
static bool castTypeNoFloats(const IDataType * type, F && f)
|
|
||||||
{
|
using ValidTypes = std::conditional_t<valid_on_float_arguments,
|
||||||
return castTypeToEither<
|
typename TypeListConcat<Types, Floats>::Type,
|
||||||
DataTypeUInt8,
|
Types>;
|
||||||
DataTypeUInt16,
|
|
||||||
DataTypeUInt32,
|
return castTypeToEitherTL<ValidTypes>(type, std::forward<decltype(f)>(f));
|
||||||
DataTypeUInt64,
|
|
||||||
DataTypeUInt128,
|
|
||||||
DataTypeUInt256,
|
|
||||||
DataTypeInt8,
|
|
||||||
DataTypeInt16,
|
|
||||||
DataTypeInt32,
|
|
||||||
DataTypeInt64,
|
|
||||||
DataTypeInt128,
|
|
||||||
DataTypeInt256,
|
|
||||||
DataTypeDate,
|
|
||||||
DataTypeDateTime,
|
|
||||||
DataTypeDecimal<Decimal32>,
|
|
||||||
DataTypeDecimal<Decimal64>,
|
|
||||||
DataTypeDecimal<Decimal128>,
|
|
||||||
DataTypeDecimal<Decimal256>,
|
|
||||||
DataTypeFixedString
|
|
||||||
>(type, std::forward<F>(f));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename F>
|
template <typename F>
|
||||||
static bool castBothTypes(const IDataType * left, const IDataType * right, F && f)
|
static bool castBothTypes(const IDataType * left, const IDataType * right, F && f)
|
||||||
{
|
|
||||||
if constexpr (valid_on_float_arguments)
|
|
||||||
{
|
{
|
||||||
return castType(left, [&](const auto & left_)
|
return castType(left, [&](const auto & left_)
|
||||||
{
|
{
|
||||||
@ -583,17 +536,6 @@ class FunctionBinaryArithmetic : public IFunction
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
return castTypeNoFloats(left, [&](const auto & left_)
|
|
||||||
{
|
|
||||||
return castTypeNoFloats(right, [&](const auto & right_)
|
|
||||||
{
|
|
||||||
return f(left_, right_);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static FunctionOverloadResolverPtr
|
static FunctionOverloadResolverPtr
|
||||||
getFunctionForIntervalArithmetic(const DataTypePtr & type0, const DataTypePtr & type1, ContextPtr context)
|
getFunctionForIntervalArithmetic(const DataTypePtr & type0, const DataTypePtr & type1, ContextPtr context)
|
||||||
@ -632,7 +574,9 @@ class FunctionBinaryArithmetic : public IFunction
|
|||||||
std::string function_name;
|
std::string function_name;
|
||||||
if (interval_data_type)
|
if (interval_data_type)
|
||||||
{
|
{
|
||||||
function_name = String(is_plus ? "add" : "subtract") + interval_data_type->getKind().toString() + 's';
|
function_name = fmt::format("{}{}s",
|
||||||
|
is_plus ? "add" : "subtract",
|
||||||
|
interval_data_type->getKind().toString());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -785,23 +729,22 @@ class FunctionBinaryArithmetic : public IFunction
|
|||||||
return function->execute(new_arguments, result_type, input_rows_count);
|
return function->execute(new_arguments, result_type, input_rows_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename ResultDataType, typename CC, typename C>
|
template <typename T, typename ResultDataType>
|
||||||
static auto helperGetOrConvert(const CC & col_const, const C & col)
|
static auto helperGetOrConvert(const auto & col_const, const auto & col)
|
||||||
{
|
{
|
||||||
using ResultType = typename ResultDataType::FieldType;
|
using ResultType = typename ResultDataType::FieldType;
|
||||||
using NativeResultType = typename NativeType<ResultType>::Type;
|
using NativeResultType = NativeType<ResultType>;
|
||||||
|
|
||||||
if constexpr (IsFloatingPoint<ResultDataType> && IsDecimalNumber<T>)
|
if constexpr (IsFloatingPoint<ResultDataType> && is_decimal<T>)
|
||||||
return DecimalUtils::convertTo<NativeResultType>(col_const->template getValue<T>(), col.getScale());
|
return DecimalUtils::convertTo<NativeResultType>(col_const->template getValue<T>(), col.getScale());
|
||||||
else if constexpr (IsDecimalNumber<T>)
|
else if constexpr (is_decimal<T>)
|
||||||
return col_const->template getValue<T>().value;
|
return col_const->template getValue<T>().value;
|
||||||
else
|
else
|
||||||
return col_const->template getValue<T>();
|
return col_const->template getValue<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <OpCase op_case, bool left_decimal, bool right_decimal, typename OpImpl, typename OpImplCheck,
|
template <OpCase op_case, bool left_decimal, bool right_decimal, typename OpImpl, typename OpImplCheck>
|
||||||
typename L, typename R, typename VR, typename SA, typename SB>
|
void helperInvokeEither(const auto& left, const auto& right, auto& vec_res, auto scale_a, auto scale_b) const
|
||||||
void helperInvokeEither(const L& left, const R& right, VR& vec_res, SA scale_a, SB scale_b) const
|
|
||||||
{
|
{
|
||||||
if (check_decimal_overflow)
|
if (check_decimal_overflow)
|
||||||
OpImplCheck::template process<op_case, left_decimal, right_decimal>(left, right, vec_res, scale_a, scale_b);
|
OpImplCheck::template process<op_case, left_decimal, right_decimal>(left, right, vec_res, scale_a, scale_b);
|
||||||
@ -809,27 +752,25 @@ class FunctionBinaryArithmetic : public IFunction
|
|||||||
OpImpl::template process<op_case, left_decimal, right_decimal>(left, right, vec_res, scale_a, scale_b);
|
OpImpl::template process<op_case, left_decimal, right_decimal>(left, right, vec_res, scale_a, scale_b);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class LeftDataType, class RightDataType, class ResultDataType,
|
template <class LeftDataType, class RightDataType, class ResultDataType>
|
||||||
class L, class R, class CL, class CR>
|
|
||||||
ColumnPtr executeNumericWithDecimal(
|
ColumnPtr executeNumericWithDecimal(
|
||||||
const L & left, const R & right,
|
const auto & left, const auto & right,
|
||||||
const ColumnConst * const col_left_const, const ColumnConst * const col_right_const,
|
const ColumnConst * const col_left_const, const ColumnConst * const col_right_const,
|
||||||
const CL * const col_left, const CR * const col_right,
|
const auto * const col_left, const auto * const col_right,
|
||||||
size_t col_left_size) const
|
size_t col_left_size) const
|
||||||
{
|
{
|
||||||
using T0 = typename LeftDataType::FieldType;
|
using T0 = typename LeftDataType::FieldType;
|
||||||
using T1 = typename RightDataType::FieldType;
|
using T1 = typename RightDataType::FieldType;
|
||||||
using ResultType = typename ResultDataType::FieldType;
|
using ResultType = typename ResultDataType::FieldType;
|
||||||
|
|
||||||
using NativeResultType = typename NativeType<ResultType>::Type;
|
using NativeResultType = NativeType<ResultType>;
|
||||||
using OpImpl = DecimalBinaryOperation<Op, ResultType, false>;
|
using OpImpl = DecimalBinaryOperation<Op, ResultType, false>;
|
||||||
using OpImplCheck = DecimalBinaryOperation<Op, ResultType, true>;
|
using OpImplCheck = DecimalBinaryOperation<Op, ResultType, true>;
|
||||||
|
|
||||||
using ColVecResult = std::conditional_t<IsDecimalNumber<ResultType>,
|
using ColVecResult = ColumnVectorOrDecimal<ResultType>;
|
||||||
ColumnDecimal<ResultType>, ColumnVector<ResultType>>;
|
|
||||||
|
|
||||||
static constexpr const bool left_is_decimal = IsDecimalNumber<T0>;
|
static constexpr const bool left_is_decimal = is_decimal<T0>;
|
||||||
static constexpr const bool right_is_decimal = IsDecimalNumber<T1>;
|
static constexpr const bool right_is_decimal = is_decimal<T1>;
|
||||||
static constexpr const bool result_is_decimal = IsDataTypeDecimal<ResultDataType>;
|
static constexpr const bool result_is_decimal = IsDataTypeDecimal<ResultDataType>;
|
||||||
|
|
||||||
typename ColVecResult::MutablePtr col_res = nullptr;
|
typename ColVecResult::MutablePtr col_res = nullptr;
|
||||||
@ -1176,9 +1117,9 @@ public:
|
|||||||
using T0 = typename LeftDataType::FieldType;
|
using T0 = typename LeftDataType::FieldType;
|
||||||
using T1 = typename RightDataType::FieldType;
|
using T1 = typename RightDataType::FieldType;
|
||||||
using ResultType = typename ResultDataType::FieldType;
|
using ResultType = typename ResultDataType::FieldType;
|
||||||
using ColVecT0 = std::conditional_t<IsDecimalNumber<T0>, ColumnDecimal<T0>, ColumnVector<T0>>;
|
using ColVecT0 = ColumnVectorOrDecimal<T0>;
|
||||||
using ColVecT1 = std::conditional_t<IsDecimalNumber<T1>, ColumnDecimal<T1>, ColumnVector<T1>>;
|
using ColVecT1 = ColumnVectorOrDecimal<T1>;
|
||||||
using ColVecResult = std::conditional_t<IsDecimalNumber<ResultType>, ColumnDecimal<ResultType>, ColumnVector<ResultType>>;
|
using ColVecResult = ColumnVectorOrDecimal<ResultType>;
|
||||||
|
|
||||||
const auto * const col_left_raw = arguments[0].column.get();
|
const auto * const col_left_raw = arguments[0].column.get();
|
||||||
const auto * const col_right_raw = arguments[1].column.get();
|
const auto * const col_right_raw = arguments[1].column.get();
|
||||||
|
@ -68,13 +68,13 @@ const ColumnConst * checkAndGetColumnConstStringOrFixedString(const IColumn * co
|
|||||||
|
|
||||||
/// Transform anything to Field.
|
/// Transform anything to Field.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline std::enable_if_t<!IsDecimalNumber<T>, Field> toField(const T & x)
|
Field toField(const T & x)
|
||||||
{
|
{
|
||||||
return Field(NearestFieldType<T>(x));
|
return Field(NearestFieldType<T>(x));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <is_decimal T>
|
||||||
inline std::enable_if_t<IsDecimalNumber<T>, Field> toField(const T & x, UInt32 scale)
|
Field toField(const T & x, UInt32 scale)
|
||||||
{
|
{
|
||||||
return Field(NearestFieldType<T>(x, scale));
|
return Field(NearestFieldType<T>(x, scale));
|
||||||
}
|
}
|
||||||
|
@ -150,7 +150,7 @@ private:
|
|||||||
using Types = std::decay_t<decltype(types)>;
|
using Types = std::decay_t<decltype(types)>;
|
||||||
using Type = typename Types::RightType;
|
using Type = typename Types::RightType;
|
||||||
using ReturnType = std::conditional_t<Impl::always_returns_float64 || !std::is_floating_point_v<Type>, Float64, Type>;
|
using ReturnType = std::conditional_t<Impl::always_returns_float64 || !std::is_floating_point_v<Type>, Float64, Type>;
|
||||||
using ColVecType = std::conditional_t<IsDecimalNumber<Type>, ColumnDecimal<Type>, ColumnVector<Type>>;
|
using ColVecType = ColumnVectorOrDecimal<Type>;
|
||||||
|
|
||||||
const auto col_vec = checkAndGetColumn<ColVecType>(col.column.get());
|
const auto col_vec = checkAndGetColumn<ColVecType>(col.column.get());
|
||||||
return (res = execute<Type, ReturnType>(col_vec)) != nullptr;
|
return (res = execute<Type, ReturnType>(col_vec)) != nullptr;
|
||||||
|
@ -38,8 +38,8 @@ template <typename A, typename Op>
|
|||||||
struct UnaryOperationImpl
|
struct UnaryOperationImpl
|
||||||
{
|
{
|
||||||
using ResultType = typename Op::ResultType;
|
using ResultType = typename Op::ResultType;
|
||||||
using ColVecA = std::conditional_t<IsDecimalNumber<A>, ColumnDecimal<A>, ColumnVector<A>>;
|
using ColVecA = ColumnVectorOrDecimal<A>;
|
||||||
using ColVecC = std::conditional_t<IsDecimalNumber<ResultType>, ColumnDecimal<ResultType>, ColumnVector<ResultType>>;
|
using ColVecC = ColumnVectorOrDecimal<ResultType>;
|
||||||
using ArrayA = typename ColVecA::Container;
|
using ArrayA = typename ColVecA::Container;
|
||||||
using ArrayC = typename ColVecC::Container;
|
using ArrayC = typename ColVecC::Container;
|
||||||
|
|
||||||
|
@ -106,8 +106,9 @@ private:
|
|||||||
else if (buckets_field.getType() == Field::Types::UInt64)
|
else if (buckets_field.getType() == Field::Types::UInt64)
|
||||||
num_buckets = checkBucketsRange(buckets_field.get<UInt64>());
|
num_buckets = checkBucketsRange(buckets_field.get<UInt64>());
|
||||||
else
|
else
|
||||||
throw Exception("Illegal type " + String(buckets_field.getTypeName()) + " of the second argument of function " + getName(),
|
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
|
||||||
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
"Illegal type {} of the second argument of function {}",
|
||||||
|
buckets_field.getTypeName(), getName());
|
||||||
|
|
||||||
const auto & hash_col = arguments[0].column;
|
const auto & hash_col = arguments[0].column;
|
||||||
const IDataType * hash_type = arguments[0].type.get();
|
const IDataType * hash_type = arguments[0].type.get();
|
||||||
|
@ -764,7 +764,7 @@ template <typename FromDataType, typename Name>
|
|||||||
struct ConvertImpl<FromDataType, std::enable_if_t<!std::is_same_v<FromDataType, DataTypeString>, DataTypeString>, Name, ConvertDefaultBehaviorTag>
|
struct ConvertImpl<FromDataType, std::enable_if_t<!std::is_same_v<FromDataType, DataTypeString>, DataTypeString>, Name, ConvertDefaultBehaviorTag>
|
||||||
{
|
{
|
||||||
using FromFieldType = typename FromDataType::FieldType;
|
using FromFieldType = typename FromDataType::FieldType;
|
||||||
using ColVecType = std::conditional_t<IsDecimalNumber<FromFieldType>, ColumnDecimal<FromFieldType>, ColumnVector<FromFieldType>>;
|
using ColVecType = ColumnVectorOrDecimal<FromFieldType>;
|
||||||
|
|
||||||
static ColumnPtr execute(const ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/)
|
static ColumnPtr execute(const ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/)
|
||||||
{
|
{
|
||||||
@ -1699,9 +1699,9 @@ private:
|
|||||||
using RightT = typename RightDataType::FieldType;
|
using RightT = typename RightDataType::FieldType;
|
||||||
|
|
||||||
static constexpr bool bad_left =
|
static constexpr bool bad_left =
|
||||||
IsDecimalNumber<LeftT> || std::is_floating_point_v<LeftT> || is_big_int_v<LeftT> || is_signed_v<LeftT>;
|
is_decimal<LeftT> || std::is_floating_point_v<LeftT> || is_big_int_v<LeftT> || is_signed_v<LeftT>;
|
||||||
static constexpr bool bad_right =
|
static constexpr bool bad_right =
|
||||||
IsDecimalNumber<RightT> || std::is_floating_point_v<RightT> || is_big_int_v<RightT> || is_signed_v<RightT>;
|
is_decimal<RightT> || std::is_floating_point_v<RightT> || is_big_int_v<RightT> || is_signed_v<RightT>;
|
||||||
|
|
||||||
/// Disallow int vs UUID conversion (but support int vs UInt128 conversion)
|
/// Disallow int vs UUID conversion (but support int vs UInt128 conversion)
|
||||||
if constexpr ((bad_left && std::is_same_v<RightDataType, DataTypeUUID>) ||
|
if constexpr ((bad_left && std::is_same_v<RightDataType, DataTypeUUID>) ||
|
||||||
@ -2585,8 +2585,9 @@ private:
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw Exception{"Conversion from " + std::string(getTypeName(from_type_index)) + " to " + to_type->getName() + " is not supported",
|
throw Exception(ErrorCodes::CANNOT_CONVERT_TYPE,
|
||||||
ErrorCodes::CANNOT_CONVERT_TYPE};
|
"Conversion from {} to {} is not supported",
|
||||||
|
from_type_index, to_type->getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2695,8 +2696,9 @@ private:
|
|||||||
return nullable_column_wrapper(arguments, result_type, column_nullable, input_rows_count);
|
return nullable_column_wrapper(arguments, result_type, column_nullable, input_rows_count);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw Exception{"Conversion from " + std::string(getTypeName(type_index)) + " to " + to_type->getName() + " is not supported",
|
throw Exception(ErrorCodes::CANNOT_CONVERT_TYPE,
|
||||||
ErrorCodes::CANNOT_CONVERT_TYPE};
|
"Conversion from {} to {} is not supported",
|
||||||
|
type_index, to_type->getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
return result_column;
|
return result_column;
|
||||||
|
@ -635,7 +635,7 @@ private:
|
|||||||
template <typename FromType>
|
template <typename FromType>
|
||||||
ColumnPtr executeType(const ColumnsWithTypeAndName & arguments) const
|
ColumnPtr executeType(const ColumnsWithTypeAndName & arguments) const
|
||||||
{
|
{
|
||||||
using ColVecType = std::conditional_t<IsDecimalNumber<FromType>, ColumnDecimal<FromType>, ColumnVector<FromType>>;
|
using ColVecType = ColumnVectorOrDecimal<FromType>;
|
||||||
|
|
||||||
if (const ColVecType * col_from = checkAndGetColumn<ColVecType>(arguments[0].column.get()))
|
if (const ColVecType * col_from = checkAndGetColumn<ColVecType>(arguments[0].column.get()))
|
||||||
{
|
{
|
||||||
@ -762,7 +762,7 @@ private:
|
|||||||
template <typename FromType, bool first>
|
template <typename FromType, bool first>
|
||||||
void executeIntType(const IColumn * column, typename ColumnVector<ToType>::Container & vec_to) const
|
void executeIntType(const IColumn * column, typename ColumnVector<ToType>::Container & vec_to) const
|
||||||
{
|
{
|
||||||
using ColVecType = std::conditional_t<IsDecimalNumber<FromType>, ColumnDecimal<FromType>, ColumnVector<FromType>>;
|
using ColVecType = ColumnVectorOrDecimal<FromType>;
|
||||||
|
|
||||||
if (const ColVecType * col_from = checkAndGetColumn<ColVecType>(column))
|
if (const ColVecType * col_from = checkAndGetColumn<ColVecType>(column))
|
||||||
{
|
{
|
||||||
@ -819,7 +819,7 @@ private:
|
|||||||
template <typename FromType, bool first>
|
template <typename FromType, bool first>
|
||||||
void executeBigIntType(const IColumn * column, typename ColumnVector<ToType>::Container & vec_to) const
|
void executeBigIntType(const IColumn * column, typename ColumnVector<ToType>::Container & vec_to) const
|
||||||
{
|
{
|
||||||
using ColVecType = std::conditional_t<IsDecimalNumber<FromType>, ColumnDecimal<FromType>, ColumnVector<FromType>>;
|
using ColVecType = ColumnVectorOrDecimal<FromType>;
|
||||||
|
|
||||||
if (const ColVecType * col_from = checkAndGetColumn<ColVecType>(column))
|
if (const ColVecType * col_from = checkAndGetColumn<ColVecType>(column))
|
||||||
{
|
{
|
||||||
|
@ -522,7 +522,7 @@ public:
|
|||||||
else if (!accurate::convertNumeric(element.getDouble(), value))
|
else if (!accurate::convertNumeric(element.getDouble(), value))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (element.isBool() && is_integer_v<NumberType> && convert_bool_to_integer)
|
else if (element.isBool() && is_integer<NumberType> && convert_bool_to_integer)
|
||||||
{
|
{
|
||||||
value = static_cast<NumberType>(element.getBool());
|
value = static_cast<NumberType>(element.getBool());
|
||||||
}
|
}
|
||||||
|
@ -315,11 +315,11 @@ template <typename T, RoundingMode rounding_mode, ScaleMode scale_mode>
|
|||||||
struct FloatRoundingImpl
|
struct FloatRoundingImpl
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
static_assert(!IsDecimalNumber<T>);
|
static_assert(!is_decimal<T>);
|
||||||
|
|
||||||
using Op = FloatRoundingComputation<T, rounding_mode, scale_mode>;
|
using Op = FloatRoundingComputation<T, rounding_mode, scale_mode>;
|
||||||
using Data = std::array<T, Op::data_count>;
|
using Data = std::array<T, Op::data_count>;
|
||||||
using ColumnType = std::conditional_t<IsDecimalNumber<T>, ColumnDecimal<T>, ColumnVector<T>>;
|
using ColumnType = ColumnVector<T>;
|
||||||
using Container = typename ColumnType::Container;
|
using Container = typename ColumnType::Container;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -413,12 +413,10 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
template <typename T, RoundingMode rounding_mode, TieBreakingMode tie_breaking_mode>
|
template <is_decimal T, RoundingMode rounding_mode, TieBreakingMode tie_breaking_mode>
|
||||||
class DecimalRoundingImpl
|
class DecimalRoundingImpl
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
static_assert(IsDecimalNumber<T>);
|
|
||||||
|
|
||||||
using NativeType = typename T::NativeType;
|
using NativeType = typename T::NativeType;
|
||||||
using Op = IntegerRoundingComputation<NativeType, rounding_mode, ScaleMode::Negative, tie_breaking_mode>;
|
using Op = IntegerRoundingComputation<NativeType, rounding_mode, ScaleMode::Negative, tie_breaking_mode>;
|
||||||
using Container = typename ColumnDecimal<T>::Container;
|
using Container = typename ColumnDecimal<T>::Container;
|
||||||
@ -453,15 +451,16 @@ public:
|
|||||||
/** Select the appropriate processing algorithm depending on the scale.
|
/** Select the appropriate processing algorithm depending on the scale.
|
||||||
*/
|
*/
|
||||||
template <typename T, RoundingMode rounding_mode, TieBreakingMode tie_breaking_mode>
|
template <typename T, RoundingMode rounding_mode, TieBreakingMode tie_breaking_mode>
|
||||||
class Dispatcher
|
struct Dispatcher
|
||||||
{
|
{
|
||||||
template <ScaleMode scale_mode>
|
template <ScaleMode scale_mode>
|
||||||
using FunctionRoundingImpl = std::conditional_t<std::is_floating_point_v<T>,
|
using FunctionRoundingImpl = std::conditional_t<std::is_floating_point_v<T>,
|
||||||
FloatRoundingImpl<T, rounding_mode, scale_mode>,
|
FloatRoundingImpl<T, rounding_mode, scale_mode>,
|
||||||
IntegerRoundingImpl<T, rounding_mode, scale_mode, tie_breaking_mode>>;
|
IntegerRoundingImpl<T, rounding_mode, scale_mode, tie_breaking_mode>>;
|
||||||
|
|
||||||
static ColumnPtr apply(const ColumnVector<T> * col, Scale scale_arg)
|
static ColumnPtr apply(const IColumn * col_general, Scale scale_arg)
|
||||||
{
|
{
|
||||||
|
const auto * const col = checkAndGetColumn<ColumnVector<T>>(col_general);
|
||||||
auto col_res = ColumnVector<T>::create();
|
auto col_res = ColumnVector<T>::create();
|
||||||
|
|
||||||
typename ColumnVector<T>::Container & vec_res = col_res->getData();
|
typename ColumnVector<T>::Container & vec_res = col_res->getData();
|
||||||
@ -488,9 +487,15 @@ class Dispatcher
|
|||||||
|
|
||||||
return col_res;
|
return col_res;
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
static ColumnPtr apply(const ColumnDecimal<T> * col, Scale scale_arg)
|
template <is_decimal T, RoundingMode rounding_mode, TieBreakingMode tie_breaking_mode>
|
||||||
|
struct Dispatcher<T, rounding_mode, tie_breaking_mode>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static ColumnPtr apply(const IColumn * col_general, Scale scale_arg)
|
||||||
{
|
{
|
||||||
|
const auto * const col = checkAndGetColumn<ColumnDecimal<T>>(col_general);
|
||||||
const typename ColumnDecimal<T>::Container & vec_src = col->getData();
|
const typename ColumnDecimal<T>::Container & vec_src = col->getData();
|
||||||
|
|
||||||
auto col_res = ColumnDecimal<T>::create(vec_src.size(), vec_src.getScale());
|
auto col_res = ColumnDecimal<T>::create(vec_src.size(), vec_src.getScale());
|
||||||
@ -501,15 +506,6 @@ class Dispatcher
|
|||||||
|
|
||||||
return col_res;
|
return col_res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
|
||||||
static ColumnPtr apply(const IColumn * column, Scale scale_arg)
|
|
||||||
{
|
|
||||||
if constexpr (is_arithmetic_v<T>)
|
|
||||||
return apply(checkAndGetColumn<ColumnVector<T>>(column), scale_arg);
|
|
||||||
else if constexpr (IsDecimalNumber<T>)
|
|
||||||
return apply(checkAndGetColumn<ColumnDecimal<T>>(column), scale_arg);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/** A template for functions that round the value of an input parameter of type
|
/** A template for functions that round the value of an input parameter of type
|
||||||
|
@ -34,7 +34,7 @@ void writeSlice(const NumericArraySlice<T> & slice, NumericArraySink<T> & sink)
|
|||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
void writeSlice(const NumericArraySlice<T> & slice, NumericArraySink<U> & sink)
|
void writeSlice(const NumericArraySlice<T> & slice, NumericArraySink<U> & sink)
|
||||||
{
|
{
|
||||||
using NativeU = typename NativeType<U>::Type;
|
using NativeU = NativeType<U>;
|
||||||
|
|
||||||
sink.elements.resize(sink.current_offset + slice.size);
|
sink.elements.resize(sink.current_offset + slice.size);
|
||||||
for (size_t i = 0; i < slice.size; ++i)
|
for (size_t i = 0; i < slice.size; ++i)
|
||||||
@ -42,9 +42,9 @@ void writeSlice(const NumericArraySlice<T> & slice, NumericArraySink<U> & sink)
|
|||||||
const auto & src = slice.data[i];
|
const auto & src = slice.data[i];
|
||||||
auto & dst = sink.elements[sink.current_offset];
|
auto & dst = sink.elements[sink.current_offset];
|
||||||
|
|
||||||
if constexpr (OverBigInt<T> || OverBigInt<U>)
|
if constexpr (is_over_big_int<T> || is_over_big_int<U>)
|
||||||
{
|
{
|
||||||
if constexpr (IsDecimalNumber<T>)
|
if constexpr (is_decimal<T>)
|
||||||
dst = static_cast<NativeU>(src.value);
|
dst = static_cast<NativeU>(src.value);
|
||||||
else
|
else
|
||||||
dst = static_cast<NativeU>(src);
|
dst = static_cast<NativeU>(src);
|
||||||
@ -99,7 +99,7 @@ inline ALWAYS_INLINE void writeSlice(const NumericArraySlice<T> & slice, Generic
|
|||||||
{
|
{
|
||||||
for (size_t i = 0; i < slice.size; ++i)
|
for (size_t i = 0; i < slice.size; ++i)
|
||||||
{
|
{
|
||||||
if constexpr (IsDecimalNumber<T>)
|
if constexpr (is_decimal<T>)
|
||||||
{
|
{
|
||||||
DecimalField field(T(slice.data[i]), 0); /// TODO: Decimal scale
|
DecimalField field(T(slice.data[i]), 0); /// TODO: Decimal scale
|
||||||
sink.elements.insert(field);
|
sink.elements.insert(field);
|
||||||
@ -558,9 +558,9 @@ bool sliceEqualElements(const NumericArraySlice<T> & first [[maybe_unused]],
|
|||||||
size_t second_ind [[maybe_unused]])
|
size_t second_ind [[maybe_unused]])
|
||||||
{
|
{
|
||||||
/// TODO: Decimal scale
|
/// TODO: Decimal scale
|
||||||
if constexpr (IsDecimalNumber<T> && IsDecimalNumber<U>)
|
if constexpr (is_decimal<T> && is_decimal<U>)
|
||||||
return accurate::equalsOp(first.data[first_ind].value, second.data[second_ind].value);
|
return accurate::equalsOp(first.data[first_ind].value, second.data[second_ind].value);
|
||||||
else if constexpr (IsDecimalNumber<T> || IsDecimalNumber<U>)
|
else if constexpr (is_decimal<T> || is_decimal<U>)
|
||||||
return false;
|
return false;
|
||||||
else
|
else
|
||||||
return accurate::equalsOp(first.data[first_ind], second.data[second_ind]);
|
return accurate::equalsOp(first.data[first_ind], second.data[second_ind]);
|
||||||
@ -588,7 +588,7 @@ bool insliceEqualElements(const NumericArraySlice<T> & first [[maybe_unused]],
|
|||||||
size_t first_ind [[maybe_unused]],
|
size_t first_ind [[maybe_unused]],
|
||||||
size_t second_ind [[maybe_unused]])
|
size_t second_ind [[maybe_unused]])
|
||||||
{
|
{
|
||||||
if constexpr (IsDecimalNumber<T>)
|
if constexpr (is_decimal<T>)
|
||||||
return accurate::equalsOp(first.data[first_ind].value, first.data[second_ind].value);
|
return accurate::equalsOp(first.data[first_ind].value, first.data[second_ind].value);
|
||||||
else
|
else
|
||||||
return accurate::equalsOp(first.data[first_ind], first.data[second_ind]);
|
return accurate::equalsOp(first.data[first_ind], first.data[second_ind]);
|
||||||
|
@ -36,7 +36,7 @@ struct NullableValueSource;
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
struct NumericArraySink : public ArraySinkImpl<NumericArraySink<T>>
|
struct NumericArraySink : public ArraySinkImpl<NumericArraySink<T>>
|
||||||
{
|
{
|
||||||
using ColVecType = std::conditional_t<IsDecimalNumber<T>, ColumnDecimal<T>, ColumnVector<T>>;
|
using ColVecType = ColumnVectorOrDecimal<T>;
|
||||||
using CompatibleArraySource = NumericArraySource<T>;
|
using CompatibleArraySource = NumericArraySource<T>;
|
||||||
using CompatibleValueSource = NumericValueSource<T>;
|
using CompatibleValueSource = NumericValueSource<T>;
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ template <typename ArraySink> struct NullableArraySink;
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
struct NumericArraySource : public ArraySourceImpl<NumericArraySource<T>>
|
struct NumericArraySource : public ArraySourceImpl<NumericArraySource<T>>
|
||||||
{
|
{
|
||||||
using ColVecType = std::conditional_t<IsDecimalNumber<T>, ColumnDecimal<T>, ColumnVector<T>>;
|
using ColVecType = ColumnVectorOrDecimal<T>;
|
||||||
using Slice = NumericArraySlice<T>;
|
using Slice = NumericArraySlice<T>;
|
||||||
using Column = ColumnArray;
|
using Column = ColumnArray;
|
||||||
|
|
||||||
@ -720,7 +720,7 @@ template <typename T>
|
|||||||
struct NumericValueSource : ValueSourceImpl<NumericValueSource<T>>
|
struct NumericValueSource : ValueSourceImpl<NumericValueSource<T>>
|
||||||
{
|
{
|
||||||
using Slice = NumericValueSlice<T>;
|
using Slice = NumericValueSlice<T>;
|
||||||
using Column = std::conditional_t<IsDecimalNumber<T>, ColumnDecimal<T>, ColumnVector<T>>;
|
using Column = ColumnVectorOrDecimal<T>;
|
||||||
|
|
||||||
using SinkType = NumericArraySink<T>;
|
using SinkType = NumericArraySink<T>;
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ struct ArraySinkCreator<Type, Types...>
|
|||||||
{
|
{
|
||||||
static std::unique_ptr<IArraySink> create(IColumn & values, ColumnArray::Offsets & offsets, size_t column_size)
|
static std::unique_ptr<IArraySink> create(IColumn & values, ColumnArray::Offsets & offsets, size_t column_size)
|
||||||
{
|
{
|
||||||
using ColVecType = std::conditional_t<IsDecimalNumber<Type>, ColumnDecimal<Type>, ColumnVector<Type>>;
|
using ColVecType = ColumnVectorOrDecimal<Type>;
|
||||||
|
|
||||||
IColumn * not_null_values = &values;
|
IColumn * not_null_values = &values;
|
||||||
bool is_nullable = false;
|
bool is_nullable = false;
|
||||||
|
@ -18,7 +18,7 @@ struct ArraySourceCreator<Type, Types...>
|
|||||||
{
|
{
|
||||||
static std::unique_ptr<IArraySource> create(const ColumnArray & col, const NullMap * null_map, bool is_const, size_t total_rows)
|
static std::unique_ptr<IArraySource> create(const ColumnArray & col, const NullMap * null_map, bool is_const, size_t total_rows)
|
||||||
{
|
{
|
||||||
using ColVecType = std::conditional_t<IsDecimalNumber<Type>, ColumnDecimal<Type>, ColumnVector<Type>>;
|
using ColVecType = ColumnVectorOrDecimal<Type>;
|
||||||
|
|
||||||
if (typeid_cast<const ColVecType *>(&col.getData()))
|
if (typeid_cast<const ColVecType *>(&col.getData()))
|
||||||
{
|
{
|
||||||
|
@ -18,7 +18,7 @@ struct ValueSourceCreator<Type, Types...>
|
|||||||
{
|
{
|
||||||
static std::unique_ptr<IValueSource> create(const IColumn & col, const NullMap * null_map, bool is_const, size_t total_rows)
|
static std::unique_ptr<IValueSource> create(const IColumn & col, const NullMap * null_map, bool is_const, size_t total_rows)
|
||||||
{
|
{
|
||||||
using ColVecType = std::conditional_t<IsDecimalNumber<Type>, ColumnDecimal<Type>, ColumnVector<Type>>;
|
using ColVecType = ColumnVectorOrDecimal<Type>;
|
||||||
|
|
||||||
if (auto column_vector = typeid_cast<const ColVecType *>(&col))
|
if (auto column_vector = typeid_cast<const ColVecType *>(&col))
|
||||||
{
|
{
|
||||||
|
@ -38,14 +38,13 @@ namespace DB
|
|||||||
* integral type which should be at least 32 bits wide, and
|
* integral type which should be at least 32 bits wide, and
|
||||||
* should preferably signed.
|
* should preferably signed.
|
||||||
*/
|
*/
|
||||||
template <typename T, std::enable_if_t<is_integer_v<T>> * = nullptr>
|
GregorianDate(is_integer auto mjd);
|
||||||
GregorianDate(T mjd);
|
|
||||||
|
|
||||||
/** Convert to Modified Julian Day. The type T is an integral type
|
/** Convert to Modified Julian Day. The type T is an integral type
|
||||||
* which should be at least 32 bits wide, and should preferably
|
* which should be at least 32 bits wide, and should preferably
|
||||||
* signed.
|
* signed.
|
||||||
*/
|
*/
|
||||||
template <typename T, std::enable_if_t<is_integer_v<T>> * = nullptr>
|
template <is_integer T>
|
||||||
T toModifiedJulianDay() const;
|
T toModifiedJulianDay() const;
|
||||||
|
|
||||||
/** Write the date in text form 'YYYY-MM-DD' to a buffer.
|
/** Write the date in text form 'YYYY-MM-DD' to a buffer.
|
||||||
@ -90,14 +89,13 @@ namespace DB
|
|||||||
* integral type which should be at least 32 bits wide, and
|
* integral type which should be at least 32 bits wide, and
|
||||||
* should preferably signed.
|
* should preferably signed.
|
||||||
*/
|
*/
|
||||||
template <typename T, std::enable_if_t<is_integer_v<T>> * = nullptr>
|
OrdinalDate(is_integer auto mjd);
|
||||||
OrdinalDate(T mjd);
|
|
||||||
|
|
||||||
/** Convert to Modified Julian Day. The type T is an integral
|
/** Convert to Modified Julian Day. The type T is an integral
|
||||||
* type which should be at least 32 bits wide, and should
|
* type which should be at least 32 bits wide, and should
|
||||||
* preferably be signed.
|
* preferably be signed.
|
||||||
*/
|
*/
|
||||||
template <typename T, std::enable_if_t<is_integer_v<T>> * = nullptr>
|
template <is_integer T>
|
||||||
T toModifiedJulianDay() const noexcept;
|
T toModifiedJulianDay() const noexcept;
|
||||||
|
|
||||||
YearT year() const noexcept
|
YearT year() const noexcept
|
||||||
@ -259,8 +257,7 @@ namespace DB
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename YearT>
|
template <typename YearT>
|
||||||
template <typename T, std::enable_if_t<is_integer_v<T>> *>
|
GregorianDate<YearT>::GregorianDate(is_integer auto mjd)
|
||||||
GregorianDate<YearT>::GregorianDate(T mjd)
|
|
||||||
{
|
{
|
||||||
const OrdinalDate<YearT> ord(mjd);
|
const OrdinalDate<YearT> ord(mjd);
|
||||||
const MonthDay md(gd::is_leap_year(ord.year()), ord.dayOfYear());
|
const MonthDay md(gd::is_leap_year(ord.year()), ord.dayOfYear());
|
||||||
@ -270,7 +267,7 @@ namespace DB
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename YearT>
|
template <typename YearT>
|
||||||
template <typename T, std::enable_if_t<is_integer_v<T>> *>
|
template <is_integer T>
|
||||||
T GregorianDate<YearT>::toModifiedJulianDay() const
|
T GregorianDate<YearT>::toModifiedJulianDay() const
|
||||||
{
|
{
|
||||||
const MonthDay md(month_, day_of_month_);
|
const MonthDay md(month_, day_of_month_);
|
||||||
@ -332,8 +329,7 @@ namespace DB
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename YearT>
|
template <typename YearT>
|
||||||
template <typename T, std::enable_if_t<is_integer_v<T>> *>
|
OrdinalDate<YearT>::OrdinalDate(is_integer auto mjd)
|
||||||
OrdinalDate<YearT>::OrdinalDate(T mjd)
|
|
||||||
{
|
{
|
||||||
const auto a = mjd + 678575;
|
const auto a = mjd + 678575;
|
||||||
const auto quad_cent = gd::div(a, 146097);
|
const auto quad_cent = gd::div(a, 146097);
|
||||||
@ -348,7 +344,7 @@ namespace DB
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename YearT>
|
template <typename YearT>
|
||||||
template <typename T, std::enable_if_t<is_integer_v<T>> *>
|
template <is_integer T>
|
||||||
T OrdinalDate<YearT>::toModifiedJulianDay() const noexcept
|
T OrdinalDate<YearT>::toModifiedJulianDay() const noexcept
|
||||||
{
|
{
|
||||||
const auto y = year_ - 1;
|
const auto y = year_ - 1;
|
||||||
|
@ -9,18 +9,18 @@ namespace DB
|
|||||||
template <typename A>
|
template <typename A>
|
||||||
struct AbsImpl
|
struct AbsImpl
|
||||||
{
|
{
|
||||||
using ResultType = std::conditional_t<IsDecimalNumber<A>, A, typename NumberTraits::ResultOfAbs<A>::Type>;
|
using ResultType = std::conditional_t<is_decimal<A>, A, typename NumberTraits::ResultOfAbs<A>::Type>;
|
||||||
static const constexpr bool allow_fixed_string = false;
|
static const constexpr bool allow_fixed_string = false;
|
||||||
|
|
||||||
static inline NO_SANITIZE_UNDEFINED ResultType apply(A a)
|
static inline NO_SANITIZE_UNDEFINED ResultType apply(A a)
|
||||||
{
|
{
|
||||||
if constexpr (IsDecimalNumber<A>)
|
if constexpr (is_decimal<A>)
|
||||||
return a < A(0) ? A(-a) : a;
|
return a < A(0) ? A(-a) : a;
|
||||||
else if constexpr (is_big_int_v<A> && is_signed_v<A>)
|
else if constexpr (is_big_int_v<A> && is_signed_v<A>)
|
||||||
return (a < 0) ? -a : a;
|
return (a < 0) ? -a : a;
|
||||||
else if constexpr (is_integer_v<A> && is_signed_v<A>)
|
else if constexpr (is_integer<A> && is_signed_v<A>)
|
||||||
return a < 0 ? static_cast<ResultType>(~a) + 1 : static_cast<ResultType>(a);
|
return a < 0 ? static_cast<ResultType>(~a) + 1 : static_cast<ResultType>(a);
|
||||||
else if constexpr (is_integer_v<A> && is_unsigned_v<A>)
|
else if constexpr (is_integer<A> && is_unsigned_v<A>)
|
||||||
return static_cast<ResultType>(a);
|
return static_cast<ResultType>(a);
|
||||||
else if constexpr (std::is_floating_point_v<A>)
|
else if constexpr (std::is_floating_point_v<A>)
|
||||||
return static_cast<ResultType>(std::abs(a));
|
return static_cast<ResultType>(std::abs(a));
|
||||||
|
@ -71,7 +71,7 @@ struct ArrayAggregateResultImpl<ArrayElement, AggregateOperation::sum>
|
|||||||
std::conditional_t<std::is_same_v<ArrayElement, UInt128>, UInt128,
|
std::conditional_t<std::is_same_v<ArrayElement, UInt128>, UInt128,
|
||||||
std::conditional_t<std::is_same_v<ArrayElement, Int256>, Int256,
|
std::conditional_t<std::is_same_v<ArrayElement, Int256>, Int256,
|
||||||
std::conditional_t<std::is_same_v<ArrayElement, UInt256>, UInt256,
|
std::conditional_t<std::is_same_v<ArrayElement, UInt256>, UInt256,
|
||||||
std::conditional_t<IsDecimalNumber<ArrayElement>, Decimal128,
|
std::conditional_t<is_decimal<ArrayElement>, Decimal128,
|
||||||
std::conditional_t<std::is_floating_point_v<ArrayElement>, Float64,
|
std::conditional_t<std::is_floating_point_v<ArrayElement>, Float64,
|
||||||
std::conditional_t<std::is_signed_v<ArrayElement>, Int64,
|
std::conditional_t<std::is_signed_v<ArrayElement>, Int64,
|
||||||
UInt64>>>>>>>;
|
UInt64>>>>>>>;
|
||||||
@ -135,8 +135,8 @@ struct ArrayAggregateImpl
|
|||||||
static NO_SANITIZE_UNDEFINED bool executeType(const ColumnPtr & mapped, const ColumnArray::Offsets & offsets, ColumnPtr & res_ptr)
|
static NO_SANITIZE_UNDEFINED bool executeType(const ColumnPtr & mapped, const ColumnArray::Offsets & offsets, ColumnPtr & res_ptr)
|
||||||
{
|
{
|
||||||
using ResultType = ArrayAggregateResult<Element, aggregate_operation>;
|
using ResultType = ArrayAggregateResult<Element, aggregate_operation>;
|
||||||
using ColVecType = std::conditional_t<IsDecimalNumber<Element>, ColumnDecimal<Element>, ColumnVector<Element>>;
|
using ColVecType = ColumnVectorOrDecimal<Element>;
|
||||||
using ColVecResultType = std::conditional_t<IsDecimalNumber<ResultType>, ColumnDecimal<ResultType>, ColumnVector<ResultType>>;
|
using ColVecResultType = ColumnVectorOrDecimal<ResultType>;
|
||||||
|
|
||||||
/// For average and product of array we return Float64 as result, but we want to keep precision
|
/// For average and product of array we return Float64 as result, but we want to keep precision
|
||||||
/// so we convert to Float64 as last step, but intermediate value is represented as result of sum operation
|
/// so we convert to Float64 as last step, but intermediate value is represented as result of sum operation
|
||||||
@ -160,7 +160,7 @@ struct ArrayAggregateImpl
|
|||||||
const auto & data = checkAndGetColumn<ColVecType>(&column_const->getDataColumn())->getData();
|
const auto & data = checkAndGetColumn<ColVecType>(&column_const->getDataColumn())->getData();
|
||||||
|
|
||||||
typename ColVecResultType::MutablePtr res_column;
|
typename ColVecResultType::MutablePtr res_column;
|
||||||
if constexpr (IsDecimalNumber<Element>)
|
if constexpr (is_decimal<Element>)
|
||||||
res_column = ColVecResultType::create(offsets.size(), data.getScale());
|
res_column = ColVecResultType::create(offsets.size(), data.getScale());
|
||||||
else
|
else
|
||||||
res_column = ColVecResultType::create(offsets.size());
|
res_column = ColVecResultType::create(offsets.size());
|
||||||
@ -183,7 +183,7 @@ struct ArrayAggregateImpl
|
|||||||
}
|
}
|
||||||
else if constexpr (aggregate_operation == AggregateOperation::average)
|
else if constexpr (aggregate_operation == AggregateOperation::average)
|
||||||
{
|
{
|
||||||
if constexpr (IsDecimalNumber<Element>)
|
if constexpr (is_decimal<Element>)
|
||||||
{
|
{
|
||||||
res[i] = DecimalUtils::convertTo<ResultType>(x, data.getScale());
|
res[i] = DecimalUtils::convertTo<ResultType>(x, data.getScale());
|
||||||
}
|
}
|
||||||
@ -197,7 +197,7 @@ struct ArrayAggregateImpl
|
|||||||
size_t array_size = offsets[i] - pos;
|
size_t array_size = offsets[i] - pos;
|
||||||
AggregationType product = x;
|
AggregationType product = x;
|
||||||
|
|
||||||
if constexpr (IsDecimalNumber<Element>)
|
if constexpr (is_decimal<Element>)
|
||||||
{
|
{
|
||||||
using T = decltype(x.value);
|
using T = decltype(x.value);
|
||||||
T x_val = x.value;
|
T x_val = x.value;
|
||||||
@ -235,7 +235,7 @@ struct ArrayAggregateImpl
|
|||||||
const auto & data = column->getData();
|
const auto & data = column->getData();
|
||||||
|
|
||||||
typename ColVecResultType::MutablePtr res_column;
|
typename ColVecResultType::MutablePtr res_column;
|
||||||
if constexpr (IsDecimalNumber<Element>)
|
if constexpr (is_decimal<Element>)
|
||||||
res_column = ColVecResultType::create(offsets.size(), data.getScale());
|
res_column = ColVecResultType::create(offsets.size(), data.getScale());
|
||||||
else
|
else
|
||||||
res_column = ColVecResultType::create(offsets.size());
|
res_column = ColVecResultType::create(offsets.size());
|
||||||
@ -250,7 +250,7 @@ struct ArrayAggregateImpl
|
|||||||
/// Array is empty
|
/// Array is empty
|
||||||
if (offsets[i] == pos)
|
if (offsets[i] == pos)
|
||||||
{
|
{
|
||||||
if constexpr (IsDecimalNumber<AggregationType>)
|
if constexpr (is_decimal<AggregationType>)
|
||||||
res[i] = aggregate_value.value;
|
res[i] = aggregate_value.value;
|
||||||
else
|
else
|
||||||
res[i] = aggregate_value;
|
res[i] = aggregate_value;
|
||||||
@ -286,7 +286,7 @@ struct ArrayAggregateImpl
|
|||||||
}
|
}
|
||||||
else if constexpr (aggregate_operation == AggregateOperation::product)
|
else if constexpr (aggregate_operation == AggregateOperation::product)
|
||||||
{
|
{
|
||||||
if constexpr (IsDecimalNumber<Element>)
|
if constexpr (is_decimal<Element>)
|
||||||
{
|
{
|
||||||
using AggregateValueDecimalUnderlyingValue = decltype(aggregate_value.value);
|
using AggregateValueDecimalUnderlyingValue = decltype(aggregate_value.value);
|
||||||
AggregateValueDecimalUnderlyingValue current_aggregate_value = aggregate_value.value;
|
AggregateValueDecimalUnderlyingValue current_aggregate_value = aggregate_value.value;
|
||||||
@ -306,7 +306,7 @@ struct ArrayAggregateImpl
|
|||||||
|
|
||||||
if constexpr (aggregate_operation == AggregateOperation::average)
|
if constexpr (aggregate_operation == AggregateOperation::average)
|
||||||
{
|
{
|
||||||
if constexpr (IsDecimalNumber<Element>)
|
if constexpr (is_decimal<Element>)
|
||||||
{
|
{
|
||||||
aggregate_value = aggregate_value / AggregationType(count);
|
aggregate_value = aggregate_value / AggregationType(count);
|
||||||
res[i] = DecimalUtils::convertTo<ResultType>(aggregate_value, data.getScale());
|
res[i] = DecimalUtils::convertTo<ResultType>(aggregate_value, data.getScale());
|
||||||
@ -316,7 +316,7 @@ struct ArrayAggregateImpl
|
|||||||
res[i] = static_cast<ResultType>(aggregate_value) / count;
|
res[i] = static_cast<ResultType>(aggregate_value) / count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if constexpr (aggregate_operation == AggregateOperation::product && IsDecimalNumber<Element>)
|
else if constexpr (aggregate_operation == AggregateOperation::product && is_decimal<Element>)
|
||||||
{
|
{
|
||||||
auto result_scale = data.getScale() * count;
|
auto result_scale = data.getScale() * count;
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ struct ArrayCompactImpl
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
static bool executeType(const ColumnPtr & mapped, const ColumnArray & array, ColumnPtr & res_ptr)
|
static bool executeType(const ColumnPtr & mapped, const ColumnArray & array, ColumnPtr & res_ptr)
|
||||||
{
|
{
|
||||||
using ColVecType = std::conditional_t<IsDecimalNumber<T>, ColumnDecimal<T>, ColumnVector<T>>;
|
using ColVecType = ColumnVectorOrDecimal<T>;
|
||||||
|
|
||||||
const ColVecType * src_values_column = checkAndGetColumn<ColVecType>(mapped.get());
|
const ColVecType * src_values_column = checkAndGetColumn<ColVecType>(mapped.get());
|
||||||
|
|
||||||
@ -39,7 +39,7 @@ struct ArrayCompactImpl
|
|||||||
const typename ColVecType::Container & src_values = src_values_column->getData();
|
const typename ColVecType::Container & src_values = src_values_column->getData();
|
||||||
|
|
||||||
typename ColVecType::MutablePtr res_values_column;
|
typename ColVecType::MutablePtr res_values_column;
|
||||||
if constexpr (IsDecimalNumber<T>)
|
if constexpr (is_decimal<T>)
|
||||||
res_values_column = ColVecType::create(src_values.size(), src_values.getScale());
|
res_values_column = ColVecType::create(src_values.size(), src_values.getScale());
|
||||||
else
|
else
|
||||||
res_values_column = ColVecType::create(src_values.size());
|
res_values_column = ColVecType::create(src_values.size());
|
||||||
|
@ -83,8 +83,8 @@ struct ArrayCumSumImpl
|
|||||||
template <typename Element, typename Result>
|
template <typename Element, typename Result>
|
||||||
static bool executeType(const ColumnPtr & mapped, const ColumnArray & array, ColumnPtr & res_ptr)
|
static bool executeType(const ColumnPtr & mapped, const ColumnArray & array, ColumnPtr & res_ptr)
|
||||||
{
|
{
|
||||||
using ColVecType = std::conditional_t<IsDecimalNumber<Element>, ColumnDecimal<Element>, ColumnVector<Element>>;
|
using ColVecType = ColumnVectorOrDecimal<Element>;
|
||||||
using ColVecResult = std::conditional_t<IsDecimalNumber<Result>, ColumnDecimal<Result>, ColumnVector<Result>>;
|
using ColVecResult = ColumnVectorOrDecimal<Result>;
|
||||||
|
|
||||||
const ColVecType * column = checkAndGetColumn<ColVecType>(&*mapped);
|
const ColVecType * column = checkAndGetColumn<ColVecType>(&*mapped);
|
||||||
|
|
||||||
@ -99,7 +99,7 @@ struct ArrayCumSumImpl
|
|||||||
const IColumn::Offsets & offsets = array.getOffsets();
|
const IColumn::Offsets & offsets = array.getOffsets();
|
||||||
|
|
||||||
typename ColVecResult::MutablePtr res_nested;
|
typename ColVecResult::MutablePtr res_nested;
|
||||||
if constexpr (IsDecimalNumber<Element>)
|
if constexpr (is_decimal<Element>)
|
||||||
{
|
{
|
||||||
const typename ColVecType::Container & data =
|
const typename ColVecType::Container & data =
|
||||||
checkAndGetColumn<ColVecType>(&column_const->getDataColumn())->getData();
|
checkAndGetColumn<ColVecType>(&column_const->getDataColumn())->getData();
|
||||||
@ -119,7 +119,7 @@ struct ArrayCumSumImpl
|
|||||||
const IColumn::Offsets & offsets = array.getOffsets();
|
const IColumn::Offsets & offsets = array.getOffsets();
|
||||||
|
|
||||||
typename ColVecResult::MutablePtr res_nested;
|
typename ColVecResult::MutablePtr res_nested;
|
||||||
if constexpr (IsDecimalNumber<Element>)
|
if constexpr (is_decimal<Element>)
|
||||||
res_nested = ColVecResult::create(0, data.getScale());
|
res_nested = ColVecResult::create(0, data.getScale());
|
||||||
else
|
else
|
||||||
res_nested = ColVecResult::create();
|
res_nested = ColVecResult::create();
|
||||||
|
@ -70,8 +70,8 @@ struct ArrayCumSumNonNegativeImpl
|
|||||||
template <typename Element, typename Result>
|
template <typename Element, typename Result>
|
||||||
static bool executeType(const ColumnPtr & mapped, const ColumnArray & array, ColumnPtr & res_ptr)
|
static bool executeType(const ColumnPtr & mapped, const ColumnArray & array, ColumnPtr & res_ptr)
|
||||||
{
|
{
|
||||||
using ColVecType = std::conditional_t<IsDecimalNumber<Element>, ColumnDecimal<Element>, ColumnVector<Element>>;
|
using ColVecType = ColumnVectorOrDecimal<Element>;
|
||||||
using ColVecResult = std::conditional_t<IsDecimalNumber<Result>, ColumnDecimal<Result>, ColumnVector<Result>>;
|
using ColVecResult = ColumnVectorOrDecimal<Result>;
|
||||||
|
|
||||||
const ColVecType * column = checkAndGetColumn<ColVecType>(&*mapped);
|
const ColVecType * column = checkAndGetColumn<ColVecType>(&*mapped);
|
||||||
|
|
||||||
@ -82,7 +82,7 @@ struct ArrayCumSumNonNegativeImpl
|
|||||||
const typename ColVecType::Container & data = column->getData();
|
const typename ColVecType::Container & data = column->getData();
|
||||||
|
|
||||||
typename ColVecResult::MutablePtr res_nested;
|
typename ColVecResult::MutablePtr res_nested;
|
||||||
if constexpr (IsDecimalNumber<Element>)
|
if constexpr (is_decimal<Element>)
|
||||||
res_nested = ColVecResult::create(0, data.getScale());
|
res_nested = ColVecResult::create(0, data.getScale());
|
||||||
else
|
else
|
||||||
res_nested = ColVecResult::create();
|
res_nested = ColVecResult::create();
|
||||||
|
@ -64,7 +64,7 @@ struct ArrayDifferenceImpl
|
|||||||
{
|
{
|
||||||
Element curr = src[pos];
|
Element curr = src[pos];
|
||||||
|
|
||||||
if constexpr (IsDecimalNumber<Element>)
|
if constexpr (is_decimal<Element>)
|
||||||
{
|
{
|
||||||
using ResultNativeType = typename Result::NativeType;
|
using ResultNativeType = typename Result::NativeType;
|
||||||
|
|
||||||
@ -92,8 +92,8 @@ struct ArrayDifferenceImpl
|
|||||||
template <typename Element, typename Result>
|
template <typename Element, typename Result>
|
||||||
static bool executeType(const ColumnPtr & mapped, const ColumnArray & array, ColumnPtr & res_ptr)
|
static bool executeType(const ColumnPtr & mapped, const ColumnArray & array, ColumnPtr & res_ptr)
|
||||||
{
|
{
|
||||||
using ColVecType = std::conditional_t<IsDecimalNumber<Element>, ColumnDecimal<Element>, ColumnVector<Element>>;
|
using ColVecType = ColumnVectorOrDecimal<Element>;
|
||||||
using ColVecResult = std::conditional_t<IsDecimalNumber<Result>, ColumnDecimal<Result>, ColumnVector<Result>>;
|
using ColVecResult = ColumnVectorOrDecimal<Result>;
|
||||||
|
|
||||||
const ColVecType * column = checkAndGetColumn<ColVecType>(&*mapped);
|
const ColVecType * column = checkAndGetColumn<ColVecType>(&*mapped);
|
||||||
|
|
||||||
@ -104,7 +104,7 @@ struct ArrayDifferenceImpl
|
|||||||
const typename ColVecType::Container & data = column->getData();
|
const typename ColVecType::Container & data = column->getData();
|
||||||
|
|
||||||
typename ColVecResult::MutablePtr res_nested;
|
typename ColVecResult::MutablePtr res_nested;
|
||||||
if constexpr (IsDecimalNumber<Element>)
|
if constexpr (is_decimal<Element>)
|
||||||
res_nested = ColVecResult::create(0, data.getScale());
|
res_nested = ColVecResult::create(0, data.getScale());
|
||||||
else
|
else
|
||||||
res_nested = ColVecResult::create();
|
res_nested = ColVecResult::create();
|
||||||
|
@ -904,7 +904,7 @@ bool FunctionArrayElement::matchKeyToIndexString(
|
|||||||
template <typename FromType, typename ToType>
|
template <typename FromType, typename ToType>
|
||||||
static constexpr bool areConvertibleTypes =
|
static constexpr bool areConvertibleTypes =
|
||||||
std::is_same_v<FromType, ToType>
|
std::is_same_v<FromType, ToType>
|
||||||
|| (is_integer_v<FromType> && is_integer_v<ToType>
|
|| (is_integer<FromType> && is_integer<ToType>
|
||||||
&& std::is_convertible_v<FromType, ToType>);
|
&& std::is_convertible_v<FromType, ToType>);
|
||||||
|
|
||||||
template <typename F>
|
template <typename F>
|
||||||
|
@ -231,12 +231,10 @@ private:
|
|||||||
key = col_fixed->getDataAt(offset + j).toString();
|
key = col_fixed->getDataAt(offset + j).toString();
|
||||||
else if (const auto * col_str = checkAndGetColumn<ColumnString>(arg.key_column.get()))
|
else if (const auto * col_str = checkAndGetColumn<ColumnString>(arg.key_column.get()))
|
||||||
key = col_str->getDataAt(offset + j).toString();
|
key = col_str->getDataAt(offset + j).toString();
|
||||||
else
|
else // should not happen
|
||||||
// should not happen
|
throw Exception(ErrorCodes::LOGICAL_ERROR,
|
||||||
throw Exception(
|
"Expected String or FixedString, got {} in {}",
|
||||||
"Expected String or FixedString, got " + std::string(getTypeName(arg.key_column->getDataType()))
|
arg.key_column->getDataType(), getName());
|
||||||
+ " in " + getName(),
|
|
||||||
ErrorCodes::LOGICAL_ERROR);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -25,7 +25,7 @@ struct BitWrapperFuncImpl
|
|||||||
{
|
{
|
||||||
// Should be a logical error, but this function is callable from SQL.
|
// Should be a logical error, but this function is callable from SQL.
|
||||||
// Need to investigate this.
|
// Need to investigate this.
|
||||||
if constexpr (!is_integer_v<A>)
|
if constexpr (!is_integer<A>)
|
||||||
throw DB::Exception("It's a bug! Only integer types are supported by __bitWrapperFunc.", ErrorCodes::BAD_ARGUMENTS);
|
throw DB::Exception("It's a bug! Only integer types are supported by __bitWrapperFunc.", ErrorCodes::BAD_ARGUMENTS);
|
||||||
return a == 0 ? static_cast<ResultType>(0b10) : static_cast<ResultType >(0b1);
|
return a == 0 ? static_cast<ResultType>(0b10) : static_cast<ResultType >(0b1);
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,20 @@
|
|||||||
namespace DB
|
namespace DB
|
||||||
{
|
{
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
template <typename Typelist, size_t ...I>
|
||||||
|
static bool castTypeToEither(const auto * type, auto && f, std::index_sequence<I...>)
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
(typeid_cast<const typename Typelist::template At<I> *>(type)
|
||||||
|
? std::forward<decltype(f)>(f)(
|
||||||
|
*typeid_cast<const typename Typelist::template At<I> *>(type))
|
||||||
|
: false)
|
||||||
|
|| ...);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template <typename... Ts, typename T, typename F>
|
template <typename... Ts, typename T, typename F>
|
||||||
static bool castTypeToEither(const T * type, F && f)
|
static bool castTypeToEither(const T * type, F && f)
|
||||||
{
|
{
|
||||||
@ -12,4 +26,12 @@ static bool castTypeToEither(const T * type, F && f)
|
|||||||
return ((typeid_cast<const Ts *>(type) ? f(*typeid_cast<const Ts *>(type)) : false) || ...);
|
return ((typeid_cast<const Ts *>(type) ? f(*typeid_cast<const Ts *>(type)) : false) || ...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Use Common/TypeList as template argument
|
||||||
|
template <class Typelist>
|
||||||
|
static constexpr bool castTypeToEitherTL(const auto * type, auto && f)
|
||||||
|
{
|
||||||
|
return detail::castTypeToEither<Typelist>(
|
||||||
|
type, std::forward<decltype(f)>(f),
|
||||||
|
std::make_index_sequence<Typelist::size>());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,7 @@ public:
|
|||||||
{
|
{
|
||||||
using Types = std::decay_t<decltype(types)>;
|
using Types = std::decay_t<decltype(types)>;
|
||||||
using Type = typename Types::RightType;
|
using Type = typename Types::RightType;
|
||||||
using ColVecType = std::conditional_t<IsDecimalNumber<Type>, ColumnDecimal<Type>, ColumnVector<Type>>;
|
using ColVecType = ColumnVectorOrDecimal<Type>;
|
||||||
|
|
||||||
if (const ColVecType * col_vec = checkAndGetColumn<ColVecType>(src_column.column.get()))
|
if (const ColVecType * col_vec = checkAndGetColumn<ColVecType>(src_column.column.get()))
|
||||||
{
|
{
|
||||||
@ -84,7 +84,7 @@ private:
|
|||||||
template <typename T, typename ColVecType>
|
template <typename T, typename ColVecType>
|
||||||
static void execute(const ColVecType & col, ColumnUInt8 & result_column, size_t rows_count)
|
static void execute(const ColVecType & col, ColumnUInt8 & result_column, size_t rows_count)
|
||||||
{
|
{
|
||||||
using NativeT = typename NativeType<T>::Type;
|
using NativeT = NativeType<T>;
|
||||||
|
|
||||||
const auto & src_data = col.getData();
|
const auto & src_data = col.getData();
|
||||||
auto & dst_data = result_column.getData();
|
auto & dst_data = result_column.getData();
|
||||||
@ -92,7 +92,7 @@ private:
|
|||||||
|
|
||||||
for (size_t i = 0; i < rows_count; ++i)
|
for (size_t i = 0; i < rows_count; ++i)
|
||||||
{
|
{
|
||||||
if constexpr (IsDecimalNumber<T>)
|
if constexpr (is_decimal<T>)
|
||||||
dst_data[i] = digits<NativeT>(src_data[i].value);
|
dst_data[i] = digits<NativeT>(src_data[i].value);
|
||||||
else
|
else
|
||||||
dst_data[i] = digits<NativeT>(src_data[i]);
|
dst_data[i] = digits<NativeT>(src_data[i]);
|
||||||
@ -102,7 +102,7 @@ private:
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
static UInt32 digits(T value)
|
static UInt32 digits(T value)
|
||||||
{
|
{
|
||||||
static_assert(!IsDecimalNumber<T>);
|
static_assert(!is_decimal<T>);
|
||||||
using DivT = std::conditional_t<is_signed_v<T>, Int32, UInt32>;
|
using DivT = std::conditional_t<is_signed_v<T>, Int32, UInt32>;
|
||||||
|
|
||||||
UInt32 res = 0;
|
UInt32 res = 0;
|
||||||
|
@ -221,7 +221,7 @@ private:
|
|||||||
template <typename T0, typename T1>
|
template <typename T0, typename T1>
|
||||||
static UInt32 decimalScale(const ColumnsWithTypeAndName & arguments [[maybe_unused]])
|
static UInt32 decimalScale(const ColumnsWithTypeAndName & arguments [[maybe_unused]])
|
||||||
{
|
{
|
||||||
if constexpr (IsDecimalNumber<T0> && IsDecimalNumber<T1>)
|
if constexpr (is_decimal<T0> && is_decimal<T1>)
|
||||||
{
|
{
|
||||||
UInt32 left_scale = getDecimalScale(*arguments[1].type);
|
UInt32 left_scale = getDecimalScale(*arguments[1].type);
|
||||||
UInt32 right_scale = getDecimalScale(*arguments[2].type);
|
UInt32 right_scale = getDecimalScale(*arguments[2].type);
|
||||||
@ -416,8 +416,8 @@ private:
|
|||||||
ColumnPtr executeTyped(
|
ColumnPtr executeTyped(
|
||||||
const ColumnUInt8 * cond_col, const ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count) const
|
const ColumnUInt8 * cond_col, const ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count) const
|
||||||
{
|
{
|
||||||
using ColVecT0 = std::conditional_t<IsDecimalNumber<T0>, ColumnDecimal<T0>, ColumnVector<T0>>;
|
using ColVecT0 = ColumnVectorOrDecimal<T0>;
|
||||||
using ColVecT1 = std::conditional_t<IsDecimalNumber<T1>, ColumnDecimal<T1>, ColumnVector<T1>>;
|
using ColVecT1 = ColumnVectorOrDecimal<T1>;
|
||||||
|
|
||||||
const IColumn * col_left_untyped = arguments[1].column.get();
|
const IColumn * col_left_untyped = arguments[1].column.get();
|
||||||
|
|
||||||
|
@ -128,10 +128,9 @@ private:
|
|||||||
dst_data[i] = outOfDigits<T>(src_data[i], precision);
|
dst_data[i] = outOfDigits<T>(src_data[i], precision);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <is_decimal T>
|
||||||
static bool outOfDigits(T dec, UInt32 precision)
|
static bool outOfDigits(T dec, UInt32 precision)
|
||||||
{
|
{
|
||||||
static_assert(IsDecimalNumber<T>);
|
|
||||||
using NativeT = typename T::NativeType;
|
using NativeT = typename T::NativeType;
|
||||||
|
|
||||||
if (precision > DecimalUtils::max_precision<T>)
|
if (precision > DecimalUtils::max_precision<T>)
|
||||||
|
@ -8,7 +8,7 @@ namespace DB
|
|||||||
template <typename A>
|
template <typename A>
|
||||||
struct NegateImpl
|
struct NegateImpl
|
||||||
{
|
{
|
||||||
using ResultType = std::conditional_t<IsDecimalNumber<A>, A, typename NumberTraits::ResultOfNegate<A>::Type>;
|
using ResultType = std::conditional_t<is_decimal<A>, A, typename NumberTraits::ResultOfNegate<A>::Type>;
|
||||||
static constexpr const bool allow_fixed_string = false;
|
static constexpr const bool allow_fixed_string = false;
|
||||||
|
|
||||||
static inline NO_SANITIZE_UNDEFINED ResultType apply(A a)
|
static inline NO_SANITIZE_UNDEFINED ResultType apply(A a)
|
||||||
|
@ -217,7 +217,7 @@ public:
|
|||||||
using From = typename FromType::FieldType;
|
using From = typename FromType::FieldType;
|
||||||
using To = typename ToType::FieldType;
|
using To = typename ToType::FieldType;
|
||||||
|
|
||||||
using FromColumnType = std::conditional_t<IsDecimalNumber<From>, ColumnDecimal<From>, ColumnVector<From>>;
|
using FromColumnType = ColumnVectorOrDecimal<From>;
|
||||||
|
|
||||||
const auto * column_from = assert_cast<const FromColumnType*>(arguments[0].column.get());
|
const auto * column_from = assert_cast<const FromColumnType*>(arguments[0].column.get());
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ struct SignImpl
|
|||||||
|
|
||||||
static inline NO_SANITIZE_UNDEFINED ResultType apply(A a)
|
static inline NO_SANITIZE_UNDEFINED ResultType apply(A a)
|
||||||
{
|
{
|
||||||
if constexpr (IsDecimalNumber<A> || std::is_floating_point_v<A>)
|
if constexpr (is_decimal<A> || std::is_floating_point_v<A>)
|
||||||
return a < A(0) ? -1 : a == A(0) ? 0 : 1;
|
return a < A(0) ? -1 : a == A(0) ? 0 : 1;
|
||||||
else if constexpr (is_signed_v<A>)
|
else if constexpr (is_signed_v<A>)
|
||||||
return a < 0 ? -1 : a == 0 ? 0 : 1;
|
return a < 0 ? -1 : a == 0 ? 0 : 1;
|
||||||
|
@ -261,10 +261,10 @@ public:
|
|||||||
+ ". This argument is optional and must be a constant string with timezone name",
|
+ ". This argument is optional and must be a constant string with timezone name",
|
||||||
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||||
if (first_argument_is_date && result_type_is_date)
|
if (first_argument_is_date && result_type_is_date)
|
||||||
throw Exception(
|
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
|
||||||
"The timezone argument of function " + getName() + " with interval type " + interval_type->getKind().toString()
|
"The timezone argument of function {} with interval type {} is allowed only when the 1st argument "
|
||||||
+ " is allowed only when the 1st argument has the type DateTime",
|
"has the type DateTime",
|
||||||
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
getName(), interval_type->getKind().toString());
|
||||||
};
|
};
|
||||||
|
|
||||||
if (arguments.size() == 2)
|
if (arguments.size() == 2)
|
||||||
|
@ -41,16 +41,8 @@ struct QuoteManipReadBuffer : std::reference_wrapper<ReadBuffer> { usin
|
|||||||
struct DoubleQuoteManipReadBuffer : std::reference_wrapper<ReadBuffer> { using std::reference_wrapper<ReadBuffer>::reference_wrapper; };
|
struct DoubleQuoteManipReadBuffer : std::reference_wrapper<ReadBuffer> { using std::reference_wrapper<ReadBuffer>::reference_wrapper; };
|
||||||
struct BinaryManipReadBuffer : std::reference_wrapper<ReadBuffer> { using std::reference_wrapper<ReadBuffer>::reference_wrapper; };
|
struct BinaryManipReadBuffer : std::reference_wrapper<ReadBuffer> { using std::reference_wrapper<ReadBuffer>::reference_wrapper; };
|
||||||
|
|
||||||
|
inline WriteBuffer & operator<<(WriteBuffer & buf, const auto & x) { writeText(x, buf); return buf; }
|
||||||
template <typename T> WriteBuffer & operator<< (WriteBuffer & buf, const T & x) { writeText(x, buf); return buf; }
|
inline WriteBuffer & operator<<(WriteBuffer & buf, const pcg32_fast & x) { PcgSerializer::serializePcg32(x, buf); return buf; }
|
||||||
/// If you do not use the manipulators, the string is displayed without an escape, as is.
|
|
||||||
template <> inline WriteBuffer & operator<< (WriteBuffer & buf, const String & x) { writeString(x, buf); return buf; }
|
|
||||||
template <> inline WriteBuffer & operator<< (WriteBuffer & buf, const std::string_view & x) { writeString(StringRef(x), buf); return buf; }
|
|
||||||
template <> inline WriteBuffer & operator<< (WriteBuffer & buf, const StringRef & x) { writeString(x, buf); return buf; }
|
|
||||||
template <> inline WriteBuffer & operator<< (WriteBuffer & buf, const char & x) { writeChar(x, buf); return buf; }
|
|
||||||
template <> inline WriteBuffer & operator<< (WriteBuffer & buf, const pcg32_fast & x) { PcgSerializer::serializePcg32(x, buf); return buf; }
|
|
||||||
|
|
||||||
inline WriteBuffer & operator<< (WriteBuffer & buf, const char * x) { writeCString(x, buf); return buf; }
|
|
||||||
|
|
||||||
inline EscapeManipWriteBuffer operator<< (WriteBuffer & buf, EscapeManip) { return buf; }
|
inline EscapeManipWriteBuffer operator<< (WriteBuffer & buf, EscapeManip) { return buf; }
|
||||||
inline QuoteManipWriteBuffer operator<< (WriteBuffer & buf, QuoteManip) { return buf; }
|
inline QuoteManipWriteBuffer operator<< (WriteBuffer & buf, QuoteManip) { return buf; }
|
||||||
@ -63,8 +55,8 @@ template <typename T> WriteBuffer & operator<< (DoubleQuoteManipWriteBuffer buf,
|
|||||||
template <typename T> WriteBuffer & operator<< (BinaryManipWriteBuffer buf, const T & x) { writeBinary(x, buf.get()); return buf; }
|
template <typename T> WriteBuffer & operator<< (BinaryManipWriteBuffer buf, const T & x) { writeBinary(x, buf.get()); return buf; }
|
||||||
|
|
||||||
inline WriteBuffer & operator<< (EscapeManipWriteBuffer buf, const String & x) { writeEscapedString(x, buf); return buf; }
|
inline WriteBuffer & operator<< (EscapeManipWriteBuffer buf, const String & x) { writeEscapedString(x, buf); return buf; }
|
||||||
inline WriteBuffer & operator<< (EscapeManipWriteBuffer buf, const std::string_view & x) { writeEscapedString(x, buf); return buf; }
|
inline WriteBuffer & operator<< (EscapeManipWriteBuffer buf, std::string_view x) { writeEscapedString(x, buf); return buf; }
|
||||||
inline WriteBuffer & operator<< (EscapeManipWriteBuffer buf, const StringRef & x) { writeEscapedString(x, buf); return buf; }
|
inline WriteBuffer & operator<< (EscapeManipWriteBuffer buf, StringRef x) { writeEscapedString(x, buf); return buf; }
|
||||||
inline WriteBuffer & operator<< (EscapeManipWriteBuffer buf, const char * x) { writeEscapedString(x, strlen(x), buf); return buf; }
|
inline WriteBuffer & operator<< (EscapeManipWriteBuffer buf, const char * x) { writeEscapedString(x, strlen(x), buf); return buf; }
|
||||||
|
|
||||||
inline WriteBuffer & operator<< (QuoteManipWriteBuffer buf, const char * x) { writeAnyQuotedString<'\''>(x, x + strlen(x), buf.get()); return buf; }
|
inline WriteBuffer & operator<< (QuoteManipWriteBuffer buf, const char * x) { writeAnyQuotedString<'\''>(x, x + strlen(x), buf.get()); return buf; }
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user