[Commits] Rev 3471: # MDEV-3817: Wrong result with index_merge+index_merge_intersection, InnoDB table, join, AND and OR conditions in file:///data0/psergey/dev2/10.0-serg-fix-imerge/

Sergey Petrunya psergey at askmonty.org
Sat Nov 3 10:24:37 EET 2012


At file:///data0/psergey/dev2/10.0-serg-fix-imerge/

------------------------------------------------------------
revno: 3471
revision-id: psergey at askmonty.org-20121103082436-wyyctfe5gpl4vu3f
parent: sergii at pisem.net-20121103112851-bvy1mlhirxbkedvf
committer: Sergey Petrunya <psergey at askmonty.org>
branch nick: 10.0-serg-fix-imerge
timestamp: Sat 2012-11-03 12:24:36 +0400
message:
  # MDEV-3817: Wrong result with index_merge+index_merge_intersection, InnoDB table, join, AND and OR conditions
  Reconcile the fixes from:
  #
  # guilhem.bichot at oracle.com-20110805143029-ywrzuz15uzgontr0
  # Fix for BUG#12698916 - "JOIN QUERY GIVES WRONG RESULT AT 2ND EXEC. OR
  # AFTER FLUSH TABLES [-INT VS NULL]"
  #
  # guilhem.bichot at oracle.com-20111209150650-tzx3ldzxe1yfwji6
  # Fix for BUG#12912171 - ASSERTION FAILED: QUICK->HEAD->READ_SET == SAVE_READ_SET
  # and
  #
  and related fixes from: BUG#1006164, MDEV-376:
  
  Now, ROR-merged QUICK_RANGE_SELECT objects make no assumptions about the values
  of table->read_set and table->write_set.
  Each QUICK_ROR_SELECT has (and had before) its own column bitmap, but now, all 
  QUICK_ROR_SELECT's functions that care: reset(), init_ror_merged_scan(), and 
  get_next()  will set table->read_set when invoked and restore it back to what 
  it was before the call before they return.
  
  This allows to avoid the mess when somebody else modifies table->read_set for 
  some reason.
=== modified file 'mysql-test/r/innodb_mrr_cpk.result'
--- a/mysql-test/r/innodb_mrr_cpk.result	2012-02-16 16:15:57 +0000
+++ b/mysql-test/r/innodb_mrr_cpk.result	2012-11-03 08:24:36 +0000
@@ -149,3 +149,25 @@
 set storage_engine=@save_storage_engine;
 set optimizer_switch=@innodb_mrr_cpk_tmp;
 drop table t0;
+#
+# MDEV-3817: Wrong result with index_merge+index_merge_intersection, InnoDB table, join, AND and OR conditions
+#
+set @tmp_mdev3817=@@optimizer_switch;
+SET optimizer_switch='index_merge=on,index_merge_intersection=on';
+CREATE TABLE t1 (
+a INT PRIMARY KEY,
+b INT,
+c VARCHAR(1024) CHARACTER SET utf8,
+d INT,
+KEY (b)
+) ENGINE=InnoDB;
+INSERT INTO t1 VALUES 
+(1, 9, 'one', 11), (2, 6, 'two', 12), (3, 2, 'three', 13), (4, 5, 'four', 14);
+CREATE TABLE t2 (e INT, g INT) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (1,9), (2,6) ;
+SELECT * FROM t1, t2 WHERE g = b AND ( a < 7 OR a > e );
+a	b	c	d	e	g
+1	9	one	11	1	9
+2	6	two	12	2	6
+DROP TABLE t1, t2;
+set optimizer_switch=@tmp_mdev3817;

=== modified file 'mysql-test/r/partition_innodb.result'
--- a/mysql-test/r/partition_innodb.result	2012-08-17 13:46:34 +0000
+++ b/mysql-test/r/partition_innodb.result	2012-11-03 08:24:36 +0000
@@ -576,4 +576,24 @@
 1	2
 0	1
 DROP TABLE t1;
