You've already forked mariadb-columnstore-engine
mirror of
https://github.com/mariadb-corporation/mariadb-columnstore-engine.git
synced 2025-07-30 19:23:07 +03:00
MCOL-4387 Convert dataconvert::decimalToString() into VDecimal and TSInt128 methods
This commit is contained in:
@ -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
|
||||
DataConvert::StringToBit(const datatypes::SystemCatalog::TypeAttributesStd& colType,
|
||||
const datatypes::ConvertFromStringParam &prm,
|
||||
|
@ -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<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)
|
||||
{
|
||||
// Trims whitespace characters off non-dict character data
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
@ -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))
|
||||
|
@ -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))
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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<int128_t>(i),
|
||||
scale[i], buf, buflen, types[i]);
|
||||
os << buf << " ";
|
||||
datatypes::VDecimal dec(0,
|
||||
scale[i],
|
||||
precision[i],
|
||||
getBinaryField<int128_t>(i));
|
||||
os << dec << " ";
|
||||
break;
|
||||
}
|
||||
//fallthrough
|
||||
|
Reference in New Issue
Block a user