MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:Georgi Kodinov Date:October 2 2008 9:33am
Subject:bzr commit into mysql-5.1 branch (kgeorge:2757) Bug#37348
View as plain text  
#At file:///home/kgeorge/mysql/bzr/B37348-5.1-5.1.29-rc/

 2757 Georgi Kodinov	2008-10-02
      Bug #37348: Crash in or immediately after JOIN::make_sum_func_list
                  
      Materializing temporary tables in outer contexts can cause the code that 
      allocates the fields that need to be copied for GROUP BY to decide to
      copy more fields than initially counted.
      Fixed by checking for the special case when it's actually wrong to 
      consider an Item_field as a thing that needs copying.
modified:
  mysql-test/r/func_group.result
  mysql-test/t/func_group.test
  sql/item.cc
  sql/item.h
  sql/sql_select.cc

=== modified file 'mysql-test/r/func_group.result'
--- a/mysql-test/r/func_group.result	2008-03-19 11:25:36 +0000
+++ b/mysql-test/r/func_group.result	2008-10-02 09:33:23 +0000
@@ -1416,4 +1416,41 @@ SELECT AVG(a), CAST(AVG(a) AS DECIMAL) F
 AVG(a)	CAST(AVG(a) AS DECIMAL)
 15	15
 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-03-19 11:25:36 +0000
+++ b/mysql-test/t/func_group.test	2008-10-02 09:33:23 +0000
@@ -933,5 +933,45 @@ SELECT AVG(a), CAST(AVG(a) AS DECIMAL) F
 
 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	2008-10-02 05:56:07 +0000
+++ b/sql/item.cc	2008-10-02 09:33:23 +0000
@@ -1319,28 +1319,6 @@ void Item_name_const::print(String *str,
 }
 
 
-/*
- need a special class to adjust printing : references to aggregate functions 
- must not be printed as refs because the aggregate functions that are added to
- the front of select list are not printed as well.
-*/
-class Item_aggregate_ref : public Item_ref
-{
-public:
-  Item_aggregate_ref(Name_resolution_context *context_arg, Item **item,
-                  const char *table_name_arg, const char *field_name_arg)
-    :Item_ref(context_arg, item, table_name_arg, field_name_arg) {}
-
-  virtual inline void print (String *str, enum_query_type query_type)
-  {
-    if (ref)
-      (*ref)->print(str, query_type);
-    else
-      Item_ident::print(str, query_type);
-  }
-};
-
-
 /**
   Move SUM items out from item tree and replace with reference.
 

=== modified file 'sql/item.h'
--- a/sql/item.h	2008-08-15 20:42:29 +0000
+++ b/sql/item.h	2008-10-02 09:33:23 +0000
@@ -2126,7 +2126,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,
@@ -2419,6 +2419,32 @@ public:
   virtual Item *real_item() { return ref; }
 };
 
+
+/*
+ need a special class to adjust printing : references to aggregate functions 
+ must not be printed as refs because the aggregate functions that are added to
+ the front of select list are not printed as well.
+*/
+class Item_aggregate_ref : public Item_ref
+{
+public:
+  Item::Type original_type;
+  Item_aggregate_ref(Name_resolution_context *context_arg, Item **item,
+                  const char *table_name_arg, const char *field_name_arg)
+    :Item_ref(context_arg, item, table_name_arg, field_name_arg), 
+     original_type((*item)->type()) {}
+
+  virtual inline void print (String *str, enum_query_type query_type)
+  {
+    if (ref)
+      (*ref)->print(str, query_type);
+    else
+      Item_ident::print(str, query_type);
+  }
+  virtual Ref_Type ref_type() { return AGGREGATE_REF; }
+};
+
+
 #ifdef MYSQL_SERVER
 #include "gstream.h"
 #include "spatial.h"

=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc	2008-08-28 09:54:50 +0000
+++ b/sql/sql_select.cc	2008-10-02 09:33:23 +0000
@@ -14804,6 +14804,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);
@@ -14816,12 +14817,24 @@ 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;
     uchar *tmp;
     Item *real_pos= pos->real_item();
-    if (real_pos->type() == Item::FIELD_ITEM)
+    /*
+      Condition decoding :
+        (i) fields
+        (ii a & b) that are not referenced through outer ref to an aggregate 
+        function
+    */
+    if (real_pos->type() == Item::FIELD_ITEM &&                        /* i */
+        !(real_pos != pos &&
+          ((Item_ref *)pos)->ref_type() == Item_ref::AGGREGATE_REF &&  /* ii */
+          ((Item_aggregate_ref *)pos)->original_type == Item::SUM_FUNC_ITEM
+         )
+        )
     {
       Item_field *item;
       if (!(item= new Item_field(thd, ((Item_field*) real_pos))))
@@ -14868,6 +14881,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.1 branch (kgeorge:2757) Bug#37348Georgi Kodinov2 Oct