1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2025-06-13 16:01:32 +03:00

MCOL-4387 Convert dataconvert::decimalToString() into VDecimal and TSInt128 methods

This commit is contained in:
Roman Nozdrin
2020-11-10 17:27:16 +00:00
parent 007b8a5082
commit 58495d0d2f
29 changed files with 793 additions and 878 deletions

View File

@ -632,16 +632,20 @@ int TypeHandlerSLongDouble::storeValueToField(rowgroup::Row &row, int pos,
int TypeHandlerXDecimal::storeValueToField64(rowgroup::Row &row, int pos, int TypeHandlerXDecimal::storeValueToField64(rowgroup::Row &row, int pos,
StoreField *f) const StoreField *f) const
{ {
int64_t val = row.getIntField(pos); return f->store_decimal64(datatypes::VDecimal(row.getIntField(pos),
return f->store_decimal64(val); f->scale(),
f->precision()));
} }
int TypeHandlerXDecimal::storeValueToField128(rowgroup::Row &row, int pos, int TypeHandlerXDecimal::storeValueToField128(rowgroup::Row &row, int pos,
StoreField *f) const StoreField *f) const
{ {
int128_t* dec= row.getBinaryField<int128_t>(pos); int128_t* decPtr = row.getBinaryField<int128_t>(pos);
return f->store_decimal128(*dec); return f->store_decimal128(datatypes::VDecimal(0,
f->scale(),
f->precision(),
decPtr));
} }
@ -780,12 +784,8 @@ TypeHandlerXDecimal::format128(const SimpleValue &v,
const const
{ {
idbassert(isValidXDecimal128(attr)); idbassert(isValidXDecimal128(attr));
ostringstream oss; datatypes::VDecimal dec(0, attr.scale, attr.precision, v.toSInt128());
char buf[datatypes::Decimal::MAXLENGTH16BYTES]; return dec.toString(true);
int128_t tmp= v.toSInt128();
DataConvert::decimalToString(&tmp, (unsigned) attr.scale, buf, (uint8_t) sizeof(buf), code());
oss << buf;
return oss.str();
} }

View File

@ -720,6 +720,7 @@ public:
virtual ~StoreField() {} virtual ~StoreField() {}
virtual int32_t colWidth() const = 0; virtual int32_t colWidth() const = 0;
virtual int32_t precision() 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_date(int64_t val) = 0;
virtual int store_datetime(int64_t val) = 0; virtual int store_datetime(int64_t val) = 0;
virtual int store_time(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_float(float val) = 0;
virtual int store_double(double val) = 0; virtual int store_double(double val) = 0;
virtual int store_long_double(long double val) = 0; virtual int store_long_double(long double val) = 0;
virtual int store_decimal64(int64_t val) = 0; virtual int store_decimal64(const datatypes::VDecimal& dec) = 0;
virtual int store_decimal128(const int128_t &val) = 0; virtual int store_decimal128(const datatypes::VDecimal& dec) = 0;
virtual int store_lob(const char *str, size_t length) = 0; virtual int store_lob(const char *str, size_t length) = 0;
}; };

View File

@ -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<VDecimal&>(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<int128_t&>(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) int Decimal::compare(const VDecimal& l, const VDecimal& r)
{ {
int128_t divisorL, divisorR; 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<int128_t>(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 } // end of namespace

View File

@ -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 uint32_t maxPowOf10 = sizeof(mcs_pow_10)/sizeof(mcs_pow_10[0])-1;
constexpr int128_t Decimal128Null = int128_t(0x8000000000000000LL) << 64; constexpr int128_t Decimal128Null = TSInt128::NullValue;
constexpr int128_t Decimal128Empty = (int128_t(0x8000000000000000LL) << 64) + 1; constexpr int128_t Decimal128Empty = TSInt128::EmptyValue;
/** /**
@ -172,7 +172,7 @@ class Decimal
Decimal() { }; Decimal() { };
~Decimal() { }; ~Decimal() { };
static constexpr uint8_t MAXLENGTH16BYTES = 42; static constexpr uint8_t MAXLENGTH16BYTES = TSInt128::maxLength();
static constexpr uint8_t MAXLENGTH8BYTES = 23; static constexpr uint8_t MAXLENGTH8BYTES = 23;
static inline bool isWideDecimalNullValue(const int128_t& val) static inline bool isWideDecimalNullValue(const int128_t& val)
@ -259,13 +259,6 @@ class Decimal
const VDecimal& r, const VDecimal& r,
VDecimal& result); 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 @brief The method detects whether decimal type is wide
using precision. using precision.
@ -558,6 +551,14 @@ class VDecimal: public TSInt128
precision(p) 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 int decimalComp(const VDecimal& d) const
{ {
lldiv_t d1 = lldiv(value, static_cast<int64_t>(mcs_pow_10[scale])); lldiv_t d1 = lldiv(value, static_cast<int64_t>(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; int64_t value;
int8_t scale; // 0~38 int8_t scale; // 0~38
uint8_t precision; // 1~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 } //end of namespace

View File

@ -17,7 +17,10 @@
MA 02110-1301, USA. MA 02110-1301, USA.
*/ */
#include <iostream>
#include "mcs_int128.h" #include "mcs_int128.h"
#include "exceptclasses.h"
namespace datatypes namespace datatypes
{ {
@ -33,6 +36,99 @@ namespace datatypes
return getLongDoubleFromFloat128(static_cast<__float128>(s128Value)); 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<const uint64_t*>(&high);
const uint64_t* mid_pod = reinterpret_cast<const uint64_t*>(&mid);
const uint64_t* low_pod = reinterpret_cast<const uint64_t*>(&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<int128_t>(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, // The method converts a wide decimal s128Value to an int64_t,
// saturating the s128Value if necessary. // saturating the s128Value if necessary.
inline int64_t TSInt128::getInt64FromWideDecimal() inline int64_t TSInt128::getInt64FromWideDecimal()

View File

@ -23,6 +23,7 @@
#include <cstdint> #include <cstdint>
#include <limits> #include <limits>
#include <type_traits> #include <type_traits>
#include <string>
// Inline asm has three argument lists: output, input and clobber list // Inline asm has three argument lists: output, input and clobber list
#if defined(__GNUC__) && (__GNUC___ > 7) #if defined(__GNUC__) && (__GNUC___ > 7)
@ -116,18 +117,41 @@ static inline long double getLongDoubleFromFloat128(const __float128& value)
class TSInt128 class TSInt128
{ {
public: 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) { } TSInt128(): s128Value(0) { }
// aligned argument // aligned argument
TSInt128(const int128_t& x) { s128Value = x; } TSInt128(const int128_t& x) { s128Value = x; }
// unaligned argument // unaligned argument
TSInt128(const int128_t* x) { assignPtrPtr(&s128Value, x); } TSInt128(const int128_t* x) { assignPtrPtr(&s128Value, x); }
// unaligned argument // unaligned argument
TSInt128(const unsigned char* x) { assignPtrPtr(&s128Value, x); } 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 // The method copies 16 bytes from one memory cell
// into another using memcpy or SIMD. // into another using memcpy or SIMD.
// memcpy in gcc >= 7 is replaced with SIMD instructions // memcpy in gcc >= 7 is replaced with SIMD instructions
@ -158,6 +182,22 @@ class TSInt128
return s128Value == static_cast<int128_t>(x); return s128Value == static_cast<int128_t>(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. // The method converts a wide decimal s128Value to a double.
inline double getDoubleFromWideDecimal(); inline double getDoubleFromWideDecimal();

View File

@ -153,8 +153,10 @@ void SimpleColumn_Decimal<len>::setNullVal()
template<int len> template<int len>
inline const std::string& SimpleColumn_Decimal<len>:: getStrVal(rowgroup::Row& row, bool& isNull) inline const std::string& SimpleColumn_Decimal<len>:: getStrVal(rowgroup::Row& row, bool& isNull)
{ {
dataconvert::DataConvert::decimalToString((int64_t)row.getIntField<len>(fInputIndex), fResultType.scale, tmp, 22, fResultType.colDataType); datatypes::VDecimal dec((int64_t)row.getIntField<len>(fInputIndex),
fResult.strVal = std::string(tmp); fResultType.scale,
fResultType.precision);
fResult.strVal = dec.toString();
return fResult.strVal; return fResult.strVal;
} }

View File

@ -632,10 +632,10 @@ inline const std::string& TreeNode::getStrVal(const std::string& timeZone)
case CalpontSystemCatalog::UDECIMAL: case CalpontSystemCatalog::UDECIMAL:
{ {
if (fResultType.colWidth == datatypes::MAXDECIMALWIDTH) 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 else
dataconvert::DataConvert::decimalToString(fResult.decimalVal.value, fResult.decimalVal.scale, tmp, 22, fResultType.colDataType); fResult.strVal = fResult.decimalVal.toString();
fResult.strVal = std::string(tmp);
break; break;
} }

View File

@ -460,13 +460,11 @@ void GroupConcator::outputRow(std::ostringstream& oss, const rowgroup::Row& row)
if (LIKELY(row.getColumnWidth(*i) == datatypes::MAXDECIMALWIDTH)) if (LIKELY(row.getColumnWidth(*i) == datatypes::MAXDECIMALWIDTH))
{ {
char buf[datatypes::Decimal::MAXLENGTH16BYTES]; datatypes::VDecimal dec(0,
scale,
int128_t* dec = row.getBinaryField<int128_t>(*i); row.getPrecision(*i),
dataconvert::DataConvert::decimalToString(dec, row.getBinaryField<int128_t>(*i));
static_cast<uint32_t>(scale), buf, oss << fixed << dec;
(uint8_t) sizeof(buf), types[*i]);
oss << fixed << buf;
} }
else else
{ {

View File

@ -1099,8 +1099,8 @@ dec4: /* have to pick a scale to use for the double. using 5... */
case CalpontSystemCatalog::DECIMAL: case CalpontSystemCatalog::DECIMAL:
case CalpontSystemCatalog::UDECIMAL: case CalpontSystemCatalog::UDECIMAL:
{ {
int64_t val; int64_t val = 0;
int128_t val128; int128_t val128 = 0;
bool isInputWide = false; bool isInputWide = false;
if (in.getColumnWidth(i) == datatypes::MAXDECIMALWIDTH) 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: case CalpontSystemCatalog::VARCHAR:
default: default:
{ {
char buf[50]; if (LIKELY(isInputWide))
dataconvert::DataConvert::decimalToString(val, scale, buf, 50, out->getColTypes()[i]); {
/* ostringstream oss; datatypes::VDecimal dec(0,
if (scale == 0) in.getScale(i),
oss << val; in.getPrecision(i),
else val128);
oss << (val / IDB_pow[scale]) << "." out->setStringField(dec.toString(), i);
<< setw(scale) << setfill('0') << (val % IDB_pow[scale]); */ }
out->setStringField(string(buf), i); else
{
datatypes::VDecimal dec(val,
in.getScale(i),
in.getPrecision(i));
out->setStringField(dec.toString(), i);
}
break; break;
} }
} }

View File

@ -38,6 +38,7 @@ public:
const CalpontSystemCatalog::ColType &type() const { return m_type; } const CalpontSystemCatalog::ColType &type() const { return m_type; }
int32_t colWidth() const override { return m_type.colWidth; } int32_t colWidth() const override { return m_type.colWidth; }
int32_t precision() const override { return m_type.precision; } 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 int store_date(int64_t val) override
{ {
@ -160,30 +161,16 @@ public:
return m_field->store(static_cast<double>(dl)); return m_field->store(static_cast<double>(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 std::string decAsAStr = dec.toString();
// to create vtable limitation. return m_field->store(decAsAStr.c_str(), decAsAStr.length(), m_field->charset());
//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());
} }
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 std::string decAsAStr = dec.toString(true);
char buf[datatypes::Decimal::MAXLENGTH16BYTES]; return m_field->store(decAsAStr.c_str(), decAsAStr.length(), m_field->charset());
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());
} }
int store_lob(const char *str, size_t length) override int store_lob(const char *str, size_t length) override

View File

@ -112,12 +112,11 @@ static int generate_result(BRM::OID_t oid, BRM::DBRM* emp, TABLE* table, THD* th
else else
{ {
table->field[4]->set_notnull(); table->field[4]->set_notnull();
std::string decAsAStr = datatypes::TSInt128(iter->partition.cprange.bigLoVal)
char buf[datatypes::Decimal::MAXLENGTH16BYTES]; .toString();
dataconvert::DataConvert::decimalToString( table->field[4]->store(decAsAStr.c_str(),
&iter->partition.cprange.bigLoVal, decAsAStr.length(),
0, buf, (uint8_t) sizeof(buf), datatypes::SystemCatalog::DECIMAL); table->field[4]->charset());
table->field[4]->store(buf, strlen(buf), table->field[4]->charset());
} }
if (iter->partition.cprange.bigHiVal <= (utils::minInt128 + 1)) 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 else
{ {
table->field[5]->set_notnull(); table->field[5]->set_notnull();
std::string decAsAStr = datatypes::TSInt128(iter->partition.cprange.bigHiVal)
char buf[datatypes::Decimal::MAXLENGTH16BYTES]; .toString();
dataconvert::DataConvert::decimalToString( table->field[5]->store(decAsAStr.c_str(),
&iter->partition.cprange.bigHiVal, decAsAStr.length(),
0, buf, (uint8_t) sizeof(buf), datatypes::SystemCatalog::DECIMAL); table->field[5]->charset());
table->field[5]->store(buf, strlen(buf), table->field[5]->charset());
} }
} }

View File

@ -25,8 +25,6 @@ using namespace dataconvert;
#include "joblisttypes.h" #include "joblisttypes.h"
#include "columnwidth.h" #include "columnwidth.h"
using CSCDataType = execplan::CalpontSystemCatalog::ColDataType;
TEST(DataConvertTest, Strtoll128) TEST(DataConvertTest, Strtoll128)
{ {
char *ep = NULL; char *ep = NULL;
@ -543,252 +541,6 @@ TEST(DataConvertTest, NumberIntValue)
EXPECT_EQ(b2, b4); EXPECT_EQ(b2, b4);
EXPECT_TRUE(pushWarning); 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) TEST(DataConvertTest, ConvertColumnData)
{ {
} }

View File

@ -84,8 +84,6 @@ TEST(Decimal, compareCheck)
TEST(Decimal, additionNoOverflowCheck) TEST(Decimal, additionNoOverflowCheck)
{ {
datatypes::SystemCatalog::ColDataType colDataType = datatypes::SystemCatalog::DECIMAL;
char buf[42];
// Addition w/o overflow check // Addition w/o overflow check
execplan::IDB_Decimal l, r, result; execplan::IDB_Decimal l, r, result;
// same precision, same scale, both positive values // same precision, same scale, both positive values
@ -143,8 +141,7 @@ TEST(Decimal, additionNoOverflowCheck)
result.s128Value = 0; result.s128Value = 0;
datatypes::Decimal::addition<int128_t, false>(l, r, result); datatypes::Decimal::addition<int128_t, false>(l, r, result);
dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); EXPECT_EQ("0.00000000000042000000000000000000000042", result.toString());
EXPECT_EQ("0.00000000000042000000000000000000000042", std::string(buf));
// same precision, L scale > R scale, both negative values // same precision, L scale > R scale, both negative values
l.s128Value = -42; l.s128Value = -42;
@ -152,8 +149,7 @@ TEST(Decimal, additionNoOverflowCheck)
result.s128Value = 0; result.s128Value = 0;
datatypes::Decimal::addition<int128_t, false>(l, r, result); datatypes::Decimal::addition<int128_t, false>(l, r, result);
dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); EXPECT_EQ("-0.00000000000042000000000000000000000042", result.toString());
EXPECT_EQ("-0.00000000000042000000000000000000000042", std::string(buf));
// same precision, L scale > R scale, +- values // same precision, L scale > R scale, +- values
l.s128Value = 42; l.s128Value = 42;
@ -161,8 +157,7 @@ TEST(Decimal, additionNoOverflowCheck)
result.s128Value = 0; result.s128Value = 0;
datatypes::Decimal::addition<int128_t, false>(l, r, result); datatypes::Decimal::addition<int128_t, false>(l, r, result);
dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); EXPECT_EQ("-0.00000000000041999999999999999999999958", result.toString());
EXPECT_EQ("-0.00000000000041999999999999999999999958", std::string(buf));
// same precision, L scale > R scale, both 0 // same precision, L scale > R scale, both 0
l.s128Value = 0; l.s128Value = 0;
@ -186,8 +181,7 @@ TEST(Decimal, additionNoOverflowCheck)
result.s128Value = 0; result.s128Value = 0;
datatypes::Decimal::addition<int128_t, false>(l, r, result); datatypes::Decimal::addition<int128_t, false>(l, r, result);
dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); EXPECT_EQ("0.00000000000004200000000000000000000420", result.toString());
EXPECT_EQ("0.00000000000004200000000000000000000420", std::string(buf));
// same precision, L scale < R scale, both negative values // same precision, L scale < R scale, both negative values
l.s128Value = -42; l.s128Value = -42;
@ -195,8 +189,7 @@ TEST(Decimal, additionNoOverflowCheck)
result.s128Value = 0; result.s128Value = 0;
datatypes::Decimal::addition<int128_t, false>(l, r, result); datatypes::Decimal::addition<int128_t, false>(l, r, result);
dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); EXPECT_EQ("-0.00000000000004200000000000000000000420", result.toString());
EXPECT_EQ("-0.00000000000004200000000000000000000420", std::string(buf));
// same precision, L scale < R scale, +- values // same precision, L scale < R scale, +- values
l.s128Value = 42; l.s128Value = 42;
@ -204,8 +197,7 @@ TEST(Decimal, additionNoOverflowCheck)
result.s128Value = 0; result.s128Value = 0;
datatypes::Decimal::addition<int128_t, false>(l, r, result); datatypes::Decimal::addition<int128_t, false>(l, r, result);
dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); EXPECT_EQ("0.00000000000004199999999999999999999580", result.toString());
EXPECT_EQ("0.00000000000004199999999999999999999580", std::string(buf));
// same precision, L scale < R scale, both 0 // same precision, L scale < R scale, both 0
l.s128Value = 0; l.s128Value = 0;
@ -220,8 +212,6 @@ TEST(Decimal, divisionNoOverflowCheck)
{ {
// DIVISION // DIVISION
// same precision, same scale, both positive values // same precision, same scale, both positive values
datatypes::SystemCatalog::ColDataType colDataType = datatypes::SystemCatalog::DECIMAL;
char buf[42];
execplan::IDB_Decimal l, r, result; execplan::IDB_Decimal l, r, result;
l.scale = 38; l.scale = 38;
@ -237,8 +227,7 @@ TEST(Decimal, divisionNoOverflowCheck)
result.s128Value = 0; result.s128Value = 0;
datatypes::Decimal::division<int128_t, false>(r, l, result); datatypes::Decimal::division<int128_t, false>(r, l, result);
dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); EXPECT_EQ("9.7674418605", result.toString());
EXPECT_EQ("9.7674418605", std::string(buf));
// same precision, same scale, both negative values // same precision, same scale, both negative values
l.s128Value = -43; l.s128Value = -43;
@ -246,8 +235,7 @@ TEST(Decimal, divisionNoOverflowCheck)
result.s128Value = 0; result.s128Value = 0;
datatypes::Decimal::division<int128_t, false>(r, l, result); datatypes::Decimal::division<int128_t, false>(r, l, result);
dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); EXPECT_EQ("9.7674418605", result.toString());
EXPECT_EQ("9.7674418605", std::string(buf));
// same precision, same scale, +- values // same precision, same scale, +- values
l.s128Value = 2200000; l.s128Value = 2200000;
@ -255,8 +243,7 @@ TEST(Decimal, divisionNoOverflowCheck)
result.s128Value = 0; result.s128Value = 0;
datatypes::Decimal::division<int128_t, false>(l, r, result); datatypes::Decimal::division<int128_t, false>(l, r, result);
dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); EXPECT_EQ("-1157.8947368421", result.toString());
EXPECT_EQ("-1157.8947368421", std::string(buf));
// same precision, same scale, l = 0 // same precision, same scale, l = 0
l.s128Value = 0; l.s128Value = 0;
@ -278,8 +265,7 @@ TEST(Decimal, divisionNoOverflowCheck)
result.s128Value = 0; result.s128Value = 0;
datatypes::Decimal::division<int128_t, false>(r, l, result); datatypes::Decimal::division<int128_t, false>(r, l, result);
dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); EXPECT_EQ("115789473684210526315789.4736842105", result.toString());
EXPECT_EQ("115789473684210526315789.4736842105", std::string(buf));
// same precision, L scale > R scale, both negative values // same precision, L scale > R scale, both negative values
l.s128Value = -22; l.s128Value = -22;
@ -287,8 +273,7 @@ TEST(Decimal, divisionNoOverflowCheck)
result.s128Value = 0; result.s128Value = 0;
datatypes::Decimal::division<int128_t, false>(r, l, result); datatypes::Decimal::division<int128_t, false>(r, l, result);
dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); EXPECT_EQ("86363636363636363636363.6363636364", result.toString());
EXPECT_EQ("86363636363636363636363.6363636364", std::string(buf));
// same precision, L scale > R scale, +- values // same precision, L scale > R scale, +- values
l.s128Value = 19; l.s128Value = 19;
@ -296,8 +281,7 @@ TEST(Decimal, divisionNoOverflowCheck)
result.s128Value = 0; result.s128Value = 0;
datatypes::Decimal::division<int128_t, false>(r, l, result); datatypes::Decimal::division<int128_t, false>(r, l, result);
dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); EXPECT_EQ("-115789473684210526315789.4736842105", result.toString());
EXPECT_EQ("-115789473684210526315789.4736842105", std::string(buf));
// same precision, L scale > R scale, R = 0 // same precision, L scale > R scale, R = 0
l.s128Value = 424242; l.s128Value = 424242;
@ -313,8 +297,7 @@ TEST(Decimal, divisionNoOverflowCheck)
result.s128Value = 0; result.s128Value = 0;
datatypes::Decimal::division<int128_t, false>(r, l, result); datatypes::Decimal::division<int128_t, false>(r, l, result);
dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); EXPECT_EQ("100000000000000000000000.0000000000", result.toString());
EXPECT_EQ("100000000000000000000000.0000000000", std::string(buf));
// same precision, L scale > R scale, both MIN negative values // same precision, L scale > R scale, both MIN negative values
utils::int128Min(l.s128Value); utils::int128Min(l.s128Value);
@ -322,8 +305,7 @@ TEST(Decimal, divisionNoOverflowCheck)
result.s128Value = 0; result.s128Value = 0;
datatypes::Decimal::division<int128_t, false>(r, l, result); datatypes::Decimal::division<int128_t, false>(r, l, result);
dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); EXPECT_EQ("100000000000000000000000.0000000000", result.toString());
EXPECT_EQ("100000000000000000000000.0000000000", std::string(buf));
// same precision, L scale < R scale, both positive values // same precision, L scale < R scale, both positive values
l.scale = 15; l.scale = 15;
@ -339,8 +321,7 @@ TEST(Decimal, divisionNoOverflowCheck)
result.s128Value = 0; result.s128Value = 0;
datatypes::Decimal::division<int128_t, false>(r, l, result); datatypes::Decimal::division<int128_t, false>(r, l, result);
dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); EXPECT_EQ("0.00000000000000000000001000000000000000", result.toString());
EXPECT_EQ("0.00000000000000000000001000000000000000", std::string(buf));
// same precision, L scale < R scale, both negative values // same precision, L scale < R scale, both negative values
l.s128Value = -22; l.s128Value = -22;
@ -348,8 +329,7 @@ TEST(Decimal, divisionNoOverflowCheck)
result.s128Value = 0; result.s128Value = 0;
datatypes::Decimal::division<int128_t, false>(r, l, result); datatypes::Decimal::division<int128_t, false>(r, l, result);
dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); EXPECT_EQ("0.00000000000000000000000863636363636364", result.toString());
EXPECT_EQ("0.00000000000000000000000863636363636364", std::string(buf));
// same precision, L scale < R scale, +- values // same precision, L scale < R scale, +- values
l.s128Value = 22; l.s128Value = 22;
@ -357,8 +337,7 @@ TEST(Decimal, divisionNoOverflowCheck)
result.s128Value = 0; result.s128Value = 0;
datatypes::Decimal::division<int128_t, false>(r, l, result); datatypes::Decimal::division<int128_t, false>(r, l, result);
dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); EXPECT_EQ("-0.00000000000000000000000863636363636364", result.toString());
EXPECT_EQ("-0.00000000000000000000000863636363636364", std::string(buf));
// same precision, L scale < R scale, R = 0 // same precision, L scale < R scale, R = 0
l.s128Value = 42; l.s128Value = 42;
@ -375,8 +354,7 @@ TEST(Decimal, divisionNoOverflowCheck)
result.s128Value = 0; result.s128Value = 0;
datatypes::Decimal::division<int128_t, false>(r, l, result); datatypes::Decimal::division<int128_t, false>(r, l, result);
dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); EXPECT_EQ("0.00000000000000000000001000000000000000", result.toString());
EXPECT_EQ("0.00000000000000000000001000000000000000", std::string(buf));
// same precision, L scale < R scale, both MIN negative values // same precision, L scale < R scale, both MIN negative values
utils::int128Min(l.s128Value); utils::int128Min(l.s128Value);
@ -384,8 +362,7 @@ TEST(Decimal, divisionNoOverflowCheck)
result.s128Value = 0; result.s128Value = 0;
datatypes::Decimal::division<int128_t, false>(r, l, result); datatypes::Decimal::division<int128_t, false>(r, l, result);
dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); EXPECT_EQ("0.00000000000000000000001000000000000000", result.toString());
EXPECT_EQ("0.00000000000000000000001000000000000000", std::string(buf));
// same precision, L scale < R scale, result.scale < (r.scale-l.scale) // same precision, L scale < R scale, result.scale < (r.scale-l.scale)
// both positive values // both positive values
@ -402,8 +379,7 @@ TEST(Decimal, divisionNoOverflowCheck)
result.s128Value = 0; result.s128Value = 0;
datatypes::Decimal::division<int128_t, false>(r, l, result); datatypes::Decimal::division<int128_t, false>(r, l, result);
dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); EXPECT_EQ("1", result.toString());
EXPECT_EQ("1", std::string(buf));
// same precision, L scale < R scale, result.scale < (r.scale-l.scale) // same precision, L scale < R scale, result.scale < (r.scale-l.scale)
// both negative values // both negative values
@ -412,8 +388,7 @@ TEST(Decimal, divisionNoOverflowCheck)
result.s128Value = 0; result.s128Value = 0;
datatypes::Decimal::division<int128_t, false>(r, l, result); datatypes::Decimal::division<int128_t, false>(r, l, result);
dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); EXPECT_EQ("9", result.toString());
EXPECT_EQ("9", std::string(buf));
// same precision, L scale < R scale, result.scale < (r.scale-l.scale) // same precision, L scale < R scale, result.scale < (r.scale-l.scale)
// +- values // +- values
@ -422,8 +397,7 @@ TEST(Decimal, divisionNoOverflowCheck)
result.s128Value = 0; result.s128Value = 0;
datatypes::Decimal::division<int128_t, false>(r, l, result); datatypes::Decimal::division<int128_t, false>(r, l, result);
dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); EXPECT_EQ("-9", result.toString());
EXPECT_EQ("-9", std::string(buf));
// same precision, L scale < R scale, result.scale < (r.scale-l.scale) // same precision, L scale < R scale, result.scale < (r.scale-l.scale)
// R = 0 // R = 0
@ -441,8 +415,7 @@ TEST(Decimal, divisionNoOverflowCheck)
result.s128Value = 0; result.s128Value = 0;
datatypes::Decimal::division<int128_t, false>(r, l, result); datatypes::Decimal::division<int128_t, false>(r, l, result);
dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); EXPECT_EQ("0", result.toString());
EXPECT_EQ("0", std::string(buf));
// same precision, L scale < R scale, result.scale < (r.scale-l.scale) // same precision, L scale < R scale, result.scale < (r.scale-l.scale)
// both MIN negative values // both MIN negative values
@ -451,8 +424,7 @@ TEST(Decimal, divisionNoOverflowCheck)
result.s128Value = 0; result.s128Value = 0;
datatypes::Decimal::division<int128_t, false>(r, l, result); datatypes::Decimal::division<int128_t, false>(r, l, result);
dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); EXPECT_EQ("0", result.toString());
EXPECT_EQ("0", std::string(buf));
} }
void doDiv(const execplan::IDB_Decimal& l, void doDiv(const execplan::IDB_Decimal& l,
@ -464,8 +436,6 @@ void doDiv(const execplan::IDB_Decimal& l,
TEST(Decimal, divisionWithOverflowCheck) TEST(Decimal, divisionWithOverflowCheck)
{ {
datatypes::SystemCatalog::ColDataType colDataType = datatypes::SystemCatalog::DECIMAL;
char buf[42];
// Divide min int128 by -1 // Divide min int128 by -1
execplan::IDB_Decimal l, r, result; execplan::IDB_Decimal l, r, result;
l.scale = 0; l.scale = 0;
@ -503,8 +473,7 @@ TEST(Decimal, divisionWithOverflowCheck)
result.s128Value = 0; result.s128Value = 0;
EXPECT_NO_THROW(doDiv(l, r, result)); EXPECT_NO_THROW(doDiv(l, r, result));
dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); EXPECT_EQ("9223372036854775809", result.toString());
EXPECT_EQ("9223372036854775809", std::string(buf));
} }
void doAdd(const execplan::IDB_Decimal& l, void doAdd(const execplan::IDB_Decimal& l,
@ -516,8 +485,6 @@ void doAdd(const execplan::IDB_Decimal& l,
TEST(Decimal, additionWithOverflowCheck) TEST(Decimal, additionWithOverflowCheck)
{ {
datatypes::SystemCatalog::ColDataType colDataType = datatypes::SystemCatalog::DECIMAL;
char buf[42];
// Add two max ints // Add two max ints
execplan::IDB_Decimal l, r, result; execplan::IDB_Decimal l, r, result;
l.scale = 0; l.scale = 0;
@ -555,14 +522,11 @@ TEST(Decimal, additionWithOverflowCheck)
result.s128Value = 0; result.s128Value = 0;
EXPECT_NO_THROW(doAdd(l, r, result)); EXPECT_NO_THROW(doAdd(l, r, result));
dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); EXPECT_EQ("-170141183460469231713240559642174554113", result.toString());
EXPECT_EQ("-170141183460469231713240559642174554113", std::string(buf));
} }
TEST(Decimal, subtractionNoOverflowCheck) TEST(Decimal, subtractionNoOverflowCheck)
{ {
datatypes::SystemCatalog::ColDataType colDataType = datatypes::SystemCatalog::DECIMAL;
char buf[42];
// Subtractio w/o overflow check // Subtractio w/o overflow check
execplan::IDB_Decimal l, r, result; execplan::IDB_Decimal l, r, result;
// same precision, same scale, both positive values // same precision, same scale, both positive values
@ -579,8 +543,7 @@ TEST(Decimal, subtractionNoOverflowCheck)
result.s128Value = 0; result.s128Value = 0;
datatypes::Decimal::subtraction<int128_t, false>(l, r, result); datatypes::Decimal::subtraction<int128_t, false>(l, r, result);
dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); EXPECT_EQ("-0.00000000000000000000000000000000000378", result.toString());
EXPECT_EQ("-0.00000000000000000000000000000000000378", std::string(buf));
// same precision, same scale, both negative values // same precision, same scale, both negative values
l.s128Value = -42; l.s128Value = -42;
@ -588,8 +551,7 @@ TEST(Decimal, subtractionNoOverflowCheck)
result.s128Value = 0; result.s128Value = 0;
datatypes::Decimal::subtraction<int128_t, false>(l, r, result); datatypes::Decimal::subtraction<int128_t, false>(l, r, result);
dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); EXPECT_EQ("0.00000000000000000000000000000000000378", result.toString());
EXPECT_EQ("0.00000000000000000000000000000000000378", std::string(buf));
// same precision, same scale, +- values // same precision, same scale, +- values
l.s128Value = 42; l.s128Value = 42;
@ -597,8 +559,7 @@ TEST(Decimal, subtractionNoOverflowCheck)
result.s128Value = 0; result.s128Value = 0;
datatypes::Decimal::subtraction<int128_t, false>(l, r, result); datatypes::Decimal::subtraction<int128_t, false>(l, r, result);
dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); EXPECT_EQ("0.00000000000000000000000000000000000462", result.toString());
EXPECT_EQ("0.00000000000000000000000000000000000462", std::string(buf));
// same precision, same scale, both 0 // same precision, same scale, both 0
l.s128Value = 0; l.s128Value = 0;
@ -623,8 +584,7 @@ TEST(Decimal, subtractionNoOverflowCheck)
result.s128Value = 0; result.s128Value = 0;
datatypes::Decimal::subtraction<int128_t, false>(l, r, result); datatypes::Decimal::subtraction<int128_t, false>(l, r, result);
dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); EXPECT_EQ("-0.00000000000041999999999999999999999958", result.toString());
EXPECT_EQ("-0.00000000000041999999999999999999999958", std::string(buf));
// same precision, L scale > R scale, both negative values // same precision, L scale > R scale, both negative values
l.s128Value = -42; l.s128Value = -42;
@ -632,8 +592,7 @@ TEST(Decimal, subtractionNoOverflowCheck)
result.s128Value = 0; result.s128Value = 0;
datatypes::Decimal::subtraction<int128_t, false>(l, r, result); datatypes::Decimal::subtraction<int128_t, false>(l, r, result);
dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); EXPECT_EQ("0.00000000000041999999999999999999999958", result.toString());
EXPECT_EQ("0.00000000000041999999999999999999999958", std::string(buf));
// same precision, L scale > R scale, +- values // same precision, L scale > R scale, +- values
l.s128Value = 42; l.s128Value = 42;
@ -641,8 +600,7 @@ TEST(Decimal, subtractionNoOverflowCheck)
result.s128Value = 0; result.s128Value = 0;
datatypes::Decimal::subtraction<int128_t, false>(l, r, result); datatypes::Decimal::subtraction<int128_t, false>(l, r, result);
dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); EXPECT_EQ("0.00000000000042000000000000000000000042", result.toString());
EXPECT_EQ("0.00000000000042000000000000000000000042", std::string(buf));
// same precision, L scale > R scale, both 0 // same precision, L scale > R scale, both 0
l.s128Value = 0; l.s128Value = 0;
@ -666,8 +624,7 @@ TEST(Decimal, subtractionNoOverflowCheck)
result.s128Value = 0; result.s128Value = 0;
datatypes::Decimal::subtraction<int128_t, false>(l, r, result); datatypes::Decimal::subtraction<int128_t, false>(l, r, result);
dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); EXPECT_EQ("0.00000000000004199999999999999999999580", result.toString());
EXPECT_EQ("0.00000000000004199999999999999999999580", std::string(buf));
// same precision, L scale < R scale, both negative values // same precision, L scale < R scale, both negative values
l.s128Value = -42; l.s128Value = -42;
@ -675,8 +632,7 @@ TEST(Decimal, subtractionNoOverflowCheck)
result.s128Value = 0; result.s128Value = 0;
datatypes::Decimal::subtraction<int128_t, false>(l, r, result); datatypes::Decimal::subtraction<int128_t, false>(l, r, result);
dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); EXPECT_EQ("-0.00000000000004199999999999999999999580", result.toString());
EXPECT_EQ("-0.00000000000004199999999999999999999580", std::string(buf));
// same precision, L scale < R scale, +- values // same precision, L scale < R scale, +- values
l.s128Value = 42; l.s128Value = 42;
@ -684,8 +640,7 @@ TEST(Decimal, subtractionNoOverflowCheck)
result.s128Value = 0; result.s128Value = 0;
datatypes::Decimal::subtraction<int128_t, false>(l, r, result); datatypes::Decimal::subtraction<int128_t, false>(l, r, result);
dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); EXPECT_EQ("0.00000000000004200000000000000000000420", result.toString());
EXPECT_EQ("0.00000000000004200000000000000000000420", std::string(buf));
// same precision, L scale < R scale, both 0 // same precision, L scale < R scale, both 0
l.s128Value = 0; l.s128Value = 0;
@ -705,8 +660,6 @@ void doSubtract(const execplan::IDB_Decimal& l,
TEST(Decimal, subtractionWithOverflowCheck) TEST(Decimal, subtractionWithOverflowCheck)
{ {
datatypes::SystemCatalog::ColDataType colDataType = datatypes::SystemCatalog::DECIMAL;
char buf[42];
// Subtract a max int from a min int // Subtract a max int from a min int
execplan::IDB_Decimal l, r, result; execplan::IDB_Decimal l, r, result;
l.scale = 0; l.scale = 0;
@ -744,16 +697,13 @@ TEST(Decimal, subtractionWithOverflowCheck)
result.s128Value = 0; result.s128Value = 0;
EXPECT_NO_THROW(doSubtract(l, r, result)); EXPECT_NO_THROW(doSubtract(l, r, result));
dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); EXPECT_EQ("170141183460469231713240559642174554112", result.toString());
EXPECT_EQ("170141183460469231713240559642174554112", std::string(buf));
} }
TEST(Decimal, multiplicationNoOverflowCheck) TEST(Decimal, multiplicationNoOverflowCheck)
{ {
// Multiplication // Multiplication
// same precision, l.scale + r.scale = result.scale, both positive values // 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; execplan::IDB_Decimal l, r, result;
l.scale = 19; l.scale = 19;
@ -769,8 +719,7 @@ TEST(Decimal, multiplicationNoOverflowCheck)
result.s128Value = 0; result.s128Value = 0;
datatypes::Decimal::multiplication<int128_t, false>(r, l, result); datatypes::Decimal::multiplication<int128_t, false>(r, l, result);
dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); EXPECT_EQ("0.85070591730234615861231965839514664960", result.toString());
EXPECT_EQ("0.85070591730234615861231965839514664960", std::string(buf));
// same precision, l.scale + r.scale = result.scale, both negative values // same precision, l.scale + r.scale = result.scale, both negative values
l.s128Value = -4611686018427387904; l.s128Value = -4611686018427387904;
@ -779,8 +728,7 @@ TEST(Decimal, multiplicationNoOverflowCheck)
result.s128Value = 0; result.s128Value = 0;
datatypes::Decimal::multiplication<int128_t, false>(r, l, result); datatypes::Decimal::multiplication<int128_t, false>(r, l, result);
dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); EXPECT_EQ("0.85070591730234615861231965839514664960", result.toString());
EXPECT_EQ("0.85070591730234615861231965839514664960", std::string(buf));
// same precision, l.scale + r.scale = result.scale, +- values // same precision, l.scale + r.scale = result.scale, +- values
l.s128Value = -4611686018427387904; l.s128Value = -4611686018427387904;
@ -788,8 +736,7 @@ TEST(Decimal, multiplicationNoOverflowCheck)
result.s128Value = 0; result.s128Value = 0;
datatypes::Decimal::multiplication<int128_t, false>(l, r, result); datatypes::Decimal::multiplication<int128_t, false>(l, r, result);
dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); EXPECT_EQ("-0.85070591730234615861231965839514664960", result.toString());
EXPECT_EQ("-0.85070591730234615861231965839514664960", std::string(buf));
// same precision, l.scale + r.scale = result.scale, l = 0 // same precision, l.scale + r.scale = result.scale, l = 0
l.s128Value = 0; l.s128Value = 0;
@ -813,8 +760,7 @@ TEST(Decimal, multiplicationNoOverflowCheck)
result.s128Value = 0; result.s128Value = 0;
datatypes::Decimal::multiplication<int128_t, false>(r, l, result); datatypes::Decimal::multiplication<int128_t, false>(r, l, result);
dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); EXPECT_EQ("0.66461399789245793645190353014017228800", result.toString());
EXPECT_EQ("0.66461399789245793645190353014017228800", std::string(buf));
// same precision, l.scale + r.scale < result.scale, both negative values // same precision, l.scale + r.scale < result.scale, both negative values
l.s128Value = -72057594037927936; l.s128Value = -72057594037927936;
@ -823,8 +769,7 @@ TEST(Decimal, multiplicationNoOverflowCheck)
result.s128Value = 0; result.s128Value = 0;
datatypes::Decimal::multiplication<int128_t, false>(r, l, result); datatypes::Decimal::multiplication<int128_t, false>(r, l, result);
dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); EXPECT_EQ("0.66461399789245793645190353014017228800", result.toString());
EXPECT_EQ("0.66461399789245793645190353014017228800", std::string(buf));
// same precision, l.scale + r.scale < result.scale, +- values // same precision, l.scale + r.scale < result.scale, +- values
l.s128Value = -72057594037927936; l.s128Value = -72057594037927936;
@ -832,8 +777,7 @@ TEST(Decimal, multiplicationNoOverflowCheck)
result.s128Value = 0; result.s128Value = 0;
datatypes::Decimal::multiplication<int128_t, false>(l, r, result); datatypes::Decimal::multiplication<int128_t, false>(l, r, result);
dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); EXPECT_EQ("-0.66461399789245793645190353014017228800", result.toString());
EXPECT_EQ("-0.66461399789245793645190353014017228800", std::string(buf));
// same precision, l.scale + r.scale < result.scale, l = 0 // same precision, l.scale + r.scale < result.scale, l = 0
l.s128Value = 0; l.s128Value = 0;
@ -859,8 +803,7 @@ TEST(Decimal, multiplicationNoOverflowCheck)
result.s128Value = 0; result.s128Value = 0;
datatypes::Decimal::multiplication<int128_t, false>(r, l, result); datatypes::Decimal::multiplication<int128_t, false>(r, l, result);
dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); EXPECT_EQ("0.01524157875323883675019051998750190521", result.toString());
EXPECT_EQ("0.01524157875323883675019051998750190521", std::string(buf));
// same precision, l.scale + r.scale > result.scale, both negative values // same precision, l.scale + r.scale > result.scale, both negative values
l.s128Value = -l.s128Value; l.s128Value = -l.s128Value;
@ -868,16 +811,14 @@ TEST(Decimal, multiplicationNoOverflowCheck)
result.s128Value = 0; result.s128Value = 0;
datatypes::Decimal::multiplication<int128_t, false>(r, l, result); datatypes::Decimal::multiplication<int128_t, false>(r, l, result);
dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); EXPECT_EQ("0.01524157875323883675019051998750190521", result.toString());
EXPECT_EQ("0.01524157875323883675019051998750190521", std::string(buf));
// same precision, l.scale + r.scale > result.scale, +- values // same precision, l.scale + r.scale > result.scale, +- values
r.s128Value = -r.s128Value; r.s128Value = -r.s128Value;
result.s128Value = 0; result.s128Value = 0;
datatypes::Decimal::multiplication<int128_t, false>(l, r, result); datatypes::Decimal::multiplication<int128_t, false>(l, r, result);
dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); EXPECT_EQ("-0.01524157875323883675019051998750190521", result.toString());
EXPECT_EQ("-0.01524157875323883675019051998750190521", std::string(buf));
// same precision, l.scale + r.scale > result.scale, l = 0 // same precision, l.scale + r.scale > result.scale, l = 0
r.s128Value = 0; r.s128Value = 0;
@ -896,8 +837,6 @@ void doMultiply(const execplan::IDB_Decimal& l,
TEST(Decimal, multiplicationWithOverflowCheck) TEST(Decimal, multiplicationWithOverflowCheck)
{ {
datatypes::SystemCatalog::ColDataType colDataType = datatypes::SystemCatalog::DECIMAL;
char buf[42];
execplan::IDB_Decimal l, r, result; execplan::IDB_Decimal l, r, result;
// result.scale >= l.scale + r.scale // result.scale >= l.scale + r.scale
l.scale = 0; l.scale = 0;
@ -940,6 +879,248 @@ TEST(Decimal, multiplicationWithOverflowCheck)
result.s128Value = 0; result.s128Value = 0;
EXPECT_NO_THROW(doMultiply(l, r, result)); EXPECT_NO_THROW(doMultiply(l, r, result));
dataconvert::DataConvert::decimalToString(&result.s128Value, result.scale, buf, 42, colDataType); EXPECT_EQ("21267647932558653966460912964485513216", result.toString());
EXPECT_EQ("21267647932558653966460912964485513216", std::string(buf));
} }
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);
}

