Skip to content

Commit

Permalink
expression: check Overflow int128 (#4762) (#4946)
Browse files Browse the repository at this point in the history
close #4512
  • Loading branch information
ti-chi-bot authored Jun 17, 2022
1 parent c09e036 commit 92f6e31
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 5 deletions.
11 changes: 7 additions & 4 deletions libs/libcommon/include/common/arithmeticOverflow.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
#pragma once
#include <boost/multiprecision/cpp_int.hpp>

namespace common
{
using Int256 = boost::multiprecision::checked_int256_t;

template <typename T>
inline bool addOverflow(T x, T y, T & res)
{
Expand Down Expand Up @@ -99,13 +102,13 @@ inline bool mulOverflow(__int128 x, __int128 y, __int128 & res)
if (!x || !y)
return false;

unsigned __int128 a = (x > 0) ? x : -x;
unsigned __int128 b = (y > 0) ? y : -y;
return (a * b) / b != a;
return res / x != y; /// whether overflow int128
}

/// Int256 doesn't use the complement representation to express negative values, but uses an extra bit to express the sign flag,
/// the actual range of Int256 is from -(2^256 - 1) to 2^256 - 1, so 2^255 ~ 2^256-1 do not overflow Int256.
template <>
inline bool mulOverflow(DB::Int256 x, DB::Int256 y, DB::Int256 & res)
inline bool mulOverflow(Int256 x, Int256 y, Int256 & res)
{
try
{
Expand Down
3 changes: 2 additions & 1 deletion libs/libcommon/src/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ target_link_libraries (date_lut_default_timezone common ${PLATFORM_LIBS})
target_link_libraries (multi_version common)
add_check(multi_version)

add_executable (gtests_libcommon gtest_json_test.cpp gtest_strong_typedef.cpp)
add_executable (gtests_libcommon gtest_json_test.cpp gtest_strong_typedef.cpp gtest_arithmetic_overflow.cpp)

target_link_libraries (gtests_libcommon gtest_main common)
add_check(gtests_libcommon)

Expand Down
52 changes: 52 additions & 0 deletions libs/libcommon/src/tests/gtest_arithmetic_overflow.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright 2022 PingCAP, Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <common/arithmeticOverflow.h>
#include <gtest/gtest.h>
TEST(OVERFLOW_Suite, SimpleTest)
{
/// mul int128
__int128 res128;
bool is_overflow;
/// 2^126
static constexpr __int128 int_126 = __int128(__int128(1) << 126);

/// 2^126 << 0 = 2^126
is_overflow = common::mulOverflow(int_126, __int128(1), res128);
ASSERT_EQ(is_overflow, false);

/// 2^126 << 1 = 2^127
is_overflow = common::mulOverflow(int_126, __int128(2), res128);
ASSERT_EQ(is_overflow, true);

/// 2^126 << 2 = 2^128
is_overflow = common::mulOverflow(int_126, __int128(4), res128);
ASSERT_EQ(is_overflow, true);

/// mul int256
common::Int256 res256;
/// 2^254
const common::Int256 int_254 = common::Int256((common::Int256(0x1) << 254));
/// 2^254 << 0 = 2^254
is_overflow = common::mulOverflow(int_254, common::Int256(1), res256);
ASSERT_EQ(is_overflow, false);

/// 2^254 << 1 = 2^255
is_overflow = common::mulOverflow(int_254, common::Int256(2), res256);
ASSERT_EQ(is_overflow, false); /// because the sign flag is processed by an extra bit, excluding from 256 bits of Int256.

/// 2^254 << 2 = 2^256
is_overflow = common::mulOverflow(int_254, common::Int256(4), res256);
ASSERT_EQ(is_overflow, true);
}
22 changes: 22 additions & 0 deletions tests/tidb-ci/fullstack-test-dt/expr_push_down.test
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,25 @@ mysql> use test; set @@tidb_isolation_read_engines='tiflash,tidb'; set @@tidb_al
| NULL | NULL | NULL | NULL | NULL | NULL | NULL | 2 |
| 平凯xingchen公司 | | 平 | | 平凯xingchen公司 | NULL | NULL | 1 |
+----------------------+------+------+------+----------------------+------+------------+----------+

## test overflow int128, uint128 or not.
mysql> drop table if exists test.t;
mysql> CREATE TABLE test.t (v1 decimal(20,20),v2 decimal(30,0));
mysql> insert into test.t values (0.00000000000000000000 , 2585910611040796672),(0.00000000000000000000 , -1901644942657191936), (0.00000000000000000000 , -11901644942657191936),(0.00000000000000000000 , 25859106110407966722),(0.00000000000000000000 , 2585912),(0.00000000000000000000 , -190);
mysql> alter table test.t set tiflash replica 1;

mysql> analyze table test.t;

func> wait_table test t

mysql> use test; set @@tidb_isolation_read_engines='tiflash,tidb'; set @@tidb_enforce_mpp=1; select v1,v2,v1>v2,v1>=v2, v1<v2,v1<=v2 from test.t;
+------------------------+-----------------------+-------+--------+-------+--------+
| v1 | v2 | v1>v2 | v1>=v2 | v1<v2 | v1<=v2 |
+------------------------+-----------------------+-------+--------+-------+--------+
| 0.00000000000000000000 | 2585910611040796672 | 0 | 0 | 1 | 1 |
| 0.00000000000000000000 | -1901644942657191936 | 1 | 1 | 0 | 0 |
| 0.00000000000000000000 | -11901644942657191936 | 1 | 1 | 0 | 0 |
| 0.00000000000000000000 | 25859106110407966722 | 0 | 0 | 1 | 1 |
| 0.00000000000000000000 | 2585912 | 0 | 0 | 1 | 1 |
| 0.00000000000000000000 | -190 | 1 | 1 | 0 | 0 |
+------------------------+-----------------------+-------+--------+-------+--------+

0 comments on commit 92f6e31

Please sign in to comment.