mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
MDEV-36389 Incorrect query results for an indexed text column
Fixes a scenario where an IN subquery returned the wrong result because the pushed WHERE clause was not retained for downstream result filtering. For example: CREATE TABLE t1 (c1 TEXT, UNIQUE (c1(1))); INSERT INTO t1 (c1) VALUES ('a'); SELECT 'abc' IN (SELECT c1 FROM t1); Internally, he 'abc' IN subquery condition becomes the constant condition: 'abc' = t1.c1 or t1.c1 is null Prior to this patch, this condition was incorrectly removed when converting the subquery engine to an index lookup-based engine. Now eligible conditions are preserved during such engine rewrites.
This commit is contained in:
committed by
Dave Gosselin
parent
3109d994eb
commit
a52362b90c
@@ -997,9 +997,9 @@ a t1.a in (select t2.a from t2)
|
||||
explain extended SELECT t1.a, t1.a in (select t2.a from t2) FROM t1;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 PRIMARY t1 index NULL PRIMARY 4 NULL 4 100.00 Using index
|
||||
2 SUBQUERY t2 index_subquery a a 5 func 2 100.00 Using index
|
||||
2 DEPENDENT SUBQUERY t2 index_subquery a a 5 func 2 100.00 Using index; Using where
|
||||
Warnings:
|
||||
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,<expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`a`) in t2 on a checking NULL having `test`.`t2`.`a` is null)))) AS `t1.a in (select t2.a from t2)` from `test`.`t1`
|
||||
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,<expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`a`) in t2 on a checking NULL where <cache>(`test`.`t1`.`a`) = `test`.`t2`.`a` or `test`.`t2`.`a` is null having `test`.`t2`.`a` is null)))) AS `t1.a in (select t2.a from t2)` from `test`.`t1`
|
||||
CREATE TABLE t3 (a int(11) default '0');
|
||||
INSERT INTO t3 VALUES (1),(2),(3);
|
||||
SELECT t1.a, t1.a in (select t2.a from t2,t3 where t3.a=t2.a) FROM t1;
|
||||
@@ -1706,27 +1706,27 @@ a3 1
|
||||
explain extended select s1, s1 NOT IN (SELECT s1 FROM t2) from t1;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index
|
||||
2 SUBQUERY t2 index_subquery s1 s1 6 func 2 100.00 Using index; Full scan on NULL key
|
||||
2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 2 100.00 Using index; Using where; Full scan on NULL key
|
||||
Warnings:
|
||||
Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,!<expr_cache><`test`.`t1`.`s1`>(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond(`test`.`t2`.`s1` is null))))) AS `s1 NOT IN (SELECT s1 FROM t2)` from `test`.`t1`
|
||||
Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,!<expr_cache><`test`.`t1`.`s1`>(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL where trigcond(<cache>(`test`.`t1`.`s1`) = `test`.`t2`.`s1` or `test`.`t2`.`s1` is null) having trigcond(`test`.`t2`.`s1` is null))))) AS `s1 NOT IN (SELECT s1 FROM t2)` from `test`.`t1`
|
||||
explain extended select s1, s1 = ANY (SELECT s1 FROM t2) from t1;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index
|
||||
2 SUBQUERY t2 index_subquery s1 s1 6 func 2 100.00 Using index; Full scan on NULL key
|
||||
2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 2 100.00 Using index; Using where; Full scan on NULL key
|
||||
Warnings:
|
||||
Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,<expr_cache><`test`.`t1`.`s1`>(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond(`test`.`t2`.`s1` is null))))) AS `s1 = ANY (SELECT s1 FROM t2)` from `test`.`t1`
|
||||
Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,<expr_cache><`test`.`t1`.`s1`>(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL where trigcond(<cache>(`test`.`t1`.`s1`) = `test`.`t2`.`s1` or `test`.`t2`.`s1` is null) having trigcond(`test`.`t2`.`s1` is null))))) AS `s1 = ANY (SELECT s1 FROM t2)` from `test`.`t1`
|
||||
explain extended select s1, s1 <> ALL (SELECT s1 FROM t2) from t1;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index
|
||||
2 SUBQUERY t2 index_subquery s1 s1 6 func 2 100.00 Using index; Full scan on NULL key
|
||||
2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 2 100.00 Using index; Using where; Full scan on NULL key
|
||||
Warnings:
|
||||
Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,!<expr_cache><`test`.`t1`.`s1`>(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond(`test`.`t2`.`s1` is null))))) AS `s1 <> ALL (SELECT s1 FROM t2)` from `test`.`t1`
|
||||
Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,!<expr_cache><`test`.`t1`.`s1`>(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL where trigcond(<cache>(`test`.`t1`.`s1`) = `test`.`t2`.`s1` or `test`.`t2`.`s1` is null) having trigcond(`test`.`t2`.`s1` is null))))) AS `s1 <> ALL (SELECT s1 FROM t2)` from `test`.`t1`
|
||||
explain extended select s1, s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2') from t1;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index
|
||||
2 SUBQUERY t2 index_subquery s1 s1 6 func 2 50.00 Using index; Using where; Full scan on NULL key
|
||||
2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 2 50.00 Using index; Using where; Full scan on NULL key
|
||||
Warnings:
|
||||
Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,!<expr_cache><`test`.`t1`.`s1`>(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL where `test`.`t2`.`s1` < 'a2' having trigcond(`test`.`t2`.`s1` is null))))) AS `s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2')` from `test`.`t1`
|
||||
Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,!<expr_cache><`test`.`t1`.`s1`>(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL where `test`.`t2`.`s1` < 'a2' and trigcond(<cache>(`test`.`t1`.`s1`) = `test`.`t2`.`s1` or `test`.`t2`.`s1` is null) having trigcond(`test`.`t2`.`s1` is null))))) AS `s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2')` from `test`.`t1`
|
||||
drop table t1,t2;
|
||||
create table t2 (a int, b int not null);
|
||||
create table t3 (a int);
|
||||
@@ -3277,7 +3277,7 @@ INSERT INTO t2 VALUES (1),(2),(3);
|
||||
EXPLAIN SELECT a, a IN (SELECT a FROM t1) FROM t2;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 PRIMARY t2 ALL NULL NULL NULL NULL 3
|
||||
2 SUBQUERY t1 index_subquery a a 5 func 3 Using index; Full scan on NULL key
|
||||
2 DEPENDENT SUBQUERY t1 index_subquery a a 5 func 3 Using index; Using where; Full scan on NULL key
|
||||
SELECT a, a IN (SELECT a FROM t1) FROM t2;
|
||||
a a IN (SELECT a FROM t1)
|
||||
1 1
|
||||
@@ -6762,7 +6762,7 @@ SET @@optimizer_switch='semijoin=off,materialization=off,in_to_exists=on,subquer
|
||||
EXPLAIN SELECT * FROM t1 WHERE a IN (SELECT a AS field1 FROM t1 GROUP BY field1);
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 PRIMARY t1 index NULL a 4 NULL 2 Using where; Using index
|
||||
2 DEPENDENT SUBQUERY t1 index_subquery a a 4 func 1 Using index
|
||||
2 SUBQUERY t1 index_subquery a a 4 func 1 Using index
|
||||
SELECT * FROM t1 WHERE a IN (SELECT a AS field1 FROM t1 GROUP BY field1);
|
||||
a
|
||||
2009-01-01
|
||||
|
Reference in New Issue
Block a user