From 77e1d6abe36a23c7c86c3cd4a632c0ab35328c58 Mon Sep 17 00:00:00 2001 From: Gagan Goel Date: Thu, 9 Jan 2020 12:37:21 -0500 Subject: [PATCH] Basic SELECT support for Decimal38 --- dbcon/ddlpackage/ddlpkg.cpp | 3 +- dbcon/mysql/ha_mcs_impl.cpp | 16 +++++- primitives/linux-port/column.cpp | 2 - utils/dataconvert/dataconvert.cpp | 73 ++++++++++++++++++++++-- utils/dataconvert/dataconvert.h | 2 + utils/rowgroup/rowgroup.h | 7 +++ writeengine/server/we_ddlcommandproc.cpp | 11 ++-- 7 files changed, 98 insertions(+), 16 deletions(-) diff --git a/dbcon/ddlpackage/ddlpkg.cpp b/dbcon/ddlpackage/ddlpkg.cpp index d048fff89..ecf6264dc 100644 --- a/dbcon/ddlpackage/ddlpkg.cpp +++ b/dbcon/ddlpackage/ddlpkg.cpp @@ -223,11 +223,10 @@ void ColumnDef::convertDecimal() fType->fType = DDL_BIGINT; fType->fLength = 8; } - else if (fType->fPrecision > 19 && fType->fPrecision <39) + else if (fType->fPrecision > 18 && fType->fPrecision < 39) { fType->fType = DDL_BINARY; fType->fLength = 16; - } } } // end of namespace diff --git a/dbcon/mysql/ha_mcs_impl.cpp b/dbcon/mysql/ha_mcs_impl.cpp index 81df0c31e..4d26ab5a0 100644 --- a/dbcon/mysql/ha_mcs_impl.cpp +++ b/dbcon/mysql/ha_mcs_impl.cpp @@ -247,6 +247,9 @@ void force_close_fep_conn(THD *thd, cal_connection_info* ci, bool check_prev_rc ci->cal_conn_hndl = 0; } +// WIP MCOL-641 +using uint128_t = unsigned __int128; + void storeNumericField(Field** f, int64_t value, CalpontSystemCatalog::ColType& ct) { // unset null bit first @@ -801,15 +804,24 @@ int fetchNextRow(uchar* buf, cal_table_info& ti, cal_connection_info* ci, bool h case CalpontSystemCatalog::DECIMAL: case CalpontSystemCatalog::UDECIMAL: { + // WIP MCOL-641 if (row.getPrecision(s) > 18) { - sscanf(row.getBinaryField(s).c_str(), "%ld",&intColVal); + // unset null bit first + if ((*f)->null_ptr) + *(*f)->null_ptr &= ~(*f)->null_bit; + + const uint128_t val = *reinterpret_cast(row.getBinaryField2(s)); + char buf[256]; + dataconvert::DataConvert::decimalToString(val, (unsigned)colType.scale, buf, 256, colType.colDataType); + Field_new_decimal* f2 = (Field_new_decimal*)*f; + f2->store(buf, strlen(buf), f2->charset()); } else { intColVal = row.getIntField(s); + storeNumericField(f, intColVal, colType); } - storeNumericField(f, intColVal, colType); break; } diff --git a/primitives/linux-port/column.cpp b/primitives/linux-port/column.cpp index f6d4e09d9..5d5885cf4 100644 --- a/primitives/linux-port/column.cpp +++ b/primitives/linux-port/column.cpp @@ -1629,7 +1629,6 @@ inline void p_Col_bin_ridArray(NewColRequestHeader* in, memcpy(argVals[argIndex],args->val, W); regex[argIndex].used = false; } - } @@ -1639,7 +1638,6 @@ inline void p_Col_bin_ridArray(NewColRequestHeader* in, while (!done) { - // if((*((uint64_t *) (bval))) != 0) // { // cout << "rid "<< rid << " value "; diff --git a/utils/dataconvert/dataconvert.cpp b/utils/dataconvert/dataconvert.cpp index df29d1d36..a28a5b394 100644 --- a/utils/dataconvert/dataconvert.cpp +++ b/utils/dataconvert/dataconvert.cpp @@ -1172,7 +1172,8 @@ struct uint128_pod uint64_t hi; }; -inline void toString(uint128_t i, char *p) +// WIP MCOL-641 +void DataConvert::toString(unsigned __int128 i, char *p) { uint64_t div = 10000000000000000000ULL; size_t div_log = 19; @@ -1191,7 +1192,7 @@ inline void toString(uint128_t i, char *p) // WIP replace snprintf with streams if (high_pod->lo != 0) { - printed_chars = snprintf(p, div_log+1, "%ld", high_pod->lo); + printed_chars = snprintf(p, div_log+1, "%lu", high_pod->lo); p += printed_chars; printed_chars = snprintf(p, div_log+1, "%019lu", mid_pod->lo); p += printed_chars; @@ -1199,10 +1200,11 @@ inline void toString(uint128_t i, char *p) printed_chars = snprintf(p, div_log+1, "%lu", mid_pod->lo); p += printed_chars; } - snprintf(p, div_log+1, "%019ld", low_pod->lo); + snprintf(p, div_log+1, "%019lu", low_pod->lo); } +// WIP MCOL-641 // Template this // result must be calloc-ed void atoi_(const string &arg, int128_t &res, size_t &size) @@ -1211,7 +1213,7 @@ void atoi_(const string &arg, int128_t &res, size_t &size) //char buf[40]; //int128_t *res_ptr = reinterpret_cast(result); res = 0; - for (int j = 0; j < arg.size(); j++) + for (size_t j = 0; j < arg.size(); j++) { // WIP res = res*10 + arg[j] - '0'; @@ -1222,6 +1224,69 @@ void atoi_(const string &arg, int128_t &res, size_t &size) size = 16; } +// WIP MCOL-641 +void DataConvert::decimalToString(unsigned __int128 int_val, uint8_t scale, char* buf, unsigned int buflen, + execplan::CalpontSystemCatalog::ColDataType colDataType) +{ + toString(int_val, buf); + + // Biggest ColumnStore supports is DECIMAL(38,x), or 38 total digits+dp+sign for column + + if (scale == 0) + return; + + //we want to move the last scale chars right by one spot to insert the dp + //we want to move the trailing null as well, so it's really 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 = "00000000000000000000000000000000000000"; //38 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) = '.'; +} + boost::any DataConvert::convertColumnData(const CalpontSystemCatalog::ColType& colType, const std::string& dataOrig, bool& pushWarning, const std::string& timeZone, bool nulFlag, bool noRoundup, bool isUpdate) diff --git a/utils/dataconvert/dataconvert.h b/utils/dataconvert/dataconvert.h index c2d27b1b8..18a079fbb 100644 --- a/utils/dataconvert/dataconvert.h +++ b/utils/dataconvert/dataconvert.h @@ -1011,6 +1011,8 @@ public: EXPORT static bool isNullData(execplan::ColumnResult* cr, int rownum, execplan::CalpontSystemCatalog::ColType colType); static inline std::string decimalToString(int64_t value, uint8_t scale, execplan::CalpontSystemCatalog::ColDataType colDataType); static inline void decimalToString(int64_t value, uint8_t scale, char* buf, unsigned int buflen, execplan::CalpontSystemCatalog::ColDataType colDataType); + EXPORT static void decimalToString(unsigned __int128 value, uint8_t scale, char* buf, unsigned int buflen, execplan::CalpontSystemCatalog::ColDataType colDataType); + EXPORT static void toString(unsigned __int128 i, char *p); static inline std::string constructRegexp(const std::string& str); static inline void trimWhitespace(int64_t& charData); static inline bool isEscapedChar(char c) diff --git a/utils/rowgroup/rowgroup.h b/utils/rowgroup/rowgroup.h index 8d89521bd..03c087cb4 100644 --- a/utils/rowgroup/rowgroup.h +++ b/utils/rowgroup/rowgroup.h @@ -435,6 +435,7 @@ public: inline void setVarBinaryField(const uint8_t* val, uint32_t len, uint32_t colIndex); inline std::string getBinaryField(uint32_t colIndex) const; + inline const uint8_t* getBinaryField2(uint32_t colIndex) const; inline boost::shared_ptr getUserData(uint32_t colIndex) const; inline void setUserData(mcsv1sdk::mcsv1Context& context, @@ -835,6 +836,12 @@ inline std::string Row::getBinaryField(uint32_t colIndex) const return std::string((char*) &data[offsets[colIndex]], getColumnWidth(colIndex)); } +// WIP MCOL-641 +inline const uint8_t* Row::getBinaryField2(uint32_t colIndex) const +{ + return &data[offsets[colIndex]]; +} + inline std::string Row::getVarBinaryStringField(uint32_t colIndex) const { if (inStringTable(colIndex)) diff --git a/writeengine/server/we_ddlcommandproc.cpp b/writeengine/server/we_ddlcommandproc.cpp index 30b50ff4c..988bb340a 100644 --- a/writeengine/server/we_ddlcommandproc.cpp +++ b/writeengine/server/we_ddlcommandproc.cpp @@ -456,13 +456,12 @@ uint8_t WE_DDLCommandProc::writeCreateSyscolumn(ByteStream& bs, std::string& err if (dataType == CalpontSystemCatalog::DECIMAL || dataType == CalpontSystemCatalog::UDECIMAL) { - if (colDefPtr->fType->fPrecision > 18) //@Bug 5717 precision cannot be over 18. + // WIP MCOL-641 + if (colDefPtr->fType->fPrecision > 38) // precision cannot be over 38. { - // WIP MCOL-641 - //ostringstream os; - //os << "Syntax error: The maximum precision (total number of digits) that can be specified is 18"; - //throw std::runtime_error(os.str()); - colDefPtr->convertDecimal(); + ostringstream os; + os << "Syntax error: The maximum precision (total number of digits) that can be specified is 38"; + throw std::runtime_error(os.str()); } else if (colDefPtr->fType->fPrecision < colDefPtr->fType->fScale) {