1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2025-08-08 14:22:09 +03:00

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

This commit is contained in:
Gagan Goel
2020-04-19 23:27:43 -04:00
committed by Roman Nozdrin
parent 554c6da8e8
commit cfe35b5c7f
28 changed files with 2102 additions and 462 deletions

View File

@@ -256,14 +256,24 @@ public:
(datatypes::Decimal::isWideDecimalType(decimal.precision)) ?
decimal.s128Value : decimal.value;
int128_t scaleMultiplier, result;
int128_t scaleMultiplier;
int32_t scaleDiff = fResultType.scale - decimal.scale;
datatypes::getScaleDivisor(scaleMultiplier, abs(scaleDiff));
// WIP MCOL-641 Unconditionall overflow check
datatypes::MultiplicationOverflowCheck mul;
decimal.s128Value = (scaleDiff > 0
&& mul(decimal.s128Value, scaleMultiplier, result))
? result : decimal.s128Value / scaleMultiplier;
if (scaleMultiplier > 1)
{
if (scaleDiff > 0)
{
// WIP MCOL-641 Unconditionall overflow check
datatypes::MultiplicationNoOverflowCheck mul;
mul(decimal.s128Value, scaleMultiplier, decimal.s128Value);
}
else
{
decimal.s128Value = (int128_t)(decimal.s128Value > 0 ?
(__float128)decimal.s128Value / scaleMultiplier + 0.5 :
(__float128)decimal.s128Value / scaleMultiplier - 0.5);
}
}
}
else if (fResultType.colWidth == utils::MAXLEGACYWIDTH)
{

View File

@@ -63,17 +63,16 @@ typedef execplan::CalpontSystemCatalog::ColType Type;
*/
struct IDB_Decimal
{
IDB_Decimal(): value(0), scale(0), precision(0)
IDB_Decimal(): s128Value(0), value(0), scale(0), precision(0)
{
s128Value = 0;
}
IDB_Decimal(int64_t val, int8_t s, uint8_t p) :
value (val),
IDB_Decimal(int64_t val, int8_t s, uint8_t p, int128_t val128 = 0) :
s128Value(val128),
value(val),
scale(s),
precision(p)
{
s128Value = 0;
}
int decimalComp(const IDB_Decimal& d) const
@@ -117,13 +116,32 @@ struct IDB_Decimal
bool operator==(const IDB_Decimal& rhs) const
{
if (utils::widthByPrecision(precision) == 16)
if (precision > datatypes::INT64MAXPRECISION &&
rhs.precision > datatypes::INT64MAXPRECISION)
{
if (scale == rhs.scale)
return s128Value == rhs.s128Value;
else
return (datatypes::Decimal::compare(*this, rhs) == 0);
}
else if (precision > datatypes::INT64MAXPRECISION &&
rhs.precision <= datatypes::INT64MAXPRECISION)
{
const_cast<IDB_Decimal&>(rhs).s128Value = rhs.value;
if (scale == rhs.scale)
return s128Value == rhs.s128Value;
else
return (datatypes::Decimal::compare(*this, rhs) == 0);
}
else if (precision <= datatypes::INT64MAXPRECISION &&
rhs.precision > datatypes::INT64MAXPRECISION)
{
if (scale == rhs.scale)
return (int128_t) value == rhs.s128Value;
else
return (datatypes::Decimal::compare(IDB_Decimal(0, scale, precision, (int128_t) value), rhs) == 0);
}
else
{
if (scale == rhs.scale)
@@ -135,13 +153,32 @@ struct IDB_Decimal
bool operator>(const IDB_Decimal& rhs) const
{
if (utils::widthByPrecision(precision) == 16)
if (precision > datatypes::INT64MAXPRECISION &&
rhs.precision > datatypes::INT64MAXPRECISION)
{
if (scale == rhs.scale)
return s128Value > rhs.s128Value;
else
return (datatypes::Decimal::compare(*this, rhs) > 0);
}
else if (precision > datatypes::INT64MAXPRECISION &&
rhs.precision <= datatypes::INT64MAXPRECISION)
{
IDB_Decimal rhstmp(0, rhs.scale, rhs.precision, (int128_t) rhs.value);
if (scale == rhstmp.scale)
return s128Value > rhstmp.s128Value;
else
return (datatypes::Decimal::compare(*this, rhstmp) > 0);
}
else if (precision <= datatypes::INT64MAXPRECISION &&
rhs.precision > datatypes::INT64MAXPRECISION)
{
if (scale == rhs.scale)
return (int128_t) value > rhs.s128Value;
else
return (datatypes::Decimal::compare(IDB_Decimal(0, scale, precision, (int128_t) value), rhs) > 0);
}
else
{
if (scale == rhs.scale)
@@ -153,13 +190,32 @@ struct IDB_Decimal
bool operator<(const IDB_Decimal& rhs) const
{
if (utils::widthByPrecision(precision) == 16)
if (precision > datatypes::INT64MAXPRECISION &&
rhs.precision > datatypes::INT64MAXPRECISION)
{
if (scale == rhs.scale)
return s128Value < rhs.s128Value;
else
return (datatypes::Decimal::compare(*this, rhs) < 0);
}
else if (precision > datatypes::INT64MAXPRECISION &&
rhs.precision <= datatypes::INT64MAXPRECISION)
{
IDB_Decimal rhstmp(0, rhs.scale, rhs.precision, (int128_t) rhs.value);
if (scale == rhstmp.scale)
return s128Value < rhstmp.s128Value;
else
return (datatypes::Decimal::compare(*this, rhstmp) < 0);
}
else if (precision <= datatypes::INT64MAXPRECISION &&
rhs.precision > datatypes::INT64MAXPRECISION)
{
if (scale == rhs.scale)
return (int128_t) value < rhs.s128Value;
else
return (datatypes::Decimal::compare(IDB_Decimal(0, scale, precision, (int128_t) value), rhs) < 0);
}
else
{
if (scale == rhs.scale)
@@ -171,13 +227,32 @@ struct IDB_Decimal
bool operator>=(const IDB_Decimal& rhs) const
{
if (utils::widthByPrecision(precision) == 16)
if (precision > datatypes::INT64MAXPRECISION &&
rhs.precision > datatypes::INT64MAXPRECISION)
{
if (scale == rhs.scale)
return s128Value >= rhs.s128Value;
else
return (datatypes::Decimal::compare(*this, rhs) >= 0);
}
else if (precision > datatypes::INT64MAXPRECISION &&
rhs.precision <= datatypes::INT64MAXPRECISION)
{
IDB_Decimal rhstmp(0, rhs.scale, rhs.precision, (int128_t) rhs.value);
if (scale == rhstmp.scale)
return s128Value >= rhstmp.s128Value;
else
return (datatypes::Decimal::compare(*this, rhstmp) >= 0);
}
else if (precision <= datatypes::INT64MAXPRECISION &&
rhs.precision > datatypes::INT64MAXPRECISION)
{
if (scale == rhs.scale)
return (int128_t) value >= rhs.s128Value;
else
return (datatypes::Decimal::compare(IDB_Decimal(0, scale, precision, (int128_t) value), rhs) >= 0);
}
else
{
if (scale == rhs.scale)
@@ -189,13 +264,32 @@ struct IDB_Decimal
bool operator<=(const IDB_Decimal& rhs) const
{
if (utils::widthByPrecision(precision) == 16)
if (precision > datatypes::INT64MAXPRECISION &&
rhs.precision > datatypes::INT64MAXPRECISION)
{
if (scale == rhs.scale)
return s128Value <= rhs.s128Value;
else
return (datatypes::Decimal::compare(*this, rhs) <= 0);
}
else if (precision > datatypes::INT64MAXPRECISION &&
rhs.precision <= datatypes::INT64MAXPRECISION)
{
IDB_Decimal rhstmp(0, rhs.scale, rhs.precision, (int128_t) rhs.value);
if (scale == rhstmp.scale)
return s128Value <= rhstmp.s128Value;
else
return (datatypes::Decimal::compare(*this, rhstmp) <= 0);
}
else if (precision <= datatypes::INT64MAXPRECISION &&
rhs.precision > datatypes::INT64MAXPRECISION)
{
if (scale == rhs.scale)
return (int128_t) value <= rhs.s128Value;
else
return (datatypes::Decimal::compare(IDB_Decimal(0, scale, precision, (int128_t) value), rhs) <= 0);
}
else
{
if (scale == rhs.scale)
@@ -207,13 +301,32 @@ struct IDB_Decimal
bool operator!=(const IDB_Decimal& rhs) const
{
if (utils::widthByPrecision(precision) == 16)
if (precision > datatypes::INT64MAXPRECISION &&
rhs.precision > datatypes::INT64MAXPRECISION)
{
if (scale == rhs.scale)
return s128Value != rhs.s128Value;
else
return (datatypes::Decimal::compare(*this, rhs) != 0);
}
else if (precision > datatypes::INT64MAXPRECISION &&
rhs.precision <= datatypes::INT64MAXPRECISION)
{
IDB_Decimal rhstmp(0, rhs.scale, rhs.precision, (int128_t) rhs.value);
if (scale == rhstmp.scale)
return s128Value != rhstmp.s128Value;
else
return (datatypes::Decimal::compare(*this, rhstmp) != 0);
}
else if (precision <= datatypes::INT64MAXPRECISION &&
rhs.precision > datatypes::INT64MAXPRECISION)
{
if (scale == rhs.scale)
return (int128_t) value != rhs.s128Value;
else
return (datatypes::Decimal::compare(IDB_Decimal(0, scale, precision, (int128_t) value), rhs) != 0);
}
else
{
if (scale == rhs.scale)
@@ -308,7 +421,7 @@ struct Result
{
Result(): intVal(0), uintVal(0), origIntVal(0), dummy(0),
doubleVal(0), longDoubleVal(0), floatVal(0), boolVal(false),
strVal(""), decimalVal(IDB_Decimal(0, 0, 0)),
strVal(""), decimalVal(IDB_Decimal()),
valueConverted(false) {}
int64_t intVal;
uint64_t uintVal;
@@ -783,7 +896,10 @@ inline const std::string& TreeNode::getStrVal(const std::string& timeZone)
case CalpontSystemCatalog::DECIMAL:
case CalpontSystemCatalog::UDECIMAL:
{
dataconvert::DataConvert::decimalToString(fResult.decimalVal.value, fResult.decimalVal.scale, tmp, 22, fResultType.colDataType);
if (fResultType.colWidth == datatypes::MAXDECIMALWIDTH)
dataconvert::DataConvert::decimalToString(&fResult.decimalVal.s128Value, fResult.decimalVal.scale, tmp, utils::MAXLENGTH16BYTES, fResultType.colDataType);
else
dataconvert::DataConvert::decimalToString(fResult.decimalVal.value, fResult.decimalVal.scale, tmp, 22, fResultType.colDataType);
fResult.strVal = std::string(tmp);
break;
}
@@ -880,7 +996,20 @@ inline int64_t TreeNode::getIntVal()
case CalpontSystemCatalog::DECIMAL:
case CalpontSystemCatalog::UDECIMAL:
{
return (int64_t)(fResult.decimalVal.value / pow((double)10, fResult.decimalVal.scale));
if (fResultType.colWidth == datatypes::MAXDECIMALWIDTH)
{
int128_t scaleDivisor;
datatypes::getScaleDivisor(scaleDivisor, fResult.decimalVal.scale);
int128_t tmpval = fResult.decimalVal.s128Value / scaleDivisor;
return datatypes::Decimal::getInt64FromWideDecimal(tmpval);
}
else
{
return (int64_t)(fResult.decimalVal.value / pow((double)10, fResult.decimalVal.scale));
}
}
case CalpontSystemCatalog::DATE:
@@ -1062,8 +1191,15 @@ inline double TreeNode::getDoubleVal()
case CalpontSystemCatalog::DECIMAL:
case CalpontSystemCatalog::UDECIMAL:
{
// this may not be accurate. if this is problematic, change to pre-calculated power array.
return (double)(fResult.decimalVal.value / pow((double)10, fResult.decimalVal.scale));
if (fResultType.colWidth == datatypes::MAXDECIMALWIDTH)
{
return datatypes::Decimal::getDoubleFromWideDecimal(fResult.decimalVal.s128Value, fResult.decimalVal.scale);
}
else
{
// this may not be accurate. if this is problematic, change to pre-calculated power array.
return (double)(fResult.decimalVal.value / pow((double)10, fResult.decimalVal.scale));
}
}
case CalpontSystemCatalog::DATE:

View File

@@ -529,7 +529,9 @@ void TupleConstantStep::fillInConstants(const rowgroup::Row& rowIn, rowgroup::Ro
//fRowConst.copyField(rowOut.getData()+2, 0); // hardcoded 2 for rid length
for (uint32_t i = 1; i < rowOut.getColumnCount(); i++)
// WIP MCOL-641 implement copyBinaryField inside copyField
if (UNLIKELY(utils::isWide(rowIn.getColumnWidth(i - 1))))
if (UNLIKELY(utils::isWide(rowIn.getColumnWidth(i - 1)) &&
(rowIn.getColType(i - 1) == CalpontSystemCatalog::DECIMAL ||
rowIn.getColType(i - 1) == CalpontSystemCatalog::UDECIMAL)))
rowIn.copyBinaryField(rowOut, i, i - 1);
else
rowIn.copyField(rowOut, i, i - 1);

View File

@@ -4095,6 +4095,20 @@ ReturnedColumn* buildFunctionColumn(
fc->functionParms(funcParms);
fc->resultType(colType_MysqlToIDB(ifp));
// if the result type is DECIMAL and any function parameter is a wide decimal
// column, set the result colwidth to wide
if (fc->resultType().colDataType == CalpontSystemCatalog::DECIMAL)
{
for (size_t i = 0; i < funcParms.size(); i++)
{
if (datatypes::Decimal::isWideDecimalType(funcParms[i]->data()->resultType()))
{
fc->resultType().colWidth = datatypes::MAXDECIMALWIDTH;
break;
}
}
}
// MySQL give string result type for date function, but has the flag set.
// we should set the result type to be datetime for comparision.
if (ifp->field_type() == MYSQL_TYPE_DATETIME ||
@@ -4410,6 +4424,14 @@ ConstantColumn* buildDecimalColumn(Item* item, gp_walk_info& gwi)
i = 1;
}
bool specialPrecision = false;
// handle the case when the constant value is 0.12345678901234567890123456789012345678
// In this case idp->decimal_precision() = 39, but we can
if (((i + 1) < str->length()) &&
str->ptr()[i] == '0' && str->ptr()[i + 1] == '.')
specialPrecision = true;
for (; i < str->length(); i++)
{
if (str->ptr()[i] == '.')
@@ -4420,7 +4442,9 @@ ConstantColumn* buildDecimalColumn(Item* item, gp_walk_info& gwi)
if (idp->decimal_precision() <= datatypes::INT64MAXPRECISION)
columnstore_decimal.value = strtoll(columnstore_decimal_val.str().c_str(), 0, 10);
else if (idp->decimal_precision() <= datatypes::INT128MAXPRECISION)
else if (idp->decimal_precision() <= datatypes::INT128MAXPRECISION ||
(idp->decimal_precision() <= datatypes::INT128MAXPRECISION + 1 &&
specialPrecision))
{
bool dummy = false;
columnstore_decimal.s128Value =
@@ -4435,9 +4459,10 @@ ConstantColumn* buildDecimalColumn(Item* item, gp_walk_info& gwi)
columnstore_decimal.value = (int64_t)(val > 0 ? val + 0.5 : val - 0.5);
}
else
columnstore_decimal.scale = idp->decimals;
columnstore_decimal.scale = idp->decimal_scale();
columnstore_decimal.precision = idp->max_length - idp->decimals;
columnstore_decimal.precision = (idp->decimal_precision() > datatypes::INT128MAXPRECISION) ?
datatypes::INT128MAXPRECISION : idp->decimal_precision();
ConstantColumn* cc = new ConstantColumn(valStr, columnstore_decimal);
cc->timeZone(gwi.thd->variables.time_zone->get_name()->ptr());
cc->charsetNumber(idp->collation.collation->number);