Commit ffc1facc authored by unknown's avatar unknown
Browse files

Bug #22367: Optimizer uses ref join type instead of eq_ref for simple join on

             strings
MySQL is setting the flag HA_END_SPACE_KEYS for all the keys that reference
text or varchar columns with collation different than binary.
This was done to handle correctly the situation where a lookup on such a key
may return more than 1 row because of the presence of many rows that differ
only by the amount of trailing space in the table's string column.
Inserting such values however appears to violate the unique checks on 
INSERT/UPDATE. Thus that flag must not be set as it will prevent the optimizer
from choosing a faster access method.
This fix removes the setting of the HA_END_SPACE_KEYS flag.


include/my_base.h:
  Bug #22367: Optimizer uses ref join type instead of eq_ref for simple join on 
               strings
   - disabled HA_END_SPACE_KEY as it's no longer needed
mysql-test/r/func_str.result:
  Bug #22367: Optimizer uses ref join type instead of eq_ref for simple join on 
               strings
   - fixed explain in an existing case
mysql-test/r/merge.result:
  Bug #22367: Optimizer uses ref join type instead of eq_ref for simple join on 
               strings
   - fixed explain in an existing case
mysql-test/r/select.result:
  Bug #22367: Optimizer uses ref join type instead of eq_ref for simple join on 
               strings
   - test case
mysql-test/r/subselect.result:
  Bug #22367: Optimizer uses ref join type instead of eq_ref for simple join on 
               strings
   - fixed explain in an existing case
mysql-test/t/select.test:
  Bug #22367: Optimizer uses ref join type instead of eq_ref for simple join on 
               strings
   - test case
parent 78bf0287
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -224,12 +224,17 @@ enum ha_base_keytype {
/* poor old NISAM has 8-bit flags :-( */
#define HA_SORT_ALLOWS_SAME	 128	/* Intern bit when sorting records */
#endif
#if MYSQL_VERSION_ID < 0x50200
/*
  Key has a part that can have end space.  If this is an unique key
  we have to handle it differently from other unique keys as we can find
  many matching rows for one key (because end space are not compared)
*/
#define HA_END_SPACE_KEY	4096
#define HA_END_SPACE_KEY      0 /* was: 4096 */
#else
#error HA_END_SPACE_KEY is obsolete, please remove it
#endif


	/* These flags can be added to key-seg-flag */

+2 −2
Original line number Diff line number Diff line
@@ -1143,9 +1143,9 @@ EXPLAIN EXTENDED
SELECT * FROM t1 INNER JOIN t2 ON code=id 
WHERE id='a12' AND (LENGTH(code)=5 OR code < 'a00');
id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
1	SIMPLE	t2	const	PRIMARY	PRIMARY	12	const	1	Using index
1	SIMPLE	t1	ref	code	code	13	const	3	Using where; Using index
1	SIMPLE	t2	ref	PRIMARY	PRIMARY	12	const	1	Using where; Using index
Warnings:
Note	1003	select `test`.`t1`.`code` AS `code`,`test`.`t2`.`id` AS `id` from `test`.`t1` join `test`.`t2` where ((`test`.`t1`.`code` = _latin1'a12') and (`test`.`t2`.`id` = _latin1'a12') and (length(`test`.`t1`.`code`) = 5))
Note	1003	select `test`.`t1`.`code` AS `code`,`test`.`t2`.`id` AS `id` from `test`.`t1` join `test`.`t2` where ((`test`.`t1`.`code` = _latin1'a12') and (length(`test`.`t1`.`code`) = 5))
DROP TABLE t1,t2;
End of 5.0 tests
+1 −1
Original line number Diff line number Diff line
@@ -626,7 +626,7 @@ id select_type table type possible_keys key key_len ref rows Extra
EXPLAIN SELECT * FROM t2 WHERE fileset_id = 2
AND file_code = '0000000115' LIMIT 1;
id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
1	SIMPLE	t2	ref	PRIMARY,files	PRIMARY	35	const,const	1	Using where
1	SIMPLE	t2	const	PRIMARY,files	PRIMARY	35	const,const	1	
DROP TABLE t2, t1;
create table t1 (x int, y int, index xy(x, y));
create table t2 (x int, y int, index xy(x, y));
+10 −0
Original line number Diff line number Diff line
@@ -3517,3 +3517,13 @@ id a b c d e
2	NULL	NULL	NULL	2	40
2	NULL	NULL	NULL	2	50
DROP TABLE t1,t2,t3;
CREATE TABLE t1 (a int, b varchar(20) NOT NULL, PRIMARY KEY(a));
CREATE TABLE t2 (a int, b varchar(20) NOT NULL,
PRIMARY KEY (a), UNIQUE KEY (b));
INSERT INTO t1 VALUES (1,'a'),(2,'b'),(3,'c');
INSERT INTO t2 VALUES (1,'a'),(2,'b'),(3,'c');
EXPLAIN SELECT t1.a FROM t1 LEFT JOIN t2 ON t2.b=t1.b WHERE t1.a=3;
id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
1	SIMPLE	t1	const	PRIMARY	PRIMARY	4	const	1	
1	SIMPLE	t2	const	b	b	22	const	1	Using index
DROP TABLE t1,t2;
+5 −5
Original line number Diff line number Diff line
@@ -363,12 +363,12 @@ INSERT INTO t8 (pseudo,email) VALUES ('joce1','test1');
INSERT INTO t8 (pseudo,email) VALUES ('2joce1','2test1');
EXPLAIN EXTENDED SELECT pseudo,(SELECT email FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce')) FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce');
id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
1	PRIMARY	t8	ref	PRIMARY	PRIMARY	37	const	1	Using where; Using index
4	SUBQUERY	t8	ref	PRIMARY	PRIMARY	37		1	Using where; Using index
2	SUBQUERY	t8	ref	PRIMARY	PRIMARY	37	const	1	Using where
3	SUBQUERY	t8	ref	PRIMARY	PRIMARY	37		1	Using where; Using index
1	PRIMARY	t8	const	PRIMARY	PRIMARY	37	const	1	Using index
4	SUBQUERY	t8	const	PRIMARY	PRIMARY	37		1	Using index
2	SUBQUERY	t8	const	PRIMARY	PRIMARY	37	const	1	
3	SUBQUERY	t8	const	PRIMARY	PRIMARY	37		1	Using index
Warnings:
Note	1003	select `test`.`t8`.`pseudo` AS `pseudo`,(select `test`.`t8`.`email` AS `email` from `test`.`t8` where (`test`.`t8`.`pseudo` = (select `test`.`t8`.`pseudo` AS `pseudo` from `test`.`t8` where (`test`.`t8`.`pseudo` = _latin1'joce')))) AS `(SELECT email FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce'))` from `test`.`t8` where (`test`.`t8`.`pseudo` = (select `test`.`t8`.`pseudo` AS `pseudo` from `test`.`t8` where (`test`.`t8`.`pseudo` = _latin1'joce')))
Note	1003	select `test`.`t8`.`pseudo` AS `pseudo`,(select `test`.`t8`.`email` AS `email` from `test`.`t8` where 1) AS `(SELECT email FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce'))` from `test`.`t8` where 1
SELECT pseudo FROM t8 WHERE pseudo=(SELECT pseudo,email FROM
t8 WHERE pseudo='joce');
ERROR 21000: Operand should contain 1 column(s)
Loading