Fix for LP BUG#908269 Wrong result with subquery in select list, EXISTS, constant MyISAM/Aria table.
Problem: When building the condition for JOIN::outer_ref_cond the optimizer forgot to take into account that this condition could depend on constant tables as well.
This commit is contained in:
parent
d21189d775
commit
cf31ccc33c
@ -5908,5 +5908,29 @@ a
|
||||
2009-02-02
|
||||
set @@optimizer_switch=@old_optimizer_switch;
|
||||
drop table t1;
|
||||
#
|
||||
# LP BUG#908269 incorrect condition in case of subqueries depending
|
||||
# on constant tables
|
||||
#
|
||||
CREATE TABLE t1 ( a INT );
|
||||
INSERT INTO t1 VALUES (1),(5);
|
||||
CREATE TABLE t2 ( b INT ) ENGINE=MyISAM;
|
||||
INSERT INTO t2 VALUES (1);
|
||||
CREATE TABLE t3 ( c INT );
|
||||
INSERT INTO t3 VALUES (4),(5);
|
||||
SET optimizer_switch='subquery_cache=off';
|
||||
SELECT ( SELECT b FROM t2 WHERE b = a OR EXISTS ( SELECT c FROM t3 WHERE c = b ) ) FROM t1;
|
||||
( SELECT b FROM t2 WHERE b = a OR EXISTS ( SELECT c FROM t3 WHERE c = b ) )
|
||||
1
|
||||
NULL
|
||||
SELECT ( SELECT b FROM t2 WHERE b = a OR b * 0) FROM t1;
|
||||
( SELECT b FROM t2 WHERE b = a OR b * 0)
|
||||
1
|
||||
NULL
|
||||
SELECT ( SELECT b FROM t2 WHERE b = a OR rand() * 0) FROM t1;
|
||||
( SELECT b FROM t2 WHERE b = a OR rand() * 0)
|
||||
1
|
||||
NULL
|
||||
drop table t1,t2,t3;
|
||||
# return optimizer switch changed in the beginning of this test
|
||||
set optimizer_switch=@subselect_tmp;
|
||||
|
@ -5909,6 +5909,30 @@ a
|
||||
2009-02-02
|
||||
set @@optimizer_switch=@old_optimizer_switch;
|
||||
drop table t1;
|
||||
#
|
||||
# LP BUG#908269 incorrect condition in case of subqueries depending
|
||||
# on constant tables
|
||||
#
|
||||
CREATE TABLE t1 ( a INT );
|
||||
INSERT INTO t1 VALUES (1),(5);
|
||||
CREATE TABLE t2 ( b INT ) ENGINE=MyISAM;
|
||||
INSERT INTO t2 VALUES (1);
|
||||
CREATE TABLE t3 ( c INT );
|
||||
INSERT INTO t3 VALUES (4),(5);
|
||||
SET optimizer_switch='subquery_cache=off';
|
||||
SELECT ( SELECT b FROM t2 WHERE b = a OR EXISTS ( SELECT c FROM t3 WHERE c = b ) ) FROM t1;
|
||||
( SELECT b FROM t2 WHERE b = a OR EXISTS ( SELECT c FROM t3 WHERE c = b ) )
|
||||
1
|
||||
NULL
|
||||
SELECT ( SELECT b FROM t2 WHERE b = a OR b * 0) FROM t1;
|
||||
( SELECT b FROM t2 WHERE b = a OR b * 0)
|
||||
1
|
||||
NULL
|
||||
SELECT ( SELECT b FROM t2 WHERE b = a OR rand() * 0) FROM t1;
|
||||
( SELECT b FROM t2 WHERE b = a OR rand() * 0)
|
||||
1
|
||||
NULL
|
||||
drop table t1,t2,t3;
|
||||
# return optimizer switch changed in the beginning of this test
|
||||
set optimizer_switch=@subselect_tmp;
|
||||
set optimizer_switch=default;
|
||||
|
@ -5905,6 +5905,30 @@ a
|
||||
2009-02-02
|
||||
set @@optimizer_switch=@old_optimizer_switch;
|
||||
drop table t1;
|
||||
#
|
||||
# LP BUG#908269 incorrect condition in case of subqueries depending
|
||||
# on constant tables
|
||||
#
|
||||
CREATE TABLE t1 ( a INT );
|
||||
INSERT INTO t1 VALUES (1),(5);
|
||||
CREATE TABLE t2 ( b INT ) ENGINE=MyISAM;
|
||||
INSERT INTO t2 VALUES (1);
|
||||
CREATE TABLE t3 ( c INT );
|
||||
INSERT INTO t3 VALUES (4),(5);
|
||||
SET optimizer_switch='subquery_cache=off';
|
||||
SELECT ( SELECT b FROM t2 WHERE b = a OR EXISTS ( SELECT c FROM t3 WHERE c = b ) ) FROM t1;
|
||||
( SELECT b FROM t2 WHERE b = a OR EXISTS ( SELECT c FROM t3 WHERE c = b ) )
|
||||
1
|
||||
NULL
|
||||
SELECT ( SELECT b FROM t2 WHERE b = a OR b * 0) FROM t1;
|
||||
( SELECT b FROM t2 WHERE b = a OR b * 0)
|
||||
1
|
||||
NULL
|
||||
SELECT ( SELECT b FROM t2 WHERE b = a OR rand() * 0) FROM t1;
|
||||
( SELECT b FROM t2 WHERE b = a OR rand() * 0)
|
||||
1
|
||||
NULL
|
||||
drop table t1,t2,t3;
|
||||
# return optimizer switch changed in the beginning of this test
|
||||
set optimizer_switch=@subselect_tmp;
|
||||
set @optimizer_switch_for_subselect_test=null;
|
||||
|
@ -5914,6 +5914,30 @@ a
|
||||
2009-02-02
|
||||
set @@optimizer_switch=@old_optimizer_switch;
|
||||
drop table t1;
|
||||
#
|
||||
# LP BUG#908269 incorrect condition in case of subqueries depending
|
||||
# on constant tables
|
||||
#
|
||||
CREATE TABLE t1 ( a INT );
|
||||
INSERT INTO t1 VALUES (1),(5);
|
||||
CREATE TABLE t2 ( b INT ) ENGINE=MyISAM;
|
||||
INSERT INTO t2 VALUES (1);
|
||||
CREATE TABLE t3 ( c INT );
|
||||
INSERT INTO t3 VALUES (4),(5);
|
||||
SET optimizer_switch='subquery_cache=off';
|
||||
SELECT ( SELECT b FROM t2 WHERE b = a OR EXISTS ( SELECT c FROM t3 WHERE c = b ) ) FROM t1;
|
||||
( SELECT b FROM t2 WHERE b = a OR EXISTS ( SELECT c FROM t3 WHERE c = b ) )
|
||||
1
|
||||
NULL
|
||||
SELECT ( SELECT b FROM t2 WHERE b = a OR b * 0) FROM t1;
|
||||
( SELECT b FROM t2 WHERE b = a OR b * 0)
|
||||
1
|
||||
NULL
|
||||
SELECT ( SELECT b FROM t2 WHERE b = a OR rand() * 0) FROM t1;
|
||||
( SELECT b FROM t2 WHERE b = a OR rand() * 0)
|
||||
1
|
||||
NULL
|
||||
drop table t1,t2,t3;
|
||||
# return optimizer switch changed in the beginning of this test
|
||||
set optimizer_switch=@subselect_tmp;
|
||||
set optimizer_switch=default;
|
||||
|
@ -5905,6 +5905,30 @@ a
|
||||
2009-02-02
|
||||
set @@optimizer_switch=@old_optimizer_switch;
|
||||
drop table t1;
|
||||
#
|
||||
# LP BUG#908269 incorrect condition in case of subqueries depending
|
||||
# on constant tables
|
||||
#
|
||||
CREATE TABLE t1 ( a INT );
|
||||
INSERT INTO t1 VALUES (1),(5);
|
||||
CREATE TABLE t2 ( b INT ) ENGINE=MyISAM;
|
||||
INSERT INTO t2 VALUES (1);
|
||||
CREATE TABLE t3 ( c INT );
|
||||
INSERT INTO t3 VALUES (4),(5);
|
||||
SET optimizer_switch='subquery_cache=off';
|
||||
SELECT ( SELECT b FROM t2 WHERE b = a OR EXISTS ( SELECT c FROM t3 WHERE c = b ) ) FROM t1;
|
||||
( SELECT b FROM t2 WHERE b = a OR EXISTS ( SELECT c FROM t3 WHERE c = b ) )
|
||||
1
|
||||
NULL
|
||||
SELECT ( SELECT b FROM t2 WHERE b = a OR b * 0) FROM t1;
|
||||
( SELECT b FROM t2 WHERE b = a OR b * 0)
|
||||
1
|
||||
NULL
|
||||
SELECT ( SELECT b FROM t2 WHERE b = a OR rand() * 0) FROM t1;
|
||||
( SELECT b FROM t2 WHERE b = a OR rand() * 0)
|
||||
1
|
||||
NULL
|
||||
drop table t1,t2,t3;
|
||||
# return optimizer switch changed in the beginning of this test
|
||||
set optimizer_switch=@subselect_tmp;
|
||||
set @optimizer_switch_for_subselect_test=null;
|
||||
|
@ -4990,5 +4990,33 @@ SELECT * FROM t1 WHERE a IN (SELECT a AS field1 FROM t1 GROUP BY field1);
|
||||
set @@optimizer_switch=@old_optimizer_switch;
|
||||
drop table t1;
|
||||
|
||||
--echo #
|
||||
--echo # LP BUG#908269 incorrect condition in case of subqueries depending
|
||||
--echo # on constant tables
|
||||
--echo #
|
||||
CREATE TABLE t1 ( a INT );
|
||||
INSERT INTO t1 VALUES (1),(5);
|
||||
|
||||
# t2 must be MyISAM or Aria and contain 1 row
|
||||
CREATE TABLE t2 ( b INT ) ENGINE=MyISAM;
|
||||
INSERT INTO t2 VALUES (1);
|
||||
|
||||
CREATE TABLE t3 ( c INT );
|
||||
INSERT INTO t3 VALUES (4),(5);
|
||||
|
||||
SET optimizer_switch='subquery_cache=off';
|
||||
|
||||
SELECT ( SELECT b FROM t2 WHERE b = a OR EXISTS ( SELECT c FROM t3 WHERE c = b ) ) FROM t1;
|
||||
|
||||
# This query just for example, it should return the same as above (1 and NULL)
|
||||
SELECT ( SELECT b FROM t2 WHERE b = a OR b * 0) FROM t1;
|
||||
|
||||
# example with "random"
|
||||
SELECT ( SELECT b FROM t2 WHERE b = a OR rand() * 0) FROM t1;
|
||||
|
||||
|
||||
drop table t1,t2,t3;
|
||||
|
||||
|
||||
--echo # return optimizer switch changed in the beginning of this test
|
||||
set optimizer_switch=@subselect_tmp;
|
||||
|
@ -8033,14 +8033,33 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
|
||||
DBUG_RETURN(1); // Impossible const condition
|
||||
}
|
||||
|
||||
COND *outer_ref_cond= make_cond_for_table(thd, cond,
|
||||
OUTER_REF_TABLE_BIT,
|
||||
OUTER_REF_TABLE_BIT,
|
||||
-1, FALSE, FALSE);
|
||||
if (outer_ref_cond)
|
||||
{
|
||||
add_cond_and_fix(thd, &outer_ref_cond, join->outer_ref_cond);
|
||||
join->outer_ref_cond= outer_ref_cond;
|
||||
if (join->table_count != join->const_tables)
|
||||
{
|
||||
COND *outer_ref_cond= make_cond_for_table(thd, cond,
|
||||
join->const_table_map |
|
||||
OUTER_REF_TABLE_BIT,
|
||||
OUTER_REF_TABLE_BIT,
|
||||
-1, FALSE, FALSE);
|
||||
if (outer_ref_cond)
|
||||
{
|
||||
add_cond_and_fix(thd, &outer_ref_cond, join->outer_ref_cond);
|
||||
join->outer_ref_cond= outer_ref_cond;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
COND *pseudo_bits_cond=
|
||||
make_cond_for_table(thd, cond,
|
||||
join->const_table_map |
|
||||
PSEUDO_TABLE_BITS,
|
||||
PSEUDO_TABLE_BITS,
|
||||
-1, FALSE, FALSE);
|
||||
if (pseudo_bits_cond)
|
||||
{
|
||||
add_cond_and_fix(thd, &pseudo_bits_cond,
|
||||
join->pseudo_bits_cond);
|
||||
join->pseudo_bits_cond= pseudo_bits_cond;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -14927,14 +14946,15 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
|
||||
/*
|
||||
HAVING will be checked after processing aggregate functions,
|
||||
But WHERE should checked here (we alredy have read tables).
|
||||
Notice that make_join_select() splits all conditions into three groups -
|
||||
exec_const_cond, outer_ref_cond, and conditions attached to non-constant
|
||||
tables. Within this IF the latter do not exist. At the same time
|
||||
Notice that make_join_select() splits all conditions in this case
|
||||
into two groups exec_const_cond and outer_ref_cond.
|
||||
Within this other conditions are not exists. At the same time
|
||||
exec_const_cond is already checked either by make_join_select or in the
|
||||
beginning of JOIN::exec. Therefore here it is sufficient to check only
|
||||
outer_ref_cond.
|
||||
pseudo_bits_cond.
|
||||
*/
|
||||
if (!join->outer_ref_cond || join->outer_ref_cond->val_int())
|
||||
DBUG_ASSERT(join->outer_ref_cond == NULL);
|
||||
if (!join->pseudo_bits_cond || join->pseudo_bits_cond->val_int())
|
||||
{
|
||||
error= (*end_select)(join, 0, 0);
|
||||
if (error == NESTED_LOOP_OK || error == NESTED_LOOP_QUERY_LIMIT)
|
||||
|
@ -1111,6 +1111,7 @@ public:
|
||||
COND *conds; // ---"---
|
||||
Item *conds_history; // store WHERE for explain
|
||||
COND *outer_ref_cond; ///<part of conds containing only outer references
|
||||
COND *pseudo_bits_cond; // part of conds containing special bita
|
||||
TABLE_LIST *tables_list; ///<hold 'tables' parameter of mysql_select
|
||||
List<TABLE_LIST> *join_list; ///< list of joined tables in reverse order
|
||||
COND_EQUAL *cond_equal;
|
||||
@ -1237,7 +1238,7 @@ public:
|
||||
rollup.state= ROLLUP::STATE_NONE;
|
||||
|
||||
no_const_tables= FALSE;
|
||||
outer_ref_cond= 0;
|
||||
outer_ref_cond= pseudo_bits_cond= NULL;
|
||||
in_to_exists_where= NULL;
|
||||
in_to_exists_having= NULL;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user