From 5ebff8ab788923cfcc25862d6c9e11ea20801fa0 Mon Sep 17 00:00:00 2001 From: Sergey Petrunya Date: Tue, 13 Sep 2011 23:45:02 +0400 Subject: [PATCH] BUG#730133: Wrong result with jkl = 7, BKA, ICP in maria-5.3 + compound index - Mrr_ordered_index_reader::interrupt_read() and resume_read() should save/restore not just index lookup tuple, but entire index tuple. Key parts that are not used for index lookup can be still used in pushed index condition. Failure to save/restore will cause the index condition to be evaluated over the wrong values. --- mysql-test/r/myisam_mrr.result | 41 +++++++++++++++++++++++++++++++- mysql-test/t/myisam_mrr.test | 43 +++++++++++++++++++++++++++++++++- sql/item.cc | 15 ++++++++++++ sql/multi_range_read.cc | 15 ++++++------ 4 files changed, 105 insertions(+), 9 deletions(-) diff --git a/mysql-test/r/myisam_mrr.result b/mysql-test/r/myisam_mrr.result index d4327a43d6a..d6af5cd3e49 100644 --- a/mysql-test/r/myisam_mrr.result +++ b/mysql-test/r/myisam_mrr.result @@ -509,5 +509,44 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE table3 ref PRIMARY,col_varchar_key col_varchar_key 3 test.table2.col_varchar_key 3 Using where; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan set join_cache_level= @save_join_cache_level; set join_buffer_size= @save_join_buffer_size; -set optimizer_switch= @myisam_mrr_tmp; drop table t1; +# +# BUG#730133: Wrong result with jkl = 7, BKA, ICP in maria-5.3 + compound index +# +set @tmp_730133_jcl= @@join_cache_level; +set join_cache_level = 7; +set @tmp_730133_os= @@optimizer_switch; +set optimizer_switch= 'join_cache_hashed=off,join_cache_bka=on,index_condition_pushdown=on,optimize_join_buffer_size=on'; +CREATE TABLE t1 (f1 int, f2 int, f3 int, f4 int, f5 int, KEY (f4,f3)); +INSERT IGNORE INTO t1 VALUES ('2','9','5','0','0'),('4','7','0','0','0'), +('6','97','190','0','0'),('7','3','6','0','0'),('11','101','186','0','0'), +('14','194','226','0','0'),('15','148','133','0','0'), +('16','9','6','0','0'),('17','9','3','0','0'),('18','1','8','0','0'), +('19','1','5','0','0'),('20','5','7','0','0'); +explain +SELECT COUNT(alias2.f2) +FROM +t1 STRAIGHT_JOIN +t1 AS alias3 STRAIGHT_JOIN +t1 AS alias2 FORCE KEY (f4) +WHERE +alias2.f4=alias3.f5 AND +alias2.f3 > alias3.f1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index NULL f4 10 NULL 12 Using index +1 SIMPLE alias3 ALL NULL NULL NULL NULL 12 Using where; Using join buffer (flat, BNL join) +1 SIMPLE alias2 ref f4 f4 5 test.alias3.f5 2 Using index condition(BKA); Using join buffer (incremental, BKA join); Key-ordered Rowid-ordered scan +SELECT COUNT(alias2.f2) +FROM +t1 STRAIGHT_JOIN +t1 AS alias3 STRAIGHT_JOIN +t1 AS alias2 FORCE KEY (f4) +WHERE +alias2.f4=alias3.f5 AND +alias2.f3 > alias3.f1; +COUNT(alias2.f2) +768 +set @@join_cache_level= @tmp_730133_jcl; +set @@optimizer_switch= @tmp_730133_os; +drop table t1; +set optimizer_switch= @myisam_mrr_tmp; diff --git a/mysql-test/t/myisam_mrr.test b/mysql-test/t/myisam_mrr.test index 9c4c7be4fa2..86024da6276 100644 --- a/mysql-test/t/myisam_mrr.test +++ b/mysql-test/t/myisam_mrr.test @@ -218,6 +218,47 @@ where set join_cache_level= @save_join_cache_level; set join_buffer_size= @save_join_buffer_size; -set optimizer_switch= @myisam_mrr_tmp; drop table t1; + +--echo # +--echo # BUG#730133: Wrong result with jkl = 7, BKA, ICP in maria-5.3 + compound index +--echo # +set @tmp_730133_jcl= @@join_cache_level; +set join_cache_level = 7; + +set @tmp_730133_os= @@optimizer_switch; +set optimizer_switch= 'join_cache_hashed=off,join_cache_bka=on,index_condition_pushdown=on,optimize_join_buffer_size=on'; + +CREATE TABLE t1 (f1 int, f2 int, f3 int, f4 int, f5 int, KEY (f4,f3)); +INSERT IGNORE INTO t1 VALUES ('2','9','5','0','0'),('4','7','0','0','0'), + ('6','97','190','0','0'),('7','3','6','0','0'),('11','101','186','0','0'), + ('14','194','226','0','0'),('15','148','133','0','0'), + ('16','9','6','0','0'),('17','9','3','0','0'),('18','1','8','0','0'), + ('19','1','5','0','0'),('20','5','7','0','0'); + +explain +SELECT COUNT(alias2.f2) +FROM + t1 STRAIGHT_JOIN + t1 AS alias3 STRAIGHT_JOIN + t1 AS alias2 FORCE KEY (f4) +WHERE + alias2.f4=alias3.f5 AND + alias2.f3 > alias3.f1; + +SELECT COUNT(alias2.f2) +FROM + t1 STRAIGHT_JOIN + t1 AS alias3 STRAIGHT_JOIN + t1 AS alias2 FORCE KEY (f4) +WHERE + alias2.f4=alias3.f5 AND + alias2.f3 > alias3.f1; + +set @@join_cache_level= @tmp_730133_jcl; +set @@optimizer_switch= @tmp_730133_os; +drop table t1; + +## This must be last line in the file: +set optimizer_switch= @myisam_mrr_tmp; diff --git a/sql/item.cc b/sql/item.cc index d0992a379e0..02263106fe8 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -9124,7 +9124,22 @@ table_map Item_ref_null_helper::used_tables() const } +/* Debugger help function */ +static char dbug_item_print_buf[256]; +const char *dbug_print_item(Item *item) +{ + char *buf= dbug_item_print_buf; + String str(buf, sizeof(dbug_item_print_buf), &my_charset_bin); + str.length(0); + if (!item) + return "(Item*)NULL"; + item->print(&str ,QT_ORDINARY); + if (str.c_ptr() == buf) + return buf; + else + return "Couldn't fit into buffer"; +} /***************************************************************************** ** Instantiate templates *****************************************************************************/ diff --git a/sql/multi_range_read.cc b/sql/multi_range_read.cc index f0a1987c383..08e91559fc6 100644 --- a/sql/multi_range_read.cc +++ b/sql/multi_range_read.cc @@ -424,10 +424,10 @@ void Mrr_ordered_index_reader::interrupt_read() { DBUG_ASSERT(support_scan_interruptions); TABLE *table= file->get_table(); + KEY *used_index= &table->key_info[file->active_index]; /* Save the current key value */ key_copy(saved_key_tuple, table->record[0], - &table->key_info[file->active_index], - keypar.key_tuple_length); + used_index, used_index->key_length); if (saved_primary_key) { @@ -452,9 +452,9 @@ void Mrr_ordered_index_reader::position() void Mrr_ordered_index_reader::resume_read() { TABLE *table= file->get_table(); + KEY *used_index= &table->key_info[file->active_index]; key_restore(table->record[0], saved_key_tuple, - &table->key_info[file->active_index], - keypar.key_tuple_length); + used_index, used_index->key_length); if (saved_primary_key) { key_restore(table->record[0], saved_primary_key, @@ -531,7 +531,7 @@ int Mrr_ordered_index_reader::init(handler *h_arg, RANGE_SEQ_IF *seq_funcs, mrr_funcs= *seq_funcs; source_exhausted= FALSE; if (support_scan_interruptions) - bzero(saved_key_tuple, keypar.key_tuple_length); + bzero(saved_key_tuple, key_info->key_length); have_saved_rowid= FALSE; return 0; } @@ -850,10 +850,11 @@ int DsMrr_impl::dsmrr_init(handler *h_arg, RANGE_SEQ_IF *seq_funcs, uint pk= h_idx->get_table()->s->primary_key; saved_pk_length= h_idx->get_table()->key_info[pk].key_length; } - + + KEY *used_index= &h_idx->get_table()->key_info[h_idx->active_index]; if (reader_factory.ordered_index_reader. set_interruption_temp_buffer(primary_file->ref_length, - keypar.key_tuple_length, + used_index->key_length, saved_pk_length, &full_buf, full_buf_end)) goto use_default_impl;