View File

@ -191,14 +191,7 @@ const string fmt(T v)
} }
else else
{ {
char buf[datatypes::Decimal::MAXLENGTH16BYTES]; oss << datatypes::TSInt128(v);
int128_t tmp = v;
dataconvert::DataConvert::decimalToString(
&tmp, 0, buf, (uint8_t) sizeof(buf), datatypes::SystemCatalog::DECIMAL);
oss << buf;
} }
} }
else if (uflg) else if (uflg)
@ -218,14 +211,7 @@ const string fmt(T v)
} }
else else
{ {
char buf[datatypes::Decimal::MAXLENGTH16BYTES]; oss << datatypes::TSInt128(v);
int128_t tmp = static_cast<uint128_t>(v);
dataconvert::DataConvert::decimalToString(
&tmp, 0, buf, (uint8_t) sizeof(buf), datatypes::SystemCatalog::DECIMAL);
oss << buf;
} }
} }
} }
@ -247,14 +233,7 @@ const string fmt(T v)
} }
else else
{ {
char buf[datatypes::Decimal::MAXLENGTH16BYTES]; oss << datatypes::TSInt128(v);
int128_t tmp = v;
dataconvert::DataConvert::decimalToString(
&tmp, 0, buf, (uint8_t) sizeof(buf), datatypes::SystemCatalog::DECIMAL);
oss << buf;
} }
} }
} }

