You've already forked mariadb-columnstore-engine
mirror of
https://github.com/mariadb-corporation/mariadb-columnstore-engine.git
synced 2025-07-29 08:21:15 +03:00
MCOL-641 Implement int128_t versions of arithmetic operations and add unit test cases.
This commit is contained in:
committed by
Roman Nozdrin
parent
b5534eb847
commit
554c6da8e8
@ -35,19 +35,19 @@ namespace execplan
|
||||
* Constructors/Destructors
|
||||
*/
|
||||
ArithmeticOperator::ArithmeticOperator() : Operator(),
|
||||
fDecimalOverflowCheck(true)
|
||||
fDecimalOverflowCheck(false)
|
||||
{
|
||||
}
|
||||
|
||||
ArithmeticOperator::ArithmeticOperator(const string& operatorName): Operator(operatorName),
|
||||
fDecimalOverflowCheck(true)
|
||||
fDecimalOverflowCheck(false)
|
||||
{
|
||||
}
|
||||
|
||||
ArithmeticOperator::ArithmeticOperator(const ArithmeticOperator& rhs):
|
||||
Operator(rhs),
|
||||
fTimeZone(rhs.timeZone()),
|
||||
fDecimalOverflowCheck(true)
|
||||
fDecimalOverflowCheck(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -196,7 +196,7 @@ public:
|
||||
return TreeNode::getBoolVal();
|
||||
}
|
||||
void adjustResultType(const CalpontSystemCatalog::ColType& m);
|
||||
constexpr inline bool getOverflowCheck()
|
||||
constexpr inline bool getOverflowCheck() const
|
||||
{
|
||||
return fDecimalOverflowCheck;
|
||||
}
|
||||
@ -209,7 +209,6 @@ private:
|
||||
template <typename result_t>
|
||||
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, cscType& resultCscType);
|
||||
std::string fTimeZone;
|
||||
bool fDecimalOverflowCheck;
|
||||
};
|
||||
@ -250,7 +249,7 @@ inline void ArithmeticOperator::evaluate(rowgroup::Row& row, bool& isNull, Parse
|
||||
// WIP MCOL-641
|
||||
case execplan::CalpontSystemCatalog::DECIMAL:
|
||||
case execplan::CalpontSystemCatalog::UDECIMAL:
|
||||
execute(fResult.decimalVal, lop->getDecimalVal(row, isNull), rop->getDecimalVal(row, isNull), isNull, fOperationType);
|
||||
execute(fResult.decimalVal, lop->getDecimalVal(row, isNull), rop->getDecimalVal(row, isNull), isNull);
|
||||
break;
|
||||
default:
|
||||
{
|
||||
@ -292,20 +291,36 @@ 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, cscType& resultCscType)
|
||||
inline void ArithmeticOperator::execute(IDB_Decimal& result, IDB_Decimal op1, IDB_Decimal op2, bool& isNull)
|
||||
{
|
||||
switch (fOp)
|
||||
{
|
||||
case OP_ADD:
|
||||
if (resultCscType.colWidth == datatypes::MAXDECIMALWIDTH)
|
||||
if (fOperationType.colWidth == datatypes::MAXDECIMALWIDTH)
|
||||
{
|
||||
datatypes::Decimal::addition<decltype(result.s128Value),true>(
|
||||
op1, op2, result);
|
||||
if (LIKELY(!fDecimalOverflowCheck))
|
||||
{
|
||||
datatypes::Decimal::addition<decltype(result.s128Value), false>(
|
||||
op1, op2, result);
|
||||
}
|
||||
else
|
||||
{
|
||||
datatypes::Decimal::addition<decltype(result.s128Value), true>(
|
||||
op1, op2, result);
|
||||
}
|
||||
}
|
||||
else if (resultCscType.colWidth == utils::MAXLEGACYWIDTH)
|
||||
else if (fOperationType.colWidth == utils::MAXLEGACYWIDTH)
|
||||
{
|
||||
datatypes::Decimal::addition<decltype(result.value),false>(
|
||||
op1, op2, result);
|
||||
if (LIKELY(!fDecimalOverflowCheck))
|
||||
{
|
||||
datatypes::Decimal::addition<decltype(result.value), false>(
|
||||
op1, op2, result);
|
||||
}
|
||||
else
|
||||
{
|
||||
datatypes::Decimal::addition<decltype(result.value), true>(
|
||||
op1, op2, result);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -315,52 +330,95 @@ inline void ArithmeticOperator::execute(IDB_Decimal& result, IDB_Decimal op1, ID
|
||||
break;
|
||||
|
||||
case OP_SUB:
|
||||
if (result.scale == op1.scale && result.scale == op2.scale)
|
||||
if (fOperationType.colWidth == datatypes::MAXDECIMALWIDTH)
|
||||
{
|
||||
result.value = op1.value - op2.value;
|
||||
break;
|
||||
if (LIKELY(!fDecimalOverflowCheck))
|
||||
{
|
||||
datatypes::Decimal::subtraction<decltype(result.s128Value), false>(
|
||||
op1, op2, result);
|
||||
}
|
||||
else
|
||||
{
|
||||
datatypes::Decimal::subtraction<decltype(result.s128Value), true>(
|
||||
op1, op2, result);
|
||||
}
|
||||
}
|
||||
else if (fOperationType.colWidth == utils::MAXLEGACYWIDTH)
|
||||
{
|
||||
if (LIKELY(!fDecimalOverflowCheck))
|
||||
{
|
||||
datatypes::Decimal::subtraction<decltype(result.value), false>(
|
||||
op1, op2, result);
|
||||
}
|
||||
else
|
||||
{
|
||||
datatypes::Decimal::subtraction<decltype(result.value), true>(
|
||||
op1, op2, result);
|
||||
}
|
||||
}
|
||||
|
||||
if (result.scale >= op1.scale)
|
||||
op1.value *= IDB_pow[result.scale - op1.scale];
|
||||
else
|
||||
op1.value = (int64_t)(op1.value > 0 ?
|
||||
(double)op1.value / IDB_pow[op1.scale - result.scale] + 0.5 :
|
||||
(double)op1.value / IDB_pow[op1.scale - result.scale] - 0.5);
|
||||
|
||||
if (result.scale >= op2.scale)
|
||||
op2.value *= IDB_pow[result.scale - op2.scale];
|
||||
else
|
||||
op2.value = (int64_t)(op2.value > 0 ?
|
||||
(double)op2.value / IDB_pow[op2.scale - result.scale] + 0.5 :
|
||||
(double)op2.value / IDB_pow[op2.scale - result.scale] - 0.5);
|
||||
|
||||
result.value = op1.value - op2.value;
|
||||
{
|
||||
throw logging::InvalidArgumentExcept(
|
||||
"Unexpected result width");
|
||||
}
|
||||
break;
|
||||
|
||||
case OP_MUL:
|
||||
if (result.scale >= op1.scale + op2.scale)
|
||||
result.value = op1.value * op2.value * IDB_pow[result.scale - (op1.scale + op2.scale)];
|
||||
if (fOperationType.colWidth == datatypes::MAXDECIMALWIDTH)
|
||||
{
|
||||
if (LIKELY(!fDecimalOverflowCheck))
|
||||
{
|
||||
datatypes::Decimal::multiplication<decltype(result.s128Value), false>(
|
||||
op1, op2, result);
|
||||
}
|
||||
else
|
||||
{
|
||||
datatypes::Decimal::multiplication<decltype(result.s128Value), true>(
|
||||
op1, op2, result);
|
||||
}
|
||||
}
|
||||
else if (fOperationType.colWidth == utils::MAXLEGACYWIDTH)
|
||||
{
|
||||
if (LIKELY(!fDecimalOverflowCheck))
|
||||
{
|
||||
datatypes::Decimal::multiplication<decltype(result.value), false>(
|
||||
op1, op2, result);
|
||||
}
|
||||
else
|
||||
{
|
||||
datatypes::Decimal::multiplication<decltype(result.value), true>(
|
||||
op1, op2, result);
|
||||
}
|
||||
}
|
||||
else
|
||||
result.value = (int64_t)(( (op1.value > 0 && op2.value > 0) || (op1.value < 0 && op2.value < 0) ?
|
||||
(double)op1.value * op2.value / IDB_pow[op1.scale + op2.scale - result.scale] + 0.5 :
|
||||
(double)op1.value * op2.value / IDB_pow[op1.scale + op2.scale - result.scale] - 0.5));
|
||||
|
||||
{
|
||||
throw logging::InvalidArgumentExcept(
|
||||
"Unexpected result width");
|
||||
}
|
||||
break;
|
||||
|
||||
case OP_DIV:
|
||||
if (resultCscType.colWidth == 16)
|
||||
if (fOperationType.colWidth == datatypes::MAXDECIMALWIDTH)
|
||||
{
|
||||
if (op2.s128Value == 0)
|
||||
if ((datatypes::Decimal::isWideDecimalType(op2.precision) && op2.s128Value == 0)
|
||||
|| (!datatypes::Decimal::isWideDecimalType(op2.precision) && op2.value == 0))
|
||||
{
|
||||
isNull = true;
|
||||
break;
|
||||
}
|
||||
|
||||
datatypes::Decimal::division<decltype(result.s128Value),false>(
|
||||
op1, op2, result);
|
||||
if (LIKELY(!fDecimalOverflowCheck))
|
||||
{
|
||||
datatypes::Decimal::division<decltype(result.s128Value), false>(
|
||||
op1, op2, result);
|
||||
}
|
||||
else
|
||||
{
|
||||
datatypes::Decimal::division<decltype(result.s128Value), true>(
|
||||
op1, op2, result);
|
||||
}
|
||||
}
|
||||
else if (resultCscType.colWidth == 8)
|
||||
else if (fOperationType.colWidth == utils::MAXLEGACYWIDTH)
|
||||
{
|
||||
if (op2.value == 0)
|
||||
{
|
||||
@ -368,8 +426,16 @@ inline void ArithmeticOperator::execute(IDB_Decimal& result, IDB_Decimal op1, ID
|
||||
break;
|
||||
}
|
||||
|
||||
datatypes::Decimal::division<decltype(result.value),false>(
|
||||
op1, op2, result);
|
||||
if (LIKELY(!fDecimalOverflowCheck))
|
||||
{
|
||||
datatypes::Decimal::division<decltype(result.value), false>(
|
||||
op1, op2, result);
|
||||
}
|
||||
else
|
||||
{
|
||||
datatypes::Decimal::division<decltype(result.value), true>(
|
||||
op1, op2, result);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
Reference in New Issue
Block a user