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

MCOL-641 Initial version of Math operations for wide decimal.

This commit is contained in:
Roman Nozdrin
2020-03-12 19:39:10 +00:00
parent 62d0c82d75
commit b09f3088ca
22 changed files with 1323 additions and 213 deletions

View File

@ -18,7 +18,6 @@
#ifndef UTILS_COLWIDTH_H
#define UTILS_COLWIDTH_H
#include "calpontsystemcatalog.h"
#include "branchpred.h"
namespace utils
@ -36,13 +35,6 @@ namespace utils
return width <= MAXLEGACYWIDTH;
}
inline bool isWideDecimalType(const execplan::CalpontSystemCatalog::ColType& ct)
{
return ((ct.colDataType == execplan::CalpontSystemCatalog::DECIMAL ||
ct.colDataType == execplan::CalpontSystemCatalog::UDECIMAL) &&
ct.colWidth == MAXCOLUMNWIDTH);
}
/** @brief Map a DECIMAL precision to data width in bytes */
inline uint8_t widthByPrecision(unsigned p)
{

View File

@ -80,9 +80,7 @@ namespace utils
inline void int128Min(int128_t& val)
{
uint64_t* ptr = reinterpret_cast<uint64_t*>(&val);
ptr[0] = 0;
ptr[1] = 0x8000000000000000;
val = int128_t(0x8000000000000000LL) << 64;
}
inline void uint128Max(uint128_t& val)

View File

@ -102,30 +102,6 @@ const string columnstore_big_precision[20] =
"99999999999999999999999999999999999999"
};
const uint64_t columnstore_pow_10[20] =
{
1ULL,
10ULL,
100ULL,
1000ULL,
10000ULL,
100000ULL,
1000000ULL,
10000000ULL,
100000000ULL,
1000000000ULL,
10000000000ULL,
100000000000ULL,
1000000000000ULL,
10000000000000ULL,
100000000000000ULL,
1000000000000000ULL,
10000000000000000ULL,
100000000000000000ULL,
1000000000000000000ULL,
10000000000000000000ULL
};
template <class T>
bool from_string(T& t, const std::string& s, std::ios_base & (*f)(std::ios_base&))
{
@ -1257,33 +1233,30 @@ size_t DataConvert::writeIntPart(int128_t* dec,
{
int128_t intPart = *dec;
int128_t high = 0, mid = 0, low = 0;
uint64_t div = 10000000000000000000ULL;
uint64_t maxUint64divisor = 10000000000000000000ULL;
if (scale)
{
const uint8_t maxPowOf10 =
(sizeof(columnstore_pow_10) / sizeof(columnstore_pow_10[0])) - 1;
// Assuming scale = [0, 56]
switch (scale / maxPowOf10)
switch (scale / datatypes::maxPowOf10)
{
case 2: // scale = [38, 56]
intPart /= columnstore_pow_10[maxPowOf10];
intPart /= columnstore_pow_10[maxPowOf10];
intPart /= datatypes::mcs_pow_10[datatypes::maxPowOf10];
intPart /= datatypes::mcs_pow_10[datatypes::maxPowOf10];
low = intPart;
break;
case 1: // scale = [19, 37]
intPart /= columnstore_pow_10[maxPowOf10];
intPart /= columnstore_pow_10[scale % maxPowOf10];
low = intPart % div;
mid = intPart / div;
intPart /= datatypes::mcs_pow_10[datatypes::maxPowOf10];
intPart /= datatypes::mcs_pow_10[scale % datatypes::maxPowOf10];
low = intPart % maxUint64divisor;
mid = intPart / maxUint64divisor;
break;
case 0: // scale = [0, 18]
intPart /= columnstore_pow_10[scale % maxPowOf10];
low = intPart % div;
intPart /= div;
mid = intPart % div;
high = intPart / div;
intPart /= datatypes::mcs_pow_10[scale % datatypes::maxPowOf10];
low = intPart % maxUint64divisor;
intPart /= maxUint64divisor;
mid = intPart % maxUint64divisor;
high = intPart / maxUint64divisor;
break;
default:
throw QueryDataExcept("writeIntPart() bad scale", formatErr);
@ -1291,10 +1264,10 @@ size_t DataConvert::writeIntPart(int128_t* dec,
}
else
{
low = intPart % div;
intPart /= div;
mid = intPart % div;
high = intPart / div;
low = intPart % maxUint64divisor;
intPart /= maxUint64divisor;
mid = intPart % maxUint64divisor;
high = intPart / maxUint64divisor;
}
// pod[0] is low 8 bytes, pod[1] is high 8 bytes
@ -1337,19 +1310,16 @@ size_t DataConvert::writeFractionalPart(int128_t* dec,
{
int128_t scaleDivisor = 1;
const uint8_t maxPowOf10 =
(sizeof(columnstore_pow_10) / sizeof(columnstore_pow_10[0])) - 1;
switch (scale / maxPowOf10)
switch (scale / datatypes::maxPowOf10)
{
case 2:
scaleDivisor *= columnstore_pow_10[maxPowOf10];
scaleDivisor *= columnstore_pow_10[maxPowOf10];
scaleDivisor *= datatypes::mcs_pow_10[datatypes::maxPowOf10];
scaleDivisor *= datatypes::mcs_pow_10[datatypes::maxPowOf10];
break;
case 1:
scaleDivisor *= columnstore_pow_10[maxPowOf10];
scaleDivisor *= datatypes::mcs_pow_10[datatypes::maxPowOf10];
case 0:
scaleDivisor *= columnstore_pow_10[scale % maxPowOf10];
scaleDivisor *= datatypes::mcs_pow_10[scale % datatypes::maxPowOf10];
}
int128_t fractionalPart = *dec % scaleDivisor;

View File

@ -42,6 +42,8 @@ using namespace joblist;
#include "../udfsdk/udfsdk.h"
#endif
#include "mcs_decimal.h"
namespace funcexp
{
@ -471,13 +473,22 @@ void FuncExp::evaluate(rowgroup::Row& row, std::vector<execplan::SRCP>& expressi
case CalpontSystemCatalog::UDECIMAL:
{
IDB_Decimal val = expression[i]->getDecimalVal(row, isNull);
// WIP check for null and overflow here.
if (expression[i]->resultType().colWidth == 16)
if (expression[i]->resultType().colWidth
== datatypes::MAXDECIMALWIDTH)
{
row.setBinaryField_offset(&val.s128Value,
expression[i]->resultType().colWidth,
row.getOffset(expression[i]->outputIndex()));
if (isNull)
{
row.setBinaryField_offset(
const_cast<int128_t*>(&datatypes::Decimal128Null),
expression[i]->resultType().colWidth,
row.getOffset(expression[i]->outputIndex()));
}
else
{
row.setBinaryField_offset(&val.s128Value,
expression[i]->resultType().colWidth,
row.getOffset(expression[i]->outputIndex()));
}
}
else
{

View File

@ -187,6 +187,16 @@ public:
std::runtime_error(msg) { }
};
/** @brief Exception for F&E framework to throw on op overflow
* Invalid Operation Exception
*/
class OperationOverflowExcept : public std::runtime_error
{
public:
/** Takes a character string describing the error. */
OperationOverflowExcept(const std::string& msg) :
std::runtime_error(msg) { }
};
/** @brief specific error exception class for getSysData in Calpontsystemcatalog.
* @bug 2574
*

View File

@ -1629,7 +1629,6 @@ void applyMapping(const int* mapping, const Row& in, Row* out)
out->setVarBinaryField(in.getVarBinaryField(i), in.getVarBinaryLength(i), mapping[i]);
else if (UNLIKELY(in.isLongString(i)))
out->setStringField(in.getStringPointer(i), in.getStringLength(i), mapping[i]);
//out->setStringField(in.getStringField(i), mapping[i]);
else if (UNLIKELY(in.isShortString(i)))
out->setUintField(in.getUintField(i), mapping[i]);
else if (UNLIKELY(in.getColTypes()[i] == execplan::CalpontSystemCatalog::LONGDOUBLE))