[feature-wip](decimalv3) Support basic agg and arithmetic operations for decimal v3 (#14513)
This commit is contained in:
@ -227,25 +227,11 @@ struct DecimalBinaryOperation {
|
||||
using ArrayC = typename ColumnDecimal<ResultType>::Container;
|
||||
|
||||
static void vector_vector(const typename Traits::ArrayA& a, const typename Traits::ArrayB& b,
|
||||
ArrayC& c, ResultType scale_a [[maybe_unused]],
|
||||
ResultType scale_b [[maybe_unused]]) {
|
||||
ArrayC& c) {
|
||||
size_t size = a.size();
|
||||
if constexpr (OpTraits::is_plus_minus) {
|
||||
if (scale_a != 1) {
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
c[i] = apply_scaled<true>(a[i], b[i], scale_a);
|
||||
}
|
||||
return;
|
||||
} else if (scale_b != 1) {
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
c[i] = apply_scaled<false>(a[i], b[i], scale_b);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if constexpr (OpTraits::is_multiply && std::is_same_v<A, Decimal128> &&
|
||||
std::is_same_v<B, Decimal128>) {
|
||||
if constexpr (OpTraits::is_multiply && IsDecimalV2<A> && IsDecimalV2<B> &&
|
||||
IsDecimalV2<ResultType>) {
|
||||
Op::vector_vector(a, b, c);
|
||||
} else {
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
@ -256,8 +242,7 @@ struct DecimalBinaryOperation {
|
||||
|
||||
/// null_map for divide and mod
|
||||
static void vector_vector(const typename Traits::ArrayA& a, const typename Traits::ArrayB& b,
|
||||
ArrayC& c, ResultType scale_a [[maybe_unused]],
|
||||
ResultType scale_b [[maybe_unused]], NullMap& null_map) {
|
||||
ArrayC& c, NullMap& null_map) {
|
||||
size_t size = a.size();
|
||||
if constexpr (IsDecimalV2<B> || IsDecimalV2<A>) {
|
||||
/// default: use it if no return before
|
||||
@ -267,44 +252,18 @@ struct DecimalBinaryOperation {
|
||||
} else {
|
||||
if constexpr (OpTraits::is_division && IsDecimalNumber<B>) {
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
c[i] = apply_scaled_div(a[i], b[i], scale_a, null_map[i]);
|
||||
c[i] = apply_scaled_div(a[i], b[i], null_map[i]);
|
||||
}
|
||||
return;
|
||||
} else if constexpr (OpTraits::is_mod) {
|
||||
if (scale_a != 1) {
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
c[i] = apply_scaled_mod<true>(a[i], b[i], scale_a, null_map[i]);
|
||||
}
|
||||
return;
|
||||
} else if (scale_b != 1) {
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
c[i] = apply_scaled_mod<false>(a[i], b[i], scale_b, null_map[i]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void vector_constant(const typename Traits::ArrayA& a, B b, ArrayC& c,
|
||||
ResultType scale_a [[maybe_unused]],
|
||||
ResultType scale_b [[maybe_unused]]) {
|
||||
static void vector_constant(const typename Traits::ArrayA& a, B b, ArrayC& c) {
|
||||
size_t size = a.size();
|
||||
if constexpr (OpTraits::is_plus_minus) {
|
||||
if (scale_a != 1) {
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
c[i] = apply_scaled<true>(a[i], b, scale_a);
|
||||
}
|
||||
return;
|
||||
} else if (scale_b != 1) {
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
c[i] = apply_scaled<false>(a[i], b, scale_b);
|
||||
}
|
||||
return;
|
||||
}
|
||||
} else if constexpr (OpTraits::is_division && IsDecimalNumber<B>) {
|
||||
if constexpr (OpTraits::is_division && IsDecimalNumber<B>) {
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
c[i] = apply_scaled_div(a[i], b, scale_a);
|
||||
c[i] = apply_scaled_div(a[i], b);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -316,26 +275,13 @@ struct DecimalBinaryOperation {
|
||||
}
|
||||
|
||||
static void vector_constant(const typename Traits::ArrayA& a, B b, ArrayC& c,
|
||||
ResultType scale_a [[maybe_unused]],
|
||||
ResultType scale_b [[maybe_unused]], NullMap& null_map) {
|
||||
NullMap& null_map) {
|
||||
size_t size = a.size();
|
||||
if constexpr (OpTraits::is_division && IsDecimalNumber<B>) {
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
c[i] = apply_scaled_div(a[i], b, scale_a, null_map[i]);
|
||||
c[i] = apply_scaled_div(a[i], b, null_map[i]);
|
||||
}
|
||||
return;
|
||||
} else if constexpr (OpTraits::is_mod) {
|
||||
if (scale_a != 1) {
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
c[i] = apply_scaled_mod<true>(a[i], b, scale_a, null_map[i]);
|
||||
}
|
||||
return;
|
||||
} else if (scale_b != 1) {
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
c[i] = apply_scaled_mod<false>(a[i], b, scale_b, null_map[i]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
@ -343,25 +289,11 @@ struct DecimalBinaryOperation {
|
||||
}
|
||||
}
|
||||
|
||||
static void constant_vector(A a, const typename Traits::ArrayB& b, ArrayC& c,
|
||||
ResultType scale_a [[maybe_unused]],
|
||||
ResultType scale_b [[maybe_unused]]) {
|
||||
static void constant_vector(A a, const typename Traits::ArrayB& b, ArrayC& c) {
|
||||
size_t size = b.size();
|
||||
if constexpr (OpTraits::is_plus_minus) {
|
||||
if (scale_a != 1) {
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
c[i] = apply_scaled<true>(a, b[i], scale_a);
|
||||
}
|
||||
return;
|
||||
} else if (scale_b != 1) {
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
c[i] = apply_scaled<false>(a, b[i], scale_b);
|
||||
}
|
||||
return;
|
||||
}
|
||||
} else if constexpr (OpTraits::is_division && IsDecimalNumber<B>) {
|
||||
if constexpr (OpTraits::is_division && IsDecimalNumber<B>) {
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
c[i] = apply_scaled_div(a, b[i], scale_a);
|
||||
c[i] = apply_scaled_div(a, b[i]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -373,26 +305,13 @@ struct DecimalBinaryOperation {
|
||||
}
|
||||
|
||||
static void constant_vector(A a, const typename Traits::ArrayB& b, ArrayC& c,
|
||||
ResultType scale_a [[maybe_unused]],
|
||||
ResultType scale_b [[maybe_unused]], NullMap& null_map) {
|
||||
NullMap& null_map) {
|
||||
size_t size = b.size();
|
||||
if constexpr (OpTraits::is_division && IsDecimalNumber<B>) {
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
c[i] = apply_scaled_div(a, b[i], scale_a, null_map[i]);
|
||||
c[i] = apply_scaled_div(a, b[i], null_map[i]);
|
||||
}
|
||||
return;
|
||||
} else if constexpr (OpTraits::is_mod) {
|
||||
if (scale_a != 1) {
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
c[i] = apply_scaled_mod<true>(a, b[i], scale_a, null_map[i]);
|
||||
}
|
||||
return;
|
||||
} else if (scale_b != 1) {
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
c[i] = apply_scaled_mod<false>(a, b[i], scale_b, null_map[i]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
@ -400,108 +319,90 @@ struct DecimalBinaryOperation {
|
||||
}
|
||||
}
|
||||
|
||||
static ResultType constant_constant(A a, B b, ResultType scale_a [[maybe_unused]],
|
||||
ResultType scale_b [[maybe_unused]]) {
|
||||
if constexpr (OpTraits::is_plus_minus) {
|
||||
if (scale_a != 1) {
|
||||
return apply_scaled<true>(a, b, scale_a);
|
||||
} else if (scale_b != 1) {
|
||||
return apply_scaled<false>(a, b, scale_b);
|
||||
}
|
||||
} else if constexpr (OpTraits::is_division && IsDecimalNumber<B>) {
|
||||
return apply_scaled_div(a, b, scale_a);
|
||||
static ResultType constant_constant(A a, B b) {
|
||||
if constexpr (OpTraits::is_division && IsDecimalNumber<B>) {
|
||||
return apply_scaled_div(a, b);
|
||||
}
|
||||
return apply(a, b);
|
||||
}
|
||||
|
||||
static ResultType constant_constant(A a, B b, ResultType scale_a [[maybe_unused]],
|
||||
ResultType scale_b [[maybe_unused]], UInt8& is_null) {
|
||||
if constexpr (OpTraits::is_plus_minus) {
|
||||
if (scale_a != 1) {
|
||||
return apply_scaled<true>(a, b, scale_a, is_null);
|
||||
} else if (scale_b != 1) {
|
||||
return apply_scaled<false>(a, b, scale_b, is_null);
|
||||
}
|
||||
} else if constexpr (OpTraits::is_division && IsDecimalNumber<B>) {
|
||||
return apply_scaled_div(a, b, scale_a, is_null);
|
||||
} else if constexpr (OpTraits::is_mod) {
|
||||
if (scale_a != 1) {
|
||||
return apply_scaled_mod<true>(a, b, scale_a, is_null);
|
||||
} else if (scale_b != 1) {
|
||||
return apply_scaled_mod<false>(a, b, scale_b, is_null);
|
||||
}
|
||||
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);
|
||||
}
|
||||
return apply(a, b, is_null);
|
||||
}
|
||||
|
||||
static ColumnPtr adapt_decimal_constant_constant(A a, B b, UInt32 scale, ResultType scale_a,
|
||||
ResultType scale_b) {
|
||||
auto column_result = ColumnDecimal<ResultType>::create(1, scale);
|
||||
static ColumnPtr adapt_decimal_constant_constant(A a, B b, DataTypePtr res_data_type) {
|
||||
auto column_result = ColumnDecimal<ResultType>::create(
|
||||
1, assert_cast<const DataTypeDecimal<ResultType>&>(*res_data_type).get_scale());
|
||||
|
||||
if constexpr (is_to_null_type) {
|
||||
auto null_map = ColumnUInt8::create(1, 0);
|
||||
column_result->get_element(0) =
|
||||
constant_constant(a, b, scale_a, scale_b, null_map->get_element(0));
|
||||
column_result->get_element(0) = constant_constant(a, b, null_map->get_element(0));
|
||||
return ColumnNullable::create(std::move(column_result), std::move(null_map));
|
||||
} else {
|
||||
column_result->get_element(0) = constant_constant(a, b, scale_a, scale_b);
|
||||
column_result->get_element(0) = constant_constant(a, b);
|
||||
return column_result;
|
||||
}
|
||||
}
|
||||
|
||||
static ColumnPtr adapt_decimal_vector_constant(ColumnPtr column_left, B b, UInt32 column_scale,
|
||||
ResultType scale_a, ResultType scale_b) {
|
||||
static ColumnPtr adapt_decimal_vector_constant(ColumnPtr column_left, B b,
|
||||
DataTypePtr res_data_type) {
|
||||
auto column_left_ptr = check_and_get_column<typename Traits::ColumnVectorA>(column_left);
|
||||
auto column_result = ColumnDecimal<ResultType>::create(column_left->size(), column_scale);
|
||||
auto column_result = ColumnDecimal<ResultType>::create(
|
||||
column_left->size(),
|
||||
assert_cast<const DataTypeDecimal<ResultType>&>(*res_data_type).get_scale());
|
||||
DCHECK(column_left_ptr != nullptr);
|
||||
|
||||
if constexpr (is_to_null_type) {
|
||||
auto null_map = ColumnUInt8::create(column_left->size(), 0);
|
||||
vector_constant(column_left_ptr->get_data(), b, column_result->get_data(), scale_a,
|
||||
scale_b, null_map->get_data());
|
||||
vector_constant(column_left_ptr->get_data(), b, column_result->get_data(),
|
||||
null_map->get_data());
|
||||
return ColumnNullable::create(std::move(column_result), std::move(null_map));
|
||||
} else {
|
||||
vector_constant(column_left_ptr->get_data(), b, column_result->get_data(), scale_a,
|
||||
scale_b);
|
||||
vector_constant(column_left_ptr->get_data(), b, column_result->get_data());
|
||||
return column_result;
|
||||
}
|
||||
}
|
||||
|
||||
static ColumnPtr adapt_decimal_constant_vector(A a, ColumnPtr column_right, UInt32 column_scale,
|
||||
ResultType scale_a, ResultType scale_b) {
|
||||
static ColumnPtr adapt_decimal_constant_vector(A a, ColumnPtr column_right,
|
||||
DataTypePtr res_data_type) {
|
||||
auto column_right_ptr = check_and_get_column<typename Traits::ColumnVectorB>(column_right);
|
||||
auto column_result = ColumnDecimal<ResultType>::create(column_right->size(), column_scale);
|
||||
auto column_result = ColumnDecimal<ResultType>::create(
|
||||
column_right->size(),
|
||||
assert_cast<const DataTypeDecimal<ResultType>&>(*res_data_type).get_scale());
|
||||
DCHECK(column_right_ptr != nullptr);
|
||||
|
||||
if constexpr (is_to_null_type) {
|
||||
auto null_map = ColumnUInt8::create(column_right->size(), 0);
|
||||
constant_vector(a, column_right_ptr->get_data(), column_result->get_data(), scale_a,
|
||||
scale_b, null_map->get_data());
|
||||
constant_vector(a, column_right_ptr->get_data(), column_result->get_data(),
|
||||
null_map->get_data());
|
||||
return ColumnNullable::create(std::move(column_result), std::move(null_map));
|
||||
} else {
|
||||
constant_vector(a, column_right_ptr->get_data(), column_result->get_data(), scale_a,
|
||||
scale_b);
|
||||
constant_vector(a, column_right_ptr->get_data(), column_result->get_data());
|
||||
return column_result;
|
||||
}
|
||||
}
|
||||
|
||||
static ColumnPtr adapt_decimal_vector_vector(ColumnPtr column_left, ColumnPtr column_right,
|
||||
UInt32 column_scale, ResultType scale_a,
|
||||
ResultType scale_b) {
|
||||
DataTypePtr res_data_type) {
|
||||
auto column_left_ptr = check_and_get_column<typename Traits::ColumnVectorA>(column_left);
|
||||
auto column_right_ptr = check_and_get_column<typename Traits::ColumnVectorB>(column_right);
|
||||
|
||||
auto column_result = ColumnDecimal<ResultType>::create(column_left->size(), column_scale);
|
||||
auto column_result = ColumnDecimal<ResultType>::create(
|
||||
column_left->size(),
|
||||
assert_cast<const DataTypeDecimal<ResultType>&>(*res_data_type).get_scale());
|
||||
DCHECK(column_left_ptr != nullptr && column_right_ptr != nullptr);
|
||||
|
||||
if constexpr (is_to_null_type) {
|
||||
auto null_map = ColumnUInt8::create(column_result->size(), 0);
|
||||
vector_vector(column_left_ptr->get_data(), column_right_ptr->get_data(),
|
||||
column_result->get_data(), scale_a, scale_b, null_map->get_data());
|
||||
column_result->get_data(), null_map->get_data());
|
||||
return ColumnNullable::create(std::move(column_result), std::move(null_map));
|
||||
} else {
|
||||
vector_vector(column_left_ptr->get_data(), column_right_ptr->get_data(),
|
||||
column_result->get_data(), scale_a, scale_b);
|
||||
column_result->get_data());
|
||||
return column_result;
|
||||
}
|
||||
}
|
||||
@ -547,19 +448,12 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
template <bool scale_left>
|
||||
static NativeResultType apply_scaled(NativeResultType a, NativeResultType b,
|
||||
NativeResultType scale) {
|
||||
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 (scale_left) {
|
||||
overflow |= common::mul_overflow(a, scale, a);
|
||||
} else {
|
||||
overflow |= common::mul_overflow(b, scale, b);
|
||||
}
|
||||
|
||||
if constexpr (OpTraits::can_overflow) {
|
||||
overflow |= Op::template apply<NativeResultType>(a, b, res);
|
||||
@ -573,11 +467,6 @@ private:
|
||||
res = max_decimal_value<ResultType>();
|
||||
}
|
||||
} else {
|
||||
if constexpr (scale_left) {
|
||||
a *= scale;
|
||||
} else {
|
||||
b *= scale;
|
||||
}
|
||||
res = apply(a, b);
|
||||
}
|
||||
|
||||
@ -586,52 +475,14 @@ private:
|
||||
}
|
||||
|
||||
static NativeResultType apply_scaled_div(NativeResultType a, NativeResultType b,
|
||||
NativeResultType scale, UInt8& is_null) {
|
||||
UInt8& is_null) {
|
||||
if constexpr (OpTraits::is_division) {
|
||||
if constexpr (check_overflow) {
|
||||
bool overflow = false;
|
||||
if constexpr (!IsDecimalNumber<A>) {
|
||||
overflow |= common::mul_overflow(scale, scale, scale);
|
||||
}
|
||||
overflow |= common::mul_overflow(a, scale, a);
|
||||
// TODO handle overflow gracefully
|
||||
if (overflow) {
|
||||
LOG(WARNING) << "Decimal math overflow";
|
||||
return max_decimal_value<ResultType>();
|
||||
}
|
||||
} else {
|
||||
if constexpr (!IsDecimalNumber<A>) {
|
||||
scale *= scale;
|
||||
}
|
||||
a *= scale;
|
||||
}
|
||||
|
||||
return apply(a, b, is_null);
|
||||
}
|
||||
}
|
||||
|
||||
template <bool scale_left>
|
||||
static NativeResultType apply_scaled_mod(NativeResultType a, NativeResultType b,
|
||||
NativeResultType scale, UInt8& is_null) {
|
||||
if constexpr (check_overflow) {
|
||||
bool overflow = false;
|
||||
if constexpr (scale_left)
|
||||
overflow |= common::mul_overflow(a, scale, a);
|
||||
else
|
||||
overflow |= common::mul_overflow(b, scale, b);
|
||||
|
||||
// TODO handle overflow gracefully
|
||||
if (overflow) {
|
||||
LOG(WARNING) << "Decimal math overflow";
|
||||
return max_decimal_value<ResultType>();
|
||||
}
|
||||
} else {
|
||||
if constexpr (scale_left)
|
||||
a *= scale;
|
||||
else
|
||||
b *= scale;
|
||||
}
|
||||
|
||||
UInt8& is_null) {
|
||||
return apply(a, b, is_null);
|
||||
}
|
||||
};
|
||||
@ -718,15 +569,13 @@ struct BinaryOperationTraits {
|
||||
DataTypeFromFieldType<typename Op::ResultType>>>;
|
||||
};
|
||||
|
||||
template <typename LeftDataType, typename RightDataType,
|
||||
template <typename LeftDataType, typename RightDataType, typename ExpectedResultDataType,
|
||||
template <typename, typename> class Operation, bool is_to_null_type>
|
||||
struct ConstOrVectorAdapter {
|
||||
static constexpr bool result_is_decimal =
|
||||
IsDataTypeDecimal<LeftDataType> || IsDataTypeDecimal<RightDataType>;
|
||||
using OpTraits = OperationTraits<Operation>;
|
||||
|
||||
using ResultDataType =
|
||||
typename BinaryOperationTraits<Operation, LeftDataType, RightDataType>::ResultDataType;
|
||||
using ResultDataType = ExpectedResultDataType;
|
||||
using ResultType = typename ResultDataType::FieldType;
|
||||
using A = typename LeftDataType::FieldType;
|
||||
using B = typename RightDataType::FieldType;
|
||||
@ -737,42 +586,27 @@ struct ConstOrVectorAdapter {
|
||||
BinaryOperationImpl<A, B, Operation<A, B>, is_to_null_type, ResultType>>;
|
||||
|
||||
static ColumnPtr execute(ColumnPtr column_left, ColumnPtr column_right,
|
||||
const LeftDataType& type_left, const RightDataType& type_right) {
|
||||
const LeftDataType& type_left, const RightDataType& type_right,
|
||||
DataTypePtr res_data_type) {
|
||||
bool is_const_left = is_column_const(*column_left);
|
||||
bool is_const_right = is_column_const(*column_right);
|
||||
|
||||
if (is_const_left && is_const_right) {
|
||||
return constant_constant(column_left, column_right, type_left, type_right);
|
||||
return constant_constant(column_left, column_right, type_left, type_right,
|
||||
res_data_type);
|
||||
} else if (is_const_left) {
|
||||
return constant_vector(column_left, column_right, type_left, type_right);
|
||||
return constant_vector(column_left, column_right, type_left, type_right, res_data_type);
|
||||
} else if (is_const_right) {
|
||||
return vector_constant(column_left, column_right, type_left, type_right);
|
||||
return vector_constant(column_left, column_right, type_left, type_right, res_data_type);
|
||||
} else {
|
||||
return vector_vector(column_left, column_right, type_left, type_right);
|
||||
return vector_vector(column_left, column_right, type_left, type_right, res_data_type);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static auto get_decimal_infos(const LeftDataType& type_left, const RightDataType& type_right) {
|
||||
ResultDataType type = decimal_result_type(type_left, type_right, OpTraits::is_multiply,
|
||||
OpTraits::is_division);
|
||||
typename ResultDataType::FieldType scale_a;
|
||||
typename ResultDataType::FieldType scale_b;
|
||||
|
||||
if constexpr (OpTraits::is_division && IsDataTypeDecimal<RightDataType> &&
|
||||
!IsDecimalV2<B> && !IsDecimalV2<A>) {
|
||||
scale_a = type_right.get_scale_multiplier();
|
||||
scale_b = 1;
|
||||
return std::make_tuple(type, scale_a, scale_b);
|
||||
}
|
||||
scale_a = type.scale_factor_for(type_left, OpTraits::is_multiply);
|
||||
scale_b = type.scale_factor_for(type_right, OpTraits::is_multiply || OpTraits::is_division);
|
||||
return std::make_tuple(type, scale_a, scale_b);
|
||||
}
|
||||
|
||||
static ColumnPtr constant_constant(ColumnPtr column_left, ColumnPtr column_right,
|
||||
const LeftDataType& type_left,
|
||||
const RightDataType& type_right) {
|
||||
const RightDataType& type_right, DataTypePtr res_data_type) {
|
||||
auto column_left_ptr = check_and_get_column<ColumnConst>(column_left);
|
||||
auto column_right_ptr = check_and_get_column<ColumnConst>(column_right);
|
||||
DCHECK(column_left_ptr != nullptr && column_right_ptr != nullptr);
|
||||
@ -780,11 +614,9 @@ private:
|
||||
ColumnPtr column_result = nullptr;
|
||||
|
||||
if constexpr (result_is_decimal) {
|
||||
auto [type, scale_a, scale_b] = get_decimal_infos(type_left, type_right);
|
||||
|
||||
column_result = OperationImpl::adapt_decimal_constant_constant(
|
||||
column_left_ptr->template get_value<A>(),
|
||||
column_right_ptr->template get_value<B>(), type.get_scale(), scale_a, scale_b);
|
||||
column_right_ptr->template get_value<B>(), res_data_type);
|
||||
|
||||
} else {
|
||||
column_result = OperationImpl::adapt_normal_constant_constant(
|
||||
@ -796,17 +628,15 @@ private:
|
||||
}
|
||||
|
||||
static ColumnPtr vector_constant(ColumnPtr column_left, ColumnPtr column_right,
|
||||
const LeftDataType& type_left,
|
||||
const RightDataType& type_right) {
|
||||
const LeftDataType& type_left, const RightDataType& type_right,
|
||||
DataTypePtr res_data_type) {
|
||||
auto column_right_ptr = check_and_get_column<ColumnConst>(column_right);
|
||||
DCHECK(column_right_ptr != nullptr);
|
||||
|
||||
if constexpr (result_is_decimal) {
|
||||
auto [type, scale_a, scale_b] = get_decimal_infos(type_left, type_right);
|
||||
|
||||
return OperationImpl::adapt_decimal_vector_constant(
|
||||
column_left->get_ptr(), column_right_ptr->template get_value<B>(),
|
||||
type.get_scale(), scale_a, scale_b);
|
||||
res_data_type);
|
||||
} else {
|
||||
return OperationImpl::adapt_normal_vector_constant(
|
||||
column_left->get_ptr(), column_right_ptr->template get_value<B>());
|
||||
@ -814,17 +644,15 @@ private:
|
||||
}
|
||||
|
||||
static ColumnPtr constant_vector(ColumnPtr column_left, ColumnPtr column_right,
|
||||
const LeftDataType& type_left,
|
||||
const RightDataType& type_right) {
|
||||
const LeftDataType& type_left, const RightDataType& type_right,
|
||||
DataTypePtr res_data_type) {
|
||||
auto column_left_ptr = check_and_get_column<ColumnConst>(column_left);
|
||||
DCHECK(column_left_ptr != nullptr);
|
||||
|
||||
if constexpr (result_is_decimal) {
|
||||
auto [type, scale_a, scale_b] = get_decimal_infos(type_left, type_right);
|
||||
|
||||
return OperationImpl::adapt_decimal_constant_vector(
|
||||
column_left_ptr->template get_value<A>(), column_right->get_ptr(),
|
||||
type.get_scale(), scale_a, scale_b);
|
||||
res_data_type);
|
||||
} else {
|
||||
return OperationImpl::adapt_normal_constant_vector(
|
||||
column_left_ptr->template get_value<A>(), column_right->get_ptr());
|
||||
@ -832,13 +660,11 @@ private:
|
||||
}
|
||||
|
||||
static ColumnPtr vector_vector(ColumnPtr column_left, ColumnPtr column_right,
|
||||
const LeftDataType& type_left, const RightDataType& type_right) {
|
||||
const LeftDataType& type_left, const RightDataType& type_right,
|
||||
DataTypePtr res_data_type) {
|
||||
if constexpr (result_is_decimal) {
|
||||
auto [type, scale_a, scale_b] = get_decimal_infos(type_left, type_right);
|
||||
|
||||
return OperationImpl::adapt_decimal_vector_vector(column_left->get_ptr(),
|
||||
column_right->get_ptr(),
|
||||
type.get_scale(), scale_a, scale_b);
|
||||
return OperationImpl::adapt_decimal_vector_vector(
|
||||
column_left->get_ptr(), column_right->get_ptr(), res_data_type);
|
||||
} else {
|
||||
return OperationImpl::adapt_normal_vector_vector(column_left->get_ptr(),
|
||||
column_right->get_ptr());
|
||||
@ -866,6 +692,16 @@ class FunctionBinaryArithmetic : public IFunction {
|
||||
});
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
static bool cast_both_types(const IDataType* left, const IDataType* right, const IDataType* res,
|
||||
F&& f) {
|
||||
return cast_type(left, [&](const auto& left_) {
|
||||
return cast_type(right, [&](const auto& right_) {
|
||||
return cast_type(res, [&](const auto& res_) { return f(left_, right_, res_); });
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public:
|
||||
static constexpr auto name = Name::name;
|
||||
|
||||
@ -932,6 +768,7 @@ public:
|
||||
size_t result, size_t input_rows_count) override {
|
||||
auto* left_generic = block.get_by_position(arguments[0]).type.get();
|
||||
auto* right_generic = block.get_by_position(arguments[1]).type.get();
|
||||
auto* result_generic = block.get_by_position(result).type.get();
|
||||
if (left_generic->is_nullable()) {
|
||||
left_generic =
|
||||
static_cast<const DataTypeNullable*>(left_generic)->get_nested_type().get();
|
||||
@ -940,19 +777,35 @@ public:
|
||||
right_generic =
|
||||
static_cast<const DataTypeNullable*>(right_generic)->get_nested_type().get();
|
||||
}
|
||||
if (result_generic->is_nullable()) {
|
||||
result_generic =
|
||||
static_cast<const DataTypeNullable*>(result_generic)->get_nested_type().get();
|
||||
}
|
||||
|
||||
bool valid = cast_both_types(
|
||||
left_generic, right_generic, [&](const auto& left, const auto& right) {
|
||||
left_generic, right_generic, result_generic,
|
||||
[&](const auto& left, const auto& right, const auto& res) {
|
||||
using LeftDataType = std::decay_t<decltype(left)>;
|
||||
using RightDataType = std::decay_t<decltype(right)>;
|
||||
using ExpectedResultDataType = std::decay_t<decltype(res)>;
|
||||
using ResultDataType =
|
||||
typename BinaryOperationTraits<Operation, LeftDataType,
|
||||
RightDataType>::ResultDataType;
|
||||
if constexpr (!std::is_same_v<ResultDataType, InvalidType>) {
|
||||
auto column_result = ConstOrVectorAdapter<LeftDataType, RightDataType,
|
||||
Operation, is_to_null_type>::
|
||||
if constexpr (
|
||||
!std::is_same_v<ResultDataType, InvalidType> &&
|
||||
(IsDataTypeDecimal<ExpectedResultDataType> ==
|
||||
IsDataTypeDecimal<
|
||||
ResultDataType>)&&(IsDataTypeDecimal<ExpectedResultDataType> ==
|
||||
(IsDataTypeDecimal<LeftDataType> ||
|
||||
IsDataTypeDecimal<RightDataType>))) {
|
||||
auto column_result = ConstOrVectorAdapter<
|
||||
LeftDataType, RightDataType,
|
||||
std::conditional_t<IsDataTypeDecimal<ExpectedResultDataType>,
|
||||
ExpectedResultDataType, ResultDataType>,
|
||||
Operation, is_to_null_type>::
|
||||
execute(block.get_by_position(arguments[0]).column,
|
||||
block.get_by_position(arguments[1]).column, left, right);
|
||||
block.get_by_position(arguments[1]).column, left, right,
|
||||
remove_nullable(block.get_by_position(result).type));
|
||||
block.replace_by_position(result, std::move(column_result));
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user