diff options
Diffstat (limited to 'sql/sql_select.cc')
-rw-r--r-- | sql/sql_select.cc | 46 |
1 files changed, 35 insertions, 11 deletions
diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 24d2a21147c..11378ac0d11 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -195,7 +195,8 @@ static bool test_if_cheaper_ordering(const JOIN_TAB *tab, ha_rows select_limit, int *new_key, int *new_key_direction, ha_rows *new_select_limit, - uint *new_used_key_parts= NULL); + uint *new_used_key_parts= NULL, + uint *saved_best_key_parts= NULL); static bool test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order, ha_rows select_limit, bool no_changes, key_map *map); @@ -592,13 +593,21 @@ JOIN::prepare(Item ***rref_pointer_array, { Item *item= *ord->item; /* - Disregard sort order if there's only "{VAR}CHAR(0) NOT NULL" fields - there. Such fields don't contain any data to sort. + Disregard sort order if there's only + zero length NOT NULL fields (e.g. {VAR}CHAR(0) NOT NULL") or + zero length NOT NULL string functions there. + Such tuples don't contain any data to sort. */ if (!real_order && - (item->type() != Item::FIELD_ITEM || - ((Item_field *) item)->field->maybe_null() || - ((Item_field *) item)->field->sort_length())) + /* Not a zero length NOT NULL field */ + ((item->type() != Item::FIELD_ITEM || + ((Item_field *) item)->field->maybe_null() || + ((Item_field *) item)->field->sort_length()) && + /* AND not a zero length NOT NULL string function. */ + (item->type() != Item::FUNC_ITEM || + item->maybe_null || + item->result_type() != STRING_RESULT || + item->max_length))) real_order= TRUE; if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM) @@ -1152,7 +1161,7 @@ JOIN::optimize() elements may be lost during further having condition transformation in JOIN::exec. */ - if (having && const_table_map) + if (having && const_table_map && !having->with_sum_func) { having->update_used_tables(); having= remove_eq_conds(thd, having, &having_value); @@ -7356,7 +7365,8 @@ remove_const(JOIN *join,ORDER *first_order, COND *cond, *simple_order=0; // Must do a temp table to sort else if (!(order_tables & not_const_tables)) { - if (order->item[0]->with_subselect) + if (order->item[0]->with_subselect && + !(join->select_lex->options & SELECT_DESCRIBE)) order->item[0]->val_str(&order->item[0]->str_value); DBUG_PRINT("info",("removing: %s", order->item[0]->full_name())); continue; // skip const item @@ -13694,6 +13704,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, } { uint best_key_parts= 0; + uint saved_best_key_parts= 0; int best_key_direction= 0; int best_key= -1; JOIN *join= tab->join; @@ -13702,7 +13713,8 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, test_if_cheaper_ordering(tab, order, table, usable_keys, ref_key, select_limit, &best_key, &best_key_direction, - &select_limit, &best_key_parts); + &select_limit, &best_key_parts, + &saved_best_key_parts); /* filesort() and join cache are usually faster than reading in @@ -13781,8 +13793,15 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, */ } } - used_key_parts= best_key_parts; order_direction= best_key_direction; + /* + saved_best_key_parts is actual number of used keyparts found by the + test_if_order_by_key function. It could differ from keyinfo->key_parts, + thus we have to restore it in case of desc order as it affects + QUICK_SELECT_DESC behaviour. + */ + used_key_parts= (order_direction == -1) ? + saved_best_key_parts : best_key_parts; } else DBUG_RETURN(0); @@ -17374,6 +17393,8 @@ void JOIN::cache_const_exprs() @param [out] new_used_key_parts NULL by default, otherwise return number of new_key prefix columns if success or undefined if the function fails + @param [out] saved_best_key_parts NULL by default, otherwise preserve the + value for further use in QUICK_SELECT_DESC @note This function takes into account table->quick_condition_rows statistic @@ -17388,7 +17409,8 @@ test_if_cheaper_ordering(const JOIN_TAB *tab, ORDER *order, TABLE *table, key_map usable_keys, int ref_key, ha_rows select_limit, int *new_key, int *new_key_direction, - ha_rows *new_select_limit, uint *new_used_key_parts) + ha_rows *new_select_limit, uint *new_used_key_parts, + uint *saved_best_key_parts) { DBUG_ENTER("test_if_cheaper_ordering"); /* @@ -17567,6 +17589,8 @@ test_if_cheaper_ordering(const JOIN_TAB *tab, ORDER *order, TABLE *table, { best_key= nr; best_key_parts= keyinfo->key_parts; + if (saved_best_key_parts) + *saved_best_key_parts= used_key_parts; best_records= quick_records; is_best_covering= is_covering; best_key_direction= direction; |