From: Sergey Glukhov Date: April 14 2011 9:33am Subject: bzr push into mysql-5.1 branch (sergey.glukhov:3657 to 3658) Bug#11756242 List-Archive: http://lists.mysql.com/commits/135411 X-Bug: 11756242 Message-Id: <201104140932.p3E9WOJn011721@acsmt358.oracle.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 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 3657 Serge Kozlov 2011-04-14 WL#5867, reorganize test cases of bugs suite removed: mysql-test/suite/bugs/ mysql-test/suite/bugs/combinations mysql-test/suite/bugs/data/ mysql-test/suite/bugs/data/rpl_bug12691.dat mysql-test/suite/bugs/r/ mysql-test/suite/bugs/r/rpl_bug12691.result mysql-test/suite/bugs/r/rpl_bug31582.result mysql-test/suite/bugs/r/rpl_bug31583.result mysql-test/suite/bugs/r/rpl_bug33029.result mysql-test/suite/bugs/r/rpl_bug38205.result mysql-test/suite/bugs/t/ mysql-test/suite/bugs/t/rpl_bug12691.test mysql-test/suite/bugs/t/rpl_bug31582.test mysql-test/suite/bugs/t/rpl_bug31583.test mysql-test/suite/bugs/t/rpl_bug33029.test mysql-test/suite/bugs/t/rpl_bug38205.test renamed: mysql-test/suite/bugs/r/rpl_bug23533.result => mysql-test/suite/binlog/r/binlog_bug23533.result mysql-test/suite/bugs/r/rpl_bug36391.result => mysql-test/suite/binlog/r/binlog_bug36391.result mysql-test/suite/bugs/r/rpl_bug37426.result => mysql-test/suite/rpl/r/rpl_bug37426.result mysql-test/suite/bugs/t/rpl_bug23533.test => mysql-test/suite/binlog/t/binlog_bug23533.test mysql-test/suite/bugs/t/rpl_bug36391-master.opt => mysql-test/suite/binlog/t/binlog_bug36391-master.opt mysql-test/suite/bugs/t/rpl_bug36391.test => mysql-test/suite/binlog/t/binlog_bug36391.test mysql-test/suite/bugs/t/rpl_bug37426.test => mysql-test/suite/rpl/t/rpl_bug37426.test modified: mysql-test/collections/default.experimental mysql-test/suite/binlog/r/binlog_bug23533.result mysql-test/suite/binlog/r/binlog_bug36391.result mysql-test/suite/rpl/r/rpl_bug37426.result mysql-test/suite/binlog/t/binlog_bug23533.test mysql-test/suite/binlog/t/binlog_bug36391.test mysql-test/suite/rpl/t/rpl_bug37426.test === 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 *) 0, curr_tmp_table, 0))) + + Procedure *save_proc= curr_join->procedure; + tmp_error= do_select(curr_join, (List *) 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 */ No bundle (reason: useless for push emails).