MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:Gleb Shchepa Date:April 1 2009 11:02am
Subject:bzr commit into mysql-5.0-bugteam branch (gshchepa:2721) Bug#37348
View as plain text  
#At file:///work/bzr/mysql-5.0-bugteam/ based on revid:joro@stripped

 2721 Gleb Shchepa	2009-04-01
      Backport bug #37348 fix 5.1 --> 5.0.
      
      Original commentary:
      
      Bug #37348: Crash in or immediately after JOIN::make_sum_func_list
                  
      The optimizer pulls up aggregate functions which should be aggregated in
      an outer select. At some point it may substitute such a function for a field
      in the temporary table. The setup_copy_fields function doesn't take this
      into account and may overrun the copy_field buffer.
                  
      Fixed by filtering out the fields referenced through the specialized
      reference for aggregates (Item_aggregate_ref).
      Added an assertion to make sure bugs that cause similar discrepancy 
      don't go undetected.
      modified:
        mysql-test/r/func_group.result
        mysql-test/t/func_group.test
        sql/item.cc
        sql/item.h
        sql/sql_select.cc

per-file messages:
  mysql-test/r/func_group.result
    Backport bug #37348 fix 5.1 --> 5.0.
  mysql-test/t/func_group.test
    Backport bug #37348 fix 5.1 --> 5.0.
  sql/item.cc
    Backport bug #37348 fix 5.1 --> 5.0.
  sql/item.h
    Backport bug #37348 fix 5.1 --> 5.0.
  sql/sql_select.cc
    Backport bug #37348 fix 5.1 --> 5.0.
=== modified file 'mysql-test/r/func_group.result'
--- a/mysql-test/r/func_group.result	2009-01-28 17:59:08 +0000
+++ b/mysql-test/r/func_group.result	2009-04-01 11:02:26 +0000
@@ -1448,4 +1448,41 @@ COUNT(*)
 0
 SET SQL_MODE=default;
 DROP TABLE t1;
+CREATE TABLE derived1 (a bigint(21));
+INSERT INTO derived1 VALUES (2);
+CREATE TABLE D (
+pk int(11) NOT NULL AUTO_INCREMENT,
+int_nokey int(11) DEFAULT NULL,
+int_key int(11) DEFAULT NULL,
+filler blob,
+PRIMARY KEY (pk),
+KEY int_key (int_key)
+);
+INSERT INTO D VALUES 
+(39,40,4,repeat('  X', 42)),
+(43,56,4,repeat('  X', 42)),
+(47,12,4,repeat('  X', 42)),
+(71,28,4,repeat('  X', 42)),
+(76,54,4,repeat('  X', 42)),
+(83,45,4,repeat('  X', 42)),
+(105,53,12,NULL);
+SELECT 
+(SELECT COUNT( int_nokey ) 
+FROM derived1 AS X 
+WHERE 
+X.int_nokey < 61 
+GROUP BY pk 
+LIMIT 1) 
+FROM D AS X 
+WHERE X.int_key < 13  
+GROUP BY int_nokey LIMIT 1;
+(SELECT COUNT( int_nokey ) 
+FROM derived1 AS X 
+WHERE 
+X.int_nokey < 61 
+GROUP BY pk 
+LIMIT 1)
+1
+DROP TABLE derived1;
+DROP TABLE D;
 End of 5.0 tests

=== modified file 'mysql-test/t/func_group.test'
--- a/mysql-test/t/func_group.test	2008-11-24 15:30:47 +0000
+++ b/mysql-test/t/func_group.test	2009-04-01 11:02:26 +0000
@@ -955,5 +955,45 @@ SET SQL_MODE=default;
 DROP TABLE t1;
 
 
