[Commits] Rev 3488: Fix of LP bug#968720. in file:///home/bell/maria/bzr/work-maria-5.3-lpb968720/

sanja at montyprogram.com sanja at montyprogram.com
Wed Apr 4 14:01:36 EEST 2012


At file:///home/bell/maria/bzr/work-maria-5.3-lpb968720/

------------------------------------------------------------
revno: 3488
revision-id: sanja at montyprogram.com-20120404110135-7eca0tt18auum3xo
parent: monty at askmonty.org-20120402092715-4cwn2rrcdeafir0x
committer: sanja at montyprogram.com
branch nick: work-maria-5.3-lpb968720
timestamp: Wed 2012-04-04 14:01:35 +0300
message:
  Fix of LP bug#968720.
  
  Problem:
  During converting from merged to materialized all items listed in used_item list changed from real tables to the temporary table of materialized join. The problem was that natural join matching made only once and on second prepare phase (first is prepare opf PREPARE statement, second is prepare phase of executing the statement) the list lack fields of natural join because it is not made second time.
  
  Solution:
  Save the used_items list after natural join matching and restore it during re-initialization.
-------------- next part --------------
=== modified file 'mysql-test/r/derived_view.result'
--- a/mysql-test/r/derived_view.result	2012-03-13 20:34:20 +0000
+++ b/mysql-test/r/derived_view.result	2012-04-04 11:01:35 +0000
@@ -1997,5 +1997,44 @@ a	b	gc
 SET SESSION optimizer_switch= @save_optimizer_switch;
 DROP VIEW v;
 DROP TABLE t1,t2;
+#
+# LP BUG#968720 crash due to converting to materialized and
+# natural join made only once
+#
+SET @save968720_optimizer_switch=@@optimizer_switch;
+SET optimizer_switch = 'derived_merge=on';
+CREATE TABLE t1 (a int, INDEX(a));
+INSERT INTO t1 VALUES (1);
+CREATE TABLE t2 (a int, INDEX(a));
+INSERT INTO t2 VALUES (1), (2);
+INSERT INTO t1 SELECT a FROM (SELECT a FROM test.t1) AS s1 NATURAL JOIN
+t2 AS s2;
+SELECT * FROM t1;
+a
+1
+1
+DELETE FROM t1;
+INSERT INTO t1 VALUES (1);
+PREPARE stmt FROM "
+INSERT INTO t1 SELECT a FROM (SELECT a FROM test.t1) AS s1 NATURAL JOIN
+t2 AS s2;
+";
+EXECUTE stmt;
+SELECT * FROM t1;
+a
+1
+1
+EXECUTE stmt;
+SELECT * FROM t1;
+a
+1
+1
+1
+1
+drop table t1,t2;
+set optimizer_switch=@save968720_optimizer_switch;
+#
+# end of 5.3 tests
+#
 set optimizer_switch=@exit_optimizer_switch;
 set join_cache_level=@exit_join_cache_level;

=== modified file 'mysql-test/t/derived_view.test'
--- a/mysql-test/t/derived_view.test	2012-03-13 20:34:20 +0000
+++ b/mysql-test/t/derived_view.test	2012-04-04 11:01:35 +0000
@@ -1380,6 +1380,43 @@ SET SESSION optimizer_switch= @save_opti
 DROP VIEW v;
 DROP TABLE t1,t2;
 
