diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index 51f361349e6..4267df8d176 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -1462,3 +1462,21 @@ set @a:=null; execute my_stmt using @a; a b drop table if exists t1; +CREATE TABLE t1 ( +colA int(11) NOT NULL, +colB varchar(255) character set utf8 NOT NULL, +PRIMARY KEY (colA) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +INSERT INTO t1 (colA, colB) VALUES (1, 'foo'), (2, 'foo bar'); +CREATE TABLE t2 ( +colA int(11) NOT NULL, +colB varchar(255) character set utf8 NOT NULL, +KEY bad (colA,colB(3)) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +INSERT INTO t2 (colA, colB) VALUES (1, 'foo'),(2, 'foo bar'); +SELECT * FROM t1 JOIN t2 ON t1.colA=t2.colA AND t1.colB=t2.colB +WHERE t1.colA < 3; +colA colB colA colB +1 foo 1 foo +2 foo bar 2 foo bar +DROP TABLE t1, t2; diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index b6137d5f084..67ca6f45188 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -1164,3 +1164,23 @@ execute my_stmt using @a; set @a:=null; execute my_stmt using @a; drop table if exists t1; + +# +# Bug#19960: Inconsistent results when joining +# InnoDB tables using partial UTF8 indexes +# +CREATE TABLE t1 ( + colA int(11) NOT NULL, + colB varchar(255) character set utf8 NOT NULL, + PRIMARY KEY (colA) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +INSERT INTO t1 (colA, colB) VALUES (1, 'foo'), (2, 'foo bar'); +CREATE TABLE t2 ( + colA int(11) NOT NULL, + colB varchar(255) character set utf8 NOT NULL, + KEY bad (colA,colB(3)) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +INSERT INTO t2 (colA, colB) VALUES (1, 'foo'),(2, 'foo bar'); +SELECT * FROM t1 JOIN t2 ON t1.colA=t2.colA AND t1.colB=t2.colB +WHERE t1.colA < 3; +DROP TABLE t1, t2; diff --git a/sql/field_conv.cc b/sql/field_conv.cc index 3200f2ca9b2..95ff985376d 100644 --- a/sql/field_conv.cc +++ b/sql/field_conv.cc @@ -428,6 +428,21 @@ static void do_varstring2(Copy_field *copy) length); } + +static void do_varstring2_mb(Copy_field *copy) +{ + int well_formed_error; + CHARSET_INFO *cs= copy->from_field->charset(); + uint char_length= (copy->to_length - HA_KEY_BLOB_LENGTH) / cs->mbmaxlen; + uint from_length= uint2korr(copy->from_ptr); + const char *from_beg= copy->from_ptr + HA_KEY_BLOB_LENGTH; + uint length= cs->cset->well_formed_len(cs, from_beg, from_beg + from_length, + char_length, &well_formed_error); + int2store(copy->to_ptr, length); + memcpy(copy->to_ptr+HA_KEY_BLOB_LENGTH, from_beg, length); +} + + /*************************************************************************** ** The different functions that fills in a Copy_field class ***************************************************************************/ @@ -587,7 +602,8 @@ void (*Copy_field::get_copy_func(Field *to,Field *from))(Copy_field*) return do_field_string; if (to_length != from_length) return (((Field_varstring*) to)->length_bytes == 1 ? - do_varstring1 : do_varstring2); + do_varstring1 : (from->charset()->mbmaxlen == 1 ? + do_varstring2 : do_varstring2_mb)); } else if (to_length < from_length) return (from->charset()->mbmaxlen == 1 ?