Skip to content

Commit cb6b340

Browse files
author
Alexander Barkov
committed
Bug#31384 DATE_ADD() and DATE_SUB() return binary data
Problem: DATE_ADD() is a hybrid function and can return DATE, DATETIME or VARCHAR data type depending on arguments. In case of VARCHAR data type, DATE_ADD() reported "binary" character set, which was wrong. Fix: make DATE_ADD() return @character_set_connection in VARCHAR context. @ mysql-test/include/ctype_numconv.inc Adding tests @ mysql-test/r/ctype_binary.result Adding tests @ mysql-test/r/ctype_cp1251.result Adding tests @ mysql-test/r/ctype_latin1.result Adding tests @ mysql-test/r/ctype_ucs.result Adding tests @ mysql-test/r/ctype_utf8.result Adding tests @ sql/item_strfunc.cc - Moving code from Item_str_ascii_func::val_str() to Item_str_func::val_str_from_val_str_ascii(), as this code needs to be shared by Item_date_add_interval. - Adding str2 parameter to be used as a buffer, instead of using private ascii_buf member. @ sql/item_strfunc.h - Moving code from Item_str_ascii_func::val_str() to Item_str_func::val_str_from_val_str_ascii() - Removing "String *val_str_convert_from_ascii(String *str, String *ascii_buf)" prototype as it was neither used nor declared. @ sql/item_timefunc.h - Overwriting parent's charset_for_protocol() method, becase we need to behave differenlty in VARCHAR and DATE/DATETYPE context. - Adding ascii_buf for conversion. - Adding val_str_ascii() prototype. - Adding val_str() which uses newly added Item_str_func::val_str_from_val_str_ascii(), passing ascii_buf as a conversion buffer.
1 parent a90d37e commit cb6b340

10 files changed

+272
-14
lines changed

mysql-test/include/ctype_numconv.inc

+26
Original file line numberDiff line numberDiff line change
@@ -1737,6 +1737,32 @@ EXPLAIN SELECT * FROM t1 WHERE date_column BETWEEN '2010-09-01' AND '2010-10-01'
17371737
DROP TABLE t1;
17381738

17391739

1740+
--echo #
1741+
--echo # Bug #31384 DATE_ADD() and DATE_SUB() return binary data
1742+
--echo #
1743+
SELECT @@collation_connection, @@character_set_results;
1744+
CREATE TABLE t1 AS
1745+
SELECT
1746+
DATE_SUB('2007-08-03', INTERVAL 1 MINUTE) AS field_str1,
1747+
DATE_SUB('2007-08-03 17:33:00', INTERVAL 1 MINUTE) AS field1_str2,
1748+
DATE_SUB(DATE('2007-08-03'), INTERVAL 1 DAY) AS field_date,
1749+
DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE) AS field_datetime;
1750+
SHOW CREATE TABLE t1;
1751+
DROP TABLE t1;
1752+
--enable_metadata
1753+
SELECT
1754+
DATE_SUB('2007-08-03', INTERVAL 1 DAY) AS field_str1,
1755+
DATE_SUB('2007-08-03 17:33:00', INTERVAL 1 MINUTE) AS field1_str2,
1756+
DATE_SUB(DATE('2007-08-03'), INTERVAL 1 DAY) AS field_date,
1757+
DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE) AS field_datetime;
1758+
--disable_metadata
1759+
SELECT
1760+
HEX(DATE_SUB('2007-08-03', INTERVAL 1 MINUTE)) AS field_str1,
1761+
HEX(DATE_SUB('2007-08-03 17:33:00', INTERVAL 1 MINUTE)) AS field1_str2,
1762+
HEX(DATE_SUB(DATE('2007-08-03'), INTERVAL 1 DAY)) AS field_date,
1763+
HEX(DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE)) AS field_datetime;
1764+
1765+
17401766
--echo #
17411767
--echo # Bug#52159 returning time type from function and empty left join causes debug assertion
17421768
--echo #

mysql-test/r/ctype_binary.result

