List:Commits« Previous MessageNext Message »
From:Olav Sandstaa Date:August 30 2010 10:04am
Subject:bzr commit into mysql-next-mr-bugfixing branch (olav:3232) Bug#52605
View as plain text  
#At file:///export/home/tmp/mysql/opt-bug52605-v2/ based on revid:epotemkin@stripped

 3232 Olav Sandstaa	2010-08-30
      Fix for Bug#52605 Adding LIMIT 1 clause to query with complex range predicate causes wrong results
                        
      The cause for the wrong result returned when adding the LIMIT 1 to
      this query was:
                        
      * during the optimize phase ICP code pushed part of the WHERE clause
        down to the storage engine based on that the query should be
        executed as a range query using the primary key.            
            
      * in the start of the execution phase the LIMIT clause is considered
        and alternative access strategies are evaluated in order to reduce
        the cost for reading records. This resulted in the switching to a
        different index for reading the data from the storage engine.
                        
      As a consequence of this change of access strategy (switching index)
      the part of the WHERE clause that had been pushed down to the storage
      engine was never evaluated.
                        
      The fix for this is to detect that we have switched index and in that
      case ensure that the condition that was previously been pushed to the
      storage engine is included in the condition that is evaluated by the
      server.
            
      Note that this patch also fixes tow other issues:
      
      * The existing code assumed that tab->pre_idx_push_select_cond contained 
        the complete original select condition. This was not always the case.
        The situation could occur when ref access is used. In this case the
        where condition that is covered by the ref access is not included when
        creating the initial select condition for a table (in make_cond_for_table().
        The tab->pre_idx_push_select_cond is based on this value. Later, just before
        calling test_if_skip_sort_order() the where condition corresponding
        to the ref access is added to the table's select condition but not
        to the tab->pre_idx_push_select_cond (in add_ref_to_table_cond()). This 
        patch adds a fix for this by extending add_ref_to_table_cond() to also
        add the condition for the ref access to tab->pre_idx_push_select_cond.
      
      * if the entire where condition was pushed down to the storage engine 
        then tab->select_cond would be NULL when calling
        test_if_skip_sort_order(). If this was replaced by the pre-pushed index
        condition it would never be restored back to NULL. This would result 
        in that the where condition would be evaluated both by the storage 
        engine and in the server.
     @ mysql-test/include/icp_tests.inc
        Test case for Bug#52605 Adding LIMIT 1 clause to query with complex 
        range predicate causes wrong results.
     @ mysql-test/r/innodb_icp.result
        Result for test case for Bug#52605 Adding LIMIT 1 clause to query
        with complex range predicate causes wrong results.
     @ mysql-test/r/innodb_icp_all.result
        Result for test case for Bug#52605 Adding LIMIT 1 clause to query
        with complex range predicate causes wrong results.
     @ mysql-test/r/innodb_icp_none.result
        Result for test case for Bug#52605 Adding LIMIT 1 clause to query
        with complex range predicate causes wrong results.
     @ mysql-test/r/myisam_icp.result
        Result for test case for Bug#52605 Adding LIMIT 1 clause to query
        with complex range predicate causes wrong results.
     @ mysql-test/r/myisam_icp_all.result
        Result for test case for Bug#52605 Adding LIMIT 1 clause to query
        with complex range predicate causes wrong results.
     @ mysql-test/r/myisam_icp_none.result
        Result for test case for Bug#52605 Adding LIMIT 1 clause to query
        with complex range predicate causes wrong results.
     @ mysql-test/r/order_by_all.result
        This change in  explain output are caused by the second 
        issue fixed in this patch. Do to failing to restore tab->select_cond
        to NULL the complete where clause was instead evaluated by the server
        in addition to being pushed to the storage engine.
     @ mysql-test/r/order_by_icp_mrr.result
        This change in  explain output are caused by the second 
        issue fixed in this patch. Do to failing to restore tab->select_cond
        to NULL the complete where clause was instead evaluated by the server
        in addition to being pushed to the storage engine.
     @ sql/sql_select.cc
        Extend test_if_skip_sort_order() to handle the situation where parts
        of the WHERE condition has been pushed down to the storage engine
        (ICP) and where we based on cost estimates switches to use a different
        index. In this case we should ensure that the original WHERE condition 
        as it was before it was pushed to the storage
        is used instead of the current where condition stored in the join_tab.
        The code in test_if_skip_sort_order() already used the original where 
        condition but restored the current where condition when exiting the function
        The fix for this is to detect if we changes to use a new index and then
        not restore the current where condition  if we have changed to use a new index.
                
        The patch also fixes two other issues in test_if_skip_sort_order():
        
        * The existing code assumed that tab->pre_idx_push_select_cond contained 
          the complete original select condition. This was not always the case.
          The situation could occur when ref access is used. In this case the
          where condition that is covered by the ref access is not included when
          creating the initial select condition for a table (in make_cond_for_table().
          The tab->pre_idx_push_select_cond is based on this value. Later, just before
          calling test_if_skip_sort_order() the where condition corresponding
          to the ref access is added to the table's select condition but not
          to the tab->pre_idx_push_select_cond (in add_ref_to_table_cond()). This 
          patch adds a fix for this by extending add_ref_to_table_cond() to also
          add the condition for the ref access to tab->pre_idx_push_select_cond.
              
        * If tab->select_cond is NULL we would store this NULL in orig_select_cond.
          When we later check if orig_select_cond should be restored back into
          tab->select_cond we are not able to distinguish between orig_select_cond 
          being NULL meaning (a) we have not stored anything in it and (b) we
          have stored an empty where condition into it. The consequence of this 
          issue was that the complete where condition could be evaluated both
          by the storage engine and by the server.

    modified:
      mysql-test/include/icp_tests.inc
      mysql-test/r/innodb_icp.result
      mysql-test/r/innodb_icp_all.result
      mysql-test/r/innodb_icp_none.result
      mysql-test/r/myisam_icp.result
      mysql-test/r/myisam_icp_all.result
      mysql-test/r/myisam_icp_none.result
      mysql-test/r/order_by_all.result
      mysql-test/r/order_by_icp_mrr.result
      sql/sql_select.cc
=== modified file 'mysql-test/include/icp_tests.inc'

=== modified file 'mysql-test/include/icp_tests.inc'
--- a/mysql-test/include/icp_tests.inc	2010-06-20 07:16:27 +0000
+++ b/mysql-test/include/icp_tests.inc	2010-08-30 10:04:02 +0000
@@ -402,3 +402,37 @@
 
 DROP TABLE t1;
 
+--echo #
+--echo # Bug#52605 - "Adding LIMIT 1 clause to query with complex range 
+--echo #              predicate causes wrong results"
+--echo #
+
+CREATE TABLE t1 (
+  pk INT NOT NULL,
+  c1 INT,
+  PRIMARY KEY (pk),
+  KEY k1 (c1)
+);
+
+INSERT INTO t1 VALUES (1,NULL);
+INSERT INTO t1 VALUES (2,6);
+INSERT INTO t1 VALUES (3,NULL);
+INSERT INTO t1 VALUES (4,6);
+INSERT INTO t1 VALUES (5,NULL);
+INSERT INTO t1 VALUES (6,NULL);
+INSERT INTO t1 VALUES (7,9);
+INSERT INTO t1 VALUES (8,0);
+
+SELECT pk, c1
+FROM t1  
+WHERE (pk BETWEEN 4 AND 5 OR pk < 2) AND c1 < 240
+ORDER BY c1
+LIMIT 1;
+
+EXPLAIN SELECT pk, c1
+FROM t1  
+WHERE (pk BETWEEN 4 AND 5 OR pk < 2) AND c1 < 240
+ORDER BY c1
+LIMIT 1;
+
+DROP TABLE t1;

=== modified file 'mysql-test/r/innodb_icp.result'
--- a/mysql-test/r/innodb_icp.result	2010-08-23 11:28:58 +0000
+++ b/mysql-test/r/innodb_icp.result	2010-08-30 10:04:02 +0000
@@ -368,5 +368,38 @@
 f1
 b
 DROP TABLE t1;
+#
+# Bug#52605 - "Adding LIMIT 1 clause to query with complex range 
+#              predicate causes wrong results"
+#
+CREATE TABLE t1 (
+pk INT NOT NULL,
+c1 INT,
+PRIMARY KEY (pk),
+KEY k1 (c1)
+);
+INSERT INTO t1 VALUES (1,NULL);
+INSERT INTO t1 VALUES (2,6);
+INSERT INTO t1 VALUES (3,NULL);
+INSERT INTO t1 VALUES (4,6);
+INSERT INTO t1 VALUES (5,NULL);
+INSERT INTO t1 VALUES (6,NULL);
+INSERT INTO t1 VALUES (7,9);
+INSERT INTO t1 VALUES (8,0);
+SELECT pk, c1
+FROM t1  
+WHERE (pk BETWEEN 4 AND 5 OR pk < 2) AND c1 < 240
+ORDER BY c1
+LIMIT 1;
+pk	c1
+4	6
+EXPLAIN SELECT pk, c1
+FROM t1  
+WHERE (pk BETWEEN 4 AND 5 OR pk < 2) AND c1 < 240
+ORDER BY c1
+LIMIT 1;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	range	PRIMARY,k1	k1	5	NULL	3	Using where; Using index
+DROP TABLE t1;
 set storage_engine= @save_storage_engine;
 set optimizer_switch=default;

=== modified file 'mysql-test/r/innodb_icp_all.result'
--- a/mysql-test/r/innodb_icp_all.result	2010-08-23 11:28:58 +0000
+++ b/mysql-test/r/innodb_icp_all.result	2010-08-30 10:04:02 +0000
@@ -368,5 +368,38 @@
 f1
 b
 DROP TABLE t1;
+#
+# Bug#52605 - "Adding LIMIT 1 clause to query with complex range 
+#              predicate causes wrong results"
+#
+CREATE TABLE t1 (
+pk INT NOT NULL,
+c1 INT,
+PRIMARY KEY (pk),
+KEY k1 (c1)
+);
+INSERT INTO t1 VALUES (1,NULL);
+INSERT INTO t1 VALUES (2,6);
+INSERT INTO t1 VALUES (3,NULL);
+INSERT INTO t1 VALUES (4,6);
+INSERT INTO t1 VALUES (5,NULL);
+INSERT INTO t1 VALUES (6,NULL);
+INSERT INTO t1 VALUES (7,9);
+INSERT INTO t1 VALUES (8,0);
+SELECT pk, c1
+FROM t1  
+WHERE (pk BETWEEN 4 AND 5 OR pk < 2) AND c1 < 240
+ORDER BY c1
+LIMIT 1;
+pk	c1
+4	6
+EXPLAIN SELECT pk, c1
+FROM t1  
+WHERE (pk BETWEEN 4 AND 5 OR pk < 2) AND c1 < 240
+ORDER BY c1
+LIMIT 1;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	range	PRIMARY,k1	k1	5	NULL	3	Using where; Using index
+DROP TABLE t1;
 set storage_engine= @save_storage_engine;
 set optimizer_switch=default;

=== modified file 'mysql-test/r/innodb_icp_none.result'
--- a/mysql-test/r/innodb_icp_none.result	2010-08-23 11:28:58 +0000
+++ b/mysql-test/r/innodb_icp_none.result	2010-08-30 10:04:02 +0000
@@ -367,5 +367,38 @@
 f1
 b
 DROP TABLE t1;
+#
+# Bug#52605 - "Adding LIMIT 1 clause to query with complex range 
+#              predicate causes wrong results"
+#
+CREATE TABLE t1 (
+pk INT NOT NULL,
+c1 INT,
+PRIMARY KEY (pk),
+KEY k1 (c1)
+);
+INSERT INTO t1 VALUES (1,NULL);
+INSERT INTO t1 VALUES (2,6);
+INSERT INTO t1 VALUES (3,NULL);
+INSERT INTO t1 VALUES (4,6);
+INSERT INTO t1 VALUES (5,NULL);
+INSERT INTO t1 VALUES (6,NULL);
+INSERT INTO t1 VALUES (7,9);
+INSERT INTO t1 VALUES (8,0);
+SELECT pk, c1
+FROM t1  
+WHERE (pk BETWEEN 4 AND 5 OR pk < 2) AND c1 < 240
+ORDER BY c1
+LIMIT 1;
+pk	c1
+4	6
+EXPLAIN SELECT pk, c1
+FROM t1  
+WHERE (pk BETWEEN 4 AND 5 OR pk < 2) AND c1 < 240
+ORDER BY c1
+LIMIT 1;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	range	PRIMARY,k1	k1	5	NULL	3	Using where; Using index
+DROP TABLE t1;
 set storage_engine= @save_storage_engine;
 set optimizer_switch=default;

=== modified file 'mysql-test/r/myisam_icp.result'
--- a/mysql-test/r/myisam_icp.result	2010-06-18 08:45:53 +0000
+++ b/mysql-test/r/myisam_icp.result	2010-08-30 10:04:02 +0000
@@ -366,4 +366,37 @@
 f1
 b
 DROP TABLE t1;
+#
+# Bug#52605 - "Adding LIMIT 1 clause to query with complex range 
+#              predicate causes wrong results"
+#
+CREATE TABLE t1 (
+pk INT NOT NULL,
+c1 INT,
+PRIMARY KEY (pk),
+KEY k1 (c1)
+);
+INSERT INTO t1 VALUES (1,NULL);
+INSERT INTO t1 VALUES (2,6);
+INSERT INTO t1 VALUES (3,NULL);
+INSERT INTO t1 VALUES (4,6);
+INSERT INTO t1 VALUES (5,NULL);
+INSERT INTO t1 VALUES (6,NULL);
+INSERT INTO t1 VALUES (7,9);
+INSERT INTO t1 VALUES (8,0);
+SELECT pk, c1
+FROM t1  
+WHERE (pk BETWEEN 4 AND 5 OR pk < 2) AND c1 < 240
+ORDER BY c1
+LIMIT 1;
+pk	c1
+4	6
+EXPLAIN SELECT pk, c1
+FROM t1  
+WHERE (pk BETWEEN 4 AND 5 OR pk < 2) AND c1 < 240
+ORDER BY c1
+LIMIT 1;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	range	PRIMARY,k1	k1	5	NULL	4	Using where
+DROP TABLE t1;
 set optimizer_switch=default;

=== modified file 'mysql-test/r/myisam_icp_all.result'
--- a/mysql-test/r/myisam_icp_all.result	2010-06-20 07:16:27 +0000
+++ b/mysql-test/r/myisam_icp_all.result	2010-08-30 10:04:02 +0000
@@ -366,4 +366,37 @@
 f1
 b
 DROP TABLE t1;
+#
+# Bug#52605 - "Adding LIMIT 1 clause to query with complex range 
+#              predicate causes wrong results"
+#
+CREATE TABLE t1 (
+pk INT NOT NULL,
+c1 INT,
+PRIMARY KEY (pk),
+KEY k1 (c1)
+);
+INSERT INTO t1 VALUES (1,NULL);
+INSERT INTO t1 VALUES (2,6);
+INSERT INTO t1 VALUES (3,NULL);
+INSERT INTO t1 VALUES (4,6);
+INSERT INTO t1 VALUES (5,NULL);
+INSERT INTO t1 VALUES (6,NULL);
+INSERT INTO t1 VALUES (7,9);
+INSERT INTO t1 VALUES (8,0);
+SELECT pk, c1
+FROM t1  
+WHERE (pk BETWEEN 4 AND 5 OR pk < 2) AND c1 < 240
+ORDER BY c1
+LIMIT 1;
+pk	c1
+4	6
+EXPLAIN SELECT pk, c1
+FROM t1  
+WHERE (pk BETWEEN 4 AND 5 OR pk < 2) AND c1 < 240
+ORDER BY c1
+LIMIT 1;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	range	PRIMARY,k1	k1	5	NULL	4	Using where
+DROP TABLE t1;
 set optimizer_switch=default;

=== modified file 'mysql-test/r/myisam_icp_none.result'
--- a/mysql-test/r/myisam_icp_none.result	2010-06-18 08:45:53 +0000
+++ b/mysql-test/r/myisam_icp_none.result	2010-08-30 10:04:02 +0000
@@ -365,4 +365,37 @@
 f1
 b
 DROP TABLE t1;
+#
+# Bug#52605 - "Adding LIMIT 1 clause to query with complex range 
+#              predicate causes wrong results"
+#
+CREATE TABLE t1 (
+pk INT NOT NULL,
+c1 INT,
+PRIMARY KEY (pk),
+KEY k1 (c1)
+);
+INSERT INTO t1 VALUES (1,NULL);
+INSERT INTO t1 VALUES (2,6);
+INSERT INTO t1 VALUES (3,NULL);
+INSERT INTO t1 VALUES (4,6);
+INSERT INTO t1 VALUES (5,NULL);
+INSERT INTO t1 VALUES (6,NULL);
+INSERT INTO t1 VALUES (7,9);
+INSERT INTO t1 VALUES (8,0);
+SELECT pk, c1
+FROM t1  
+WHERE (pk BETWEEN 4 AND 5 OR pk < 2) AND c1 < 240
+ORDER BY c1
+LIMIT 1;
+pk	c1
+4	6
+EXPLAIN SELECT pk, c1
+FROM t1  
+WHERE (pk BETWEEN 4 AND 5 OR pk < 2) AND c1 < 240
+ORDER BY c1
+LIMIT 1;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	range	PRIMARY,k1	k1	5	NULL	4	Using where
+DROP TABLE t1;
 set optimizer_switch=default;

=== modified file 'mysql-test/r/order_by_all.result'
--- a/mysql-test/r/order_by_all.result	2010-07-04 15:07:55 +0000
+++ b/mysql-test/r/order_by_all.result	2010-08-30 10:04:02 +0000
@@ -1108,7 +1108,7 @@
 1	SIMPLE	t2	index	k2	k3	5	NULL	73	Using where
 EXPLAIN SELECT id,c3 FROM t2 WHERE c2 BETWEEN 20 AND 30 ORDER BY c3 LIMIT 4000;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	t2	range	k2	k2	5	NULL	386	Using index condition; Using where; Using MRR; Using filesort
+1	SIMPLE	t2	range	k2	k2	5	NULL	386	Using index condition; Using MRR; Using filesort
 SELECT id,c3 FROM t2 WHERE c2=11 ORDER BY c3 LIMIT 20;
 id	c3
 6	14

=== modified file 'mysql-test/r/order_by_icp_mrr.result'
--- a/mysql-test/r/order_by_icp_mrr.result	2010-07-04 15:07:55 +0000
+++ b/mysql-test/r/order_by_icp_mrr.result	2010-08-30 10:04:02 +0000
@@ -1108,7 +1108,7 @@
 1	SIMPLE	t2	index	k2	k3	5	NULL	73	Using where
 EXPLAIN SELECT id,c3 FROM t2 WHERE c2 BETWEEN 20 AND 30 ORDER BY c3 LIMIT 4000;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	t2	range	k2	k2	5	NULL	386	Using index condition; Using where; Using MRR; Using filesort
+1	SIMPLE	t2	range	k2	k2	5	NULL	386	Using index condition; Using MRR; Using filesort
 SELECT id,c3 FROM t2 WHERE c2=11 ORDER BY c3 LIMIT 20;
 id	c3
 6	14

=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc	2010-08-19 16:44:09 +0000
+++ b/sql/sql_select.cc	2010-08-30 10:04:02 +0000
@@ -19329,6 +19329,8 @@
   SQL_SELECT *select=tab->select;
   QUICK_SELECT_I *save_quick= 0;
   Item *orig_select_cond= 0;
+  bool orig_select_cond_saved= false;
+  bool changed_key= false;
   DBUG_ENTER("test_if_skip_sort_order");
   LINT_INIT(ref_key_parts);
 
@@ -19395,8 +19397,17 @@
       */
       if (table->covering_keys.is_set(ref_key))
 	usable_keys.intersect(table->covering_keys);
+      /*
+        If part of the select condition has been pushed we use the
+        select condition as it was before pushing. The original
+        select condition is saved so that it can be restored when
+        exiting this function (if we have not changed index).
+      */
       if (tab->pre_idx_push_select_cond)
+      {
         orig_select_cond= tab->set_cond(tab->pre_idx_push_select_cond, __LINE__);
+        orig_select_cond_saved= true;
+      }
 
       if ((new_ref_key= test_if_subkey(order, table, ref_key, ref_key_parts,
 				       &usable_keys)) < MAX_KEY)
@@ -19445,6 +19456,7 @@
             goto use_filesort;
 	}
         ref_key= new_ref_key;
+        changed_key= true;
       }
     }
     /* Check if we get the rows in requested sorted order by using the key */
