From a2aa4b84796c7f1cb327f3ad469066e3cb42127b Mon Sep 17 00:00:00 2001 From: David Hall Date: Mon, 25 Feb 2019 14:54:46 -0600 Subject: [PATCH] MCOL-1822 Intermediate checkin. DISTINCT not working. --- dbcon/execplan/aggregatecolumn.h | 9 + dbcon/execplan/arithmeticcolumn.h | 5 + dbcon/execplan/constantcolumn.cpp | 1 - dbcon/execplan/functioncolumn.h | 4 + dbcon/execplan/operator.h | 4 + dbcon/execplan/parsetree.h | 8 + dbcon/execplan/predicateoperator.cpp | 10 + dbcon/execplan/predicateoperator.h | 29 + dbcon/execplan/treenode.h | 98 ++- dbcon/execplan/windowfunctioncolumn.h | 6 + dbcon/joblist/batchprimitiveprocessor-jl.cpp | 56 +- dbcon/joblist/jlf_common.h | 4 - dbcon/joblist/jlf_subquery.cpp | 5 + dbcon/joblist/jlf_tuplejoblist.cpp | 19 +- dbcon/joblist/joblistfactory.cpp | 49 +- dbcon/joblist/joblisttypes.h | 2 +- dbcon/joblist/primitivestep.h | 4 +- dbcon/joblist/rowestimator.cpp | 2 +- dbcon/joblist/rowestimator.h | 2 +- dbcon/joblist/subquerytransformer.cpp | 11 +- dbcon/joblist/tupleaggregatestep.cpp | 389 +++------ dbcon/mysql/ha_calpont_execplan.cpp | 79 +- dbcon/mysql/ha_calpont_impl.cpp | 69 +- exemgr/main.cpp | 3 +- utils/common/nullvaluemanip.cpp | 5 +- utils/dataconvert/dataconvert.cpp | 3 +- utils/funcexp/func_abs.cpp | 8 + utils/funcexp/func_case.cpp | 47 ++ utils/funcexp/func_cast.cpp | 94 +++ utils/funcexp/func_ceil.cpp | 64 ++ utils/funcexp/func_coalesce.cpp | 25 + utils/funcexp/func_exp.cpp | 32 + utils/funcexp/func_floor.cpp | 60 ++ utils/funcexp/func_from_unixtime.cpp | 8 + utils/funcexp/func_greatest.cpp | 20 + utils/funcexp/func_if.cpp | 18 + utils/funcexp/func_ifnull.cpp | 19 + utils/funcexp/func_in.cpp | 21 + utils/funcexp/func_isnull.cpp | 4 + utils/funcexp/func_least.cpp | 20 + utils/funcexp/func_math.cpp | 20 + utils/funcexp/func_mod.cpp | 132 +++ utils/funcexp/func_nullif.cpp | 103 +++ utils/funcexp/func_pow.cpp | 38 + utils/funcexp/func_round.cpp | 97 ++- utils/funcexp/func_truncate.cpp | 82 +- utils/funcexp/funchelpers.h | 10 + utils/funcexp/functor.cpp | 6 + utils/funcexp/functor.h | 12 + utils/funcexp/functor_all.h | 40 + utils/funcexp/functor_bool.h | 8 + utils/funcexp/functor_dtm.h | 23 + utils/funcexp/functor_export.h | 8 + utils/funcexp/functor_int.h | 8 + utils/funcexp/functor_real.h | 54 +- utils/funcexp/functor_str.h | 2 +- utils/joiner/tuplejoiner.cpp | 478 +++++++++-- utils/joiner/tuplejoiner.h | 49 +- utils/rowgroup/rowaggregation.cpp | 827 ++++++++----------- utils/rowgroup/rowaggregation.h | 12 +- utils/udfsdk/udfsdk.cpp | 16 + utils/udfsdk/udfsdk.h | 16 + utils/windowfunction/frameboundrange.cpp | 14 + utils/windowfunction/wf_nth_value.cpp | 6 + utils/windowfunction/wf_percentile.cpp | 7 +- utils/windowfunction/wf_udaf.cpp | 15 + utils/windowfunction/windowfunctiontype.cpp | 10 + 67 files changed, 2391 insertions(+), 1018 deletions(-) diff --git a/dbcon/execplan/aggregatecolumn.h b/dbcon/execplan/aggregatecolumn.h index 07bbab0b6..443be7eff 100644 --- a/dbcon/execplan/aggregatecolumn.h +++ b/dbcon/execplan/aggregatecolumn.h @@ -384,6 +384,15 @@ public: return TreeNode::getDoubleVal(); } + /** + * F&E + */ + virtual long double getLongDoubleVal(rowgroup::Row& row, bool& isNull) + { + evaluate(row, isNull); + return TreeNode::getLongDoubleVal(); + } + /** * F&E */ diff --git a/dbcon/execplan/arithmeticcolumn.h b/dbcon/execplan/arithmeticcolumn.h index 191416fbf..b4e6ab3a9 100644 --- a/dbcon/execplan/arithmeticcolumn.h +++ b/dbcon/execplan/arithmeticcolumn.h @@ -233,6 +233,11 @@ public: return fExpression->getDoubleVal(row, isNull); } + virtual long double getLongDoubleVal(rowgroup::Row& row, bool& isNull) + { + return fExpression->getLongDoubleVal(row, isNull); + } + virtual IDB_Decimal getDecimalVal(rowgroup::Row& row, bool& isNull) { return fExpression->getDecimalVal(row, isNull); diff --git a/dbcon/execplan/constantcolumn.cpp b/dbcon/execplan/constantcolumn.cpp index 60d99580d..ea8bb913c 100644 --- a/dbcon/execplan/constantcolumn.cpp +++ b/dbcon/execplan/constantcolumn.cpp @@ -316,7 +316,6 @@ void ConstantColumn::serialize(messageqcpp::ByteStream& b) const b << (uint64_t)fResult.decimalVal.value; b << (uint8_t)fResult.decimalVal.scale; b << (uint8_t)fResult.decimalVal.precision; - b << fResult.longDoubleVal; } void ConstantColumn::unserialize(messageqcpp::ByteStream& b) diff --git a/dbcon/execplan/functioncolumn.h b/dbcon/execplan/functioncolumn.h index 5a099d1d2..59ed92146 100644 --- a/dbcon/execplan/functioncolumn.h +++ b/dbcon/execplan/functioncolumn.h @@ -225,6 +225,10 @@ public: { return fFunctor->getDoubleVal(row, fFunctionParms, isNull, fOperationType); } + virtual long double getLongDoubleVal(rowgroup::Row& row, bool& isNull) + { + return fFunctor->getLongDoubleVal(row, fFunctionParms, isNull, fOperationType); + } virtual IDB_Decimal getDecimalVal(rowgroup::Row& row, bool& isNull) { IDB_Decimal decimal = fFunctor->getDecimalVal(row, fFunctionParms, isNull, fOperationType); diff --git a/dbcon/execplan/operator.h b/dbcon/execplan/operator.h index 1a33dcb94..a253c6593 100644 --- a/dbcon/execplan/operator.h +++ b/dbcon/execplan/operator.h @@ -178,6 +178,10 @@ public: { return fResult.doubleVal; } + virtual long double getLongDoubleVal(rowgroup::Row& row, bool& isNull, ParseTree* lop, ParseTree* rop) + { + return fResult.longDoubleVal; + } virtual IDB_Decimal getDecimalVal(rowgroup::Row& row, bool& isNull, ParseTree* lop, ParseTree* rop) { return fResult.decimalVal; diff --git a/dbcon/execplan/parsetree.h b/dbcon/execplan/parsetree.h index 2ad41b6bb..112649f81 100644 --- a/dbcon/execplan/parsetree.h +++ b/dbcon/execplan/parsetree.h @@ -250,6 +250,14 @@ public: return fData->getDoubleVal(row, isNull); } + inline long double getLongDoubleVal(rowgroup::Row& row, bool& isNull) + { + if (fLeft && fRight) + return (reinterpret_cast(fData))->getLongDoubleVal(row, isNull, fLeft, fRight); + else + return fData->getLongDoubleVal(row, isNull); + } + inline IDB_Decimal getDecimalVal(rowgroup::Row& row, bool& isNull) { if (fLeft && fRight) diff --git a/dbcon/execplan/predicateoperator.cpp b/dbcon/execplan/predicateoperator.cpp index 166a8edc0..6f84d2353 100644 --- a/dbcon/execplan/predicateoperator.cpp +++ b/dbcon/execplan/predicateoperator.cpp @@ -317,6 +317,10 @@ void PredicateOperator::setOpType(Type& l, Type& r) fOperationType.colWidth = 8; break; + case execplan::CalpontSystemCatalog::LONGDOUBLE: + fOperationType.colDataType = execplan::CalpontSystemCatalog::LONGDOUBLE; + fOperationType.colWidth = 16; + break; default: fOperationType.colDataType = execplan::CalpontSystemCatalog::DOUBLE; fOperationType.colWidth = 8; @@ -370,6 +374,12 @@ void PredicateOperator::setOpType(Type& l, Type& r) fOperationType.colWidth = 255; } } + else if (l.colDataType == execplan::CalpontSystemCatalog::LONGDOUBLE || + r.colDataType == execplan::CalpontSystemCatalog::LONGDOUBLE) + { + fOperationType.colDataType = execplan::CalpontSystemCatalog::LONGDOUBLE; + fOperationType.colWidth = 16; + } else { fOperationType.colDataType = execplan::CalpontSystemCatalog::DOUBLE; diff --git a/dbcon/execplan/predicateoperator.h b/dbcon/execplan/predicateoperator.h index 6253d9389..30251c510 100644 --- a/dbcon/execplan/predicateoperator.h +++ b/dbcon/execplan/predicateoperator.h @@ -256,6 +256,35 @@ inline bool PredicateOperator::getBoolVal(rowgroup::Row& row, bool& isNull, Retu return numericCompare(val1, rop->getDoubleVal(row, isNull)) && !isNull; } + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + if (fOp == OP_ISNULL) + { + lop->getLongDoubleVal(row, isNull); + bool ret = isNull; + isNull = false; + return ret; + } + + if (fOp == OP_ISNOTNULL) + { + lop->getLongDoubleVal(row, isNull); + bool ret = isNull; + isNull = false; + return !ret; + } + + if (isNull) + return false; + + long double val1 = lop->getLongDoubleVal(row, isNull); + + if (isNull) + return false; + + return numericCompare(val1, rop->getLongDoubleVal(row, isNull)) && !isNull; + } + case execplan::CalpontSystemCatalog::DECIMAL: case execplan::CalpontSystemCatalog::UDECIMAL: { diff --git a/dbcon/execplan/treenode.h b/dbcon/execplan/treenode.h index 126d7ee6c..0fc836dad 100644 --- a/dbcon/execplan/treenode.h +++ b/dbcon/execplan/treenode.h @@ -239,7 +239,7 @@ inline std::string removeTrailing0(char* val, uint32_t length) struct Result { Result(): intVal(0), uintVal(0), origIntVal(0), dummy(0), - doubleVal(0), floatVal(0), boolVal(false), + doubleVal(0), longDoubleVal(0), floatVal(0), boolVal(false), strVal(""), decimalVal(IDB_Decimal(0, 0, 0)), valueConverted(false) {} int64_t intVal; @@ -409,6 +409,7 @@ public: inline uint64_t getUintVal(); inline float getFloatVal(); inline double getDoubleVal(); + inline long double getLongDoubleVal(); inline IDB_Decimal getDecimalVal(); inline int32_t getDateIntVal(); inline int64_t getDatetimeIntVal(); @@ -957,6 +958,9 @@ inline double TreeNode::getDoubleVal() case CalpontSystemCatalog::UDOUBLE: return fResult.doubleVal; + case CalpontSystemCatalog::LONGDOUBLE: + return (double)fResult.longDoubleVal; + case CalpontSystemCatalog::DECIMAL: case CalpontSystemCatalog::UDECIMAL: { @@ -975,6 +979,74 @@ inline double TreeNode::getDoubleVal() return fResult.doubleVal; } +inline long double TreeNode::getLongDoubleVal() +{ + switch (fResultType.colDataType) + { + case CalpontSystemCatalog::CHAR: + if (fResultType.colWidth <= 8) + return strtold((char*)(&fResult.origIntVal), NULL); + + return strtold(fResult.strVal.c_str(), NULL); + + case CalpontSystemCatalog::VARCHAR: + if (fResultType.colWidth <= 7) + return strtold((char*)(&fResult.origIntVal), NULL); + + return strtold(fResult.strVal.c_str(), NULL); + + //FIXME: ??? + case CalpontSystemCatalog::VARBINARY: + case CalpontSystemCatalog::BLOB: + case CalpontSystemCatalog::TEXT: + if (fResultType.colWidth <= 7) + return strtold((char*)(&fResult.origIntVal), NULL); + + return strtold(fResult.strVal.c_str(), NULL); + + case CalpontSystemCatalog::BIGINT: + case CalpontSystemCatalog::TINYINT: + case CalpontSystemCatalog::SMALLINT: + case CalpontSystemCatalog::MEDINT: + case CalpontSystemCatalog::INT: + return (double)fResult.intVal; + + case CalpontSystemCatalog::UBIGINT: + case CalpontSystemCatalog::UTINYINT: + case CalpontSystemCatalog::USMALLINT: + case CalpontSystemCatalog::UMEDINT: + case CalpontSystemCatalog::UINT: + return (long double)fResult.uintVal; + + case CalpontSystemCatalog::FLOAT: + case CalpontSystemCatalog::UFLOAT: + return (long double)fResult.floatVal; + + case CalpontSystemCatalog::DOUBLE: + case CalpontSystemCatalog::UDOUBLE: + return (long double)fResult.doubleVal; + + case CalpontSystemCatalog::LONGDOUBLE: + return (long double)fResult.longDoubleVal; + + case CalpontSystemCatalog::DECIMAL: + case CalpontSystemCatalog::UDECIMAL: + { + // this may not be accurate. if this is problematic, change to pre-calculated power array. + return (long double)(fResult.decimalVal.value / pow((long double)10, fResult.decimalVal.scale)); + } + + case CalpontSystemCatalog::DATE: + case CalpontSystemCatalog::DATETIME: + case CalpontSystemCatalog::TIME: + return (long double)fResult.intVal; + + default: + throw logging::InvalidConversionExcept("TreeNode::getDoubleVal: Invalid conversion."); + } + + return fResult.doubleVal; +} inline IDB_Decimal TreeNode::getDecimalVal() { switch (fResultType.colDataType) @@ -993,7 +1065,7 @@ inline IDB_Decimal TreeNode::getDecimalVal() case CalpontSystemCatalog::INT: case CalpontSystemCatalog::SMALLINT: case CalpontSystemCatalog::TINYINT: - fResult.decimalVal.value = (int64_t)(fResult.intVal * pow((double)10, fResultType.scale)); + fResult.decimalVal.value = (int64_t)(fResult.intVal * pow((double)10.0, fResultType.scale)); fResult.decimalVal.scale = fResultType.scale; fResult.decimalVal.precision = fResultType.precision; break; @@ -1003,11 +1075,28 @@ inline IDB_Decimal TreeNode::getDecimalVal() case CalpontSystemCatalog::UINT: case CalpontSystemCatalog::USMALLINT: case CalpontSystemCatalog::UTINYINT: - fResult.decimalVal.value = (int64_t)(fResult.uintVal * pow((double)10, fResultType.scale)); + fResult.decimalVal.value = (int64_t)(fResult.uintVal * pow((double)10.0, fResultType.scale)); fResult.decimalVal.scale = fResultType.scale; fResult.decimalVal.precision = fResultType.precision; break; + case CalpontSystemCatalog::LONGDOUBLE: + { + long double dlScaled = fResult.longDoubleVal; + if (fResultType.scale > 0) + { + dlScaled= fResult.longDoubleVal * pow((double)10.0, fResultType.scale); + } + if (dlScaled > (double)MAX_BIGINT) + { + throw logging::InvalidConversionExcept("TreeNode::getDecimalVal: decimal overflow."); + } + fResult.decimalVal.value = (int64_t)roundl((fResult.longDoubleVal * pow((double)10.0, fResultType.scale))); + fResult.decimalVal.scale = fResultType.scale; + fResult.decimalVal.precision = fResultType.precision; + } + break; + case CalpontSystemCatalog::DATE: throw logging::InvalidConversionExcept("TreeNode::getDecimalVal: Invalid conversion from date."); @@ -1029,9 +1118,6 @@ inline IDB_Decimal TreeNode::getDecimalVal() case CalpontSystemCatalog::UDOUBLE: throw logging::InvalidConversionExcept("TreeNode::getDecimalVal: non-support conversion from double unsigned"); - case CalpontSystemCatalog::LONGDOUBLE: - throw logging::InvalidConversionExcept("TreeNode::getDecimalVal: non-support conversion from long double"); - case CalpontSystemCatalog::DECIMAL: case CalpontSystemCatalog::UDECIMAL: return fResult.decimalVal; diff --git a/dbcon/execplan/windowfunctioncolumn.h b/dbcon/execplan/windowfunctioncolumn.h index 47c82b805..732d956cd 100644 --- a/dbcon/execplan/windowfunctioncolumn.h +++ b/dbcon/execplan/windowfunctioncolumn.h @@ -202,6 +202,12 @@ public: return TreeNode::getDoubleVal(); } + virtual long double getLongDoubleVal(rowgroup::Row& row, bool& isNull) + { + evaluate(row, isNull); + return TreeNode::getLongDoubleVal(); + } + virtual IDB_Decimal getDecimalVal(rowgroup::Row& row, bool& isNull) { evaluate(row, isNull); diff --git a/dbcon/joblist/batchprimitiveprocessor-jl.cpp b/dbcon/joblist/batchprimitiveprocessor-jl.cpp index 8adf80e12..e21f7cca4 100644 --- a/dbcon/joblist/batchprimitiveprocessor-jl.cpp +++ b/dbcon/joblist/batchprimitiveprocessor-jl.cpp @@ -1411,12 +1411,19 @@ bool BatchPrimitiveProcessorJL::nextTupleJoinerMsg(ByteStream& bs) } } - bs << (uint8_t) isNull; - if (!isNull) { tlData = makeTypelessKey(r, smallSideKeys[joinerNum], - tlKeyLens[joinerNum], &fa); + tlKeyLens[joinerNum], &fa, + largeSideRG, tJoiners[joinerNum]->getLargeKeyColumns()); + if (tlData.len == 0) + { + isNull = true; + } + } + bs << (uint8_t) isNull; + if (!isNull) + { tlData.serialize(bs); bs << i; } @@ -1442,7 +1449,48 @@ bool BatchPrimitiveProcessorJL::nextTupleJoinerMsg(ByteStream& bs) { r.setPointer((*tSmallSide)[i]); - if (r.isUnsigned(smallKeyCol)) + if ( r.getColType(smallKeyCol)== CalpontSystemCatalog::LONGDOUBLE) + { + // Small side is a long double. Since CS can't store larger than DOUBLE, + // we need to convert to whatever type large side is -- double or int64 + long double smallkeyld = r.getLongDoubleField(smallKeyCol); + switch (largeSideRG.getColType(tJoiners[joinerNum]->getLargeKeyColumns()[0])) + { + case CalpontSystemCatalog::DOUBLE: + case CalpontSystemCatalog::UDOUBLE: + case CalpontSystemCatalog::FLOAT: + case CalpontSystemCatalog::UFLOAT: + { + if (smallkeyld > MAX_DOUBLE || smallkeyld < MIN_DOUBLE) + { + smallkey = joblist::UBIGINTEMPTYROW; + } + else + { + double d = (double)smallkeyld; + smallkey = *(int64_t*)&d; + } + break; + } + default: + { + if (r.isUnsigned(smallKeyCol) && smallkeyld > MAX_UBIGINT) + { + smallkey = joblist::UBIGINTEMPTYROW; + } + else if (smallkeyld > MAX_BIGINT || smallkeyld < MIN_BIGINT) + { + smallkey = joblist::UBIGINTEMPTYROW; + } + else + { + smallkey = (int64_t)smallkeyld; + } + break; + } + } + } + else if (r.isUnsigned(smallKeyCol)) smallkey = r.getUintField(smallKeyCol); else smallkey = r.getIntField(smallKeyCol); diff --git a/dbcon/joblist/jlf_common.h b/dbcon/joblist/jlf_common.h index 669a26b4b..2ae8018c8 100644 --- a/dbcon/joblist/jlf_common.h +++ b/dbcon/joblist/jlf_common.h @@ -277,10 +277,6 @@ struct JobInfo std::multimap cloneAggregateColMap; std::vector > aggEidIndexList; - // for AVG to support CNX_USE_DECIMAL_SCALE - // map - std::map scaleOfAvg; - // table pairs with incompatible join which is treated as expression std::map incompatibleJoinMap; diff --git a/dbcon/joblist/jlf_subquery.cpp b/dbcon/joblist/jlf_subquery.cpp index 1e4eaeeec..08592d314 100644 --- a/dbcon/joblist/jlf_subquery.cpp +++ b/dbcon/joblist/jlf_subquery.cpp @@ -125,6 +125,11 @@ void getColumnValue(ConstantColumn** cc, uint64_t i, const Row& row) *cc = new ConstantColumn(oss.str(), row.getDoubleField(i)); break; + case CalpontSystemCatalog::LONGDOUBLE: + oss << fixed << row.getLongDoubleField(i); + *cc = new ConstantColumn(oss.str(), row.getLongDoubleField(i)); + break; + case CalpontSystemCatalog::DATE: oss << dataconvert::DataConvert::dateToString(row.getUintField<4>(i)); *cc = new ConstantColumn(oss.str()); diff --git a/dbcon/joblist/jlf_tuplejoblist.cpp b/dbcon/joblist/jlf_tuplejoblist.cpp index b006eb90c..996f1369d 100644 --- a/dbcon/joblist/jlf_tuplejoblist.cpp +++ b/dbcon/joblist/jlf_tuplejoblist.cpp @@ -1454,7 +1454,10 @@ bool addFunctionJoin(vector& joinedTables, JobStepVector& joinSteps, TupleInfo ti1 = getTupleInfo(key1, jobInfo); TupleInfo ti2 = getTupleInfo(key2, jobInfo); - if (ti1.dtype == CalpontSystemCatalog::CHAR || ti1.dtype == CalpontSystemCatalog::VARCHAR || ti1.dtype == CalpontSystemCatalog::TEXT) + if (ti1.dtype == CalpontSystemCatalog::CHAR + || ti1.dtype == CalpontSystemCatalog::VARCHAR + || ti1.dtype == CalpontSystemCatalog::TEXT) +// || ti1.dtype == CalpontSystemCatalog::LONGDOUBLE) m1->second.fTypeless = m2->second.fTypeless = true; // ti2 is compatible else m1->second.fTypeless = m2->second.fTypeless = false; @@ -3623,9 +3626,21 @@ void associateTupleJobSteps(JobStepVector& querySteps, JobStepVector& projectSte TupleInfo ti2(getTupleInfo(key2, jobInfo)); if (ti1.width > 8 || ti2.width > 8) - m1->second.fTypeless = m2->second.fTypeless = true; + { + if (ti1.dtype == execplan::CalpontSystemCatalog::LONGDOUBLE + || ti2.dtype == execplan::CalpontSystemCatalog::LONGDOUBLE) + { + m1->second.fTypeless = m2->second.fTypeless = false; + } + else + { + m1->second.fTypeless = m2->second.fTypeless = true; + } + } else + { m1->second.fTypeless = m2->second.fTypeless = false; + } } else { diff --git a/dbcon/joblist/joblistfactory.cpp b/dbcon/joblist/joblistfactory.cpp index 04989e7b7..97bd6a53c 100644 --- a/dbcon/joblist/joblistfactory.cpp +++ b/dbcon/joblist/joblistfactory.cpp @@ -695,44 +695,13 @@ void updateAggregateColType(AggregateColumn* ac, const SRCP& srcp, int op, JobIn else if ((fc = dynamic_cast(srcp.get())) != NULL) ct = fc->resultType(); - if (op == AggregateColumn::SUM || op == AggregateColumn::DISTINCT_SUM) - { - if (ct.colDataType == CalpontSystemCatalog::TINYINT || - ct.colDataType == CalpontSystemCatalog::SMALLINT || - ct.colDataType == CalpontSystemCatalog::MEDINT || - ct.colDataType == CalpontSystemCatalog::INT || - ct.colDataType == CalpontSystemCatalog::BIGINT || - ct.colDataType == CalpontSystemCatalog::DECIMAL || - ct.colDataType == CalpontSystemCatalog::UDECIMAL) - { - ct.colWidth = sizeof(int64_t); - - if (ct.scale != 0) - ct.colDataType = CalpontSystemCatalog::DECIMAL; - else - ct.colDataType = CalpontSystemCatalog::BIGINT; - - ct.precision = 19; - } - - if (ct.colDataType == CalpontSystemCatalog::UTINYINT || - ct.colDataType == CalpontSystemCatalog::USMALLINT || - ct.colDataType == CalpontSystemCatalog::UMEDINT || - ct.colDataType == CalpontSystemCatalog::UINT || - ct.colDataType == CalpontSystemCatalog::UBIGINT) - { - ct.colWidth = sizeof(uint64_t); - ct.colDataType = CalpontSystemCatalog::UBIGINT; - ct.precision = 20; - } - } - else if (op == AggregateColumn::STDDEV_POP || op == AggregateColumn::STDDEV_SAMP || - op == AggregateColumn::VAR_POP || op == AggregateColumn::VAR_SAMP) + if (op == AggregateColumn::STDDEV_POP || op == AggregateColumn::STDDEV_SAMP || + op == AggregateColumn::VAR_POP || op == AggregateColumn::VAR_SAMP) { ct.colWidth = sizeof(double); ct.colDataType = CalpontSystemCatalog::DOUBLE; ct.scale = 0; - ct.precision = 0; + ct.precision = -1; } else if (op == AggregateColumn::UDAF) { @@ -1059,7 +1028,11 @@ const JobStepVector doAggProject(const CalpontSelectExecutionPlan* csep, JobInfo // Set the col type based on the single parm. // Changing col type based on a parm if multiple parms // doesn't really make sense. - updateAggregateColType(aggc, srcp, op, jobInfo); + if (op != AggregateColumn::SUM && op != AggregateColumn::DISTINCT_SUM && + op != AggregateColumn::AVG && op != AggregateColumn::DISTINCT_AVG) + { + updateAggregateColType(aggc, srcp, op, jobInfo); + } } aggCt = aggc->resultType(); @@ -1203,9 +1176,6 @@ const JobStepVector doAggProject(const CalpontSelectExecutionPlan* csep, JobInfo // remember the columns to be returned jobInfo.returnedColVec.push_back(make_pair(tupleKey, op)); - if (op == AggregateColumn::AVG || op == AggregateColumn::DISTINCT_AVG) - jobInfo.scaleOfAvg[tupleKey] = (ct.scale << 8) + aggCt.scale; - // bug 1499 distinct processing, save unique distinct columns if (doDistinct && (jobInfo.distinctColVec.end() == @@ -1354,9 +1324,6 @@ const JobStepVector doAggProject(const CalpontSelectExecutionPlan* csep, JobInfo // remember the columns to be returned jobInfo.returnedColVec.push_back(make_pair(tupleKey, op)); - if (op == AggregateColumn::AVG || op == AggregateColumn::DISTINCT_AVG) - jobInfo.scaleOfAvg[tupleKey] = (ct.scale << 8) + aggCt.scale; - // bug 1499 distinct processing, save unique distinct columns if (doDistinct && (jobInfo.distinctColVec.end() == diff --git a/dbcon/joblist/joblisttypes.h b/dbcon/joblist/joblisttypes.h index 2174f3002..82c8fe7ca 100644 --- a/dbcon/joblist/joblisttypes.h +++ b/dbcon/joblist/joblisttypes.h @@ -52,7 +52,7 @@ const uint32_t FLOATNULL = 0xFFAAAAAA; const uint32_t FLOATEMPTYROW = 0xFFAAAAAB; const uint64_t DOUBLENULL = 0xFFFAAAAAAAAAAAAAULL; const uint64_t DOUBLEEMPTYROW = 0xFFFAAAAAAAAAAAABULL; -const long double LONGDOUBLENULL = nanl(""); +const long double LONGDOUBLENULL = INFINITY; const uint32_t DATENULL = 0xFFFFFFFE; const uint32_t DATEEMPTYROW = 0xFFFFFFFF; diff --git a/dbcon/joblist/primitivestep.h b/dbcon/joblist/primitivestep.h index 8dd02e0e1..cc18cb43d 100644 --- a/dbcon/joblist/primitivestep.h +++ b/dbcon/joblist/primitivestep.h @@ -1410,7 +1410,7 @@ private: boost::mutex serializeJoinerMutex; boost::condition condvarWakeupProducer, condvar; - std::vector scanFlags; // use to keep track of which extents to eliminate from this step + std::vector scanFlags; // use to keep track of which extents to eliminate from this step bool BPPIsAllocated; uint32_t uniqueID; ResourceManager* fRm; @@ -1476,7 +1476,7 @@ private: * component and this new array as the runtime component. The final CP decision * is scanFlags & runtimeCP. */ - std::vector runtimeCPFlags; + std::vector runtimeCPFlags; /* semijoin vars */ rowgroup::RowGroup joinFERG; diff --git a/dbcon/joblist/rowestimator.cpp b/dbcon/joblist/rowestimator.cpp index e69c66d79..8ec09488c 100644 --- a/dbcon/joblist/rowestimator.cpp +++ b/dbcon/joblist/rowestimator.cpp @@ -455,7 +455,7 @@ float RowEstimator::estimateRowReturnFactor(const BRM::EMEntry& emEntry, // This function returns the estimated row count for the entire TupleBPS. It samples the last 20 (configurable) extents to // calculate the estimate. uint64_t RowEstimator::estimateRows(const vector& cpColVec, - const std::vector& scanFlags, + const std::vector& scanFlags, BRM::DBRM& dbrm, const execplan::CalpontSystemCatalog::OID oid) diff --git a/dbcon/joblist/rowestimator.h b/dbcon/joblist/rowestimator.h index 477bc2b30..01547c2d0 100644 --- a/dbcon/joblist/rowestimator.h +++ b/dbcon/joblist/rowestimator.h @@ -62,7 +62,7 @@ public: * */ uint64_t estimateRows(const std::vector& cpColVec, - const std::vector & scanFlags, + const std::vector & scanFlags, BRM::DBRM& dbrm, const execplan::CalpontSystemCatalog::OID oid); diff --git a/dbcon/joblist/subquerytransformer.cpp b/dbcon/joblist/subquerytransformer.cpp index c212c701d..fb8d0db55 100644 --- a/dbcon/joblist/subquerytransformer.cpp +++ b/dbcon/joblist/subquerytransformer.cpp @@ -230,8 +230,15 @@ SJSTEP& SubQueryTransformer::makeSubQueryStep(execplan::CalpontSelectExecutionPl ct.colDataType = row.getColTypes()[i]; ct.scale = row.getScale(i); - if (ct.scale != 0 && ct.precision != -1) - ct.colDataType = CalpontSystemCatalog::DECIMAL; + if (colDataTypeInRg != CalpontSystemCatalog::FLOAT && + colDataTypeInRg != CalpontSystemCatalog::UFLOAT && + colDataTypeInRg != CalpontSystemCatalog::DOUBLE && + colDataTypeInRg != CalpontSystemCatalog::UDOUBLE && + colDataTypeInRg != CalpontSystemCatalog::LONGDOUBLE) + { + if (ct.scale != 0 && ct.precision != -1) + ct.colDataType = CalpontSystemCatalog::DECIMAL; + } ct.precision = row.getPrecision(i); fVtable.columnType(ct, i); diff --git a/dbcon/joblist/tupleaggregatestep.cpp b/dbcon/joblist/tupleaggregatestep.cpp index 61768dfd3..689be0306 100644 --- a/dbcon/joblist/tupleaggregatestep.cpp +++ b/dbcon/joblist/tupleaggregatestep.cpp @@ -738,13 +738,13 @@ void TupleAggregateStep::configDeliveredRowGroup(const JobInfo& jobInfo) // correct the scale vector scale = fRowGroupOut.getScale(); - for (uint64_t i = 0; i < scale.size(); i++) - { +// for (uint64_t i = 0; i < scale.size(); i++) +// { // to support CNX_DECIMAL_SCALE the avg column's scale is coded with two scales: // fe's avg column scale << 8 + original column scale //if ((scale[i] & 0x0000FF00) > 0) - scale[i] = scale[i] & 0x000000FF; - } +// scale[i] = scale[i] & 0x000000FF; +// } size_t retColCount = jobInfo.nonConstDelCols.size(); @@ -1402,43 +1402,10 @@ void TupleAggregateStep::prep1PhaseAggregate( oidsAgg.push_back(oidsProj[colProj]); keysAgg.push_back(key); - - if (typeProj[colProj] == CalpontSystemCatalog::DOUBLE || - typeProj[colProj] == CalpontSystemCatalog::UDOUBLE || - typeProj[colProj] == CalpontSystemCatalog::FLOAT || - typeProj[colProj] == CalpontSystemCatalog::UFLOAT) - { - typeAgg.push_back(typeProj[colProj]); - scaleAgg.push_back(scaleProj[colProj]); - precisionAgg.push_back(precisionProj[colProj]); - widthAgg.push_back(width[colProj]); - } - else if (isUnsigned(typeProj[colProj])) - { - typeAgg.push_back(CalpontSystemCatalog::UBIGINT); - uint32_t scale = scaleProj[colProj]; - - // for int average, FE expects a decimal - if (aggOp == ROWAGG_AVG) - scale = jobInfo.scaleOfAvg[key]; // scale += 4; - - scaleAgg.push_back(scale); - precisionAgg.push_back(20); - widthAgg.push_back(bigUintWidth); - } - else - { - typeAgg.push_back(CalpontSystemCatalog::BIGINT); - uint32_t scale = scaleProj[colProj]; - - // for int average, FE expects a decimal - if (aggOp == ROWAGG_AVG) - scale = jobInfo.scaleOfAvg[key]; // scale += 4; - - scaleAgg.push_back(scale); - precisionAgg.push_back(19); - widthAgg.push_back(bigIntWidth); - } + typeAgg.push_back(CalpontSystemCatalog::LONGDOUBLE); + precisionAgg.push_back(-1); + widthAgg.push_back(sizeof(long double)); + scaleAgg.push_back(scaleProj[colProj]); } break; @@ -1450,16 +1417,7 @@ void TupleAggregateStep::prep1PhaseAggregate( scaleAgg.push_back(0); // work around count() in select subquery precisionAgg.push_back(9999); - - if (isUnsigned(typeProj[colProj])) - { - typeAgg.push_back(CalpontSystemCatalog::UBIGINT); - } - else - { - typeAgg.push_back(CalpontSystemCatalog::BIGINT); - } - + typeAgg.push_back(CalpontSystemCatalog::UBIGINT); widthAgg.push_back(bigIntWidth); } break; @@ -1603,7 +1561,7 @@ void TupleAggregateStep::prep1PhaseAggregate( keysAgg.push_back(k->first); scaleAgg.push_back(0); precisionAgg.push_back(19); - typeAgg.push_back(CalpontSystemCatalog::BIGINT); + typeAgg.push_back(CalpontSystemCatalog::UBIGINT); widthAgg.push_back(bigIntWidth); } } @@ -1643,7 +1601,7 @@ void TupleAggregateStep::prep1PhaseAggregate( oidsAgg.push_back(oidsAgg[j]); keysAgg.push_back(keysAgg[j]); scaleAgg.push_back(0); - precisionAgg.push_back(0); + precisionAgg.push_back(-1); typeAgg.push_back(CalpontSystemCatalog::LONGDOUBLE); widthAgg.push_back(sizeof(long double)); ++lastCol; @@ -1652,7 +1610,7 @@ void TupleAggregateStep::prep1PhaseAggregate( oidsAgg.push_back(oidsAgg[j]); keysAgg.push_back(keysAgg[j]); scaleAgg.push_back(0); - precisionAgg.push_back(0); + precisionAgg.push_back(-1); typeAgg.push_back(CalpontSystemCatalog::LONGDOUBLE); widthAgg.push_back(sizeof(long double)); ++lastCol; @@ -1973,47 +1931,19 @@ void TupleAggregateStep::prep1PhaseDistinctAggregate( oidsAgg.push_back(oidsProj[colProj]); keysAgg.push_back(aggKey); - - if (typeProj[colProj] != CalpontSystemCatalog::DOUBLE && - typeProj[colProj] != CalpontSystemCatalog::FLOAT) - { - if (isUnsigned(typeProj[colProj])) - { - typeAgg.push_back(CalpontSystemCatalog::UBIGINT); - precisionAgg.push_back(20); - } - else - { - typeAgg.push_back(CalpontSystemCatalog::BIGINT); - precisionAgg.push_back(19); - } - - uint32_t scale = scaleProj[colProj]; - - // for int average, FE expects a decimal - if (aggOp == ROWAGG_AVG) - scale = jobInfo.scaleOfAvg[aggKey]; // scale += 4; - - scaleAgg.push_back(scale); - widthAgg.push_back(bigIntWidth); - } - else - { - typeAgg.push_back(typeProj[colProj]); - scaleAgg.push_back(scaleProj[colProj]); - precisionAgg.push_back(precisionProj[colProj]); - widthAgg.push_back(widthProj[colProj]); - } - + typeAgg.push_back(CalpontSystemCatalog::LONGDOUBLE); + precisionAgg.push_back(-1); + widthAgg.push_back(sizeof(long double)); + scaleAgg.push_back(scaleProj[colProj]); colAgg++; - } - // has distinct step, put the count column for avg next to the sum - // let fall through to add a count column for average function + // has distinct step, put the count column for avg next to the sum + // let fall through to add a count column for average function if (aggOp == ROWAGG_AVG) funct->fAuxColumnIndex = colAgg; else break; + } case ROWAGG_COUNT_ASTERISK: case ROWAGG_COUNT_COL_NAME: @@ -2070,7 +2000,7 @@ void TupleAggregateStep::prep1PhaseDistinctAggregate( oidsAgg.push_back(oidsProj[colProj]); keysAgg.push_back(aggKey); scaleAgg.push_back(0); - precisionAgg.push_back(0); + precisionAgg.push_back(-1); typeAgg.push_back(CalpontSystemCatalog::LONGDOUBLE); widthAgg.push_back(sizeof(long double)); ++colAgg; @@ -2079,7 +2009,7 @@ void TupleAggregateStep::prep1PhaseDistinctAggregate( oidsAgg.push_back(oidsProj[colProj]); keysAgg.push_back(aggKey); scaleAgg.push_back(0); - precisionAgg.push_back(0); + precisionAgg.push_back(-1); typeAgg.push_back(CalpontSystemCatalog::LONGDOUBLE); widthAgg.push_back(sizeof(long double)); ++colAgg; @@ -2321,37 +2251,10 @@ void TupleAggregateStep::prep1PhaseDistinctAggregate( oidsAggDist.push_back(oidsAgg[colAgg]); keysAggDist.push_back(retKey); - - if (typeAgg[colAgg] != CalpontSystemCatalog::DOUBLE && - typeAgg[colAgg] != CalpontSystemCatalog::FLOAT) - { - if (isUnsigned(typeAgg[colAgg])) - { - typeAggDist.push_back(CalpontSystemCatalog::UBIGINT); - precisionAggDist.push_back(20); - } - else - { - typeAggDist.push_back(CalpontSystemCatalog::BIGINT); - precisionAggDist.push_back(19); - } - - uint32_t scale = scaleProj[colAgg]; - - // for int average, FE expects a decimal - if (aggOp == ROWAGG_DISTINCT_AVG) - scale = jobInfo.scaleOfAvg[retKey]; // scale += 4; - - scaleAggDist.push_back(scale); - widthAggDist.push_back(bigIntWidth); - } - else - { - typeAggDist.push_back(typeAgg[colAgg]); - scaleAggDist.push_back(scaleAgg[colAgg]); - precisionAggDist.push_back(precisionAgg[colAgg]); - widthAggDist.push_back(widthAgg[colAgg]); - } + typeAggDist.push_back(CalpontSystemCatalog::LONGDOUBLE); + precisionAggDist.push_back(-1); + widthAggDist.push_back(sizeof(long double)); + scaleAggDist.push_back(scaleProj[colAgg]); } break; @@ -2362,16 +2265,7 @@ void TupleAggregateStep::prep1PhaseDistinctAggregate( scaleAggDist.push_back(0); // work around count() in select subquery precisionAggDist.push_back(9999); - - if (isUnsigned(typeAgg[colAgg])) - { - typeAggDist.push_back(CalpontSystemCatalog::UBIGINT); - } - else - { - typeAggDist.push_back(CalpontSystemCatalog::BIGINT); - } - + typeAggDist.push_back(CalpontSystemCatalog::UBIGINT); widthAggDist.push_back(bigIntWidth); } break; @@ -2659,7 +2553,7 @@ void TupleAggregateStep::prep1PhaseDistinctAggregate( keysAggDist.push_back(k->first); scaleAggDist.push_back(0); precisionAggDist.push_back(19); - typeAggDist.push_back(CalpontSystemCatalog::BIGINT); + typeAggDist.push_back(CalpontSystemCatalog::UBIGINT); widthAggDist.push_back(bigIntWidth); } } @@ -2739,7 +2633,7 @@ void TupleAggregateStep::prep1PhaseDistinctAggregate( oidsAggDist.push_back(oidsAggDist[j]); keysAggDist.push_back(keysAggDist[j]); scaleAggDist.push_back(0); - precisionAggDist.push_back(0); + precisionAggDist.push_back(-1); typeAggDist.push_back(CalpontSystemCatalog::LONGDOUBLE); widthAggDist.push_back(sizeof(long double)); ++lastCol; @@ -3151,13 +3045,32 @@ void TupleAggregateStep::prep2PhasesAggregate( SP_ROWAGG_GRPBY_t groupby(new RowAggGroupByCol(colProj, colAggPm)); groupByPm.push_back(groupby); - // PM: just copy down to aggregation rowgroup + // PM: Except for SUM/AVG, just copy down to aggregation rowgroup + RowAggFunctionType aggOp = rowgroup::ROWAGG_COUNT_NO_OP; + for (size_t agg = 0; agg < aggColVec.size(); ++agg) + { + if (aggColVec[agg].first == key) + { + aggOp = functionIdMap(aggColVec[agg].second); + break; + } + } oidsAggPm.push_back(oidsProj[colProj]); keysAggPm.push_back(key); scaleAggPm.push_back(scaleProj[colProj]); - precisionAggPm.push_back(precisionProj[colProj]); - typeAggPm.push_back(typeProj[colProj]); - widthAggPm.push_back(width[colProj]); + if (aggOp == ROWAGG_DISTINCT_SUM || + aggOp == ROWAGG_DISTINCT_AVG) + { + typeAggPm.push_back(CalpontSystemCatalog::LONGDOUBLE); + precisionAggPm.push_back(-1); + widthAggPm.push_back(sizeof(long double)); + } + else + { + typeAggPm.push_back(typeProj[colProj]); + widthAggPm.push_back(width[colProj]); + precisionAggPm.push_back(precisionProj[colProj]); + } aggFuncMap.insert(make_pair(boost::make_tuple(keysAggPm[colAggPm], 0, pUDAFFunc, udafc ? udafc->getContext().getParamKeys() : NULL), colAggPm)); colAggPm++; @@ -3277,49 +3190,15 @@ void TupleAggregateStep::prep2PhasesAggregate( oidsAggPm.push_back(oidsProj[colProj]); keysAggPm.push_back(aggKey); - - if (typeProj[colProj] == CalpontSystemCatalog::DOUBLE || - typeProj[colProj] == CalpontSystemCatalog::UDOUBLE || - typeProj[colProj] == CalpontSystemCatalog::FLOAT || - typeProj[colProj] == CalpontSystemCatalog::UFLOAT) - { - typeAggPm.push_back(typeProj[colProj]); - scaleAggPm.push_back(scaleProj[colProj]); - precisionAggPm.push_back(precisionProj[colProj]); - widthAggPm.push_back(width[colProj]); - } - else if (isUnsigned(typeProj[colProj])) - { - typeAggPm.push_back(CalpontSystemCatalog::UBIGINT); - uint32_t scale = scaleProj[colProj]; - - // for int average, FE expects a decimal - if (aggOp == ROWAGG_AVG) - scale = jobInfo.scaleOfAvg[aggKey]; // scale += 4; - - scaleAggPm.push_back(scale); - precisionAggPm.push_back(20); - widthAggPm.push_back(bigUintWidth); - } - else - { - typeAggPm.push_back(CalpontSystemCatalog::BIGINT); - uint32_t scale = scaleProj[colProj]; - - // for int average, FE expects a decimal - if (aggOp == ROWAGG_AVG) - scale = jobInfo.scaleOfAvg[aggKey]; // scale += 4; - - scaleAggPm.push_back(scale); - precisionAggPm.push_back(19); - widthAggPm.push_back(bigIntWidth); - } - + typeAggPm.push_back(CalpontSystemCatalog::LONGDOUBLE); + scaleAggPm.push_back(scaleProj[colProj]); + precisionAggPm.push_back(-1); + widthAggPm.push_back(sizeof(long double)); colAggPm++; } - // PM: put the count column for avg next to the sum - // let fall through to add a count column for average function + // PM: put the count column for avg next to the sum + // let fall through to add a count column for average function if (aggOp != ROWAGG_AVG) break; @@ -3331,16 +3210,7 @@ void TupleAggregateStep::prep2PhasesAggregate( scaleAggPm.push_back(0); // work around count() in select subquery precisionAggPm.push_back(9999); - - if (isUnsigned(typeProj[colProj])) - { - typeAggPm.push_back(CalpontSystemCatalog::UBIGINT); - } - else - { - typeAggPm.push_back(CalpontSystemCatalog::BIGINT); - } - + typeAggPm.push_back(CalpontSystemCatalog::UBIGINT); widthAggPm.push_back(bigIntWidth); colAggPm++; } @@ -3378,7 +3248,7 @@ void TupleAggregateStep::prep2PhasesAggregate( oidsAggPm.push_back(oidsProj[colProj]); keysAggPm.push_back(aggKey); scaleAggPm.push_back(0); - precisionAggPm.push_back(0); + precisionAggPm.push_back(-1); typeAggPm.push_back(CalpontSystemCatalog::LONGDOUBLE); widthAggPm.push_back(sizeof(long double)); ++colAggPm; @@ -3387,7 +3257,7 @@ void TupleAggregateStep::prep2PhasesAggregate( oidsAggPm.push_back(oidsProj[colProj]); keysAggPm.push_back(aggKey); scaleAggPm.push_back(0); - precisionAggPm.push_back(0); + precisionAggPm.push_back(-1); typeAggPm.push_back(CalpontSystemCatalog::LONGDOUBLE); widthAggPm.push_back(sizeof(long double)); ++colAggPm; @@ -3612,7 +3482,7 @@ void TupleAggregateStep::prep2PhasesAggregate( keysAggUm.push_back(retKey); scaleAggUm.push_back(0); precisionAggUm.push_back(19); - typeAggUm.push_back(CalpontSystemCatalog::BIGINT); + typeAggUm.push_back(CalpontSystemCatalog::UBIGINT); widthAggUm.push_back(bigIntWidth); } } @@ -3779,7 +3649,7 @@ void TupleAggregateStep::prep2PhasesAggregate( keysAggUm.push_back(k->first); scaleAggUm.push_back(0); precisionAggUm.push_back(19); - typeAggUm.push_back(CalpontSystemCatalog::BIGINT); + typeAggUm.push_back(CalpontSystemCatalog::UBIGINT); widthAggUm.push_back(bigIntWidth); } } @@ -3818,7 +3688,7 @@ void TupleAggregateStep::prep2PhasesAggregate( oidsAggUm.push_back(oidsAggUm[j]); keysAggUm.push_back(keysAggUm[j]); scaleAggUm.push_back(0); - precisionAggUm.push_back(0); + precisionAggUm.push_back(-1); typeAggUm.push_back(CalpontSystemCatalog::LONGDOUBLE); widthAggUm.push_back(sizeof(long double)); ++lastCol; @@ -3827,7 +3697,7 @@ void TupleAggregateStep::prep2PhasesAggregate( oidsAggUm.push_back(oidsAggUm[j]); keysAggUm.push_back(keysAggUm[j]); scaleAggUm.push_back(0); - precisionAggUm.push_back(0); + precisionAggUm.push_back(-1); typeAggUm.push_back(CalpontSystemCatalog::LONGDOUBLE); widthAggUm.push_back(sizeof(long double)); ++lastCol; @@ -4035,16 +3905,37 @@ void TupleAggregateStep::prep2PhasesDistinctAggregate( uint64_t colProj = projColPosMap[key]; - SP_ROWAGG_GRPBY_t groupby(new RowAggGroupByCol(colProj, colAggPm)); +// SP_ROWAGG_GRPBY_t groupby(new RowAggGroupByCol(colProj, colAggPm)); + SP_ROWAGG_GRPBY_t groupby(new RowAggGroupByCol(colProj)); groupByPm.push_back(groupby); - // PM: just copy down to aggregation rowgroup + // PM: Except for SUM/AVG, just copy down to aggregation rowgroup + RowAggFunctionType aggOp = rowgroup::ROWAGG_COUNT_NO_OP; + for (size_t agg = 0; agg < aggColVec.size(); ++agg) + { + if (aggColVec[agg].first == key) + { + aggOp = functionIdMap(aggColVec[agg].second); + break; + } + } oidsAggPm.push_back(oidsProj[colProj]); keysAggPm.push_back(key); scaleAggPm.push_back(scaleProj[colProj]); precisionAggPm.push_back(precisionProj[colProj]); - typeAggPm.push_back(typeProj[colProj]); - widthAggPm.push_back(width[colProj]); + if (aggOp == ROWAGG_DISTINCT_SUM || + aggOp == ROWAGG_DISTINCT_AVG) + { + typeAggPm.push_back(CalpontSystemCatalog::LONGDOUBLE); + precisionAggPm.push_back(-1); + widthAggPm.push_back(sizeof(long double)); + } + else + { + typeAggPm.push_back(typeProj[colProj]); + widthAggPm.push_back(width[colProj]); + precisionAggPm.push_back(precisionProj[colProj]); + } aggFuncMap.insert(make_pair(boost::make_tuple(keysAggPm[colAggPm], 0, pUDAFFunc, udafc ? udafc->getContext().getParamKeys() : NULL), colAggPm)); colAggPm++; @@ -4171,43 +4062,15 @@ void TupleAggregateStep::prep2PhasesDistinctAggregate( oidsAggPm.push_back(oidsProj[colProj]); keysAggPm.push_back(aggKey); - - if (typeProj[colProj] != CalpontSystemCatalog::DOUBLE && - typeProj[colProj] != CalpontSystemCatalog::FLOAT) - { - if (isUnsigned(typeProj[colProj])) - { - typeAggPm.push_back(CalpontSystemCatalog::UBIGINT); - precisionAggPm.push_back(20); - } - else - { - typeAggPm.push_back(CalpontSystemCatalog::BIGINT); - precisionAggPm.push_back(19); - } - - uint32_t scale = scaleProj[colProj]; - - // for int average, FE expects a decimal - if (aggOp == ROWAGG_AVG) - scale = jobInfo.scaleOfAvg[aggKey]; // scale += 4; - - scaleAggPm.push_back(scale); - widthAggPm.push_back(bigIntWidth); - } - else - { - typeAggPm.push_back(typeProj[colProj]); - scaleAggPm.push_back(scaleProj[colProj]); - precisionAggPm.push_back(precisionProj[colProj]); - widthAggPm.push_back(width[colProj]); - } - + typeAggPm.push_back(CalpontSystemCatalog::LONGDOUBLE); + precisionAggPm.push_back(-1); + widthAggPm.push_back(sizeof(long double)); + scaleAggPm.push_back(scaleProj[colProj]); colAggPm++; } - // PM: put the count column for avg next to the sum - // let fall through to add a count column for average function + // PM: put the count column for avg next to the sum + // let fall through to add a count column for average function if (aggOp == ROWAGG_AVG) funct->fAuxColumnIndex = colAggPm; else @@ -4268,7 +4131,7 @@ void TupleAggregateStep::prep2PhasesDistinctAggregate( oidsAggPm.push_back(oidsProj[colProj]); keysAggPm.push_back(aggKey); scaleAggPm.push_back(0); - precisionAggPm.push_back(0); + precisionAggPm.push_back(-1); typeAggPm.push_back(CalpontSystemCatalog::LONGDOUBLE); widthAggPm.push_back(sizeof(long double)); ++colAggPm; @@ -4277,7 +4140,7 @@ void TupleAggregateStep::prep2PhasesDistinctAggregate( oidsAggPm.push_back(oidsProj[colProj]); keysAggPm.push_back(aggKey); scaleAggPm.push_back(0); - precisionAggPm.push_back(0); + precisionAggPm.push_back(-1); typeAggPm.push_back(CalpontSystemCatalog::LONGDOUBLE); widthAggPm.push_back(sizeof(long double)); ++colAggPm; @@ -4566,41 +4429,14 @@ void TupleAggregateStep::prep2PhasesDistinctAggregate( oidsAggDist.push_back(oidsAggUm[colUm]); keysAggDist.push_back(retKey); - - if (typeAggUm[colUm] != CalpontSystemCatalog::DOUBLE && - typeAggUm[colUm] != CalpontSystemCatalog::FLOAT) - { - if (isUnsigned(typeAggUm[colUm])) - { - typeAggDist.push_back(CalpontSystemCatalog::UBIGINT); - precisionAggDist.push_back(20); - } - else - { - typeAggDist.push_back(CalpontSystemCatalog::BIGINT); - precisionAggDist.push_back(19); - } - - uint32_t scale = scaleAggUm[colUm]; - - // for int average, FE expects a decimal - if (aggOp == ROWAGG_DISTINCT_AVG) - scale = jobInfo.scaleOfAvg[retKey]; // scale += 4; - - scaleAggDist.push_back(scale); - widthAggDist.push_back(bigIntWidth); - } - else - { - typeAggDist.push_back(typeAggUm[colUm]); - scaleAggDist.push_back(scaleAggUm[colUm]); - precisionAggDist.push_back(precisionAggUm[colUm]); - widthAggDist.push_back(widthAggUm[colUm]); - } + typeAggDist.push_back(typeAggUm[colUm]); + scaleAggDist.push_back(scaleAggUm[colUm]); + precisionAggDist.push_back(precisionAggUm[colUm]); + widthAggDist.push_back(widthAggUm[colUm]); } - // PM: put the count column for avg next to the sum - // let fall through to add a count column for average function - //if (aggOp != ROWAGG_DISTINCT_AVG) + // PM: put the count column for avg next to the sum + // let fall through to add a count column for average function + //if (aggOp != ROWAGG_DISTINCT_AVG) break; case ROWAGG_COUNT_DISTINCT_COL_NAME: @@ -4610,16 +4446,7 @@ void TupleAggregateStep::prep2PhasesDistinctAggregate( scaleAggDist.push_back(0); // work around count() in select subquery precisionAggDist.push_back(9999); - - if (isUnsigned(typeAggUm[colUm])) - { - typeAggDist.push_back(CalpontSystemCatalog::UBIGINT); - } - else - { - typeAggDist.push_back(CalpontSystemCatalog::BIGINT); - } - + typeAggDist.push_back(CalpontSystemCatalog::UBIGINT); widthAggDist.push_back(bigIntWidth); } break; @@ -4847,7 +4674,7 @@ void TupleAggregateStep::prep2PhasesDistinctAggregate( keysAggDist.push_back(k->first); scaleAggDist.push_back(0); precisionAggDist.push_back(19); - typeAggDist.push_back(CalpontSystemCatalog::BIGINT); + typeAggDist.push_back(CalpontSystemCatalog::UBIGINT); widthAggDist.push_back(bigIntWidth); } } @@ -4918,7 +4745,7 @@ void TupleAggregateStep::prep2PhasesDistinctAggregate( oidsAggDist.push_back(oidsAggDist[j]); keysAggDist.push_back(keysAggDist[j]); scaleAggDist.push_back(0); - precisionAggDist.push_back(0); + precisionAggDist.push_back(-1); typeAggDist.push_back(CalpontSystemCatalog::LONGDOUBLE); widthAggDist.push_back(sizeof(long double)); ++lastCol; @@ -4927,7 +4754,7 @@ void TupleAggregateStep::prep2PhasesDistinctAggregate( oidsAggDist.push_back(oidsAggDist[j]); keysAggDist.push_back(keysAggDist[j]); scaleAggDist.push_back(0); - precisionAggDist.push_back(0); + precisionAggDist.push_back(-1); typeAggDist.push_back(CalpontSystemCatalog::LONGDOUBLE); widthAggDist.push_back(sizeof(long double)); ++lastCol; diff --git a/dbcon/mysql/ha_calpont_execplan.cpp b/dbcon/mysql/ha_calpont_execplan.cpp index 83be3c650..9e92162a0 100644 --- a/dbcon/mysql/ha_calpont_execplan.cpp +++ b/dbcon/mysql/ha_calpont_execplan.cpp @@ -3372,7 +3372,6 @@ ReturnedColumn* buildFunctionColumn( return ac; } - // comment out for now until case function is fully tested. else if (funcName == "case") { fc = buildCaseFunction(ifp, gwi, nonSupport); @@ -4500,39 +4499,9 @@ ReturnedColumn* buildAggregateColumn(Item* item, gp_walk_info& gwi) { CalpontSystemCatalog::ColType ct = parm->resultType(); ct.colDataType = CalpontSystemCatalog::LONGDOUBLE; + ct.colWidth = 16; ct.scale += 4; -// ct.colWidth = 8; - -#if 0 - switch (ct.colDataType) - { - case CalpontSystemCatalog::TINYINT: - case CalpontSystemCatalog::SMALLINT: - case CalpontSystemCatalog::MEDINT: - case CalpontSystemCatalog::INT: - case CalpontSystemCatalog::BIGINT: - case CalpontSystemCatalog::DECIMAL: - case CalpontSystemCatalog::UDECIMAL: - case CalpontSystemCatalog::UTINYINT: - case CalpontSystemCatalog::USMALLINT: - case CalpontSystemCatalog::UMEDINT: - case CalpontSystemCatalog::UINT: - case CalpontSystemCatalog::UBIGINT: - ct.scale += 4; - break; - - case CalpontSystemCatalog::FLOAT: - case CalpontSystemCatalog::UFLOAT: - case CalpontSystemCatalog::DOUBLE: - case CalpontSystemCatalog::UDOUBLE: - ct.colDataType = CalpontSystemCatalog::DOUBLE; - ct.colWidth = 8; - break; - - default: - break; - } -#endif + ct.precision = -1; ac->resultType(ct); } else if (isp->sum_func() == Item_sum::COUNT_FUNC || @@ -4549,48 +4518,8 @@ ReturnedColumn* buildAggregateColumn(Item* item, gp_walk_info& gwi) { CalpontSystemCatalog::ColType ct = parm->resultType(); ct.colDataType = CalpontSystemCatalog::LONGDOUBLE; - ct.scale += 4; -#if 0 - switch (ct.colDataType) - { - case CalpontSystemCatalog::TINYINT: - case CalpontSystemCatalog::SMALLINT: - case CalpontSystemCatalog::MEDINT: - case CalpontSystemCatalog::INT: - case CalpontSystemCatalog::BIGINT: - ct.colDataType = CalpontSystemCatalog::BIGINT; - - // no break, let fall through - - case CalpontSystemCatalog::DECIMAL: - case CalpontSystemCatalog::UDECIMAL: - ct.colWidth = 8; - break; - - case CalpontSystemCatalog::UTINYINT: - case CalpontSystemCatalog::USMALLINT: - case CalpontSystemCatalog::UMEDINT: - case CalpontSystemCatalog::UINT: - case CalpontSystemCatalog::UBIGINT: - ct.colDataType = CalpontSystemCatalog::UBIGINT; - ct.colWidth = 8; - break; - -#if PROMOTE_FLOAT_TO_DOUBLE_ON_SUM - - case CalpontSystemCatalog::FLOAT: - case CalpontSystemCatalog::UFLOAT: - case CalpontSystemCatalog::DOUBLE: - case CalpontSystemCatalog::UDOUBLE: - ct.colDataType = CalpontSystemCatalog::DOUBLE; - ct.colWidth = 8; - break; -#endif - - default: - break; - } -#endif + ct.colWidth = 16; + ct.precision = -1; ac->resultType(ct); } else if (isp->sum_func() == Item_sum::STD_FUNC || diff --git a/dbcon/mysql/ha_calpont_impl.cpp b/dbcon/mysql/ha_calpont_impl.cpp index 0a633fe1c..58170f5aa 100644 --- a/dbcon/mysql/ha_calpont_impl.cpp +++ b/dbcon/mysql/ha_calpont_impl.cpp @@ -705,37 +705,58 @@ int fetchNextRow(uchar* buf, cal_table_info& ti, cal_connection_info* ci, bool h case CalpontSystemCatalog::LONGDOUBLE: { - double dl = row.getLongDoubleField(s); - + long double dl = row.getLongDoubleField(s); if (dl == std::numeric_limits::infinity()) - continue; - - Field_double* f2 = (Field_double*)*f; - // bug 3483, reserve enough space for the longest double value - // -1.7976931348623157E+308 to -2.2250738585072014E-308, 0, and - // 2.2250738585072014E-308 to 1.7976931348623157E+308. - (*f)->field_length = 310; - - //double double_val = *(double*)(&value); - //f2->store(double_val); - if ((f2->decimals() == DECIMAL_NOT_SPECIFIED && row.getScale(s) > 0) - || f2->decimals() < row.getScale(s)) { - f2->dec = row.getScale(s); + continue; } - f2->store(dl); + switch((*f)->type()) + { + case MYSQL_TYPE_NEWDECIMAL: + { + char buf[310]; + Field_new_decimal* f2 = (Field_new_decimal*)*f; + if ((f2->decimals() == DECIMAL_NOT_SPECIFIED && row.getScale(s) > 0) + || f2->decimals() < row.getScale(s)) + { + f2->dec = row.getScale(s); + } +// dl /= pow(10.0, (double)f2->dec); + snprintf(buf, 310, "%.20Lg", dl); + f2->store(buf, strlen(buf), f2->charset()); + if ((*f)->null_ptr) + *(*f)->null_ptr &= ~(*f)->null_bit; + } + break; + case MYSQL_TYPE_DOUBLE: + { + Field_double* f2 = (Field_double*)*f; - if ((*f)->null_ptr) - *(*f)->null_ptr &= ~(*f)->null_bit; + // bug 3483, reserve enough space for the longest double value + // -1.7976931348623157E+308 to -2.2250738585072014E-308, 0, and + // 2.2250738585072014E-308 to 1.7976931348623157E+308. + (*f)->field_length = 310; + + if ((f2->decimals() == DECIMAL_NOT_SPECIFIED && row.getScale(s) > 0) + || f2->decimals() < row.getScale(s)) + { + f2->dec = row.getScale(s); + } + dl /= pow(10.0, (double)f2->dec); + + f2->store(static_cast(dl)); + if ((*f)->null_ptr) + *(*f)->null_ptr &= ~(*f)->null_bit; + } + break; + default: + { + continue; // Shouldn't happen. Functions should not return long double to other than double or decimal return type. + } + } break; - - - //int64_t* icvp = (int64_t*)&dl; - //intColVal = *icvp; - //storeNumericField(f, intColVal, colType); - //break; } case CalpontSystemCatalog::DECIMAL: diff --git a/exemgr/main.cpp b/exemgr/main.cpp index a403360ac..e34431e9d 100644 --- a/exemgr/main.cpp +++ b/exemgr/main.cpp @@ -718,8 +718,7 @@ new_plan: string emsg("NOERROR"); ByteStream emsgBs; ByteStream::quadbyte tflg = 0; - jl = JobListFactory::makeJobList( - &csep, fRm, true, true); + jl = JobListFactory::makeJobList(&csep, fRm, true, true); // assign query stats jl->queryStats(fStats); diff --git a/utils/common/nullvaluemanip.cpp b/utils/common/nullvaluemanip.cpp index 475f495cc..dc0777eef 100644 --- a/utils/common/nullvaluemanip.cpp +++ b/utils/common/nullvaluemanip.cpp @@ -122,9 +122,6 @@ uint64_t getNullValue(CalpontSystemCatalog::ColDataType t, uint32_t colWidth) case CalpontSystemCatalog::UBIGINT: return joblist::UBIGINTNULL; - case CalpontSystemCatalog::LONGDOUBLE: - return -1; // no NULL value for long double yet, this is a nan. - case CalpontSystemCatalog::VARBINARY: default: ostringstream os; @@ -233,7 +230,7 @@ int64_t getSignedNullValue(CalpontSystemCatalog::ColDataType t, uint32_t colWidt return (int64_t)joblist::UBIGINTNULL; case CalpontSystemCatalog::LONGDOUBLE: - return -1; // no NULL value for long double yet, this is a nan. + return (int64_t)joblist::LONGDOUBLENULL; case CalpontSystemCatalog::VARBINARY: default: diff --git a/utils/dataconvert/dataconvert.cpp b/utils/dataconvert/dataconvert.cpp index 7614385b5..08a833cd0 100644 --- a/utils/dataconvert/dataconvert.cpp +++ b/utils/dataconvert/dataconvert.cpp @@ -3208,8 +3208,9 @@ CalpontSystemCatalog::ColType DataConvert::convertUnionColType(vector unionedType.scale) ? types[i].scale : unionedType.scale; unionedType.colWidth = sizeof(long double); + unionedType.precision = -1; break; default: diff --git a/utils/funcexp/func_abs.cpp b/utils/funcexp/func_abs.cpp index 14cb5531a..2cb25c001 100644 --- a/utils/funcexp/func_abs.cpp +++ b/utils/funcexp/func_abs.cpp @@ -78,6 +78,14 @@ double Func_abs::getDoubleVal(Row& row, return fabs(parm[0]->data()->getDoubleVal(row, isNull)); } +long double Func_abs::getLongDoubleVal(Row& row, + FunctionParm& parm, + bool& isNull, + CalpontSystemCatalog::ColType&) +{ + return fabsl(parm[0]->data()->getLongDoubleVal(row, isNull)); +} + } // namespace funcexp // vim:ts=4 sw=4: diff --git a/utils/funcexp/func_case.cpp b/utils/funcexp/func_case.cpp index 03ca241f8..46371026a 100644 --- a/utils/funcexp/func_case.cpp +++ b/utils/funcexp/func_case.cpp @@ -243,6 +243,27 @@ inline uint64_t simple_case_cmp(Row& row, break; } + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + long double ev = parm[n]->data()->getLongDoubleVal(row, isNull); + + if (isNull) + break; + + for (i = 1; i <= whereCount; i++) + { + if (ev == parm[i]->data()->getLongDoubleVal(row, isNull) && !isNull) + { + foundIt = true; + break; + } + else + isNull = false; + } + + break; + } + default: { std::ostringstream oss; @@ -510,6 +531,19 @@ double Func_simple_case::getDoubleVal(Row& row, return parm[i]->data()->getDoubleVal(row, isNull); } +long double Func_simple_case::getLongDoubleVal(Row& row, + FunctionParm& parm, + bool& isNull, + CalpontSystemCatalog::ColType& operationColType) +{ + uint64_t i = simple_case_cmp(row, parm, isNull, operationColType); + + if (isNull) + return doubleNullVal(); + + return parm[i]->data()->getLongDoubleVal(row, isNull); +} + int32_t Func_simple_case::getDateIntVal(rowgroup::Row& row, FunctionParm& parm, @@ -649,6 +683,19 @@ double Func_searched_case::getDoubleVal(Row& row, return parm[i]->data()->getDoubleVal(row, isNull); } +long double Func_searched_case::getLongDoubleVal(Row& row, + FunctionParm& parm, + bool& isNull, + CalpontSystemCatalog::ColType&) +{ + uint64_t i = searched_case_cmp(row, parm, isNull); + + if (isNull) + return longDoubleNullVal(); + + return parm[i]->data()->getLongDoubleVal(row, isNull); +} + int32_t Func_searched_case::getDateIntVal(rowgroup::Row& row, FunctionParm& parm, diff --git a/utils/funcexp/func_cast.cpp b/utils/funcexp/func_cast.cpp index b396c45ea..75262f13a 100644 --- a/utils/funcexp/func_cast.cpp +++ b/utils/funcexp/func_cast.cpp @@ -139,6 +139,26 @@ int64_t Func_cast_signed::getIntVal(Row& row, } break; + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + long double value = parm[0]->data()->getLongDoubleVal(row, isNull); + + if (value > 0) + value += 0.5; + else if (value < 0) + value -= 0.5; + + int64_t ret = (int64_t) value; + + if (value > (long double) numeric_limits::max()) + ret = numeric_limits::max(); + else if (value < (long double) (numeric_limits::min() + 2)) + ret = numeric_limits::min() + 2; // IDB min for bigint + + return ret; + } + break; + case execplan::CalpontSystemCatalog::VARCHAR: case execplan::CalpontSystemCatalog::CHAR: case execplan::CalpontSystemCatalog::TEXT: @@ -266,6 +286,26 @@ uint64_t Func_cast_unsigned::getUintVal(Row& row, } break; + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + long double value = parm[0]->data()->getLongDoubleVal(row, isNull); + + if (value > 0) + value += 0.5; + else if (value < 0) + value -= 0.5; + + uint64_t ret = (uint64_t) value; + + if (value > (long double) numeric_limits::max() - 2) + ret = numeric_limits::max(); + else if (value < 0) + ret = 0; + + return ret; + } + break; + case execplan::CalpontSystemCatalog::VARCHAR: case execplan::CalpontSystemCatalog::CHAR: case execplan::CalpontSystemCatalog::TEXT: @@ -391,6 +431,12 @@ string Func_cast_char::getStrVal(Row& row, } break; + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + return helpers::longDoubleToString(parm[0]->data()->getLongDoubleVal(row, isNull)).substr(0, length); + } + break; + case execplan::CalpontSystemCatalog::FLOAT: case execplan::CalpontSystemCatalog::UFLOAT: { @@ -526,6 +572,17 @@ double Func_cast_date::getDoubleVal(Row& row, operationColType); } +long double Func_cast_date::getLongDoubleVal(Row& row, + FunctionParm& parm, + bool& isNull, + CalpontSystemCatalog::ColType& operationColType) +{ + return (long double) Func_cast_date::getDatetimeIntVal(row, + parm, + isNull, + operationColType); +} + int32_t Func_cast_date::getDateIntVal(rowgroup::Row& row, FunctionParm& parm, @@ -795,6 +852,17 @@ double Func_cast_datetime::getDoubleVal(Row& row, operationColType); } +long double Func_cast_datetime::getLongDoubleVal(Row& row, + FunctionParm& parm, + bool& isNull, + CalpontSystemCatalog::ColType& operationColType) +{ + return (long double) Func_cast_datetime::getDatetimeIntVal(row, + parm, + isNull, + operationColType); +} + int64_t Func_cast_datetime::getDatetimeIntVal(rowgroup::Row& row, FunctionParm& parm, bool& isNull, @@ -1099,6 +1167,26 @@ IDB_Decimal Func_cast_decimal::getDecimalVal(Row& row, } break; + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + long double value = parm[0]->data()->getLongDoubleVal(row, isNull); + + if (value > 0) + decimal.value = (int64_t) (value * helpers::powerOf10_c[decimals] + 0.5); + else if (value < 0) + decimal.value = (int64_t) (value * helpers::powerOf10_c[decimals] - 0.5); + else + decimal.value = 0; + + decimal.scale = decimals; + + if ( value > max_number_decimal ) + decimal.value = max_number_decimal; + else if ( value < -max_number_decimal ) + decimal.value = -max_number_decimal; + } + break; + case execplan::CalpontSystemCatalog::DECIMAL: case execplan::CalpontSystemCatalog::UDECIMAL: { @@ -1426,6 +1514,12 @@ double Func_cast_double::getDoubleVal(Row& row, } break; + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + dblval = static_cast(parm[0]->data()->getLongDoubleVal(row, isNull)); + } + break; + case execplan::CalpontSystemCatalog::DECIMAL: case execplan::CalpontSystemCatalog::UDECIMAL: { diff --git a/utils/funcexp/func_ceil.cpp b/utils/funcexp/func_ceil.cpp index f270ed641..8fda7c6de 100644 --- a/utils/funcexp/func_ceil.cpp +++ b/utils/funcexp/func_ceil.cpp @@ -219,6 +219,12 @@ uint64_t Func_ceil::getUintVal(Row& row, } break; + case CalpontSystemCatalog::LONGDOUBLE: + { + ret = (uint64_t) ceill(parm[0]->data()->getLongDoubleVal(row, isNull)); + } + break; + case CalpontSystemCatalog::VARCHAR: case CalpontSystemCatalog::CHAR: case CalpontSystemCatalog::TEXT: @@ -293,6 +299,52 @@ double Func_ceil::getDoubleVal(Row& row, if (!isNull) ret = ceil(strtod(str.c_str(), 0)); } + else if (op_ct.colDataType == CalpontSystemCatalog::LONGDOUBLE) + { + ret = (double)ceill(parm[0]->data()->getLongDoubleVal(row, isNull)); + } + else + { + if (isUnsigned(op_ct.colDataType)) + { + ret = (double) getUintVal(row, parm, isNull, op_ct); + } + else + { + ret = (double) getIntVal(row, parm, isNull, op_ct); + } + } + + return ret; +} + +long double Func_ceil::getLongDoubleVal(Row& row, + FunctionParm& parm, + bool& isNull, + CalpontSystemCatalog::ColType& op_ct) +{ + long double ret = 0.0; + + if (op_ct.colDataType == CalpontSystemCatalog::LONGDOUBLE) + { + ret = ceill(parm[0]->data()->getLongDoubleVal(row, isNull)); + } + else if (op_ct.colDataType == CalpontSystemCatalog::DOUBLE || + op_ct.colDataType == CalpontSystemCatalog::UDOUBLE || + op_ct.colDataType == CalpontSystemCatalog::FLOAT || + op_ct.colDataType == CalpontSystemCatalog::UFLOAT) + { + ret = ceil(parm[0]->data()->getDoubleVal(row, isNull)); + } + else if (op_ct.colDataType == CalpontSystemCatalog::VARCHAR || + op_ct.colDataType == CalpontSystemCatalog::CHAR || + op_ct.colDataType == CalpontSystemCatalog::TEXT) + { + const string& str = parm[0]->data()->getStrVal(row, isNull); + + if (!isNull) + ret = ceil(strtod(str.c_str(), 0)); + } else { if (isUnsigned(op_ct.colDataType)) @@ -334,6 +386,18 @@ string Func_ceil::getStrVal(Row& row, *d = '\0'; } + else if (op_ct.colDataType == CalpontSystemCatalog::LONGDOUBLE) + { + snprintf(tmp, 511, "%Lf", getLongDoubleVal(row, parm, isNull, op_ct)); + + // remove the decimals in the oss string. + char* d = tmp; + + while ((*d != '.') && (*d != '\0')) + d++; + + *d = '\0'; + } else if (isUnsigned(op_ct.colDataType)) { #ifndef __LP64__ diff --git a/utils/funcexp/func_coalesce.cpp b/utils/funcexp/func_coalesce.cpp index e03040350..c79119bb7 100644 --- a/utils/funcexp/func_coalesce.cpp +++ b/utils/funcexp/func_coalesce.cpp @@ -188,6 +188,31 @@ double Func_coalesce::getDoubleVal(rowgroup::Row& row, } +long double Func_coalesce::getLongDoubleVal(rowgroup::Row& row, + FunctionParm& parm, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& ct) +{ + long double d = 0.0; + + for (uint32_t i = 0; i < parm.size(); i++) + { + d = parm[i]->data()->getLongDoubleVal(row, isNull); + + if (isNull) + { + isNull = false; + continue; + } + + return d; + } + + isNull = true; + return d; +} + + execplan::IDB_Decimal Func_coalesce::getDecimalVal(rowgroup::Row& row, FunctionParm& parm, bool& isNull, diff --git a/utils/funcexp/func_exp.cpp b/utils/funcexp/func_exp.cpp index 8f1a5bbec..a1913064d 100644 --- a/utils/funcexp/func_exp.cpp +++ b/utils/funcexp/func_exp.cpp @@ -81,6 +81,38 @@ double Func_exp::getDoubleVal(Row& row, return ret; } +long double Func_exp::getLongDoubleVal(Row& row, + FunctionParm& parm, + bool& isNull, + CalpontSystemCatalog::ColType&) +{ + // null value is indicated by isNull + long double x = parm[0]->data()->getLongDoubleVal(row, isNull); + long double ret = 0.0; + + if (!isNull) + { + errno = 0; + ret = expl(x); + + if (errno == ERANGE) // display NULL for out range value + { + if (x > 0) + { + isNull = true; + Message::Args args; + args.add("exp"); + args.add((double)x); + unsigned errcode = ERR_FUNC_OUT_OF_RANGE_RESULT; + throw IDBExcept(IDBErrorInfo::instance()->errorMsg(errcode, args), errcode); + } + else + ret = 0.0; + } + } + + return ret; +} } // namespace funcexp // vim:ts=4 sw=4: diff --git a/utils/funcexp/func_floor.cpp b/utils/funcexp/func_floor.cpp index eb05b405f..8e632c971 100644 --- a/utils/funcexp/func_floor.cpp +++ b/utils/funcexp/func_floor.cpp @@ -118,6 +118,12 @@ int64_t Func_floor::getIntVal(Row& row, } break; + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + ret = (int64_t) floorl(parm[0]->data()->getLongDoubleVal(row, isNull)); + } + break; + case execplan::CalpontSystemCatalog::VARCHAR: case execplan::CalpontSystemCatalog::CHAR: case execplan::CalpontSystemCatalog::TEXT: @@ -216,6 +222,12 @@ uint64_t Func_floor::getUintVal(Row& row, } break; + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + ret = (uint64_t) floorl(parm[0]->data()->getLongDoubleVal(row, isNull)); + } + break; + case execplan::CalpontSystemCatalog::VARCHAR: case execplan::CalpontSystemCatalog::CHAR: case execplan::CalpontSystemCatalog::TEXT: @@ -286,6 +298,10 @@ double Func_floor::getDoubleVal(Row& row, { ret = floor(parm[0]->data()->getDoubleVal(row, isNull)); } + else if (op_ct.colDataType == CalpontSystemCatalog::LONGDOUBLE) + { + ret = floorl(parm[0]->data()->getLongDoubleVal(row, isNull)); + } else if (op_ct.colDataType == CalpontSystemCatalog::VARCHAR || op_ct.colDataType == CalpontSystemCatalog::CHAR || op_ct.colDataType == CalpontSystemCatalog::TEXT) @@ -303,6 +319,38 @@ double Func_floor::getDoubleVal(Row& row, return ret; } +long double Func_floor::getLongDoubleVal(Row& row, + FunctionParm& parm, + bool& isNull, + CalpontSystemCatalog::ColType& op_ct) +{ + long double ret = 0.0; + + if (op_ct.colDataType == CalpontSystemCatalog::LONGDOUBLE || + op_ct.colDataType == CalpontSystemCatalog::FLOAT) + { + ret = floor(parm[0]->data()->getDoubleVal(row, isNull)); + } + else if (op_ct.colDataType == CalpontSystemCatalog::LONGDOUBLE) + { + ret = floorl(parm[0]->data()->getLongDoubleVal(row, isNull)); + } + else if (op_ct.colDataType == CalpontSystemCatalog::VARCHAR || + op_ct.colDataType == CalpontSystemCatalog::CHAR || + op_ct.colDataType == CalpontSystemCatalog::TEXT) + { + const string& str = parm[0]->data()->getStrVal(row, isNull); + + if (!isNull) + ret = floor(strtod(str.c_str(), 0)); + } + else + { + ret = (long double) getIntVal(row, parm, isNull, op_ct); + } + + return ret; +} string Func_floor::getStrVal(Row& row, FunctionParm& parm, @@ -329,6 +377,18 @@ string Func_floor::getStrVal(Row& row, *d = '\0'; } + if (op_ct.colDataType == CalpontSystemCatalog::LONGDOUBLE) + { + snprintf(tmp, 511, "%Lf", getLongDoubleVal(row, parm, isNull, op_ct)); + + // remove the decimals in the oss string. + char* d = tmp; + + while ((*d != '.') && (*d != '\0')) + d++; + + *d = '\0'; + } else if (isUnsigned(op_ct.colDataType)) { #ifndef __LP64__ diff --git a/utils/funcexp/func_from_unixtime.cpp b/utils/funcexp/func_from_unixtime.cpp index 9968ba1f0..9f116c751 100644 --- a/utils/funcexp/func_from_unixtime.cpp +++ b/utils/funcexp/func_from_unixtime.cpp @@ -209,6 +209,14 @@ double Func_from_unixtime::getDoubleVal(rowgroup::Row& row, return (double) atoi(getStrVal(row, parm, isNull, ct).c_str()); } +long double Func_from_unixtime::getLongDoubleVal(rowgroup::Row& row, + FunctionParm& parm, + bool& isNull, + CalpontSystemCatalog::ColType& ct) +{ + return (long double) getDoubleVal(row, parm, isNull, ct); +} + } // namespace funcexp // vim:ts=4 sw=4: diff --git a/utils/funcexp/func_greatest.cpp b/utils/funcexp/func_greatest.cpp index de63c283e..4b55d2250 100644 --- a/utils/funcexp/func_greatest.cpp +++ b/utils/funcexp/func_greatest.cpp @@ -121,6 +121,26 @@ double Func_greatest::getDoubleVal(rowgroup::Row& row, return (double) greatestStr; } +long double Func_greatest::getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct) +{ + long double str = fp[0]->data()->getLongDoubleVal(row, isNull); + + long double greatestStr = str; + + for (uint32_t i = 1; i < fp.size(); i++) + { + long double str1 = fp[i]->data()->getLongDoubleVal(row, isNull); + + if ( greatestStr < str1 ) + greatestStr = str1; + } + + return greatestStr; +} + std::string Func_greatest::getStrVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, diff --git a/utils/funcexp/func_if.cpp b/utils/funcexp/func_if.cpp index ad65d10c9..7141037da 100644 --- a/utils/funcexp/func_if.cpp +++ b/utils/funcexp/func_if.cpp @@ -61,6 +61,9 @@ bool boolVal(SPTP& parm, Row& row) case CalpontSystemCatalog::UDOUBLE: ret = (parm->data()->getDoubleVal(row, isNull) != 0); + case CalpontSystemCatalog::LONGDOUBLE: + ret = (parm->data()->getLongDoubleVal(row, isNull) != 0); + case CalpontSystemCatalog::DECIMAL: case CalpontSystemCatalog::UDECIMAL: ret = (parm->data()->getDecimalVal(row, isNull).value != 0); @@ -188,6 +191,21 @@ double Func_if::getDoubleVal(Row& row, } } +long double Func_if::getLongDoubleVal(Row& row, + FunctionParm& parm, + bool& isNull, + CalpontSystemCatalog::ColType&) +{ + if (boolVal(parm[0], row)) + { + return parm[1]->data()->getLongDoubleVal(row, isNull); + } + else + { + return parm[2]->data()->getLongDoubleVal(row, isNull); + } +} + int32_t Func_if::getDateIntVal(Row& row, FunctionParm& parm, diff --git a/utils/funcexp/func_ifnull.cpp b/utils/funcexp/func_ifnull.cpp index 4b8606d4e..8879a98dc 100644 --- a/utils/funcexp/func_ifnull.cpp +++ b/utils/funcexp/func_ifnull.cpp @@ -129,6 +129,25 @@ double Func_ifnull::getDoubleVal(Row& row, return r; } +long double Func_ifnull::getLongDoubleVal(Row& row, + FunctionParm& parm, + bool& isNull, + CalpontSystemCatalog::ColType&) +{ + if (isNull) + return 0.0; + + long double r = parm[0]->data()->getLongDoubleVal(row, isNull); + + if (isNull) + { + isNull = false; + return parm[1]->data()->getLongDoubleVal(row, isNull); + } + + return r; +} + int32_t Func_ifnull::getDateIntVal(Row& row, FunctionParm& parm, diff --git a/utils/funcexp/func_in.cpp b/utils/funcexp/func_in.cpp index e271fa0f7..f34d9f8b6 100644 --- a/utils/funcexp/func_in.cpp +++ b/utils/funcexp/func_in.cpp @@ -203,6 +203,27 @@ inline bool getBoolForIn(rowgroup::Row& row, return false; } + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + long double val = pm[0]->data()->getLongDoubleVal(row, isNull); + + if (isNull) + return false; + + for (uint32_t i = 1; i < pm.size(); i++) + { + isNull = false; + + if ( val == pm[i]->data()->getLongDoubleVal(row, isNull) && !isNull ) + return true; + + if (isNull && isNotIn) + return true; // will be reversed to false by the caller + } + + return false; + } + case execplan::CalpontSystemCatalog::DECIMAL: case execplan::CalpontSystemCatalog::UDECIMAL: { diff --git a/utils/funcexp/func_isnull.cpp b/utils/funcexp/func_isnull.cpp index 3558f6e30..709abf814 100644 --- a/utils/funcexp/func_isnull.cpp +++ b/utils/funcexp/func_isnull.cpp @@ -74,6 +74,10 @@ bool Func_isnull::getBoolVal(Row& row, parm[0]->data()->getStrVal(row, isNull); break; + case CalpontSystemCatalog::LONGDOUBLE: + parm[0]->data()->getLongDoubleVal(row, isNull); + break; + default: parm[0]->data()->getIntVal(row, isNull); } diff --git a/utils/funcexp/func_least.cpp b/utils/funcexp/func_least.cpp index 9ba5c98de..874548d07 100644 --- a/utils/funcexp/func_least.cpp +++ b/utils/funcexp/func_least.cpp @@ -100,6 +100,26 @@ double Func_least::getDoubleVal(rowgroup::Row& row, return (double) leastStr; } +long double Func_least::getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct) +{ + long double str = fp[0]->data()->getLongDoubleVal(row, isNull); + + long double leastStr = str; + + for (uint32_t i = 1; i < fp.size(); i++) + { + long double str1 = fp[i]->data()->getLongDoubleVal(row, isNull); + + if ( leastStr > str1 ) + leastStr = str1; + } + + return leastStr; +} + std::string Func_least::getStrVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, diff --git a/utils/funcexp/func_math.cpp b/utils/funcexp/func_math.cpp index 8592ec8b0..6863517b8 100644 --- a/utils/funcexp/func_math.cpp +++ b/utils/funcexp/func_math.cpp @@ -1523,6 +1523,26 @@ string Func_format::getStrVal(Row& row, } break; + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + long double rawValue = parm[0]->data()->getLongDoubleVal(row, isNull); + + // roundup + if (scale < 0) scale = 0; + + if (rawValue >= 0) + rawValue += 0.5 / pow(10.0, scale); + else + rawValue -= 0.5 / pow(10.0, scale); + + // double's can be *really* long to print out. Max mysql + // is e308 so allow for 308 + 36 decimal places minimum. + char buf[384]; + snprintf(buf, 384, "%0.36Lf", rawValue); + value = buf; + } + break; + default: { std::ostringstream oss; diff --git a/utils/funcexp/func_mod.cpp b/utils/funcexp/func_mod.cpp index c5eb05112..a13780d17 100644 --- a/utils/funcexp/func_mod.cpp +++ b/utils/funcexp/func_mod.cpp @@ -142,6 +142,14 @@ double Func_mod::getDoubleVal(Row& row, } break; + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + long double value = parm[0]->data()->getLongDoubleVal(row, isNull); + + mod = (double)fmodl(value, div); + } + break; + case execplan::CalpontSystemCatalog::FLOAT: case execplan::CalpontSystemCatalog::UFLOAT: { @@ -181,6 +189,110 @@ double Func_mod::getDoubleVal(Row& row, return mod; } +long double Func_mod::getLongDoubleVal(Row& row, + FunctionParm& parm, + bool& isNull, + CalpontSystemCatalog::ColType& operationColType) +{ + if ( parm.size() < 2 ) + { + isNull = true; + return 0; + } + + int64_t div = parm[1]->data()->getIntVal(row, isNull); + + if ( div == 0 ) + { + isNull = true; + return 0; + } + + long double mod = 0; + + switch (parm[0]->data()->resultType().colDataType) + { + case execplan::CalpontSystemCatalog::BIGINT: + case execplan::CalpontSystemCatalog::INT: + case execplan::CalpontSystemCatalog::MEDINT: + case execplan::CalpontSystemCatalog::TINYINT: + case execplan::CalpontSystemCatalog::SMALLINT: + { + int64_t value = parm[0]->data()->getIntVal(row, isNull); + + mod = value % div; + } + break; + + case execplan::CalpontSystemCatalog::UBIGINT: + case execplan::CalpontSystemCatalog::UINT: + case execplan::CalpontSystemCatalog::UMEDINT: + case execplan::CalpontSystemCatalog::UTINYINT: + case execplan::CalpontSystemCatalog::USMALLINT: + { + uint64_t udiv = parm[1]->data()->getIntVal(row, isNull); + uint64_t uvalue = parm[0]->data()->getUintVal(row, isNull); + + mod = uvalue % udiv; + } + break; + + case execplan::CalpontSystemCatalog::DOUBLE: + case execplan::CalpontSystemCatalog::UDOUBLE: + { + double value = parm[0]->data()->getDoubleVal(row, isNull); + + mod = fmod(value, div); + } + break; + + case execplan::CalpontSystemCatalog::FLOAT: + case execplan::CalpontSystemCatalog::UFLOAT: + { + float value = parm[0]->data()->getFloatVal(row, isNull); + + mod = fmod(value, div); + } + break; + + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + long double value = parm[0]->data()->getLongDoubleVal(row, isNull); + + mod = fmodl(value, div); + } + break; + + case execplan::CalpontSystemCatalog::DECIMAL: + case execplan::CalpontSystemCatalog::UDECIMAL: + { + IDB_Decimal d = parm[0]->data()->getDecimalVal(row, isNull); + int64_t value = d.value / helpers::power(d.scale); + + mod = value % div; + } + break; + + case execplan::CalpontSystemCatalog::CHAR: + case execplan::CalpontSystemCatalog::VARCHAR: + case execplan::CalpontSystemCatalog::TEXT: + { + double value = parm[0]->data()->getDoubleVal(row, isNull); + mod = fmod(value, div); + break; + } + + default: + { + std::ostringstream oss; + oss << "mod: datatype of " << execplan::colDataTypeToString(parm[0]->data()->resultType().colDataType); + throw logging::IDBExcept(oss.str(), ERR_DATATYPE_NOT_SUPPORT); + } + } + + return mod; +} + int64_t Func_mod::getIntVal(Row& row, FunctionParm& parm, bool& isNull, @@ -250,6 +362,14 @@ int64_t Func_mod::getIntVal(Row& row, } break; + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + long double value = parm[0]->data()->getLongDoubleVal(row, isNull); + + mod = fmodl(value, div); + } + break; + case execplan::CalpontSystemCatalog::DECIMAL: case execplan::CalpontSystemCatalog::UDECIMAL: { @@ -340,6 +460,14 @@ uint64_t Func_mod::getUIntVal(Row& row, } break; + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + long double value = parm[0]->data()->getLongDoubleVal(row, isNull); + + mod = fmodl(value, div); + } + break; + case execplan::CalpontSystemCatalog::DECIMAL: case execplan::CalpontSystemCatalog::UDECIMAL: { @@ -387,6 +515,10 @@ std::string Func_mod::getStrVal(Row& row, return intToString(getIntVal(row, fp, isNull, op_ct)); break; + case execplan::CalpontSystemCatalog::LONGDOUBLE: + return longDoubleToString(getLongDoubleVal(row, fp, isNull, op_ct)); + break; + default: return doubleToString(getDoubleVal(row, fp, isNull, op_ct)); break; diff --git a/utils/funcexp/func_nullif.cpp b/utils/funcexp/func_nullif.cpp index 04a45534a..3a40fe134 100644 --- a/utils/funcexp/func_nullif.cpp +++ b/utils/funcexp/func_nullif.cpp @@ -579,6 +579,109 @@ double Func_nullif::getDoubleVal(rowgroup::Row& row, break; } + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + exp2 = (double)parm[1]->data()->getLongDoubleVal(row, isNull); + + if (isNull) + { + isNull = false; + return exp1; + } + + break; + } + + case execplan::CalpontSystemCatalog::DATE: + { + exp2 = parm[1]->data()->getDateIntVal(row, isNull); + + if (isNull) + { + isNull = false; + return exp1; + } + + break; + } + break; + + case execplan::CalpontSystemCatalog::TIME: + case execplan::CalpontSystemCatalog::DATETIME: + { + exp2 = parm[1]->data()->getDatetimeIntVal(row, isNull); + + if (isNull) + { + isNull = false; + return exp1; + } + + break; + } + + default: + { + isNull = true; + } + } + + if ( exp1 == exp2 ) + { + isNull = true; + return 0; + } + + return exp1; +} + + +long double Func_nullif::getLongDoubleVal(rowgroup::Row& row, + FunctionParm& parm, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct) +{ + long double exp1 = parm[0]->data()->getLongDoubleVal(row, isNull); + long double exp2 = 0; + + switch (parm[1]->data()->resultType().colDataType) + { + case execplan::CalpontSystemCatalog::BIGINT: + case execplan::CalpontSystemCatalog::INT: + case execplan::CalpontSystemCatalog::MEDINT: + case execplan::CalpontSystemCatalog::TINYINT: + case execplan::CalpontSystemCatalog::SMALLINT: + case execplan::CalpontSystemCatalog::DOUBLE: + case execplan::CalpontSystemCatalog::FLOAT: + case execplan::CalpontSystemCatalog::DECIMAL: + case execplan::CalpontSystemCatalog::VARCHAR: + case execplan::CalpontSystemCatalog::CHAR: + case execplan::CalpontSystemCatalog::TEXT: + { + exp2 = parm[1]->data()->getDoubleVal(row, isNull); + + if (isNull) + { + isNull = false; + return exp1; + } + + break; + } + + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + exp2 = parm[1]->data()->getLongDoubleVal(row, isNull); + + if (isNull) + { + isNull = false; + return exp1; + } + + break; + } + case execplan::CalpontSystemCatalog::DATE: { exp2 = parm[1]->data()->getDateIntVal(row, isNull); diff --git a/utils/funcexp/func_pow.cpp b/utils/funcexp/func_pow.cpp index c838d174e..cbe1a9905 100644 --- a/utils/funcexp/func_pow.cpp +++ b/utils/funcexp/func_pow.cpp @@ -89,6 +89,44 @@ double Func_pow::getDoubleVal(Row& row, return 0.0; } +long double Func_pow::getLongDoubleVal(Row& row, + FunctionParm& parm, + bool& isNull, + CalpontSystemCatalog::ColType&) +{ + // null value is indicated by isNull + long double base = parm[0]->data()->getLongDoubleVal(row, isNull); + + if (!isNull) + { + // Should this be long double? Not sure on usage. + double exponent = parm[1]->data()->getDoubleVal(row, isNull); + + if (!isNull) + { + errno = 0; + long double x = powl(base, (long double)exponent); + + // @bug3490, 4461, rule out domain error, pole error and overflow range error. + if (!isfinite(x)) + { + isNull = true; + Message::Args args; + args.add("pow"); + args.add((double)base); + args.add(exponent); + unsigned errcode = ERR_FUNC_OUT_OF_RANGE_RESULT; + throw IDBExcept(IDBErrorInfo::instance()->errorMsg(errcode, args), errcode); + } + + + return x; + } + } + + return 0.0; +} + } // namespace funcexp // vim:ts=4 sw=4: diff --git a/utils/funcexp/func_round.cpp b/utils/funcexp/func_round.cpp index c107fc0fc..eab18abc2 100644 --- a/utils/funcexp/func_round.cpp +++ b/utils/funcexp/func_round.cpp @@ -45,7 +45,9 @@ namespace using namespace funcexp; -inline void decimalPlaceDouble(FunctionParm& fp, int64_t& s, double& p, Row& row, bool& isNull) +// P should either be double or long double +template +inline void decimalPlaceDouble(FunctionParm& fp, int64_t& s, P& p, Row& row, bool& isNull) { s = fp[1]->data()->getIntVal(row, isNull); int64_t d = s; @@ -60,9 +62,9 @@ inline void decimalPlaceDouble(FunctionParm& fp, int64_t& s, double& p, Row& row r *= 10; if (d >= 0) - p = (double) r; + p = (P) r; else - p = 1.0 / ((double) r); + p = 1.0 / ((P) r); } } @@ -200,6 +202,67 @@ double Func_round::getDoubleVal(Row& row, return d; } +long double Func_round::getLongDoubleVal(Row& row, + FunctionParm& parm, + bool& isNull, + CalpontSystemCatalog::ColType& op_ct) +{ + if (execplan::CalpontSystemCatalog::LONGDOUBLE == op_ct.colDataType) + { + int64_t d = 0; + long double p = 1; + + if (parm.size() > 1) // round(X, D) + decimalPlaceDouble(parm, d, p, row, isNull); + + if (isNull) + return 0.0; + + long double x = parm[0]->data()->getLongDoubleVal(row, isNull); + + if (!isNull) + { + x *= p; + + if (x >= 0) + x = floor(x + 0.5); + else + x = ceil(x - 0.5); + + if (p != 0.0) + x /= p; + else + x = 0.0; + } + + return x; + } + + if (isUnsigned(op_ct.colDataType)) + { + return getUintVal(row, parm, isNull, op_ct); + } + + IDB_Decimal x = getDecimalVal(row, parm, isNull, op_ct); + + if (isNull) + return 0.0; + + double d = x.value; + + if (x.scale > 0) + { + while (x.scale-- > 0) + d /= 10.0; + } + else + { + while (x.scale++ < 0) + d *= 10.0; + } + + return d; +} IDB_Decimal Func_round::getDecimalVal(Row& row, FunctionParm& parm, @@ -330,6 +393,34 @@ IDB_Decimal Func_round::getDecimalVal(Row& row, } break; + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + int64_t s = 0; + long double p = 1; + + if (parm.size() > 1) // round(X, D) + decimalPlaceDouble(parm, s, p, row, isNull); + + if (isNull) + break; + + long double x = parm[0]->data()->getDoubleVal(row, isNull); + + if (!isNull) + { + x *= p; + + if (x >= 0) + x = floor(x + 0.5); + else + x = ceil(x - 0.5); + + decimal.value = (int64_t) x; + decimal.scale = s; + } + } + break; + case execplan::CalpontSystemCatalog::DATE: { int32_t s = 0; diff --git a/utils/funcexp/func_truncate.cpp b/utils/funcexp/func_truncate.cpp index 2da482ab8..9976e9c38 100644 --- a/utils/funcexp/func_truncate.cpp +++ b/utils/funcexp/func_truncate.cpp @@ -42,7 +42,9 @@ namespace using namespace funcexp; -inline void decimalPlaceDouble(FunctionParm& fp, int64_t& s, double& p, Row& row, bool& isNull) +// P should be double or long double +template +inline void decimalPlaceDouble(FunctionParm& fp, int64_t& s, P& p, Row& row, bool& isNull) { s = fp[1]->data()->getIntVal(row, isNull); int64_t d = s; @@ -57,9 +59,9 @@ inline void decimalPlaceDouble(FunctionParm& fp, int64_t& s, double& p, Row& row r *= 10; if (d >= 0) - p = (double) r; + p = (P) r; else - p = 1.0 / ((double) r); + p = 1.0 / ((P) r); } } @@ -223,6 +225,60 @@ double Func_truncate::getDoubleVal(Row& row, return d; } +long double Func_truncate::getLongDoubleVal(Row& row, + FunctionParm& parm, + bool& isNull, + CalpontSystemCatalog::ColType& op_ct) +{ + if (execplan::CalpontSystemCatalog::LONGDOUBLE == op_ct.colDataType) + { + int64_t d = 0; + long double p = 1; + decimalPlaceDouble(parm, d, p, row, isNull); + + if (isNull) + return 0.0; + + long double x = parm[0]->data()->getLongDoubleVal(row, isNull); + + if (!isNull) + { + x *= p; + + if (x > 0) + x = floor(x); + else + x = ceil(x); + + if (p != 0.0) + x /= p; + else + x = 0.0; + } + + return x; + } + + IDB_Decimal x = getDecimalVal(row, parm, isNull, op_ct); + + if (isNull) + return 0.0; + + double d = x.value; + + if (x.scale > 0) + { + while (x.scale-- > 0) + d /= 10.0; + } + else + { + while (x.scale++ < 0) + d *= 10.0; + } + + return d; +} IDB_Decimal Func_truncate::getDecimalVal(Row& row, FunctionParm& parm, @@ -325,6 +381,26 @@ IDB_Decimal Func_truncate::getDecimalVal(Row& row, } break; + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + int64_t s = 0; + long double p = 1; + decimalPlaceDouble(parm, s, p, row, isNull); + + if (isNull) + break; + + long double x = parm[0]->data()->getLongDoubleVal(row, isNull); + + if (!isNull) + { + x *= p; + decimal.value = (int64_t) x; + decimal.scale = s; + } + } + break; + case execplan::CalpontSystemCatalog::DATE: { int32_t s = 0; diff --git a/utils/funcexp/funchelpers.h b/utils/funcexp/funchelpers.h index ebb78f8cc..b6942bc68 100644 --- a/utils/funcexp/funchelpers.h +++ b/utils/funcexp/funchelpers.h @@ -751,6 +751,16 @@ string doubleToString(double d) return buf; } +inline +string longDoubleToString(long double ld) +{ + // long double's can be *really* long to print out. Max mysql + // is e308 so allow for 308 + 36 decimal places minimum. + char buf[384]; + snprintf(buf, 384, "%Lf", ld); + return buf; +} + //@bug6146, remove duplicate function with incorrect impl. Use the DataConvert::decimalToString() //string decimalToString( execplan::IDB_Decimal x, int p ) diff --git a/utils/funcexp/functor.cpp b/utils/funcexp/functor.cpp index 1e50ea1fc..4350d2dc0 100644 --- a/utils/funcexp/functor.cpp +++ b/utils/funcexp/functor.cpp @@ -60,6 +60,7 @@ void Func::init() double* dp = reinterpret_cast(&dni); fDoubleNullVal = *dp; + fDoubleNullVal = joblist::LONGDOUBLENULL; } @@ -341,6 +342,11 @@ string Func::doubleToString(double d) return helpers::doubleToString(d); } +string Func::longDoubleToString(long double ld) +{ + return helpers::longDoubleToString(ld); +} + } // namespace funcexp // vim:ts=4 sw=4: diff --git a/utils/funcexp/functor.h b/utils/funcexp/functor.h index 20914e99e..ff3d68976 100644 --- a/utils/funcexp/functor.h +++ b/utils/funcexp/functor.h @@ -90,6 +90,11 @@ public: bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct) = 0; + virtual long double getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct) = 0; + virtual std::string getStrVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, @@ -152,6 +157,11 @@ public: { return fDoubleNullVal; } + const long double longDoubleNullVal() const + { + return fLongDoubleNullVal; + } + protected: virtual uint32_t stringToDate(std::string); @@ -164,6 +174,7 @@ protected: virtual std::string intToString(int64_t); virtual std::string doubleToString(double); + virtual std::string longDoubleToString(long double); virtual int64_t nowDatetime(); virtual int64_t addTime(DateTime& dt1, dataconvert::Time& dt2); @@ -180,6 +191,7 @@ private: float fFloatNullVal; double fDoubleNullVal; + long double fLongDoubleNullVal; }; diff --git a/utils/funcexp/functor_all.h b/utils/funcexp/functor_all.h index 553abc40f..24dbebfaf 100644 --- a/utils/funcexp/functor_all.h +++ b/utils/funcexp/functor_all.h @@ -85,6 +85,11 @@ public: bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct); + long double getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); + std::string getStrVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, @@ -137,6 +142,11 @@ public: bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct); + long double getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); + std::string getStrVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, @@ -185,6 +195,11 @@ public: bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct); + long double getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); + std::string getStrVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, @@ -232,6 +247,11 @@ public: bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct); + long double getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); + std::string getStrVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, @@ -289,6 +309,11 @@ public: bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct); + long double getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); + std::string getStrVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, @@ -337,6 +362,11 @@ public: bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct); + long double getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); + std::string getStrVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, @@ -384,6 +414,11 @@ public: bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct); + long double getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); + std::string getStrVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, @@ -456,6 +491,11 @@ public: bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct); + long double getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); + execplan::IDB_Decimal getDecimalVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, diff --git a/utils/funcexp/functor_bool.h b/utils/funcexp/functor_bool.h index b7b85106b..27e32fbbc 100644 --- a/utils/funcexp/functor_bool.h +++ b/utils/funcexp/functor_bool.h @@ -64,6 +64,14 @@ public: return (getBoolVal(row, fp, isNull, op_ct) ? 1.0 : 0.0); } + long double getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct) + { + return (getBoolVal(row, fp, isNull, op_ct) ? 1.0 : 0.0); + } + std::string getStrVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, diff --git a/utils/funcexp/functor_dtm.h b/utils/funcexp/functor_dtm.h index bcff47854..79c4eabd1 100644 --- a/utils/funcexp/functor_dtm.h +++ b/utils/funcexp/functor_dtm.h @@ -57,6 +57,14 @@ public: return (double) getIntVal(row, fp, isNull, op_ct); } + long double getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct) + { + return (long double) getIntVal(row, fp, isNull, op_ct); + } + /* std::string getStrVal(rowgroup::Row& row, FunctionParm& fp, @@ -196,6 +204,11 @@ public: bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct); + long double getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); + std::string getStrVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, @@ -238,6 +251,11 @@ public: bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct); + long double getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); + std::string getStrVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, @@ -423,6 +441,11 @@ public: bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct); + long double getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); + std::string getStrVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, diff --git a/utils/funcexp/functor_export.h b/utils/funcexp/functor_export.h index a58293f98..8cec08373 100644 --- a/utils/funcexp/functor_export.h +++ b/utils/funcexp/functor_export.h @@ -58,6 +58,14 @@ public: bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct); + long double getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct) + { + return (long double)getDoubleVal(row, fp, isNull, op_ct); + } + std::string getStrVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, diff --git a/utils/funcexp/functor_int.h b/utils/funcexp/functor_int.h index 2eb7cc63e..15319ee3a 100644 --- a/utils/funcexp/functor_int.h +++ b/utils/funcexp/functor_int.h @@ -55,6 +55,14 @@ public: return ((double) getIntVal(row, fp, isNull, op_ct)); } + long double getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct) + { + return ((long double) getIntVal(row, fp, isNull, op_ct)); + } + std::string getStrVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, diff --git a/utils/funcexp/functor_real.h b/utils/funcexp/functor_real.h index 5d40ce589..341602ddf 100644 --- a/utils/funcexp/functor_real.h +++ b/utils/funcexp/functor_real.h @@ -57,12 +57,14 @@ public: { return ((uint64_t) getDoubleVal(row, fp, isNull, op_ct)); } - /* - double getDoubleVal(rowgroup::Row& row, - FunctionParm& fp, - bool& isNull, - execplan::CalpontSystemCatalog::ColType& op_ct) = 0; - */ + + long double getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct) + { + return ((long double) getDoubleVal(row, fp, isNull, op_ct)); + } std::string getStrVal(rowgroup::Row& row, FunctionParm& fp, @@ -99,6 +101,11 @@ public: bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct); + long double getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); + execplan::IDB_Decimal getDecimalVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, @@ -120,6 +127,11 @@ public: FunctionParm& fp, bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct); + + long double getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); }; @@ -137,6 +149,11 @@ public: FunctionParm& fp, bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct); + + long double getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); }; @@ -165,6 +182,11 @@ public: bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct); + long double getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); + execplan::IDB_Decimal getDecimalVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, @@ -202,6 +224,11 @@ public: bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct); + long double getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); + std::string getStrVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, @@ -239,6 +266,11 @@ public: bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct); + long double getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); + std::string getStrVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, @@ -271,6 +303,11 @@ public: bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct); + long double getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); + std::string getStrVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, @@ -350,6 +387,11 @@ public: bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct); + long double getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); + execplan::IDB_Decimal getDecimalVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, diff --git a/utils/funcexp/functor_str.h b/utils/funcexp/functor_str.h index 820228848..6624290ac 100644 --- a/utils/funcexp/functor_str.h +++ b/utils/funcexp/functor_str.h @@ -57,7 +57,7 @@ public: return strtod(getStrVal(row, fp, isNull, op_ct).c_str(), NULL); } - double getLongDoubleVal(rowgroup::Row& row, + long double getLongDoubleVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct) diff --git a/utils/joiner/tuplejoiner.cpp b/utils/joiner/tuplejoiner.cpp index edc94b067..c84e54ae0 100644 --- a/utils/joiner/tuplejoiner.cpp +++ b/utils/joiner/tuplejoiner.cpp @@ -45,7 +45,14 @@ TupleJoiner::TupleJoiner( smallRG(smallInput), largeRG(largeInput), joinAlg(INSERTING), joinType(jt), threadCount(1), typelessJoin(false), bSignedUnsignedJoin(false), uniqueLimit(100), finished(false) { - if (smallRG.usesStringTable()) + if (smallRG.getColTypes()[smallJoinColumn] == CalpontSystemCatalog::LONGDOUBLE) + { + STLPoolAllocator > alloc(64 * 1024 * 1024 + 1); + _pool = alloc.getPoolAllocator(); + + ld.reset(new ldhash_t(10, hasher(), ldhash_t::key_equal(), alloc)); + } + else if (smallRG.usesStringTable()) { STLPoolAllocator > alloc(64 * 1024 * 1024 + 1); _pool = alloc.getPoolAllocator(); @@ -131,8 +138,14 @@ TupleJoiner::TupleJoiner( if (keyLength > 65536) keyLength = 65536; } + else if (smallRG.getColTypes()[smallKeyColumns[i]] == CalpontSystemCatalog::LONGDOUBLE) + { + keyLength += sizeof(long double); + } else + { keyLength += 8; + } // Set bSignedUnsignedJoin if one or more join columns are signed to unsigned compares. if (smallRG.isUnsigned(smallKeyColumns[i]) != largeRG.isUnsigned(largeKeyColumns[i])) @@ -198,9 +211,20 @@ void TupleJoiner::insert(Row& r, bool zeroTheRid) { if (typelessJoin) { - ht->insert(pair - (makeTypelessKey(r, smallKeyColumns, keyLength, &storedKeyAlloc), - r.getPointer())); + TypelessData td = makeTypelessKey(r, smallKeyColumns, keyLength, &storedKeyAlloc, + largeRG, largeKeyColumns); + if (td.len > 0) + { + ht->insert(pair(td, r.getPointer())); + } + } + else if (r.getColType(smallKeyColumns[0]) == execplan::CalpontSystemCatalog::LONGDOUBLE) + { + long double smallKey = r.getLongDoubleField(smallKeyColumns[0]); + if (UNLIKELY(smallKey == joblist::LONGDOUBLENULL)) + ld->insert(pair(joblist::LONGDOUBLENULL, r.getPointer())); + else + ld->insert(pair(smallKey, r.getPointer())); } else if (!smallRG.usesStringTable()) { @@ -260,9 +284,16 @@ void TupleJoiner::match(rowgroup::Row& largeSideRow, uint32_t largeRowIndex, uin thIterator it; pair range; - largeKey = makeTypelessKey(largeSideRow, largeKeyColumns, keyLength, &tmpKeyAlloc[threadID]); - it = ht->find(largeKey); - + largeKey = makeTypelessKey(largeSideRow, largeKeyColumns, keyLength, &tmpKeyAlloc[threadID], smallRG, smallKeyColumns); + if (largeKey.len > 0) + { + it = ht->find(largeKey); + } + else + { + return; + } + if (it == ht->end() && !(joinType & (LARGEOUTER | MATCHNULLS))) return; @@ -271,6 +302,28 @@ void TupleJoiner::match(rowgroup::Row& largeSideRow, uint32_t largeRowIndex, uin for (; range.first != range.second; ++range.first) matches->push_back(range.first->second); } + else if (largeSideRow.getColType(largeKeyColumns[0]) == CalpontSystemCatalog::LONGDOUBLE + && ld) + { + // This is a compare of two long double + long double largeKey; + ldIterator it; + pair range; + Row r; + + largeKey = largeSideRow.getLongDoubleField(largeKeyColumns[0]); + it = ld->find(largeKey); + + if (it == ld->end() && !(joinType & (LARGEOUTER | MATCHNULLS))) + return; + + range = ld->equal_range(largeKey); + + for (; range.first != range.second; ++range.first) + { + matches->push_back(range.first->second); + } + } else if (!smallRG.usesStringTable()) { int64_t largeKey; @@ -278,7 +331,11 @@ void TupleJoiner::match(rowgroup::Row& largeSideRow, uint32_t largeRowIndex, uin pair range; Row r; - if (largeSideRow.isUnsigned(largeKeyColumns[0])) + if (largeSideRow.getColType(largeKeyColumns[0]) == CalpontSystemCatalog::LONGDOUBLE) + { + largeKey = (int64_t)largeSideRow.getLongDoubleField(largeKeyColumns[0]); + } + else if (largeSideRow.isUnsigned(largeKeyColumns[0])) { largeKey = (int64_t)largeSideRow.getUintField(largeKeyColumns[0]); } @@ -287,19 +344,41 @@ void TupleJoiner::match(rowgroup::Row& largeSideRow, uint32_t largeRowIndex, uin largeKey = largeSideRow.getIntField(largeKeyColumns[0]); } - it = h->find(largeKey); - - if (it == end() && !(joinType & (LARGEOUTER | MATCHNULLS))) - return; - - range = h->equal_range(largeKey); - - //smallRG.initRow(&r); - for (; range.first != range.second; ++range.first) + if (ld) { - //r.setData(range.first->second); - //cerr << "matched small side row: " << r.toString() << endl; - matches->push_back(range.first->second); + // Compare against long double + ldIterator it; + pair range; + long double ldKey = largeKey; +// ldKey = 6920; + it = ld->find(ldKey); + + if (it == ld->end() && !(joinType & (LARGEOUTER | MATCHNULLS))) + return; + + range = ld->equal_range(ldKey); + + for (; range.first != range.second; ++range.first) + { + matches->push_back(range.first->second); + } + } + else + { + it = h->find(largeKey); + + if (it == h->end() && !(joinType & (LARGEOUTER | MATCHNULLS))) + return; + + range = h->equal_range(largeKey); + + //smallRG.initRow(&r); + for (; range.first != range.second; ++range.first) + { + //r.setData(range.first->second); + //cerr << "matched small side row: " << r.toString() << endl; + matches->push_back(range.first->second); + } } } else @@ -335,7 +414,14 @@ void TupleJoiner::match(rowgroup::Row& largeSideRow, uint32_t largeRowIndex, uin if (UNLIKELY(inUM() && (joinType & MATCHNULLS) && !isNull && !typelessJoin)) { - if (!smallRG.usesStringTable()) + if (smallRG.getColType(largeKeyColumns[0]) == CalpontSystemCatalog::LONGDOUBLE) + { + pair range = ld->equal_range(joblist::LONGDOUBLENULL); + + for (; range.first != range.second; ++range.first) + matches->push_back(range.first->second); + } + else if (!smallRG.usesStringTable()) { pair range = h->equal_range(getJoinNullValue()); @@ -357,7 +443,14 @@ void TupleJoiner::match(rowgroup::Row& largeSideRow, uint32_t largeRowIndex, uin { if (!typelessJoin) { - if (!smallRG.usesStringTable()) + if (smallRG.getColType(smallKeyColumns[0]) == CalpontSystemCatalog::LONGDOUBLE) + { + ldIterator it; + + for (it = ld->begin(); it != ld->end(); ++it) + matches->push_back(it->second); + } + else if (!smallRG.usesStringTable()) { iterator it; @@ -410,6 +503,7 @@ void TupleJoiner::doneInserting() tr1::unordered_set::iterator uit; sthash_t::iterator sthit; hash_t::iterator hit; + ldhash_t::iterator ldit; typelesshash_t::iterator thit; uint32_t i, pmpos = 0, rowCount; Row smallRow; @@ -425,6 +519,8 @@ void TupleJoiner::doneInserting() pmpos = 0; else if (typelessJoin) thit = ht->begin(); + else if (smallRG.getColType(smallKeyColumns[0]) == CalpontSystemCatalog::LONGDOUBLE) + ldit = ld->begin(); else if (!smallRG.usesStringTable()) hit = h->begin(); else @@ -439,6 +535,11 @@ void TupleJoiner::doneInserting() smallRow.setPointer(thit->second); ++thit; } + else if (smallRG.getColType(smallKeyColumns[col]) == CalpontSystemCatalog::LONGDOUBLE) + { + smallRow.setPointer(ldit->second); + ++ldit; + } else if (!smallRG.usesStringTable()) { smallRow.setPointer(hit->second); @@ -450,6 +551,25 @@ void TupleJoiner::doneInserting() ++sthit; } + if (smallRow.getColType(smallKeyColumns[col]) == CalpontSystemCatalog::LONGDOUBLE) + { + double dval = (double)roundl(smallRow.getLongDoubleField(smallKeyColumns[col])); + switch (largeRG.getColType(largeKeyColumns[col])) + { + case CalpontSystemCatalog::DOUBLE: + case CalpontSystemCatalog::UDOUBLE: + case CalpontSystemCatalog::FLOAT: + case CalpontSystemCatalog::UFLOAT: + { + uniquer.insert(*(int64_t*)&dval); + } + default: + { + uniquer.insert((int64_t)dval); + } + } + } + else if (smallRow.isUnsigned(smallKeyColumns[col])) { uniquer.insert((int64_t)smallRow.getUintField(smallKeyColumns[col])); @@ -614,11 +734,23 @@ void TupleJoiner::getUnmarkedRows(vector* out) out->push_back(it->second); } } + else if (smallRG.getColType(smallKeyColumns[0]) == CalpontSystemCatalog::LONGDOUBLE) + { + ldIterator it; + + for (it = ld->begin(); it != ld->end(); ++it) + { + smallR.setPointer(it->second); + + if (!smallR.isMarked()) + out->push_back(it->second); + } + } else if (!smallRG.usesStringTable()) { iterator it; - for (it = begin(); it != end(); ++it) + for (it = h->begin(); it != h->end(); ++it) { smallR.setPointer(it->second); @@ -670,8 +802,9 @@ void TupleJoiner::updateCPData(const Row& r) for (col = 0; col < smallKeyColumns.size(); col++) { +// if (r.getColumnWidth(smallKeyColumns[col]) > 8) if (r.isLongString(smallKeyColumns[col])) - continue; + continue; int64_t& min = cpValues[col][0], &max = cpValues[col][1]; @@ -693,7 +826,29 @@ void TupleJoiner::updateCPData(const Row& r) } else if (r.isUnsigned(smallKeyColumns[col])) { - uint64_t uval = r.getUintField(smallKeyColumns[col]); + uint64_t uval; + if (r.getColType(smallKeyColumns[col]) == CalpontSystemCatalog::LONGDOUBLE) + { + double dval = (double)roundl(r.getLongDoubleField(smallKeyColumns[col])); + switch (largeRG.getColType(largeKeyColumns[col])) + { + case CalpontSystemCatalog::DOUBLE: + case CalpontSystemCatalog::UDOUBLE: + case CalpontSystemCatalog::FLOAT: + case CalpontSystemCatalog::UFLOAT: + { + uval = *(uint64_t*)&dval; + } + default: + { + uval = (uint64_t)dval; + } + } + } + else + { + uval = r.getUintField(smallKeyColumns[col]); + } if (uval > static_cast(max)) max = static_cast(uval); @@ -703,7 +858,29 @@ void TupleJoiner::updateCPData(const Row& r) } else { - int64_t val = r.getIntField(smallKeyColumns[col]); + int64_t val; + if (r.getColType(smallKeyColumns[col]) == CalpontSystemCatalog::LONGDOUBLE) + { + double dval = (double)roundl(r.getLongDoubleField(smallKeyColumns[col])); + switch (largeRG.getColType(largeKeyColumns[col])) + { + case CalpontSystemCatalog::DOUBLE: + case CalpontSystemCatalog::UDOUBLE: + case CalpontSystemCatalog::FLOAT: + case CalpontSystemCatalog::UFLOAT: + { + val = *(int64_t*)&dval; + } + default: + { + val = (int64_t)dval; + } + } + } + else + { + val = r.getIntField(smallKeyColumns[col]); + } if (val > max) max = val; @@ -720,6 +897,8 @@ size_t TupleJoiner::size() const { if (UNLIKELY(typelessJoin)) return ht->size(); + else if (smallRG.getColType(smallKeyColumns[0]) == CalpontSystemCatalog::LONGDOUBLE) + return ld->size(); else if (!smallRG.usesStringTable()) return h->size(); else @@ -768,20 +947,18 @@ TypelessData makeTypelessKey(const Row& r, const vector& keyCols, ret.data[off++] = 0; } + else if (r.isUnsigned(keyCols[i])) + { + if (off + 8 > keylen) + goto toolong; + *((uint64_t*) &ret.data[off]) = r.getUintField(keyCols[i]); + off += 8; + } else { if (off + 8 > keylen) goto toolong; - - if (r.isUnsigned(keyCols[i])) - { - *((uint64_t*) &ret.data[off]) = r.getUintField(keyCols[i]); - } - else - { - *((int64_t*) &ret.data[off]) = r.getIntField(keyCols[i]); - } - + *((int64_t*) &ret.data[off]) = r.getIntField(keyCols[i]); off += 8; } } @@ -795,7 +972,132 @@ toolong: return ret; } -TypelessData makeTypelessKey(const Row& r, const vector& keyCols, PoolAllocator* fa) +TypelessData makeTypelessKey(const Row& r, const vector& keyCols, + uint32_t keylen, FixedAllocator* fa, + const rowgroup::RowGroup& otherSideRG, const std::vector& otherKeyCols) +{ + TypelessData ret; + uint32_t off = 0, i, j; + execplan::CalpontSystemCatalog::ColDataType type; + + ret.data = (uint8_t*) fa->allocate(); + + for (i = 0; i < keyCols.size(); i++) + { + type = r.getColTypes()[keyCols[i]]; + + if (type == CalpontSystemCatalog::VARCHAR || + type == CalpontSystemCatalog::CHAR || + type == CalpontSystemCatalog::TEXT) + { + // this is a string, copy a normalized version + const uint8_t* str = r.getStringPointer(keyCols[i]); + uint32_t width = r.getStringLength(keyCols[i]); + + if (width > 65536) + { + throw runtime_error("Cannot join strings greater than 64KB"); + } + + for (j = 0; j < width && str[j] != 0; j++) + { + if (off >= keylen) + goto toolong; + + ret.data[off++] = str[j]; + } + + if (off >= keylen) + goto toolong; + + ret.data[off++] = 0; + } + else if (r.getColType(keyCols[i]) == CalpontSystemCatalog::LONGDOUBLE) + { + if (off + sizeof(long double) > keylen) + goto toolong; + // Small side is a long double. Since CS can't store larger than DOUBLE, + // we need to convert to whatever type large side is -- double or int64 + long double keyld = r.getLongDoubleField(keyCols[i]); + switch (otherSideRG.getColType(otherKeyCols[i])) + { + case CalpontSystemCatalog::DOUBLE: + case CalpontSystemCatalog::UDOUBLE: + case CalpontSystemCatalog::FLOAT: + case CalpontSystemCatalog::UFLOAT: + { + if (off + 8 > keylen) + goto toolong; + if (keyld > MAX_DOUBLE || keyld < MIN_DOUBLE) + { + ret.len = 0; + return ret; + } + else + { + double d = (double)keyld; + *((int64_t*) &ret.data[off]) = *(int64_t*)&d; + } + break; + } + case CalpontSystemCatalog::LONGDOUBLE: + { + if (off + sizeof(long double) > keylen) + goto toolong; + *((long double*) &ret.data[off]) = keyld; + off += sizeof(long double); + break; + } + default: + { + if (off + 8 > keylen) + goto toolong; + if (r.isUnsigned(keyCols[i]) && keyld > MAX_UBIGINT) + { + ret.len = 0; + return ret; + } + else if (keyld > MAX_BIGINT || keyld < MIN_BIGINT) + { + ret.len = 0; + return ret; + } + else + { + *((int64_t*) &ret.data[off]) = (int64_t)keyld; + off += 8; + } + break; + } + } + } + else if (r.isUnsigned(keyCols[i])) + { + if (off + 8 > keylen) + goto toolong; + *((uint64_t*) &ret.data[off]) = r.getUintField(keyCols[i]); + off += 8; + } + else + { + if (off + 8 > keylen) + goto toolong; + *((int64_t*) &ret.data[off]) = r.getIntField(keyCols[i]); + off += 8; + } + } + + ret.len = off; + fa->truncateBy(keylen - off); + return ret; +toolong: + fa->truncateBy(keylen); + ret.len = 0; + return ret; +} + +TypelessData makeTypelessKey(const Row& r, const vector& keyCols, PoolAllocator* fa, + const rowgroup::RowGroup& otherSideRG, const std::vector& otherKeyCols) { TypelessData ret; uint32_t off = 0, i, j; @@ -808,7 +1110,12 @@ TypelessData makeTypelessKey(const Row& r, const vector& keyCols, Pool { type = r.getColTypes()[keyCols[i]]; - if (r.isCharType(keyCols[i])) + if (r.getColType(keyCols[i]) == CalpontSystemCatalog::LONGDOUBLE + && otherSideRG.getColType(otherKeyCols[i]) == CalpontSystemCatalog::LONGDOUBLE) + { + keylen += sizeof(long double); + } + else if (r.isCharType(keyCols[i])) keylen += r.getStringLength(keyCols[i]) + 1; else keylen += 8; @@ -838,17 +1145,66 @@ TypelessData makeTypelessKey(const Row& r, const vector& keyCols, Pool ret.data[off++] = 0; } + else if (type == CalpontSystemCatalog::LONGDOUBLE) + { + // Small side is a long double. Since CS can't store larger than DOUBLE, + // we need to convert to whatever type large side is -- double or int64 + long double keyld = r.getLongDoubleField(keyCols[i]); + switch (otherSideRG.getColType(otherKeyCols[i])) + { + case CalpontSystemCatalog::DOUBLE: + case CalpontSystemCatalog::UDOUBLE: + case CalpontSystemCatalog::FLOAT: + case CalpontSystemCatalog::UFLOAT: + { + if (keyld > MAX_DOUBLE || keyld < MIN_DOUBLE) + { + ret.len = 0; + return ret; + } + else + { + double d = (double)keyld; + *((int64_t*) &ret.data[off]) = *(int64_t*)&d; + off += 8; + } + break; + } + case CalpontSystemCatalog::LONGDOUBLE: + { + *((long double*) &ret.data[off]) = keyld; + off += sizeof(long double); + break; + } + default: + { + if (r.isUnsigned(keyCols[i]) && keyld > MAX_UBIGINT) + { + ret.len = 0; + return ret; + } + else if (keyld > MAX_BIGINT || keyld < MIN_BIGINT) + { + ret.len = 0; + return ret; + } + else + { + *((int64_t*) &ret.data[off]) = (int64_t)keyld; + off += 8; + } + break; + } + } + } + else if (r.isUnsigned(keyCols[i])) + { + *((uint64_t*)&ret.data[off]) = r.getUintField(keyCols[i]); + off += 8; + } else { - if (r.isUnsigned(keyCols[i])) - { - *((uint64_t*)&ret.data[off]) = r.getUintField(keyCols[i]); - } - else - { - *((int64_t*)&ret.data[off]) = r.getIntField(keyCols[i]); - } - + *((int64_t*)&ret.data[off]) = r.getIntField(keyCols[i]); off += 8; } } @@ -881,25 +1237,29 @@ uint64_t getHashOfTypelessKey(const Row& r, const vector& keyCols, uin ret = hasher((const char*) str, len, ret); /* for (uint32_t j = 0; j < width && str[j] != 0; j++) - ret.data[off++] = str[j]; + ret.data[off++] = str[j]; */ ret = hasher(&nullChar, 1, ret); width += len + 1; } + else if (r.getColType(keyCols[i]) == CalpontSystemCatalog::LONGDOUBLE) + { + long double tmp = r.getLongDoubleField(keyCols[i]); + ret = hasher((char*) &tmp, sizeof(long double), ret); + width += sizeof(long double); + } + else + if (r.isUnsigned(keyCols[i])) + { + tmp = r.getUintField(keyCols[i]); + ret = hasher((char*) &tmp, 8, ret); + width += 8; + } else { + tmp = r.getIntField(keyCols[i]); + ret = hasher((char*) &tmp, 8, ret); width += 8; - - if (r.isUnsigned(keyCols[i])) - { - tmp = r.getUintField(keyCols[i]); - ret = hasher((char*) &tmp, 8, ret); - } - else - { - tmp = r.getIntField(keyCols[i]); - ret = hasher((char*) &tmp, 8, ret); - } } } diff --git a/utils/joiner/tuplejoiner.h b/utils/joiner/tuplejoiner.h index 0391e7cdf..211dd5cfe 100644 --- a/utils/joiner/tuplejoiner.h +++ b/utils/joiner/tuplejoiner.h @@ -78,14 +78,30 @@ inline bool TypelessData::operator==(const TypelessData& t) const return (memcmp(data, t.data, len) == 0); } +// Comparator for long double in the hash +class LongDoubleEq +{ +public: + LongDoubleEq(){}; + inline bool operator()(const long double& pos1, const long double& pos2) const + { + return pos1 == pos2; + } +}; + /* This function makes the keys for string & compound joins. The length of the * key is limited by keylen. Keys that are longer are assigned a length of 0 on return, * signifying that it shouldn't match anything. */ extern TypelessData makeTypelessKey(const rowgroup::Row&, const std::vector&, uint32_t keylen, utils::FixedAllocator* fa); +// MCOL-1822 SUM/AVG as long double: pass in RG and col so we can determine type conversion extern TypelessData makeTypelessKey(const rowgroup::Row&, - const std::vector&, utils::PoolAllocator* fa); + const std::vector&, uint32_t keylen, utils::FixedAllocator* fa, + const rowgroup::RowGroup&, const std::vector&); +extern TypelessData makeTypelessKey(const rowgroup::Row&, + const std::vector&, utils::PoolAllocator* fa, + const rowgroup::RowGroup&, const std::vector&); extern uint64_t getHashOfTypelessKey(const rowgroup::Row&, const std::vector&, uint32_t seed = 0); @@ -99,10 +115,26 @@ public: { return fHasher((char*) &val, 8); } + inline size_t operator()(uint64_t val) const + { + return fHasher((char*) &val, 8); + } inline size_t operator()(const TypelessData& e) const { return fHasher((char*) e.data, e.len); } + inline size_t operator()(long double val) const + { + if (sizeof(long double) == 8) // Probably just MSC, but you never know. + { + return fHasher((char*) &val, sizeof(long double)); + } + else + { + // For Linux x86_64, long double is stored in 128 bits, but only 80 are significant + return fHasher((char*) &val, 10); + } + } private: utils::Hasher fHasher; @@ -300,29 +332,24 @@ private: utils::STLPoolAllocator > > sthash_t; typedef std::tr1::unordered_multimap, utils::STLPoolAllocator > > typelesshash_t; + // MCOL-1822 Add support for Long Double AVG/SUM small side + typedef std::tr1::unordered_multimap > > ldhash_t; typedef hash_t::iterator iterator; typedef typelesshash_t::iterator thIterator; + typedef ldhash_t::iterator ldIterator; TupleJoiner(); TupleJoiner(const TupleJoiner&); TupleJoiner& operator=(const TupleJoiner&); - iterator begin() - { - return h->begin(); - } - iterator end() - { - return h->end(); - } - - rowgroup::RGData smallNullMemory; boost::scoped_ptr h; // used for UM joins on ints boost::scoped_ptr sth; // used for UM join on ints where the backing table uses a string table + boost::scoped_ptr ld; // used for UM join on long double std::vector rows; // used for PM join /* This struct is rough. The BPP-JL stores the parsed results for diff --git a/utils/rowgroup/rowaggregation.cpp b/utils/rowgroup/rowaggregation.cpp index 8a80ca683..ac3310326 100644 --- a/utils/rowgroup/rowaggregation.cpp +++ b/utils/rowgroup/rowaggregation.cpp @@ -203,6 +203,10 @@ inline float getFloatNullValue() return *y; } +inline long double getLongDoubleNullValue() +{ + return joblist::LONGDOUBLENULL; +} inline string getStringNullValue() { @@ -229,6 +233,7 @@ const static_any::any& RowAggregation::ulongTypeId((unsigned long)1); const static_any::any& RowAggregation::ullTypeId((unsigned long long)1); const static_any::any& RowAggregation::floatTypeId((float)1); const static_any::any& RowAggregation::doubleTypeId((double)1); +const static_any::any& RowAggregation::longdoubleTypeId((long double)1); const static_any::any& RowAggregation::strTypeId(typeStr); KeyStorage::KeyStorage(const RowGroup& keys, Row** tRow) : tmpRow(tRow), rg(keys) @@ -357,6 +362,15 @@ inline void RowAggregation::updateDoubleMinMax(double val1, double val2, int64_t } +inline void RowAggregation::updateLongDoubleMinMax(long double val1, long double val2, int64_t col, int func) +{ + if (isNull(fRowGroupOut, fRow, col)) + fRow.setLongDoubleField(val1, col); + else if (minMax(val1, val2, func)) + fRow.setLongDoubleField(val1, col); +} + + inline void RowAggregation::updateFloatMinMax(float val1, float val2, int64_t col, int func) { if (isNull(fRowGroupOut, fRow, col)) @@ -396,124 +410,6 @@ void RowAggregation::updateStringMinMax(string val1, string val2, int64_t col, i #endif } - -inline void RowAggregation::updateIntSum(int64_t val1, int64_t val2, int64_t col) -{ - if (isNull(fRowGroupOut, fRow, col)) - { - fRow.setIntField(val1, col); - } - else - { -#ifndef PROMOTE_AGGR_OVRFLW_TO_DBL - - if (((val2 >= 0) && ((numeric_limits::max() - val2) >= val1)) || - ((val2 < 0) && ((numeric_limits::min() - val2) <= val1))) - fRow.setIntField(val1 + val2, col); - -#else /* PROMOTE_AGGR_OVRFLW_TO_DBL */ - - if (fRow.getColTypes()[col] != execplan::CalpontSystemCatalog::DOUBLE && - fRow.getColTypes()[col] != execplan::CalpontSystemCatalog::UDOUBLE) - { - if (((val2 >= 0) && ((numeric_limits::max() - val2) >= val1)) || - ((val2 < 0) && ((numeric_limits::min() - val2) <= val1))) - { - fRow.setIntField(val1 + val2, col); - } - else - { - execplan::CalpontSystemCatalog::ColDataType* cdtp = fRow.getColTypes(); - cdtp += col; - *cdtp = execplan::CalpontSystemCatalog::DOUBLE; - updateDoubleSum((double)val1, (double)val2, col); - } - } - -#endif /* PROMOTE_AGGR_OVRFLW_TO_DBL */ - else - { -#ifndef PROMOTE_AGGR_OVRFLW_TO_DBL - ostringstream oss; - oss << overflowMsg << ": " << val2 << "+" << val1; - - if (val2 > 0) - oss << " > " << numeric_limits::max(); - else - oss << " < " << numeric_limits::min(); - - throw logging::QueryDataExcept(oss.str(), logging::aggregateDataErr); -#else /* PROMOTE_AGGR_OVRFLW_TO_DBL */ - double* dp2 = (double*)&val2; - updateDoubleSum((double)val1, *dp2, col); -#endif /* PROMOTE_AGGR_OVRFLW_TO_DBL */ - } - } -} - -inline void RowAggregation::updateUintSum(uint64_t val1, uint64_t val2, int64_t col) -{ - if (isNull(fRowGroupOut, fRow, col)) - { - fRow.setUintField(val1, col); - } - else - { -#ifndef PROMOTE_AGGR_OVRFLW_TO_DBL - - if ((numeric_limits::max() - val2) >= val1) - fRow.setUintField(val1 + val2, col); - else - { - ostringstream oss; - oss << overflowMsg << ": " << val2 << "+" << val1 << " > " << numeric_limits::max(); - throw logging::QueryDataExcept(oss.str(), logging::aggregateDataErr); - } - -#else /* PROMOTE_AGGR_OVRFLW_TO_DBL */ - - if (fRow.getColTypes()[col] != execplan::CalpontSystemCatalog::DOUBLE && - fRow.getColTypes()[col] != execplan::CalpontSystemCatalog::UDOUBLE) - { - if ((numeric_limits::max() - val2) >= val1) - { - fRow.setUintField(val1 + val2, col); - } - else - { - execplan::CalpontSystemCatalog::ColDataType* cdtp = fRow.getColTypes(); - cdtp += col; - *cdtp = execplan::CalpontSystemCatalog::DOUBLE; - updateDoubleSum((double)val1, (double)val2, col); - } - } - else - { - double* dp2 = (double*)&val2; - updateDoubleSum((double)val1, *dp2, col); - } - -#endif /* PROMOTE_AGGR_OVRFLW_TO_DBL */ - } -} - -inline void RowAggregation::updateDoubleSum(double val1, double val2, int64_t col) -{ - if (isNull(fRowGroupOut, fRow, col)) - fRow.setDoubleField(val1, col); - else - fRow.setDoubleField(val1 + val2, col); -} - - -inline void RowAggregation::updateFloatSum(float val1, float val2, int64_t col) -{ - if (isNull(fRowGroupOut, fRow, col)) - fRow.setFloatField(val1, col); - else - fRow.setFloatField(val1 + val2, col); -} - //------------------------------------------------------------------------------ // Verify if the column value is NULL // row(in) - Row to be included in aggregation. @@ -598,6 +494,12 @@ inline bool RowAggregation::isNull(const RowGroup* pRowGroup, const Row& row, in break; } + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + ret = (row.getLongDoubleField(col) == joblist::LONGDOUBLENULL); + break; + } + case execplan::CalpontSystemCatalog::MEDINT: case execplan::CalpontSystemCatalog::INT: { @@ -1134,6 +1036,12 @@ void RowAggregation::initMapData(const Row& rowIn) break; } + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + fRow.setLongDoubleField(rowIn.getLongDoubleField(colIn), colOut); + break; + } + case execplan::CalpontSystemCatalog::FLOAT: case execplan::CalpontSystemCatalog::UFLOAT: { @@ -1265,6 +1173,12 @@ void RowAggregation::makeAggFieldsNull(Row& row) break; } + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + row.setLongDoubleField(getLongDoubleNullValue(), colOut); + break; + } + case execplan::CalpontSystemCatalog::FLOAT: case execplan::CalpontSystemCatalog::UFLOAT: { @@ -1290,7 +1204,7 @@ void RowAggregation::makeAggFieldsNull(Row& row) //------------------------------------------------------------------------------ -// Update the min/max/sum fields if input is not null. +// Update the min/max fields if input is not null. // rowIn(in) - Row to be included in aggregation. // colIn(in) - column in the input row group // colOut(in) - column in the output row group @@ -1298,7 +1212,7 @@ void RowAggregation::makeAggFieldsNull(Row& row) // Note: NULL value check must be done on UM & PM // UM may receive NULL values, too. //------------------------------------------------------------------------------ -void RowAggregation::doMinMaxSum(const Row& rowIn, int64_t colIn, int64_t colOut, int funcType) +void RowAggregation::doMinMax(const Row& rowIn, int64_t colIn, int64_t colOut, int funcType) { int colDataType = (fRowGroupIn.getColTypes())[colIn]; @@ -1317,12 +1231,7 @@ void RowAggregation::doMinMaxSum(const Row& rowIn, int64_t colIn, int64_t colOut { int64_t valIn = rowIn.getIntField(colIn); int64_t valOut = fRow.getIntField(colOut); - - if (funcType == ROWAGG_SUM || funcType == ROWAGG_DISTINCT_SUM) - updateIntSum(valIn, valOut, colOut); - else - updateIntMinMax(valIn, valOut, colOut, funcType); - + updateIntMinMax(valIn, valOut, colOut, funcType); break; } @@ -1334,12 +1243,7 @@ void RowAggregation::doMinMaxSum(const Row& rowIn, int64_t colIn, int64_t colOut { uint64_t valIn = rowIn.getUintField(colIn); uint64_t valOut = fRow.getUintField(colOut); - - if (funcType == ROWAGG_SUM || funcType == ROWAGG_DISTINCT_SUM) - updateUintSum(valIn, valOut, colOut); - else - updateUintMinMax(valIn, valOut, colOut, funcType); - + updateUintMinMax(valIn, valOut, colOut, funcType); break; } @@ -1347,16 +1251,7 @@ void RowAggregation::doMinMaxSum(const Row& rowIn, int64_t colIn, int64_t colOut case execplan::CalpontSystemCatalog::VARCHAR: case execplan::CalpontSystemCatalog::TEXT: { - if (funcType == ROWAGG_SUM) - { - std::ostringstream errmsg; - errmsg << "RowAggregation: sum(CHAR[]) is not supported."; - cerr << errmsg.str() << endl; - throw logging::QueryDataExcept(errmsg.str(), logging::aggregateFuncErr); - } - int colWidth = fRowGroupIn.getColumnWidth(colIn); - if (colWidth <= 8) { uint64_t valIn = rowIn.getUintField(colIn); @@ -1369,7 +1264,6 @@ void RowAggregation::doMinMaxSum(const Row& rowIn, int64_t colIn, int64_t colOut string valOut = fRow.getStringField(colOut); updateStringMinMax(valIn, valOut, colOut, funcType); } - break; } @@ -1378,12 +1272,7 @@ void RowAggregation::doMinMaxSum(const Row& rowIn, int64_t colIn, int64_t colOut { double valIn = rowIn.getDoubleField(colIn); double valOut = fRow.getDoubleField(colOut); - - if (funcType == ROWAGG_SUM) - updateDoubleSum(valIn, valOut, colOut); - else - updateDoubleMinMax(valIn, valOut, colOut, funcType); - + updateDoubleMinMax(valIn, valOut, colOut, funcType); break; } @@ -1392,12 +1281,7 @@ void RowAggregation::doMinMaxSum(const Row& rowIn, int64_t colIn, int64_t colOut { float valIn = rowIn.getFloatField(colIn); float valOut = fRow.getFloatField(colOut); - - if (funcType == ROWAGG_SUM) - updateFloatSum(valIn, valOut, colOut); - else - updateFloatMinMax(valIn, valOut, colOut, funcType); - + updateFloatMinMax(valIn, valOut, colOut, funcType); break; } @@ -1405,20 +1289,20 @@ void RowAggregation::doMinMaxSum(const Row& rowIn, int64_t colIn, int64_t colOut case execplan::CalpontSystemCatalog::DATETIME: case execplan::CalpontSystemCatalog::TIME: { - if (funcType == ROWAGG_SUM) - { - std::ostringstream errmsg; - errmsg << "RowAggregation: sum(date|date time) is not supported."; - cerr << errmsg.str() << endl; - throw logging::QueryDataExcept(errmsg.str(), logging::aggregateFuncErr); - } - uint64_t valIn = rowIn.getUintField(colIn); uint64_t valOut = fRow.getUintField(colOut); updateUintMinMax(valIn, valOut, colOut, funcType); break; } + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + long double valIn = rowIn.getDoubleField(colIn); + long double valOut = fRow.getDoubleField(colOut); + updateLongDoubleMinMax(valIn, valOut, colOut, funcType); + break; + } + default: { break; @@ -1426,6 +1310,113 @@ void RowAggregation::doMinMaxSum(const Row& rowIn, int64_t colIn, int64_t colOut } } +//------------------------------------------------------------------------------ +// Update the sum fields if input is not null. +// rowIn(in) - Row to be included in aggregation. +// colIn(in) - column in the input row group +// colOut(in) - column in the output row group +// funcType(in) - aggregation function type +// Note: NULL value check must be done on UM & PM +// UM may receive NULL values, too. +//------------------------------------------------------------------------------ +void RowAggregation::doSum(const Row& rowIn, int64_t colIn, int64_t colOut, int funcType) +{ + int colDataType = (fRowGroupIn.getColTypes())[colIn]; + long double valIn = 0; + long double valOut = fRow.getLongDoubleField(colOut); + if (isNull(&fRowGroupIn, rowIn, colIn) == true) + return; + + switch (colDataType) + { + case execplan::CalpontSystemCatalog::TINYINT: + case execplan::CalpontSystemCatalog::SMALLINT: + case execplan::CalpontSystemCatalog::MEDINT: + case execplan::CalpontSystemCatalog::INT: + case execplan::CalpontSystemCatalog::BIGINT: + { + valIn = rowIn.getIntField(colIn); + break; + } + + case execplan::CalpontSystemCatalog::UTINYINT: + case execplan::CalpontSystemCatalog::USMALLINT: + case execplan::CalpontSystemCatalog::UMEDINT: + case execplan::CalpontSystemCatalog::UINT: + case execplan::CalpontSystemCatalog::UBIGINT: + { + valIn = rowIn.getUintField(colIn); + break; + } + + case execplan::CalpontSystemCatalog::DECIMAL: + case execplan::CalpontSystemCatalog::UDECIMAL: + { + valIn = rowIn.getIntField(colIn); + double scale = (double)(fRowGroupIn.getScale())[colIn]; + if (valIn != 0 && scale > 0) + { + valIn /= pow(10.0, scale); + } + break; + } + + case execplan::CalpontSystemCatalog::CHAR: + case execplan::CalpontSystemCatalog::VARCHAR: + case execplan::CalpontSystemCatalog::TEXT: + { + std::ostringstream errmsg; + errmsg << "RowAggregation: sum(CHAR[]) is not supported."; + cerr << errmsg.str() << endl; + throw logging::QueryDataExcept(errmsg.str(), logging::aggregateFuncErr); + break; + } + + case execplan::CalpontSystemCatalog::DOUBLE: + case execplan::CalpontSystemCatalog::UDOUBLE: + { + valIn = rowIn.getDoubleField(colIn); + break; + } + + case execplan::CalpontSystemCatalog::FLOAT: + case execplan::CalpontSystemCatalog::UFLOAT: + { + valIn = rowIn.getFloatField(colIn); + break; + } + + case execplan::CalpontSystemCatalog::DATE: + case execplan::CalpontSystemCatalog::DATETIME: + case execplan::CalpontSystemCatalog::TIME: + { + std::ostringstream errmsg; + errmsg << "RowAggregation: sum(date|date time) is not supported."; + cerr << errmsg.str() << endl; + throw logging::QueryDataExcept(errmsg.str(), logging::aggregateFuncErr); + break; + } + + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + valIn = rowIn.getLongDoubleField(colIn); + break; + } + + default: + { + break; + } + } + if (isNull(fRowGroupOut, fRow, colOut)) + { + fRow.setLongDoubleField(valIn, colOut); + } + else + { + fRow.setLongDoubleField(valIn+valOut, colOut); + } +} //------------------------------------------------------------------------------ // Update the and/or/xor fields if input is not null. @@ -1507,12 +1498,15 @@ void RowAggregation::doBitOp(const Row& rowIn, int64_t colIn, int64_t colOut, in case execplan::CalpontSystemCatalog::FLOAT: case execplan::CalpontSystemCatalog::UDOUBLE: case execplan::CalpontSystemCatalog::UFLOAT: + case execplan::CalpontSystemCatalog::LONGDOUBLE: { double dbl = 0.0; if (colDataType == execplan::CalpontSystemCatalog::DOUBLE || colDataType == execplan::CalpontSystemCatalog::UDOUBLE) dbl = rowIn.getDoubleField(colIn); + else if (colDataType == execplan::CalpontSystemCatalog::LONGDOUBLE) + dbl = (double)rowIn.getLongDoubleField(colIn); else dbl = rowIn.getFloatField(colIn); @@ -1684,13 +1678,16 @@ void RowAggregation::updateEntry(const Row& rowIn) if (isNull(&fRowGroupIn, rowIn, colIn) == true) break; case ROWAGG_COUNT_ASTERISK: - fRow.setIntField<8>(fRow.getIntField<8>(colOut) + 1, colOut); + fRow.setUintField<8>(fRow.getUintField<8>(colOut) + 1, colOut); break; case ROWAGG_MIN: case ROWAGG_MAX: + doMinMax(rowIn, colIn, colOut, fFunctionCols[i]->fAggFunction); + break; + case ROWAGG_SUM: - doMinMaxSum(rowIn, colIn, colOut, fFunctionCols[i]->fAggFunction); + doSum(rowIn, colIn, colOut, fFunctionCols[i]->fAggFunction); break; case ROWAGG_AVG: @@ -1749,11 +1746,13 @@ void RowAggregation::updateEntry(const Row& rowIn) //------------------------------------------------------------------------------ void RowAggregation::doAvg(const Row& rowIn, int64_t colIn, int64_t colOut, int64_t colAux) { - int colDataType = (fRowGroupIn.getColTypes())[colIn]; - if (isNull(&fRowGroupIn, rowIn, colIn) == true) return; + int colDataType = (fRowGroupIn.getColTypes())[colIn]; + long double valIn = 0; + long double valOut = fRow.getLongDoubleField(colOut); + switch (colDataType) { case execplan::CalpontSystemCatalog::TINYINT: @@ -1761,70 +1760,9 @@ void RowAggregation::doAvg(const Row& rowIn, int64_t colIn, int64_t colOut, int6 case execplan::CalpontSystemCatalog::MEDINT: case execplan::CalpontSystemCatalog::INT: case execplan::CalpontSystemCatalog::BIGINT: - case execplan::CalpontSystemCatalog::DECIMAL: - case execplan::CalpontSystemCatalog::UDECIMAL: { - int64_t valIn = rowIn.getIntField(colIn); - - if (fRow.getIntField(colAux) == 0) - { - fRow.setIntField(valIn, colOut); - fRow.setIntField(1, colAux); - } - else - { - int64_t valOut = fRow.getIntField(colOut); -#ifndef PROMOTE_AGGR_OVRFLW_TO_DBL - - if (((valOut >= 0) && ((numeric_limits::max() - valOut) >= valIn)) || - ((valOut < 0) && ((numeric_limits::min() - valOut) <= valIn))) - fRow.setIntField(valIn + valOut, colOut); - -#else /* PROMOTE_AGGR_OVRFLW_TO_DBL */ - - if (fRow.getColTypes()[colOut] != execplan::CalpontSystemCatalog::DOUBLE) - { - if (((valOut >= 0) && ((numeric_limits::max() - valOut) >= valIn)) || - ((valOut < 0) && ((numeric_limits::min() - valOut) <= valIn))) - { - fRow.setIntField(valIn + valOut, colOut); - fRow.setIntField(fRow.getIntField(colAux) + 1, colAux); - } - else - { - execplan::CalpontSystemCatalog::ColDataType* cdtp = fRow.getColTypes(); - cdtp += colOut; - *cdtp = execplan::CalpontSystemCatalog::DOUBLE; - fRow.setDoubleField((double)valIn + (double)valOut, colOut); - fRow.setIntField(fRow.getIntField(colAux) + 1, colAux); - } - } - -#endif /* PROMOTE_AGGR_OVRFLW_TO_DBL */ - else -#ifndef PROMOTE_AGGR_OVRFLW_TO_DBL - { - ostringstream oss; - oss << overflowMsg << ": " << valOut << "+" << valIn; - - if (valOut > 0) - oss << " > " << numeric_limits::max(); - else - oss << " < " << numeric_limits::min(); - - throw logging::QueryDataExcept(oss.str(), logging::aggregateDataErr); - } - - fRow.setIntField(fRow.getIntField(colAux) + 1, colAux); -#else /* PROMOTE_AGGR_OVRFLW_TO_DBL */ - { - double* dp = (double*)&valOut; - fRow.setDoubleField((double)valIn + *dp, colOut); - fRow.setIntField(fRow.getIntField(colAux) + 1, colAux); - } -#endif /* PROMOTE_AGGR_OVRFLW_TO_DBL */ - } - + valIn = rowIn.getIntField(colIn); + break; break; } @@ -1834,98 +1772,39 @@ void RowAggregation::doAvg(const Row& rowIn, int64_t colIn, int64_t colOut, int6 case execplan::CalpontSystemCatalog::UINT: case execplan::CalpontSystemCatalog::UBIGINT: { - uint64_t valIn = rowIn.getUintField(colIn); + valIn = rowIn.getUintField(colIn); + break; + } - if (fRow.getUintField(colAux) == 0) + case execplan::CalpontSystemCatalog::DECIMAL: + case execplan::CalpontSystemCatalog::UDECIMAL: + { + valIn = rowIn.getIntField(colIn); + double scale = (double)(fRowGroupIn.getScale())[colIn]; + if (valIn != 0 && scale > 0) { - fRow.setUintField(valIn, colOut); - fRow.setUintField(1, colAux); + valIn /= pow(10.0, scale); } - else - { - uint64_t valOut = fRow.getUintField(colOut); -#ifndef PROMOTE_AGGR_OVRFLW_TO_DBL - - if ((numeric_limits::max() - valOut) >= valIn) - { - fRow.setUintField(valIn + valOut, colOut); - fRow.setUintField(fRow.getUintField(colAux) + 1, colAux); - } - else - { - ostringstream oss; - oss << overflowMsg << ": " << valOut << "+" << valIn << " > " << numeric_limits::max(); - throw logging::QueryDataExcept(oss.str(), logging::aggregateDataErr); - } - -#else /* PROMOTE_AGGR_OVRFLW_TO_DBL */ - - if (fRow.getColTypes()[colOut] != execplan::CalpontSystemCatalog::DOUBLE) - { - if ((numeric_limits::max() - valOut) >= valIn) - { - fRow.setUintField(valIn + valOut, colOut); - fRow.setUintField(fRow.getUintField(colAux) + 1, colAux); - } - else - { - execplan::CalpontSystemCatalog::ColDataType* cdtp = fRow.getColTypes(); - cdtp += colOut; - *cdtp = execplan::CalpontSystemCatalog::DOUBLE; - fRow.setDoubleField((double)valIn + (double)valOut, colOut); - fRow.setUintField(fRow.getUintField(colAux) + 1, colAux); - } - } - else - { - double* dp = (double*)&valOut; - fRow.setDoubleField((double)valIn + *dp, colOut); - fRow.setUintField(fRow.getUintField(colAux) + 1, colAux); - } - -#endif /* PROMOTE_AGGR_OVRFLW_TO_DBL */ - } - break; } case execplan::CalpontSystemCatalog::DOUBLE: case execplan::CalpontSystemCatalog::UDOUBLE: { - double valIn = rowIn.getDoubleField(colIn); - - if (fRow.getIntField(colAux) == 0) - { - fRow.setDoubleField(valIn, colOut); - fRow.setIntField(1, colAux); - } - else - { - double valOut = fRow.getDoubleField(colOut); - fRow.setDoubleField(valIn + valOut, colOut); - fRow.setIntField(fRow.getIntField(colAux) + 1, colAux); - } - + valIn = rowIn.getDoubleField(colIn); break; } case execplan::CalpontSystemCatalog::FLOAT: case execplan::CalpontSystemCatalog::UFLOAT: { - float valIn = rowIn.getFloatField(colIn); - - if (fRow.getIntField(colAux) == 0) - { - fRow.setFloatField(valIn, colOut); - fRow.setIntField(1, colAux); - } - else - { - float valOut = fRow.getFloatField(colOut); - fRow.setFloatField(valIn + valOut, colOut); - fRow.setIntField(fRow.getIntField(colAux) + 1, colAux); - } + valIn = rowIn.getFloatField(colIn); + break; + } + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + valIn = rowIn.getLongDoubleField(colIn); break; } @@ -1938,6 +1817,18 @@ void RowAggregation::doAvg(const Row& rowIn, int64_t colIn, int64_t colOut, int6 break; } } + + if (fRow.getUintField(colAux) == 0) + { + // This is the first value + fRow.setLongDoubleField(valIn, colOut); + fRow.setUintField(1, colAux); + } + else + { + fRow.setLongDoubleField(valIn + valOut, colOut); + fRow.setUintField(fRow.getUintField(colAux) + 1, colAux); + } } @@ -1988,6 +1879,10 @@ void RowAggregation::doStatistics(const Row& rowIn, int64_t colIn, int64_t colOu valIn = (long double) rowIn.getFloatField(colIn); break; + case execplan::CalpontSystemCatalog::LONGDOUBLE: + valIn = rowIn.getLongDoubleField(colIn); + break; + default: std::ostringstream errmsg; errmsg << "RowAggregation: no average for data type: " << colDataType; @@ -2137,6 +2032,22 @@ void RowAggregation::doUDAF(const Row& rowIn, int64_t colIn, int64_t colOut, break; } + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + datum.dataType = execplan::CalpontSystemCatalog::LONGDOUBLE; + + if (cc) + { + datum.columnData = cc->getLongDoubleVal(const_cast(rowIn), bIsNull); + } + else + { + datum.columnData = rowIn.getLongDoubleField(colIn); + } + + break; + } + case execplan::CalpontSystemCatalog::FLOAT: case execplan::CalpontSystemCatalog::UFLOAT: { @@ -2509,13 +2420,16 @@ void RowAggregationUM::updateEntry(const Row& rowIn) if (isNull(&fRowGroupIn, rowIn, colIn) == true) break; case ROWAGG_COUNT_ASTERISK: - fRow.setIntField<8>(fRow.getIntField<8>(colOut) + 1, colOut); + fRow.setUintField<8>(fRow.getUintField<8>(colOut) + 1, colOut); break; case ROWAGG_MIN: case ROWAGG_MAX: + doMinMax(rowIn, colIn, colOut, fFunctionCols[i]->fAggFunction); + break; + case ROWAGG_SUM: - doMinMaxSum(rowIn, colIn, colOut, fFunctionCols[i]->fAggFunction); + doSum(rowIn, colIn, colOut, fFunctionCols[i]->fAggFunction); break; case ROWAGG_AVG: @@ -2600,12 +2514,11 @@ void RowAggregationUM::calculateAvgColumns() { int64_t colOut = fFunctionCols[i]->fOutputColumnIndex; int64_t colAux = fFunctionCols[i]->fAuxColumnIndex; - int colDataType = (fRowGroupOut->getColTypes())[colOut]; - int scale = fRowGroupOut->getScale()[colOut]; - int scale1 = scale >> 8; - int scale2 = scale & 0x000000FF; - long double factor = pow(10.0, scale2 - scale1); +// int scale = fRowGroupOut->getScale()[colOut]; +// int scale1 = scale >> 8; +// int scale2 = scale & 0x000000FF; +// long double factor = pow(10.0, scale2 - scale1); for (uint64_t j = 0; j < fRowGroupOut->getRowCount(); j++) { @@ -2618,97 +2531,11 @@ void RowAggregationUM::calculateAvgColumns() long double sum = 0.0; long double avg = 0.0; - switch (colDataType) - { - case execplan::CalpontSystemCatalog::DOUBLE: - case execplan::CalpontSystemCatalog::UDOUBLE: - sum = fRow.getDoubleField(colOut); - avg = sum / cnt; - fRow.setDoubleField(avg, colOut); - break; - - case execplan::CalpontSystemCatalog::FLOAT: - case execplan::CalpontSystemCatalog::UFLOAT: - sum = fRow.getFloatField(colOut); - avg = sum / cnt; - fRow.setFloatField(avg, colOut); - break; - - case execplan::CalpontSystemCatalog::TINYINT: - case execplan::CalpontSystemCatalog::SMALLINT: - case execplan::CalpontSystemCatalog::MEDINT: - case execplan::CalpontSystemCatalog::INT: - case execplan::CalpontSystemCatalog::BIGINT: - case execplan::CalpontSystemCatalog::DECIMAL: - case execplan::CalpontSystemCatalog::UDECIMAL: - sum = static_cast(fRow.getIntField(colOut)); - avg = sum / cnt; - avg *= factor; - avg += (avg < 0) ? (-0.5) : (0.5); - - if (avg > (long double) numeric_limits::max() || - avg < (long double) numeric_limits::min()) -#ifndef PROMOTE_AGGR_OVRFLW_TO_DBL - { - ostringstream oss; - oss << overflowMsg << ": " << avg << "(incl factor " << factor; - - if (avg > 0) - oss << ") > " << numeric_limits::max(); - else - oss << ") < " << numeric_limits::min(); - - throw logging::QueryDataExcept(oss.str(), logging::aggregateDataErr); - } - - fRow.setIntField((int64_t) avg, colOut); -#else /* PROMOTE_AGGR_OVRFLW_TO_DBL */ - { - sum = fRow.getDoubleField(colOut); - avg = sum / cnt; - avg += (avg < 0) ? (-0.5) : (0.5); - fRow.getColTypes()[colOut] = execplan::CalpontSystemCatalog::DOUBLE; - fRow.setDoubleField(avg, colOut); - } - else - fRow.setIntField((int64_t)avg, colOut); - -#endif /* PROMOTE_AGGR_OVRFLW_TO_DBL */ - break; - - case execplan::CalpontSystemCatalog::UTINYINT: - case execplan::CalpontSystemCatalog::USMALLINT: - case execplan::CalpontSystemCatalog::UMEDINT: - case execplan::CalpontSystemCatalog::UINT: - case execplan::CalpontSystemCatalog::UBIGINT: - sum = static_cast(fRow.getUintField(colOut)); - avg = sum / cnt; - avg *= factor; - avg += (avg < 0) ? (-0.5) : (0.5); - - if (avg > (long double) numeric_limits::max()) -#ifndef PROMOTE_AGGR_OVRFLW_TO_DBL - { - ostringstream oss; - oss << overflowMsg << ": " << avg << "(incl factor " << factor << ") > " << numeric_limits::max(); - throw logging::QueryDataExcept(oss.str(), logging::aggregateDataErr); - } - - fRow.setUintField((uint64_t) avg, colOut); -#else /* PROMOTE_AGGR_OVRFLW_TO_DBL */ - { - sum = fRow.getDoubleField(colOut); - avg = sum / cnt; - avg += 0.5; - fRow.getColTypes()[colOut] = execplan::CalpontSystemCatalog::DOUBLE; - fRow.setDoubleField(avg, colOut); - } - else - fRow.setUintField((uint64_t)avg, colOut); - -#endif /* PROMOTE_AGGR_OVRFLW_TO_DBL */ - break; - } + // MCOL-1822 Always long double + sum = fRow.getLongDoubleField(colOut); + avg = sum / cnt; +// avg *= factor; + fRow.setLongDoubleField(avg, colOut); } } } @@ -2729,6 +2556,7 @@ void RowAggregationUM::SetUDAFValue(static_any::any& valOut, int64_t colOut) uint64_t uintOut = 0; float floatOut = 0.0; double doubleOut = 0.0; + long double longdoubleOut = 0.0; ostringstream oss; std::string strOut; @@ -2896,6 +2724,16 @@ void RowAggregationUM::SetUDAFValue(static_any::any& valOut, int64_t colOut) break; + case execplan::CalpontSystemCatalog::LONGDOUBLE: + if (valOut.compatible(doubleTypeId)) + { + longdoubleOut = valOut.cast(); + fRow.setLongDoubleField(longdoubleOut, colOut); + bSetSuccess = true; + } + + break; + default: { std::ostringstream errmsg; @@ -2919,10 +2757,12 @@ void RowAggregationUM::SetUDAFAnyValue(static_any::any& valOut, int64_t colOut) // that they didn't set in mcsv1_UDAF::init(), but this // handles whatever return type is given and casts // it to whatever they said to return. + // TODO: Save cpu cycles here. int64_t intOut = 0; uint64_t uintOut = 0; float floatOut = 0.0; double doubleOut = 0.0; + long double longdoubleOut = 0.0; ostringstream oss; std::string strOut; @@ -2996,12 +2836,24 @@ void RowAggregationUM::SetUDAFAnyValue(static_any::any& valOut, int64_t colOut) { floatOut = valOut.cast(); doubleOut = floatOut; + longdoubleOut = doubleOut; intOut = uintOut = floatOut; oss << floatOut; } else if (valOut.compatible(doubleTypeId)) { doubleOut = valOut.cast(); + longdoubleOut = doubleOut; + floatOut = (float)doubleOut; + uintOut = (uint64_t)doubleOut; + intOut = (int64_t)doubleOut; + oss << doubleOut; + } + + else if (valOut.compatible(longdoubleTypeId)) + { + longdoubleOut = valOut.cast(); + doubleOut = (double)longdoubleOut; floatOut = (float)doubleOut; uintOut = (uint64_t)doubleOut; intOut = (int64_t)doubleOut; @@ -3015,6 +2867,7 @@ void RowAggregationUM::SetUDAFAnyValue(static_any::any& valOut, int64_t colOut) intOut = atol(strOut.c_str()); uintOut = strtoul(strOut.c_str(), NULL, 10); doubleOut = strtod(strOut.c_str(), NULL); + longdoubleOut = strtold(strOut.c_str(), NULL); floatOut = (float)doubleOut; } else @@ -3094,6 +2947,10 @@ void RowAggregationUM::SetUDAFAnyValue(static_any::any& valOut, int64_t colOut) fRow.setVarBinaryField(strOut, colOut); break; + case execplan::CalpontSystemCatalog::LONGDOUBLE: + fRow.setLongDoubleField(longdoubleOut, colOut); + break; + default: { std::ostringstream errmsg; @@ -3329,10 +3186,6 @@ void RowAggregationUM::doNullConstantAggregate(const ConstantAggData& aggData, u { case ROWAGG_MIN: case ROWAGG_MAX: - case ROWAGG_AVG: - case ROWAGG_SUM: - case ROWAGG_DISTINCT_AVG: - case ROWAGG_DISTINCT_SUM: case ROWAGG_STATS: { switch (colDataType) @@ -3394,14 +3247,30 @@ void RowAggregationUM::doNullConstantAggregate(const ConstantAggData& aggData, u fRow.setStringField("", colOut); } break; + + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + fRow.setLongDoubleField(getLongDoubleNullValue(), colOut); + } + break; + } } break; + case ROWAGG_AVG: + case ROWAGG_SUM: + case ROWAGG_DISTINCT_AVG: + case ROWAGG_DISTINCT_SUM: + { + fRow.setLongDoubleField(getLongDoubleNullValue(), colOut); + } + break; + case ROWAGG_COUNT_COL_NAME: case ROWAGG_COUNT_DISTINCT_COL_NAME: { - fRow.setIntField(0, colOut); + fRow.setUintField(0, colOut); } break; @@ -3548,6 +3417,12 @@ void RowAggregationUM::doNotNullConstantAggregate(const ConstantAggData& aggData } break; + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + fRow.setLongDoubleField(strtold(aggData.fConstValue.c_str(), 0), colOut); + } + break; + case execplan::CalpontSystemCatalog::FLOAT: case execplan::CalpontSystemCatalog::UFLOAT: { @@ -3650,6 +3525,13 @@ void RowAggregationUM::doNotNullConstantAggregate(const ConstantAggData& aggData } break; + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + long double dbl = strtold(aggData.fConstValue.c_str(), 0) * rowCnt; + fRow.setLongDoubleField(dbl, colOut); + } + break; + case execplan::CalpontSystemCatalog::FLOAT: case execplan::CalpontSystemCatalog::UFLOAT: { @@ -3712,6 +3594,12 @@ void RowAggregationUM::doNotNullConstantAggregate(const ConstantAggData& aggData } break; + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + fRow.setLongDoubleField(0.0, colOut); + } + break; + case execplan::CalpontSystemCatalog::FLOAT: case execplan::CalpontSystemCatalog::UFLOAT: { @@ -3746,13 +3634,13 @@ void RowAggregationUM::doNotNullConstantAggregate(const ConstantAggData& aggData case ROWAGG_COUNT_COL_NAME: { - fRow.setIntField(rowCnt, colOut); + fRow.setUintField(rowCnt, colOut); } break; case ROWAGG_COUNT_DISTINCT_COL_NAME: { - fRow.setIntField(1, colOut); + fRow.setUintField(1, colOut); } break; @@ -3839,6 +3727,12 @@ void RowAggregationUM::doNotNullConstantAggregate(const ConstantAggData& aggData } break; + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + datum.columnData = strtold(aggData.fConstValue.c_str(), 0); + } + break; + case execplan::CalpontSystemCatalog::FLOAT: case execplan::CalpontSystemCatalog::UFLOAT: { @@ -4065,15 +3959,18 @@ void RowAggregationUMP2::updateEntry(const Row& rowIn) case ROWAGG_COUNT_ASTERISK: case ROWAGG_COUNT_COL_NAME: { - int64_t count = fRow.getIntField<8>(colOut) + rowIn.getIntField<8>(colIn); - fRow.setIntField<8>(count, colOut); + uint64_t count = fRow.getUintField<8>(colOut) + rowIn.getUintField<8>(colIn); + fRow.setUintField<8>(count, colOut); break; } case ROWAGG_MIN: case ROWAGG_MAX: + doMinMax(rowIn, colIn, colOut, fFunctionCols[i]->fAggFunction); + break; + case ROWAGG_SUM: - doMinMaxSum(rowIn, colIn, colOut, fFunctionCols[i]->fAggFunction); + doSum(rowIn, colIn, colOut, fFunctionCols[i]->fAggFunction); break; case ROWAGG_AVG: @@ -4142,11 +4039,13 @@ void RowAggregationUMP2::updateEntry(const Row& rowIn) //------------------------------------------------------------------------------ void RowAggregationUMP2::doAvg(const Row& rowIn, int64_t colIn, int64_t colOut, int64_t colAux) { - int colDataType = (fRowGroupIn.getColTypes())[colIn]; - if (isNull(&fRowGroupIn, rowIn, colIn) == true) return; + int colDataType = (fRowGroupIn.getColTypes())[colIn]; + long double valIn = 0; + long double valOut = fRow.getLongDoubleField(colOut); + switch (colDataType) { case execplan::CalpontSystemCatalog::TINYINT: @@ -4154,23 +4053,8 @@ void RowAggregationUMP2::doAvg(const Row& rowIn, int64_t colIn, int64_t colOut, case execplan::CalpontSystemCatalog::MEDINT: case execplan::CalpontSystemCatalog::INT: case execplan::CalpontSystemCatalog::BIGINT: - case execplan::CalpontSystemCatalog::DECIMAL: - case execplan::CalpontSystemCatalog::UDECIMAL: { - int64_t valIn = rowIn.getIntField(colIn); - - if (fRow.getIntField(colAux) == 0) - { - fRow.setIntField(valIn, colOut); - fRow.setIntField(rowIn.getIntField(colIn + 1), colAux); - } - else - { - int64_t valOut = fRow.getIntField(colOut); - fRow.setIntField(valIn + valOut, colOut); - fRow.setIntField(rowIn.getIntField(colIn + 1) + fRow.getIntField(colAux), colAux); - } - + valIn = rowIn.getIntField(colIn); break; } @@ -4180,60 +4064,40 @@ void RowAggregationUMP2::doAvg(const Row& rowIn, int64_t colIn, int64_t colOut, case execplan::CalpontSystemCatalog::UINT: case execplan::CalpontSystemCatalog::UBIGINT: { - uint64_t valIn = rowIn.getUintField(colIn); + valIn = rowIn.getUintField(colIn); + break; + } - if (fRow.getUintField(colAux) == 0) + case execplan::CalpontSystemCatalog::DECIMAL: + case execplan::CalpontSystemCatalog::UDECIMAL: + { + valIn = rowIn.getIntField(colIn); + break; + double scale = (double)(fRowGroupIn.getScale())[colIn]; + if (valIn != 0 && scale > 0) { - fRow.setUintField(valIn, colOut); - fRow.setUintField(rowIn.getUintField(colIn + 1), colAux); + valIn /= pow(10.0, scale); } - else - { - uint64_t valOut = fRow.getUintField(colOut); - fRow.setUintField(valIn + valOut, colOut); - fRow.setUintField(rowIn.getUintField(colIn + 1) + fRow.getUintField(colAux), colAux); - } - break; } case execplan::CalpontSystemCatalog::DOUBLE: case execplan::CalpontSystemCatalog::UDOUBLE: { - double valIn = rowIn.getDoubleField(colIn); - - if (fRow.getIntField(colAux) == 0) - { - fRow.setDoubleField(valIn, colOut); - fRow.setIntField(rowIn.getIntField(colIn + 1), colAux); - } - else - { - double valOut = fRow.getDoubleField(colOut); - fRow.setDoubleField(valIn + valOut, colOut); - fRow.setIntField(rowIn.getIntField(colIn + 1) + fRow.getIntField(colAux), colAux); - } - + valIn = rowIn.getDoubleField(colIn); break; } case execplan::CalpontSystemCatalog::FLOAT: case execplan::CalpontSystemCatalog::UFLOAT: { - float valIn = rowIn.getFloatField(colIn); - - if (fRow.getIntField(colAux) == 0) - { - fRow.setFloatField(valIn, colOut); - fRow.setIntField(rowIn.getIntField(colIn + 1), colAux); - } - else - { - float valOut = fRow.getFloatField(colOut); - fRow.setFloatField(valIn + valOut, colOut); - fRow.setIntField(rowIn.getIntField(colIn + 1) + fRow.getIntField(colAux), colAux); - } + valIn = rowIn.getFloatField(colIn); + break; + } + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + valIn = rowIn.getLongDoubleField(colIn); break; } @@ -4246,8 +4110,19 @@ void RowAggregationUMP2::doAvg(const Row& rowIn, int64_t colIn, int64_t colOut, break; } } -} + int64_t cnt = fRow.getUintField(colAux); + if (cnt == 0) + { + fRow.setLongDoubleField(valIn, colOut); + fRow.setUintField(rowIn.getUintField(colIn + 1), colAux); + } + else + { + fRow.setLongDoubleField(valIn + valOut, colOut); + fRow.setUintField(rowIn.getUintField(colIn + 1) + cnt, colAux); + } +} //------------------------------------------------------------------------------ // Update the sum and count fields for stattistics if input is not null. @@ -4478,23 +4353,25 @@ void RowAggregationDistinct::updateEntry(const Row& rowIn) case ROWAGG_COUNT_ASTERISK: case ROWAGG_COUNT_COL_NAME: { - int64_t count = fRow.getIntField<8>(colOut) + rowIn.getIntField<8>(colIn); - fRow.setIntField<8>(count, colOut); + uint64_t count = fRow.getUintField<8>(colOut) + rowIn.getUintField<8>(colIn); + fRow.setUintField<8>(count, colOut); break; } case ROWAGG_COUNT_DISTINCT_COL_NAME: if (isNull(&fRowGroupIn, rowIn, colIn) != true) - fRow.setIntField<8>(fRow.getIntField<8>(colOut) + 1, colOut); + fRow.setUintField<8>(fRow.getUintField<8>(colOut) + 1, colOut); break; case ROWAGG_MIN: case ROWAGG_MAX: + doMinMax(rowIn, colIn, colOut, fFunctionCols[i]->fAggFunction); + break; + case ROWAGG_SUM: case ROWAGG_DISTINCT_SUM: - - doMinMaxSum(rowIn, colIn, colOut, fFunctionCols[i]->fAggFunction); + doSum(rowIn, colIn, colOut, fFunctionCols[i]->fAggFunction); break; case ROWAGG_AVG: diff --git a/utils/rowgroup/rowaggregation.h b/utils/rowgroup/rowaggregation.h index e039d5c2a..47d365085 100644 --- a/utils/rowgroup/rowaggregation.h +++ b/utils/rowgroup/rowaggregation.h @@ -612,14 +612,15 @@ protected: virtual void attachGroupConcatAg(); virtual void updateEntry(const Row& row); - virtual void doMinMaxSum(const Row&, int64_t, int64_t, int); + virtual void doMinMax(const Row&, int64_t, int64_t, int); + virtual void doSum(const Row&, int64_t, int64_t, int); virtual void doAvg(const Row&, int64_t, int64_t, int64_t); virtual void doStatistics(const Row&, int64_t, int64_t, int64_t); virtual void doBitOp(const Row&, int64_t, int64_t, int); virtual void doUDAF(const Row&, int64_t, int64_t, int64_t, uint64_t& funcColsIdx); virtual bool countSpecial(const RowGroup* pRG) { - fRow.setIntField<8>(fRow.getIntField<8>(0) + pRG->getRowCount(), 0); + fRow.setUintField<8>(fRow.getUintField<8>(0) + pRG->getRowCount(), 0); return true; } @@ -642,13 +643,9 @@ protected: inline void updateUintMinMax(uint64_t val1, uint64_t val2, int64_t col, int func); inline void updateCharMinMax(uint64_t val1, uint64_t val2, int64_t col, int func); inline void updateDoubleMinMax(double val1, double val2, int64_t col, int func); + inline void updateLongDoubleMinMax(long double val1, long double val2, int64_t col, int func); inline void updateFloatMinMax(float val1, float val2, int64_t col, int func); inline void updateStringMinMax(std::string val1, std::string val2, int64_t col, int func); - inline void updateIntSum(int64_t val1, int64_t val2, int64_t col); - inline void updateUintSum(uint64_t val1, uint64_t val2, int64_t col); - inline void updateDoubleSum(double val1, double val2, int64_t col); - inline void updateFloatSum(float val1, float val2, int64_t col); - std::vector fGroupByCols; std::vector fFunctionCols; RowAggMap_t* fAggMapPtr; @@ -711,6 +708,7 @@ protected: static const static_any::any& ullTypeId; static const static_any::any& floatTypeId; static const static_any::any& doubleTypeId; + static const static_any::any& longdoubleTypeId; static const static_any::any& strTypeId; }; diff --git a/utils/udfsdk/udfsdk.cpp b/utils/udfsdk/udfsdk.cpp index 9a8973232..f91473a81 100644 --- a/utils/udfsdk/udfsdk.cpp +++ b/utils/udfsdk/udfsdk.cpp @@ -201,6 +201,14 @@ double MCS_add::getDoubleVal(Row& row, return 0; } +long double MCS_add::getLongDoubleVal(Row& row, + FunctionParm& parm, + bool& isNull, + CalpontSystemCatalog::ColType& op_ct) +{ + return getDoubleVal(row, parm, isNull, op_ct); +} + float MCS_add::getFloatVal(Row& row, FunctionParm& parm, bool& isNull, @@ -349,6 +357,14 @@ double MCS_isnull::getDoubleVal(Row& row, return (getBoolVal(row, parm, isNull, op_ct) ? 1 : 0); } +long double MCS_isnull::getLongDoubleVal(Row& row, + FunctionParm& parm, + bool& isNull, + CalpontSystemCatalog::ColType& op_ct) +{ + return (getBoolVal(row, parm, isNull, op_ct) ? 1 : 0); +} + float MCS_isnull::getFloatVal(Row& row, FunctionParm& parm, bool& isNull, diff --git a/utils/udfsdk/udfsdk.h b/utils/udfsdk/udfsdk.h index 2160d552b..04e1c07b5 100644 --- a/utils/udfsdk/udfsdk.h +++ b/utils/udfsdk/udfsdk.h @@ -170,6 +170,14 @@ public: bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct); + /** + * Returns a long double result of this function. + */ + + virtual long double getLongDoubleVal(rowgroup::Row& row, + funcexp::FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); /** * Returns a float result of this function. */ @@ -266,6 +274,14 @@ public: bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct); + /** + * Returns a double result of this function. + */ + virtual long double getLongDoubleVal(rowgroup::Row& row, + funcexp::FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); + /** * Returns a float result of this function. */ diff --git a/utils/windowfunction/frameboundrange.cpp b/utils/windowfunction/frameboundrange.cpp index cdb65f5f9..8d73aace2 100644 --- a/utils/windowfunction/frameboundrange.cpp +++ b/utils/windowfunction/frameboundrange.cpp @@ -313,6 +313,20 @@ void FrameBoundExpressionRange::validate() break; } + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + long double tmp = this->fRow.getLongDoubleField(this->fIndex[1]); + this->fIsZero = (tmp == 0.0); + + if (tmp < 0) + { + invalid = true; + oss << tmp; + } + + break; + } + case execplan::CalpontSystemCatalog::FLOAT: case execplan::CalpontSystemCatalog::UFLOAT: { diff --git a/utils/windowfunction/wf_nth_value.cpp b/utils/windowfunction/wf_nth_value.cpp index eacd1202a..f5be1462f 100644 --- a/utils/windowfunction/wf_nth_value.cpp +++ b/utils/windowfunction/wf_nth_value.cpp @@ -97,6 +97,12 @@ boost::shared_ptr WF_nth_value::makeFunction(int id, cons break; } + case CalpontSystemCatalog::LONGDOUBLE: + { + func.reset(new WF_nth_value(id, name)); + break; + } + default: { func.reset(new WF_nth_value(id, name)); diff --git a/utils/windowfunction/wf_percentile.cpp b/utils/windowfunction/wf_percentile.cpp index b3e56c17a..d7b2ab9ca 100644 --- a/utils/windowfunction/wf_percentile.cpp +++ b/utils/windowfunction/wf_percentile.cpp @@ -146,12 +146,17 @@ boost::shared_ptr WF_percentile::makeFunction(int id, con case CalpontSystemCatalog::UDOUBLE: case CalpontSystemCatalog::FLOAT: case CalpontSystemCatalog::UFLOAT: - case CalpontSystemCatalog::LONGDOUBLE: { func.reset(new WF_percentile(id, name)); break; } + case CalpontSystemCatalog::LONGDOUBLE: + { + func.reset(new WF_percentile(id, name)); + break; + } + default: { string errStr = name + "(" + colType2String[ct] + ")"; diff --git a/utils/windowfunction/wf_udaf.cpp b/utils/windowfunction/wf_udaf.cpp index 250f3fc42..6b1359334 100644 --- a/utils/windowfunction/wf_udaf.cpp +++ b/utils/windowfunction/wf_udaf.cpp @@ -557,6 +557,7 @@ void WF_udaf::SetUDAFValue(static_any::any& valOut, int64_t colOut, uint64_t uintOut = 0; float floatOut = 0.0; double doubleOut = 0.0; + long double longdoubleOut = 0.0; ostringstream oss; std::string strOut; @@ -630,12 +631,14 @@ void WF_udaf::SetUDAFValue(static_any::any& valOut, int64_t colOut, { floatOut = valOut.cast(); doubleOut = floatOut; + longdoubleOut = floatOut; intOut = uintOut = floatOut; oss << floatOut; } else if (valOut.compatible(doubleTypeId)) { doubleOut = valOut.cast(); + longdoubleOut = doubleOut; floatOut = (float)doubleOut; uintOut = (uint64_t)doubleOut; intOut = (int64_t)doubleOut; @@ -649,6 +652,7 @@ void WF_udaf::SetUDAFValue(static_any::any& valOut, int64_t colOut, intOut = atol(strOut.c_str()); uintOut = strtoul(strOut.c_str(), NULL, 10); doubleOut = strtod(strOut.c_str(), NULL); + longdoubleOut = doubleOut; floatOut = (float)doubleOut; } else @@ -718,6 +722,17 @@ void WF_udaf::SetUDAFValue(static_any::any& valOut, int64_t colOut, } break; + case execplan::CalpontSystemCatalog::LONGDOUBLE: + if (valOut.empty()) + { + setValue(colDataType, b, e, c, (long double*)NULL); + } + else + { + setValue(colDataType, b, e, c, &longdoubleOut); + } + break; + case execplan::CalpontSystemCatalog::CHAR: case execplan::CalpontSystemCatalog::VARCHAR: case execplan::CalpontSystemCatalog::TEXT: diff --git a/utils/windowfunction/windowfunctiontype.cpp b/utils/windowfunction/windowfunctiontype.cpp index 471cdc1ac..930e6eecc 100644 --- a/utils/windowfunction/windowfunctiontype.cpp +++ b/utils/windowfunction/windowfunctiontype.cpp @@ -503,6 +503,16 @@ void WindowFunctionType::implicit2T(uint64_t i, T& t, int s) break; } + case CalpontSystemCatalog::LONGDOUBLE: + { + if (s == 0) + t = (T) fRow.getLongDoubleField(i); + else + t = (T) (fRow.getLongDoubleField(i) * IDB_pow[s]); // s is scale, [0, 18] + + break; + } + case CalpontSystemCatalog::CHAR: case CalpontSystemCatalog::VARCHAR: default: