Commit cf31ccc3 authored by unknown's avatar unknown

Fix for LP BUG#908269 Wrong result with subquery in select list, EXISTS,...

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.
parent d21189d7
......@@ -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,7 +8033,10 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
DBUG_RETURN(1); // Impossible const condition
}
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);
......@@ -8043,6 +8046,22 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *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;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment