1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2025-07-30 19:23:07 +03:00

Fixes for Decimal multiplication overflow check and RowGroup UTs

This commit is contained in:
Roman Nozdrin
2020-11-22 17:55:22 +00:00
parent 23af547fb8
commit 5ba6737965
4 changed files with 50 additions and 35 deletions

View File

@ -735,6 +735,4 @@ namespace datatypes
os << dec.toString(); os << dec.toString();
return os; return os;
} }
} // end of namespace } // end of namespace

View File

@ -415,28 +415,26 @@ struct DivisionOverflowCheck {
} }
}; };
/** //
@brief The structure contains an overflow check for int128 // @brief The structure contains an overflow check for int128
and int64_t multiplication. // and int64_t multiplication.
*/ //
struct MultiplicationOverflowCheck { struct MultiplicationOverflowCheck {
void operator()(const int128_t& x, const int128_t& y) void operator()(const int128_t& x, const int128_t& y)
{ {
if (x * y / y != x) int128_t tempR = 0;
{ this->operator()(x, y, tempR);
throw logging::OperationOverflowExcept(
"Decimal::multiplication<int128_t> or scale multiplication \
produces an overflow.");
}
} }
bool operator()(const int128_t& x, const int128_t& y, int128_t& r) bool operator()(const int128_t& x, const int128_t& y, int128_t& r)
{ {
if ((r = x * y) / y != x) volatile int128_t z = x * y;
if (z / y != x)
{ {
throw logging::OperationOverflowExcept( throw logging::OperationOverflowExcept(
"Decimal::multiplication<int128_t> or scale multiplication \ "Decimal::multiplication<int128_t> or scale multiplication \
produces an overflow."); produces an overflow.");
} }
r = z;
return true; return true;
} }
void operator()(const int64_t x, const int64_t y) void operator()(const int64_t x, const int64_t y)
@ -838,6 +836,7 @@ class VDecimal: public TSInt128
// STRICTLY for unit tests!!! // STRICTLY for unit tests!!!
void setTSInt64Value(const int64_t x) { value = x; } void setTSInt64Value(const int64_t x) { value = x; }
void setTSInt128Value(const int128_t& x) { s128Value = x; } void setTSInt128Value(const int128_t& x) { s128Value = x; }
void setScale(const uint8_t x) { scale = x; }
private: private:
uint8_t writeIntPart(const int128_t& x, uint8_t writeIntPart(const int128_t& x,

View File

@ -508,7 +508,6 @@ TEST(Decimal, additionWithOverflowCheck)
result.scale = 1; result.scale = 1;
result.precision = 38; result.precision = 38;
result.s128Value = 0; result.s128Value = 0;
EXPECT_THROW(doAdd(l, r, result), logging::OperationOverflowExcept); EXPECT_THROW(doAdd(l, r, result), logging::OperationOverflowExcept);
// Normal execution w/o overflow // Normal execution w/o overflow
@ -880,6 +879,26 @@ TEST(Decimal, multiplicationWithOverflowCheck)
EXPECT_NO_THROW(doMultiply(l, r, result)); EXPECT_NO_THROW(doMultiply(l, r, result));
EXPECT_EQ("21267647932558653966460912964485513216", result.toString()); EXPECT_EQ("21267647932558653966460912964485513216", result.toString());
l.setTSInt128Value((int128_t)1 << 122);
l.setScale(0);
r.setTSInt128Value(100);
r.setScale(0);
EXPECT_THROW(doMultiply(l, r, result), logging::OperationOverflowExcept);
l.setTSInt128Value((int128_t)1 << 65);
l.setScale(0);
r.setTSInt128Value((int128_t)1 << 64);
r.setScale(0);
EXPECT_THROW(doMultiply(l, r, result), logging::OperationOverflowExcept);
l.setTSInt128Value((int128_t)1 << 122);
l.setScale(0);
r.setTSInt128Value(2);
r.setScale(0);
EXPECT_NO_THROW(doMultiply(l, r, result));
EXPECT_EQ("10633823966279326983230456482242756608", result.toString());
} }
TEST(Decimal, DecimalToStringCheckScale0) TEST(Decimal, DecimalToStringCheckScale0)

View File

@ -104,12 +104,11 @@ protected:
sValueVector.push_back(0); sValueVector.push_back(0);
sValueVector.push_back(nullValue-1); sValueVector.push_back(nullValue-1);
uValueVector.push_back(nullValue); anotherValueVector.push_back(nullValue);
uValueVector.push_back(42); anotherValueVector.push_back(42);
uValueVector.push_back(bigValue); anotherValueVector.push_back(bigValue);
uValueVector.push_back(0); anotherValueVector.push_back(0);
uValueVector.push_back(nullValue-1); anotherValueVector.push_back(nullValue-1);
s8ValueVector.push_back(joblist::TINYINTNULL); s8ValueVector.push_back(joblist::TINYINTNULL);
s8ValueVector.push_back(-0x79); s8ValueVector.push_back(-0x79);
s8ValueVector.push_back(0); s8ValueVector.push_back(0);
@ -138,8 +137,8 @@ protected:
{ {
r.setBinaryField_offset(&sValueVector[i], r.setBinaryField_offset(&sValueVector[i],
sizeof(sValueVector[0]), offsets[0]); sizeof(sValueVector[0]), offsets[0]);
r.setBinaryField_offset(&uValueVector[i], r.setBinaryField_offset(&anotherValueVector[i],
sizeof(uValueVector[0]), offsets[1]); sizeof(anotherValueVector[0]), offsets[1]);
r.setIntField(s64ValueVector[i], 2); r.setIntField(s64ValueVector[i], 2);
r.setIntField(s32ValueVector[i], 3); r.setIntField(s32ValueVector[i], 3);
r.setIntField(s16ValueVector[i], 4); r.setIntField(s16ValueVector[i], 4);
@ -159,7 +158,7 @@ protected:
uint32_t rowSize; uint32_t rowSize;
size_t rowCount; size_t rowCount;
std::vector<int128_t> sValueVector; std::vector<int128_t> sValueVector;
std::vector<uint128_t> uValueVector; std::vector<int128_t> anotherValueVector;
std::vector<int64_t> s8ValueVector; std::vector<int64_t> s8ValueVector;
std::vector<int64_t> s16ValueVector; std::vector<int64_t> s16ValueVector;
std::vector<int64_t> s32ValueVector; std::vector<int64_t> s32ValueVector;
@ -199,15 +198,15 @@ TEST_F(RowDecimalTest, InitToNullAndIsNullValueCheck)
TEST_F(RowDecimalTest, GetBinaryFieldCheck) TEST_F(RowDecimalTest, GetBinaryFieldCheck)
{ {
rg.getRow(0, &r); rg.getRow(0, &r);
uint128_t* u128Value; int128_t* a128Value;
int128_t* s128Value; int128_t* s128Value;
for (size_t i = 0; i < sValueVector.size(); i++) for (size_t i = 0; i < sValueVector.size(); i++)
{ {
s128Value = r.getBinaryField<int128_t>(0); s128Value = r.getBinaryField<int128_t>(0);
EXPECT_EQ(sValueVector[i], *s128Value); EXPECT_EQ(sValueVector[i], *s128Value);
u128Value = r.getBinaryField<uint128_t>(1); a128Value = r.getBinaryField<int128_t>(1);
EXPECT_EQ(uValueVector[i], *u128Value); EXPECT_EQ(anotherValueVector[i], *a128Value);
//EXPECT_EQ(s64ValueVector[i], r.getIntField(2)); //EXPECT_EQ(s64ValueVector[i], r.getIntField(2));
//EXPECT_EQ(s32ValueVector[i],r.getIntField(3)); //EXPECT_EQ(s32ValueVector[i],r.getIntField(3));
//EXPECT_EQ(r.getIntField(4),s16ValueVector[i]); //EXPECT_EQ(r.getIntField(4),s16ValueVector[i]);
@ -246,27 +245,27 @@ TEST_F(RowDecimalTest, ApplyMappingCheck)
rg.getRow(1, &r); rg.getRow(1, &r);
rg.getRow(2, &rOutMappingCheck); rg.getRow(2, &rOutMappingCheck);
int128_t* s128Value = rOutMappingCheck.getBinaryField<int128_t>(0); int128_t* s128Value = rOutMappingCheck.getBinaryField<int128_t>(0);
uint128_t* u128Value = rOutMappingCheck.getBinaryField<uint128_t>(1); int128_t* a128Value = rOutMappingCheck.getBinaryField<int128_t>(1);
EXPECT_NE(sValueVector[1], *s128Value); EXPECT_NE(sValueVector[1], *s128Value);
EXPECT_NE(uValueVector[1], *u128Value); EXPECT_NE(anotherValueVector[1], *a128Value);
applyMapping(mapping, r, &rOutMappingCheck); applyMapping(mapping, r, &rOutMappingCheck);
s128Value = rOutMappingCheck.getBinaryField<int128_t>(0); s128Value = rOutMappingCheck.getBinaryField<int128_t>(0);
u128Value = rOutMappingCheck.getBinaryField<uint128_t>(1); a128Value = rOutMappingCheck.getBinaryField<int128_t>(1);
EXPECT_EQ(sValueVector[1], *s128Value); EXPECT_EQ(sValueVector[1], *s128Value);
EXPECT_EQ(uValueVector[1], *u128Value); EXPECT_EQ(anotherValueVector[1], *a128Value);
} }
TEST_F(RowDecimalTest, CopyBinaryFieldCheck) TEST_F(RowDecimalTest, CopyBinaryFieldCheck)
{ {
int128_t constVal = 1; int128_t constVal = 1;
int128_t *col1Out, *col1In; int128_t *col1Out, *col1In;
uint128_t *col2Out, *col2In; int128_t *col2Out, *col2In;
rgOut.getRow(0, &rOut); rgOut.getRow(0, &rOut);
for (size_t i = 0; i < sValueVector.size(); i++) for (size_t i = 0; i < sValueVector.size(); i++)
{ {
rOut.setBinaryField_offset(&constVal, 16, offsets[0]); rOut.setBinaryField_offset(&constVal, 16, offsets[0]);
rOut.setBinaryField_offset((uint128_t*)&constVal, 16, offsets[1]); rOut.setBinaryField_offset(&constVal, 16, offsets[1]);
rOut.nextRow(rowSize); rOut.nextRow(rowSize);
} }
@ -278,14 +277,14 @@ TEST_F(RowDecimalTest, CopyBinaryFieldCheck)
{ {
col1In = r.getBinaryField<int128_t>(0); col1In = r.getBinaryField<int128_t>(0);
col1Out = rOut.getBinaryField<int128_t>(0); col1Out = rOut.getBinaryField<int128_t>(0);
col2In = r.getBinaryField<uint128_t>(1); col2In = r.getBinaryField<int128_t>(1);
col2Out = rOut.getBinaryField<uint128_t>(1); col2Out = rOut.getBinaryField<int128_t>(1);
EXPECT_NE(*col1In, *col1Out); EXPECT_NE(*col1In, *col1Out);
EXPECT_NE(*col2In, *col2Out); EXPECT_NE(*col2In, *col2Out);
r.copyBinaryField<int128_t>(rOut, 0, 0); r.copyBinaryField<int128_t>(rOut, 0, 0);
r.copyBinaryField<int128_t>(rOut, 1, 1); r.copyBinaryField<int128_t>(rOut, 1, 1);
col1Out = rOut.getBinaryField<int128_t>(0); col1Out = rOut.getBinaryField<int128_t>(0);
col2Out = rOut.getBinaryField<uint128_t>(1); col2Out = rOut.getBinaryField<int128_t>(1);
EXPECT_EQ(*col1In, *col1Out); EXPECT_EQ(*col1In, *col1Out);
EXPECT_EQ(*col2In, *col2Out); EXPECT_EQ(*col2In, *col2Out);
r.nextRow(rowSize); r.nextRow(rowSize);