1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2025-07-29 08:21:15 +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

@ -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,

View File

@ -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