diff --git a/datatypes/mcs_datatype.cpp b/datatypes/mcs_datatype.cpp index 39eff198d..5e3fa225a 100644 --- a/datatypes/mcs_datatype.cpp +++ b/datatypes/mcs_datatype.cpp @@ -630,7 +630,7 @@ int TypeHandlerSLongDouble::storeValueToField(rowgroup::Row &row, int pos, int TypeHandlerXDecimal::storeValueToField64(rowgroup::Row &row, int pos, StoreField *f) const { - return f->store_decimal64(datatypes::VDecimal(row.getIntField(pos), + return f->store_decimal64(datatypes::Decimal(row.getIntField(pos), f->scale(), f->precision())); } @@ -640,7 +640,7 @@ int TypeHandlerXDecimal::storeValueToField128(rowgroup::Row &row, int pos, StoreField *f) const { int128_t* decPtr = row.getBinaryField(pos); - return f->store_decimal128(datatypes::VDecimal(0, + return f->store_decimal128(datatypes::Decimal(0, f->scale(), f->precision(), decPtr)); @@ -782,7 +782,7 @@ TypeHandlerXDecimal::format128(const SimpleValue &v, const { idbassert(isValidXDecimal128(attr)); - datatypes::VDecimal dec(0, attr.scale, attr.precision, v.toSInt128()); + datatypes::Decimal dec(0, attr.scale, attr.precision, v.toSInt128()); return dec.toString(true); } diff --git a/datatypes/mcs_datatype.h b/datatypes/mcs_datatype.h index 1ca250a82..01361c657 100644 --- a/datatypes/mcs_datatype.h +++ b/datatypes/mcs_datatype.h @@ -727,8 +727,8 @@ public: virtual int store_float(float val) = 0; virtual int store_double(double val) = 0; virtual int store_long_double(long double val) = 0; - virtual int store_decimal64(const datatypes::VDecimal& dec) = 0; - virtual int store_decimal128(const datatypes::VDecimal& dec) = 0; + virtual int store_decimal64(const datatypes::Decimal& dec) = 0; + virtual int store_decimal128(const datatypes::Decimal& dec) = 0; virtual int store_lob(const char *str, size_t length) = 0; }; diff --git a/datatypes/mcs_decimal.cpp b/datatypes/mcs_decimal.cpp index 8eccc4e9d..37bbcf81e 100644 --- a/datatypes/mcs_decimal.cpp +++ b/datatypes/mcs_decimal.cpp @@ -49,9 +49,9 @@ namespace datatypes template - void addSubtractExecute(const VDecimal& l, - const VDecimal& r, - VDecimal& result, + void addSubtractExecute(const Decimal& l, + const Decimal& r, + Decimal& result, BinaryOperation op, OpOverflowCheck opOverflowCheck, MultiplicationOverflowCheck mulOverflowCheck) @@ -109,9 +109,9 @@ namespace datatypes template - void divisionExecute(const VDecimal& l, - const VDecimal& r, - VDecimal& result, + void divisionExecute(const Decimal& l, + const Decimal& r, + Decimal& result, OpOverflowCheck opOverflowCheck, MultiplicationOverflowCheck mulOverflowCheck) { @@ -148,9 +148,9 @@ namespace datatypes template - void multiplicationExecute(const VDecimal& l, - const VDecimal& r, - VDecimal& result, + void multiplicationExecute(const Decimal& l, + const Decimal& r, + Decimal& result, OpOverflowCheck opOverflowCheck, MultiplicationOverflowCheck mulOverflowCheck) { @@ -195,7 +195,7 @@ namespace datatypes } } - int Decimal::compare(const VDecimal& l, const VDecimal& r) + int Decimal::compare(const Decimal& l, const Decimal& r) { int128_t divisorL, divisorR; getScaleDivisor(divisorL, l.scale); @@ -242,8 +242,8 @@ namespace datatypes // no overflow check template<> - void Decimal::addition(const VDecimal& l, - const VDecimal& r, VDecimal& result) + void Decimal::addition(const Decimal& l, + const Decimal& r, Decimal& result) { std::plus add; NoOverflowCheck noOverflowCheck; @@ -252,8 +252,8 @@ namespace datatypes // with overflow check template<> - void Decimal::addition(const VDecimal& l, - const VDecimal& r, VDecimal& result) + void Decimal::addition(const Decimal& l, + const Decimal& r, Decimal& result) { std::plus add; AdditionOverflowCheck overflowCheck; @@ -263,8 +263,8 @@ namespace datatypes // no overflow check template<> - void Decimal::addition(const VDecimal& l, - const VDecimal& r, VDecimal& result) + void Decimal::addition(const Decimal& l, + const Decimal& r, Decimal& result) { if (result.scale == l.scale && result.scale == r.scale) { @@ -293,8 +293,8 @@ namespace datatypes // with overflow check template<> - void Decimal::addition(const VDecimal& l, - const VDecimal& r, VDecimal& result) + void Decimal::addition(const Decimal& l, + const Decimal& r, Decimal& result) { AdditionOverflowCheck additionOverflowCheck; MultiplicationOverflowCheck mulOverflowCheck; @@ -328,8 +328,8 @@ namespace datatypes // no overflow check template<> - void Decimal::subtraction(const VDecimal& l, - const VDecimal& r, VDecimal& result) + void Decimal::subtraction(const Decimal& l, + const Decimal& r, Decimal& result) { std::minus subtract; NoOverflowCheck noOverflowCheck; @@ -338,8 +338,8 @@ namespace datatypes // with overflow check template<> - void Decimal::subtraction(const VDecimal& l, - const VDecimal& r, VDecimal& result) + void Decimal::subtraction(const Decimal& l, + const Decimal& r, Decimal& result) { std::minus subtract; SubtractionOverflowCheck overflowCheck; @@ -349,8 +349,8 @@ namespace datatypes // no overflow check template<> - void Decimal::subtraction(const VDecimal& l, - const VDecimal& r, VDecimal& result) + void Decimal::subtraction(const Decimal& l, + const Decimal& r, Decimal& result) { if (result.scale == l.scale && result.scale == r.scale) { @@ -379,8 +379,8 @@ namespace datatypes // with overflow check template<> - void Decimal::subtraction(const VDecimal& l, - const VDecimal& r, VDecimal& result) + void Decimal::subtraction(const Decimal& l, + const Decimal& r, Decimal& result) { SubtractionOverflowCheck subtractionOverflowCheck; MultiplicationOverflowCheck mulOverflowCheck; @@ -414,8 +414,8 @@ namespace datatypes // no overflow check template<> - void Decimal::division(const VDecimal& l, - const VDecimal& r, VDecimal& result) + void Decimal::division(const Decimal& l, + const Decimal& r, Decimal& result) { NoOverflowCheck noOverflowCheck; divisionExecute(l, r, result, noOverflowCheck, noOverflowCheck); @@ -423,8 +423,8 @@ namespace datatypes // With overflow check template<> - void Decimal::division(const VDecimal& l, - const VDecimal& r, VDecimal& result) + void Decimal::division(const Decimal& l, + const Decimal& r, Decimal& result) { DivisionOverflowCheck overflowCheck; MultiplicationOverflowCheck mulOverflowCheck; @@ -434,8 +434,8 @@ namespace datatypes // no overflow check // We rely on the zero check from ArithmeticOperator::execute template<> - void Decimal::division(const VDecimal& l, - const VDecimal& r, VDecimal& result) + void Decimal::division(const Decimal& l, + const Decimal& r, Decimal& result) { if (result.scale >= l.scale - r.scale) result.value = (int64_t)(( (l.value > 0 && r.value > 0) || (l.value < 0 && r.value < 0) ? @@ -449,8 +449,8 @@ namespace datatypes // With overflow check template<> - void Decimal::division(const VDecimal& l, - const VDecimal& r, VDecimal& result) + void Decimal::division(const Decimal& l, + const Decimal& r, Decimal& result) { DivisionOverflowCheck divisionOverflowCheck; @@ -469,8 +469,8 @@ namespace datatypes // no overflow check template<> - void Decimal::multiplication(const VDecimal& l, - const VDecimal& r, VDecimal& result) + void Decimal::multiplication(const Decimal& l, + const Decimal& r, Decimal& result) { MultiplicationNoOverflowCheck noOverflowCheck; multiplicationExecute(l, r, result, noOverflowCheck, noOverflowCheck); @@ -478,8 +478,8 @@ namespace datatypes // With overflow check template<> - void Decimal::multiplication(const VDecimal& l, - const VDecimal& r, VDecimal& result) + void Decimal::multiplication(const Decimal& l, + const Decimal& r, Decimal& result) { MultiplicationOverflowCheck mulOverflowCheck; multiplicationExecute(l, r, result, mulOverflowCheck, mulOverflowCheck); @@ -487,8 +487,8 @@ namespace datatypes // no overflow check template<> - void Decimal::multiplication(const VDecimal& l, - const VDecimal& r, VDecimal& result) + void Decimal::multiplication(const Decimal& l, + const Decimal& r, Decimal& result) { if (result.scale >= l.scale + r.scale) result.value = l.value * r.value * mcs_pow_10[result.scale - (l.scale + r.scale)]; @@ -500,8 +500,8 @@ namespace datatypes // With overflow check template<> - void Decimal::multiplication(const VDecimal& l, - const VDecimal& r, VDecimal& result) + void Decimal::multiplication(const Decimal& l, + const Decimal& r, Decimal& result) { MultiplicationOverflowCheck mulOverflowCheck; @@ -521,7 +521,7 @@ namespace datatypes } // Writes integer part of a Decimal using int128 argument provided - uint8_t VDecimal::writeIntPart(const int128_t& x, + uint8_t Decimal::writeIntPart(const int128_t& x, char* buf, const uint8_t buflen) const { @@ -552,7 +552,7 @@ namespace datatypes high = intPart / maxUint64divisor; break; default: - throw logging::QueryDataExcept("VDecimal::writeIntPart() bad scale", + throw logging::QueryDataExcept("Decimal::writeIntPart() bad scale", logging::formatErr); } @@ -560,14 +560,14 @@ namespace datatypes uint8_t written = p - buf; if (buflen <= written) { - throw logging::QueryDataExcept("VDecimal::writeIntPart() char buffer overflow.", + throw logging::QueryDataExcept("Decimal::writeIntPart() char buffer overflow.", logging::formatErr); } return written; } - uint8_t VDecimal::writeFractionalPart(const int128_t& x, + uint8_t Decimal::writeFractionalPart(const int128_t& x, char* buf, const uint8_t buflen) const { @@ -605,7 +605,7 @@ namespace datatypes // The method writes Decimal based on TSInt128 with scale provided. // It first writes sign, then extracts integer part // prints delimiter and then decimal part. - std::string VDecimal::toStringTSInt128WithScale() const + std::string Decimal::toStringTSInt128WithScale() const { char buf[Decimal::MAXLENGTH16BYTES]; uint8_t left = sizeof(buf); @@ -633,13 +633,13 @@ namespace datatypes uint8_t written = p - buf; if (sizeof(buf) <= written) { - throw logging::QueryDataExcept("VDecimal::toString() char buffer overflow.", + throw logging::QueryDataExcept("Decimal::toString() char buffer overflow.", logging::formatErr); } return std::string(buf); } - std::string VDecimal::toStringTSInt64() const + std::string Decimal::toStringTSInt64() const { char buf[Decimal::MAXLENGTH8BYTES]; // Need 19 digits maxium to hold a sum result of 18 digits decimal column. @@ -706,7 +706,7 @@ namespace datatypes } // Dispatcher method for toString() implementations - std::string VDecimal::toString(bool hasTSInt128) const + std::string Decimal::toString(bool hasTSInt128) const { // There must be no empty at this point though if (isNull()) @@ -730,7 +730,7 @@ namespace datatypes return std::to_string(value); } - std::ostream& operator<<(std::ostream& os, const VDecimal& dec) + std::ostream& operator<<(std::ostream& os, const Decimal& dec) { os << dec.toString(); return os; diff --git a/datatypes/mcs_decimal.h b/datatypes/mcs_decimal.h index 5b8e26c14..56050388d 100644 --- a/datatypes/mcs_decimal.h +++ b/datatypes/mcs_decimal.h @@ -26,11 +26,13 @@ #include "widedecimalutils.h" #include "mcs_int128.h" #include "mcs_float128.h" +#include "checks.h" +#include "branchpred.h" namespace datatypes { - class VDecimal; + class Decimal; } // A class by Fabio Fernandes pulled off of stackoverflow @@ -158,21 +160,16 @@ inline void getScaleDivisor(T& divisor, const int8_t scale) } } - -/** - @brief Contains subset of decimal related operations. - - Most of the methods are static to allow to call them from - the existing code. - The main purpose of the class is to collect methods for a - base Datatype class. -*/ -class Decimal +// @brief The class for Decimal related operations +// The class contains Decimal related operations are scale and +// precision aware. +// This class will inherit from: +// DecimalMeta class that stores scale and precision +// Storage classes TSInt128 and int64 +// !!! There are some static classes that will exists during transition period. +class Decimal: public TSInt128 { public: - Decimal() { }; - ~Decimal() { }; - static constexpr uint8_t MAXLENGTH16BYTES = TSInt128::maxLength(); static constexpr uint8_t MAXLENGTH8BYTES = 23; @@ -200,44 +197,44 @@ class Decimal static constexpr int128_t maxInt128 = (int128_t(0x7FFFFFFFFFFFFFFFLL) << 64) + 0xFFFFFFFFFFFFFFFFLL; /** - @brief Compares two VDecimal taking scale into account. + @brief Compares two Decimal taking scale into account. */ - static int compare(const VDecimal& l, const VDecimal& r); + static int compare(const Decimal& l, const Decimal& r); /** @brief Addition template that supports overflow check and two internal representations of decimal. */ template - static void addition(const VDecimal& l, - const VDecimal& r, - VDecimal& result); + static void addition(const Decimal& l, + const Decimal& r, + Decimal& result); /** @brief Subtraction template that supports overflow check and two internal representations of decimal. */ template - static void subtraction(const VDecimal& l, - const VDecimal& r, - VDecimal& result); + static void subtraction(const Decimal& l, + const Decimal& r, + Decimal& result); /** @brief Division template that supports overflow check and two internal representations of decimal. */ template - static void division(const VDecimal& l, - const VDecimal& r, - VDecimal& result); + static void division(const Decimal& l, + const Decimal& r, + Decimal& result); /** @brief Multiplication template that supports overflow check and two internal representations of decimal. */ template - static void multiplication(const VDecimal& l, - const VDecimal& r, - VDecimal& result); + static void multiplication(const Decimal& l, + const Decimal& r, + Decimal& result); /** @brief The method detects whether decimal type is wide @@ -249,85 +246,6 @@ class Decimal && precision <= INT128MAXPRECISION; } - /** - @brief The method converts a __float128 value to an int64_t. - */ - static inline int64_t getInt64FromFloat128(const __float128& value) - { - if (value > static_cast<__float128>(INT64_MAX)) - return INT64_MAX; - else if (value < static_cast<__float128>(INT64_MIN)) - return INT64_MIN; - - return static_cast(value); - } - - /** - @brief The method converts a __float128 value to an uint64_t. - */ - static inline uint64_t getUInt64FromFloat128(const __float128& value) - { - if (value > static_cast<__float128>(UINT64_MAX)) - return UINT64_MAX; - else if (value < 0) - return 0; - - return static_cast(value); - } - - /** - @brief The method converts a wide decimal value to an uint32_t. - */ - static inline uint32_t getUInt32FromWideDecimal(const int128_t& value) - { - if (value > static_cast(UINT32_MAX)) - return UINT32_MAX; - else if (value < 0) - return 0; - - return static_cast(value); - } - - /** - @brief The method converts a wide decimal value to an int32_t. - */ - static inline int32_t getInt32FromWideDecimal(const int128_t& value) - { - if (value > static_cast(INT32_MAX)) - return INT32_MAX; - else if (value < static_cast(INT32_MIN)) - return INT32_MIN; - - return static_cast(value); - } - - /** - @brief The method converts a wide decimal value to an uint64_t. - */ - static inline uint64_t getUInt64FromWideDecimal(const int128_t& value) - { - if (value > static_cast(UINT64_MAX)) - return UINT64_MAX; - else if (value < 0) - return 0; - - return static_cast(value); - } - - /** - @brief The method converts a wide decimal value to an int64_t, - saturating the value if necessary. - */ - static inline int64_t getInt64FromWideDecimal(const int128_t& value) - { - if (value > static_cast(INT64_MAX)) - return INT64_MAX; - else if (value < static_cast(INT64_MIN)) - return INT64_MIN; - - return static_cast(value); - } - /** @brief MDB increases scale by up to 4 digits calculating avg() */ @@ -340,7 +258,461 @@ class Decimal scale += (scaleAvailable >= MAXSCALEINC4AVG) ? MAXSCALEINC4AVG : scaleAvailable; precision += (precisionAvailable >= MAXSCALEINC4AVG) ? MAXSCALEINC4AVG : precisionAvailable; } -}; + + Decimal(): value(0), scale(0), precision(0) + { + } + + Decimal(int64_t val, int8_t s, uint8_t p, const int128_t &val128 = 0) : + TSInt128(val128), + value(val), + scale(s), + precision(p) + { } + + Decimal(int64_t unused, int8_t s, uint8_t p, const int128_t* val128Ptr) : + TSInt128(val128Ptr), + value(unused), + scale(s), + precision(p) + { } + + Decimal(const TSInt128& val128, int8_t s, uint8_t p) : + TSInt128(val128), + value(0), + scale(s), + precision(p) + { } + + + int decimalComp(const Decimal& d) const + { + lldiv_t d1 = lldiv(value, static_cast(mcs_pow_10[scale])); + lldiv_t d2 = lldiv(d.value, static_cast(mcs_pow_10[d.scale])); + + int ret = 0; + + if (d1.quot > d2.quot) + { + ret = 1; + } + else if (d1.quot < d2.quot) + { + ret = -1; + } + else + { + // rem carries the value's sign, but needs to be normalized. + int64_t s = scale - d.scale; + + if (s < 0) + { + if ((d1.rem * static_cast(mcs_pow_10[-s])) > d2.rem) + ret = 1; + else if ((d1.rem * static_cast(mcs_pow_10[-s])) < d2.rem) + ret = -1; + } + else + { + if (d1.rem > (d2.rem * static_cast(mcs_pow_10[s]))) + ret = 1; + else if (d1.rem < (d2.rem * static_cast(mcs_pow_10[s]))) + ret = -1; + } + } + + return ret; + } + + inline TSInt128 toTSInt128() const + { + return TSInt128(s128Value); + } + + inline TFloat128 toTFloat128() const + { + return TFloat128(s128Value); + } + + inline double toDouble() const + { + int128_t scaleDivisor; + getScaleDivisor(scaleDivisor, scale); + datatypes::TFloat128 tmpval((__float128) s128Value / scaleDivisor); + return static_cast(tmpval); + } + + inline operator double() const + { + return toDouble(); + } + + inline long double toLongDouble() const + { + datatypes::TFloat128 y(s128Value); + return static_cast(y); + } + + + // This method returns integral part as a TSInt128 and + // fractional part as a TFloat128 + inline std::pair getIntegralAndDividedFractional() const + { + int128_t scaleDivisor; + getScaleDivisor(scaleDivisor, scale); + return std::make_pair(TSInt128(s128Value / scaleDivisor), + TFloat128((__float128)(s128Value % scaleDivisor) / scaleDivisor)); + } + + // This method returns integral part as a TSInt128 and + // fractional part as a TFloat128 + inline std::pair getIntegralAndFractional() const + { + int128_t scaleDivisor; + getScaleDivisor(scaleDivisor, scale); + return std::make_pair(TSInt128(s128Value / scaleDivisor), + TSInt128(s128Value % scaleDivisor)); + } + + inline std::tuple getIntegralFractionalAndDivisor() const + { + int128_t scaleDivisor; + getScaleDivisor(scaleDivisor, scale); + return std::make_tuple(TSInt128(s128Value / scaleDivisor), + TSInt128(s128Value % scaleDivisor), + TSInt128(scaleDivisor)); + } + + inline TSInt128 getIntegralPart() const + { + int128_t scaleDivisor = 0; + if(LIKELY(utils::is_nonnegative(scale))) + { + return TSInt128(getIntegralPartNonNegativeScale(scaleDivisor)); + } + return TSInt128(getIntegralPartNegativeScale(scaleDivisor)); + } + + // !!! This is a very hevyweight rouding style + // Argument determines if it is a ceil + // rounding or not. 0 - ceil rounding + inline TSInt128 getRoundedIntegralPart(const uint8_t roundingFactor = 0) const + { + int128_t flooredScaleDivisor = 0; + int128_t roundedValue = getIntegralPartNonNegativeScale(flooredScaleDivisor); + int128_t ceiledScaleDivisor = (flooredScaleDivisor <= 10) ? 1 : (flooredScaleDivisor / 10); + int128_t leftO = (s128Value - roundedValue * flooredScaleDivisor) / ceiledScaleDivisor; + if (leftO > roundingFactor) + { + roundedValue++; + } + + return TSInt128(roundedValue); + } + + inline TSInt128 getPosNegRoundedIntegralPart(const uint8_t roundingFactor = 0) const + { + int128_t flooredScaleDivisor = 0; + int128_t roundedValue = getIntegralPartNonNegativeScale(flooredScaleDivisor); + int128_t ceiledScaleDivisor = (flooredScaleDivisor <= 10) ? 1 : (flooredScaleDivisor / 10); + int128_t leftO = (s128Value - roundedValue * flooredScaleDivisor) / ceiledScaleDivisor; + if (utils::is_nonnegative(roundedValue) && leftO > roundingFactor) + { + roundedValue++; + } + if (utils::is_negative(roundedValue) && leftO < -roundingFactor) + { + roundedValue--; + } + + return TSInt128(roundedValue); + } + + // MOD operator for an integer divisor to be used + // for integer rhs + inline TSInt128 operator%(const TSInt128& div) const + { + if (!isScaled()) + { + return s128Value % div.getValue(); + } + // Scale the value and calculate + // (LHS.value % RHS.value) * LHS.scaleMultiplier + LHS.scale_div_remainder + auto integralFractionalDivisor = getIntegralFractionalAndDivisor(); + return (std::get<0>(integralFractionalDivisor) % div.getValue()) * std::get<2>(integralFractionalDivisor) + std::get<1>(integralFractionalDivisor); + } + + bool operator==(const Decimal& rhs) const + { + if (precision > datatypes::INT64MAXPRECISION && + rhs.precision > datatypes::INT64MAXPRECISION) + { + if (scale == rhs.scale) + return s128Value == rhs.s128Value; + else + return (datatypes::Decimal::compare(*this, rhs) == 0); + } + else if (precision > datatypes::INT64MAXPRECISION && + rhs.precision <= datatypes::INT64MAXPRECISION) + { + const_cast(rhs).s128Value = rhs.value; + + if (scale == rhs.scale) + return s128Value == rhs.s128Value; + else + return (datatypes::Decimal::compare(*this, rhs) == 0); + } + else if (precision <= datatypes::INT64MAXPRECISION && + rhs.precision > datatypes::INT64MAXPRECISION) + { + if (scale == rhs.scale) + return (int128_t) value == rhs.s128Value; + else + return (datatypes::Decimal::compare(Decimal(0, scale, precision, (int128_t) value), rhs) == 0); + } + else + { + if (scale == rhs.scale) + return value == rhs.value; + else + return (decimalComp(rhs) == 0); + } + } + + bool operator>(const Decimal& rhs) const + { + if (precision > datatypes::INT64MAXPRECISION && + rhs.precision > datatypes::INT64MAXPRECISION) + { + if (scale == rhs.scale) + return s128Value > rhs.s128Value; + else + return (datatypes::Decimal::compare(*this, rhs) > 0); + } + else if (precision > datatypes::INT64MAXPRECISION && + rhs.precision <= datatypes::INT64MAXPRECISION) + { + Decimal rhstmp(0, rhs.scale, rhs.precision, (int128_t) rhs.value); + + if (scale == rhstmp.scale) + return s128Value > rhstmp.s128Value; + else + return (datatypes::Decimal::compare(*this, rhstmp) > 0); + } + else if (precision <= datatypes::INT64MAXPRECISION && + rhs.precision > datatypes::INT64MAXPRECISION) + { + if (scale == rhs.scale) + return (int128_t) value > rhs.s128Value; + else + return (datatypes::Decimal::compare(Decimal(0, scale, precision, (int128_t) value), rhs) > 0); + } + else + { + if (scale == rhs.scale) + return value > rhs.value; + else + return (decimalComp(rhs) > 0); + } + } + + bool operator<(const Decimal& rhs) const + { + if (precision > datatypes::INT64MAXPRECISION && + rhs.precision > datatypes::INT64MAXPRECISION) + { + if (scale == rhs.scale) + return s128Value < rhs.s128Value; + else + return (datatypes::Decimal::compare(*this, rhs) < 0); + } + else if (precision > datatypes::INT64MAXPRECISION && + rhs.precision <= datatypes::INT64MAXPRECISION) + { + Decimal rhstmp(0, rhs.scale, rhs.precision, (int128_t) rhs.value); + + if (scale == rhstmp.scale) + return s128Value < rhstmp.s128Value; + else + return (datatypes::Decimal::compare(*this, rhstmp) < 0); + } + else if (precision <= datatypes::INT64MAXPRECISION && + rhs.precision > datatypes::INT64MAXPRECISION) + { + if (scale == rhs.scale) + return (int128_t) value < rhs.s128Value; + else + return (datatypes::Decimal::compare(Decimal(0, scale, precision, (int128_t) value), rhs) < 0); + } + else + { + if (scale == rhs.scale) + return value < rhs.value; + else + return (decimalComp(rhs) < 0); + } + } + + bool operator>=(const Decimal& rhs) const + { + if (precision > datatypes::INT64MAXPRECISION && + rhs.precision > datatypes::INT64MAXPRECISION) + { + if (scale == rhs.scale) + return s128Value >= rhs.s128Value; + else + return (datatypes::Decimal::compare(*this, rhs) >= 0); + } + else if (precision > datatypes::INT64MAXPRECISION && + rhs.precision <= datatypes::INT64MAXPRECISION) + { + Decimal rhstmp(0, rhs.scale, rhs.precision, (int128_t) rhs.value); + + if (scale == rhstmp.scale) + return s128Value >= rhstmp.s128Value; + else + return (datatypes::Decimal::compare(*this, rhstmp) >= 0); + } + else if (precision <= datatypes::INT64MAXPRECISION && + rhs.precision > datatypes::INT64MAXPRECISION) + { + if (scale == rhs.scale) + return (int128_t) value >= rhs.s128Value; + else + return (datatypes::Decimal::compare(Decimal(0, scale, precision, (int128_t) value), rhs) >= 0); + } + else + { + if (scale == rhs.scale) + return value >= rhs.value; + else + return (decimalComp(rhs) >= 0); + } + } + + bool operator<=(const Decimal& rhs) const + { + if (precision > datatypes::INT64MAXPRECISION && + rhs.precision > datatypes::INT64MAXPRECISION) + { + if (scale == rhs.scale) + return s128Value <= rhs.s128Value; + else + return (datatypes::Decimal::compare(*this, rhs) <= 0); + } + else if (precision > datatypes::INT64MAXPRECISION && + rhs.precision <= datatypes::INT64MAXPRECISION) + { + Decimal rhstmp(0, rhs.scale, rhs.precision, (int128_t) rhs.value); + + if (scale == rhstmp.scale) + return s128Value <= rhstmp.s128Value; + else + return (datatypes::Decimal::compare(*this, rhstmp) <= 0); + } + else if (precision <= datatypes::INT64MAXPRECISION && + rhs.precision > datatypes::INT64MAXPRECISION) + { + if (scale == rhs.scale) + return (int128_t) value <= rhs.s128Value; + else + return (datatypes::Decimal::compare(Decimal(0, scale, precision, (int128_t) value), rhs) <= 0); + } + else + { + if (scale == rhs.scale) + return value <= rhs.value; + else + return (decimalComp(rhs) <= 0); + } + } + + bool operator!=(const Decimal& rhs) const + { + if (precision > datatypes::INT64MAXPRECISION && + rhs.precision > datatypes::INT64MAXPRECISION) + { + if (scale == rhs.scale) + return s128Value != rhs.s128Value; + else + return (datatypes::Decimal::compare(*this, rhs) != 0); + } + else if (precision > datatypes::INT64MAXPRECISION && + rhs.precision <= datatypes::INT64MAXPRECISION) + { + Decimal rhstmp(0, rhs.scale, rhs.precision, (int128_t) rhs.value); + + if (scale == rhstmp.scale) + return s128Value != rhstmp.s128Value; + else + return (datatypes::Decimal::compare(*this, rhstmp) != 0); + } + else if (precision <= datatypes::INT64MAXPRECISION && + rhs.precision > datatypes::INT64MAXPRECISION) + { + if (scale == rhs.scale) + return (int128_t) value != rhs.s128Value; + else + return (datatypes::Decimal::compare(Decimal(0, scale, precision, (int128_t) value), rhs) != 0); + } + else + { + if (scale == rhs.scale) + return value != rhs.value; + else + return (decimalComp(rhs) != 0); + } + } + + inline bool isTSInt128ByPrecision() const + { + return precision > INT64MAXPRECISION + && precision <= INT128MAXPRECISION; + } + + inline bool isScaled() const + { + return scale != 0; + } + + // hasTSInt128 explicitly tells to print int128 out in cases + // where precision can't detect decimal type properly, e.g. + // DECIMAL(10)/DECIMAL(38) + std::string toString(bool hasTSInt128 = false) const; + friend std::ostream& operator<<(std::ostream& os, const Decimal& dec); + + int64_t value; + int8_t scale; // 0~38 + uint8_t precision; // 1~38 + + // STRICTLY for unit tests!!! + void setTSInt64Value(const int64_t x) { value = x; } + void setTSInt128Value(const int128_t& x) { s128Value = x; } + void setScale(const uint8_t x) { scale = x; } + + private: + uint8_t writeIntPart(const int128_t& x, + char* buf, + const uint8_t buflen) const; + uint8_t writeFractionalPart(const int128_t& x, + char* buf, + const uint8_t buflen) const; + std::string toStringTSInt128WithScale() const; + std::string toStringTSInt64() const; + + inline int128_t getIntegralPartNonNegativeScale(int128_t& scaleDivisor) const + { + getScaleDivisor(scaleDivisor, scale); + return s128Value / scaleDivisor; + } + + inline int128_t getIntegralPartNegativeScale(int128_t& scaleDivisor) const + { + getScaleDivisor(scaleDivisor, -scale); + // Calls for overflow check + return s128Value * scaleDivisor; + } +}; //end of Decimal /** @brief The structure contains an overflow check for int128 @@ -480,330 +852,5 @@ struct NoOverflowCheck { } }; - -/** - * @brief VDecimal type - * - */ -class VDecimal: public TSInt128 -{ - public: - VDecimal(): value(0), scale(0), precision(0) - { - } - - VDecimal(int64_t val, int8_t s, uint8_t p, const int128_t &val128 = 0) : - TSInt128(val128), - value(val), - scale(s), - precision(p) - { } - - VDecimal(int64_t unused, int8_t s, uint8_t p, const int128_t* val128Ptr) : - TSInt128(val128Ptr), - value(unused), - scale(s), - precision(p) - { } - - - int decimalComp(const VDecimal& d) const - { - lldiv_t d1 = lldiv(value, static_cast(mcs_pow_10[scale])); - lldiv_t d2 = lldiv(d.value, static_cast(mcs_pow_10[d.scale])); - - int ret = 0; - - if (d1.quot > d2.quot) - { - ret = 1; - } - else if (d1.quot < d2.quot) - { - ret = -1; - } - else - { - // rem carries the value's sign, but needs to be normalized. - int64_t s = scale - d.scale; - - if (s < 0) - { - if ((d1.rem * static_cast(mcs_pow_10[-s])) > d2.rem) - ret = 1; - else if ((d1.rem * static_cast(mcs_pow_10[-s])) < d2.rem) - ret = -1; - } - else - { - if (d1.rem > (d2.rem * static_cast(mcs_pow_10[s]))) - ret = 1; - else if (d1.rem < (d2.rem * static_cast(mcs_pow_10[s]))) - ret = -1; - } - } - - return ret; - } - - inline TSInt128 toTSInt128() const - { - return TSInt128(s128Value); - } - - inline TFloat128 toTFloat128() const - { - return TFloat128(s128Value); - } - - inline double toDouble() const - { - int128_t scaleDivisor; - getScaleDivisor(scaleDivisor, scale); - datatypes::TFloat128 tmpval((__float128) s128Value / scaleDivisor); - return static_cast(tmpval); - } - - inline operator double() const - { - return toDouble(); - } - - bool operator==(const VDecimal& rhs) const - { - if (isTSInt128ByPrecision() && rhs.isTSInt128ByPrecision()) - { - if (scale == rhs.scale) - return s128Value == rhs.s128Value; - else - return (datatypes::Decimal::compare(*this, rhs) == 0); - } - else if (isTSInt128ByPrecision() && !rhs.isTSInt128ByPrecision()) - { - const_cast(rhs).s128Value = rhs.value; - - if (scale == rhs.scale) - return s128Value == rhs.s128Value; - else - return (datatypes::Decimal::compare(*this, rhs) == 0); - } - else if (!isTSInt128ByPrecision() && rhs.isTSInt128ByPrecision()) - { - if (scale == rhs.scale) - return (int128_t) value == rhs.s128Value; - else - return (datatypes::Decimal::compare(VDecimal(0, scale, precision, (int128_t) value), rhs) == 0); - } - else - { - if (scale == rhs.scale) - return value == rhs.value; - else - return (decimalComp(rhs) == 0); - } - } - - bool operator>(const VDecimal& rhs) const - { - if (isTSInt128ByPrecision() && rhs.isTSInt128ByPrecision()) - { - if (scale == rhs.scale) - return s128Value > rhs.s128Value; - else - return (datatypes::Decimal::compare(*this, rhs) > 0); - } - else if (isTSInt128ByPrecision() && !rhs.isTSInt128ByPrecision()) - { - VDecimal rhstmp(0, rhs.scale, rhs.precision, (int128_t) rhs.value); - - if (scale == rhstmp.scale) - return s128Value > rhstmp.s128Value; - else - return (datatypes::Decimal::compare(*this, rhstmp) > 0); - } - else if (!isTSInt128ByPrecision() && rhs.isTSInt128ByPrecision()) - { - if (scale == rhs.scale) - return (int128_t) value > rhs.s128Value; - else - return (datatypes::Decimal::compare(VDecimal(0, scale, precision, (int128_t) value), rhs) > 0); - } - else - { - if (scale == rhs.scale) - return value > rhs.value; - else - return (decimalComp(rhs) > 0); - } - } - - bool operator<(const VDecimal& rhs) const - { - if (isTSInt128ByPrecision() && rhs.isTSInt128ByPrecision()) - { - if (scale == rhs.scale) - return s128Value < rhs.s128Value; - else - return (datatypes::Decimal::compare(*this, rhs) < 0); - } - else if (isTSInt128ByPrecision() && !rhs.isTSInt128ByPrecision()) - { - VDecimal rhstmp(0, rhs.scale, rhs.precision, (int128_t) rhs.value); - - if (scale == rhstmp.scale) - return s128Value < rhstmp.s128Value; - else - return (datatypes::Decimal::compare(*this, rhstmp) < 0); - } - else if (!isTSInt128ByPrecision() && rhs.isTSInt128ByPrecision()) - { - if (scale == rhs.scale) - return (int128_t) value < rhs.s128Value; - else - return (datatypes::Decimal::compare(VDecimal(0, scale, precision, (int128_t) value), rhs) < 0); - } - else - { - if (scale == rhs.scale) - return value < rhs.value; - else - return (decimalComp(rhs) < 0); - } - } - - bool operator>=(const VDecimal& rhs) const - { - if (isTSInt128ByPrecision() && rhs.isTSInt128ByPrecision()) - { - if (scale == rhs.scale) - return s128Value >= rhs.s128Value; - else - return (datatypes::Decimal::compare(*this, rhs) >= 0); - } - else if (isTSInt128ByPrecision() && !rhs.isTSInt128ByPrecision()) - { - VDecimal rhstmp(0, rhs.scale, rhs.precision, (int128_t) rhs.value); - - if (scale == rhstmp.scale) - return s128Value >= rhstmp.s128Value; - else - return (datatypes::Decimal::compare(*this, rhstmp) >= 0); - } - else if (!isTSInt128ByPrecision() && rhs.isTSInt128ByPrecision()) - { - if (scale == rhs.scale) - return (int128_t) value >= rhs.s128Value; - else - return (datatypes::Decimal::compare(VDecimal(0, scale, precision, (int128_t) value), rhs) >= 0); - } - else - { - if (scale == rhs.scale) - return value >= rhs.value; - else - return (decimalComp(rhs) >= 0); - } - } - - bool operator<=(const VDecimal& rhs) const - { - if (isTSInt128ByPrecision() && rhs.isTSInt128ByPrecision()) - { - if (scale == rhs.scale) - return s128Value <= rhs.s128Value; - else - return (datatypes::Decimal::compare(*this, rhs) <= 0); - } - else if (isTSInt128ByPrecision() && !rhs.isTSInt128ByPrecision()) - { - VDecimal rhstmp(0, rhs.scale, rhs.precision, (int128_t) rhs.value); - - if (scale == rhstmp.scale) - return s128Value <= rhstmp.s128Value; - else - return (datatypes::Decimal::compare(*this, rhstmp) <= 0); - } - else if (!isTSInt128ByPrecision() && rhs.isTSInt128ByPrecision()) - { - if (scale == rhs.scale) - return (int128_t) value <= rhs.s128Value; - else - return (datatypes::Decimal::compare(VDecimal(0, scale, precision, (int128_t) value), rhs) <= 0); - } - else - { - if (scale == rhs.scale) - return value <= rhs.value; - else - return (decimalComp(rhs) <= 0); - } - } - - bool operator!=(const VDecimal& rhs) const - { - if (isTSInt128ByPrecision() && rhs.isTSInt128ByPrecision()) - { - if (scale == rhs.scale) - return s128Value != rhs.s128Value; - else - return (datatypes::Decimal::compare(*this, rhs) != 0); - } - else if (isTSInt128ByPrecision() && !rhs.isTSInt128ByPrecision()) - { - VDecimal rhstmp(0, rhs.scale, rhs.precision, (int128_t) rhs.value); - - if (scale == rhstmp.scale) - return s128Value != rhstmp.s128Value; - else - return (datatypes::Decimal::compare(*this, rhstmp) != 0); - } - else if (!isTSInt128ByPrecision() && rhs.isTSInt128ByPrecision()) - { - if (scale == rhs.scale) - return (int128_t) value != rhs.s128Value; - else - return (datatypes::Decimal::compare(VDecimal(0, scale, precision, (int128_t) value), rhs) != 0); - } - else - { - if (scale == rhs.scale) - return value != rhs.value; - else - return (decimalComp(rhs) != 0); - } - } - - inline bool isTSInt128ByPrecision() const - { - return precision > INT64MAXPRECISION - && precision <= INT128MAXPRECISION; - } - // hasTSInt128 explicitly tells to print int128 out in cases - // where precision can't detect decimal type properly, e.g. - // DECIMAL(10)/DECIMAL(38) - std::string toString(bool hasTSInt128 = false) const; - friend std::ostream& operator<<(std::ostream& os, const VDecimal& dec); - - int64_t value; - int8_t scale; // 0~38 - uint8_t precision; // 1~38 - - // STRICTLY for unit tests!!! - void setTSInt64Value(const int64_t x) { value = x; } - void setTSInt128Value(const int128_t& x) { s128Value = x; } - void setScale(const uint8_t x) { scale = x; } - -private: - uint8_t writeIntPart(const int128_t& x, - char* buf, - const uint8_t buflen) const; - uint8_t writeFractionalPart(const int128_t& x, - char* buf, - const uint8_t buflen) const; - std::string toStringTSInt128WithScale() const; - std::string toStringTSInt64() const; - -}; - } //end of namespace #endif diff --git a/datatypes/mcs_float128.h b/datatypes/mcs_float128.h index 825858804..52c12c150 100644 --- a/datatypes/mcs_float128.h +++ b/datatypes/mcs_float128.h @@ -25,9 +25,28 @@ namespace datatypes { -//class TSInt128; +class TSInt128; +class TFloat128; using int128_t = __int128; +// Type defined integral types +// for templates +template +struct get_integral_type { + typedef T type; +}; + +template<> +struct get_integral_type{ + typedef __float128 type; +}; + +template<> +struct get_integral_type{ + typedef int128_t type; +}; + + class TFloat128 { public: @@ -66,6 +85,40 @@ class TFloat128 return toLongDouble(); } + inline int64_t toTSInt64() const + { + if (value > static_cast<__float128>(INT64_MAX)) + return INT64_MAX; + else if (value < static_cast<__float128>(INT64_MIN)) + return INT64_MIN; + + return static_cast(value); + } + + inline operator int64_t() const + { + return toTSInt64(); + } + + inline int64_t toTUInt64() const + { + if (value > static_cast<__float128>(UINT64_MAX)) + return UINT64_MAX; + else if (value < 0) + return 0; + + return static_cast(value); + } + + inline operator uint64_t() const + { + return toTUInt64(); + } + + inline TFloat128 operator+(const TFloat128& rhs) const + { + return TFloat128(value + rhs.value); + } inline long double toLongDouble() const { diff --git a/datatypes/mcs_int128.cpp b/datatypes/mcs_int128.cpp index 0c488c40f..fb6df19fd 100644 --- a/datatypes/mcs_int128.cpp +++ b/datatypes/mcs_int128.cpp @@ -117,50 +117,5 @@ namespace datatypes return os; } - // The method converts a wide decimal s128Value to an int64_t, - // saturating the s128Value if necessary. - inline int64_t TSInt128::getInt64FromWideDecimal() - { - if (s128Value > static_cast(INT64_MAX)) - return INT64_MAX; - else if (s128Value < static_cast(INT64_MIN)) - return INT64_MIN; - - return static_cast(s128Value); - } - - // The method converts a wide decimal s128Value to an uint32_t. - inline uint32_t TSInt128::getUInt32FromWideDecimal() - { - if (s128Value > static_cast(UINT32_MAX)) - return UINT32_MAX; - else if (s128Value < 0) - return 0; - - return static_cast(s128Value); - } - - // The method converts a wide decimal s128Value to an uint64_t. - inline uint64_t TSInt128::getUInt64FromWideDecimal() - { - if (s128Value > static_cast(UINT64_MAX)) - return UINT64_MAX; - else if (s128Value < 0) - return 0; - - return static_cast(s128Value); - } - - // The method converts a wide decimal s128Value to an int32_t. - inline int32_t TSInt128::getInt32FromWideDecimal() - { - if (s128Value > static_cast(INT32_MAX)) - return INT32_MAX; - else if (s128Value < static_cast(INT32_MIN)) - return INT32_MIN; - - return static_cast(s128Value); - } - } // end of namespace datatypes // vim:ts=2 sw=2: diff --git a/datatypes/mcs_int128.h b/datatypes/mcs_int128.h index c458589d2..291114e4d 100644 --- a/datatypes/mcs_int128.h +++ b/datatypes/mcs_int128.h @@ -200,16 +200,81 @@ class TSInt128 return static_cast(s128Value); } + inline operator int32_t() const + { + if (s128Value > static_cast(INT32_MAX)) + return INT32_MAX; + if (s128Value < static_cast(INT32_MIN)) + return INT32_MIN; + + return static_cast(s128Value); + } + + inline operator uint32_t() const + { + if (s128Value > static_cast(UINT32_MAX)) + return UINT32_MAX; + if (s128Value < 0) + return 0; + + return static_cast(s128Value); + } + + inline operator int64_t() const + { + if (s128Value > static_cast(INT64_MAX)) + return INT64_MAX; + if (s128Value < static_cast(INT64_MIN)) + return INT64_MIN; + + return static_cast(s128Value); + } + + inline operator uint64_t() const + { + if (s128Value > static_cast(UINT64_MAX)) + return UINT64_MAX; + if (s128Value < 0) + return 0; + + return static_cast(s128Value); + } + inline operator TFloat128() const { return toTFloat128(); } + inline TSInt128 operator%(const int64_t& rhs) const + { + return TSInt128(s128Value % rhs); + } + + inline TSInt128 operator%(const int128_t& rhs) const + { + return TSInt128(s128Value % rhs); + } + + inline TSInt128 operator*(const TSInt128& rhs) const + { + return TSInt128(s128Value * rhs.s128Value); + } + + inline TSInt128 operator+(const TSInt128& rhs) const + { + return TSInt128(s128Value + rhs.s128Value); + } + inline TFloat128 toTFloat128() const { return TFloat128(s128Value); } + inline const int128_t& getValue() const + { + return s128Value; + } + // print int128_t parts represented as PODs uint8_t printPodParts(char* buf, const int128_t& high, @@ -226,19 +291,6 @@ class TSInt128 friend std::ostream& operator<<(std::ostream& os, const TSInt128& x); - // The method converts a wide decimal s128Value to an int64_t, - // saturating the s128Value if necessary. - inline int64_t getInt64FromWideDecimal(); - - // The method converts a wide decimal s128Value to an uint32_t. - inline uint32_t getUInt32FromWideDecimal(); - - // The method converts a wide decimal s128Value to an uint64_t. - inline uint64_t getUInt64FromWideDecimal(); - - // The method converts a wide decimal s128Value to an int32_t. - inline int32_t getInt32FromWideDecimal(); - int128_t s128Value; }; // end of class diff --git a/dbcon/execplan/simplecolumn_decimal.h b/dbcon/execplan/simplecolumn_decimal.h index 4e78607cf..accce199a 100644 --- a/dbcon/execplan/simplecolumn_decimal.h +++ b/dbcon/execplan/simplecolumn_decimal.h @@ -153,7 +153,7 @@ void SimpleColumn_Decimal::setNullVal() template inline const std::string& SimpleColumn_Decimal:: getStrVal(rowgroup::Row& row, bool& isNull) { - datatypes::VDecimal dec((int64_t)row.getIntField(fInputIndex), + datatypes::Decimal dec((int64_t)row.getIntField(fInputIndex), fResultType.scale, fResultType.precision); fResult.strVal = dec.toString(); diff --git a/dbcon/execplan/treenode.h b/dbcon/execplan/treenode.h index 113aa3970..9017f562b 100644 --- a/dbcon/execplan/treenode.h +++ b/dbcon/execplan/treenode.h @@ -55,24 +55,7 @@ namespace execplan { typedef execplan::CalpontSystemCatalog::ColType Type; - - -class IDB_Decimal: public datatypes::VDecimal -{ -public: - IDB_Decimal() = default; - IDB_Decimal(int64_t val, int8_t s, uint8_t p, const int128_t &val128 = 0) : - VDecimal(val, s, p, val128) {} - - inline void operator=(const datatypes::TSInt128& rhs) - { - value = 0; scale = 0; precision = 0; - datatypes::TSInt128::operator=(rhs); - } -}; - - -typedef IDB_Decimal CNX_Decimal; +typedef datatypes::Decimal IDB_Decimal; /** * @brief IDB_Regex struct @@ -728,13 +711,7 @@ inline int64_t TreeNode::getIntVal() { if (fResultType.colWidth == datatypes::MAXDECIMALWIDTH) { - int128_t scaleDivisor; - - datatypes::getScaleDivisor(scaleDivisor, fResult.decimalVal.scale); - - int128_t tmpval = fResult.decimalVal.s128Value / scaleDivisor; - - return datatypes::Decimal::getInt64FromWideDecimal(tmpval); + return static_cast(fResult.decimalVal.getIntegralPart()); } else { diff --git a/dbcon/joblist/groupconcat.cpp b/dbcon/joblist/groupconcat.cpp index a1d0a28ae..d0dd69763 100644 --- a/dbcon/joblist/groupconcat.cpp +++ b/dbcon/joblist/groupconcat.cpp @@ -460,7 +460,7 @@ void GroupConcator::outputRow(std::ostringstream& oss, const rowgroup::Row& row) if (LIKELY(row.getColumnWidth(*i) == datatypes::MAXDECIMALWIDTH)) { - datatypes::VDecimal dec(0, + datatypes::Decimal dec(0, scale, row.getPrecision(*i), row.getBinaryField(*i)); diff --git a/dbcon/joblist/tupleunion.cpp b/dbcon/joblist/tupleunion.cpp index 8bd445b1e..5388f8471 100644 --- a/dbcon/joblist/tupleunion.cpp +++ b/dbcon/joblist/tupleunion.cpp @@ -1188,7 +1188,7 @@ dec4: /* have to pick a scale to use for the double. using 5.. { if (LIKELY(isInputWide)) { - datatypes::VDecimal dec(0, + datatypes::Decimal dec(0, in.getScale(i), in.getPrecision(i), val128); @@ -1196,7 +1196,7 @@ dec4: /* have to pick a scale to use for the double. using 5.. } else { - datatypes::VDecimal dec(val, + datatypes::Decimal dec(val, in.getScale(i), in.getPrecision(i)); out->setStringField(dec.toString(), i); diff --git a/dbcon/mysql/ha_mcs_datatype.h b/dbcon/mysql/ha_mcs_datatype.h index d3bae935f..8d4d739e1 100644 --- a/dbcon/mysql/ha_mcs_datatype.h +++ b/dbcon/mysql/ha_mcs_datatype.h @@ -161,13 +161,13 @@ public: return m_field->store(static_cast(dl)); } - int store_decimal64(const datatypes::VDecimal& dec) override + int store_decimal64(const datatypes::Decimal& dec) override { std::string decAsAStr = dec.toString(); return m_field->store(decAsAStr.c_str(), decAsAStr.length(), m_field->charset()); } - int store_decimal128(const datatypes::VDecimal& dec) override + int store_decimal128(const datatypes::Decimal& dec) override { std::string decAsAStr = dec.toString(true); return m_field->store(decAsAStr.c_str(), decAsAStr.length(), m_field->charset()); diff --git a/tests/mcs_decimal-tests.cpp b/tests/mcs_decimal-tests.cpp index cb2c26eb8..d0e14aa1b 100644 --- a/tests/mcs_decimal-tests.cpp +++ b/tests/mcs_decimal-tests.cpp @@ -908,7 +908,7 @@ TEST(Decimal, DecimalToStringCheckScale0) int precision = 38; int scale = 0; res = 0; - datatypes::VDecimal dec(0, scale, precision, res); + datatypes::Decimal dec(0, scale, precision, res); // test simple values expected = "0"; @@ -957,7 +957,7 @@ TEST(Decimal, DecimalToStringCheckScale10) int precision = 38; int scale = 10; res = 0; - datatypes::VDecimal dec(0, scale, precision, res); + datatypes::Decimal dec(0, scale, precision, res); // test simple values expected = "0.0000000000"; @@ -1029,7 +1029,7 @@ TEST(Decimal, DecimalToStringCheckScale38) int precision = 38; int scale = 38; res = 0; - datatypes::VDecimal dec(0, scale, precision, res); + datatypes::Decimal dec(0, scale, precision, res); // test simple values res = 0; @@ -1089,7 +1089,7 @@ TEST(Decimal, DecimalToStringCheckScale37) int precision = 38; int scale = 37; res = 0; - datatypes::VDecimal dec(0, scale, precision, res); + datatypes::Decimal dec(0, scale, precision, res); // test simple values res = 0; diff --git a/utils/funcexp/func_cast.cpp b/utils/funcexp/func_cast.cpp index 928357469..d5717f59b 100644 --- a/utils/funcexp/func_cast.cpp +++ b/utils/funcexp/func_cast.cpp @@ -188,22 +188,7 @@ int64_t Func_cast_signed::getIntVal(Row& row, if (parm[0]->data()->resultType().colWidth == datatypes::MAXDECIMALWIDTH) { - int128_t scaleDivisor, scaleDivisor2; - - datatypes::getScaleDivisor(scaleDivisor, d.scale); - - scaleDivisor2 = (scaleDivisor <= 10) ? 1 : (scaleDivisor / 10); - - int128_t tmpval = d.s128Value / scaleDivisor; - int128_t lefto = (d.s128Value - tmpval * scaleDivisor) / scaleDivisor2; - - if (tmpval >= 0 && lefto > 4) - tmpval++; - - if (tmpval < 0 && lefto < -4) - tmpval--; - - return datatypes::Decimal::getInt64FromWideDecimal(tmpval); + return static_cast(d.getPosNegRoundedIntegralPart(4)); } else { @@ -1206,13 +1191,7 @@ int64_t Func_cast_decimal::getIntVal(Row& row, if (decimal.isTSInt128ByPrecision()) { - int128_t scaleDivisor; - - datatypes::getScaleDivisor(scaleDivisor, decimal.scale); - - int128_t tmpval = decimal.s128Value / scaleDivisor; - - return datatypes::Decimal::getInt64FromWideDecimal(tmpval); + return static_cast(decimal.getIntegralPart()); } return (int64_t) decimal.value / helpers::powerOf10_c[decimal.scale]; diff --git a/utils/funcexp/func_ceil.cpp b/utils/funcexp/func_ceil.cpp index 687f50c85..656db9cd4 100644 --- a/utils/funcexp/func_ceil.cpp +++ b/utils/funcexp/func_ceil.cpp @@ -99,17 +99,7 @@ int64_t Func_ceil::getIntVal(Row& row, if (op_ct.colWidth == datatypes::MAXDECIMALWIDTH) { - int128_t tmp = d.s128Value; - int128_t scaleDivisor; - datatypes::getScaleDivisor(scaleDivisor, d.scale); - d.s128Value /= scaleDivisor; - - // Add 1 if this is a positive number and there were values to the right of the - // decimal point so that we return the largest integer value not less than X. - if ((tmp - (d.s128Value * scaleDivisor)) > 0) - d.s128Value += 1; - - ret = datatypes::Decimal::getInt64FromWideDecimal(d.s128Value); + ret = static_cast(d.getRoundedIntegralPart()); } else { @@ -252,17 +242,7 @@ uint64_t Func_ceil::getUintVal(Row& row, if (op_ct.colWidth == datatypes::MAXDECIMALWIDTH) { - int128_t tmp = d.s128Value; - int128_t scaleDivisor; - datatypes::getScaleDivisor(scaleDivisor, d.scale); - d.s128Value /= scaleDivisor; - - // Add 1 if this is a positive number and there were values to the right of the - // decimal point so that we return the largest integer value not less than X. - if ((tmp - (d.s128Value * scaleDivisor)) > 0) - d.s128Value += 1; - - ret = datatypes::Decimal::getUInt64FromWideDecimal(d.s128Value); + ret = static_cast(d.getRoundedIntegralPart()); } else { @@ -548,6 +528,8 @@ IDB_Decimal Func_ceil::getDecimalVal(Row& row, bool& isNull, CalpontSystemCatalog::ColType& op_ct) { + // Questionable approach. I believe we should use pointer here + // and call an appropriate ctor IDB_Decimal ret; switch (op_ct.colDataType) @@ -583,15 +565,9 @@ IDB_Decimal Func_ceil::getDecimalVal(Row& row, if (op_ct.colWidth == datatypes::MAXDECIMALWIDTH) { - int128_t tmp = ret.s128Value; - int128_t scaleDivisor; - datatypes::getScaleDivisor(scaleDivisor, ret.scale); - ret.s128Value /= scaleDivisor; - - // Add 1 if this is a positive number and there were values to the right of the - // decimal point so that we return the largest integer value not less than X. - if ((tmp - (ret.s128Value * scaleDivisor)) > 0) - ret.s128Value += 1; + ret = IDB_Decimal(ret.getRoundedIntegralPart(), + ret.scale, + ret.precision); } else { diff --git a/utils/funcexp/func_char.cpp b/utils/funcexp/func_char.cpp index 8387953e5..f0d2e1395 100644 --- a/utils/funcexp/func_char.cpp +++ b/utils/funcexp/func_char.cpp @@ -138,33 +138,22 @@ string Func_char::getStrVal(Row& row, { IDB_Decimal d = rc->getDecimalVal(row, isNull); + uint8_t roundingFactor = 4; if (ct.colWidth == datatypes::MAXDECIMALWIDTH) { if (d.s128Value < 0) return ""; - - int128_t scaleDivisor, scaleDivisor2; - - datatypes::getScaleDivisor(scaleDivisor, d.scale); - - scaleDivisor2 = (scaleDivisor <= 10) ? 1 : (scaleDivisor / 10); - - int128_t tmpval = d.s128Value / scaleDivisor; - int128_t lefto = (d.s128Value - tmpval * scaleDivisor) / scaleDivisor2; - - if (lefto > 4) - tmpval++; - - value = datatypes::Decimal::getInt32FromWideDecimal(tmpval); + // rounding by the left over + value = static_cast(d.getRoundedIntegralPart(roundingFactor)); } else { double dscale = d.scale; // get decimal and round up value = d.value / pow(10.0, dscale); - int lefto = (d.value - value * pow(10.0, dscale)) / pow(10.0, dscale - 1); + uint8_t lefto = (d.value - value * pow(10.0, dscale)) / pow(10.0, dscale - 1); - if ( lefto > 4 ) + if ( lefto > roundingFactor ) value++; } } diff --git a/utils/funcexp/func_elt.cpp b/utils/funcexp/func_elt.cpp index c9c811d6c..0388b4937 100644 --- a/utils/funcexp/func_elt.cpp +++ b/utils/funcexp/func_elt.cpp @@ -77,22 +77,7 @@ string Func_elt::getStrVal(rowgroup::Row& row, if (parm[0]->data()->resultType().colWidth == datatypes::MAXDECIMALWIDTH) { - int128_t scaleDivisor, scaleDivisor2; - - datatypes::getScaleDivisor(scaleDivisor, d.scale); - - scaleDivisor2 = (scaleDivisor <= 10) ? 1 : (scaleDivisor / 10); - - int128_t tmpval = d.s128Value / scaleDivisor; - int128_t lefto = (d.s128Value - tmpval * scaleDivisor) / scaleDivisor2; - - if (utils::is_nonnegative(tmpval) && lefto > 4) - tmpval++; - - if (utils::is_negative(tmpval) && lefto < -4) - tmpval--; - - number = datatypes::Decimal::getInt64FromWideDecimal(tmpval); + number = static_cast(d.getPosNegRoundedIntegralPart(4)); } else { diff --git a/utils/funcexp/func_floor.cpp b/utils/funcexp/func_floor.cpp index 8e87be745..170963541 100644 --- a/utils/funcexp/func_floor.cpp +++ b/utils/funcexp/func_floor.cpp @@ -160,7 +160,7 @@ int64_t Func_floor::getIntVal(Row& row, if (op_ct.colWidth == datatypes::MAXDECIMALWIDTH) { - ret = datatypes::Decimal::getInt64FromWideDecimal(tmp.s128Value); + ret = static_cast(tmp.toTSInt128()); } else { diff --git a/utils/funcexp/func_from_unixtime.cpp b/utils/funcexp/func_from_unixtime.cpp index ab88e39e0..287a95315 100644 --- a/utils/funcexp/func_from_unixtime.cpp +++ b/utils/funcexp/func_from_unixtime.cpp @@ -67,10 +67,9 @@ DateTime getDateTime(rowgroup::Row& row, if (parm[0]->data()->resultType().colWidth == datatypes::MAXDECIMALWIDTH) { - int128_t scaleDivisor; - datatypes::getScaleDivisor(scaleDivisor, dec.scale); - val = datatypes::Decimal::getInt64FromWideDecimal(dec.s128Value / scaleDivisor); - msec = datatypes::Decimal::getUInt32FromWideDecimal(dec.s128Value % scaleDivisor); + auto integralAndFractional = dec.getIntegralAndFractional(); + val = static_cast(integralAndFractional.first); + msec = static_cast(integralAndFractional.second); } else { diff --git a/utils/funcexp/func_makedate.cpp b/utils/funcexp/func_makedate.cpp index 64c2d5e5d..0158f51b4 100644 --- a/utils/funcexp/func_makedate.cpp +++ b/utils/funcexp/func_makedate.cpp @@ -72,22 +72,7 @@ uint64_t makedate(rowgroup::Row& row, if (parm[0]->data()->resultType().colWidth == datatypes::MAXDECIMALWIDTH) { - int128_t scaleDivisor, scaleDivisor2; - - datatypes::getScaleDivisor(scaleDivisor, d.scale); - - scaleDivisor2 = (scaleDivisor <= 10) ? 1 : (scaleDivisor / 10); - - int128_t tmpval = d.s128Value / scaleDivisor; - int128_t lefto = (d.s128Value - tmpval * scaleDivisor) / scaleDivisor2; - - if (tmpval >= 0 && lefto > 4) - tmpval++; - - if (tmpval < 0 && lefto < -4) - tmpval--; - - year = datatypes::Decimal::getInt64FromWideDecimal(tmpval); + year = static_cast(d.getPosNegRoundedIntegralPart(4)); } else { @@ -156,29 +141,14 @@ uint64_t makedate(rowgroup::Row& row, if (parm[1]->data()->resultType().colWidth == datatypes::MAXDECIMALWIDTH) { - int128_t scaleDivisor, scaleDivisor2; - - datatypes::getScaleDivisor(scaleDivisor, d.scale); - - scaleDivisor2 = (scaleDivisor <= 10) ? 1 : (scaleDivisor / 10); - - int128_t tmpval = d.s128Value / scaleDivisor; - int128_t lefto = (d.s128Value - tmpval * scaleDivisor) / scaleDivisor2; - - if (tmpval >= 0 && lefto > 4) - tmpval++; - - if (tmpval < 0 && lefto < -4) - tmpval--; - + int64_t tmpval = static_cast(d.getPosNegRoundedIntegralPart(4)); if (tmpval < 1) { isNull = true; return 0; } - int64_t tmpval64 = datatypes::Decimal::getInt64FromWideDecimal(tmpval); - dayofyear = helpers::intToString(tmpval64); + dayofyear = helpers::intToString(tmpval); } else { diff --git a/utils/funcexp/func_maketime.cpp b/utils/funcexp/func_maketime.cpp index 6e315c7ec..598577630 100644 --- a/utils/funcexp/func_maketime.cpp +++ b/utils/funcexp/func_maketime.cpp @@ -78,22 +78,7 @@ string Func_maketime::getStrVal(rowgroup::Row& row, if (parm[0]->data()->resultType().colWidth == datatypes::MAXDECIMALWIDTH) { - int128_t scaleDivisor, scaleDivisor2; - - datatypes::getScaleDivisor(scaleDivisor, d.scale); - - scaleDivisor2 = (scaleDivisor <= 10) ? 1 : (scaleDivisor / 10); - - int128_t tmpval = d.s128Value / scaleDivisor; - int128_t lefto = (d.s128Value - tmpval * scaleDivisor) / scaleDivisor2; - - if (tmpval >= 0 && lefto > 4) - tmpval++; - - if (tmpval < 0 && lefto < -4) - tmpval--; - - hour = datatypes::Decimal::getInt64FromWideDecimal(tmpval); + hour = static_cast(d.getPosNegRoundedIntegralPart(4)); } else { @@ -142,22 +127,7 @@ string Func_maketime::getStrVal(rowgroup::Row& row, if (parm[1]->data()->resultType().colWidth == datatypes::MAXDECIMALWIDTH) { - int128_t scaleDivisor, scaleDivisor2; - - datatypes::getScaleDivisor(scaleDivisor, d.scale); - - scaleDivisor2 = (scaleDivisor <= 10) ? 1 : (scaleDivisor / 10); - - int128_t tmpval = d.s128Value / scaleDivisor; - int128_t lefto = (d.s128Value - tmpval * scaleDivisor) / scaleDivisor2; - - if (tmpval >= 0 && lefto > 4) - tmpval++; - - if (tmpval < 0 && lefto < -4) - tmpval--; - - min = datatypes::Decimal::getInt64FromWideDecimal(tmpval); + min = static_cast(d.getPosNegRoundedIntegralPart(4)); } else { @@ -212,22 +182,7 @@ string Func_maketime::getStrVal(rowgroup::Row& row, if (parm[2]->data()->resultType().colWidth == datatypes::MAXDECIMALWIDTH) { - int128_t scaleDivisor, scaleDivisor2; - - datatypes::getScaleDivisor(scaleDivisor, d.scale); - - scaleDivisor2 = (scaleDivisor <= 10) ? 1 : (scaleDivisor / 10); - - int128_t tmpval = d.s128Value / scaleDivisor; - int128_t lefto = (d.s128Value - tmpval * scaleDivisor) / scaleDivisor2; - - if (tmpval >= 0 && lefto > 4) - tmpval++; - - if (tmpval < 0 && lefto < -4) - tmpval--; - - sec = datatypes::Decimal::getInt64FromWideDecimal(tmpval); + sec = static_cast(d.getPosNegRoundedIntegralPart(4)); } else { diff --git a/utils/funcexp/func_mod.cpp b/utils/funcexp/func_mod.cpp index f66bd42e7..26424176e 100644 --- a/utils/funcexp/func_mod.cpp +++ b/utils/funcexp/func_mod.cpp @@ -56,59 +56,40 @@ IDB_Decimal Func_mod::getDecimalVal(Row& row, bool& isNull, CalpontSystemCatalog::ColType& operationColType) { - IDB_Decimal retValue; - retValue.value = 0; - retValue.scale = 0; - if ( parm.size() < 2 ) { isNull = true; - return retValue; + return IDB_Decimal(); } if (parm[0]->data()->resultType().isWideDecimalType() || parm[1]->data()->resultType().isWideDecimalType()) { IDB_Decimal div = parm[1]->data()->getDecimalVal(row, isNull); - - int128_t divInt, dividendInt; - - if (parm[1]->data()->resultType().colWidth == datatypes::MAXDECIMALWIDTH) - divInt = div.s128Value; - else - divInt = div.value; - + int128_t divInt = (parm[1]->data()->resultType().colWidth == datatypes::MAXDECIMALWIDTH) ? div.s128Value : div.value; + if (divInt == 0) { isNull = true; - return retValue; + return IDB_Decimal(); } IDB_Decimal d = parm[0]->data()->getDecimalVal(row, isNull); - if (parm[0]->data()->resultType().colWidth == datatypes::MAXDECIMALWIDTH) - dividendInt = d.s128Value; - else - dividendInt = d.value; - - // integer division - if (d.scale == 0 && div.scale == 0) + // two special cases: both Decimals has no scale + // or divisor has no scale + if (!div.isScaled()) { - retValue.s128Value = dividendInt % divInt; - } - // special case integer division - else if (div.scale == 0) - { - int128_t scaleDivisor; - datatypes::getScaleDivisor(scaleDivisor, d.scale); - int128_t value = dividendInt / scaleDivisor; - int128_t lefto = dividendInt % scaleDivisor; - int128_t mod = (value % divInt) * scaleDivisor + lefto; - retValue.s128Value = mod; + return IDB_Decimal(d % div.toTSInt128(), + d.scale, + datatypes::INT128MAXPRECISION); } // float division else { + int128_t dividendInt = (parm[0]->data()->resultType().colWidth == datatypes::MAXDECIMALWIDTH) ? d.s128Value : d.value; + + __float128 divF, dividendF; int128_t scaleDivisor; @@ -121,32 +102,26 @@ IDB_Decimal Func_mod::getDecimalVal(Row& row, __float128 mod = fmodq(dividendF, divF) * scaleDivisor; - retValue.s128Value = (int128_t) mod; + return IDB_Decimal(datatypes::TSInt128((int128_t) mod), + d.scale, + datatypes::INT128MAXPRECISION); } - retValue.scale = d.scale; - retValue.precision = datatypes::INT128MAXPRECISION; } - else + int64_t div = parm[1]->data()->getIntVal(row, isNull); + + if ( div == 0 ) { - int64_t div = parm[1]->data()->getIntVal(row, isNull); - - if ( div == 0 ) - { - isNull = true; - return retValue; - } - - IDB_Decimal d = parm[0]->data()->getDecimalVal(row, isNull); - int64_t value = d.value / pow(10.0, d.scale); - int lefto = d.value % (int)pow(10.0, d.scale); - - int64_t mod = (value % div) * pow(10.0, d.scale) + lefto; - - retValue.value = mod; - retValue.scale = d.scale; + isNull = true; + return IDB_Decimal(); } - return retValue; + IDB_Decimal d = parm[0]->data()->getDecimalVal(row, isNull); + int64_t value = d.value / pow(10.0, d.scale); + int lefto = d.value % (int)pow(10.0, d.scale); + + int64_t mod = (value % div) * pow(10.0, d.scale) + lefto; + // It is misterious but precision is set to 0! + return IDB_Decimal(mod, d.scale, 0); } @@ -227,29 +202,7 @@ double Func_mod::getDoubleVal(Row& row, case execplan::CalpontSystemCatalog::DECIMAL: case execplan::CalpontSystemCatalog::UDECIMAL: { - IDB_Decimal d = parm[0]->data()->getDecimalVal(row, isNull); - - if (parm[0]->data()->resultType().colWidth == datatypes::MAXDECIMALWIDTH) - { - if (d.scale == 0) - { - mod = d.s128Value % div; - } - else - { - int128_t scaleDivisor; - datatypes::getScaleDivisor(scaleDivisor, d.scale); - int128_t value = d.s128Value / scaleDivisor; - int128_t lefto = d.s128Value % scaleDivisor; - datatypes::TFloat128 tmp((__float128) (value % div) + (__float128) lefto / scaleDivisor); - mod = static_cast(tmp); - } - } - else - { - int64_t value = d.value / pow(10.0, d.scale); - mod = value % div; - } + mod = doDecimal(parm, div, row, isNull); } break; @@ -350,29 +303,7 @@ long double Func_mod::getLongDoubleVal(Row& row, case execplan::CalpontSystemCatalog::DECIMAL: case execplan::CalpontSystemCatalog::UDECIMAL: { - IDB_Decimal d = parm[0]->data()->getDecimalVal(row, isNull); - - if (parm[0]->data()->resultType().colWidth == datatypes::MAXDECIMALWIDTH) - { - if (d.scale == 0) - { - mod = d.s128Value % div; - } - else - { - int128_t scaleDivisor; - datatypes::getScaleDivisor(scaleDivisor, d.scale); - int128_t value = d.s128Value / scaleDivisor; - int128_t lefto = d.s128Value % scaleDivisor; - datatypes::TFloat128 tmp((__float128) (value % div) + (__float128) lefto / scaleDivisor); - mod = static_cast(tmp); - } - } - else - { - int64_t value = d.value / pow(10.0, d.scale); - mod = value % div; - } + mod = doDecimal(parm, div, row, isNull); } break; @@ -476,29 +407,7 @@ int64_t Func_mod::getIntVal(Row& row, case execplan::CalpontSystemCatalog::DECIMAL: case execplan::CalpontSystemCatalog::UDECIMAL: { - IDB_Decimal d = parm[0]->data()->getDecimalVal(row, isNull); - - if (parm[0]->data()->resultType().colWidth == datatypes::MAXDECIMALWIDTH) - { - if (d.scale == 0) - { - mod = d.s128Value % div; - } - else - { - int128_t scaleDivisor; - datatypes::getScaleDivisor(scaleDivisor, d.scale); - int128_t value = d.s128Value / scaleDivisor; - int128_t lefto = d.s128Value % scaleDivisor; - __float128 tmp = (__float128) (value % div) + (__float128) lefto / scaleDivisor; - mod = datatypes::Decimal::getInt64FromFloat128(tmp); - } - } - else - { - int64_t value = d.value / pow(10.0, d.scale); - mod = value % div; - } + mod = doDecimal(parm, div, row, isNull); } break; @@ -593,29 +502,7 @@ uint64_t Func_mod::getUIntVal(Row& row, case execplan::CalpontSystemCatalog::DECIMAL: case execplan::CalpontSystemCatalog::UDECIMAL: { - IDB_Decimal d = parm[0]->data()->getDecimalVal(row, isNull); - - if (parm[0]->data()->resultType().colWidth == datatypes::MAXDECIMALWIDTH) - { - if (d.scale == 0) - { - mod = d.s128Value % div; - } - else - { - int128_t scaleDivisor; - datatypes::getScaleDivisor(scaleDivisor, d.scale); - int128_t value = d.s128Value / scaleDivisor; - int128_t lefto = d.s128Value % scaleDivisor; - __float128 tmp = (__float128) (value % div) + (__float128) lefto / scaleDivisor; - mod = datatypes::Decimal::getUInt64FromFloat128(tmp); - } - } - else - { - int64_t value = d.value / pow(10.0, d.scale); - mod = value % div; - } + mod = doDecimal(parm, div, row, isNull); } break; diff --git a/utils/funcexp/func_round.cpp b/utils/funcexp/func_round.cpp index 8162811bc..0adbba692 100644 --- a/utils/funcexp/func_round.cpp +++ b/utils/funcexp/func_round.cpp @@ -133,18 +133,7 @@ int64_t Func_round::getIntVal(Row& row, } else { - if (x.scale > 0) - { - while (x.scale-- > 0) - x.s128Value /= 10; - } - else - { - while (x.scale++ < 0) - x.s128Value *= 10; - } - - return datatypes::Decimal::getInt64FromWideDecimal(x.s128Value); + return static_cast(x.getIntegralPart()); } } diff --git a/utils/funcexp/func_truncate.cpp b/utils/funcexp/func_truncate.cpp index dc59cc578..8718fc832 100644 --- a/utils/funcexp/func_truncate.cpp +++ b/utils/funcexp/func_truncate.cpp @@ -136,18 +136,7 @@ int64_t Func_truncate::getIntVal(Row& row, } else { - if (x.scale > 0) - { - while (x.scale-- > 0) - x.s128Value /= 10; - } - else - { - while (x.scale++ < 0) - x.s128Value *= 10; - } - - return datatypes::Decimal::getInt64FromWideDecimal(x.s128Value); + return static_cast(x.getIntegralPart()); } } diff --git a/utils/funcexp/functor_real.h b/utils/funcexp/functor_real.h index d31a55686..968f400fe 100644 --- a/utils/funcexp/functor_real.h +++ b/utils/funcexp/functor_real.h @@ -427,6 +427,35 @@ public: FunctionParm& fp, bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct); +private: + template + ModType doDecimal(const FunctionParm& parm, + const int64_t div, + rowgroup::Row& row, + bool isNull) + { + execplan::IDB_Decimal d = parm[0]->data()->getDecimalVal(row, isNull); + + if (parm[0]->data()->resultType().colWidth == datatypes::MAXDECIMALWIDTH) + { + if (!d.isScaled()) + { + return d.toTSInt128() % div; + } + else + { + auto intAndFract = d.getIntegralAndDividedFractional(); + + datatypes::TSInt128 integralRemainder = intAndFract.first % div; + return static_cast(integralRemainder.toTFloat128() + + intAndFract.second); + + } + } + int64_t value = d.value / pow(10.0, d.scale); + return value % div; + } + }; diff --git a/utils/rowgroup/rowgroup.cpp b/utils/rowgroup/rowgroup.cpp index 122850edc..9f31b6388 100644 --- a/utils/rowgroup/rowgroup.cpp +++ b/utils/rowgroup/rowgroup.cpp @@ -637,7 +637,7 @@ string Row::toString() const case CalpontSystemCatalog::UDECIMAL: if (colWidths[i] == datatypes::MAXDECIMALWIDTH) { - datatypes::VDecimal dec(0, + datatypes::Decimal dec(0, scale[i], precision[i], getBinaryField(i)); diff --git a/writeengine/server/we_dmlcommandproc.cpp b/writeengine/server/we_dmlcommandproc.cpp index 0753ac7b8..6aaeac340 100644 --- a/writeengine/server/we_dmlcommandproc.cpp +++ b/writeengine/server/we_dmlcommandproc.cpp @@ -2994,7 +2994,7 @@ uint8_t WE_DMLCommandProc::processUpdate(messageqcpp::ByteStream& bs, { if (fetchColColwidths[fetchColPos] == datatypes::MAXDECIMALWIDTH) { - datatypes::VDecimal dec(0, + datatypes::Decimal dec(0, fetchColScales[fetchColPos], rowGroups[txnId]->getPrecision()[fetchColPos], row.getBinaryField(fetchColPos)); @@ -3037,7 +3037,7 @@ uint8_t WE_DMLCommandProc::processUpdate(messageqcpp::ByteStream& bs, } else { - datatypes::VDecimal dec(intColVal, + datatypes::Decimal dec(intColVal, fetchColScales[fetchColPos], rowGroups[txnId]->getPrecision()[fetchColPos]); value = dec.toString(); @@ -3349,7 +3349,7 @@ uint8_t WE_DMLCommandProc::processUpdate(messageqcpp::ByteStream& bs, { if (fetchColColwidths[fetchColPos] == datatypes::MAXDECIMALWIDTH) { - datatypes::VDecimal dec(0, + datatypes::Decimal dec(0, fetchColScales[fetchColPos], rowGroups[txnId]->getPrecision()[fetchColPos], row.getBinaryField(fetchColPos)); @@ -3393,7 +3393,7 @@ uint8_t WE_DMLCommandProc::processUpdate(messageqcpp::ByteStream& bs, } else { - datatypes::VDecimal dec(intColVal, + datatypes::Decimal dec(intColVal, fetchColScales[fetchColPos], rowGroups[txnId]->getPrecision()[fetchColPos]); value = dec.toString();