Commit b97b9536 authored by Alexander Barkov's avatar Alexander Barkov

MDEV-4857 Wrong result of HOUR('1 00:00:00')

modified:
  mysql-test/r/func_time.result
  mysql-test/t/func_time.test
  sql-common/my_time.c
  sql/item_func.h
  sql/item_timefunc.cc
  sql/mysql_priv.h
  sql/time.cc
parent 928543ca
...@@ -365,7 +365,7 @@ extract(DAY_MINUTE FROM "02 10:11:12") ...@@ -365,7 +365,7 @@ extract(DAY_MINUTE FROM "02 10:11:12")
21011 21011
select extract(DAY_SECOND FROM "225 10:11:12"); select extract(DAY_SECOND FROM "225 10:11:12");
extract(DAY_SECOND FROM "225 10:11:12") extract(DAY_SECOND FROM "225 10:11:12")
8385959 34225959
Warnings: Warnings:
Warning 1292 Truncated incorrect time value: '225 10:11:12' Warning 1292 Truncated incorrect time value: '225 10:11:12'
select extract(HOUR FROM "1999-01-02 10:11:12"); select extract(HOUR FROM "1999-01-02 10:11:12");
...@@ -1035,7 +1035,7 @@ Warning 1105 Cast to unsigned converted negative integer to it's positive comple ...@@ -1035,7 +1035,7 @@ Warning 1105 Cast to unsigned converted negative integer to it's positive comple
Warning 1292 Truncated incorrect time value: '18446744073709551615:00:00' Warning 1292 Truncated incorrect time value: '18446744073709551615:00:00'
SELECT EXTRACT(HOUR FROM '100000:02:03'); SELECT EXTRACT(HOUR FROM '100000:02:03');
EXTRACT(HOUR FROM '100000:02:03') EXTRACT(HOUR FROM '100000:02:03')
838 22
Warnings: Warnings:
Warning 1292 Truncated incorrect time value: '100000:02:03' Warning 1292 Truncated incorrect time value: '100000:02:03'
CREATE TABLE t1(f1 TIME); CREATE TABLE t1(f1 TIME);
...@@ -2320,3 +2320,30 @@ DROP TABLE t1; ...@@ -2320,3 +2320,30 @@ DROP TABLE t1;
SELECT MAKETIME(0, 0, -0.1); SELECT MAKETIME(0, 0, -0.1);
MAKETIME(0, 0, -0.1) MAKETIME(0, 0, -0.1)
NULL NULL
#
# MDEV-4857 Wrong result of HOUR('1 00:00:00')
#
SELECT HOUR('1 02:00:00'), HOUR('26:00:00');
HOUR('1 02:00:00') HOUR('26:00:00')
26 26
SELECT HOUR(TIME'1 02:00:00'), HOUR(TIME'26:00:00');
HOUR(TIME'1 02:00:00') HOUR(TIME'26:00:00')
26 26
SELECT HOUR(TIME('1 02:00:00')), HOUR(TIME('26:00:00'));
HOUR(TIME('1 02:00:00')) HOUR(TIME('26:00:00'))
26 26
SELECT DAY(TIME('1 02:00:00')), DAY(TIME('26:00:00'));
DAY(TIME('1 02:00:00')) DAY(TIME('26:00:00'))
0 0
SELECT EXTRACT(HOUR FROM '1 02:00:00'), EXTRACT(HOUR FROM '26:00:00');
EXTRACT(HOUR FROM '1 02:00:00') EXTRACT(HOUR FROM '26:00:00')
2 2
SELECT EXTRACT(HOUR FROM TIME'1 02:00:00'), EXTRACT(HOUR FROM TIME'26:00:00');
EXTRACT(HOUR FROM TIME'1 02:00:00') EXTRACT(HOUR FROM TIME'26:00:00')
2 2
SELECT EXTRACT(HOUR FROM TIME('1 02:00:00')), EXTRACT(HOUR FROM TIME('26:00:00'));
EXTRACT(HOUR FROM TIME('1 02:00:00')) EXTRACT(HOUR FROM TIME('26:00:00'))
2 2
SELECT EXTRACT(DAY FROM TIME('1 02:00:00')), EXTRACT(DAY FROM TIME('26:00:00'));
EXTRACT(DAY FROM TIME('1 02:00:00')) EXTRACT(DAY FROM TIME('26:00:00'))
1 1
...@@ -1405,3 +1405,15 @@ DROP TABLE t1; ...@@ -1405,3 +1405,15 @@ DROP TABLE t1;
--echo # --echo #
SELECT MAKETIME(0, 0, -0.1); SELECT MAKETIME(0, 0, -0.1);
--echo #
--echo # MDEV-4857 Wrong result of HOUR('1 00:00:00')
--echo #
SELECT HOUR('1 02:00:00'), HOUR('26:00:00');
SELECT HOUR(TIME'1 02:00:00'), HOUR(TIME'26:00:00');
SELECT HOUR(TIME('1 02:00:00')), HOUR(TIME('26:00:00'));
SELECT DAY(TIME('1 02:00:00')), DAY(TIME('26:00:00'));
SELECT EXTRACT(HOUR FROM '1 02:00:00'), EXTRACT(HOUR FROM '26:00:00');
SELECT EXTRACT(HOUR FROM TIME'1 02:00:00'), EXTRACT(HOUR FROM TIME'26:00:00');
SELECT EXTRACT(HOUR FROM TIME('1 02:00:00')), EXTRACT(HOUR FROM TIME('26:00:00'));
SELECT EXTRACT(DAY FROM TIME('1 02:00:00')), EXTRACT(DAY FROM TIME('26:00:00'));
...@@ -648,8 +648,8 @@ str_to_time(const char *str, uint length, MYSQL_TIME *l_time, ...@@ -648,8 +648,8 @@ str_to_time(const char *str, uint length, MYSQL_TIME *l_time,
l_time->year= 0; /* For protocol::store_time */ l_time->year= 0; /* For protocol::store_time */
l_time->month= 0; l_time->month= 0;
l_time->day= date[0]; l_time->day= 0;
l_time->hour= date[1]; l_time->hour= date[1] + date[0] * 24; /* Mix days and hours */
l_time->minute= date[2]; l_time->minute= date[2];
l_time->second= date[3]; l_time->second= date[3];
l_time->second_part= date[4]; l_time->second_part= date[4];
......
...@@ -158,7 +158,9 @@ class Item_func :public Item_result_field ...@@ -158,7 +158,9 @@ class Item_func :public Item_result_field
} }
inline bool get_arg0_time(MYSQL_TIME *ltime) inline bool get_arg0_time(MYSQL_TIME *ltime)
{ {
return (null_value=args[0]->get_time(ltime)); null_value= args[0]->get_time(ltime);
DBUG_ASSERT(ltime->time_type != MYSQL_TIMESTAMP_TIME || ltime->day == 0);
return null_value;
} }
bool is_null() { bool is_null() {
update_null_value(); update_null_value();
......
...@@ -2033,6 +2033,10 @@ longlong Item_extract::val_int() ...@@ -2033,6 +2033,10 @@ longlong Item_extract::val_int()
return 0; return 0;
neg= ltime.neg ? -1 : 1; neg= ltime.neg ? -1 : 1;
DBUG_ASSERT(ltime.time_type != MYSQL_TIMESTAMP_TIME || ltime.day == 0);
if (ltime.time_type == MYSQL_TIMESTAMP_TIME)
time_to_daytime_interval(&ltime);
switch (int_type) { switch (int_type) {
case INTERVAL_YEAR: return ltime.year; case INTERVAL_YEAR: return ltime.year;
case INTERVAL_YEAR_MONTH: return ltime.year*100L+ltime.month; case INTERVAL_YEAR_MONTH: return ltime.year*100L+ltime.month;
......
...@@ -2527,6 +2527,7 @@ bool str_to_time_with_warn(const char *str,uint length,MYSQL_TIME *l_time, ...@@ -2527,6 +2527,7 @@ bool str_to_time_with_warn(const char *str,uint length,MYSQL_TIME *l_time,
ulong fuzzydate); ulong fuzzydate);
timestamp_type str_to_datetime_with_warn(const char *str, uint length, timestamp_type str_to_datetime_with_warn(const char *str, uint length,
MYSQL_TIME *l_time, ulong flags); MYSQL_TIME *l_time, ulong flags);
void time_to_daytime_interval(MYSQL_TIME *l_time);
void localtime_to_TIME(MYSQL_TIME *to, struct tm *from); void localtime_to_TIME(MYSQL_TIME *to, struct tm *from);
void calc_time_from_sec(MYSQL_TIME *to, long seconds, long microseconds); void calc_time_from_sec(MYSQL_TIME *to, long seconds, long microseconds);
......
...@@ -1045,3 +1045,22 @@ int my_time_compare(MYSQL_TIME *a, MYSQL_TIME *b) ...@@ -1045,3 +1045,22 @@ int my_time_compare(MYSQL_TIME *a, MYSQL_TIME *b)
return 0; return 0;
} }
/*
Convert a TIME value to DAY-TIME interval, e.g. for extraction:
EXTRACT(DAY FROM x), EXTRACT(HOUR FROM x), etc.
Moves full days from ltime->hour to ltime->day.
Note, time_type is set to MYSQL_TIMESTAMP_NONE, to make sure that
the structure is not used for anything else other than extraction:
non-extraction TIME functions expect zero day value!
*/
void time_to_daytime_interval(MYSQL_TIME *ltime)
{
DBUG_ASSERT(ltime->time_type == MYSQL_TIMESTAMP_TIME);
DBUG_ASSERT(ltime->year == 0);
DBUG_ASSERT(ltime->month == 0);
DBUG_ASSERT(ltime->day == 0);
ltime->day= ltime->hour / 24;
ltime->hour%= 24;
ltime->time_type= MYSQL_TIMESTAMP_NONE;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment