summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/innodb_mrr.result84
-rw-r--r--mysql-test/t/innodb_mrr.test87
-rw-r--r--sql/multi_range_read.cc54
-rw-r--r--sql/multi_range_read.h14
4 files changed, 237 insertions, 2 deletions
diff --git a/mysql-test/r/innodb_mrr.result b/mysql-test/r/innodb_mrr.result
index 83c7611acf3..76a0e0516b2 100644
--- a/mysql-test/r/innodb_mrr.result
+++ b/mysql-test/r/innodb_mrr.result
@@ -576,3 +576,87 @@ count(*)
480
set join_cache_level= @my_save_join_cache_level;
drop table t1;
+#
+# BUG#671340: Diverging results in with mrr_sort_keys=ON|OFF and join_cache_level=5
+#
+CREATE TABLE t1 (
+pk int(11) NOT NULL AUTO_INCREMENT,
+col_int_key int(11) NOT NULL,
+col_varchar_key varchar(1) NOT NULL,
+col_varchar_nokey varchar(1) NOT NULL,
+PRIMARY KEY (pk),
+KEY col_int_key (col_int_key),
+KEY col_varchar_key (col_varchar_key,col_int_key)
+) ENGINE=InnoDB;
+INSERT INTO t1 VALUES
+(10,8,'v','v'),
+(11,8,'f','f'),
+(12,5,'v','v'),
+(13,8,'s','s'),
+(14,8,'a','a'),
+(15,6,'p','p'),
+(16,7,'z','z'),
+(17,2,'a','a'),
+(18,5,'h','h'),
+(19,7,'h','h'),
+(20,2,'v','v'),
+(21,9,'v','v'),
+(22,142,'b','b'),
+(23,3,'y','y'),
+(24,0,'v','v'),
+(25,3,'m','m'),
+(26,5,'z','z'),
+(27,9,'n','n'),
+(28,1,'d','d'),
+(29,107,'a','a');
+CREATE TABLE t2 (
+pk int(11) NOT NULL AUTO_INCREMENT,
+col_int_key int(11) NOT NULL,
+col_varchar_key varchar(1) NOT NULL,
+col_varchar_nokey varchar(1) NOT NULL,
+PRIMARY KEY (pk),
+KEY col_int_key (col_int_key),
+KEY col_varchar_key (col_varchar_key,col_int_key)
+) ENGINE=InnoDB;
+INSERT INTO t2 VALUES
+(1,9,'x','x'),
+(2,5,'g','g'),
+(3,1,'o','o'),
+(4,0,'g','g'),
+(5,1,'v','v'),
+(6,190,'m','m'),
+(7,6,'x','x'),
+(8,3,'c','c'),
+(9,4,'z','z'),
+(10,3,'i','i'),
+(11,186,'x','x'),
+(12,1,'g','g'),
+(13,8,'q','q'),
+(14,226,'m','m'),
+(15,133,'p','p'),
+(16,6,'e','e'),
+(17,3,'t','t'),
+(18,8,'j','j'),
+(19,5,'h','h'),
+(20,7,'w','w');
+SELECT count(*), sum(table1.col_int_key*table2.pk)
+FROM
+t2 AS table1, t1 AS table2, t2 AS table3
+WHERE
+table3.col_varchar_nokey = table2.col_varchar_key AND table3.pk > table2.col_varchar_nokey ;
+count(*) sum(table1.col_int_key*table2.pk)
+240 185955
+set @my_save_join_cache_level= @@join_cache_level;
+set @my_save_join_buffer_size= @@join_buffer_size;
+set join_cache_level=6;
+set join_buffer_size=1500;
+SELECT count(*), sum(table1.col_int_key*table2.pk)
+FROM
+t2 AS table1, t1 AS table2, t2 AS table3
+WHERE
+table3.col_varchar_nokey = table2.col_varchar_key AND table3.pk > table2.col_varchar_nokey ;
+count(*) sum(table1.col_int_key*table2.pk)
+240 185955
+drop table t1,t2;
+set join_cache_level=@my_save_join_cache_level;
+set join_buffer_size=@my_save_join_buffer_size;
diff --git a/mysql-test/t/innodb_mrr.test b/mysql-test/t/innodb_mrr.test
index 33deb470345..70c7c54332e 100644
--- a/mysql-test/t/innodb_mrr.test
+++ b/mysql-test/t/innodb_mrr.test
@@ -277,3 +277,90 @@ select count(*) from
set join_cache_level= @my_save_join_cache_level;
drop table t1;
+
+--echo #
+--echo # BUG#671340: Diverging results in with mrr_sort_keys=ON|OFF and join_cache_level=5
+--echo #
+CREATE TABLE t1 (
+ pk int(11) NOT NULL AUTO_INCREMENT,
+ col_int_key int(11) NOT NULL,
+ col_varchar_key varchar(1) NOT NULL,
+ col_varchar_nokey varchar(1) NOT NULL,
+ PRIMARY KEY (pk),
+ KEY col_int_key (col_int_key),
+ KEY col_varchar_key (col_varchar_key,col_int_key)
+) ENGINE=InnoDB;
+INSERT INTO t1 VALUES
+ (10,8,'v','v'),
+ (11,8,'f','f'),
+ (12,5,'v','v'),
+ (13,8,'s','s'),
+ (14,8,'a','a'),
+ (15,6,'p','p'),
+ (16,7,'z','z'),
+ (17,2,'a','a'),
+ (18,5,'h','h'),
+ (19,7,'h','h'),
+ (20,2,'v','v'),
+ (21,9,'v','v'),
+ (22,142,'b','b'),
+ (23,3,'y','y'),
+ (24,0,'v','v'),
+ (25,3,'m','m'),
+ (26,5,'z','z'),
+ (27,9,'n','n'),
+ (28,1,'d','d'),
+ (29,107,'a','a');
+
+CREATE TABLE t2 (
+ pk int(11) NOT NULL AUTO_INCREMENT,
+ col_int_key int(11) NOT NULL,
+ col_varchar_key varchar(1) NOT NULL,
+ col_varchar_nokey varchar(1) NOT NULL,
+ PRIMARY KEY (pk),
+ KEY col_int_key (col_int_key),
+ KEY col_varchar_key (col_varchar_key,col_int_key)
+) ENGINE=InnoDB;
+INSERT INTO t2 VALUES
+ (1,9,'x','x'),
+ (2,5,'g','g'),
+ (3,1,'o','o'),
+ (4,0,'g','g'),
+ (5,1,'v','v'),
+ (6,190,'m','m'),
+ (7,6,'x','x'),
+ (8,3,'c','c'),
+ (9,4,'z','z'),
+ (10,3,'i','i'),
+ (11,186,'x','x'),
+ (12,1,'g','g'),
+ (13,8,'q','q'),
+ (14,226,'m','m'),
+ (15,133,'p','p'),
+ (16,6,'e','e'),
+ (17,3,'t','t'),
+ (18,8,'j','j'),
+ (19,5,'h','h'),
+ (20,7,'w','w');
+
+SELECT count(*), sum(table1.col_int_key*table2.pk)
+FROM
+ t2 AS table1, t1 AS table2, t2 AS table3
+WHERE
+ table3.col_varchar_nokey = table2.col_varchar_key AND table3.pk > table2.col_varchar_nokey ;
+
+set @my_save_join_cache_level= @@join_cache_level;
+set @my_save_join_buffer_size= @@join_buffer_size;
+set join_cache_level=6;
+set join_buffer_size=1500;
+
+SELECT count(*), sum(table1.col_int_key*table2.pk)
+FROM
+ t2 AS table1, t1 AS table2, t2 AS table3
+WHERE
+ table3.col_varchar_nokey = table2.col_varchar_key AND table3.pk > table2.col_varchar_nokey ;
+
+drop table t1,t2;
+set join_cache_level=@my_save_join_cache_level;
+set join_buffer_size=@my_save_join_buffer_size;
+
diff --git a/sql/multi_range_read.cc b/sql/multi_range_read.cc
index 9a276520243..9dcad4c1247 100644
--- a/sql/multi_range_read.cc
+++ b/sql/multi_range_read.cc
@@ -372,6 +372,42 @@ int Mrr_ordered_index_reader::get_next(char **range_info)
DBUG_RETURN(0);
}
+void Mrr_ordered_index_reader::set_temp_space(uchar *space)
+{
+ //saved_key_tuple= space;
+ saved_rowid= space;
+ have_saved_rowid= FALSE;
+}
+
+void Mrr_ordered_index_reader::interrupt_read()
+{
+ /*
+ key_copy(saved_key_tuple, file->get_table()->record[0],
+ &file->get_table()->key_info[file->active_index],
+ keypar.key_tuple_length);
+ */
+ /* Save the last rowid */
+ memcpy(saved_rowid, file->ref, file->ref_length);
+ have_saved_rowid= TRUE;
+}
+
+void Mrr_ordered_index_reader::position()
+{
+ if (have_saved_rowid)
+ memcpy(file->ref, saved_rowid, file->ref_length);
+ else
+ Mrr_index_reader::position();
+}
+
+void Mrr_ordered_index_reader::resume_read()
+{
+ /*
+ key_restore(file->get_table()->record[0], saved_key_tuple,
+ &file->get_table()->key_info[file->active_index],
+ keypar.key_tuple_length);
+ */
+}
+
/**
Fill the buffer with (lookup_tuple, range_id) pairs and sort
@@ -480,6 +516,8 @@ int Mrr_ordered_index_reader::init(handler *h_arg, RANGE_SEQ_IF *seq_funcs,
*/
disallow_identical_key_handling= test(mrr_funcs.skip_index_tuple);
+ /*bzero(saved_key_tuple, keypar.key_tuple_length);*/
+ have_saved_rowid= FALSE;
return 0;
}
@@ -571,6 +609,7 @@ int Mrr_ordered_rndpos_reader::refill_from_index_reader()
last_identical_rowid= NULL;
+ index_reader->resume_read();
while (rowid_buffer->can_write())
{
res= index_reader->get_next(&range_info);
@@ -589,6 +628,7 @@ int Mrr_ordered_rndpos_reader::refill_from_index_reader()
rowid_buffer->write();
}
+ index_reader->interrupt_read();
/* Sort the buffer contents by rowid */
rowid_buffer->sort((qsort2_cmp)rowid_cmp_reverse, (void*)file);
@@ -788,6 +828,16 @@ int DsMrr_impl::dsmrr_init(handler *h_arg, RANGE_SEQ_IF *seq_funcs,
keypar.key_size_in_keybuf= keypar.use_key_pointers?
sizeof(char*) : keypar.key_tuple_length;
key_buff_elem_size= keypar.key_size_in_keybuf + (int)is_mrr_assoc * sizeof(void*);
+
+ /* Ordered index reader needs some space to store an index tuple */
+ if (strategy != index_strategy)
+ {
+ if (full_buf_end - full_buf <= (ptrdiff_t)primary_file->ref_length/*keypar.key_tuple_length*/)
+ goto use_default_impl;
+ reader_factory.ordered_index_reader.set_temp_space(full_buf);
+ //full_buf += keypar.key_tuple_length;
+ full_buf += primary_file->ref_length;
+ }
}
if (strategy == index_strategy)
@@ -1039,7 +1089,7 @@ int Mrr_ordered_index_reader::compare_keys_reverse(void* arg, uchar* key1,
bool DsMrr_impl::setup_buffer_sharing(uint key_size_in_keybuf,
key_part_map key_tuple_map)
{
- uint key_buff_elem_size= key_size_in_keybuf +
+ long key_buff_elem_size= key_size_in_keybuf +
(int)is_mrr_assoc * sizeof(void*);
KEY *key_info= &primary_file->get_table()->key_info[keyno];
@@ -1186,6 +1236,7 @@ int Key_value_records_iterator::init(Mrr_ordered_index_reader *owner_arg)
move_to_next_key_value();
return res;
}
+ owner->have_saved_rowid= FALSE;
get_next_row= FALSE;
return 0;
}
@@ -1212,6 +1263,7 @@ int Key_value_records_iterator::get_next()
return res;
}
identical_key_it.init(owner->key_buffer);
+ owner->have_saved_rowid= FALSE;
get_next_row= FALSE;
}
diff --git a/sql/multi_range_read.h b/sql/multi_range_read.h
index f6e84e78e4d..a22ef0fef61 100644
--- a/sql/multi_range_read.h
+++ b/sql/multi_range_read.h
@@ -211,8 +211,11 @@ public:
/* Get pointer to place where every get_next() call will put rowid */
virtual uchar *get_rowid_ptr() = 0;
/* Get the rowid (call this after get_next() call) */
- void position();
+ virtual void position();
virtual bool skip_record(char *range_id, uchar *rowid) = 0;
+
+ virtual void interrupt_read() {}
+ virtual void resume_read() {}
};
@@ -269,6 +272,10 @@ public:
mrr_funcs.skip_index_tuple(mrr_iter, range_info));
}
+ void set_temp_space(uchar *space);
+ void interrupt_read();
+ void resume_read();
+ void position();
private:
Key_value_records_iterator kv_it;
@@ -300,6 +307,11 @@ private:
/* TRUE == reached eof when enumerating ranges */
bool source_exhausted;
+
+ /* TODO */
+ /*uchar *saved_key_tuple;*/
+ uchar *saved_rowid;
+ bool have_saved_rowid;
static int compare_keys(void* arg, uchar* key1, uchar* key2);
static int compare_keys_reverse(void* arg, uchar* key1, uchar* key2);