summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorSergey Glukhov <sergey.glukhov@oracle.com>2011-04-14 12:11:57 +0400
committerSergey Glukhov <sergey.glukhov@oracle.com>2011-04-14 12:11:57 +0400
commit3abe56f31d90f2cc84399e042b5f105b87b2b01a (patch)
treed055cd7700bc24e34e07d29c5c3bc54a1f74e58c /sql
parent729e9a65943823b2636ea8dc3c50486a3844c02c (diff)
downloadmariadb-git-3abe56f31d90f2cc84399e042b5f105b87b2b01a.tar.gz
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
Diffstat (limited to 'sql')
-rw-r--r--sql/sql_select.cc16
1 files changed, 12 insertions, 4 deletions
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index eb2559fc600..84a09fbc7e6 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -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 __attribute__((unused)),
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 */