1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2025-07-30 19:23:07 +03:00

MCOL 3474 Fix Timediff results after accounting for new test cases

This commit is contained in:
jmrojas2332
2019-12-04 22:48:07 +00:00
parent 16b004dc07
commit c29c41e235
3 changed files with 62 additions and 35 deletions

View File

@ -3005,6 +3005,14 @@ int64_t DataConvert::intToDatetime(int64_t data, bool* date)
else else
{ {
y = atoi(year.c_str()); 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()); m = atoi(month.c_str());
@ -3056,10 +3064,10 @@ int64_t DataConvert::intToTime(int64_t data, bool fromString)
#if defined(__GNUC__) && __GNUC__ >= 7 #if defined(__GNUC__) && __GNUC__ >= 7
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat-truncation=" #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 #pragma GCC diagnostic pop
#else #else
snprintf( buf, 15, "%llu", (long long unsigned int)data); snprintf( buf, 15, "%lld", (long long int)data);
#endif #endif
//string date = buf; //string date = buf;
@ -3090,8 +3098,8 @@ int64_t DataConvert::intToTime(int64_t data, bool fromString)
case 7: case 7:
hour = string(bufread, 3); hour = string(bufread, 3);
min = string(bufread + 2, 2); min = string(bufread + 3, 2);
sec = string(bufread + 4, 2); sec = string(bufread + 5, 2);
break; break;
case 6: case 6:
@ -3152,7 +3160,7 @@ int64_t DataConvert::intToTime(int64_t data, bool fromString)
atime.msecond = ms; atime.msecond = ms;
atime.is_neg = isNeg; atime.is_neg = isNeg;
return *(reinterpret_cast<uint64_t*>(&atime)); return *(reinterpret_cast<int64_t*>(&atime));
} }
int64_t DataConvert::stringToTime(const string& data) int64_t DataConvert::stringToTime(const string& data)

View File

@ -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 ) CalpontSystemCatalog::ColType Func_timediff::operationType( FunctionParm& fp, CalpontSystemCatalog::ColType& resultType )
{ {
return resultType; return resultType;
@ -163,14 +171,10 @@ string Func_timediff::getStrVal(rowgroup::Row& row,
case execplan::CalpontSystemCatalog::TEXT: case execplan::CalpontSystemCatalog::TEXT:
text = parm[0]->data()->getStrVal(row, isNull); 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); 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 else
{ {
val1 = dataconvert::DataConvert::stringToTime(text); val1 = dataconvert::DataConvert::stringToTime(text);
@ -184,7 +188,7 @@ string Func_timediff::getStrVal(rowgroup::Row& row,
case execplan::CalpontSystemCatalog::TINYINT: case execplan::CalpontSystemCatalog::TINYINT:
case execplan::CalpontSystemCatalog::SMALLINT: case execplan::CalpontSystemCatalog::SMALLINT:
text = parm[0]->data()->getStrVal(row, isNull); 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); val1 = dataconvert::DataConvert::intToDatetime(parm[0]->data()->getIntVal(row, isNull), &isDate1);
else else
{ {
@ -202,7 +206,7 @@ string Func_timediff::getStrVal(rowgroup::Row& row,
else else
{ {
text = parm[0]->data()->getStrVal(row, isNull); 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); val1 = dataconvert::DataConvert::intToDatetime(parm[0]->data()->getIntVal(row, isNull), &isDate1);
else else
{ {
@ -252,14 +256,10 @@ 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);
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); 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 else
{ {
val2 = dataconvert::DataConvert::stringToTime(text); val2 = dataconvert::DataConvert::stringToTime(text);
@ -273,7 +273,7 @@ string Func_timediff::getStrVal(rowgroup::Row& row,
case execplan::CalpontSystemCatalog::TINYINT: case execplan::CalpontSystemCatalog::TINYINT:
case execplan::CalpontSystemCatalog::SMALLINT: case execplan::CalpontSystemCatalog::SMALLINT:
text = parm[1]->data()->getStrVal(row, isNull); 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); val2 = dataconvert::DataConvert::intToDatetime(parm[1]->data()->getIntVal(row, isNull), &isDate2);
else else
{ {
@ -291,7 +291,7 @@ string Func_timediff::getStrVal(rowgroup::Row& row,
else else
{ {
text = parm[1]->data()->getStrVal(row, isNull); 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); val2 = dataconvert::DataConvert::intToDatetime(parm[1]->data()->getIntVal(row, isNull), &isDate2);
else else
{ {
@ -363,7 +363,5 @@ double Func_timediff::getDoubleVal(rowgroup::Row& row,
return atof(getStrVal(row, fp, isNull, op_ct).c_str()); return atof(getStrVal(row, fp, isNull, op_ct).c_str());
} }
} // namespace funcexp } // namespace funcexp
// vim:ts=4 sw=4: // vim:ts=4 sw=4:

View File

@ -393,21 +393,42 @@ 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 = isDateTime ? (uint32_t)((time1 >> 48) & 0xffff) : 0; if (isDateTime)
month1 = isDateTime ? (uint32_t)((time1 >> 44) & 0xf) : 0; {
day1 = isDateTime ? (uint32_t)((time1 >> 38) & 0x3f) : (uint32_t)((time1 >> 52) & 0x7ff); year1 = (uint32_t)((time1 >> 48) & 0xffff);
hour1 = isDateTime ? (uint32_t)((time1 >> 32) & 0x3f) : (uint32_t)((time1 >> 40) & 0xfff); month1 = (uint32_t)((time1 >> 44) & 0xf);
min1 = isDateTime ? (uint32_t)((time1 >> 26) & 0x3f) : (uint32_t)((time1 >> 32) & 0xff); day1 = (uint32_t)((time1 >> 38) & 0x3f);
sec1 = isDateTime ? (uint32_t)((time1 >> 20) & 0x3f) : (uint32_t)((time1 >> 24) & 0xff); hour1 = (uint32_t)((time1 >> 32) & 0x3f);
msec1 = isDateTime ? (uint32_t)((time1 & 0xfffff)) : (uint32_t)(time1 & 0xffffff); 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; year2 = (uint32_t)((time2 >> 48) & 0xffff);
month2 = isDateTime ? (uint32_t)((time2 >> 44) & 0xf) : 0; month2 = (uint32_t)((time2 >> 44) & 0xf);
day2 = isDateTime ? (uint32_t)((time2 >> 38) & 0x3f) : (uint32_t)((time2 >> 52) & 0x7ff);; day2 = (uint32_t)((time2 >> 38) & 0x3f);
hour2 = isDateTime ? (uint32_t)((time2 >> 32) & 0x3f) : (uint32_t)((time2 >> 40) & 0xfff); hour2 = (uint32_t)((time2 >> 32) & 0x3f);
min2 = isDateTime ? (uint32_t)((time2 >> 26) & 0x3f) : (uint32_t)((time2 >> 32) & 0xff); min2 = (uint32_t)((time2 >> 26) & 0x3f);
sec2 = isDateTime ? (uint32_t)((time2 >> 20) & 0x3f) : (uint32_t)((time2 >> 24) & 0xff); sec2 = (uint32_t)((time2 >> 20) & 0x3f);
msec2 = isDateTime ? (uint32_t)((time2 & 0xfffff)) : (uint32_t)(time2 & 0xffffff); 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); days = calc_mysql_daynr(year1, month1, day1);