From ff5d72021e26d1f3cec834c78b183918c4e95baf Mon Sep 17 00:00:00 2001 From: "gshchepa/uchum@gleb.loc" <> Date: Sat, 28 Jul 2007 23:10:38 +0500 Subject: [PATCH] Fixed bug #29834. Using view columns by their names during an execution of a prepared SELECT statement or a SELECT statement inside a SP caused a memory leak. --- mysql-test/r/sp.result | 71 ++++++++++++++++++++++++++++++++++++++++ mysql-test/t/sp.test | 74 ++++++++++++++++++++++++++++++++++++++++++ sql/sql_base.cc | 6 ++-- 3 files changed, 148 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index b411c65fae..313fdca7f8 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -1,5 +1,9 @@ use test; drop table if exists t1,t2,t3,t4; +drop view if exists v1; +drop procedure if exists p1; +drop procedure if exists p2; +drop function if exists f1; create table t1 ( id char(16) not null default '', data int not null @@ -6176,4 +6180,71 @@ v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VI DROP VIEW v1; DROP FUNCTION metered; DROP TABLE t1; +SET @p1_p2_cnt= 2; +CREATE TABLE t1 (c1 INT); +CREATE VIEW v1 AS SELECT * FROM t1; +PREPARE s1 FROM 'SELECT c1 FROM v1'; +EXECUTE s1; +c1 +EXECUTE s1; +c1 +CREATE PROCEDURE p1(IN loops BIGINT(19) UNSIGNED) +BEGIN +WHILE loops > 0 DO +SELECT c1 FROM v1; +SET loops = loops - 1; +END WHILE; +END| +CREATE PROCEDURE p2(IN loops BIGINT(19) UNSIGNED) +BEGIN +WHILE loops > 0 DO +SELECT c1 FROM v1; +CALL p1(@p1_p2_cnt); +SET loops = loops - 1; +END WHILE; +END| +CREATE FUNCTION f1(loops INT UNSIGNED) +RETURNS INT +BEGIN +DECLARE tmp INT; +WHILE loops > 0 DO +SELECT c1 INTO tmp FROM v1; +SET loops = loops - 1; +END WHILE; +RETURN loops; +END| +CALL p1(2); +c1 +c1 +CALL p2(2); +c1 +c1 +c1 +c1 +c1 +c1 +SELECT f1(2); +f1(2) +0 +Warnings: +Warning 1329 No data - zero rows fetched, selected, or processed +Warning 1329 No data - zero rows fetched, selected, or processed +PREPARE s1 FROM 'SELECT f1(2)'; +EXECUTE s1; +f1(2) +0 +Warnings: +Warning 1329 No data - zero rows fetched, selected, or processed +Warning 1329 No data - zero rows fetched, selected, or processed +EXECUTE s1; +f1(2) +0 +Warnings: +Warning 1329 No data - zero rows fetched, selected, or processed +Warning 1329 No data - zero rows fetched, selected, or processed +DROP PROCEDURE p1; +DROP PROCEDURE p2; +DROP FUNCTION f1; +DROP VIEW v1; +DROP TABLE t1; End of 5.0 tests diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 2f82482bdf..088ce9b72f 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -23,6 +23,10 @@ use test; # --disable_warnings drop table if exists t1,t2,t3,t4; +drop view if exists v1; +drop procedure if exists p1; +drop procedure if exists p2; +drop function if exists f1; --enable_warnings create table t1 ( id char(16) not null default '', @@ -7134,5 +7138,75 @@ DROP VIEW v1; DROP FUNCTION metered; DROP TABLE t1; +# +# Bug#29834: Accessing a view column by name in SP/PS causes a memory leak. +# +# This is leak test. Run with large number assigned to $execute_cnt, +# $p1_cnt, $p2_cnt, @p1_p2_cnt, $f1_normal_cnt or $f1_prep_cnt variables. +# + +let $execute_cnt= 2; +let $p1_cnt= 2; +let $p2_cnt= 2; +SET @p1_p2_cnt= 2; +let $f1_normal_cnt= 2; +let $f1_prep_cnt= 2; + +CREATE TABLE t1 (c1 INT); +CREATE VIEW v1 AS SELECT * FROM t1; + +PREPARE s1 FROM 'SELECT c1 FROM v1'; +while ($execute_cnt) +{ + EXECUTE s1; + dec $execute_cnt; +} + +DELIMITER |; + +CREATE PROCEDURE p1(IN loops BIGINT(19) UNSIGNED) +BEGIN + WHILE loops > 0 DO + SELECT c1 FROM v1; + SET loops = loops - 1; + END WHILE; +END| + +CREATE PROCEDURE p2(IN loops BIGINT(19) UNSIGNED) +BEGIN + WHILE loops > 0 DO + SELECT c1 FROM v1; + CALL p1(@p1_p2_cnt); + SET loops = loops - 1; + END WHILE; +END| + +CREATE FUNCTION f1(loops INT UNSIGNED) + RETURNS INT +BEGIN + DECLARE tmp INT; + WHILE loops > 0 DO + SELECT c1 INTO tmp FROM v1; + SET loops = loops - 1; + END WHILE; + RETURN loops; +END| + +DELIMITER ;| + +eval CALL p1($p1_cnt); +eval CALL p2($p2_cnt); + +eval SELECT f1($f1_normal_cnt); + +eval PREPARE s1 FROM 'SELECT f1($f1_prep_cnt)'; +EXECUTE s1; +EXECUTE s1; + +DROP PROCEDURE p1; +DROP PROCEDURE p2; +DROP FUNCTION f1; +DROP VIEW v1; +DROP TABLE t1; --echo End of 5.0 tests diff --git a/sql/sql_base.cc b/sql/sql_base.cc index ed00671414..deb46f0d93 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -3435,7 +3435,7 @@ find_field_in_view(THD *thd, TABLE_LIST *table_list, table_list->alias, name, item_name, (ulong) ref)); Field_iterator_view field_it; field_it.set(table_list); - Query_arena *arena, backup; + Query_arena *arena= 0, backup; DBUG_ASSERT(table_list->schema_table_reformed || (ref != 0 && table_list->view != 0)); @@ -3444,14 +3444,14 @@ find_field_in_view(THD *thd, TABLE_LIST *table_list, if (!my_strcasecmp(system_charset_info, field_it.name(), name)) { // in PS use own arena or data will be freed after prepare - if (register_tree_change) + if (register_tree_change && thd->stmt_arena->is_stmt_prepare_or_first_sp_execute()) arena= thd->activate_stmt_arena_if_needed(&backup); /* create_item() may, or may not create a new Item, depending on the column reference. See create_view_field() for details. */ Item *item= field_it.create_item(thd); - if (register_tree_change && arena) + if (arena) thd->restore_active_arena(arena, &backup); if (!item) -- 2.30.9