[Commits] Rev 4417: MDEV-7260: Crash in get_best_combination when executing multi-table UPDATE with nested views in file:///home/bell/maria/bzr/work-maria-5.5-MDEV-7260/

sanja at askmonty.org sanja at askmonty.org
Wed Feb 4 19:32:34 EET 2015


At file:///home/bell/maria/bzr/work-maria-5.5-MDEV-7260/

------------------------------------------------------------
revno: 4417
revision-id: sanja at askmonty.org-20150204173215-8e5s8f5mjk1qtrxh
parent: sergii at pisem.net-20150129133431-85vpfgesj50hozfu
committer: sanja at askmonty.org
branch nick: work-maria-5.5-MDEV-7260
timestamp: Wed 2015-02-04 18:32:15 +0100
message:
  MDEV-7260: Crash in get_best_combination when executing multi-table UPDATE with nested views
  
  Do not use merge_for_insert for commands which use SELECT because optimizer can't work with such tables.
  
  Fixes which makes multi-delete working with normally merged views.
-------------- next part --------------
=== modified file 'mysql-test/r/view.result'
--- a/mysql-test/r/view.result	2014-12-21 18:23:28 +0000
+++ b/mysql-test/r/view.result	2015-02-04 17:32:15 +0000
@@ -5398,6 +5398,19 @@ DROP VIEW v1;
 DROP TABLE t1, t2;
 create view v1 as select 1;
 drop view v1;
+#
+# MDEV-7260: Crash in get_best_combination when executing multi-table
+# UPDATE with nested views
+#
+CREATE TABLE `t1` (`id` bigint(20));
+INSERT INTO `t1` VALUES (1),(2);
+CREATE TABLE `t2` (`id` bigint(20));
+CREATE TABLE `t3` (`id` bigint(20), `flag` tinyint(4));
+create view v1 as select id from t1;
+create view v2 as select t2.* from (t2 left join v1 using (id));
+update t3 left join v2 using (id) set flag=flag+1;
+drop view v2, v1;
+drop table t1, t2, t3;
 # -----------------------------------------------------------------
 # -- End of 5.5 tests.
 # -----------------------------------------------------------------

=== modified file 'mysql-test/t/view.test'
--- a/mysql-test/t/view.test	2014-12-21 18:23:28 +0000
+++ b/mysql-test/t/view.test	2015-02-04 17:32:15 +0000
@@ -5345,6 +5345,28 @@ create view v1 as select 1;
 
 drop view v1;
 
+--echo #
+--echo # MDEV-7260: Crash in get_best_combination when executing multi-table
+--echo # UPDATE with nested views
+--echo #
+
+CREATE TABLE `t1` (`id` bigint(20));
+
+INSERT INTO `t1` VALUES (1),(2);
+
+CREATE TABLE `t2` (`id` bigint(20));
+
+CREATE TABLE `t3` (`id` bigint(20), `flag` tinyint(4));
+
+create view v1 as select id from t1;
+
+create view v2 as select t2.* from (t2 left join v1 using (id));
+
+update t3 left join v2 using (id) set flag=flag+1;
+
+drop view v2, v1;
+drop table t1, t2, t3;
+
 --echo # -----------------------------------------------------------------
 --echo # -- End of 5.5 tests.
 --echo # -----------------------------------------------------------------

=== modified file 'sql/sql_base.cc'
--- a/sql/sql_base.cc	2014-10-31 13:07:29 +0000
+++ b/sql/sql_base.cc	2015-02-04 17:32:15 +0000
@@ -2028,6 +2028,9 @@ unique_table(THD *thd, TABLE_LIST *table
              bool check_alias)
 {
   TABLE_LIST *dup;
+
+  table= table->find_table_for_update();
+
   if (table->table && table->table->file->ht->db_type == DB_TYPE_MRG_MYISAM)
   {
     TABLE_LIST *child;

=== modified file 'sql/sql_delete.cc'
--- a/sql/sql_delete.cc	2014-07-23 15:53:29 +0000
+++ b/sql/sql_delete.cc	2015-02-04 17:32:15 +0000
@@ -657,9 +657,10 @@ multi_delete::initialize_tables(JOIN *jo
   delete_while_scanning= 1;
   for (walk= delete_tables; walk; walk= walk->next_local)
   {
-    tables_to_delete_from|= walk->table->map;
+    TABLE_LIST *tbl= walk->correspondent_table->find_table_for_update();
+    tables_to_delete_from|= tbl->table->map;
     if (delete_while_scanning &&
-        unique_table(thd, walk, join->tables_list, false))
+        unique_table(thd, tbl, join->tables_list, false))
     {
       /*
         If the table we are going to delete from appears

=== modified file 'sql/sql_derived.cc'
--- a/sql/sql_derived.cc	2014-07-31 07:11:10 +0000
+++ b/sql/sql_derived.cc	2015-02-04 17:32:15 +0000
@@ -507,6 +507,9 @@ bool mysql_derived_merge_for_insert(THD
     DBUG_RETURN(FALSE);
   if (derived->is_materialized_derived())
     DBUG_RETURN(mysql_derived_prepare(thd, lex, derived));
+  if ((thd->lex->sql_command == SQLCOM_UPDATE_MULTI ||
+       thd->lex->sql_command == SQLCOM_DELETE_MULTI))
+    DBUG_RETURN(FALSE);
   if (!derived->is_multitable())
   {
     if (!derived->single_table_updatable())

=== modified file 'sql/table.h'
--- a/sql/table.h	2014-12-21 18:23:28 +0000
+++ b/sql/table.h	2015-02-04 17:32:15 +0000
@@ -1984,6 +1984,16 @@ struct TABLE_LIST
   TABLE_LIST *find_underlying_table(TABLE *table);
   TABLE_LIST *first_leaf_for_name_resolution();
   TABLE_LIST *last_leaf_for_name_resolution();
+  TABLE_LIST *find_table_for_update()
+  {
+    TABLE_LIST *tbl= this;
+    while(!tbl->is_multitable() && tbl->single_table_updatable() &&
+        tbl->merge_underlying_list)
+    {
+      tbl= tbl->merge_underlying_list;
+    }
+    return tbl;
+  }
   TABLE *get_real_join_table();
   bool is_leaf_for_name_resolution();
   inline TABLE_LIST *top_table()



More information about the commits mailing list