[Commits] Rev 3380: Fix for LP BUG#908269 Wrong result with subquery in select list, EXISTS, constant MyISAM/Aria table. in file:///home/bell/maria/bzr/work-maria-5.3-lpb908269/

sanja at montyprogram.com sanja at montyprogram.com
Tue Jan 10 23:26:03 EET 2012


At file:///home/bell/maria/bzr/work-maria-5.3-lpb908269/

------------------------------------------------------------
revno: 3380
revision-id: sanja at montyprogram.com-20120110212600-7reo4b844qsyx0pi
parent: psergey at askmonty.org-20120110142056-vfrkhr2y6u6va4el
committer: sanja at montyprogram.com
branch nick: work-maria-5.3-lpb908269
timestamp: Tue 2012-01-10 23:26:00 +0200
message:
  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.
-------------- next part --------------
=== modified file 'mysql-test/r/subselect.result'
--- a/mysql-test/r/subselect.result	2011-12-24 16:55:10 +0000
+++ b/mysql-test/r/subselect.result	2012-01-10 21:26:00 +0000
@@ -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;

=== modified file 'mysql-test/r/subselect_no_mat.result'
--- a/mysql-test/r/subselect_no_mat.result	2011-12-24 16:55:10 +0000
+++ b/mysql-test/r/subselect_no_mat.result	2012-01-10 21:26:00 +0000
@@ -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;

=== modified file 'mysql-test/r/subselect_no_opts.result'
--- a/mysql-test/r/subselect_no_opts.result	2011-12-24 16:55:10 +0000
+++ b/mysql-test/r/subselect_no_opts.result	2012-01-10 21:26:00 +0000
@@ -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;

=== modified file 'mysql-test/r/subselect_no_scache.result'
--- a/mysql-test/r/subselect_no_scache.result	2011-12-24 16:55:10 +0000
+++ b/mysql-test/r/subselect_no_scache.result	2012-01-10 21:26:00 +0000
@@ -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;

=== modified file 'mysql-test/r/subselect_no_semijoin.result'
--- a/mysql-test/r/subselect_no_semijoin.result	2011-12-24 16:55:10 +0000
+++ b/mysql-test/r/subselect_no_semijoin.result	2012-01-10 21:26:00 +0000
@@ -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;

=== modified file 'mysql-test/t/subselect.test'
--- a/mysql-test/t/subselect.test	2011-12-24 16:55:10 +0000
+++ b/mysql-test/t/subselect.test	2012-01-10 21:26:00 +0000
@@ -4990,5 +4990,33 @@ SELECT * FROM t1 WHERE a IN (SELECT a AS
 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;

=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc	2012-01-08 10:43:14 +0000
+++ b/sql/sql_select.cc	2012-01-10 21:26:00 +0000
@@ -8033,14 +8033,33 @@ make_join_select(JOIN *join,SQL_SELECT *
           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,
     /*
       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)

=== modified file 'sql/sql_select.h'
--- a/sql/sql_select.h	2011-12-19 14:07:19 +0000
+++ b/sql/sql_select.h	2012-01-10 21:26:00 +0000
@@ -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;
   }



More information about the commits mailing list