diff options
author | Alexander Barkov <bar@mariadb.org> | 2016-12-19 14:28:08 +0400 |
---|---|---|
committer | Alexander Barkov <bar@mariadb.org> | 2016-12-19 14:28:08 +0400 |
commit | 2f6fede8d5f7e98319b4b7b557bd565fdb42fac3 (patch) | |
tree | f57ad1b04932d80eb36f05a5ef55cb62dece012c | |
parent | c4d9dc705b781bb155aab8f04cece2b87116d3c1 (diff) | |
download | mariadb-git-2f6fede8d5f7e98319b4b7b557bd565fdb42fac3.tar.gz |
MDEV-10524 Assertion `arg1_int >= 0' failed in Item_func_additive_op::result_precision()
This change is a backport from 10.0 to 5.5 for:
1. The full patch for:
MDEV-4841 Wrong character set of ADDTIME() and DATE_ADD()
9adb6e991ec87b65d04929f115d9d0c899e4ab19
2. A small fragment of:
MDEV-5298 Illegal mix of collations on timestamp
03f6778d61a74bdd7d09103a16473a2a5624cf66
which overrides Item_temporal_hybrid_func::cmp_type(),
and adds a new line into cache_temporal_4265.result.
-rw-r--r-- | mysql-test/include/ctype_numconv.inc | 26 | ||||
-rw-r--r-- | mysql-test/r/cache_temporal_4265.result | 1 | ||||
-rw-r--r-- | mysql-test/r/ctype_binary.result | 42 | ||||
-rw-r--r-- | mysql-test/r/ctype_cp1251.result | 46 | ||||
-rw-r--r-- | mysql-test/r/ctype_latin1.result | 42 | ||||
-rw-r--r-- | mysql-test/r/ctype_ucs.result | 48 | ||||
-rw-r--r-- | mysql-test/r/ctype_utf8.result | 46 | ||||
-rw-r--r-- | mysql-test/r/func_time.result | 6 | ||||
-rw-r--r-- | mysql-test/t/func_time.test | 5 | ||||
-rw-r--r-- | sql/item_func.h | 1 | ||||
-rw-r--r-- | sql/item_strfunc.cc | 2 | ||||
-rw-r--r-- | sql/item_strfunc.h | 1 | ||||
-rw-r--r-- | sql/item_timefunc.cc | 29 | ||||
-rw-r--r-- | sql/item_timefunc.h | 62 | ||||
-rw-r--r-- | sql/sql_const.h | 2 | ||||
-rw-r--r-- | sql/sql_time.cc | 17 | ||||
-rw-r--r-- | sql/sql_time.h | 2 |
17 files changed, 341 insertions, 37 deletions
diff --git a/mysql-test/include/ctype_numconv.inc b/mysql-test/include/ctype_numconv.inc index 9b21e7f38c1..47b52be9cec 100644 --- a/mysql-test/include/ctype_numconv.inc +++ b/mysql-test/include/ctype_numconv.inc @@ -1743,6 +1743,11 @@ DROP TABLE t1; --echo # Bug #31384 DATE_ADD() and DATE_SUB() return binary data --echo # SELECT @@collation_connection, @@character_set_results; +SELECT + CHARSET(DATE_SUB('2007-08-03', INTERVAL 1 MINUTE)) AS field_str1, + CHARSET(DATE_SUB('2007-08-03 17:33:00', INTERVAL 1 MINUTE)) AS field_str2, + CHARSET(DATE_SUB(DATE('2007-08-03'), INTERVAL 1 DAY)) AS field_date, + CHARSET(DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE)) AS field_datetime; CREATE TABLE t1 AS SELECT DATE_SUB('2007-08-03', INTERVAL 1 MINUTE) AS field_str1, @@ -1766,7 +1771,26 @@ SELECT HEX(DATE_SUB('2007-08-03 17:33:00', INTERVAL 1 MINUTE)) AS field1_str2, HEX(DATE_SUB(DATE('2007-08-03'), INTERVAL 1 DAY)) AS field_date, HEX(DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE)) AS field_datetime; - + +--echo # +--echo # MDEV-4841 Wrong character set of ADDTIME() and DATE_ADD() +--echo # +SELECT @@collation_connection, @@character_set_results; +SELECT + CHARSET(ADDTIME(_latin1'10:01:01',_latin1'10:00:00')) AS addtime1, + CHARSET(ADDTIME('10:01:01','10:00:00')) AS addtime2, + CHARSET(DATE_ADD(_latin1'2001-01-01 10:01:01',interval 10 second)) AS date_add1, + CHARSET(DATE_ADD('2001-01-01 10:01:01',interval 10 second)) AS date_add2; +CREATE TABLE t1 AS +SELECT + ADDTIME(_latin1'10:01:01',_latin1'10:00:00') AS addtime1, + ADDTIME('10:01:01','10:00:00') AS addtime2, + DATE_ADD(_latin1'2001-01-01 10:01:01',interval 10 second) AS date_add1, + DATE_ADD('2001-01-01 10:01:01',interval 10 second) AS date_add2; +SHOW CREATE TABLE t1; +SELECT * FROM t1; +DROP TABLE t1; + --echo # --echo # Bug#11926811 / Bug#60625 Illegal mix of collations --echo # diff --git a/mysql-test/r/cache_temporal_4265.result b/mysql-test/r/cache_temporal_4265.result index 7f215de43fb..980bb957e19 100644 --- a/mysql-test/r/cache_temporal_4265.result +++ b/mysql-test/r/cache_temporal_4265.result @@ -7,6 +7,7 @@ a 2002-03-04 Warnings: Note 1003 2000-01-01 +Note 1003 2000-01-06 set debug_dbug=''; drop table t1; create table t1 (id int not null, ut timestamp(6) not null); diff --git a/mysql-test/r/ctype_binary.result b/mysql-test/r/ctype_binary.result index e7bf1238210..3fc440b8354 100644 --- a/mysql-test/r/ctype_binary.result +++ b/mysql-test/r/ctype_binary.result @@ -2777,6 +2777,13 @@ DROP TABLE t1; SELECT @@collation_connection, @@character_set_results; @@collation_connection @@character_set_results binary binary +SELECT +CHARSET(DATE_SUB('2007-08-03', INTERVAL 1 MINUTE)) AS field_str1, +CHARSET(DATE_SUB('2007-08-03 17:33:00', INTERVAL 1 MINUTE)) AS field_str2, +CHARSET(DATE_SUB(DATE('2007-08-03'), INTERVAL 1 DAY)) AS field_date, +CHARSET(DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE)) AS field_datetime; +field_str1 field_str2 field_date field_datetime +binary binary binary binary CREATE TABLE t1 AS SELECT DATE_SUB('2007-08-03', INTERVAL 1 MINUTE) AS field_str1, @@ -2786,8 +2793,8 @@ DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE) AS field_da SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( - `field_str1` varchar(19) DEFAULT NULL, - `field1_str2` varchar(19) DEFAULT NULL, + `field_str1` varbinary(19) DEFAULT NULL, + `field1_str2` varbinary(19) DEFAULT NULL, `field_date` date DEFAULT NULL, `field_datetime` datetime DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 @@ -2812,6 +2819,37 @@ HEX(DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE)) AS fie field_str1 field1_str2 field_date field_datetime 323030372D30382D30322032333A35393A3030 323030372D30382D30332031373A33323A3030 323030372D30382D3032 323030372D30382D30332031373A33323A3030 # +# MDEV-4841 Wrong character set of ADDTIME() and DATE_ADD() +# +SELECT @@collation_connection, @@character_set_results; +@@collation_connection @@character_set_results +binary binary +SELECT +CHARSET(ADDTIME(_latin1'10:01:01',_latin1'10:00:00')) AS addtime1, +CHARSET(ADDTIME('10:01:01','10:00:00')) AS addtime2, +CHARSET(DATE_ADD(_latin1'2001-01-01 10:01:01',interval 10 second)) AS date_add1, +CHARSET(DATE_ADD('2001-01-01 10:01:01',interval 10 second)) AS date_add2; +addtime1 addtime2 date_add1 date_add2 +binary binary binary binary +CREATE TABLE t1 AS +SELECT +ADDTIME(_latin1'10:01:01',_latin1'10:00:00') AS addtime1, +ADDTIME('10:01:01','10:00:00') AS addtime2, +DATE_ADD(_latin1'2001-01-01 10:01:01',interval 10 second) AS date_add1, +DATE_ADD('2001-01-01 10:01:01',interval 10 second) AS date_add2; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `addtime1` varbinary(26) DEFAULT NULL, + `addtime2` varbinary(26) DEFAULT NULL, + `date_add1` varbinary(19) DEFAULT NULL, + `date_add2` varbinary(19) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +SELECT * FROM t1; +addtime1 addtime2 date_add1 date_add2 +20:01:01 20:01:01 2001-01-01 10:01:11 2001-01-01 10:01:11 +DROP TABLE t1; +# # Bug#11926811 / Bug#60625 Illegal mix of collations # SELECT @@collation_connection; diff --git a/mysql-test/r/ctype_cp1251.result b/mysql-test/r/ctype_cp1251.result index 2a7d4ed1fb4..9d5dea2f286 100644 --- a/mysql-test/r/ctype_cp1251.result +++ b/mysql-test/r/ctype_cp1251.result @@ -3169,6 +3169,13 @@ DROP TABLE t1; SELECT @@collation_connection, @@character_set_results; @@collation_connection @@character_set_results cp1251_general_ci cp1251 +SELECT +CHARSET(DATE_SUB('2007-08-03', INTERVAL 1 MINUTE)) AS field_str1, +CHARSET(DATE_SUB('2007-08-03 17:33:00', INTERVAL 1 MINUTE)) AS field_str2, +CHARSET(DATE_SUB(DATE('2007-08-03'), INTERVAL 1 DAY)) AS field_date, +CHARSET(DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE)) AS field_datetime; +field_str1 field_str2 field_date field_datetime +cp1251 cp1251 binary binary CREATE TABLE t1 AS SELECT DATE_SUB('2007-08-03', INTERVAL 1 MINUTE) AS field_str1, @@ -3178,8 +3185,8 @@ DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE) AS field_da SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( - `field_str1` varchar(19) DEFAULT NULL, - `field1_str2` varchar(19) DEFAULT NULL, + `field_str1` varchar(19) CHARACTER SET cp1251 DEFAULT NULL, + `field1_str2` varchar(19) CHARACTER SET cp1251 DEFAULT NULL, `field_date` date DEFAULT NULL, `field_datetime` datetime DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 @@ -3190,8 +3197,8 @@ DATE_SUB('2007-08-03 17:33:00', INTERVAL 1 MINUTE) AS field1_str2, DATE_SUB(DATE('2007-08-03'), INTERVAL 1 DAY) AS field_date, DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE) AS field_datetime; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr -def field_str1 254 19 10 Y 128 0 63 -def field1_str2 254 19 19 Y 128 0 63 +def field_str1 254 19 10 Y 0 0 51 +def field1_str2 254 19 19 Y 0 0 51 def field_date 10 10 10 Y 128 0 63 def field_datetime 12 19 19 Y 128 0 63 field_str1 field1_str2 field_date field_datetime @@ -3204,6 +3211,37 @@ HEX(DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE)) AS fie field_str1 field1_str2 field_date field_datetime 323030372D30382D30322032333A35393A3030 323030372D30382D30332031373A33323A3030 323030372D30382D3032 323030372D30382D30332031373A33323A3030 # +# MDEV-4841 Wrong character set of ADDTIME() and DATE_ADD() +# +SELECT @@collation_connection, @@character_set_results; +@@collation_connection @@character_set_results +cp1251_general_ci cp1251 +SELECT +CHARSET(ADDTIME(_latin1'10:01:01',_latin1'10:00:00')) AS addtime1, +CHARSET(ADDTIME('10:01:01','10:00:00')) AS addtime2, +CHARSET(DATE_ADD(_latin1'2001-01-01 10:01:01',interval 10 second)) AS date_add1, +CHARSET(DATE_ADD('2001-01-01 10:01:01',interval 10 second)) AS date_add2; +addtime1 addtime2 date_add1 date_add2 +cp1251 cp1251 cp1251 cp1251 +CREATE TABLE t1 AS +SELECT +ADDTIME(_latin1'10:01:01',_latin1'10:00:00') AS addtime1, +ADDTIME('10:01:01','10:00:00') AS addtime2, +DATE_ADD(_latin1'2001-01-01 10:01:01',interval 10 second) AS date_add1, +DATE_ADD('2001-01-01 10:01:01',interval 10 second) AS date_add2; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `addtime1` varchar(26) CHARACTER SET cp1251 DEFAULT NULL, + `addtime2` varchar(26) CHARACTER SET cp1251 DEFAULT NULL, + `date_add1` varchar(19) CHARACTER SET cp1251 DEFAULT NULL, + `date_add2` varchar(19) CHARACTER SET cp1251 DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +SELECT * FROM t1; +addtime1 addtime2 date_add1 date_add2 +20:01:01 20:01:01 2001-01-01 10:01:11 2001-01-01 10:01:11 +DROP TABLE t1; +# # Bug#11926811 / Bug#60625 Illegal mix of collations # SELECT @@collation_connection; diff --git a/mysql-test/r/ctype_latin1.result b/mysql-test/r/ctype_latin1.result index dc96495b1ac..db9d03a8656 100644 --- a/mysql-test/r/ctype_latin1.result +++ b/mysql-test/r/ctype_latin1.result @@ -3351,6 +3351,13 @@ DROP TABLE t1; SELECT @@collation_connection, @@character_set_results; @@collation_connection @@character_set_results latin1_swedish_ci latin1 +SELECT +CHARSET(DATE_SUB('2007-08-03', INTERVAL 1 MINUTE)) AS field_str1, +CHARSET(DATE_SUB('2007-08-03 17:33:00', INTERVAL 1 MINUTE)) AS field_str2, +CHARSET(DATE_SUB(DATE('2007-08-03'), INTERVAL 1 DAY)) AS field_date, +CHARSET(DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE)) AS field_datetime; +field_str1 field_str2 field_date field_datetime +latin1 latin1 binary binary CREATE TABLE t1 AS SELECT DATE_SUB('2007-08-03', INTERVAL 1 MINUTE) AS field_str1, @@ -3372,8 +3379,8 @@ DATE_SUB('2007-08-03 17:33:00', INTERVAL 1 MINUTE) AS field1_str2, DATE_SUB(DATE('2007-08-03'), INTERVAL 1 DAY) AS field_date, DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE) AS field_datetime; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr -def field_str1 254 19 10 Y 128 0 63 -def field1_str2 254 19 19 Y 128 0 63 +def field_str1 254 19 10 Y 0 0 8 +def field1_str2 254 19 19 Y 0 0 8 def field_date 10 10 10 Y 128 0 63 def field_datetime 12 19 19 Y 128 0 63 field_str1 field1_str2 field_date field_datetime @@ -3386,6 +3393,37 @@ HEX(DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE)) AS fie field_str1 field1_str2 field_date field_datetime 323030372D30382D30322032333A35393A3030 323030372D30382D30332031373A33323A3030 323030372D30382D3032 323030372D30382D30332031373A33323A3030 # +# MDEV-4841 Wrong character set of ADDTIME() and DATE_ADD() +# +SELECT @@collation_connection, @@character_set_results; +@@collation_connection @@character_set_results +latin1_swedish_ci latin1 +SELECT +CHARSET(ADDTIME(_latin1'10:01:01',_latin1'10:00:00')) AS addtime1, +CHARSET(ADDTIME('10:01:01','10:00:00')) AS addtime2, +CHARSET(DATE_ADD(_latin1'2001-01-01 10:01:01',interval 10 second)) AS date_add1, +CHARSET(DATE_ADD('2001-01-01 10:01:01',interval 10 second)) AS date_add2; +addtime1 addtime2 date_add1 date_add2 +latin1 latin1 latin1 latin1 +CREATE TABLE t1 AS +SELECT +ADDTIME(_latin1'10:01:01',_latin1'10:00:00') AS addtime1, +ADDTIME('10:01:01','10:00:00') AS addtime2, +DATE_ADD(_latin1'2001-01-01 10:01:01',interval 10 second) AS date_add1, +DATE_ADD('2001-01-01 10:01:01',interval 10 second) AS date_add2; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `addtime1` varchar(26) DEFAULT NULL, + `addtime2` varchar(26) DEFAULT NULL, + `date_add1` varchar(19) DEFAULT NULL, + `date_add2` varchar(19) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +SELECT * FROM t1; +addtime1 addtime2 date_add1 date_add2 +20:01:01 20:01:01 2001-01-01 10:01:11 2001-01-01 10:01:11 +DROP TABLE t1; +# # Bug#11926811 / Bug#60625 Illegal mix of collations # SELECT @@collation_connection; diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result index 96e0970e4a6..c38a03f76a8 100644 --- a/mysql-test/r/ctype_ucs.result +++ b/mysql-test/r/ctype_ucs.result @@ -4167,6 +4167,13 @@ DROP TABLE t1; SELECT @@collation_connection, @@character_set_results; @@collation_connection @@character_set_results ucs2_general_ci latin1 +SELECT +CHARSET(DATE_SUB('2007-08-03', INTERVAL 1 MINUTE)) AS field_str1, +CHARSET(DATE_SUB('2007-08-03 17:33:00', INTERVAL 1 MINUTE)) AS field_str2, +CHARSET(DATE_SUB(DATE('2007-08-03'), INTERVAL 1 DAY)) AS field_date, +CHARSET(DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE)) AS field_datetime; +field_str1 field_str2 field_date field_datetime +ucs2 ucs2 binary binary CREATE TABLE t1 AS SELECT DATE_SUB('2007-08-03', INTERVAL 1 MINUTE) AS field_str1, @@ -4176,8 +4183,8 @@ DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE) AS field_da SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( - `field_str1` varchar(19) DEFAULT NULL, - `field1_str2` varchar(19) DEFAULT NULL, + `field_str1` varchar(19) CHARACTER SET ucs2 DEFAULT NULL, + `field1_str2` varchar(19) CHARACTER SET ucs2 DEFAULT NULL, `field_date` date DEFAULT NULL, `field_datetime` datetime DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 @@ -4188,8 +4195,8 @@ DATE_SUB('2007-08-03 17:33:00', INTERVAL 1 MINUTE) AS field1_str2, DATE_SUB(DATE('2007-08-03'), INTERVAL 1 DAY) AS field_date, DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE) AS field_datetime; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr -def field_str1 254 19 10 Y 128 0 63 -def field1_str2 254 19 19 Y 128 0 63 +def field_str1 254 19 10 Y 0 0 8 +def field1_str2 254 19 19 Y 0 0 8 def field_date 10 10 10 Y 128 0 63 def field_datetime 12 19 19 Y 128 0 63 field_str1 field1_str2 field_date field_datetime @@ -4200,7 +4207,38 @@ HEX(DATE_SUB('2007-08-03 17:33:00', INTERVAL 1 MINUTE)) AS field1_str2, HEX(DATE_SUB(DATE('2007-08-03'), INTERVAL 1 DAY)) AS field_date, HEX(DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE)) AS field_datetime; field_str1 field1_str2 field_date field_datetime -323030372D30382D30322032333A35393A3030 323030372D30382D30332031373A33323A3030 323030372D30382D3032 323030372D30382D30332031373A33323A3030 +0032003000300037002D00300038002D00300032002000320033003A00350039003A00300030 0032003000300037002D00300038002D00300033002000310037003A00330032003A00300030 323030372D30382D3032 323030372D30382D30332031373A33323A3030 +# +# MDEV-4841 Wrong character set of ADDTIME() and DATE_ADD() +# +SELECT @@collation_connection, @@character_set_results; +@@collation_connection @@character_set_results +ucs2_general_ci latin1 +SELECT +CHARSET(ADDTIME(_latin1'10:01:01',_latin1'10:00:00')) AS addtime1, +CHARSET(ADDTIME('10:01:01','10:00:00')) AS addtime2, +CHARSET(DATE_ADD(_latin1'2001-01-01 10:01:01',interval 10 second)) AS date_add1, +CHARSET(DATE_ADD('2001-01-01 10:01:01',interval 10 second)) AS date_add2; +addtime1 addtime2 date_add1 date_add2 +ucs2 ucs2 ucs2 ucs2 +CREATE TABLE t1 AS +SELECT +ADDTIME(_latin1'10:01:01',_latin1'10:00:00') AS addtime1, +ADDTIME('10:01:01','10:00:00') AS addtime2, +DATE_ADD(_latin1'2001-01-01 10:01:01',interval 10 second) AS date_add1, +DATE_ADD('2001-01-01 10:01:01',interval 10 second) AS date_add2; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `addtime1` varchar(26) CHARACTER SET ucs2 DEFAULT NULL, + `addtime2` varchar(26) CHARACTER SET ucs2 DEFAULT NULL, + `date_add1` varchar(19) CHARACTER SET ucs2 DEFAULT NULL, + `date_add2` varchar(19) CHARACTER SET ucs2 DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +SELECT * FROM t1; +addtime1 addtime2 date_add1 date_add2 +20:01:01 20:01:01 2001-01-01 10:01:11 2001-01-01 10:01:11 +DROP TABLE t1; # # Bug#11926811 / Bug#60625 Illegal mix of collations # diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index 294c2cb2be1..74fed6a3162 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -4988,6 +4988,13 @@ DROP TABLE t1; SELECT @@collation_connection, @@character_set_results; @@collation_connection @@character_set_results utf8_general_ci utf8 +SELECT +CHARSET(DATE_SUB('2007-08-03', INTERVAL 1 MINUTE)) AS field_str1, +CHARSET(DATE_SUB('2007-08-03 17:33:00', INTERVAL 1 MINUTE)) AS field_str2, +CHARSET(DATE_SUB(DATE('2007-08-03'), INTERVAL 1 DAY)) AS field_date, +CHARSET(DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE)) AS field_datetime; +field_str1 field_str2 field_date field_datetime +utf8 utf8 binary binary CREATE TABLE t1 AS SELECT DATE_SUB('2007-08-03', INTERVAL 1 MINUTE) AS field_str1, @@ -4997,8 +5004,8 @@ DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE) AS field_da SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( - `field_str1` varchar(19) DEFAULT NULL, - `field1_str2` varchar(19) DEFAULT NULL, + `field_str1` varchar(19) CHARACTER SET utf8 DEFAULT NULL, + `field1_str2` varchar(19) CHARACTER SET utf8 DEFAULT NULL, `field_date` date DEFAULT NULL, `field_datetime` datetime DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 @@ -5009,8 +5016,8 @@ DATE_SUB('2007-08-03 17:33:00', INTERVAL 1 MINUTE) AS field1_str2, DATE_SUB(DATE('2007-08-03'), INTERVAL 1 DAY) AS field_date, DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE) AS field_datetime; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr -def field_str1 254 19 10 Y 128 0 63 -def field1_str2 254 19 19 Y 128 0 63 +def field_str1 254 57 10 Y 0 0 33 +def field1_str2 254 57 19 Y 0 0 33 def field_date 10 10 10 Y 128 0 63 def field_datetime 12 19 19 Y 128 0 63 field_str1 field1_str2 field_date field_datetime @@ -5023,6 +5030,37 @@ HEX(DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE)) AS fie field_str1 field1_str2 field_date field_datetime 323030372D30382D30322032333A35393A3030 323030372D30382D30332031373A33323A3030 323030372D30382D3032 323030372D30382D30332031373A33323A3030 # +# MDEV-4841 Wrong character set of ADDTIME() and DATE_ADD() +# +SELECT @@collation_connection, @@character_set_results; +@@collation_connection @@character_set_results +utf8_general_ci utf8 +SELECT +CHARSET(ADDTIME(_latin1'10:01:01',_latin1'10:00:00')) AS addtime1, +CHARSET(ADDTIME('10:01:01','10:00:00')) AS addtime2, +CHARSET(DATE_ADD(_latin1'2001-01-01 10:01:01',interval 10 second)) AS date_add1, +CHARSET(DATE_ADD('2001-01-01 10:01:01',interval 10 second)) AS date_add2; +addtime1 addtime2 date_add1 date_add2 +utf8 utf8 utf8 utf8 +CREATE TABLE t1 AS +SELECT +ADDTIME(_latin1'10:01:01',_latin1'10:00:00') AS addtime1, +ADDTIME('10:01:01','10:00:00') AS addtime2, +DATE_ADD(_latin1'2001-01-01 10:01:01',interval 10 second) AS date_add1, +DATE_ADD('2001-01-01 10:01:01',interval 10 second) AS date_add2; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `addtime1` varchar(26) CHARACTER SET utf8 DEFAULT NULL, + `addtime2` varchar(26) CHARACTER SET utf8 DEFAULT NULL, + `date_add1` varchar(19) CHARACTER SET utf8 DEFAULT NULL, + `date_add2` varchar(19) CHARACTER SET utf8 DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +SELECT * FROM t1; +addtime1 addtime2 date_add1 date_add2 +20:01:01 20:01:01 2001-01-01 10:01:11 2001-01-01 10:01:11 +DROP TABLE t1; +# # Bug#11926811 / Bug#60625 Illegal mix of collations # SELECT @@collation_connection; diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index ef5e3487a99..68b1e0f04ad 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -2620,3 +2620,9 @@ id date1 date2 DATE_ADD(a.date1,INTERVAL -10 DAY) TO_DAYS(a.date1)-10 17 NULL NULL NULL NULL 18 2010-10-13 2010-10-03 2010-10-03 734413 DROP TABLE t1; +# +# MDEV-10524 Assertion `arg1_int >= 0' failed in Item_func_additive_op::result_precision() +# +SELECT 1 MOD ADDTIME( '13:58:57', '00:00:01' ) + 2; +1 MOD ADDTIME( '13:58:57', '00:00:01' ) + 2 +3 diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index 45214aed6e7..92e1c38cec2 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -1597,3 +1597,8 @@ INSERT INTO t1 VALUES (17, NULL); INSERT INTO t1 VALUES (18, '2010-10-13'); SELECT a.id,a.date1,FROM_DAYS(TO_DAYS(a.date1)-10) as date2, DATE_ADD(a.date1,INTERVAL -10 DAY),TO_DAYS(a.date1)-10 FROM t1 a ORDER BY a.id; DROP TABLE t1; + +--echo # +--echo # MDEV-10524 Assertion `arg1_int >= 0' failed in Item_func_additive_op::result_precision() +--echo # +SELECT 1 MOD ADDTIME( '13:58:57', '00:00:01' ) + 2; diff --git a/sql/item_func.h b/sql/item_func.h index 667be3c0438..0da38e22c7f 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -39,6 +39,7 @@ protected: 0 means get this number from first argument */ uint allowed_arg_cols; + String *val_str_from_val_str_ascii(String *str, String *str2); void count_only_length(Item **item, uint nitems); void count_real_length(Item **item, uint nitems); diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 94370d45cef..ec9580bfabd 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -70,7 +70,7 @@ size_t username_char_length= 16; Normally conversion does not happen, and val_str_ascii() is immediately returned instead. */ -String *Item_str_func::val_str_from_val_str_ascii(String *str, String *str2) +String *Item_func::val_str_from_val_str_ascii(String *str, String *str2) { DBUG_ASSERT(fixed == 1); diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 7606c281548..00ae60a7fb1 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -62,7 +62,6 @@ public: enum Item_result result_type () const { return STRING_RESULT; } void left_right_max_length(); bool fix_fields(THD *thd, Item **ref); - String *val_str_from_val_str_ascii(String *str, String *str2); }; diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 28e93683422..420fb29f518 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -1455,25 +1455,29 @@ bool get_interval_value(Item *args,interval_type int_type, INTERVAL *interval) void Item_temporal_func::fix_length_and_dec() { + uint char_length= mysql_temporal_int_part_length(field_type()); /* We set maybe_null to 1 as default as any bad argument with date or time can get us to return NULL. */ maybe_null= 1; - max_length= mysql_temporal_int_part_length(field_type()); + if (decimals) { if (decimals == NOT_FIXED_DEC) - max_length+= TIME_SECOND_PART_DIGITS + 1; + char_length+= TIME_SECOND_PART_DIGITS + 1; else { set_if_smaller(decimals, TIME_SECOND_PART_DIGITS); - max_length+= decimals + 1; + char_length+= decimals + 1; } } sql_mode= current_thd->variables.sql_mode & (MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE); - collation.set(&my_charset_numeric, DERIVATION_NUMERIC, MY_REPERTOIRE_ASCII); + collation.set(field_type() == MYSQL_TYPE_STRING ? + default_charset() : &my_charset_numeric, + DERIVATION_NUMERIC, MY_REPERTOIRE_ASCII); + fix_char_length(char_length); } String *Item_temporal_func::val_str(String *str) @@ -1483,6 +1487,23 @@ String *Item_temporal_func::val_str(String *str) } +String *Item_temporal_hybrid_func::val_str_ascii(String *str) +{ + DBUG_ASSERT(fixed == 1); + MYSQL_TIME ltime; + + if (get_date(<ime, 0) || + (null_value= my_TIME_to_str(<ime, str, decimals))) + return (String *) 0; + + /* Check that the returned timestamp type matches to the function type */ + DBUG_ASSERT(cached_field_type == MYSQL_TYPE_STRING || + ltime.time_type == MYSQL_TIMESTAMP_NONE || + mysql_type_to_time_type(cached_field_type) == ltime.time_type); + return str; +} + + bool Item_func_from_days::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) { longlong value=args[0]->val_int(); diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index 3a03ee4b27a..0062d500835 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -506,6 +506,50 @@ public: }; +/** + Abstract class for functions returning TIME, DATE, DATETIME or string values, + whose data type depends on parameters and is set at fix_fields time. +*/ +class Item_temporal_hybrid_func: public Item_temporal_func +{ +protected: + enum_field_types cached_field_type; // TIME, DATE, DATETIME or STRING + String ascii_buf; // Conversion buffer +public: + Item_temporal_hybrid_func(Item *a,Item *b) + :Item_temporal_func(a,b) {} + enum_field_types field_type() const { return cached_field_type; } + Item_result cmp_type() const + { + return cached_field_type == MYSQL_TYPE_STRING ? + STRING_RESULT : TIME_RESULT; + } + const CHARSET_INFO *charset_for_protocol() const + { + /* + Can return TIME, DATE, DATETIME or VARCHAR depending on arguments. + Send using "binary" when TIME, DATE or DATETIME, + or using collation.collation when VARCHAR + (which is fixed from @@collation_connection in fix_length_and_dec). + */ + DBUG_ASSERT(fixed == 1); + return cached_field_type == MYSQL_TYPE_STRING ? + collation.collation : &my_charset_bin; + } + /** + Return string value in ASCII character set. + */ + String *val_str_ascii(String *str); + /** + Return string value in @@character_set_connection. + */ + String *val_str(String *str) + { + return val_str_from_val_str_ascii(str, &ascii_buf); + } +}; + + class Item_datefunc :public Item_temporal_func { public: @@ -763,17 +807,15 @@ public: }; -class Item_date_add_interval :public Item_temporal_func +class Item_date_add_interval :public Item_temporal_hybrid_func { - enum_field_types cached_field_type; public: const interval_type int_type; // keep it public const bool date_sub_interval; // keep it public Item_date_add_interval(Item *a,Item *b,interval_type type_arg,bool neg_arg) - :Item_temporal_func(a,b),int_type(type_arg), date_sub_interval(neg_arg) {} + :Item_temporal_hybrid_func(a,b),int_type(type_arg), date_sub_interval(neg_arg) {} const char *func_name() const { return "date_add_interval"; } void fix_length_and_dec(); - enum_field_types field_type() const { return cached_field_type; } bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date); bool eq(const Item *item, bool binary_cmp) const; void print(String *str, enum_query_type query_type); @@ -911,16 +953,14 @@ public: }; -class Item_func_add_time :public Item_temporal_func +class Item_func_add_time :public Item_temporal_hybrid_func { const bool is_date; int sign; - enum_field_types cached_field_type; public: Item_func_add_time(Item *a, Item *b, bool type_arg, bool neg_arg) - :Item_temporal_func(a, b), is_date(type_arg) { sign= neg_arg ? -1 : 1; } - enum_field_types field_type() const { return cached_field_type; } + :Item_temporal_hybrid_func(a, b), is_date(type_arg) { sign= neg_arg ? -1 : 1; } void fix_length_and_dec(); bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date); void print(String *str, enum_query_type query_type); @@ -1019,9 +1059,8 @@ public: }; -class Item_func_str_to_date :public Item_temporal_func +class Item_func_str_to_date :public Item_temporal_hybrid_func { - enum_field_types cached_field_type; timestamp_type cached_timestamp_type; bool const_item; String subject_converter; @@ -1029,12 +1068,11 @@ class Item_func_str_to_date :public Item_temporal_func CHARSET_INFO *internal_charset; public: Item_func_str_to_date(Item *a, Item *b) - :Item_temporal_func(a, b), const_item(false), + :Item_temporal_hybrid_func(a, b), const_item(false), internal_charset(NULL) {} bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date); const char *func_name() const { return "str_to_date"; } - enum_field_types field_type() const { return cached_field_type; } void fix_length_and_dec(); }; diff --git a/sql/sql_const.h b/sql/sql_const.h index 9d227601a20..3c127a03826 100644 --- a/sql/sql_const.h +++ b/sql/sql_const.h @@ -54,7 +54,7 @@ #define MIN_TIME_WIDTH 10 /* -HHH:MM:SS */ #define MAX_TIME_WIDTH 16 /* -DDDDDD HH:MM:SS */ #define MAX_TIME_FULL_WIDTH 23 /* -DDDDDD HH:MM:SS.###### */ -#define MAX_DATETIME_FULL_WIDTH 29 /* YYYY-MM-DD HH:MM:SS.###### AM */ +#define MAX_DATETIME_FULL_WIDTH 26 /* YYYY-MM-DD HH:MM:SS.###### */ #define MAX_DATETIME_WIDTH 19 /* YYYY-MM-DD HH:MM:SS */ #define MAX_DATETIME_COMPRESSED_WIDTH 14 /* YYYYMMDDHHMMSS */ #define MAX_DATETIME_PRECISION 6 diff --git a/sql/sql_time.cc b/sql/sql_time.cc index c5c65391758..d912a7b78d6 100644 --- a/sql/sql_time.cc +++ b/sql/sql_time.cc @@ -838,6 +838,23 @@ const char *get_date_time_format_str(KNOWN_DATE_TIME_FORMAT *format, } } + +/** + Convert TIME/DATE/DATETIME value to String. + @param l_time DATE value + @param OUT str String to convert to + @param dec Number of fractional digits. +*/ +bool my_TIME_to_str(const MYSQL_TIME *ltime, String *str, uint dec) +{ + if (str->alloc(MAX_DATE_STRING_REP_LENGTH)) + return true; + str->set_charset(&my_charset_numeric); + str->length(my_TIME_to_str(ltime, const_cast<char*>(str->ptr()), dec)); + return false; +} + + void make_truncated_value_warning(THD *thd, MYSQL_ERROR::enum_warning_level level, const ErrConv *sval, diff --git a/sql/sql_time.h b/sql/sql_time.h index ad752121044..9becdcd4200 100644 --- a/sql/sql_time.h +++ b/sql/sql_time.h @@ -74,6 +74,8 @@ extern DATE_TIME_FORMAT *date_time_format_copy(THD *thd, DATE_TIME_FORMAT *format); const char *get_date_time_format_str(KNOWN_DATE_TIME_FORMAT *format, timestamp_type type); +bool my_TIME_to_str(const MYSQL_TIME *ltime, String *str, uint dec); + /* MYSQL_TIME operations */ bool date_add_interval(MYSQL_TIME *ltime, interval_type int_type, INTERVAL interval); |