[Commits] Rev 3377: Fix for LP BUG#910123 MariaDB 5.3.3 causes 1093 error on Drupal in file:///home/bell/maria/bzr/work-maria-5.3-lpb910123/

sanja at montyprogram.com sanja at montyprogram.com
Tue Jan 10 16:59:56 EET 2012


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

------------------------------------------------------------
revno: 3377
revision-id: sanja at montyprogram.com-20120110145953-m9z6b92c3d5z6jmj
parent: igor at askmonty.org-20120103040636-nc6o55vsxqadd1n0
committer: sanja at montyprogram.com
branch nick: work-maria-5.3-lpb910123
timestamp: Tue 2012-01-10 16:59:53 +0200
message:
  Fix for LP BUG#910123 MariaDB 5.3.3 causes 1093 error on Drupal
  
  Problem was that now we can merge derived table (subquery in the FROM clause).
  Fix: in case of detected conflict and presence of derived table "over" the table which cased the conflict - try materialization strategy.
-------------- next part --------------
=== modified file 'mysql-test/r/derived_opt.result'
--- a/mysql-test/r/derived_opt.result	2011-07-21 22:55:08 +0000
+++ b/mysql-test/r/derived_opt.result	2012-01-10 14:59:53 +0000
@@ -273,4 +273,13 @@ ON alias3.f4 != 0
 ) ON alias3.f4 != 0;
 f4	f4	f2	f4
 drop table t1,t2,t3,t4;
+#
+# LP BUG#910123 MariaDB 5.3.3 causes 1093 error on Drupal
+# Fix: force materialization in case of conflict
+#
+SET optimizer_switch='derived_merge=on';
+CREATE TABLE t1 ( i INT );
+INSERT INTO t1 VALUES ( (SELECT 1 FROM ( SELECT * FROM t1 ) as a) );
+drop table t1;
+set optimizer_switch=@save_optimizer_switch;
 set optimizer_switch=@exit_optimizer_switch;