+40
Original file line numberDiff line numberDiff line change
@@ -2767,6 +2767,46 @@ id select_type table type possible_keys key key_len ref rows Extra
27672767
1 SIMPLE t1 range date_column date_column 9 NULL 1 Using where
27682768
DROP TABLE t1;
27692769
#
2770+
# Bug #31384 DATE_ADD() and DATE_SUB() return binary data
2771+
#
2772+
SELECT @@collation_connection, @@character_set_results;
2773+
@@collation_connection @@character_set_results
2774+
binary binary
2775+
CREATE TABLE t1 AS
2776+
SELECT
2777+
DATE_SUB('2007-08-03', INTERVAL 1 MINUTE) AS field_str1,
2778+
DATE_SUB('2007-08-03 17:33:00', INTERVAL 1 MINUTE) AS field1_str2,
2779+
DATE_SUB(DATE('2007-08-03'), INTERVAL 1 DAY) AS field_date,
2780+
DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE) AS field_datetime;
2781+
SHOW CREATE TABLE t1;
2782+
Table Create Table
2783+
t1 CREATE TABLE `t1` (
2784+
`field_str1` varbinary(29) DEFAULT NULL,
2785+
`field1_str2` varbinary(29) DEFAULT NULL,
2786+
`field_date` date DEFAULT NULL,
2787+
`field_datetime` datetime DEFAULT NULL
2788+
) ENGINE=MyISAM DEFAULT CHARSET=latin1
2789+
DROP TABLE t1;
2790+
SELECT
2791+
DATE_SUB('2007-08-03', INTERVAL 1 DAY) AS field_str1,
2792+
DATE_SUB('2007-08-03 17:33:00', INTERVAL 1 MINUTE) AS field1_str2,
2793+
DATE_SUB(DATE('2007-08-03'), INTERVAL 1 DAY) AS field_date,
2794+
DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE) AS field_datetime;
2795+
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
2796+
def field_str1 254 29 10 Y 128 31 63
2797+
def field1_str2 254 29 19 Y 128 31 63
2798+
def field_date 10 29 10 Y 128 31 63
2799+
def field_datetime 12 29 19 Y 128 31 63
2800+
field_str1 field1_str2 field_date field_datetime
2801+
2007-08-02 2007-08-03 17:32:00 2007-08-02 2007-08-03 17:32:00
2802+
SELECT
2803+
HEX(DATE_SUB('2007-08-03', INTERVAL 1 MINUTE)) AS field_str1,
2804+
HEX(DATE_SUB('2007-08-03 17:33:00', INTERVAL 1 MINUTE)) AS field1_str2,
2805+
HEX(DATE_SUB(DATE('2007-08-03'), INTERVAL 1 DAY)) AS field_date,
2806+
HEX(DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE)) AS field_datetime;
2807+
field_str1 field1_str2 field_date field_datetime
2808+
323030372D30382D30322032333A35393A3030 323030372D30382D30332031373A33323A3030 323030372D30382D3032 323030372D30382D30332031373A33323A3030
2809+
#
27702810
# Bug#52159 returning time type from function and empty left join causes debug assertion
27712811
#
27722812
CREATE FUNCTION f1() RETURNS TIME RETURN 1;

mysql-test/r/ctype_cp1251.result

