[Commits] Rev 2978: Fix of LP BUG#675248. in file:///home/bell/maria/bzr/work-maria-5.1-lb675248-prep-where/

sanja at askmonty.org sanja at askmonty.org
Tue Nov 23 20:43:34 EET 2010


At file:///home/bell/maria/bzr/work-maria-5.1-lb675248-prep-where/

------------------------------------------------------------
revno: 2978
revision-id: sanja at askmonty.org-20101123184334-vat0hpjgjct10jgv
parent: knielsen at knielsen-hq.org-20101123062444-y8bpq0wggf9zyxpt
committer: sanja at askmonty.org
branch nick: work-maria-5.1-lb675248-prep-where
timestamp: Tue 2010-11-23 20:43:34 +0200
message:
  Fix of LP BUG#675248.
  
  Registration of pointer change if we assign it to other pointer which should be identical after statement execution (PS/SP).
-------------- next part --------------
=== modified file 'mysql-test/r/subselect.result'
--- a/mysql-test/r/subselect.result	2010-08-02 09:01:24 +0000
+++ b/mysql-test/r/subselect.result	2010-11-23 18:43:34 +0000
@@ -4730,4 +4730,23 @@ ORDER BY (SELECT * FROM t1 WHERE MATCH(a
 SELECT * FROM t2 UNION SELECT * FROM t2
 ORDER BY (SELECT * FROM t1 WHERE MATCH(a) AGAINST ('+abc' IN BOOLEAN MODE));
 DROP TABLE t1,t2;
+# LP BUG#675248 - select->prep_where references on freed memory 
+CREATE TABLE t1 (a int, b int);
+insert into t1 values (1,1),(0,0);
+CREATE TABLE t2 (c int);
+insert into t2 values (1),(2);
+prepare stmt1 from "select sum(a),(select sum(c) from t2 where table1.b) as sub
+from t1 as table1 group by sub";
+execute stmt1;
+sum(a)	sub
+0	NULL
+1	3
+deallocate prepare stmt1;
+prepare stmt1 from "select sum(a),(select sum(c) from t2 having table1.b) as sub
+from t1 as table1";
+execute stmt1;
+sum(a)	sub
+1	3
+deallocate prepare stmt1;
+drop table t1,t2;
 End of 5.1 tests

=== modified file 'mysql-test/t/subselect.test'
--- a/mysql-test/t/subselect.test	2010-08-02 09:01:24 +0000
+++ b/mysql-test/t/subselect.test	2010-11-23 18:43:34 +0000
@@ -3735,4 +3735,28 @@ SELECT * FROM t2 UNION SELECT * FROM t2
 DROP TABLE t1,t2;
 --enable_result_log
 
+--echo # LP BUG#675248 - select->prep_where references on freed memory 
+
+CREATE TABLE t1 (a int, b int);
+insert into t1 values (1,1),(0,0);
+
+CREATE TABLE t2 (c int);
+insert into t2 values (1),(2);
+
+prepare stmt1 from "select sum(a),(select sum(c) from t2 where table1.b) as sub
+from t1 as table1 group by sub";
+
+execute stmt1;
+
+deallocate prepare stmt1;
+
+prepare stmt1 from "select sum(a),(select sum(c) from t2 having table1.b) as sub
+from t1 as table1";
+
+execute stmt1;
+
+deallocate prepare stmt1;
+
+drop table t1,t2;
+
 --echo End of 5.1 tests

=== modified file 'sql/sql_class.cc'
--- a/sql/sql_class.cc	2010-11-02 15:22:57 +0000
+++ b/sql/sql_class.cc	2010-11-23 18:43:34 +0000
@@ -1621,6 +1621,36 @@ void THD::nocheck_register_item_tree_cha
   change_list.append(change);
 }
 
+/**
+  Check and register item change if needed
+
+  @param place           place where we should assign new value
+  @param new_value       place of the new value
+
+  @details
+    Let C be a reference to an item that changed the reference A
+    at the location (occurrence) L1 and this change has been registered.
+    If C is substituted for reference A another location (occurrence) L2
+    that is to be registered as well than this change has to be
+    consistent with the first change in order the procedure that rollback
+    changes to substitute the same reference at both locations L1 and L2.
+*/
+
+void THD::check_and_register_item_tree_change(Item **place, Item **new_value,
+                                              MEM_ROOT *runtime_memroot)
+{
+  Item_change_record *change;
+  I_List_iterator<Item_change_record> it(change_list);
+  while ((change= it++))
+  {
+    if (change->place == new_value)
+      break; // we need only very first value
+  }
+  if (change)
+    nocheck_register_item_tree_change(place, change->old_value,
+                                      runtime_memroot);
+}
+
 
 void THD::rollback_item_tree_changes()
 {

=== modified file 'sql/sql_class.h'
--- a/sql/sql_class.h	2010-11-03 21:40:53 +0000
+++ b/sql/sql_class.h	2010-11-23 18:43:34 +0000
@@ -1568,7 +1568,7 @@ public:
   /*
     This is to track items changed during execution of a prepared
     statement/stored procedure. It's created by
-    register_item_tree_change() in memory root of THD, and freed in
+    nocheck_register_item_tree_change() in memory root of THD, and freed in
     rollback_item_tree_changes(). For conventional execution it's always
     empty.
   */
@@ -2175,8 +2175,26 @@ public:
       nocheck_register_item_tree_change(place, *place, mem_root);
     *place= new_value;
   }
+  /**
+    Make change in item tree after checking whether it needs registering
+
+
+    @param place         place where we should assign new value
+    @param new_value     place of the new value
+
+    @details
+    see check_and_register_item_tree_change details
+  */
+  void check_and_register_item_tree(Item **place, Item **new_value)
+  {
+    if (!stmt_arena->is_conventional())
+      check_and_register_item_tree_change(place, new_value, mem_root);
+    *place= *new_value;
+  }
   void nocheck_register_item_tree_change(Item **place, Item *old_value,
                                          MEM_ROOT *runtime_memroot);
+  void check_and_register_item_tree_change(Item **place, Item **new_value,
+                                           MEM_ROOT *runtime_memroot);
   void rollback_item_tree_changes();
 
   /*

=== modified file 'sql/sql_lex.cc'
--- a/sql/sql_lex.cc	2010-08-27 14:12:44 +0000
+++ b/sql/sql_lex.cc	2010-11-23 18:43:34 +0000
@@ -2890,7 +2890,7 @@ static void fix_prepare_info_in_table_li
   {
     if (tbl->on_expr)
     {
-      tbl->prep_on_expr= tbl->on_expr;
+      thd->check_and_register_item_tree(&tbl->prep_on_expr, &tbl->on_expr);
       tbl->on_expr= tbl->on_expr->copy_andor_structure(thd);
     }
     fix_prepare_info_in_table_list(thd, tbl->merge_underlying_list);
@@ -2924,12 +2924,12 @@ void st_select_lex::fix_prepare_informat
     first_execution= 0;
     if (*conds)
     {
-      prep_where= *conds;
+      thd->check_and_register_item_tree(&prep_where, conds);
       *conds= where= prep_where->copy_andor_structure(thd);
     }
     if (*having_conds)
     {
-      prep_having= *having_conds;
+      thd->check_and_register_item_tree(&prep_having, having_conds);
       *having_conds= having= prep_having->copy_andor_structure(thd);
     }
     fix_prepare_info_in_table_list(thd, table_list.first);



More information about the commits mailing list