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

 3658 Sergey Glukhov	2011-04-14
      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-14 08:11:57 +0000
@@ -135,4 +135,17 @@ 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)
+SELECT * FROM t2 LIMIT 1 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.t2.f2	1	1	1	1	0	0	1.0000	0.0000	ENUM('1') NOT NULL
+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-14 08:11:57 +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,15 @@ 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();
+SELECT * FROM t2 LIMIT 1 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-14 08:11:57 +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-20110414081157-hv5h2rljma7um9yc.bundle
Thread
bzr commit into mysql-5.1 branch (sergey.glukhov:3658) Bug#11756242Sergey Glukhov14 Apr
  • Re: bzr commit into mysql-5.1 branch (sergey.glukhov:3658)Bug#11756242Bjorn Munch14 Apr
    • Re: bzr commit into mysql-5.1 branch (sergey.glukhov:3658) Bug#11756242Sergey Glukhov14 Apr
      • Re: bzr commit into mysql-5.1 branch (sergey.glukhov:3658) Bug#11756242Øystein Grøvlen14 Apr
        • Re: bzr commit into mysql-5.1 branch (sergey.glukhov:3658) Bug#11756242Paul DuBois14 Apr
          • Re: bzr commit into mysql-5.1 branch (sergey.glukhov:3658)Bug#11756242Sergei Golubchik14 Apr