summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mnogosearch.org>2013-12-02 15:50:35 +0400
committerAlexander Barkov <bar@mnogosearch.org>2013-12-02 15:50:35 +0400
commit5a8bd446adf3d1a53b8bc4dd88b3830bf0270865 (patch)
tree1c5fa5001e8d82bf01b4bbc2e7c5703499342656
parent87355a453d4661a75f3b451b30b1867910915675 (diff)
parentb97b9536c71b3ad5ef521a1f21c527057a0a01c6 (diff)
downloadmariadb-git-5a8bd446adf3d1a53b8bc4dd88b3830bf0270865.tar.gz
Merge 5.3->5.5
pending merges: Alexander Barkov 2013-12-02 MDEV-4857 Wrong result of HOUR('1 00:00:00')
-rw-r--r--mysql-test/r/func_time.result31
-rw-r--r--mysql-test/t/func_time.test12
-rw-r--r--sql-common/my_time.c4
-rw-r--r--sql/item_func.h4
-rw-r--r--sql/item_timefunc.cc4
-rw-r--r--sql/sql_time.cc19
-rw-r--r--sql/sql_time.h1
7 files changed, 70 insertions, 5 deletions
diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result
index e8d2e0056e9..670754c623e 100644
--- a/mysql-test/r/func_time.result
+++ b/mysql-test/r/func_time.result
@@ -365,7 +365,7 @@ extract(DAY_MINUTE FROM "02 10:11:12")
21011
select extract(DAY_SECOND FROM "225 10:11:12");
extract(DAY_SECOND FROM "225 10:11:12")
-8385959
+34225959
Warnings:
Warning 1292 Truncated incorrect time value: '225 10:11:12'
select extract(HOUR FROM "1999-01-02 10:11:12");
@@ -1025,7 +1025,7 @@ Note 1105 Cast to unsigned converted negative integer to it's positive complemen
Warning 1292 Truncated incorrect time value: '18446744073709551615:00:00'
SELECT EXTRACT(HOUR FROM '100000:02:03');
EXTRACT(HOUR FROM '100000:02:03')
-838
+22
Warnings:
Warning 1292 Truncated incorrect time value: '100000:02:03'
CREATE TABLE t1(f1 TIME);
@@ -2347,3 +2347,30 @@ DROP TABLE t1;
SELECT MAKETIME(0, 0, -0.1);
MAKETIME(0, 0, -0.1)
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
diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test
index c17edbf676c..d1b26cb478d 100644
--- a/mysql-test/t/func_time.test
+++ b/mysql-test/t/func_time.test
@@ -1435,3 +1435,15 @@ DROP TABLE t1;
--echo #
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'));
diff --git a/sql-common/my_time.c b/sql-common/my_time.c
index 69cd9458135..b91028cc1ea 100644
--- a/sql-common/my_time.c
+++ b/sql-common/my_time.c
@@ -645,8 +645,8 @@ fractional:
l_time->year= 0; /* For protocol::store_time */
l_time->month= 0;
- l_time->day= date[0];
- l_time->hour= date[1];
+ l_time->day= 0;
+ l_time->hour= date[1] + date[0] * 24; /* Mix days and hours */
l_time->minute= date[2];
l_time->second= date[3];
l_time->second_part= date[4];
diff --git a/sql/item_func.h b/sql/item_func.h
index 309b25f1933..bbf7643eaa0 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -159,7 +159,9 @@ public:
Item **item, uint nitems);
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() {
update_null_value();
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index ab536e58f1c..4b10675c48d 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -2142,6 +2142,10 @@ longlong Item_extract::val_int()
return 0;
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) {
case INTERVAL_YEAR: return ltime.year;
case INTERVAL_YEAR_MONTH: return ltime.year*100L+ltime.month;
diff --git a/sql/sql_time.cc b/sql/sql_time.cc
index dab8a907678..2c89237c2d2 100644
--- a/sql/sql_time.cc
+++ b/sql/sql_time.cc
@@ -1085,3 +1085,22 @@ int my_time_compare(MYSQL_TIME *a, MYSQL_TIME *b)
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;
+}
diff --git a/sql/sql_time.h b/sql/sql_time.h
index f8b1e950b14..ab8f0e0b962 100644
--- a/sql/sql_time.h
+++ b/sql/sql_time.h
@@ -33,6 +33,7 @@ typedef struct st_known_date_time_format KNOWN_DATE_TIME_FORMAT;
ulong convert_period_to_month(ulong period);
ulong convert_month_to_period(ulong month);
+void time_to_daytime_interval(MYSQL_TIME *l_time);
bool get_date_from_daynr(long daynr,uint *year, uint *month, uint *day);
my_time_t TIME_to_timestamp(THD *thd, const MYSQL_TIME *t, uint *error_code);
bool str_to_time_with_warn(CHARSET_INFO *cs, const char *str, uint length,