You've already forked mariadb-columnstore-engine
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:
committed by
Roman Nozdrin
parent
554c6da8e8
commit
cfe35b5c7f
@@ -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)
|
||||
{
|
||||
|
@@ -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:
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
Reference in New Issue
Block a user