List:Commits« Previous MessageNext Message »
From:Mattias Jonsson Date:August 10 2010 8:43am
Subject:bzr commit into mysql-5.1-bugteam branch (mattias.jonsson:3480) Bug#55458
View as plain text  
#At file:///Users/mattiasj/mysql-bzr/b55458-51-bt/ based on revid:jon.hauglid@stripped

 3480 Mattias Jonsson	2010-08-10
      Bug#55458: Partitioned MyISAM table gets crashed by multi-table update
      
      Problem was that the handler call ::extra(HA_EXTRA_CACHE) was cached
      but the ::extra(HA_EXTRA_PREPARE_FOR_UPDATE) was not.
      
      Solution was to also cache the other call and forward it when moving
      to a new partition to scan.
     @ mysql-test/r/partition.result
        test result
     @ mysql-test/t/partition.test
        New test from bug report.
     @ sql/ha_partition.cc
        cache the HA_EXTRA_PREPARE_FOR_UPDATE just like HA_EXTRA_CACHE.
     @ sql/ha_partition.h
        Added cache flag for HA_EXTRA_PREPARE_FOR_UPDATE

    modified:
      mysql-test/r/partition.result
      mysql-test/t/partition.test
      sql/ha_partition.cc
      sql/ha_partition.h
=== modified file 'mysql-test/r/partition.result'
--- a/mysql-test/r/partition.result	2010-03-22 12:30:27 +0000
+++ b/mysql-test/r/partition.result	2010-08-10 08:43:12 +0000
@@ -1,4 +1,29 @@
 drop table if exists t1, t2;
+#
+# Bug#55458: Partitioned MyISAM table gets crashed by multi-table update 
+#
+CREATE TABLE t1 (
+`id` int NOT NULL,
+`user_num` int DEFAULT NULL,
+PRIMARY KEY (`id`)
+) ENGINE=MyISAM CHARSET=latin1;
+INSERT INTO t1 VALUES (1,8601);
+INSERT INTO t1 VALUES (2,8601);
+INSERT INTO t1 VALUES (3,8601);
+INSERT INTO t1 VALUES (4,8601);
+CREATE TABLE t2 (
+`id` int(11) NOT NULL,
+`user_num` int DEFAULT NULL,
+`name` varchar(64) NOT NULL,
+PRIMARY KEY (`id`)
+) ENGINE=MyISAM CHARSET=latin1
+PARTITION BY HASH (id)
+PARTITIONS 2;
+INSERT INTO t2 VALUES (1,8601,'John');
+INSERT INTO t2 VALUES (2,8601,'JS');
+INSERT INTO t2 VALUES (3,8601,'John S');
+UPDATE t1, t2 SET t2.name = 'John Smith' WHERE t1.user_num = t2.user_num;
+DROP TABLE t1, t2;
 CREATE TABLE t1 (a INT, b INT)
 PARTITION BY LIST (a)
 SUBPARTITION BY HASH (b)

=== modified file 'mysql-test/t/partition.test'
--- a/mysql-test/t/partition.test	2010-03-22 12:30:27 +0000
+++ b/mysql-test/t/partition.test	2010-08-10 08:43:12 +0000
@@ -14,6 +14,33 @@
 drop table if exists t1, t2;
 --enable_warnings
 
+--echo #
+--echo # Bug#55458: Partitioned MyISAM table gets crashed by multi-table update 
+--echo #
+CREATE TABLE t1 (
+  `id` int NOT NULL,
+  `user_num` int DEFAULT NULL,
+  PRIMARY KEY (`id`)
+) ENGINE=MyISAM CHARSET=latin1;
+INSERT INTO t1 VALUES (1,8601);
+INSERT INTO t1 VALUES (2,8601);
+INSERT INTO t1 VALUES (3,8601);
+INSERT INTO t1 VALUES (4,8601);
+CREATE TABLE t2 (
+  `id` int(11) NOT NULL,
+  `user_num` int DEFAULT NULL,
+  `name` varchar(64) NOT NULL,
+  PRIMARY KEY (`id`)
+) ENGINE=MyISAM CHARSET=latin1
+PARTITION BY HASH (id)
+PARTITIONS 2;
+INSERT INTO t2 VALUES (1,8601,'John');
+INSERT INTO t2 VALUES (2,8601,'JS');
+INSERT INTO t2 VALUES (3,8601,'John S');
+
+UPDATE t1, t2 SET t2.name = 'John Smith' WHERE t1.user_num = t2.user_num;
+
+DROP TABLE t1, t2;
 #
 # Bug#48276: can't add column if subpartition exists
 CREATE TABLE t1 (a INT, b INT)

