[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
Thu Apr 5 23:23:25 EEST 2012


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

------------------------------------------------------------
revno: 3488
revision-id: sanja at montyprogram.com-20120405202324-bmipnkpbgxofgl0f
parent: monty at askmonty.org-20120402092715-4cwn2rrcdeafir0x
committer: sanja at montyprogram.com
branch nick: work-maria-5.3-lpb968720
timestamp: Thu 2012-04-05 23:23:24 +0300
message:
  Fix of LP bug#968720.
  
  When a view/derived table is converted from merged to materialized the
  items from the used_item lists are substituted for items referring to
  the fields of the result of the materialization. The problem appeared
  with queries employing natural joins. Since the resolution of a natural
  join was performed only once the used_item list formed at the second
  execution of the query lacked the references to the fields that were
  used only in the equality predicates generated for the natural join.
-------------- 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-05 20:23:24 +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-05 20:23:24 +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-05 20:23:24 +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->persistent_used_items= table_ref_1->used_items;
+  table_ref_2->persistent_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-05 20:23:24 +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, i++);
+    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-05 20:23:24 +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 (thd->stmt_arena->is_conventional() ||
+      thd->stmt_arena->is_stmt_prepare_or_first_sp_execute())
+  {
+    /* initialize lists */
+    used_items.empty();
+    persistent_used_items.empty();
+  }
+  else
+  {
+    /*
+      Copy the list created by natural join procedure because the procedure
+      will not be repeated.
+    */
+    used_items= persistent_used_items;
+  }
 
   if (field_translation)
   {
@@ -4598,7 +4612,7 @@ Item *create_view_field(THD *thd, TABLE_
   if (view->table && view->table->maybe_null)
     item->maybe_null= TRUE;
   /* Save item in case we will need to fall back to materialization. */
-  view->used_items.push_back(item);
+  view->used_items.push_front(item);
   DBUG_RETURN(item);
 }
 
@@ -6070,7 +6084,11 @@ bool TABLE_LIST::change_refs_to_fields()
       if (!materialized_items[idx])
         return TRUE;
     }
-    ref->ref= materialized_items + idx;
+    /*
+      We need to restore the pointers after the execution of the
+      prepared statement.
+    */
+    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-05 20:23:24 +0000
@@ -1600,7 +1600,13 @@ struct TABLE_LIST
   /* TRUE <=> don't prepare this derived table/view as it should be merged.*/
   bool          skip_prepare_derived;
 
+  /*
+    Items created by create_view_field and collected to change them in case
+    of materialization of the view/derived table
+  */
   List<Item>    used_items;
+  /* Sublist (tail) of persistent used_items */
+  List<Item>    persistent_used_items;
   Item          **materialized_items;
 
   /* View creation context. */



More information about the commits mailing list