List:Commits« Previous MessageNext Message »
From:Sergey Glukhov Date:April 8 2011 8:45am
Subject:bzr commit into mysql-5.1 branch (sergey.glukhov:3645) Bug#11756242
View as plain text  
#At file:///home/gluh/MySQL/mysql-5.1/ based on revid:sergey.glukhov@stripped

 3645 Sergey Glukhov	2011-04-08
      Bug#11756242  48137: PROCEDURE ANALYSE() LEAKS MEMORY WHEN RETURNING NULL
      There are two problems with ANALYSE():
      
      1. Memory leak 
      it happens because do_select() can overwrite
      JOIN::procedure field(with zero value in our case) and
      JOIN destructor don't free the memory allocated for
      JOIN::procedure. The fix is to save original JOIN::procedure
      before do_select() call and restore it after do_select
      execution.
      
      2. Wrong result
      If ANALYSE() procedure is used for the statement with LIMIT clause
      it could retrun empty result set. It happens because of missing 
      analyse::end_of_records() call. First end_send() function call
      returns NESTED_LOOP_QUERY_LIMIT and second call of end_send() with
      end_of_records flag enabled does not happen. The fix is to return
      NESTED_LOOP_OK from end_send() if procedure is active.
     @ mysql-test/r/analyse.result
        test case
     @ mysql-test/t/analyse.test
        test case
     @ sql/sql_select.cc
        --save original JOIN::procedure before do_select() call and
          restore it after do_select execution.
        --return NESTED_LOOP_OK from end_send() if procedure is active

    modified:
      mysql-test/r/analyse.result
      mysql-test/t/analyse.test
      sql/sql_select.cc
=== modified file 'mysql-test/r/analyse.result'
--- a/mysql-test/r/analyse.result	2011-03-14 18:03:22 +0000
+++ b/mysql-test/r/analyse.result	2011-04-08 08:45:29 +0000
@@ -135,4 +135,14 @@ SELECT * FROM t1 PROCEDURE ANALYSE();
 Field_name	Min_value	Max_value	Min_length	Max_length	Empties_or_zeros	Nulls	Avg_value_or_avg_length	Std	Optimal_fieldtype
 test.t1.a	e	e-	1	2	0	0	1.3333	NULL	ENUM('e','e-') NOT NULL
 DROP TABLE t1;
+#
+# Bug#11756242  48137: PROCEDURE ANALYSE() LEAKS MEMORY WHEN RETURNING NULL
+#
+CREATE TABLE t1(f1 INT) ENGINE=MYISAM;
+CREATE TABLE t2(f2 INT) ENGINE=INNODB;
+INSERT INTO t2 VALUES (1);
+SELECT DISTINCTROW f1 FROM t1 NATURAL RIGHT OUTER JOIN t2 PROCEDURE ANALYSE();
+Field_name	Min_value	Max_value	Min_length	Max_length	Empties_or_zeros	Nulls	Avg_value_or_avg_length	Std	Optimal_fieldtype
+test.t1.f1	NULL	NULL	0	0	0	1	0.0	0.0	CHAR(0)
+DROP TABLE t1, t2;
 End of 5.1 tests

=== modified file 'mysql-test/t/analyse.test'
--- a/mysql-test/t/analyse.test	2011-03-14 18:03:22 +0000
+++ b/mysql-test/t/analyse.test	2011-04-08 08:45:29 +0000
@@ -1,6 +1,7 @@
 #
 # Test of procedure analyse
 #
+-- source include/have_innodb.inc
 
 --disable_warnings
 drop table if exists t1,t2;
@@ -144,4 +145,14 @@ INSERT INTO t1 VALUES ('e'),('e'),('e-')
 SELECT * FROM t1 PROCEDURE ANALYSE();
 DROP TABLE t1;
 
+--echo #
+--echo # Bug#11756242  48137: PROCEDURE ANALYSE() LEAKS MEMORY WHEN RETURNING NULL
+--echo #
+
+CREATE TABLE t1(f1 INT) ENGINE=MYISAM;
+CREATE TABLE t2(f2 INT) ENGINE=INNODB;
+INSERT INTO t2 VALUES (1);
+SELECT DISTINCTROW f1 FROM t1 NATURAL RIGHT OUTER JOIN t2 PROCEDURE ANALYSE();
+DROP TABLE t1, t2;
+
 --echo End of 5.1 tests

=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc	2011-02-22 21:03:32 +0000
+++ b/sql/sql_select.cc	2011-04-08 08:45:29 +0000
@@ -1929,7 +1929,11 @@ JOIN::exec()
     if (!curr_join->sort_and_group &&
         curr_join->const_tables != curr_join->tables)
       curr_join->join_tab[curr_join->const_tables].sorted= 0;
-    if ((tmp_error= do_select(curr_join, (List<Item> *) 0, curr_tmp_table, 0)))
+
+    Procedure *save_proc= curr_join->procedure;
+    tmp_error= do_select(curr_join, (List<Item> *) 0, curr_tmp_table, 0);
+    curr_join->procedure= save_proc;
+    if (tmp_error)
     {
       error= tmp_error;
       DBUG_VOID_RETURN;
@@ -12354,10 +12358,14 @@ end_send(JOIN *join, JOIN_TAB *join_tab 
     int error;
     if (join->having && join->having->val_int() == 0)
       DBUG_RETURN(NESTED_LOOP_OK);               // Didn't match having
-    error=0;
     if (join->procedure)
-      error=join->procedure->send_row(join->procedure_fields_list);
-    else if (join->do_send_rows)
+    {
+      if (join->procedure->send_row(join->procedure_fields_list))
+        DBUG_RETURN(NESTED_LOOP_ERROR);
+      DBUG_RETURN(NESTED_LOOP_OK);
+    }
+    error=0;
+    if (join->do_send_rows)
       error=join->result->send_data(*join->fields);
     if (error)
       DBUG_RETURN(NESTED_LOOP_ERROR); /* purecov: inspected */


Attachment: [text/bzr-bundle] bzr/sergey.glukhov@oracle.com-20110408084529-ighkkh6m1p94mk0g.bundle
Thread
bzr commit into mysql-5.1 branch (sergey.glukhov:3645) Bug#11756242Sergey Glukhov8 Apr