MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:Alexey Kopytov Date:May 25 2010 2:43pm
Subject:bzr commit into mysql-5.1-bugteam branch (Alexey.Kopytov:3394)
Bug#53830
View as plain text  
#At file:///data/src/bzr_new/bugteam/bug53830/my51-bug53830/ based on revid:gshchepa@stripped

 3394 Alexey Kopytov	2010-05-25
      Bug #53830: !table || (!table->read_set ||
                   bitmap_is_set(table->read_set, field_index))
      
      UPDATE on an InnoDB table modifying the same index that is used
      to satisfy the WHERE condition could trigger a debug assertion
      under some circumstances.
      
      Since for engines with the HA_PRIMARY_KEY_IN_READ_INDEX flag
      set results of an index scan on a secondary index are appended
      by the primary key value, if a query involves only columns from
      the primary key and a secondary index, the latter is considered
      to be covering.
      
      That tricks mysql_update() to mark for reading only columns
      from the secondary index when it does an index scan to retrieve
      rows to update in case a part of that key is also being
      updated. However, there may be other columns in WHERE that are
      part of the primary key, but not the secondary one.
      
      What we actually want to do in this case is to add index
      columns to the existing WHERE columns bitmap rather than
      replace it.
     @ mysql-test/r/innodb_mysql.result
        Test case for bug #53830.
     @ mysql-test/t/innodb_mysql.test
        Test case for bug #53830.
     @ sql/sql_update.cc
        Add index columns to the read_set bitmap, don't replace it.
     @ sql/table.cc
        Added a new add_read_columns_used_by_index() function to 
        st_table.
     @ sql/table.h
        Added a new add_read_columns_used_by_index() function to 
        st_table.

    modified:
      mysql-test/r/innodb_mysql.result
      mysql-test/t/innodb_mysql.test
      sql/sql_update.cc
      sql/table.cc
      sql/table.h
=== modified file 'mysql-test/r/innodb_mysql.result'
--- a/mysql-test/r/innodb_mysql.result	2010-05-07 05:38:42 +0000
+++ b/mysql-test/r/innodb_mysql.result	2010-05-25 14:43:45 +0000
@@ -2408,4 +2408,13 @@ id	select_type	table	type	possible_keys	
 1	SIMPLE	t1	const	PRIMARY	NULL	NULL	NULL	1	Impossible ON condition
 1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	3	Using where
 DROP TABLE t1,t2;
+#
+# Bug #53830: !table || (!table->read_set || bitmap_is_set(table->read_set, field_index))
+#
+CREATE TABLE t1 (a INT, b INT, c INT, d INT,
+PRIMARY KEY(a,b,c), KEY(b,d))
+ENGINE=InnoDB;
+INSERT INTO t1 VALUES (0, 77, 1, 3);
+UPDATE t1 SET d = 0 WHERE b = 77 AND c = 25;
+DROP TABLE t1;
 End of 5.1 tests

=== modified file 'mysql-test/t/innodb_mysql.test'
--- a/mysql-test/t/innodb_mysql.test	2010-05-07 05:38:42 +0000
+++ b/mysql-test/t/innodb_mysql.test	2010-05-25 14:43:45 +0000
@@ -649,4 +649,18 @@ EXPLAIN SELECT t1.id,t2.id FROM t2 LEFT 
 
 DROP TABLE t1,t2;
 
+
+--echo #
+--echo # Bug #53830: !table || (!table->read_set || bitmap_is_set(table->read_set, field_index))
+--echo #
+
+CREATE TABLE t1 (a INT, b INT, c INT, d INT,
+                 PRIMARY KEY(a,b,c), KEY(b,d))
+                 ENGINE=InnoDB;
+INSERT INTO t1 VALUES (0, 77, 1, 3);
+
+UPDATE t1 SET d = 0 WHERE b = 77 AND c = 25;
+
+DROP TABLE t1;
+
 --echo End of 5.1 tests

=== modified file 'sql/sql_update.cc'
--- a/sql/sql_update.cc	2010-05-12 11:19:12 +0000
+++ b/sql/sql_update.cc	2010-05-25 14:43:45 +0000
@@ -397,7 +397,7 @@ int mysql_update(THD *thd,
       matching rows before updating the table!
     */
     if (used_index < MAX_KEY && old_covering_keys.is_set(used_index))
-      table->mark_columns_used_by_index(used_index);
+      table->add_read_columns_used_by_index(used_index);
     else
     {
       table->use_all_columns();

=== modified file 'sql/table.cc'
--- a/sql/table.cc	2010-05-21 18:47:32 +0000
+++ b/sql/table.cc	2010-05-25 14:43:45 +0000
@@ -4378,6 +4378,27 @@ void st_table::mark_columns_used_by_inde
 
 
 /*
+  Add fields used by a specified index to the table's read_set.
+
+  NOTE:
+    The original state can be restored with
+    restore_column_maps_after_mark_index().
+*/
+
+void st_table::add_read_columns_used_by_index(uint index)
+{
+  MY_BITMAP *bitmap= &tmp_set;
+  DBUG_ENTER("st_table::add_read_columns_used_by_index");
+
+  set_keyread(TRUE);
+  bitmap_copy(bitmap, read_set);
+  mark_columns_used_by_index_no_reset(index, bitmap);
+  column_bitmaps_set(bitmap, write_set);
+  DBUG_VOID_RETURN;
+}
+
+
+/*
   Restore to use normal column maps after key read
 
   NOTES

=== modified file 'sql/table.h'
--- a/sql/table.h	2010-05-08 03:25:33 +0000
+++ b/sql/table.h	2010-05-25 14:43:45 +0000
@@ -865,6 +865,7 @@ struct st_table {
   void prepare_for_position(void);
   void mark_columns_used_by_index_no_reset(uint index, MY_BITMAP *map);
   void mark_columns_used_by_index(uint index);
+  void add_read_columns_used_by_index(uint index);
   void restore_column_maps_after_mark_index();
   void mark_auto_increment_column(void);
   void mark_columns_needed_for_update(void);


Attachment: [text/bzr-bundle] bzr/alexey.kopytov@sun.com-20100525144345-o32em1pwf1rk2spg.bundle
Thread
bzr commit into mysql-5.1-bugteam branch (Alexey.Kopytov:3394)Bug#53830Alexey Kopytov25 May