1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2025-04-18 21:44:02 +03:00
mariadb-columnstore-engine/tests/rowgroup-tests.cpp
2025-03-27 22:12:48 +00:00

413 lines
13 KiB
C++

/* Copyright (C) 2020 MariaDB Corporation
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
#include <gtest/gtest.h> // googletest header file
#include <cstring>
#include <iostream>
#include <numeric>
#include "countingallocator.h"
#include "rowgroup.h"
#include "columnwidth.h"
#include "joblisttypes.h"
#include "dataconvert.h"
#define WIDE_DEC_PRECISION 38U
#define INITIAL_ROW_OFFSET 2
using CSCDataType = execplan::CalpontSystemCatalog::ColDataType;
using datatypes::TSInt128;
using RGFieldsType = std::vector<uint32_t>;
rowgroup::RowGroup setupRG(const std::vector<execplan::CalpontSystemCatalog::ColDataType>& cts,
const RGFieldsType& widths, const RGFieldsType& charsets)
{
std::vector<execplan::CalpontSystemCatalog::ColDataType> types = cts;
RGFieldsType offsets{2};
for (auto w : widths)
{
offsets.push_back(offsets.back() + w);
}
RGFieldsType roids(widths.size());
std::iota(roids.begin(), roids.end(), 3000);
RGFieldsType tkeys(widths.size());
std::fill(tkeys.begin(), tkeys.end(), 1);
RGFieldsType cscale(widths.size());
std::fill(cscale.begin(), cscale.end(), 0);
RGFieldsType precision(widths.size());
std::fill(precision.begin(), precision.end(), 20);
return rowgroup::RowGroup(roids.size(), // column count
offsets, // oldOffset
roids, // column oids
tkeys, // keys
types, // types
charsets, // charset numbers
cscale, // scale
precision, // precision
20, // sTableThreshold
true // useStringTable
);
}
class RowDecimalTest : public ::testing::Test
{
protected:
void SetUp() override
{
uint32_t precision = WIDE_DEC_PRECISION;
uint32_t oid = 3001;
std::vector<CSCDataType> types;
std::vector<decltype(precision)> precisionVec;
std::vector<uint32_t> roids, tkeys, cscale;
std::vector<uint32_t> widthVec;
std::vector<uint32_t> charSetNumVec;
types.push_back(execplan::CalpontSystemCatalog::DECIMAL);
types.push_back(execplan::CalpontSystemCatalog::UDECIMAL);
for (size_t i = 0; i <= 3; i++)
types.push_back(execplan::CalpontSystemCatalog::DECIMAL);
precisionVec.push_back(precision);
precisionVec.push_back(precision);
precisionVec.push_back(18);
precisionVec.push_back(9);
precisionVec.push_back(4);
precisionVec.push_back(2);
uint32_t offset = INITIAL_ROW_OFFSET;
offsets.push_back(offset);
for (size_t i = 0; i < types.size(); i++)
{
uint8_t width = utils::widthByPrecision(precisionVec[i]);
widthVec.push_back(width);
offset += width;
offsets.push_back(offset);
roids.push_back(oid + i);
tkeys.push_back(i + 1);
cscale.push_back(0);
charSetNumVec.push_back(8);
}
rowgroup::RowGroup inRG(roids.size(), // column count
offsets, // oldOffset
roids, // column oids
tkeys, // keys
types, // types
charSetNumVec, // charset numbers
cscale, // scale
precisionVec, // precision
20, // sTableThreshold
false // useStringTable
);
rg = rgOut = inRG;
rgD.reinit(rg);
rgDOut.reinit(rgOut);
rg.setData(&rgD);
rgOut.setData(&rgDOut);
rg.initRow(&r);
rg.initRow(&rOutMappingCheck);
rg.initRow(&rOut);
rg.initRow(&sameRow);
rg.initRow(&nonequiRow);
rowSize = r.getSize();
rg.getRow(0, &r);
int128_t nullValue = 0;
int128_t bigValue = 0;
datatypes::Decimal::setWideDecimalNullValue(nullValue);
bigValue = -static_cast<int128_t>(0xFFFFFFFF) * 0xFFFFFFFFFFFFFFFF;
sValueVector.push_back(nullValue);
sValueVector.push_back(-42);
sValueVector.push_back(bigValue);
sValueVector.push_back(0);
sValueVector.push_back(nullValue - 1);
anotherValueVector.push_back(nullValue);
anotherValueVector.push_back(42);
anotherValueVector.push_back(bigValue);
anotherValueVector.push_back(0);
anotherValueVector.push_back(nullValue - 1);
s8ValueVector.push_back(joblist::TINYINTNULL);
s8ValueVector.push_back(-0x79);
s8ValueVector.push_back(0);
s8ValueVector.push_back(0x81);
s8ValueVector.push_back(joblist::TINYINTNULL - 1);
s16ValueVector.push_back(joblist::SMALLINTNULL);
s16ValueVector.push_back(-0x79);
s16ValueVector.push_back(0);
s16ValueVector.push_back(0x81);
s16ValueVector.push_back(joblist::SMALLINTNULL - 1);
s32ValueVector.push_back(joblist::INTNULL);
s32ValueVector.push_back(-0x79);
s32ValueVector.push_back(0);
s32ValueVector.push_back(0x81);
s32ValueVector.push_back(joblist::INTNULL - 1);
s64ValueVector.push_back(joblist::BIGINTNULL);
s64ValueVector.push_back(-0x79);
s64ValueVector.push_back(0);
s64ValueVector.push_back(0x81);
s64ValueVector.push_back(joblist::BIGINTNULL - 1);
for (size_t i = 0; i < sValueVector.size(); i++)
{
r.setBinaryField_offset(&sValueVector[i], sizeof(sValueVector[0]), offsets[0]);
r.setBinaryField_offset(&anotherValueVector[i], sizeof(anotherValueVector[0]), offsets[1]);
r.setIntField(s64ValueVector[i], 2);
r.setIntField(s32ValueVector[i], 3);
r.setIntField(s16ValueVector[i], 4);
r.setIntField(s8ValueVector[i], 5);
r.nextRow();
}
rowCount = sValueVector.size();
}
// void TearDown() override {}
rowgroup::Row r, rOut, sameRow, nonequiRow;
rowgroup::Row rOutMappingCheck;
rowgroup::RowGroup rg, rgOut;
rowgroup::RGData rgD, rgDOut;
uint32_t rowSize;
size_t rowCount;
std::vector<int128_t> sValueVector;
std::vector<int128_t> anotherValueVector;
std::vector<int64_t> s8ValueVector;
std::vector<int64_t> s16ValueVector;
std::vector<int64_t> s32ValueVector;
std::vector<int64_t> s64ValueVector;
std::vector<uint32_t> offsets;
};
TEST_F(RowDecimalTest, NonNullValueCheck)
{
rg.getRow(1, &r);
for (size_t i = 1; i <= sValueVector.size(); i++)
{
EXPECT_FALSE(r.isNullValue(0));
EXPECT_FALSE(r.isNullValue(1));
EXPECT_FALSE(r.isNullValue(2));
EXPECT_FALSE(r.isNullValue(3));
EXPECT_FALSE(r.isNullValue(4));
EXPECT_FALSE(r.isNullValue(5));
r.nextRow();
}
}
TEST_F(RowDecimalTest, InitToNullAndIsNullValueCheck)
{
rg.getRow(0, &r);
r.initToNull();
EXPECT_TRUE(r.isNullValue(0));
EXPECT_TRUE(r.isNullValue(1));
EXPECT_TRUE(r.isNullValue(2));
EXPECT_TRUE(r.isNullValue(3));
EXPECT_TRUE(r.isNullValue(4));
EXPECT_TRUE(r.isNullValue(5));
}
TEST_F(RowDecimalTest, GetBinaryFieldCheck)
{
rg.getRow(0, &r);
TSInt128 a128Value;
TSInt128 s128Value;
for (size_t i = 0; i < sValueVector.size(); i++)
{
s128Value = r.getTSInt128Field(0);
EXPECT_EQ(sValueVector[i], s128Value.getValue());
a128Value = r.getTSInt128Field(1);
EXPECT_EQ(anotherValueVector[i], a128Value.getValue());
// EXPECT_EQ(s64ValueVector[i], r.getIntField(2));
// EXPECT_EQ(s32ValueVector[i],r.getIntField(3));
// EXPECT_EQ(r.getIntField(4),s16ValueVector[i]);
// EXPECT_EQ(r.getIntField(5),s8ValueVector[i]);
r.nextRow();
}
}
TEST_F(RowDecimalTest, ToStringCheck)
{
std::vector<std::string> exemplarVector;
exemplarVector.push_back(std::string("[ 0]: 0: NULL NULL NULL NULL NULL NULL "));
exemplarVector.push_back(std::string("[ 0]: 0: -42 42 -121 -121 -121 -121 "));
exemplarVector.push_back(
std::string("[ 0]: 0: -79228162495817593515539431425 -79228162495817593515539431425 0 0 0 0 "));
exemplarVector.push_back(std::string("[ 0]: 0: 0 0 129 129 129 -127 "));
exemplarVector.push_back(
std::string("[ 0]: 0: 170141183460469231731687303715884105727 "
"170141183460469231731687303715884105727 9223372036854775807 2147483647 32767 127 "));
rg.getRow(0, &r);
r.initToNull();
for (auto& el : exemplarVector)
{
EXPECT_EQ(el, r.toString());
r.nextRow();
}
}
TEST_F(RowDecimalTest, ToCSVCheck)
{
}
TEST_F(RowDecimalTest, ApplyMappingCheck)
{
int mapping[] = {0, 1, -1, -1, -1, -1};
rg.getRow(1, &r);
rg.getRow(2, &rOutMappingCheck);
auto s128Value = rOutMappingCheck.getTSInt128Field(0);
auto a128Value = rOutMappingCheck.getTSInt128Field(1);
EXPECT_NE(s128Value.getValue(), sValueVector[1]);
EXPECT_NE(a128Value.getValue(), anotherValueVector[1]);
applyMapping(mapping, r, &rOutMappingCheck);
s128Value = rOutMappingCheck.getTSInt128Field(0);
a128Value = rOutMappingCheck.getTSInt128Field(1);
EXPECT_EQ(sValueVector[1], s128Value.getValue());
EXPECT_EQ(anotherValueVector[1], a128Value.getValue());
}
TEST_F(RowDecimalTest, CopyBinaryFieldCheck)
{
int128_t constVal = 1;
TSInt128 col1Out, col1In;
TSInt128 col2Out, col2In;
rgOut.getRow(0, &rOut);
for (size_t i = 0; i < sValueVector.size(); i++)
{
rOut.setBinaryField_offset(&constVal, 16, offsets[0]);
rOut.setBinaryField_offset(&constVal, 16, offsets[1]);
rOut.nextRow();
}
rgOut.initRow(&rOut);
rgOut.getRow(0, &rOut);
rg.getRow(0, &r);
for (size_t i = 0; i < sValueVector.size(); i++)
{
col1In = r.getTSInt128Field(0);
col1Out = rOut.getTSInt128Field(0);
col2In = r.getTSInt128Field(1);
col2Out = rOut.getTSInt128Field(1);
EXPECT_NE(col1In, col1Out);
EXPECT_NE(col2In, col2Out);
r.copyBinaryField(rOut, 0, 0);
r.copyBinaryField(rOut, 1, 1);
col1Out = rOut.getTSInt128Field(0);
col2Out = rOut.getTSInt128Field(1);
EXPECT_EQ(col1In.getValue(), col1Out.getValue());
EXPECT_EQ(col2In.getValue(), col2Out.getValue());
r.nextRow();
rOut.nextRow();
}
}
TEST_F(RowDecimalTest, RowEqualsCheck)
{
rg.getRow(0, &r);
rg.getRow(0, &sameRow);
rg.getRow(1, &nonequiRow);
for (size_t i = 0; i < sValueVector.size(); i++)
{
EXPECT_TRUE(r.equals(sameRow));
if (i < sValueVector.size() - 1)
{
EXPECT_FALSE(r.equals(nonequiRow));
}
r.nextRow();
sameRow.nextRow();
if (i < sValueVector.size() - 1)
{
nonequiRow.nextRow();
}
}
}
static const constexpr int64_t MemoryAllowance = 10 * 1024 * 1024;
class RGDataTest : public ::testing::Test
{
protected:
RGDataTest()
: allocatedMemory(MemoryAllowance) {}
void SetUp() override
{
rg = setupRG({execplan::CalpontSystemCatalog::VARCHAR, execplan::CalpontSystemCatalog::UDECIMAL,
execplan::CalpontSystemCatalog::DECIMAL, execplan::CalpontSystemCatalog::DECIMAL,
execplan::CalpontSystemCatalog::DECIMAL, execplan::CalpontSystemCatalog::DECIMAL},
{65536, 16, 8, 4, 2, 1}, {8, 8, 8, 8, 8, 8});
}
// void TearDown() override {}
rowgroup::Row r;
rowgroup::RowGroup rg;
rowgroup::RGData rgD;
std::atomic<int64_t> allocatedMemory{MemoryAllowance};
};
// bool useStringTable = true;
TEST_F(RGDataTest, AllocData)
{
allocators::CountingAllocator<rowgroup::RGDataBufType> alloc(&allocatedMemory, MemoryAllowance / 100, MemoryAllowance / 10000);
rgD = rowgroup::RGData(rg, alloc);
rg.setData(&rgD);
rg.initRow(&r);
rg.getRow(0, &r);
auto currentAllocation = allocatedMemory.load();
EXPECT_LE(currentAllocation, MemoryAllowance - rg.getMaxDataSize());
r.setStringField(utils::ConstString{"testaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, 0);
EXPECT_LE(allocatedMemory.load(), currentAllocation);
currentAllocation = allocatedMemory.load();
r.nextRow();
r.setStringField(utils::ConstString{"testaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, 0);
EXPECT_EQ(allocatedMemory.load(), currentAllocation);
currentAllocation = allocatedMemory.load();
r.nextRow();
std::string longString(64 * 1024 + 1000, 'a');
auto cs = utils::ConstString(longString);
r.setStringField(cs, 0);
EXPECT_LE(allocatedMemory.load(), currentAllocation);
rgD = rowgroup::RGData(rg);
EXPECT_EQ(allocatedMemory.load(), MemoryAllowance);
// reinit
}