Bug#19960 Inconsistent results when joining InnoDB tables using partial UTF8 indexes
Adding a multibyte-aware VARCHAR copying function, to put correct column prefix, taking in account number of characters (instead just limiting on number of bytes). For example, for a KEY(col(3)) on a UTF8 column when copying the string 'foo bar foo', we should put only 3 leftmost characters: 'foo'. 9 characters were incorrectly put before this fix. mysql-test/r/ctype_utf8.result: Adding test case mysql-test/t/ctype_utf8.test: Adding test case sql/field_conv.cc: Adding multibyte aware copy function for VARCHAR
This commit is contained in:
parent
2bfeecca15
commit
695bcb9e7b
@ -1462,3 +1462,21 @@ set @a:=null;
|
|||||||
execute my_stmt using @a;
|
execute my_stmt using @a;
|
||||||
a b
|
a b
|
||||||
drop table if exists t1;
|
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;
|
||||||
|
@ -1164,3 +1164,23 @@ execute my_stmt using @a;
|
|||||||
set @a:=null;
|
set @a:=null;
|
||||||
execute my_stmt using @a;
|
execute my_stmt using @a;
|
||||||
drop table if exists t1;
|
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;
|
||||||
|
@ -428,6 +428,21 @@ static void do_varstring2(Copy_field *copy)
|
|||||||
length);
|
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
|
** 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;
|
return do_field_string;
|
||||||
if (to_length != from_length)
|
if (to_length != from_length)
|
||||||
return (((Field_varstring*) to)->length_bytes == 1 ?
|
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)
|
else if (to_length < from_length)
|
||||||
return (from->charset()->mbmaxlen == 1 ?
|
return (from->charset()->mbmaxlen == 1 ?
|
||||||
|
Loading…
x
Reference in New Issue
Block a user