@@ -19516,15 +19528,13 @@
             table->set_keyread(TRUE);
           if (tab->pre_idx_push_select_cond)
           {
-            Item *tmp_cond= tab->pre_idx_push_select_cond;
-            if (orig_select_cond)
-            {
-              tmp_cond= and_conds(tmp_cond, orig_select_cond);
-              tmp_cond->quick_fix_field();
-            }
-            tab->set_cond(tmp_cond, __LINE__);
-            /* orig_select_cond was merged, no need to restore original one. */
+            tab->set_cond(tab->pre_idx_push_select_cond, __LINE__);
+            /*
+              orig_select_cond is a part of pre_idx_push_select_cond,
+              no need to restore it.
+            */
             orig_select_cond= 0;
+            orig_select_cond_saved= false;
           }
           table->file->ha_index_or_rnd_end();
           if (join->select_options & SELECT_DESCRIBE)
@@ -19564,6 +19574,7 @@
       */
       used_key_parts= (order_direction == -1) ?
         saved_best_key_parts :  best_key_parts;
+      changed_key= true;
     }
     else
       goto use_filesort; 
@@ -19618,12 +19629,16 @@
   }
   else if (select && select->quick)
     select->quick->need_sorted_output();
-  if (orig_select_cond)
+  /*
+    Restore condition only if we didn't chose index different to what we used
+    for ICP.
+  */
+  if (orig_select_cond_saved && !changed_key)
     tab->set_cond(orig_select_cond, __LINE__);
   DBUG_RETURN(1);
 
 use_filesort:
-  if (orig_select_cond)
+  if (orig_select_cond_saved)
     tab->set_cond(orig_select_cond, __LINE__);
   DBUG_RETURN(0);
 }
@@ -21447,6 +21462,42 @@
     func->save_in_result_field(1);
 }
 
+/**
+  Create a condition for a const reference for a table.
+
+  @param thd      THD pointer
+  @param join_tab pointer to the table
+
+  @return A pointer to the created condition for the const reference.
+  @retval !NULL if the condition was created successfully
+  @retval NULL if an error has occured
+*/
+
+static Item_cond_and *create_cond_for_const_ref(THD *thd, JOIN_TAB *join_tab)
+{
+  DBUG_ENTER("create_cond_for_const_ref");
+  DBUG_ASSERT(join_tab->ref.key_parts);
+
+  TABLE *table= join_tab->table;
+  Item_cond_and *cond= new Item_cond_and();
+  if (!cond)
+    DBUG_RETURN(NULL);
+
+  for (uint i=0 ; i < join_tab->ref.key_parts ; i++)
+  {
+    Field *field= table->field[table->key_info[join_tab->ref.key].key_part[i].
+                               fieldnr-1];
+    Item *value= join_tab->ref.items[i];
+    cond->add(new Item_func_equal(new Item_field(field), value));
+  }
+  if (thd->is_fatal_error)
+    DBUG_RETURN(NULL);
+
+  if (!cond->fixed)
+    cond->fix_fields(thd, (Item**)&cond);
+
+  DBUG_RETURN(cond);
+}
 
 /**
   Create a condition for a const reference and add this to the
@@ -21459,24 +21510,14 @@
   if (!join_tab->ref.key_parts)
     DBUG_RETURN(FALSE);
 
-  Item_cond_and *cond=new Item_cond_and();
-  TABLE *table=join_tab->table;
   int error= 0;
+
+  /* Create a condition representing the const reference. */
+  Item_cond_and *cond= create_cond_for_const_ref(thd, join_tab);
   if (!cond)
     DBUG_RETURN(TRUE);
 