+#
+# BUG#12912171 - ASSERTION FAILED: QUICK->HEAD->READ_SET ==
+# SAVE_READ_SET
+#
+CREATE TABLE t1 (
+a INT,
+b INT,
+c INT,
+PRIMARY KEY (c,a), KEY (a),KEY (a)
+) ENGINE=INNODB PARTITION BY KEY () PARTITIONS 2;
+INSERT INTO t1 VALUES (1,5,1),(2,4,1),(3,3,1),(4,2,1),(5,1,1);
+UPDATE t1 SET b = 0, c=1 WHERE a <=>0;
+SELECT * FROM t1;
+a	b	c
+1	5	1
+2	4	1
+3	3	1
+4	2	1
+5	1	1
+DROP TABLE t1;
 set global default_storage_engine=default;

=== modified file 'mysql-test/r/range.result'
--- a/mysql-test/r/range.result	2012-04-07 13:58:46 +0000
+++ b/mysql-test/r/range.result	2012-11-03 08:24:36 +0000
@@ -1953,3 +1953,49 @@
 14	1	1	q
 9	7	1	s
 DROP TABLE t1;
+#
+# BUG#13256446 - ASSERTION QUICK->HEAD->READ_SET ==
+# SAVE_READ_SET' FAILED IN OPT_RANGE.CC:1606 
+#
+CREATE TABLE t1 (
+f1 INT AUTO_INCREMENT,
+f2 INT,
+f3 INT,
+f4 INT,
+PRIMARY KEY (f1),KEY(f2)
+) ENGINE=INNODB;
+CREATE ALGORITHM=MERGE VIEW v2 AS SELECT f1,f2,f3,f4 FROM t1 WHERE f2=103;
+INSERT INTO t1 VALUES (154,0,NULL,0),(0,NULL,9,0),
+(NULL,102,NULL,3),(0,3,NULL,0), (9,0,NULL,0),(0,9,NULL,157);
+SELECT * FROM v2;
+f1	f2	f3	f4
+UPDATE v2 SET f4=0, f2=NULL, f1=NULL WHERE f1 > 16 ORDER BY f1;
+SELECT * FROM v2;
+f1	f2	f3	f4
+DROP TABLE t1;
+DROP VIEW v2;
+CREATE TABLE t1 (
+f1 INT AUTO_INCREMENT,
+f2 INT,
+f3 INT,
+f4 INT,
+PRIMARY KEY (f1),KEY(f2)
+) ENGINE=INNODB;
+INSERT INTO t1 VALUES(1,NULL,NULL,0), (2,2,0,3), (9,0,107,18),
+(10,0,0,0), (231,0,0,0), (232,0,8,0), (234,0,0,NULL), (235,8,0,3);
+CREATE ALGORITHM=MERGE VIEW v3 AS SELECT f1,f2,f3,f4 FROM t1 WHERE f1<=85 ;
+SELECT * FROM v3;
+f1	f2	f3	f4
+1	NULL	NULL	0
+2	2	0	3
+9	0	107	18
+10	0	0	0
+UPDATE v3 SET f3=0, f4=4 WHERE f2=68 ORDER BY f1;
+SELECT * FROM v3;
+f1	f2	f3	f4
+1	NULL	NULL	0
+2	2	0	3
+9	0	107	18
+10	0	0	0
+DROP TABLE t1;
+DROP VIEW v3;

=== modified file 'mysql-test/r/range_mrr_icp.result'
--- a/mysql-test/r/range_mrr_icp.result	2012-04-07 13:58:46 +0000
+++ b/mysql-test/r/range_mrr_icp.result	2012-11-03 08:24:36 +0000
@@ -1955,4 +1955,50 @@
 9	7	1	s
 14	1	1	q
 DROP TABLE t1;
