diff --git a/datatypes/mcs_datatype.h b/datatypes/mcs_datatype.h index c257e9b11..b46deb198 100644 --- a/datatypes/mcs_datatype.h +++ b/datatypes/mcs_datatype.h @@ -361,7 +361,6 @@ static inline bool isWideDecimalType(const datatypes::SystemCatalog::ColDataType dt == SystemCatalog::UDECIMAL); } - /** convenience function to determine if column type is a char * type */ @@ -480,27 +479,18 @@ inline bool isSignedInteger(const datatypes::SystemCatalog::ColDataType type) } } - /** - @brief Returns true if all arguments have a DECIMAL/UDECIMAL type + @brief The method netects whether type sum and avg aggregate will have + wide decimal underlying type */ -static inline bool isDecimalOperands(const SystemCatalog::ColDataType resultDataType, - const SystemCatalog::ColDataType leftColDataType, - const SystemCatalog::ColDataType rightColDataType) +inline bool hasUnderlyingWideDecimalForSumAndAvg(datatypes::SystemCatalog::ColDataType type) { - return ((resultDataType == SystemCatalog::DECIMAL || - resultDataType == SystemCatalog::UDECIMAL) && - (leftColDataType == SystemCatalog::DECIMAL || - leftColDataType == SystemCatalog::UDECIMAL) && - (rightColDataType == SystemCatalog::DECIMAL || - rightColDataType == SystemCatalog::UDECIMAL)); + return datatypes::isSignedInteger(type) || datatypes::isUnsigned(type); } } // end of namespace datatypes - - namespace datatypes { @@ -1957,7 +1947,7 @@ public: MinMaxInfo widenMinMaxInfo(const SystemCatalog::TypeAttributesStd &attr, const MinMaxInfo &a, const MinMaxInfo &b) const override - { + { return MinMaxInfo::widenSInt64(a, b); } MinMaxPartitionInfo getExtentPartitionInfo(const SystemCatalog::TypeAttributesStd &attr, @@ -2038,7 +2028,7 @@ public: MinMaxInfo widenMinMaxInfo(const SystemCatalog::TypeAttributesStd &attr, const MinMaxInfo &a, const MinMaxInfo &b) const override - { + { return MinMaxInfo::widenSInt64(a, b); } MinMaxPartitionInfo getExtentPartitionInfo(const SystemCatalog::TypeAttributesStd &attr, @@ -2123,7 +2113,7 @@ public: MinMaxInfo widenMinMaxInfo(const SystemCatalog::TypeAttributesStd &attr, const MinMaxInfo &a, const MinMaxInfo &b) const override - { + { return MinMaxInfo::widenSInt128(a, b); } MinMaxPartitionInfo getExtentPartitionInfo(const SystemCatalog::TypeAttributesStd &attr, @@ -2202,7 +2192,7 @@ public: MinMaxInfo widenMinMaxInfo(const SystemCatalog::TypeAttributesStd &attr, const MinMaxInfo &a, const MinMaxInfo &b) const override - { + { return MinMaxInfo::widenSInt128(a, b); } MinMaxPartitionInfo getExtentPartitionInfo(const SystemCatalog::TypeAttributesStd &attr, diff --git a/dbcon/execplan/functioncolumn.h b/dbcon/execplan/functioncolumn.h index 47d87ff64..d5f5b65bb 100644 --- a/dbcon/execplan/functioncolumn.h +++ b/dbcon/execplan/functioncolumn.h @@ -285,7 +285,7 @@ public: } decimal.scale = fResultType.scale; - decimal.precision = fResultType.precision; + decimal.precision = std::max(fResultType.precision, static_cast(decimal.precision)); return decimal; } virtual bool getBoolVal(rowgroup::Row& row, bool& isNull) diff --git a/dbcon/joblist/tupleaggregatestep.cpp b/dbcon/joblist/tupleaggregatestep.cpp index d8c17fa07..d23ff5d16 100644 --- a/dbcon/joblist/tupleaggregatestep.cpp +++ b/dbcon/joblist/tupleaggregatestep.cpp @@ -361,6 +361,13 @@ void wideDecimalOrLongDouble(const uint64_t colProj, precisionAgg.push_back(precisionProj[colProj]); widthAgg.push_back(width[colProj]); } + else if (datatypes::hasUnderlyingWideDecimalForSumAndAvg(type)) + { + typeAgg.push_back(CalpontSystemCatalog::DECIMAL); + scaleAgg.push_back(0); + precisionAgg.push_back(datatypes::INT128MAXPRECISION); + widthAgg.push_back(datatypes::MAXDECIMALWIDTH); + } else { typeAgg.push_back(CalpontSystemCatalog::LONGDOUBLE); @@ -1683,6 +1690,14 @@ void TupleAggregateStep::prep1PhaseDistinctAggregate( // for count column of average function map avgFuncMap, avgDistFuncMap; + // collect the projected column info, prepare for aggregation + vector width; + for (uint64_t i = 0; i < keysProj.size(); i++) + { + width.push_back(projRG.getColumnWidth(i)); + } + + // associate the columns between projected RG and aggregate RG on UM // populated the aggregate columns // the groupby columns are put in front, even not a returned column @@ -1934,11 +1949,10 @@ void TupleAggregateStep::prep1PhaseDistinctAggregate( oidsAgg.push_back(oidsProj[colProj]); keysAgg.push_back(aggKey); - typeAgg.push_back(CalpontSystemCatalog::LONGDOUBLE); csNumAgg.push_back(8); - precisionAgg.push_back(-1); - widthAgg.push_back(sizeof(long double)); - scaleAgg.push_back(0); + wideDecimalOrLongDouble(colProj, typeProj[colProj], + precisionProj, scaleProj, width, + typeAgg, scaleAgg, precisionAgg, widthAgg); colAgg++; // has distinct step, put the count column for avg next to the sum @@ -2265,11 +2279,10 @@ void TupleAggregateStep::prep1PhaseDistinctAggregate( oidsAggDist.push_back(oidsAgg[colAgg]); keysAggDist.push_back(retKey); - typeAggDist.push_back(CalpontSystemCatalog::LONGDOUBLE); + wideDecimalOrLongDouble(colAgg, typeAgg[colAgg], + precisionAgg, scaleAgg, widthAgg, + typeAggDist, scaleAggDist, precisionAggDist, widthAggDist); csNumAggDist.push_back(8); - precisionAggDist.push_back(-1); - widthAggDist.push_back(sizeof(long double)); - scaleAggDist.push_back(0); } break; @@ -2343,11 +2356,10 @@ void TupleAggregateStep::prep1PhaseDistinctAggregate( { oidsAggDist.push_back(oidsAgg[colAgg]); keysAggDist.push_back(retKey); - scaleAggDist.push_back(0); - typeAggDist.push_back(CalpontSystemCatalog::LONGDOUBLE); csNumAggDist.push_back(8); - precisionAggDist.push_back(-1); - widthAggDist.push_back(sizeof(long double)); + wideDecimalOrLongDouble(colAgg, typeAgg[colAgg], + precisionAgg, scaleAgg, widthAgg, + typeAggDist, scaleAggDist, precisionAggDist, widthAggDist); } else { @@ -4166,11 +4178,10 @@ void TupleAggregateStep::prep2PhasesDistinctAggregate( oidsAggPm.push_back(oidsProj[colProj]); keysAggPm.push_back(aggKey); - typeAggPm.push_back(CalpontSystemCatalog::LONGDOUBLE); csNumAggPm.push_back(8); - precisionAggPm.push_back(-1); - widthAggPm.push_back(sizeof(long double)); - scaleAggPm.push_back(0); + wideDecimalOrLongDouble(colProj, typeProj[colProj], + precisionProj, scaleProj, width, + typeAggPm, scaleAggPm, precisionAggPm, widthAggPm); colAggPm++; } @@ -4546,11 +4557,10 @@ void TupleAggregateStep::prep2PhasesDistinctAggregate( oidsAggDist.push_back(oidsAggUm[colUm]); keysAggDist.push_back(retKey); - typeAggDist.push_back(CalpontSystemCatalog::LONGDOUBLE); csNumAggDist.push_back(8); - precisionAggDist.push_back(-1); - widthAggDist.push_back(sizeof(long double)); - scaleAggDist.push_back(0); + wideDecimalOrLongDouble(colUm, typeAggPm[colUm], + precisionAggPm, scaleAggPm, widthAggPm, + typeAggDist, scaleAggDist, precisionAggDist, widthAggDist); } // PM: put the count column for avg next to the sum // let fall through to add a count column for average function @@ -4614,11 +4624,10 @@ void TupleAggregateStep::prep2PhasesDistinctAggregate( { oidsAggDist.push_back(oidsAggUm[colUm]); keysAggDist.push_back(retKey); - scaleAggDist.push_back(0); - typeAggDist.push_back(CalpontSystemCatalog::LONGDOUBLE); csNumAggDist.push_back(8); - precisionAggDist.push_back(-1); - widthAggDist.push_back(sizeof(long double)); + wideDecimalOrLongDouble(colUm, typeAggUm[colUm], + precisionAggUm, scaleAggUm, widthAggUm, + typeAggDist, scaleAggDist, precisionAggDist, widthAggDist); } else { diff --git a/dbcon/mysql/ha_mcs_execplan.cpp b/dbcon/mysql/ha_mcs_execplan.cpp index bea224b8c..3ad93a9e8 100755 --- a/dbcon/mysql/ha_mcs_execplan.cpp +++ b/dbcon/mysql/ha_mcs_execplan.cpp @@ -342,7 +342,7 @@ bool nonConstFunc(Item_func* ifp) ***********************************************************/ void getColNameFromItem(std::ostringstream& ostream, Item* item) { -// Item_func doesn't have proper db.table.field values +// Item_func doesn't have proper db.table.field values // inherited from Item_ident. TBD what is the valid output. // !!!dynamic_cast fails compilation ostream << "'"; @@ -506,7 +506,7 @@ bool sortItemIsInGrouping(Item* sort_item, ORDER* groupcol) { Item* group_item = *(groupcol->item); found = (group_item->eq(sort_item, false)) ? true : false; - // Detect aggregation functions first then traverse + // Detect aggregation functions first then traverse // if sort field is a Func and group field // is either Field or Func // Consider nonConstFunc() check here @@ -524,9 +524,9 @@ bool sortItemIsInGrouping(Item* sort_item, ORDER* groupcol) /*@brief buildAggFrmTempField- build aggr func from extSELECT list item*/ /*********************************************************** * DESCRIPTION: - * Server adds additional aggregation items to extended SELECT list and - * references them in projection and HAVING. This f() finds - * corresponding item in extSelAggColsItems and builds + * Server adds additional aggregation items to extended SELECT list and + * references them in projection and HAVING. This f() finds + * corresponding item in extSelAggColsItems and builds * ReturnedColumn using the item. * PARAMETERS: * item Item* used to build aggregation @@ -585,7 +585,7 @@ ReturnedColumn* buildAggFrmTempField(Item* item, gp_walk_info& gwi) * searches for semantically equal SF in the list of already * applied equi predicates. * TODO - * We must move find_select_handler to either future or + * We must move find_select_handler to either future or * later execution phase. * PARAMETERS: * gwi main structure @@ -2289,7 +2289,7 @@ bool buildPredicateItem(Item_func* ifp, gp_walk_info* gwip) ConstantColumn* nlhs1 = new ConstantColumn("", ConstantColumn::NULLDATA); nlhs1->timeZone(gwip->thd->variables.time_zone->get_name()->ptr()); sop.reset(new PredicateOperator("isnull")); - sop->setOpType(lhs->resultType(), rhs->resultType()); + sop->setOpType(lhs->resultType(), rhs->resultType()); sfn1 = new SimpleFilter(sop, rhs, nlhs1); sfn1->timeZone(gwip->thd->variables.time_zone->get_name()->ptr()); ParseTree* ptpl = new ParseTree(sfn1); @@ -2307,7 +2307,7 @@ bool buildPredicateItem(Item_func* ifp, gp_walk_info* gwip) ptpn->right(ptpr); // a = b sop.reset(new PredicateOperator("=")); - sop->setOpType(lhs->resultType(), rhs->resultType()); + sop->setOpType(lhs->resultType(), rhs->resultType()); sfo = new SimpleFilter(sop, lhs->clone(), rhs->clone()); sfo->timeZone(gwip->thd->variables.time_zone->get_name()->ptr()); // OR with the NULL comparison tree @@ -3158,7 +3158,7 @@ CalpontSystemCatalog::ColType colType_MysqlToIDB (const Item* item) ct.colDataType = CalpontSystemCatalog::VARCHAR; // MCOL-4758 the longest TEXT we deal with is 16777215 so - // limit to that. + // limit to that. if (item->max_length < 16777215) ct.colWidth = item->max_length; else @@ -3444,7 +3444,7 @@ ReturnedColumn* buildReturnedColumn( gwi.fatalParseError = true; gwi.parseErrorText = IDBErrorInfo::instance()->errorMsg(ERR_NON_SUPPORT_SELECT_SUB); break; - + default: gwi.fatalParseError = true; gwi.parseErrorText = "Unknown REF item"; @@ -3541,7 +3541,7 @@ ReturnedColumn* buildReturnedColumn( if (rc) rc->charsetNumber(item->collation.collation->number); - + return rc; } @@ -3725,9 +3725,7 @@ ArithmeticColumn* buildArithmeticColumn( const CalpontSystemCatalog::ColType& leftColType = pt->left()->data()->resultType(); const CalpontSystemCatalog::ColType& rightColType = pt->right()->data()->resultType(); - // Only tinker with the type if all columns involved are decimal - if (datatypes::isDecimalOperands(mysqlType.colDataType, - leftColType.colDataType, rightColType.colDataType)) + if (datatypes::isDecimal(leftColType.colDataType) || datatypes::isDecimal(rightColType.colDataType)) { int32_t leftColWidth = leftColType.colWidth; int32_t rightColWidth = rightColType.colWidth; @@ -3742,6 +3740,8 @@ ArithmeticColumn* buildArithmeticColumn( int32_t scale1 = leftColType.scale; int32_t scale2 = rightColType.scale; + mysqlType.precision = datatypes::INT128MAXPRECISION; + if (funcName == "/" && (mysqlType.scale - (scale1 - scale2)) > datatypes::INT128MAXPRECISION) { @@ -4276,7 +4276,7 @@ ReturnedColumn* buildFunctionColumn( fc->resultType(ct); } fc->expressionId(ci->expressionId++); - // A few functions use a different collation than that found in + // A few functions use a different collation than that found in // the base ifp class if (funcName == "locate" || funcName == "find_in_set" || @@ -4421,7 +4421,7 @@ FunctionColumn* buildCaseFunction(Item_func* item, gp_walk_info& gwi, bool& nonS if ((item->functype() == Item_func::CASE_SEARCHED_FUNC) && (i < arg_offset)) { - // MCOL-1472 Nested CASE with an ISNULL predicate. We don't want the predicate + // MCOL-1472 Nested CASE with an ISNULL predicate. We don't want the predicate // to pull off of rcWorkStack, so we set this inCaseStmt flag to tell it // not to. gwi.inCaseStmt = true; @@ -4539,7 +4539,7 @@ ConstantColumn* buildDecimalColumn(Item* item, gp_walk_info& gwi) bool specialPrecision = false; // handle the case when the constant value is 0.12345678901234567890123456789012345678 - // In this case idp->decimal_precision() = 39, but we can + // 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; @@ -4735,7 +4735,7 @@ ReturnedColumn* buildAggregateColumn(Item* item, gp_walk_info& gwi) // Argument_count() is the # of formal parms to the agg fcn. Columnstore // only supports 1 argument except UDAnF, COUNT(DISTINC) and GROUP_CONCAT - if (isp->argument_count() != 1 + if (isp->argument_count() != 1 && isp->sum_func() != Item_sum::COUNT_DISTINCT_FUNC && isp->sum_func() != Item_sum::GROUP_CONCAT_FUNC && isp->sum_func() != Item_sum::UDF_SUM_FUNC) @@ -4813,7 +4813,7 @@ ReturnedColumn* buildAggregateColumn(Item* item, gp_walk_info& gwi) { Item* ord_col = *(*order_item)->item; - if (ord_col->type() == Item::CONST_ITEM + if (ord_col->type() == Item::CONST_ITEM && ord_col->cmp_type() == INT_RESULT) { Item_int* id = (Item_int*)ord_col; @@ -5058,6 +5058,19 @@ ReturnedColumn* buildAggregateColumn(Item* item, gp_walk_info& gwi) ct.precision = precision; ct.scale = scale; } + else if (datatypes::hasUnderlyingWideDecimalForSumAndAvg(ct.colDataType)) + { + uint32_t precision = datatypes::INT128MAXPRECISION; + uint32_t scale = ct.scale; + ct.colDataType = CalpontSystemCatalog::DECIMAL; + ct.colWidth = datatypes::MAXDECIMALWIDTH; + if (isAvg) + { + datatypes::Decimal::setScalePrecision4Avg(precision, scale); + } + ct.scale = scale; + ct.precision = precision; + } else { ct.colDataType = CalpontSystemCatalog::LONGDOUBLE; @@ -5164,7 +5177,7 @@ because it has multiple arguments."; { for (uint32_t i = 0; i < gwi.returnedCols.size(); i++) { - if (*ac == gwi.returnedCols[i].get() + if (*ac == gwi.returnedCols[i].get() && ac->alias() == gwi.returnedCols[i].get()->alias()) ac->expressionId(gwi.returnedCols[i]->expressionId()); } @@ -5922,7 +5935,7 @@ void gp_walk(const Item* item, void* arg) { boost::shared_ptr scsp(sc->clone()); gwip->scsp = scsp; - + if (col->type() == Item::FIELD_ITEM) { const auto &field_name = string(((Item_field*)item)->field_name.str); @@ -6155,8 +6168,8 @@ void gp_walk(const Item* item, void* arg) * functions or arithmetic expressions for vtable post process. */ void parse_item (Item* item, vector& field_vec, - bool& hasNonSupportItem, - uint16_t& parseInfo, + bool& hasNonSupportItem, + uint16_t& parseInfo, gp_walk_info* gwi) { Item::Type itype = item->type(); @@ -6226,7 +6239,7 @@ void parse_item (Item* item, vector& field_vec, // special handling for count(*). This should not be treated as constant. if (isp->argument_count() == 1 && - ( sfitempp[0]->type() == Item::CONST_ITEM && + ( sfitempp[0]->type() == Item::CONST_ITEM && (sfitempp[0]->cmp_type() == INT_RESULT || sfitempp[0]->cmp_type() == STRING_RESULT || sfitempp[0]->cmp_type() == REAL_RESULT || @@ -6250,7 +6263,7 @@ void parse_item (Item* item, vector& field_vec, ReturnedColumn* rc = NULL; if (gwi) rc = buildAggFrmTempField(ref, *gwi); - + if (!rc) { Item_field* ifp = reinterpret_cast(*(ref->ref)); @@ -6476,7 +6489,7 @@ int processFrom(bool &isUnion, setError(gwi.thd, ER_CHECK_NOT_IMPLEMENTED, gwi.parseErrorText, gwi); return ER_CHECK_NOT_IMPLEMENTED; } - + string viewName = getViewName(table_ptr); if (lower_case_table_names) { @@ -7173,7 +7186,7 @@ int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, } setExecutionParams(gwi, csep); - + gwi.subSelectType = csep->subType(); uint32_t sessionID = csep->sessionID(); gwi.sessionid = sessionID; @@ -7478,7 +7491,7 @@ int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, { Message::Args args; args.add(ifp->func_name()); - gwi.parseErrorText = + gwi.parseErrorText = IDBErrorInfo::instance()->errorMsg(ERR_NON_SUPPORTED_FUNCTION, args); setError(gwi.thd, ER_CHECK_NOT_IMPLEMENTED, gwi.parseErrorText, gwi); return ER_CHECK_NOT_IMPLEMENTED; @@ -7521,7 +7534,7 @@ int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, } // MCOL-2178 This switch doesn't handl // ROW_ - default: + default: { IDEBUG(cerr << "Warning unsupported cmp_type() in projection" << endl); //noop @@ -7651,7 +7664,7 @@ int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, } break; } - + default: { @@ -8141,7 +8154,7 @@ int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, if ((*(ordercol->item))->type() == Item::WINDOW_FUNC_ITEM) gwi.hasWindowFunc = true; // MCOL-2166 Looking for this sorting item in GROUP_BY items list. - // Shouldn't look into this if query doesn't have GROUP BY or + // Shouldn't look into this if query doesn't have GROUP BY or // aggregations if(select_lex.agg_func_used() && select_lex.group_list.first && !sortItemIsInGrouping(*ordercol->item, @@ -8180,9 +8193,9 @@ int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, Item* ord_item = *(ordercol->item); // ignore not_used column on order by. - if ((ord_item->type() == Item::CONST_ITEM - && ord_item->cmp_type() == INT_RESULT) - && ord_item->full_name() + if ((ord_item->type() == Item::CONST_ITEM + && ord_item->cmp_type() == INT_RESULT) + && ord_item->full_name() && !strcmp(ord_item->full_name(), "Not_used")) { continue; @@ -8325,7 +8338,7 @@ int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, for (; ordercol; ordercol = ordercol->next) { Item* ord_item = *(ordercol->item); - + if (ord_item->name.length) { // for union order by 1 case. For unknown reason, it doesn't show in_field_list @@ -8681,7 +8694,7 @@ ConstantColumn* buildConstColFromFilter(SimpleColumn* originalSC, continue; op = simpFilter->op(); - execplan::ReturnedColumn* rc = dynamic_cast(simpleCol); + execplan::ReturnedColumn* rc = dynamic_cast(simpleCol); // The filter could have any kind of op if ( originalSC->sameColumn(rc) ) @@ -9183,7 +9196,7 @@ int getGroupPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, cal_gro boost::shared_ptr spac(ac); gwi.returnedCols.push_back(spac); // This item could be used in projection or HAVING later. - gwi.extSelAggColsItems.push_back(item); + gwi.extSelAggColsItems.push_back(item); break; } @@ -9973,9 +9986,9 @@ int getGroupPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, cal_gro bool nonAggField = true; // ignore not_used column on order by. - if ((ord_item->type() == Item::CONST_ITEM - && ord_item->cmp_type() == INT_RESULT) - && ord_item->full_name() + if ((ord_item->type() == Item::CONST_ITEM + && ord_item->cmp_type() == INT_RESULT) + && ord_item->full_name() && !strcmp(ord_item->full_name(), "Not_used")) { continue; @@ -10360,13 +10373,13 @@ int getGroupPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, cal_gro // LIMIT and OFFSET are extracted from TABLE_LIST elements. // All of JOIN-ed tables contain relevant limit and offset. uint64_t limit = (uint64_t)-1; - if (gi.groupByTables->select_lex->limit_params.select_limit && + if (gi.groupByTables->select_lex->limit_params.select_limit && ( limit = static_cast(gi.groupByTables->select_lex->limit_params.select_limit)->val_int() ) && limit != (uint64_t)-1 ) { csep->limitNum(limit); } - else if (csep->hasOrderBy()) + else if (csep->hasOrderBy()) { // We use LimitedOrderBy so set the limit to // go through the check in addOrderByAndLimit diff --git a/utils/rowgroup/rowaggregation.cpp b/utils/rowgroup/rowaggregation.cpp index e87cb55df..3d02e62a4 100755 --- a/utils/rowgroup/rowaggregation.cpp +++ b/utils/rowgroup/rowaggregation.cpp @@ -1278,7 +1278,7 @@ void RowAggregation::doMinMax(const Row& rowIn, int64_t colIn, int64_t colOut, i //------------------------------------------------------------------------------ void RowAggregation::doSum(const Row& rowIn, int64_t colIn, int64_t colOut, int funcType) { - int colDataType = rowIn.getColType(colIn); + datatypes::SystemCatalog::ColDataType colDataType = rowIn.getColType(colIn); long double valIn = 0; bool isWideDataType = false; void *wideValInPtr = nullptr; @@ -1328,7 +1328,7 @@ void RowAggregation::doSum(const Row& rowIn, int64_t colIn, int64_t colOut, int idbassert(0); throw std::logic_error("RowAggregation::doSum(): DECIMAL bad length."); } - + break; } @@ -1379,9 +1379,26 @@ void RowAggregation::doSum(const Row& rowIn, int64_t colIn, int64_t colOut, int break; } } - if (LIKELY(!isWideDataType)) + + bool notFirstValue = !isNull(fRowGroupOut, fRow, colOut); + + if (datatypes::hasUnderlyingWideDecimalForSumAndAvg(colDataType) || isWideDataType) { - if (LIKELY(!isNull(fRowGroupOut, fRow, colOut))) + if (LIKELY(notFirstValue)) + { + int128_t *valOutPtr = fRow.getBinaryField(colOut); + int128_t sum = (isWideDataType) ? *valOutPtr + *reinterpret_cast(wideValInPtr) : *valOutPtr + valIn; + fRow.setBinaryField(&sum, colOut); + } + else + { + int128_t sum = (isWideDataType) ? *reinterpret_cast(wideValInPtr) : valIn; + fRow.setBinaryField(&sum, colOut); + } + } + else + { + if (notFirstValue) { long double valOut = fRow.getLongDoubleField(colOut); fRow.setLongDoubleField(valIn+valOut, colOut); @@ -1390,22 +1407,7 @@ void RowAggregation::doSum(const Row& rowIn, int64_t colIn, int64_t colOut, int { fRow.setLongDoubleField(valIn, colOut); } - } - else - { - uint32_t offset = fRow.getOffset(colOut); - int128_t* dec = reinterpret_cast(wideValInPtr); - if (LIKELY(!isNull(fRowGroupOut, fRow, colOut))) - { - int128_t *valOutPtr = fRow.getBinaryField(colOut); - int128_t sum = *valOutPtr + *dec; - fRow.setBinaryField_offset(&sum, sizeof(sum), offset); - } - else - { - fRow.setBinaryField_offset(dec, sizeof(*dec), offset); - } - } // end-of isWideDataType block + } // end-of long double processing block } //------------------------------------------------------------------------------ @@ -1823,9 +1825,8 @@ void RowAggregation::doAvg(const Row& rowIn, int64_t colIn, int64_t colOut, int6 if (rowIn.isNullValue(colIn)) return; - int colDataType = rowIn.getColType(colIn); + datatypes::SystemCatalog::ColDataType colDataType = rowIn.getColType(colIn); long double valIn = 0; - long double valOut = fRow.getLongDoubleField(colOut); bool isWideDataType = false; void *wideValInPtr = nullptr; @@ -1907,8 +1908,6 @@ void RowAggregation::doAvg(const Row& rowIn, int64_t colIn, int64_t colOut, int6 // min(count) = 0 uint64_t count = fRow.getUintField(colAux); - bool notFirstValue = count > 0; - // Set count column if (merge) { @@ -1919,29 +1918,34 @@ void RowAggregation::doAvg(const Row& rowIn, int64_t colIn, int64_t colOut, int6 fRow.setUintField<8>(count + 1, colAux); } - // Set sum column - if (LIKELY(!isWideDataType)) + bool notFirstValue = count > 0; + + if (datatypes::hasUnderlyingWideDecimalForSumAndAvg(colDataType) || isWideDataType) { - if (LIKELY(notFirstValue)) - fRow.setLongDoubleField(valIn + valOut, colOut); - else // This is the first value - fRow.setLongDoubleField(valIn, colOut); - } - else - { - uint32_t offset = fRow.getOffset(colOut); - int128_t* dec = reinterpret_cast(wideValInPtr); if (LIKELY(notFirstValue)) { int128_t *valOutPtr = fRow.getBinaryField(colOut); - int128_t sum = *valOutPtr + *dec; - fRow.setBinaryField_offset(&sum, sizeof(sum), offset); + int128_t sum = (isWideDataType) ? *valOutPtr + *reinterpret_cast(wideValInPtr) : *valOutPtr + valIn; + fRow.setBinaryField(&sum, colOut); } else { - fRow.setBinaryField_offset(dec, sizeof(*dec), offset); + int128_t sum = (isWideDataType) ? *reinterpret_cast(wideValInPtr) : valIn; + fRow.setBinaryField(&sum, colOut); } } + else + { + if (LIKELY(notFirstValue)) + { + long double valOut = fRow.getLongDoubleField(colOut); + fRow.setLongDoubleField(valIn+valOut, colOut); + } + else + { + fRow.setLongDoubleField(valIn, colOut); + } + } // end-of long double processing block } @@ -3614,7 +3618,7 @@ void RowAggregationUM::doNotNullConstantAggregate(const ConstantAggData& aggData { fRow.setIntField(strtol(aggData.fConstValue.c_str(), nullptr, 10), colOut); } - break; + break; // AVG should not be uint32_t result type. case execplan::CalpontSystemCatalog::UTINYINT: @@ -3777,7 +3781,7 @@ void RowAggregationUM::doNotNullConstantAggregate(const ConstantAggData& aggData // TODO: isn't precision loss possible below? dbl *= datatypes::scaleDivisor(fRowGroupOut->getScale()[i]); dbl *= rowCnt; - + if ((dbl > 0 && dbl > (double) numeric_limits::max()) || (dbl < 0 && dbl < (double) numeric_limits::min())) throw logging::QueryDataExcept(overflowMsg, logging::aggregateDataErr); @@ -4280,9 +4284,8 @@ void RowAggregationUMP2::doAvg(const Row& rowIn, int64_t colIn, int64_t colOut, if (rowIn.isNullValue(colIn)) return; - int colDataType = rowIn.getColType(colIn); + datatypes::SystemCatalog::ColDataType colDataType = rowIn.getColType(colIn); long double valIn = 0; - long double valOut = fRow.getLongDoubleField(colOut); bool isWideDataType = false; void *wideValInPtr = nullptr; @@ -4362,37 +4365,39 @@ void RowAggregationUMP2::doAvg(const Row& rowIn, int64_t colIn, int64_t colOut, } } - uint64_t cnt = fRow.getUintField(colAux); - if (LIKELY(!isWideDataType)) + uint64_t count = fRow.getUintField(colAux); + bool notFirstValue = count > 0; + + if (datatypes::hasUnderlyingWideDecimalForSumAndAvg(colDataType) || isWideDataType) { - if (LIKELY(cnt > 0)) + if (LIKELY(notFirstValue)) { - fRow.setLongDoubleField(valIn + valOut, colOut); - fRow.setUintField(rowIn.getUintField(colIn + 1) + cnt, colAux); + int128_t *valOutPtr = fRow.getBinaryField(colOut); + int128_t sum = (isWideDataType) ? *valOutPtr + *reinterpret_cast(wideValInPtr) : *valOutPtr + valIn; + fRow.setUintField(rowIn.getUintField(colIn + 1) + count, colAux); + fRow.setBinaryField(&sum, colOut); } else { - fRow.setLongDoubleField(valIn, colOut); + int128_t sum = (isWideDataType) ? *reinterpret_cast(wideValInPtr) : valIn; fRow.setUintField(rowIn.getUintField(colIn + 1), colAux); + fRow.setBinaryField(&sum, colOut); } } else { - uint32_t offset = fRow.getOffset(colOut); - int128_t* dec = reinterpret_cast(wideValInPtr); - if (LIKELY(cnt > 0)) + if (LIKELY(notFirstValue)) { - int128_t *valOutPtr = fRow.getBinaryField(colOut); - int128_t sum = *valOutPtr + *dec; - fRow.setBinaryField_offset(&sum, sizeof(sum), offset); - fRow.setUintField(rowIn.getUintField(colIn + 1) + cnt, colAux); + long double valOut = fRow.getLongDoubleField(colOut); + fRow.setUintField(rowIn.getUintField(colIn + 1) + count, colAux); + fRow.setLongDoubleField(valIn+valOut, colOut); } else { - fRow.setBinaryField_offset(dec, sizeof(*dec), offset); fRow.setUintField(rowIn.getUintField(colIn + 1), colAux); + fRow.setLongDoubleField(valIn, colOut); } - } + } // end-of long double processing block } //------------------------------------------------------------------------------