You've already forked mariadb-columnstore-engine
mirror of
https://github.com/mariadb-corporation/mariadb-columnstore-engine.git
synced 2025-08-07 03:22:57 +03:00
MCOL-641 Fixes for arithmetic operations.
1. Perform type promotion to wide decimal if the result of an arithmetic operation has a precision > 18. 2. Only set the decimal width of an arithmetic operation to wide if both the LHS and RHS of the operation are decimal types.
This commit is contained in:
committed by
Roman Nozdrin
parent
844472d812
commit
1f4a781704
@@ -470,6 +470,21 @@ class Decimal
|
|||||||
scale += (scaleAvailable >= MAXSCALEINC4AVG) ? MAXSCALEINC4AVG : scaleAvailable;
|
scale += (scaleAvailable >= MAXSCALEINC4AVG) ? MAXSCALEINC4AVG : scaleAvailable;
|
||||||
precision += (precisionAvailable >= MAXSCALEINC4AVG) ? MAXSCALEINC4AVG : precisionAvailable;
|
precision += (precisionAvailable >= MAXSCALEINC4AVG) ? MAXSCALEINC4AVG : precisionAvailable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Returns true if all arguments have a DECIMAL/UDECIMAL type
|
||||||
|
*/
|
||||||
|
static inline bool isDecimalOperands(const ColDataTypeAlias resultDataType,
|
||||||
|
const ColDataTypeAlias leftColDataType,
|
||||||
|
const ColDataTypeAlias rightColDataType)
|
||||||
|
{
|
||||||
|
return ((resultDataType == execplan::CalpontSystemCatalog::DECIMAL ||
|
||||||
|
resultDataType == execplan::CalpontSystemCatalog::UDECIMAL) &&
|
||||||
|
(leftColDataType == execplan::CalpontSystemCatalog::DECIMAL ||
|
||||||
|
leftColDataType == execplan::CalpontSystemCatalog::UDECIMAL) &&
|
||||||
|
(rightColDataType == execplan::CalpontSystemCatalog::DECIMAL ||
|
||||||
|
rightColDataType == execplan::CalpontSystemCatalog::UDECIMAL));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -343,12 +343,8 @@ namespace joblist
|
|||||||
void wideDecimalOrLongDouble(const uint64_t colProj,
|
void wideDecimalOrLongDouble(const uint64_t colProj,
|
||||||
const CalpontSystemCatalog::ColDataType type,
|
const CalpontSystemCatalog::ColDataType type,
|
||||||
const vector<uint32_t>& precisionProj,
|
const vector<uint32_t>& precisionProj,
|
||||||
const vector<uint32_t>& oidsProj,
|
|
||||||
const uint32_t aggKey,
|
|
||||||
const vector<uint32_t>& scaleProj,
|
const vector<uint32_t>& scaleProj,
|
||||||
const vector<uint32_t>& width,
|
const vector<uint32_t>& width,
|
||||||
vector<uint32_t>& oidsAgg,
|
|
||||||
vector<uint32_t>& keysAgg,
|
|
||||||
vector<CalpontSystemCatalog::ColDataType>& typeAgg,
|
vector<CalpontSystemCatalog::ColDataType>& typeAgg,
|
||||||
vector<uint32_t>& scaleAgg,
|
vector<uint32_t>& scaleAgg,
|
||||||
vector<uint32_t>& precisionAgg,
|
vector<uint32_t>& precisionAgg,
|
||||||
@@ -358,8 +354,6 @@ void wideDecimalOrLongDouble(const uint64_t colProj,
|
|||||||
|| type == CalpontSystemCatalog::UDECIMAL)
|
|| type == CalpontSystemCatalog::UDECIMAL)
|
||||||
&& datatypes::Decimal::isWideDecimalType(precisionProj[colProj]))
|
&& datatypes::Decimal::isWideDecimalType(precisionProj[colProj]))
|
||||||
{
|
{
|
||||||
oidsAgg.push_back(oidsProj[colProj]);
|
|
||||||
keysAgg.push_back(aggKey);
|
|
||||||
typeAgg.push_back(type);
|
typeAgg.push_back(type);
|
||||||
scaleAgg.push_back(scaleProj[colProj]);
|
scaleAgg.push_back(scaleProj[colProj]);
|
||||||
precisionAgg.push_back(precisionProj[colProj]);
|
precisionAgg.push_back(precisionProj[colProj]);
|
||||||
@@ -367,8 +361,6 @@ void wideDecimalOrLongDouble(const uint64_t colProj,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
oidsAgg.push_back(oidsProj[colProj]);
|
|
||||||
keysAgg.push_back(aggKey);
|
|
||||||
typeAgg.push_back(CalpontSystemCatalog::LONGDOUBLE);
|
typeAgg.push_back(CalpontSystemCatalog::LONGDOUBLE);
|
||||||
scaleAgg.push_back(0);
|
scaleAgg.push_back(0);
|
||||||
precisionAgg.push_back(-1);
|
precisionAgg.push_back(-1);
|
||||||
@@ -758,29 +750,38 @@ void TupleAggregateStep::configDeliveredRowGroup(const JobInfo& jobInfo)
|
|||||||
if (jobInfo.havingStep)
|
if (jobInfo.havingStep)
|
||||||
{
|
{
|
||||||
retColCount = jobInfo.returnedColVec.size();
|
retColCount = jobInfo.returnedColVec.size();
|
||||||
|
|
||||||
idbassert(jobInfo.returnedColVec.size() == jobInfo.nonConstCols.size());
|
idbassert(jobInfo.returnedColVec.size() == jobInfo.nonConstCols.size());
|
||||||
for (auto& rc : jobInfo.nonConstCols)
|
|
||||||
|
for (size_t i = 0; i < jobInfo.nonConstCols.size() &&
|
||||||
|
scaleIter != scale.end(); i++)
|
||||||
{
|
{
|
||||||
auto& colType = rc->resultType();
|
const auto& colType = jobInfo.nonConstCols[i]->resultType();
|
||||||
|
|
||||||
if (datatypes::Decimal::isWideDecimalType(colType))
|
if (datatypes::Decimal::isWideDecimalType(colType))
|
||||||
{
|
{
|
||||||
*scaleIter = colType.scale;
|
*scaleIter = colType.scale;
|
||||||
*precisionIter = colType.precision;
|
*precisionIter = colType.precision;
|
||||||
}
|
}
|
||||||
|
|
||||||
scaleIter++; precisionIter++;
|
scaleIter++; precisionIter++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
retColCount = jobInfo.nonConstDelCols.size();
|
retColCount = jobInfo.nonConstDelCols.size();
|
||||||
for (auto& rc : jobInfo.nonConstDelCols)
|
|
||||||
|
for (size_t i = 0; i < jobInfo.nonConstDelCols.size() &&
|
||||||
|
scaleIter != scale.end(); i++)
|
||||||
{
|
{
|
||||||
auto& colType = rc->resultType();
|
const auto& colType = jobInfo.nonConstDelCols[i]->resultType();
|
||||||
|
|
||||||
if (datatypes::Decimal::isWideDecimalType(colType))
|
if (datatypes::Decimal::isWideDecimalType(colType))
|
||||||
{
|
{
|
||||||
*scaleIter = colType.scale;
|
*scaleIter = colType.scale;
|
||||||
*precisionIter = colType.precision;
|
*precisionIter = colType.precision;
|
||||||
}
|
}
|
||||||
|
|
||||||
scaleIter++; precisionIter++;
|
scaleIter++; precisionIter++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1356,10 +1357,13 @@ void TupleAggregateStep::prep1PhaseAggregate(
|
|||||||
cerr << "prep1PhaseAggregate: " << emsg << endl;
|
cerr << "prep1PhaseAggregate: " << emsg << endl;
|
||||||
throw IDBExcept(emsg, ERR_AGGREGATE_TYPE_NOT_SUPPORT);
|
throw IDBExcept(emsg, ERR_AGGREGATE_TYPE_NOT_SUPPORT);
|
||||||
}
|
}
|
||||||
|
|
||||||
wideDecimalOrLongDouble(colProj, typeProj[colProj],
|
wideDecimalOrLongDouble(colProj, typeProj[colProj],
|
||||||
precisionProj, oidsProj, key, scaleProj, width,
|
precisionProj, scaleProj, width,
|
||||||
oidsAgg, keysAgg, typeAgg, scaleAgg,
|
typeAgg, scaleAgg, precisionAgg, widthAgg);
|
||||||
precisionAgg, widthAgg);
|
|
||||||
|
oidsAgg.push_back(oidsProj[colProj]);
|
||||||
|
keysAgg.push_back(key);
|
||||||
csNumAgg.push_back(csNumProj[colProj]);
|
csNumAgg.push_back(csNumProj[colProj]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -3181,10 +3185,13 @@ void TupleAggregateStep::prep2PhasesAggregate(
|
|||||||
cerr << "prep2PhasesAggregate: " << emsg << endl;
|
cerr << "prep2PhasesAggregate: " << emsg << endl;
|
||||||
throw IDBExcept(emsg, ERR_AGGREGATE_TYPE_NOT_SUPPORT);
|
throw IDBExcept(emsg, ERR_AGGREGATE_TYPE_NOT_SUPPORT);
|
||||||
}
|
}
|
||||||
|
|
||||||
wideDecimalOrLongDouble(colProj, typeProj[colProj],
|
wideDecimalOrLongDouble(colProj, typeProj[colProj],
|
||||||
precisionProj, oidsProj, aggKey, scaleProj, width,
|
precisionProj, scaleProj, width,
|
||||||
oidsAggPm, keysAggPm, typeAggPm, scaleAggPm,
|
typeAggPm, scaleAggPm, precisionAggPm, widthAggPm);
|
||||||
precisionAggPm, widthAggPm);
|
|
||||||
|
oidsAggPm.push_back(oidsProj[colProj]);
|
||||||
|
keysAggPm.push_back(aggKey);
|
||||||
csNumAggPm.push_back(8);
|
csNumAggPm.push_back(8);
|
||||||
colAggPm++;
|
colAggPm++;
|
||||||
}
|
}
|
||||||
@@ -3469,9 +3476,11 @@ void TupleAggregateStep::prep2PhasesAggregate(
|
|||||||
if (aggOp == ROWAGG_SUM)
|
if (aggOp == ROWAGG_SUM)
|
||||||
{
|
{
|
||||||
wideDecimalOrLongDouble(colPm, typeProj[colPm],
|
wideDecimalOrLongDouble(colPm, typeProj[colPm],
|
||||||
precisionProj, oidsProj, retKey, scaleProj, widthAggPm,
|
precisionProj, scaleProj, widthAggPm,
|
||||||
oidsAggUm, keysAggUm, typeAggUm, scaleAggUm,
|
typeAggUm, scaleAggUm, precisionAggUm, widthAggUm);
|
||||||
precisionAggUm, widthAggUm);
|
|
||||||
|
oidsAggUm.push_back(oidsProj[colPm]);
|
||||||
|
keysAggUm.push_back(retKey);
|
||||||
csNumAggUm.push_back(8);
|
csNumAggUm.push_back(8);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@@ -3602,68 +3602,51 @@ ArithmeticColumn* buildArithmeticColumn(
|
|||||||
|
|
||||||
// @bug5715. Use InfiniDB adjusted coltype for result type.
|
// @bug5715. Use InfiniDB adjusted coltype for result type.
|
||||||
// decimal arithmetic operation gives double result when the session variable is set.
|
// decimal arithmetic operation gives double result when the session variable is set.
|
||||||
CalpontSystemCatalog::ColType mysql_type = colType_MysqlToIDB(item);
|
CalpontSystemCatalog::ColType mysqlType = colType_MysqlToIDB(item);
|
||||||
|
|
||||||
if (mysql_type.colDataType == CalpontSystemCatalog::DECIMAL ||
|
const CalpontSystemCatalog::ColType& leftColType = pt->left()->data()->resultType();
|
||||||
mysql_type.colDataType == CalpontSystemCatalog::UDECIMAL)
|
const CalpontSystemCatalog::ColType& rightColType = pt->right()->data()->resultType();
|
||||||
{
|
|
||||||
int32_t leftColWidth = pt->left()->data()->resultType().colWidth;
|
// Only tinker with the type if all columns involved are decimal
|
||||||
int32_t rightColWidth = pt->right()->data()->resultType().colWidth;
|
if (datatypes::Decimal::isDecimalOperands(mysqlType.colDataType,
|
||||||
|
leftColType.colDataType, rightColType.colDataType))
|
||||||
// Revert back to legacy values of scale and precision
|
|
||||||
// if the 2 columns involved in the expression are not wide
|
|
||||||
if (leftColWidth <= utils::MAXLEGACYWIDTH &&
|
|
||||||
rightColWidth <= utils::MAXLEGACYWIDTH)
|
|
||||||
{
|
|
||||||
Item_decimal* idp = (Item_decimal*)item;
|
|
||||||
|
|
||||||
mysql_type.colWidth = 8;
|
|
||||||
|
|
||||||
unsigned int precision = idp->max_length;
|
|
||||||
unsigned int scale = idp->decimals;
|
|
||||||
|
|
||||||
datatypes::Decimal::setDecimalScalePrecisionLegacy(mysql_type,
|
|
||||||
precision, scale);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
|
int32_t leftColWidth = leftColType.colWidth;
|
||||||
|
int32_t rightColWidth = rightColType.colWidth;
|
||||||
|
|
||||||
if (leftColWidth == datatypes::MAXDECIMALWIDTH ||
|
if (leftColWidth == datatypes::MAXDECIMALWIDTH ||
|
||||||
rightColWidth == datatypes::MAXDECIMALWIDTH)
|
rightColWidth == datatypes::MAXDECIMALWIDTH)
|
||||||
mysql_type.colWidth = datatypes::MAXDECIMALWIDTH;
|
|
||||||
|
|
||||||
if (mysql_type.colWidth == datatypes::MAXDECIMALWIDTH)
|
|
||||||
{
|
{
|
||||||
|
mysqlType.colWidth = datatypes::MAXDECIMALWIDTH;
|
||||||
|
|
||||||
string funcName = item->func_name();
|
string funcName = item->func_name();
|
||||||
|
|
||||||
int32_t scale1 = pt->left()->data()->resultType().scale;
|
int32_t scale1 = leftColType.scale;
|
||||||
int32_t scale2 = pt->right()->data()->resultType().scale;
|
int32_t scale2 = rightColType.scale;
|
||||||
|
|
||||||
if (funcName == "/" &&
|
if (funcName == "/" &&
|
||||||
(mysql_type.scale - (scale1 - scale2)) >
|
(mysqlType.scale - (scale1 - scale2)) > datatypes::INT128MAXPRECISION)
|
||||||
datatypes::INT128MAXPRECISION)
|
|
||||||
{
|
{
|
||||||
Item_decimal* idp = (Item_decimal*)item;
|
Item_decimal* idp = (Item_decimal*)item;
|
||||||
|
|
||||||
unsigned int precision = idp->decimal_precision();
|
unsigned int precision = idp->decimal_precision();
|
||||||
unsigned int scale = idp->decimal_scale();
|
unsigned int scale = idp->decimal_scale();
|
||||||
|
|
||||||
datatypes::Decimal::setDecimalScalePrecisionHeuristic(mysql_type, precision, scale);
|
datatypes::Decimal::setDecimalScalePrecisionHeuristic(mysqlType, precision, scale);
|
||||||
|
|
||||||
if (mysql_type.scale < scale1)
|
if (mysqlType.scale < scale1)
|
||||||
mysql_type.scale = scale1;
|
mysqlType.scale = scale1;
|
||||||
|
|
||||||
if (mysql_type.precision < mysql_type.scale)
|
if (mysqlType.precision < mysqlType.scale)
|
||||||
mysql_type.precision = mysql_type.scale;
|
mysqlType.precision = mysqlType.scale;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_double_for_decimal_math(current_thd) == true)
|
if (get_double_for_decimal_math(current_thd) == true)
|
||||||
aop->adjustResultType(mysql_type);
|
aop->adjustResultType(mysqlType);
|
||||||
else
|
else
|
||||||
aop->resultType(mysql_type);
|
aop->resultType(mysqlType);
|
||||||
|
|
||||||
// adjust decimal result type according to internalDecimalScale
|
// adjust decimal result type according to internalDecimalScale
|
||||||
if (gwi.internalDecimalScale >= 0 && aop->resultType().colDataType == CalpontSystemCatalog::DECIMAL)
|
if (gwi.internalDecimalScale >= 0 && aop->resultType().colDataType == CalpontSystemCatalog::DECIMAL)
|
||||||
|
Reference in New Issue
Block a user