+#
+# BUG#13256446 - ASSERTION QUICK->HEAD->READ_SET ==
+# SAVE_READ_SET' FAILED IN OPT_RANGE.CC:1606 
+#
+CREATE TABLE t1 (
+f1 INT AUTO_INCREMENT,
+f2 INT,
+f3 INT,
+f4 INT,
+PRIMARY KEY (f1),KEY(f2)
+) ENGINE=INNODB;
+CREATE ALGORITHM=MERGE VIEW v2 AS SELECT f1,f2,f3,f4 FROM t1 WHERE f2=103;
+INSERT INTO t1 VALUES (154,0,NULL,0),(0,NULL,9,0),
+(NULL,102,NULL,3),(0,3,NULL,0), (9,0,NULL,0),(0,9,NULL,157);
+SELECT * FROM v2;
+f1	f2	f3	f4
+UPDATE v2 SET f4=0, f2=NULL, f1=NULL WHERE f1 > 16 ORDER BY f1;
+SELECT * FROM v2;
+f1	f2	f3	f4
+DROP TABLE t1;
+DROP VIEW v2;
+CREATE TABLE t1 (
+f1 INT AUTO_INCREMENT,
+f2 INT,
+f3 INT,
+f4 INT,
+PRIMARY KEY (f1),KEY(f2)
+) ENGINE=INNODB;
+INSERT INTO t1 VALUES(1,NULL,NULL,0), (2,2,0,3), (9,0,107,18),
+(10,0,0,0), (231,0,0,0), (232,0,8,0), (234,0,0,NULL), (235,8,0,3);
+CREATE ALGORITHM=MERGE VIEW v3 AS SELECT f1,f2,f3,f4 FROM t1 WHERE f1<=85 ;
+SELECT * FROM v3;
+f1	f2	f3	f4
+1	NULL	NULL	0
+2	2	0	3
+9	0	107	18
+10	0	0	0
+UPDATE v3 SET f3=0, f4=4 WHERE f2=68 ORDER BY f1;
+SELECT * FROM v3;
+f1	f2	f3	f4
+1	NULL	NULL	0
+2	2	0	3
+9	0	107	18
+10	0	0	0
+DROP TABLE t1;
+DROP VIEW v3;
 set optimizer_switch=@mrr_icp_extra_tmp;

=== modified file 'mysql-test/r/update.result'
--- a/mysql-test/r/update.result	2012-02-15 17:08:08 +0000
+++ b/mysql-test/r/update.result	2012-11-03 08:24:36 +0000
@@ -561,3 +561,45 @@
 DROP VIEW v1;
 DROP FUNCTION f1;
 DROP TABLE t1;
+#
+# Verify that UPDATE does the same number of handler_update
+# operations, no matter if there is ORDER BY or not.
+#
+CREATE TABLE t1 (i INT) ENGINE=INNODB;
+INSERT INTO t1 VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19),
+(20),(21),(22),(23),(24),(25),(26),(27),(28),(29),
+(30),(31),(32),(33),(34),(35);
+CREATE TABLE t2 (a CHAR(2), b CHAR(2), c CHAR(2), d CHAR(2),
+INDEX idx (a,b(1),c)) ENGINE=INNODB;
+INSERT INTO t2 SELECT i, i, i, i FROM t1;
+FLUSH STATUS;
+START TRANSACTION;
+UPDATE t2 SET d = 10 WHERE b = 10 LIMIT 5;
+SHOW STATUS LIKE 'HANDLER_UPDATE';
+Variable_name	Value
+Handler_update	1
+ROLLBACK;
+FLUSH STATUS;
+START TRANSACTION;
+UPDATE t2 SET d = 10 WHERE b = 10 ORDER BY a, c LIMIT 5;
+SHOW STATUS LIKE 'HANDLER_UPDATE';
+Variable_name	Value
+Handler_update	1
+ROLLBACK;
+Same test with a different UPDATE.
+ALTER TABLE t2 DROP INDEX idx, ADD INDEX idx2 (a, b);
+FLUSH STATUS;
+START TRANSACTION;
+UPDATE t2 SET c = 10 LIMIT 5;
+SHOW STATUS LIKE 'HANDLER_UPDATE';
+Variable_name	Value
+Handler_update	5
+ROLLBACK;
+FLUSH STATUS;
+START TRANSACTION;
+UPDATE t2 SET c = 10 ORDER BY a, b DESC LIMIT 5;
+SHOW STATUS LIKE 'HANDLER_UPDATE';
+Variable_name	Value
+Handler_update	5
+ROLLBACK;
+DROP TABLE t1, t2;

