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

MCOL-641 Changed the hint to search for GTest headers.

This commit introduces DataConvert UTs.

DataConvert::decimalToString now can negative values.

Next version for Row::toString(), applyMapping UT checks.

Row:equals() is now wide-DECIMAL aware.
This commit is contained in:
drrtuy
2020-02-24 17:22:52 +03:00
committed by Roman Nozdrin
parent c23ead2703
commit b29d0c9daa
7 changed files with 142 additions and 39 deletions

View File

@ -17,10 +17,9 @@ find_library(PTHREAD_LIBRARY
HINTS ${GTEST_ROOT_DIR}/lib HINTS ${GTEST_ROOT_DIR}/lib
) )
find_path(GTEST_INCLUDE_DIR find_path(GTEST_INCLUDE_DIR
NAMES gtest.h NAMES gtest.h
HINTS ${GTEST_ROOT_DIR}/include HINTS ${GTEST_ROOT_DIR}/include/gtest
) )
include(FindPackageHandleStandardArgs) include(FindPackageHandleStandardArgs)

View File

@ -1004,6 +1004,12 @@ inline bool isNumeric(const execplan::CalpontSystemCatalog::ColDataType type)
} }
} }
inline bool isDecimal(const execplan::CalpontSystemCatalog::ColDataType type)
{
return (type == execplan::CalpontSystemCatalog::DECIMAL ||
type == execplan::CalpontSystemCatalog::UDECIMAL);
}
/** convenience function to determine if column type is an /** convenience function to determine if column type is an
* unsigned type * unsigned type
*/ */

View File

@ -11,3 +11,9 @@ add_library(dataconvert SHARED ${dataconvert_LIB_SRCS})
add_dependencies(dataconvert loggingcpp) add_dependencies(dataconvert loggingcpp)
install(TARGETS dataconvert DESTINATION ${ENGINE_LIBDIR} COMPONENT columnstore-engine) install(TARGETS dataconvert DESTINATION ${ENGINE_LIBDIR} COMPONENT columnstore-engine)
if (WITH_DATACONVERT_UT)
add_executable(dataconvert_tests dataconvert-tests.cpp)
target_link_libraries(dataconvert_tests ${ENGINE_LDFLAGS} ${GTEST_LIBRARIES} ${ENGINE_EXEC_LIBS} ${MARIADB_CLIENT_LIBS})
install(TARGETS dataconvert_tests DESTINATION ${ENGINE_BINDIR} COMPONENT columnstore-platform)
endif()

View File

