From 638202417f7cc748b2f970d9f97e23cc36ab973b Mon Sep 17 00:00:00 2001 From: David Hall Date: Thu, 30 Jul 2020 17:28:11 -0500 Subject: [PATCH] MCOL-4171 --- dbcon/execplan/arithmeticoperator.h | 2 +- dbcon/execplan/simplecolumn.cpp | 2 +- dbcon/execplan/windowfunctioncolumn.cpp | 36 ++- dbcon/joblist/groupconcat.cpp | 4 +- dbcon/mysql/ha_mcs_impl.cpp | 2 +- utils/messageqcpp/bytestream.cpp | 27 +++ utils/messageqcpp/bytestream.h | 13 + utils/regr/moda.cpp | 51 ++-- utils/regr/moda.h | 52 +++- utils/rowgroup/rowaggregation.cpp | 10 +- utils/rowgroup/rowgroup.h | 29 ++- utils/udfsdk/mcsv1_udaf.cpp | 2 + utils/udfsdk/mcsv1_udaf.h | 10 + utils/windowfunction/frameboundrange.cpp | 47 +++- utils/windowfunction/idborderby.cpp | 19 +- utils/windowfunction/wf_count.cpp | 22 +- utils/windowfunction/wf_count.h | 2 +- utils/windowfunction/wf_lead_lag.cpp | 34 ++- utils/windowfunction/wf_lead_lag.h | 2 +- utils/windowfunction/wf_min_max.cpp | 32 ++- utils/windowfunction/wf_min_max.h | 2 +- utils/windowfunction/wf_nth_value.cpp | 32 ++- utils/windowfunction/wf_nth_value.h | 2 +- utils/windowfunction/wf_ntile.cpp | 2 +- utils/windowfunction/wf_ntile.h | 2 +- utils/windowfunction/wf_percentile.cpp | 32 ++- utils/windowfunction/wf_percentile.h | 2 +- utils/windowfunction/wf_ranking.cpp | 2 +- utils/windowfunction/wf_ranking.h | 2 +- utils/windowfunction/wf_row_number.cpp | 2 +- utils/windowfunction/wf_row_number.h | 2 +- utils/windowfunction/wf_stats.cpp | 42 +++- utils/windowfunction/wf_stats.h | 2 +- utils/windowfunction/wf_sum_avg.cpp | 251 +++++++++++--------- utils/windowfunction/wf_sum_avg.h | 29 ++- utils/windowfunction/wf_udaf.cpp | 97 ++++++-- utils/windowfunction/wf_udaf.h | 2 +- utils/windowfunction/windowfunctiontype.cpp | 133 +++++++++-- utils/windowfunction/windowfunctiontype.h | 8 + writeengine/wrapper/writeengine.cpp | 13 +- 40 files changed, 807 insertions(+), 250 deletions(-) diff --git a/dbcon/execplan/arithmeticoperator.h b/dbcon/execplan/arithmeticoperator.h index 5286ab25c..416daeea4 100644 --- a/dbcon/execplan/arithmeticoperator.h +++ b/dbcon/execplan/arithmeticoperator.h @@ -196,7 +196,7 @@ public: return TreeNode::getBoolVal(); } void adjustResultType(const CalpontSystemCatalog::ColType& m); - constexpr inline bool getOverflowCheck() const + const inline bool getOverflowCheck() const { return fDecimalOverflowCheck; } diff --git a/dbcon/execplan/simplecolumn.cpp b/dbcon/execplan/simplecolumn.cpp index 09328ae9f..7201a366c 100644 --- a/dbcon/execplan/simplecolumn.cpp +++ b/dbcon/execplan/simplecolumn.cpp @@ -503,7 +503,7 @@ bool SimpleColumn::singleTable(CalpontSystemCatalog::TableAliasName& tan) void SimpleColumn::evaluate(Row& row, bool& isNull) { // WIP Move this block into an appropriate place - if (UNLIKELY(fInputOffset == -1)) + if (UNLIKELY((int)(fInputOffset == (uint32_t)-1))) { fInputOffset = row.getOffset(fInputIndex); } diff --git a/dbcon/execplan/windowfunctioncolumn.cpp b/dbcon/execplan/windowfunctioncolumn.cpp index f14d9656f..d32e41651 100644 --- a/dbcon/execplan/windowfunctioncolumn.cpp +++ b/dbcon/execplan/windowfunctioncolumn.cpp @@ -52,6 +52,8 @@ using namespace rowgroup; #include "joblisttypes.h" using namespace joblist; +#include "widedecimalutils.h" + #ifdef _MSC_VER #define strcasecmp stricmp #endif @@ -387,9 +389,16 @@ void WindowFunctionColumn::adjustResultType() boost::iequals(fFunctionName, "AVG") || boost::iequals(fFunctionName, "AVG_DISTINCT")) { - fResultType.colDataType = CalpontSystemCatalog::LONGDOUBLE; - fResultType.colWidth = sizeof(long double); - fResultType.precision = -1; + if (fFunctionParms[0]->resultType().colDataType == CalpontSystemCatalog::DECIMAL) + { + fResultType.colWidth = sizeof(int128_t); + } + else + { + fResultType.colDataType = CalpontSystemCatalog::LONGDOUBLE; + fResultType.colWidth = sizeof(long double); + fResultType.precision = -1; + } } } @@ -661,18 +670,35 @@ void WindowFunctionColumn::evaluate(Row& row, bool& isNull) break; } - default: + case 8: { if (row.equals<8>(BIGINTNULL, fInputIndex)) isNull = true; else { - fResult.decimalVal.value = (int64_t)row.getUintField<8>(fInputIndex); + fResult.decimalVal.value = row.getIntField<8>(fInputIndex); fResult.decimalVal.scale = (unsigned)fResultType.scale; } break; } + + case 16: + { + int128_t dec = row.getInt128Field(fInputIndex); + if (utils::isWideDecimalNullValue(dec)) + isNull = true; + else + { + fResult.decimalVal.s128Value = dec; + fResult.decimalVal.scale = (unsigned)fResultType.scale; + } + + break; + } + default: + // Should log error + break; } break; diff --git a/dbcon/joblist/groupconcat.cpp b/dbcon/joblist/groupconcat.cpp index 942cd254f..09b57a325 100644 --- a/dbcon/joblist/groupconcat.cpp +++ b/dbcon/joblist/groupconcat.cpp @@ -938,7 +938,7 @@ void GroupConcatOrderBy::getResult(uint8_t* buff, const string& sep) rowStack.pop(); } - size_t resultSize = oss.str().size(); + int64_t resultSize = oss.str().size(); resultSize = (resultSize > fGroupConcatLen) ? fGroupConcatLen : resultSize; fOutputString.reset(new uint8_t[resultSize + 2]); fOutputString[resultSize] = '\0'; @@ -1102,7 +1102,7 @@ void GroupConcatNoOrder::getResult(uint8_t* buff, const string& sep) fDataQueue.pop(); } - size_t resultSize = oss.str().size(); + int64_t resultSize = oss.str().size(); resultSize = (resultSize > fGroupConcatLen) ? fGroupConcatLen : resultSize; fOutputString.reset(new uint8_t[resultSize + 2]); fOutputString[resultSize] = '\0'; diff --git a/dbcon/mysql/ha_mcs_impl.cpp b/dbcon/mysql/ha_mcs_impl.cpp index f334a3375..2724d2ba1 100644 --- a/dbcon/mysql/ha_mcs_impl.cpp +++ b/dbcon/mysql/ha_mcs_impl.cpp @@ -2342,9 +2342,9 @@ int ha_mcs_impl_discover_existence(const char* schema, const char* name) int ha_mcs_impl_direct_update_delete_rows(bool execute, ha_rows *affected_rows, const std::vector& condStack) { THD* thd = current_thd; - int rc = 0; cal_impl_if::gp_walk_info gwi; gwi.thd = thd; + int rc = 0; if (thd->slave_thread && !get_replication_slave(thd) && ( thd->lex->sql_command == SQLCOM_INSERT || diff --git a/utils/messageqcpp/bytestream.cpp b/utils/messageqcpp/bytestream.cpp index edfa9f90b..ec6872dcb 100644 --- a/utils/messageqcpp/bytestream.cpp +++ b/utils/messageqcpp/bytestream.cpp @@ -236,6 +236,17 @@ ByteStream& ByteStream::operator<<(const uint64_t o) } // WIP MCOL-641 +ByteStream& ByteStream::operator<<(const int128_t& o) +{ + if (fBuf == 0 || (fCurInPtr - fBuf + 16U > fMaxLen + ISSOverhead)) + growBuf(fMaxLen + BlockSize); + + *((int128_t*) fCurInPtr) = o; + fCurInPtr += 16; + + return *this; +} + ByteStream& ByteStream::operator<<(const uint128_t& o) { if (fBuf == 0 || (fCurInPtr - fBuf + 16U > fMaxLen + ISSOverhead)) @@ -332,6 +343,13 @@ ByteStream& ByteStream::operator>>(uint64_t& o) } // WIP MCOL-641 +ByteStream& ByteStream::operator>>(int128_t& o) +{ + peek(o); + fCurOutPtr += 16; + return *this; +} + ByteStream& ByteStream::operator>>(uint128_t& o) { peek(o); @@ -420,6 +438,15 @@ void ByteStream::peek(uint64_t& o) const } // WIP MCOL-641 +void ByteStream::peek(int128_t& o) const +{ + + if (length() < 16) + throw underflow_error("ByteStream>int128_t: not enough data in stream to fill datatype"); + + o = *((int128_t*) fCurOutPtr); +} + void ByteStream::peek(uint128_t& o) const { diff --git a/utils/messageqcpp/bytestream.h b/utils/messageqcpp/bytestream.h index aea3c60b1..59aa1679c 100644 --- a/utils/messageqcpp/bytestream.h +++ b/utils/messageqcpp/bytestream.h @@ -45,6 +45,7 @@ class ByteStreamTestSuite; #define EXPORT #endif +using int128_t = __int128; using uint128_t = unsigned __int128; namespace messageqcpp @@ -147,6 +148,10 @@ public: */ EXPORT ByteStream& operator<<(const uint64_t o); // WIP MCOL-641 + /** + * push an uint128_t onto the end of the stream. The byte order is whatever the native byte order is. + */ + EXPORT ByteStream& operator<<(const int128_t& o); /** * push an uint128_t onto the end of the stream. The byte order is whatever the native byte order is. */ @@ -216,6 +221,10 @@ public: */ EXPORT ByteStream& operator>>(uint64_t& o); // WIP MCOL-641 + /** + * extract an uint128_t from the front of the stream. The byte order is whatever the native byte order is. + */ + EXPORT ByteStream& operator>>(int128_t& o); /** * extract an uint128_t from the front of the stream. The byte order is whatever the native byte order is. */ @@ -291,6 +300,10 @@ public: */ EXPORT void peek(uint64_t& o) const; // WIP MCOL-641 + /** + * Peek at an uint128_t from the front of the stream. The byte order is whatever the native byte order is. + */ + EXPORT void peek(int128_t& o) const; /** * Peek at an uint128_t from the front of the stream. The byte order is whatever the native byte order is. */ diff --git a/utils/regr/moda.cpp b/utils/regr/moda.cpp index caf6cd1f8..e1bc44a9a 100644 --- a/utils/regr/moda.cpp +++ b/utils/regr/moda.cpp @@ -103,9 +103,12 @@ mcsv1_UDAF* moda::getImpl(mcsv1Context* context) case 4: data->modaImpl = &moda_impl_int32; break; - default: + case 8: data->modaImpl = &moda_impl_int64; break; + case 16: + data->modaImpl = &moda_impl_int128; + break; } break; case execplan::CalpontSystemCatalog::UTINYINT: @@ -179,11 +182,18 @@ mcsv1_UDAF::ReturnCode moda::init(mcsv1Context* context, { context->setColWidth(4); } - else + else if (colTypes[0].precision < 19) { context->setColWidth(8); } + else + { + context->setColWidth(16); + } + + context->setScale(colTypes[0].scale); } + context->setPrecision(colTypes[0].precision); mcsv1_UDAF* impl = getImpl(context); @@ -203,10 +213,7 @@ template mcsv1_UDAF::ReturnCode Moda_impl_T::init(mcsv1Context* context, ColumnDatum* colTypes) { - context->setScale(context->getScale()); - context->setPrecision(19); return mcsv1_UDAF::SUCCESS; - } template @@ -224,7 +231,7 @@ mcsv1_UDAF::ReturnCode Moda_impl_T::nextValue(mcsv1Context* context, ColumnDa { static_any::any& valIn = valsIn[0].columnData; ModaData* data = static_cast(context->getUserData()); - std::unordered_map* map = data->getMap(); + std::unordered_map >* map = data->getMap(); if (valIn.empty()) { @@ -261,9 +268,9 @@ mcsv1_UDAF::ReturnCode Moda_impl_T::subEvaluate(mcsv1Context* context, const ModaData* outData = static_cast(context->getUserData()); const ModaData* inData = static_cast(userDataIn); - std::unordered_map* outMap = outData->getMap(); - std::unordered_map* inMap = inData->getMap(); - typename std::unordered_map::const_iterator iter; + std::unordered_map >* outMap = outData->getMap(); + std::unordered_map >* inMap = inData->getMap(); + typename std::unordered_map >::const_iterator iter; for (iter = inMap->begin(); iter != inMap->end(); ++iter) { @@ -283,7 +290,7 @@ mcsv1_UDAF::ReturnCode Moda_impl_T::evaluate(mcsv1Context* context, static_an long double avg = 0; T val = 0; ModaData* data = static_cast(context->getUserData()); - std::unordered_map* map = data->getMap(); + std::unordered_map >* map = data->getMap(); if (map->size() == 0) { @@ -292,7 +299,7 @@ mcsv1_UDAF::ReturnCode Moda_impl_T::evaluate(mcsv1Context* context, static_an } avg = data->fCount ? data->fSum / data->fCount : 0; - typename std::unordered_map::iterator iter; + typename std::unordered_map >::iterator iter; for (iter = map->begin(); iter != map->end(); ++iter) { @@ -303,11 +310,13 @@ mcsv1_UDAF::ReturnCode Moda_impl_T::evaluate(mcsv1Context* context, static_an } else if (iter->second == maxCnt) { + T absval = val >= 0 ? val : -val; + T absfirst = iter->first >= 0 ? iter->first : -iter->first; // Tie breaker: choose the closest to avg. If still tie, choose smallest long double dist1 = val > avg ? (long double)val-avg : avg-(long double)val; long double dist2 = iter->first > avg ? (long double)iter->first-avg : avg-(long double)iter->first; if ((dist1 > dist2) - || ((dist1 == dist2) && (std::fabs(val) > std::fabs(iter->first)))) + || ((dist1 == dist2) && (absval > absfirst))) { val = iter->first; } @@ -328,7 +337,7 @@ mcsv1_UDAF::ReturnCode Moda_impl_T::dropValue(mcsv1Context* context, ColumnDa { static_any::any& valDropped = valsDropped[0].columnData; ModaData* data = static_cast(context->getUserData()); - std::unordered_map* map = data->getMap(); + std::unordered_map >* map = data->getMap(); if (valDropped.empty()) { @@ -379,9 +388,12 @@ void ModaData::serialize(messageqcpp::ByteStream& bs) const case 4: serializeMap(bs); break; - default: + case 8: serializeMap(bs); break; + case 16: + serializeMap(bs); + break; } break; case execplan::CalpontSystemCatalog::UTINYINT: @@ -447,9 +459,12 @@ void ModaData::unserialize(messageqcpp::ByteStream& bs) case 4: unserializeMap(bs); break; - default: + case 8: unserializeMap(bs); break; + case 16: + unserializeMap(bs); + break; } break; case execplan::CalpontSystemCatalog::UTINYINT: @@ -519,10 +534,14 @@ void ModaData::cleanup() clear(); deleteMap(); break; - default: + case 8: clear(); deleteMap(); break; + case 16: + clear(); + deleteMap(); + break; } break; case execplan::CalpontSystemCatalog::UTINYINT: diff --git a/utils/regr/moda.h b/utils/regr/moda.h index f8c0ef822..ae47f8462 100644 --- a/utils/regr/moda.h +++ b/utils/regr/moda.h @@ -45,6 +45,7 @@ #include "mcsv1_udaf.h" #include "calpontsystemcatalog.h" #include "windowfunctioncolumn.h" +#include "hasher.h" #if defined(_MSC_VER) && defined(xxxRGNODE_DLLEXPORT) #define EXPORT __declspec(dllexport) @@ -54,6 +55,38 @@ namespace mcsv1sdk { +// A hasher that handles int128_t +template +struct hasher +{ + inline size_t operator()(T val) const + { + return fHasher((char*) &val, sizeof(T)); + } + +private: + utils::Hasher fHasher; +}; + +template<> +struct hasher +{ + 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; +}; + // Override UserData for data storage struct ModaData : public UserData { @@ -69,22 +102,22 @@ struct ModaData : public UserData virtual void unserialize(messageqcpp::ByteStream& bs); template - std::unordered_map* getMap() + std::unordered_map >* getMap() { if (!fMap) { // Just in time creation - fMap = new std::unordered_map; + fMap = new std::unordered_map >; } - return (std::unordered_map*) fMap; + return (std::unordered_map >*) fMap; } // The const version is only called by serialize() // It shouldn't (and can't) create a new map. template - std::unordered_map* getMap() const + std::unordered_map >* getMap() const { - return (std::unordered_map*) fMap; + return (std::unordered_map >*) fMap; } template @@ -92,7 +125,7 @@ struct ModaData : public UserData { if (fMap) { - delete (std::unordered_map*) fMap; + delete (std::unordered_map >*) fMap; fMap = NULL; } } @@ -123,10 +156,10 @@ private: template void serializeMap(messageqcpp::ByteStream& bs) const { - std::unordered_map* map = getMap(); + std::unordered_map >* map = getMap(); if (map) { - typename std::unordered_map::const_iterator iter; + typename std::unordered_map >::const_iterator iter; bs << (uint64_t)map->size(); for (iter = map->begin(); iter != map->end(); ++iter) { @@ -147,7 +180,7 @@ private: T num; uint64_t sz; bs >> sz; - std::unordered_map* map = getMap(); + std::unordered_map >* map = getMap(); map->clear(); for (uint64_t i = 0; i < sz; ++i) { @@ -234,6 +267,7 @@ protected: Moda_impl_T moda_impl_int16; Moda_impl_T moda_impl_int32; Moda_impl_T moda_impl_int64; + Moda_impl_T moda_impl_int128; Moda_impl_T moda_impl_uint8; Moda_impl_T moda_impl_uint16; Moda_impl_T moda_impl_uint32; diff --git a/utils/rowgroup/rowaggregation.cpp b/utils/rowgroup/rowaggregation.cpp index f39dea607..491b4ef27 100755 --- a/utils/rowgroup/rowaggregation.cpp +++ b/utils/rowgroup/rowaggregation.cpp @@ -479,7 +479,7 @@ inline bool RowAggregation::isNull(const RowGroup* pRowGroup, const Row& row, in else { //@bug 1821 - ret = (row.equals("", col) || row.equals(joblist::CPNULLSTRMARK, col)); + ret = (row.equals(string(""), col) || row.equals(joblist::CPNULLSTRMARK, col)); } break; @@ -577,7 +577,7 @@ inline bool RowAggregation::isNull(const RowGroup* pRowGroup, const Row& row, in case execplan::CalpontSystemCatalog::VARBINARY: case execplan::CalpontSystemCatalog::BLOB: { - ret = (row.equals("", col) || row.equals(joblist::CPNULLSTRMARK, col)); + ret = (row.equals(string(""), col) || row.equals(joblist::CPNULLSTRMARK, col)); break; } @@ -1528,7 +1528,7 @@ void RowAggregation::doSum(const Row& rowIn, int64_t colIn, int64_t colOut, int int128_t* dec = reinterpret_cast(wideValInPtr); if (LIKELY(!isNull(fRowGroupOut, fRow, colOut))) { - int128_t *valOutPtr = fRow.getBinaryField(valOutPtr, colOut); + int128_t *valOutPtr = fRow.getBinaryField(colOut); int128_t sum = *valOutPtr + *dec; fRow.setBinaryField_offset(&sum, sizeof(sum), offset); } @@ -1989,7 +1989,7 @@ void RowAggregation::doAvg(const Row& rowIn, int64_t colIn, int64_t colOut, int6 int128_t* dec = reinterpret_cast(wideValInPtr); if (LIKELY(notFirstValue)) { - int128_t *valOutPtr = fRow.getBinaryField(valOutPtr, colOut); + int128_t *valOutPtr = fRow.getBinaryField(colOut); int128_t sum = *valOutPtr + *dec; fRow.setBinaryField_offset(&sum, sizeof(sum), offset); } @@ -4366,7 +4366,7 @@ void RowAggregationUMP2::doAvg(const Row& rowIn, int64_t colIn, int64_t colOut, int128_t* dec = reinterpret_cast(wideValInPtr); if (LIKELY(cnt > 0)) { - int128_t *valOutPtr = fRow.getBinaryField(valOutPtr, colOut); + int128_t *valOutPtr = fRow.getBinaryField(colOut); int128_t sum = *valOutPtr + *dec; fRow.setBinaryField_offset(&sum, sizeof(sum), offset); fRow.setUintField(rowIn.getUintField(colIn + 1) + cnt, colAux); diff --git a/utils/rowgroup/rowgroup.h b/utils/rowgroup/rowgroup.h index c6a1daed8..31712c2ad 100644 --- a/utils/rowgroup/rowgroup.h +++ b/utils/rowgroup/rowgroup.h @@ -380,7 +380,8 @@ public: template inline bool equals(uint64_t val, uint32_t colIndex) const; inline bool equals(long double val, uint32_t colIndex) const; bool equals(const std::string& val, uint32_t colIndex) const; - + inline bool equals(int128_t val, uint32_t colIndex) const; + inline double getDoubleField(uint32_t colIndex) const; inline float getFloatField(uint32_t colIndex) const; inline double getDecimalField(uint32_t colIndex) const @@ -388,6 +389,8 @@ public: return 0.0; // TODO: Do something here } inline long double getLongDoubleField(uint32_t colIndex) const; + inline int128_t getInt128Field(uint32_t colIndex) const; + inline uint128_t getUint128Field(uint32_t colIndex) const; inline uint64_t getBaseRid() const; inline uint64_t getRid() const; @@ -417,6 +420,7 @@ public: inline void setFloatField(float val, uint32_t colIndex); inline void setDecimalField(double val, uint32_t colIndex) { }; // TODO: Do something here inline void setLongDoubleField(long double val, uint32_t colIndex); + inline void setInt128Field(int128_t val, uint32_t colIndex); inline void setRid(uint64_t rid); @@ -674,7 +678,7 @@ inline bool Row::inStringTable(uint32_t col) const template inline bool Row::equals(T* value, uint32_t colIndex) const { - return reinterpret_cast(&data[offsets[colIndex]]) == value; + return *reinterpret_cast(&data[offsets[colIndex]]) == *value; } template @@ -704,6 +708,12 @@ inline bool Row::equals(long double val, uint32_t colIndex) const { return *((long double*) &data[offsets[colIndex]]) == val; } + +inline bool Row::equals(int128_t val, uint32_t colIndex) const +{ + return *((int128_t*) &data[offsets[colIndex]]) == val; +} + template inline uint64_t Row::getUintField(uint32_t colIndex) const { @@ -951,6 +961,16 @@ inline long double Row::getLongDoubleField(uint32_t colIndex) const return *((long double*) &data[offsets[colIndex]]); } +inline int128_t Row::getInt128Field(uint32_t colIndex) const +{ + return *((int128_t*) &data[offsets[colIndex]]); +} + +inline uint128_t Row::getUint128Field(uint32_t colIndex) const +{ + return *((uint128_t*) &data[offsets[colIndex]]); +} + inline uint64_t Row::getRid() const { return baseRid + *((uint16_t*) data); @@ -1158,6 +1178,11 @@ inline void Row::setLongDoubleField(long double val, uint32_t colIndex) } } +inline void Row::setInt128Field(int128_t val, uint32_t colIndex) +{ + *((int128_t*)&data[offsets[colIndex]]) = val; +} + inline void Row::setVarBinaryField(const std::string& val, uint32_t colIndex) { if (inStringTable(colIndex)) diff --git a/utils/udfsdk/mcsv1_udaf.cpp b/utils/udfsdk/mcsv1_udaf.cpp index 326c7fee0..f23d53c52 100755 --- a/utils/udfsdk/mcsv1_udaf.cpp +++ b/utils/udfsdk/mcsv1_udaf.cpp @@ -278,11 +278,13 @@ const static_any::any& mcsv1_UDAF::shortTypeId((short)1); const static_any::any& mcsv1_UDAF::intTypeId((int)1); const static_any::any& mcsv1_UDAF::longTypeId((long)1); const static_any::any& mcsv1_UDAF::llTypeId((long long)1); +const static_any::any& mcsv1_UDAF::int128TypeId((int128_t)1); const static_any::any& mcsv1_UDAF::ucharTypeId((unsigned char)1); const static_any::any& mcsv1_UDAF::ushortTypeId((unsigned short)1); const static_any::any& mcsv1_UDAF::uintTypeId((unsigned int)1); const static_any::any& mcsv1_UDAF::ulongTypeId((unsigned long)1); const static_any::any& mcsv1_UDAF::ullTypeId((unsigned long long)1); +const static_any::any& mcsv1_UDAF::uint128TypeId((uint128_t)1); const static_any::any& mcsv1_UDAF::floatTypeId((float)1); const static_any::any& mcsv1_UDAF::doubleTypeId((double)1); const static_any::any& mcsv1_UDAF::strTypeId(typeStr); diff --git a/utils/udfsdk/mcsv1_udaf.h b/utils/udfsdk/mcsv1_udaf.h index d7096c052..6c0ea7370 100755 --- a/utils/udfsdk/mcsv1_udaf.h +++ b/utils/udfsdk/mcsv1_udaf.h @@ -638,11 +638,13 @@ protected: static const static_any::any& intTypeId; static const static_any::any& longTypeId; static const static_any::any& llTypeId; + static const static_any::any& int128TypeId; static const static_any::any& ucharTypeId; static const static_any::any& ushortTypeId; static const static_any::any& uintTypeId; static const static_any::any& ulongTypeId; static const static_any::any& ullTypeId; + static const static_any::any& uint128TypeId; static const static_any::any& floatTypeId; static const static_any::any& doubleTypeId; static const static_any::any& strTypeId; @@ -1069,6 +1071,14 @@ inline T mcsv1_UDAF::convertAnyTo(static_any::any& valIn) { val = valIn.cast(); } + else if (valIn.compatible(int128TypeId)) + { + val = valIn.cast(); + } + else if (valIn.compatible(uint128TypeId)) + { + val = valIn.cast(); + } else { throw std::runtime_error("mcsv1_UDAF::convertAnyTo(): input param has unrecognized type"); diff --git a/utils/windowfunction/frameboundrange.cpp b/utils/windowfunction/frameboundrange.cpp index 21323f823..e10cb6fbd 100644 --- a/utils/windowfunction/frameboundrange.cpp +++ b/utils/windowfunction/frameboundrange.cpp @@ -285,7 +285,6 @@ void FrameBoundExpressionRange::validate() case execplan::CalpontSystemCatalog::MEDINT: case execplan::CalpontSystemCatalog::INT: case execplan::CalpontSystemCatalog::BIGINT: - case execplan::CalpontSystemCatalog::DECIMAL: { int64_t tmp = this->fRow.getIntField(this->fIndex[1]); this->fIsZero = (tmp == 0); @@ -299,6 +298,33 @@ void FrameBoundExpressionRange::validate() break; } + case execplan::CalpontSystemCatalog::DECIMAL: + { + if (this->fRow.getColumnWidth(this->fIndex[1]) < 16) + { + int64_t tmp = this->fRow.getIntField(this->fIndex[1]); + this->fIsZero = (tmp == 0); + + if (tmp < 0) + { + invalid = true; + oss << ""; + } + } + else + { + int128_t tmp = this->fRow.getInt128Field(this->fIndex[1]); + this->fIsZero = (tmp == 0); + + if (tmp < 0) + { + invalid = true; + oss << ""; + } + } + break; + } + case execplan::CalpontSystemCatalog::DOUBLE: case execplan::CalpontSystemCatalog::UDOUBLE: { @@ -343,15 +369,30 @@ void FrameBoundExpressionRange::validate() break; } + case execplan::CalpontSystemCatalog::UDECIMAL: + { + if (this->fRow.getColumnWidth(this->fIndex[1]) < 16) + { + uint64_t tmp = this->fRow.getUintField(this->fIndex[1]); + this->fIsZero = (tmp == 0); + break; + } + else + { + uint128_t tmp = this->fRow.getUint128Field(this->fIndex[1]); + this->fIsZero = (tmp == 0); + break; + } + } + case execplan::CalpontSystemCatalog::UTINYINT: case execplan::CalpontSystemCatalog::USMALLINT: case execplan::CalpontSystemCatalog::UMEDINT: case execplan::CalpontSystemCatalog::UINT: case execplan::CalpontSystemCatalog::UBIGINT: - case execplan::CalpontSystemCatalog::UDECIMAL: default: { - int64_t tmp = this->fRow.getIntField(this->fIndex[1]); + uint64_t tmp = this->fRow.getUintField(this->fIndex[1]); this->fIsZero = (tmp == 0); break; } diff --git a/utils/windowfunction/idborderby.cpp b/utils/windowfunction/idborderby.cpp index 58b01ee38..6814ed4ad 100644 --- a/utils/windowfunction/idborderby.cpp +++ b/utils/windowfunction/idborderby.cpp @@ -610,7 +610,7 @@ void CompareRule::compileRules(const std::vector& spec, const rowgr case datatypes::MAXDECIMALWIDTH: c = new WideDecimalCompare(*i, offsets[i->fIndex]); break; case datatypes::MAXLEGACYWIDTH: - c = new BigIntCompare(*i); + c = new BigIntCompare(*i); break; case 1 : c = new TinyIntCompare(*i); break; case 2 : @@ -837,8 +837,6 @@ bool EqualCompData::operator()(Row::Pointer a, Row::Pointer b) case CalpontSystemCatalog::MEDINT: case CalpontSystemCatalog::INT: case CalpontSystemCatalog::BIGINT: - case CalpontSystemCatalog::DECIMAL: - case CalpontSystemCatalog::UDECIMAL: case CalpontSystemCatalog::UTINYINT: case CalpontSystemCatalog::USMALLINT: case CalpontSystemCatalog::UMEDINT: @@ -854,6 +852,21 @@ bool EqualCompData::operator()(Row::Pointer a, Row::Pointer b) break; } + case CalpontSystemCatalog::DECIMAL: + case CalpontSystemCatalog::UDECIMAL: + { + // equal compare. ignore sign and null + if (fRow1.getColumnWidth(*i) < 16) + { + eq = (fRow1.getUintField(*i) == fRow2.getUintField(*i)); + } + else + { + eq = (fRow1.getUint128Field(*i) == fRow2.getUint128Field(*i)); + } + break; + } + case CalpontSystemCatalog::CHAR: case CalpontSystemCatalog::VARCHAR: { diff --git a/utils/windowfunction/wf_count.cpp b/utils/windowfunction/wf_count.cpp index 7af4acb0a..d7e9b104e 100644 --- a/utils/windowfunction/wf_count.cpp +++ b/utils/windowfunction/wf_count.cpp @@ -55,7 +55,7 @@ namespace windowfunction template -boost::shared_ptr WF_count::makeFunction(int id, const string& name, int ct) +boost::shared_ptr WF_count::makeFunction(int id, const string& name, int ct, WindowFunctionColumn* wc) { boost::shared_ptr func; @@ -70,7 +70,25 @@ boost::shared_ptr WF_count::makeFunction(int id, const st } case CalpontSystemCatalog::BINARY: + { std::cout << __FILE__<< ":" <<__LINE__ << " Fix for 16 Bytes ?" << std::endl; + break; + } + + case CalpontSystemCatalog::DECIMAL: + case CalpontSystemCatalog::UDECIMAL: + { + if (wc->functionParms()[0]->resultType().colWidth < 16) + { + func.reset(new WF_count(id, name)); + } + else + { + func.reset(new WF_count(id, name)); + } + break; + } + default: { func.reset(new WF_count(id, name)); break; @@ -176,7 +194,7 @@ void WF_count::operator()(int64_t b, int64_t e, int64_t c) template -boost::shared_ptr WF_count::makeFunction(int, const string&, int); +boost::shared_ptr WF_count::makeFunction(int, const string&, int, WindowFunctionColumn*); } //namespace diff --git a/utils/windowfunction/wf_count.h b/utils/windowfunction/wf_count.h index cc4b63959..934489815 100644 --- a/utils/windowfunction/wf_count.h +++ b/utils/windowfunction/wf_count.h @@ -43,7 +43,7 @@ public: WindowFunctionType* clone() const; void resetData(); - static boost::shared_ptr makeFunction(int, const string&, int); + static boost::shared_ptr makeFunction(int, const string&, int, WindowFunctionColumn*); protected: diff --git a/utils/windowfunction/wf_lead_lag.cpp b/utils/windowfunction/wf_lead_lag.cpp index cb15f3490..62fab334b 100644 --- a/utils/windowfunction/wf_lead_lag.cpp +++ b/utils/windowfunction/wf_lead_lag.cpp @@ -53,7 +53,7 @@ namespace windowfunction template -boost::shared_ptr WF_lead_lag::makeFunction(int id, const string& name, int ct) +boost::shared_ptr WF_lead_lag::makeFunction(int id, const string& name, int ct, WindowFunctionColumn* wc) { boost::shared_ptr func; @@ -64,7 +64,6 @@ boost::shared_ptr WF_lead_lag::makeFunction(int id, const case CalpontSystemCatalog::MEDINT: case CalpontSystemCatalog::INT: case CalpontSystemCatalog::BIGINT: - case CalpontSystemCatalog::DECIMAL: { func.reset(new WF_lead_lag(id, name)); break; @@ -75,7 +74,6 @@ boost::shared_ptr WF_lead_lag::makeFunction(int id, const case CalpontSystemCatalog::UMEDINT: case CalpontSystemCatalog::UINT: case CalpontSystemCatalog::UBIGINT: - case CalpontSystemCatalog::UDECIMAL: case CalpontSystemCatalog::DATE: case CalpontSystemCatalog::DATETIME: case CalpontSystemCatalog::TIMESTAMP: @@ -85,6 +83,32 @@ boost::shared_ptr WF_lead_lag::makeFunction(int id, const break; } + case CalpontSystemCatalog::DECIMAL: + { + if (wc->functionParms()[0]->resultType().colWidth < 16) + { + func.reset(new WF_lead_lag(id, name)); + } + else + { + func.reset(new WF_lead_lag(id, name)); + } + break; + } + + case CalpontSystemCatalog::UDECIMAL: + { + if (wc->functionParms()[0]->resultType().colWidth < 16) + { + func.reset(new WF_lead_lag(id, name)); + } + else + { + func.reset(new WF_lead_lag(id, name)); + } + break; + } + case CalpontSystemCatalog::DOUBLE: case CalpontSystemCatalog::UDOUBLE: { @@ -293,10 +317,12 @@ void WF_lead_lag::operator()(int64_t b, int64_t e, int64_t c) template -boost::shared_ptr WF_lead_lag::makeFunction(int, const string&, int); +boost::shared_ptr WF_lead_lag::makeFunction(int, const string&, int, WindowFunctionColumn*); template void WF_lead_lag::parseParms(const std::vector&); template void WF_lead_lag::parseParms(const std::vector&); +template void WF_lead_lag::parseParms(const std::vector&); +template void WF_lead_lag::parseParms(const std::vector&); template void WF_lead_lag::parseParms(const std::vector&); template void WF_lead_lag::parseParms(const std::vector&); template void WF_lead_lag::parseParms(const std::vector&); diff --git a/utils/windowfunction/wf_lead_lag.h b/utils/windowfunction/wf_lead_lag.h index de14ca702..81b707ae2 100644 --- a/utils/windowfunction/wf_lead_lag.h +++ b/utils/windowfunction/wf_lead_lag.h @@ -43,7 +43,7 @@ public: void resetData(); void parseParms(const std::vector&); - static boost::shared_ptr makeFunction(int, const string&, int); + static boost::shared_ptr makeFunction(int, const string&, int, WindowFunctionColumn*); protected: T fValue; diff --git a/utils/windowfunction/wf_min_max.cpp b/utils/windowfunction/wf_min_max.cpp index 4ae76e84d..f9c410362 100644 --- a/utils/windowfunction/wf_min_max.cpp +++ b/utils/windowfunction/wf_min_max.cpp @@ -52,7 +52,7 @@ namespace windowfunction template -boost::shared_ptr WF_min_max::makeFunction(int id, const string& name, int ct) +boost::shared_ptr WF_min_max::makeFunction(int id, const string& name, int ct, WindowFunctionColumn* wc) { boost::shared_ptr func; @@ -63,7 +63,6 @@ boost::shared_ptr WF_min_max::makeFunction(int id, const case CalpontSystemCatalog::MEDINT: case CalpontSystemCatalog::INT: case CalpontSystemCatalog::BIGINT: - case CalpontSystemCatalog::DECIMAL: { func.reset(new WF_min_max(id, name)); break; @@ -74,7 +73,6 @@ boost::shared_ptr WF_min_max::makeFunction(int id, const case CalpontSystemCatalog::UMEDINT: case CalpontSystemCatalog::UINT: case CalpontSystemCatalog::UBIGINT: - case CalpontSystemCatalog::UDECIMAL: case CalpontSystemCatalog::DATE: case CalpontSystemCatalog::DATETIME: case CalpontSystemCatalog::TIMESTAMP: @@ -84,6 +82,32 @@ boost::shared_ptr WF_min_max::makeFunction(int id, const break; } + case CalpontSystemCatalog::DECIMAL: + { + if (wc->functionParms()[0]->resultType().colWidth < 16) + { + func.reset(new WF_min_max(id, name)); + } + else + { + func.reset(new WF_min_max(id, name)); + } + break; + } + + case CalpontSystemCatalog::UDECIMAL: + { + if (wc->functionParms()[0]->resultType().colWidth < 16) + { + func.reset(new WF_min_max(id, name)); + } + else + { + func.reset(new WF_min_max(id, name)); + } + break; + } + case CalpontSystemCatalog::DOUBLE: case CalpontSystemCatalog::UDOUBLE: { @@ -173,7 +197,7 @@ void WF_min_max::operator()(int64_t b, int64_t e, int64_t c) template -boost::shared_ptr WF_min_max::makeFunction(int, const string&, int); +boost::shared_ptr WF_min_max::makeFunction(int, const string&, int, WindowFunctionColumn*); } //namespace diff --git a/utils/windowfunction/wf_min_max.h b/utils/windowfunction/wf_min_max.h index aac8d579c..ebe12df65 100644 --- a/utils/windowfunction/wf_min_max.h +++ b/utils/windowfunction/wf_min_max.h @@ -42,7 +42,7 @@ public: WindowFunctionType* clone() const; void resetData(); - static boost::shared_ptr makeFunction(int, const string&, int); + static boost::shared_ptr makeFunction(int, const string&, int, WindowFunctionColumn*); protected: T fValue; diff --git a/utils/windowfunction/wf_nth_value.cpp b/utils/windowfunction/wf_nth_value.cpp index c736c0e92..9c566345f 100644 --- a/utils/windowfunction/wf_nth_value.cpp +++ b/utils/windowfunction/wf_nth_value.cpp @@ -53,7 +53,7 @@ namespace windowfunction template -boost::shared_ptr WF_nth_value::makeFunction(int id, const string& name, int ct) +boost::shared_ptr WF_nth_value::makeFunction(int id, const string& name, int ct, WindowFunctionColumn* wc) { boost::shared_ptr func; @@ -64,7 +64,6 @@ boost::shared_ptr WF_nth_value::makeFunction(int id, cons case CalpontSystemCatalog::MEDINT: case CalpontSystemCatalog::INT: case CalpontSystemCatalog::BIGINT: - case CalpontSystemCatalog::DECIMAL: { func.reset(new WF_nth_value(id, name)); break; @@ -75,7 +74,6 @@ boost::shared_ptr WF_nth_value::makeFunction(int id, cons case CalpontSystemCatalog::UMEDINT: case CalpontSystemCatalog::UINT: case CalpontSystemCatalog::UBIGINT: - case CalpontSystemCatalog::UDECIMAL: case CalpontSystemCatalog::DATE: case CalpontSystemCatalog::DATETIME: case CalpontSystemCatalog::TIMESTAMP: @@ -85,6 +83,32 @@ boost::shared_ptr WF_nth_value::makeFunction(int id, cons break; } + case CalpontSystemCatalog::DECIMAL: + { + if (wc->functionParms()[0]->resultType().colWidth < 16) + { + func.reset(new WF_nth_value(id, name)); + } + else + { + func.reset(new WF_nth_value(id, name)); + } + break; + } + + case CalpontSystemCatalog::UDECIMAL: + { + if (wc->functionParms()[0]->resultType().colWidth < 16) + { + func.reset(new WF_nth_value(id, name)); + } + else + { + func.reset(new WF_nth_value(id, name)); + } + break; + } + case CalpontSystemCatalog::DOUBLE: case CalpontSystemCatalog::UDOUBLE: { @@ -273,7 +297,7 @@ void WF_nth_value::operator()(int64_t b, int64_t e, int64_t c) template -boost::shared_ptr WF_nth_value::makeFunction(int, const string&, int); +boost::shared_ptr WF_nth_value::makeFunction(int, const string&, int, WindowFunctionColumn*); } //namespace diff --git a/utils/windowfunction/wf_nth_value.h b/utils/windowfunction/wf_nth_value.h index 313313210..8ea294b02 100644 --- a/utils/windowfunction/wf_nth_value.h +++ b/utils/windowfunction/wf_nth_value.h @@ -43,7 +43,7 @@ public: void resetData(); void parseParms(const std::vector&); - static boost::shared_ptr makeFunction(int, const string&, int); + static boost::shared_ptr makeFunction(int, const string&, int, WindowFunctionColumn*); protected: T fValue; diff --git a/utils/windowfunction/wf_ntile.cpp b/utils/windowfunction/wf_ntile.cpp index 3bf2a3c24..9361609a6 100644 --- a/utils/windowfunction/wf_ntile.cpp +++ b/utils/windowfunction/wf_ntile.cpp @@ -54,7 +54,7 @@ namespace windowfunction { -boost::shared_ptr WF_ntile::makeFunction(int id, const string& name, int ct) +boost::shared_ptr WF_ntile::makeFunction(int id, const string& name, int ct, WindowFunctionColumn* wc) { boost::shared_ptr func(new WF_ntile(id, name)); return func; diff --git a/utils/windowfunction/wf_ntile.h b/utils/windowfunction/wf_ntile.h index 783ee1983..45d5ba64a 100644 --- a/utils/windowfunction/wf_ntile.h +++ b/utils/windowfunction/wf_ntile.h @@ -43,7 +43,7 @@ public: void resetData(); void parseParms(const std::vector&); - static boost::shared_ptr makeFunction(int, const string&, int); + static boost::shared_ptr makeFunction(int, const string&, int, WindowFunctionColumn*); protected: diff --git a/utils/windowfunction/wf_percentile.cpp b/utils/windowfunction/wf_percentile.cpp index 0c93b1434..043e36c08 100644 --- a/utils/windowfunction/wf_percentile.cpp +++ b/utils/windowfunction/wf_percentile.cpp @@ -56,7 +56,7 @@ namespace windowfunction { template -boost::shared_ptr WF_percentile::makeFunction(int id, const string& name, int ct) +boost::shared_ptr WF_percentile::makeFunction(int id, const string& name, int ct, WindowFunctionColumn* wc) { boost::shared_ptr func; @@ -69,7 +69,6 @@ boost::shared_ptr WF_percentile::makeFunction(int id, con case CalpontSystemCatalog::MEDINT: case CalpontSystemCatalog::INT: case CalpontSystemCatalog::BIGINT: - case CalpontSystemCatalog::DECIMAL: { func.reset(new WF_percentile(id, name)); break; @@ -80,7 +79,6 @@ boost::shared_ptr WF_percentile::makeFunction(int id, con case CalpontSystemCatalog::UMEDINT: case CalpontSystemCatalog::UINT: case CalpontSystemCatalog::UBIGINT: - case CalpontSystemCatalog::UDECIMAL: case CalpontSystemCatalog::DATE: case CalpontSystemCatalog::DATETIME: case CalpontSystemCatalog::TIMESTAMP: @@ -90,6 +88,32 @@ boost::shared_ptr WF_percentile::makeFunction(int id, con break; } + case CalpontSystemCatalog::DECIMAL: + { + if (wc->functionParms()[0]->resultType().colWidth < 16) + { + func.reset(new WF_percentile(id, name)); + } + else + { + func.reset(new WF_percentile(id, name)); + } + break; + } + + case CalpontSystemCatalog::UDECIMAL: + { + if (wc->functionParms()[0]->resultType().colWidth < 16) + { + func.reset(new WF_percentile(id, name)); + } + else + { + func.reset(new WF_percentile(id, name)); + } + break; + } + case CalpontSystemCatalog::DOUBLE: case CalpontSystemCatalog::UDOUBLE: { @@ -371,7 +395,7 @@ void WF_percentile::operator()(int64_t b, int64_t e, int64_t c) template -boost::shared_ptr WF_percentile::makeFunction(int, const string&, int); +boost::shared_ptr WF_percentile::makeFunction(int, const string&, int, WindowFunctionColumn*); } //namespace diff --git a/utils/windowfunction/wf_percentile.h b/utils/windowfunction/wf_percentile.h index afc2f69b3..ae2c8db50 100644 --- a/utils/windowfunction/wf_percentile.h +++ b/utils/windowfunction/wf_percentile.h @@ -44,7 +44,7 @@ public: void resetData(); void parseParms(const std::vector&); - static boost::shared_ptr makeFunction(int, const string&, int); + static boost::shared_ptr makeFunction(int, const string&, int, WindowFunctionColumn*); protected: diff --git a/utils/windowfunction/wf_ranking.cpp b/utils/windowfunction/wf_ranking.cpp index 4e9765630..818820ee5 100644 --- a/utils/windowfunction/wf_ranking.cpp +++ b/utils/windowfunction/wf_ranking.cpp @@ -53,7 +53,7 @@ namespace windowfunction { -boost::shared_ptr WF_ranking::makeFunction(int id, const string& name, int ct) +boost::shared_ptr WF_ranking::makeFunction(int id, const string& name, int ct, WindowFunctionColumn* wc) { boost::shared_ptr func(new WF_ranking(id, name)); return func; diff --git a/utils/windowfunction/wf_ranking.h b/utils/windowfunction/wf_ranking.h index c8be23ba4..ce95bd122 100644 --- a/utils/windowfunction/wf_ranking.h +++ b/utils/windowfunction/wf_ranking.h @@ -42,7 +42,7 @@ public: WindowFunctionType* clone() const; void resetData(); - static boost::shared_ptr makeFunction(int, const string&, int); + static boost::shared_ptr makeFunction(int, const string&, int, WindowFunctionColumn*); protected: diff --git a/utils/windowfunction/wf_row_number.cpp b/utils/windowfunction/wf_row_number.cpp index cac718317..048422614 100644 --- a/utils/windowfunction/wf_row_number.cpp +++ b/utils/windowfunction/wf_row_number.cpp @@ -53,7 +53,7 @@ namespace windowfunction { -boost::shared_ptr WF_row_number::makeFunction(int id, const string& name, int ct) +boost::shared_ptr WF_row_number::makeFunction(int id, const string& name, int ct, WindowFunctionColumn* wc) { boost::shared_ptr func(new WF_row_number(id, name)); return func; diff --git a/utils/windowfunction/wf_row_number.h b/utils/windowfunction/wf_row_number.h index 65a1b6618..4b6a61c08 100644 --- a/utils/windowfunction/wf_row_number.h +++ b/utils/windowfunction/wf_row_number.h @@ -42,7 +42,7 @@ public: WindowFunctionType* clone() const; void resetData(); - static boost::shared_ptr makeFunction(int, const string&, int); + static boost::shared_ptr makeFunction(int, const string&, int, WindowFunctionColumn*); protected: diff --git a/utils/windowfunction/wf_stats.cpp b/utils/windowfunction/wf_stats.cpp index 8b06eda61..1804ad432 100644 --- a/utils/windowfunction/wf_stats.cpp +++ b/utils/windowfunction/wf_stats.cpp @@ -55,7 +55,7 @@ namespace windowfunction template -boost::shared_ptr WF_stats::makeFunction(int id, const string& name, int ct) +boost::shared_ptr WF_stats::makeFunction(int id, const string& name, int ct, WindowFunctionColumn* wc) { boost::shared_ptr func; @@ -66,7 +66,6 @@ boost::shared_ptr WF_stats::makeFunction(int id, const st case CalpontSystemCatalog::MEDINT: case CalpontSystemCatalog::INT: case CalpontSystemCatalog::BIGINT: - case CalpontSystemCatalog::DECIMAL: { func.reset(new WF_stats(id, name)); break; @@ -77,12 +76,37 @@ boost::shared_ptr WF_stats::makeFunction(int id, const st case CalpontSystemCatalog::UMEDINT: case CalpontSystemCatalog::UINT: case CalpontSystemCatalog::UBIGINT: - case CalpontSystemCatalog::UDECIMAL: { func.reset(new WF_stats(id, name)); break; } + case CalpontSystemCatalog::DECIMAL: + { + if (wc->functionParms()[0]->resultType().colWidth < 16) + { + func.reset(new WF_stats(id, name)); + } + else + { + func.reset(new WF_stats(id, name)); + } + break; + } + + case CalpontSystemCatalog::UDECIMAL: + { + if (wc->functionParms()[0]->resultType().colWidth < 16) + { + func.reset(new WF_stats(id, name)); + } + else + { + func.reset(new WF_stats(id, name)); + } + break; + } + case CalpontSystemCatalog::DOUBLE: case CalpontSystemCatalog::UDOUBLE: { @@ -177,17 +201,19 @@ void WF_stats::operator()(int64_t b, int64_t e, int64_t c) { int scale = fRow.getScale(colIn); long double factor = pow(10.0, scale); + long double ldSum1 = fSum1; + long double ldSum2 = fSum2; // adjust the scale if necessary if (scale != 0 && cdt != CalpontSystemCatalog::LONGDOUBLE) { - fSum1 /= factor; - fSum2 /= factor * factor; + ldSum1 /= factor; + ldSum2 /= factor * factor; } - long double stat = fSum1 * fSum1 / fCount; - stat = fSum2 - stat; + long double stat = ldSum1 * ldSum1 / fCount; + stat = ldSum2 - stat; if (fFunctionId == WF__STDDEV_POP) stat = sqrt(stat / fCount); @@ -220,7 +246,7 @@ void WF_stats::operator()(int64_t b, int64_t e, int64_t c) template -boost::shared_ptr WF_stats::makeFunction(int, const string&, int); +boost::shared_ptr WF_stats::makeFunction(int, const string&, int, WindowFunctionColumn*); } //namespace diff --git a/utils/windowfunction/wf_stats.h b/utils/windowfunction/wf_stats.h index 381920482..6bff926a6 100644 --- a/utils/windowfunction/wf_stats.h +++ b/utils/windowfunction/wf_stats.h @@ -42,7 +42,7 @@ public: WindowFunctionType* clone() const; void resetData(); - static boost::shared_ptr makeFunction(int, const string&, int); + static boost::shared_ptr makeFunction(int, const string&, int, WindowFunctionColumn*); protected: long double fSum1; diff --git a/utils/windowfunction/wf_sum_avg.cpp b/utils/windowfunction/wf_sum_avg.cpp index d0d5f46f7..0ad1c1a30 100644 --- a/utils/windowfunction/wf_sum_avg.cpp +++ b/utils/windowfunction/wf_sum_avg.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2014 InfiniDB, Inc. +/* CopyrighT (C) 2014 InfiniDB, Inc. Copyright (c) 2019 MariaDB Corporation This program is free software; you can redistribute it and/or @@ -50,112 +50,116 @@ using namespace joblist; #include "wf_sum_avg.h" -#if 0 -namespace +namespace windowfunction { - -template -void checkSumLimit(T sum, T val) +template +void WF_sum_avg::checkSumLimit(long double val, long double sum) { } - -template<> -void checkSumLimit(int64_t sum, int64_t val) +template +inline void WF_sum_avg::checkSumLimit(int128_t val, int128_t sum) { - if (((sum >= 0) && ((numeric_limits::max() - sum) < val)) || - ((sum < 0) && ((numeric_limits::min() - sum) > val))) + if (((sum >= 0) && ((fMax128 - sum) < val)) || + ((sum < 0) && ((fMin128 - sum) > val))) { - string errStr = "SUM(int):"; + string errStr = "SUM(int128_t)"; + errStr = IDBErrorInfo::instance()->errorMsg(ERR_WF_OVERFLOW, errStr); + cerr << errStr << endl; + throw IDBExcept(errStr, ERR_WF_OVERFLOW); + } +} - ostringstream oss; - oss << sum << "+" << val; +template +inline void WF_sum_avg::checkSumLimit(uint128_t val, uint128_t sum) +{ + if ((fMaxu128 - sum) < val) + { + string errStr = "SUM(uint128_t)"; + errStr = IDBErrorInfo::instance()->errorMsg(ERR_WF_OVERFLOW, errStr); + cerr << errStr << endl; + throw IDBExcept(errStr, ERR_WF_OVERFLOW); + } +} - if (sum > 0) - oss << " > " << numeric_limits::max(); +template +int128_t WF_sum_avg::calculateAvg(int128_t sum, uint64_t count, int scale) +{ + int128_t factor = pow(10.0, scale); + int128_t avg; + if (scale > 0) + { + if ((sum * factor) / factor == sum) + { + avg = sum * factor; + avg /= count; + } else - oss << " < " << numeric_limits::min(); - - errStr += oss.str(); - - errStr = IDBErrorInfo::instance()->errorMsg(ERR_WF_OVERFLOW, errStr); - cerr << errStr << endl; - throw IDBExcept(errStr, ERR_WF_OVERFLOW); + { + // scale won't fit before divide, we're gonna lose precision. + avg = sum / count; + if ((avg * factor) / factor != avg) // Still won't fit + { + string errStr = string("AVG(int)"); + errStr = IDBErrorInfo::instance()->errorMsg(ERR_WF_OVERFLOW, errStr); + cerr << errStr << endl; + throw IDBExcept(errStr, ERR_WF_OVERFLOW); + } + avg *= factor; + } } -} - - -template<> -void checkSumLimit(uint64_t sum, uint64_t val) -{ - if ((sum >= 0) && ((numeric_limits::max() - sum) < val)) + else { - string errStr = "SUM(unsigned):"; - - ostringstream oss; - oss << sum << "+" << val << " > " << numeric_limits::max(); - errStr += oss.str(); - - errStr = IDBErrorInfo::instance()->errorMsg(ERR_WF_OVERFLOW, errStr); - cerr << errStr << endl; - throw IDBExcept(errStr, ERR_WF_OVERFLOW); + avg = sum / count; } -} - - -template<> -long double calculateAvg(long double sum, uint64_t count, int s) -{ - return sum / count; -} - -long double avgWithLimit(long double sum, uint64_t count, int scale, long double u, long double l) -{ - long double factor = pow(10.0, scale); - long double avg = sum / count; - avg *= factor; + avg += (avg < 0) ? (-0.5) : (0.5); - - if (avg > u || avg < l) - { - string errStr = string("AVG") + (l < 0 ? "(int):" : "(unsign)"); - ostringstream oss; - oss << avg; - errStr += oss.str(); - - errStr = IDBErrorInfo::instance()->errorMsg(ERR_WF_OVERFLOW, errStr); - cerr << errStr << endl; - throw IDBExcept(errStr, ERR_WF_OVERFLOW); - } - return avg; } - -template<> -int64_t calculateAvg(int64_t sum, uint64_t count, int scale) +template +uint128_t WF_sum_avg::calculateAvg(uint128_t sum, uint64_t count, int scale) { - int64_t t = (int64_t) avgWithLimit(sum, count, scale, - numeric_limits::max(), numeric_limits::min()); - return t; + uint128_t factor = pow(10.0, scale); + uint128_t avg = sum; + if (scale > 0) + { + if ((sum * factor) / factor == sum) + { + avg = sum * factor; + avg /= count; + } + else + { + // scale won't fit before divide, we're gonna lose precision. + avg = sum / count; + if ((avg * factor) / factor != avg) // Still won't fit + { + string errStr = string("AVG(int)"); + errStr = IDBErrorInfo::instance()->errorMsg(ERR_WF_OVERFLOW, errStr); + cerr << errStr << endl; + throw IDBExcept(errStr, ERR_WF_OVERFLOW); + } + avg *= factor; + } + } + else + { + avg = sum / count; + } + avg += 0.5; + return avg; } - -template<> -uint64_t calculateAvg(uint64_t sum, uint64_t count, int scale) +template +inline long double WF_sum_avg::calculateAvg(long double sum, uint64_t count, int scale) { - uint64_t t = (uint64_t) avgWithLimit(sum, count, scale, numeric_limits::max(), 0); - return t; + return sum / count; } -} -#endif - -namespace windowfunction -{ - -template -boost::shared_ptr WF_sum_avg::makeFunction(int id, const string& name, int ct) +// For the static function makeFunction, the template parameters are ignored +template +boost::shared_ptr WF_sum_avg::makeFunction(int id, const string& name, int ct, WindowFunctionColumn* wc) { boost::shared_ptr func; switch (ct) @@ -165,9 +169,9 @@ boost::shared_ptr WF_sum_avg::makeFunction(int id, const case CalpontSystemCatalog::MEDINT: case CalpontSystemCatalog::INT: case CalpontSystemCatalog::BIGINT: - case CalpontSystemCatalog::DECIMAL: { - func.reset(new WF_sum_avg(id, name)); + // Look into using int128_t instead of long double + func.reset(new WF_sum_avg(id, name)); break; } @@ -176,29 +180,54 @@ boost::shared_ptr WF_sum_avg::makeFunction(int id, const case CalpontSystemCatalog::UMEDINT: case CalpontSystemCatalog::UINT: case CalpontSystemCatalog::UBIGINT: + { + func.reset(new WF_sum_avg(id, name)); + break; + } + + case CalpontSystemCatalog::DECIMAL: + { + if (wc->functionParms()[0]->resultType().colWidth < 16) + { + func.reset(new WF_sum_avg(id, name)); + } + else + { + func.reset(new WF_sum_avg(id, name)); + } + break; + } + case CalpontSystemCatalog::UDECIMAL: { - func.reset(new WF_sum_avg(id, name)); + if (wc->functionParms()[0]->resultType().colWidth < 16) + { + func.reset(new WF_sum_avg(id, name)); + } + else + { + func.reset(new WF_sum_avg(id, name)); + } break; } case CalpontSystemCatalog::DOUBLE: case CalpontSystemCatalog::UDOUBLE: { - func.reset(new WF_sum_avg(id, name)); + func.reset(new WF_sum_avg(id, name)); break; } case CalpontSystemCatalog::FLOAT: case CalpontSystemCatalog::UFLOAT: { - func.reset(new WF_sum_avg(id, name)); + func.reset(new WF_sum_avg(id, name)); break; } case CalpontSystemCatalog::LONGDOUBLE: { - func.reset(new WF_sum_avg(id, name)); + func.reset(new WF_sum_avg(id, name)); break; } default: @@ -216,15 +245,15 @@ boost::shared_ptr WF_sum_avg::makeFunction(int id, const } -template -WindowFunctionType* WF_sum_avg::clone() const +template +WindowFunctionType* WF_sum_avg::clone() const { - return new WF_sum_avg(*this); + return new WF_sum_avg(*this); } -template -void WF_sum_avg::resetData() +template +void WF_sum_avg::resetData() { fAvg = 0; fSum = 0; @@ -235,8 +264,8 @@ void WF_sum_avg::resetData() } -template -void WF_sum_avg::operator()(int64_t b, int64_t e, int64_t c) +template +void WF_sum_avg::operator()(int64_t b, int64_t e, int64_t c) { uint64_t colOut = fFieldIndex[0]; @@ -251,8 +280,7 @@ void WF_sum_avg::operator()(int64_t b, int64_t e, int64_t c) e = c; uint64_t colIn = fFieldIndex[1]; - double scale = fRow.getScale(colIn); - + int scale = fRow.getScale(colOut) - fRow.getScale(colIn); for (int64_t i = b; i <= e; i++) { if (i % 1000 == 0 && fStep->cancelled()) @@ -263,34 +291,27 @@ void WF_sum_avg::operator()(int64_t b, int64_t e, int64_t c) if (fRow.isNullValue(colIn) == true) continue; - T valIn; CDT cdt; - getValue(colIn, valIn, &cdt); -// checkSumLimit(fSum, valIn); + getValue(colIn, fVal, &cdt); - if ((!fDistinct) || (fSet.find(valIn) == fSet.end())) + if ((!fDistinct) || (fSet.find(fVal) == fSet.end())) { - long double val = valIn; - if (scale && - cdt != CalpontSystemCatalog::LONGDOUBLE) - { - val /= pow(10.0, scale); - } - fSum += val; + checkSumLimit(fVal, fSum); + fSum += (T_OUT)fVal; fCount++; if (fDistinct) - fSet.insert(valIn); + fSet.insert(fVal); } } if ((fCount > 0) && (fFunctionId == WF__AVG || fFunctionId == WF__AVG_DISTINCT)) { - fAvg = fSum / fCount; + fAvg = calculateAvg(fSum, fCount, scale); } } - long double* v = NULL; + T_OUT* v = NULL; if (fCount > 0) { @@ -307,7 +328,7 @@ void WF_sum_avg::operator()(int64_t b, int64_t e, int64_t c) template -boost::shared_ptr WF_sum_avg::makeFunction(int, const string&, int); +boost::shared_ptr WF_sum_avg::makeFunction(int, const string&, int, WindowFunctionColumn*); } //namespace diff --git a/utils/windowfunction/wf_sum_avg.h b/utils/windowfunction/wf_sum_avg.h index 48d46453b..b86a9c16d 100644 --- a/utils/windowfunction/wf_sum_avg.h +++ b/utils/windowfunction/wf_sum_avg.h @@ -29,8 +29,9 @@ namespace windowfunction { - -template +// T_IN is the data type of the input values. +// T_OUT is the data type we are using for output and internal values +template class WF_sum_avg : public WindowFunctionType { public: @@ -38,6 +39,9 @@ public: WindowFunctionType(id, name), fDistinct(id != WF__SUM && id != WF__AVG) { resetData(); + utils::int128Max(fMax128); + utils::int128Min(fMin128); + utils::uint128Max(fMaxu128); } // pure virtual in base @@ -45,16 +49,27 @@ public: WindowFunctionType* clone() const; void resetData(); - static boost::shared_ptr makeFunction(int, const string&, int); + static boost::shared_ptr makeFunction(int, const string&, int, WindowFunctionColumn*); protected: - long double fAvg; - long double fSum; + T_IN fVal; + T_OUT fAvg; + T_OUT fSum; uint64_t fCount; bool fDistinct; - std::set fSet; -}; + std::set fSet; + int128_t fMax128; + int128_t fMin128; + uint128_t fMaxu128; + void checkSumLimit(long double val, long double sum); + void checkSumLimit(int128_t val, int128_t sum); + void checkSumLimit(uint128_t val, uint128_t sum); + + int128_t calculateAvg(int128_t sum, uint64_t count, int scale); + uint128_t calculateAvg(uint128_t sum, uint64_t count, int scale); + long double calculateAvg(long double sum, uint64_t count, int scale); +}; } // namespace diff --git a/utils/windowfunction/wf_udaf.cpp b/utils/windowfunction/wf_udaf.cpp index c1dc5a908..fb5f3521a 100644 --- a/utils/windowfunction/wf_udaf.cpp +++ b/utils/windowfunction/wf_udaf.cpp @@ -56,7 +56,7 @@ using namespace joblist; namespace windowfunction { -boost::shared_ptr WF_udaf::makeFunction(int id, const string& name, int ct, mcsv1sdk::mcsv1Context& context) +boost::shared_ptr WF_udaf::makeFunction(int id, const string& name, int ct, mcsv1sdk::mcsv1Context& context, WindowFunctionColumn* wc) { boost::shared_ptr func; @@ -544,11 +544,13 @@ void WF_udaf::SetUDAFValue(static_any::any& valOut, int64_t colOut, static const static_any::any& intTypeId = (int)1; static const static_any::any& longTypeId = (long)1; static const static_any::any& llTypeId = (long long)1; + static const static_any::any& int128TypeId = (int128_t)1; static const static_any::any& ucharTypeId = (unsigned char)1; static const static_any::any& ushortTypeId = (unsigned short)1; static const static_any::any& uintTypeId = (unsigned int)1; static const static_any::any& ulongTypeId = (unsigned long)1; static const static_any::any& ullTypeId = (unsigned long long)1; + static const static_any::any& uint128TypeId = (int128_t)1; static const static_any::any& floatTypeId = (float)1; static const static_any::any& doubleTypeId = (double)1; static const std::string typeStr(""); @@ -562,6 +564,8 @@ void WF_udaf::SetUDAFValue(static_any::any& valOut, int64_t colOut, // it to whatever they said to return. int64_t intOut = 0; uint64_t uintOut = 0; + int128_t int128Out = 0; + uint128_t uint128Out = 0; float floatOut = 0.0; double doubleOut = 0.0; long double longdoubleOut = 0.0; @@ -651,6 +655,24 @@ void WF_udaf::SetUDAFValue(static_any::any& valOut, int64_t colOut, intOut = (int64_t)doubleOut; oss << doubleOut; } + else if (valOut.compatible(int128TypeId)) + { + int128Out = valOut.cast(); + uintOut = intOut = int128Out; // may truncate + floatOut = int128Out; + doubleOut = int128Out; + longdoubleOut = int128Out; + oss << longdoubleOut; + } + else if (valOut.compatible(uint128TypeId)) + { + uint128Out = valOut.cast(); + uintOut = intOut = uint128Out; // may truncate + floatOut = uint128Out; + doubleOut = uint128Out; + longdoubleOut = uint128Out; + oss << longdoubleOut; + } if (valOut.compatible(strTypeId)) { @@ -901,33 +923,66 @@ void WF_udaf::operator()(int64_t b, int64_t e, int64_t c) case CalpontSystemCatalog::DECIMAL: case CalpontSystemCatalog::UDECIMAL: { - int64_t valIn; - - if (cc) + if (fRow.getColumnWidth(colIn) < 16) { - valIn = cc->getDecimalVal(fRow, isNull).value; + int64_t valIn; + + if (cc) + { + valIn = cc->getDecimalVal(fRow, isNull).value; + } + else + { + getValue(colIn, valIn); + } + + // Check for distinct, if turned on. + // Currently, distinct only works on the first parameter. + if (k == 0 && fDistinct) + { + std::pair val = make_pair(valIn, 1); + std::pair distinct; + distinct = fDistinctMap.insert(val); + if (distinct.second == false) + { + ++(*distinct.first).second; + bSkipIt = true; + continue; + } + } + + datum.columnData = valIn; } else { - getValue(colIn, valIn); - } + int128_t valIn; - // Check for distinct, if turned on. - // Currently, distinct only works on the first parameter. - if (k == 0 && fDistinct) - { - std::pair val = make_pair(valIn, 1); - std::pair distinct; - distinct = fDistinctMap.insert(val); - if (distinct.second == false) + if (cc) { - ++(*distinct.first).second; - bSkipIt = true; - continue; + valIn = cc->getDecimalVal(fRow, isNull).s128Value; + } + else + { + getValue(colIn, valIn); } - } - datum.columnData = valIn; + // Check for distinct, if turned on. + // Currently, distinct only works on the first parameter. + if (k == 0 && fDistinct) + { + std::pair val = make_pair(valIn, 1); + std::pair distinct; + distinct = fDistinctMap.insert(val); + if (distinct.second == false) + { + ++(*distinct.first).second; + bSkipIt = true; + continue; + } + } + + datum.columnData = valIn; + } break; } @@ -1154,7 +1209,7 @@ void WF_udaf::operator()(int64_t b, int64_t e, int64_t c) fPrev = c; } -boost::shared_ptr WF_udaf::makeFunction(int id, const string& name, int ct, mcsv1sdk::mcsv1Context& context); +boost::shared_ptr WF_udaf::makeFunction(int id, const string& name, int ct, mcsv1sdk::mcsv1Context& context, WindowFunctionColumn*); } //namespace // vim:ts=4 sw=4: diff --git a/utils/windowfunction/wf_udaf.h b/utils/windowfunction/wf_udaf.h index 38515285f..e87b39759 100644 --- a/utils/windowfunction/wf_udaf.h +++ b/utils/windowfunction/wf_udaf.h @@ -104,7 +104,7 @@ protected: public: static boost::shared_ptr makeFunction(int id, const string& name, - int ct, mcsv1sdk::mcsv1Context& context); + int ct, mcsv1sdk::mcsv1Context& context, WindowFunctionColumn* wc); }; diff --git a/utils/windowfunction/windowfunctiontype.cpp b/utils/windowfunction/windowfunctiontype.cpp index 600f5784f..6356a04bb 100644 --- a/utils/windowfunction/windowfunctiontype.cpp +++ b/utils/windowfunction/windowfunctiontype.cpp @@ -150,67 +150,67 @@ WindowFunctionType::makeWindowFunction(const string& name, int ct, WindowFunctio int functionId = windowFunctionId[algorithm::to_upper_copy(name)]; // The template parameters here are dummies to execute the static makeFunction - // which sets the real type based on ct. + // which sets the real types based on ct. switch (functionId) { case WF__COUNT_ASTERISK: case WF__COUNT: case WF__COUNT_DISTINCT: - af = WF_count::makeFunction(functionId, name, ct); + af = WF_count::makeFunction(functionId, name, ct, wc); break; case WF__MIN: case WF__MAX: - af = WF_min_max::makeFunction(functionId, name, ct); + af = WF_min_max::makeFunction(functionId, name, ct, wc); break; case WF__SUM: case WF__AVG: case WF__SUM_DISTINCT: case WF__AVG_DISTINCT: - af = WF_sum_avg::makeFunction(functionId, name, ct); + af = WF_sum_avg::makeFunction(functionId, name, ct, wc); break; case WF__STDDEV_POP: case WF__STDDEV_SAMP: case WF__VAR_POP: case WF__VAR_SAMP: - af = WF_stats::makeFunction(functionId, name, ct); + af = WF_stats::makeFunction(functionId, name, ct, wc); break; case WF__ROW_NUMBER: - af = WF_row_number::makeFunction(functionId, name, ct); + af = WF_row_number::makeFunction(functionId, name, ct, wc); break; case WF__RANK: case WF__DENSE_RANK: case WF__PERCENT_RANK: case WF__CUME_DIST: - af = WF_ranking::makeFunction(functionId, name, ct); + af = WF_ranking::makeFunction(functionId, name, ct, wc); break; case WF__FIRST_VALUE: case WF__LAST_VALUE: case WF__NTH_VALUE: - af = WF_nth_value::makeFunction(functionId, name, ct); + af = WF_nth_value::makeFunction(functionId, name, ct, wc); break; case WF__LEAD: case WF__LAG: - af = WF_lead_lag::makeFunction(functionId, name, ct); + af = WF_lead_lag::makeFunction(functionId, name, ct, wc); break; case WF__NTILE: - af = WF_ntile::makeFunction(functionId, name, ct); + af = WF_ntile::makeFunction(functionId, name, ct, wc); break; case WF__PERCENTILE_CONT: case WF__PERCENTILE_DISC: - af = WF_percentile::makeFunction(functionId, name, ct); + af = WF_percentile::makeFunction(functionId, name, ct, wc); break; case WF__UDAF: - af = WF_udaf::makeFunction(functionId, name, ct, wc->getUDAFContext()); + af = WF_udaf::makeFunction(functionId, name, ct, wc->getUDAFContext(), wc); break; case WF__REGR_SLOPE: @@ -229,7 +229,7 @@ WindowFunctionType::makeWindowFunction(const string& name, int ct, WindowFunctio break; } - // Copy the only the constant parameter pointers + // Copy only the constant parameter pointers af->constParms(wc->functionParms()); return af; @@ -308,6 +308,26 @@ template<> void WindowFunctionType::getValue(uint64_t i, string& t, CDT* // By not setting cdt, we let it default to the column's type } +template<> void WindowFunctionType::getValue(uint64_t i, int128_t& t, CDT* cdt) +{ + t = fRow.getInt128Field(i); + + if (cdt) + { + *cdt = execplan::CalpontSystemCatalog::DECIMAL; + } +} + +template<> void WindowFunctionType::getValue(uint64_t i, uint128_t& t, CDT* cdt) +{ + t = fRow.getUint128Field(i); + + if (cdt) + { + *cdt = execplan::CalpontSystemCatalog::DECIMAL; + } +} + template void WindowFunctionType::setValue(uint64_t i, T& t) { } @@ -337,6 +357,11 @@ template<> void WindowFunctionType::setValue(uint64_t i, long doubl fRow.setLongDoubleField(t, i); } +template<> void WindowFunctionType::setValue(uint64_t i, int128_t& t) +{ + fRow.setInt128Field(t, i); +} + template<> void WindowFunctionType::setValue(uint64_t i, string& t) { fRow.setStringField(t, i); @@ -389,7 +414,6 @@ void WindowFunctionType::setValue(int ct, int64_t b, int64_t e, int64_t c, T* v) case CalpontSystemCatalog::MEDINT: case CalpontSystemCatalog::INT: case CalpontSystemCatalog::BIGINT: - case CalpontSystemCatalog::DECIMAL: { int64_t iv = *v; setValue(i, iv); @@ -401,13 +425,26 @@ void WindowFunctionType::setValue(int ct, int64_t b, int64_t e, int64_t c, T* v) case CalpontSystemCatalog::UMEDINT: case CalpontSystemCatalog::UINT: case CalpontSystemCatalog::UBIGINT: - case CalpontSystemCatalog::UDECIMAL: { uint64_t uv = *v; setValue(i, uv); break; } + case CalpontSystemCatalog::DECIMAL: + { + int128_t iv = *v; + setValue(i, iv); + break; + } + + case CalpontSystemCatalog::UDECIMAL: + { + uint128_t uv = *v; + setValue(i, uv); + break; + } + case CalpontSystemCatalog::DOUBLE: case CalpontSystemCatalog::UDOUBLE: { @@ -452,7 +489,6 @@ void WindowFunctionType::implicit2T(uint64_t i, T& t, int s) case CalpontSystemCatalog::MEDINT: case CalpontSystemCatalog::INT: case CalpontSystemCatalog::BIGINT: - case CalpontSystemCatalog::DECIMAL: { t = (T) fRow.getIntField(i); pw = s - fRow.getScale(i); // pw is difference of scales, will be in [-18, 18] @@ -470,7 +506,6 @@ void WindowFunctionType::implicit2T(uint64_t i, T& t, int s) case CalpontSystemCatalog::UMEDINT: case CalpontSystemCatalog::UINT: case CalpontSystemCatalog::UBIGINT: - case CalpontSystemCatalog::UDECIMAL: { t = (T) fRow.getUintField(i); pw = s - fRow.getScale(i); // pw is difference of scales, will be in [-18, 18] @@ -483,6 +518,40 @@ void WindowFunctionType::implicit2T(uint64_t i, T& t, int s) break; } + case CalpontSystemCatalog::DECIMAL: + { + uint32_t w = fRow.getColumnWidth(i); + if (w < 16) + t = (T) fRow.getIntField(i); + else + t = (T) fRow.getInt128Field(i); + pw = s - fRow.getScale(i); // pw is difference of scales, will be in [-18, 18] + + if (pw > 0) + t *= IDB_pow[pw]; + else if (pw < 0) + t /= IDB_pow[-pw]; + + break; + } + + case CalpontSystemCatalog::UDECIMAL: + { + uint32_t w = fRow.getColumnWidth(i); + if (w < 16) + t = (T) fRow.getUintField(i); + else + t = (T) fRow.getUint128Field(i); + pw = s - fRow.getScale(i); // pw is difference of scales, will be in [-18, 18] + + if (pw > 0) + t *= IDB_pow[pw]; + else if (pw < 0) + t /= IDB_pow[-pw]; + + break; + } + case CalpontSystemCatalog::DOUBLE: case CalpontSystemCatalog::UDOUBLE: { @@ -552,6 +621,18 @@ void WindowFunctionType::getConstValue(ConstantColumn* cc, uint64_t& t t = cc->getUintVal(fRow, b); } +template<> +void WindowFunctionType::getConstValue(ConstantColumn* cc, int128_t& t, bool& b) +{ + t = cc->getDecimalVal(fRow, b).s128Value; +} + +template<> +void WindowFunctionType::getConstValue(ConstantColumn* cc, uint128_t& t, bool& b) +{ + t = cc->getDecimalVal(fRow, b).s128Value; +} + template<> void WindowFunctionType::getConstValue(ConstantColumn* cc, double& t, bool& b) { @@ -581,12 +662,16 @@ template void WindowFunctionType::implicit2T(uint64_t, uint64_t&, int) template void WindowFunctionType::implicit2T(uint64_t, float&, int); template void WindowFunctionType::implicit2T(uint64_t, double&, int); template void WindowFunctionType::implicit2T(uint64_t, long double&, int); +template void WindowFunctionType::implicit2T(uint64_t, int128_t&, int); +template void WindowFunctionType::implicit2T(uint64_t, uint128_t&, int); template void WindowFunctionType::setValue(int, int64_t, int64_t, int64_t, int64_t*); template void WindowFunctionType::setValue(int, int64_t, int64_t, int64_t, uint64_t*); template void WindowFunctionType::setValue(int, int64_t, int64_t, int64_t, float*); template void WindowFunctionType::setValue(int, int64_t, int64_t, int64_t, double*); template void WindowFunctionType::setValue(int, int64_t, int64_t, int64_t, long double*); +template void WindowFunctionType::setValue(int, int64_t, int64_t, int64_t, int128_t*); +template void WindowFunctionType::setValue(int, int64_t, int64_t, int64_t, uint128_t*); void* WindowFunctionType::getNullValueByType(int ct, int pos) { @@ -610,7 +695,8 @@ void* WindowFunctionType::getNullValueByType(int ct, int pos) // static uint64_t char4Null = joblist::CHAR4NULL; // static uint64_t char8Null = joblist::CHAR8NULL; static string stringNull(""); - + static int128_t int128Null; // Set at runtime; + void* v = NULL; switch (ct) @@ -714,9 +800,18 @@ void* WindowFunctionType::getNullValueByType(int ct, int pos) v = &intNull; break; - default: + case 8: v = &bigIntNull; break; + + case 16: + utils::setWideDecimalNullValue(int128Null); + v = &int128Null; + break; + + default: + break; + } break; diff --git a/utils/windowfunction/windowfunctiontype.h b/utils/windowfunction/windowfunctiontype.h index 9260cc4a2..1c7dea375 100644 --- a/utils/windowfunction/windowfunctiontype.h +++ b/utils/windowfunction/windowfunctiontype.h @@ -226,6 +226,10 @@ protected: { return fRow.getIntField(i); } + int128_t getInt128Value(uint64_t i) + { + return fRow.getInt128Field(i); + } double getDoubleValue(uint64_t i) { return fRow.getDoubleField(i); @@ -238,6 +242,10 @@ protected: { fRow.setIntField(v, i); } + void setInt128Value(int64_t i, int128_t v) + { + fRow.setInt128Field(v, i); + } void setDoubleValue(int64_t i, double v) { fRow.setDoubleField(v, i); diff --git a/writeengine/wrapper/writeengine.cpp b/writeengine/wrapper/writeengine.cpp index 24407d513..e75ee794e 100644 --- a/writeengine/wrapper/writeengine.cpp +++ b/writeengine/wrapper/writeengine.cpp @@ -837,7 +837,18 @@ int WriteEngineWrapper::deleteRow(const TxnID& txnid, const vector inline void allocateValArray(void*& valArray, ColTupleList::size_type totalRow, ColType colType, int colWidth) { - valArray = calloc(totalRow, colWidth); + switch (colType) + { + case WriteEngine::WR_VARBINARY : // treat same as char for now + case WriteEngine::WR_CHAR: + case WriteEngine::WR_BLOB: + case WriteEngine::WR_TEXT: + valArray = (char*) calloc(sizeof(char), totalRow * MAX_COLUMN_BOUNDARY); + break; + default: + valArray = calloc(totalRow, colWidth); + break; + } // TODO MCOL-641 is commenting out the switch statement below correct? #if 0 switch (colType)