From 69dd6609193beb4e7acd3e6ad216eca0ccfb8179 Mon Sep 17 00:00:00 2001 From: chertus Date: Wed, 26 Sep 2018 14:25:50 +0300 Subject: [PATCH] fix crash on decimal division by zero [issue-3221] --- dbms/src/Functions/FunctionsArithmetic.h | 22 ++++++++++--------- .../0_stateless/00700_decimal_arithm.sql | 11 ++++++++++ 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/dbms/src/Functions/FunctionsArithmetic.h b/dbms/src/Functions/FunctionsArithmetic.h index 890e510240e..0081e5355b2 100644 --- a/dbms/src/Functions/FunctionsArithmetic.h +++ b/dbms/src/Functions/FunctionsArithmetic.h @@ -739,16 +739,6 @@ template <> struct NativeType { using Type = Int128; }; template typename Operation, typename ResultType_, bool _check_overflow = true> struct DecimalBinaryOperation { - using ResultType = ResultType_; - using NativeResultType = typename NativeType::Type; - using Op = Operation; - using ColVecA = std::conditional_t, ColumnDecimal, ColumnVector>; - using ColVecB = std::conditional_t, ColumnDecimal, ColumnVector>; - using ArrayA = typename ColVecA::Container; - using ArrayB = typename ColVecB::Container; - using ArrayC = typename ColumnDecimal::Container; - using SelfNoOverflow = DecimalBinaryOperation; - static constexpr bool is_plus_minus = std::is_same_v, PlusImpl> || std::is_same_v, MinusImpl>; static constexpr bool is_multiply = std::is_same_v, MultiplyImpl>; @@ -758,6 +748,18 @@ struct DecimalBinaryOperation static constexpr bool is_plus_minus_compare = is_plus_minus || is_compare; static constexpr bool can_overflow = is_plus_minus || is_multiply; + using ResultType = ResultType_; + using NativeResultType = typename NativeType::Type; + using Op = std::conditional_t, /// substitute divide by intDiv (throw on division by zero) + Operation>; + using ColVecA = std::conditional_t, ColumnDecimal, ColumnVector>; + using ColVecB = std::conditional_t, ColumnDecimal, ColumnVector>; + using ArrayA = typename ColVecA::Container; + using ArrayB = typename ColVecB::Container; + using ArrayC = typename ColumnDecimal::Container; + using SelfNoOverflow = DecimalBinaryOperation; + static void vector_vector(const ArrayA & a, const ArrayB & b, ArrayC & c, ResultType scale_a, ResultType scale_b, bool check_overflow) { if (check_overflow) diff --git a/dbms/tests/queries/0_stateless/00700_decimal_arithm.sql b/dbms/tests/queries/0_stateless/00700_decimal_arithm.sql index 7ebd189b690..b5bd53b3782 100644 --- a/dbms/tests/queries/0_stateless/00700_decimal_arithm.sql +++ b/dbms/tests/queries/0_stateless/00700_decimal_arithm.sql @@ -66,4 +66,15 @@ SELECT (i * i) != 0, (i / i) = 1 FROM test.decimal WHERE i > 0; SELECT e + 1 > e, e + 10 > e, 1 + e > e, 10 + e > e FROM test.decimal WHERE e > 0; SELECT f + 1 > f, f + 10 > f, 1 + f > f, 10 + f > f FROM test.decimal WHERE f > 0; +SELECT 1 / toDecimal32(0, 0); -- { serverError 153 } +SELECT 1 / toDecimal64(0, 1); -- { serverError 153 } +SELECT 1 / toDecimal128(0, 2); -- { serverError 153 } +SELECT 0 / toDecimal32(0, 3); -- { serverError 153 } +SELECT 0 / toDecimal64(0, 4); -- { serverError 153 } +SELECT 0 / toDecimal128(0, 5); -- { serverError 153 } + +SELECT toDecimal32(0, 0) / toInt8(0); -- { serverError 153 } +SELECT toDecimal64(0, 1) / toInt32(0); -- { serverError 153 } +SELECT toDecimal128(0, 2) / toInt64(0); -- { serverError 153 } + DROP TABLE IF EXISTS test.decimal;