=== modified file 'mysql-test/t/innodb_mrr_cpk.test'
--- a/mysql-test/t/innodb_mrr_cpk.test	2011-07-08 14:46:47 +0000
+++ b/mysql-test/t/innodb_mrr_cpk.test	2012-11-03 08:24:36 +0000
@@ -139,3 +139,29 @@
 set optimizer_switch=@innodb_mrr_cpk_tmp;
 drop table t0;
 
+--echo #
+--echo # MDEV-3817: Wrong result with index_merge+index_merge_intersection, InnoDB table, join, AND and OR conditions
+--echo #
+
+set @tmp_mdev3817=@@optimizer_switch;
+SET optimizer_switch='index_merge=on,index_merge_intersection=on';
+
+CREATE TABLE t1 (
+ a INT PRIMARY KEY,
+ b INT,
+ c VARCHAR(1024) CHARACTER SET utf8,
+ d INT,
+ KEY (b)
+) ENGINE=InnoDB;
+
+INSERT INTO t1 VALUES 
+(1, 9, 'one', 11), (2, 6, 'two', 12), (3, 2, 'three', 13), (4, 5, 'four', 14);
+
+CREATE TABLE t2 (e INT, g INT) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (1,9), (2,6) ;
+
+SELECT * FROM t1, t2 WHERE g = b AND ( a < 7 OR a > e );
+
+DROP TABLE t1, t2;
+set optimizer_switch=@tmp_mdev3817;
+

=== modified file 'mysql-test/t/partition_innodb.test'
--- a/mysql-test/t/partition_innodb.test	2012-08-17 13:46:34 +0000
+++ b/mysql-test/t/partition_innodb.test	2012-11-03 08:24:36 +0000
@@ -665,4 +665,19 @@
 SELECT * FROM t1;
 DROP TABLE t1;
 
+--echo #
+--echo # BUG#12912171 - ASSERTION FAILED: QUICK->HEAD->READ_SET ==
+--echo # SAVE_READ_SET
+--echo #
+CREATE TABLE t1 (
+ a INT,
+ b INT,
+ c INT,
+ PRIMARY KEY (c,a), KEY (a),KEY (a)
+) ENGINE=INNODB PARTITION BY KEY () PARTITIONS 2;
+INSERT INTO t1 VALUES (1,5,1),(2,4,1),(3,3,1),(4,2,1),(5,1,1);
+UPDATE t1 SET b = 0, c=1 WHERE a <=>0;
+SELECT * FROM t1;
+DROP TABLE t1;
+
 set global default_storage_engine=default;

=== modified file 'mysql-test/t/range.test'
--- a/mysql-test/t/range.test	2012-04-07 13:58:46 +0000
+++ b/mysql-test/t/range.test	2012-11-03 08:24:36 +0000
@@ -1,6 +1,7 @@
 #
 # Problem with range optimizer
 #
+--source include/have_innodb.inc
 
 --disable_warnings
 drop table if exists t1, t2, t3, t10, t100;
@@ -1549,3 +1550,58 @@
 SELECT * FROM t1 force index(d)  WHERE d = 'q' OR d >= 'q' OR (d IN ( 'j' , 's' , 'i' ) AND ( b = 102 ));
 
 DROP TABLE t1;
