From 957dc446151d340abe783cebf9a415a2d03256de Mon Sep 17 00:00:00 2001 From: Andrew Hutchings Date: Fri, 27 Apr 2018 21:18:14 +0100 Subject: [PATCH] MCOL-392 Function fixes Fixes most of the functions in funcexp so that time and datetime's microseconds are handled correctly --- dbcon/execplan/treenode.h | 19 +++-- dbcon/mysql/ha_calpont_execplan.cpp | 3 +- utils/dataconvert/dataconvert.cpp | 12 +-- utils/dataconvert/dataconvert.h | 111 ++++++++++++++++------------ utils/funcexp/func_add_time.cpp | 49 ++++++++---- utils/funcexp/func_between.cpp | 31 ++++++-- utils/funcexp/func_extract.cpp | 97 +++++++++++++++++++++++- utils/funcexp/func_greatest.cpp | 5 +- utils/funcexp/func_hour.cpp | 20 ++++- utils/funcexp/func_least.cpp | 5 +- utils/funcexp/func_time.cpp | 20 +++-- 11 files changed, 271 insertions(+), 101 deletions(-) diff --git a/dbcon/execplan/treenode.h b/dbcon/execplan/treenode.h index 27795ea9d..08b8b43c8 100644 --- a/dbcon/execplan/treenode.h +++ b/dbcon/execplan/treenode.h @@ -666,14 +666,14 @@ inline const std::string& TreeNode::getStrVal() case CalpontSystemCatalog::DATETIME: { - dataconvert::DataConvert::datetimeToString(fResult.intVal, tmp, 255); + dataconvert::DataConvert::datetimeToString(fResult.intVal, tmp, 255, fResultType.precision); fResult.strVal = std::string(tmp); break; } case CalpontSystemCatalog::TIME: { - dataconvert::DataConvert::timeToString(fResult.intVal, tmp, 255); + dataconvert::DataConvert::timeToString(fResult.intVal, tmp, 255, fResultType.precision); fResult.strVal = std::string(tmp); break; } @@ -992,11 +992,20 @@ inline int64_t TreeNode::getDatetimeIntVal() else if (fResultType.colDataType == execplan::CalpontSystemCatalog::TIME) { dataconvert::Time tt; + int day = 0; memcpy(&tt, &fResult.intVal, 8); - if (tt.hour > 23 || tt.hour < 0) - throw logging::InvalidConversionExcept("TreeNode::getDecimalVal: Invalid conversion from time (out of range)."); - dataconvert::DateTime dt(0, 0, 0, tt.hour, tt.minute, tt.second, tt.msecond); + // Note, this should probably be current date +/- time + if (tt.hour > 23) + { + day = tt.hour / 24; + tt.hour = tt.hour % 24; + } + else if (tt.hour < 0) + { + tt.hour = 0; + } + dataconvert::DateTime dt(0, 0, day, tt.hour, tt.minute, tt.second, tt.msecond); memcpy(&fResult.intVal, &dt, 8); return fResult.intVal; } diff --git a/dbcon/mysql/ha_calpont_execplan.cpp b/dbcon/mysql/ha_calpont_execplan.cpp index fe2f96e52..210da9992 100644 --- a/dbcon/mysql/ha_calpont_execplan.cpp +++ b/dbcon/mysql/ha_calpont_execplan.cpp @@ -3518,8 +3518,7 @@ ReturnedColumn* buildFunctionColumn(Item_func* ifp, gp_walk_info& gwi, bool& non if (ifp->field_type() == MYSQL_TYPE_DATETIME || ifp->field_type() == MYSQL_TYPE_DATETIME2 || ifp->field_type() == MYSQL_TYPE_TIMESTAMP || - ifp->field_type() == MYSQL_TYPE_TIMESTAMP2 || - funcName == "add_time") + ifp->field_type() == MYSQL_TYPE_TIMESTAMP2) { CalpontSystemCatalog::ColType ct; ct.colDataType = CalpontSystemCatalog::DATETIME; diff --git a/utils/dataconvert/dataconvert.cpp b/utils/dataconvert/dataconvert.cpp index bfdb25239..41dff9aa9 100644 --- a/utils/dataconvert/dataconvert.cpp +++ b/utils/dataconvert/dataconvert.cpp @@ -2065,9 +2065,9 @@ std::string DataConvert::datetimeToString( long long datetimevalue, long decima { snprintf(buf + strlen(buf), 21 + decimals, ".%d", dt.msecond); // Pad end with zeros - if (strlen(buf) < (21 + decimals)) + if (strlen(buf) < (size_t)(21 + decimals)) { - sprintf(buf + strlen(buf), "%0*d", 21 + decimals - strlen(buf), 0); + sprintf(buf + strlen(buf), "%0*d", (int)(21 + decimals - strlen(buf)), 0); } } return buf; @@ -2091,9 +2091,9 @@ std::string DataConvert::timeToString( long long timevalue, long decimals ) size_t start = strlen(buf); snprintf(buf + strlen(buf), 12 + decimals, ".%d", dt.msecond); // Pad end with zeros - if (strlen(buf) - start < decimals) + if (strlen(buf) - start < (size_t)decimals) { - sprintf(buf + strlen(buf), "%0*d", decimals - (strlen(buf) - start), 0); + sprintf(buf + strlen(buf), "%0*d", (int)(decimals - (strlen(buf) - start) + 1), 0); } } return buf; @@ -2642,7 +2642,7 @@ int64_t DataConvert::intToTime(int64_t data) atime.second = 0; atime.msecond = 0; - return *(reinterpret_cast(&atime)); + return *(reinterpret_cast(&atime)); } snprintf( buf, 15, "%llu", (long long unsigned int)data); @@ -2696,7 +2696,7 @@ int64_t DataConvert::stringToTime(const string& data) // -34 <= D <= 34 // -838 <= H <= 838 uint64_t min = 0, sec = 0, msec = 0; - int64_t day = 0, hour = 0; + int64_t day = -1, hour = 0; string time, hms, ms; char* end = NULL; diff --git a/utils/dataconvert/dataconvert.h b/utils/dataconvert/dataconvert.h index 057d617ef..8c35bec4b 100644 --- a/utils/dataconvert/dataconvert.h +++ b/utils/dataconvert/dataconvert.h @@ -173,7 +173,7 @@ struct DateTime inline int64_t DateTime::convertToMySQLint() const { - return (int64_t) (year * 10000000000000000LL) + (month * 100000000000000) + (day * 1000000000000) + (hour * 10000000000) + (minute * 100000000) + (second * 1000000) + msecond; + return (int64_t) (year * 10000000000LL) + (month * 100000000) + (day * 1000000) + (hour * 10000) + (minute * 100) + second; } inline @@ -235,16 +235,11 @@ void Time::reset() inline int64_t Time::convertToMySQLint() const { - return (int64_t) (hour * 10000000000) + (minute * 100000000) + (second * 1000000) + msecond; + return (int64_t) (hour * 10000) + (minute * 100) + second; } static uint32_t daysInMonth[13] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0}; -inline uint32_t getDaysInMonth(uint32_t month) -{ - return ( (month < 1 || month > 12) ? 0 : daysInMonth[month - 1]); -} - inline bool isLeapYear ( int year) { if ( year % 400 == 0 ) @@ -256,6 +251,18 @@ inline bool isLeapYear ( int year) return false; } +inline uint32_t getDaysInMonth(uint32_t month, int year) +{ + if (month < 1 || month > 12) + return 0; + + uint32_t days = daysInMonth[month - 1]; + if ((month == 2) && isLeapYear(year)) + days++; + + return days; +} + inline bool isDateValid ( int day, int month, int year) { @@ -266,11 +273,7 @@ bool isDateValid ( int day, int month, int year) return true; } - int daycheck = getDaysInMonth( month ); - - if ( month == 2 && isLeapYear( year ) ) - // 29 days in February in a leap year - daycheck = 29; + int daycheck = getDaysInMonth( month, year ); if ( ( year < 1000 ) || ( year > 9999 ) ) valid = false; @@ -407,7 +410,7 @@ public: * @param data the columns string representation of it's data */ EXPORT static std::string datetimeToString( long long datetimevalue, long decimals = 0 ); - static inline void datetimeToString( long long datetimevalue, char* buf, unsigned int buflen ); + static inline void datetimeToString( long long datetimevalue, char* buf, unsigned int buflen, long decimals = 0 ); /** * @brief convert a columns data from native format to a string @@ -416,7 +419,7 @@ public: * @param data the columns string representation of it's data */ EXPORT static std::string timeToString( long long timevalue, long decimals = 0 ); - static inline void timeToString( long long timevalue, char* buf, unsigned int buflen ); + static inline void timeToString( long long timevalue, char* buf, unsigned int buflen, long decimals = 0); /** * @brief convert a columns data from native format to a string @@ -537,37 +540,48 @@ inline void DataConvert::dateToString( int datevalue, char* buf, unsigned int bu ); } -inline void DataConvert::datetimeToString( long long datetimevalue, char* buf, unsigned int buflen ) +inline void DataConvert::datetimeToString( long long datetimevalue, char* buf, unsigned int buflen, long decimals ) { + // 10 is default which means we don't need microseconds + if (decimals > 6 || decimals < 0) + { + decimals = 0; + } + int msec = 0; if ((datetimevalue & 0xfffff) > 0) { - snprintf( buf, buflen, "%04d-%02d-%02d %02d:%02d:%02d.%d", - (unsigned)((datetimevalue >> 48) & 0xffff), - (unsigned)((datetimevalue >> 44) & 0xf), - (unsigned)((datetimevalue >> 38) & 0x3f), - (unsigned)((datetimevalue >> 32) & 0x3f), - (unsigned)((datetimevalue >> 26) & 0x3f), - (unsigned)((datetimevalue >> 20) & 0x3f), - (unsigned)((datetimevalue) & 0xfffff) - ); + msec = (unsigned)((datetimevalue) & 0xfffff); } - else + snprintf( buf, buflen, "%04d-%02d-%02d %02d:%02d:%02d", + (unsigned)((datetimevalue >> 48) & 0xffff), + (unsigned)((datetimevalue >> 44) & 0xf), + (unsigned)((datetimevalue >> 38) & 0x3f), + (unsigned)((datetimevalue >> 32) & 0x3f), + (unsigned)((datetimevalue >> 26) & 0x3f), + (unsigned)((datetimevalue >> 20) & 0x3f) + ); + + if (msec || decimals) { - snprintf( buf, buflen, "%04d-%02d-%02d %02d:%02d:%02d", - (unsigned)((datetimevalue >> 48) & 0xffff), - (unsigned)((datetimevalue >> 44) & 0xf), - (unsigned)((datetimevalue >> 38) & 0x3f), - (unsigned)((datetimevalue >> 32) & 0x3f), - (unsigned)((datetimevalue >> 26) & 0x3f), - (unsigned)((datetimevalue >> 20) & 0x3f) - ); + 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); + } } } -inline void DataConvert::timeToString( long long timevalue, char* buf, unsigned int buflen ) +inline void DataConvert::timeToString( long long timevalue, char* buf, unsigned int buflen, long decimals ) { + // 10 is default which means we don't need microseconds + if (decimals > 6 || decimals < 0) + { + decimals = 0; + } // Handle negative correctly - int hour = 0; + int hour = 0, msec = 0; if ((timevalue >> 40) & 0x800) { hour = 0xfffff000; @@ -577,20 +591,23 @@ inline void DataConvert::timeToString( long long timevalue, char* buf, unsigned if ((timevalue & 0xffffff) > 0) { - snprintf( buf, buflen, "%02d:%02d:%02d.%d", - hour, - (unsigned)((timevalue >> 32) & 0xff), - (unsigned)((timevalue >> 24) & 0xff), - (unsigned)((timevalue) & 0xffffff) - ); + msec = (unsigned)((timevalue) & 0xffffff); } - else + snprintf( buf, buflen, "%02d:%02d:%02d", + hour, + (unsigned)((timevalue >> 32) & 0xff), + (unsigned)((timevalue >> 24) & 0xff) + ); + + if (msec || decimals) { - snprintf( buf, buflen, "%02d:%02d:%02d", - hour, - (unsigned)((timevalue >> 32) & 0xff), - (unsigned)((timevalue >> 24) & 0xff) - ); + 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); + } } } diff --git a/utils/funcexp/func_add_time.cpp b/utils/funcexp/func_add_time.cpp index 6fa7a5c19..0fa379bfd 100644 --- a/utils/funcexp/func_add_time.cpp +++ b/utils/funcexp/func_add_time.cpp @@ -80,16 +80,15 @@ int64_t addTime(DateTime& dt1, Time& dt2) } hour = (signed)(dt1.hour + dt2.hour + min / 60); - dt.hour = tmp = hour % 24; -// if (tmp < -1) - if (tmp < 0) // fix for subtime dlh + if ((hour < 0) || (hour > 23)) { - dt.hour = tmp + 24; - dt2.day--; + dt.hour = hour % 24; + dt2.day = hour / 24; } - day = (signed)(dt1.day + dt2.day + hour / 24); + day = (signed)(dt1.day + dt2.day); + if (isLeapYear(dt1.year) && dt1.month == 2) day--; @@ -97,7 +96,7 @@ int64_t addTime(DateTime& dt1, Time& dt2) month = dt1.month; int addyear = 0; - if (dt2.day < 0 || dt2.hour < 0) + if (day < 0) { int monthSave = month; @@ -106,7 +105,7 @@ int64_t addTime(DateTime& dt1, Time& dt2) month = (month == 1 ? 12 : month - 1); for (; day <= 0 && month > 0; month--) - day += getDaysInMonth(month); + day += getDaysInMonth(month, dt1.year); month++; // month=12; @@ -119,10 +118,10 @@ int64_t addTime(DateTime& dt1, Time& dt2) { int monthSave = month; - while (day > getDaysInMonth(month)) + while (day > getDaysInMonth(month, dt1.year)) { - for (; day > getDaysInMonth(month) && month <= 12; month++) - day -= getDaysInMonth(month); + for (; day > getDaysInMonth(month, dt1.year) && month <= 12; month++) + day -= getDaysInMonth(month, dt1.year); if (month > 12) month = 1; @@ -175,8 +174,23 @@ int64_t addTime(Time& dt1, Time& dt2) dt2.hour--; } - hour = (signed)(dt1.hour + dt2.hour + min / 60); - dt.hour = tmp = hour % 838; + dt.hour = (signed)(dt1.hour + dt2.hour + min / 60); + + // Saturation + if (dt.hour > 838) + { + dt.hour = 838; + dt.minute = 59; + dt.second = 59; + dt.msecond = 999999; + } + else if (dt.hour < -838) + { + dt.hour = -838; + dt.minute = 59; + dt.second = 59; + dt.msecond = 999999; + } return *(reinterpret_cast(&dt)); } @@ -226,6 +240,13 @@ int64_t Func_add_time::getDatetimeIntVal(rowgroup::Row& row, if (isNull) return -1; + // Adding a zero date to a time is always NULL + if (val1 == 0) + { + isNull = true; + return -1; + } + const string& val2 = parm[1]->data()->getStrVal(row, isNull); int sign = parm[2]->data()->getIntVal(row, isNull); DateTime dt1; @@ -311,7 +332,7 @@ int64_t Func_add_time::getTimeIntVal(rowgroup::Row& row, const string& val2 = parm[1]->data()->getStrVal(row, isNull); int sign = parm[2]->data()->getIntVal(row, isNull); Time dt1; - dt1.hour = (val1 >> 40) & 0xff; + dt1.hour = (val1 >> 40) & 0xfff; dt1.minute = (val1 >> 32) & 0xff; dt1.second = (val1 >> 24) & 0xff; dt1.msecond = val1 & 0xffffff; diff --git a/utils/funcexp/func_between.cpp b/utils/funcexp/func_between.cpp index 8398593c4..f23d67826 100644 --- a/utils/funcexp/func_between.cpp +++ b/utils/funcexp/func_between.cpp @@ -158,20 +158,21 @@ inline bool getBool(rowgroup::Row& row, case execplan::CalpontSystemCatalog::TIME: { - int64_t val = pm[0]->data()->getTimeIntVal(row, isNull); + // Shift out unused day for compare + int64_t val = pm[0]->data()->getTimeIntVal(row, isNull) << 12; if (notBetween) { - if (!numericGE(val, pm[1]->data()->getTimeIntVal(row, isNull)) && !isNull) + if (!numericGE(val, pm[1]->data()->getTimeIntVal(row, isNull) << 12) && !isNull) return true; isNull = false; - return (!numericLE(val, pm[2]->data()->getTimeIntVal(row, isNull)) && !isNull); + return (!numericLE(val, pm[2]->data()->getTimeIntVal(row, isNull) << 12) && !isNull); } return !isNull && - numericGE(val, pm[1]->data()->getTimeIntVal(row, isNull)) && - numericLE(val, pm[2]->data()->getTimeIntVal(row, isNull)); + numericGE(val, pm[1]->data()->getTimeIntVal(row, isNull) << 12) && + numericLE(val, pm[2]->data()->getTimeIntVal(row, isNull) << 12); } case execplan::CalpontSystemCatalog::DOUBLE: @@ -265,7 +266,8 @@ CalpontSystemCatalog::ColType Func_between::operationType( FunctionParm& fp, Cal fp[i]->data()->resultType().colDataType != CalpontSystemCatalog::TEXT && fp[i]->data()->resultType().colDataType != CalpontSystemCatalog::VARCHAR) || ct.colDataType == CalpontSystemCatalog::DATE || - ct.colDataType == CalpontSystemCatalog::DATETIME) + ct.colDataType == CalpontSystemCatalog::DATETIME || + ct.colDataType == CalpontSystemCatalog::TIME) { allString = false; } @@ -293,6 +295,23 @@ CalpontSystemCatalog::ColType Func_between::operationType( FunctionParm& fp, Cal } } } + else if (op.operationType().colDataType == CalpontSystemCatalog::TIME) + { + ConstantColumn* cc = NULL; + + for (uint32_t i = 1; i < fp.size(); i++) + { + cc = dynamic_cast(fp[i]->data()); + + if (cc) + { + Result result = cc->result(); + result.intVal = dataconvert::DataConvert::timeToInt(result.strVal); + cc->result(result); + } + } + } + return ct; } diff --git a/utils/funcexp/func_extract.cpp b/utils/funcexp/func_extract.cpp index d5a6cc5b5..67fc70a4d 100644 --- a/utils/funcexp/func_extract.cpp +++ b/utils/funcexp/func_extract.cpp @@ -131,6 +131,90 @@ long long dateGet( uint64_t time, IntervalColumn::interval_type unit, bool dateT throw runtime_error("unit type is not supported: " + unit); }; } + +long long timeGet( uint64_t time, IntervalColumn::interval_type unit ) +{ + int32_t hour = 0, + min = 0, + sec = 0, + msec = 0, + day = 0; + + min = (int32_t)((time >> 32) & 0xff); + sec = (int32_t)((time >> 24) & 0xff); + msec = (int32_t)((time & 0xfffff)); + + // If negative, mask so it doesn't turn positive + int64_t mask = 0; + if ((time >> 40) & 0x800) + mask = 0xfffffffffffff000; + hour = mask | ((time >> 40) & 0xfff); + + // Always positive! + day = abs(hour / 24); + + switch ( unit ) + { + case IntervalColumn::INTERVAL_YEAR: + case IntervalColumn::INTERVAL_MONTH: + return 0; + + case IntervalColumn::INTERVAL_DAY: + return day; + + case IntervalColumn::INTERVAL_HOUR: + return hour; + + case IntervalColumn::INTERVAL_MINUTE: + return min; + + case IntervalColumn::INTERVAL_SECOND: + return sec; + + case IntervalColumn::INTERVAL_MICROSECOND: + return msec; + + case IntervalColumn::INTERVAL_QUARTER: + case IntervalColumn::INTERVAL_WEEK: + case IntervalColumn::INTERVAL_YEAR_MONTH: + return 0; + + case IntervalColumn::INTERVAL_DAY_HOUR: + return (day * 100) + hour; + + case IntervalColumn::INTERVAL_DAY_MINUTE: + return (day * 10000) + (hour * 100) + min; + + case IntervalColumn::INTERVAL_DAY_SECOND: + return (day * 1000000) + (hour * 10000) + (min * 100) + sec; + + case IntervalColumn::INTERVAL_HOUR_MINUTE: + return (hour * 100) + min; + + case IntervalColumn::INTERVAL_HOUR_SECOND: + return (hour * 10000) + (min * 100) + sec; + + case IntervalColumn::INTERVAL_MINUTE_SECOND: + return (min * 100) + sec; + + case IntervalColumn::INTERVAL_DAY_MICROSECOND: + return (((day * 1000000) + (hour * 10000) + (min * 100) + sec) * 1000000) + msec; + + case IntervalColumn::INTERVAL_HOUR_MICROSECOND: + return (((hour * 10000) + (min * 100) + sec) * 1000000) + msec; + + case IntervalColumn::INTERVAL_MINUTE_MICROSECOND: + return (((min * 100) + sec) * 1000000) + msec; + + case IntervalColumn::INTERVAL_SECOND_MICROSECOND: + return (sec * 1000000) + msec; + + default: + throw runtime_error("unit type is not supported: " + unit); + }; +} + + } namespace funcexp @@ -148,16 +232,21 @@ int64_t Func_extract::getIntVal(rowgroup::Row& row, { IntervalColumn::interval_type unit = static_cast(parm[1]->data()->getIntVal(row, isNull)); uint64_t time; + bool isTime = false; //@bug4678 handle conversion from non date/datetime datatype switch (parm[0]->data()->resultType().colDataType) { case CalpontSystemCatalog::DATE: case CalpontSystemCatalog::DATETIME: - case CalpontSystemCatalog::TIME: time = parm[0]->data()->getDatetimeIntVal(row, isNull); break; + case CalpontSystemCatalog::TIME: + time = parm[0]->data()->getTimeIntVal(row, isNull); + isTime = true; + break; + case CalpontSystemCatalog::VARCHAR: case CalpontSystemCatalog::CHAR: case CalpontSystemCatalog::TEXT: @@ -182,7 +271,11 @@ int64_t Func_extract::getIntVal(rowgroup::Row& row, time = parm[0]->data()->getIntVal(row, isNull); } - long long value = dateGet( time, unit, false ); + long long value; + if (isTime) + value = timeGet( time, unit ); + else + value = dateGet( time, unit, false ); return value; } diff --git a/utils/funcexp/func_greatest.cpp b/utils/funcexp/func_greatest.cpp index 50ff4204a..11650ddca 100644 --- a/utils/funcexp/func_greatest.cpp +++ b/utils/funcexp/func_greatest.cpp @@ -211,13 +211,14 @@ int64_t Func_greatest::getTimeIntVal(rowgroup::Row& row, bool& isNull, execplan::CalpontSystemCatalog::ColType& ct) { - int64_t str = fp[0]->data()->getTimeIntVal(row, isNull); + // Strip off unused day + int64_t str = fp[0]->data()->getTimeIntVal(row, isNull) << 12; int64_t greatestStr = str; for (uint32_t i = 1; i < fp.size(); i++) { - int64_t str1 = fp[i]->data()->getTimeIntVal(row, isNull); + int64_t str1 = fp[i]->data()->getTimeIntVal(row, isNull) << 12; if ( greatestStr < str1 ) greatestStr = str1; diff --git a/utils/funcexp/func_hour.cpp b/utils/funcexp/func_hour.cpp index b9e3da9ec..353d0cc4e 100644 --- a/utils/funcexp/func_hour.cpp +++ b/utils/funcexp/func_hour.cpp @@ -48,6 +48,7 @@ int64_t Func_hour::getIntVal(rowgroup::Row& row, CalpontSystemCatalog::ColType& op_ct) { int64_t val = 0; + bool isTime = false; switch (parm[0]->data()->resultType().colDataType) { @@ -110,7 +111,8 @@ int64_t Func_hour::getIntVal(rowgroup::Row& row, case execplan::CalpontSystemCatalog::TIME: { - val = parm[0]->data()->getDatetimeIntVal(row, isNull); + isTime = true; + val = parm[0]->data()->getTimeIntVal(row, isNull); break; } @@ -123,10 +125,20 @@ int64_t Func_hour::getIntVal(rowgroup::Row& row, if (isNull) return -1; - if ( val < 1000000000 ) - return 0; + if (isTime) + { + // If negative, mask so it doesn't turn positive + int64_t mask = 0; + if ((val >> 40) & 0x800) + mask = 0xfffffffffffff000; + val = mask | ((val >> 40) & 0xfff); + } + else + { + val = (val >> 32) & 0x3f; + } - return (uint32_t)((val >> 32) & 0x3f); + return val; } diff --git a/utils/funcexp/func_least.cpp b/utils/funcexp/func_least.cpp index ef71e44e6..70a64f267 100644 --- a/utils/funcexp/func_least.cpp +++ b/utils/funcexp/func_least.cpp @@ -187,13 +187,14 @@ int64_t Func_least::getTimeIntVal(rowgroup::Row& row, bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct) { - int64_t str = fp[0]->data()->getTimeIntVal(row, isNull); + // Strip off unused day + int64_t str = fp[0]->data()->getTimeIntVal(row, isNull) << 12; int64_t leastStr = str; for (uint32_t i = 1; i < fp.size(); i++) { - int64_t str1 = fp[i]->data()->getTimeIntVal(row, isNull); + int64_t str1 = fp[i]->data()->getTimeIntVal(row, isNull) << 12; if ( leastStr > str1 ) leastStr = str1; diff --git a/utils/funcexp/func_time.cpp b/utils/funcexp/func_time.cpp index 8aab1389b..bd28d6e6c 100644 --- a/utils/funcexp/func_time.cpp +++ b/utils/funcexp/func_time.cpp @@ -59,7 +59,7 @@ string Func_time::getStrVal(rowgroup::Row& row, case execplan::CalpontSystemCatalog::TINYINT: case execplan::CalpontSystemCatalog::SMALLINT: { - val = dataconvert::DataConvert::intToDatetime(parm[0]->data()->getIntVal(row, isNull)); + val = dataconvert::DataConvert::intToTime(parm[0]->data()->getIntVal(row, isNull)); if (val == -1) isNull = true; @@ -73,7 +73,7 @@ string Func_time::getStrVal(rowgroup::Row& row, { if (parm[0]->data()->resultType().scale) { - val = dataconvert::DataConvert::intToDatetime(parm[0]->data()->getIntVal(row, isNull)); + val = dataconvert::DataConvert::intToTime(parm[0]->data()->getIntVal(row, isNull)); if (val == -1) isNull = true; @@ -96,7 +96,7 @@ string Func_time::getStrVal(rowgroup::Row& row, case execplan::CalpontSystemCatalog::CHAR: case execplan::CalpontSystemCatalog::TEXT: { - val = dataconvert::DataConvert::stringToDatetime(parm[0]->data()->getStrVal(row, isNull)); + val = dataconvert::DataConvert::stringToTime(parm[0]->data()->getStrVal(row, isNull)); if (val == -1) isNull = true; @@ -106,16 +106,14 @@ string Func_time::getStrVal(rowgroup::Row& row, break; } - case execplan::CalpontSystemCatalog::DATE: + case execplan::CalpontSystemCatalog::TIME: { - val = parm[0]->data()->getDatetimeIntVal(row, isNull); + val = parm[0]->data()->getTimeIntVal(row, isNull); break; } - - case execplan::CalpontSystemCatalog::TIME: case execplan::CalpontSystemCatalog::DATETIME: { - val = parm[0]->data()->getDatetimeIntVal(row, isNull); + val = parm[0]->data()->getTimeIntVal(row, isNull); break; } @@ -129,9 +127,9 @@ string Func_time::getStrVal(rowgroup::Row& row, return ""; char buf[30] = {'\0'}; - dataconvert::DataConvert::datetimeToString(val, buf, sizeof(buf)); + dataconvert::DataConvert::timeToString(val, buf, sizeof(buf)); string time(buf); - return time.substr(11, 80); + return time; } int64_t Func_time::getIntVal(rowgroup::Row& row, @@ -139,7 +137,7 @@ int64_t Func_time::getIntVal(rowgroup::Row& row, bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct) { - return dataconvert::DataConvert::datetimeToInt(getStrVal(row, fp, isNull, op_ct)); + return dataconvert::DataConvert::timeToInt(getStrVal(row, fp, isNull, op_ct)); } double Func_time::getDoubleVal(rowgroup::Row& row,