1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2025-07-05 15:41:14 +03:00

MCOL-641 Addition now works for DECIMAL columns with precision > 18.

This commit is contained in:
drrtuy
2020-01-26 11:07:45 +03:00
committed by Roman Nozdrin
parent 54c152d6c8
commit 98213c0094
11 changed files with 175 additions and 14 deletions

View File

@ -43,6 +43,7 @@ namespace execplan
class ArithmeticOperator : public Operator class ArithmeticOperator : public Operator
{ {
using cscType = execplan::CalpontSystemCatalog::ColType;
public: public:
ArithmeticOperator(); ArithmeticOperator();
@ -200,6 +201,7 @@ private:
template <typename result_t> template <typename result_t>
inline result_t execute(result_t op1, result_t op2, bool& isNull); inline result_t execute(result_t op1, result_t op2, bool& isNull);
inline void execute(IDB_Decimal& result, IDB_Decimal op1, IDB_Decimal op2, bool& isNull); inline void execute(IDB_Decimal& result, IDB_Decimal op1, IDB_Decimal op2, bool& isNull);
inline void execute(IDB_Decimal& result, IDB_Decimal op1, IDB_Decimal op2, bool& isNull, cscType& resultCscType);
std::string fTimeZone; std::string fTimeZone;
}; };
@ -236,12 +238,11 @@ inline void ArithmeticOperator::evaluate(rowgroup::Row& row, bool& isNull, Parse
case execplan::CalpontSystemCatalog::LONGDOUBLE: case execplan::CalpontSystemCatalog::LONGDOUBLE:
fResult.longDoubleVal = execute(lop->getLongDoubleVal(row, isNull), rop->getLongDoubleVal(row, isNull), isNull); fResult.longDoubleVal = execute(lop->getLongDoubleVal(row, isNull), rop->getLongDoubleVal(row, isNull), isNull);
break; break;
// WIP MCOL-641
case execplan::CalpontSystemCatalog::DECIMAL: case execplan::CalpontSystemCatalog::DECIMAL:
case execplan::CalpontSystemCatalog::UDECIMAL: case execplan::CalpontSystemCatalog::UDECIMAL:
execute (fResult.decimalVal, lop->getDecimalVal(row, isNull), rop->getDecimalVal(row, isNull), isNull); execute(fResult.decimalVal, lop->getDecimalVal(row, isNull), rop->getDecimalVal(row, isNull), isNull, fOperationType);
break; break;
default: default:
{ {
std::ostringstream oss; std::ostringstream oss;
@ -282,11 +283,21 @@ inline result_t ArithmeticOperator::execute(result_t op1, result_t op2, bool& is
} }
} }
inline void ArithmeticOperator::execute(IDB_Decimal& result, IDB_Decimal op1, IDB_Decimal op2, bool& isNull) inline void ArithmeticOperator::execute(IDB_Decimal& result, IDB_Decimal op1, IDB_Decimal op2, bool& isNull, cscType& resultCscType)
{ {
switch (fOp) switch (fOp)
{ {
case OP_ADD: case OP_ADD:
if (resultCscType.precision > 18)
{
// WIP make this a separate function w and w/o overflow check
if (resultCscType.colDataType == execplan::CalpontSystemCatalog::DECIMAL)
result.__v.__s128 = op1.__v.__s128 + op2.__v.__s128;
else
result.__v.__u128 = op1.__v.__u128 + op2.__v.__u128;
break;
}
if (result.scale == op1.scale && result.scale == op2.scale) if (result.scale == op1.scale && result.scale == op2.scale)
{ {
result.value = op1.value + op2.value; result.value = op1.value + op2.value;

View File

@ -49,6 +49,7 @@ ReturnedColumn::ReturnedColumn(): fReturnAll (false),
fColPosition(-1), fColPosition(-1),
fHasAggregate(false), fHasAggregate(false),
fInputIndex(-1), fInputIndex(-1),
fInputOffset(-1),
fOutputIndex(-1), fOutputIndex(-1),
fExpressionId ((uint32_t) - 1) fExpressionId ((uint32_t) - 1)
{ {
@ -69,6 +70,7 @@ ReturnedColumn::ReturnedColumn(const string& sql):
fHasAggregate(false), fHasAggregate(false),
fData(sql), fData(sql),
fInputIndex(-1), fInputIndex(-1),
fInputOffset(-1),
fOutputIndex(-1), fOutputIndex(-1),
fExpressionId ((uint32_t) - 1) fExpressionId ((uint32_t) - 1)
{ {
@ -88,6 +90,7 @@ ReturnedColumn::ReturnedColumn(const uint32_t sessionID, const bool returnAll):
fColPosition(-1), fColPosition(-1),
fHasAggregate(false), fHasAggregate(false),
fInputIndex(-1), fInputIndex(-1),
fInputOffset(-1),
fOutputIndex(-1), fOutputIndex(-1),
fExpressionId ((uint32_t) - 1) fExpressionId ((uint32_t) - 1)
{ {
@ -109,6 +112,7 @@ ReturnedColumn::ReturnedColumn(const ReturnedColumn& rhs, const uint32_t session
fHasAggregate(rhs.fHasAggregate), fHasAggregate(rhs.fHasAggregate),
fData(rhs.fData), fData(rhs.fData),
fInputIndex(rhs.fInputIndex), fInputIndex(rhs.fInputIndex),
fInputOffset(rhs.fInputOffset),
fOutputIndex(rhs.fOutputIndex), fOutputIndex(rhs.fOutputIndex),
fExpressionId (rhs.fExpressionId) fExpressionId (rhs.fExpressionId)
{ {
@ -141,6 +145,7 @@ void ReturnedColumn::serialize(messageqcpp::ByteStream& b) const
b << (uint64_t)fColSource; b << (uint64_t)fColSource;
b << (int64_t)fColPosition; b << (int64_t)fColPosition;
b << (uint32_t)fInputIndex; b << (uint32_t)fInputIndex;
b << (uint32_t)fInputOffset;
b << (uint32_t)fOutputIndex; b << (uint32_t)fOutputIndex;
b << (int32_t)fSequence; b << (int32_t)fSequence;
b << (uint8_t)fReturnAll; b << (uint8_t)fReturnAll;
@ -163,6 +168,7 @@ void ReturnedColumn::unserialize(messageqcpp::ByteStream& b)
b >> (uint64_t&)fColSource; b >> (uint64_t&)fColSource;
b >> (int64_t&)fColPosition; b >> (int64_t&)fColPosition;
b >> (uint32_t&)fInputIndex; b >> (uint32_t&)fInputIndex;
b >> (uint32_t&)fInputOffset;
b >> (uint32_t&)fOutputIndex; b >> (uint32_t&)fOutputIndex;
b >> (int32_t&)fSequence; b >> (int32_t&)fSequence;
b >> (uint8_t&)fReturnAll; b >> (uint8_t&)fReturnAll;

View File

@ -374,6 +374,7 @@ public:
protected: protected:
std::string fErrMsg; /// error occured in evaluation std::string fErrMsg; /// error occured in evaluation
uint32_t fInputIndex; /// index to the input rowgroup uint32_t fInputIndex; /// index to the input rowgroup
uint32_t fInputOffset; /// index to the input rowgroup
uint32_t fOutputIndex; /// index to the output rowgroup uint32_t fOutputIndex; /// index to the output rowgroup
uint32_t fExpressionId; /// unique id for this expression uint32_t fExpressionId; /// unique id for this expression
}; };

View File

@ -51,6 +51,7 @@ using namespace joblist;
#include "aggregatecolumn.h" #include "aggregatecolumn.h"
#include "constantfilter.h" #include "constantfilter.h"
#include "../../utils/windowfunction/windowfunction.h" #include "../../utils/windowfunction/windowfunction.h"
#include "utils/common/branchpred.h"
namespace execplan namespace execplan
{ {
@ -482,6 +483,7 @@ void SimpleColumn::setDerivedTable()
// @todo make aggregate filter to having clause. not optimize it for now // @todo make aggregate filter to having clause. not optimize it for now
if (fDerivedRefCol && if (fDerivedRefCol &&
// WIP replace with typeid()
(dynamic_cast<AggregateColumn*>(fDerivedRefCol) || (dynamic_cast<AggregateColumn*>(fDerivedRefCol) ||
dynamic_cast<WindowFunctionColumn*>(fDerivedRefCol))) dynamic_cast<WindowFunctionColumn*>(fDerivedRefCol)))
fDerivedTable = ""; fDerivedTable = "";
@ -500,6 +502,12 @@ bool SimpleColumn::singleTable(CalpontSystemCatalog::TableAliasName& tan)
// @todo move to inline // @todo move to inline
void SimpleColumn::evaluate(Row& row, bool& isNull) void SimpleColumn::evaluate(Row& row, bool& isNull)
{ {
// WIP Move this block into an appropriate place
if (UNLIKELY(fInputOffset == -1))
{
fInputOffset = row.getOffset(fInputIndex);
}
bool isNull2 = row.isNullValue(fInputIndex); bool isNull2 = row.isNullValue(fInputIndex);
if (isNull2) if (isNull2)
@ -627,7 +635,16 @@ void SimpleColumn::evaluate(Row& row, bool& isNull)
{ {
case 16: case 16:
{ {
fResult.decimalVal.value = row.getIntField<16>(fInputIndex); if (fResultType.colDataType == CalpontSystemCatalog::UDECIMAL)
{
fResult.decimalVal.__v.__u128 =
*row.getBinaryField_offset<decltype(fResult.decimalVal.__v.__u128)>(fInputOffset);
}
else
{
fResult.decimalVal.__v.__s128 =
*row.getBinaryField_offset<decltype(fResult.decimalVal.__v.__s128)>(fInputOffset);
}
fResult.decimalVal.scale = (unsigned)fResultType.scale; fResult.decimalVal.scale = (unsigned)fResultType.scale;
break; break;
} }

View File

@ -36,6 +36,7 @@
#include "exceptclasses.h" #include "exceptclasses.h"
#include "dataconvert.h" #include "dataconvert.h"
using int128_t = __int128;
using uint128_t = unsigned __int128; using uint128_t = unsigned __int128;
namespace messageqcpp namespace messageqcpp
@ -63,11 +64,17 @@ typedef execplan::CalpontSystemCatalog::ColType Type;
*/ */
struct IDB_Decimal struct IDB_Decimal
{ {
IDB_Decimal(): val(0), value(0), scale(0), precision(0) {} IDB_Decimal(): value(0), scale(0), precision(0)
{
__v.__s128 = 0;
}
IDB_Decimal(int64_t val, int8_t s, uint8_t p) : IDB_Decimal(int64_t val, int8_t s, uint8_t p) :
value (val), value (val),
scale(s), scale(s),
precision(p) {} precision(p)
{
__v.__s128 = 0;
}
int decimalComp(const IDB_Decimal& d) const int decimalComp(const IDB_Decimal& d) const
{ {
@ -151,7 +158,11 @@ struct IDB_Decimal
return (decimalComp(rhs) != 0); return (decimalComp(rhs) != 0);
} }
uint128_t val; union {
uint128_t __u128;
int128_t __s128;
int64_t __s64[2];
} __v;
int64_t value; int64_t value;
int8_t scale; // 0~38 int8_t scale; // 0~38
uint8_t precision; // 1~38 uint8_t precision; // 1~38

View File

@ -1726,7 +1726,7 @@ void BatchPrimitiveProcessor::execute()
if (fe2->evaluate(&fe2In)) if (fe2->evaluate(&fe2In))
{ {
applyMapping(fe2Mapping, fe2In, &fe2Out); applyMapping(fe2Mapping, fe2In, &fe2Out);
//cerr << " passed. output row: " << fe2Out.toString() << endl; cerr << " passed. output row: " << fe2Out.toString() << endl;
fe2Out.setRid (fe2In.getRelRid()); fe2Out.setRid (fe2In.getRelRid());
fe2Output.incRowCount(); fe2Output.incRowCount();
fe2Out.nextRow(); fe2Out.nextRow();

View File

@ -593,7 +593,7 @@ void ColumnCommand::prep(int8_t outputType, bool absRids)
break; break;
case 16: case 16:
// WIP MCOL-641 // WIP MCOL-641
cout << __FILE__<< ":" <<__LINE__ << " Fix shift and mask for 16 Bytes ?"<< endl; cout << __FILE__<< ":" <<__LINE__ << " Set shift and mask for 16 Bytes"<< endl;
shift = 1; shift = 1;
mask = 0x01; mask = 0x01;
break; break;

View File

@ -1198,7 +1198,7 @@ void DataConvert::toString(T* dec, char *p, size_t buflen)
char* original_p = p; char* original_p = p;
int printed_chars = 0; int printed_chars = 0;
// WIP replace snprintf with streams // WIP replace snprintf with streams
if (high_pod->lo != 0) { if (high_pod->lo != 0) {
printed_chars = snprintf(p, div_log+1, "%lu", high_pod->lo); printed_chars = snprintf(p, div_log+1, "%lu", high_pod->lo);
p += printed_chars; p += printed_chars;

View File

@ -472,10 +472,26 @@ void FuncExp::evaluate(rowgroup::Row& row, std::vector<execplan::SRCP>& expressi
{ {
IDB_Decimal val = expression[i]->getDecimalVal(row, isNull); IDB_Decimal val = expression[i]->getDecimalVal(row, isNull);
if (isNull) // WIP
row.setIntField<8>(BIGINTNULL, expression[i]->outputIndex()); if (expression[i]->resultType().precision > 18)
{
// WIP make this a separate function w and w/o overflow check
if (expression[i]->resultType().colDataType == execplan::CalpontSystemCatalog::DECIMAL)
row.setBinaryField(reinterpret_cast<uint8_t*>(&val.__v.__s128),
expression[i]->resultType().colWidth,
row.getOffset(expression[i]->outputIndex()));
else
row.setBinaryField(reinterpret_cast<uint8_t*>(&val.__v.__u128),
expression[i]->resultType().colWidth,
row.getOffset(expression[i]->outputIndex()));
}
else else
row.setIntField<8>(val.value, expression[i]->outputIndex()); {
if (isNull)
row.setIntField<8>(BIGINTNULL, expression[i]->outputIndex());
else
row.setIntField<8>(val.value, expression[i]->outputIndex());
}
break; break;
} }

View File

@ -42,12 +42,15 @@ using namespace execplan;
#include "nullvaluemanip.h" #include "nullvaluemanip.h"
#include "rowgroup.h" #include "rowgroup.h"
#include "dataconvert.h"
#include "collation.h" #include "collation.h"
namespace rowgroup namespace rowgroup
{ {
using cscType = execplan::CalpontSystemCatalog::ColDataType;
StringStore::StringStore() : empty(true), fUseStoreStringMutex(false) { } StringStore::StringStore() : empty(true), fUseStoreStringMutex(false) { }
StringStore::StringStore(const StringStore&) StringStore::StringStore(const StringStore&)
@ -630,6 +633,19 @@ string Row::toString() const
} }
case CalpontSystemCatalog::BINARY: case CalpontSystemCatalog::BINARY:
std::cout << __FILE__<< ":" <<__LINE__ << " Fix for 16 Bytes ?" << std::endl; std::cout << __FILE__<< ":" <<__LINE__ << " Fix for 16 Bytes ?" << std::endl;
break;
// WIP
case CalpontSystemCatalog::DECIMAL:
if (precision[i] > 18)
{
char *buf = (char*)alloca(precision[i] + 3);
// empty the buffer
dataconvert::DataConvert::toString<uint128_t>(getBinaryField<uint128_t>(i),
buf, precision[i]+3);
os << buf << " ";
break;
}
// fallback if the precision < 18
default: default:
os << getIntField(i) << " "; os << getIntField(i) << " ";
break; break;
@ -866,6 +882,79 @@ void Row::initToNull()
} }
} }
template<typename T, uint8_t cscT, uint32_t width>
inline bool Row::isNullValue_offset(uint32_t offset) const
{
ostringstream os;
os << "Row::isNullValue(): got bad column type at offset(";
os << offset;
os << "). Width=";
os << width << endl;
throw logic_error(os.str());
}
/*
// WIP how to make if that enables explicit template for two cscTypes?
// Method template resolution could impose some perf degradation
template<int64_t,(uint8_t)CalpontSystemCatalog::DECIMAL,16>
inline bool Row::isNullValue_offset(uint32_t offset) const
{
return (*reinterpret_cast<int64_t*>(&data[offset]) == static_cast<int64_t>(joblist::BIGINTNULL));
}
template<int64_t,CalpontSystemCatalog::UDECIMAL,16>
inline bool Row::isNullValue_offset(uint32_t offset) const
{
return (*reinterpret_cast<int64_t*>(&data[offset]) == static_cast<int64_t>(joblist::BIGINTNULL));
}
template<int64_t,CalpontSystemCatalog::DECIMAL,8>
inline bool Row::isNullValue_offset(uint32_t offset) const
{
return (*reinterpret_cast<int64_t*>(&data[offset]) == static_cast<int64_t>(joblist::BIGINTNULL));
}
template<int64_t,CalpontSystemCatalog::UDECIMAL,8>
inline bool Row::isNullValue_offset(uint32_t offset) const
{
return (*reinterpret_cast<int64_t*>(&data[offset]) == static_cast<int64_t>(joblist::BIGINTNULL));
}
template<uint8_t,CalpontSystemCatalog::UDECIMAL,1>
inline bool Row::isNullValue_offset(uint32_t offset) const
{
return (data[offset] == joblist::TINYINTNULL);
}
template<uint8_t,CalpontSystemCatalog::DECIMAL,1>
inline bool Row::isNullValue_offset(uint32_t offset) const
{
return (data[offset] == joblist::TINYINTNULL);
}
template<int16_t,CalpontSystemCatalog::UDECIMAL,2>
inline bool Row::isNullValue_offset(uint32_t offset) const
{
return (*reinterpret_cast<int16_t*>(&data[offset]) == static_cast<int16_t>(joblist::SMALLINTNULL));
}
template<int16_t,CalpontSystemCatalog::UDECIMAL,2>
inline bool Row::isNullValue_offset(uint32_t offset) const
{
return (*reinterpret_cast<int16_t*>(&data[offset]) == static_cast<int16_t>(joblist::SMALLINTNULL));
}
template<int32_t,CalpontSystemCatalog::UDECIMAL,4>
inline bool Row::isNullValue_offset(uint32_t offset) const
{
return (*reinterpret_cast<int32_t*>(&data[offset]) == static_cast<int32_t>(joblist::INTNULL));
}
template<int32_t,CalpontSystemCatalog::DECIMAL,4>
inline bool Row::isNullValue_offset(uint32_t offset) const
{
return (*reinterpret_cast<int32_t*>(&data[offset]) == static_cast<int32_t>(joblist::INTNULL));
}
*/
bool Row::isNullValue(uint32_t colIndex) const bool Row::isNullValue(uint32_t colIndex) const
{ {
switch (types[colIndex]) switch (types[colIndex])
@ -1533,6 +1622,13 @@ void applyMapping(const int* mapping, const Row& in, Row* out)
out->setUintField(in.getUintField(i), mapping[i]); out->setUintField(in.getUintField(i), mapping[i]);
else if (UNLIKELY(in.getColTypes()[i] == execplan::CalpontSystemCatalog::LONGDOUBLE)) else if (UNLIKELY(in.getColTypes()[i] == execplan::CalpontSystemCatalog::LONGDOUBLE))
out->setLongDoubleField(in.getLongDoubleField(i), mapping[i]); out->setLongDoubleField(in.getLongDoubleField(i), mapping[i]);
// WIP this doesn't look right b/c we can pushdown colType
// Migrate to offset based methods here
// code precision 2 width convertor
else if (UNLIKELY(in.getColTypes()[i] == execplan::CalpontSystemCatalog::DECIMAL &&
in.getColumnWidth(i) == 16))
out->setBinaryField(in.getBinaryField<uint8_t>(i), 16,
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

@ -69,6 +69,7 @@ typedef const struct charset_info_st CHARSET_INFO;
namespace rowgroup namespace rowgroup
{ {
//using cscType = execplan::CalpontSystemCatalog::ColDataType;
const int16_t rgCommonSize = 8192; const int16_t rgCommonSize = 8192;
/* /*
@ -447,6 +448,8 @@ public:
uint64_t getNullValue(uint32_t colIndex) const; uint64_t getNullValue(uint32_t colIndex) const;
bool isNullValue(uint32_t colIndex) const; bool isNullValue(uint32_t colIndex) const;
template<typename T, uint8_t cscT, uint32_t len>
inline bool isNullValue_offset(uint32_t offset) const;
// when NULLs are pulled out via getIntField(), they come out with these values. // when NULLs are pulled out via getIntField(), they come out with these values.
// Ex: the 1-byte int null value is 0x80. When it gets cast to an int64_t // Ex: the 1-byte int null value is 0x80. When it gets cast to an int64_t