List:Commits« Previous MessageNext Message »
From:Evgeny Potemkin Date:May 13 2010 4:40pm
Subject:bzr commit into mysql-next-mr-bugfixing branch (epotemkin:3173)
Bug#45227
View as plain text  
#At file:///work/bzrroot/backporting-next-mr-2/ based on revid:epotemkin@stripped

 3173 Evgeny Potemkin	2010-05-13
      Bug#45227: Lost HAVING clause led to a wrong result.
      
      The per-table condition is stored in the select_cond variable for each table.
      When index condition pushdown is used it is saved prior to
      pushing to pre_idx_push_select_cond variable. After that condition is split
      and pushable part is pushed and another part is left in the select_cond
      variable. If condition is fully pushed the select_cond variable is set to NULL.
      When there is no GROUP BY clause or aggregate functions HAVING condition is appended
      to select_cond variable.
      The test_if_skip_sort_order function tries to find an index to use for sorting
      instead of filesort and to do so it restores original condition. It assumes that
      condition is fully saved in the pre_idx_push_select_cond and simply overwrites the
      select_cond variable, thus loosing the appended HAVING condition.
      
      Now the test_if_skip_sort_order function saves original condition from
      select_cond variable prior to overwriting it and restores it before
      returning.
      The JOIN_TAB::set_cond function added to correctly set per-table condition.
      Original revid:epotemkin@stripped
     @ mysql-test/r/select.result
        A test case added for the bug#45277.
     @ mysql-test/r/select_jcl6.result
        A test case added for the bug#45277.
     @ mysql-test/t/select.test
        A test case added for the bug#45277.
     @ sql/sql_select.cc
        Bug#45227: Lost HAVING clause led to a wrong result.
        
        Now the test_if_skip_sort_order function saves original condition from
        select_cond variable prior to overwriting it and restores it before
        returning.
     @ sql/sql_select.h
        Bug#45227: Lost HAVING clause led to a wrong result.
        
        The JOIN_TAB::set_cond function added to correctly set per-table condition.

    modified:
      mysql-test/r/select.result
      mysql-test/r/select_jcl6.result
      mysql-test/t/select.test
      sql/sql_select.cc
      sql/sql_select.h
=== modified file 'mysql-test/r/select.result'
--- a/mysql-test/r/select.result	2010-05-12 16:03:52 +0000
+++ b/mysql-test/r/select.result	2010-05-13 16:40:00 +0000
@@ -4928,3 +4928,34 @@ f1
 b
 DROP TABLE t1;
 SET SESSION optimizer_switch=@old_optimizer_switch;
+#
+# Bug#45277: Lost HAVING clause led to a wrong result.
+#
+CREATE TABLE `CC` (
+`int_nokey` int(11) NOT NULL,
+`int_key` int(11) NOT NULL,
+`varchar_key` varchar(1) NOT NULL,
+`varchar_nokey` varchar(1) NOT NULL,
+KEY `int_key` (`int_key`),
+KEY `varchar_key` (`varchar_key`)
+);
+INSERT INTO `CC` VALUES
+(0,8,'q','q'),(5,8,'m','m'),(7,3,'j','j'),(1,2,'z','z'),(8,2,'a','a'),(2,6,'',''),(1,8,'e'
+,'e'),(8,9,'t','t'),(5,2,'q','q'),(4,6,'b','b'),(5,5,'w','w'),(3,2,'m','m'),(0,4,'x','x'),
+(8,9,'',''),(0,6,'w','w'),(4,5,'x','x'),(0,0,'e','e'),(0,0,'e','e'),(2,8,'p','p'),(0,0,'x'
+,'x');
+EXPLAIN SELECT `varchar_nokey` G1  FROM CC  WHERE `int_nokey` AND `int_key`  <= 4
+HAVING G1  ORDER  BY `varchar_key` LIMIT  6   ;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	CC	range	int_key	int_key	4	NULL	10	Using index condition; Using where; Using MRR; Using filesort
+SELECT `varchar_nokey` G1  FROM CC  WHERE `int_nokey` AND `int_key`  <= 4
+HAVING G1  ORDER  BY `varchar_key` LIMIT  6   ;
+G1
+Warnings:
+Warning	1292	Truncated incorrect DOUBLE value: 'j'
+Warning	1292	Truncated incorrect DOUBLE value: 'z'
+Warning	1292	Truncated incorrect DOUBLE value: 'a'
+Warning	1292	Truncated incorrect DOUBLE value: 'q'
+Warning	1292	Truncated incorrect DOUBLE value: 'm'
+DROP TABLE CC;
+# End of test#45277

