mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-24 08:32:02 +00:00
decimal field extraction (from column or type)
This commit is contained in:
parent
479166283e
commit
01c8b1d7bb
@ -8,6 +8,12 @@
|
||||
namespace DB
|
||||
{
|
||||
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int LOGICAL_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/** Stuff for comparing numbers.
|
||||
* Integer values are compared as usual.
|
||||
* Floating-point numbers are compared this way that NaNs always end up at the end
|
||||
@ -117,6 +123,54 @@ template <> inline UInt64 unionCastToUInt64(Float32 x)
|
||||
}
|
||||
|
||||
|
||||
/// PaddedPODArray extended by Decimal scale
|
||||
template <typename T, size_t INITIAL_SIZE = 4096>
|
||||
class DecPaddedPODArray : public PODArray<T, INITIAL_SIZE, Allocator<false>, sizeof(T)-1>
|
||||
{
|
||||
public:
|
||||
using Base = PODArray<T, INITIAL_SIZE, Allocator<false>, sizeof(T)-1>;
|
||||
using Base::operator[];
|
||||
|
||||
DecPaddedPODArray()
|
||||
{}
|
||||
|
||||
DecPaddedPODArray(size_t n)
|
||||
: Base(n)
|
||||
{}
|
||||
|
||||
DecPaddedPODArray(size_t n, const T & x)
|
||||
: Base(n, x)
|
||||
{}
|
||||
|
||||
DecPaddedPODArray(typename Base::const_iterator from_begin, typename Base::const_iterator from_end)
|
||||
: Base(from_begin, from_end)
|
||||
{}
|
||||
|
||||
DecPaddedPODArray(std::initializer_list<T> il)
|
||||
: DecPaddedPODArray(std::begin(il), std::end(il))
|
||||
{}
|
||||
|
||||
DecPaddedPODArray(DecPaddedPODArray && other)
|
||||
{
|
||||
this->swap(other);
|
||||
std::swap(scale, other.scale);
|
||||
}
|
||||
|
||||
DecPaddedPODArray & operator= (DecPaddedPODArray && other)
|
||||
{
|
||||
this->swap(other);
|
||||
std::swap(scale, other.scale);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void setScale(UInt32 s) { scale = s; }
|
||||
UInt32 getScale() const { return scale; }
|
||||
|
||||
private:
|
||||
UInt32 scale = std::numeric_limits<UInt32>::max();
|
||||
};
|
||||
|
||||
|
||||
/** A template for columns that use a simple array to store.
|
||||
*/
|
||||
template <typename T>
|
||||
@ -131,7 +185,7 @@ private:
|
||||
|
||||
public:
|
||||
using value_type = T;
|
||||
using Container = PaddedPODArray<value_type>;
|
||||
using Container = std::conditional_t<decTrait<T>(), DecPaddedPODArray<value_type>, PaddedPODArray<value_type>>;
|
||||
|
||||
private:
|
||||
ColumnVector() {}
|
||||
@ -215,12 +269,20 @@ public:
|
||||
|
||||
Field operator[](size_t n) const override
|
||||
{
|
||||
return typename NearestFieldType<T>::Type(data[n]);
|
||||
if constexpr (decTrait<T>())
|
||||
{
|
||||
UInt32 scale = data.getScale();
|
||||
if (scale == std::numeric_limits<UInt32>::max())
|
||||
throw Exception("Extracting Decimal field with unknown scale. Scale is lost.", ErrorCodes::LOGICAL_ERROR);
|
||||
return DecField(data[n], scale);
|
||||
}
|
||||
else
|
||||
return typename NearestFieldType<T>::Type(data[n]);
|
||||
}
|
||||
|
||||
void get(size_t n, Field & res) const override
|
||||
{
|
||||
res = typename NearestFieldType<T>::Type(data[n]);
|
||||
res = (*this)[n];
|
||||
}
|
||||
|
||||
UInt64 get64(size_t n) const override;
|
||||
|
@ -41,6 +41,7 @@ public:
|
||||
operator Dec32() const { return dec; }
|
||||
operator Dec64() const { return dec; }
|
||||
operator Dec128() const { return dec; }
|
||||
|
||||
UInt32 getScale() const { return scale; }
|
||||
|
||||
bool operator < (const DecField & r) const;
|
||||
@ -51,8 +52,6 @@ public:
|
||||
bool operator >= (const DecField & r) const { return r <= * this; }
|
||||
bool operator != (const DecField & r) const { return !(*this == r); }
|
||||
|
||||
bool hasScale() const { return scale != wrongScale(); }
|
||||
|
||||
private:
|
||||
Int128 dec;
|
||||
UInt32 scale;
|
||||
|
@ -148,7 +148,9 @@ Field DataTypeDecimal<T>::getDefault() const
|
||||
template <typename T>
|
||||
MutableColumnPtr DataTypeDecimal<T>::createColumn() const
|
||||
{
|
||||
return ColumnType::create();
|
||||
auto column = ColumnType::create();
|
||||
column->getData().setScale(scale);
|
||||
return column;
|
||||
}
|
||||
|
||||
|
||||
|
@ -15,6 +15,18 @@ namespace common
|
||||
return __builtin_add_overflow(x, y, &res);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool addOverflow(Int32 x, Int32 y, Int32 & res)
|
||||
{
|
||||
return __builtin_sadd_overflow(x, y, &res);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool addOverflow(Int64 x, Int64 y, Int64 & res)
|
||||
{
|
||||
return __builtin_saddl_overflow(x, y, &res);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool addOverflow(__int128 x, __int128 y, __int128 & res)
|
||||
{
|
||||
@ -28,6 +40,18 @@ namespace common
|
||||
return __builtin_sub_overflow(x, y, &res);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool subOverflow(Int32 x, Int32 y, Int32 & res)
|
||||
{
|
||||
return __builtin_ssub_overflow(x, y, &res);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool subOverflow(Int64 x, Int64 y, Int64 & res)
|
||||
{
|
||||
return __builtin_ssubl_overflow(x, y, &res);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool subOverflow(__int128 x, __int128 y, __int128 & res)
|
||||
{
|
||||
@ -41,6 +65,18 @@ namespace common
|
||||
return __builtin_mul_overflow(x, y, &res);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool mulOverflow(Int32 x, Int32 y, Int32 & res)
|
||||
{
|
||||
return __builtin_smul_overflow(x, y, &res);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool mulOverflow(Int64 x, Int64 y, Int64 & res)
|
||||
{
|
||||
return __builtin_smull_overflow(x, y, &res);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool mulOverflow(__int128 x, __int128 y, __int128 & res)
|
||||
{
|
||||
|
@ -90,8 +90,10 @@ template <typename A, typename Op>
|
||||
struct UnaryOperationImpl
|
||||
{
|
||||
using ResultType = typename Op::ResultType;
|
||||
using ArrayA = typename ColumnVector<A>::Container;
|
||||
using ArrayC = typename ColumnVector<ResultType>::Container;
|
||||
|
||||
static void NO_INLINE vector(const PaddedPODArray<A> & a, PaddedPODArray<ResultType> & c)
|
||||
static void NO_INLINE vector(const ArrayA & a, ArrayC & c)
|
||||
{
|
||||
size_t size = a.size();
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
@ -729,6 +731,9 @@ struct DecimalBinaryOperation
|
||||
using ResultType = ResultType_;
|
||||
using NativeResultType = typename NativeType<ResultType>::Type;
|
||||
using Op = Operation<NativeResultType, NativeResultType>;
|
||||
using ArrayA = typename ColumnVector<A>::Container;
|
||||
using ArrayB = typename ColumnVector<B>::Container;
|
||||
using ArrayC = typename ColumnVector<ResultType>::Container;
|
||||
|
||||
static constexpr bool is_plus_minus = std::is_same_v<Operation<Int32, Int32>, PlusImpl<Int32, Int32>> ||
|
||||
std::is_same_v<Operation<Int32, Int32>, MinusImpl<Int32, Int32>>;
|
||||
@ -739,7 +744,7 @@ struct DecimalBinaryOperation
|
||||
static constexpr bool is_plus_minus_compare = is_plus_minus || is_compare;
|
||||
static constexpr bool can_overflow = is_plus_minus || is_multiply;
|
||||
|
||||
static void NO_INLINE vector_vector(const PaddedPODArray<A> & a, const PaddedPODArray<B> & b, PaddedPODArray<ResultType> & c,
|
||||
static void NO_INLINE vector_vector(const ArrayA & a, const ArrayB & b, ArrayC & c,
|
||||
ResultType scale_a [[maybe_unused]], ResultType scale_b [[maybe_unused]])
|
||||
{
|
||||
size_t size = a.size();
|
||||
@ -770,7 +775,7 @@ struct DecimalBinaryOperation
|
||||
c[i] = apply(a[i], b[i]);
|
||||
}
|
||||
|
||||
static void NO_INLINE vector_constant(const PaddedPODArray<A> & a, B b, PaddedPODArray<ResultType> & c,
|
||||
static void NO_INLINE vector_constant(const ArrayA & a, B b, ArrayC & c,
|
||||
ResultType scale_a [[maybe_unused]], ResultType scale_b [[maybe_unused]])
|
||||
{
|
||||
size_t size = a.size();
|
||||
@ -801,7 +806,7 @@ struct DecimalBinaryOperation
|
||||
c[i] = apply(a[i], b);
|
||||
}
|
||||
|
||||
static void NO_INLINE constant_vector(A a, const PaddedPODArray<B> & b, PaddedPODArray<ResultType> & c,
|
||||
static void NO_INLINE constant_vector(A a, const ArrayB & b, ArrayC & c,
|
||||
ResultType scale_a [[maybe_unused]], ResultType scale_b [[maybe_unused]])
|
||||
{
|
||||
size_t size = b.size();
|
||||
@ -1221,6 +1226,8 @@ public:
|
||||
if constexpr (result_is_decimal)
|
||||
{
|
||||
ResultDataType type = decimalResultType(left, right, is_multiply, is_division);
|
||||
vec_res.setScale(type.getScale());
|
||||
|
||||
typename ResultDataType::FieldType scale_a = type.scaleFactorFor(left, is_multiply);
|
||||
typename ResultDataType::FieldType scale_b = type.scaleFactorFor(right, is_multiply || is_division);
|
||||
if constexpr (IsDecimal<RightDataType> && is_division)
|
||||
@ -1238,6 +1245,8 @@ public:
|
||||
if constexpr (result_is_decimal)
|
||||
{
|
||||
ResultDataType type = decimalResultType(left, right, is_multiply, is_division);
|
||||
vec_res.setScale(type.getScale());
|
||||
|
||||
typename ResultDataType::FieldType scale_a = type.scaleFactorFor(left, is_multiply);
|
||||
typename ResultDataType::FieldType scale_b = type.scaleFactorFor(right, is_multiply || is_division);
|
||||
if constexpr (IsDecimal<RightDataType> && is_division)
|
||||
|
@ -225,6 +225,10 @@ class DecimalComparison
|
||||
public:
|
||||
using CompareInt = typename DecCompareInt<A, B>::Type;
|
||||
using Op = Operation<CompareInt, CompareInt>;
|
||||
using ColVecA = ColumnVector<A>;
|
||||
using ColVecB = ColumnVector<B>;
|
||||
using ArrayA = typename ColVecA::Container;
|
||||
using ArrayB = typename ColVecB::Container;
|
||||
|
||||
DecimalComparison(Block & block, size_t result, const ColumnWithTypeAndName & col_left, const ColumnWithTypeAndName & col_right)
|
||||
{
|
||||
@ -332,9 +336,6 @@ private:
|
||||
template <bool scale_left, bool scale_right>
|
||||
static ColumnPtr apply(const ColumnPtr & c0, const ColumnPtr & c1, CompareInt scale)
|
||||
{
|
||||
using ColVecA = ColumnVector<A>;
|
||||
using ColVecB = ColumnVector<B>;
|
||||
|
||||
auto c_res = ColumnUInt8::create();
|
||||
|
||||
if constexpr (_actual)
|
||||
@ -424,7 +425,7 @@ private:
|
||||
}
|
||||
|
||||
template <bool scale_left, bool scale_right>
|
||||
static void NO_INLINE vector_vector(const PaddedPODArray<A> & a, const PaddedPODArray<B> & b, PaddedPODArray<UInt8> & c,
|
||||
static void NO_INLINE vector_vector(const ArrayA & a, const ArrayB & b, PaddedPODArray<UInt8> & c,
|
||||
CompareInt scale)
|
||||
{
|
||||
size_t size = a.size();
|
||||
@ -443,7 +444,7 @@ private:
|
||||
}
|
||||
|
||||
template <bool scale_left, bool scale_right>
|
||||
static void NO_INLINE vector_constant(const PaddedPODArray<A> & a, B b, PaddedPODArray<UInt8> & c, CompareInt scale)
|
||||
static void NO_INLINE vector_constant(const ArrayA & a, B b, PaddedPODArray<UInt8> & c, CompareInt scale)
|
||||
{
|
||||
size_t size = a.size();
|
||||
const A * a_pos = &a[0];
|
||||
@ -459,7 +460,7 @@ private:
|
||||
}
|
||||
|
||||
template <bool scale_left, bool scale_right>
|
||||
static void NO_INLINE constant_vector(A a, const PaddedPODArray<B> & b, PaddedPODArray<UInt8> & c, CompareInt scale)
|
||||
static void NO_INLINE constant_vector(A a, const ArrayB & b, PaddedPODArray<UInt8> & c, CompareInt scale)
|
||||
{
|
||||
size_t size = b.size();
|
||||
const B * b_pos = &b[0];
|
||||
|
@ -33,3 +33,5 @@
|
||||
0 1
|
||||
0 1
|
||||
0 1
|
||||
-42 -42 -42 -0.420000000 -0.420000000000000000 -0.42000000000000000000000000000000000000 -42.42000 -42.420000000 -42.420000000000000000 -42.42
|
||||
42 42 42 0.420000000 0.420000000000000000 0.42000000000000000000000000000000000000 42.42000 42.420000000 42.420000000000000000 42.42
|
||||
|
@ -62,7 +62,7 @@ SELECT h = 10000000000 FROM test.decimal WHERE a = 42; -- { serverError 405 }
|
||||
SELECT i = 10000000000, (i - g + 10000000000) = 10000000000 FROM test.decimal WHERE a = 42;
|
||||
SELECT 10000000000 = i, 10000000000 = (i - g + 10000000000) FROM test.decimal WHERE a = 42;
|
||||
|
||||
--SELECT min(a), min(b), min(c), min(d), min(e), min(f), min(g), min(h), min(i), min(j) FROM test.decimal;
|
||||
--SELECT max(a), max(b), max(c), max(d), max(e), max(f), max(g), max(h), max(i), max(j) FROM test.decimal;
|
||||
SELECT min(a), min(b), min(c), min(d), min(e), min(f), min(g), min(h), min(i), min(j) FROM test.decimal;
|
||||
SELECT max(a), max(b), max(c), max(d), max(e), max(f), max(g), max(h), max(i), max(j) FROM test.decimal;
|
||||
|
||||
DROP TABLE IF EXISTS test.decimal;
|
||||
|
Loading…
Reference in New Issue
Block a user