diff options
-rw-r--r-- | mysql-test/r/innodb_mrr.result | 84 | ||||
-rw-r--r-- | mysql-test/t/innodb_mrr.test | 87 | ||||
-rw-r--r-- | sql/multi_range_read.cc | 54 | ||||
-rw-r--r-- | sql/multi_range_read.h | 14 |
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); |