fix decimal vs int arithm, add some tests

This commit is contained in:
chertus 2018-08-02 17:28:55 +03:00
parent 267f28f98d
commit e1881d4cfb
7 changed files with 198 additions and 57 deletions

View File

@ -189,7 +189,7 @@ public:
/// @returns multiplier for U to become T with correct scale /// @returns multiplier for U to become T with correct scale
template <typename U> template <typename U>
T scaleFactorFor(const DataTypeDecimal<U> & x) const T scaleFactorFor(const DataTypeDecimal<U> & x, bool ) const
{ {
if (getScale() < x.getScale()) if (getScale() < x.getScale())
throw Exception("Decimal result's scale is less then argiment's one", ErrorCodes::ARGUMENT_OUT_OF_BOUND); throw Exception("Decimal result's scale is less then argiment's one", ErrorCodes::ARGUMENT_OUT_OF_BOUND);
@ -198,7 +198,12 @@ public:
} }
template <typename U> template <typename U>
T scaleFactorFor(const DataTypeNumber<U> & ) const { return 1; } T scaleFactorFor(const DataTypeNumber<U> & , bool is_multiply_or_divisor) const
{
if (is_multiply_or_divisor)
return 1;
return getScaleMultiplier();
}
T parseFromString(const String & str) const; T parseFromString(const String & str) const;
@ -214,7 +219,7 @@ template <typename T, typename U>
typename std::enable_if_t<(sizeof(T) >= sizeof(U)), const DataTypeDecimal<T>> typename std::enable_if_t<(sizeof(T) >= sizeof(U)), const DataTypeDecimal<T>>
decimalResultType(const DataTypeDecimal<T> & tx, const DataTypeDecimal<U> & ty, bool is_multiply, bool is_divide) decimalResultType(const DataTypeDecimal<T> & tx, const DataTypeDecimal<U> & ty, bool is_multiply, bool is_divide)
{ {
T scale = (tx.getScale() > ty.getScale() ? tx.getScale() : ty.getScale()); UInt32 scale = (tx.getScale() > ty.getScale() ? tx.getScale() : ty.getScale());
if (is_multiply) if (is_multiply)
scale = tx.getScale() + ty.getScale(); scale = tx.getScale() + ty.getScale();
else if (is_divide) else if (is_divide)
@ -226,7 +231,7 @@ template <typename T, typename U>
typename std::enable_if_t<(sizeof(T) < sizeof(U)), const DataTypeDecimal<U>> typename std::enable_if_t<(sizeof(T) < sizeof(U)), const DataTypeDecimal<U>>
decimalResultType(const DataTypeDecimal<T> & tx, const DataTypeDecimal<U> & ty, bool is_multiply, bool is_divide) decimalResultType(const DataTypeDecimal<T> & tx, const DataTypeDecimal<U> & ty, bool is_multiply, bool is_divide)
{ {
U scale = (tx.getScale() > ty.getScale() ? tx.getScale() : ty.getScale()); UInt32 scale = (tx.getScale() > ty.getScale() ? tx.getScale() : ty.getScale());
if (is_multiply) if (is_multiply)
scale = tx.getScale() * ty.getScale(); scale = tx.getScale() * ty.getScale();
else if (is_divide) else if (is_divide)

View File

@ -233,7 +233,6 @@ template <typename A, typename B>
struct DivideIntegralImpl struct DivideIntegralImpl
{ {
using ResultType = typename NumberTraits::ResultOfIntegerDivision<A, B>::Type; using ResultType = typename NumberTraits::ResultOfIntegerDivision<A, B>::Type;
static const constexpr bool allow_decimal = false;
template <typename Result = ResultType> template <typename Result = ResultType>
static inline Result apply(A a, B b) static inline Result apply(A a, B b)
@ -251,7 +250,6 @@ template <typename A, typename B>
struct DivideIntegralOrZeroImpl struct DivideIntegralOrZeroImpl
{ {
using ResultType = typename NumberTraits::ResultOfIntegerDivision<A, B>::Type; using ResultType = typename NumberTraits::ResultOfIntegerDivision<A, B>::Type;
static const constexpr bool allow_decimal = false;
template <typename Result = ResultType> template <typename Result = ResultType>
static inline Result apply(A a, B b) static inline Result apply(A a, B b)
@ -268,7 +266,6 @@ template <typename A, typename B>
struct ModuloImpl struct ModuloImpl
{ {
using ResultType = typename NumberTraits::ResultOfModulo<A, B>::Type; using ResultType = typename NumberTraits::ResultOfModulo<A, B>::Type;
static const constexpr bool allow_decimal = false;
template <typename Result = ResultType> template <typename Result = ResultType>
static inline Result apply(A a, B b) static inline Result apply(A a, B b)
@ -286,7 +283,6 @@ template <typename A, typename B>
struct BitAndImpl struct BitAndImpl
{ {
using ResultType = typename NumberTraits::ResultOfBit<A, B>::Type; using ResultType = typename NumberTraits::ResultOfBit<A, B>::Type;
static const constexpr bool allow_decimal = false;
template <typename Result = ResultType> template <typename Result = ResultType>
static inline Result apply(A a, B b) static inline Result apply(A a, B b)
@ -310,7 +306,6 @@ template <typename A, typename B>
struct BitOrImpl struct BitOrImpl
{ {
using ResultType = typename NumberTraits::ResultOfBit<A, B>::Type; using ResultType = typename NumberTraits::ResultOfBit<A, B>::Type;
static const constexpr bool allow_decimal = false;
template <typename Result = ResultType> template <typename Result = ResultType>
static inline Result apply(A a, B b) static inline Result apply(A a, B b)
@ -334,7 +329,6 @@ template <typename A, typename B>
struct BitXorImpl struct BitXorImpl
{ {
using ResultType = typename NumberTraits::ResultOfBit<A, B>::Type; using ResultType = typename NumberTraits::ResultOfBit<A, B>::Type;
static const constexpr bool allow_decimal = false;
template <typename Result = ResultType> template <typename Result = ResultType>
static inline Result apply(A a, B b) static inline Result apply(A a, B b)
@ -358,7 +352,6 @@ template <typename A, typename B>
struct BitShiftLeftImpl struct BitShiftLeftImpl
{ {
using ResultType = typename NumberTraits::ResultOfBit<A, B>::Type; using ResultType = typename NumberTraits::ResultOfBit<A, B>::Type;
static const constexpr bool allow_decimal = false;
template <typename Result = ResultType> template <typename Result = ResultType>
static inline Result apply(A a, B b) static inline Result apply(A a, B b)
@ -382,7 +375,6 @@ template <typename A, typename B>
struct BitShiftRightImpl struct BitShiftRightImpl
{ {
using ResultType = typename NumberTraits::ResultOfBit<A, B>::Type; using ResultType = typename NumberTraits::ResultOfBit<A, B>::Type;
static const constexpr bool allow_decimal = false;
template <typename Result = ResultType> template <typename Result = ResultType>
static inline Result apply(A a, B b) static inline Result apply(A a, B b)
@ -406,7 +398,6 @@ template <typename A, typename B>
struct BitRotateLeftImpl struct BitRotateLeftImpl
{ {
using ResultType = typename NumberTraits::ResultOfBit<A, B>::Type; using ResultType = typename NumberTraits::ResultOfBit<A, B>::Type;
static const constexpr bool allow_decimal = false;
template <typename Result = ResultType> template <typename Result = ResultType>
static inline Result apply(A a, B b) static inline Result apply(A a, B b)
@ -433,7 +424,6 @@ template <typename A, typename B>
struct BitRotateRightImpl struct BitRotateRightImpl
{ {
using ResultType = typename NumberTraits::ResultOfBit<A, B>::Type; using ResultType = typename NumberTraits::ResultOfBit<A, B>::Type;
static const constexpr bool allow_decimal = false;
template <typename Result = ResultType> template <typename Result = ResultType>
static inline Result apply(A a, B b) static inline Result apply(A a, B b)
@ -459,7 +449,6 @@ template <typename A, typename B>
struct BitTestImpl struct BitTestImpl
{ {
using ResultType = UInt8; using ResultType = UInt8;
static const constexpr bool allow_decimal = false;
template <typename Result = ResultType> template <typename Result = ResultType>
static inline Result apply(A a, B b) static inline Result apply(A a, B b)
@ -476,7 +465,6 @@ template <typename A, typename B>
struct LeastBaseImpl struct LeastBaseImpl
{ {
using ResultType = NumberTraits::ResultOfLeast<A, B>; using ResultType = NumberTraits::ResultOfLeast<A, B>;
static const constexpr bool allow_decimal = false;
template <typename Result = ResultType> template <typename Result = ResultType>
static inline Result apply(A a, B b) static inline Result apply(A a, B b)
@ -502,7 +490,6 @@ template <typename A, typename B>
struct LeastSpecialImpl struct LeastSpecialImpl
{ {
using ResultType = std::make_signed_t<A>; using ResultType = std::make_signed_t<A>;
static const constexpr bool allow_decimal = false;
template <typename Result = ResultType> template <typename Result = ResultType>
static inline Result apply(A a, B b) static inline Result apply(A a, B b)
@ -524,7 +511,6 @@ template <typename A, typename B>
struct GreatestBaseImpl struct GreatestBaseImpl
{ {
using ResultType = NumberTraits::ResultOfGreatest<A, B>; using ResultType = NumberTraits::ResultOfGreatest<A, B>;
static const constexpr bool allow_decimal = false;
template <typename Result = ResultType> template <typename Result = ResultType>
static inline Result apply(A a, B b) static inline Result apply(A a, B b)
@ -550,7 +536,6 @@ template <typename A, typename B>
struct GreatestSpecialImpl struct GreatestSpecialImpl
{ {
using ResultType = std::make_unsigned_t<A>; using ResultType = std::make_unsigned_t<A>;
static const constexpr bool allow_decimal = false;
template <typename Result = ResultType> template <typename Result = ResultType>
static inline Result apply(A a, B b) static inline Result apply(A a, B b)
@ -634,7 +619,6 @@ template <typename A, typename B>
struct GCDImpl struct GCDImpl
{ {
using ResultType = typename NumberTraits::ResultOfAdditionMultiplication<A, B>::Type; using ResultType = typename NumberTraits::ResultOfAdditionMultiplication<A, B>::Type;
static const constexpr bool allow_decimal = false;
template <typename Result = ResultType> template <typename Result = ResultType>
static inline Result apply(A a, B b) static inline Result apply(A a, B b)
@ -655,7 +639,6 @@ template <typename A, typename B>
struct LCMImpl struct LCMImpl
{ {
using ResultType = typename NumberTraits::ResultOfAdditionMultiplication<A, B>::Type; using ResultType = typename NumberTraits::ResultOfAdditionMultiplication<A, B>::Type;
static const constexpr bool allow_decimal = false;
template <typename Result = ResultType> template <typename Result = ResultType>
static inline Result apply(A a, B b) static inline Result apply(A a, B b)
@ -715,15 +698,18 @@ struct IntExp10Impl
/// * no agrs scale. ScaleR = Scale1 + Scale2; /// * no agrs scale. ScaleR = Scale1 + Scale2;
/// / first arg scale. ScaleR = Scale1 (scale_a = DecimalType<B>::getScale()). /// / first arg scale. ScaleR = Scale1 (scale_a = DecimalType<B>::getScale()).
template <typename A, typename B, typename Op, typename ResultType_ = typename Op::ResultType> template <typename A, typename B, typename Op, typename ResultType_ = typename Op::ResultType>
struct ScaledBinaryOperation struct DecimalBinaryOperation
{ {
using ResultType = ResultType_; using ResultType = ResultType_;
static constexpr bool is_plus_minus = std::is_same_v<Op, PlusImpl<ResultType, ResultType>> ||
std::is_same_v<Op, MinusImpl<ResultType, ResultType>>;
static constexpr bool is_division = std::is_same_v<Op, DivideFloatingImpl<ResultType, ResultType>>;
static void NO_INLINE vector_vector(const PaddedPODArray<A> & a, const PaddedPODArray<B> & b, PaddedPODArray<ResultType> & c, static void NO_INLINE vector_vector(const PaddedPODArray<A> & a, const PaddedPODArray<B> & b, PaddedPODArray<ResultType> & c,
ResultType scale_a [[maybe_unused]], ResultType scale_b [[maybe_unused]]) ResultType scale_a [[maybe_unused]], ResultType scale_b [[maybe_unused]])
{ {
size_t size = a.size(); size_t size = a.size();
if constexpr (std::is_same_v<Op, PlusImpl<A, B>> || std::is_same_v<Op, MinusImpl<A, B>>) if constexpr (is_plus_minus)
{ {
if (scale_a != 1) if (scale_a != 1)
{ {
@ -738,7 +724,7 @@ struct ScaledBinaryOperation
return; return;
} }
} }
else if constexpr (std::is_same_v<Op, DivideFloatingImpl<A, B>>) else if constexpr (is_division)
{ {
for (size_t i = 0; i < size; ++i) for (size_t i = 0; i < size; ++i)
c[i] = Op::template apply<ResultType>(a[i] * scale_a, b[i]); c[i] = Op::template apply<ResultType>(a[i] * scale_a, b[i]);
@ -754,7 +740,7 @@ struct ScaledBinaryOperation
ResultType scale_a [[maybe_unused]], ResultType scale_b [[maybe_unused]]) ResultType scale_a [[maybe_unused]], ResultType scale_b [[maybe_unused]])
{ {
size_t size = a.size(); size_t size = a.size();
if constexpr (std::is_same_v<Op, PlusImpl<A, B>> || std::is_same_v<Op, MinusImpl<A, B>>) if constexpr (is_plus_minus)
{ {
if (scale_a != 1) if (scale_a != 1)
{ {
@ -769,7 +755,7 @@ struct ScaledBinaryOperation
return; return;
} }
} }
else if constexpr (std::is_same_v<Op, DivideFloatingImpl<A, B>>) else if constexpr (is_division)
{ {
for (size_t i = 0; i < size; ++i) for (size_t i = 0; i < size; ++i)
c[i] = Op::template apply<ResultType>(a[i] * scale_a, b); c[i] = Op::template apply<ResultType>(a[i] * scale_a, b);
@ -785,7 +771,7 @@ struct ScaledBinaryOperation
ResultType scale_a [[maybe_unused]], ResultType scale_b [[maybe_unused]]) ResultType scale_a [[maybe_unused]], ResultType scale_b [[maybe_unused]])
{ {
size_t size = b.size(); size_t size = b.size();
if constexpr (std::is_same_v<Op, PlusImpl<A, B>> || std::is_same_v<Op, MinusImpl<A, B>>) if constexpr (is_plus_minus)
{ {
if (scale_a != 1) if (scale_a != 1)
{ {
@ -800,7 +786,7 @@ struct ScaledBinaryOperation
return; return;
} }
} }
else if constexpr (std::is_same_v<Op, DivideFloatingImpl<A, B>>) else if constexpr (is_division)
{ {
for (size_t i = 0; i < size; ++i) for (size_t i = 0; i < size; ++i)
c[i] = Op::template apply<ResultType>(a * scale_a, b[i]); c[i] = Op::template apply<ResultType>(a * scale_a, b[i]);
@ -814,9 +800,9 @@ struct ScaledBinaryOperation
static ResultType constant_constant(A a, B b, ResultType scale_a [[maybe_unused]], ResultType scale_b [[maybe_unused]]) static ResultType constant_constant(A a, B b, ResultType scale_a [[maybe_unused]], ResultType scale_b [[maybe_unused]])
{ {
if constexpr (std::is_same_v<Op, PlusImpl<A, B>> || std::is_same_v<Op, MinusImpl<A, B>>) if constexpr (is_plus_minus)
return Op::template apply<ResultType>(a * scale_a, b * scale_b); return Op::template apply<ResultType>(a * scale_a, b * scale_b);
else if constexpr (std::is_same_v<Op, DivideFloatingImpl<A, B>>) else if constexpr (is_division)
return Op::template apply<ResultType>(a * scale_a, b); return Op::template apply<ResultType>(a * scale_a, b);
return Op::template apply<ResultType>(a, b); return Op::template apply<ResultType>(a, b);
} }
@ -862,13 +848,21 @@ struct BinaryOperationTraits
{ {
using T0 = typename LeftDataType::FieldType; using T0 = typename LeftDataType::FieldType;
using T1 = typename RightDataType::FieldType; using T1 = typename RightDataType::FieldType;
private: /// it's not correct for Decimal
using Op = Operation<T0, T1>; using Op = Operation<T0, T1>;
public:
static constexpr bool allow_decimal =
std::is_same_v<Operation<T0, T0>, PlusImpl<T0, T0>> ||
std::is_same_v<Operation<T0, T0>, MinusImpl<T0, T0>> ||
std::is_same_v<Operation<T0, T0>, MultiplyImpl<T0, T0>> ||
std::is_same_v<Operation<T0, T0>, DivideFloatingImpl<T0, T0>>;
/// Appropriate result type for binary operator on numeric types. "Date" can also mean /// Appropriate result type for binary operator on numeric types. "Date" can also mean
/// DateTime, but if both operands are Dates, their type must be the same (e.g. Date - DateTime is invalid). /// DateTime, but if both operands are Dates, their type must be the same (e.g. Date - DateTime is invalid).
using ResultDataType = Switch< using ResultDataType = Switch<
/// Decimal cases /// Decimal cases
Case<!Operation<T0, T1>::allow_decimal && (IsDecimal<LeftDataType> || IsDecimal<RightDataType>), InvalidType>, Case<!allow_decimal && (IsDecimal<LeftDataType> || IsDecimal<RightDataType>), InvalidType>,
Case<IsDecimal<LeftDataType> && IsDecimal<RightDataType> && UseLeftDecimal<LeftDataType, RightDataType>, LeftDataType>, Case<IsDecimal<LeftDataType> && IsDecimal<RightDataType> && UseLeftDecimal<LeftDataType, RightDataType>, LeftDataType>,
Case<IsDecimal<LeftDataType> && IsDecimal<RightDataType>, RightDataType>, Case<IsDecimal<LeftDataType> && IsDecimal<RightDataType>, RightDataType>,
Case<IsDecimal<LeftDataType> && !IsDecimal<RightDataType> && IsIntegral<RightDataType>, LeftDataType>, Case<IsDecimal<LeftDataType> && !IsDecimal<RightDataType> && IsIntegral<RightDataType>, LeftDataType>,
@ -1022,11 +1016,9 @@ public:
{ {
if constexpr (IsDecimal<LeftDataType> && IsDecimal<RightDataType>) if constexpr (IsDecimal<LeftDataType> && IsDecimal<RightDataType>)
{ {
using T0 = typename LeftDataType::FieldType; constexpr bool is_multiply = std::is_same_v<Op<UInt8, UInt8>, MultiplyImpl<UInt8, UInt8>>;
using T1 = typename RightDataType::FieldType; constexpr bool is_division = std::is_same_v<Op<UInt8, UInt8>, DivideFloatingImpl<UInt8, UInt8>>;
ResultDataType result_type = decimalResultType(left, right, ResultDataType result_type = decimalResultType(left, right, is_multiply, is_division);
std::is_same_v<Op<T0, T1>, MultiplyImpl<T0, T1>>,
std::is_same_v<Op<T0, T1>, DivideFloatingImpl<T0, T1>>);
type_res = std::make_shared<ResultDataType>(result_type.getPrecision(), result_type.getScale()); type_res = std::make_shared<ResultDataType>(result_type.getPrecision(), result_type.getScale());
} }
else if constexpr (IsDecimal<LeftDataType>) else if constexpr (IsDecimal<LeftDataType>)
@ -1080,6 +1072,9 @@ public:
if constexpr (!std::is_same_v<ResultDataType, InvalidType>) if constexpr (!std::is_same_v<ResultDataType, InvalidType>)
{ {
constexpr bool resultIsDecimal = IsDecimal<LeftDataType> || IsDecimal<RightDataType>; constexpr bool resultIsDecimal = IsDecimal<LeftDataType> || IsDecimal<RightDataType>;
constexpr bool is_multiply = std::is_same_v<Op<UInt8, UInt8>, MultiplyImpl<UInt8, UInt8>>;
constexpr bool is_division = std::is_same_v<Op<UInt8, UInt8>, DivideFloatingImpl<UInt8, UInt8>>;
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;
@ -1087,8 +1082,9 @@ public:
using ColVecT1 = ColumnVector<T1, !IsDecimal<RightDataType>>; using ColVecT1 = ColumnVector<T1, !IsDecimal<RightDataType>>;
using ColVecResult = ColumnVector<ResultType, !resultIsDecimal>; using ColVecResult = ColumnVector<ResultType, !resultIsDecimal>;
/// Decimal operations need scale. Operations are on result type.
using OpImpl = std::conditional_t<IsDecimal<ResultDataType>, using OpImpl = std::conditional_t<IsDecimal<ResultDataType>,
ScaledBinaryOperation<T0, T1, Op<T0, T1>, ResultType>, DecimalBinaryOperation<T0, T1, Op<ResultType, ResultType>, ResultType>,
BinaryOperationImpl<T0, T1, Op<T0, T1>, ResultType>>; BinaryOperationImpl<T0, T1, Op<T0, T1>, ResultType>>;
auto col_left_raw = block.getByPosition(arguments[0]).column.get(); auto col_left_raw = block.getByPosition(arguments[0]).column.get();
@ -1100,13 +1096,15 @@ public:
/// the only case with a non-vector result /// the only case with a non-vector result
if constexpr (resultIsDecimal) if constexpr (resultIsDecimal)
{ {
ResultDataType type = decimalResultType(left, right, ResultDataType type = decimalResultType(left, right, is_multiply, is_division);
std::is_same_v<Op<T0, T1>, MultiplyImpl<T0, T1>>, typename ResultDataType::FieldType scale_a = type.scaleFactorFor(left, is_multiply);
std::is_same_v<Op<T0, T1>, DivideFloatingImpl<T0, T1>>); typename ResultDataType::FieldType scale_b = type.scaleFactorFor(right, is_multiply || is_division);
typename ResultDataType::FieldType scale_a = type.scaleFactorFor(left); if constexpr (IsDecimal<RightDataType> && is_division)
typename ResultDataType::FieldType scale_b = type.scaleFactorFor(right); {
if constexpr (IsDecimal<RightDataType> && std::is_same_v<Op<T0, T1>, DivideFloatingImpl<T0, T1>>)
scale_a = right.getScaleMultiplier(); scale_a = right.getScaleMultiplier();
if (!IsDecimal<LeftDataType>)
scale_a *= scale_a;
}
auto res = OpImpl::constant_constant(col_left->template getValue<T0>(), col_right->template getValue<T1>(), auto res = OpImpl::constant_constant(col_left->template getValue<T0>(), col_right->template getValue<T1>(),
scale_a, scale_b); scale_a, scale_b);
block.getByPosition(result).column = block.getByPosition(result).column =
@ -1130,13 +1128,15 @@ public:
{ {
if constexpr (resultIsDecimal) if constexpr (resultIsDecimal)
{ {
ResultDataType type = decimalResultType(left, right, ResultDataType type = decimalResultType(left, right, is_multiply, is_division);
std::is_same_v<Op<T0, T1>, MultiplyImpl<T0, T1>>, typename ResultDataType::FieldType scale_a = type.scaleFactorFor(left, is_multiply);
std::is_same_v<Op<T0, T1>, DivideFloatingImpl<T0, T1>>); typename ResultDataType::FieldType scale_b = type.scaleFactorFor(right, is_multiply || is_division);
typename ResultDataType::FieldType scale_a = type.scaleFactorFor(left); if constexpr (IsDecimal<RightDataType> && is_division)
typename ResultDataType::FieldType scale_b = type.scaleFactorFor(right); {
if constexpr (IsDecimal<RightDataType> && std::is_same_v<Op<T0, T1>, DivideFloatingImpl<T0, T1>>)
scale_a = right.getScaleMultiplier(); scale_a = right.getScaleMultiplier();
if (!IsDecimal<LeftDataType>)
scale_a *= scale_a;
}
OpImpl::constant_vector(col_left->template getValue<T0>(), col_right->getData(), vec_res, scale_a, scale_b); OpImpl::constant_vector(col_left->template getValue<T0>(), col_right->getData(), vec_res, scale_a, scale_b);
} }
else else
@ -1149,13 +1149,15 @@ public:
{ {
if constexpr (resultIsDecimal) if constexpr (resultIsDecimal)
{ {
ResultDataType type = decimalResultType(left, right, ResultDataType type = decimalResultType(left, right, is_multiply, is_division);
std::is_same_v<Op<T0, T1>, MultiplyImpl<T0, T1>>, typename ResultDataType::FieldType scale_a = type.scaleFactorFor(left, is_multiply);
std::is_same_v<Op<T0, T1>, DivideFloatingImpl<T0, T1>>); typename ResultDataType::FieldType scale_b = type.scaleFactorFor(right, is_multiply || is_division);
typename ResultDataType::FieldType scale_a = type.scaleFactorFor(left); if constexpr (IsDecimal<RightDataType> && is_division)
typename ResultDataType::FieldType scale_b = type.scaleFactorFor(right); {
if constexpr (IsDecimal<RightDataType> && std::is_same_v<Op<T0, T1>, DivideFloatingImpl<T0, T1>>)
scale_a = right.getScaleMultiplier(); scale_a = right.getScaleMultiplier();
if (!IsDecimal<LeftDataType>)
scale_a *= scale_a;
}
if (auto col_right = checkAndGetColumn<ColVecT1>(col_right_raw)) if (auto col_right = checkAndGetColumn<ColVecT1>(col_right_raw))
OpImpl::vector_vector(col_left->getData(), col_right->getData(), vec_res, scale_a, scale_b); OpImpl::vector_vector(col_left->getData(), col_right->getData(), vec_res, scale_a, scale_b);

View File

@ -244,8 +244,8 @@ private:
if (decimal0 && decimal1) if (decimal0 && decimal1)
{ {
auto result_type = decimalResultType(*decimal0, *decimal1, false, false); auto result_type = decimalResultType(*decimal0, *decimal1, false, false);
shift.a = result_type.scaleFactorFor(*decimal0); shift.a = result_type.scaleFactorFor(*decimal0, false);
shift.b = result_type.scaleFactorFor(*decimal1); shift.b = result_type.scaleFactorFor(*decimal1, false);
} }
else if (decimal0) else if (decimal0)
shift.b = decimal0->getScaleMultiplier(); shift.b = decimal0->getScaleMultiplier();

View File

@ -0,0 +1,20 @@
63.420000000 -21.420000000 41.580000000 890.820000000 -890.820000000 0.060189908 -0.194099961
84 0 1764 1
84 0 1764 1
84 0 1764 1
84.840 0.000 1799.456400 1.000
84.84 0.00 1799.4564 1.00
63 21 -42 882 -882 2 0
63 21 -42 882 -882 2 0
63 21 -42 882 -882 2 0
63.420 21.420 -41.580 890.820 -890.820 2.020 0.505
63.420000000 21.420000000 -41.580000000 890.820000000 -890.820000000 2.020000000 0.505000000
63.420000000000000000 21.420000000000000000 -41.580000000000000000 890.820000000000000000 -890.820000000000000000 2.020000000000000000 0.505000000000000000
63.42 21.42 -41.58 890.82 -890.82 2.02 0.50
63 -21 42 882 -882 0 2
63 -21 42 882 -882 0 2
63 -21 42 882 -882 0 2
63.420 -21.420 41.580 890.820 -890.820 0.495 1.980
63.420000000 -21.420000000 41.580000000 890.820000000 -890.820000000
63.420000000000000000 -21.420000000000000000 41.580000000000000000 890.820000000000000000 -890.820000000000000000 0.495049504950495049 1.980198019801980198
63.42 -21.42 41.58 890.82 -890.82 0.49 1.98

View File

@ -0,0 +1,54 @@
CREATE DATABASE IF NOT EXISTS test;
DROP TABLE IF EXISTS test.decimal;
CREATE TABLE IF NOT EXISTS test.decimal
(
a DECIMAL(9,0),
b DECIMAL(18,0),
c DECIMAL(38,0),
d DECIMAL(9, 9),
e DEC(18, 18),
f dec(38, 38),
g Decimal(9, 3),
h decimal(18, 9),
i deciMAL(38, 18),
j dec(4,2)
) ENGINE = Memory;
INSERT INTO test.decimal (a, b, c, d, e, f, g, h, i, j) VALUES (0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
INSERT INTO test.decimal (a, b, c, d, e, f, g, h, i, j) VALUES (42, 42, 42, 0.42, 0.42, 0.42, 42.42, 42.42, 42.42, 42.42);
INSERT INTO test.decimal (a, b, c, d, e, f, g, h, i, j) VALUES (-42, -42, -42, -0.42, -0.42, -0.42, -42.42, -42.42, -42.42, -42.42);
SELECT 21 + h, 21 - h, 84 - h, 21 * h, -21 * h, 21 / h, 84 / h FROM test.decimal WHERE h > 0;
SELECT a + a, a - a, a * a, a / a FROM test.decimal WHERE a = 42;
SELECT b + b, b - b, b * b, b / b FROM test.decimal WHERE b = 42;
SELECT c + c, c - c, c * c, c / c FROM test.decimal WHERE c = 42;
SELECT e + e, e - e, e * e, e / e FROM test.decimal WHERE e > 0; -- { serverError 69 }
SELECT f + f, f - f, f * f, f / f FROM test.decimal WHERE f > 0; -- { serverError 69 }
SELECT g + g, g - g, g * g, g / g FROM test.decimal WHERE g > 0;
--SELECT h + h, h - h, h * h, h / h FROM test.decimal WHERE h > 0; -- overflow
--SELECT i + i, i - i, i * i, i / i FROM test.decimal WHERE i > 0; -- overflow
SELECT j + j, j - j, j * j, j / j FROM test.decimal WHERE j > 0;
SELECT a + 21, a - 21, a - 84, a * 21, a * -21, a / 21, a / 84 FROM test.decimal WHERE a = 42;
SELECT b + 21, b - 21, b - 84, b * 21, b * -21, b / 21, b / 84 FROM test.decimal WHERE b = 42;
SELECT c + 21, c - 21, c - 84, c * 21, c * -21, c / 21, c / 84 FROM test.decimal WHERE c = 42;
--SELECT e + 21, e - 21, e - 84, e * 21, e * -21, e / 21, e / 84 FROM test.decimal WHERE e > 0; -- overflow
--SELECT f + 21, f - 21, f - 84, f * 21, f * -21, f / 21, f / 84 FROM test.decimal WHERE f > 0; -- { serverError 69 }
SELECT g + 21, g - 21, g - 84, g * 21, g * -21, g / 21, g / 84 FROM test.decimal WHERE g > 0;
SELECT h + 21, h - 21, h - 84, h * 21, h * -21, h / 21, h / 84 FROM test.decimal WHERE h > 0;
SELECT i + 21, i - 21, i - 84, i * 21, i * -21, i / 21, i / 84 FROM test.decimal WHERE i > 0;
SELECT j + 21, j - 21, j - 84, j * 21, j * -21, j / 21, j / 84 FROM test.decimal WHERE j > 0;
SELECT 21 + a, 21 - a, 84 - a, 21 * a, -21 * a, 21 / a, 84 / a FROM test.decimal WHERE a = 42;
SELECT 21 + b, 21 - b, 84 - b, 21 * b, -21 * b, 21 / b, 84 / b FROM test.decimal WHERE b = 42;
SELECT 21 + c, 21 - c, 84 - c, 21 * c, -21 * c, 21 / c, 84 / c FROM test.decimal WHERE c = 42;
--SELECT 21 + e, 21 - e, 84 - e, 21 * e, -21 * e, 21 / e, 84 / e FROM test.decimal WHERE e > 0; -- overflow
--SELECT 21 + f, 21 - f, 84 - f, 21 * f, -21 * f, 21 / f, 84 / f FROM test.decimal WHERE f > 0; -- { serverError 69 }
SELECT 21 + g, 21 - g, 84 - g, 21 * g, -21 * g, 21 / g, 84 / g FROM test.decimal WHERE g > 0;
SELECT 21 + h, 21 - h, 84 - h, 21 * h, -21 * h FROM test.decimal WHERE h > 0; --overflow 21 / h, 84 / h
SELECT 21 + i, 21 - i, 84 - i, 21 * i, -21 * i, 21 / i, 84 / i FROM test.decimal WHERE i > 0;
SELECT 21 + j, 21 - j, 84 - j, 21 * j, -21 * j, 21 / j, 84 / j FROM test.decimal WHERE j > 0;
--DROP TABLE IF EXISTS test.defaults;

View File

@ -0,0 +1,17 @@
-42 -42 1 0 0 0 1 1
42 42 1 0 0 0 1 1
-42 -42.42000 0 0 1 1 0 1
42 42.42000 0 1 0 1 1 0
1 1 1
0 0 0
-42 0 0 0 0
42 1 1 1 1
-42 0 0 0 0
42 1 1 1 1
0.420000000 0.420000000000000000 0.42000000000000000000000000000000000000
42.42 42.420000000 42.420000000000000000 42.42
-42.42 -42.420000000 -42.420000000000000000 -42.42
42 42 42
42 42 42
42 42 42
42 42 42

View File

@ -0,0 +1,43 @@
CREATE DATABASE IF NOT EXISTS test;
DROP TABLE IF EXISTS test.decimal;
CREATE TABLE IF NOT EXISTS test.decimal
(
a DECIMAL(9,0),
b DECIMAL(18,0),
c DECIMAL(38,0),
d DECIMAL(9, 9),
e DEC(18, 18),
f dec(38, 38),
g Decimal(9, 5),
h decimal(18, 9),
i deciMAL(38, 18),
j dec(4,2)
) ENGINE = Memory;
INSERT INTO test.decimal (a, b, c, d, e, f, g, h, i, j) VALUES (42, 42, 42, 0.42, 0.42, 0.42, 42.42, 42.42, 42.42, 42.42);
INSERT INTO test.decimal (a, b, c, d, e, f, g, h, i, j) VALUES (-42, -42, -42, -0.42, -0.42, -0.42, -42.42, -42.42, -42.42, -42.42);
SELECT a > toFloat64(0) FROM test.decimal; -- { serverError 43 }
SELECT g > toFloat32(0) FROM test.decimal; -- { serverError 43 }
SELECT a > '0.0' FROM test.decimal; -- { serverError 43 }
SELECT a, b, a = b, a < b, a > b, a != b, a <= b, a >= b FROM test.decimal ORDER BY a;
SELECT a, g, a = g, a < g, a > g, a != g, a <= g, a >= g FROM test.decimal ORDER BY a;
SELECT a > 0, b > 0, g > 0 FROM test.decimal;
SELECT a, g > toInt8(0), g > toInt16(0), g > toInt32(0), g > toInt64(0) FROM test.decimal ORDER BY a;
SELECT a, g > toUInt8(0), g > toUInt16(0), g > toUInt32(0), g > toUInt64(0) FROM test.decimal ORDER BY a;
SELECT a, b, g FROM test.decimal WHERE a IN(42) AND b IN(42) AND g IN(42);
SELECT a, b, g FROM test.decimal WHERE a > 0 AND a <= 42 AND b <= 42 AND g <= 42;
SELECT d, e, f from test.decimal WHERE d > 0 AND d < 1 AND e > 0 AND e < 1 AND f > 0 AND f < 1;
SELECT j, h, i, j from test.decimal WHERE j > 42 AND h > 42 AND h > 42 AND j > 42;
SELECT j, h, i, j from test.decimal WHERE j < 42 AND h < 42 AND h < 42 AND j < 42;
SELECT a, b, c FROM test.decimal WHERE a = toInt8(42) AND b = toInt8(42) AND c = toInt8(42);
SELECT a, b, c FROM test.decimal WHERE a = toInt16(42) AND b = toInt16(42) AND c = toInt16(42);
SELECT a, b, c FROM test.decimal WHERE a = toInt32(42) AND b = toInt32(42) AND c = toInt32(42);
SELECT a, b, c FROM test.decimal WHERE a = toInt64(42) AND b = toInt64(42) AND c = toInt64(42);
SELECT a, b, c FROM test.decimal WHERE a = toFloat32(42); -- { serverError 43 }
SELECT a, b, c FROM test.decimal WHERE a = toFloat64(42); -- { serverError 43 }
DROP TABLE IF EXISTS test.defaults;