View File

@ -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<uint64_t*>(&high);
uint64_t* mid_pod = reinterpret_cast<uint64_t*>(&mid);
uint64_t* low_pod = reinterpret_cast<uint64_t*>(&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<int128_t>(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 boost::any
DataConvert::StringToBit(const datatypes::SystemCatalog::TypeAttributesStd& colType, DataConvert::StringToBit(const datatypes::SystemCatalog::TypeAttributesStd& colType,
const datatypes::ConvertFromStringParam &prm, const datatypes::ConvertFromStringParam &prm,

View File

@ -1037,15 +1037,6 @@ public:
EXPORT static bool isColumnTimeValid( int64_t time ); EXPORT static bool isColumnTimeValid( int64_t time );
EXPORT static bool isColumnTimeStampValid( int64_t timeStamp ); 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 std::string constructRegexp(const std::string& str);
static inline void trimWhitespace(int64_t& charData); static inline void trimWhitespace(int64_t& charData);
static inline bool isEscapedChar(char c) static inline bool isEscapedChar(char c)
@ -1298,96 +1289,6 @@ inline void DataConvert::timeToString1( long long timevalue, char* buf, unsigned
#endif #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<uint64_t>(int_val));
#else
snprintf(buf, buflen, "%lu", static_cast<uint64_t>(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) inline void DataConvert::trimWhitespace(int64_t& charData)
{ {
// Trims whitespace characters off non-dict character data // Trims whitespace characters off non-dict character data

View File

@ -542,15 +542,10 @@ string Func_cast_char::getStrVal(Row& row,
{ {
IDB_Decimal d = parm[0]->data()->getDecimalVal(row, isNull); IDB_Decimal d = parm[0]->data()->getDecimalVal(row, isNull);
char buf[80];
if (parm[0]->data()->resultType().colWidth == datatypes::MAXDECIMALWIDTH) 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 else
dataconvert::DataConvert::decimalToString( d.value, d.scale, buf, 80, parm[0]->data()->resultType().colDataType); return d.toString().substr(0, length);
string sbuf = buf;
return sbuf.substr(0, length);
} }
break; break;
@ -1231,17 +1226,10 @@ string Func_cast_decimal::getStrVal(Row& row,
parm, parm,
isNull, isNull,
operationColType); operationColType);
if (operationColType.colWidth == datatypes::MAXDECIMALWIDTH)
char buf[80]; return decimal.toString(true);
if (decimal.precision > datatypes::INT64MAXPRECISION)
dataconvert::DataConvert::decimalToString( &decimal.s128Value, decimal.scale, buf, 80, operationColType.colDataType);
else else
dataconvert::DataConvert::decimalToString( decimal.value, decimal.scale, buf, 80, operationColType.colDataType); return decimal.toString();
string value = buf;
return value;
} }

View File

@ -515,11 +515,11 @@ string Func_ceil::getStrVal(Row& row,
if (op_ct.colWidth == datatypes::MAXDECIMALWIDTH) if (op_ct.colWidth == datatypes::MAXDECIMALWIDTH)
{ {
dataconvert::DataConvert::decimalToString(&d.s128Value, d.scale, tmp, 511, op_ct.colDataType); return d.toString(true);
} }
else else
{ {
dataconvert::DataConvert::decimalToString(d.value, d.scale, tmp, 511, op_ct.colDataType); return d.toString();
} }
} }
else if (isUnsigned(op_ct.colDataType)) else if (isUnsigned(op_ct.colDataType))

View File

@ -436,11 +436,11 @@ string Func_floor::getStrVal(Row& row,
if (op_ct.colWidth == datatypes::MAXDECIMALWIDTH) if (op_ct.colWidth == datatypes::MAXDECIMALWIDTH)
{ {
dataconvert::DataConvert::decimalToString(&d.s128Value, d.scale, tmp, 511, op_ct.colDataType); return d.toString(true);
} }
else else
{ {
dataconvert::DataConvert::decimalToString(d.value, d.scale, tmp, 511, op_ct.colDataType); return d.toString();
} }
} }
else if (isUnsigned(op_ct.colDataType)) else if (isUnsigned(op_ct.colDataType))

View File

@ -1849,8 +1849,7 @@ string Func_format::getStrVal(Row& row,
{ {
IDB_Decimal decimal = parm[0]->data()->getDecimalVal(row, isNull); IDB_Decimal decimal = parm[0]->data()->getDecimalVal(row, isNull);
char buf[80]; // This is an unacceptable way of doing rounding
//perform rouding if needed //perform rouding if needed
if ( scale < 0 ) if ( scale < 0 )
scale = 0; scale = 0;
@ -1912,9 +1911,7 @@ string Func_format::getStrVal(Row& row,
decimal.s128Value = x; decimal.s128Value = x;
} }
value = decimal.toString(true);
dataconvert::DataConvert::decimalToString(&decimal.s128Value,
decimal.scale, buf, 80, parm[0]->data()->resultType().colDataType);
} }
else else
{ {
@ -1973,12 +1970,8 @@ string Func_format::getStrVal(Row& row,
decimal.value = x; decimal.value = x;
} }
value = decimal.toString();
dataconvert::DataConvert::decimalToString( decimal.value,
decimal.scale, buf, 80, parm[0]->data()->resultType().colDataType);
} }
value = buf;
} }
break; break;

View File

@ -116,18 +116,15 @@ inline bool getBool(rowgroup::Row& row,
{ {
IDB_Decimal d = pm[0]->data()->getDecimalVal(row, isNull); IDB_Decimal d = pm[0]->data()->getDecimalVal(row, isNull);
char buf[80];
if (pm[0]->data()->resultType().colWidth == datatypes::MAXDECIMALWIDTH) 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 else
{ {
dataconvert::DataConvert::decimalToString(d.value, d.scale, buf, 80, pm[0]->data()->resultType().colDataType); expr = d.toString();
} }
expr = buf;
break; break;
} }
@ -198,18 +195,14 @@ inline bool getBool(rowgroup::Row& row,
{ {
IDB_Decimal d = pm[1]->data()->getDecimalVal(row, isNull); IDB_Decimal d = pm[1]->data()->getDecimalVal(row, isNull);
char buf[80];
if (pm[1]->data()->resultType().colWidth == datatypes::MAXDECIMALWIDTH) 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 else
{ {
dataconvert::DataConvert::decimalToString(d.value, d.scale, buf, 80, pm[1]->data()->resultType().colDataType); pattern = d.toString();
} }
pattern = buf;
break; break;
} }

View File

@ -721,13 +721,9 @@ string Func_round::getStrVal(Row& row,
} }
if (!op_ct.isWideDecimalType()) if (!op_ct.isWideDecimalType())
return dataconvert::DataConvert::decimalToString(x.value, x.scale, op_ct.colDataType); return x.toString();
else else
{ return x.toString(true);
char buf[datatypes::Decimal::MAXLENGTH16BYTES];
dataconvert::DataConvert::decimalToString( &x.s128Value, x.scale, buf, (uint8_t) sizeof(buf), op_ct.colDataType);
return string(buf);
}
} }

View File

@ -740,13 +740,9 @@ string Func_truncate::getStrVal(Row& row,
} }
if (!op_ct.isWideDecimalType()) if (!op_ct.isWideDecimalType())
return dataconvert::DataConvert::decimalToString(x.value, x.scale, op_ct.colDataType); return x.toString();
else else
{ return x.toString(true);
char buf[datatypes::Decimal::MAXLENGTH16BYTES];
dataconvert::DataConvert::decimalToString( &x.s128Value, x.scale, buf, (uint8_t) sizeof(buf), op_ct.colDataType);
return string(buf);
}
} }

View File

@ -785,10 +785,6 @@ string longDoubleToString(long double ld)
return buf; 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 ); 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 IDB_date_format(const dataconvert::DateTime&, const std::string&);
const std::string timediff(int64_t, int64_t, bool isDateTime = true); const std::string timediff(int64_t, int64_t, bool isDateTime = true);

View File

@ -640,12 +640,11 @@ string Row::toString() const
case CalpontSystemCatalog::UDECIMAL: case CalpontSystemCatalog::UDECIMAL:
if (colWidths[i] == datatypes::MAXDECIMALWIDTH) if (colWidths[i] == datatypes::MAXDECIMALWIDTH)
{ {
unsigned int buflen = datatypes::Decimal::MAXLENGTH16BYTES; datatypes::VDecimal dec(0,
char *buf = (char*)alloca(buflen); scale[i],
// empty the buffer precision[i],
dataconvert::DataConvert::decimalToString(getBinaryField<int128_t>(i), getBinaryField<int128_t>(i));
scale[i], buf, buflen, types[i]); os << dec << " ";
os << buf << " ";
break; break;
} }
//fallthrough //fallthrough