+#
+# Bug #37348: Crash in or immediately after JOIN::make_sum_func_list
+#
+
+CREATE TABLE derived1 (a bigint(21));
+INSERT INTO derived1 VALUES (2);
+
+
+CREATE TABLE D (
+  pk int(11) NOT NULL AUTO_INCREMENT,
+  int_nokey int(11) DEFAULT NULL,
+  int_key int(11) DEFAULT NULL,
+  filler blob,
+  PRIMARY KEY (pk),
+  KEY int_key (int_key)
+);
+
+INSERT INTO D VALUES 
+  (39,40,4,repeat('  X', 42)),
+  (43,56,4,repeat('  X', 42)),
+  (47,12,4,repeat('  X', 42)),
+  (71,28,4,repeat('  X', 42)),
+  (76,54,4,repeat('  X', 42)),
+  (83,45,4,repeat('  X', 42)),
+  (105,53,12,NULL);
+
+SELECT 
+  (SELECT COUNT( int_nokey ) 
+   FROM derived1 AS X 
+   WHERE 
+     X.int_nokey < 61 
+   GROUP BY pk 
+   LIMIT 1) 
+FROM D AS X 
+WHERE X.int_key < 13  
+GROUP BY int_nokey LIMIT 1;
+
+DROP TABLE derived1;
+DROP TABLE D;
+
 ###
 --echo End of 5.0 tests

=== modified file 'sql/item.cc'
--- a/sql/item.cc	2009-03-27 12:58:34 +0000
+++ b/sql/item.cc	2009-04-01 11:02:26 +0000
@@ -1323,6 +1323,7 @@ public:
     else
       Item_ident::print(str);
   }
+  virtual Ref_Type ref_type() { return AGGREGATE_REF; }
 };
 
 

=== modified file 'sql/item.h'
--- a/sql/item.h	2009-02-19 13:20:44 +0000
+++ b/sql/item.h	2009-04-01 11:02:26 +0000
@@ -1899,7 +1899,7 @@ class Item_ref :public Item_ident
 protected:
   void set_properties();
 public:
-  enum Ref_Type { REF, DIRECT_REF, VIEW_REF, OUTER_REF };
+  enum Ref_Type { REF, DIRECT_REF, VIEW_REF, OUTER_REF, AGGREGATE_REF };
   Field *result_field;			 /* Save result here */
   Item **ref;
   Item_ref(Name_resolution_context *context_arg,

=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc	2009-03-19 13:44:58 +0000
+++ b/sql/sql_select.cc	2009-04-01 11:02:26 +0000
@@ -14205,6 +14205,7 @@ setup_copy_fields(THD *thd, TMP_TABLE_PA
   Item *pos;
   List_iterator_fast<Item> li(all_fields);
   Copy_field *copy= NULL;
+  IF_DBUG(Copy_field *copy_start);
   res_selected_fields.empty();
   res_all_fields.empty();
   List_iterator_fast<Item> itr(res_all_fields);
@@ -14217,12 +14218,19 @@ setup_copy_fields(THD *thd, TMP_TABLE_PA
     goto err2;
 
   param->copy_funcs.empty();
+  IF_DBUG(copy_start= copy);
   for (i= 0; (pos= li++); i++)
   {
     Field *field;
     char *tmp;
     Item *real_pos= pos->real_item();
-    if (real_pos->type() == Item::FIELD_ITEM)
+    /*
+      Aggregate functions can be substituted for fields (by e.g. temp tables).
+      We need to filter those substituted fields out.
+    */
+    if (real_pos->type() == Item::FIELD_ITEM &&
+        !(real_pos != pos &&
+          ((Item_ref *)pos)->ref_type() == Item_ref::AGGREGATE_REF))
     {
       Item_field *item;
       if (!(item= new Item_field(thd, ((Item_field*) real_pos))))
@@ -14270,6 +14278,7 @@ setup_copy_fields(THD *thd, TMP_TABLE_PA
 	  goto err;
         if (copy)
         {
+          DBUG_ASSERT (param->field_count > (uint) (copy - copy_start));
           copy->set(tmp, item->result_field);
           item->result_field->move_field(copy->to_ptr,copy->to_null_ptr,1);
 #ifdef HAVE_purify

Thread
bzr commit into mysql-5.0-bugteam branch (gshchepa:2721) Bug#37348Gleb Shchepa1 Apr