=== modified file 'mysql-test/r/select_jcl6.result'
--- a/mysql-test/r/select_jcl6.result	2010-05-12 16:03:52 +0000
+++ b/mysql-test/r/select_jcl6.result	2010-05-13 16:40:00 +0000
@@ -4932,6 +4932,37 @@ f1
 b
 DROP TABLE t1;
 SET SESSION optimizer_switch=@old_optimizer_switch;
+#
+# Bug#45277: Lost HAVING clause led to a wrong result.
+#
+CREATE TABLE `CC` (
+`int_nokey` int(11) NOT NULL,
+`int_key` int(11) NOT NULL,
+`varchar_key` varchar(1) NOT NULL,
+`varchar_nokey` varchar(1) NOT NULL,
+KEY `int_key` (`int_key`),
+KEY `varchar_key` (`varchar_key`)
+);
+INSERT INTO `CC` VALUES
+(0,8,'q','q'),(5,8,'m','m'),(7,3,'j','j'),(1,2,'z','z'),(8,2,'a','a'),(2,6,'',''),(1,8,'e'
+,'e'),(8,9,'t','t'),(5,2,'q','q'),(4,6,'b','b'),(5,5,'w','w'),(3,2,'m','m'),(0,4,'x','x'),
+(8,9,'',''),(0,6,'w','w'),(4,5,'x','x'),(0,0,'e','e'),(0,0,'e','e'),(2,8,'p','p'),(0,0,'x'
+,'x');
+EXPLAIN SELECT `varchar_nokey` G1  FROM CC  WHERE `int_nokey` AND `int_key`  <= 4
+HAVING G1  ORDER  BY `varchar_key` LIMIT  6   ;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	CC	range	int_key	int_key	4	NULL	10	Using index condition; Using where; Using MRR; Using filesort
+SELECT `varchar_nokey` G1  FROM CC  WHERE `int_nokey` AND `int_key`  <= 4
+HAVING G1  ORDER  BY `varchar_key` LIMIT  6   ;
+G1
+Warnings:
+Warning	1292	Truncated incorrect DOUBLE value: 'j'
+Warning	1292	Truncated incorrect DOUBLE value: 'z'
+Warning	1292	Truncated incorrect DOUBLE value: 'a'
+Warning	1292	Truncated incorrect DOUBLE value: 'q'
+Warning	1292	Truncated incorrect DOUBLE value: 'm'
+DROP TABLE CC;
+# End of test#45277
 set optimizer_join_cache_level=default;
 show variables like 'optimizer_join_cache_level';
 Variable_name	Value

=== modified file 'mysql-test/t/select.test'
--- a/mysql-test/t/select.test	2010-05-07 21:14:09 +0000
+++ b/mysql-test/t/select.test	2010-05-13 16:40:00 +0000
@@ -4190,3 +4190,28 @@ DROP TABLE t1;
 
 SET SESSION optimizer_switch=@old_optimizer_switch;
 
+--echo #
+--echo # Bug#45277: Lost HAVING clause led to a wrong result.
+--echo #
+CREATE TABLE `CC` (
+  `int_nokey` int(11) NOT NULL,
+  `int_key` int(11) NOT NULL,
+  `varchar_key` varchar(1) NOT NULL,
+  `varchar_nokey` varchar(1) NOT NULL,
+  KEY `int_key` (`int_key`),
+  KEY `varchar_key` (`varchar_key`)
+);
+INSERT INTO `CC` VALUES
+(0,8,'q','q'),(5,8,'m','m'),(7,3,'j','j'),(1,2,'z','z'),(8,2,'a','a'),(2,6,'',''),(1,8,'e'
+,'e'),(8,9,'t','t'),(5,2,'q','q'),(4,6,'b','b'),(5,5,'w','w'),(3,2,'m','m'),(0,4,'x','x'),
+(8,9,'',''),(0,6,'w','w'),(4,5,'x','x'),(0,0,'e','e'),(0,0,'e','e'),(2,8,'p','p'),(0,0,'x'
+,'x');
+EXPLAIN SELECT `varchar_nokey` G1  FROM CC  WHERE `int_nokey` AND `int_key`  <= 4
+  HAVING G1  ORDER  BY `varchar_key` LIMIT  6   ;
+
+SELECT `varchar_nokey` G1  FROM CC  WHERE `int_nokey` AND `int_key`  <= 4
+  HAVING G1  ORDER  BY `varchar_key` LIMIT  6   ;
+
+DROP TABLE CC;
+--echo # End of test#45277
+

