diff options
author | Sergey Glukhov <sergey.glukhov@oracle.com> | 2011-04-14 12:11:57 +0400 |
---|---|---|
committer | Sergey Glukhov <sergey.glukhov@oracle.com> | 2011-04-14 12:11:57 +0400 |
commit | 3abe56f31d90f2cc84399e042b5f105b87b2b01a (patch) | |
tree | d055cd7700bc24e34e07d29c5c3bc54a1f74e58c /sql | |
parent | 729e9a65943823b2636ea8dc3c50486a3844c02c (diff) | |
download | mariadb-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.cc | 16 |
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 */ |