=== modified file 'mysql-test/t/derived_opt.test'
--- a/mysql-test/t/derived_opt.test	2011-07-21 22:55:08 +0000
+++ b/mysql-test/t/derived_opt.test	2012-01-10 14:59:53 +0000
@@ -202,5 +202,15 @@ RIGHT JOIN (
 
 drop table t1,t2,t3,t4;
 
+--echo #
+--echo # LP BUG#910123 MariaDB 5.3.3 causes 1093 error on Drupal
+--echo # Fix: force materialization in case of conflict
+--echo #
+SET optimizer_switch='derived_merge=on';
+CREATE TABLE t1 ( i INT );
+INSERT INTO t1 VALUES ( (SELECT 1 FROM ( SELECT * FROM t1 ) as a) );
+drop table t1;
+set optimizer_switch=@save_optimizer_switch;
+
 # The following command must be the last one the file 
 set optimizer_switch=@exit_optimizer_switch;

=== modified file 'sql/sql_base.cc'
--- a/sql/sql_base.cc	2011-12-11 16:39:33 +0000
+++ b/sql/sql_base.cc	2012-01-10 14:59:53 +0000
@@ -1707,11 +1707,12 @@ TABLE_LIST* unique_table(THD *thd, TABLE
   t_name= table->table_name;
   t_alias= table->alias;
 
+retry:
   DBUG_PRINT("info", ("real table: %s.%s", d_name, t_name));
-  for (;;)
+  for (TABLE_LIST *tl= table_list;;)
   {
-    if (((! (res= find_table_in_global_list(table_list, d_name, t_name))) &&
-         (! (res= mysql_lock_have_duplicate(thd, table, table_list)))) ||
+    if (((! (res= find_table_in_global_list(tl, d_name, t_name))) &&
+         (! (res= mysql_lock_have_duplicate(thd, table, tl)))) ||
         ((!res->table || res->table != table->table) &&
          (!check_alias || !(lower_case_table_names ?
           my_strcasecmp(files_charset_info, t_alias, res->alias) :
@@ -1724,10 +1725,23 @@ TABLE_LIST* unique_table(THD *thd, TABLE
       processed in derived table or top select of multi-update/multi-delete
       (exclude_from_table_unique_test) or prelocking placeholder.
     */
-    table_list= res->next_global;
+    tl= res->next_global;
     DBUG_PRINT("info",
                ("found same copy of table or table which we should skip"));
   }
+  if (res && res->belong_to_derived)
+  {
+    /* Try to fix */
+    TABLE_LIST *derived=  res->belong_to_derived;
+    if (derived->is_merged_derived())
+    {
+      DBUG_PRINT("info",
+                 ("convert merged to materialization to resolve the conflict"));
+      derived->change_refs_to_fields();
+      derived->set_materialized_derived();
+    }
+    goto retry;
+  }
   DBUG_RETURN(res);
 }
 

=== modified file 'sql/sql_lex.cc'
--- a/sql/sql_lex.cc	2011-12-11 17:28:05 +0000
+++ b/sql/sql_lex.cc	2012-01-10 14:59:53 +0000
@@ -2885,6 +2885,7 @@ void st_lex::cleanup_after_one_table_ope
   if (all_selects_list != &select_lex)
   {
     derived_tables= 0;
+    select_lex.exclude_from_table_unique_test= false;
     /* cleunup underlying units (units of VIEW) */
     for (SELECT_LEX_UNIT *un= select_lex.first_inner_unit();
          un;

=== modified file 'sql/sql_union.cc'
--- a/sql/sql_union.cc	2011-12-11 09:34:44 +0000
+++ b/sql/sql_union.cc	2012-01-10 14:59:53 +0000
@@ -961,6 +961,7 @@ bool st_select_lex::cleanup()
   }
   non_agg_fields.empty();
   inner_refs_list.empty();
+  exclude_from_table_unique_test= FALSE;
   DBUG_RETURN(error);
 }
 

=== modified file 'sql/table.cc'
--- a/sql/table.cc	2011-12-11 17:28:05 +0000
+++ b/sql/table.cc	2012-01-10 14:59:53 +0000
@@ -4356,6 +4356,36 @@ bool TABLE_LIST::prepare_security(THD *t
   DBUG_RETURN(FALSE);
 }
 
+#ifndef DBUG_OFF
+void TABLE_LIST::set_check_merged()
+{
+  DBUG_ASSERT(derived);
+  /*
+    It is not simple to check all, but at least this should be checked:
+    this select is not excluded or the exclusion came from above.
+  */
+  DBUG_ASSERT(!derived->first_select()->exclude_from_table_unique_test ||
+              derived->outer_select()->
+              exclude_from_table_unique_test);
+}
+#endif
+
+void TABLE_LIST::set_check_materialized()
+{
+  DBUG_ASSERT(derived);
+  if (!derived->first_select()->exclude_from_table_unique_test)
+    derived->set_unique_exclude();
+  else
+  {
+    /*
+      The subtree should be already excluded
+    */
+    DBUG_ASSERT(!derived->first_select()->first_inner_unit() ||
+                derived->first_select()->first_inner_unit()->first_select()->
+                exclude_from_table_unique_test);
+  }
+}
+
 
 Natural_join_column::Natural_join_column(Field_translator *field_param,
                                          TABLE_LIST *tab)
@@ -5890,8 +5920,9 @@ bool TABLE_LIST::init_derived(THD *thd,
   */
   if (is_materialized_derived())
   {
-    unit->master_unit()->set_unique_exclude();
+    set_check_materialized();
   }
+
   /*
     Create field translation for mergeable derived tables/views.
     For derived tables field translation can be created only after

=== modified file 'sql/table.h'
--- a/sql/table.h	2011-12-11 17:28:05 +0000
+++ b/sql/table.h	2012-01-10 14:59:53 +0000
@@ -1747,16 +1747,18 @@ struct TABLE_LIST
   inline void set_merged_derived()
   {
     derived_type= ((derived_type & DTYPE_MASK) |
-                    DTYPE_TABLE | DTYPE_MERGE);
+                   DTYPE_TABLE | DTYPE_MERGE);
+    set_check_merged();
   }
   inline bool is_materialized_derived()
   {
     return (derived_type & DTYPE_MATERIALIZE);
   }
-  inline void set_materialized_derived()
+  void set_materialized_derived()
   {
     derived_type= ((derived_type & DTYPE_MASK) |
-                    DTYPE_TABLE | DTYPE_MATERIALIZE);
+                   DTYPE_TABLE | DTYPE_MATERIALIZE);
+    set_check_materialized();
   }
   inline bool is_multitable()
   {
@@ -1800,6 +1802,12 @@ struct TABLE_LIST
 private:
   bool prep_check_option(THD *thd, uint8 check_opt_type);
   bool prep_where(THD *thd, Item **conds, bool no_where_clause);
+  void set_check_materialized();
+#ifndef DBUG_OFF
+  void set_check_merged();
+#else
+  inline void set_check_merged() {}
+#endif
   /*
     Cleanup for re-execution in a prepared statement or a stored
     procedure.



More information about the commits mailing list