+40
Original file line numberDiff line numberDiff line change
@@ -3157,6 +3157,46 @@ id select_type table type possible_keys key key_len ref rows Extra
31573157
1 SIMPLE t1 range date_column date_column 9 NULL 1 Using where
31583158
DROP TABLE t1;
31593159
#
3160+
# Bug #31384 DATE_ADD() and DATE_SUB() return binary data
3161+
#
3162+
SELECT @@collation_connection, @@character_set_results;
3163+
@@collation_connection @@character_set_results
3164+
cp1251_general_ci cp1251
3165+
CREATE TABLE t1 AS
3166+
SELECT
3167+
DATE_SUB('2007-08-03', INTERVAL 1 MINUTE) AS field_str1,
3168+
DATE_SUB('2007-08-03 17:33:00', INTERVAL 1 MINUTE) AS field1_str2,
3169+
DATE_SUB(DATE('2007-08-03'), INTERVAL 1 DAY) AS field_date,
3170+
DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE) AS field_datetime;
3171+
SHOW CREATE TABLE t1;
3172+
Table Create Table
3173+
t1 CREATE TABLE `t1` (
3174+
`field_str1` varchar(29) CHARACTER SET cp1251 DEFAULT NULL,
3175+
`field1_str2` varchar(29) CHARACTER SET cp1251 DEFAULT NULL,
3176+
`field_date` date DEFAULT NULL,
3177+
`field_datetime` datetime DEFAULT NULL
3178+
) ENGINE=MyISAM DEFAULT CHARSET=latin1
3179+
DROP TABLE t1;
3180+
SELECT
3181+
DATE_SUB('2007-08-03', INTERVAL 1 DAY) AS field_str1,
3182+
DATE_SUB('2007-08-03 17:33:00', INTERVAL 1 MINUTE) AS field1_str2,
3183+
DATE_SUB(DATE('2007-08-03'), INTERVAL 1 DAY) AS field_date,
3184+
DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE) AS field_datetime;
3185+
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
3186+
def field_str1 254 29 10 Y 0 31 51
3187+
def field1_str2 254 29 19 Y 0 31 51
3188+
def field_date 10 29 10 Y 128 31 63
3189+
def field_datetime 12 29 19 Y 128 31 63
3190+
field_str1 field1_str2 field_date field_datetime
3191+
2007-08-02 2007-08-03 17:32:00 2007-08-02 2007-08-03 17:32:00
3192+
SELECT
3193+
HEX(DATE_SUB('2007-08-03', INTERVAL 1 MINUTE)) AS field_str1,
3194+
HEX(DATE_SUB('2007-08-03 17:33:00', INTERVAL 1 MINUTE)) AS field1_str2,
3195+
HEX(DATE_SUB(DATE('2007-08-03'), INTERVAL 1 DAY)) AS field_date,
3196+
HEX(DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE)) AS field_datetime;
3197+
field_str1 field1_str2 field_date field_datetime
3198+
323030372D30382D30322032333A35393A3030 323030372D30382D30332031373A33323A3030 323030372D30382D3032 323030372D30382D30332031373A33323A3030
3199+
#
31603200
# Bug#52159 returning time type from function and empty left join causes debug assertion
31613201
#
31623202
CREATE FUNCTION f1() RETURNS TIME RETURN 1;

mysql-test/r/ctype_latin1.result

+40
Original file line numberDiff line numberDiff line change
@@ -3186,6 +3186,46 @@ id select_type table type possible_keys key key_len ref rows Extra
31863186
1 SIMPLE t1 range date_column date_column 9 NULL 1 Using where
31873187
DROP TABLE t1;
31883188
#
3189+
# Bug #31384 DATE_ADD() and DATE_SUB() return binary data
3190+
#
3191+
SELECT @@collation_connection, @@character_set_results;
3192+
@@collation_connection @@character_set_results
3193+
latin1_swedish_ci latin1
3194+
CREATE TABLE t1 AS
3195+
SELECT
3196+
DATE_SUB('2007-08-03', INTERVAL 1 MINUTE) AS field_str1,
3197+
DATE_SUB('2007-08-03 17:33:00', INTERVAL 1 MINUTE) AS field1_str2,
3198+
DATE_SUB(DATE('2007-08-03'), INTERVAL 1 DAY) AS field_date,
3199+
DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE) AS field_datetime;
3200+
SHOW CREATE TABLE t1;
3201+
Table Create Table
3202+
t1 CREATE TABLE `t1` (
3203+
`field_str1` varchar(29) DEFAULT NULL,
3204+
`field1_str2` varchar(29) DEFAULT NULL,
3205+
`field_date` date DEFAULT NULL,
3206+
`field_datetime` datetime DEFAULT NULL
3207+
) ENGINE=MyISAM DEFAULT CHARSET=latin1
3208+
DROP TABLE t1;
3209+
SELECT
3210+
DATE_SUB('2007-08-03', INTERVAL 1 DAY) AS field_str1,
3211+
DATE_SUB('2007-08-03 17:33:00', INTERVAL 1 MINUTE) AS field1_str2,
3212+
DATE_SUB(DATE('2007-08-03'), INTERVAL 1 DAY) AS field_date,
3213+
DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE) AS field_datetime;
3214+
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
3215+
def field_str1 254 29 10 Y 0 31 8
3216+
def field1_str2 254 29 19 Y 0 31 8
3217+
def field_date 10 29 10 Y 128 31 63
3218+
def field_datetime 12 29 19 Y 128 31 63
3219+
field_str1 field1_str2 field_date field_datetime
3220+
2007-08-02 2007-08-03 17:32:00 2007-08-02 2007-08-03 17:32:00
3221+
SELECT
3222+
HEX(DATE_SUB('2007-08-03', INTERVAL 1 MINUTE)) AS field_str1,
3223+
HEX(DATE_SUB('2007-08-03 17:33:00', INTERVAL 1 MINUTE)) AS field1_str2,
3224+
HEX(DATE_SUB(DATE('2007-08-03'), INTERVAL 1 DAY)) AS field_date,
3225+
HEX(DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE)) AS field_datetime;
3226+
field_str1 field1_str2 field_date field_datetime
3227+
323030372D30382D30322032333A35393A3030 323030372D30382D30332031373A33323A3030 323030372D30382D3032 323030372D30382D30332031373A33323A3030
3228+
#
31893229
# Bug#52159 returning time type from function and empty left join causes debug assertion
31903230
#
31913231
CREATE FUNCTION f1() RETURNS TIME RETURN 1;

