1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2025-07-29 08:21:15 +03:00

MCOL-641 Add support for functions (Part 2).

This commit is contained in:
Gagan Goel
2020-07-13 17:52:24 -04:00
committed by Roman Nozdrin
parent bd0d5af123
commit 6aea838360
50 changed files with 578 additions and 125 deletions

View File

@ -56,8 +56,12 @@ bool getUIntValFromParm(
const execplan::SPTP& parm,
uint64_t& value,
bool& isNull,
const string& timeZone)
const string& timeZone,
bool& isBigVal,
int128_t& bigval)
{
isBigVal = false;
switch (parm->data()->resultType().colDataType)
{
case execplan::CalpontSystemCatalog::BIGINT:
@ -104,10 +108,12 @@ bool getUIntValFromParm(
if (parm->data()->resultType().colWidth == datatypes::MAXDECIMALWIDTH)
{
isBigVal = true;
if (parm->data()->resultType().colDataType == execplan::CalpontSystemCatalog::UDECIMAL &&
d.value < 0)
{
value = 0;
bigval = 0;
break;
}
@ -126,12 +132,7 @@ bool getUIntValFromParm(
if (tmpval < 0 && lefto < -4)
tmpval--;
if (tmpval > static_cast<int128_t>(INT64_MAX))
tmpval = INT64_MAX;
else if (tmpval < static_cast<int128_t>(INT64_MIN))
tmpval = INT64_MIN;
value = tmpval;
bigval = tmpval;
}
else
{
@ -229,15 +230,39 @@ int64_t Func_bitand::getIntVal(Row& row,
uint64_t val1 = 0;
uint64_t val2 = 0;
if (!getUIntValFromParm(row, parm[0], val1, isNull, timeZone()) ||
!getUIntValFromParm(row, parm[1], val2, isNull, timeZone()))
int128_t bigval1 = 0;
int128_t bigval2 = 0;
bool isBigVal1;
bool isBigVal2;
if (!getUIntValFromParm(row, parm[0], val1, isNull, timeZone(), isBigVal1, bigval1) ||
!getUIntValFromParm(row, parm[1], val2, isNull, timeZone(), isBigVal2, bigval2))
{
std::ostringstream oss;
oss << "bitand: datatype of " << execplan::colDataTypeToString(operationColType.colDataType);
throw logging::IDBExcept(oss.str(), ERR_DATATYPE_NOT_SUPPORT);
}
return val1 & val2;
if (LIKELY(!isBigVal1 && !isBigVal2))
{
return val1 & val2;
}
// Type promotion to int128_t
if (!isBigVal1)
bigval1 = val1;
if (!isBigVal2)
bigval2 = val2;
int128_t res = bigval1 & bigval2;
if (res > static_cast<int128_t>(UINT64_MAX))
res = UINT64_MAX;
else if (res < static_cast<int128_t>(INT64_MIN))
res = INT64_MIN;
return (int64_t) res;
}
@ -265,15 +290,39 @@ int64_t Func_leftshift::getIntVal(Row& row,
uint64_t val1 = 0;
uint64_t val2 = 0;
if (!getUIntValFromParm(row, parm[0], val1, isNull, timeZone()) ||
!getUIntValFromParm(row, parm[1], val2, isNull, timeZone()))
int128_t bigval1 = 0;
int128_t bigval2 = 0;
bool isBigVal1;
bool isBigVal2;
if (!getUIntValFromParm(row, parm[0], val1, isNull, timeZone(), isBigVal1, bigval1) ||
!getUIntValFromParm(row, parm[1], val2, isNull, timeZone(), isBigVal2, bigval2))
{
std::ostringstream oss;
oss << "leftshift: datatype of " << execplan::colDataTypeToString(operationColType.colDataType);
throw logging::IDBExcept(oss.str(), ERR_DATATYPE_NOT_SUPPORT);
}
return val1 << val2;
if (LIKELY(!isBigVal1 && !isBigVal2))
{
return val1 << val2;
}
// Type promotion to int128_t
if (!isBigVal1)
bigval1 = val1;
if (!isBigVal2)
bigval2 = val2;
int128_t res = bigval1 << bigval2;
if (res > static_cast<int128_t>(UINT64_MAX))
res = UINT64_MAX;
else if (res < static_cast<int128_t>(INT64_MIN))
res = INT64_MIN;
return (int64_t) res;
}
@ -301,15 +350,39 @@ int64_t Func_rightshift::getIntVal(Row& row,
uint64_t val1 = 0;
uint64_t val2 = 0;
if (!getUIntValFromParm(row, parm[0], val1, isNull, timeZone()) ||
!getUIntValFromParm(row, parm[1], val2, isNull, timeZone()))
int128_t bigval1 = 0;
int128_t bigval2 = 0;
bool isBigVal1;
bool isBigVal2;
if (!getUIntValFromParm(row, parm[0], val1, isNull, timeZone(), isBigVal1, bigval1) ||
!getUIntValFromParm(row, parm[1], val2, isNull, timeZone(), isBigVal2, bigval2))
{
std::ostringstream oss;
oss << "rightshift: datatype of " << execplan::colDataTypeToString(operationColType.colDataType);
throw logging::IDBExcept(oss.str(), ERR_DATATYPE_NOT_SUPPORT);
}
return val1 >> val2;
if (LIKELY(!isBigVal1 && !isBigVal2))
{
return val1 >> val2;
}
// Type promotion to int128_t
if (!isBigVal1)
bigval1 = val1;
if (!isBigVal2)
bigval2 = val2;
int128_t res = bigval1 >> bigval2;
if (res > static_cast<int128_t>(UINT64_MAX))
res = UINT64_MAX;
else if (res < static_cast<int128_t>(INT64_MIN))
res = INT64_MIN;
return (int64_t) res;
}
@ -337,15 +410,39 @@ int64_t Func_bitor::getIntVal(Row& row,
uint64_t val1 = 0;
uint64_t val2 = 0;
if (!getUIntValFromParm(row, parm[0], val1, isNull, timeZone()) ||
!getUIntValFromParm(row, parm[1], val2, isNull, timeZone()))
int128_t bigval1 = 0;
int128_t bigval2 = 0;
bool isBigVal1;
bool isBigVal2;
if (!getUIntValFromParm(row, parm[0], val1, isNull, timeZone(), isBigVal1, bigval1) ||
!getUIntValFromParm(row, parm[1], val2, isNull, timeZone(), isBigVal2, bigval2))
{
std::ostringstream oss;
oss << "bitor: datatype of " << execplan::colDataTypeToString(operationColType.colDataType);
throw logging::IDBExcept(oss.str(), ERR_DATATYPE_NOT_SUPPORT);
}
return val1 | val2;
if (LIKELY(!isBigVal1 && !isBigVal2))
{
return val1 | val2;
}
// Type promotion to int128_t
if (!isBigVal1)
bigval1 = val1;
if (!isBigVal2)
bigval2 = val2;
int128_t res = bigval1 | bigval2;
if (res > static_cast<int128_t>(UINT64_MAX))
res = UINT64_MAX;
else if (res < static_cast<int128_t>(INT64_MIN))
res = INT64_MIN;
return (int64_t) res;
}
uint64_t Func_bitor::getUintVal(rowgroup::Row& row,
@ -381,15 +478,39 @@ int64_t Func_bitxor::getIntVal(Row& row,
uint64_t val1 = 0;
uint64_t val2 = 0;
if (!getUIntValFromParm(row, parm[0], val1, isNull, timeZone()) ||
!getUIntValFromParm(row, parm[1], val2, isNull, timeZone()))
int128_t bigval1 = 0;
int128_t bigval2 = 0;
bool isBigVal1;
bool isBigVal2;
if (!getUIntValFromParm(row, parm[0], val1, isNull, timeZone(), isBigVal1, bigval1) ||
!getUIntValFromParm(row, parm[1], val2, isNull, timeZone(), isBigVal2, bigval2))
{
std::ostringstream oss;
oss << "bitxor: datatype of " << execplan::colDataTypeToString(operationColType.colDataType);
throw logging::IDBExcept(oss.str(), ERR_DATATYPE_NOT_SUPPORT);
}
return val1 ^ val2;
if (LIKELY(!isBigVal1 && !isBigVal2))
{
return val1 ^ val2;
}
// Type promotion to int128_t
if (!isBigVal1)
bigval1 = val1;
if (!isBigVal2)
bigval2 = val2;
int128_t res = bigval1 ^ bigval2;
if (res > static_cast<int128_t>(UINT64_MAX))
res = UINT64_MAX;
else if (res < static_cast<int128_t>(INT64_MIN))
res = INT64_MIN;
return (int64_t) res;
}
@ -403,6 +524,20 @@ CalpontSystemCatalog::ColType Func_bit_count::operationType( FunctionParm& fp, C
return resultType;
}
inline int64_t bitCount(uint64_t val)
{
// Refer to Hacker's Delight Chapter 5
// for the bit counting algo used here
val = val - ((val >> 1) & 0x5555555555555555);
val = (val & 0x3333333333333333) + ((val >> 2) & 0x3333333333333333);
val = (val + (val >> 4)) & 0x0F0F0F0F0F0F0F0F;
val = val + (val >> 8);
val = val + (val >> 16);
val = val + (val >> 32);
return (int64_t)(val & 0x000000000000007F);
}
int64_t Func_bit_count::getIntVal(Row& row,
FunctionParm& parm,
bool& isNull,
@ -416,24 +551,25 @@ int64_t Func_bit_count::getIntVal(Row& row,
uint64_t val = 0;
if (!getUIntValFromParm(row, parm[0], val, isNull, timeZone()))
int128_t bigval = 0;
bool isBigVal;
if (!getUIntValFromParm(row, parm[0], val, isNull, timeZone(), isBigVal, bigval))
{
std::ostringstream oss;
oss << "bit_count: datatype of " << execplan::colDataTypeToString(operationColType.colDataType);
throw logging::IDBExcept(oss.str(), ERR_DATATYPE_NOT_SUPPORT);
}
// Refer to Hacker's Delight Chapter 5
// for the bit counting algo used here
val = val - ((val >> 1) & 0x5555555555555555);
val = (val & 0x3333333333333333) + ((val >> 2) & 0x3333333333333333);
val = (val + (val >> 4)) & 0x0F0F0F0F0F0F0F0F;
val = val + (val >> 8);
val = val + (val >> 16);
val = val + (val >> 32);
return (int64_t)(val & 0x000000000000007F);
if (LIKELY(!isBigVal))
{
return bitCount(val);
}
else
{
return (bitCount(*reinterpret_cast<uint64_t*>(&bigval)) +
bitCount(*(reinterpret_cast<uint64_t*>(&bigval) + 1)));
}
}