=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc	2010-05-13 08:48:37 +0000
+++ b/sql/sql_select.cc	2010-05-13 16:40:00 +0000
@@ -18860,6 +18860,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,OR
   SQL_SELECT *select=tab->select;
   key_map usable_keys;
   QUICK_SELECT_I *save_quick= 0;
+  COND *orig_select_cond= 0;
   DBUG_ENTER("test_if_skip_sort_order");
   LINT_INIT(ref_key_parts);
 
@@ -18927,11 +18928,8 @@ test_if_skip_sort_order(JOIN_TAB *tab,OR
       if (table->covering_keys.is_set(ref_key))
 	usable_keys.intersect(table->covering_keys);
       if (tab->pre_idx_push_select_cond)
-      {
-        tab->set_select_cond(tab->pre_idx_push_select_cond, __LINE__);
-        if (tab->select)
-          tab->select->cond= tab->select_cond;
-      }
+        orig_select_cond= tab->set_cond(tab->pre_idx_push_select_cond, __LINE__);
+
       if ((new_ref_key= test_if_subkey(order, table, ref_key, ref_key_parts,
 				       &usable_keys)) < MAX_KEY)
       {
@@ -18952,7 +18950,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,OR
 
           if (create_ref_for_key(tab->join, tab, keyuse, 
                                  tab->join->const_table_map))
-            DBUG_RETURN(0);
+            goto use_filesort;
 
           pick_table_access_method(tab);
 	}
@@ -18977,7 +18975,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,OR
                                         tab->join->unit->select_limit_cnt,0,
                                         TRUE) <=
               0)
-            DBUG_RETURN(0);
+            goto use_filesort;
 	}
         ref_key= new_ref_key;
       }
@@ -19177,7 +19175,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,OR
          tab->join->tables > tab->join->const_tables + 1) &&
          ((unsigned) best_key != table->s->primary_key ||
           !table->file->primary_key_is_clustered()))
-      DBUG_RETURN(0);
+      goto use_filesort;
 
     if (best_key >= 0)
     {
@@ -19217,9 +19215,15 @@ test_if_skip_sort_order(JOIN_TAB *tab,OR
             table->set_keyread(TRUE);
           if (tab->pre_idx_push_select_cond)
           {
-            tab->set_select_cond(tab->pre_idx_push_select_cond, __LINE__);
-            if (tab->select)
-              tab->select->cond= tab->select_cond;
+            COND *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. */
+            orig_select_cond= 0;
           }
           table->file->ha_index_or_rnd_end();
           if (join->select_options & SELECT_DESCRIBE)
@@ -19254,7 +19258,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,OR
       order_direction= best_key_direction;
     }
     else
-      DBUG_RETURN(0); 
+      goto use_filesort; 
   } 
 
 check_reverse_order:                  
@@ -19278,7 +19282,7 @@ check_reverse_order:                  
         {
           tab->limit= 0;
           select->quick= save_quick;
-          DBUG_RETURN(0);                   // Use filesort
+          goto use_filesort;                   // Use filesort
         }
             
         /* ORDER BY range_key DESC */
@@ -19289,7 +19293,7 @@ check_reverse_order:                  
 	  delete tmp;
           select->quick= save_quick;
           tab->limit= 0;
-	  DBUG_RETURN(0);		// Reverse sort not supported
+	  goto use_filesort;		// Reverse sort not supported
 	}
 	select->quick=tmp;
       }
@@ -19309,7 +19313,14 @@ check_reverse_order:                  
   }
   else if (select && select->quick)
     select->quick->need_sorted_output();
+  if (orig_select_cond)
+    tab->set_cond(orig_select_cond, __LINE__);
   DBUG_RETURN(1);
+
+use_filesort:
+  if (orig_select_cond)
+    tab->set_cond(orig_select_cond, __LINE__);
+  DBUG_RETURN(0);
 }
 
 

=== modified file 'sql/sql_select.h'
--- a/sql/sql_select.h	2010-05-11 16:23:10 +0000
+++ b/sql/sql_select.h	2010-05-13 16:40:00 +0000
@@ -355,6 +355,14 @@ typedef struct st_join_table
                         select_cond, to, line, this));
     select_cond= to;
   }
+  COND *set_cond(COND *new_cond, uint line)
+  {
+    COND *tmp_select_cond= select_cond;
+    set_select_cond(new_cond, line);
+    if (select)
+      select->cond= new_cond;
+    return tmp_select_cond;
+  }
 } JOIN_TAB;
 
 /* 


Attachment: [text/bzr-bundle] bzr/epotemkin@mysql.com-20100513164000-3166lrje1ifgl3t3.bundle
Thread
bzr commit into mysql-next-mr-bugfixing branch (epotemkin:3173)Bug#45227Evgeny Potemkin13 May