Skip to content

Commit

Permalink
expression: check Overflow int128 (#4762)
Browse files Browse the repository at this point in the history
close #4512
  • Loading branch information
fzhedu authored May 20, 2022
1 parent 952cb0a commit 71613fd
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 3 deletions.
7 changes: 4 additions & 3 deletions libs/libcommon/include/common/arithmeticOverflow.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
// limitations under the License.

#pragma once
#include "types.h"

namespace common
{
Expand Down Expand Up @@ -113,11 +114,11 @@ 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(Int256 x, Int256 y, Int256 & res)
{
Expand Down
1 change: 1 addition & 0 deletions libs/libcommon/src/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ add_executable (gtests_libcommon
gtest_mem_utils.cpp
gtest_crc64.cpp
gtest_logger.cpp
gtest_arithmetic_overflow.cpp
)
target_link_libraries (gtests_libcommon gtest_main common)
add_check(gtests_libcommon)
Expand Down
53 changes: 53 additions & 0 deletions libs/libcommon/src/tests/gtest_arithmetic_overflow.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// 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 <common/types.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
Int256 res256;
/// 2^254
static constexpr Int256 int_254 = Int256((Int256(0x1) << 254));
/// 2^254 << 0 = 2^254
is_overflow = common::mulOverflow(int_254, Int256(1), res256);
ASSERT_EQ(is_overflow, false);

/// 2^254 << 1 = 2^255
is_overflow = common::mulOverflow(int_254, 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, 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 @@ -110,3 +110,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 71613fd

Please sign in to comment.