=== modified file 'mysql-test/r/innodb_mysql_lock2.result' --- mysql-test/r/innodb_mysql_lock2.result 2010-07-19 16:09:51 +0000 +++ mysql-test/r/innodb_mysql_lock2.result 2011-03-16 07:20:41 +0000 @@ -605,11 +605,11 @@ # Acquire SR metadata lock on t1. select * from t1; i +4 1 +5 2 3 -4 -5 # Switching to connection 'con1'. # Sending: alter table t1 rebuild partition p0; === modified file 'mysql-test/r/partition.result' --- mysql-test/r/partition.result 2011-03-11 09:58:45 +0000 +++ mysql-test/r/partition.result 2011-03-16 07:20:41 +0000 @@ -1776,9 +1776,9 @@ (18446744073709551613), (18446744073709551612); select * from t1; a +18446744073709551614 18446744073709551612 18446744073709551613 -18446744073709551614 18446744073709551615 select * from t1 where a = 18446744073709551615; a @@ -1786,9 +1786,9 @@ delete from t1 where a = 18446744073709551615; select * from t1; a +18446744073709551614 18446744073709551612 18446744073709551613 -18446744073709551614 drop table t1; CREATE TABLE t1 ( num int(11) NOT NULL, cs int(11) NOT NULL) === modified file 'sql/opt_range.cc' --- sql/opt_range.cc 2011-03-03 22:26:19 +0000 +++ sql/opt_range.cc 2011-03-16 08:03:51 +0000 @@ -1179,7 +1179,9 @@ QUICK_RANGE_SELECT::QUICK_RANGE_SELECT(THD *thd, TABLE *table, uint key_nr, bool no_alloc, MEM_ROOT *parent_alloc, bool *create_error) - :free_file(0),cur_range(NULL),last_range(0),dont_free(0) + :free_file(0),cur_range(NULL),last_range(0), + mrr_flags(0),mrr_buf_size(0),mrr_buf_desc(NULL), + dont_free(0) { my_bitmap_map *bitmap; DBUG_ENTER("QUICK_RANGE_SELECT::QUICK_RANGE_SELECT"); @@ -1192,7 +1194,6 @@ /* 'thd' is not accessible in QUICK_RANGE_SELECT::reset(). */ mrr_buf_size= thd->variables.read_rnd_buff_size; - mrr_buf_desc= NULL; if (!no_alloc && !parent_alloc) { @@ -1220,17 +1221,12 @@ } -void QUICK_RANGE_SELECT::need_sorted_output() +void QUICK_RANGE_SELECT::need_sorted_output(bool sort) { - if (!(mrr_flags & HA_MRR_SORTED)) - { - /* - Native implementation can't produce sorted output. We'll have to - switch to default - */ - mrr_flags |= HA_MRR_USE_DEFAULT_IMPL; - } - mrr_flags |= HA_MRR_SORTED; + if (sort) + mrr_flags |= HA_MRR_SORTED; + else + mrr_flags &= ~HA_MRR_SORTED; } @@ -8714,7 +8710,8 @@ { if (in_ror_merged_scan) head->column_bitmaps_set_no_signal(&column_bitmap, &column_bitmap); - if ((error= file->ha_index_init(index,1))) + bool sorted= (mrr_flags & HA_MRR_SORTED); + if ((error= file->ha_index_init(index,sorted))) DBUG_RETURN(error); } @@ -8989,10 +8986,11 @@ last_range->make_min_endpoint(&start_key, prefix_length, keypart_map); last_range->make_max_endpoint(&end_key, prefix_length, keypart_map); + bool sorted= (mrr_flags & HA_MRR_SORTED); result= file->read_range_first(last_range->min_keypart_map ? &start_key : 0, last_range->max_keypart_map ? &end_key : 0, test(last_range->flag & EQ_RANGE), - TRUE); + sorted); if (last_range->flag == (UNIQUE_RANGE | EQ_RANGE)) last_range= 0; // Stop searching @@ -9104,6 +9102,7 @@ */ mrr_buf_desc= NULL; mrr_flags |= HA_MRR_USE_DEFAULT_IMPL; + mrr_flags |= HA_MRR_SORTED; // 'sorted' as internals use index_last/_prev mrr_buf_size= 0; @@ -10584,12 +10583,19 @@ if (quick_prefix_records == HA_POS_ERROR) quick->quick_prefix_select= NULL; /* Can't construct a quick select. */ else + { /* Make a QUICK_RANGE_SELECT to be used for group prefix retrieval. */ quick->quick_prefix_select= get_quick_select(param, param_idx, index_tree, - HA_MRR_USE_DEFAULT_IMPL, 0, + HA_MRR_USE_DEFAULT_IMPL | HA_MRR_SORTED, + 0, &quick->alloc); - + if (!quick->quick_prefix_select) + { + delete quick; + DBUG_RETURN(NULL); + } + } /* Extract the SEL_ARG subtree that contains only ranges for the MIN/MAX attribute, and create an array of QUICK_RANGES to be used by the @@ -10985,7 +10991,11 @@ DBUG_ENTER("QUICK_GROUP_MIN_MAX_SELECT::reset"); head->set_keyread(TRUE); /* We need only the key attributes */ - if ((result= file->ha_index_init(index,1))) + + // Request ordered index access as usage of ::index_last(), ::index_first() + // within QUICK_GROUP_MIN_MAX_SELECT depends on it. + bool sorted= true; + if ((result= file->ha_index_init(index,sorted))) DBUG_RETURN(result); if (quick_prefix_select && quick_prefix_select->reset()) DBUG_RETURN(1); === modified file 'sql/opt_range.h' --- sql/opt_range.h 2010-12-17 12:58:04 +0000 +++ sql/opt_range.h 2011-03-16 07:20:41 +0000 @@ -285,11 +285,15 @@ virtual bool clustered_pk_range() { return false; } /* - Request that this quick select produces sorted output. Not all quick - selects can do it, the caller is responsible for calling this function - only for those quick selects that can. + Request that this quick select produces sorted output if 'sort==true'. + Not all quick selects can provide sorted output, the caller is responsible + for calling this function only for those quick selects that can. + Caller is allowed to later cancel its sorted request by setting + 'sort==false'. However, the implementation is allowed to provide sorted + output even in this case if benificial, or required by implementation + internals. */ - virtual void need_sorted_output() = 0; + virtual void need_sorted_output(bool sort) = 0; enum { QS_TYPE_RANGE = 0, QS_TYPE_INDEX_MERGE = 1, @@ -399,7 +403,7 @@ /* Quick select that does a range scan on a single key. The records are - returned in key order. + returned in key order if ::need_sorted_output(true) has been called. */ class QUICK_RANGE_SELECT : public QUICK_SELECT_I { @@ -465,7 +469,7 @@ MEM_ROOT *parent_alloc, bool *create_error); ~QUICK_RANGE_SELECT(); - void need_sorted_output(); + void need_sorted_output(bool sort); int init(); int reset(void); int get_next(); @@ -569,7 +573,7 @@ ~QUICK_INDEX_MERGE_SELECT(); int init(); - void need_sorted_output() { DBUG_ASSERT(0); /* Can't do it */ } + void need_sorted_output(bool sort) { DBUG_ASSERT(!sort); /* Can't do it */ } int reset(void); int get_next(); bool reverse_sorted() { return false; } @@ -647,7 +651,7 @@ ~QUICK_ROR_INTERSECT_SELECT(); int init(); - void need_sorted_output() { DBUG_ASSERT(0); /* Can't do it */ } + void need_sorted_output(bool sort) { DBUG_ASSERT(!sort); /* Can't do it */ } int reset(void); int get_next(); bool reverse_sorted() { return false; } @@ -718,7 +722,7 @@ ~QUICK_ROR_UNION_SELECT(); int init(); - void need_sorted_output() { DBUG_ASSERT(0); /* Can't do it */ } + void need_sorted_output(bool sort) { DBUG_ASSERT(!sort); /* Can't do it */ } int reset(void); int get_next(); bool reverse_sorted() { return false; } @@ -860,7 +864,7 @@ void adjust_prefix_ranges(); bool alloc_buffers(); int init(); - void need_sorted_output() { /* always do it */ } + void need_sorted_output(bool sort) { /* always do it */ } int reset(); int get_next(); bool reverse_sorted() { return false; } === modified file 'sql/sql_select.cc' --- sql/sql_select.cc 2011-03-11 09:35:38 +0000 +++ sql/sql_select.cc 2011-03-16 08:24:41 +0000 @@ -1467,7 +1467,7 @@ output is not supported. */ if (tab->select && tab->select->quick) - tab->select->quick->need_sorted_output(); + tab->select->quick->need_sorted_output(true); /* Calculate key length */ keylen= 0; @@ -2739,6 +2739,23 @@ /** + There may be a pending 'sorted' request on the specified + 'join_tab' which we now has decided we can ignore. +*/ +static void +disable_sorted_access(JOIN_TAB* join_tab) +{ + DBUG_ENTER("disable_sorted_access"); + join_tab->sorted= 0; + if (join_tab->select && join_tab->select->quick) + { + join_tab->select->quick->need_sorted_output(false); + } + DBUG_VOID_RETURN; +} + + +/** Exec select. @todo @@ -2917,7 +2934,7 @@ curr_join->const_tables != curr_join->tables && curr_join->best_positions[curr_join->const_tables].sj_strategy != SJ_OPT_LOOSE_SCAN) - curr_join->join_tab[curr_join->const_tables].sorted= 0; + disable_sorted_access(&curr_join->join_tab[curr_join->const_tables]); if ((tmp_error= do_select(curr_join, (List *) 0, curr_tmp_table, 0))) { error= tmp_error; @@ -3083,7 +3100,7 @@ curr_join->group_list= 0; if (!curr_join->sort_and_group && curr_join->const_tables != curr_join->tables) - curr_join->join_tab[curr_join->const_tables].sorted= 0; + disable_sorted_access(&curr_join->join_tab[curr_join->const_tables]); if (setup_sum_funcs(curr_join->thd, curr_join->sum_funcs) || (tmp_error= do_select(curr_join, (List *) 0, curr_tmp_table, 0))) @@ -11165,7 +11182,7 @@ { uint i, jcl; bool statistics= test(!(join->select_options & SELECT_DESCRIBE)); - bool sorted= 1; + bool sorted= (join->order || join->group_list); uint first_sjm_table= MAX_TABLES; uint last_sjm_table= MAX_TABLES; DBUG_ENTER("make_join_readinfo"); @@ -18163,6 +18180,7 @@ int error; if (!table->file->inited) { + DBUG_ASSERT(!tab->sorted); // Don't expect sort req. for single row. table->file->ha_index_init(table_ref->key, tab->sorted); } @@ -18472,7 +18490,7 @@ tab->read_record.index=tab->index; tab->read_record.record=table->record[0]; if (!table->file->inited) - table->file->ha_index_init(tab->index, 1); + table->file->ha_index_init(tab->index, tab->sorted); if ((error= tab->table->file->ha_index_last(tab->table->record[0]))) return report_error(table, error); return 0; @@ -18496,7 +18514,7 @@ TABLE *table= tab->table; if (!table->file->inited) - table->file->ha_index_init(tab->ref.key, 1); + table->file->ha_index_init(tab->ref.key, tab->sorted); table->file->ft_init(); if ((error= table->file->ft_read(table->record[0]))) @@ -20274,7 +20292,7 @@ } } else if (select && select->quick) - select->quick->need_sorted_output(); + select->quick->need_sorted_output(true); } // QEP has been modified @@ -23181,9 +23199,22 @@ if (quick_type == QUICK_SELECT_I::QS_TYPE_RANGE && !(((QUICK_RANGE_SELECT*)(tab->select->quick))->mrr_flags & - HA_MRR_USE_DEFAULT_IMPL)) + (HA_MRR_USE_DEFAULT_IMPL | HA_MRR_SORTED))) { - extra.append(STRING_WITH_LEN("; Using MRR")); + /* + During normal execution of a query, multi_range_read_init() is + called to initialize MRR. If HA_MRR_SORTED is set at this point, + multi_range_read_init() for any native MRR implementation will + revert to default MRR because they cannot produce sorted output + currently. + Calling multi_range_read_init() can potentially be costly, so it + is not done when executing an EXPLAIN. We therefore make the + assumption that HA_MRR_SORTED means no MRR. If some MRR native + implementation will support sorted output in the future, a + function "bool mrr_supports_sorted()" should be added in the + handler. + */ + extra.append(STRING_WITH_LEN("; Using MRR")); } if (need_tmp_table) {