+
+--disable_parsing
+# MariaDB: Moved the following to partition.test
+--echo #
+--echo # BUG#12912171 - ASSERTION FAILED: QUICK->HEAD->READ_SET ==
+--echo # SAVE_READ_SET
+--echo #
+CREATE TABLE t1 (
+ a INT,
+ b INT,
+ c INT,
+ PRIMARY KEY (c,a), KEY (a),KEY (a)
+) ENGINE=INNODB PARTITION BY KEY () PARTITIONS 2;
+INSERT INTO t1 VALUES (1,5,1),(2,4,1),(3,3,1),(4,2,1),(5,1,1);
+UPDATE t1 SET b = 0, c=1 WHERE a <=>0;
+SELECT * FROM t1;
+DROP TABLE t1;
+--enable_parsing
+
+--echo #
+--echo # BUG#13256446 - ASSERTION QUICK->HEAD->READ_SET ==
+--echo # SAVE_READ_SET' FAILED IN OPT_RANGE.CC:1606 
+--echo #
+CREATE TABLE t1 (
+ f1 INT AUTO_INCREMENT,
+ f2 INT,
+ f3 INT,
+ f4 INT,
+ PRIMARY KEY (f1),KEY(f2)
+) ENGINE=INNODB;
+CREATE ALGORITHM=MERGE VIEW v2 AS SELECT f1,f2,f3,f4 FROM t1 WHERE f2=103;
+INSERT INTO t1 VALUES (154,0,NULL,0),(0,NULL,9,0),
+ (NULL,102,NULL,3),(0,3,NULL,0), (9,0,NULL,0),(0,9,NULL,157);
+SELECT * FROM v2;
+UPDATE v2 SET f4=0, f2=NULL, f1=NULL WHERE f1 > 16 ORDER BY f1;
+SELECT * FROM v2;
+DROP TABLE t1;
+DROP VIEW v2;
+
+CREATE TABLE t1 (
+ f1 INT AUTO_INCREMENT,
+ f2 INT,
+ f3 INT,
+ f4 INT,
+ PRIMARY KEY (f1),KEY(f2)
+) ENGINE=INNODB;
+INSERT INTO t1 VALUES(1,NULL,NULL,0), (2,2,0,3), (9,0,107,18),
+ (10,0,0,0), (231,0,0,0), (232,0,8,0), (234,0,0,NULL), (235,8,0,3);
+CREATE ALGORITHM=MERGE VIEW v3 AS SELECT f1,f2,f3,f4 FROM t1 WHERE f1<=85 ;
+SELECT * FROM v3;
+UPDATE v3 SET f3=0, f4=4 WHERE f2=68 ORDER BY f1; 
+SELECT * FROM v3;
+DROP TABLE t1;
+DROP VIEW v3;
+

=== modified file 'mysql-test/t/update.test'
--- a/mysql-test/t/update.test	2010-07-19 09:03:52 +0000
+++ b/mysql-test/t/update.test	2012-11-03 08:24:36 +0000
@@ -2,6 +2,8 @@
 # test of updating of keys
 #
 
+-- source include/have_innodb.inc
+
 --disable_warnings
 drop table if exists t1,t2;
 --enable_warnings
@@ -503,3 +505,42 @@
 DROP VIEW v1;
 DROP FUNCTION f1;
 DROP TABLE t1;
+
+--echo #
+--echo # Verify that UPDATE does the same number of handler_update
+--echo # operations, no matter if there is ORDER BY or not.
+--echo #
+
+CREATE TABLE t1 (i INT) ENGINE=INNODB;
+INSERT INTO t1 VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19),
+                      (20),(21),(22),(23),(24),(25),(26),(27),(28),(29),
+                      (30),(31),(32),(33),(34),(35);
+CREATE TABLE t2 (a CHAR(2), b CHAR(2), c CHAR(2), d CHAR(2),
+                 INDEX idx (a,b(1),c)) ENGINE=INNODB;
+INSERT INTO t2 SELECT i, i, i, i FROM t1;
+FLUSH STATUS; # FLUSH is autocommit, so we put it outside of transaction
+START TRANSACTION;
+UPDATE t2 SET d = 10 WHERE b = 10 LIMIT 5;
+SHOW STATUS LIKE 'HANDLER_UPDATE';
+ROLLBACK;
+FLUSH STATUS;
+START TRANSACTION;
+UPDATE t2 SET d = 10 WHERE b = 10 ORDER BY a, c LIMIT 5;
+SHOW STATUS LIKE 'HANDLER_UPDATE';
+ROLLBACK;
+
+--echo Same test with a different UPDATE.
+
+ALTER TABLE t2 DROP INDEX idx, ADD INDEX idx2 (a, b);
+FLUSH STATUS;
+START TRANSACTION;
+UPDATE t2 SET c = 10 LIMIT 5;
+SHOW STATUS LIKE 'HANDLER_UPDATE';
+ROLLBACK;
+FLUSH STATUS;
+START TRANSACTION;
+UPDATE t2 SET c = 10 ORDER BY a, b DESC LIMIT 5;
+SHOW STATUS LIKE 'HANDLER_UPDATE';
+ROLLBACK;
+DROP TABLE t1, t2;
+