View File

@ -300,7 +300,6 @@ void BRMReporter::sendCPToFile( )
{ {
if (fCPInfo.size() > 0) if (fCPInfo.size() > 0)
{ {
char buf[datatypes::Decimal::MAXLENGTH16BYTES];
std::ostringstream oss; std::ostringstream oss;
oss << "Writing " << fCPInfo.size() << " CP updates for table " << oss << "Writing " << fCPInfo.size() << " CP updates for table " <<
fTableName << " to report file " << fRptFileName; fTableName << " to report file " << fRptFileName;
@ -319,14 +318,9 @@ void BRMReporter::sendCPToFile( )
} }
else else
{ {
std::string bigMin, bigMax; datatypes::TSInt128 bigMin(&fCPInfo[i].bigMin);
datatypes::TSInt128 bigMax(&fCPInfo[i].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;
fRptFile << "CP: " << fCPInfo[i].startLbid << ' ' << fRptFile << "CP: " << fCPInfo[i].startLbid << ' ' <<
bigMax << ' ' << bigMax << ' ' <<
bigMin << ' ' << bigMin << ' ' <<

View File

@ -2994,16 +2994,11 @@ uint8_t WE_DMLCommandProc::processUpdate(messageqcpp::ByteStream& bs,
{ {
if (fetchColColwidths[fetchColPos] == datatypes::MAXDECIMALWIDTH) if (fetchColColwidths[fetchColPos] == datatypes::MAXDECIMALWIDTH)
{ {
int128_t* dec; datatypes::VDecimal dec(0,
char buf[datatypes::Decimal::MAXLENGTH16BYTES]; fetchColScales[fetchColPos],
dec = row.getBinaryField<int128_t>(fetchColPos); rowGroups[txnId]->getPrecision()[fetchColPos],
row.getBinaryField<int128_t>(fetchColPos));
dataconvert::DataConvert::decimalToString(dec, value = dec.toString(true);
(unsigned)fetchColScales[fetchColPos], buf,
(uint8_t) sizeof(buf), fetchColTypes[fetchColPos]);
value.assign(buf);
break; break;
} }
} }
@ -3042,12 +3037,10 @@ uint8_t WE_DMLCommandProc::processUpdate(messageqcpp::ByteStream& bs,
} }
else else
{ {
const int ctmp_size = 65 + 1 + 1 + 1; datatypes::VDecimal dec(intColVal,
char ctmp[ctmp_size] = {0}; fetchColScales[fetchColPos],
DataConvert::decimalToString( rowGroups[txnId]->getPrecision()[fetchColPos]);
intColVal, fetchColScales[fetchColPos], value = dec.toString();
ctmp, ctmp_size, fetchColTypes[fetchColPos]);
value = ctmp; // null termination by decimalToString
} }
} }
break; break;
@ -3356,16 +3349,11 @@ uint8_t WE_DMLCommandProc::processUpdate(messageqcpp::ByteStream& bs,
{ {
if (fetchColColwidths[fetchColPos] == datatypes::MAXDECIMALWIDTH) if (fetchColColwidths[fetchColPos] == datatypes::MAXDECIMALWIDTH)
{ {
int128_t* dec; datatypes::VDecimal dec(0,
char buf[datatypes::Decimal::MAXLENGTH16BYTES]; fetchColScales[fetchColPos],
dec = row.getBinaryField<int128_t>(fetchColPos); rowGroups[txnId]->getPrecision()[fetchColPos],
row.getBinaryField<int128_t>(fetchColPos));
dataconvert::DataConvert::decimalToString(dec, value = dec.toString(true);
(unsigned)fetchColScales[fetchColPos], buf,
(uint8_t) sizeof(buf), fetchColTypes[fetchColPos]);
value = buf;
break; break;
} }
} }
@ -3405,12 +3393,10 @@ uint8_t WE_DMLCommandProc::processUpdate(messageqcpp::ByteStream& bs,
} }
else else
{ {
const int ctmp_size = 65 + 1 + 1 + 1; datatypes::VDecimal dec(intColVal,
char ctmp[ctmp_size] = {0}; fetchColScales[fetchColPos],
DataConvert::decimalToString( rowGroups[txnId]->getPrecision()[fetchColPos]);
intColVal, fetchColScales[fetchColPos], value = dec.toString();
ctmp, ctmp_size, fetchColTypes[fetchColPos]);
value = ctmp; // null termination by decimalToString
} }
} }
break; break;

View File

@ -3896,11 +3896,8 @@ void WriteEngineWrapper::printInputValue(const ColStructList& colStructList,
curStr = boost::lexical_cast<string>(boost::any_cast<long long>(curTuple.data)); curStr = boost::lexical_cast<string>(boost::any_cast<long long>(curTuple.data));
else if (curTuple.data.type() == typeid(int128_t)) else if (curTuple.data.type() == typeid(int128_t))
{ {
// WIP replace with a single call datatypes::TSInt128 val(boost::any_cast<int128_t>(curTuple.data));
char buf[datatypes::Decimal::MAXLENGTH16BYTES]; curStr = val.toString();
int128_t val = boost::any_cast<int128_t>(curTuple.data);
dataconvert::DataConvert::decimalToString(&val, 0, buf, (uint8_t) sizeof(buf), curColStruct.colDataType);
curStr.assign(buf);
} }
else if (curTuple.data.type() == typeid(double)) else if (curTuple.data.type() == typeid(double))
curStr = boost::lexical_cast<string>(boost::any_cast<double>(curTuple.data)); curStr = boost::lexical_cast<string>(boost::any_cast<double>(curTuple.data));