diff options
author | Alexander Barkov <bar@mariadb.com> | 2018-10-20 19:51:14 +0400 |
---|---|---|
committer | Alexander Barkov <bar@mariadb.com> | 2018-10-20 19:51:14 +0400 |
commit | f6a20205148853f4cd352a21de3b77f2372ad50d (patch) | |
tree | db68549ebba514202189fcd970ebf0c4333feb73 | |
parent | 0e5a4ac2532c64a545796c787354dc41d61d0e62 (diff) | |
download | mariadb-git-f6a20205148853f4cd352a21de3b77f2372ad50d.tar.gz |
MDEV-17477 Wrong result for TIME('-2001-01-01 10:20:30') and numerous other str-to-time conversion problems
MDEV-17478 Wrong result for TIME('+100:20:30')
-rw-r--r-- | mysql-test/main/func_time.result | 98 | ||||
-rw-r--r-- | mysql-test/main/func_time.test | 38 | ||||
-rw-r--r-- | mysql-test/main/query_cache.result | 12 | ||||
-rw-r--r-- | mysql-test/main/str_to_datetime_457.result | 2 | ||||
-rw-r--r-- | mysql-test/suite/funcs_1/r/innodb_func_view.result | 36 | ||||
-rw-r--r-- | mysql-test/suite/funcs_1/r/memory_func_view.result | 36 | ||||
-rw-r--r-- | mysql-test/suite/funcs_1/r/myisam_func_view.result | 36 | ||||
-rw-r--r-- | sql-common/my_time.c | 303 |
8 files changed, 400 insertions, 161 deletions
diff --git a/mysql-test/main/func_time.result b/mysql-test/main/func_time.result index 1a1eeed5639..a6def9e70b0 100644 --- a/mysql-test/main/func_time.result +++ b/mysql-test/main/func_time.result @@ -6145,3 +6145,101 @@ t2 CREATE TABLE `t2` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DROP TABLE t2; DROP TABLE t1; +# +# MDEV-17478 Wrong result for TIME('+100:20:30') +# +SELECT TIME('+100:20:30'); +TIME('+100:20:30') +100:20:30 +# +# MDEV-17477 Wrong result for TIME('-2001-01-01 10:20:30') +# +SELECT TIME('-2001-01-01 10:20:30'); +TIME('-2001-01-01 10:20:30') +NULL +Warnings: +Warning 1292 Truncated incorrect time value: '-2001-01-01 10:20:30' +SELECT TIME('2001-01-01') AS c1, TIME('2001-01-01 ') AS c2; +c1 c2 +00:20:01 00:20:01 +Warnings: +Warning 1292 Truncated incorrect time value: '2001-01-01' +Warning 1292 Truncated incorrect time value: '2001-01-01 ' +SELECT TIME('0001:01:01 '), TIME('0001:01:01 '); +TIME('0001:01:01 ') TIME('0001:01:01 ') +01:01:01 01:01:01 +SELECT TIME('1 2'), TIME('1 2 '); +TIME('1 2') TIME('1 2 ') +00:00:01 00:00:01 +Warnings: +Warning 1292 Truncated incorrect time value: '1 2' +Warning 1292 Truncated incorrect time value: '1 2 ' +SELECT TIME('2001-01-01T'), TIME('2001-01-01T '); +TIME('2001-01-01T') TIME('2001-01-01T ') +00:00:00 00:00:00 +SELECT TIME('901-01-01T1'), TIME('901-01-01T10'); +TIME('901-01-01T1') TIME('901-01-01T10') +01:00:00 10:00:00 +SELECT TIME('091-01-01T1'), TIME('091-01-01T10'); +TIME('091-01-01T1') TIME('091-01-01T10') +01:00:00 10:00:00 +SELECT TIME('0001:01:01x'), TIME('0001:01:01xx'); +TIME('0001:01:01x') TIME('0001:01:01xx') +01:01:01 01:01:01 +Warnings: +Warning 1292 Truncated incorrect time value: '0001:01:01x' +Warning 1292 Truncated incorrect time value: '0001:01:01xx' +SELECT TIME('0001:01:01.'), TIME('0001:01:01..'); +TIME('0001:01:01.') TIME('0001:01:01..') +01:01:01 01:01:01 +Warnings: +Warning 1292 Truncated incorrect time value: '0001:01:01..' +SELECT TIME('0001:01:01-'), TIME('0001:01:01--'); +TIME('0001:01:01-') TIME('0001:01:01--') +01:01:01 01:01:01 +Warnings: +Warning 1292 Truncated incorrect time value: '0001:01:01-' +Warning 1292 Truncated incorrect time value: '0001:01:01--' +SELECT TIME('0001:01:01-'), TIME('0001:01:01--'); +TIME('0001:01:01-') TIME('0001:01:01--') +01:01:01 01:01:01 +Warnings: +Warning 1292 Truncated incorrect time value: '0001:01:01-' +Warning 1292 Truncated incorrect time value: '0001:01:01--' +SELECT TIME('-xxx'), TIME('-xxxxxxxxxxxxxxxxxxxx'); +TIME('-xxx') TIME('-xxxxxxxxxxxxxxxxxxxx') +NULL NULL +Warnings: +Warning 1292 Truncated incorrect time value: '-xxx' +Warning 1292 Truncated incorrect time value: '-xxxxxxxxxxxxxxxxxxxx' +SELECT TIME('- '), TIME('- '); +TIME('- ') TIME('- ') +NULL NULL +Warnings: +Warning 1292 Truncated incorrect time value: '- ' +Warning 1292 Truncated incorrect time value: '- ' +SELECT TIME('-'), TIME('-'); +TIME('-') TIME('-') +NULL NULL +Warnings: +Warning 1292 Truncated incorrect time value: '-' +Warning 1292 Truncated incorrect time value: '-' +SELECT TIME('1-1-1 1:1:1'), TIME('1-1-1 1:1:1.0'); +TIME('1-1-1 1:1:1') TIME('1-1-1 1:1:1.0') +01:01:01 01:01:01.0 +SELECT TIME('1-1-1 1:2:3'), TIME('1-1-1 1:2:3.0'); +TIME('1-1-1 1:2:3') TIME('1-1-1 1:2:3.0') +01:02:03 01:02:03.0 +SELECT +CAST('20050326112233 garbage' as datetime), +CAST('20050326 garbage' as date), +CAST('50326 garbage' as time); +CAST('20050326112233 garbage' as datetime) CAST('20050326 garbage' as date) CAST('50326 garbage' as time) +2005-03-26 11:22:33 2005-03-26 05:03:26 +Warnings: +Warning 1292 Truncated incorrect datetime value: '20050326112233 garbage' +Warning 1292 Truncated incorrect date value: '20050326 garbage' +Warning 1292 Truncated incorrect time value: '50326 garbage' +SELECT TIME('- 01:00:00'), TIME('- 1 01:00:00'); +TIME('- 01:00:00') TIME('- 1 01:00:00') +-01:00:00 -25:00:00 diff --git a/mysql-test/main/func_time.test b/mysql-test/main/func_time.test index 8fc0977a496..4c9315629f1 100644 --- a/mysql-test/main/func_time.test +++ b/mysql-test/main/func_time.test @@ -3056,3 +3056,41 @@ FROM t1; SHOW CREATE TABLE t2; DROP TABLE t2; DROP TABLE t1; + + +--echo # +--echo # MDEV-17478 Wrong result for TIME('+100:20:30') +--echo # + +SELECT TIME('+100:20:30'); + +--echo # +--echo # MDEV-17477 Wrong result for TIME('-2001-01-01 10:20:30') +--echo # + +SELECT TIME('-2001-01-01 10:20:30'); +SELECT TIME('2001-01-01') AS c1, TIME('2001-01-01 ') AS c2; +SELECT TIME('0001:01:01 '), TIME('0001:01:01 '); +SELECT TIME('1 2'), TIME('1 2 '); + +SELECT TIME('2001-01-01T'), TIME('2001-01-01T '); +SELECT TIME('901-01-01T1'), TIME('901-01-01T10'); +SELECT TIME('091-01-01T1'), TIME('091-01-01T10'); + +SELECT TIME('0001:01:01x'), TIME('0001:01:01xx'); +SELECT TIME('0001:01:01.'), TIME('0001:01:01..'); +SELECT TIME('0001:01:01-'), TIME('0001:01:01--'); +SELECT TIME('0001:01:01-'), TIME('0001:01:01--'); + +SELECT TIME('-xxx'), TIME('-xxxxxxxxxxxxxxxxxxxx'); +SELECT TIME('- '), TIME('- '); +SELECT TIME('-'), TIME('-'); +SELECT TIME('1-1-1 1:1:1'), TIME('1-1-1 1:1:1.0'); +SELECT TIME('1-1-1 1:2:3'), TIME('1-1-1 1:2:3.0'); + +SELECT + CAST('20050326112233 garbage' as datetime), + CAST('20050326 garbage' as date), + CAST('50326 garbage' as time); + +SELECT TIME('- 01:00:00'), TIME('- 1 01:00:00'); diff --git a/mysql-test/main/query_cache.result b/mysql-test/main/query_cache.result index e1123b1cb8b..f5d8b5eb461 100644 --- a/mysql-test/main/query_cache.result +++ b/mysql-test/main/query_cache.result @@ -967,19 +967,19 @@ INSERT INTO t1 VALUES ('20050326'); INSERT INTO t1 VALUES ('20050325'); SELECT COUNT(*) FROM t1 WHERE date BETWEEN '20050326' AND '20050327 invalid'; COUNT(*) -0 +1 Warnings: -Warning 1292 Incorrect datetime value: '20050327 invalid' +Warning 1292 Truncated incorrect date value: '20050327 invalid' SELECT COUNT(*) FROM t1 WHERE date BETWEEN '20050326' AND '20050328 invalid'; COUNT(*) -0 +1 Warnings: -Warning 1292 Incorrect datetime value: '20050328 invalid' +Warning 1292 Truncated incorrect date value: '20050328 invalid' SELECT COUNT(*) FROM t1 WHERE date BETWEEN '20050326' AND '20050327 invalid'; COUNT(*) -0 +1 Warnings: -Warning 1292 Incorrect datetime value: '20050327 invalid' +Warning 1292 Truncated incorrect date value: '20050327 invalid' show status like "Qcache_queries_in_cache"; Variable_name Value Qcache_queries_in_cache 0 diff --git a/mysql-test/main/str_to_datetime_457.result b/mysql-test/main/str_to_datetime_457.result index 4fd0d00691c..41a8ee9bf90 100644 --- a/mysql-test/main/str_to_datetime_457.result +++ b/mysql-test/main/str_to_datetime_457.result @@ -1,6 +1,6 @@ select cast('01:02:03 ' as time), cast('01:02:03 ' as time); cast('01:02:03 ' as time) cast('01:02:03 ' as time) -01:02:03 00:00:00 +01:02:03 01:02:03 select cast('2002-011-012' as date), cast('2002.11.12' as date), cast('2002.011.012' as date); cast('2002-011-012' as date) cast('2002.11.12' as date) cast('2002.011.012' as date) 2002-11-12 2002-11-12 2002-11-12 diff --git a/mysql-test/suite/funcs_1/r/innodb_func_view.result b/mysql-test/suite/funcs_1/r/innodb_func_view.result index 481787e4eaa..c956ab1955e 100644 --- a/mysql-test/suite/funcs_1/r/innodb_func_view.result +++ b/mysql-test/suite/funcs_1/r/innodb_func_view.result @@ -3778,8 +3778,8 @@ WHERE select_id = 51 OR select_id IS NULL order by id; CAST(my_varbinary_1000 AS TIME) my_varbinary_1000 id NULL NULL 1 NULL 2 -00:00:00 <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3 --00:00:00 ---äÖüß@µ*$-- 4 +NULL <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3 +NULL ---äÖüß@µ*$-- 4 -00:00:01 -1 5 41:58:00 1 17:58 23 Warnings: @@ -3795,8 +3795,8 @@ WHERE select_id = 51 OR select_id IS NULL) order by id; CAST(my_varbinary_1000 AS TIME) my_varbinary_1000 id NULL NULL 1 NULL 2 -00:00:00 <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3 --00:00:00 ---äÖüß@µ*$-- 4 +NULL <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3 +NULL ---äÖüß@µ*$-- 4 -00:00:01 -1 5 41:58:00 1 17:58 23 Warnings: @@ -3813,9 +3813,9 @@ my_binary_30, id FROM t1_values WHERE select_id = 50 OR select_id IS NULL order by id; CAST(my_binary_30 AS TIME) my_binary_30 id NULL NULL 1 -00:00:00 2 -00:00:00 <--------30 characters-------> 3 --00:00:00 ---äÖüß@µ*$-- 4 +NULL 2 +NULL <--------30 characters-------> 3 +NULL ---äÖüß@µ*$-- 4 -00:00:01 -1 5 41:58:00 1 17:58 22 Warnings: @@ -3832,9 +3832,9 @@ WHERE v1.id IN (SELECT id FROM t1_values WHERE select_id = 50 OR select_id IS NULL) order by id; CAST(my_binary_30 AS TIME) my_binary_30 id NULL NULL 1 -00:00:00 -00:00:00 <--------30 characters-------> 3 --00:00:00 ---äÖüß@µ*$-- +NULL +NULL <--------30 characters-------> 3 +NULL ---äÖüß@µ*$-- -00:00:01 -1 41:58:00 1 17:58 Warnings: @@ -3854,8 +3854,8 @@ WHERE select_id = 49 OR select_id IS NULL order by id; CAST(my_varchar_1000 AS TIME) my_varchar_1000 id NULL NULL 1 NULL 2 -00:00:00 <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3 --00:00:00 ---äÖüß@µ*$-- 4 +NULL <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3 +NULL ---äÖüß@µ*$-- 4 -00:00:01 -1 5 41:58:00 1 17:58 21 Warnings: @@ -3871,8 +3871,8 @@ WHERE select_id = 49 OR select_id IS NULL) order by id; CAST(my_varchar_1000 AS TIME) my_varchar_1000 id NULL NULL 1 NULL 2 -00:00:00 <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3 --00:00:00 ---äÖüß@µ*$-- 4 +NULL <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3 +NULL ---äÖüß@µ*$-- 4 -00:00:01 -1 5 41:58:00 1 17:58 21 Warnings: @@ -3890,8 +3890,8 @@ WHERE select_id = 48 OR select_id IS NULL order by id; CAST(my_char_30 AS TIME) my_char_30 id NULL NULL 1 NULL 2 -00:00:00 <--------30 characters-------> 3 --00:00:00 ---äÖüß@µ*$-- 4 +NULL <--------30 characters-------> 3 +NULL ---äÖüß@µ*$-- 4 -00:00:01 -1 5 41:58:00 1 17:58 20 Warnings: @@ -3907,8 +3907,8 @@ WHERE select_id = 48 OR select_id IS NULL) order by id; CAST(my_char_30 AS TIME) my_char_30 id NULL NULL 1 NULL 2 -00:00:00 <--------30 characters-------> 3 --00:00:00 ---äÖüß@µ*$-- 4 +NULL <--------30 characters-------> 3 +NULL ---äÖüß@µ*$-- 4 -00:00:01 -1 5 41:58:00 1 17:58 20 Warnings: diff --git a/mysql-test/suite/funcs_1/r/memory_func_view.result b/mysql-test/suite/funcs_1/r/memory_func_view.result index 3a75e4abac5..cd306b6b379 100644 --- a/mysql-test/suite/funcs_1/r/memory_func_view.result +++ b/mysql-test/suite/funcs_1/r/memory_func_view.result @@ -3779,8 +3779,8 @@ WHERE select_id = 51 OR select_id IS NULL order by id; CAST(my_varbinary_1000 AS TIME) my_varbinary_1000 id NULL NULL 1 NULL 2 -00:00:00 <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3 --00:00:00 ---äÖüß@µ*$-- 4 +NULL <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3 +NULL ---äÖüß@µ*$-- 4 -00:00:01 -1 5 41:58:00 1 17:58 23 Warnings: @@ -3796,8 +3796,8 @@ WHERE select_id = 51 OR select_id IS NULL) order by id; CAST(my_varbinary_1000 AS TIME) my_varbinary_1000 id NULL NULL 1 NULL 2 -00:00:00 <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3 --00:00:00 ---äÖüß@µ*$-- 4 +NULL <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3 +NULL ---äÖüß@µ*$-- 4 -00:00:01 -1 5 41:58:00 1 17:58 23 Warnings: @@ -3814,9 +3814,9 @@ my_binary_30, id FROM t1_values WHERE select_id = 50 OR select_id IS NULL order by id; CAST(my_binary_30 AS TIME) my_binary_30 id NULL NULL 1 -00:00:00 2 -00:00:00 <--------30 characters-------> 3 --00:00:00 ---äÖüß@µ*$-- 4 +NULL 2 +NULL <--------30 characters-------> 3 +NULL ---äÖüß@µ*$-- 4 -00:00:01 -1 5 41:58:00 1 17:58 22 Warnings: @@ -3833,9 +3833,9 @@ WHERE v1.id IN (SELECT id FROM t1_values WHERE select_id = 50 OR select_id IS NULL) order by id; CAST(my_binary_30 AS TIME) my_binary_30 id NULL NULL 1 -00:00:00 -00:00:00 <--------30 characters-------> 3 --00:00:00 ---äÖüß@µ*$-- +NULL +NULL <--------30 characters-------> 3 +NULL ---äÖüß@µ*$-- -00:00:01 -1 41:58:00 1 17:58 Warnings: @@ -3855,8 +3855,8 @@ WHERE select_id = 49 OR select_id IS NULL order by id; CAST(my_varchar_1000 AS TIME) my_varchar_1000 id NULL NULL 1 NULL 2 -00:00:00 <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3 --00:00:00 ---äÖüß@µ*$-- 4 +NULL <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3 +NULL ---äÖüß@µ*$-- 4 -00:00:01 -1 5 41:58:00 1 17:58 21 Warnings: @@ -3872,8 +3872,8 @@ WHERE select_id = 49 OR select_id IS NULL) order by id; CAST(my_varchar_1000 AS TIME) my_varchar_1000 id NULL NULL 1 NULL 2 -00:00:00 <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3 --00:00:00 ---äÖüß@µ*$-- 4 +NULL <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3 +NULL ---äÖüß@µ*$-- 4 -00:00:01 -1 5 41:58:00 1 17:58 21 Warnings: @@ -3891,8 +3891,8 @@ WHERE select_id = 48 OR select_id IS NULL order by id; CAST(my_char_30 AS TIME) my_char_30 id NULL NULL 1 NULL 2 -00:00:00 <--------30 characters-------> 3 --00:00:00 ---äÖüß@µ*$-- 4 +NULL <--------30 characters-------> 3 +NULL ---äÖüß@µ*$-- 4 -00:00:01 -1 5 41:58:00 1 17:58 20 Warnings: @@ -3908,8 +3908,8 @@ WHERE select_id = 48 OR select_id IS NULL) order by id; CAST(my_char_30 AS TIME) my_char_30 id NULL NULL 1 NULL 2 -00:00:00 <--------30 characters-------> 3 --00:00:00 ---äÖüß@µ*$-- 4 +NULL <--------30 characters-------> 3 +NULL ---äÖüß@µ*$-- 4 -00:00:01 -1 5 41:58:00 1 17:58 20 Warnings: diff --git a/mysql-test/suite/funcs_1/r/myisam_func_view.result b/mysql-test/suite/funcs_1/r/myisam_func_view.result index 3a75e4abac5..cd306b6b379 100644 --- a/mysql-test/suite/funcs_1/r/myisam_func_view.result +++ b/mysql-test/suite/funcs_1/r/myisam_func_view.result @@ -3779,8 +3779,8 @@ WHERE select_id = 51 OR select_id IS NULL order by id; CAST(my_varbinary_1000 AS TIME) my_varbinary_1000 id NULL NULL 1 NULL 2 -00:00:00 <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3 --00:00:00 ---äÖüß@µ*$-- 4 +NULL <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3 +NULL ---äÖüß@µ*$-- 4 -00:00:01 -1 5 41:58:00 1 17:58 23 Warnings: @@ -3796,8 +3796,8 @@ WHERE select_id = 51 OR select_id IS NULL) order by id; CAST(my_varbinary_1000 AS TIME) my_varbinary_1000 id NULL NULL 1 NULL 2 -00:00:00 <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3 --00:00:00 ---äÖüß@µ*$-- 4 +NULL <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3 +NULL ---äÖüß@µ*$-- 4 -00:00:01 -1 5 41:58:00 1 17:58 23 Warnings: @@ -3814,9 +3814,9 @@ my_binary_30, id FROM t1_values WHERE select_id = 50 OR select_id IS NULL order by id; CAST(my_binary_30 AS TIME) my_binary_30 id NULL NULL 1 -00:00:00 2 -00:00:00 <--------30 characters-------> 3 --00:00:00 ---äÖüß@µ*$-- 4 +NULL 2 +NULL <--------30 characters-------> 3 +NULL ---äÖüß@µ*$-- 4 -00:00:01 -1 5 41:58:00 1 17:58 22 Warnings: @@ -3833,9 +3833,9 @@ WHERE v1.id IN (SELECT id FROM t1_values WHERE select_id = 50 OR select_id IS NULL) order by id; CAST(my_binary_30 AS TIME) my_binary_30 id NULL NULL 1 -00:00:00 -00:00:00 <--------30 characters-------> 3 --00:00:00 ---äÖüß@µ*$-- +NULL +NULL <--------30 characters-------> 3 +NULL ---äÖüß@µ*$-- -00:00:01 -1 41:58:00 1 17:58 Warnings: @@ -3855,8 +3855,8 @@ WHERE select_id = 49 OR select_id IS NULL order by id; CAST(my_varchar_1000 AS TIME) my_varchar_1000 id NULL NULL 1 NULL 2 -00:00:00 <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3 --00:00:00 ---äÖüß@µ*$-- 4 +NULL <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3 +NULL ---äÖüß@µ*$-- 4 -00:00:01 -1 5 41:58:00 1 17:58 21 Warnings: @@ -3872,8 +3872,8 @@ WHERE select_id = 49 OR select_id IS NULL) order by id; CAST(my_varchar_1000 AS TIME) my_varchar_1000 id NULL NULL 1 NULL 2 -00:00:00 <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3 --00:00:00 ---äÖüß@µ*$-- 4 +NULL <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3 +NULL ---äÖüß@µ*$-- 4 -00:00:01 -1 5 41:58:00 1 17:58 21 Warnings: @@ -3891,8 +3891,8 @@ WHERE select_id = 48 OR select_id IS NULL order by id; CAST(my_char_30 AS TIME) my_char_30 id NULL NULL 1 NULL 2 -00:00:00 <--------30 characters-------> 3 --00:00:00 ---äÖüß@µ*$-- 4 +NULL <--------30 characters-------> 3 +NULL ---äÖüß@µ*$-- 4 -00:00:01 -1 5 41:58:00 1 17:58 20 Warnings: @@ -3908,8 +3908,8 @@ WHERE select_id = 48 OR select_id IS NULL) order by id; CAST(my_char_30 AS TIME) my_char_30 id NULL NULL 1 NULL 2 -00:00:00 <--------30 characters-------> 3 --00:00:00 ---äÖüß@µ*$-- 4 +NULL <--------30 characters-------> 3 +NULL ---äÖüß@µ*$-- 4 -00:00:01 -1 5 41:58:00 1 17:58 20 Warnings: diff --git a/sql-common/my_time.c b/sql-common/my_time.c index ce6e4846fad..4f03482f6e0 100644 --- a/sql-common/my_time.c +++ b/sql-common/my_time.c @@ -271,6 +271,128 @@ int check_time_range(MYSQL_TIME *ltime, uint dec, int *warning) } + /* Remove trailing spaces and garbage */ +static my_bool get_suffix(const char *str, size_t length, size_t *new_length) +{ + /* + QQ: perhaps 'T' should be considered as a date/time delimiter only + if it's followed by a digit. Learn ISO 8601 details. + */ + my_bool garbage= FALSE; + for ( ; length > 0 ; length--) + { + char ch= str[length - 1]; + if (my_isdigit(&my_charset_latin1, ch) || + my_ispunct(&my_charset_latin1, ch)) + break; + if (my_isspace(&my_charset_latin1, ch)) + continue; + if (ch == 'T') + { + /* 'T' has a meaning only after a digit. Otherwise it's a garbage */ + if (length >= 2 && my_isdigit(&my_charset_latin1, str[length - 2])) + break; + } + garbage= TRUE; + } + *new_length= length; + return garbage; +} + + +static size_t get_prefix(const char *str, size_t length, const char **endptr) +{ + const char *str0= str, *end= str + length; + for (; str < end && my_isspace(&my_charset_latin1, *str) ; str++) + { } + *endptr= str; + return str - str0; +} + + +static size_t get_sign(my_bool *neg, const char *str, size_t length, + const char **endptr) +{ + const char *str0= str; + if (length) + { + if ((*neg= (*str == '-')) || (*str == '+')) + str++; + } + else + *neg= FALSE; + *endptr= str; + return str - str0; +} + + +static my_bool find_body(my_bool *neg, const char *str, size_t length, + MYSQL_TIME *to, int *warn, + const char **new_str, size_t *new_length) +{ + size_t sign_length; + *warn= 0; + length-= get_prefix(str, length, &str); + sign_length= get_sign(neg, str, length, &str); + length-= sign_length; + /* There can be a space after a sign again: '- 10:20:30' or '- 1 10:20:30' */ + length-= get_prefix(str, length, &str); + if (get_suffix(str, length, &length)) + *warn|= MYSQL_TIME_WARN_TRUNCATED; + *new_str= str; + *new_length= length; + if (!length || !my_isdigit(&my_charset_latin1, *str)) + { + *warn|= MYSQL_TIME_WARN_TRUNCATED; + set_zero_time(to, MYSQL_TIMESTAMP_ERROR); + return TRUE; + } + return FALSE; +} + + +static my_bool +is_datetime_body_candidate(const char *str, size_t length) +{ + static uint min_date_length= 5; /* '1-1-1' -> '0001-01-01' */ + uint pos; + if (length >= 12) + return TRUE; + /* + The shortest possible DATE is '1-1-1', which is 5 characters. + To make a full datetime it should be at least followed by a space or a 'T'. + */ + if (length < min_date_length + 1/* DATE/TIME separator */) + return FALSE; + for (pos= min_date_length; pos < length; pos++) + { + if (str[pos] == 'T') /* Date/time separator */ + return TRUE; + if (str[pos] == ' ') + { + /* + We found a space. If can be a DATE/TIME separator: + TIME('1-1-1 1:1:1.0) -> '0001-01-01 01:01:01.0' + + But it can be also a DAY/TIME separator: + TIME('1 11') -> 35:00:00 = 1 day 11 hours + TIME('1 111') -> 135:00:00 = 1 day 111 hours + TIME('11 11') -> 275:00:00 = 11 days 11 hours + TIME('111 11') -> 838:59:59 = 111 days 11 hours with overflow + TIME('1111 11') -> 838:59:59 = 1111 days 11 hours with overflow + */ + for (pos= 0 ; pos < min_date_length; pos++) + { + if (my_ispunct(&my_charset_latin1, str[pos])) /* Can be a DATE */ + return TRUE; + } + return FALSE; + } + } + return FALSE; +} + + static my_bool str_to_DDhhmmssff_internal(my_bool neg, const char *str, size_t length, MYSQL_TIME *l_time, ulong max_hour, @@ -282,7 +404,7 @@ str_to_DDhhmmssff_internal(my_bool neg, const char *str, size_t length, Convert a timestamp string to a MYSQL_TIME value. SYNOPSIS - str_to_datetime() + str_to_datetime_or_date_body() str String to parse length Length of string l_time Date is stored here @@ -323,34 +445,16 @@ str_to_DDhhmmssff_internal(my_bool neg, const char *str, size_t length, #define MAX_DATE_PARTS 8 -my_bool -str_to_datetime(const char *str, size_t length, MYSQL_TIME *l_time, - ulonglong flags, MYSQL_TIME_STATUS *status) +static my_bool +str_to_datetime_or_date_body(const char *str, size_t length, MYSQL_TIME *l_time, + ulonglong flags, MYSQL_TIME_STATUS *status) { const char *end=str+length, *pos; uint number_of_fields= 0, digits, year_length, not_zero_date; - DBUG_ENTER("str_to_datetime"); + DBUG_ENTER("str_to_datetime_or_date_body"); DBUG_ASSERT(C_FLAGS_OK(flags)); bzero(l_time, sizeof(*l_time)); - if (flags & C_TIME_TIME_ONLY) - { - my_bool ret= str_to_time(str, length, l_time, flags, status); - DBUG_RETURN(ret); - } - - my_time_status_init(status); - - /* Skip space at start */ - for (; str != end && my_isspace(&my_charset_latin1, *str) ; str++) - ; - if (str == end || ! my_isdigit(&my_charset_latin1, *str)) - { - status->warnings= MYSQL_TIME_WARN_TRUNCATED; - l_time->time_type= MYSQL_TIMESTAMP_NONE; - DBUG_RETURN(1); - } - /* Calculate number of digits in first part. If length= 8 or >= 14 then year is of format YYYY. @@ -442,43 +546,22 @@ str_to_datetime(const char *str, size_t length, MYSQL_TIME *l_time, l_time->time_type= (number_of_fields <= 3 ? MYSQL_TIMESTAMP_DATE : MYSQL_TIMESTAMP_DATETIME); - for (; str != end ; str++) - { - if (!my_isspace(&my_charset_latin1,*str)) - { - status->warnings= MYSQL_TIME_WARN_TRUNCATED; - break; - } - } + if (str != end) + status->warnings= MYSQL_TIME_WARN_TRUNCATED; DBUG_RETURN(FALSE); err: - bzero((char*) l_time, sizeof(*l_time)); - l_time->time_type= MYSQL_TIMESTAMP_ERROR; + set_zero_time(l_time, MYSQL_TIMESTAMP_ERROR); DBUG_RETURN(TRUE); } -static size_t get_prefix_and_sign(my_bool *neg, const char *str, size_t length) -{ - const char *str0= str, *end= str + length; - for (; str < end && my_isspace(&my_charset_latin1, *str) ; str++) - { } - if (str < end && *str == '-') - { - *neg= TRUE; - str++; - } - return str - str0; -} - - /* Convert a time string to a MYSQL_TIME struct. SYNOPSIS - str_to_time() + str_to_datetime_or_date_or_time_body() str A string in full TIMESTAMP format or [-] DAYS [H]H:MM:SS, [H]H:MM:SS, [M]M:SS, [H]HMMSS, [M]MSS or [S]S @@ -503,44 +586,31 @@ static size_t get_prefix_and_sign(my_bool *neg, const char *str, size_t length) TRUE on error */ -my_bool str_to_time(const char *str, size_t length, MYSQL_TIME *l_time, - ulonglong fuzzydate, MYSQL_TIME_STATUS *status) +my_bool str_to_datetime_or_date_or_time_body(const char *str, size_t length, + MYSQL_TIME *l_time, + ulonglong fuzzydate, + MYSQL_TIME_STATUS *status) { - my_bool neg= 0; - size_t tmp_length; const char *endptr; DBUG_ASSERT(C_FLAGS_OK(fuzzydate)); - my_time_status_init(status); - - if ((tmp_length= get_prefix_and_sign(&neg, str, length))) - { - str+= tmp_length; - length-= tmp_length; - } - if (!length) - { - status->warnings|= MYSQL_TIME_WARN_TRUNCATED; - goto err; - } - /* Check first if this is a full TIMESTAMP */ - if (length >= 12) + if (is_datetime_body_candidate(str, length)) { /* Probably full timestamp */ - (void) str_to_datetime(str, length, l_time, - (fuzzydate & ~C_TIME_TIME_ONLY) | C_TIME_DATETIME_ONLY, - status); + (void) str_to_datetime_or_date_body(str, length, l_time, + (fuzzydate & ~C_TIME_TIME_ONLY) | + C_TIME_DATETIME_ONLY, + status); if (l_time->time_type >= MYSQL_TIMESTAMP_ERROR) return l_time->time_type == MYSQL_TIMESTAMP_ERROR; my_time_status_init(status); } - if (!str_to_DDhhmmssff_internal(neg, str, length, l_time, TIME_MAX_HOUR, + if (!str_to_DDhhmmssff_internal(FALSE, str, length, l_time, TIME_MAX_HOUR, status, &endptr)) return FALSE; -err: - bzero((char*) l_time, sizeof(*l_time)); - l_time->time_type= MYSQL_TIMESTAMP_ERROR; + + set_zero_time(l_time, MYSQL_TIMESTAMP_ERROR); return TRUE; } @@ -548,31 +618,22 @@ err: my_bool str_to_DDhhmmssff(const char *str, size_t length, MYSQL_TIME *ltime, ulong max_hour, MYSQL_TIME_STATUS *status) { - my_bool neg= 0; - size_t tmp_length; + my_bool neg; const char *endptr; - my_time_status_init(status); + int warn; - /* Remove trailing spaces */ - for ( ; length > 0 && my_isspace(&my_charset_latin1, str[length - 1]) ; ) - length--; - - if ((tmp_length= get_prefix_and_sign(&neg, str, length))) - { - str+= tmp_length; - length-= tmp_length; - } - if (!length) + my_time_status_init(status); + if (find_body(&neg, str, length, ltime, &warn, &str, &length)) { - status->warnings|= MYSQL_TIME_WARN_TRUNCATED; - set_zero_time(ltime, MYSQL_TIMESTAMP_ERROR); + status->warnings= warn; return TRUE; } /* Reject anything that might be parsed as a full TIMESTAMP */ - if (length >= 12) /* The same condition with str_to_time() */ + if (is_datetime_body_candidate(str, length)) { - (void) str_to_datetime(str, length, ltime, C_TIME_DATETIME_ONLY, status); + (void) str_to_datetime_or_date_body(str, length, ltime, + C_TIME_DATETIME_ONLY, status); if (ltime->time_type > MYSQL_TIMESTAMP_ERROR) { status->warnings|= MYSQL_TIME_WARN_TRUNCATED; @@ -591,6 +652,57 @@ my_bool str_to_DDhhmmssff(const char *str, size_t length, MYSQL_TIME *ltime, status, &endptr) || (endptr < str + length && endptr[0] == '-')) return TRUE; + status->warnings|= warn; + return FALSE; +} + + +my_bool str_to_time(const char *str, size_t length, MYSQL_TIME *l_time, + ulonglong fuzzydate, MYSQL_TIME_STATUS *status) +{ + my_bool neg; + int warn; + DBUG_ASSERT(C_FLAGS_OK(fuzzydate)); + my_time_status_init(status); + if (find_body(&neg, str, length, l_time, &warn, &str, &length)) + { + status->warnings= warn; + return TRUE; + } + /* + QQ: Perhaps we should modify xxx_body() to return endptr. + If endptr points to '-', return an error. + */ + if (str_to_datetime_or_date_or_time_body(str, length, l_time, + fuzzydate, status)) + return TRUE; + status->warnings|= warn; + l_time->neg= neg; + return FALSE; +} + + +my_bool +str_to_datetime(const char *str, size_t length, MYSQL_TIME *l_time, + ulonglong flags, MYSQL_TIME_STATUS *status) +{ + my_bool neg, rc; + int warn; + DBUG_ASSERT(C_FLAGS_OK(flags)); + my_time_status_init(status); + if (find_body(&neg, str, length, l_time, &warn, &str, &length)) + { + status->warnings= warn; + return TRUE; + } + rc= (flags & C_TIME_TIME_ONLY) ? + str_to_datetime_or_date_or_time_body(str, length, l_time, flags, status) : + str_to_datetime_or_date_body(str, length, l_time, flags, status); + status->warnings|= warn; + if (rc) + return rc; + if ((l_time->neg= neg) && l_time->time_type != MYSQL_TIMESTAMP_TIME) + return TRUE; return FALSE; } @@ -749,16 +861,7 @@ fractional: /* Check if there is garbage at end of the MYSQL_TIME specification */ if (str != end) - { - do - { - if (!my_isspace(&my_charset_latin1,*str)) - { - status->warnings|= MYSQL_TIME_WARN_TRUNCATED; - break; - } - } while (++str != end); - } + status->warnings|= MYSQL_TIME_WARN_TRUNCATED; return FALSE; err: |