=== modified file 'sql/opt_range.cc'
--- a/sql/opt_range.cc	2012-11-03 11:28:51 +0000
+++ b/sql/opt_range.cc	2012-11-03 08:24:36 +0000
@@ -1788,8 +1788,6 @@
     bzero((char*) &alloc,sizeof(alloc));
   file= head->file;
   record= head->record[0];
-  save_read_set= head->read_set;
-  save_write_set= head->write_set;
 
   /* Allocate a bitmap for used columns (Q: why not on MEM_ROOT?) */
   if (!(bitmap= (my_bitmap_map*) my_malloc(head->s->column_bitmap_size,
@@ -1859,7 +1857,6 @@
     free_root(&alloc,MYF(0));
     my_free(column_bitmap.bitmap);
   }
-  head->column_bitmaps_set(save_read_set, save_write_set);
   my_free(mrr_buf_desc);
   DBUG_VOID_RETURN;
 }
@@ -2002,6 +1999,8 @@
   handler *save_file= file, *org_file;
   my_bool org_key_read;
   THD *thd= head->in_use;
+  MY_BITMAP * const save_read_set= head->read_set;
+  MY_BITMAP * const save_write_set= head->write_set;
   DBUG_ENTER("QUICK_RANGE_SELECT::init_ror_merged_scan");
 
   in_ror_merged_scan= 1;
@@ -2052,6 +2051,7 @@
   last_rowid= file->ref;
 
 end:
+  DBUG_ASSERT(head->read_set == &column_bitmap);
   /*
     We are only going to read key fields and call position() on 'file'
     The following sets head->tmp_set to only use this key and then updates
@@ -2065,7 +2065,8 @@
   if (!head->no_keyread)
   {
     doing_key_read= 1;
-    head->mark_columns_used_by_index(index);
+    head->mark_columns_used_by_index_no_reset(index, head->read_set);
+    head->enable_keyread();
   }
 
   head->prepare_for_position();
@@ -2087,8 +2088,9 @@
 
   head->file= org_file;
   head->key_read= org_key_read;
-  bitmap_copy(&column_bitmap, head->read_set);
-  head->column_bitmaps_set(&column_bitmap, &column_bitmap);
+
+  /* Restore head->read_set (and write_set) to what they had before the call */
+  head->column_bitmaps_set(save_read_set, save_write_set);
  
   if (reset())
   {
@@ -2145,9 +2147,19 @@
   while ((cur= quick_it++))
   {
     quick= cur->quick;
+#ifndef DBUG_OFF
+    const MY_BITMAP * const save_read_set= quick->head->read_set;
+    const MY_BITMAP * const save_write_set= quick->head->write_set;
+#endif
     if (quick->init_ror_merged_scan(FALSE))
       DBUG_RETURN(1);
     quick->file->extra(HA_EXTRA_KEYREAD_PRESERVE_FIELDS);
+
+    // Sets are shared by all members of "quick_selects" so must not change
+#ifndef DBUG_OFF
+    DBUG_ASSERT(quick->head->read_set == save_read_set);
+    DBUG_ASSERT(quick->head->write_set == save_write_set);
+#endif
     /* All merged scans share the same record buffer in intersection. */
     quick->record= head->record[0];
   }
@@ -10941,16 +10953,20 @@
   uchar *mrange_buff;
   int   error;
   HANDLER_BUFFER empty_buf;
+  MY_BITMAP * const save_read_set= head->read_set;
+  MY_BITMAP * const save_write_set= head->write_set;
   DBUG_ENTER("QUICK_RANGE_SELECT::reset");
   last_range= NULL;
   cur_range= (QUICK_RANGE**) ranges.buffer;
+  RANGE_SEQ_IF seq_funcs= {NULL, quick_range_seq_init, quick_range_seq_next, 0, 0};
+
+  if (in_ror_merged_scan)
+    head->column_bitmaps_set_no_signal(&column_bitmap, &column_bitmap);
 
   if (file->inited == handler::NONE)
   {
-    if (in_ror_merged_scan)
-      head->column_bitmaps_set_no_signal(&column_bitmap, &column_bitmap);
     if ((error= file->ha_index_init(index,1)))
-        DBUG_RETURN(error);
+      goto err;
   }
 
   /* Allocate buffer if we need one but haven't allocated it yet */
@@ -10985,10 +11001,14 @@
   if (!mrr_buf_desc)
     empty_buf.buffer= empty_buf.buffer_end= empty_buf.end_of_used_area= NULL;
  
-  RANGE_SEQ_IF seq_funcs= {NULL, quick_range_seq_init, quick_range_seq_next, 0, 0};
   error= file->multi_range_read_init(&seq_funcs, (void*)this, ranges.elements,
                                      mrr_flags, mrr_buf_desc? mrr_buf_desc: 
                                                               &empty_buf);
+err:
+  /* Restore bitmaps set on entry */
+  if (in_ror_merged_scan)
+    head->column_bitmaps_set_no_signal(save_read_set, save_write_set);
+  
   DBUG_RETURN(error);
 }
 
@@ -11011,6 +11031,9 @@
 int QUICK_RANGE_SELECT::get_next()
 {
   range_id_t dummy;
+  MY_BITMAP * const save_read_set= head->read_set;
+  MY_BITMAP * const save_write_set= head->write_set;
+
   DBUG_ENTER("QUICK_RANGE_SELECT::get_next");
   if (in_ror_merged_scan)
   {

=== modified file 'sql/opt_range.h'
--- a/sql/opt_range.h	2012-06-24 16:10:11 +0000
+++ b/sql/opt_range.h	2012-11-03 08:24:36 +0000
@@ -430,7 +430,7 @@
 
   /* Members to deal with case when this quick select is a ROR-merged scan */
   bool in_ror_merged_scan;
-  MY_BITMAP column_bitmap, *save_read_set, *save_write_set;
+  MY_BITMAP column_bitmap;
   bool free_file;   /* TRUE <=> this->file is "owned" by this quick select */
 
   /* Range pointers to be used when not using MRR interface */

=== modified file 'sql/sql_update.cc'
--- a/sql/sql_update.cc	2012-10-19 18:38:59 +0000
+++ b/sql/sql_update.cc	2012-11-03 08:24:36 +0000
@@ -480,12 +480,15 @@
       We can't update table directly;  We must first search after all
       matching rows before updating the table!
     */
+
+    // Verify that table->restore_column_maps_after_mark_index() will work
+    DBUG_ASSERT(table->read_set == &table->def_read_set);
+    DBUG_ASSERT(table->write_set == &table->def_write_set);
+
     if (used_index < MAX_KEY && old_covering_keys.is_set(used_index))
       table->add_read_columns_used_by_index(used_index);
     else
-    {
       table->use_all_columns();
-    }
 
     /* note: We avoid sorting if we sort on the used index */
     if (order && (need_sort || used_key_is_modified))
@@ -619,8 +622,11 @@
       if (error >= 0)
 	goto err;
     }
-    if (table->key_read)
-      table->restore_column_maps_after_mark_index();
+    /*
+      This restore bitmaps, works for add_read_columns_used_by_index() and
+      use_all_columns():
+    */
+    table->restore_column_maps_after_mark_index();
   }
 
   if (ignore)



More information about the commits mailing list