From 48f29ae11f83d0190edcfc4853f274ec89725bec Mon Sep 17 00:00:00 2001 From: Artem Zuikov Date: Wed, 9 Sep 2020 16:18:58 +0300 Subject: [PATCH] Fix bug in Decimal scale (#14603) --- src/Core/DecimalComparison.h | 2 +- src/DataTypes/DataTypeDecimalBase.h | 39 ++++++++----------- src/Functions/FunctionBinaryArithmetic.h | 23 ++++++----- .../01095_tpch_like_smoke.reference | 2 +- .../01474_decimal_scale_bug.reference | 18 +++++++++ .../0_stateless/01474_decimal_scale_bug.sql | 20 ++++++++++ 6 files changed, 67 insertions(+), 37 deletions(-) create mode 100644 tests/queries/0_stateless/01474_decimal_scale_bug.reference create mode 100644 tests/queries/0_stateless/01474_decimal_scale_bug.sql diff --git a/src/Core/DecimalComparison.h b/src/Core/DecimalComparison.h index 93992029634..b9ae2a1fe79 100644 --- a/src/Core/DecimalComparison.h +++ b/src/Core/DecimalComparison.h @@ -129,7 +129,7 @@ private: Shift shift; if (decimal0 && decimal1) { - auto result_type = decimalResultType(*decimal0, *decimal1, false, false); + auto result_type = decimalResultType(*decimal0, *decimal1); shift.a = static_cast(result_type.scaleFactorFor(*decimal0, false).value); shift.b = static_cast(result_type.scaleFactorFor(*decimal1, false).value); } diff --git a/src/DataTypes/DataTypeDecimalBase.h b/src/DataTypes/DataTypeDecimalBase.h index 265d58d69e1..c5669ab735a 100644 --- a/src/DataTypes/DataTypeDecimalBase.h +++ b/src/DataTypes/DataTypeDecimalBase.h @@ -156,38 +156,31 @@ protected: }; -template typename DecimalType> -typename std::enable_if_t<(sizeof(T) >= sizeof(U)), DecimalType> -inline decimalResultType(const DecimalType & tx, const DecimalType & ty, bool is_multiply, bool is_divide) +template typename DecimalType> +inline auto decimalResultType(const DecimalType & tx, const DecimalType & ty) { - UInt32 scale = (tx.getScale() > ty.getScale() ? tx.getScale() : ty.getScale()); - if (is_multiply) + UInt32 scale{}; + if constexpr (is_multiply) scale = tx.getScale() + ty.getScale(); - else if (is_divide) + else if constexpr (is_division) scale = tx.getScale(); - return DecimalType(DecimalUtils::maxPrecision(), scale); + else + scale = (tx.getScale() > ty.getScale() ? tx.getScale() : ty.getScale()); + + if constexpr (sizeof(T) < sizeof(U)) + return DecimalType(DecimalUtils::maxPrecision(), scale); + else + return DecimalType(DecimalUtils::maxPrecision(), scale); } -template typename DecimalType> -typename std::enable_if_t<(sizeof(T) < sizeof(U)), const DecimalType> -inline decimalResultType(const DecimalType & tx, const DecimalType & ty, bool is_multiply, bool is_divide) -{ - UInt32 scale = (tx.getScale() > ty.getScale() ? tx.getScale() : ty.getScale()); - if (is_multiply) - scale = tx.getScale() * ty.getScale(); - else if (is_divide) - scale = tx.getScale(); - return DecimalType(DecimalUtils::maxPrecision(), scale); -} - -template typename DecimalType> -inline const DecimalType decimalResultType(const DecimalType & tx, const DataTypeNumber &, bool, bool) +template typename DecimalType> +inline const DecimalType decimalResultType(const DecimalType & tx, const DataTypeNumber &) { return DecimalType(DecimalUtils::maxPrecision(), tx.getScale()); } -template typename DecimalType> -inline const DecimalType decimalResultType(const DataTypeNumber &, const DecimalType & ty, bool, bool) +template typename DecimalType> +inline const DecimalType decimalResultType(const DataTypeNumber &, const DecimalType & ty) { return DecimalType(DecimalUtils::maxPrecision(), ty.getScale()); } diff --git a/src/Functions/FunctionBinaryArithmetic.h b/src/Functions/FunctionBinaryArithmetic.h index d899a95ddc6..15b6ea6ca5d 100644 --- a/src/Functions/FunctionBinaryArithmetic.h +++ b/src/Functions/FunctionBinaryArithmetic.h @@ -561,6 +561,9 @@ public: template