1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2025-07-30 19:23:07 +03:00

MCOL-641 Replaced NULL binary constants.

DataConvert::decimalToString, toString, writeIntPart, writeFractionalPart are not templates anymore.
This commit is contained in:
Roman Nozdrin
2020-03-02 14:38:40 +00:00
parent 61647c1f5b
commit 97ee1609b2
16 changed files with 200 additions and 193 deletions

View File

@ -83,8 +83,11 @@ const uint16_t NULL_UINT16 = USMALLINTNULL;
const uint32_t NULL_UINT32 = UINTNULL; const uint32_t NULL_UINT32 = UINTNULL;
const uint64_t NULL_UINT64 = UBIGINTNULL; const uint64_t NULL_UINT64 = UBIGINTNULL;
const uint64_t BINARYEMPTYROW = UBIGINTEMPTYROW; const uint64_t BINARYNULLVALUELOW = 0ULL;
const uint64_t BINARYNULL = UBIGINTNULL; const uint64_t BINARYNULLVALUEHIGH = 0x8000000000000000ULL;
const uint64_t BINARYEMPTYVALUELOW = 1ULL;
const uint64_t BINARYEMPTYVALUEHIGH = 0x8000000000000000ULL;
const uint64_t BINARYEMPTYROW = 0ULL;
const std::string CPNULLSTRMARK("_CpNuLl_"); const std::string CPNULLSTRMARK("_CpNuLl_");
const std::string CPSTRNOTFOUND("_CpNoTf_"); const std::string CPSTRNOTFOUND("_CpNoTf_");

View File

