MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:<gshchepa Date:July 28 2007 10:56am
Subject:bk commit into 5.0 tree (gshchepa:1.2527) BUG#29834
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of uchum. When uchum does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2007-07-28 15:56:02+05:00, gshchepa@stripped +3 -0
  Fixed bug #29834.
  Repetitive access to a view column by it's name during
  executions of SP/PS caused a memory leak.

  mysql-test/r/sp.result@stripped, 2007-07-28 14:08:38+05:00, gshchepa@stripped +71 -0
    Updated test case for bug #29834.

  mysql-test/t/sp.test@stripped, 2007-07-28 14:08:35+05:00, gshchepa@stripped +74 -0
    Updated test case for bug #29834.

  sql/sql_base.cc@stripped, 2007-07-28 14:07:54+05:00, gshchepa@stripped +3 -3
    Fixed bug #29834.
    The find_field_in_view function has been modified to
    allocate Item_direct_view_ref objects in the execution
    memory during 2nd, 3rd etc. executions of PS/SP
    instead of the permanent memory.

diff -Nrup a/mysql-test/r/sp.result b/mysql-test/r/sp.result
--- a/mysql-test/r/sp.result	2007-06-07 12:07:38 +05:00
+++ b/mysql-test/r/sp.result	2007-07-28 14:08:38 +05:00
@@ -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
@@ -6175,5 +6179,72 @@ View	Create View
 v1	CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `test`.`metered`(`t1`.`a`) AS `metered` from `t1`
 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 -Nrup a/mysql-test/t/sp.test b/mysql-test/t/sp.test
--- a/mysql-test/t/sp.test	2007-06-29 13:27:19 +05:00
+++ b/mysql-test/t/sp.test	2007-07-28 14:08:35 +05:00
@@ -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 -Nrup a/sql/sql_base.cc b/sql/sql_base.cc
--- a/sql/sql_base.cc	2007-06-03 12:03:12 +05:00
+++ b/sql/sql_base.cc	2007-07-28 14:07:54 +05:00
@@ -3435,7 +3435,7 @@ find_field_in_view(THD *thd, 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 
     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)
Thread
bk commit into 5.0 tree (gshchepa:1.2527) BUG#29834gshchepa28 Jul