+--echo #
+--echo # LP BUG#968720 crash due to converting to materialized and
+--echo # natural join made only once
+--echo #
+
+SET @save968720_optimizer_switch=@@optimizer_switch;
+SET optimizer_switch = 'derived_merge=on';
+
+CREATE TABLE t1 (a int, INDEX(a));
+INSERT INTO t1 VALUES (1);
+
+CREATE TABLE t2 (a int, INDEX(a));
+INSERT INTO t2 VALUES (1), (2);
+
+INSERT INTO t1 SELECT a FROM (SELECT a FROM test.t1) AS s1 NATURAL JOIN
+t2 AS s2;
+SELECT * FROM t1;
+
+DELETE FROM t1;
+INSERT INTO t1 VALUES (1);
+
+PREPARE stmt FROM "
+INSERT INTO t1 SELECT a FROM (SELECT a FROM test.t1) AS s1 NATURAL JOIN
+t2 AS s2;
+";
+EXECUTE stmt;
+SELECT * FROM t1;
+EXECUTE stmt;
+SELECT * FROM t1;
+
+drop table t1,t2;
+set optimizer_switch=@save968720_optimizer_switch;
+
+--echo #
+--echo # end of 5.3 tests
+--echo #
+
 # The following command must be the last one the file 
 set optimizer_switch=@exit_optimizer_switch;
 set join_cache_level=@exit_join_cache_level;

=== modified file 'sql/sql_base.cc'
--- a/sql/sql_base.cc	2012-03-23 16:22:39 +0000
+++ b/sql/sql_base.cc	2012-04-04 11:01:35 +0000
@@ -7276,6 +7276,14 @@ mark_common_columns(THD *thd, TABLE_LIST
   */
   result= FALSE;
 
+  /*
+    Save the lists made during natural join matching (because
+    the matching done only once but we need the list in case
+    of prepared statements).
+  */
+  table_ref_1->save_used_items= table_ref_1->used_items;
+  table_ref_2->save_used_items= table_ref_2->used_items;
+
 err:
   if (arena)
     thd->restore_active_arena(arena, &backup);

=== modified file 'sql/sql_list.h'
--- a/sql/sql_list.h	2012-02-16 14:56:10 +0000
+++ b/sql/sql_list.h	2012-04-04 11:01:35 +0000
@@ -257,6 +257,26 @@ public:
       last= &first;
     return tmp->info;
   }
+
+  /**
+    Cut the list with leaving not more then n elements
+  */
+  inline uint cut(uint n)
+  {
+    list_node *element= first;
+    uint i= 0;
+    for (;
+         i < n && element != &end_of_list;
+         element= element->next);
+    if (element != &end_of_list)
+    {
+      elements= i + 1;
+      last= &element->next;
+      element->next= &end_of_list;
+    }
+    return i + 1;
+  }
+
   /*
     Remove from this list elements that are contained in the passed list. 
     We assume that the passed list is a tail of this list (that is, the whole 

=== modified file 'sql/table.cc'
--- a/sql/table.cc	2012-03-28 10:58:14 +0000
+++ b/sql/table.cc	2012-04-04 11:01:35 +0000
@@ -3540,7 +3540,21 @@ bool TABLE_LIST::create_field_translatio
   Query_arena *arena= thd->stmt_arena, backup;
   bool res= FALSE;
 
-  used_items.empty();
+  if (select->first_natural_join_processing || save_used_items.elements == 0)
+  {
+    /* initialize lists */
+    used_items.empty();
+    save_used_items.empty();
+  }
+  else
+  {
+    /*
+      Copy the list created by natural join procedure because the procedure
+      will not be repeated.
+    */
+    used_items= save_used_items;
+    used_items.cut(save_used_items.elements);
+  }
 
   if (field_translation)
   {
@@ -6070,7 +6084,11 @@ bool TABLE_LIST::change_refs_to_fields()
       if (!materialized_items[idx])
         return TRUE;
     }
-    ref->ref= materialized_items + idx;
+    /*
+      Following is a bit hack but pointer length is equal everywhere
+      and we need revert pointers after prepared statement execution.
+    */
+    thd->change_item_tree((Item **)&ref->ref, (Item*)materialized_items + idx);
   }
 
   return FALSE;

=== modified file 'sql/table.h'
--- a/sql/table.h	2012-03-24 16:08:59 +0000
+++ b/sql/table.h	2012-04-04 11:01:35 +0000
@@ -1601,6 +1601,7 @@ struct TABLE_LIST
   bool          skip_prepare_derived;
 
   List<Item>    used_items;
+  List<Item>    save_used_items;
   Item          **materialized_items;
 
   /* View creation context. */



More information about the commits mailing list