mysql-test/r/ctype_ucs.result

+40
Original file line numberDiff line numberDiff line change
@@ -4009,6 +4009,46 @@ id select_type table type possible_keys key key_len ref rows Extra
40094009
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using where
40104010
DROP TABLE t1;
40114011
#
4012+
# Bug #31384 DATE_ADD() and DATE_SUB() return binary data
4013+
#
4014+
SELECT @@collation_connection, @@character_set_results;
4015+
@@collation_connection @@character_set_results
4016+
ucs2_general_ci latin1
4017+
CREATE TABLE t1 AS
4018+
SELECT
4019+
DATE_SUB('2007-08-03', INTERVAL 1 MINUTE) AS field_str1,
4020+
DATE_SUB('2007-08-03 17:33:00', INTERVAL 1 MINUTE) AS field1_str2,
4021+
DATE_SUB(DATE('2007-08-03'), INTERVAL 1 DAY) AS field_date,
4022+
DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE) AS field_datetime;
4023+
SHOW CREATE TABLE t1;
4024+
Table Create Table
4025+
t1 CREATE TABLE `t1` (
4026+
`field_str1` varchar(29) CHARACTER SET ucs2 DEFAULT NULL,
4027+
`field1_str2` varchar(29) CHARACTER SET ucs2 DEFAULT NULL,
4028+
`field_date` date DEFAULT NULL,
4029+
`field_datetime` datetime DEFAULT NULL
4030+
) ENGINE=MyISAM DEFAULT CHARSET=latin1
4031+
DROP TABLE t1;
4032+
SELECT
4033+
DATE_SUB('2007-08-03', INTERVAL 1 DAY) AS field_str1,
4034+
DATE_SUB('2007-08-03 17:33:00', INTERVAL 1 MINUTE) AS field1_str2,
4035+
DATE_SUB(DATE('2007-08-03'), INTERVAL 1 DAY) AS field_date,
4036+
DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE) AS field_datetime;
4037+
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
4038+
def field_str1 254 29 10 Y 0 31 8
4039+
def field1_str2 254 29 19 Y 0 31 8
4040+
def field_date 10 29 10 Y 128 31 63
4041+
def field_datetime 12 29 19 Y 128 31 63
4042+
field_str1 field1_str2 field_date field_datetime
4043+
2007-08-02 2007-08-03 17:32:00 2007-08-02 2007-08-03 17:32:00
4044+
SELECT
4045+
HEX(DATE_SUB('2007-08-03', INTERVAL 1 MINUTE)) AS field_str1,
4046+
HEX(DATE_SUB('2007-08-03 17:33:00', INTERVAL 1 MINUTE)) AS field1_str2,
4047+
HEX(DATE_SUB(DATE('2007-08-03'), INTERVAL 1 DAY)) AS field_date,
4048+
HEX(DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE)) AS field_datetime;
4049+
field_str1 field1_str2 field_date field_datetime
4050+
0032003000300037002D00300038002D00300032002000320033003A00350039003A00300030 0032003000300037002D00300038002D00300033002000310037003A00330032003A00300030 323030372D30382D3032 323030372D30382D30332031373A33323A3030
4051+
#
40124052
# Bug#52159 returning time type from function and empty left join causes debug assertion
40134053
#
40144054
CREATE FUNCTION f1() RETURNS TIME RETURN 1;

mysql-test/r/ctype_utf8.result

