From fa1641e1f3c68e240d79099ae9a3a1346997e4d4 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 10 Aug 2006 15:37:24 +0200 Subject: [PATCH] Bug#19844: time_format in Union truncates values time_format() claimed %H and %k would return at most two digits (hours 0-23), but this coincided neither with actual behaviour nor with docs. this is not visible in simple queries; forcing a temp-table is probably the easiest way to see this. adjusted the return-length appropriately; the alternative would be to adjust the docs to say that behaviour for > 99 hours is undefined. --- Bug#19844: time_format in Union truncates values time_format() claimed %H and %k would return at most two digits (hours 0-23), but this coincided neither with actual behaviour nor with docs. this is not visible in simple queries; forcing a temp-table is probably the easiest way to see this. adjusted the return-length appropriately; the alternative would be to adjust the docs to say that behaviour for > 99 hours is undefined. mysql-test/r/func_time.result: Bug#19844: time_format in Union truncates values show time_format() handles %H and %k correctly four > 99 hours mysql-test/t/func_time.test: Bug#19844: time_format in Union truncates values show time_format() handles %H and %k correctly four > 99 hours sql/item_timefunc.cc: Bug#19844: time_format in Union truncates values unbreak promises we make about field-length of %H and %k in time_format() so they coincide with the actual range rather than just 0..23. the docs say we must operate outside that range, so we'd better do it right. --- Bug#19844: time_format in Union truncates values unbreak promises we make about field-length of %H and %k in time_format() so they coincide with the actual range rather than just 0..23. the docs say we must operate outside that range, so we'd better do it right. One digit values are padded to two digits with %H, "longer" values are handled correctly up to seven digits including any sign. (clarified comments as per jimw's suggestion.) --- mysql-test/r/func_time.result | 21 +++++++++++++++++++++ mysql-test/t/func_time.test | 20 +++++++++++++++++++- sql/item_timefunc.cc | 6 ++++-- 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index d8ba606a558..47a0f83802c 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -695,3 +695,24 @@ t1 CREATE TABLE `t1` ( `from_unixtime(1) + 0` double(23,6) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; +(select time_format(timediff(now(), DATE_SUB(now(),INTERVAL 5 DAY)),'%H') As H) +union +(select time_format(timediff(now(), DATE_SUB(now(),INTERVAL 5 DAY)),'%H') As H); +H +120 +(select time_format(timediff(now(), DATE_SUB(now(),INTERVAL 5 DAY)),'%k') As H) +union +(select time_format(timediff(now(), DATE_SUB(now(),INTERVAL 5 DAY)),'%k') As H); +H +120 +(select time_format(timediff(now(), DATE_SUB(now(),INTERVAL 5 HOUR)),'%H') As H) +union +(select time_format(timediff(now(), DATE_SUB(now(),INTERVAL 5 HOUR)),'%H') As H); +H +05 +(select time_format(timediff(now(), DATE_SUB(now(),INTERVAL 5 HOUR)),'%k') As H) +union +(select time_format(timediff(now(), DATE_SUB(now(),INTERVAL 5 HOUR)),'%k') As H); +H +5 +End of 4.1 tests diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index b8647a281d4..472f3d81d2b 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -368,4 +368,22 @@ create table t1 select now() - now(), curtime() - curtime(), show create table t1; drop table t1; -# End of 4.1 tests +# +# Bug #19844 time_format in Union truncates values +# + +(select time_format(timediff(now(), DATE_SUB(now(),INTERVAL 5 DAY)),'%H') As H) +union +(select time_format(timediff(now(), DATE_SUB(now(),INTERVAL 5 DAY)),'%H') As H); +(select time_format(timediff(now(), DATE_SUB(now(),INTERVAL 5 DAY)),'%k') As H) +union +(select time_format(timediff(now(), DATE_SUB(now(),INTERVAL 5 DAY)),'%k') As H); +(select time_format(timediff(now(), DATE_SUB(now(),INTERVAL 5 HOUR)),'%H') As H) +union +(select time_format(timediff(now(), DATE_SUB(now(),INTERVAL 5 HOUR)),'%H') As H); + +(select time_format(timediff(now(), DATE_SUB(now(),INTERVAL 5 HOUR)),'%k') As H) +union +(select time_format(timediff(now(), DATE_SUB(now(),INTERVAL 5 HOUR)),'%k') As H); + +--echo End of 4.1 tests diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 44d9b422263..febc92e34f6 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -1600,14 +1600,12 @@ uint Item_func_date_format::format_length(const String *format) case 'u': /* week (00..52), where week starts with Monday */ case 'V': /* week 1..53 used with 'x' */ case 'v': /* week 1..53 used with 'x', where week starts with Monday */ - case 'H': /* hour (00..23) */ case 'y': /* year, numeric, 2 digits */ case 'm': /* month, numeric */ case 'd': /* day (of the month), numeric */ case 'h': /* hour (01..12) */ case 'I': /* --||-- */ case 'i': /* minutes, numeric */ - case 'k': /* hour ( 0..23) */ case 'l': /* hour ( 1..12) */ case 'p': /* locale's AM or PM */ case 'S': /* second (00..61) */ @@ -1616,6 +1614,10 @@ uint Item_func_date_format::format_length(const String *format) case 'e': /* day (0..31) */ size += 2; break; + case 'k': /* hour ( 0..23) */ + case 'H': /* hour (00..23; value > 23 OK, padding always 2-digit) */ + size += 7; /* docs allow > 23, range depends on sizeof(unsigned int) */ + break; case 'r': /* time, 12-hour (hh:mm:ss [AP]M) */ size += 11; break;