1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2025-08-01 06:46:55 +03:00

MCOL-392 Function fixes

Fixes most of the functions in funcexp so that time and datetime's
microseconds are handled correctly
This commit is contained in:
Andrew Hutchings
2018-04-27 21:18:14 +01:00
parent bd50bbb8bb
commit 957dc44615
11 changed files with 271 additions and 101 deletions

View File

@ -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<uint64_t*>(&atime));
return *(reinterpret_cast<int64_t*>(&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;

View File

@ -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);
}
}
}