diff --git a/mysql-test/include/oversized_varchar_key.inc b/mysql-test/include/oversized_varchar_key.inc new file mode 100644 index 000000000000..39f847915c98 --- /dev/null +++ b/mysql-test/include/oversized_varchar_key.inc @@ -0,0 +1,174 @@ +eval CREATE TABLE t1 ( pk VARCHAR(16) NOT NULL PRIMARY KEY ) CHARSET=$charset COLLATE=$collation; + +INSERT INTO t1 VALUES ('abc'), ('def'), ('ghi'), ('jkl'), ('mno'); +ANALYZE TABLE t1; + +EXPLAIN +SELECT * FROM t1 WHERE pk IN ('abc', 'this_value_is_>16', 'def'); +SELECT * FROM t1 WHERE pk IN ('abc', 'this_value_is_>16', 'def'); + +EXPLAIN +SELECT * FROM t1 WHERE pk IN ('abc', 'this_value_is_>16', 'def'); +SELECT * FROM t1 WHERE pk IN ('abc', 'this_value_is_>16', 'def'); + +EXPLAIN +SELECT * FROM t1 WHERE pk IN ('this_value_is_>16'); +SELECT * FROM t1 WHERE pk IN ('this_value_is_>16'); + +EXPLAIN +SELECT * FROM t1 WHERE pk IN ('this_value_is_>16', 'and_so_is_this_one'); +SELECT * FROM t1 WHERE pk IN ('this_value_is_>16', 'and_so_is_this_one'); + + +eval CREATE TABLE t2 ( a VARCHAR(1), KEY (a) ) CHARSET=$charset COLLATE=$collation; + +INSERT INTO t2 VALUES (NULL), ('a'), ('b'), ('æ'), ('ß'), ('s'); +INSERT INTO t2 SELECT 'x' FROM t2; +INSERT INTO t2 SELECT 'x' FROM t2; + +ANALYZE TABLE t2; + +--echo # Strings containing soft hyphen (U+00AD) will not match for UTF-16 + +EXPLAIN +SELECT * FROM t2 WHERE a IN ('ae', concat(_utf8mb4 x'c2ad', 'b'), 'ss'); +SELECT * FROM t2 WHERE a IN ('ae', concat(_utf8mb4 x'c2ad', 'b'), 'ss'); + +EXPLAIN +SELECT * FROM t2 WHERE a IN (concat(_utf8mb4 x'c2ad', 'ae'), 'ss'); +SELECT * FROM t2 WHERE a IN (concat(_utf8mb4 x'c2ad', 'ae'), 'ss'); + + +EXPLAIN +SELECT * FROM t2 WHERE a IN (concat(_utf8mb4 x'c2ad', 'ae', _utf8mb4 x'c2ad'), 'ss'); +SELECT * FROM t2 WHERE a IN (concat(_utf8mb4 x'c2ad', 'ae', _utf8mb4 x'c2ad'), 'ss'); + +EXPLAIN +SELECT * FROM t2 WHERE a = 'ae' OR a = concat(_utf8mb4 x'c2ad', 'b') OR a = 'ss'; +SELECT * FROM t2 WHERE a = 'ae' OR a = concat(_utf8mb4 x'c2ad', 'b') OR a = 'ss'; + +--echo # The plan is unstable in this case, however it always uses an index, and results are consistent. +--replace_column 5 X 10 X +EXPLAIN +SELECT * FROM t2 WHERE a IN ('ae', concat(repeat(_utf8mb4 x'c2ad', 2), 'b', repeat(_utf8mb4 x'c2ad', 2))); +--echo # Adding handler statistics to show that execution is also consistent. +FLUSH STATUS; +SELECT * FROM t2 WHERE a IN ('ae', concat(repeat(_utf8mb4 x'c2ad', 2), 'b', repeat(_utf8mb4 x'c2ad', 2))); +SHOW STATUS LIKE 'Handler_read_%'; + + +eval CREATE TABLE t3 ( a VARCHAR(768), KEY(a)) CHARSET=$charset COLLATE=$collation; + +INSERT INTO t3 VALUES( repeat('æ', 767) ), ( repeat('æ', 768) ); + +ANALYZE TABLE t3; + +EXPLAIN +SELECT 1 FROM t3 WHERE a IN ( 'a', repeat('æ', 767) ); +SELECT 1 FROM t3 WHERE a IN ( 'a', repeat('æ', 767) ); + +EXPLAIN +SELECT 1 FROM t3 WHERE a IN ( 'a', repeat('ae', 768) ); +SELECT 1 FROM t3 WHERE a IN ( 'a', repeat('ae', 768) ); + +EXPLAIN +SELECT 1 FROM t3 WHERE a IN ( 'a', repeat('ae', 769) ); +SELECT 1 FROM t3 WHERE a IN ( 'a', repeat('ae', 769) ); + + +eval CREATE TABLE t4 ( a VARCHAR(100), KEY(a(50))) CHARSET=$charset COLLATE=$collation; + +INSERT INTO t4 VALUES ( repeat('æ', 98) ), ( repeat('æ', 99) ), ( repeat('æ', 100) ); +INSERT INTO t4 VALUES ( concat(repeat( 'a', 50 ), repeat( 'æ', 50 )) ); + +ANALYZE TABLE t4; + +EXPLAIN +SELECT 1 FROM t4 WHERE a IN ( 'a', repeat('æ', 98) ); +SELECT 1 FROM t4 WHERE a IN ( 'a', repeat('æ', 98) ); + + +eval CREATE TABLE t5 ( a VARCHAR(16383), KEY(a(768))) CHARSET=$charset COLLATE=$collation; + +INSERT INTO t5 VALUES( repeat('æ', 16383) ), ( repeat('æ', 16382) ), ( repeat('æ', 16381) ); + +ANALYZE TABLE t5; + +EXPLAIN +SELECT 1 FROM t5 WHERE a IN ( 'a', repeat('æ', 16381) ); +SELECT 1 FROM t5 WHERE a IN ( 'a', repeat('æ', 16381) ); + +EXPLAIN +SELECT 1 FROM t5 WHERE a IN ( 'a', repeat('æ', 16382) ); +SELECT 1 FROM t5 WHERE a IN ( 'a', repeat('æ', 16382) ); + +EXPLAIN +SELECT 1 FROM t5 WHERE a IN ( 'a', repeat('æ', 16383) ); +SELECT 1 FROM t5 WHERE a IN ( 'a', repeat('æ', 16383) ); + + +eval CREATE TABLE t6 ( a VARCHAR(6), KEY(a(3)) ) CHARSET=$charset COLLATE=$collation; + +INSERT INTO t6 VALUES ('aaaaaa'), ('æaaaaa'), ('ææaaaa'), ('æææaaa'), ('ææææaa'), ('æææææa'), ('ææææææ'), + ('😊aaaaa'), ('😊æaaaa'), ('😊😊aaaa'), ('😊😊æaaa'), ('😊😊😊aaa'); + +ANALYZE TABLE t6; + +EXPLAIN +SELECT * FROM t6 WHERE a IN ( '', 'aaaaaa' ); +SELECT * FROM t6 WHERE a IN ( '', 'aaaaaa' ); + +EXPLAIN +SELECT * FROM t6 WHERE a IN ( '', 'æaaaaa' ); +SELECT * FROM t6 WHERE a IN ( '', 'æaaaaa' ); + +EXPLAIN +SELECT * FROM t6 WHERE a IN ( '', 'ææaaaa' ); +SELECT * FROM t6 WHERE a IN ( '', 'ææaaaa' ); + +EXPLAIN +SELECT * FROM t6 WHERE a IN ( '', 'æææaaa' ); +SELECT * FROM t6 WHERE a IN ( '', 'æææaaa' ); + +EXPLAIN +SELECT * FROM t6 WHERE a IN ( '', 'ææææaa' ); +SELECT * FROM t6 WHERE a IN ( '', 'ææææaa' ); + +EXPLAIN +SELECT * FROM t6 WHERE a IN ( '', 'æææææa' ); +SELECT * FROM t6 WHERE a IN ( '', 'æææææa' ); + +EXPLAIN +SELECT * FROM t6 WHERE a IN ( '', 'ææææææ' ); +SELECT * FROM t6 WHERE a IN ( '', 'ææææææ' ); + +EXPLAIN +SELECT * FROM t6 WHERE a IN ( '', '😊aaaaa'); +SELECT * FROM t6 WHERE a IN ( '', '😊aaaaa'); + +EXPLAIN +SELECT * FROM t6 WHERE a IN ( '', '😊æaaaa'); +SELECT * FROM t6 WHERE a IN ( '', '😊æaaaa'); + +EXPLAIN +SELECT * FROM t6 WHERE a IN ( '', '😊😊aaaa'); +SELECT * FROM t6 WHERE a IN ( '', '😊😊aaaa'); + +EXPLAIN +SELECT * FROM t6 WHERE a IN ( '', '😊😊æaaa'); +SELECT * FROM t6 WHERE a IN ( '', '😊😊😊aaa'); + +EXPLAIN +SELECT * FROM t6 WHERE a IN ('aaaaaa', 'æaaaaa', 'ææaaaa', 'æææaaa', 'ææææaa', 'æææææa', 'ææææææ'); +SELECT * FROM t6 WHERE a IN ('aaaaaa', 'æaaaaa', 'ææaaaa', 'æææaaa', 'ææææaa', 'æææææa', 'ææææææ'); + +EXPLAIN +SELECT * FROM t6 WHERE a IN + ('aaaaaa', 'æaaaaa', 'ææaaaa', 'æææaaa', 'ææææaa', 'æææææa', 'ææææææ', + '😊aaaaa', '😊æaaaa', '😊😊aaaa', '😊😊æaaa', '😊😊😊aaa'); +SELECT * FROM t6 WHERE a IN + ('aaaaaa', 'æaaaaa', 'ææaaaa', 'æææaaa', 'ææææaa', 'æææææa', 'ææææææ', + '😊aaaaa', '😊æaaaa', '😊😊aaaa', '😊😊æaaa', '😊😊😊aaa'); + + +DROP TABLE t1, t2, t3, t4, t5, t6; diff --git a/mysql-test/r/type_varchar.result b/mysql-test/r/type_varchar.result deleted file mode 100644 index 0a84407c1b93..000000000000 --- a/mysql-test/r/type_varchar.result +++ /dev/null @@ -1,582 +0,0 @@ -drop table if exists t1, t2; -create table t1 (v varchar(30), c char(3), e enum('abc','def','ghi'), t text); -show create table t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `v` varchar(30) DEFAULT NULL, - `c` char(3) DEFAULT NULL, - `e` enum('abc','def','ghi') DEFAULT NULL, - `t` text -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci -insert into t1 values ('abc', 'de', 'ghi', 'jkl'); -insert into t1 values ('abc ', 'de ', 'ghi', 'jkl '); -insert into t1 values ('abc ', 'd ', 'ghi', 'jkl '); -select length(v),length(c),length(e),length(t) from t1; -length(v) length(c) length(e) length(t) -3 2 3 3 -4 2 3 4 -7 1 3 7 -drop table t1; -create table t1 (v varchar(20)) charset latin1; -insert into t1 values('a '); -select v='a' from t1; -v='a' -1 -select binary v='a' from t1; -binary v='a' -0 -Warnings: -Warning 1287 'BINARY expr' is deprecated and will be removed in a future release. Please use CAST instead -select binary v='a ' from t1; -binary v='a ' -1 -Warnings: -Warning 1287 'BINARY expr' is deprecated and will be removed in a future release. Please use CAST instead -insert into t1 values('a'); -alter table t1 add primary key (v); -ERROR 23000: Duplicate entry 'a ' for key 't1.PRIMARY' -drop table t1; -create table t1 (v varbinary(20)); -insert into t1 values('a'); -insert into t1 values('a '); -alter table t1 add primary key (v); -drop table t1; -create table t1 (v varchar(254), index (v)) charset latin1; -insert into t1 values ("This is a test "); -insert into t1 values ("Some sample data"); -insert into t1 values (" garbage "); -insert into t1 values (" This is a test "); -insert into t1 values ("This is a test"); -insert into t1 values ("Hello world"); -insert into t1 values ("Foo bar"); -insert into t1 values ("This is a test"); -insert into t1 values ("MySQL varchar test"); -insert into t1 values ("test MySQL varchar"); -insert into t1 values ("This is a long string to have some random length data included"); -insert into t1 values ("Short string"); -insert into t1 values ("VSS"); -insert into t1 values ("Some samples"); -insert into t1 values ("Bar foo"); -insert into t1 values ("Bye"); -ANALYZE TABLE t1; -Table Op Msg_type Msg_text -test.t1 analyze status OK -select * from t1 where v like 'This is a test' order by v; -v -This is a test -This is a test -select * from t1 where v='This is a test' order by v; -v -This is a test -This is a test -This is a test -select * from t1 where v like 'S%' order by v; -v -Short string -Some sample data -Some samples -explain select * from t1 where v like 'This is a test' order by v; -id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 NULL range v v 257 NULL 3 100.00 Using where; Using index -Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`v` AS `v` from `test`.`t1` where (`test`.`t1`.`v` like 'This is a test') order by `test`.`t1`.`v` -Helper line 1 for --skip_if_hypergraph diffing -explain select * from t1 where v='This is a test' order by v; -id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 NULL ref v v 257 const 3 100.00 Using index -Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`v` AS `v` from `test`.`t1` where (`test`.`t1`.`v` = 'This is a test') order by `test`.`t1`.`v` -Helper line 2 for --skip_if_hypergraph diffing -explain select * from t1 where v like 'S%' order by v; -id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 NULL range v v 257 NULL 3 100.00 Using where; Using index -Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`v` AS `v` from `test`.`t1` where (`test`.`t1`.`v` like 'S%') order by `test`.`t1`.`v` -alter table t1 change v v varchar(255); -ANALYZE TABLE t1; -Table Op Msg_type Msg_text -test.t1 analyze status OK -select * from t1 where v like 'This is a test' order by v; -v -This is a test -This is a test -select * from t1 where v='This is a test' order by v; -v -This is a test -This is a test -This is a test -select * from t1 where v like 'S%' order by v; -v -Short string -Some sample data -Some samples -explain select * from t1 where v like 'This is a test' order by v; -id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 NULL range v v 258 NULL 3 100.00 Using where; Using index -Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`v` AS `v` from `test`.`t1` where (`test`.`t1`.`v` like 'This is a test') order by `test`.`t1`.`v` -Helper line 1 for --skip_if_hypergraph diffing -explain select * from t1 where v='This is a test' order by v; -id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 NULL ref v v 258 const 3 100.00 Using index -Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`v` AS `v` from `test`.`t1` where (`test`.`t1`.`v` = 'This is a test') order by `test`.`t1`.`v` -Helper line 2 for --skip_if_hypergraph diffing -explain select * from t1 where v like 'S%' order by v; -id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 NULL range v v 258 NULL 3 100.00 Using where; Using index -Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`v` AS `v` from `test`.`t1` where (`test`.`t1`.`v` like 'S%') order by `test`.`t1`.`v` -alter table t1 change v v varchar(256); -ANALYZE TABLE t1; -Table Op Msg_type Msg_text -test.t1 analyze status OK -select * from t1 where v like 'This is a test' order by v; -v -This is a test -This is a test -select * from t1 where v='This is a test' order by v; -v -This is a test -This is a test -This is a test -select * from t1 where v like 'S%' order by v; -v -Short string -Some sample data -Some samples -explain select * from t1 where v like 'This is a test' order by v; -id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 NULL range v v 259 NULL 3 100.00 Using where; Using index -Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`v` AS `v` from `test`.`t1` where (`test`.`t1`.`v` like 'This is a test') order by `test`.`t1`.`v` -Helper line 1 for --skip_if_hypergraph diffing -explain select * from t1 where v='This is a test' order by v; -id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 NULL ref v v 259 const 3 100.00 Using index -Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`v` AS `v` from `test`.`t1` where (`test`.`t1`.`v` = 'This is a test') order by `test`.`t1`.`v` -Helper line 2 for --skip_if_hypergraph diffing -explain select * from t1 where v like 'S%' order by v; -id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 NULL range v v 259 NULL 3 100.00 Using where; Using index -Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`v` AS `v` from `test`.`t1` where (`test`.`t1`.`v` like 'S%') order by `test`.`t1`.`v` -alter table t1 change v v varchar(257); -ANALYZE TABLE t1; -Table Op Msg_type Msg_text -test.t1 analyze status OK -select * from t1 where v like 'This is a test' order by v; -v -This is a test -This is a test -select * from t1 where v='This is a test' order by v; -v -This is a test -This is a test -This is a test -select * from t1 where v like 'S%' order by v; -v -Short string -Some sample data -Some samples -explain select * from t1 where v like 'This is a test' order by v; -id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 NULL range v v 260 NULL 3 100.00 Using where; Using index -Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`v` AS `v` from `test`.`t1` where (`test`.`t1`.`v` like 'This is a test') order by `test`.`t1`.`v` -Helper line 1 for --skip_if_hypergraph diffing -explain select * from t1 where v='This is a test' order by v; -id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 NULL ref v v 260 const 3 100.00 Using index -Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`v` AS `v` from `test`.`t1` where (`test`.`t1`.`v` = 'This is a test') order by `test`.`t1`.`v` -Helper line 2 for --skip_if_hypergraph diffing -explain select * from t1 where v like 'S%' order by v; -id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 NULL range v v 260 NULL 3 100.00 Using where; Using index -Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`v` AS `v` from `test`.`t1` where (`test`.`t1`.`v` like 'S%') order by `test`.`t1`.`v` -alter table t1 change v v varchar(258); -ANALYZE TABLE t1; -Table Op Msg_type Msg_text -test.t1 analyze status OK -select * from t1 where v like 'This is a test' order by v; -v -This is a test -This is a test -select * from t1 where v='This is a test' order by v; -v -This is a test -This is a test -This is a test -select * from t1 where v like 'S%' order by v; -v -Short string -Some sample data -Some samples -explain select * from t1 where v like 'This is a test' order by v; -id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 NULL range v v 261 NULL 3 100.00 Using where; Using index -Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`v` AS `v` from `test`.`t1` where (`test`.`t1`.`v` like 'This is a test') order by `test`.`t1`.`v` -Helper line 1 for --skip_if_hypergraph diffing -explain select * from t1 where v='This is a test' order by v; -id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 NULL ref v v 261 const 3 100.00 Using index -Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`v` AS `v` from `test`.`t1` where (`test`.`t1`.`v` = 'This is a test') order by `test`.`t1`.`v` -Helper line 2 for --skip_if_hypergraph diffing -explain select * from t1 where v like 'S%' order by v; -id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 NULL range v v 261 NULL 3 100.00 Using where; Using index -Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`v` AS `v` from `test`.`t1` where (`test`.`t1`.`v` like 'S%') order by `test`.`t1`.`v` -alter table t1 change v v varchar(259); -ANALYZE TABLE t1; -Table Op Msg_type Msg_text -test.t1 analyze status OK -select * from t1 where v like 'This is a test' order by v; -v -This is a test -This is a test -select * from t1 where v='This is a test' order by v; -v -This is a test -This is a test -This is a test -select * from t1 where v like 'S%' order by v; -v -Short string -Some sample data -Some samples -explain select * from t1 where v like 'This is a test' order by v; -id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 NULL range v v 262 NULL 3 100.00 Using where; Using index -Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`v` AS `v` from `test`.`t1` where (`test`.`t1`.`v` like 'This is a test') order by `test`.`t1`.`v` -Helper line 3 for --skip_if_hypergraph diffing -explain select * from t1 where v='This is a test' order by v; -id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 NULL ref v v 262 const 3 100.00 Using index -Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`v` AS `v` from `test`.`t1` where (`test`.`t1`.`v` = 'This is a test') order by `test`.`t1`.`v` -Helper line 4 for --skip_if_hypergraph diffing -explain select * from t1 where v like 'S%' order by v; -id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 NULL range v v 262 NULL 3 100.00 Using where; Using index -Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`v` AS `v` from `test`.`t1` where (`test`.`t1`.`v` like 'S%') order by `test`.`t1`.`v` -alter table t1 change v v varchar(258); -ANALYZE TABLE t1; -Table Op Msg_type Msg_text -test.t1 analyze status OK -select * from t1 where v like 'This is a test' order by v; -v -This is a test -This is a test -select * from t1 where v='This is a test' order by v; -v -This is a test -This is a test -This is a test -select * from t1 where v like 'S%' order by v; -v -Short string -Some sample data -Some samples -explain select * from t1 where v like 'This is a test' order by v; -id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 NULL range v v 261 NULL 3 100.00 Using where; Using index -Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`v` AS `v` from `test`.`t1` where (`test`.`t1`.`v` like 'This is a test') order by `test`.`t1`.`v` -Helper line 3 for --skip_if_hypergraph diffing -explain select * from t1 where v='This is a test' order by v; -id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 NULL ref v v 261 const 3 100.00 Using index -Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`v` AS `v` from `test`.`t1` where (`test`.`t1`.`v` = 'This is a test') order by `test`.`t1`.`v` -Helper line 4 for --skip_if_hypergraph diffing -explain select * from t1 where v like 'S%' order by v; -id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 NULL range v v 261 NULL 3 100.00 Using where; Using index -Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`v` AS `v` from `test`.`t1` where (`test`.`t1`.`v` like 'S%') order by `test`.`t1`.`v` -alter table t1 change v v varchar(257); -ANALYZE TABLE t1; -Table Op Msg_type Msg_text -test.t1 analyze status OK -select * from t1 where v like 'This is a test' order by v; -v -This is a test -This is a test -select * from t1 where v='This is a test' order by v; -v -This is a test -This is a test -This is a test -select * from t1 where v like 'S%' order by v; -v -Short string -Some sample data -Some samples -explain select * from t1 where v like 'This is a test' order by v; -id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 NULL range v v 260 NULL 3 100.00 Using where; Using index -Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`v` AS `v` from `test`.`t1` where (`test`.`t1`.`v` like 'This is a test') order by `test`.`t1`.`v` -Helper line 3 for --skip_if_hypergraph diffing -explain select * from t1 where v='This is a test' order by v; -id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 NULL ref v v 260 const 3 100.00 Using index -Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`v` AS `v` from `test`.`t1` where (`test`.`t1`.`v` = 'This is a test') order by `test`.`t1`.`v` -Helper line 4 for --skip_if_hypergraph diffing -explain select * from t1 where v like 'S%' order by v; -id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 NULL range v v 260 NULL 3 100.00 Using where; Using index -Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`v` AS `v` from `test`.`t1` where (`test`.`t1`.`v` like 'S%') order by `test`.`t1`.`v` -alter table t1 change v v varchar(256); -ANALYZE TABLE t1; -Table Op Msg_type Msg_text -test.t1 analyze status OK -select * from t1 where v like 'This is a test' order by v; -v -This is a test -This is a test -select * from t1 where v='This is a test' order by v; -v -This is a test -This is a test -This is a test -select * from t1 where v like 'S%' order by v; -v -Short string -Some sample data -Some samples -explain select * from t1 where v like 'This is a test' order by v; -id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 NULL range v v 259 NULL 3 100.00 Using where; Using index -Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`v` AS `v` from `test`.`t1` where (`test`.`t1`.`v` like 'This is a test') order by `test`.`t1`.`v` -Helper line 3 for --skip_if_hypergraph diffing -explain select * from t1 where v='This is a test' order by v; -id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 NULL ref v v 259 const 3 100.00 Using index -Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`v` AS `v` from `test`.`t1` where (`test`.`t1`.`v` = 'This is a test') order by `test`.`t1`.`v` -Helper line 4 for --skip_if_hypergraph diffing -explain select * from t1 where v like 'S%' order by v; -id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 NULL range v v 259 NULL 3 100.00 Using where; Using index -Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`v` AS `v` from `test`.`t1` where (`test`.`t1`.`v` like 'S%') order by `test`.`t1`.`v` -alter table t1 change v v varchar(255); -ANALYZE TABLE t1; -Table Op Msg_type Msg_text -test.t1 analyze status OK -select * from t1 where v like 'This is a test' order by v; -v -This is a test -This is a test -select * from t1 where v='This is a test' order by v; -v -This is a test -This is a test -This is a test -select * from t1 where v like 'S%' order by v; -v -Short string -Some sample data -Some samples -explain select * from t1 where v like 'This is a test' order by v; -id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 NULL range v v 258 NULL 3 100.00 Using where; Using index -Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`v` AS `v` from `test`.`t1` where (`test`.`t1`.`v` like 'This is a test') order by `test`.`t1`.`v` -Helper line 3 for --skip_if_hypergraph diffing -explain select * from t1 where v='This is a test' order by v; -id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 NULL ref v v 258 const 3 100.00 Using index -Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`v` AS `v` from `test`.`t1` where (`test`.`t1`.`v` = 'This is a test') order by `test`.`t1`.`v` -Helper line 4 for --skip_if_hypergraph diffing -explain select * from t1 where v like 'S%' order by v; -id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 NULL range v v 258 NULL 3 100.00 Using where; Using index -Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`v` AS `v` from `test`.`t1` where (`test`.`t1`.`v` like 'S%') order by `test`.`t1`.`v` -alter table t1 change v v varchar(254); -ANALYZE TABLE t1; -Table Op Msg_type Msg_text -test.t1 analyze status OK -select * from t1 where v like 'This is a test' order by v; -v -This is a test -This is a test -select * from t1 where v='This is a test' order by v; -v -This is a test -This is a test -This is a test -select * from t1 where v like 'S%' order by v; -v -Short string -Some sample data -Some samples -explain select * from t1 where v like 'This is a test' order by v; -id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 NULL range v v 257 NULL 3 100.00 Using where; Using index -Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`v` AS `v` from `test`.`t1` where (`test`.`t1`.`v` like 'This is a test') order by `test`.`t1`.`v` -Helper line 3 for --skip_if_hypergraph diffing -explain select * from t1 where v='This is a test' order by v; -id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 NULL ref v v 257 const 3 100.00 Using index -Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`v` AS `v` from `test`.`t1` where (`test`.`t1`.`v` = 'This is a test') order by `test`.`t1`.`v` -Helper line 4 for --skip_if_hypergraph diffing -explain select * from t1 where v like 'S%' order by v; -id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 NULL range v v 257 NULL 3 100.00 Using where; Using index -Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`v` AS `v` from `test`.`t1` where (`test`.`t1`.`v` like 'S%') order by `test`.`t1`.`v` -alter table t1 change v v varchar(253); -alter table t1 change v v varchar(254), drop key v; -alter table t1 change v v varchar(300), add key (v(10)); -select * from t1 where v like 'This is a test' order by v; -v -This is a test -This is a test -select * from t1 where v='This is a test' order by v; -v -This is a test -This is a test -This is a test -select * from t1 where v like 'S%' order by v; -v -Short string -Some sample data -Some samples -explain select * from t1 where v like 'This is a test' order by v; -id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 NULL range v v 13 NULL 4 100.00 Using where; Using filesort -Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`v` AS `v` from `test`.`t1` where (`test`.`t1`.`v` like 'This is a test') order by `test`.`t1`.`v` -Helper line 5 for --skip_if_hypergraph diffing -explain select * from t1 where v='This is a test' order by v; -id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 NULL ref v v 13 const 4 100.00 Using where -Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`v` AS `v` from `test`.`t1` where (`test`.`t1`.`v` = 'This is a test') order by `test`.`t1`.`v` -Helper line 6 for --skip_if_hypergraph diffing -explain select * from t1 where v like 'S%' order by v; -id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 NULL range v v 13 NULL 3 100.00 Using where; Using filesort -Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`v` AS `v` from `test`.`t1` where (`test`.`t1`.`v` like 'S%') order by `test`.`t1`.`v` -drop table t1; -create table t1 (pkcol varchar(16), othercol varchar(16), primary key (pkcol)); -insert into t1 values ('test', 'something'); -update t1 set othercol='somethingelse' where pkcol='test'; -select * from t1; -pkcol othercol -test somethingelse -drop table t1; -create table t1 (a int, b varchar(12)); -insert into t1 values (1, 'A'), (22, NULL); -create table t2 (a int); -insert into t2 values (22), (22); -select t1.a, t1.b, min(t1.b) from t1 inner join t2 ON t2.a = t1.a -group by t1.b, t1.a; -a b min(t1.b) -22 NULL NULL -drop table t1, t2; -create table t1 (f1 varchar(65500)) charset latin1; -create index index1 on t1(f1(10)); -show create table t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `f1` varchar(65500) DEFAULT NULL, - KEY `index1` (`f1`(10)) -) ENGINE=InnoDB DEFAULT CHARSET=latin1 -alter table t1 modify f1 varchar(255); -show create table t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `f1` varchar(255) DEFAULT NULL, - KEY `index1` (`f1`(10)) -) ENGINE=InnoDB DEFAULT CHARSET=latin1 -alter table t1 modify f1 tinytext; -show create table t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `f1` tinytext, - KEY `index1` (`f1`(10)) -) ENGINE=InnoDB DEFAULT CHARSET=latin1 -drop table t1; -DROP TABLE IF EXISTS t1; -CREATE TABLE t1(f1 VARCHAR(100) DEFAULT 'test'); -INSERT INTO t1 VALUES(SUBSTR(f1, 1, 3)); -DROP TABLE IF EXISTS t1; -CREATE TABLE t1(f1 CHAR(100) DEFAULT 'test'); -INSERT INTO t1 VALUES(SUBSTR(f1, 1, 3)); -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 (a CHAR(2)); -INSERT INTO t1 VALUES (10), (50), (30), ('1a'), (60), ('t'); -SELECT a,(a + 0) FROM t1 ORDER BY a; -a (a + 0) -10 10 -1a 1 -30 30 -50 50 -60 60 -t 0 -Warnings: -Warning 1292 Truncated incorrect DOUBLE value: '1a' -Warning 1292 Truncated incorrect DOUBLE value: 't' -SELECT a,(a DIV 2) FROM t1 ORDER BY a; -a (a DIV 2) -10 5 -1a 0 -30 15 -50 25 -60 30 -t 0 -Warnings: -Warning 1292 Truncated incorrect DECIMAL value: '1a' -Warning 1366 Incorrect DECIMAL value: '0' for column '' at row -1 -Warning 1292 Truncated incorrect DECIMAL value: 't' -SELECT a,CAST(a AS SIGNED) FROM t1 ORDER BY a; -a CAST(a AS SIGNED) -10 10 -1a 1 -30 30 -50 50 -60 60 -t 0 -Warnings: -Warning 1292 Truncated incorrect INTEGER value: '1a' -Warning 1292 Truncated incorrect INTEGER value: 't' -DROP TABLE t1; -CREATE TABLE t1 (a VARCHAR(16)); -INSERT INTO t1 VALUES ('5'), ('s'), (''); -SELECT 5 = a FROM t1; -5 = a -1 -0 -0 -Warnings: -Warning 1292 Truncated incorrect DOUBLE value: 's' -DROP TABLE t1; -CREATE TABLE t1 (a CHAR(16)); -INSERT INTO t1 VALUES ('5'), ('s'), (''); -SELECT 5 = a FROM t1; -5 = a -1 -0 -0 -Warnings: -Warning 1292 Truncated incorrect DOUBLE value: 's' -DROP TABLE t1; diff --git a/mysql-test/suite/percona/r/bug118009.result b/mysql-test/suite/percona/r/bug118009.result new file mode 100644 index 000000000000..dde7a456352e --- /dev/null +++ b/mysql-test/suite/percona/r/bug118009.result @@ -0,0 +1,744 @@ +# +# Bug#118009: SELECT query on primary key column deteriorates to full +# table scan when filter involves too long string +# +CREATE TABLE t1 ( pk VARCHAR(16) NOT NULL PRIMARY KEY ) CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; +INSERT INTO t1 VALUES ('abc'), ('def'), ('ghi'), ('jkl'), ('mno'); +ANALYZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 analyze status OK +EXPLAIN +SELECT * FROM t1 WHERE pk IN ('abc', 'this_value_is_>16', 'def'); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 NULL index PRIMARY PRIMARY 66 NULL 5 60.00 Using where; Using index +Warnings: +Note 1003 /* select#1 */ select `test`.`t1`.`pk` AS `pk` from `test`.`t1` where (`test`.`t1`.`pk` in ('abc','this_value_is_>16','def')) +SELECT * FROM t1 WHERE pk IN ('abc', 'this_value_is_>16', 'def'); +pk +abc +def +EXPLAIN +SELECT * FROM t1 WHERE pk IN ('abc', 'this_value_is_>16', 'def'); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 NULL index PRIMARY PRIMARY 66 NULL 5 60.00 Using where; Using index +Warnings: +Note 1003 /* select#1 */ select `test`.`t1`.`pk` AS `pk` from `test`.`t1` where (`test`.`t1`.`pk` in ('abc','this_value_is_>16','def')) +SELECT * FROM t1 WHERE pk IN ('abc', 'this_value_is_>16', 'def'); +pk +abc +def +EXPLAIN +SELECT * FROM t1 WHERE pk IN ('this_value_is_>16'); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table +Warnings: +Note 1003 /* select#1 */ select NULL AS `pk` from `test`.`t1` where multiple equal('this_value_is_>16', NULL) +SELECT * FROM t1 WHERE pk IN ('this_value_is_>16'); +pk +EXPLAIN +SELECT * FROM t1 WHERE pk IN ('this_value_is_>16', 'and_so_is_this_one'); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 NULL range PRIMARY PRIMARY 66 NULL 2 100.00 Using where; Using index +Warnings: +Note 1003 /* select#1 */ select `test`.`t1`.`pk` AS `pk` from `test`.`t1` where (`test`.`t1`.`pk` in ('this_value_is_>16','and_so_is_this_one')) +SELECT * FROM t1 WHERE pk IN ('this_value_is_>16', 'and_so_is_this_one'); +pk +CREATE TABLE t2 ( a VARCHAR(1), KEY (a) ) CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; +INSERT INTO t2 VALUES (NULL), ('a'), ('b'), ('æ'), ('ß'), ('s'); +INSERT INTO t2 SELECT 'x' FROM t2; +INSERT INTO t2 SELECT 'x' FROM t2; +ANALYZE TABLE t2; +Table Op Msg_type Msg_text +test.t2 analyze status OK +# Strings containing soft hyphen (U+00AD) will not match for UTF-16 +EXPLAIN +SELECT * FROM t2 WHERE a IN ('ae', concat(_utf8mb4 x'c2ad', 'b'), 'ss'); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t2 NULL range a a 7 NULL 3 100.00 Using where; Using index +Warnings: +Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a` from `test`.`t2` where (`test`.`t2`.`a` in ('ae',(concat(_utf8mb4'\xC2\xAD','b')),'ss')) +SELECT * FROM t2 WHERE a IN ('ae', concat(_utf8mb4 x'c2ad', 'b'), 'ss'); +a +æ +b +ß +EXPLAIN +SELECT * FROM t2 WHERE a IN (concat(_utf8mb4 x'c2ad', 'ae'), 'ss'); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t2 NULL range a a 7 NULL 2 100.00 Using where; Using index +Warnings: +Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a` from `test`.`t2` where (`test`.`t2`.`a` in ((concat(_utf8mb4'\xC2\xAD','ae')),'ss')) +SELECT * FROM t2 WHERE a IN (concat(_utf8mb4 x'c2ad', 'ae'), 'ss'); +a +æ +ß +EXPLAIN +SELECT * FROM t2 WHERE a IN (concat(_utf8mb4 x'c2ad', 'ae', _utf8mb4 x'c2ad'), 'ss'); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t2 NULL range a a 7 NULL 2 100.00 Using where; Using index +Warnings: +Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a` from `test`.`t2` where (`test`.`t2`.`a` in ((concat(_utf8mb4'\xC2\xAD','ae',_utf8mb4'\xC2\xAD')),'ss')) +SELECT * FROM t2 WHERE a IN (concat(_utf8mb4 x'c2ad', 'ae', _utf8mb4 x'c2ad'), 'ss'); +a +æ +ß +EXPLAIN +SELECT * FROM t2 WHERE a = 'ae' OR a = concat(_utf8mb4 x'c2ad', 'b') OR a = 'ss'; +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t2 NULL range a a 7 NULL 3 100.00 Using where; Using index +Warnings: +Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a` from `test`.`t2` where ((`test`.`t2`.`a` = 'ae') or (`test`.`t2`.`a` = (concat(_utf8mb4'\xC2\xAD','b'))) or (`test`.`t2`.`a` = 'ss')) +SELECT * FROM t2 WHERE a = 'ae' OR a = concat(_utf8mb4 x'c2ad', 'b') OR a = 'ss'; +a +æ +b +ß +# The plan is unstable in this case, however it always uses an index, and results are consistent. +EXPLAIN +SELECT * FROM t2 WHERE a IN ('ae', concat(repeat(_utf8mb4 x'c2ad', 2), 'b', repeat(_utf8mb4 x'c2ad', 2))); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t2 NULL X a a 7 NULL X 100.00 Using where; Using index +Warnings: +Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a` from `test`.`t2` where (`test`.`t2`.`a` in ('ae',(concat(repeat(_utf8mb4'\xC2\xAD',2),'b',repeat(_utf8mb4'\xC2\xAD',2))))) +# Adding handler statistics to show that execution is also consistent. +FLUSH STATUS; +SELECT * FROM t2 WHERE a IN ('ae', concat(repeat(_utf8mb4 x'c2ad', 2), 'b', repeat(_utf8mb4 x'c2ad', 2))); +a +æ +SHOW STATUS LIKE 'Handler_read_%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 2 +Handler_read_last 0 +Handler_read_next 1 +Handler_read_prev 0 +Handler_read_rnd 0 +Handler_read_rnd_next 0 +CREATE TABLE t3 ( a VARCHAR(768), KEY(a)) CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; +INSERT INTO t3 VALUES( repeat('æ', 767) ), ( repeat('æ', 768) ); +ANALYZE TABLE t3; +Table Op Msg_type Msg_text +test.t3 analyze status OK +EXPLAIN +SELECT 1 FROM t3 WHERE a IN ( 'a', repeat('æ', 767) ); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t3 NULL index a a 3075 NULL 2 100.00 Using where; Using index +Warnings: +Note 1003 /* select#1 */ select 1 AS `1` from `test`.`t3` where (`test`.`t3`.`a` in ('a',(repeat('æ',767)))) +SELECT 1 FROM t3 WHERE a IN ( 'a', repeat('æ', 767) ); +1 +1 +EXPLAIN +SELECT 1 FROM t3 WHERE a IN ( 'a', repeat('ae', 768) ); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t3 NULL index a a 3075 NULL 2 100.00 Using where; Using index +Warnings: +Note 1003 /* select#1 */ select 1 AS `1` from `test`.`t3` where (`test`.`t3`.`a` in ('a',(repeat('ae',768)))) +SELECT 1 FROM t3 WHERE a IN ( 'a', repeat('ae', 768) ); +1 +1 +EXPLAIN +SELECT 1 FROM t3 WHERE a IN ( 'a', repeat('ae', 769) ); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t3 NULL index a a 3075 NULL 2 100.00 Using where; Using index +Warnings: +Note 1003 /* select#1 */ select 1 AS `1` from `test`.`t3` where (`test`.`t3`.`a` in ('a',(repeat('ae',769)))) +SELECT 1 FROM t3 WHERE a IN ( 'a', repeat('ae', 769) ); +1 +CREATE TABLE t4 ( a VARCHAR(100), KEY(a(50))) CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; +INSERT INTO t4 VALUES ( repeat('æ', 98) ), ( repeat('æ', 99) ), ( repeat('æ', 100) ); +INSERT INTO t4 VALUES ( concat(repeat( 'a', 50 ), repeat( 'æ', 50 )) ); +ANALYZE TABLE t4; +Table Op Msg_type Msg_text +test.t4 analyze status OK +EXPLAIN +SELECT 1 FROM t4 WHERE a IN ( 'a', repeat('æ', 98) ); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t4 NULL range a a 203 NULL 4 100.00 Using where +Warnings: +Note 1003 /* select#1 */ select 1 AS `1` from `test`.`t4` where (`test`.`t4`.`a` in ('a',(repeat('æ',98)))) +SELECT 1 FROM t4 WHERE a IN ( 'a', repeat('æ', 98) ); +1 +1 +CREATE TABLE t5 ( a VARCHAR(16383), KEY(a(768))) CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; +INSERT INTO t5 VALUES( repeat('æ', 16383) ), ( repeat('æ', 16382) ), ( repeat('æ', 16381) ); +ANALYZE TABLE t5; +Table Op Msg_type Msg_text +test.t5 analyze status OK +EXPLAIN +SELECT 1 FROM t5 WHERE a IN ( 'a', repeat('æ', 16381) ); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t5 NULL range a a 3075 NULL 4 100.00 Using where +Warnings: +Note 1003 /* select#1 */ select 1 AS `1` from `test`.`t5` where (`test`.`t5`.`a` in ('a',(repeat('æ',16381)))) +SELECT 1 FROM t5 WHERE a IN ( 'a', repeat('æ', 16381) ); +1 +1 +EXPLAIN +SELECT 1 FROM t5 WHERE a IN ( 'a', repeat('æ', 16382) ); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t5 NULL range a a 3075 NULL 4 100.00 Using where +Warnings: +Note 1003 /* select#1 */ select 1 AS `1` from `test`.`t5` where (`test`.`t5`.`a` in ('a',(repeat('æ',16382)))) +SELECT 1 FROM t5 WHERE a IN ( 'a', repeat('æ', 16382) ); +1 +1 +EXPLAIN +SELECT 1 FROM t5 WHERE a IN ( 'a', repeat('æ', 16383) ); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t5 NULL range a a 3075 NULL 4 100.00 Using where +Warnings: +Note 1003 /* select#1 */ select 1 AS `1` from `test`.`t5` where (`test`.`t5`.`a` in ('a',(repeat('æ',16383)))) +SELECT 1 FROM t5 WHERE a IN ( 'a', repeat('æ', 16383) ); +1 +1 +CREATE TABLE t6 ( a VARCHAR(6), KEY(a(3)) ) CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; +INSERT INTO t6 VALUES ('aaaaaa'), ('æaaaaa'), ('ææaaaa'), ('æææaaa'), ('ææææaa'), ('æææææa'), ('ææææææ'), +('😊aaaaa'), ('😊æaaaa'), ('😊😊aaaa'), ('😊😊æaaa'), ('😊😊😊aaa'); +ANALYZE TABLE t6; +Table Op Msg_type Msg_text +test.t6 analyze status OK +EXPLAIN +SELECT * FROM t6 WHERE a IN ( '', 'aaaaaa' ); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t6 NULL range a a 15 NULL 2 100.00 Using where +Warnings: +Note 1003 /* select#1 */ select `test`.`t6`.`a` AS `a` from `test`.`t6` where (`test`.`t6`.`a` in ('','aaaaaa')) +SELECT * FROM t6 WHERE a IN ( '', 'aaaaaa' ); +a +aaaaaa +EXPLAIN +SELECT * FROM t6 WHERE a IN ( '', 'æaaaaa' ); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t6 NULL range a a 15 NULL 2 100.00 Using where +Warnings: +Note 1003 /* select#1 */ select `test`.`t6`.`a` AS `a` from `test`.`t6` where (`test`.`t6`.`a` in ('','æaaaaa')) +SELECT * FROM t6 WHERE a IN ( '', 'æaaaaa' ); +a +æaaaaa +EXPLAIN +SELECT * FROM t6 WHERE a IN ( '', 'ææaaaa' ); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t6 NULL range a a 15 NULL 2 100.00 Using where +Warnings: +Note 1003 /* select#1 */ select `test`.`t6`.`a` AS `a` from `test`.`t6` where (`test`.`t6`.`a` in ('','ææaaaa')) +SELECT * FROM t6 WHERE a IN ( '', 'ææaaaa' ); +a +ææaaaa +EXPLAIN +SELECT * FROM t6 WHERE a IN ( '', 'æææaaa' ); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t6 NULL range a a 15 NULL 5 100.00 Using where +Warnings: +Note 1003 /* select#1 */ select `test`.`t6`.`a` AS `a` from `test`.`t6` where (`test`.`t6`.`a` in ('','æææaaa')) +SELECT * FROM t6 WHERE a IN ( '', 'æææaaa' ); +a +æææaaa +EXPLAIN +SELECT * FROM t6 WHERE a IN ( '', 'ææææaa' ); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t6 NULL range a a 15 NULL 5 100.00 Using where +Warnings: +Note 1003 /* select#1 */ select `test`.`t6`.`a` AS `a` from `test`.`t6` where (`test`.`t6`.`a` in ('','ææææaa')) +SELECT * FROM t6 WHERE a IN ( '', 'ææææaa' ); +a +ææææaa +EXPLAIN +SELECT * FROM t6 WHERE a IN ( '', 'æææææa' ); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t6 NULL range a a 15 NULL 5 100.00 Using where +Warnings: +Note 1003 /* select#1 */ select `test`.`t6`.`a` AS `a` from `test`.`t6` where (`test`.`t6`.`a` in ('','æææææa')) +SELECT * FROM t6 WHERE a IN ( '', 'æææææa' ); +a +æææææa +EXPLAIN +SELECT * FROM t6 WHERE a IN ( '', 'ææææææ' ); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t6 NULL range a a 15 NULL 5 100.00 Using where +Warnings: +Note 1003 /* select#1 */ select `test`.`t6`.`a` AS `a` from `test`.`t6` where (`test`.`t6`.`a` in ('','ææææææ')) +SELECT * FROM t6 WHERE a IN ( '', 'ææææææ' ); +a +ææææææ +EXPLAIN +SELECT * FROM t6 WHERE a IN ( '', '😊aaaaa'); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t6 NULL range a a 15 NULL 2 100.00 Using where +Warnings: +Warning 1300 Cannot convert string '\xF0\x9F\x98\x8Aaa...' from utf8mb4 to utf8mb3 +Note 1003 /* select#1 */ select `test`.`t6`.`a` AS `a` from `test`.`t6` where (`test`.`t6`.`a` in ('','?aaaaa')) +SELECT * FROM t6 WHERE a IN ( '', '😊aaaaa'); +a +😊aaaaa +EXPLAIN +SELECT * FROM t6 WHERE a IN ( '', '😊æaaaa'); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t6 NULL range a a 15 NULL 2 100.00 Using where +Warnings: +Warning 1300 Cannot convert string '\xF0\x9F\x98\x8A\xC3\xA6...' from utf8mb4 to utf8mb3 +Note 1003 /* select#1 */ select `test`.`t6`.`a` AS `a` from `test`.`t6` where (`test`.`t6`.`a` in ('','?æaaaa')) +SELECT * FROM t6 WHERE a IN ( '', '😊æaaaa'); +a +😊æaaaa +EXPLAIN +SELECT * FROM t6 WHERE a IN ( '', '😊😊aaaa'); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t6 NULL range a a 15 NULL 2 100.00 Using where +Warnings: +Warning 1300 Cannot convert string '\xF0\x9F\x98\x8A\xF0\x9F...' from utf8mb4 to utf8mb3 +Note 1003 /* select#1 */ select `test`.`t6`.`a` AS `a` from `test`.`t6` where (`test`.`t6`.`a` in ('','??aaaa')) +SELECT * FROM t6 WHERE a IN ( '', '😊😊aaaa'); +a +😊😊aaaa +EXPLAIN +SELECT * FROM t6 WHERE a IN ( '', '😊😊æaaa'); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t6 NULL range a a 15 NULL 2 100.00 Using where +Warnings: +Warning 1300 Cannot convert string '\xF0\x9F\x98\x8A\xF0\x9F...' from utf8mb4 to utf8mb3 +Note 1003 /* select#1 */ select `test`.`t6`.`a` AS `a` from `test`.`t6` where (`test`.`t6`.`a` in ('','??æaaa')) +SELECT * FROM t6 WHERE a IN ( '', '😊😊😊aaa'); +a +😊😊😊aaa +EXPLAIN +SELECT * FROM t6 WHERE a IN ('aaaaaa', 'æaaaaa', 'ææaaaa', 'æææaaa', 'ææææaa', 'æææææa', 'ææææææ'); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t6 NULL range a a 15 NULL 7 100.00 Using where +Warnings: +Note 1003 /* select#1 */ select `test`.`t6`.`a` AS `a` from `test`.`t6` where (`test`.`t6`.`a` in ('aaaaaa','æaaaaa','ææaaaa','æææaaa','ææææaa','æææææa','ææææææ')) +SELECT * FROM t6 WHERE a IN ('aaaaaa', 'æaaaaa', 'ææaaaa', 'æææaaa', 'ææææaa', 'æææææa', 'ææææææ'); +a +aaaaaa +æaaaaa +ææaaaa +æææaaa +ææææaa +æææææa +ææææææ +EXPLAIN +SELECT * FROM t6 WHERE a IN +('aaaaaa', 'æaaaaa', 'ææaaaa', 'æææaaa', 'ææææaa', 'æææææa', 'ææææææ', +'😊aaaaa', '😊æaaaa', '😊😊aaaa', '😊😊æaaa', '😊😊😊aaa'); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t6 NULL ALL a NULL NULL NULL 12 100.00 Using where +Warnings: +Warning 1300 Cannot convert string '\xF0\x9F\x98\x8Aaa...' from utf8mb4 to utf8mb3 +Warning 1300 Cannot convert string '\xF0\x9F\x98\x8A\xC3\xA6...' from utf8mb4 to utf8mb3 +Warning 1300 Cannot convert string '\xF0\x9F\x98\x8A\xF0\x9F...' from utf8mb4 to utf8mb3 +Warning 1300 Cannot convert string '\xF0\x9F\x98\x8A\xF0\x9F...' from utf8mb4 to utf8mb3 +Warning 1300 Cannot convert string '\xF0\x9F\x98\x8A\xF0\x9F...' from utf8mb4 to utf8mb3 +Note 1003 /* select#1 */ select `test`.`t6`.`a` AS `a` from `test`.`t6` where (`test`.`t6`.`a` in ('aaaaaa','æaaaaa','ææaaaa','æææaaa','ææææaa','æææææa','ææææææ','?aaaaa','?æaaaa','??aaaa','??æaaa','???aaa')) +SELECT * FROM t6 WHERE a IN +('aaaaaa', 'æaaaaa', 'ææaaaa', 'æææaaa', 'ææææaa', 'æææææa', 'ææææææ', +'😊aaaaa', '😊æaaaa', '😊😊aaaa', '😊😊æaaa', '😊😊😊aaa'); +a +aaaaaa +æaaaaa +ææaaaa +æææaaa +ææææaa +æææææa +ææææææ +😊aaaaa +😊æaaaa +😊😊aaaa +😊😊æaaa +😊😊😊aaa +DROP TABLE t1, t2, t3, t4, t5, t6; +CREATE TABLE t1 ( pk VARCHAR(16) NOT NULL PRIMARY KEY ) CHARSET=utf16 COLLATE=utf16_unicode_520_ci; +INSERT INTO t1 VALUES ('abc'), ('def'), ('ghi'), ('jkl'), ('mno'); +ANALYZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 analyze status OK +EXPLAIN +SELECT * FROM t1 WHERE pk IN ('abc', 'this_value_is_>16', 'def'); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 NULL index PRIMARY PRIMARY 66 NULL 5 60.00 Using where; Using index +Warnings: +Note 1003 /* select#1 */ select `test`.`t1`.`pk` AS `pk` from `test`.`t1` where (`test`.`t1`.`pk` in ('abc','this_value_is_>16','def')) +SELECT * FROM t1 WHERE pk IN ('abc', 'this_value_is_>16', 'def'); +pk +abc +def +EXPLAIN +SELECT * FROM t1 WHERE pk IN ('abc', 'this_value_is_>16', 'def'); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 NULL index PRIMARY PRIMARY 66 NULL 5 60.00 Using where; Using index +Warnings: +Note 1003 /* select#1 */ select `test`.`t1`.`pk` AS `pk` from `test`.`t1` where (`test`.`t1`.`pk` in ('abc','this_value_is_>16','def')) +SELECT * FROM t1 WHERE pk IN ('abc', 'this_value_is_>16', 'def'); +pk +abc +def +EXPLAIN +SELECT * FROM t1 WHERE pk IN ('this_value_is_>16'); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table +Warnings: +Note 1003 /* select#1 */ select NULL AS `pk` from `test`.`t1` where (NULL = 'this_value_is_>16') +SELECT * FROM t1 WHERE pk IN ('this_value_is_>16'); +pk +EXPLAIN +SELECT * FROM t1 WHERE pk IN ('this_value_is_>16', 'and_so_is_this_one'); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 NULL range PRIMARY PRIMARY 66 NULL 2 100.00 Using where; Using index +Warnings: +Note 1003 /* select#1 */ select `test`.`t1`.`pk` AS `pk` from `test`.`t1` where (`test`.`t1`.`pk` in ('this_value_is_>16','and_so_is_this_one')) +SELECT * FROM t1 WHERE pk IN ('this_value_is_>16', 'and_so_is_this_one'); +pk +CREATE TABLE t2 ( a VARCHAR(1), KEY (a) ) CHARSET=utf16 COLLATE=utf16_unicode_520_ci; +INSERT INTO t2 VALUES (NULL), ('a'), ('b'), ('æ'), ('ß'), ('s'); +INSERT INTO t2 SELECT 'x' FROM t2; +INSERT INTO t2 SELECT 'x' FROM t2; +ANALYZE TABLE t2; +Table Op Msg_type Msg_text +test.t2 analyze status OK +# Strings containing soft hyphen (U+00AD) will not match for UTF-16 +EXPLAIN +SELECT * FROM t2 WHERE a IN ('ae', concat(_utf8mb4 x'c2ad', 'b'), 'ss'); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t2 NULL range a a 7 NULL 3 100.00 Using where; Using index +Warnings: +Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a` from `test`.`t2` where (`test`.`t2`.`a` in ('ae',(convert(concat(_utf8mb4'\xC2\xAD','b') using utf16)),'ss')) +SELECT * FROM t2 WHERE a IN ('ae', concat(_utf8mb4 x'c2ad', 'b'), 'ss'); +a +æ +ß +EXPLAIN +SELECT * FROM t2 WHERE a IN (concat(_utf8mb4 x'c2ad', 'ae'), 'ss'); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t2 NULL range a a 7 NULL 2 100.00 Using where; Using index +Warnings: +Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a` from `test`.`t2` where (`test`.`t2`.`a` in ((convert(concat(_utf8mb4'\xC2\xAD','ae') using utf16)),'ss')) +SELECT * FROM t2 WHERE a IN (concat(_utf8mb4 x'c2ad', 'ae'), 'ss'); +a +ß +EXPLAIN +SELECT * FROM t2 WHERE a IN (concat(_utf8mb4 x'c2ad', 'ae', _utf8mb4 x'c2ad'), 'ss'); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t2 NULL range a a 7 NULL 2 100.00 Using where; Using index +Warnings: +Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a` from `test`.`t2` where (`test`.`t2`.`a` in ((convert(concat(_utf8mb4'\xC2\xAD','ae',_utf8mb4'\xC2\xAD') using utf16)),'ss')) +SELECT * FROM t2 WHERE a IN (concat(_utf8mb4 x'c2ad', 'ae', _utf8mb4 x'c2ad'), 'ss'); +a +ß +EXPLAIN +SELECT * FROM t2 WHERE a = 'ae' OR a = concat(_utf8mb4 x'c2ad', 'b') OR a = 'ss'; +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t2 NULL range a a 7 NULL 3 100.00 Using where; Using index +Warnings: +Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a` from `test`.`t2` where ((`test`.`t2`.`a` = 'ae') or (`test`.`t2`.`a` = (convert(concat(_utf8mb4'\xC2\xAD','b') using utf16))) or (`test`.`t2`.`a` = 'ss')) +SELECT * FROM t2 WHERE a = 'ae' OR a = concat(_utf8mb4 x'c2ad', 'b') OR a = 'ss'; +a +æ +ß +# The plan is unstable in this case, however it always uses an index, and results are consistent. +EXPLAIN +SELECT * FROM t2 WHERE a IN ('ae', concat(repeat(_utf8mb4 x'c2ad', 2), 'b', repeat(_utf8mb4 x'c2ad', 2))); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t2 NULL X a a 7 NULL X 100.00 Using where; Using index +Warnings: +Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a` from `test`.`t2` where (`test`.`t2`.`a` in ('ae',(convert(concat(repeat(_utf8mb4'\xC2\xAD',2),'b',repeat(_utf8mb4'\xC2\xAD',2)) using utf16)))) +# Adding handler statistics to show that execution is also consistent. +FLUSH STATUS; +SELECT * FROM t2 WHERE a IN ('ae', concat(repeat(_utf8mb4 x'c2ad', 2), 'b', repeat(_utf8mb4 x'c2ad', 2))); +a +æ +SHOW STATUS LIKE 'Handler_read_%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 2 +Handler_read_last 0 +Handler_read_next 1 +Handler_read_prev 0 +Handler_read_rnd 0 +Handler_read_rnd_next 0 +CREATE TABLE t3 ( a VARCHAR(768), KEY(a)) CHARSET=utf16 COLLATE=utf16_unicode_520_ci; +INSERT INTO t3 VALUES( repeat('æ', 767) ), ( repeat('æ', 768) ); +ANALYZE TABLE t3; +Table Op Msg_type Msg_text +test.t3 analyze status OK +EXPLAIN +SELECT 1 FROM t3 WHERE a IN ( 'a', repeat('æ', 767) ); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t3 NULL index a a 3075 NULL 2 100.00 Using where; Using index +Warnings: +Note 1003 /* select#1 */ select 1 AS `1` from `test`.`t3` where (`test`.`t3`.`a` in ('a',(convert(repeat('æ',767) using utf16)))) +SELECT 1 FROM t3 WHERE a IN ( 'a', repeat('æ', 767) ); +1 +1 +EXPLAIN +SELECT 1 FROM t3 WHERE a IN ( 'a', repeat('ae', 768) ); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t3 NULL index a a 3075 NULL 2 100.00 Using where; Using index +Warnings: +Note 1003 /* select#1 */ select 1 AS `1` from `test`.`t3` where (`test`.`t3`.`a` in ('a',(convert(repeat('ae',768) using utf16)))) +SELECT 1 FROM t3 WHERE a IN ( 'a', repeat('ae', 768) ); +1 +1 +EXPLAIN +SELECT 1 FROM t3 WHERE a IN ( 'a', repeat('ae', 769) ); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t3 NULL index a a 3075 NULL 2 100.00 Using where; Using index +Warnings: +Note 1003 /* select#1 */ select 1 AS `1` from `test`.`t3` where (`test`.`t3`.`a` in ('a',(convert(repeat('ae',769) using utf16)))) +SELECT 1 FROM t3 WHERE a IN ( 'a', repeat('ae', 769) ); +1 +CREATE TABLE t4 ( a VARCHAR(100), KEY(a(50))) CHARSET=utf16 COLLATE=utf16_unicode_520_ci; +INSERT INTO t4 VALUES ( repeat('æ', 98) ), ( repeat('æ', 99) ), ( repeat('æ', 100) ); +INSERT INTO t4 VALUES ( concat(repeat( 'a', 50 ), repeat( 'æ', 50 )) ); +ANALYZE TABLE t4; +Table Op Msg_type Msg_text +test.t4 analyze status OK +EXPLAIN +SELECT 1 FROM t4 WHERE a IN ( 'a', repeat('æ', 98) ); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t4 NULL range a a 203 NULL 4 100.00 Using where +Warnings: +Note 1003 /* select#1 */ select 1 AS `1` from `test`.`t4` where (`test`.`t4`.`a` in ('a',(convert(repeat('æ',98) using utf16)))) +SELECT 1 FROM t4 WHERE a IN ( 'a', repeat('æ', 98) ); +1 +1 +CREATE TABLE t5 ( a VARCHAR(16383), KEY(a(768))) CHARSET=utf16 COLLATE=utf16_unicode_520_ci; +INSERT INTO t5 VALUES( repeat('æ', 16383) ), ( repeat('æ', 16382) ), ( repeat('æ', 16381) ); +ANALYZE TABLE t5; +Table Op Msg_type Msg_text +test.t5 analyze status OK +EXPLAIN +SELECT 1 FROM t5 WHERE a IN ( 'a', repeat('æ', 16381) ); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t5 NULL range a a 3075 NULL 4 100.00 Using where +Warnings: +Note 1003 /* select#1 */ select 1 AS `1` from `test`.`t5` where (`test`.`t5`.`a` in ('a',(convert(repeat('æ',16381) using utf16)))) +SELECT 1 FROM t5 WHERE a IN ( 'a', repeat('æ', 16381) ); +1 +1 +EXPLAIN +SELECT 1 FROM t5 WHERE a IN ( 'a', repeat('æ', 16382) ); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t5 NULL range a a 3075 NULL 4 100.00 Using where +Warnings: +Note 1003 /* select#1 */ select 1 AS `1` from `test`.`t5` where (`test`.`t5`.`a` in ('a',(convert(repeat('æ',16382) using utf16)))) +SELECT 1 FROM t5 WHERE a IN ( 'a', repeat('æ', 16382) ); +1 +1 +EXPLAIN +SELECT 1 FROM t5 WHERE a IN ( 'a', repeat('æ', 16383) ); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t5 NULL range a a 3075 NULL 4 100.00 Using where +Warnings: +Note 1003 /* select#1 */ select 1 AS `1` from `test`.`t5` where (`test`.`t5`.`a` in ('a',(convert(repeat('æ',16383) using utf16)))) +SELECT 1 FROM t5 WHERE a IN ( 'a', repeat('æ', 16383) ); +1 +1 +CREATE TABLE t6 ( a VARCHAR(6), KEY(a(3)) ) CHARSET=utf16 COLLATE=utf16_unicode_520_ci; +INSERT INTO t6 VALUES ('aaaaaa'), ('æaaaaa'), ('ææaaaa'), ('æææaaa'), ('ææææaa'), ('æææææa'), ('ææææææ'), +('😊aaaaa'), ('😊æaaaa'), ('😊😊aaaa'), ('😊😊æaaa'), ('😊😊😊aaa'); +ANALYZE TABLE t6; +Table Op Msg_type Msg_text +test.t6 analyze status OK +EXPLAIN +SELECT * FROM t6 WHERE a IN ( '', 'aaaaaa' ); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t6 NULL range a a 15 NULL 2 100.00 Using where +Warnings: +Note 1003 /* select#1 */ select `test`.`t6`.`a` AS `a` from `test`.`t6` where (`test`.`t6`.`a` in ('','aaaaaa')) +SELECT * FROM t6 WHERE a IN ( '', 'aaaaaa' ); +a +aaaaaa +EXPLAIN +SELECT * FROM t6 WHERE a IN ( '', 'æaaaaa' ); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t6 NULL range a a 15 NULL 2 100.00 Using where +Warnings: +Note 1003 /* select#1 */ select `test`.`t6`.`a` AS `a` from `test`.`t6` where (`test`.`t6`.`a` in ('','æaaaaa')) +SELECT * FROM t6 WHERE a IN ( '', 'æaaaaa' ); +a +æaaaaa +EXPLAIN +SELECT * FROM t6 WHERE a IN ( '', 'ææaaaa' ); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t6 NULL range a a 15 NULL 2 100.00 Using where +Warnings: +Note 1003 /* select#1 */ select `test`.`t6`.`a` AS `a` from `test`.`t6` where (`test`.`t6`.`a` in ('','ææaaaa')) +SELECT * FROM t6 WHERE a IN ( '', 'ææaaaa' ); +a +ææaaaa +EXPLAIN +SELECT * FROM t6 WHERE a IN ( '', 'æææaaa' ); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t6 NULL range a a 15 NULL 5 100.00 Using where +Warnings: +Note 1003 /* select#1 */ select `test`.`t6`.`a` AS `a` from `test`.`t6` where (`test`.`t6`.`a` in ('','æææaaa')) +SELECT * FROM t6 WHERE a IN ( '', 'æææaaa' ); +a +æææaaa +EXPLAIN +SELECT * FROM t6 WHERE a IN ( '', 'ææææaa' ); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t6 NULL range a a 15 NULL 5 100.00 Using where +Warnings: +Note 1003 /* select#1 */ select `test`.`t6`.`a` AS `a` from `test`.`t6` where (`test`.`t6`.`a` in ('','ææææaa')) +SELECT * FROM t6 WHERE a IN ( '', 'ææææaa' ); +a +ææææaa +EXPLAIN +SELECT * FROM t6 WHERE a IN ( '', 'æææææa' ); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t6 NULL range a a 15 NULL 5 100.00 Using where +Warnings: +Note 1003 /* select#1 */ select `test`.`t6`.`a` AS `a` from `test`.`t6` where (`test`.`t6`.`a` in ('','æææææa')) +SELECT * FROM t6 WHERE a IN ( '', 'æææææa' ); +a +æææææa +EXPLAIN +SELECT * FROM t6 WHERE a IN ( '', 'ææææææ' ); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t6 NULL range a a 15 NULL 5 100.00 Using where +Warnings: +Note 1003 /* select#1 */ select `test`.`t6`.`a` AS `a` from `test`.`t6` where (`test`.`t6`.`a` in ('','ææææææ')) +SELECT * FROM t6 WHERE a IN ( '', 'ææææææ' ); +a +ææææææ +EXPLAIN +SELECT * FROM t6 WHERE a IN ( '', '😊aaaaa'); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t6 NULL range a a 15 NULL 2 100.00 Using where +Warnings: +Warning 1300 Cannot convert string '\xD8\x3D\xDE\x0A\x00\x61...' from utf16 to utf8mb3 +Note 1003 /* select#1 */ select `test`.`t6`.`a` AS `a` from `test`.`t6` where (`test`.`t6`.`a` in ('','?aaaaa')) +SELECT * FROM t6 WHERE a IN ( '', '😊aaaaa'); +a +😊aaaaa +EXPLAIN +SELECT * FROM t6 WHERE a IN ( '', '😊æaaaa'); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t6 NULL range a a 15 NULL 2 100.00 Using where +Warnings: +Warning 1300 Cannot convert string '\xD8\x3D\xDE\x0A\x00\xE6...' from utf16 to utf8mb3 +Note 1003 /* select#1 */ select `test`.`t6`.`a` AS `a` from `test`.`t6` where (`test`.`t6`.`a` in ('','?æaaaa')) +SELECT * FROM t6 WHERE a IN ( '', '😊æaaaa'); +a +😊æaaaa +EXPLAIN +SELECT * FROM t6 WHERE a IN ( '', '😊😊aaaa'); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t6 NULL range a a 15 NULL 2 100.00 Using where +Warnings: +Warning 1300 Cannot convert string '\xD8\x3D\xDE\x0A\xD8\x3D...' from utf16 to utf8mb3 +Note 1003 /* select#1 */ select `test`.`t6`.`a` AS `a` from `test`.`t6` where (`test`.`t6`.`a` in ('','??aaaa')) +SELECT * FROM t6 WHERE a IN ( '', '😊😊aaaa'); +a +😊😊aaaa +EXPLAIN +SELECT * FROM t6 WHERE a IN ( '', '😊😊æaaa'); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t6 NULL range a a 15 NULL 2 100.00 Using where +Warnings: +Warning 1300 Cannot convert string '\xD8\x3D\xDE\x0A\xD8\x3D...' from utf16 to utf8mb3 +Note 1003 /* select#1 */ select `test`.`t6`.`a` AS `a` from `test`.`t6` where (`test`.`t6`.`a` in ('','??æaaa')) +SELECT * FROM t6 WHERE a IN ( '', '😊😊😊aaa'); +a +😊😊😊aaa +EXPLAIN +SELECT * FROM t6 WHERE a IN ('aaaaaa', 'æaaaaa', 'ææaaaa', 'æææaaa', 'ææææaa', 'æææææa', 'ææææææ'); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t6 NULL range a a 15 NULL 7 100.00 Using where +Warnings: +Note 1003 /* select#1 */ select `test`.`t6`.`a` AS `a` from `test`.`t6` where (`test`.`t6`.`a` in ('aaaaaa','æaaaaa','ææaaaa','æææaaa','ææææaa','æææææa','ææææææ')) +SELECT * FROM t6 WHERE a IN ('aaaaaa', 'æaaaaa', 'ææaaaa', 'æææaaa', 'ææææaa', 'æææææa', 'ææææææ'); +a +aaaaaa +æaaaaa +ææaaaa +æææaaa +ææææaa +æææææa +ææææææ +EXPLAIN +SELECT * FROM t6 WHERE a IN +('aaaaaa', 'æaaaaa', 'ææaaaa', 'æææaaa', 'ææææaa', 'æææææa', 'ææææææ', +'😊aaaaa', '😊æaaaa', '😊😊aaaa', '😊😊æaaa', '😊😊😊aaa'); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t6 NULL ALL a NULL NULL NULL 12 100.00 Using where +Warnings: +Warning 1300 Cannot convert string '\xD8\x3D\xDE\x0A\x00\x61...' from utf16 to utf8mb3 +Warning 1300 Cannot convert string '\xD8\x3D\xDE\x0A\x00\xE6...' from utf16 to utf8mb3 +Warning 1300 Cannot convert string '\xD8\x3D\xDE\x0A\xD8\x3D...' from utf16 to utf8mb3 +Warning 1300 Cannot convert string '\xD8\x3D\xDE\x0A\xD8\x3D...' from utf16 to utf8mb3 +Warning 1300 Cannot convert string '\xD8\x3D\xDE\x0A\xD8\x3D...' from utf16 to utf8mb3 +Note 1003 /* select#1 */ select `test`.`t6`.`a` AS `a` from `test`.`t6` where (`test`.`t6`.`a` in ('aaaaaa','æaaaaa','ææaaaa','æææaaa','ææææaa','æææææa','ææææææ','?aaaaa','?æaaaa','??aaaa','??æaaa','???aaa')) +SELECT * FROM t6 WHERE a IN +('aaaaaa', 'æaaaaa', 'ææaaaa', 'æææaaa', 'ææææaa', 'æææææa', 'ææææææ', +'😊aaaaa', '😊æaaaa', '😊😊aaaa', '😊😊æaaa', '😊😊😊aaa'); +a +aaaaaa +æaaaaa +ææaaaa +æææaaa +ææææaa +æææææa +ææææææ +😊aaaaa +😊æaaaa +😊😊aaaa +😊😊æaaa +😊😊😊aaa +DROP TABLE t1, t2, t3, t4, t5, t6; +CREATE TABLE t1 ( +a VARCHAR(3), +KEY(a) +); +INSERT INTO t1 VALUES ('aaa'), ('bbb'), ('ccc'); +CREATE FUNCTION bad_str() RETURNS VARBINARY(10) DETERMINISTIC NO SQL +BEGIN +RETURN concat('aaaaaaaaaa', UNHEX('73C080')); # invalid overlong UTF-8 NUL +END // +SELECT * FROM t1 WHERE a < bad_str(); +ERROR 22001: Data too long for column 'bad_str' at row 1 +DROP FUNCTION bad_str; +DROP TABLE t1; +SET NAMES utf8 COLLATE utf8_general_ci; +Warnings: +Warning 3719 'utf8' is currently an alias for the character set UTF8MB3, but will be an alias for UTF8MB4 in a future release. Please consider using UTF8MB4 in order to be unambiguous. +Warning 3778 'utf8mb3_general_ci' is a collation of the deprecated character set UTF8MB3. Please consider using UTF8MB4 with an appropriate collation instead. +CREATE TABLE t1 ( +a VARCHAR(2) CHARACTER SET utf8mb3, +KEY ( a ) +); +Warnings: +Warning 1287 'utf8mb3' is deprecated and will be removed in a future release. Please use utf8mb4 instead +INSERT INTO t1 VALUES ( 'a' ), ( 'b' ); +EXPLAIN +SELECT a FROM t1 WHERE a < 'a😊'; +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 NULL index a a 9 NULL 2 50.00 Using where; Using index +Warnings: +Warning 1300 Invalid utf8mb3 character string: 'F09F98' +Warning 1366 Incorrect string value: '\xF0\x9F\x98\x8A' for column 'a' at row 1 +Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` < 'a😊') +SELECT a FROM t1 WHERE a < 'a😊'; +a +a +Warnings: +Warning 1300 Invalid utf8mb3 character string: 'F09F98' +Warning 1366 Incorrect string value: '\xF0\x9F\x98\x8A' for column 'a' at row 1 +EXPLAIN +SELECT a FROM t1 FORCE KEY ( a ) WHERE a < CHAR( 'a😊' USING utf8mb3 ) ORDER BY a; +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 NULL range a a 9 NULL 1 100.00 Using where; Using index +Warnings: +Warning 1287 'utf8mb3' is deprecated and will be removed in a future release. Please use utf8mb4 instead +Warning 1300 Invalid utf8mb3 character string: 'F09F98' +Warning 1292 Truncated incorrect INTEGER value: 'a????' +Warning 1292 Truncated incorrect INTEGER value: 'a????' +Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` FORCE INDEX (`a`) where (`test`.`t1`.`a` < (char('a😊'))) order by `test`.`t1`.`a` +SELECT a FROM t1 FORCE KEY ( a ) WHERE a < CHAR( 'a😊' USING utf8mb3 ) ORDER BY a; +a +Warnings: +Warning 1287 'utf8mb3' is deprecated and will be removed in a future release. Please use utf8mb4 instead +Warning 1300 Invalid utf8mb3 character string: 'F09F98' +Warning 1292 Truncated incorrect INTEGER value: 'a????' +Warning 1292 Truncated incorrect INTEGER value: 'a????' +DROP TABLE t1; diff --git a/mysql-test/suite/percona/t/bug118009.test b/mysql-test/suite/percona/t/bug118009.test new file mode 100644 index 000000000000..a15d0edd7f30 --- /dev/null +++ b/mysql-test/suite/percona/t/bug118009.test @@ -0,0 +1,54 @@ +--echo # +--echo # Bug#118009: SELECT query on primary key column deteriorates to full +--echo # table scan when filter involves too long string +--echo # + +--let charset=utf8mb4 +--let collation=utf8mb4_0900_ai_ci +--source include/oversized_varchar_key.inc + +--let charset=utf16 +--let collation=utf16_unicode_520_ci +--source include/oversized_varchar_key.inc + +CREATE TABLE t1 ( + a VARCHAR(3), + KEY(a) +); + +INSERT INTO t1 VALUES ('aaa'), ('bbb'), ('ccc'); + +DELIMITER //; + +CREATE FUNCTION bad_str() RETURNS VARBINARY(10) DETERMINISTIC NO SQL +BEGIN + RETURN concat('aaaaaaaaaa', UNHEX('73C080')); # invalid overlong UTF-8 NUL +END // + +DELIMITER ;// + +--error ER_DATA_TOO_LONG +SELECT * FROM t1 WHERE a < bad_str(); + +DROP FUNCTION bad_str; +DROP TABLE t1; + +SET NAMES utf8 COLLATE utf8_general_ci; + + +CREATE TABLE t1 ( + a VARCHAR(2) CHARACTER SET utf8mb3, + KEY ( a ) +); + +INSERT INTO t1 VALUES ( 'a' ), ( 'b' ); + +EXPLAIN +SELECT a FROM t1 WHERE a < 'a😊'; +SELECT a FROM t1 WHERE a < 'a😊'; + +EXPLAIN +SELECT a FROM t1 FORCE KEY ( a ) WHERE a < CHAR( 'a😊' USING utf8mb3 ) ORDER BY a; +SELECT a FROM t1 FORCE KEY ( a ) WHERE a < CHAR( 'a😊' USING utf8mb3 ) ORDER BY a; + +DROP TABLE t1; diff --git a/mysql-test/t/type_varchar.test b/mysql-test/t/type_varchar.test deleted file mode 100644 index 9a52ae98ab76..000000000000 --- a/mysql-test/t/type_varchar.test +++ /dev/null @@ -1,180 +0,0 @@ ---disable_query_log -call mtr.add_suppression(".InnoDB. Compare_key: table=.*, index=.*"); ---enable_query_log - ---disable_warnings -drop table if exists t1, t2; ---enable_warnings - -create table t1 (v varchar(30), c char(3), e enum('abc','def','ghi'), t text); -show create table t1; -insert into t1 values ('abc', 'de', 'ghi', 'jkl'); -insert into t1 values ('abc ', 'de ', 'ghi', 'jkl '); -insert into t1 values ('abc ', 'd ', 'ghi', 'jkl '); -select length(v),length(c),length(e),length(t) from t1; -drop table t1; - -create table t1 (v varchar(20)) charset latin1; -insert into t1 values('a '); -select v='a' from t1; -select binary v='a' from t1; -select binary v='a ' from t1; -insert into t1 values('a'); ---error ER_DUP_ENTRY -alter table t1 add primary key (v); -drop table t1; -create table t1 (v varbinary(20)); -insert into t1 values('a'); -insert into t1 values('a '); -alter table t1 add primary key (v); -drop table t1; - -# -# Test with varchar of lengths 254,255,256,258 & 258 to ensure we do not -# have any problems with varchar with one or two byte length_bytes -# - -create table t1 (v varchar(254), index (v)) charset latin1; -insert into t1 values ("This is a test "); -insert into t1 values ("Some sample data"); -insert into t1 values (" garbage "); -insert into t1 values (" This is a test "); -insert into t1 values ("This is a test"); -insert into t1 values ("Hello world"); -insert into t1 values ("Foo bar"); -insert into t1 values ("This is a test"); -insert into t1 values ("MySQL varchar test"); -insert into t1 values ("test MySQL varchar"); -insert into t1 values ("This is a long string to have some random length data included"); -insert into t1 values ("Short string"); -insert into t1 values ("VSS"); -insert into t1 values ("Some samples"); -insert into t1 values ("Bar foo"); -insert into t1 values ("Bye"); -let $i= 255; -let $j= 5; -while ($j) -{ - ANALYZE TABLE t1; - select * from t1 where v like 'This is a test' order by v; - select * from t1 where v='This is a test' order by v; - select * from t1 where v like 'S%' order by v; - explain select * from t1 where v like 'This is a test' order by v; - --echo Helper line 1 for --skip_if_hypergraph diffing - explain select * from t1 where v='This is a test' order by v; - --echo Helper line 2 for --skip_if_hypergraph diffing - explain select * from t1 where v like 'S%' order by v; - eval alter table t1 change v v varchar($i); - inc $i; - dec $j; -} -let $i= 258; -let $j= 6; -while ($j) -{ - ANALYZE TABLE t1; - select * from t1 where v like 'This is a test' order by v; - select * from t1 where v='This is a test' order by v; - select * from t1 where v like 'S%' order by v; - explain select * from t1 where v like 'This is a test' order by v; - --echo Helper line 3 for --skip_if_hypergraph diffing - explain select * from t1 where v='This is a test' order by v; - --echo Helper line 4 for --skip_if_hypergraph diffing - explain select * from t1 where v like 'S%' order by v; - eval alter table t1 change v v varchar($i); - dec $i; - dec $j; -} -alter table t1 change v v varchar(254), drop key v; - -# Test with length(varchar) > 256 and key < 256 (to ensure things works with -# different kind of packing - -alter table t1 change v v varchar(300), add key (v(10)); -select * from t1 where v like 'This is a test' order by v; -select * from t1 where v='This is a test' order by v; -select * from t1 where v like 'S%' order by v; -explain select * from t1 where v like 'This is a test' order by v; ---echo Helper line 5 for --skip_if_hypergraph diffing -explain select * from t1 where v='This is a test' order by v; ---echo Helper line 6 for --skip_if_hypergraph diffing -explain select * from t1 where v like 'S%' order by v; -drop table t1; - -# -# bug#9339 - meaningless Field_varstring::get_key_image -# -create table t1 (pkcol varchar(16), othercol varchar(16), primary key (pkcol)); -insert into t1 values ('test', 'something'); -update t1 set othercol='somethingelse' where pkcol='test'; -select * from t1; -drop table t1; - -# -# Bug #9489: problems with key handling -# - -create table t1 (a int, b varchar(12)); -insert into t1 values (1, 'A'), (22, NULL); -create table t2 (a int); -insert into t2 values (22), (22); -select t1.a, t1.b, min(t1.b) from t1 inner join t2 ON t2.a = t1.a - group by t1.b, t1.a; -drop table t1, t2; - -# -# Bug #10543: convert varchar with index to text -# -create table t1 (f1 varchar(65500)) charset latin1; -create index index1 on t1(f1(10)); -show create table t1; -alter table t1 modify f1 varchar(255); -show create table t1; -alter table t1 modify f1 tinytext; -show create table t1; -drop table t1; - -# -# BUG#15588: String overrun -# - ---disable_warnings -DROP TABLE IF EXISTS t1; ---enable_warnings - -CREATE TABLE t1(f1 VARCHAR(100) DEFAULT 'test'); -INSERT INTO t1 VALUES(SUBSTR(f1, 1, 3)); -DROP TABLE IF EXISTS t1; - -CREATE TABLE t1(f1 CHAR(100) DEFAULT 'test'); -INSERT INTO t1 VALUES(SUBSTR(f1, 1, 3)); -DROP TABLE IF EXISTS t1; - - -# -# Bug #11927: Warnings shown for CAST( chr as signed) but not (chr + 0) -# -CREATE TABLE t1 (a CHAR(2)); -INSERT INTO t1 VALUES (10), (50), (30), ('1a'), (60), ('t'); -SELECT a,(a + 0) FROM t1 ORDER BY a; -SELECT a,(a DIV 2) FROM t1 ORDER BY a; -SELECT a,CAST(a AS SIGNED) FROM t1 ORDER BY a; -DROP TABLE t1; - -# -# Bug #28299: To-number conversion warnings work differenly with CHAR -# and VARCHAR sp variables -# -# * Verify that 'Truncated incorrect DOUBLE value' is shown for 's' -# when using both CHAR and VARCHAR. -# - -CREATE TABLE t1 (a VARCHAR(16)); -INSERT INTO t1 VALUES ('5'), ('s'), (''); -SELECT 5 = a FROM t1; -DROP TABLE t1; - -CREATE TABLE t1 (a CHAR(16)); -INSERT INTO t1 VALUES ('5'), ('s'), (''); -SELECT 5 = a FROM t1; -DROP TABLE t1; diff --git a/sql/range_optimizer/range_analysis.cc b/sql/range_optimizer/range_analysis.cc index d2c981330784..331b04ff9ab9 100644 --- a/sql/range_optimizer/range_analysis.cc +++ b/sql/range_optimizer/range_analysis.cc @@ -24,6 +24,7 @@ #include #include #include +#include #include "field_types.h" #include "memory_debugging.h" @@ -70,6 +71,8 @@ #include "sql_string.h" #include "template_utils.h" +bool is_prefix_index(TABLE *table, uint idx); + /* A null_sel_tree is used in get_func_mm_tree_from_in_predicate to pass as an argument to tree_or. It is used only to influence the return @@ -1392,6 +1395,76 @@ static bool save_value_and_handle_conversion( return true; } +/** + Creates a search key for a value that may be larger than the index it + searches. + + The code inside save_value_and_handle_conversion() cannot create a + search key if the value is larger than the declared size of the index. This + happens because the code instantiating search keys is tied to the Field + class, which doesn't allocate room for keys larger than the index. For unicode + strings, there is no limit for how large the search key can be. For instance, + multiple character can match a single character, for example "ae" can match + "æ" in many collations. A more contrived example is that any number of SMALL + HYPHEN (U+00AD) can be in the search string as they are ignored in string + matching. + + If any one search key cannot be created, the optimizer falls back + to table scan. This function act as a second chance, allocating as large a + buffer as needed and creates the search key there instead. Since the scenario + can only happen for strings, the procedure is much simpler than for arbitrary + types. + + @param value The search value. + @param field The column the value is being compared against. + @param key_part The index column for the index being considered. + @param alloc MEM_ROOT used to allocate the key buffer from. + + @return Pointer to the key buffer, or nullptr if the search key could not be + created. +*/ +static uchar *make_oversized_search_key(Item *value, const Field *field, + const KEY_PART *key_part, + MEM_ROOT *alloc) { + const size_t null_bytes = field->is_nullable() ? 1 : 0; + const size_t size_bytes = 2; + String buf; + auto *str_value = value->val_str(&buf); + if (str_value == nullptr) return nullptr; + + const CHARSET_INFO *cs = field->charset(); + size_t key_len = + cs->coll->strnxfrmlen(cs, str_value->length() * cs->mbmaxlen); + auto *key_buf = + static_cast(alloc->Alloc(null_bytes + size_bytes + key_len)); + if (key_buf == nullptr) return nullptr; + + int nchars = is_prefix_index(field->table, key_part->key) + ? key_part->length / cs->mbmaxlen + : key_len / cs->mbmaxlen; + + const char *well_formed_error_pos; + const char *cannot_convert_error_pos; + const char *from_end_pos; + + auto num_bytes_in_key = well_formed_copy_nchars( + cs, key_buf + null_bytes + size_bytes, str_value->length(), cs, + str_value->ptr(), str_value->length(), nchars, &well_formed_error_pos, + &cannot_convert_error_pos, &from_end_pos); + + if (well_formed_error_pos != nullptr || cannot_convert_error_pos != nullptr) { + return nullptr; + } + + if (field->is_nullable()) { + key_buf[0] = char{field->is_real_null()}; + } + + int2store(key_buf + null_bytes, num_bytes_in_key); + + return reinterpret_cast(key_buf); +} + static SEL_ROOT *get_mm_leaf(THD *thd, RANGE_OPT_PARAM *param, Item *cond_func, Field *field, KEY_PART *key_part, Item_func::Functype type, Item *value, @@ -1400,7 +1473,7 @@ static SEL_ROOT *get_mm_leaf(THD *thd, RANGE_OPT_PARAM *param, Item *cond_func, bool optimize_range; SEL_ROOT *tree = nullptr; MEM_ROOT *const alloc = param->temp_mem_root; - uchar *str; + uchar *str{nullptr}; const char *impossible_cond_cause = nullptr; DBUG_TRACE; @@ -1584,6 +1657,17 @@ static SEL_ROOT *get_mm_leaf(THD *thd, RANGE_OPT_PARAM *param, Item *cond_func, &tree, value, type, field, &impossible_cond_cause, alloc, param->query_block, inexact); + if (always_true_or_false && *inexact && is_string_type(field->type()) && + (!is_prefix_index(field->table, key_part->key) || + type == Item_func::EQ_FUNC)) { + // The handler cannot currently handle non-equality ranges on prefix + // indexes. + str = make_oversized_search_key(value, field, key_part, alloc); + if (str != nullptr) { + always_true_or_false = false; + } + } + if (field->type() == MYSQL_TYPE_GEOMETRY && save_geom_type != Field::GEOM_GEOMETRY) { down_cast(field)->geom_type = save_geom_type; @@ -1602,12 +1686,15 @@ static SEL_ROOT *get_mm_leaf(THD *thd, RANGE_OPT_PARAM *param, Item *cond_func, goto end; } - str = (uchar *)alloc->Alloc(key_part->store_length + 1); - if (!str) goto end; - if (field->is_nullable()) - *str = (uchar)field->is_real_null(); // Set to 1 if null - field->get_key_image(str + null_bytes, key_part->length, - key_part->image_type); + if (str == nullptr) { + // Create the search key if we didn't already. + str = (uchar *)alloc->Alloc(key_part->store_length + 1); + if (!str) goto end; + if (field->is_nullable()) + *str = (uchar)field->is_real_null(); // Set to 1 if null + field->get_key_image(str + null_bytes, key_part->length, + key_part->image_type); + } SEL_ARG *root; root = new (alloc) SEL_ARG(field, str, str, !(key_part->flag & HA_REVERSE_SORT));