From edb2e2f36d2f9ff40e7b4c6413cdc1b5b29e151f Mon Sep 17 00:00:00 2001 From: Andrew Hutchings Date: Thu, 26 Apr 2018 14:28:17 +0100 Subject: [PATCH] MCOL-392 Fix negative time handling --- utils/dataconvert/dataconvert.cpp | 12 ++++++++---- utils/dataconvert/dataconvert.h | 24 +++++++++++++++++++++--- utils/funcexp/func_bitand.cpp | 7 ++++++- utils/rowgroup/rowaggregation.cpp | 10 +++++++++- 4 files changed, 44 insertions(+), 9 deletions(-) diff --git a/utils/dataconvert/dataconvert.cpp b/utils/dataconvert/dataconvert.cpp index b5b1ae619..013e3f05c 100644 --- a/utils/dataconvert/dataconvert.cpp +++ b/utils/dataconvert/dataconvert.cpp @@ -863,12 +863,11 @@ bool mysql_str_to_time( const string& input, Time& output ) { int32_t datesepct = 0; uint32_t dtend = 0; + bool isNeg = false; /** * We need to deal with the time portion. * The rules are: - * - Time portion may be empty - * - Time portion may start with 'T' * - Time portion always ends with '\0' * - Time portion always starts with hour * - Without time separators (':'): @@ -890,7 +889,7 @@ bool mysql_str_to_time( const string& input, Time& output ) uint32_t timesep_ct = 0; bool has_usec = false; uint32_t len_before_msec = 0; - uint32_t tmstart = ( input[dtend] == ' ' || input[dtend] == 'T' ) ? dtend + 1 : dtend; + uint32_t tmstart = dtend; uint32_t tmend = tmstart; for ( ; tmend < input.length(); ++tmend ) @@ -918,6 +917,11 @@ bool mysql_str_to_time( const string& input, Time& output ) len_before_msec = ( tmend - tmstart ); has_usec = true; } + else if (c == '-' && (tmend == tmstart)) + { + isNeg = true; + ++tmstart; + } else { timesep_ct++; @@ -998,7 +1002,7 @@ bool mysql_str_to_time( const string& input, Time& output ) return false; } - output.hour = hour; + output.hour = isNeg ? 0-hour : hour; output.minute = min; output.second = sec; output.msecond = usec; diff --git a/utils/dataconvert/dataconvert.h b/utils/dataconvert/dataconvert.h index 7f148daf8..1c7b7f663 100644 --- a/utils/dataconvert/dataconvert.h +++ b/utils/dataconvert/dataconvert.h @@ -566,10 +566,19 @@ inline void DataConvert::datetimeToString( long long datetimevalue, char* buf, u inline void DataConvert::timeToString( long long timevalue, char* buf, unsigned int buflen ) { + // Handle negative correctly + int hour = 0; + if ((timevalue >> 40) & 0xf00) + { + hour = 0xfffff000; + } + + hour |= ((timevalue >> 40) & 0xfff); + if ((timevalue & 0xffffff) > 0) { snprintf( buf, buflen, "%02d:%02d:%02d.%d", - (unsigned)((timevalue >> 40) & 0xfff), + hour, (unsigned)((timevalue >> 32) & 0xff), (unsigned)((timevalue >> 24) & 0xff), (unsigned)((timevalue) & 0xffffff) @@ -578,7 +587,7 @@ inline void DataConvert::timeToString( long long timevalue, char* buf, unsigned else { snprintf( buf, buflen, "%02d:%02d:%02d", - (unsigned)((timevalue >> 40) & 0xfff), + hour, (unsigned)((timevalue >> 32) & 0xff), (unsigned)((timevalue >> 24) & 0xff) ); @@ -608,8 +617,17 @@ inline void DataConvert::datetimeToString1( long long datetimevalue, char* buf, inline void DataConvert::timeToString1( long long timevalue, char* buf, unsigned int buflen ) { + // Handle negative correctly + int hour = 0; + if ((timevalue >> 40) & 0xf00) + { + hour = 0xfffff000; + } + + hour |= ((timevalue >> 40) & 0xfff); + snprintf( buf, buflen, "%02d%02d%02d", - (unsigned)((timevalue >> 40) & 0xfff), + hour, (unsigned)((timevalue >> 32) & 0xff), (unsigned)((timevalue >> 14) & 0xff) ); diff --git a/utils/funcexp/func_bitand.cpp b/utils/funcexp/func_bitand.cpp index eceb4e4c0..3966d7a42 100644 --- a/utils/funcexp/func_bitand.cpp +++ b/utils/funcexp/func_bitand.cpp @@ -165,8 +165,13 @@ int64_t Func_bitand::getIntVal(Row& row, min = 0, sec = 0, msec = 0; + // Handle negative correctly + if ((time >> 40) & 0xf00) + { + hour = 0xfffff000; + } - hour = (uint32_t)((time >> 40) & 0xfff); + hour |= ((time >> 40) & 0xfff); min = (uint32_t)((time >> 32) & 0xff); sec = (uint32_t)((time >> 24) & 0xff); msec = (uint32_t)(time & 0xffffff); diff --git a/utils/rowgroup/rowaggregation.cpp b/utils/rowgroup/rowaggregation.cpp index a7edd9248..b6d72fede 100644 --- a/utils/rowgroup/rowaggregation.cpp +++ b/utils/rowgroup/rowaggregation.cpp @@ -1541,7 +1541,15 @@ void RowAggregation::doBitOp(const Row& rowIn, int64_t colIn, int64_t colOut, in case execplan::CalpontSystemCatalog::TIME: { int64_t dtm = rowIn.getUintField(colIn); - valIn = (((dtm >> 40) & 0xfff) * 10000000000) + + // Handle negative correctly + int hour = 0; + if ((dtm >> 40) & 0xf00) + { + hour = 0xfffff000; + } + + hour |= ((dtm >> 40) & 0xfff); + valIn = (hour * 10000000000) + (((dtm >> 32) & 0xff) * 100000000) + (((dtm >> 24) & 0xff) * 1000000) + (dtm & 0xffffff); break; }