Commit a89d88dc authored by Georgi Kodinov's avatar Georgi Kodinov

Bug #45989 take 2 : memory leak after explain encounters an

error in the query.

Fixes a leak after materializing a GROUP BY subquery to a 
temp table when the subquery has a blob column in the SELECT
list.
Fixed by correctly destructing temporary buffers for re-usable
queries
parent 8c65b726
...@@ -4615,4 +4615,16 @@ FROM t1,t1 a ...@@ -4615,4 +4615,16 @@ FROM t1,t1 a
); );
1 1
DROP TABLE t1; DROP TABLE t1;
#
# Bug #45989 take 2 : memory leak after explain encounters an
# error in the query
#
CREATE TABLE t1(a LONGTEXT);
INSERT INTO t1 VALUES (repeat('a',@@global.max_allowed_packet));
INSERT INTO t1 VALUES (repeat('b',@@global.max_allowed_packet));
EXPLAIN EXTENDED SELECT DISTINCT 1 FROM t1,
(SELECT DISTINCTROW a AS away FROM t1 GROUP BY a WITH ROLLUP) AS d1
WHERE t1.a = d1.a;
ERROR 42S22: Unknown column 'd1.a' in 'where clause'
DROP TABLE t1;
End of 5.1 tests. End of 5.1 tests.
...@@ -3600,4 +3600,21 @@ SELECT 1 FROM t1 WHERE a <> SOME ...@@ -3600,4 +3600,21 @@ SELECT 1 FROM t1 WHERE a <> SOME
); );
DROP TABLE t1; DROP TABLE t1;
--echo #
--echo # Bug #45989 take 2 : memory leak after explain encounters an
--echo # error in the query
--echo #
CREATE TABLE t1(a LONGTEXT);
INSERT INTO t1 VALUES (repeat('a',@@global.max_allowed_packet));
INSERT INTO t1 VALUES (repeat('b',@@global.max_allowed_packet));
--error ER_BAD_FIELD_ERROR
EXPLAIN EXTENDED SELECT DISTINCT 1 FROM t1,
(SELECT DISTINCTROW a AS away FROM t1 GROUP BY a WITH ROLLUP) AS d1
WHERE t1.a = d1.a;
DROP TABLE t1;
--echo End of 5.1 tests. --echo End of 5.1 tests.
...@@ -2313,6 +2313,12 @@ JOIN::destroy() ...@@ -2313,6 +2313,12 @@ JOIN::destroy()
tab->cleanup(); tab->cleanup();
} }
tmp_join->tmp_join= 0; tmp_join->tmp_join= 0;
/*
We need to clean up tmp_table_param for reusable JOINs (having non-zero
and different from self tmp_join) because it's not being cleaned up
anywhere else (as we need to keep the join is reusable).
*/
tmp_table_param.cleanup();
tmp_table_param.copy_field= 0; tmp_table_param.copy_field= 0;
DBUG_RETURN(tmp_join->destroy()); DBUG_RETURN(tmp_join->destroy());
} }
...@@ -5838,6 +5844,12 @@ JOIN::make_simple_join(JOIN *parent, TABLE *tmp_table) ...@@ -5838,6 +5844,12 @@ JOIN::make_simple_join(JOIN *parent, TABLE *tmp_table)
const_table_map= 0; const_table_map= 0;
tmp_table_param.field_count= tmp_table_param.sum_func_count= tmp_table_param.field_count= tmp_table_param.sum_func_count=
tmp_table_param.func_count= 0; tmp_table_param.func_count= 0;
/*
We need to destruct the copy_field (allocated in create_tmp_table())
before setting it to 0 if the join is not "reusable".
*/
if (!tmp_join || tmp_join != this)
tmp_table_param.cleanup();
tmp_table_param.copy_field= tmp_table_param.copy_field_end=0; tmp_table_param.copy_field= tmp_table_param.copy_field_end=0;
first_record= sort_and_group=0; first_record= sort_and_group=0;
send_records= (ha_rows) 0; send_records= (ha_rows) 0;
......
...@@ -354,7 +354,25 @@ class JOIN :public Sql_alloc ...@@ -354,7 +354,25 @@ class JOIN :public Sql_alloc
*/ */
bool no_const_tables; bool no_const_tables;
JOIN *tmp_join; ///< copy of this JOIN to be used with temporary tables /**
Copy of this JOIN to be used with temporary tables.
tmp_join is used when the JOIN needs to be "reusable" (e.g. in a subquery
that gets re-executed several times) and we know will use temporary tables
for materialization. The materialization to a temporary table overwrites the
JOIN structure to point to the temporary table after the materialization is
done. This is where tmp_join is used : it's a copy of the JOIN before the
materialization and is used in restoring before re-execution by overwriting
the current JOIN structure with the saved copy.
Because of this we should pay extra care of not freeing up helper structures
that are referenced by the original contents of the JOIN. We can check for
this by making sure the "current" join is not the temporary copy, e.g.
!tmp_join || tmp_join != join
We should free these sub-structures at JOIN::destroy() if the "current" join
has a copy is not that copy.
*/
JOIN *tmp_join;
ROLLUP rollup; ///< Used with rollup ROLLUP rollup; ///< Used with rollup
bool select_distinct; ///< Set if SELECT DISTINCT bool select_distinct; ///< Set if SELECT DISTINCT
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment