From c29c41e235385d1a2b95f9f49fd07c5639eae135 Mon Sep 17 00:00:00 2001 From: jmrojas2332 Date: Wed, 4 Dec 2019 22:48:07 +0000 Subject: [PATCH] MCOL 3474 Fix Timediff results after accounting for new test cases --- utils/dataconvert/dataconvert.cpp | 18 ++++++++---- utils/funcexp/func_timediff.cpp | 30 +++++++++---------- utils/funcexp/funchelpers.h | 49 ++++++++++++++++++++++--------- 3 files changed, 62 insertions(+), 35 deletions(-) diff --git a/utils/dataconvert/dataconvert.cpp b/utils/dataconvert/dataconvert.cpp index fb347253f..5d9a808d9 100644 --- a/utils/dataconvert/dataconvert.cpp +++ b/utils/dataconvert/dataconvert.cpp @@ -3005,6 +3005,14 @@ int64_t DataConvert::intToDatetime(int64_t data, bool* date) else { y = atoi(year.c_str()); + + // special handling for 2-byte year + if (year.length() == 2) + { + y += 2000; + if (y > 2069) + y -= 100; + } } m = atoi(month.c_str()); @@ -3056,10 +3064,10 @@ int64_t DataConvert::intToTime(int64_t data, bool fromString) #if defined(__GNUC__) && __GNUC__ >= 7 #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wformat-truncation=" - snprintf( buf, 15, "%llu", (long long unsigned int)data); + snprintf( buf, 15, "%lld", (long long int)data); #pragma GCC diagnostic pop #else - snprintf( buf, 15, "%llu", (long long unsigned int)data); + snprintf( buf, 15, "%lld", (long long int)data); #endif //string date = buf; @@ -3090,8 +3098,8 @@ int64_t DataConvert::intToTime(int64_t data, bool fromString) case 7: hour = string(bufread, 3); - min = string(bufread + 2, 2); - sec = string(bufread + 4, 2); + min = string(bufread + 3, 2); + sec = string(bufread + 5, 2); break; case 6: @@ -3152,7 +3160,7 @@ int64_t DataConvert::intToTime(int64_t data, bool fromString) atime.msecond = ms; atime.is_neg = isNeg; - return *(reinterpret_cast(&atime)); + return *(reinterpret_cast(&atime)); } int64_t DataConvert::stringToTime(const string& data) diff --git a/utils/funcexp/func_timediff.cpp b/utils/funcexp/func_timediff.cpp index 729045798..881c04017 100644 --- a/utils/funcexp/func_timediff.cpp +++ b/utils/funcexp/func_timediff.cpp @@ -94,6 +94,14 @@ const string timediff( int64_t time1, int64_t time2, bool isDateTime) } } +bool treatIntAsDatetime(const std::string &text) +{ + // min used when converting into to datetime is YYYYMMDD + // note: time diffing an int perceived to be in the format YYMMDD is actually treated as HHMMSS. Same functionality as MDB + bool isNeg = text.find("-") == 0; + return (text.length() > 8) || (text.length() >= 8 && !isNeg); +} + CalpontSystemCatalog::ColType Func_timediff::operationType( FunctionParm& fp, CalpontSystemCatalog::ColType& resultType ) { return resultType; @@ -163,14 +171,10 @@ string Func_timediff::getStrVal(rowgroup::Row& row, case execplan::CalpontSystemCatalog::TEXT: text = parm[0]->data()->getStrVal(row, isNull); - if (text.length() >= 14) // datetime has length at least 14 + if (text.length() >= 12) // datetime has length at least 12 (YYMMDDHHMMSS), convert others to time { val1 = dataconvert::DataConvert::stringToDatetime(text, &isDate1); } - else if (text.length() == 8 && text.find("-") == string::npos && text.find(":") == string::npos) // special case, this is exactly a date - { - val1 = dataconvert::DataConvert::intToDatetime(parm[0]->data()->getIntVal(row, isNull), &isDate1); - } else { val1 = dataconvert::DataConvert::stringToTime(text); @@ -184,7 +188,7 @@ string Func_timediff::getStrVal(rowgroup::Row& row, case execplan::CalpontSystemCatalog::TINYINT: case execplan::CalpontSystemCatalog::SMALLINT: text = parm[0]->data()->getStrVal(row, isNull); - if (text.length() >= 14) // datetime has length at least 14 + if (treatIntAsDatetime(text)) val1 = dataconvert::DataConvert::intToDatetime(parm[0]->data()->getIntVal(row, isNull), &isDate1); else { @@ -202,7 +206,7 @@ string Func_timediff::getStrVal(rowgroup::Row& row, else { text = parm[0]->data()->getStrVal(row, isNull); - if (text.length() >= 14) // datetime has length at least 14 + if (treatIntAsDatetime(text)) val1 = dataconvert::DataConvert::intToDatetime(parm[0]->data()->getIntVal(row, isNull), &isDate1); else { @@ -252,14 +256,10 @@ string Func_timediff::getStrVal(rowgroup::Row& row, case execplan::CalpontSystemCatalog::CHAR: case execplan::CalpontSystemCatalog::TEXT: text = parm[1]->data()->getStrVal(row, isNull); - if (text.length() >= 14) // datetime has length at least 14 + if (text.length() >= 12) // datetime has length at least 12 (YYMMDDHHMMSS), convert others to time { val2 = dataconvert::DataConvert::stringToDatetime(text, &isDate2); } - else if (text.length() == 8 && text.find("-") == string::npos && text.find(":") == string::npos) // special case, this is exactly a date - { - val2 = dataconvert::DataConvert::intToDatetime(parm[1]->data()->getIntVal(row, isNull), &isDate2); - } else { val2 = dataconvert::DataConvert::stringToTime(text); @@ -273,7 +273,7 @@ string Func_timediff::getStrVal(rowgroup::Row& row, case execplan::CalpontSystemCatalog::TINYINT: case execplan::CalpontSystemCatalog::SMALLINT: text = parm[1]->data()->getStrVal(row, isNull); - if (text.length() >= 14) // datetime has length at least 14 + if (treatIntAsDatetime(text)) val2 = dataconvert::DataConvert::intToDatetime(parm[1]->data()->getIntVal(row, isNull), &isDate2); else { @@ -291,7 +291,7 @@ string Func_timediff::getStrVal(rowgroup::Row& row, else { text = parm[1]->data()->getStrVal(row, isNull); - if (text.length() >= 14) // datetime has length at least 14 + if (treatIntAsDatetime(text)) val2 = dataconvert::DataConvert::intToDatetime(parm[1]->data()->getIntVal(row, isNull), &isDate2); else { @@ -363,7 +363,5 @@ double Func_timediff::getDoubleVal(rowgroup::Row& row, return atof(getStrVal(row, fp, isNull, op_ct).c_str()); } - - } // namespace funcexp // vim:ts=4 sw=4: diff --git a/utils/funcexp/funchelpers.h b/utils/funcexp/funchelpers.h index b240477b2..013b81b0d 100644 --- a/utils/funcexp/funchelpers.h +++ b/utils/funcexp/funchelpers.h @@ -393,21 +393,42 @@ inline bool calc_time_diff(int64_t time1, int64_t time2, int l_sign, long long* sec2 = 0, msec2 = 0; - year1 = isDateTime ? (uint32_t)((time1 >> 48) & 0xffff) : 0; - month1 = isDateTime ? (uint32_t)((time1 >> 44) & 0xf) : 0; - day1 = isDateTime ? (uint32_t)((time1 >> 38) & 0x3f) : (uint32_t)((time1 >> 52) & 0x7ff); - hour1 = isDateTime ? (uint32_t)((time1 >> 32) & 0x3f) : (uint32_t)((time1 >> 40) & 0xfff); - min1 = isDateTime ? (uint32_t)((time1 >> 26) & 0x3f) : (uint32_t)((time1 >> 32) & 0xff); - sec1 = isDateTime ? (uint32_t)((time1 >> 20) & 0x3f) : (uint32_t)((time1 >> 24) & 0xff); - msec1 = isDateTime ? (uint32_t)((time1 & 0xfffff)) : (uint32_t)(time1 & 0xffffff); + if (isDateTime) + { + year1 = (uint32_t)((time1 >> 48) & 0xffff); + month1 = (uint32_t)((time1 >> 44) & 0xf); + day1 = (uint32_t)((time1 >> 38) & 0x3f); + hour1 = (uint32_t)((time1 >> 32) & 0x3f); + min1 = (uint32_t)((time1 >> 26) & 0x3f); + sec1 = (uint32_t)((time1 >> 20) & 0x3f); + msec1 = (uint32_t)((time1 & 0xfffff)); - year2 = isDateTime ? (uint32_t)((time2 >> 48) & 0xffff) : 0; - month2 = isDateTime ? (uint32_t)((time2 >> 44) & 0xf) : 0; - day2 = isDateTime ? (uint32_t)((time2 >> 38) & 0x3f) : (uint32_t)((time2 >> 52) & 0x7ff);; - hour2 = isDateTime ? (uint32_t)((time2 >> 32) & 0x3f) : (uint32_t)((time2 >> 40) & 0xfff); - min2 = isDateTime ? (uint32_t)((time2 >> 26) & 0x3f) : (uint32_t)((time2 >> 32) & 0xff); - sec2 = isDateTime ? (uint32_t)((time2 >> 20) & 0x3f) : (uint32_t)((time2 >> 24) & 0xff); - msec2 = isDateTime ? (uint32_t)((time2 & 0xfffff)) : (uint32_t)(time2 & 0xffffff); + year2 = (uint32_t)((time2 >> 48) & 0xffff); + month2 = (uint32_t)((time2 >> 44) & 0xf); + day2 = (uint32_t)((time2 >> 38) & 0x3f); + hour2 = (uint32_t)((time2 >> 32) & 0x3f); + min2 = (uint32_t)((time2 >> 26) & 0x3f); + sec2 = (uint32_t)((time2 >> 20) & 0x3f); + msec2 = (uint32_t)(time2 & 0xfffff); + } + else + { + year1 = 0; + month1 = 0; + day1 = (time1 >> 52) & 0x7ff; + hour1 = (time1 >> 40) & 0xfff; + min1 = (time1 >> 32) & 0xff; + sec1 = (time1 >> 24) & 0xff; + msec1 = time1 & 0xffffff; + + year2 = 0; + month2 = 0; + day2 = (time2 >> 52) & 0x7ff; + hour2 = (time2 >> 40) & 0xfff; + min2 = (time2 >> 32) & 0xff; + sec2 = (time2 >> 24) & 0xff; + msec2 = time2 & 0xffffff; + } days = calc_mysql_daynr(year1, month1, day1);