diff --git a/datatypes/mcs_datatype.cpp b/datatypes/mcs_datatype.cpp index 533a8518d..fdbf149f4 100644 --- a/datatypes/mcs_datatype.cpp +++ b/datatypes/mcs_datatype.cpp @@ -632,16 +632,20 @@ int TypeHandlerSLongDouble::storeValueToField(rowgroup::Row &row, int pos, int TypeHandlerXDecimal::storeValueToField64(rowgroup::Row &row, int pos, StoreField *f) const { - int64_t val = row.getIntField(pos); - return f->store_decimal64(val); + return f->store_decimal64(datatypes::VDecimal(row.getIntField(pos), + f->scale(), + f->precision())); } int TypeHandlerXDecimal::storeValueToField128(rowgroup::Row &row, int pos, StoreField *f) const { - int128_t* dec= row.getBinaryField(pos); - return f->store_decimal128(*dec); + int128_t* decPtr = row.getBinaryField(pos); + return f->store_decimal128(datatypes::VDecimal(0, + f->scale(), + f->precision(), + decPtr)); } @@ -780,12 +784,8 @@ TypeHandlerXDecimal::format128(const SimpleValue &v, const { idbassert(isValidXDecimal128(attr)); - ostringstream oss; - char buf[datatypes::Decimal::MAXLENGTH16BYTES]; - int128_t tmp= v.toSInt128(); - DataConvert::decimalToString(&tmp, (unsigned) attr.scale, buf, (uint8_t) sizeof(buf), code()); - oss << buf; - return oss.str(); + datatypes::VDecimal 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 162fdad8e..87c894da3 100644 --- a/datatypes/mcs_datatype.h +++ b/datatypes/mcs_datatype.h @@ -720,6 +720,7 @@ public: virtual ~StoreField() {} virtual int32_t colWidth() const = 0; virtual int32_t precision() const = 0; + virtual int32_t scale() const = 0; virtual int store_date(int64_t val) = 0; virtual int store_datetime(int64_t val) = 0; virtual int store_time(int64_t val) = 0; @@ -730,8 +731,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(int64_t val) = 0; - virtual int store_decimal128(const int128_t &val) = 0; + virtual int store_decimal64(const datatypes::VDecimal& dec) = 0; + virtual int store_decimal128(const datatypes::VDecimal& 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 9da2894c5..b2563251f 100644 --- a/datatypes/mcs_decimal.cpp +++ b/datatypes/mcs_decimal.cpp @@ -195,45 +195,6 @@ namespace datatypes } } - std::string Decimal::toString(VDecimal& value) - { - char buf[Decimal::MAXLENGTH16BYTES]; - if (value.s128Value == Decimal128Null) - { - return std::string("NULL"); - } - else if (value.s128Value == Decimal128Empty) - { - return std::string("EMPTY"); - } - dataconvert::DataConvert::decimalToString(&value.s128Value, - value.scale, buf, (uint8_t) sizeof(buf), - datatypes::SystemCatalog::DECIMAL); - return std::string(buf); - } - - std::string Decimal::toString(const VDecimal& value) - { - return toString(const_cast(value)); - } - - std::string Decimal::toString(const int128_t& value) - { - char buf[Decimal::MAXLENGTH16BYTES]; - if (value == Decimal128Null) - { - return std::string("NULL"); - } - else if (value == Decimal128Empty) - { - return std::string("EMPTY"); - } - int128_t& constLessValue = const_cast(value); - dataconvert::DataConvert::decimalToString(&constLessValue, - 0, buf, sizeof(buf), datatypes::SystemCatalog::DECIMAL); - return std::string(buf); - } - int Decimal::compare(const VDecimal& l, const VDecimal& r) { int128_t divisorL, divisorR; @@ -559,4 +520,221 @@ namespace datatypes } } + // Writes integer part of a Decimal using int128 argument provided + uint8_t VDecimal::writeIntPart(const int128_t& x, + char* buf, + const uint8_t buflen) const + { + char* p = buf; + int128_t intPart = x; + int128_t high = 0, mid = 0, low = 0; + uint64_t maxUint64divisor = 10000000000000000000ULL; + + // Assuming scale = [0, 56] + switch (scale / datatypes::maxPowOf10) + { + case 2: // scale = [38, 56] + intPart /= datatypes::mcs_pow_10[datatypes::maxPowOf10]; + intPart /= datatypes::mcs_pow_10[datatypes::maxPowOf10]; + low = intPart; + break; + case 1: // scale = [19, 37] + intPart /= datatypes::mcs_pow_10[datatypes::maxPowOf10]; + intPart /= datatypes::mcs_pow_10[scale % datatypes::maxPowOf10]; + low = intPart % maxUint64divisor; + mid = intPart / maxUint64divisor; + break; + case 0: // scale = [0, 18] + intPart /= datatypes::mcs_pow_10[scale % datatypes::maxPowOf10]; + low = intPart % maxUint64divisor; + intPart /= maxUint64divisor; + mid = intPart % maxUint64divisor; + high = intPart / maxUint64divisor; + break; + default: + throw logging::QueryDataExcept("VDecimal::writeIntPart() bad scale", + logging::formatErr); + } + + p += printPodParts(p, high, mid, low); + uint8_t written = p - buf; + if (buflen <= written) + { + throw logging::QueryDataExcept("VDecimal::writeIntPart() char buffer overflow.", + logging::formatErr); + } + + return written; + } + + uint8_t VDecimal::writeFractionalPart(const int128_t& x, + char* buf, + const uint8_t buflen) const + { + int128_t scaleDivisor = 1; + char* p = buf; + + switch (scale / datatypes::maxPowOf10) + { + case 2: + scaleDivisor *= datatypes::mcs_pow_10[datatypes::maxPowOf10]; + scaleDivisor *= datatypes::mcs_pow_10[datatypes::maxPowOf10]; + break; + case 1: + scaleDivisor *= datatypes::mcs_pow_10[datatypes::maxPowOf10]; + //fallthrough + case 0: + scaleDivisor *= datatypes::mcs_pow_10[scale % datatypes::maxPowOf10]; + } + + int128_t fractionalPart = x % scaleDivisor; + + // divide by the base until we have non-zero quotient + scaleDivisor /= 10; + + while (scaleDivisor > 1 && fractionalPart / scaleDivisor == 0) + { + *p++ = '0'; + scaleDivisor /= 10; + } + size_t written = p - buf;; + p += TSInt128::writeIntPart(fractionalPart, p, buflen - written); + return p - buf; + } + + // 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 + { + char buf[Decimal::MAXLENGTH16BYTES]; + uint8_t left = sizeof(buf); + char* p = buf; + int128_t tempValue = s128Value; + // sign + if (tempValue < static_cast(0)) + { + *p++ = '-'; + tempValue *= -1; + left--; + } + + // integer part + p += writeIntPart(tempValue, p, left); + + // decimal delimiter + *p++ = '.'; + // decimal part + left = sizeof(buf) - (p - buf); + p += writeFractionalPart(tempValue, p, left); + + *p = '\0'; + + uint8_t written = p - buf; + if (sizeof(buf) <= written) + { + throw logging::QueryDataExcept("VDecimal::toString() char buffer overflow.", + logging::formatErr); + } + return std::string(buf); + } + + std::string VDecimal::toStringTSInt64() const + { + char buf[Decimal::MAXLENGTH8BYTES]; + // Need 19 digits maxium to hold a sum result of 18 digits decimal column. + // We don't make a copy of value b/c we mutate its string + // representation. +#ifndef __LP64__ + snprintf(buf, sizeof(buf), "%lld", value); +#else + snprintf(buf, sizeof(buf), "%ld", value); +#endif + + //we want to move the last dt_scale chars right by one spot + // to insert the dp we want to move the trailing null as well, + // so it's really dt_scale+1 chars + size_t l1 = strlen(buf); + char* ptr = &buf[0]; + + if (value < 0) + { + ptr++; + idbassert(l1 >= 2); + l1--; + } + + //need to make sure we have enough leading zeros for this to work. + //at this point scale is always > 0 + size_t l2 = 1; + + if ((unsigned)scale > l1) + { + const char* zeros = "00000000000000000000"; //20 0's + size_t diff = 0; + + if (value != 0) + diff = scale - l1; //this will always be > 0 + else + diff = scale; + + memmove((ptr + diff), ptr, l1 + 1); //also move null + memcpy(ptr, zeros, diff); + + if (value != 0) + l1 = 0; + else + l1 = 1; + } + else if ((unsigned)scale == l1) + { + l1 = 0; + l2 = 2; + } + else + { + l1 -= scale; + } + + memmove((ptr + l1 + l2), (ptr + l1), scale + 1); //also move null + + if (l2 == 2) + *(ptr + l1++) = '0'; + + *(ptr + l1) = '.'; + return std::string(buf); + } + + // Dispatcher method for toString() implementations + std::string VDecimal::toString(bool hasTSInt128) const + { + // There must be no empty at this point though + if (isNull()) + { + return std::string("NULL"); + } + + if(LIKELY(hasTSInt128 || isTSInt128ByPrecision())) + { + if (scale) + { + return toStringTSInt128WithScale(); + } + return TSInt128::toString(); + } + // TSInt64 Decimal + if (scale) + { + return toStringTSInt64(); + } + return std::to_string(value); + } + + std::ostream& operator<<(std::ostream& os, const VDecimal& dec) + { + os << dec.toString(); + return os; + } + + } // end of namespace diff --git a/datatypes/mcs_decimal.h b/datatypes/mcs_decimal.h index 74fd6935a..387c4f662 100644 --- a/datatypes/mcs_decimal.h +++ b/datatypes/mcs_decimal.h @@ -131,8 +131,8 @@ const int128_t mcs_pow_10_128[20] = }; constexpr uint32_t maxPowOf10 = sizeof(mcs_pow_10)/sizeof(mcs_pow_10[0])-1; -constexpr int128_t Decimal128Null = int128_t(0x8000000000000000LL) << 64; -constexpr int128_t Decimal128Empty = (int128_t(0x8000000000000000LL) << 64) + 1; +constexpr int128_t Decimal128Null = TSInt128::NullValue; +constexpr int128_t Decimal128Empty = TSInt128::EmptyValue; /** @@ -172,7 +172,7 @@ class Decimal Decimal() { }; ~Decimal() { }; - static constexpr uint8_t MAXLENGTH16BYTES = 42; + static constexpr uint8_t MAXLENGTH16BYTES = TSInt128::maxLength(); static constexpr uint8_t MAXLENGTH8BYTES = 23; static inline bool isWideDecimalNullValue(const int128_t& val) @@ -259,13 +259,6 @@ class Decimal const VDecimal& r, VDecimal& result); - /** - @brief Convenience methods to put decimal into a std::string. - */ - static std::string toString(VDecimal& value); - static std::string toString(const VDecimal& value); - static std::string toString(const int128_t& value); - /** @brief The method detects whether decimal type is wide using precision. @@ -558,6 +551,14 @@ class VDecimal: public TSInt128 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])); @@ -819,9 +820,35 @@ class VDecimal: public TSInt128 } } + 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; } + +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 diff --git a/datatypes/mcs_int128.cpp b/datatypes/mcs_int128.cpp index abaa9a27f..d94f5f1bb 100644 --- a/datatypes/mcs_int128.cpp +++ b/datatypes/mcs_int128.cpp @@ -17,7 +17,10 @@ MA 02110-1301, USA. */ +#include + #include "mcs_int128.h" +#include "exceptclasses.h" namespace datatypes { @@ -33,6 +36,99 @@ namespace datatypes return getLongDoubleFromFloat128(static_cast<__float128>(s128Value)); } + uint8_t TSInt128::printPodParts(char* buf, + const int128_t& high, + const int128_t& mid, + const int128_t& low) const + { + char* p = buf; + // pod[0] is low 8 bytes, pod[1] is high 8 bytes + const uint64_t* high_pod = reinterpret_cast(&high); + const uint64_t* mid_pod = reinterpret_cast(&mid); + const uint64_t* low_pod = reinterpret_cast(&low); + + if (high_pod[0] != 0) + { + p += sprintf(p, "%lu", high_pod[0]); + p += sprintf(p, "%019lu", mid_pod[0]); + p += sprintf(p, "%019lu", low_pod[0]); + } + else if (mid_pod[0] != 0) + { + p += sprintf(p, "%lu", mid_pod[0]); + p += sprintf(p, "%019lu", low_pod[0]); + } + else + { + p += sprintf(p, "%lu", low_pod[0]); + } + return p - buf; + } + + // This method writes unsigned integer representation of TSInt128 + uint8_t TSInt128::writeIntPart(const int128_t& x, + char* buf, + const uint8_t buflen) const + { + char* p = buf; + int128_t high = 0, mid = 0, low = 0; + uint64_t maxUint64divisor = 10000000000000000000ULL; + + low = x % maxUint64divisor; + int128_t value = x / maxUint64divisor; + mid = value % maxUint64divisor; + high = value / maxUint64divisor; + + p += printPodParts(p, high, mid, low); + uint8_t written = p - buf; + if (buflen <= written) + { + throw logging::QueryDataExcept("TSInt128::writeIntPart() char buffer overflow.", + logging::formatErr); + } + + return written; + } + + // conversion to std::string + std::string TSInt128::toString() const + { + if (isNull()) + { + return std::string("NULL"); + } + + if (isEmpty()) + { + return std::string("EMPTY"); + } + + int128_t tempValue = s128Value; + char buf[TSInt128::MAXLENGTH16BYTES]; + uint8_t left = sizeof(buf); + char* p = buf; + // sign + if (tempValue < static_cast(0)) + { + *p++ = '-'; + tempValue *= -1; + left--; + } + // integer part + // reduce the size by one to account for \0 + left--; + p += writeIntPart(tempValue, p, left); + *p = '\0'; + + return std::string(buf); + } + + std::ostream& operator<<(std::ostream& os, const TSInt128& x) + { + os << x.toString(); + return os; + } + // The method converts a wide decimal s128Value to an int64_t, // saturating the s128Value if necessary. inline int64_t TSInt128::getInt64FromWideDecimal() diff --git a/datatypes/mcs_int128.h b/datatypes/mcs_int128.h index ef8a3e262..1bab9171c 100644 --- a/datatypes/mcs_int128.h +++ b/datatypes/mcs_int128.h @@ -23,6 +23,7 @@ #include #include #include +#include // Inline asm has three argument lists: output, input and clobber list #if defined(__GNUC__) && (__GNUC___ > 7) @@ -116,18 +117,41 @@ static inline long double getLongDoubleFromFloat128(const __float128& value) class TSInt128 { public: - // A variety of ctors for aligned and unaligned arguments + static constexpr uint8_t MAXLENGTH16BYTES = 42; + static constexpr int128_t NullValue = int128_t(0x8000000000000000LL) << 64; + static constexpr int128_t EmptyValue = (int128_t(0x8000000000000000LL) << 64) + 1; + + + // A variety of ctors for aligned and unaligned arguments TSInt128(): s128Value(0) { } - // aligned argument + // aligned argument TSInt128(const int128_t& x) { s128Value = x; } - // unaligned argument + // unaligned argument TSInt128(const int128_t* x) { assignPtrPtr(&s128Value, x); } - // unaligned argument + // unaligned argument TSInt128(const unsigned char* x) { assignPtrPtr(&s128Value, x); } + // Method returns max length of a string representation + static constexpr uint8_t maxLength() + { + return TSInt128::MAXLENGTH16BYTES; + } + + // Checks if the value is NULL + inline bool isNull() const + { + return s128Value == NullValue; + } + + // Checks if the value is Empty + inline bool isEmpty() const + { + return s128Value == EmptyValue; + } + // The method copies 16 bytes from one memory cell // into another using memcpy or SIMD. // memcpy in gcc >= 7 is replaced with SIMD instructions @@ -158,6 +182,22 @@ class TSInt128 return s128Value == static_cast(x); } + // print int128_t parts represented as PODs + uint8_t printPodParts(char* buf, + const int128_t& high, + const int128_t& mid, + const int128_t& low) const; + + // writes integer part of dec into a buffer + uint8_t writeIntPart(const int128_t& x, + char* buf, + const uint8_t buflen) const; + + // string representation of TSInt128 + std::string toString() const; + + friend std::ostream& operator<<(std::ostream& os, const TSInt128& x); + // The method converts a wide decimal s128Value to a double. inline double getDoubleFromWideDecimal(); diff --git a/dbcon/execplan/simplecolumn_decimal.h b/dbcon/execplan/simplecolumn_decimal.h index a6fdac5e4..4e78607cf 100644 --- a/dbcon/execplan/simplecolumn_decimal.h +++ b/dbcon/execplan/simplecolumn_decimal.h @@ -153,8 +153,10 @@ void SimpleColumn_Decimal::setNullVal() template inline const std::string& SimpleColumn_Decimal:: getStrVal(rowgroup::Row& row, bool& isNull) { - dataconvert::DataConvert::decimalToString((int64_t)row.getIntField(fInputIndex), fResultType.scale, tmp, 22, fResultType.colDataType); - fResult.strVal = std::string(tmp); + datatypes::VDecimal dec((int64_t)row.getIntField(fInputIndex), + fResultType.scale, + fResultType.precision); + fResult.strVal = dec.toString(); return fResult.strVal; } diff --git a/dbcon/execplan/treenode.h b/dbcon/execplan/treenode.h index 9eee7e30a..1b7fd316c 100644 --- a/dbcon/execplan/treenode.h +++ b/dbcon/execplan/treenode.h @@ -632,10 +632,10 @@ inline const std::string& TreeNode::getStrVal(const std::string& timeZone) case CalpontSystemCatalog::UDECIMAL: { if (fResultType.colWidth == datatypes::MAXDECIMALWIDTH) - dataconvert::DataConvert::decimalToString(&fResult.decimalVal.s128Value, fResult.decimalVal.scale, tmp, datatypes::Decimal::MAXLENGTH16BYTES, fResultType.colDataType); + // Explicit path for TSInt128 decimals with low precision + fResult.strVal = fResult.decimalVal.toString(true); else - dataconvert::DataConvert::decimalToString(fResult.decimalVal.value, fResult.decimalVal.scale, tmp, 22, fResultType.colDataType); - fResult.strVal = std::string(tmp); + fResult.strVal = fResult.decimalVal.toString(); break; } diff --git a/dbcon/joblist/groupconcat.cpp b/dbcon/joblist/groupconcat.cpp index b5ba3390f..a1d0a28ae 100644 --- a/dbcon/joblist/groupconcat.cpp +++ b/dbcon/joblist/groupconcat.cpp @@ -460,13 +460,11 @@ void GroupConcator::outputRow(std::ostringstream& oss, const rowgroup::Row& row) if (LIKELY(row.getColumnWidth(*i) == datatypes::MAXDECIMALWIDTH)) { - char buf[datatypes::Decimal::MAXLENGTH16BYTES]; - - int128_t* dec = row.getBinaryField(*i); - dataconvert::DataConvert::decimalToString(dec, - static_cast(scale), buf, - (uint8_t) sizeof(buf), types[*i]); - oss << fixed << buf; + datatypes::VDecimal dec(0, + scale, + row.getPrecision(*i), + row.getBinaryField(*i)); + oss << fixed << dec; } else { diff --git a/dbcon/joblist/tupleunion.cpp b/dbcon/joblist/tupleunion.cpp index 4344109f1..438dc8ef2 100644 --- a/dbcon/joblist/tupleunion.cpp +++ b/dbcon/joblist/tupleunion.cpp @@ -1099,8 +1099,8 @@ dec4: /* have to pick a scale to use for the double. using 5... */ case CalpontSystemCatalog::DECIMAL: case CalpontSystemCatalog::UDECIMAL: { - int64_t val; - int128_t val128; + int64_t val = 0; + int128_t val128 = 0; bool isInputWide = false; if (in.getColumnWidth(i) == datatypes::MAXDECIMALWIDTH) @@ -1185,15 +1185,21 @@ dec4: /* have to pick a scale to use for the double. using 5... */ case CalpontSystemCatalog::VARCHAR: default: { - char buf[50]; - dataconvert::DataConvert::decimalToString(val, scale, buf, 50, out->getColTypes()[i]); - /* ostringstream oss; - if (scale == 0) - oss << val; - else - oss << (val / IDB_pow[scale]) << "." - << setw(scale) << setfill('0') << (val % IDB_pow[scale]); */ - out->setStringField(string(buf), i); + if (LIKELY(isInputWide)) + { + datatypes::VDecimal dec(0, + in.getScale(i), + in.getPrecision(i), + val128); + out->setStringField(dec.toString(), i); + } + else + { + datatypes::VDecimal dec(val, + in.getScale(i), + in.getPrecision(i)); + out->setStringField(dec.toString(), i); + } break; } } diff --git a/dbcon/mysql/ha_mcs_datatype.h b/dbcon/mysql/ha_mcs_datatype.h index 56ffd7cba..0014d65a9 100644 --- a/dbcon/mysql/ha_mcs_datatype.h +++ b/dbcon/mysql/ha_mcs_datatype.h @@ -38,6 +38,7 @@ public: const CalpontSystemCatalog::ColType &type() const { return m_type; } int32_t colWidth() const override { return m_type.colWidth; } int32_t precision() const override { return m_type.precision; } + int32_t scale() const override { return m_type.scale; } int store_date(int64_t val) override { @@ -160,30 +161,16 @@ public: return m_field->store(static_cast(dl)); } - int store_decimal64(int64_t val) override + int store_decimal64(const datatypes::VDecimal& dec) override { - // @bug4388 stick to InfiniDB's scale in case mysql gives wrong scale due - // to create vtable limitation. - //if (f2->dec < m_type.scale) - // f2->dec = m_type.scale; - - // WIP MCOL-641 - // This is too much - char buf[256]; - dataconvert::DataConvert::decimalToString(val, (unsigned)m_type.scale, - buf, sizeof(buf), m_type.colDataType); - return m_field->store(buf, strlen(buf), m_field->charset()); + std::string decAsAStr = dec.toString(); + return m_field->store(decAsAStr.c_str(), decAsAStr.length(), m_field->charset()); } - int store_decimal128(const int128_t &val) override + int store_decimal128(const datatypes::VDecimal& dec) override { - // We won't have more than [+-][0][.] + up to 38 digits - char buf[datatypes::Decimal::MAXLENGTH16BYTES]; - dataconvert::DataConvert::decimalToString((int128_t*) &val, - (unsigned) m_type.scale, - buf, (uint8_t) sizeof(buf), - m_type.colDataType); - return m_field->store(buf, strlen(buf), m_field->charset()); + std::string decAsAStr = dec.toString(true); + return m_field->store(decAsAStr.c_str(), decAsAStr.length(), m_field->charset()); } int store_lob(const char *str, size_t length) override diff --git a/dbcon/mysql/is_columnstore_extents.cpp b/dbcon/mysql/is_columnstore_extents.cpp index 7e6f01165..f1ab1f3a7 100644 --- a/dbcon/mysql/is_columnstore_extents.cpp +++ b/dbcon/mysql/is_columnstore_extents.cpp @@ -112,12 +112,11 @@ static int generate_result(BRM::OID_t oid, BRM::DBRM* emp, TABLE* table, THD* th else { table->field[4]->set_notnull(); - - char buf[datatypes::Decimal::MAXLENGTH16BYTES]; - dataconvert::DataConvert::decimalToString( - &iter->partition.cprange.bigLoVal, - 0, buf, (uint8_t) sizeof(buf), datatypes::SystemCatalog::DECIMAL); - table->field[4]->store(buf, strlen(buf), table->field[4]->charset()); + std::string decAsAStr = datatypes::TSInt128(iter->partition.cprange.bigLoVal) + .toString(); + table->field[4]->store(decAsAStr.c_str(), + decAsAStr.length(), + table->field[4]->charset()); } if (iter->partition.cprange.bigHiVal <= (utils::minInt128 + 1)) @@ -127,12 +126,11 @@ static int generate_result(BRM::OID_t oid, BRM::DBRM* emp, TABLE* table, THD* th else { table->field[5]->set_notnull(); - - char buf[datatypes::Decimal::MAXLENGTH16BYTES]; - dataconvert::DataConvert::decimalToString( - &iter->partition.cprange.bigHiVal, - 0, buf, (uint8_t) sizeof(buf), datatypes::SystemCatalog::DECIMAL); - table->field[5]->store(buf, strlen(buf), table->field[5]->charset()); + std::string decAsAStr = datatypes::TSInt128(iter->partition.cprange.bigHiVal) + .toString(); + table->field[5]->store(decAsAStr.c_str(), + decAsAStr.length(), + table->field[5]->charset()); } } diff --git a/tests/dataconvert-tests.cpp b/tests/dataconvert-tests.cpp index 17c816c98..a6c7179b5 100644 --- a/tests/dataconvert-tests.cpp +++ b/tests/dataconvert-tests.cpp @@ -25,8 +25,6 @@ using namespace dataconvert; #include "joblisttypes.h" #include "columnwidth.h" -using CSCDataType = execplan::CalpontSystemCatalog::ColDataType; - TEST(DataConvertTest, Strtoll128) { char *ep = NULL; @@ -543,252 +541,6 @@ TEST(DataConvertTest, NumberIntValue) EXPECT_EQ(b2, b4); EXPECT_TRUE(pushWarning); } - -TEST(DataConvertTest, DecimalToStringCheckScale0) -{ - datatypes::SystemCatalog::TypeHolderStd ct; - ct.colDataType = datatypes::SystemCatalog::DECIMAL; - char buf[42]; - string input, expected; - ct.precision = 38; - ct.scale = 0; - int128_t res; - - // test simple values - res = 0; - expected = "0"; - DataConvert::decimalToString(&res, ct.scale, buf, 42, ct.colDataType); - EXPECT_EQ(string(buf), expected); - res = 2; - expected = "2"; - DataConvert::decimalToString(&res, ct.scale, buf, 42, ct.colDataType); - EXPECT_EQ(string(buf), expected); - res = -2; - expected = "-2"; - DataConvert::decimalToString(&res, ct.scale, buf, 42, ct.colDataType); - EXPECT_EQ(string(buf), expected); - res = 123; - expected = "123"; - DataConvert::decimalToString(&res, ct.scale, buf, 42, ct.colDataType); - EXPECT_EQ(string(buf), expected); - res = -123; - expected = "-123"; - DataConvert::decimalToString(&res, ct.scale, buf, 42, ct.colDataType); - EXPECT_EQ(string(buf), expected); - - // test max/min decimal (i.e. 38 9's) - res = ((((((((int128_t)999999999 * 1000000000) + 999999999) * 1000000000) + 999999999) * 1000000000 ) + 999999999) * 100) + 99; - expected = "99999999999999999999999999999999999999"; - DataConvert::decimalToString(&res, ct.scale, buf, 42, ct.colDataType); - EXPECT_EQ(string(buf), expected); - res = -res; - expected = "-99999999999999999999999999999999999999"; - DataConvert::decimalToString(&res, ct.scale, buf, 42, ct.colDataType); - EXPECT_EQ(string(buf), expected); - - // test trailing zeros - res = 123000; - expected = "123000"; - DataConvert::decimalToString(&res, ct.scale, buf, 42, ct.colDataType); - EXPECT_EQ(string(buf), expected); - res = -res; - expected = "-123000"; - DataConvert::decimalToString(&res, ct.scale, buf, 42, ct.colDataType); - EXPECT_EQ(string(buf), expected); -} -TEST(DataConvertTest, DecimalToStringCheckScale10) -{ - datatypes::SystemCatalog::TypeHolderStd ct; - ct.colDataType = datatypes::SystemCatalog::DECIMAL; - char buf[42]; - string input, expected; - ct.precision = 38; - ct.scale = 10; - int128_t res; - - // test simple values - res = 0; - expected = "0.0000000000"; - DataConvert::decimalToString(&res, ct.scale, buf, 42, ct.colDataType); - EXPECT_EQ(string(buf), expected); - res = 2; - expected = "0.0000000002"; - DataConvert::decimalToString(&res, ct.scale, buf, 42, ct.colDataType); - EXPECT_EQ(string(buf), expected); - res = -2; - expected = "-0.0000000002"; - DataConvert::decimalToString(&res, ct.scale, buf, 42, ct.colDataType); - EXPECT_EQ(string(buf), expected); - res = 123; - expected = "0.0000000123"; - DataConvert::decimalToString(&res, ct.scale, buf, 42, ct.colDataType); - EXPECT_EQ(string(buf), expected); - res = -123; - expected = "-0.0000000123"; - DataConvert::decimalToString(&res, ct.scale, buf, 42, ct.colDataType); - EXPECT_EQ(string(buf), expected); - res = 12345678901; - expected = "1.2345678901"; - DataConvert::decimalToString(&res, ct.scale, buf, 42, ct.colDataType); - EXPECT_EQ(string(buf), expected); - res = -12345678901; - expected = "-1.2345678901"; - DataConvert::decimalToString(&res, ct.scale, buf, 42, ct.colDataType); - EXPECT_EQ(string(buf), expected); - - // test max/min decimal (i.e. 38 9's) - res = ((((((((int128_t)999999999 * 1000000000) + 999999999) * 1000000000) + 999999999) * 1000000000 ) + 999999999) * 100) + 99; - expected = "9999999999999999999999999999.9999999999"; - DataConvert::decimalToString(&res, ct.scale, buf, 42, ct.colDataType); - EXPECT_EQ(string(buf), expected); - res = -res; - expected = "-9999999999999999999999999999.9999999999"; - DataConvert::decimalToString(&res, ct.scale, buf, 42, ct.colDataType); - EXPECT_EQ(string(buf), expected); - - // test trailing zeros - res = 123000; - expected = "0.0000123000"; - DataConvert::decimalToString(&res, ct.scale, buf, 42, ct.colDataType); - EXPECT_EQ(string(buf), expected); - res = -res; - expected = "-0.0000123000"; - DataConvert::decimalToString(&res, ct.scale, buf, 42, ct.colDataType); - EXPECT_EQ(string(buf), expected); - - // test leading zeros - res = 10000000009; - expected = "1.0000000009"; - DataConvert::decimalToString(&res, ct.scale, buf, 42, ct.colDataType); - EXPECT_EQ(string(buf), expected); - res = -res; - expected = "-1.0000000009"; - DataConvert::decimalToString(&res, ct.scale, buf, 42, ct.colDataType); - EXPECT_EQ(string(buf), expected); -} - -TEST(DataConvertTest, DecimalToStringCheckScale38) -{ - datatypes::SystemCatalog::TypeHolderStd ct; - ct.colDataType = datatypes::SystemCatalog::DECIMAL; - char buf[42]; - string input, expected; - ct.precision = 38; - ct.scale = 38; - int128_t res; - - // test simple values - res = 0; - expected = "0.00000000000000000000000000000000000000"; - DataConvert::decimalToString(&res, ct.scale, buf, 42, ct.colDataType); - EXPECT_EQ(string(buf), expected); - res = 2; - expected = "0.00000000000000000000000000000000000002"; - DataConvert::decimalToString(&res, ct.scale, buf, 42, ct.colDataType); - EXPECT_EQ(string(buf), expected); - res = -2; - expected = "-0.00000000000000000000000000000000000002"; - DataConvert::decimalToString(&res, ct.scale, buf, 42, ct.colDataType); - EXPECT_EQ(string(buf), expected); - res = 123; - expected = "0.00000000000000000000000000000000000123"; - DataConvert::decimalToString(&res, ct.scale, buf, 42, ct.colDataType); - EXPECT_EQ(string(buf), expected); - res = -123; - expected = "-0.00000000000000000000000000000000000123"; - DataConvert::decimalToString(&res, ct.scale, buf, 42, ct.colDataType); - EXPECT_EQ(string(buf), expected); - res = ((((((int128_t)1234567890 * 10000000000) + 1234567890) * 10000000000) + 1234567890) * 100000000 ) + 12345678; - expected = "0.12345678901234567890123456789012345678"; - DataConvert::decimalToString(&res, ct.scale, buf, 42, ct.colDataType); - EXPECT_EQ(string(buf), expected); - res = -res; - expected = "-0.12345678901234567890123456789012345678"; - DataConvert::decimalToString(&res, ct.scale, buf, 42, ct.colDataType); - EXPECT_EQ(string(buf), expected); - - // test max/min decimal (i.e. 38 9's) - res = ((((((((int128_t)999999999 * 1000000000) + 999999999) * 1000000000) + 999999999) * 1000000000 ) + 999999999) * 100) + 99; - expected = "0.99999999999999999999999999999999999999"; - DataConvert::decimalToString(&res, ct.scale, buf, 42, ct.colDataType); - EXPECT_EQ(string(buf), expected); - res = -res; - expected = "-0.99999999999999999999999999999999999999"; - DataConvert::decimalToString(&res, ct.scale, buf, 42, ct.colDataType); - EXPECT_EQ(string(buf), expected); - - // test trailing zeros - res = 123000; - expected = "0.00000000000000000000000000000000123000"; - DataConvert::decimalToString(&res, ct.scale, buf, 42, ct.colDataType); - EXPECT_EQ(string(buf), expected); - res = -res; - expected = "-0.00000000000000000000000000000000123000"; - DataConvert::decimalToString(&res, ct.scale, buf, 42, ct.colDataType); - EXPECT_EQ(string(buf), expected); -} - -TEST(DataConvertTest, DecimalToStringCheckScale37) -{ - datatypes::SystemCatalog::TypeHolderStd ct; - ct.colDataType = datatypes::SystemCatalog::DECIMAL; - char buf[42]; - string expected; - ct.precision = 38; - ct.scale = 37; - int128_t res; - - // test simple values - res = 0; - expected = "0.0000000000000000000000000000000000000"; - DataConvert::decimalToString(&res, ct.scale, buf, 42, ct.colDataType); - EXPECT_EQ(string(buf), expected); - res = 2; - expected = "0.0000000000000000000000000000000000002"; - DataConvert::decimalToString(&res, ct.scale, buf, 42, ct.colDataType); - EXPECT_EQ(string(buf), expected); - res = -2; - expected = "-0.0000000000000000000000000000000000002"; - DataConvert::decimalToString(&res, ct.scale, buf, 42, ct.colDataType); - EXPECT_EQ(string(buf), expected); - res = 123; - expected = "0.0000000000000000000000000000000000123"; - DataConvert::decimalToString(&res, ct.scale, buf, 42, ct.colDataType); - EXPECT_EQ(string(buf), expected); - res = -123; - expected = "-0.0000000000000000000000000000000000123"; - DataConvert::decimalToString(&res, ct.scale, buf, 42, ct.colDataType); - EXPECT_EQ(string(buf), expected); - res = ((((((int128_t)1234567890 * 10000000000) + 1234567890) * 10000000000) + 1234567890) * 100000000 ) + 12345678; - expected = "1.2345678901234567890123456789012345678"; - DataConvert::decimalToString(&res, ct.scale, buf, 42, ct.colDataType); - EXPECT_EQ(string(buf), expected); - res = -res; - expected = "-1.2345678901234567890123456789012345678"; - DataConvert::decimalToString(&res, ct.scale, buf, 42, ct.colDataType); - EXPECT_EQ(string(buf), expected); - - // test max/min decimal (i.e. 38 9's) - res = ((((((((int128_t)999999999 * 1000000000) + 999999999) * 1000000000) + 999999999) * 1000000000 ) + 999999999) * 100) + 99; - expected = "9.9999999999999999999999999999999999999"; - DataConvert::decimalToString(&res, ct.scale, buf, 42, ct.colDataType); - EXPECT_EQ(string(buf), expected); - res = -res; - expected = "-9.9999999999999999999999999999999999999"; - DataConvert::decimalToString(&res, ct.scale, buf, 42, ct.colDataType); - EXPECT_EQ(string(buf), expected); - - // test trailing zeros - res = 123000; - expected = "0.0000000000000000000000000000000123000"; - DataConvert::decimalToString(&res, ct.scale, buf, 42, ct.colDataType); - EXPECT_EQ(string(buf), expected); - res = -res; - expected = "-0.0000000000000000000000000000000123000"; - DataConvert::decimalToString(&res, ct.scale, buf, 42, ct.colDataType); - EXPECT_EQ(string(buf), expected); -} - TEST(DataConvertTest, ConvertColumnData) { } diff --git a/tests/mcs_decimal-tests.cpp b/tests/mcs_decimal-tests.cpp index 762db7365..5d5b29189 100644 --- a/tests/mcs_decimal-tests.cpp +++ b/tests/mcs_decimal-tests.cpp @@ -84,8 +84,6 @@ TEST(Decimal, compareCheck) TEST(Decimal, additionNoOverflowCheck) { - datatypes::SystemCatalog::ColDataType colDataType = datatypes::SystemCatalog::DECIMAL; - char buf[42]; // Addition w/o overflow check execplan::IDB_Decimal l, r, result; // same precision, same scale, both positive values @@ -143,8 +141,7 @@ TEST(Decimal, additionNoOverflowCheck) result.s128Value = 0; datatypes::Decimal::addition(l, r, result); - dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); - EXPECT_EQ("0.00000000000042000000000000000000000042", std::string(buf)); + EXPECT_EQ("0.00000000000042000000000000000000000042", result.toString()); // same precision, L scale > R scale, both negative values l.s128Value = -42; @@ -152,8 +149,7 @@ TEST(Decimal, additionNoOverflowCheck) result.s128Value = 0; datatypes::Decimal::addition(l, r, result); - dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); - EXPECT_EQ("-0.00000000000042000000000000000000000042", std::string(buf)); + EXPECT_EQ("-0.00000000000042000000000000000000000042", result.toString()); // same precision, L scale > R scale, +- values l.s128Value = 42; @@ -161,8 +157,7 @@ TEST(Decimal, additionNoOverflowCheck) result.s128Value = 0; datatypes::Decimal::addition(l, r, result); - dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); - EXPECT_EQ("-0.00000000000041999999999999999999999958", std::string(buf)); + EXPECT_EQ("-0.00000000000041999999999999999999999958", result.toString()); // same precision, L scale > R scale, both 0 l.s128Value = 0; @@ -186,8 +181,7 @@ TEST(Decimal, additionNoOverflowCheck) result.s128Value = 0; datatypes::Decimal::addition(l, r, result); - dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); - EXPECT_EQ("0.00000000000004200000000000000000000420", std::string(buf)); + EXPECT_EQ("0.00000000000004200000000000000000000420", result.toString()); // same precision, L scale < R scale, both negative values l.s128Value = -42; @@ -195,8 +189,7 @@ TEST(Decimal, additionNoOverflowCheck) result.s128Value = 0; datatypes::Decimal::addition(l, r, result); - dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); - EXPECT_EQ("-0.00000000000004200000000000000000000420", std::string(buf)); + EXPECT_EQ("-0.00000000000004200000000000000000000420", result.toString()); // same precision, L scale < R scale, +- values l.s128Value = 42; @@ -204,8 +197,7 @@ TEST(Decimal, additionNoOverflowCheck) result.s128Value = 0; datatypes::Decimal::addition(l, r, result); - dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); - EXPECT_EQ("0.00000000000004199999999999999999999580", std::string(buf)); + EXPECT_EQ("0.00000000000004199999999999999999999580", result.toString()); // same precision, L scale < R scale, both 0 l.s128Value = 0; @@ -220,8 +212,6 @@ TEST(Decimal, divisionNoOverflowCheck) { // DIVISION // same precision, same scale, both positive values - datatypes::SystemCatalog::ColDataType colDataType = datatypes::SystemCatalog::DECIMAL; - char buf[42]; execplan::IDB_Decimal l, r, result; l.scale = 38; @@ -237,8 +227,7 @@ TEST(Decimal, divisionNoOverflowCheck) result.s128Value = 0; datatypes::Decimal::division(r, l, result); - dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); - EXPECT_EQ("9.7674418605", std::string(buf)); + EXPECT_EQ("9.7674418605", result.toString()); // same precision, same scale, both negative values l.s128Value = -43; @@ -246,8 +235,7 @@ TEST(Decimal, divisionNoOverflowCheck) result.s128Value = 0; datatypes::Decimal::division(r, l, result); - dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); - EXPECT_EQ("9.7674418605", std::string(buf)); + EXPECT_EQ("9.7674418605", result.toString()); // same precision, same scale, +- values l.s128Value = 2200000; @@ -255,8 +243,7 @@ TEST(Decimal, divisionNoOverflowCheck) result.s128Value = 0; datatypes::Decimal::division(l, r, result); - dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); - EXPECT_EQ("-1157.8947368421", std::string(buf)); + EXPECT_EQ("-1157.8947368421", result.toString()); // same precision, same scale, l = 0 l.s128Value = 0; @@ -278,8 +265,7 @@ TEST(Decimal, divisionNoOverflowCheck) result.s128Value = 0; datatypes::Decimal::division(r, l, result); - dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); - EXPECT_EQ("115789473684210526315789.4736842105", std::string(buf)); + EXPECT_EQ("115789473684210526315789.4736842105", result.toString()); // same precision, L scale > R scale, both negative values l.s128Value = -22; @@ -287,8 +273,7 @@ TEST(Decimal, divisionNoOverflowCheck) result.s128Value = 0; datatypes::Decimal::division(r, l, result); - dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); - EXPECT_EQ("86363636363636363636363.6363636364", std::string(buf)); + EXPECT_EQ("86363636363636363636363.6363636364", result.toString()); // same precision, L scale > R scale, +- values l.s128Value = 19; @@ -296,8 +281,7 @@ TEST(Decimal, divisionNoOverflowCheck) result.s128Value = 0; datatypes::Decimal::division(r, l, result); - dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); - EXPECT_EQ("-115789473684210526315789.4736842105", std::string(buf)); + EXPECT_EQ("-115789473684210526315789.4736842105", result.toString()); // same precision, L scale > R scale, R = 0 l.s128Value = 424242; @@ -313,8 +297,7 @@ TEST(Decimal, divisionNoOverflowCheck) result.s128Value = 0; datatypes::Decimal::division(r, l, result); - dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); - EXPECT_EQ("100000000000000000000000.0000000000", std::string(buf)); + EXPECT_EQ("100000000000000000000000.0000000000", result.toString()); // same precision, L scale > R scale, both MIN negative values utils::int128Min(l.s128Value); @@ -322,8 +305,7 @@ TEST(Decimal, divisionNoOverflowCheck) result.s128Value = 0; datatypes::Decimal::division(r, l, result); - dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); - EXPECT_EQ("100000000000000000000000.0000000000", std::string(buf)); + EXPECT_EQ("100000000000000000000000.0000000000", result.toString()); // same precision, L scale < R scale, both positive values l.scale = 15; @@ -339,8 +321,7 @@ TEST(Decimal, divisionNoOverflowCheck) result.s128Value = 0; datatypes::Decimal::division(r, l, result); - dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); - EXPECT_EQ("0.00000000000000000000001000000000000000", std::string(buf)); + EXPECT_EQ("0.00000000000000000000001000000000000000", result.toString()); // same precision, L scale < R scale, both negative values l.s128Value = -22; @@ -348,8 +329,7 @@ TEST(Decimal, divisionNoOverflowCheck) result.s128Value = 0; datatypes::Decimal::division(r, l, result); - dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); - EXPECT_EQ("0.00000000000000000000000863636363636364", std::string(buf)); + EXPECT_EQ("0.00000000000000000000000863636363636364", result.toString()); // same precision, L scale < R scale, +- values l.s128Value = 22; @@ -357,8 +337,7 @@ TEST(Decimal, divisionNoOverflowCheck) result.s128Value = 0; datatypes::Decimal::division(r, l, result); - dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); - EXPECT_EQ("-0.00000000000000000000000863636363636364", std::string(buf)); + EXPECT_EQ("-0.00000000000000000000000863636363636364", result.toString()); // same precision, L scale < R scale, R = 0 l.s128Value = 42; @@ -375,8 +354,7 @@ TEST(Decimal, divisionNoOverflowCheck) result.s128Value = 0; datatypes::Decimal::division(r, l, result); - dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); - EXPECT_EQ("0.00000000000000000000001000000000000000", std::string(buf)); + EXPECT_EQ("0.00000000000000000000001000000000000000", result.toString()); // same precision, L scale < R scale, both MIN negative values utils::int128Min(l.s128Value); @@ -384,8 +362,7 @@ TEST(Decimal, divisionNoOverflowCheck) result.s128Value = 0; datatypes::Decimal::division(r, l, result); - dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); - EXPECT_EQ("0.00000000000000000000001000000000000000", std::string(buf)); + EXPECT_EQ("0.00000000000000000000001000000000000000", result.toString()); // same precision, L scale < R scale, result.scale < (r.scale-l.scale) // both positive values @@ -402,8 +379,7 @@ TEST(Decimal, divisionNoOverflowCheck) result.s128Value = 0; datatypes::Decimal::division(r, l, result); - dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); - EXPECT_EQ("1", std::string(buf)); + EXPECT_EQ("1", result.toString()); // same precision, L scale < R scale, result.scale < (r.scale-l.scale) // both negative values @@ -412,8 +388,7 @@ TEST(Decimal, divisionNoOverflowCheck) result.s128Value = 0; datatypes::Decimal::division(r, l, result); - dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); - EXPECT_EQ("9", std::string(buf)); + EXPECT_EQ("9", result.toString()); // same precision, L scale < R scale, result.scale < (r.scale-l.scale) // +- values @@ -422,8 +397,7 @@ TEST(Decimal, divisionNoOverflowCheck) result.s128Value = 0; datatypes::Decimal::division(r, l, result); - dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); - EXPECT_EQ("-9", std::string(buf)); + EXPECT_EQ("-9", result.toString()); // same precision, L scale < R scale, result.scale < (r.scale-l.scale) // R = 0 @@ -441,8 +415,7 @@ TEST(Decimal, divisionNoOverflowCheck) result.s128Value = 0; datatypes::Decimal::division(r, l, result); - dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); - EXPECT_EQ("0", std::string(buf)); + EXPECT_EQ("0", result.toString()); // same precision, L scale < R scale, result.scale < (r.scale-l.scale) // both MIN negative values @@ -451,8 +424,7 @@ TEST(Decimal, divisionNoOverflowCheck) result.s128Value = 0; datatypes::Decimal::division(r, l, result); - dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); - EXPECT_EQ("0", std::string(buf)); + EXPECT_EQ("0", result.toString()); } void doDiv(const execplan::IDB_Decimal& l, @@ -464,8 +436,6 @@ void doDiv(const execplan::IDB_Decimal& l, TEST(Decimal, divisionWithOverflowCheck) { - datatypes::SystemCatalog::ColDataType colDataType = datatypes::SystemCatalog::DECIMAL; - char buf[42]; // Divide min int128 by -1 execplan::IDB_Decimal l, r, result; l.scale = 0; @@ -503,8 +473,7 @@ TEST(Decimal, divisionWithOverflowCheck) result.s128Value = 0; EXPECT_NO_THROW(doDiv(l, r, result)); - dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); - EXPECT_EQ("9223372036854775809", std::string(buf)); + EXPECT_EQ("9223372036854775809", result.toString()); } void doAdd(const execplan::IDB_Decimal& l, @@ -516,8 +485,6 @@ void doAdd(const execplan::IDB_Decimal& l, TEST(Decimal, additionWithOverflowCheck) { - datatypes::SystemCatalog::ColDataType colDataType = datatypes::SystemCatalog::DECIMAL; - char buf[42]; // Add two max ints execplan::IDB_Decimal l, r, result; l.scale = 0; @@ -555,14 +522,11 @@ TEST(Decimal, additionWithOverflowCheck) result.s128Value = 0; EXPECT_NO_THROW(doAdd(l, r, result)); - dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); - EXPECT_EQ("-170141183460469231713240559642174554113", std::string(buf)); + EXPECT_EQ("-170141183460469231713240559642174554113", result.toString()); } TEST(Decimal, subtractionNoOverflowCheck) { - datatypes::SystemCatalog::ColDataType colDataType = datatypes::SystemCatalog::DECIMAL; - char buf[42]; // Subtractio w/o overflow check execplan::IDB_Decimal l, r, result; // same precision, same scale, both positive values @@ -579,8 +543,7 @@ TEST(Decimal, subtractionNoOverflowCheck) result.s128Value = 0; datatypes::Decimal::subtraction(l, r, result); - dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); - EXPECT_EQ("-0.00000000000000000000000000000000000378", std::string(buf)); + EXPECT_EQ("-0.00000000000000000000000000000000000378", result.toString()); // same precision, same scale, both negative values l.s128Value = -42; @@ -588,8 +551,7 @@ TEST(Decimal, subtractionNoOverflowCheck) result.s128Value = 0; datatypes::Decimal::subtraction(l, r, result); - dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); - EXPECT_EQ("0.00000000000000000000000000000000000378", std::string(buf)); + EXPECT_EQ("0.00000000000000000000000000000000000378", result.toString()); // same precision, same scale, +- values l.s128Value = 42; @@ -597,8 +559,7 @@ TEST(Decimal, subtractionNoOverflowCheck) result.s128Value = 0; datatypes::Decimal::subtraction(l, r, result); - dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); - EXPECT_EQ("0.00000000000000000000000000000000000462", std::string(buf)); + EXPECT_EQ("0.00000000000000000000000000000000000462", result.toString()); // same precision, same scale, both 0 l.s128Value = 0; @@ -623,8 +584,7 @@ TEST(Decimal, subtractionNoOverflowCheck) result.s128Value = 0; datatypes::Decimal::subtraction(l, r, result); - dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); - EXPECT_EQ("-0.00000000000041999999999999999999999958", std::string(buf)); + EXPECT_EQ("-0.00000000000041999999999999999999999958", result.toString()); // same precision, L scale > R scale, both negative values l.s128Value = -42; @@ -632,8 +592,7 @@ TEST(Decimal, subtractionNoOverflowCheck) result.s128Value = 0; datatypes::Decimal::subtraction(l, r, result); - dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); - EXPECT_EQ("0.00000000000041999999999999999999999958", std::string(buf)); + EXPECT_EQ("0.00000000000041999999999999999999999958", result.toString()); // same precision, L scale > R scale, +- values l.s128Value = 42; @@ -641,8 +600,7 @@ TEST(Decimal, subtractionNoOverflowCheck) result.s128Value = 0; datatypes::Decimal::subtraction(l, r, result); - dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); - EXPECT_EQ("0.00000000000042000000000000000000000042", std::string(buf)); + EXPECT_EQ("0.00000000000042000000000000000000000042", result.toString()); // same precision, L scale > R scale, both 0 l.s128Value = 0; @@ -666,8 +624,7 @@ TEST(Decimal, subtractionNoOverflowCheck) result.s128Value = 0; datatypes::Decimal::subtraction(l, r, result); - dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); - EXPECT_EQ("0.00000000000004199999999999999999999580", std::string(buf)); + EXPECT_EQ("0.00000000000004199999999999999999999580", result.toString()); // same precision, L scale < R scale, both negative values l.s128Value = -42; @@ -675,8 +632,7 @@ TEST(Decimal, subtractionNoOverflowCheck) result.s128Value = 0; datatypes::Decimal::subtraction(l, r, result); - dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); - EXPECT_EQ("-0.00000000000004199999999999999999999580", std::string(buf)); + EXPECT_EQ("-0.00000000000004199999999999999999999580", result.toString()); // same precision, L scale < R scale, +- values l.s128Value = 42; @@ -684,8 +640,7 @@ TEST(Decimal, subtractionNoOverflowCheck) result.s128Value = 0; datatypes::Decimal::subtraction(l, r, result); - dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); - EXPECT_EQ("0.00000000000004200000000000000000000420", std::string(buf)); + EXPECT_EQ("0.00000000000004200000000000000000000420", result.toString()); // same precision, L scale < R scale, both 0 l.s128Value = 0; @@ -705,8 +660,6 @@ void doSubtract(const execplan::IDB_Decimal& l, TEST(Decimal, subtractionWithOverflowCheck) { - datatypes::SystemCatalog::ColDataType colDataType = datatypes::SystemCatalog::DECIMAL; - char buf[42]; // Subtract a max int from a min int execplan::IDB_Decimal l, r, result; l.scale = 0; @@ -744,16 +697,13 @@ TEST(Decimal, subtractionWithOverflowCheck) result.s128Value = 0; EXPECT_NO_THROW(doSubtract(l, r, result)); - dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); - EXPECT_EQ("170141183460469231713240559642174554112", std::string(buf)); + EXPECT_EQ("170141183460469231713240559642174554112", result.toString()); } TEST(Decimal, multiplicationNoOverflowCheck) { // Multiplication // same precision, l.scale + r.scale = result.scale, both positive values - datatypes::SystemCatalog::ColDataType colDataType = datatypes::SystemCatalog::DECIMAL; - char buf[42]; execplan::IDB_Decimal l, r, result; l.scale = 19; @@ -769,8 +719,7 @@ TEST(Decimal, multiplicationNoOverflowCheck) result.s128Value = 0; datatypes::Decimal::multiplication(r, l, result); - dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); - EXPECT_EQ("0.85070591730234615861231965839514664960", std::string(buf)); + EXPECT_EQ("0.85070591730234615861231965839514664960", result.toString()); // same precision, l.scale + r.scale = result.scale, both negative values l.s128Value = -4611686018427387904; @@ -779,8 +728,7 @@ TEST(Decimal, multiplicationNoOverflowCheck) result.s128Value = 0; datatypes::Decimal::multiplication(r, l, result); - dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); - EXPECT_EQ("0.85070591730234615861231965839514664960", std::string(buf)); + EXPECT_EQ("0.85070591730234615861231965839514664960", result.toString()); // same precision, l.scale + r.scale = result.scale, +- values l.s128Value = -4611686018427387904; @@ -788,8 +736,7 @@ TEST(Decimal, multiplicationNoOverflowCheck) result.s128Value = 0; datatypes::Decimal::multiplication(l, r, result); - dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); - EXPECT_EQ("-0.85070591730234615861231965839514664960", std::string(buf)); + EXPECT_EQ("-0.85070591730234615861231965839514664960", result.toString()); // same precision, l.scale + r.scale = result.scale, l = 0 l.s128Value = 0; @@ -813,8 +760,7 @@ TEST(Decimal, multiplicationNoOverflowCheck) result.s128Value = 0; datatypes::Decimal::multiplication(r, l, result); - dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); - EXPECT_EQ("0.66461399789245793645190353014017228800", std::string(buf)); + EXPECT_EQ("0.66461399789245793645190353014017228800", result.toString()); // same precision, l.scale + r.scale < result.scale, both negative values l.s128Value = -72057594037927936; @@ -823,8 +769,7 @@ TEST(Decimal, multiplicationNoOverflowCheck) result.s128Value = 0; datatypes::Decimal::multiplication(r, l, result); - dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); - EXPECT_EQ("0.66461399789245793645190353014017228800", std::string(buf)); + EXPECT_EQ("0.66461399789245793645190353014017228800", result.toString()); // same precision, l.scale + r.scale < result.scale, +- values l.s128Value = -72057594037927936; @@ -832,8 +777,7 @@ TEST(Decimal, multiplicationNoOverflowCheck) result.s128Value = 0; datatypes::Decimal::multiplication(l, r, result); - dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); - EXPECT_EQ("-0.66461399789245793645190353014017228800", std::string(buf)); + EXPECT_EQ("-0.66461399789245793645190353014017228800", result.toString()); // same precision, l.scale + r.scale < result.scale, l = 0 l.s128Value = 0; @@ -859,8 +803,7 @@ TEST(Decimal, multiplicationNoOverflowCheck) result.s128Value = 0; datatypes::Decimal::multiplication(r, l, result); - dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); - EXPECT_EQ("0.01524157875323883675019051998750190521", std::string(buf)); + EXPECT_EQ("0.01524157875323883675019051998750190521", result.toString()); // same precision, l.scale + r.scale > result.scale, both negative values l.s128Value = -l.s128Value; @@ -868,16 +811,14 @@ TEST(Decimal, multiplicationNoOverflowCheck) result.s128Value = 0; datatypes::Decimal::multiplication(r, l, result); - dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); - EXPECT_EQ("0.01524157875323883675019051998750190521", std::string(buf)); + EXPECT_EQ("0.01524157875323883675019051998750190521", result.toString()); // same precision, l.scale + r.scale > result.scale, +- values r.s128Value = -r.s128Value; result.s128Value = 0; datatypes::Decimal::multiplication(l, r, result); - dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); - EXPECT_EQ("-0.01524157875323883675019051998750190521", std::string(buf)); + EXPECT_EQ("-0.01524157875323883675019051998750190521", result.toString()); // same precision, l.scale + r.scale > result.scale, l = 0 r.s128Value = 0; @@ -896,8 +837,6 @@ void doMultiply(const execplan::IDB_Decimal& l, TEST(Decimal, multiplicationWithOverflowCheck) { - datatypes::SystemCatalog::ColDataType colDataType = datatypes::SystemCatalog::DECIMAL; - char buf[42]; execplan::IDB_Decimal l, r, result; // result.scale >= l.scale + r.scale l.scale = 0; @@ -940,6 +879,248 @@ TEST(Decimal, multiplicationWithOverflowCheck) result.s128Value = 0; EXPECT_NO_THROW(doMultiply(l, r, result)); - dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); - EXPECT_EQ("21267647932558653966460912964485513216", std::string(buf)); + EXPECT_EQ("21267647932558653966460912964485513216", result.toString()); } + +TEST(Decimal, DecimalToStringCheckScale0) +{ + string input, expected; + int128_t res; + int precision = 38; + int scale = 0; + res = 0; + datatypes::VDecimal dec(0, scale, precision, res); + + // test simple values + expected = "0"; + EXPECT_EQ(dec.toString(), expected); + res = 2; + expected = "2"; + dec.setTSInt128Value(res); + EXPECT_EQ(dec.toString(), expected); + res = -2; + expected = "-2"; + dec.setTSInt128Value(res); + EXPECT_EQ(dec.toString(), expected); + res = 123; + expected = "123"; + dec.setTSInt128Value(res); + EXPECT_EQ(dec.toString(), expected); + res = -123; + expected = "-123"; + dec.setTSInt128Value(res); + EXPECT_EQ(dec.toString(), expected); + + // test max/min decimal (i.e. 38 9's) + res = ((((((((int128_t)999999999 * 1000000000) + 999999999) * 1000000000) + 999999999) * 1000000000 ) + 999999999) * 100) + 99; + expected = "99999999999999999999999999999999999999"; + dec.setTSInt128Value(res); + EXPECT_EQ(dec.toString(), expected); + res = -res; + expected = "-99999999999999999999999999999999999999"; + dec.setTSInt128Value(res); + EXPECT_EQ(dec.toString(), expected); + + // test trailing zeros + res = 123000; + expected = "123000"; + dec.setTSInt128Value(res); + EXPECT_EQ(dec.toString(), expected); + res = -res; + expected = "-123000"; + dec.setTSInt128Value(res); + EXPECT_EQ(dec.toString(), expected); +} +TEST(Decimal, DecimalToStringCheckScale10) +{ + string input, expected; + int128_t res; + int precision = 38; + int scale = 10; + res = 0; + datatypes::VDecimal dec(0, scale, precision, res); + + // test simple values + expected = "0.0000000000"; + dec.setTSInt128Value(res); + EXPECT_EQ(dec.toString(), expected); + + res = 2; + expected = "0.0000000002"; + dec.setTSInt128Value(res); + EXPECT_EQ(dec.toString(), expected); + + res = -2; + expected = "-0.0000000002"; + dec.setTSInt128Value(res); + EXPECT_EQ(dec.toString(), expected); + + res = 123; + expected = "0.0000000123"; + dec.setTSInt128Value(res); + EXPECT_EQ(dec.toString(), expected); + res = -123; + expected = "-0.0000000123"; + dec.setTSInt128Value(res); + EXPECT_EQ(dec.toString(), expected); + res = 12345678901; + expected = "1.2345678901"; + dec.setTSInt128Value(res); + EXPECT_EQ(dec.toString(), expected); + res = -12345678901; + expected = "-1.2345678901"; + dec.setTSInt128Value(res); + EXPECT_EQ(dec.toString(), expected); + + // test max/min decimal (i.e. 38 9's) + res = ((((((((int128_t)999999999 * 1000000000) + 999999999) * 1000000000) + 999999999) * 1000000000 ) + 999999999) * 100) + 99; + expected = "9999999999999999999999999999.9999999999"; + dec.setTSInt128Value(res); + EXPECT_EQ(dec.toString(), expected); + res = -res; + expected = "-9999999999999999999999999999.9999999999"; + dec.setTSInt128Value(res); + EXPECT_EQ(dec.toString(), expected); + + // test trailing zeros + res = 123000; + expected = "0.0000123000"; + dec.setTSInt128Value(res); + EXPECT_EQ(dec.toString(), expected); + res = -res; + expected = "-0.0000123000"; + dec.setTSInt128Value(res); + EXPECT_EQ(dec.toString(), expected); + + // test leading zeros + res = 10000000009; + expected = "1.0000000009"; + dec.setTSInt128Value(res); + EXPECT_EQ(dec.toString(), expected); + res = -res; + expected = "-1.0000000009"; + dec.setTSInt128Value(res); + EXPECT_EQ(dec.toString(), expected); +} + +TEST(Decimal, DecimalToStringCheckScale38) +{ + string input, expected; + int128_t res; + int precision = 38; + int scale = 38; + res = 0; + datatypes::VDecimal dec(0, scale, precision, res); + + // test simple values + res = 0; + expected = "0.00000000000000000000000000000000000000"; + dec.setTSInt128Value(res); + EXPECT_EQ(dec.toString(), expected); + res = 2; + expected = "0.00000000000000000000000000000000000002"; + dec.setTSInt128Value(res); + EXPECT_EQ(dec.toString(), expected); + res = -2; + expected = "-0.00000000000000000000000000000000000002"; + dec.setTSInt128Value(res); + EXPECT_EQ(dec.toString(), expected); + res = 123; + expected = "0.00000000000000000000000000000000000123"; + dec.setTSInt128Value(res); + EXPECT_EQ(dec.toString(), expected); + res = -123; + expected = "-0.00000000000000000000000000000000000123"; + dec.setTSInt128Value(res); + EXPECT_EQ(dec.toString(), expected); + res = ((((((int128_t)1234567890 * 10000000000) + 1234567890) * 10000000000) + 1234567890) * 100000000 ) + 12345678; + expected = "0.12345678901234567890123456789012345678"; + dec.setTSInt128Value(res); + EXPECT_EQ(dec.toString(), expected); + res = -res; + expected = "-0.12345678901234567890123456789012345678"; + dec.setTSInt128Value(res); + EXPECT_EQ(dec.toString(), expected); + + // test max/min decimal (i.e. 38 9's) + res = ((((((((int128_t)999999999 * 1000000000) + 999999999) * 1000000000) + 999999999) * 1000000000 ) + 999999999) * 100) + 99; + expected = "0.99999999999999999999999999999999999999"; + dec.setTSInt128Value(res); + EXPECT_EQ(dec.toString(), expected); + res = -res; + expected = "-0.99999999999999999999999999999999999999"; + dec.setTSInt128Value(res); + EXPECT_EQ(dec.toString(), expected); + + // test trailing zeros + res = 123000; + expected = "0.00000000000000000000000000000000123000"; + dec.setTSInt128Value(res); + EXPECT_EQ(dec.toString(), expected); + res = -res; + expected = "-0.00000000000000000000000000000000123000"; + dec.setTSInt128Value(res); + EXPECT_EQ(dec.toString(), expected); +} + +TEST(Decimal, DecimalToStringCheckScale37) +{ + string input, expected; + int128_t res; + int precision = 38; + int scale = 37; + res = 0; + datatypes::VDecimal dec(0, scale, precision, res); + + // test simple values + res = 0; + expected = "0.0000000000000000000000000000000000000"; + dec.setTSInt128Value(res); + EXPECT_EQ(dec.toString(), expected); + res = 2; + expected = "0.0000000000000000000000000000000000002"; + dec.setTSInt128Value(res); + EXPECT_EQ(dec.toString(), expected); + res = -2; + expected = "-0.0000000000000000000000000000000000002"; + dec.setTSInt128Value(res); + EXPECT_EQ(dec.toString(), expected); + res = 123; + expected = "0.0000000000000000000000000000000000123"; + dec.setTSInt128Value(res); + EXPECT_EQ(dec.toString(), expected); + res = -123; + expected = "-0.0000000000000000000000000000000000123"; + dec.setTSInt128Value(res); + EXPECT_EQ(dec.toString(), expected); + res = ((((((int128_t)1234567890 * 10000000000) + 1234567890) * 10000000000) + 1234567890) * 100000000 ) + 12345678; + expected = "1.2345678901234567890123456789012345678"; + dec.setTSInt128Value(res); + EXPECT_EQ(dec.toString(), expected); + res = -res; + expected = "-1.2345678901234567890123456789012345678"; + dec.setTSInt128Value(res); + EXPECT_EQ(dec.toString(), expected); + + // test max/min decimal (i.e. 38 9's) + res = ((((((((int128_t)999999999 * 1000000000) + 999999999) * 1000000000) + 999999999) * 1000000000 ) + 999999999) * 100) + 99; + expected = "9.9999999999999999999999999999999999999"; + dec.setTSInt128Value(res); + EXPECT_EQ(dec.toString(), expected); + res = -res; + expected = "-9.9999999999999999999999999999999999999"; + dec.setTSInt128Value(res); + EXPECT_EQ(dec.toString(), expected); + + // test trailing zeros + res = 123000; + expected = "0.0000000000000000000000000000000123000"; + dec.setTSInt128Value(res); + EXPECT_EQ(dec.toString(), expected); + res = -res; + expected = "-0.0000000000000000000000000000000123000"; + dec.setTSInt128Value(res); + EXPECT_EQ(dec.toString(), expected); +} + + diff --git a/tools/editem/editem.cpp b/tools/editem/editem.cpp index dd39875df..e106db90d 100644 --- a/tools/editem/editem.cpp +++ b/tools/editem/editem.cpp @@ -191,14 +191,7 @@ const string fmt(T v) } else { - char buf[datatypes::Decimal::MAXLENGTH16BYTES]; - - int128_t tmp = v; - - dataconvert::DataConvert::decimalToString( - &tmp, 0, buf, (uint8_t) sizeof(buf), datatypes::SystemCatalog::DECIMAL); - - oss << buf; + oss << datatypes::TSInt128(v); } } else if (uflg) @@ -218,14 +211,7 @@ const string fmt(T v) } else { - char buf[datatypes::Decimal::MAXLENGTH16BYTES]; - - int128_t tmp = static_cast(v); - - dataconvert::DataConvert::decimalToString( - &tmp, 0, buf, (uint8_t) sizeof(buf), datatypes::SystemCatalog::DECIMAL); - - oss << buf; + oss << datatypes::TSInt128(v); } } } @@ -247,14 +233,7 @@ const string fmt(T v) } else { - char buf[datatypes::Decimal::MAXLENGTH16BYTES]; - - int128_t tmp = v; - - dataconvert::DataConvert::decimalToString( - &tmp, 0, buf, (uint8_t) sizeof(buf), datatypes::SystemCatalog::DECIMAL); - - oss << buf; + oss << datatypes::TSInt128(v); } } } diff --git a/utils/dataconvert/dataconvert.cpp b/utils/dataconvert/dataconvert.cpp index 12a766976..11c40c221 100644 --- a/utils/dataconvert/dataconvert.cpp +++ b/utils/dataconvert/dataconvert.cpp @@ -1204,175 +1204,6 @@ bool stringToTimestampStruct(const string& data, TimeStamp& timeStamp, const str } -size_t DataConvert::writeIntPart(int128_t* dec, - char* p, - const unsigned int buflen, - const uint8_t scale) -{ - int128_t intPart = *dec; - int128_t high = 0, mid = 0, low = 0; - uint64_t maxUint64divisor = 10000000000000000000ULL; - - if (scale) - { - // Assuming scale = [0, 56] - switch (scale / datatypes::maxPowOf10) - { - case 2: // scale = [38, 56] - intPart /= datatypes::mcs_pow_10[datatypes::maxPowOf10]; - intPart /= datatypes::mcs_pow_10[datatypes::maxPowOf10]; - low = intPart; - break; - case 1: // scale = [19, 37] - intPart /= datatypes::mcs_pow_10[datatypes::maxPowOf10]; - intPart /= datatypes::mcs_pow_10[scale % datatypes::maxPowOf10]; - low = intPart % maxUint64divisor; - mid = intPart / maxUint64divisor; - break; - case 0: // scale = [0, 18] - intPart /= datatypes::mcs_pow_10[scale % datatypes::maxPowOf10]; - low = intPart % maxUint64divisor; - intPart /= maxUint64divisor; - mid = intPart % maxUint64divisor; - high = intPart / maxUint64divisor; - break; - default: - throw QueryDataExcept("writeIntPart() bad scale", formatErr); - } - } - else - { - low = intPart % maxUint64divisor; - intPart /= maxUint64divisor; - mid = intPart % maxUint64divisor; - high = intPart / maxUint64divisor; - } - - // pod[0] is low 8 bytes, pod[1] is high 8 bytes - uint64_t* high_pod = reinterpret_cast(&high); - uint64_t* mid_pod = reinterpret_cast(&mid); - uint64_t* low_pod = reinterpret_cast(&low); - char* original_p = p; - - // WIP replace sprintf with streams - if (high_pod[0] != 0) - { - p += sprintf(p, "%lu", high_pod[0]); - p += sprintf(p, "%019lu", mid_pod[0]); - p += sprintf(p, "%019lu", low_pod[0]); - } - else if (mid_pod[0] != 0) - { - p += sprintf(p, "%lu", mid_pod[0]); - p += sprintf(p, "%019lu", low_pod[0]); - } - else - { - p += sprintf(p, "%lu", low_pod[0]); - } - - size_t written = p - original_p; - - if (buflen <= written) - { - throw QueryDataExcept("writeIntPart() char buffer overflow.", formatErr); - } - - return written; -} - -size_t DataConvert::writeFractionalPart(int128_t* dec, - char* p, - const unsigned int buflen, - const uint8_t scale) -{ - int128_t scaleDivisor = 1; - - switch (scale / datatypes::maxPowOf10) - { - case 2: - scaleDivisor *= datatypes::mcs_pow_10[datatypes::maxPowOf10]; - scaleDivisor *= datatypes::mcs_pow_10[datatypes::maxPowOf10]; - break; - case 1: - scaleDivisor *= datatypes::mcs_pow_10[datatypes::maxPowOf10]; - case 0: - scaleDivisor *= datatypes::mcs_pow_10[scale % datatypes::maxPowOf10]; - } - - int128_t fractionalPart = *dec % scaleDivisor; - - // divide by the base until we have non-zero quotient - size_t written = 0; - scaleDivisor /= 10; - - char* original_p = p; - - while (scaleDivisor > 1 && fractionalPart / scaleDivisor == 0) - { - *p++ = '0'; - written++; - scaleDivisor /= 10; - } - - p += writeIntPart(&fractionalPart, p, buflen - written, 0); - - written = p - original_p; - - // this should never be true - if (written < scale) - { - for (size_t left = written; left < scale; left++) - { - *p++ = '0'; - } - } - - return written; -} - -void DataConvert::decimalToString(int128_t* dec, - const uint8_t scale, - char *p, - const unsigned int buflen, - cscDataType colDataType) // colDataType is redundant -{ - char* original_p = p; - size_t written = 0; - // Raise exception on NULL and EMPTY value - if (datatypes::Decimal::isWideDecimalNullValue(*dec) || - datatypes::Decimal::isWideDecimalEmptyValue(*dec)) - { - throw QueryDataExcept("toString() char buffer overflow.", formatErr); - } - - if (*dec < static_cast(0)) - { - *p++ = '-'; - *dec *= -1; - } - - written = writeIntPart(dec, p, buflen, scale); - p += written; - - if (scale) - { - *p++ = '.'; - written = p - original_p; - p += writeFractionalPart(dec, p, buflen - written, scale); - } - - *p = '\0'; - - written = p - original_p; - - if (buflen <= written) - { - throw QueryDataExcept("toString() char buffer overflow.", formatErr); - } -} - - boost::any DataConvert::StringToBit(const datatypes::SystemCatalog::TypeAttributesStd& colType, const datatypes::ConvertFromStringParam &prm, diff --git a/utils/dataconvert/dataconvert.h b/utils/dataconvert/dataconvert.h index 794544b77..5cbd28929 100644 --- a/utils/dataconvert/dataconvert.h +++ b/utils/dataconvert/dataconvert.h @@ -1037,15 +1037,6 @@ public: EXPORT static bool isColumnTimeValid( int64_t time ); EXPORT static bool isColumnTimeStampValid( int64_t timeStamp ); - static inline std::string decimalToString(int64_t value, uint8_t scale, cscDataType colDataType); - static inline void decimalToString(int64_t value, uint8_t scale, char* buf, unsigned int buflen, cscDataType colDataType); - - static void decimalToString(int128_t* dec, const uint8_t scale, char* buf, const unsigned int buflen, cscDataType colDataType); - static size_t writeIntPart(int128_t* dec, char* p, const unsigned int buflen, - const uint8_t scale); - static size_t writeFractionalPart(int128_t* dec, char* p, const unsigned int buflen, - const uint8_t scale); - static inline std::string constructRegexp(const std::string& str); static inline void trimWhitespace(int64_t& charData); static inline bool isEscapedChar(char c) @@ -1298,96 +1289,6 @@ inline void DataConvert::timeToString1( long long timevalue, char* buf, unsigned #endif } -inline std::string DataConvert::decimalToString(int64_t value, uint8_t scale, cscDataType colDataType) -{ - // This is too much - char buf[80]; - DataConvert::decimalToString(value, scale, buf, 80, colDataType); - return std::string(buf); -} - -inline void DataConvert::decimalToString(int64_t int_val, uint8_t scale, - char* buf, unsigned int buflen, cscDataType colDataType) -{ - // Need to convert a string with a binary unsigned number in it to a 64-bit signed int - - // MySQL seems to round off values unless we use the string store method. Groan. - // Taken from ha_mcs_impl.cpp - - //biggest Calpont supports is DECIMAL(18,x), or 18 total digits+dp+sign for column - // Need 19 digits maxium to hold a sum result of 18 digits decimal column. - if (isUnsigned(colDataType)) - { -#ifndef __LP64__ - snprintf(buf, buflen, "%llu", static_cast(int_val)); -#else - snprintf(buf, buflen, "%lu", static_cast(int_val)); -#endif - } - else - { -#ifndef __LP64__ - snprintf(buf, buflen, "%lld", int_val); -#else - snprintf(buf, buflen, "%ld", int_val); -#endif - } - - if (scale == 0) - return; - - //we want to move the last dt_scale chars right by one spot to insert the dp - //we want to move the trailing null as well, so it's really dt_scale+1 chars - size_t l1 = strlen(buf); - char* ptr = &buf[0]; - - if (int_val < 0) - { - ptr++; - idbassert(l1 >= 2); - l1--; - } - - //need to make sure we have enough leading zeros for this to work... - //at this point scale is always > 0 - size_t l2 = 1; - - if ((unsigned)scale > l1) - { - const char* zeros = "00000000000000000000"; //20 0's - size_t diff = 0; - - if (int_val != 0) - diff = scale - l1; //this will always be > 0 - else - diff = scale; - - memmove((ptr + diff), ptr, l1 + 1); //also move null - memcpy(ptr, zeros, diff); - - if (int_val != 0) - l1 = 0; - else - l1 = 1; - } - else if ((unsigned)scale == l1) - { - l1 = 0; - l2 = 2; - } - else - { - l1 -= scale; - } - - memmove((ptr + l1 + l2), (ptr + l1), scale + 1); //also move null - - if (l2 == 2) - *(ptr + l1++) = '0'; - - *(ptr + l1) = '.'; -} - inline void DataConvert::trimWhitespace(int64_t& charData) { // Trims whitespace characters off non-dict character data diff --git a/utils/funcexp/func_cast.cpp b/utils/funcexp/func_cast.cpp index a4c9fbe49..aa0212a48 100644 --- a/utils/funcexp/func_cast.cpp +++ b/utils/funcexp/func_cast.cpp @@ -542,15 +542,10 @@ string Func_cast_char::getStrVal(Row& row, { IDB_Decimal d = parm[0]->data()->getDecimalVal(row, isNull); - char buf[80]; - if (parm[0]->data()->resultType().colWidth == datatypes::MAXDECIMALWIDTH) - dataconvert::DataConvert::decimalToString( &d.s128Value, d.scale, buf, 80, parm[0]->data()->resultType().colDataType); + return d.toString(true).substr(0, length); else - dataconvert::DataConvert::decimalToString( d.value, d.scale, buf, 80, parm[0]->data()->resultType().colDataType); - - string sbuf = buf; - return sbuf.substr(0, length); + return d.toString().substr(0, length); } break; @@ -1231,17 +1226,10 @@ string Func_cast_decimal::getStrVal(Row& row, parm, isNull, operationColType); - - char buf[80]; - - if (decimal.precision > datatypes::INT64MAXPRECISION) - dataconvert::DataConvert::decimalToString( &decimal.s128Value, decimal.scale, buf, 80, operationColType.colDataType); + if (operationColType.colWidth == datatypes::MAXDECIMALWIDTH) + return decimal.toString(true); else - dataconvert::DataConvert::decimalToString( decimal.value, decimal.scale, buf, 80, operationColType.colDataType); - - string value = buf; - return value; - + return decimal.toString(); } diff --git a/utils/funcexp/func_ceil.cpp b/utils/funcexp/func_ceil.cpp index d78fab53b..de374af85 100644 --- a/utils/funcexp/func_ceil.cpp +++ b/utils/funcexp/func_ceil.cpp @@ -515,11 +515,11 @@ string Func_ceil::getStrVal(Row& row, if (op_ct.colWidth == datatypes::MAXDECIMALWIDTH) { - dataconvert::DataConvert::decimalToString(&d.s128Value, d.scale, tmp, 511, op_ct.colDataType); + return d.toString(true); } else { - dataconvert::DataConvert::decimalToString(d.value, d.scale, tmp, 511, op_ct.colDataType); + return d.toString(); } } else if (isUnsigned(op_ct.colDataType)) diff --git a/utils/funcexp/func_floor.cpp b/utils/funcexp/func_floor.cpp index a8afa77f1..3252fa031 100644 --- a/utils/funcexp/func_floor.cpp +++ b/utils/funcexp/func_floor.cpp @@ -436,11 +436,11 @@ string Func_floor::getStrVal(Row& row, if (op_ct.colWidth == datatypes::MAXDECIMALWIDTH) { - dataconvert::DataConvert::decimalToString(&d.s128Value, d.scale, tmp, 511, op_ct.colDataType); + return d.toString(true); } else { - dataconvert::DataConvert::decimalToString(d.value, d.scale, tmp, 511, op_ct.colDataType); + return d.toString(); } } else if (isUnsigned(op_ct.colDataType)) diff --git a/utils/funcexp/func_math.cpp b/utils/funcexp/func_math.cpp index fd0c0753b..a64e8fd75 100644 --- a/utils/funcexp/func_math.cpp +++ b/utils/funcexp/func_math.cpp @@ -1849,8 +1849,7 @@ string Func_format::getStrVal(Row& row, { IDB_Decimal decimal = parm[0]->data()->getDecimalVal(row, isNull); - char buf[80]; - + // This is an unacceptable way of doing rounding //perform rouding if needed if ( scale < 0 ) scale = 0; @@ -1912,9 +1911,7 @@ string Func_format::getStrVal(Row& row, decimal.s128Value = x; } - - dataconvert::DataConvert::decimalToString(&decimal.s128Value, - decimal.scale, buf, 80, parm[0]->data()->resultType().colDataType); + value = decimal.toString(true); } else { @@ -1973,12 +1970,8 @@ string Func_format::getStrVal(Row& row, decimal.value = x; } - - dataconvert::DataConvert::decimalToString( decimal.value, - decimal.scale, buf, 80, parm[0]->data()->resultType().colDataType); + value = decimal.toString(); } - - value = buf; } break; diff --git a/utils/funcexp/func_regexp.cpp b/utils/funcexp/func_regexp.cpp index 4a484c8e3..0fa61b0a0 100644 --- a/utils/funcexp/func_regexp.cpp +++ b/utils/funcexp/func_regexp.cpp @@ -116,18 +116,15 @@ inline bool getBool(rowgroup::Row& row, { IDB_Decimal d = pm[0]->data()->getDecimalVal(row, isNull); - char buf[80]; - if (pm[0]->data()->resultType().colWidth == datatypes::MAXDECIMALWIDTH) { - dataconvert::DataConvert::decimalToString(&d.s128Value, d.scale, buf, 80, pm[0]->data()->resultType().colDataType); + expr = d.toString(true); } else { - dataconvert::DataConvert::decimalToString(d.value, d.scale, buf, 80, pm[0]->data()->resultType().colDataType); + expr = d.toString(); } - expr = buf; break; } @@ -198,18 +195,14 @@ inline bool getBool(rowgroup::Row& row, { IDB_Decimal d = pm[1]->data()->getDecimalVal(row, isNull); - char buf[80]; - if (pm[1]->data()->resultType().colWidth == datatypes::MAXDECIMALWIDTH) { - dataconvert::DataConvert::decimalToString(&d.s128Value, d.scale, buf, 80, pm[1]->data()->resultType().colDataType); + pattern = d.toString(true); } else { - dataconvert::DataConvert::decimalToString(d.value, d.scale, buf, 80, pm[1]->data()->resultType().colDataType); + pattern = d.toString(); } - - pattern = buf; break; } diff --git a/utils/funcexp/func_round.cpp b/utils/funcexp/func_round.cpp index 4e3ad260c..b034cf3b3 100644 --- a/utils/funcexp/func_round.cpp +++ b/utils/funcexp/func_round.cpp @@ -721,13 +721,9 @@ string Func_round::getStrVal(Row& row, } if (!op_ct.isWideDecimalType()) - return dataconvert::DataConvert::decimalToString(x.value, x.scale, op_ct.colDataType); + return x.toString(); else - { - char buf[datatypes::Decimal::MAXLENGTH16BYTES]; - dataconvert::DataConvert::decimalToString( &x.s128Value, x.scale, buf, (uint8_t) sizeof(buf), op_ct.colDataType); - return string(buf); - } + return x.toString(true); } diff --git a/utils/funcexp/func_truncate.cpp b/utils/funcexp/func_truncate.cpp index 9ab383774..02455de61 100644 --- a/utils/funcexp/func_truncate.cpp +++ b/utils/funcexp/func_truncate.cpp @@ -740,13 +740,9 @@ string Func_truncate::getStrVal(Row& row, } if (!op_ct.isWideDecimalType()) - return dataconvert::DataConvert::decimalToString(x.value, x.scale, op_ct.colDataType); + return x.toString(); else - { - char buf[datatypes::Decimal::MAXLENGTH16BYTES]; - dataconvert::DataConvert::decimalToString( &x.s128Value, x.scale, buf, (uint8_t) sizeof(buf), op_ct.colDataType); - return string(buf); - } + return x.toString(true); } diff --git a/utils/funcexp/funchelpers.h b/utils/funcexp/funchelpers.h index 709d441bc..3317a5f69 100644 --- a/utils/funcexp/funchelpers.h +++ b/utils/funcexp/funchelpers.h @@ -785,10 +785,6 @@ string longDoubleToString(long double ld) return buf; } -//@bug6146, remove duplicate function with incorrect impl. Use the DataConvert::decimalToString() -//string decimalToString( execplan::IDB_Decimal x, int p ) - - uint64_t dateAdd( uint64_t time, const std::string& expr, execplan::IntervalColumn::interval_type unit, bool dateType, execplan::OpType funcType ); const std::string IDB_date_format(const dataconvert::DateTime&, const std::string&); const std::string timediff(int64_t, int64_t, bool isDateTime = true); diff --git a/utils/rowgroup/rowgroup.cpp b/utils/rowgroup/rowgroup.cpp index fbeb69ab7..d477bafc3 100644 --- a/utils/rowgroup/rowgroup.cpp +++ b/utils/rowgroup/rowgroup.cpp @@ -640,12 +640,11 @@ string Row::toString() const case CalpontSystemCatalog::UDECIMAL: if (colWidths[i] == datatypes::MAXDECIMALWIDTH) { - unsigned int buflen = datatypes::Decimal::MAXLENGTH16BYTES; - char *buf = (char*)alloca(buflen); - // empty the buffer - dataconvert::DataConvert::decimalToString(getBinaryField(i), - scale[i], buf, buflen, types[i]); - os << buf << " "; + datatypes::VDecimal dec(0, + scale[i], + precision[i], + getBinaryField(i)); + os << dec << " "; break; } //fallthrough diff --git a/writeengine/bulk/we_brmreporter.cpp b/writeengine/bulk/we_brmreporter.cpp index 229a8c333..5517325e1 100644 --- a/writeengine/bulk/we_brmreporter.cpp +++ b/writeengine/bulk/we_brmreporter.cpp @@ -300,7 +300,6 @@ void BRMReporter::sendCPToFile( ) { if (fCPInfo.size() > 0) { - char buf[datatypes::Decimal::MAXLENGTH16BYTES]; std::ostringstream oss; oss << "Writing " << fCPInfo.size() << " CP updates for table " << fTableName << " to report file " << fRptFileName; @@ -319,14 +318,9 @@ void BRMReporter::sendCPToFile( ) } else { - std::string bigMin, bigMax; - - dataconvert::DataConvert::decimalToString(&fCPInfo[i].bigMin, 0, buf, (uint8_t) sizeof(buf), fCPInfo[i].type); - bigMin = buf; - - dataconvert::DataConvert::decimalToString(&fCPInfo[i].bigMax, 0, buf, (uint8_t) sizeof(buf), fCPInfo[i].type); - bigMax = buf; - + datatypes::TSInt128 bigMin(&fCPInfo[i].bigMin); + datatypes::TSInt128 bigMax(&fCPInfo[i].bigMax); + fRptFile << "CP: " << fCPInfo[i].startLbid << ' ' << bigMax << ' ' << bigMin << ' ' << diff --git a/writeengine/server/we_dmlcommandproc.cpp b/writeengine/server/we_dmlcommandproc.cpp index 3eeed68fc..0753ac7b8 100644 --- a/writeengine/server/we_dmlcommandproc.cpp +++ b/writeengine/server/we_dmlcommandproc.cpp @@ -2994,16 +2994,11 @@ uint8_t WE_DMLCommandProc::processUpdate(messageqcpp::ByteStream& bs, { if (fetchColColwidths[fetchColPos] == datatypes::MAXDECIMALWIDTH) { - int128_t* dec; - char buf[datatypes::Decimal::MAXLENGTH16BYTES]; - dec = row.getBinaryField(fetchColPos); - - dataconvert::DataConvert::decimalToString(dec, - (unsigned)fetchColScales[fetchColPos], buf, - (uint8_t) sizeof(buf), fetchColTypes[fetchColPos]); - - value.assign(buf); - + datatypes::VDecimal dec(0, + fetchColScales[fetchColPos], + rowGroups[txnId]->getPrecision()[fetchColPos], + row.getBinaryField(fetchColPos)); + value = dec.toString(true); break; } } @@ -3042,12 +3037,10 @@ uint8_t WE_DMLCommandProc::processUpdate(messageqcpp::ByteStream& bs, } else { - const int ctmp_size = 65 + 1 + 1 + 1; - char ctmp[ctmp_size] = {0}; - DataConvert::decimalToString( - intColVal, fetchColScales[fetchColPos], - ctmp, ctmp_size, fetchColTypes[fetchColPos]); - value = ctmp; // null termination by decimalToString + datatypes::VDecimal dec(intColVal, + fetchColScales[fetchColPos], + rowGroups[txnId]->getPrecision()[fetchColPos]); + value = dec.toString(); } } break; @@ -3356,16 +3349,11 @@ uint8_t WE_DMLCommandProc::processUpdate(messageqcpp::ByteStream& bs, { if (fetchColColwidths[fetchColPos] == datatypes::MAXDECIMALWIDTH) { - int128_t* dec; - char buf[datatypes::Decimal::MAXLENGTH16BYTES]; - dec = row.getBinaryField(fetchColPos); - - dataconvert::DataConvert::decimalToString(dec, - (unsigned)fetchColScales[fetchColPos], buf, - (uint8_t) sizeof(buf), fetchColTypes[fetchColPos]); - - value = buf; - + datatypes::VDecimal dec(0, + fetchColScales[fetchColPos], + rowGroups[txnId]->getPrecision()[fetchColPos], + row.getBinaryField(fetchColPos)); + value = dec.toString(true); break; } } @@ -3405,12 +3393,10 @@ uint8_t WE_DMLCommandProc::processUpdate(messageqcpp::ByteStream& bs, } else { - const int ctmp_size = 65 + 1 + 1 + 1; - char ctmp[ctmp_size] = {0}; - DataConvert::decimalToString( - intColVal, fetchColScales[fetchColPos], - ctmp, ctmp_size, fetchColTypes[fetchColPos]); - value = ctmp; // null termination by decimalToString + datatypes::VDecimal dec(intColVal, + fetchColScales[fetchColPos], + rowGroups[txnId]->getPrecision()[fetchColPos]); + value = dec.toString(); } } break; diff --git a/writeengine/wrapper/writeengine.cpp b/writeengine/wrapper/writeengine.cpp index 2b5948a92..de9853f5d 100644 --- a/writeengine/wrapper/writeengine.cpp +++ b/writeengine/wrapper/writeengine.cpp @@ -3896,11 +3896,8 @@ void WriteEngineWrapper::printInputValue(const ColStructList& colStructList, curStr = boost::lexical_cast(boost::any_cast(curTuple.data)); else if (curTuple.data.type() == typeid(int128_t)) { - // WIP replace with a single call - char buf[datatypes::Decimal::MAXLENGTH16BYTES]; - int128_t val = boost::any_cast(curTuple.data); - dataconvert::DataConvert::decimalToString(&val, 0, buf, (uint8_t) sizeof(buf), curColStruct.colDataType); - curStr.assign(buf); + datatypes::TSInt128 val(boost::any_cast(curTuple.data)); + curStr = val.toString(); } else if (curTuple.data.type() == typeid(double)) curStr = boost::lexical_cast(boost::any_cast(curTuple.data));