← Back to team overview

maria-developers team mailing list archive

Please review MDEV-10524 Assertion `arg1_int >= 0' failed in Item_func_additive_op::result_precision()

 

Hello Sergei,

Please review a patch for MDEV-10524.
Thanks!
commit 72817bb386320080de87f9cfe899e6f74341d251
Author: Alexander Barkov <bar@xxxxxxxxxxx>
Date:   Thu Dec 15 19:40:09 2016 +0400

    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.

diff --git a/mysql-test/include/ctype_numconv.inc b/mysql-test/include/ctype_numconv.inc
index 9b21e7f..47b52be 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 7f215de..980bb95 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 e7bf123..3fc440b 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 2a7d4ed..9d5dea2 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 dc96495..db9d03a 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 96e0970..c38a03f 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 294c2cb..74fed6a 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 ef5e348..68b1e0f 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 45214ae..92e1c38 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 667be3c..cfa97ea 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -39,6 +39,7 @@ class Item_func :public Item_result_field
     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);
@@ -46,6 +47,8 @@ class Item_func :public Item_result_field
   void count_datetime_length(Item **item, uint nitems);
   bool count_string_result_length(enum_field_types field_type,
                                   Item **item, uint nitems);
+  /* maybe_null can't be changed by parameters or used table state */
+  bool persistent_maybe_null;
 public:
   uint arg_count;
   table_map used_tables_cache, not_null_tables_cache;
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 94370d4..ec9580b 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 7606c28..00ae60a 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -62,7 +62,6 @@ class Item_str_func :public Item_func
   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 28e9368..420fb29 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(&ltime, 0) ||
+      (null_value= my_TIME_to_str(&ltime, 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 3a03ee4..0062d50 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -506,6 +506,50 @@ class Item_temporal_func: public Item_func
 };
 
 
+/**
+  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 @@ class Item_func_sec_to_time :public Item_timefunc
 };
 
 
-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 @@ class Item_func_makedate :public Item_temporal_func
 };
 
 
-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 @@ class Item_func_get_format :public Item_str_ascii_func
 };
 
 
-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 9d22760..3c127a0 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 c5c6539..d912a7b 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 ad75212..9becdcd 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);

Follow ups