+40
Original file line numberDiff line numberDiff line change
@@ -4898,6 +4898,46 @@ id select_type table type possible_keys key key_len ref rows Extra
48984898
1 SIMPLE t1 range date_column date_column 9 NULL 1 Using where
48994899
DROP TABLE t1;
49004900
#
4901+
# Bug #31384 DATE_ADD() and DATE_SUB() return binary data
4902+
#
4903+
SELECT @@collation_connection, @@character_set_results;
4904+
@@collation_connection @@character_set_results
4905+
utf8_general_ci utf8
4906+
CREATE TABLE t1 AS
4907+
SELECT
4908+
DATE_SUB('2007-08-03', INTERVAL 1 MINUTE) AS field_str1,
4909+
DATE_SUB('2007-08-03 17:33:00', INTERVAL 1 MINUTE) AS field1_str2,
4910+
DATE_SUB(DATE('2007-08-03'), INTERVAL 1 DAY) AS field_date,
4911+
DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE) AS field_datetime;
4912+
SHOW CREATE TABLE t1;
4913+
Table Create Table
4914+
t1 CREATE TABLE `t1` (
4915+
`field_str1` varchar(29) CHARACTER SET utf8 DEFAULT NULL,
4916+
`field1_str2` varchar(29) CHARACTER SET utf8 DEFAULT NULL,
4917+
`field_date` date DEFAULT NULL,
4918+
`field_datetime` datetime DEFAULT NULL
4919+
) ENGINE=MyISAM DEFAULT CHARSET=latin1
4920+
DROP TABLE t1;
4921+
SELECT
4922+
DATE_SUB('2007-08-03', INTERVAL 1 DAY) AS field_str1,
4923+
DATE_SUB('2007-08-03 17:33:00', INTERVAL 1 MINUTE) AS field1_str2,
4924+
DATE_SUB(DATE('2007-08-03'), INTERVAL 1 DAY) AS field_date,
4925+
DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE) AS field_datetime;
4926+
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
4927+
def field_str1 254 87 10 Y 0 31 33
4928+
def field1_str2 254 87 19 Y 0 31 33
4929+
def field_date 10 29 10 Y 128 31 63
4930+
def field_datetime 12 29 19 Y 128 31 63
4931+
field_str1 field1_str2 field_date field_datetime
4932+
2007-08-02 2007-08-03 17:32:00 2007-08-02 2007-08-03 17:32:00
4933+
SELECT
4934+
HEX(DATE_SUB('2007-08-03', INTERVAL 1 MINUTE)) AS field_str1,
4935+
HEX(DATE_SUB('2007-08-03 17:33:00', INTERVAL 1 MINUTE)) AS field1_str2,
4936+
HEX(DATE_SUB(DATE('2007-08-03'), INTERVAL 1 DAY)) AS field_date,
4937+
HEX(DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE)) AS field_datetime;
4938+
field_str1 field1_str2 field_date field_datetime
4939+
323030372D30382D30322032333A35393A3030 323030372D30382D30332031373A33323A3030 323030372D30382D3032 323030372D30382D30332031373A33323A3030
4940+
#
49014941
# Bug#52159 returning time type from function and empty left join causes debug assertion
49024942
#
49034943
CREATE FUNCTION f1() RETURNS TIME RETURN 1;

sql/item_strfunc.cc

+7-7
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ String my_empty_string("",default_charset_info);
7070
Normally conversion does not happen, and val_str_ascii() is immediately
7171
returned instead.
7272
*/
73-
String *Item_str_ascii_func::val_str(String *str)
73+
String *Item_str_func::val_str_from_val_str_ascii(String *str, String *str2)
7474
{
7575
DBUG_ASSERT(fixed == 1);
7676

@@ -82,19 +82,19 @@ String *Item_str_ascii_func::val_str(String *str)
8282
return res;
8383
}
8484

85-
DBUG_ASSERT(str != &ascii_buf);
85+
DBUG_ASSERT(str != str2);
8686

8787
uint errors;
88-
String *res= val_str_ascii(&ascii_buf);
88+
String *res= val_str_ascii(str);
8989
if (!res)
9090
return 0;
9191

92-
if ((null_value= str->copy(res->ptr(), res->length(),
93-
&my_charset_latin1, collation.collation,
94-
&errors)))
92+
if ((null_value= str2->copy(res->ptr(), res->length(),
93+
&my_charset_latin1, collation.collation,
94+
&errors)))
9595
return 0;
9696

97-
return str;
97+
return str2;
9898
}
9999

100100

sql/item_strfunc.h

+5-2
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ class Item_str_func :public Item_func
5151
enum Item_result result_type () const { return STRING_RESULT; }
5252
void left_right_max_length();
5353
bool fix_fields(THD *thd, Item **ref);
54+
String *val_str_from_val_str_ascii(String *str, String *str2);
5455
};
5556