@ -805,36 +805,21 @@ int fetchNextRow(uchar* buf, cal_table_info& ti, cal_connection_info* ci, bool h
case CalpontSystemCatalog::DECIMAL: case CalpontSystemCatalog::DECIMAL:
case CalpontSystemCatalog::UDECIMAL: case CalpontSystemCatalog::UDECIMAL:
{ {
// WIP MCOL-641 if (colType.colWidth == 16)
if (row.getPrecision(s) > 18)
{ {
// unset null bit first // unset null bit first
// Might be redundant // Might be redundant
if ((*f)->null_ptr) if ((*f)->null_ptr)
*(*f)->null_ptr &= ~(*f)->null_bit; *(*f)->null_ptr &= ~(*f)->null_bit;
uint128_t* udec;
int128_t* dec; int128_t* dec;
// We won't have more than 38 digits + sign + dp // We won't have more than [+-][0][.] + up to 38 digits
// Make this precision based char buf[utils::MAXLENGTH16BYTES];
char buf[41];
// This C-style cast doesn't look appropriate. dec = row.getBinaryField<int128_t>(s);
// Is there a way to use decltype instead of if? dataconvert::DataConvert::decimalToString(dec,
if (colType.colDataType == CalpontSystemCatalog::DECIMAL) (unsigned)colType.scale, buf,
{ sizeof(buf), colType.colDataType);
dec = row.getBinaryField<int128_t>(s);
dataconvert::DataConvert::decimalToString(dec,
(unsigned)colType.scale, buf,
sizeof(buf), colType.colDataType);
}
else
{
udec = row.getBinaryField<uint128_t>(s);
dataconvert::DataConvert::decimalToString(udec,
(unsigned)colType.scale, buf,
sizeof(buf), colType.colDataType);
}
Field_new_decimal* f2 = (Field_new_decimal*)*f; Field_new_decimal* f2 = (Field_new_decimal*)*f;
f2->store(buf, strlen(buf), f2->charset()); f2->store(buf, strlen(buf), f2->charset());

View File

@ -40,6 +40,7 @@ using namespace boost;
#include "stats.h" #include "stats.h"
#include "primproc.h" #include "primproc.h"
#include "dataconvert.h" #include "dataconvert.h"
#include "widedecimalutils.h"
using namespace logging; using namespace logging;
using namespace dbbc; using namespace dbbc;
using namespace primitives; using namespace primitives;
@ -277,16 +278,17 @@ template<>
inline bool isEmptyVal<32>(uint8_t type, const uint8_t* ival) // For BINARY inline bool isEmptyVal<32>(uint8_t type, const uint8_t* ival) // For BINARY
{ {
const uint64_t* val = reinterpret_cast<const uint64_t*>(ival); const uint64_t* val = reinterpret_cast<const uint64_t*>(ival);
return ((val[0] == joblist::BINARYEMPTYROW) && (val[1] == joblist::BINARYEMPTYROW) return ((val[0] == joblist::BINARYEMPTYVALUELOW)
&& (val[2] == joblist::BINARYEMPTYROW) && (val[3] == joblist::BINARYEMPTYROW)); && (val[1] == joblist::BINARYNULLVALUELOW)
&& (val[2] == joblist::BINARYNULLVALUELOW)
&& (val[3] == joblist::BINARYEMPTYVALUEHIGH));
} }
template<> template<>
inline bool isEmptyVal<16>(uint8_t type, const uint8_t* ival) // For BINARY inline bool isEmptyVal<16>(uint8_t type, const uint8_t* ival) // For BINARY
{ {
const uint64_t* val = reinterpret_cast<const uint64_t*>(ival); const int128_t* val = reinterpret_cast<const int128_t*>(ival);
return ((val[0] == joblist::BINARYEMPTYROW) && (val[1] == joblist::BINARYEMPTYROW)); return utils::isWideDecimalEmptyValue (*val);
} }
template<> template<>
@ -410,19 +412,22 @@ inline bool isEmptyVal<1>(uint8_t type, const uint8_t* ival)
template<int> template<int>
inline bool isNullVal(uint8_t type, const uint8_t* val8); inline bool isNullVal(uint8_t type, const uint8_t* val8);
// WIP This method only works for wide DECIMAL so far.
template<> template<>
inline bool isNullVal<16>(uint8_t type, const uint8_t* ival) // For BINARY inline bool isNullVal<16>(uint8_t type, const uint8_t* ival) // For BINARY
{ {
const uint64_t* val = reinterpret_cast<const uint64_t*>(ival); const int128_t* val = reinterpret_cast<const int128_t*>(ival);
return ((val[0] == joblist::BINARYNULL) && (val[1] == joblist::BINARYEMPTYROW)); return utils::isWideDecimalNullValue (*val);
} }
template<> template<>
inline bool isNullVal<32>(uint8_t type, const uint8_t* ival) // For BINARY inline bool isNullVal<32>(uint8_t type, const uint8_t* ival) // For BINARY
{ {
const uint64_t* val = reinterpret_cast<const uint64_t*>(ival); const uint64_t* val = reinterpret_cast<const uint64_t*>(ival);
return ((val[0] == joblist::BINARYNULL) && (val[1] == joblist::BINARYEMPTYROW) return ((val[0] == joblist::BINARYNULLVALUELOW)
&& (val[2] == joblist::BINARYEMPTYROW) && (val[3] == joblist::BINARYEMPTYROW)); && (val[1] == joblist::BINARYNULLVALUELOW)
&& (val[2] == joblist::BINARYNULLVALUELOW)
&& (val[3] == joblist::BINARYNULLVALUEHIGH));
} }
template<> template<>

View File

@ -40,6 +40,7 @@ using namespace std;
#include "primitiveserver.h" #include "primitiveserver.h"
#include "primproc.h" #include "primproc.h"
#include "stats.h" #include "stats.h"
#include "widedecimalutils.h"
using namespace messageqcpp; using namespace messageqcpp;
using namespace rowgroup; using namespace rowgroup;
@ -1062,9 +1063,8 @@ const uint64_t ColumnCommand::getEmptyRowValue( const CSCDataType dataType, cons
void ColumnCommand::getEmptyRowValue(const CSCDataType dataType, void ColumnCommand::getEmptyRowValue(const CSCDataType dataType,
const int width, messageqcpp::ByteStream::hexbyte* space) const const int width, messageqcpp::ByteStream::hexbyte* space) const
{ {
uint64_t *ptr = reinterpret_cast<uint64_t*>(space); int128_t *val = reinterpret_cast<int128_t*>(space);
ptr[0] = joblist::BINARYEMPTYROW; utils::setWideDecimalEMptyValue(*val);
ptr[1] = joblist::BINARYEMPTYROW;
} }
void ColumnCommand::getLBIDList(uint32_t loopCount, vector<int64_t>* lbids) void ColumnCommand::getLBIDList(uint32_t loopCount, vector<int64_t>* lbids)

View File

@ -18,11 +18,12 @@
#ifndef UTILS_COLWIDTH_H #ifndef UTILS_COLWIDTH_H
#define UTILS_COLWIDTH_H #define UTILS_COLWIDTH_H
#define MAXLEGACYWIDTH 8
#define MAXCOLUMNWIDTH 16
namespace utils namespace utils
{ {
const uint8_t MAXLEGACYWIDTH = 8ULL;
const uint8_t MAXCOLUMNWIDTH = 16ULL;
inline bool isWide(uint8_t width) inline bool isWide(uint8_t width)
{ {
return width > MAXLEGACYWIDTH; return width > MAXLEGACYWIDTH;

View File

@ -127,7 +127,7 @@ uint64_t getNullValue(CalpontSystemCatalog::ColDataType t, uint32_t colWidth)
return joblist::UBIGINTNULL; return joblist::UBIGINTNULL;
case CalpontSystemCatalog::BINARY: case CalpontSystemCatalog::BINARY:
return joblist::BINARYNULL; return joblist::BINARYNULLVALUELOW;
case CalpontSystemCatalog::VARBINARY: case CalpontSystemCatalog::VARBINARY:
default: default:
@ -201,7 +201,6 @@ int64_t getSignedNullValue(CalpontSystemCatalog::ColDataType t, uint32_t colWidt
default: default:
throw logic_error("getSignedNullValue() Can't return the NULL string"); throw logic_error("getSignedNullValue() Can't return the NULL string");
} }
break; break;
} }
@ -219,8 +218,14 @@ int64_t getSignedNullValue(CalpontSystemCatalog::ColDataType t, uint32_t colWidt
case 4 : case 4 :
return (int64_t) ((int32_t) joblist::INTNULL); return (int64_t) ((int32_t) joblist::INTNULL);
default: case 8:
return joblist::BIGINTNULL; return joblist::BIGINTNULL;
default:
ostringstream os;
os << "getSignedNullValue(): got bad column width (" << t <<
"). Width=" << colWidth << endl;
throw logic_error(os.str());
} }
break; break;
@ -243,7 +248,7 @@ int64_t getSignedNullValue(CalpontSystemCatalog::ColDataType t, uint32_t colWidt
return (int64_t)joblist::LONGDOUBLENULL; return (int64_t)joblist::LONGDOUBLENULL;
case CalpontSystemCatalog::BINARY: case CalpontSystemCatalog::BINARY:
return (int64_t)joblist::BINARYNULL; return (int64_t)joblist::BINARYNULLVALUELOW;
case CalpontSystemCatalog::VARBINARY: case CalpontSystemCatalog::VARBINARY:
default: default:

View File

@ -18,30 +18,58 @@
#ifndef WIDE_DECIMAL_UTILS_H #ifndef WIDE_DECIMAL_UTILS_H
#define WIDE_DECIMAL_UTILS_H #define WIDE_DECIMAL_UTILS_H
namespace utils
{
using int128_t = __int128; using int128_t = __int128;
using uint128_t = unsigned __int128; using uint128_t = unsigned __int128;
const uint64_t BINARYNULLVALUELOW = 0ULL; namespace utils
const uint64_t BINARYNULLVALUEHIGH = 0x8000000000000000ULL; {
const uint64_t BINARYEMPTYVALUELOW = 1ULL; const uint64_t BINARYNULLVALUELOW = 0ULL;
const uint64_t BINARYEMPTYVALUEHIGH = 0x8000000000000000ULL; const uint64_t BINARYNULLVALUEHIGH = 0x8000000000000000ULL;
const uint64_t BINARYEMPTYVALUELOW = 1ULL;
const uint64_t BINARYEMPTYVALUEHIGH = 0x8000000000000000ULL;
const uint8_t MAXLENGTH16BYTES = 42;
inline bool isWideDecimalNullValue(const int128_t val) inline bool isWideDecimalNullValue(const int128_t& val)
{ {
const uint64_t* ptr = reinterpret_cast<const uint64_t*>(&val); const uint64_t* ptr = reinterpret_cast<const uint64_t*>(&val);
return (ptr[0] == BINARYNULLVALUELOW && ptr[1] == BINARYNULLVALUEHIGH); return (ptr[0] == BINARYNULLVALUELOW && ptr[1] == BINARYNULLVALUEHIGH);
} }
inline bool isWideDecimalEmptyValue(const int128_t val) inline bool isWideDecimalEmptyValue(const int128_t& val)
{ {
const uint64_t* ptr = reinterpret_cast<const uint64_t*>(&val); const uint64_t* ptr = reinterpret_cast<const uint64_t*>(&val);
return (ptr[0] == BINARYEMPTYVALUELOW && ptr[1] == BINARYEMPTYVALUEHIGH); return (ptr[0] == BINARYEMPTYVALUELOW && ptr[1] == BINARYEMPTYVALUEHIGH);
} }
inline void int128Max(int128_t& val) inline void setWideDecimalNullValue(int128_t& val)
{
uint64_t* ptr = reinterpret_cast<uint64_t*>(&val);
ptr[0] = BINARYNULLVALUELOW;
ptr[1] = BINARYNULLVALUEHIGH;
}
inline void setWideDecimalEMptyValue(int128_t& val)
{
uint64_t* ptr = reinterpret_cast<uint64_t*>(&val);
ptr[0] = BINARYEMPTYVALUELOW;
ptr[1] = BINARYEMPTYVALUEHIGH;
}
inline void setWideDecimalNullValue(int128_t* val)
{
uint64_t* ptr = reinterpret_cast<uint64_t*>(val);
ptr[0] = BINARYNULLVALUELOW;
ptr[1] = BINARYNULLVALUEHIGH;
}
inline void setWideDecimalEMptyValue(int128_t* val)
{
uint64_t* ptr = reinterpret_cast<uint64_t*>(val);
ptr[0] = BINARYEMPTYVALUELOW;
ptr[1] = BINARYEMPTYVALUEHIGH;
}
inline void int128Max(int128_t& val)
{ {
uint64_t* ptr = reinterpret_cast<uint64_t*>(&val); uint64_t* ptr = reinterpret_cast<uint64_t*>(&val);
ptr[0] = 0xFFFFFFFFFFFFFFFF; ptr[0] = 0xFFFFFFFFFFFFFFFF;
@ -61,7 +89,6 @@ const uint64_t BINARYEMPTYVALUEHIGH = 0x8000000000000000ULL;
ptr[0] = 0xFFFFFFFFFFFFFFFF; ptr[0] = 0xFFFFFFFFFFFFFFFF;
ptr[1] = 0xFFFFFFFFFFFFFFFF; ptr[1] = 0xFFFFFFFFFFFFFFFF;
} }
} }
#endif // WIDE_DECIMAL_UTILS_H #endif // WIDE_DECIMAL_UTILS_H

View File

@ -102,6 +102,29 @@ const string columnstore_big_precision[20] =
"99999999999999999999999999999999999999" "99999999999999999999999999999999999999"
}; };
const uint64_t columnstore_pow_10[20] =
{
1ULL,
10ULL,
100ULL,
1000ULL,
10000ULL,
100000ULL,
1000000ULL,
10000000ULL,
100000000ULL,
1000000000ULL,
10000000000ULL,
100000000000ULL,
1000000000000ULL,
10000000000000ULL,
100000000000000ULL,
1000000000000000ULL,
10000000000000000ULL,
100000000000000000ULL,
1000000000000000000ULL,
10000000000000000000ULL
};
template <class T> template <class T>
bool from_string(T& t, const std::string& s, std::ios_base & (*f)(std::ios_base&)) bool from_string(T& t, const std::string& s, std::ios_base & (*f)(std::ios_base&))
{ {
@ -1226,32 +1249,37 @@ bool stringToTimestampStruct(const string& data, TimeStamp& timeStamp, const str
} }
// WIP MCOL-641 size_t DataConvert::writeIntPart(int128_t* dec, char* p,
template <typename T>
size_t DataConvert::writeIntPart(T* dec, char* p,
const uint16_t buflen, const uint16_t buflen,
const uint8_t scale) //don't need this const uint8_t scale)
{ {
T intPart = *dec; int128_t intPart = *dec;
if (scale) if (scale)
{ {
//TODO Use dictionary to produce divisor uint8_t maxPowOf10 = sizeof(columnstore_pow_10)/sizeof(columnstore_pow_10[0])-1;
// instead of a loop switch (scale/maxPowOf10)
for (size_t i = 0; i < scale; i++) {
intPart /= 10; case(2):
intPart /= columnstore_pow_10[maxPowOf10];
intPart /= columnstore_pow_10[maxPowOf10];
break;
case(1):
intPart /= columnstore_pow_10[maxPowOf10];
case(0):
intPart /= columnstore_pow_10[scale%maxPowOf10];
}
} }
// optimize for less then uint64_t values
uint64_t div = 10000000000000000000ULL; uint64_t div = 10000000000000000000ULL;
T high = intPart; int128_t high = intPart;
T low; int128_t low;
low = high % div; low = high % div;
high /= div; high /= div;
T mid; int128_t mid;
mid = high % div; mid = high % div;
high /= div; high /= div;
// pod[0] is high 8 byte, pod[1] is low // pod[0] is low 8 byte, pod[1] is high
uint64_t* high_pod = reinterpret_cast<uint64_t*>(&high); uint64_t* high_pod = reinterpret_cast<uint64_t*>(&high);
uint64_t* mid_pod = reinterpret_cast<uint64_t*>(&mid); uint64_t* mid_pod = reinterpret_cast<uint64_t*>(&mid);
uint64_t* low_pod = reinterpret_cast<uint64_t*>(&low); uint64_t* low_pod = reinterpret_cast<uint64_t*>(&low);
@ -1287,17 +1315,29 @@ size_t DataConvert::writeIntPart(T* dec, char* p,
return p-original_p; return p-original_p;
} }
template<typename T> size_t DataConvert::writeFractionalPart(int128_t* dec, char* p,
size_t DataConvert::writeFractionalPart(T* dec, char* p,
const uint16_t buflen, const uint16_t buflen,
const uint8_t scale) const uint8_t scale)
{ {
//TODO Use dictionary instead of multiplication. int128_t scaleDivisor = 1;
T scaleDivisor = 10;
for (size_t i = 1; i < scale; i++) uint8_t maxPowOf10 = sizeof(columnstore_pow_10)/sizeof(columnstore_pow_10[0])-1;
scaleDivisor *= 10; switch (scale/maxPowOf10)
{
case(2):
scaleDivisor *= columnstore_pow_10[maxPowOf10];
scaleDivisor *= columnstore_pow_10[maxPowOf10];
break;
case(1):
scaleDivisor *= columnstore_pow_10[maxPowOf10];
case(0):
scaleDivisor *= columnstore_pow_10[scale%maxPowOf10];
}
//for (size_t i = 1; i < scale; i++)
// scaleDivisor *= 10;
T fractionalPart = *dec % scaleDivisor; int128_t fractionalPart = *dec % scaleDivisor;
// divide by the base untill we have non-zero quotinent // divide by the base untill we have non-zero quotinent
size_t written = 0; size_t written = 0;
scaleDivisor /= 10; scaleDivisor /= 10;
@ -1319,38 +1359,24 @@ size_t DataConvert::writeFractionalPart(T* dec, char* p,
return scale; return scale;
} }
template<typename T> void DataConvert::toString(int128_t* dec, uint8_t scale,
void DataConvert::toString(T* dec, uint8_t scale,
char *p, unsigned int buflen) char *p, unsigned int buflen)
{ {
char* original_p = p; char* original_p = p;
size_t written = 0; size_t written = 0;
// Early return for NULL value // Raise exception on NULL and EMPTY value
int128_t sign = 0; if (utils::isWideDecimalNullValue(*dec) || utils::isWideDecimalEmptyValue(*dec))
// WIP use constants here
// WIP Treat both magics here
uint64_t* signPod = reinterpret_cast<uint64_t*>(&sign);
signPod[1] = utils::BINARYNULLVALUEHIGH;
if (*dec == sign)
{ {
*p++ = '0'; throw QueryDataExcept("toString() char buffer overflow.", formatErr);
if (scale)
{
*p++ = '.';
while (scale-- > 0)
*p++ = '0';
}
return;
} }
if (*dec < static_cast<T>(0)) if (*dec < static_cast<int128_t>(0))
{ {
*p++ = '-'; *p++ = '-';
*dec *= -1; *dec *= -1;
} }
written = writeIntPart<T>(dec, p, buflen, scale); written = writeIntPart(dec, p, buflen, scale);
p += written; p += written;
if (scale) if (scale)
@ -1365,10 +1391,6 @@ void DataConvert::toString(T* dec, uint8_t scale,
} }
} }
template
void DataConvert::toString<int128_t>(int128_t* dec, uint8_t scale,
char *p, unsigned int buflen);
// WIP MCOL-641 // WIP MCOL-641
void atoi128(const std::string& arg, int128_t& res) void atoi128(const std::string& arg, int128_t& res)
{ {
@ -1397,25 +1419,14 @@ void atoi128(const std::string& arg, uint128_t& res)
} }
} }
// WIP MCOL-641 void DataConvert::decimalToString(int128_t* valuePtr,
// Doesn't work for -0.042
template <typename T>
void DataConvert::decimalToString(T* valuePtr,
uint8_t scale, uint8_t scale,
char* buf, char* buf,
unsigned int buflen, unsigned int buflen,
cscDataType colDataType) // We don't need the last one cscDataType colDataType) // We don't need the last one
{ {
toString(valuePtr, scale, buf, buflen);
toString<T>(valuePtr, scale, buf, buflen);
} }
// Explicit instantiation
template
void DataConvert::decimalToString<int128_t>(int128_t* value, uint8_t scale,
char* buf, unsigned int buflen, cscDataType colDataType);
template
void DataConvert::decimalToString<uint128_t>(uint128_t* value, uint8_t scale,
char* buf, unsigned int buflen, cscDataType colDataType);
boost::any boost::any
DataConvert::convertColumnData(const CalpontSystemCatalog::ColType& colType, DataConvert::convertColumnData(const CalpontSystemCatalog::ColType& colType,

View File

@ -1041,17 +1041,13 @@ public:
EXPORT static bool isNullData(execplan::ColumnResult* cr, int rownum, execplan::CalpontSystemCatalog::ColType colType); EXPORT static bool isNullData(execplan::ColumnResult* cr, int rownum, execplan::CalpontSystemCatalog::ColType colType);
static inline std::string decimalToString(int64_t value, uint8_t scale, cscDataType colDataType); 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 inline void decimalToString(int64_t value, uint8_t scale, char* buf, unsigned int buflen, cscDataType colDataType);
template <typename T> static void decimalToString(int128_t* value, uint8_t scale, char* buf, unsigned int buflen, cscDataType colDataType);
EXPORT static void decimalToString(T* value, uint8_t scale, char* buf, unsigned int buflen, cscDataType colDataType);
template <typename T> static void toString(int128_t* dec, uint8_t scale, char* p, unsigned int buflen);
static void toString(T* dec, uint8_t scale, char* p, unsigned int buflen); static size_t writeIntPart(int128_t* dec, char* p, const uint16_t buflen,
template <typename T> const uint8_t scale);
static size_t writeIntPart(T* dec, char* p, const uint16_t buflen, static size_t writeFractionalPart(int128_t* dec, char* p, const uint16_t buflen,
const uint8_t scale); const uint8_t scale);
template <typename T>
static size_t writeFractionalPart(T* dec, char* p,
const uint16_t buflen, const uint8_t scale);
static inline void int128Max(int128_t& i) static inline void int128Max(int128_t& i)
{ {

View File

@ -477,11 +477,11 @@ void FuncExp::evaluate(rowgroup::Row& row, std::vector<execplan::SRCP>& expressi
{ {
// WIP make this a separate function w and w/o overflow check // WIP make this a separate function w and w/o overflow check
if (expression[i]->resultType().colDataType == execplan::CalpontSystemCatalog::DECIMAL) if (expression[i]->resultType().colDataType == execplan::CalpontSystemCatalog::DECIMAL)
row.setBinaryField_offset(reinterpret_cast<uint8_t*>(&val.__v.__s128), row.setBinaryField_offset(&val.__v.__s128,
expression[i]->resultType().colWidth, expression[i]->resultType().colWidth,
row.getOffset(expression[i]->outputIndex())); row.getOffset(expression[i]->outputIndex()));
else else
row.setBinaryField_offset(reinterpret_cast<uint8_t*>(&val.__v.__u128), row.setBinaryField_offset(&val.__v.__u128,
expression[i]->resultType().colWidth, expression[i]->resultType().colWidth,
row.getOffset(expression[i]->outputIndex())); row.getOffset(expression[i]->outputIndex()));
} }

View File

@ -53,6 +53,7 @@
#include "vlarray.h" #include "vlarray.h"
#include "collation.h" #include "collation.h"
#include "widedecimalutils.h"
//..comment out NDEBUG to enable assertions, uncomment NDEBUG to disable //..comment out NDEBUG to enable assertions, uncomment NDEBUG to disable
//#define NDEBUG //#define NDEBUG
@ -222,19 +223,8 @@ inline string getStringNullValue()
return joblist::CPNULLSTRMARK; return joblist::CPNULLSTRMARK;
} }
inline uint64_t getBinaryNullValue()
{
return joblist::BINARYNULL;
} }
inline uint64_t getBinaryEmptyValue()
{
return joblist::BINARYEMPTYROW;
}
}
namespace rowgroup namespace rowgroup
{ {
const std::string typeStr(""); const std::string typeStr("");
@ -1176,14 +1166,11 @@ void RowAggregation::makeAggFieldsNull(Row& row)
} }
else else
{ {
// WIP This is only 1st part of the value int128_t nullValue = 0;
uint64_t nullValue = getBinaryNullValue(); utils::setWideDecimalNullValue(nullValue);
uint64_t emptyValue = getBinaryEmptyValue();
uint32_t offset = row.getOffset(colOut); uint32_t offset = row.getOffset(colOut);
row.setBinaryField_offset(&nullValue, sizeof(nullValue), row.setBinaryField_offset(&nullValue, sizeof(nullValue),
offset); offset);
row.setBinaryField_offset(&emptyValue, sizeof(nullValue),
offset+sizeof(nullValue));
} }
break; break;
} }

View File

@ -91,15 +91,9 @@ class RowDecimalTest : public ::testing::Test {
int128_t nullValue = 0; int128_t nullValue = 0;
int128_t bigValue = 0; int128_t bigValue = 0;
uint64_t* uint128_pod = reinterpret_cast<uint64_t*>(&nullValue); uint64_t* uint128_pod = reinterpret_cast<uint64_t*>(&nullValue);
uint128_pod[0] = joblist::BINARYNULL; uint128_pod[0] = joblist::UBIGINTNULL;
uint128_pod[1] = joblist::BINARYEMPTYROW; uint128_pod[1] = joblist::UBIGINTEMPTYROW;
bigValue = -static_cast<int128_t>(0xFFFFFFFF)*0xFFFFFFFFFFFFFFFF; bigValue = -static_cast<int128_t>(0xFFFFFFFF)*0xFFFFFFFFFFFFFFFF;
//char buf[utils::precisionByWidth(16)+3];
//memset(&buf[0], 0, sizeof(buf));
//int scale1 = 3;
//dataconvert::DataConvert::decimalToString(&bigValue, scale1, buf,
// utils::precisionByWidth(sizeof(bigValue))+3,types[0]);
//std::cout << buf << std::endl;
sValueVector.push_back(nullValue); sValueVector.push_back(nullValue);
sValueVector.push_back(-42); sValueVector.push_back(-42);
sValueVector.push_back(bigValue); sValueVector.push_back(bigValue);
@ -136,8 +130,6 @@ class RowDecimalTest : public ::testing::Test {
s64ValueVector.push_back(0x81); s64ValueVector.push_back(0x81);
s64ValueVector.push_back(joblist::BIGINTNULL-1); s64ValueVector.push_back(joblist::BIGINTNULL-1);
//r.initToNull();
//r.nextRow(rowSize);
for(size_t i = 0; i < sValueVector.size(); i++) { for(size_t i = 0; i < sValueVector.size(); i++) {
r.setBinaryField_offset(&sValueVector[i], r.setBinaryField_offset(&sValueVector[i],
sizeof(sValueVector[0]), offsets[0]); sizeof(sValueVector[0]), offsets[0]);

View File

@ -44,6 +44,7 @@ using namespace execplan;
#include "rowgroup.h" #include "rowgroup.h"
#include "dataconvert.h" #include "dataconvert.h"
#include "columnwidth.h" #include "columnwidth.h"
#include "widedecimalutils.h"
#include "collation.h" #include "collation.h"
@ -850,9 +851,7 @@ void Row::initToNull()
case 16 : case 16 :
{ {
uint64_t *dec = reinterpret_cast<uint64_t*>(&data[offsets[i]]); utils::setWideDecimalNullValue(reinterpret_cast<int128_t&>(data[offsets[i]]));
dec[0] = joblist::BINARYNULL;
dec[1] = joblist::BINARYEMPTYROW;
break; break;
} }
default: default:
@ -881,9 +880,7 @@ void Row::initToNull()
break; break;
case CalpontSystemCatalog::BINARY: case CalpontSystemCatalog::BINARY:
{ {
uint64_t *dec = reinterpret_cast<uint64_t*>(&data[offsets[i]]); utils::setWideDecimalNullValue(reinterpret_cast<int128_t&>(data[offsets[i]]));
dec[0] = joblist::BINARYNULL;
dec[1] = joblist::BINARYEMPTYROW;
} }
break; break;
@ -915,11 +912,11 @@ inline bool
Row::isNullValue_offset<execplan::CalpontSystemCatalog::BINARY,32>( Row::isNullValue_offset<execplan::CalpontSystemCatalog::BINARY,32>(
uint32_t offset) const uint32_t offset) const
{ {
const int64_t *intPtr = reinterpret_cast<const int64_t*>(&data[offset]); const uint64_t *intPtr = reinterpret_cast<const uint64_t*>(&data[offset]);
return ((intPtr[0] == static_cast<int64_t>(joblist::BINARYNULL)) && return ((intPtr[0] == static_cast<uint64_t>(utils::BINARYNULLVALUELOW)) &&
(intPtr[1] == static_cast<int64_t>(joblist::BINARYEMPTYROW)) && (intPtr[1] == static_cast<uint64_t>(utils::BINARYNULLVALUELOW)) &&
(intPtr[2] == static_cast<int64_t>(joblist::BINARYEMPTYROW)) && (intPtr[2] == static_cast<uint64_t>(utils::BINARYNULLVALUELOW)) &&
(intPtr[3] == static_cast<int64_t>(joblist::BINARYEMPTYROW))); (intPtr[3] == static_cast<uint64_t>(utils::BINARYEMPTYVALUEHIGH)));
} }
template<> template<>
@ -927,9 +924,8 @@ inline bool
Row::isNullValue_offset<execplan::CalpontSystemCatalog::BINARY,16>( Row::isNullValue_offset<execplan::CalpontSystemCatalog::BINARY,16>(
uint32_t offset) const uint32_t offset) const
{ {
const int64_t *intPtr = reinterpret_cast<const int64_t*>(&data[offset]); const int128_t *intPtr = reinterpret_cast<const int128_t*>(&data[offset]);
return ((intPtr[0] == static_cast<int64_t>(joblist::BINARYNULL)) return utils::isWideDecimalNullValue (*intPtr);
&& (intPtr[1] == static_cast<int64_t>(joblist::BINARYEMPTYROW)));
} }
template<> template<>
@ -937,9 +933,8 @@ inline bool
Row::isNullValue_offset<execplan::CalpontSystemCatalog::DECIMAL,16>( Row::isNullValue_offset<execplan::CalpontSystemCatalog::DECIMAL,16>(
uint32_t offset) const uint32_t offset) const
{ {
const int64_t *intPtr = reinterpret_cast<const int64_t*>(&data[offset]); const int128_t *intPtr = reinterpret_cast<const int128_t*>(&data[offset]);
return ((intPtr[0] == static_cast<int64_t>(joblist::BINARYNULL)) return utils::isWideDecimalNullValue (*intPtr);
&& (intPtr[1] == static_cast<int64_t>(joblist::BINARYEMPTYROW)));
} }
template<> template<>
@ -1059,8 +1054,7 @@ bool Row::isNullValue(uint32_t colIndex) const
case CalpontSystemCatalog::UDECIMAL: case CalpontSystemCatalog::UDECIMAL:
{ {
// WIP MCOL-641 Allmighty hack. // WIP MCOL-641 Allmighty hack.
int32_t width = getColumnWidth(colIndex); switch (getColumnWidth(colIndex))
switch (width)
{ {
// MCOL-641 // MCOL-641
case 16: case 16:

View File

@ -814,22 +814,27 @@ inline uint32_t Row::getStringLength(uint32_t colIndex) const
memcpy(&data[offset], strdata, length); memcpy(&data[offset], strdata, length);
}*/ }*/
// WIP MCOL-641. This method can be applied to uint8_t* buffers. // MCOL-641. This method can be applied to uint8_t* buffers.
template<typename T> template<typename T>
inline void Row::setBinaryField(T* value, uint32_t width, uint32_t colIndex) inline void Row::setBinaryField(T* value, uint32_t width, uint32_t colIndex)
{ {
memcpy(&data[offsets[colIndex]], value, width); memcpy(&data[offsets[colIndex]], value, width);
} }
// WIP MCOL-641. This method !cannot! be applied to uint8_t* buffers. // MCOL-641. This method !cannot! be applied to uint8_t* buffers.
template<typename T> template<typename T>
inline void Row::setBinaryField_offset(T* value, uint32_t width, uint32_t offset) inline void Row::setBinaryField_offset(T* value, uint32_t width, uint32_t offset)
{ {
// WIP Compare performance. // WIP Compare performance.
//memcpy(&data[offset], value, width);
*reinterpret_cast<T*>(&data[offset]) = *value; *reinterpret_cast<T*>(&data[offset]) = *value;
} }
template<>
inline void Row::setBinaryField_offset<uint8_t>(uint8_t* value, uint32_t width, uint32_t offset)
{
memcpy(&data[offset], value, width);
}
inline void Row::setStringField(const uint8_t* strdata, uint32_t length, uint32_t colIndex) inline void Row::setStringField(const uint8_t* strdata, uint32_t length, uint32_t colIndex)
{ {
uint64_t offset; uint64_t offset;

View File

@ -51,8 +51,8 @@ using namespace BRM;
#include "cacheutils.h" #include "cacheutils.h"
#include "IDBDataFile.h" #include "IDBDataFile.h"
#include "IDBPolicy.h" #include "IDBPolicy.h"
#include "checks.h" #include "checks.h"
#include "columnwidth.h"
namespace WriteEngine namespace WriteEngine
{ {
@ -3000,21 +3000,16 @@ uint8_t WE_DMLCommandProc::processUpdate(messageqcpp::ByteStream& bs,
case CalpontSystemCatalog::UDECIMAL: case CalpontSystemCatalog::UDECIMAL:
{ {
// WIP MCOL-641 // WIP MCOL-641
// decimal width > 8 cannot be stored in an integer if (fetchColColwidths[fetchColPos] == 16)
if (fetchColColwidths[fetchColPos] > 8)
{ {
int128_t* dec; int128_t* dec;
char buf[41]; char buf[utils::MAXLENGTH16BYTES];
dec = row.getBinaryField<int128_t>(fetchColPos); dec = row.getBinaryField<int128_t>(fetchColPos);
dataconvert::DataConvert::decimalToString<int128_t>(dec, dataconvert::DataConvert::decimalToString(dec,
(unsigned)fetchColScales[fetchColPos], buf, (unsigned)fetchColScales[fetchColPos], buf,
sizeof(buf), fetchColTypes[fetchColPos]); sizeof(buf), fetchColTypes[fetchColPos]);
value = buf; value.assign(buf);
//value = row.getStringField(fetchColPos);
//unsigned i = strlen(value.c_str());
//value = value.substr(0, i);
break; break;
} }
@ -3368,22 +3363,17 @@ uint8_t WE_DMLCommandProc::processUpdate(messageqcpp::ByteStream& bs,
case CalpontSystemCatalog::DECIMAL: case CalpontSystemCatalog::DECIMAL:
case CalpontSystemCatalog::UDECIMAL: case CalpontSystemCatalog::UDECIMAL:
{ {
// WIP MCOL-641 if (fetchColColwidths[fetchColPos] == 16)
// decimal width > 8 cannot be stored in an integer
if (fetchColColwidths[fetchColPos] > 8)
{ {
// WIP MCOL-641
int128_t* dec; int128_t* dec;
char buf[41]; char buf[utils::MAXLENGTH16BYTES];
dec = row.getBinaryField<int128_t>(fetchColPos); dec = row.getBinaryField<int128_t>(fetchColPos);
dataconvert::DataConvert::decimalToString<int128_t>(dec, dataconvert::DataConvert::decimalToString(dec,
(unsigned)fetchColScales[fetchColPos], buf, (unsigned)fetchColScales[fetchColPos], buf,
sizeof(buf), fetchColTypes[fetchColPos]); sizeof(buf), fetchColTypes[fetchColPos]);
value = buf; value = buf;
//value = row.getStringField(fetchColPos);
//unsigned i = strlen(value.c_str());
//value = value.substr(0, i);
break; break;
} }

View File

@ -58,6 +58,7 @@ using namespace execplan;
#include "MonitorProcMem.h" #include "MonitorProcMem.h"
using namespace idbdatafile; using namespace idbdatafile;
#include "dataconvert.h" #include "dataconvert.h"
#include "widedecimalutils.h"
#ifdef _MSC_VER #ifdef _MSC_VER
#define isnan _isnan #define isnan _isnan
@ -3973,11 +3974,16 @@ void WriteEngineWrapper::printInputValue(const ColStructList& colStructList,
curStr = boost::lexical_cast<string>(boost::any_cast<float>(curTuple.data)); curStr = boost::lexical_cast<string>(boost::any_cast<float>(curTuple.data));
else if (curTuple.data.type() == typeid(long long)) else if (curTuple.data.type() == typeid(long long))
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))
{
// WIP replace with a single call
char buf[utils::MAXLENGTH16BYTES];
int128_t val = boost::any_cast<int128_t>(curTuple.data);
dataconvert::DataConvert::toString(&val, 0, buf, utils::MAXLENGTH16BYTES);
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));
// else
// if (curTuple.data.type() == typeid(bool))
// curStr = boost::lexical_cast<string>(boost::any_cast<bool>(curTuple.data));
else if (curTuple.data.type() == typeid(short)) else if (curTuple.data.type() == typeid(short))
curStr = boost::lexical_cast<string>(boost::any_cast<short>(curTuple.data)); curStr = boost::lexical_cast<string>(boost::any_cast<short>(curTuple.data));
else if (curTuple.data.type() == typeid(char)) else if (curTuple.data.type() == typeid(char))