[feature](decimal) support decimal256 (#25386)

This commit is contained in:
TengJianPing
2023-10-25 15:47:51 +08:00
committed by GitHub
parent 97c2fe75d1
commit 693982fd1a
153 changed files with 5647 additions and 633 deletions

View File

@ -79,7 +79,7 @@ struct OperationTraits {
std::is_same_v<Op, DivideIntegralImpl<T, T>>;
static constexpr bool can_overflow =
(is_plus_minus || is_multiply) &&
(IsDecimalV2<OpA> || IsDecimalV2<OpB> || IsDecimal128I<OpA> || IsDecimal128I<OpB>);
(IsDecimalV2<OpA> || IsDecimalV2<OpB> || IsDecimal256<OpA> || IsDecimal256<OpB>);
static constexpr bool has_variadic_argument =
!std::is_void_v<decltype(has_variadic_argument_types(std::declval<Op>()))>;
};
@ -239,7 +239,7 @@ struct DecimalBinaryOperation {
Op::vector_vector(a, b, c, size);
} else {
for (size_t i = 0; i < size; i++) {
c[i] = apply(a[i], b[i]);
c[i] = typename ArrayC::value_type(apply(a[i], b[i]));
}
}
}
@ -251,11 +251,20 @@ struct DecimalBinaryOperation {
if constexpr (IsDecimalV2<B> || IsDecimalV2<A>) {
/// default: use it if no return before
for (size_t i = 0; i < size; ++i) {
c[i] = apply(a[i], b[i], null_map[i]);
c[i] = typename ArrayC::value_type(apply(a[i], b[i], null_map[i]));
}
} else if constexpr (OpTraits::is_division && (IsDecimalNumber<B> || IsDecimalNumber<A>)) {
for (size_t i = 0; i < size; ++i) {
c[i] = apply_scaled_div(a[i], b[i], null_map[i]);
if constexpr (IsDecimalNumber<B> && IsDecimalNumber<A>) {
c[i] = typename ArrayC::value_type(
apply_scaled_div(a[i].value, b[i].value, null_map[i]));
} else if constexpr (IsDecimalNumber<A>) {
c[i] = typename ArrayC::value_type(
apply_scaled_div(a[i].value, b[i], null_map[i]));
} else {
c[i] = typename ArrayC::value_type(
apply_scaled_div(a[i], b[i].value, null_map[i]));
}
}
} else if constexpr ((OpTraits::is_multiply || OpTraits::is_plus_minus) &&
(IsDecimalNumber<B> || IsDecimalNumber<A>)) {
@ -264,7 +273,7 @@ struct DecimalBinaryOperation {
}
} else {
for (size_t i = 0; i < size; ++i) {
c[i] = apply(a[i], b[i], null_map[i]);
c[i] = typename ArrayC::value_type(apply(a[i], b[i], null_map[i]));
}
}
}
@ -273,14 +282,14 @@ struct DecimalBinaryOperation {
typename ArrayC::value_type* c, size_t size) {
if constexpr (OpTraits::is_division && IsDecimalNumber<B>) {
for (size_t i = 0; i < size; ++i) {
c[i] = apply_scaled_div(a[i], b);
c[i] = typename ArrayC::value_type(apply_scaled_div(a[i], b));
}
return;
}
/// default: use it if no return before
for (size_t i = 0; i < size; ++i) {
c[i] = apply(a[i], b);
c[i] = typename ArrayC::value_type(apply(a[i], b));
}
}
@ -288,7 +297,7 @@ struct DecimalBinaryOperation {
typename ArrayC::value_type* c, NullMap& null_map, size_t size) {
if constexpr (OpTraits::is_division && IsDecimalNumber<B>) {
for (size_t i = 0; i < size; ++i) {
c[i] = apply_scaled_div(a[i], b, null_map[i]);
c[i] = typename ArrayC::value_type(apply_scaled_div(a[i], b.value, null_map[i]));
}
} else if constexpr ((OpTraits::is_multiply || OpTraits::is_plus_minus) &&
(IsDecimalNumber<B> || IsDecimalNumber<A>)) {
@ -297,7 +306,7 @@ struct DecimalBinaryOperation {
}
} else {
for (size_t i = 0; i < size; ++i) {
c[i] = apply(a[i], b, null_map[i]);
c[i] = typename ArrayC::value_type(apply(a[i], b, null_map[i]));
}
}
}
@ -307,11 +316,12 @@ struct DecimalBinaryOperation {
if constexpr (IsDecimalV2<A> || IsDecimalV2<B>) {
DecimalV2Value da(a);
for (size_t i = 0; i < size; ++i) {
c[i] = Op::template apply(da, DecimalV2Value(b[i])).value();
c[i] = typename ArrayC::value_type(
Op::template apply(da, DecimalV2Value(b[i])).value());
}
} else {
for (size_t i = 0; i < size; ++i) {
c[i] = apply(a, b[i]);
c[i] = typename ArrayC::value_type(apply(a, b[i]));
}
}
}
@ -320,7 +330,7 @@ struct DecimalBinaryOperation {
typename ArrayC::value_type* c, NullMap& null_map, size_t size) {
if constexpr (OpTraits::is_division && IsDecimalNumber<B>) {
for (size_t i = 0; i < size; ++i) {
c[i] = apply_scaled_div(a, b[i], null_map[i]);
c[i] = typename ArrayC::value_type(apply_scaled_div(a, b[i].value, null_map[i]));
}
} else if constexpr ((OpTraits::is_multiply || OpTraits::is_plus_minus) &&
(IsDecimalNumber<B> || IsDecimalNumber<A>)) {
@ -329,23 +339,27 @@ struct DecimalBinaryOperation {
}
} else {
for (size_t i = 0; i < size; ++i) {
c[i] = apply(a, b[i], null_map[i]);
c[i] = typename ArrayC::value_type(apply(a, b[i], null_map[i]));
}
}
}
static ResultType constant_constant(A a, B b) { return apply(a, b); }
static ResultType constant_constant(A a, B b) { return ResultType(apply(a, b)); }
static ResultType constant_constant(A a, B b, UInt8& is_null) {
if constexpr (OpTraits::is_division && IsDecimalNumber<B>) {
return apply_scaled_div(a, b, is_null);
if constexpr (IsDecimalNumber<A>) {
return ResultType(apply_scaled_div(a.value, b.value, is_null));
} else {
return ResultType(apply_scaled_div(a, b.value, is_null));
}
} else if constexpr ((OpTraits::is_multiply || OpTraits::is_plus_minus) &&
(IsDecimalNumber<B> || IsDecimalNumber<A>)) {
NativeResultType res;
is_null = apply_op_safely(a, b, res);
return res;
return ResultType(res);
} else {
return apply(a, b, is_null);
return ResultType(apply(a, b, is_null));
}
}
@ -459,7 +473,7 @@ private:
NativeResultType res;
// TODO handle overflow gracefully
if (Op::template apply<NativeResultType>(a, b, res)) {
res = type_limit<ResultType>::max();
res = type_limit<ResultType>::max().value;
}
return res;
} else {
@ -475,7 +489,7 @@ private:
DecimalV2Value l(a);
DecimalV2Value r(b);
auto ans = Op::template apply(l, r, is_null);
NativeResultType result;
NativeResultType result {};
memcpy(&result, &ans, std::min(sizeof(result), sizeof(ans)));
return result;
} else {
@ -483,32 +497,6 @@ private:
}
}
static NativeResultType apply_scaled(NativeResultType a, NativeResultType b) {
if constexpr (OpTraits::is_plus_minus) {
NativeResultType res;
if constexpr (check_overflow) {
bool overflow = false;
if constexpr (OpTraits::can_overflow) {
overflow |= Op::template apply<NativeResultType>(a, b, res);
} else {
res = Op::template apply<NativeResultType>(a, b);
}
// TODO handle overflow gracefully
if (overflow) {
LOG(WARNING) << "Decimal math overflow";
res = type_limit<ResultType>::max();
}
} else {
res = apply(a, b);
}
return res;
}
}
static NativeResultType apply_scaled_div(NativeResultType a, NativeResultType b,
UInt8& is_null) {
if constexpr (OpTraits::is_division) {
@ -559,6 +547,15 @@ inline constexpr bool IsIntegral<DataTypeInt128> = true;
template <typename A, typename B>
constexpr bool UseLeftDecimal = false;
template <>
inline constexpr bool UseLeftDecimal<DataTypeDecimal<Decimal256>, DataTypeDecimal<Decimal32>> =
true;
template <>
inline constexpr bool UseLeftDecimal<DataTypeDecimal<Decimal256>, DataTypeDecimal<Decimal64>> =
true;
template <>
inline constexpr bool UseLeftDecimal<DataTypeDecimal<Decimal256>, DataTypeDecimal<Decimal128I>> =
true;
template <>
inline constexpr bool UseLeftDecimal<DataTypeDecimal<Decimal128I>, DataTypeDecimal<Decimal32>> =
true;
template <>
@ -725,8 +722,8 @@ class FunctionBinaryArithmetic : public IFunction {
return cast_type_to_either<DataTypeUInt8, DataTypeInt8, DataTypeInt16, DataTypeInt32,
DataTypeInt64, DataTypeInt128, DataTypeFloat32, DataTypeFloat64,
DataTypeDecimal<Decimal32>, DataTypeDecimal<Decimal64>,
DataTypeDecimal<Decimal128>, DataTypeDecimal<Decimal128I>>(
type, std::forward<F>(f));
DataTypeDecimal<Decimal128>, DataTypeDecimal<Decimal128I>,
DataTypeDecimal<Decimal256>>(type, std::forward<F>(f));
}
template <typename F>