Skip to content

Commit

Permalink
fix crash on decimal division by zero [issue-3221]
Browse files Browse the repository at this point in the history
  • Loading branch information
4ertus2 committed Sep 26, 2018
1 parent b326b95 commit 69dd660
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 10 deletions.
22 changes: 12 additions & 10 deletions dbms/src/Functions/FunctionsArithmetic.h
Original file line number Diff line number Diff line change
Expand Up @@ -739,16 +739,6 @@ template <> struct NativeType<Decimal128> { using Type = Int128; };
template <typename A, typename B, template <typename, typename> typename Operation, typename ResultType_, bool _check_overflow = true>
struct DecimalBinaryOperation
{
using ResultType = ResultType_;
using NativeResultType = typename NativeType<ResultType>::Type;
using Op = Operation<NativeResultType, NativeResultType>;
using ColVecA = std::conditional_t<IsDecimalNumber<A>, ColumnDecimal<A>, ColumnVector<A>>;
using ColVecB = std::conditional_t<IsDecimalNumber<B>, ColumnDecimal<B>, ColumnVector<B>>;
using ArrayA = typename ColVecA::Container;
using ArrayB = typename ColVecB::Container;
using ArrayC = typename ColumnDecimal<ResultType>::Container;
using SelfNoOverflow = DecimalBinaryOperation<A, B, Operation, ResultType_, false>;

static constexpr bool is_plus_minus = std::is_same_v<Operation<Int32, Int32>, PlusImpl<Int32, Int32>> ||
std::is_same_v<Operation<Int32, Int32>, MinusImpl<Int32, Int32>>;
static constexpr bool is_multiply = std::is_same_v<Operation<Int32, Int32>, MultiplyImpl<Int32, Int32>>;
Expand All @@ -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<ResultType>::Type;
using Op = std::conditional_t<is_division,
DivideIntegralImpl<NativeResultType, NativeResultType>, /// substitute divide by intDiv (throw on division by zero)
Operation<NativeResultType, NativeResultType>>;
using ColVecA = std::conditional_t<IsDecimalNumber<A>, ColumnDecimal<A>, ColumnVector<A>>;
using ColVecB = std::conditional_t<IsDecimalNumber<B>, ColumnDecimal<B>, ColumnVector<B>>;
using ArrayA = typename ColVecA::Container;
using ArrayB = typename ColVecB::Container;
using ArrayC = typename ColumnDecimal<ResultType>::Container;
using SelfNoOverflow = DecimalBinaryOperation<A, B, Operation, ResultType_, false>;

static void vector_vector(const ArrayA & a, const ArrayB & b, ArrayC & c, ResultType scale_a, ResultType scale_b, bool check_overflow)
{
if (check_overflow)
Expand Down
11 changes: 11 additions & 0 deletions dbms/tests/queries/0_stateless/00700_decimal_arithm.sql
Original file line number Diff line number Diff line change
Expand Up @@ -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;

0 comments on commit 69dd660

Please sign in to comment.