1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2025-07-29 08:21:15 +03:00

MCOL 3474 Fix TIMEDIFF w/ non-temporal data types

This commit is contained in:
jmrojas2332
2019-12-03 06:47:36 +00:00
parent 57724e5515
commit 252268ef63
2 changed files with 79 additions and 28 deletions

View File

@ -45,7 +45,7 @@ namespace funcexp
namespace helpers namespace helpers
{ {
const string timediff( int64_t time1, int64_t time2) const string timediff( int64_t time1, int64_t time2, bool isDateTime)
{ {
long long seconds; long long seconds;
long long microseconds; long long microseconds;
@ -56,9 +56,9 @@ const string timediff( int64_t time1, int64_t time2)
l_sign = -l_sign; l_sign = -l_sign;
if ( time1 > time2 ) if ( time1 > time2 )
helpers::calc_time_diff(time1, time2, l_sign, &seconds, &microseconds); helpers::calc_time_diff(time1, time2, l_sign, &seconds, &microseconds, isDateTime);
else else
helpers::calc_time_diff(time2, time1, l_sign, &seconds, &microseconds); helpers::calc_time_diff(time2, time1, l_sign, &seconds, &microseconds, isDateTime);
long t_seconds; long t_seconds;
int hour = seconds / 3600L; int hour = seconds / 3600L;
@ -162,8 +162,20 @@ string Func_timediff::getStrVal(rowgroup::Row& row,
case execplan::CalpontSystemCatalog::CHAR: case execplan::CalpontSystemCatalog::CHAR:
case execplan::CalpontSystemCatalog::TEXT: case execplan::CalpontSystemCatalog::TEXT:
text = parm[0]->data()->getStrVal(row, isNull); text = parm[0]->data()->getStrVal(row, isNull);
isTime1 = std::count(text.begin(), text.end(), '-') <= 1; // Time can have at most 1 dash (signifies negative)
val1 = dataconvert::DataConvert::stringToDatetime(text, &isDate1); if (text.length() >= 14) // datetime has length at least 14
{
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);
isTime1 = true;
}
break; break;
case execplan::CalpontSystemCatalog::BIGINT: case execplan::CalpontSystemCatalog::BIGINT:
@ -171,7 +183,14 @@ string Func_timediff::getStrVal(rowgroup::Row& row,
case execplan::CalpontSystemCatalog::MEDINT: case execplan::CalpontSystemCatalog::MEDINT:
case execplan::CalpontSystemCatalog::TINYINT: case execplan::CalpontSystemCatalog::TINYINT:
case execplan::CalpontSystemCatalog::SMALLINT: case execplan::CalpontSystemCatalog::SMALLINT:
val1 = dataconvert::DataConvert::intToDatetime(parm[0]->data()->getIntVal(row, isNull), &isDate1); text = parm[0]->data()->getStrVal(row, isNull);
if (text.length() >= 14) // datetime has length at least 14
val1 = dataconvert::DataConvert::intToDatetime(parm[0]->data()->getIntVal(row, isNull), &isDate1);
else
{
val1 = dataconvert::DataConvert::intToTime(parm[0]->data()->getIntVal(row, isNull));
isTime1 = true;
}
break; break;
case execplan::CalpontSystemCatalog::DECIMAL: case execplan::CalpontSystemCatalog::DECIMAL:
@ -182,7 +201,14 @@ string Func_timediff::getStrVal(rowgroup::Row& row,
} }
else else
{ {
val1 = dataconvert::DataConvert::intToDatetime(parm[0]->data()->getIntVal(row, isNull), &isDate1); text = parm[0]->data()->getStrVal(row, isNull);
if (text.length() >= 14) // datetime has length at least 14
val1 = dataconvert::DataConvert::intToDatetime(parm[0]->data()->getIntVal(row, isNull), &isDate1);
else
{
val1 = dataconvert::DataConvert::intToTime(parm[0]->data()->getIntVal(row, isNull));
isTime1 = true;
}
break; break;
} }
@ -226,8 +252,19 @@ string Func_timediff::getStrVal(rowgroup::Row& row,
case execplan::CalpontSystemCatalog::CHAR: case execplan::CalpontSystemCatalog::CHAR:
case execplan::CalpontSystemCatalog::TEXT: case execplan::CalpontSystemCatalog::TEXT:
text = parm[1]->data()->getStrVal(row, isNull); text = parm[1]->data()->getStrVal(row, isNull);
isTime2 = std::count(text.begin(), text.end(), '-') <= 1; // Time can have at most 1 dash (signifies negative) if (text.length() >= 14) // datetime has length at least 14
val2 = dataconvert::DataConvert::stringToDatetime(text, &isDate2); {
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);
isTime2 = true;
}
break; break;
case execplan::CalpontSystemCatalog::BIGINT: case execplan::CalpontSystemCatalog::BIGINT:
@ -235,7 +272,14 @@ string Func_timediff::getStrVal(rowgroup::Row& row,
case execplan::CalpontSystemCatalog::MEDINT: case execplan::CalpontSystemCatalog::MEDINT:
case execplan::CalpontSystemCatalog::TINYINT: case execplan::CalpontSystemCatalog::TINYINT:
case execplan::CalpontSystemCatalog::SMALLINT: case execplan::CalpontSystemCatalog::SMALLINT:
val2 = dataconvert::DataConvert::intToDatetime(parm[1]->data()->getIntVal(row, isNull), &isDate2); text = parm[1]->data()->getStrVal(row, isNull);
if (text.length() >= 14) // datetime has length at least 14
val2 = dataconvert::DataConvert::intToDatetime(parm[1]->data()->getIntVal(row, isNull), &isDate2);
else
{
val2 = dataconvert::DataConvert::intToTime(parm[1]->data()->getIntVal(row, isNull));
isTime2 = true;
}
break; break;
case execplan::CalpontSystemCatalog::DECIMAL: case execplan::CalpontSystemCatalog::DECIMAL:
@ -246,7 +290,14 @@ string Func_timediff::getStrVal(rowgroup::Row& row,
} }
else else
{ {
val2 = dataconvert::DataConvert::intToDatetime(parm[1]->data()->getIntVal(row, isNull), &isDate2); text = parm[1]->data()->getStrVal(row, isNull);
if (text.length() >= 14) // datetime has length at least 14
val2 = dataconvert::DataConvert::intToDatetime(parm[1]->data()->getIntVal(row, isNull), &isDate2);
else
{
val2 = dataconvert::DataConvert::intToTime(parm[1]->data()->getIntVal(row, isNull));
isTime2 = true;
}
break; break;
} }
@ -262,7 +313,7 @@ string Func_timediff::getStrVal(rowgroup::Row& row,
// both date format or both datetime format. Diff between time and datetime returns NULL in MariaDB // both date format or both datetime format. Diff between time and datetime returns NULL in MariaDB
if ((isDate1 && isDate2) || ((!isDate1 && !isDate2) && (isTime1 == isTime2))) if ((isDate1 && isDate2) || ((!isDate1 && !isDate2) && (isTime1 == isTime2)))
return helpers::timediff( val1, val2); return helpers::timediff( val1, val2, !isTime1);
isNull = true; isNull = true;
return ""; return "";

View File

@ -371,7 +371,7 @@ inline uint32_t calc_mysql_week( uint32_t year, uint32_t month, uint32_t day,
return days / 7 + 1; return days / 7 + 1;
} }
inline bool calc_time_diff(int64_t time1, int64_t time2, int l_sign, long long* seconds_out, long long* microseconds_out) inline bool calc_time_diff(int64_t time1, int64_t time2, int l_sign, long long* seconds_out, long long* microseconds_out, bool isDateTime = true)
{ {
int64_t days; int64_t days;
bool neg; bool neg;
@ -393,21 +393,21 @@ inline bool calc_time_diff(int64_t time1, int64_t time2, int l_sign, long long*
sec2 = 0, sec2 = 0,
msec2 = 0; msec2 = 0;
year1 = (uint32_t)((time1 >> 48) & 0xffff); year1 = isDateTime ? (uint32_t)((time1 >> 48) & 0xffff) : 0;
month1 = (uint32_t)((time1 >> 44) & 0xf); month1 = isDateTime ? (uint32_t)((time1 >> 44) & 0xf) : 0;
day1 = (uint32_t)((time1 >> 38) & 0x3f); day1 = isDateTime ? (uint32_t)((time1 >> 38) & 0x3f) : (uint32_t)((time1 >> 52) & 0x7ff);
hour1 = (uint32_t)((time1 >> 32) & 0x3f); hour1 = isDateTime ? (uint32_t)((time1 >> 32) & 0x3f) : (uint32_t)((time1 >> 40) & 0xfff);
min1 = (uint32_t)((time1 >> 26) & 0x3f); min1 = isDateTime ? (uint32_t)((time1 >> 26) & 0x3f) : (uint32_t)((time1 >> 32) & 0xff);
sec1 = (uint32_t)((time1 >> 20) & 0x3f); sec1 = isDateTime ? (uint32_t)((time1 >> 20) & 0x3f) : (uint32_t)((time1 >> 24) & 0xff);
msec1 = (uint32_t)((time1 & 0xfffff)); msec1 = isDateTime ? (uint32_t)((time1 & 0xfffff)) : (uint32_t)(time1 & 0xffffff);
year2 = (uint32_t)((time2 >> 48) & 0xffff); year2 = isDateTime ? (uint32_t)((time2 >> 48) & 0xffff) : 0;
month2 = (uint32_t)((time2 >> 44) & 0xf); month2 = isDateTime ? (uint32_t)((time2 >> 44) & 0xf) : 0;
day2 = (uint32_t)((time2 >> 38) & 0x3f); day2 = isDateTime ? (uint32_t)((time2 >> 38) & 0x3f) : (uint32_t)((time2 >> 52) & 0x7ff);;
hour2 = (uint32_t)((time2 >> 32) & 0x3f); hour2 = isDateTime ? (uint32_t)((time2 >> 32) & 0x3f) : (uint32_t)((time2 >> 40) & 0xfff);
min2 = (uint32_t)((time2 >> 26) & 0x3f); min2 = isDateTime ? (uint32_t)((time2 >> 26) & 0x3f) : (uint32_t)((time2 >> 32) & 0xff);
sec2 = (uint32_t)((time2 >> 20) & 0x3f); sec2 = isDateTime ? (uint32_t)((time2 >> 20) & 0x3f) : (uint32_t)((time2 >> 24) & 0xff);
msec2 = (uint32_t)((time2 & 0xfffff)); msec2 = isDateTime ? (uint32_t)((time2 & 0xfffff)) : (uint32_t)(time2 & 0xffffff);
days = calc_mysql_daynr(year1, month1, day1); days = calc_mysql_daynr(year1, month1, day1);
@ -768,7 +768,7 @@ string longDoubleToString(long double ld)
uint64_t dateAdd( uint64_t time, const std::string& expr, execplan::IntervalColumn::interval_type unit, bool dateType, execplan::OpType funcType ); uint64_t dateAdd( uint64_t time, const std::string& expr, execplan::IntervalColumn::interval_type unit, bool dateType, execplan::OpType funcType );
const std::string IDB_date_format(const dataconvert::DateTime&, const std::string&); const std::string IDB_date_format(const dataconvert::DateTime&, const std::string&);
const std::string timediff(int64_t, int64_t); const std::string timediff(int64_t, int64_t, bool isDateTime = true);
const char* convNumToStr(int64_t, char*, int); const char* convNumToStr(int64_t, char*, int);
} //namespace funcexp::helpers } //namespace funcexp::helpers