From: Date: March 15 2005 2:15pm Subject: bk commit into 4.1 tree (bar:1.2120) BUG#8785 List-Archive: http://lists.mysql.com/internals/23036 X-Bug: 8785 Message-Id: <200503151315.j2FDFr5x004660@bar.intranet.mysql.r18.ru> Below is the list of changes that have just been committed into a local 4.1 repository of bar. When bar does a push these changes will be propagated to the main repository and, within 24 hours after the push, to the public repository. For information on how to access the public repository see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html ChangeSet 1.2120 05/03/15 17:15:47 bar@stripped +5 -0 # Bug#8785 Problem with nested concats and character set conversion of a string constant. sql/sql_string.h 1.55 05/03/15 17:15:43 bar@stripped +4 -0 A new method to cut Alloced_length to str_length for string constants, to avoid reusing them as a buffer in things like CONCAT(). sql/item_strfunc.cc 1.220 05/03/15 17:15:43 bar@stripped +1 -2 Remove previous fix: it was not 100% correct. A non const_item() can return a constant String. sql/item.cc 1.194 05/03/15 17:15:43 bar@stripped +12 -0 # Bug#8785 Problem with nested concats and character set conversion of a string constant. mysql-test/t/ctype_utf8.test 1.50 05/03/15 17:15:43 bar@stripped +9 -0 Addign test mysql-test/r/ctype_utf8.result 1.50 05/03/15 17:15:43 bar@stripped +7 -0 Adding test # This is a BitKeeper patch. What follows are the unified diffs for the # set of deltas contained in the patch. The rest of the patch, the part # that BitKeeper cares about, is below these diffs. # User: bar # Host: bar.intranet.mysql.r18.ru # Root: /usr/home/bar/mysql-4.1 --- 1.193/sql/item.cc 2005-03-09 18:50:57 +04:00 +++ 1.194/sql/item.cc 2005-03-15 17:15:43 +04:00 @@ -236,6 +236,18 @@ return NULL; } conv->str_value.copy(); + /* + The above line executes str_value.realloc() internally, + which alligns Alloced_length using ALLIGN_SIZE. + In the case of Item_string::str_value we don't want + Alloced_length to be longer than str_length. + Otherwise, some functions like Item_func_concat::val_str() + try to reuse str_value as a buffer for concatenation result + for optimization purposes, so our string constant become + corrupted. See bug#8785 for more details. + Let's shrink Alloced_length to str_length to avoid this problem. + */ + conv->str_value.shrink_to_length(); return conv; } --- 1.219/sql/item_strfunc.cc 2005-03-09 22:37:24 +04:00 +++ 1.220/sql/item_strfunc.cc 2005-03-15 17:15:43 +04:00 @@ -277,8 +277,7 @@ current_thd->variables.max_allowed_packet); goto null; } - if (!args[0]->const_item() && - res->alloced_length() >= res->length()+res2->length()) + if (res->alloced_length() >= res->length()+res2->length()) { // Use old buffer res->append(*res2); } --- 1.54/sql/sql_string.h 2005-02-15 04:55:37 +04:00 +++ 1.55/sql/sql_string.h 2005-03-15 17:15:43 +04:00 @@ -177,6 +177,10 @@ } } } + inline void shrink_to_length() + { + Alloced_length= str_length; + } bool is_alloced() { return alloced; } inline String& operator = (const String &s) { --- 1.49/mysql-test/r/ctype_utf8.result 2005-02-21 17:17:13 +04:00 +++ 1.50/mysql-test/r/ctype_utf8.result 2005-03-15 17:15:43 +04:00 @@ -861,6 +861,13 @@ one two DROP TABLE t1; +create table t1 (f1 varchar(1) not null) default charset utf8; +insert into t1 values (''), (''); +select concat(concat(_latin1'->',f1),_latin1'<-') from t1; +concat(concat(_latin1'->',f1),_latin1'<-') +-><- +-><- +drop table t1; select convert(_koi8r'É' using utf8) < convert(_koi8r'Ê' using utf8); convert(_koi8r'É' using utf8) < convert(_koi8r'Ê' using utf8) 1 --- 1.49/mysql-test/t/ctype_utf8.test 2005-02-21 17:17:10 +04:00 +++ 1.50/mysql-test/t/ctype_utf8.test 2005-03-15 17:15:43 +04:00 @@ -695,6 +695,15 @@ DROP TABLE t1; # +# Bug#8785 +# the same problem with the above, but with nested CONCATs +# +create table t1 (f1 varchar(1) not null) default charset utf8; +insert into t1 values (''), (''); +select concat(concat(_latin1'->',f1),_latin1'<-') from t1; +drop table t1; + +# # Bug#8385: utf8_general_ci treats Cyrillic letters I and SHORT I as the same # select convert(_koi8r'É' using utf8) < convert(_koi8r'Ê' using utf8);