Details
-
Bug
-
Status: Closed (View Workflow)
-
Major
-
Resolution: Fixed
-
5.5(EOL), 10.0(EOL), 10.1(EOL)
-
None
Description
SET NAMES utf8 COLLATE utf8_german2_ci; |
DROP TABLE IF EXISTS t1; |
CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET utf8 COLLATE utf8_german2_ci); |
INSERT INTO t1 VALUES ('ae'),('ä'); |
SELECT * FROM t1 WHERE a='ae'; |
SELECT * FROM t1 WHERE a LIKE 'ä'; |
returns these results:
+------+
|
| a |
|
+------+
|
| ae |
|
| ä |
|
+------+
|
2 rows in set (0.01 sec)
|
|
+------+
|
| a |
|
+------+
|
| ä |
|
+------+
|
1 row in set (0.00 sec)
|
This is correct. Equality works taking into account contractions and expansions and returns both rows, while LIKE is performed one-character-to-one-character, so only one record matches.
Now if I join both conditions with AND in a single WHERE, I expect one row with 'ä' to be returned, as it matches both conditions:
SELECT * FROM t1 WHERE a='ae' AND a LIKE 'ä'; |
But in fact I get an empty set.
EXPLAIN EXTENDED returns "Impossible where", which is not correct:
mysql> EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='ae' AND a LIKE 'ä';
|
+------+-------------+-------+------+---------------+------+---------+------+------+----------+------------------+
|
| 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 |
|
+------+-------------+-------+------+---------------+------+---------+------+------+----------+------------------+
|
After tracing the code, it seems that constant propagation was erroneously applied.
Attachments
Activity
Field | Original Value | New Value |
---|---|---|
Description |
{code:sql} SET NAMES utf8 COLLATE utf8_german2_ci; DROP TABLE IF EXISTS t1; CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET utf8 COLLATE utf8_german2_ci); INSERT INTO t1 VALUES ('ae'),('ä'); SELECT * FROM t1 WHERE a='ae'; SELECT * FROM t1 WHERE a LIKE 'ä'; {code} returns these results: {noformat} +------+ | a | +------+ | ae | | ä | +------+ 2 rows in set (0.01 sec) +------+ | a | +------+ | ä | +------+ 1 row in set (0.00 sec) {noformat} This is correct. Equality works taking into account contractions and expansions, while LIKE is performed one-character-to-one-character. Now if I join both conditions with AND in a single WHERE, I expect one row with 'ä' to be returned: {code:sql} SELECT * FROM t1 WHERE a='ae' AND a LIKE 'ä'; {code} But in fact I get empty set. EXPLAIN EXTENDED returns "Impossible where", which is not correct: {noformat} +------+-------------+-------+------+---------------+------+---------+------+------+----------+------------------+ | 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 | +------+-------------+-------+------+---------------+------+---------+------+------+----------+------------------+ {noformat} |
{code:sql} SET NAMES utf8 COLLATE utf8_german2_ci; DROP TABLE IF EXISTS t1; CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET utf8 COLLATE utf8_german2_ci); INSERT INTO t1 VALUES ('ae'),('ä'); SELECT * FROM t1 WHERE a='ae'; SELECT * FROM t1 WHERE a LIKE 'ä'; {code} returns these results: {noformat} +------+ | a | +------+ | ae | | ä | +------+ 2 rows in set (0.01 sec) +------+ | a | +------+ | ä | +------+ 1 row in set (0.00 sec) {noformat} This is correct. Equality works taking into account contractions and expansions and returns both rows, while LIKE is performed one-character-to-one-character, so only one record matches. Now if I join both conditions with AND in a single WHERE, I expect one row with 'ä' to be returned: {code:sql} SELECT * FROM t1 WHERE a='ae' AND a LIKE 'ä'; {code} But in fact I get empty set. EXPLAIN EXTENDED returns "Impossible where", which is not correct: {noformat} +------+-------------+-------+------+---------------+------+---------+------+------+----------+------------------+ | 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 | +------+-------------+-------+------+---------------+------+---------+------+------+----------+------------------+ {noformat} |
Description |
{code:sql} SET NAMES utf8 COLLATE utf8_german2_ci; DROP TABLE IF EXISTS t1; CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET utf8 COLLATE utf8_german2_ci); INSERT INTO t1 VALUES ('ae'),('ä'); SELECT * FROM t1 WHERE a='ae'; SELECT * FROM t1 WHERE a LIKE 'ä'; {code} returns these results: {noformat} +------+ | a | +------+ | ae | | ä | +------+ 2 rows in set (0.01 sec) +------+ | a | +------+ | ä | +------+ 1 row in set (0.00 sec) {noformat} This is correct. Equality works taking into account contractions and expansions and returns both rows, while LIKE is performed one-character-to-one-character, so only one record matches. Now if I join both conditions with AND in a single WHERE, I expect one row with 'ä' to be returned: {code:sql} SELECT * FROM t1 WHERE a='ae' AND a LIKE 'ä'; {code} But in fact I get empty set. EXPLAIN EXTENDED returns "Impossible where", which is not correct: {noformat} +------+-------------+-------+------+---------------+------+---------+------+------+----------+------------------+ | 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 | +------+-------------+-------+------+---------------+------+---------+------+------+----------+------------------+ {noformat} |
{code:sql} SET NAMES utf8 COLLATE utf8_german2_ci; DROP TABLE IF EXISTS t1; CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET utf8 COLLATE utf8_german2_ci); INSERT INTO t1 VALUES ('ae'),('ä'); SELECT * FROM t1 WHERE a='ae'; SELECT * FROM t1 WHERE a LIKE 'ä'; {code} returns these results: {noformat} +------+ | a | +------+ | ae | | ä | +------+ 2 rows in set (0.01 sec) +------+ | a | +------+ | ä | +------+ 1 row in set (0.00 sec) {noformat} This is correct. Equality works taking into account contractions and expansions and returns both rows, while LIKE is performed one-character-to-one-character, so only one record matches. Now if I join both conditions with AND in a single WHERE, I expect one row with 'ä' to be returned, as it matches both conditions: {code:sql} SELECT * FROM t1 WHERE a='ae' AND a LIKE 'ä'; {code} But in fact I get empty set. EXPLAIN EXTENDED returns "Impossible where", which is not correct: {noformat} +------+-------------+-------+------+---------------+------+---------+------+------+----------+------------------+ | 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 | +------+-------------+-------+------+---------------+------+---------+------+------+----------+------------------+ {noformat} |
Description |
{code:sql} SET NAMES utf8 COLLATE utf8_german2_ci; DROP TABLE IF EXISTS t1; CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET utf8 COLLATE utf8_german2_ci); INSERT INTO t1 VALUES ('ae'),('ä'); SELECT * FROM t1 WHERE a='ae'; SELECT * FROM t1 WHERE a LIKE 'ä'; {code} returns these results: {noformat} +------+ | a | +------+ | ae | | ä | +------+ 2 rows in set (0.01 sec) +------+ | a | +------+ | ä | +------+ 1 row in set (0.00 sec) {noformat} This is correct. Equality works taking into account contractions and expansions and returns both rows, while LIKE is performed one-character-to-one-character, so only one record matches. Now if I join both conditions with AND in a single WHERE, I expect one row with 'ä' to be returned, as it matches both conditions: {code:sql} SELECT * FROM t1 WHERE a='ae' AND a LIKE 'ä'; {code} But in fact I get empty set. EXPLAIN EXTENDED returns "Impossible where", which is not correct: {noformat} +------+-------------+-------+------+---------------+------+---------+------+------+----------+------------------+ | 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 | +------+-------------+-------+------+---------------+------+---------+------+------+----------+------------------+ {noformat} |
{code:sql} SET NAMES utf8 COLLATE utf8_german2_ci; DROP TABLE IF EXISTS t1; CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET utf8 COLLATE utf8_german2_ci); INSERT INTO t1 VALUES ('ae'),('ä'); SELECT * FROM t1 WHERE a='ae'; SELECT * FROM t1 WHERE a LIKE 'ä'; {code} returns these results: {noformat} +------+ | a | +------+ | ae | | ä | +------+ 2 rows in set (0.01 sec) +------+ | a | +------+ | ä | +------+ 1 row in set (0.00 sec) {noformat} This is correct. Equality works taking into account contractions and expansions and returns both rows, while LIKE is performed one-character-to-one-character, so only one record matches. Now if I join both conditions with AND in a single WHERE, I expect one row with 'ä' to be returned, as it matches both conditions: {code:sql} SELECT * FROM t1 WHERE a='ae' AND a LIKE 'ä'; {code} But in fact I get an empty set. EXPLAIN EXTENDED returns "Impossible where", which is not correct: {noformat} +------+-------------+-------+------+---------------+------+---------+------+------+----------+------------------+ | 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 | +------+-------------+-------+------+---------------+------+---------+------+------+----------+------------------+ {noformat} |
Description |
{code:sql} SET NAMES utf8 COLLATE utf8_german2_ci; DROP TABLE IF EXISTS t1; CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET utf8 COLLATE utf8_german2_ci); INSERT INTO t1 VALUES ('ae'),('ä'); SELECT * FROM t1 WHERE a='ae'; SELECT * FROM t1 WHERE a LIKE 'ä'; {code} returns these results: {noformat} +------+ | a | +------+ | ae | | ä | +------+ 2 rows in set (0.01 sec) +------+ | a | +------+ | ä | +------+ 1 row in set (0.00 sec) {noformat} This is correct. Equality works taking into account contractions and expansions and returns both rows, while LIKE is performed one-character-to-one-character, so only one record matches. Now if I join both conditions with AND in a single WHERE, I expect one row with 'ä' to be returned, as it matches both conditions: {code:sql} SELECT * FROM t1 WHERE a='ae' AND a LIKE 'ä'; {code} But in fact I get an empty set. EXPLAIN EXTENDED returns "Impossible where", which is not correct: {noformat} +------+-------------+-------+------+---------------+------+---------+------+------+----------+------------------+ | 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 | +------+-------------+-------+------+---------------+------+---------+------+------+----------+------------------+ {noformat} |
{code:sql} SET NAMES utf8 COLLATE utf8_german2_ci; DROP TABLE IF EXISTS t1; CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET utf8 COLLATE utf8_german2_ci); INSERT INTO t1 VALUES ('ae'),('ä'); SELECT * FROM t1 WHERE a='ae'; SELECT * FROM t1 WHERE a LIKE 'ä'; {code} returns these results: {noformat} +------+ | a | +------+ | ae | | ä | +------+ 2 rows in set (0.01 sec) +------+ | a | +------+ | ä | +------+ 1 row in set (0.00 sec) {noformat} This is correct. Equality works taking into account contractions and expansions and returns both rows, while LIKE is performed one-character-to-one-character, so only one record matches. Now if I join both conditions with AND in a single WHERE, I expect one row with 'ä' to be returned, as it matches both conditions: {code:sql} SELECT * FROM t1 WHERE a='ae' AND a LIKE 'ä'; {code} But in fact I get an empty set. EXPLAIN EXTENDED returns "Impossible where", which is not correct: {noformat} mysql> EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='ae' AND a LIKE 'ä'; +------+-------------+-------+------+---------------+------+---------+------+------+----------+------------------+ | 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 | +------+-------------+-------+------+---------------+------+---------+------+------+----------+------------------+ {noformat} |
Description |
{code:sql} SET NAMES utf8 COLLATE utf8_german2_ci; DROP TABLE IF EXISTS t1; CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET utf8 COLLATE utf8_german2_ci); INSERT INTO t1 VALUES ('ae'),('ä'); SELECT * FROM t1 WHERE a='ae'; SELECT * FROM t1 WHERE a LIKE 'ä'; {code} returns these results: {noformat} +------+ | a | +------+ | ae | | ä | +------+ 2 rows in set (0.01 sec) +------+ | a | +------+ | ä | +------+ 1 row in set (0.00 sec) {noformat} This is correct. Equality works taking into account contractions and expansions and returns both rows, while LIKE is performed one-character-to-one-character, so only one record matches. Now if I join both conditions with AND in a single WHERE, I expect one row with 'ä' to be returned, as it matches both conditions: {code:sql} SELECT * FROM t1 WHERE a='ae' AND a LIKE 'ä'; {code} But in fact I get an empty set. EXPLAIN EXTENDED returns "Impossible where", which is not correct: {noformat} mysql> EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='ae' AND a LIKE 'ä'; +------+-------------+-------+------+---------------+------+---------+------+------+----------+------------------+ | 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 | +------+-------------+-------+------+---------------+------+---------+------+------+----------+------------------+ {noformat} |
{code:sql} SET NAMES utf8 COLLATE utf8_german2_ci; DROP TABLE IF EXISTS t1; CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET utf8 COLLATE utf8_german2_ci); INSERT INTO t1 VALUES ('ae'),('ä'); SELECT * FROM t1 WHERE a='ae'; SELECT * FROM t1 WHERE a LIKE 'ä'; {code} returns these results: {noformat} +------+ | a | +------+ | ae | | ä | +------+ 2 rows in set (0.01 sec) +------+ | a | +------+ | ä | +------+ 1 row in set (0.00 sec) {noformat} This is correct. Equality works taking into account contractions and expansions and returns both rows, while LIKE is performed one-character-to-one-character, so only one record matches. Now if I join both conditions with AND in a single WHERE, I expect one row with 'ä' to be returned, as it matches both conditions: {code:sql} SELECT * FROM t1 WHERE a='ae' AND a LIKE 'ä'; {code} But in fact I get an empty set. EXPLAIN EXTENDED returns "Impossible where", which is not correct: {noformat} mysql> EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='ae' AND a LIKE 'ä'; +------+-------------+-------+------+---------------+------+---------+------+------+----------+------------------+ | 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 | +------+-------------+-------+------+---------------+------+---------+------+------+----------+------------------+ {noformat} After tracing the code, it seems that constant propagation was erroneously applied. |
Component/s | Optimizer [ 10200 ] | |
Fix Version/s | 10.0.16 [ 17900 ] | |
Fix Version/s | 10.0 [ 16000 ] | |
Resolution | Fixed [ 1 ] | |
Status | Open [ 1 ] | Closed [ 6 ] |
Workflow | MariaDB v2 [ 58633 ] | MariaDB v3 [ 61804 ] |
Workflow | MariaDB v3 [ 61804 ] | MariaDB v4 [ 148497 ] |
Trying to find where exactly it happens. It's not equality propagation. Equality propagation code sees that the charset is "complex" and doesn't create an Item_equal:
#0 my_propagate_complex (cs=0x555556b94d60, str=0x0, length=0) at /home/psergey/dev-git/10.1-explain-json-r4/strings/ctype-simple.c:1683
#1 0x0000555555a50463 in check_simple_equality (left_item=0x7fffc6443898, right_item=0x7fffc64439a0, item=0x7fffc6443a38, cond_equal=0x7fffc6bb3a80) at /home/psergey/dev-git/10.1-explain-json-r4/sql/sql_select.cc:12415
#2 0x0000555555a50886 in check_equality (thd=0x7fffd0366070, item=0x7fffc6443a38, cond_equal=0x7fffc6bb3a80, eq_list=0x7fffc6bb3af0) at /home/psergey/dev-git/10.1-explain-json-r4/sql/sql_select.cc:12559
#3 0x0000555555a50991 in build_equal_items_for_cond (thd=0x7fffd0366070, cond=0x7fffc6443f88, inherited=0x0, link_item_fields=true) at /home/psergey/dev-git/10.1-explain-json-r4/sql/sql_select.cc:12662
#4 0x0000555555a51125 in build_equal_items (join=0x7fffc6444170, cond=0x7fffc6443f88, inherited=0x0, join_list=0x7fffd036a5f0, ignore_on_conds=false, cond_equal_ref=0x7fffc64445c0, link_equal_fields=true) at /home/psergey/dev-git/10.1-explain-json-r4/sql/sql_select.cc:12871
#5 0x0000555555a54535 in optimize_cond (join=0x7fffc6444170, conds=0x7fffc6443f88, join_list=0x7fffd036a5f0, ignore_on_conds=false, cond_value=0x7fffc6444498, cond_equal=0x7fffc64445c0, flags=1) at /home/psergey/dev-git/10.1-explain-json-r4/sql/sql_select.cc:14418
#6 0x0000555555a3237c in JOIN::optimize_inner (this=0x7fffc6444170) at /home/psergey/dev-git/10.1-explain-json-r4/sql/sql_select.cc:1199
#7 0x0000555555a31b02 in JOIN::optimize (this=0x7fffc6444170) at /home/psergey/dev-git/10.1-explain-json-r4/sql/sql_select.cc:1023
#8 0x0000555555a39bff in mysql_select (thd=0x7fffd0366070, rref_pointer_array=0x7fffd036a6f0, tables=0x7fffc64432a0, wild_num=1, fields=..., conds=0x7fffc6443f88, og_num=0, order=0x0, group=0x0, having=0x0, proc_param=0x0, select_options=2147748608, result=0x7fffc6444150, unit=0x7fffd0369d90, select_lex=0x7fffd036a478) at /home/psergey/dev-git/10.1-explain-json-r4/sql/sql_select.cc:3306
#9 0x0000555555a2fd0c in handle_select (thd=0x7fffd0366070, lex=0x7fffd0369cc8, result=0x7fffc6444150, setup_tables_done_option=0) at /home/psergey/dev-git/10.1-explain-json-r4/sql/sql_select.cc:372
#10 0x0000555555a02328 in execute_sqlcom_select (thd=0x7fffd0366070, all_tables=0x7fffc64432a0) at /home/psergey/dev-git/10.1-explain-json-r4/sql/sql_parse.cc:5675
#11 0x00005555559f89f2 in mysql_execute_command (thd=0x7fffd0366070) at /home/psergey/dev-git/10.1-explain-json-r4/sql/sql_parse.cc:2806
#12 0x0000555555a0543b in mysql_parse (thd=0x7fffd0366070, rawbuf=0x7fffc6443088 "SELECT * FROM t1 WHERE a='ae' AND a LIKE 'ä'", length=45, parser_state=0x7fffc6bb5090) at /home/psergey/dev-git/10.1-explain-json-r4/sql/sql_parse.cc:6946