From 6948ab85a3308f9e4b29fd4aa739eed4231bfdc5 Mon Sep 17 00:00:00 2001 From: Andrew Hutchings Date: Mon, 4 Jun 2018 19:57:42 +0100 Subject: [PATCH 1/6] MCOL-1427 Fix microsecond padding for display We were padding from right, we needed to pad from left. --- dbcon/mysql/ha_calpont_impl.cpp | 4 ++-- utils/dataconvert/dataconvert.cpp | 19 ++++--------------- utils/dataconvert/dataconvert.h | 19 +++---------------- 3 files changed, 9 insertions(+), 33 deletions(-) diff --git a/dbcon/mysql/ha_calpont_impl.cpp b/dbcon/mysql/ha_calpont_impl.cpp index 1ee343e90..21649c2d0 100644 --- a/dbcon/mysql/ha_calpont_impl.cpp +++ b/dbcon/mysql/ha_calpont_impl.cpp @@ -582,7 +582,7 @@ int fetchNextRow(uchar* buf, cal_table_info& ti, cal_connection_info* ci, bool h *(*f)->null_ptr &= ~(*f)->null_bit; intColVal = row.getUintField<8>(s); - DataConvert::datetimeToString(intColVal, tmp, 255); + DataConvert::datetimeToString(intColVal, tmp, 255, colType.precision); /* setting the field_length is a sort-of hack. The length * at this point can be long enough to include mseconds. @@ -606,7 +606,7 @@ int fetchNextRow(uchar* buf, cal_table_info& ti, cal_connection_info* ci, bool h *(*f)->null_ptr &= ~(*f)->null_bit; intColVal = row.getUintField<8>(s); - DataConvert::timeToString(intColVal, tmp, 255); + DataConvert::timeToString(intColVal, tmp, 255, colType.precision); Field_varstring* f2 = (Field_varstring*)*f; f2->store(tmp, strlen(tmp), f2->charset()); diff --git a/utils/dataconvert/dataconvert.cpp b/utils/dataconvert/dataconvert.cpp index 7b92f36b0..398622631 100644 --- a/utils/dataconvert/dataconvert.cpp +++ b/utils/dataconvert/dataconvert.cpp @@ -2082,13 +2082,8 @@ std::string DataConvert::datetimeToString( long long datetimevalue, long decima if (dt.msecond && decimals) { - snprintf(buf + strlen(buf), 21 + decimals, ".%d", dt.msecond); - - // Pad end with zeros - if (strlen(buf) < (size_t)(21 + decimals)) - { - sprintf(buf + strlen(buf), "%0*d", (int)(21 + decimals - strlen(buf)), 0); - } + // Pad start with zeros + sprintf(buf + strlen(buf), ".%0*d", (int)decimals, dt.msecond); } return buf; @@ -2118,14 +2113,8 @@ std::string DataConvert::timeToString( long long timevalue, long decimals ) if (dt.msecond && decimals) { - size_t start = strlen(buf); - snprintf(buf + strlen(buf), 12 + decimals, ".%d", dt.msecond); - - // Pad end with zeros - if (strlen(buf) - start < (size_t)decimals) - { - sprintf(buf + strlen(buf), "%0*d", (int)(decimals - (strlen(buf) - start) + 1), 0); - } + // Pad start with zeros + sprintf(buf + strlen(buf), ".%0*d", (int)decimals, dt.msecond); } return buf; diff --git a/utils/dataconvert/dataconvert.h b/utils/dataconvert/dataconvert.h index 0cf3480c5..c01f261b6 100644 --- a/utils/dataconvert/dataconvert.h +++ b/utils/dataconvert/dataconvert.h @@ -587,14 +587,7 @@ inline void DataConvert::datetimeToString( long long datetimevalue, char* buf, u if (msec || decimals) { - size_t start = strlen(buf); - snprintf(buf + strlen(buf), buflen - start, ".%d", msec); - - // Pad end with zeros - if (strlen(buf) - start < (size_t)decimals) - { - snprintf(buf + strlen(buf), buflen - strlen(buf), "%0*d", (int)(decimals - (strlen(buf) - start) + 1), 0); - } + snprintf(buf + strlen(buf), buflen - strlen(buf), ".%0*d", (int)decimals, msec); } } @@ -636,14 +629,8 @@ inline void DataConvert::timeToString( long long timevalue, char* buf, unsigned if (msec || decimals) { - size_t start = strlen(buf); - snprintf(buf + strlen(buf), buflen - start, ".%d", msec); - - // Pad end with zeros - if (strlen(buf) - start < (size_t)decimals) - { - snprintf(buf + strlen(buf), buflen - strlen(buf), "%0*d", (int)(decimals - (strlen(buf) - start) + 1), 0); - } + // Pad start with zeros + snprintf(buf + strlen(buf), buflen - strlen(buf), ".%0*d", (int)decimals, msec); } } From fd6a2f46a51486eae4990b516b8300002522114f Mon Sep 17 00:00:00 2001 From: Andrew Hutchings Date: Mon, 4 Jun 2018 20:47:33 +0100 Subject: [PATCH 2/6] MCOL-1429 Fix DAYNAME()/MONTHNAME() NULL result For NULL result -1 cast to a uint was used as an array index. This caused crashes with TIME data type. --- utils/funcexp/func_dayname.cpp | 4 +++- utils/funcexp/func_monthname.cpp | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/utils/funcexp/func_dayname.cpp b/utils/funcexp/func_dayname.cpp index 3825bc1a3..325fb2f4a 100644 --- a/utils/funcexp/func_dayname.cpp +++ b/utils/funcexp/func_dayname.cpp @@ -145,7 +145,9 @@ string Func_dayname::getStrVal(rowgroup::Row& row, bool& isNull, CalpontSystemCatalog::ColType& op_ct) { - uint32_t weekday = getIntVal(row, parm, isNull, op_ct); + int32_t weekday = getIntVal(row, parm, isNull, op_ct); + if (weekday == -1) + return ""; return helpers::weekdayFullNames[weekday]; } diff --git a/utils/funcexp/func_monthname.cpp b/utils/funcexp/func_monthname.cpp index dbe5aa513..8d8200775 100644 --- a/utils/funcexp/func_monthname.cpp +++ b/utils/funcexp/func_monthname.cpp @@ -47,7 +47,9 @@ string Func_monthname::getStrVal(rowgroup::Row& row, bool& isNull, CalpontSystemCatalog::ColType& op_ct) { - uint32_t month = getIntVal(row, parm, isNull, op_ct); + int32_t month = getIntVal(row, parm, isNull, op_ct); + if (month == -1) + return ""; return helpers::monthFullNames[month]; } From 92cb6345fb16cff3db76fa373a3381c630d4e27f Mon Sep 17 00:00:00 2001 From: Andrew Hutchings Date: Mon, 4 Jun 2018 22:03:50 +0100 Subject: [PATCH 3/6] MCOL-1428 Fix SUBTIME() with day in WHERE SUBTIME() with day number used the DATETIME funciton instead of TIME so got stuck in an endless loop. Now uses the TIME calculations instead. --- utils/funcexp/func_add_time.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/utils/funcexp/func_add_time.cpp b/utils/funcexp/func_add_time.cpp index c3d5d7d85..edd05c6d4 100644 --- a/utils/funcexp/func_add_time.cpp +++ b/utils/funcexp/func_add_time.cpp @@ -223,7 +223,14 @@ int64_t Func_add_time::getIntVal(rowgroup::Row& row, bool& isNull, CalpontSystemCatalog::ColType& op_ct) { - return getDatetimeIntVal(row, parm, isNull, op_ct); + if (parm[0]->data()->resultType().colDataType == execplan::CalpontSystemCatalog::TIME) + { + return getTimeIntVal(row, parm, isNull, op_ct); + } + else + { + return getDatetimeIntVal(row, parm, isNull, op_ct); + } } string Func_add_time::getStrVal(rowgroup::Row& row, From d7562aa0ae718f1b53a332deecfee8edd59a7e3e Mon Sep 17 00:00:00 2001 From: Andrew Hutchings Date: Tue, 5 Jun 2018 12:54:37 +0100 Subject: [PATCH 4/6] MCOL-1419 Fix TIME update saturation values We should saturate at the maximum and minimum values for TIME. --- utils/dataconvert/dataconvert.cpp | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/utils/dataconvert/dataconvert.cpp b/utils/dataconvert/dataconvert.cpp index 398622631..6c66a07de 100644 --- a/utils/dataconvert/dataconvert.cpp +++ b/utils/dataconvert/dataconvert.cpp @@ -859,7 +859,7 @@ bool mysql_str_to_datetime( const string& input, DateTime& output, bool& isDate return true; } -bool mysql_str_to_time( const string& input, Time& output ) +bool mysql_str_to_time( const string& input, Time& output, long decimals ) { int32_t datesepct = 0; uint32_t dtend = 0; @@ -999,20 +999,21 @@ bool mysql_str_to_time( const string& input, Time& output ) if ( !isTimeValid( hour, min, sec, usec ) ) { // Emulate MariaDB's time saturation - if (hour > 838) + // TODO: msec saturation + if ((hour > 838) && !isNeg) { output.hour = 838; output.minute = 59; output.second = 59; - output.msecond = 999999; + output.msecond = exp10(decimals) - 1; output.is_neg = 0; } - else if (hour < -838) + else if ((hour < -838) || ((hour > 838) && isNeg)) { output.hour = -838; output.minute = 59; output.second = 59; - output.msecond = 999999; + output.msecond = exp10(decimals) - 1; output.is_neg = 1; } // If neither of the above match then we return a 0 time @@ -1068,9 +1069,9 @@ bool stringToDatetimeStruct(const string& data, DateTime& dtime, bool* date) return true; } -bool stringToTimeStruct(const string& data, Time& dtime) +bool stringToTimeStruct(const string& data, Time& dtime, long decimals) { - if ( !mysql_str_to_time( data, dtime ) ) + if ( !mysql_str_to_time( data, dtime, decimals ) ) return false; return true; @@ -1415,15 +1416,11 @@ DataConvert::convertColumnData(const CalpontSystemCatalog::ColType& colType, { Time aTime; - if (stringToTimeStruct(data, aTime)) + if (!stringToTimeStruct(data, aTime, colType.precision)) { - value = (int64_t) * (reinterpret_cast(&aTime)); - } - else - { - value = (int64_t) 0; pushWarning = true; } + value = (int64_t) * (reinterpret_cast(&aTime)); } break; From 09269af6d89de4d5d30c12f26c5d83742447b0a4 Mon Sep 17 00:00:00 2001 From: Andrew Hutchings Date: Thu, 7 Jun 2018 12:16:55 +0100 Subject: [PATCH 5/6] MCOL-1417 Fix cpimport TIME saturation --- utils/dataconvert/dataconvert.cpp | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/utils/dataconvert/dataconvert.cpp b/utils/dataconvert/dataconvert.cpp index 6c66a07de..1a2e90a88 100644 --- a/utils/dataconvert/dataconvert.cpp +++ b/utils/dataconvert/dataconvert.cpp @@ -1907,6 +1907,7 @@ int64_t DataConvert::convertColumnTime( { status = 0; char* p; + char* retp = NULL; char* savePoint = NULL; p = const_cast(dataOrg); int64_t value = 0; @@ -1923,6 +1924,17 @@ int64_t DataConvert::convertColumnTime( return value; } + if (dataOrgLen == 0) + { + return value; + } + if (dataOrgLen < 3) + { + // Not enough chars to be a time + status = -1; + return value; + } + if (p[0] == '-') { isNeg = true; @@ -1931,9 +1943,9 @@ int64_t DataConvert::convertColumnTime( errno = 0; p = strtok_r(p, ":.", &savePoint); - inHour = strtol(p, 0, 10); + inHour = strtol(p, &retp, 10); - if (errno) + if (errno || !retp) { status = -1; return value; @@ -1947,9 +1959,9 @@ int64_t DataConvert::convertColumnTime( return value; } - inMinute = strtol(p, 0, 10); + inMinute = strtol(p, &retp, 10); - if (errno) + if (errno || !retp) { status = -1; return value; @@ -1963,9 +1975,9 @@ int64_t DataConvert::convertColumnTime( return value; } - inSecond = strtol(p, 0, 10); + inSecond = strtol(p, &retp, 10); - if (errno) + if (errno || !retp) { status = -1; return value; @@ -1975,9 +1987,9 @@ int64_t DataConvert::convertColumnTime( if (p != NULL) { - inMicrosecond = strtol(p, 0, 10); + inMicrosecond = strtol(p, &retp, 10); - if (errno) + if (errno || !retp) { status = -1; return value; From e2141e0b69ab82ba580faf2dcef1b0f5b673b32e Mon Sep 17 00:00:00 2001 From: Andrew Hutchings Date: Thu, 7 Jun 2018 12:41:44 +0100 Subject: [PATCH 6/6] MCOL-1418 Fix negative time storage for LDI --- dbcon/mysql/ha_calpont_dml.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dbcon/mysql/ha_calpont_dml.cpp b/dbcon/mysql/ha_calpont_dml.cpp index cf103a801..a9b64b757 100644 --- a/dbcon/mysql/ha_calpont_dml.cpp +++ b/dbcon/mysql/ha_calpont_dml.cpp @@ -895,6 +895,10 @@ int ha_calpont_impl_write_batch_row_(uchar* buf, TABLE* table, cal_impl_if::cal_ longlong tmp = my_time_packed_from_binary(pos, table->field[colpos]->decimals()); TIME_from_longlong_time_packed(<ime, tmp); + if (ltime.neg) + { + fprintf(ci.filePtr, "-"); + } if (!ltime.second_part) { fprintf(ci.filePtr, "%02d:%02d:%02d%c",