=== modified file 'sql/ha_partition.cc'
--- a/sql/ha_partition.cc	2010-07-08 23:09:31 +0000
+++ b/sql/ha_partition.cc	2010-08-10 08:43:12 +0000
@@ -232,6 +232,7 @@ void ha_partition::init_handler_variable
   m_innodb= FALSE;
   m_extra_cache= FALSE;
   m_extra_cache_size= 0;
+  m_extra_prepare_for_update= FALSE;
   m_handler_status= handler_not_initialized;
   m_low_byte_first= 1;
   m_part_field_array= NULL;
@@ -5549,9 +5550,20 @@ int ha_partition::extra(enum ha_extra_fu
   case HA_EXTRA_PREPARE_FOR_RENAME:
     DBUG_RETURN(prepare_for_rename());
     break;
+  case HA_EXTRA_PREPARE_FOR_UPDATE:
+    DBUG_ASSERT(m_extra_cache);
+    /*
+      Needs to be run on the first partition in the range now, and 
+      later in late_extra_cache, when switching to a new partition to scan.
+    */
+    m_extra_prepare_for_update= TRUE;
+    if (m_part_spec.start_part != NO_CURRENT_PART_ID)
+    {
+      VOID(m_file[m_part_spec.start_part]->extra(HA_EXTRA_PREPARE_FOR_UPDATE));
+    }
+    break;
   case HA_EXTRA_NORMAL:
   case HA_EXTRA_QUICK:
-  case HA_EXTRA_PREPARE_FOR_UPDATE:
   case HA_EXTRA_FORCE_REOPEN:
   case HA_EXTRA_PREPARE_FOR_DROP:
   case HA_EXTRA_FLUSH_CACHE:
@@ -5578,6 +5590,7 @@ int ha_partition::extra(enum ha_extra_fu
   {
     m_extra_cache= FALSE;
     m_extra_cache_size= 0;
+    m_extra_prepare_for_update= FALSE;
     DBUG_RETURN(loop_extra(operation));
   }
   case HA_EXTRA_IGNORE_NO_KEY:
@@ -5705,6 +5718,7 @@ int ha_partition::extra_opt(enum ha_extr
 void ha_partition::prepare_extra_cache(uint cachesize)
 {
   DBUG_ENTER("ha_partition::prepare_extra_cache()");
+  DBUG_PRINT("info", ("cachesize %u", cachesize));
 
   m_extra_cache= TRUE;
   m_extra_cache_size= cachesize;
@@ -5793,14 +5807,21 @@ void ha_partition::late_extra_cache(uint
 {
   handler *file;
   DBUG_ENTER("ha_partition::late_extra_cache");
+  DBUG_PRINT("info", ("extra_cache %u partid %u size %u", m_extra_cache,
+                      partition_id, m_extra_cache_size));
 
-  if (!m_extra_cache)
+  if (!m_extra_cache && !m_extra_prepare_for_update)
     DBUG_VOID_RETURN;
   file= m_file[partition_id];
   if (m_extra_cache_size == 0)
     VOID(file->extra(HA_EXTRA_CACHE));
   else
     VOID(file->extra_opt(HA_EXTRA_CACHE, m_extra_cache_size));
+  if (m_extra_prepare_for_update)
+  {
+    DBUG_ASSERT(m_extra_cache);
+    VOID(file->extra(HA_EXTRA_PREPARE_FOR_UPDATE));
+  }
   DBUG_VOID_RETURN;
 }
 
@@ -5821,7 +5842,7 @@ void ha_partition::late_extra_no_cache(u
   handler *file;
   DBUG_ENTER("ha_partition::late_extra_no_cache");
 
-  if (!m_extra_cache)
+  if (!m_extra_cache && !m_extra_prepare_for_update)
     DBUG_VOID_RETURN;
   file= m_file[partition_id];
   VOID(file->extra(HA_EXTRA_NO_CACHE));

=== modified file 'sql/ha_partition.h'
--- a/sql/ha_partition.h	2010-07-09 13:00:33 +0000
+++ b/sql/ha_partition.h	2010-08-10 08:43:12 +0000
@@ -154,6 +154,8 @@ private:
   */
   bool m_extra_cache;
   uint m_extra_cache_size;
+  /* The same goes for HA_EXTRA_PREPARE_FOR_UPDATE */
+  bool m_extra_prepare_for_update;
 
   void init_handler_variables();
   /*


Attachment: [text/bzr-bundle] bzr/mattias.jonsson@oracle.com-20100810084312-7pqozmh1gv90aq90.bundle
Thread
bzr commit into mysql-5.1-bugteam branch (mattias.jonsson:3480) Bug#55458Mattias Jonsson10 Aug