5657

@@ -66,8 +67,10 @@ class Item_str_ascii_func :public Item_str_func
6667
Item_str_ascii_func(Item *a) :Item_str_func(a) {}
6768
Item_str_ascii_func(Item *a,Item *b) :Item_str_func(a,b) {}
6869
Item_str_ascii_func(Item *a,Item *b,Item *c) :Item_str_func(a,b,c) {}
69-
String *val_str_convert_from_ascii(String *str, String *ascii_buf);
70-
String *val_str(String *str);
70+
String *val_str(String *str)
71+
{
72+
return val_str_from_val_str_ascii(str, &ascii_buf);
73+
}
7174
virtual String *val_str_ascii(String *)= 0;
7275
};
7376

sql/item_timefunc.cc

+16-3
Original file line numberDiff line numberDiff line change
@@ -2205,8 +2205,6 @@ void Item_date_add_interval::fix_length_and_dec()
22052205
enum_field_types arg0_field_type;
22062206

22072207
maybe_null=1;
2208-
fix_length_and_charset_datetime(MAX_DATETIME_FULL_WIDTH);
2209-
value.alloc(max_length);
22102208

22112209
/*
22122210
The field type for the result of an Item_date function is defined as
@@ -2231,6 +2229,21 @@ void Item_date_add_interval::fix_length_and_dec()
22312229
else
22322230
cached_field_type= MYSQL_TYPE_DATETIME;
22332231
}
2232+
2233+
if (cached_field_type == MYSQL_TYPE_STRING)
2234+
{
2235+
/* Behave as a usual string function when return type is VARCHAR. */
2236+
fix_length_and_charset(MAX_DATETIME_FULL_WIDTH, default_charset());
2237+
}
2238+
else
2239+
{
2240+
/*
2241+
Follow the "Number-to-string conversion" rules as in WorkLog 2649
2242+
when return type is DATE or DATETIME.
2243+
*/
2244+
fix_length_and_charset_datetime(MAX_DATETIME_FULL_WIDTH);
2245+
}
2246+
value.alloc(max_length);
22342247
}
22352248

22362249

@@ -2253,7 +2266,7 @@ bool Item_date_add_interval::get_date(MYSQL_TIME *ltime, uint fuzzy_date)
22532266
}
22542267

22552268

2256-
String *Item_date_add_interval::val_str(String *str)
2269+
String *Item_date_add_interval::val_str_ascii(String *str)
22572270
{
22582271
DBUG_ASSERT(fixed == 1);
22592272
MYSQL_TIME ltime;

sql/item_timefunc.h

+18-2
Original file line numberDiff line numberDiff line change
@@ -773,16 +773,32 @@ class Item_date_add_interval :public Item_date_func
773773
{
774774
String value;
775775
enum_field_types cached_field_type;
776-
776+
String ascii_buf;
777777
public:
778778
const interval_type int_type; // keep it public
779779
const bool date_sub_interval; // keep it public
780780
Item_date_add_interval(Item *a,Item *b,interval_type type_arg,bool neg_arg)
781781
:Item_date_func(a,b),int_type(type_arg), date_sub_interval(neg_arg) {}
782-
String *val_str(String *);
782+
String *val_str_ascii(String *str);
783+
String *val_str(String *str)
784+
{
785+
return val_str_from_val_str_ascii(str, &ascii_buf);
786+
}
783787
const char *func_name() const { return "date_add_interval"; }
784788
void fix_length_and_dec();
785789
enum_field_types field_type() const { return cached_field_type; }
790+
CHARSET_INFO *charset_for_protocol(void) const
791+
{
792+
/*
793+
DATE_ADD() can return DATE, DATETIME or VARCHAR depending on arguments.
794+
Send using "binary" when DATE or DATETIME,
795+
or using collation.collation when VARCHAR
796+
(which was fixed from @collation_connection in fix_length_and_dec).
797+
*/
798+
DBUG_ASSERT(fixed == 1);
799+
return cached_field_type == MYSQL_TYPE_STRING ?
800+
collation.collation : &my_charset_bin;
801+
}
786802
longlong val_int();
787803
bool get_date(MYSQL_TIME *res, uint fuzzy_date);
788804
bool eq(const Item *item, bool binary_cmp) const;

0 commit comments

Comments
 (0)