@ -1220,7 +1220,7 @@ size_t DataConvert::writeIntPart(T* dec, char* p,
if (buflen <= p-original_p) if (buflen <= p-original_p)
{ {
throw QueryDataExcept("toString() char buffer overflow.", formatErr); throw QueryDataExcept("writeIntPart() char buffer overflow.", formatErr);
} }
return p-original_p; return p-original_p;
} }
@ -1352,31 +1352,27 @@ void DataConvert::decimalToString(T* valuePtr,
unsigned int buflen, unsigned int buflen,
cscDataType colDataType) // We don't need the last one cscDataType colDataType) // We don't need the last one
{ {
if (*valuePtr < static_cast<T>(0)) T value = *valuePtr;
char* ptr = &buf[0];
size_t l1 = buflen;
if (value < static_cast<T>(0))
{ {
*buf++ = '-'; *ptr++ = '-';
*valuePtr *= -1; value *= -1;
idbassert(l1 >= 2);
l1--;
} }
toString<T>(valuePtr, buf, buflen); //we want to move the last scale chars right by one spot to insert the dp
//we want to move the trailing null as well, so it's really scale+1 chars
toString<T>(&value, ptr, buflen);
// Biggest ColumnStore supports is DECIMAL(38,x), or 38 total digits+dp+sign for column // Biggest ColumnStore supports is DECIMAL(38,x), or 38 total digits+dp+sign for column
if (scale == 0) if (scale == 0)
return; return;
//we want to move the last scale chars right by one spot to insert the dp
//we want to move the trailing null as well, so it's really scale+1 chars
size_t l1 = strlen(buf);
char* ptr = &buf[0];
if (*valuePtr < 0)
{
ptr++;
idbassert(l1 >= 2);
l1--;
}
//need to make sure we have enough leading zeros for this to work... //need to make sure we have enough leading zeros for this to work...
//at this point scale is always > 0 //at this point scale is always > 0
size_t l2 = 1; size_t l2 = 1;

View File

@ -67,14 +67,15 @@ class RowDecimalTest : public ::testing::Test {
rg.setData(&rgD); rg.setData(&rgD);
rg.initRow(&r); rg.initRow(&r);
rg.initRow(&rOutMappingCheck);
rowSize = r.getSize(); rowSize = r.getSize();
rg.getRow(0, &r); rg.getRow(0, &r);
int128_t nullValue = 0; int128_t nullValue = 0;
int128_t bigValue = 0; int128_t bigValue = 0;
uint64_t* uint128_pod = reinterpret_cast<uint64_t*>(&nullValue); uint64_t* uint128_pod = reinterpret_cast<uint64_t*>(&nullValue);
uint128_pod[0] = joblist::BINARYEMPTYROW; uint128_pod[0] = joblist::BINARYNULL;
uint128_pod[1] = joblist::BINARYNULL; uint128_pod[1] = joblist::BINARYEMPTYROW;
bigValue = -static_cast<int128_t>(0xFFFFFFFF)*0xFFFFFFFFFFFFFFFF; bigValue = -static_cast<int128_t>(0xFFFFFFFF)*0xFFFFFFFFFFFFFFFF;
//char buf[utils::precisionByWidth(16)+3]; //char buf[utils::precisionByWidth(16)+3];
//memset(&buf[0], 0, sizeof(buf)); //memset(&buf[0], 0, sizeof(buf));
@ -82,7 +83,7 @@ class RowDecimalTest : public ::testing::Test {
//dataconvert::DataConvert::decimalToString(&bigValue, scale1, buf, //dataconvert::DataConvert::decimalToString(&bigValue, scale1, buf,
// utils::precisionByWidth(sizeof(bigValue))+3,types[0]); // utils::precisionByWidth(sizeof(bigValue))+3,types[0]);
//std::cout << buf << std::endl; //std::cout << buf << std::endl;
sValueVector.push_back(nullValue-2); sValueVector.push_back(nullValue);
sValueVector.push_back(-42); sValueVector.push_back(-42);
sValueVector.push_back(bigValue); sValueVector.push_back(bigValue);
sValueVector.push_back(0); sValueVector.push_back(0);
@ -136,6 +137,7 @@ class RowDecimalTest : public ::testing::Test {
// void TearDown() override {} // void TearDown() override {}
rowgroup::Row r; rowgroup::Row r;
rowgroup::Row rOutMappingCheck;
rowgroup::RowGroup rg; rowgroup::RowGroup rg;
rowgroup::RGData rgD; rowgroup::RGData rgD;
uint32_t rowSize; uint32_t rowSize;
@ -200,7 +202,7 @@ TEST_F(RowDecimalTest, toStringCheck) {
exemplarVector.push_back(std::string("0: -42 42 -121 -121 -121 -121 ")); exemplarVector.push_back(std::string("0: -42 42 -121 -121 -121 -121 "));
exemplarVector.push_back(std::string("0: -79228162495817593515539431425 -79228162495817593515539431425 0 0 0 0 ")); exemplarVector.push_back(std::string("0: -79228162495817593515539431425 -79228162495817593515539431425 0 0 0 0 "));
exemplarVector.push_back(std::string("0: 0 0 129 129 129 -127 ")); exemplarVector.push_back(std::string("0: 0 0 129 129 129 -127 "));
exemplarVector.push_back(std::string("0: -18446744073709551618 -18446744073709551618 9223372036854775807 2147483647 32767 127 ")); exemplarVector.push_back(std::string("0: -3 -3 9223372036854775807 2147483647 32767 127 "));
rg.getRow(0, &r); rg.getRow(0, &r);
r.initToNull(); r.initToNull();
@ -212,7 +214,22 @@ TEST_F(RowDecimalTest, toStringCheck) {
TEST_F(RowDecimalTest, toCSVCheck) { TEST_F(RowDecimalTest, toCSVCheck) {
} }
TEST_F(RowDecimalTest, applyMappingCheck) { TEST_F(RowDecimalTest, applyMappingCheck) {
int mapping[] = {0, 1, -1, -1, -1, -1};
rg.getRow(1, &r);
rg.getRow(2, &rOutMappingCheck);
int128_t* s128Value = rOutMappingCheck.getBinaryField<int128_t>(0);
uint128_t* u128Value = rOutMappingCheck.getBinaryField<uint128_t>(1);
EXPECT_NE(sValueVector[1], *s128Value);
EXPECT_NE(uValueVector[1], *u128Value);
applyMapping(mapping, r, &rOutMappingCheck);
s128Value = rOutMappingCheck.getBinaryField<int128_t>(0);
EXPECT_EQ(sValueVector[1], *s128Value);
u128Value = rOutMappingCheck.getBinaryField<uint128_t>(1);
EXPECT_EQ(uValueVector[1], *u128Value);
} }
TEST_F(RowDecimalTest, equalsCheck) {
// WIP
TEST_F(RowDecimalTest, RowEqualsCheck) {
} }

View File

@ -638,12 +638,12 @@ string Row::toString() const
// WIP // WIP
case CalpontSystemCatalog::DECIMAL: case CalpontSystemCatalog::DECIMAL:
case CalpontSystemCatalog::UDECIMAL: case CalpontSystemCatalog::UDECIMAL:
if (colWidths[i] > MAXLEGACYWIDTH) if (colWidths[i] == sizeof(int128_t))
{ {
char *buf = (char*)alloca(precision[i] + 3); char *buf = (char*)alloca(precision[i] + 3);
// empty the buffer // empty the buffer
dataconvert::DataConvert::toString(getBinaryField<int128_t>(i), dataconvert::DataConvert::decimalToString(getBinaryField<int128_t>(i),
buf, precision[i]+3); //WIP scale[i] scale[i], buf, precision[i]+3, types[i]);
os << buf << " "; os << buf << " ";
break; break;
} }
@ -1048,8 +1048,6 @@ bool Row::isNullValue(uint32_t colIndex) const
case 8: case 8:
return return
(*((uint64_t*) &data[offsets[colIndex]]) == joblist::CHAR8NULL); (*((uint64_t*) &data[offsets[colIndex]]) == joblist::CHAR8NULL);
case 16:
std::cout << __FILE__<< ":" <<__LINE__ << " Fix for 16 Bytes ?" << std::endl;
default: default:
return (*((uint64_t*) &data[offsets[colIndex]]) == *((uint64_t*) joblist::CPNULLSTRMARK.c_str())); return (*((uint64_t*) &data[offsets[colIndex]]) == *((uint64_t*) joblist::CPNULLSTRMARK.c_str()));
} }
@ -1646,10 +1644,10 @@ void applyMapping(const int* mapping, const Row& in, Row* out)
// WIP this doesn't look right b/c we can pushdown colType // WIP this doesn't look right b/c we can pushdown colType
// Migrate to offset based methods here // Migrate to offset based methods here
// code precision 2 width convertor // code precision 2 width convertor
else if (UNLIKELY(in.getColTypes()[i] == execplan::CalpontSystemCatalog::DECIMAL && else if (UNLIKELY(execplan::isDecimal(in.getColTypes()[i])
in.getColumnWidth(i) == 16)) && in.getColumnWidth(i) == 16))
out->setBinaryField_offset(in.getBinaryField<uint8_t>(i), 16, out->setBinaryField_offset(in.getBinaryField<int128_t>(i), 16,
out->getOffset(mapping[i])); out->getOffset(mapping[i]));
else if (in.isUnsigned(i)) else if (in.isUnsigned(i))
out->setUintField(in.getUintField(i), mapping[i]); out->setUintField(in.getUintField(i), mapping[i]);
else else

View File

@ -375,6 +375,8 @@ public:
inline uint64_t getUintField(uint32_t colIndex) const; inline uint64_t getUintField(uint32_t colIndex) const;
template<int len> inline int64_t getIntField(uint32_t colIndex) const; template<int len> inline int64_t getIntField(uint32_t colIndex) const;
inline int64_t getIntField(uint32_t colIndex) const; inline int64_t getIntField(uint32_t colIndex) const;
template<typename T>
inline bool equals(T* value, uint32_t colIndex) const;
template<int len> inline bool equals(uint64_t val, uint32_t colIndex) const; template<int len> inline bool equals(uint64_t val, uint32_t colIndex) const;
inline bool equals(long double val, uint32_t colIndex) const; inline bool equals(long double val, uint32_t colIndex) const;
bool equals(const std::string& val, uint32_t colIndex) const; bool equals(const std::string& val, uint32_t colIndex) const;
@ -664,6 +666,12 @@ inline bool Row::inStringTable(uint32_t col) const
return strings && getColumnWidth(col) >= sTableThreshold && !forceInline[col]; return strings && getColumnWidth(col) >= sTableThreshold && !forceInline[col];
} }
template<typename T>
inline bool Row::equals(T* value, uint32_t colIndex) const
{
return reinterpret_cast<T*>(&data[offsets[colIndex]]) == value;
}
template<int len> template<int len>
inline bool Row::equals(uint64_t val, uint32_t colIndex) const inline bool Row::equals(uint64_t val, uint32_t colIndex) const
{ {
@ -681,8 +689,6 @@ inline bool Row::equals(uint64_t val, uint32_t colIndex) const
case 8: case 8:
return *((uint64_t*) &data[offsets[colIndex]]) == val; return *((uint64_t*) &data[offsets[colIndex]]) == val;
case 16:
std::cout << __FILE__<< ":" <<__LINE__ << " Fix for 16 Bytes ?" << std::endl;
default: default:
idbassert(0); idbassert(0);
throw std::logic_error("Row::equals(): bad length."); throw std::logic_error("Row::equals(): bad length.");
@ -710,8 +716,6 @@ inline uint64_t Row::getUintField(uint32_t colIndex) const
case 8: case 8:
return *((uint64_t*) &data[offsets[colIndex]]); return *((uint64_t*) &data[offsets[colIndex]]);
case 16:
std::cout << __FILE__<< ":" <<__LINE__ << " Fix for 16 Bytes ?" << std::endl;
default: default:
idbassert(0); idbassert(0);
throw std::logic_error("Row::getUintField(): bad length."); throw std::logic_error("Row::getUintField(): bad length.");
@ -730,8 +734,6 @@ inline uint64_t Row::getUintField(uint32_t colIndex) const
case 4: case 4:
return *((uint32_t*) &data[offsets[colIndex]]); return *((uint32_t*) &data[offsets[colIndex]]);
case 16:
std::cout << __FILE__<< ":" <<__LINE__ << " Fix for 16 Bytes ?" << std::endl;
case 8: case 8:
return *((uint64_t*) &data[offsets[colIndex]]); return *((uint64_t*) &data[offsets[colIndex]]);
@ -1281,6 +1283,85 @@ inline uint64_t Row::hash(uint32_t lastCol) const
return ret; return ret;
} }
inline bool Row::equals(const Row& r2, const std::vector<uint32_t>& keyCols) const
{
for (uint32_t i = 0; i < keyCols.size(); i++)
{
const uint32_t& col = keyCols[i];
cscDataType columnType = getColType(i);
if (!isLongString(col))
{
if (UNLIKELY(columnType == execplan::CalpontSystemCatalog::LONGDOUBLE))
{
if (getLongDoubleField(i) != r2.getLongDoubleField(i))
return false;
}
else if (UNLIKELY(execplan::isDecimal(columnType)))
{
if (getBinaryField<int128_t>(i) != r2.getBinaryField<int128_t>(i))
return false;
}
else if (getUintField(col) != r2.getUintField(col))
return false;
}
else
{
if (getStringLength(col) != r2.getStringLength(col))
return false;
if (memcmp(getStringPointer(col), r2.getStringPointer(col), getStringLength(col)))
return false;
}
}
return true;
}
inline bool Row::equals(const Row& r2, uint32_t lastCol) const
{
// This check fires with empty r2 only.
if (lastCol >= columnCount)
return true;
if (!useStringTable && !r2.useStringTable)
return !(memcmp(&data[offsets[0]], &r2.data[offsets[0]], offsets[lastCol + 1] - offsets[0]));
for (uint32_t i = 0; i <= lastCol; i++)
{
cscDataType columnType = getColType(i);
if (!isLongString(i))
{
if (UNLIKELY(getColType(i) == execplan::CalpontSystemCatalog::LONGDOUBLE))
{
if (getLongDoubleField(i) != r2.getLongDoubleField(i))
return false;
}
else if (UNLIKELY(execplan::isDecimal(columnType)))
{
if (getBinaryField<int128_t>(i) != r2.getBinaryField<int128_t>(i))
return false;
}
else if (getUintField(i) != r2.getUintField(i))
return false;
}
else
{
uint32_t len = getStringLength(i);
if (len != r2.getStringLength(i))
return false;
if (memcmp(getStringPointer(i), r2.getStringPointer(i), len))
return false;
}
}
return true;
}
inline bool Row::equals(const Row& r2) const inline bool Row::equals(const Row& r2) const
{ {
return equals(r2, columnCount - 1); return equals(r2, columnCount - 1);