-  for (uint i=0 ; i < join_tab->ref.key_parts ; i++)
-  {
-    Field *field=table->field[table->key_info[join_tab->ref.key].key_part[i].
-			      fieldnr-1];
-    Item *value=join_tab->ref.items[i];
-    cond->add(new Item_func_equal(new Item_field(field), value));
-  }
-  if (thd->is_fatal_error)
-    DBUG_RETURN(TRUE);
-
-  if (!cond->fixed)
-    cond->fix_fields(thd, (Item**)&cond);
+  /* Add this condition to the existing select condtion */
   if (join_tab->select)
   {
     if (join_tab->select->cond)
@@ -21488,6 +21529,22 @@
                                           &error)))
     join_tab->set_select_cond(cond, __LINE__);
 
+  /*
+    If we have pushed parts of the select condition down to the
+    storage engine we also need to add the condition for the const
+    reference to the pre_idx_push_select_cond since this might be used
+    later (in test_if_skip_sort_order()) instead of the select_cond.
+  */
+  if (join_tab->pre_idx_push_select_cond)
+  {
+    cond= create_cond_for_const_ref(thd, join_tab);
+    if (!cond)
+      DBUG_RETURN(TRUE);
+    if (cond->add(join_tab->pre_idx_push_select_cond))
+      DBUG_RETURN(TRUE);
+    join_tab->pre_idx_push_select_cond = cond;
+  }
+
   DBUG_RETURN(error ? TRUE : FALSE);
 }
 


Attachment: [text/bzr-bundle] bzr/olav@sun.com-20100830100402-yxz564brnvkycspf.bundle
Thread
bzr commit into mysql-next-mr-bugfixing branch (olav:3232) Bug#52605Olav Sandstaa30 Aug