MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:Georgi Kodinov Date:February 4 2010 3:18pm
Subject:bzr commit into mysql-5.1-bugteam branch (joro:3356) Bug#45989
View as plain text  
#At file:///home/kgeorge/mysql/work/B45989-5.1-bugteam/ based on revid:staale.smedseng@stripped

 3356 Georgi Kodinov	2010-02-02
      Bug #45989 take 2 : memory leak after explain encounters an
      error in the query.
      
      Fixes a leak after materializing a GROUP BY subquery to a 
      temp table when the subquery has a blob column in the SELECT
      list.
      Fixed by correctly destructing temporary buffers for re-usable
      queries

    modified:
      mysql-test/r/subselect.result
      mysql-test/t/subselect.test
      sql/sql_select.cc
      sql/sql_select.h
=== modified file 'mysql-test/r/subselect.result'
--- a/mysql-test/r/subselect.result	2009-12-23 15:11:22 +0000
+++ b/mysql-test/r/subselect.result	2010-02-02 16:30:23 +0000
@@ -4615,4 +4615,16 @@ FROM t1,t1 a
 );
 1
 DROP TABLE t1;
+#
+# Bug #45989 take 2 : memory leak after explain encounters an 
+# error in the query
+#
+CREATE TABLE t1(a LONGTEXT);
+INSERT INTO t1 VALUES (repeat('a',@@global.max_allowed_packet));
+INSERT INTO t1 VALUES (repeat('b',@@global.max_allowed_packet));
+EXPLAIN EXTENDED SELECT DISTINCT 1 FROM t1,
+(SELECT DISTINCTROW a AS away FROM t1 GROUP BY a WITH ROLLUP) AS d1  
+WHERE t1.a = d1.a;
+ERROR 42S22: Unknown column 'd1.a' in 'where clause'
+DROP TABLE t1;
 End of 5.1 tests.

=== modified file 'mysql-test/t/subselect.test'
--- a/mysql-test/t/subselect.test	2009-12-23 15:11:22 +0000
+++ b/mysql-test/t/subselect.test	2010-02-02 16:30:23 +0000
@@ -3600,4 +3600,21 @@ SELECT 1 FROM t1 WHERE a <> SOME
 );
 DROP TABLE t1;
 
+--echo #
+--echo # Bug #45989 take 2 : memory leak after explain encounters an 
+--echo # error in the query
+--echo #
+
+CREATE TABLE t1(a LONGTEXT);
+INSERT INTO t1 VALUES (repeat('a',@@global.max_allowed_packet));
+INSERT INTO t1 VALUES (repeat('b',@@global.max_allowed_packet));
+
+--error ER_BAD_FIELD_ERROR
+EXPLAIN EXTENDED SELECT DISTINCT 1 FROM t1,
+(SELECT DISTINCTROW a AS away FROM t1 GROUP BY a WITH ROLLUP) AS d1  
+WHERE t1.a = d1.a;
+
+DROP TABLE t1;
+
+
 --echo End of 5.1 tests.

=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc	2010-02-02 16:37:56 +0000
+++ b/sql/sql_select.cc	2010-02-02 16:30:23 +0000
@@ -2313,6 +2313,12 @@ JOIN::destroy()
 	tab->cleanup();
     }
     tmp_join->tmp_join= 0;
+    /*
+      We need to clean up tmp_table_param for reusable JOINs (having non-zero
+      and different from self tmp_join) because it's not being cleaned up
+      anywhere else (as we need to keep the join is reusable).
+    */
+    tmp_table_param.cleanup();
     tmp_table_param.copy_field= 0;
     DBUG_RETURN(tmp_join->destroy());
   }
@@ -5838,6 +5844,12 @@ JOIN::make_simple_join(JOIN *parent, TAB
   const_table_map= 0;
   tmp_table_param.field_count= tmp_table_param.sum_func_count=
     tmp_table_param.func_count= 0;
+  /*
+    We need to destruct the copy_field (allocated in create_tmp_table())
+    before setting it to 0 if the join is not "reusable".
+  */
+  if (!tmp_join || tmp_join != this) 
+    tmp_table_param.cleanup(); 
   tmp_table_param.copy_field= tmp_table_param.copy_field_end=0;
   first_record= sort_and_group=0;
   send_records= (ha_rows) 0;

=== modified file 'sql/sql_select.h'
--- a/sql/sql_select.h	2010-01-15 14:09:20 +0000
+++ b/sql/sql_select.h	2010-02-02 16:30:23 +0000
@@ -354,7 +354,25 @@ public:
   */
   bool no_const_tables; 
   
-  JOIN *tmp_join; ///< copy of this JOIN to be used with temporary tables
+  /**
+    Copy of this JOIN to be used with temporary tables.
+
+    tmp_join is used when the JOIN needs to be "reusable" (e.g. in a subquery
+    that gets re-executed several times) and we know will use temporary tables
+    for materialization. The materialization to a temporary table overwrites the
+    JOIN structure to point to the temporary table after the materialization is
+    done. This is where tmp_join is used : it's a copy of the JOIN before the
+    materialization and is used in restoring before re-execution by overwriting
+    the current JOIN structure with the saved copy.
+    Because of this we should pay extra care of not freeing up helper structures
+    that are referenced by the original contents of the JOIN. We can check for
+    this by making sure the "current" join is not the temporary copy, e.g.
+    !tmp_join || tmp_join != join
+ 
+    We should free these sub-structures at JOIN::destroy() if the "current" join
+    has a copy is not that copy.
+  */
+  JOIN *tmp_join;
   ROLLUP rollup;				///< Used with rollup
 
   bool select_distinct;				///< Set if SELECT DISTINCT


Attachment: [text/bzr-bundle] bzr/joro@sun.com-20100202163023-mn03jv5mvqqfpoa1.bundle
Thread
bzr commit into mysql-5.1-bugteam branch (joro:3356) Bug#45989Georgi Kodinov4 Feb