diff --git a/mysql-test/main/cset_narrowing.result b/mysql-test/main/cset_narrowing.result index 8c5c6809e27..0671af0ecdc 100644 --- a/mysql-test/main/cset_narrowing.result +++ b/mysql-test/main/cset_narrowing.result @@ -303,7 +303,7 @@ EXPLAIN "rows": 4, "cost": "COST_REPLACED", "filtered": 100, - "index_condition": "t1.mb3 = '????' or t1.mb3 = 'hello'" + "index_condition": "t1.mb3 = '�' or t1.mb3 = 'hello'" } } ] @@ -520,7 +520,7 @@ EXPLAIN "rows": 1, "cost": "COST_REPLACED", "filtered": 100, - "index_condition": "t1.mb3 = t10.mb4" + "index_condition": "t1.mb3 = 'hello'" } }, { @@ -536,7 +536,7 @@ EXPLAIN "rows": 1, "cost": "COST_REPLACED", "filtered": 100, - "index_condition": "t2.mb4 = t10.mb4 and concat(convert(t1.mb3 using utf8mb4),t2.mb4,t10.mb4) <> 'Bebebe'" + "index_condition": "t2.mb4 = 'hello' and concat(convert(t1.mb3 using utf8mb4),t2.mb4,t10.mb4) <> 'Bebebe'" } } ] @@ -553,15 +553,15 @@ JS [ { "transformation": "equality_propagation", - "resulting_condition": "t10.mb4 = 'hello' and concat(convert(t1.mb3 using utf8mb4),t2.mb4,t10.mb4) <> 'Bebebe' and multiple equal(t1.mb3, t2.mb4, t10.mb4)" + "resulting_condition": "concat(convert(t1.mb3 using utf8mb4),t2.mb4,t10.mb4) <> 'Bebebe' and multiple equal('hello', t1.mb3, t2.mb4, t10.mb4)" }, { "transformation": "constant_propagation", - "resulting_condition": "t10.mb4 = 'hello' and concat(convert(t1.mb3 using utf8mb4),t2.mb4,t10.mb4) <> 'Bebebe' and multiple equal(t1.mb3, t2.mb4, t10.mb4)" + "resulting_condition": "concat(convert(t1.mb3 using utf8mb4),t2.mb4,t10.mb4) <> 'Bebebe' and multiple equal('hello', t1.mb3, t2.mb4, t10.mb4)" }, { "transformation": "trivial_condition_removal", - "resulting_condition": "t10.mb4 = 'hello' and concat(convert(t1.mb3 using utf8mb4),t2.mb4,t10.mb4) <> 'Bebebe' and multiple equal(t1.mb3, t2.mb4, t10.mb4)" + "resulting_condition": "concat(convert(t1.mb3 using utf8mb4),t2.mb4,t10.mb4) <> 'Bebebe' and multiple equal('hello', t1.mb3, t2.mb4, t10.mb4)" } ] } diff --git a/mysql-test/main/ctype_cp1250_ch.result b/mysql-test/main/ctype_cp1250_ch.result index fb0373349fd..bc7275115a5 100644 --- a/mysql-test/main/ctype_cp1250_ch.result +++ b/mysql-test/main/ctype_cp1250_ch.result @@ -220,7 +220,7 @@ EXPLAIN EXTENDED SELECT a, LENGTH(a) FROM t1 WHERE a NOT LIKE 'a ' AND a='a'; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: -Note 1003 select `test`.`t1`.`a` AS `a`,octet_length(`test`.`t1`.`a`) AS `LENGTH(a)` from `test`.`t1` where `test`.`t1`.`a` not like 'a ' and `test`.`t1`.`a` = 'a' +Note 1003 select `test`.`t1`.`a` AS `a`,octet_length(`test`.`t1`.`a`) AS `LENGTH(a)` from `test`.`t1` where `test`.`t1`.`a` = 'a' and `test`.`t1`.`a` not like 'a ' DROP TABLE t1; # # End of MDEV-8694 diff --git a/mysql-test/main/ctype_uca.result b/mysql-test/main/ctype_uca.result index f0d5e90fb7a..c47c2c17031 100644 --- a/mysql-test/main/ctype_uca.result +++ b/mysql-test/main/ctype_uca.result @@ -8522,7 +8522,7 @@ EXPLAIN EXTENDED SELECT a, LENGTH(a) FROM t1 WHERE a NOT LIKE 'a ' AND a='a'; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: -Note 1003 select `test`.`t1`.`a` AS `a`,octet_length(`test`.`t1`.`a`) AS `LENGTH(a)` from `test`.`t1` where `test`.`t1`.`a` not like 'a ' and `test`.`t1`.`a` = 'a' +Note 1003 select `test`.`t1`.`a` AS `a`,octet_length(`test`.`t1`.`a`) AS `LENGTH(a)` from `test`.`t1` where `test`.`t1`.`a` = 'a' and `test`.`t1`.`a` not like 'a ' DROP TABLE t1; # # End of MDEV-8694 @@ -8680,7 +8680,7 @@ EXPLAIN EXTENDED SELECT a, LENGTH(a) FROM t1 WHERE a NOT LIKE 'a ' AND a='a'; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: -Note 1003 select `test`.`t1`.`a` AS `a`,octet_length(`test`.`t1`.`a`) AS `LENGTH(a)` from `test`.`t1` where `test`.`t1`.`a` not like 'a ' and `test`.`t1`.`a` = 'a' +Note 1003 select `test`.`t1`.`a` AS `a`,octet_length(`test`.`t1`.`a`) AS `LENGTH(a)` from `test`.`t1` where `test`.`t1`.`a` = 'a' and `test`.`t1`.`a` not like 'a ' DROP TABLE t1; # # End of MDEV-8694 diff --git a/mysql-test/main/ctype_utf8.result b/mysql-test/main/ctype_utf8.result index 670cd9242b9..d3a5090e310 100644 --- a/mysql-test/main/ctype_utf8.result +++ b/mysql-test/main/ctype_utf8.result @@ -9421,7 +9421,7 @@ EXPLAIN EXTENDED SELECT * FROM t1 WHERE (a,a)=(10,'1e1'); id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: -Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 10 and `test`.`t1`.`a` = '1e1' +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = '1e1' and `test`.`t1`.`a` = 10 DROP TABLE t1; # # MDEV-8688 Wrong result for SELECT..WHERE varchar_column IN (1,2,3) AND varchar_column=' 1'; diff --git a/mysql-test/main/ctype_utf8mb3_general_ci.result b/mysql-test/main/ctype_utf8mb3_general_ci.result index 82eabea637b..cc564cda261 100644 --- a/mysql-test/main/ctype_utf8mb3_general_ci.result +++ b/mysql-test/main/ctype_utf8mb3_general_ci.result @@ -575,7 +575,7 @@ EXPLAIN EXTENDED SELECT a, LENGTH(a) FROM t1 WHERE a NOT LIKE 'a ' AND a='a'; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: -Note 1003 select `test`.`t1`.`a` AS `a`,octet_length(`test`.`t1`.`a`) AS `LENGTH(a)` from `test`.`t1` where `test`.`t1`.`a` not like 'a ' and `test`.`t1`.`a` = 'a' +Note 1003 select `test`.`t1`.`a` AS `a`,octet_length(`test`.`t1`.`a`) AS `LENGTH(a)` from `test`.`t1` where `test`.`t1`.`a` = 'a' and `test`.`t1`.`a` not like 'a ' DROP TABLE t1; # # End of MDEV-8694 diff --git a/mysql-test/main/ctype_utf8mb3_uca1400_ai_ci.result b/mysql-test/main/ctype_utf8mb3_uca1400_ai_ci.result index 7912e59bf4b..d672ff9317a 100644 --- a/mysql-test/main/ctype_utf8mb3_uca1400_ai_ci.result +++ b/mysql-test/main/ctype_utf8mb3_uca1400_ai_ci.result @@ -575,7 +575,7 @@ EXPLAIN EXTENDED SELECT a, LENGTH(a) FROM t1 WHERE a NOT LIKE 'a ' AND a='a'; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: -Note 1003 select `test`.`t1`.`a` AS `a`,octet_length(`test`.`t1`.`a`) AS `LENGTH(a)` from `test`.`t1` where `test`.`t1`.`a` not like 'a ' and `test`.`t1`.`a` = 'a' +Note 1003 select `test`.`t1`.`a` AS `a`,octet_length(`test`.`t1`.`a`) AS `LENGTH(a)` from `test`.`t1` where `test`.`t1`.`a` = 'a' and `test`.`t1`.`a` not like 'a ' DROP TABLE t1; # # End of MDEV-8694 diff --git a/mysql-test/main/ctype_utf8mb4_general_ci.result b/mysql-test/main/ctype_utf8mb4_general_ci.result index afc2105ed53..ea0c8f2d858 100644 --- a/mysql-test/main/ctype_utf8mb4_general_ci.result +++ b/mysql-test/main/ctype_utf8mb4_general_ci.result @@ -575,7 +575,7 @@ EXPLAIN EXTENDED SELECT a, LENGTH(a) FROM t1 WHERE a NOT LIKE 'a ' AND a='a'; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: -Note 1003 select `test`.`t1`.`a` AS `a`,octet_length(`test`.`t1`.`a`) AS `LENGTH(a)` from `test`.`t1` where `test`.`t1`.`a` not like 'a ' and `test`.`t1`.`a` = 'a' +Note 1003 select `test`.`t1`.`a` AS `a`,octet_length(`test`.`t1`.`a`) AS `LENGTH(a)` from `test`.`t1` where `test`.`t1`.`a` = 'a' and `test`.`t1`.`a` not like 'a ' DROP TABLE t1; # # End of MDEV-8694 diff --git a/mysql-test/main/ctype_utf8mb4_uca1400_ai_ci.result b/mysql-test/main/ctype_utf8mb4_uca1400_ai_ci.result index f13fac20e43..75c75fe9356 100644 --- a/mysql-test/main/ctype_utf8mb4_uca1400_ai_ci.result +++ b/mysql-test/main/ctype_utf8mb4_uca1400_ai_ci.result @@ -575,7 +575,7 @@ EXPLAIN EXTENDED SELECT a, LENGTH(a) FROM t1 WHERE a NOT LIKE 'a ' AND a='a'; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: -Note 1003 select `test`.`t1`.`a` AS `a`,octet_length(`test`.`t1`.`a`) AS `LENGTH(a)` from `test`.`t1` where `test`.`t1`.`a` not like 'a ' and `test`.`t1`.`a` = 'a' +Note 1003 select `test`.`t1`.`a` AS `a`,octet_length(`test`.`t1`.`a`) AS `LENGTH(a)` from `test`.`t1` where `test`.`t1`.`a` = 'a' and `test`.`t1`.`a` not like 'a ' DROP TABLE t1; # # End of MDEV-8694 diff --git a/mysql-test/main/func_in.result b/mysql-test/main/func_in.result index bffe78de5b4..ed1766a5447 100644 --- a/mysql-test/main/func_in.result +++ b/mysql-test/main/func_in.result @@ -1276,3 +1276,203 @@ drop table t1; # # End of 10.6 tests # +# +# MDEV-35845 WHERE COL IN (item0, item1, ..., itemN) AND COL = item1 +# Optimization +# +create table t1 (v varchar(64), t text, c char(32)); +insert into t1 values ('a','a','a'),('b','b','b'); +explain extended select * from t1 where v in ('a','b') and v = 'b'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`v` AS `v`,`test`.`t1`.`t` AS `t`,`test`.`t1`.`c` AS `c` from `test`.`t1` where `test`.`t1`.`v` = 'b' +explain extended select * from t1 where t in ('a','b') and t = 'b'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`v` AS `v`,`test`.`t1`.`t` AS `t`,`test`.`t1`.`c` AS `c` from `test`.`t1` where `test`.`t1`.`t` = 'b' +explain extended select * from t1 where c in ('a','b') and c = 'b'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`v` AS `v`,`test`.`t1`.`t` AS `t`,`test`.`t1`.`c` AS `c` from `test`.`t1` where `test`.`t1`.`c` = 'b' +explain extended select * from t1 where v not in ('a','b') and v = 'b'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +Warnings: +Note 1003 select `test`.`t1`.`v` AS `v`,`test`.`t1`.`t` AS `t`,`test`.`t1`.`c` AS `c` from `test`.`t1` where 0 +select * from t1 where v in ('a','b') and v = 'b'; +v t c +b b b +select * from t1 where v in ('a','x') and v = 'b'; +v t c +select * from t1 where v not in ('a','b') and v = 'b'; +v t c +drop table t1; +# The predicant is left alone when the IN predicate and the equality +# compare with different collations. Under utf8mb3_german2_ci the +# o-umlaut row matches 'oe', under utf8mb3_general_ci it does not, so +# the two predicates ask different questions and neither one answers +# for the other. +# Each list holds two values because a one value list is parsed as an +# equality and never becomes an IN predicate. +set names utf8mb3 collate utf8mb3_german2_ci; +create table t1 (a char(10) character set utf8mb3); +insert into t1 values (_utf8mb3 0xC3B6),('oe'); +explain extended select * from t1 +where a in ('oe','xx') and a = 'oe' collate utf8mb3_german2_ci; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` in ('oe','xx') and `test`.`t1`.`a` = 'oe' +select hex(a) from t1 +where a in ('oe','xx') and a = 'oe' collate utf8mb3_german2_ci; +hex(a) +6F65 +# Only the first value of the next list carries the other collation, so +# the second value on its own would allow the rewrite. Refusing the +# whole predicate shows the check runs per value. +explain extended select * from t1 +where a in ('oe' collate utf8mb3_german2_ci,'xx') and a = 'oe'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 'oe' and `test`.`t1`.`a` in (('oe' collate utf8mb3_german2_ci),'xx') +select hex(a) from t1 +where a in ('oe' collate utf8mb3_german2_ci,'xx') and a = 'oe'; +hex(a) +6F65 +# With one collation throughout, the same rows let the rewrite happen. +# The equality on its own matches both rows, so keeping the IN above is +# what holds the o-umlaut row back. +explain extended select * from t1 where a in ('oe','xx') and a = 'oe'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 'oe' +select hex(a) from t1 where a in ('oe','xx') and a = 'oe'; +hex(a) +6F65 +select hex(a) from t1 where a = 'oe' collate utf8mb3_german2_ci; +hex(a) +C3B6 +6F65 +drop table t1; +set names default; +# A constant that stands in for another item is refused. Comparing the +# literal 1 against a YEAR column turns it into the value the column +# would hold, 2001, and the value list is converted the same way. A +# clone of that constant carries the literal 1, which matches nothing in +# the converted list, so the predicant keeps the column. +# The equality is <=> rather than = so that the multiple equality +# machinery leaves the condition to this rewrite. +create table t1 (y year); +insert into t1 values (2001),(2002),(2003); +explain extended select * from t1 where y in (1,2) and y <=> 1; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`y` AS `y` from `test`.`t1` where `test`.`t1`.`y` in (2001,2002) and `test`.`t1`.`y` <=> 2001 +select * from t1 where y in (1,2) and y <=> 1; +y +2001 +select * from t1 where y in (1,2) and y <=> 2; +y +2002 +select * from t1 where y in (1,2) and y <=> 3; +y +drop table t1; +# A NULL in the list leaves the predicant alone. A column in the list +# does not, and the rewritten predicate still answers correctly. +create table t1 (v varchar(64), w varchar(64)); +insert into t1 values ('a','a'),('b','b'); +explain extended select * from t1 where v in ('a',NULL) and v = 'b'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +Warnings: +Note 1003 select `test`.`t1`.`v` AS `v`,`test`.`t1`.`w` AS `w` from `test`.`t1` where 0 +select * from t1 where v in ('a',NULL) and v = 'b'; +v w +explain extended select * from t1 where v in ('a',w) and v = 'b'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`v` AS `v`,`test`.`t1`.`w` AS `w` from `test`.`t1` where `test`.`t1`.`v` = 'b' and 'b' in ('a',`test`.`t1`.`w`) +select * from t1 where v in ('a',w) and v = 'b'; +v w +b b +drop table t1; +# The rewrite is undone after each execution of a prepared statement +# and done again on the next, with the parameter values bound for it. +create table t1 (v varchar(64)); +insert into t1 values ('a'),('b'); +prepare s from 'explain extended + select * from t1 where v in (''a'',''b'') and v = ''b'''; +execute s; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`v` AS `v` from `test`.`t1` where `test`.`t1`.`v` = 'b' +execute s; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`v` AS `v` from `test`.`t1` where `test`.`t1`.`v` = 'b' +prepare s from 'select * from t1 where v in (''a'',''b'') and v = ''b'''; +execute s; +v +b +execute s; +v +b +# Parameters in the list make the IN predicate TRUE and then FALSE. +prepare s from 'explain extended + select * from t1 where v in (?,?) and v = ''b'''; +execute s using 'a', 'b'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`v` AS `v` from `test`.`t1` where `test`.`t1`.`v` = 'b' +execute s using 'a', 'x'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +Warnings: +Note 1003 select `test`.`t1`.`v` AS `v` from `test`.`t1` where 0 +prepare s from 'select * from t1 where v in (?,?) and v = ''b'''; +execute s using 'a', 'b'; +v +b +execute s using 'a', 'x'; +v +execute s using 'a', 'b'; +v +b +# A parameter in the equality is cloned with the value bound for each +# execution. +prepare s from 'explain extended + select * from t1 where v in (''a'',''b'') and v = ?'; +execute s using 'b'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`v` AS `v` from `test`.`t1` where `test`.`t1`.`v` = 'b' +execute s using 'x'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +Warnings: +Note 1003 select `test`.`t1`.`v` AS `v` from `test`.`t1` where 0 +prepare s from 'select * from t1 where v in (''a'',''b'') and v = ?'; +execute s using 'b'; +v +b +execute s using 'x'; +v +execute s using 'a'; +v +a +deallocate prepare s; +drop table t1; +# +# End of 11.8 tests +# diff --git a/mysql-test/main/func_in.test b/mysql-test/main/func_in.test index e65d29567ed..f4f1584555f 100644 --- a/mysql-test/main/func_in.test +++ b/mysql-test/main/func_in.test @@ -936,3 +936,119 @@ drop table t1; --echo # --echo # End of 10.6 tests --echo # + +--echo # +--echo # MDEV-35845 WHERE COL IN (item0, item1, ..., itemN) AND COL = item1 +--echo # Optimization +--echo # + +create table t1 (v varchar(64), t text, c char(32)); +insert into t1 values ('a','a','a'),('b','b','b'); +explain extended select * from t1 where v in ('a','b') and v = 'b'; +explain extended select * from t1 where t in ('a','b') and t = 'b'; +explain extended select * from t1 where c in ('a','b') and c = 'b'; +explain extended select * from t1 where v not in ('a','b') and v = 'b'; +select * from t1 where v in ('a','b') and v = 'b'; +select * from t1 where v in ('a','x') and v = 'b'; +select * from t1 where v not in ('a','b') and v = 'b'; +drop table t1; + +--echo # The predicant is left alone when the IN predicate and the equality +--echo # compare with different collations. Under utf8mb3_german2_ci the +--echo # o-umlaut row matches 'oe', under utf8mb3_general_ci it does not, so +--echo # the two predicates ask different questions and neither one answers +--echo # for the other. +--echo # Each list holds two values because a one value list is parsed as an +--echo # equality and never becomes an IN predicate. + +set names utf8mb3 collate utf8mb3_german2_ci; +create table t1 (a char(10) character set utf8mb3); +insert into t1 values (_utf8mb3 0xC3B6),('oe'); +explain extended select * from t1 + where a in ('oe','xx') and a = 'oe' collate utf8mb3_german2_ci; +select hex(a) from t1 + where a in ('oe','xx') and a = 'oe' collate utf8mb3_german2_ci; +--echo # Only the first value of the next list carries the other collation, so +--echo # the second value on its own would allow the rewrite. Refusing the +--echo # whole predicate shows the check runs per value. +explain extended select * from t1 + where a in ('oe' collate utf8mb3_german2_ci,'xx') and a = 'oe'; +select hex(a) from t1 + where a in ('oe' collate utf8mb3_german2_ci,'xx') and a = 'oe'; +--echo # With one collation throughout, the same rows let the rewrite happen. +--echo # The equality on its own matches both rows, so keeping the IN above is +--echo # what holds the o-umlaut row back. +explain extended select * from t1 where a in ('oe','xx') and a = 'oe'; +select hex(a) from t1 where a in ('oe','xx') and a = 'oe'; +select hex(a) from t1 where a = 'oe' collate utf8mb3_german2_ci; +drop table t1; +set names default; + +--echo # A constant that stands in for another item is refused. Comparing the +--echo # literal 1 against a YEAR column turns it into the value the column +--echo # would hold, 2001, and the value list is converted the same way. A +--echo # clone of that constant carries the literal 1, which matches nothing in +--echo # the converted list, so the predicant keeps the column. +--echo # The equality is <=> rather than = so that the multiple equality +--echo # machinery leaves the condition to this rewrite. + +create table t1 (y year); +insert into t1 values (2001),(2002),(2003); +explain extended select * from t1 where y in (1,2) and y <=> 1; +select * from t1 where y in (1,2) and y <=> 1; +select * from t1 where y in (1,2) and y <=> 2; +select * from t1 where y in (1,2) and y <=> 3; +drop table t1; + +--echo # A NULL in the list leaves the predicant alone. A column in the list +--echo # does not, and the rewritten predicate still answers correctly. + +create table t1 (v varchar(64), w varchar(64)); +insert into t1 values ('a','a'),('b','b'); +explain extended select * from t1 where v in ('a',NULL) and v = 'b'; +select * from t1 where v in ('a',NULL) and v = 'b'; +explain extended select * from t1 where v in ('a',w) and v = 'b'; +select * from t1 where v in ('a',w) and v = 'b'; +drop table t1; + +--echo # The rewrite is undone after each execution of a prepared statement +--echo # and done again on the next, with the parameter values bound for it. + +create table t1 (v varchar(64)); +insert into t1 values ('a'),('b'); + +prepare s from 'explain extended + select * from t1 where v in (''a'',''b'') and v = ''b'''; +execute s; +execute s; +prepare s from 'select * from t1 where v in (''a'',''b'') and v = ''b'''; +execute s; +execute s; + +--echo # Parameters in the list make the IN predicate TRUE and then FALSE. +prepare s from 'explain extended + select * from t1 where v in (?,?) and v = ''b'''; +execute s using 'a', 'b'; +execute s using 'a', 'x'; +prepare s from 'select * from t1 where v in (?,?) and v = ''b'''; +execute s using 'a', 'b'; +execute s using 'a', 'x'; +execute s using 'a', 'b'; + +--echo # A parameter in the equality is cloned with the value bound for each +--echo # execution. +prepare s from 'explain extended + select * from t1 where v in (''a'',''b'') and v = ?'; +execute s using 'b'; +execute s using 'x'; +prepare s from 'select * from t1 where v in (''a'',''b'') and v = ?'; +execute s using 'b'; +execute s using 'x'; +execute s using 'a'; + +deallocate prepare s; +drop table t1; + +--echo # +--echo # End of 11.8 tests +--echo # diff --git a/mysql-test/main/having.result b/mysql-test/main/having.result index 24690127b66..6f07159b288 100644 --- a/mysql-test/main/having.result +++ b/mysql-test/main/having.result @@ -713,7 +713,7 @@ select * from mysql.help_topic where example = 'foo' having description is null; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible HAVING Warnings: -Note 1003 select `mysql`.`help_topic`.`help_topic_id` AS `help_topic_id`,`mysql`.`help_topic`.`name` AS `name`,`mysql`.`help_topic`.`help_category_id` AS `help_category_id`,`mysql`.`help_topic`.`description` AS `description`,`mysql`.`help_topic`.`example` AS `example`,`mysql`.`help_topic`.`url` AS `url` from `mysql`.`help_topic` where `mysql`.`help_topic`.`example` = 'foo' having 0 +Note 1003 select `mysql`.`help_topic`.`help_topic_id` AS `help_topic_id`,`mysql`.`help_topic`.`name` AS `name`,`mysql`.`help_topic`.`help_category_id` AS `help_category_id`,`mysql`.`help_topic`.`description` AS `description`,`mysql`.`help_topic`.`example` AS `example`,`mysql`.`help_topic`.`url` AS `url` from `mysql`.`help_topic` where multiple equal('foo', `mysql`.`help_topic`.`example`) having 0 select * from mysql.help_topic where example = 'foo' having description is null; help_topic_id name help_category_id description example url # diff --git a/mysql-test/main/information_schema.result b/mysql-test/main/information_schema.result index 820c6c488ef..255f6730f2f 100644 --- a/mysql-test/main/information_schema.result +++ b/mysql-test/main/information_schema.result @@ -1734,7 +1734,7 @@ from information_schema.tables a, information_schema.columns b where a.table_name='t1' and a.table_schema='test' and b.table_name=a.table_name; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE a ALL NULL TABLE_SCHEMA,TABLE_NAME NULL NULL NULL Using where; Skip_open_table; Scanned 0 databases -1 SIMPLE b ALL NULL NULL NULL NULL NULL Using where; Open_frm_only; Scanned all databases; Using join buffer (flat, BNL join) +1 SIMPLE b ALL NULL TABLE_NAME NULL NULL NULL Using where; Open_frm_only; Scanned 1 database; Using join buffer (flat, BNL join) SELECT * FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = 'mysqltest'; CATALOG_NAME SCHEMA_NAME DEFAULT_CHARACTER_SET_NAME DEFAULT_COLLATION_NAME SQL_PATH SCHEMA_COMMENT diff --git a/mysql-test/main/innodb_ext_key.result b/mysql-test/main/innodb_ext_key.result index 6c07915ab11..ee4ae3c8efa 100644 --- a/mysql-test/main/innodb_ext_key.result +++ b/mysql-test/main/innodb_ext_key.result @@ -779,7 +779,7 @@ EXPLAIN "rows": 1, "cost": "COST_REPLACED", "filtered": 100, - "index_condition": "t1.pk1 <= 5 and t1.pk2 <= 5 and t1.f2 = 'abc'", + "index_condition": "t1.f2 = 'abc' and t1.pk1 <= 5 and t1.pk2 <= 5", "attached_condition": "t1.f1 <= '3'" } } @@ -816,7 +816,7 @@ EXPLAIN "rows": 1, "cost": "COST_REPLACED", "filtered": 100, - "index_condition": "t1.f2 <= 5 and t1.pk2 <= 5 and t1.pk1 = 'abc'", + "index_condition": "t1.pk1 = 'abc' and t1.f2 <= 5 and t1.pk2 <= 5", "attached_condition": "t1.f1 <= '3'" } } diff --git a/mysql-test/main/join.result b/mysql-test/main/join.result index d9dbf80642b..9003a54178a 100644 --- a/mysql-test/main/join.result +++ b/mysql-test/main/join.result @@ -759,10 +759,6 @@ from information_schema.statistics join information_schema.columns using(table_n TABLE_NAME COLUMN_NAME TABLE_CATALOG TABLE_SCHEMA NON_UNIQUE INDEX_SCHEMA INDEX_NAME SEQ_IN_INDEX COLLATION SUB_PART PACKED NULLABLE INDEX_TYPE COMMENT TABLE_CATALOG TABLE_SCHEMA COLUMN_DEFAULT IS_NULLABLE DATA_TYPE CHARACTER_MAXIMUM_LENGTH CHARACTER_OCTET_LENGTH NUMERIC_PRECISION NUMERIC_SCALE CHARACTER_SET_NAME COLLATION_NAME COLUMN_TYPE COLUMN_KEY EXTRA COLUMN_COMMENT global_priv Host def mysql 0 mysql PRIMARY 1 A NULL NULL BTREE def mysql '' NO char 255 765 NULL NULL utf8mb3 utf8mb3_bin char(255) PRI global_priv User def mysql 0 mysql PRIMARY 2 A NULL NULL BTREE def mysql '' NO char 128 384 NULL NULL utf8mb3 utf8mb3_bin char(128) PRI -Warnings: -Warning 1286 Unknown storage engine 'InnoDB' -Warning 1286 Unknown storage engine 'InnoDB' -Warning 1286 Unknown storage engine 'InnoDB' drop table t1; drop table t2; drop table t3; diff --git a/mysql-test/main/mrr_derived_crash_4610.result b/mysql-test/main/mrr_derived_crash_4610.result index d7800e8a2a9..c1b732fb21b 100644 --- a/mysql-test/main/mrr_derived_crash_4610.result +++ b/mysql-test/main/mrr_derived_crash_4610.result @@ -8,7 +8,7 @@ explain select 1 from join t1 on f1 = f3 where f3 = 'aaaa' order by val; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 const PRIMARY PRIMARY 12 const 1 -1 PRIMARY ref key0 key0 13 const 0 Using where; Using filesort +1 PRIMARY ALL NULL NULL NULL NULL 2 Using where; Using filesort 2 DERIVED t4 ALL NULL NULL NULL NULL 1 2 DERIVED t2 ALL NULL NULL NULL NULL 1 Using join buffer (flat, BNL join) 2 DERIVED t3 ALL NULL NULL NULL NULL 1 Using where; Using join buffer (incremental, BNL join) diff --git a/mysql-test/main/ps.result b/mysql-test/main/ps.result index 5b36be3426a..cc7c7361ceb 100644 --- a/mysql-test/main/ps.result +++ b/mysql-test/main/ps.result @@ -1209,24 +1209,12 @@ prepare my_stmt from @aux; execute my_stmt; COUNT(*) 47 -Warnings: -Warning 1286 Unknown storage engine 'InnoDB' -Warning 1286 Unknown storage engine 'InnoDB' -Warning 1286 Unknown storage engine 'InnoDB' execute my_stmt; COUNT(*) 47 -Warnings: -Warning 1286 Unknown storage engine 'InnoDB' -Warning 1286 Unknown storage engine 'InnoDB' -Warning 1286 Unknown storage engine 'InnoDB' execute my_stmt; COUNT(*) 47 -Warnings: -Warning 1286 Unknown storage engine 'InnoDB' -Warning 1286 Unknown storage engine 'InnoDB' -Warning 1286 Unknown storage engine 'InnoDB' deallocate prepare my_stmt; drop procedure if exists p1| drop table if exists t1| diff --git a/mysql-test/main/rowid_filter_innodb.result b/mysql-test/main/rowid_filter_innodb.result index bb01a1cfd78..0e6aa42dd44 100644 --- a/mysql-test/main/rowid_filter_innodb.result +++ b/mysql-test/main/rowid_filter_innodb.result @@ -3156,7 +3156,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE a ref PRIMARY,acei_aclid acei_aclid 8 test.t.id 1 100.00 Using where 1 SIMPLE fi ref filt_aceid,filt_fh filt_aceid 8 test.a.id 24 14.46 Using where Warnings: -Note 1003 select `test`.`t`.`id` AS `id`,`test`.`fi`.`id` AS `id`,`test`.`fi`.`aceid` AS `aceid`,`test`.`fi`.`clid` AS `clid`,`test`.`fi`.`fh` AS `fh` from `test`.`acli` `t` join `test`.`acei` `a` join `test`.`filt` `fi` where `test`.`t`.`tp` = 121 and `test`.`a`.`atp` = 1 and `test`.`fi`.`aceid` = `test`.`a`.`id` and `test`.`a`.`aclid` = `test`.`t`.`id` and `test`.`t`.`rid` = 'B5FCC8C7111E4E3CBC21AAF5012F59C2' and `test`.`fi`.`fh` in (6311439873746261694,-397087483897438286,8518228073041491534,-5420422472375069774) +Note 1003 select `test`.`t`.`id` AS `id`,`test`.`fi`.`id` AS `id`,`test`.`fi`.`aceid` AS `aceid`,`test`.`fi`.`clid` AS `clid`,`test`.`fi`.`fh` AS `fh` from `test`.`acli` `t` join `test`.`acei` `a` join `test`.`filt` `fi` where `test`.`t`.`rid` = 'B5FCC8C7111E4E3CBC21AAF5012F59C2' and `test`.`t`.`tp` = 121 and `test`.`a`.`atp` = 1 and `test`.`fi`.`aceid` = `test`.`a`.`id` and `test`.`a`.`aclid` = `test`.`t`.`id` and `test`.`fi`.`fh` in (6311439873746261694,-397087483897438286,8518228073041491534,-5420422472375069774) set statement optimizer_switch='rowid_filter=off' for select t.id, fi.* from (acli t inner join acei a on a.aclid = t.id) inner join filt fi on a.id = fi.aceid @@ -3213,7 +3213,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE a ref PRIMARY,acei_aclid acei_aclid 8 test.t.id 1 100.00 Using where 1 SIMPLE fi ref|filter filt_aceid,filt_fh filt_aceid|filt_fh 8|8 test.a.id 24 (14%) 14.46 Using where; Using rowid filter Warnings: -Note 1003 select `test`.`t`.`id` AS `id`,`test`.`fi`.`id` AS `id`,`test`.`fi`.`aceid` AS `aceid`,`test`.`fi`.`clid` AS `clid`,`test`.`fi`.`fh` AS `fh` from `test`.`acli` `t` join `test`.`acei` `a` join `test`.`filt` `fi` where `test`.`t`.`tp` = 121 and `test`.`a`.`atp` = 1 and `test`.`fi`.`aceid` = `test`.`a`.`id` and `test`.`a`.`aclid` = `test`.`t`.`id` and `test`.`t`.`rid` = 'B5FCC8C7111E4E3CBC21AAF5012F59C2' and `test`.`fi`.`fh` in (6311439873746261694,-397087483897438286,8518228073041491534,-5420422472375069774) +Note 1003 select `test`.`t`.`id` AS `id`,`test`.`fi`.`id` AS `id`,`test`.`fi`.`aceid` AS `aceid`,`test`.`fi`.`clid` AS `clid`,`test`.`fi`.`fh` AS `fh` from `test`.`acli` `t` join `test`.`acei` `a` join `test`.`filt` `fi` where `test`.`t`.`rid` = 'B5FCC8C7111E4E3CBC21AAF5012F59C2' and `test`.`t`.`tp` = 121 and `test`.`a`.`atp` = 1 and `test`.`fi`.`aceid` = `test`.`a`.`id` and `test`.`a`.`aclid` = `test`.`t`.`id` and `test`.`fi`.`fh` in (6311439873746261694,-397087483897438286,8518228073041491534,-5420422472375069774) set statement optimizer_switch='rowid_filter=on' for select t.id, fi.* from (acli t inner join acei a on a.aclid = t.id) inner join filt fi on a.id = fi.aceid @@ -3272,7 +3272,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE a ref PRIMARY,acei_aclid acei_aclid 8 test.t.id 1 100.00 Using where; Using join buffer (flat, BKA join); Rowid-ordered scan 1 SIMPLE fi ref filt_aceid,filt_fh filt_aceid 8 test.a.id 24 14.46 Using where; Using join buffer (incremental, BKA join); Rowid-ordered scan Warnings: -Note 1003 select `test`.`t`.`id` AS `id`,`test`.`fi`.`id` AS `id`,`test`.`fi`.`aceid` AS `aceid`,`test`.`fi`.`clid` AS `clid`,`test`.`fi`.`fh` AS `fh` from `test`.`acli` `t` join `test`.`acei` `a` join `test`.`filt` `fi` where `test`.`t`.`tp` = 121 and `test`.`a`.`atp` = 1 and `test`.`fi`.`aceid` = `test`.`a`.`id` and `test`.`a`.`aclid` = `test`.`t`.`id` and `test`.`t`.`rid` = 'B5FCC8C7111E4E3CBC21AAF5012F59C2' and `test`.`fi`.`fh` in (6311439873746261694,-397087483897438286,8518228073041491534,-5420422472375069774) +Note 1003 select `test`.`t`.`id` AS `id`,`test`.`fi`.`id` AS `id`,`test`.`fi`.`aceid` AS `aceid`,`test`.`fi`.`clid` AS `clid`,`test`.`fi`.`fh` AS `fh` from `test`.`acli` `t` join `test`.`acei` `a` join `test`.`filt` `fi` where `test`.`t`.`rid` = 'B5FCC8C7111E4E3CBC21AAF5012F59C2' and `test`.`t`.`tp` = 121 and `test`.`a`.`atp` = 1 and `test`.`fi`.`aceid` = `test`.`a`.`id` and `test`.`a`.`aclid` = `test`.`t`.`id` and `test`.`fi`.`fh` in (6311439873746261694,-397087483897438286,8518228073041491534,-5420422472375069774) set statement optimizer_switch='rowid_filter=off' for select t.id, fi.* from (acli t inner join acei a on a.aclid = t.id) inner join filt fi on a.id = fi.aceid @@ -3329,7 +3329,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE a ref PRIMARY,acei_aclid acei_aclid 8 test.t.id 1 100.00 Using where; Using join buffer (flat, BKA join); Rowid-ordered scan 1 SIMPLE fi ref|filter filt_aceid,filt_fh filt_aceid|filt_fh 8|8 test.a.id 24 (14%) 14.46 Using where; Using join buffer (incremental, BKA join); Rowid-ordered scan; Using rowid filter Warnings: -Note 1003 select `test`.`t`.`id` AS `id`,`test`.`fi`.`id` AS `id`,`test`.`fi`.`aceid` AS `aceid`,`test`.`fi`.`clid` AS `clid`,`test`.`fi`.`fh` AS `fh` from `test`.`acli` `t` join `test`.`acei` `a` join `test`.`filt` `fi` where `test`.`t`.`tp` = 121 and `test`.`a`.`atp` = 1 and `test`.`fi`.`aceid` = `test`.`a`.`id` and `test`.`a`.`aclid` = `test`.`t`.`id` and `test`.`t`.`rid` = 'B5FCC8C7111E4E3CBC21AAF5012F59C2' and `test`.`fi`.`fh` in (6311439873746261694,-397087483897438286,8518228073041491534,-5420422472375069774) +Note 1003 select `test`.`t`.`id` AS `id`,`test`.`fi`.`id` AS `id`,`test`.`fi`.`aceid` AS `aceid`,`test`.`fi`.`clid` AS `clid`,`test`.`fi`.`fh` AS `fh` from `test`.`acli` `t` join `test`.`acei` `a` join `test`.`filt` `fi` where `test`.`t`.`rid` = 'B5FCC8C7111E4E3CBC21AAF5012F59C2' and `test`.`t`.`tp` = 121 and `test`.`a`.`atp` = 1 and `test`.`fi`.`aceid` = `test`.`a`.`id` and `test`.`a`.`aclid` = `test`.`t`.`id` and `test`.`fi`.`fh` in (6311439873746261694,-397087483897438286,8518228073041491534,-5420422472375069774) set statement optimizer_switch='rowid_filter=on' for select t.id, fi.* from (acli t inner join acei a on a.aclid = t.id) inner join filt fi on a.id = fi.aceid @@ -3424,7 +3424,7 @@ ANALYZE "r_engine_stats": REPLACED, "filtered": 100, "r_total_filtered": 100, - "attached_condition": "t.tp = 121 and t.rid = 'B5FCC8C7111E4E3CBC21AAF5012F59C2'", + "attached_condition": "t.rid = 'B5FCC8C7111E4E3CBC21AAF5012F59C2' and t.tp = 121", "r_filtered": 100, "using_index": true } diff --git a/mysql-test/main/sargable_casefold.result b/mysql-test/main/sargable_casefold.result index d9488b983e2..688d7ac79e4 100644 --- a/mysql-test/main/sargable_casefold.result +++ b/mysql-test/main/sargable_casefold.result @@ -206,7 +206,7 @@ select a from t3 ignore index(a) where a=b and upper(b)='ABC'; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t3 ref b b 99 const 1 100.00 Using index condition; Using where Warnings: -Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` IGNORE INDEX (`a`) where `test`.`t3`.`a` = `test`.`t3`.`b` and `test`.`t3`.`b` = 'ABC' +Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` IGNORE INDEX (`a`) where `test`.`t3`.`b` = 'ABC' and `test`.`t3`.`a` = 'ABC' # # Check that rewrite isn't applied for non-applicable collations # diff --git a/sql/field.cc b/sql/field.cc index d9e1c64d746..3c719694f8c 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -2403,16 +2403,7 @@ Field_str::Field_str(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg, bool Field_str::test_if_equality_guarantees_uniqueness(const Item *item) const { - /* - Can't guarantee uniqueness when comparing a CHAR/VARCHAR/TEXT, - BINARY/VARBINARY/BLOB, ENUM,SET columns to an item with cmp_type() - of INT_RESULT, DOUBLE_RESULT, DECIMAL_RESULT or TIME_RESULT. - Example: - SELECT * FROM t1 WHERE varchar_column=DATE'2001-01-01' - return non-unuque values, e.g. '2001-01-01' and '2001-01-01x'. - */ - if (!field_charset()->propagate(0, 0) || - item->cmp_type() != STRING_RESULT) + if (item->cmp_type() != STRING_RESULT) return false; /* Can't guarantee uniqueness when comparing to @@ -7614,6 +7605,56 @@ uint32 Field_longstr::max_data_length() const } +/* + Convert a constant held by an Item_equal into this field's character set. + + @param ctx The comparison context. ctx.compare_collation() is the + collation the Item_equal compares under, and the constant's + bytes are in that collation's character set. + + Item_equal::add_const() and eliminate_item_equal() assume that every + constant held by an Item_equal is directly comparable with every field + member. A utf8mb3_general_ci field and a utf8mb4_general_ci field can + share one Item_equal through charset narrowing, so when an equality + "utf8mb3_field = utf8mb4_constant" is manufactured for such a member the + constant has to be narrowed first. Narrowing maps characters outside the + BMP to U+FFFD, which is what utf8mb4_general_ci compares them as. + + @return the constant itself when its character set is the field's, + a new string literal in the field's character set, + or NULL when the constant cannot be represented in the field's + character set, which makes the equality unusable. +*/ +Item *Field_longstr::get_equal_const_item(THD *thd, const Context &ctx, + Item *const_item) +{ + if (ctx.subst_constraint() != ANY_SUBST || + const_item->cmp_type() != STRING_RESULT) + return const_item; + CHARSET_INFO *from= ctx.compare_collation(); + if (!from || my_charset_same(charset(), from)) + return const_item; + + StringBuffer buf; + String *str= const_item->val_str(&buf); + if (!str) + return const_item; // NULL, nothing to convert + + CHARSET_INFO *conv_cs= Utf8_narrow::should_do_narrowing(this, from) ? + utf8mb3_from_mb4.charset() : charset(); + uint errors= 0; + StringBuffer conv; + if (conv.copy(str->ptr(), str->length(), from, conv_cs, &errors) || errors) + return NULL; + + char *copy= thd->strmake(conv.ptr(), conv.length()); + if (!copy) + return NULL; + return new (thd->mem_root) Item_string(thd, copy, conv.length(), charset(), + const_item->collation.derivation); +} + + Data_type_compatibility Field_longstr::cmp_to_string_with_same_collation(const Item_bool_func *cond, const Item *item) const diff --git a/sql/field.h b/sql/field.h index e7384c75f2d..5b6237a1bca 100644 --- a/sql/field.h +++ b/sql/field.h @@ -2345,6 +2345,8 @@ public: return bitmap_is_set(table->write_set, field_index); } bool match_collation_to_optimize_range() const { return true; } + Item *get_equal_const_item(THD *thd, const Context &ctx, Item *const_item) + override; Data_type_compatibility can_optimize_keypart_ref(const Item_bool_func *cond, const Item *item) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index fcc18df4921..850a7ffd214 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -19126,6 +19126,22 @@ Item *eliminate_item_equal(THD *thd, COND *cond, COND_EQUAL *upper_levels, */ Item *head_item= (!item_const && current_sjm && current_sjm_head != field_item) ? current_sjm_head: head; + if (item_const) + { + /* + The constant is held in the comparison collation of the multiple + equality. A member that joined it through charset narrowing has a + different character set, so convert the constant for that member. + */ + Field *field= it.get_curr_field(); + head_item= field->get_equal_const_item(thd, + Item::Context(Item::ANY_SUBST, + item_equal->compare_type_handler(), + item_equal->compare_collation()), + item_const); + if (!head_item) + return 0; + } eq_item= new (thd->mem_root) Item_func_eq(thd, field_item, head_item); if (!eq_item || eq_item->set_cmp_func(thd)) diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_27172,usual_handler.rdiff b/storage/spider/mysql-test/spider/bugfix/r/mdev_27172,usual_handler.rdiff index 194eecf3b37..fa4c3de37c7 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/mdev_27172,usual_handler.rdiff +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_27172,usual_handler.rdiff @@ -1,12 +1,12 @@ ---- ../src/storage/spider/mysql-test/spider/bugfix/r/mdev_27172.result 2024-11-15 17:14:27.541903833 +1100 -+++ ../src/storage/spider/mysql-test/spider/bugfix/r/mdev_27172.reject 2025-10-22 17:40:25.831151167 +1100 -@@ -66,6 +66,9 @@ +--- storage/spider/mysql-test/spider/bugfix/r/mdev_27172.result 2025-11-13 13:38:25.377373719 +1300 ++++ storage/spider/mysql-test/spider/bugfix/r/mdev_27172,usual_handler.reject 2026-10-15 14:40:08.495538888 +1300 +@@ -72,6 +72,9 @@ connection child2_1; SELECT argument FROM mysql.general_log WHERE argument LIKE 'select `id`,`greeting` from %'; argument -+select `id`,`greeting` from `auto_test_remote`.`tbl_a` where `greeting` = 'Aloha!' and ((`greeting` = 'Aloha!') and ((case `greeting` when 'Aloha!' then _latin1'one' else _latin1'more' end) = _latin1'one')) -+select `id`,`greeting` from `auto_test_remote`.`tbl_b` where `greeting` like 'Aloha%' and ((`greeting` = 'Aloha!') and ((case `greeting` when 'Aloha!' then _latin1'one' else _latin1'more' end) = _latin1'one')) -+select `id`,`greeting` from `auto_test_remote`.`tbl_c` where `greeting` like 'Aloha%' and ((`greeting` = 'Aloha!') and ((case `greeting` when 'Aloha!' then _latin1'one' else _latin1'more' end) = _latin1'one')) ++select `id`,`greeting` from `auto_test_remote`.`tbl_a` where `greeting` = 'Aloha!' and (`greeting` = 'Aloha!') ++select `id`,`greeting` from `auto_test_remote`.`tbl_b` where `greeting` like 'Aloha%' and (`greeting` = 'Aloha!') ++select `id`,`greeting` from `auto_test_remote`.`tbl_c` where `greeting` like 'Aloha%' and (`greeting` = 'Aloha!') connection child2_1; SET @@global.general_log = @general_log_backup; SET @@global.log_output = @log_output_backup;