=== modified file 'mysql-test/r/innodb_ext_key.result'
--- mysql-test/r/innodb_ext_key.result	2014-03-05 22:20:10 +0000
+++ mysql-test/r/innodb_ext_key.result	2014-07-18 11:03:00 +0000
@@ -1002,7 +1002,7 @@ insert into t2 (b) values (null), (null)
 set optimizer_switch='extended_keys=on';
 explain select a from t1 where b is null order by a desc limit 2;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	t1	ref	b	b	9	const	2	Using where; Using filesort
+1	SIMPLE	t1	index	b	PRIMARY	8	NULL	3	Using where
 select a from t1 where b is null order by a desc limit 2;
 a
 3

=== modified file 'sql/opt_range.cc'
--- sql/opt_range.cc	2014-06-05 22:07:27 +0000
+++ sql/opt_range.cc	2014-07-18 13:17:51 +0000
@@ -920,6 +920,7 @@ QUICK_RANGE_SELECT *get_quick_select(PAR
                                      SEL_ARG *key_tree, uint mrr_flags, 
                                      uint mrr_buf_size, MEM_ROOT *alloc);
 static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree,
+                                       key_map keys_to_make_select_from,
                                        bool index_read_must_be_used,
                                        bool update_tbl_stats,
                                        double read_time);
@@ -2939,6 +2940,7 @@ static int fill_used_fields_bitmap(PARAM
 */
 
 int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
+                                  key_map keys_to_make_select_from,
 				  table_map prev_tables,
 				  ha_rows limit, bool force_quick_range, 
                                   bool ordered_output)
@@ -2974,6 +2976,8 @@ int SQL_SELECT::test_quick_select(THD *t
   DBUG_PRINT("info",("Time to scan table: %g", read_time));
 
   keys_to_use.intersect(head->keys_in_use_for_query);
+  keys_to_make_select_from.intersect(head->keys_in_use_for_query);
+
   if (!keys_to_use.is_clear_all())
   {
     uchar buff[STACK_BUFF_ALLOC];
@@ -3120,7 +3124,9 @@ int SQL_SELECT::test_quick_select(THD *t
       remove_nonrange_trees(&param, tree);
 
       /* Get best 'range' plan and prepare data for making other plans */
-      if ((range_trp= get_key_scans_params(&param, tree, FALSE, TRUE,
+      if ((range_trp= get_key_scans_params(&param, tree,
+                                           keys_to_make_select_from,
+                                           FALSE, TRUE,
                                            best_read_time)))
       {
         best_trp= range_trp;
@@ -5148,7 +5154,9 @@ TABLE_READ_PLAN *get_best_disjunct_quick
   {
     DBUG_EXECUTE("info", print_sel_tree(param, *ptree, &(*ptree)->keys_map,
                                         "tree in SEL_IMERGE"););
-    if (!(*cur_child= get_key_scans_params(param, *ptree, TRUE, FALSE, read_time)))
+    key_map dummy;
+    dummy.set_all();
+    if (!(*cur_child= get_key_scans_params(param, *ptree, dummy, TRUE, FALSE, read_time)))
     {
       /*
         One of index scans in this index_merge is more expensive than entire
@@ -5469,7 +5477,9 @@ TABLE_READ_PLAN *merge_same_index_scans(
       2. the functions that estimate the cost of a range scan and an
          index merge retrievals are not well calibrated
     */
-    trp= get_key_scans_params(param, *imerge->trees, FALSE, TRUE,
+    key_map dummy;
+    dummy.set_all();
+    trp= get_key_scans_params(param, *imerge->trees, dummy, FALSE, TRUE,
                               read_time);
   }
 
@@ -7192,6 +7202,7 @@ TRP_ROR_INTERSECT *get_best_covering_ror
 */
 
 static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree,
+                                       key_map keys_to_make_select_from,
                                        bool index_read_must_be_used, 
                                        bool update_tbl_stats,
                                        double read_time)
@@ -7233,6 +7244,8 @@ static TRP_RANGE *get_key_scans_params(P
       if ((*key)->type == SEL_ARG::MAYBE_KEY ||
           (*key)->maybe_flag)
         param->needed_reg->set_bit(keynr);
+      if (!keys_to_make_select_from.is_set(keynr))
+        continue;
 
       bool read_index_only= index_read_must_be_used ? TRUE :
                             (bool) param->table->covering_keys.is_set(keynr);
@@ -10610,6 +10623,7 @@ ha_rows check_quick_select(PARAM *param,
       param->table->quick_condition_rows=
         MY_MIN(param->table->quick_condition_rows, rows);
       param->table->quick_rows[keynr]= rows;
+      param->table->quick_costs[keynr]= cost->total_cost();
     }
   }
   /* Figure out if the key scan is ROR (returns rows in ROWID order) or not */

=== modified file 'sql/opt_range.h'
--- sql/opt_range.h	2014-02-19 10:05:15 +0000
+++ sql/opt_range.h	2014-07-18 13:13:23 +0000
@@ -994,7 +994,7 @@ class SQL_SELECT :public Sql_alloc {
   {
     key_map tmp;
     tmp.set_all();
-    return test_quick_select(thd, tmp, 0, limit, force_quick_range, FALSE) < 0;
+    return test_quick_select(thd, tmp, tmp, 0, limit, force_quick_range, FALSE) < 0;
   }
   /* 
     RETURN
@@ -1009,7 +1009,9 @@ class SQL_SELECT :public Sql_alloc {
       rc= -1;
     return rc;
   }
-  int test_quick_select(THD *thd, key_map keys, table_map prev_tables,
+  int test_quick_select(THD *thd, key_map keys, 
+                        key_map keys_to_make_select_from,
+                        table_map prev_tables,
 			ha_rows limit, bool force_quick_range, 
                         bool ordered_output);
 };

=== modified file 'sql/sql_select.cc'
--- sql/sql_select.cc	2014-06-09 18:18:53 +0000
+++ sql/sql_select.cc	2014-07-18 13:22:06 +0000
@@ -66,6 +66,7 @@ const char *join_type_str[]={ "UNKNOWN",
                               "hash_index", "hash_index_merge" };
 
 struct st_sargable_param;
+FILE *out1;
 
 static void optimize_keyuse(JOIN *join, DYNAMIC_ARRAY *keyuse_array);
 static bool make_join_statistics(JOIN *join, List<TABLE_LIST> &leaves, 
@@ -3337,7 +3338,7 @@ static ha_rows get_quick_record_count(TH
   {
     select->head=table;
     table->reginfo.impossible_range=0;
-    if ((error= select->test_quick_select(thd, *(key_map *)keys,(table_map) 0,
+    if ((error= select->test_quick_select(thd, *(key_map *)keys,*(key_map *)keys,(table_map) 0,
                                           limit, 0, FALSE)) == 1)
       DBUG_RETURN(select->quick->records);
     if (error == -1)
@@ -9620,7 +9654,7 @@ make_join_select(JOIN *join,SQL_SELECT *
 	    if (sel->cond && !sel->cond->fixed)
 	      sel->cond->quick_fix_field();
 
-	    if (sel->test_quick_select(thd, tab->keys,
+	    if (sel->test_quick_select(thd, tab->keys, tab->keys,
 				       ((used_tables & ~ current_map) |
                                         OUTER_REF_TABLE_BIT),
 				       (join->select_options &
@@ -9635,7 +9669,7 @@ make_join_select(JOIN *join,SQL_SELECT *
 	      */
               sel->cond=orig_cond;
               if (!*tab->on_expr_ref ||
-                  sel->test_quick_select(thd, tab->keys,
+                  sel->test_quick_select(thd, tab->keys, tab->keys,
                                          used_tables & ~ current_map,
                                          (join->select_options &
                                           OPTION_FOUND_ROWS ?
@@ -18458,7 +18492,7 @@ test_if_quick_select(JOIN_TAB *tab)
 
   delete tab->select->quick;
   tab->select->quick=0;
-  return tab->select->test_quick_select(tab->join->thd, tab->keys,
+  return tab->select->test_quick_select(tab->join->thd, tab->keys, tab->keys,
 					(table_map) 0, HA_POS_ERROR, 0,
                                         FALSE);
 }
@@ -20128,7 +20162,13 @@ test_if_skip_sort_order(JOIN_TAB *tab,OR
           save_cond= select->cond;
           if (select->pre_idx_push_select_cond)
             select->cond= select->pre_idx_push_select_cond;
-          res= select->test_quick_select(tab->join->thd, new_ref_key_map, 0,
+          key_map keys_for_analysis;
+          if (tab)
+            keys_for_analysis= tab->const_keys;
+          else
+            keys_for_analysis= table->quick_keys; //TODO where are the original
+          res= select->test_quick_select(tab->join->thd, 
+                                         keys_for_analysis, new_ref_key_map, 0,
                                          (tab->join->select_options &
                                           OPTION_FOUND_ROWS) ?
                                          HA_POS_ERROR :
@@ -20187,7 +20227,13 @@ test_if_skip_sort_order(JOIN_TAB *tab,OR
       map.clear_all();       // Force the creation of quick select
       map.set_bit(best_key); // only best_key.
       select->quick= 0;
-      select->test_quick_select(join->thd, map, 0,
+      key_map keys_for_analysis;
+      if (tab)
+        keys_for_analysis= tab->const_keys;
+      else
+        keys_for_analysis= table->quick_keys; //TODO where are the original
+
+      select->test_quick_select(join->thd, keys_for_analysis, map, 0,
                                 join->select_options & OPTION_FOUND_ROWS ?
                                 HA_POS_ERROR :
                                 join->unit->select_limit_cnt,
@@ -24522,14 +24568,11 @@ JOIN::reoptimize(Item *added_where, tabl
   if (sort_and_filter_keyuse(thd, &keyuse, true))
     return REOPT_ERROR;
   optimize_keyuse(this, &keyuse);
-
   if (optimize_semijoin_nests(this, join_tables))
     return REOPT_ERROR;
-
   /* Re-run the join optimizer to compute a new query plan. */
   if (choose_plan(this, join_tables))
     return REOPT_ERROR;
-
   return REOPT_NEW_PLAN;
 }
 
@@ -24570,6 +24613,70 @@ void JOIN::cache_const_exprs()
 }
 
 
+/*
+  Get a cost of reading rows_limit rows through index keynr.
+
+  If there is a quick select, we try to use it.
+  If the quick select looks like ref(const), we try to use it too.
+
+*/
+
+static bool get_range_limit_read_cost(const JOIN_TAB *tab, 
+                                      const TABLE *table, 
+                                      uint keynr, 
+                                      ha_rows rows_limit,
+                                      double *read_time)
+{
+  bool res= false;
+  /* 
+    We need to adjust the estiamtes if we had a quick select (or ref(const)) on
+    index keynr.
+    (the check for tab->table is for handling single-table UPDATE/DELETEs)
+  */
+  if (table->quick_keys.is_set(keynr))
+  {
+    double quick_rows= table->quick_rows[keynr];
+    double tmp;
+    if (tab && table->quick_n_ranges[keynr] == 1)
+    {
+      /*
+        - We've had a join optimizer (tab!=NULL) (we don't have one when d
+           UPDATE/DELETE
+        - AND range access is actually ref(const). Ref access uses different
+          cost formulas than range (this is awful, yes). To compare
+          apples-to-apples, we reuse the cost formula from best_access_path:
+      */
+
+      /* Limit the number of matched rows */
+      tmp= quick_rows;
+      set_if_smaller(tmp, (double) tab->join->thd->variables.max_seeks_for_key);
+      if (table->covering_keys.is_set(keynr))
+        tmp= table->file->keyread_time(keynr, 1, (ha_rows) tmp);
+      else
+        tmp= table->file->read_time(keynr, 1,
+                                    (ha_rows) MY_MIN(tmp,tab->worst_seeks));
+    }
+    else
+      tmp= table->quick_costs[keynr];
+
+    if (quick_rows > rows_limit)
+    {
+      /*
+        LIMIT clause specifies that we will need to read fewer records than
+        quick select will return. Assume that quick select's cost is
+        proportional to the number of records we need to return (e.g. if we 
+        only need 1/3rd of records, it will cost us 1/3rd of quick select's
+        read time)
+      */
+      tmp *= rows_limit / quick_rows;
+    }
+    *read_time= tmp;
+    res= true;
+  }
+  return res;
+}
+
+
 /**
   Find a cheaper access key than a given @a key
 
@@ -24662,6 +24769,11 @@ test_if_cheaper_ordering(const JOIN_TAB
   }
   else
     read_time= table->file->scan_time();
+  
+  /*
+    TODO: add cost of sorting here.
+  */
+  read_time += COST_EPS;
 
   /*
     Calculate the selectivity of the ref_key for REF_ACCESS. For
@@ -24819,8 +24931,12 @@ test_if_cheaper_ordering(const JOIN_TAB
           to calculate the cost of accessing data rows for one 
           index entry.
         */
-        index_scan_time= select_limit/rec_per_key *
-                         MY_MIN(rec_per_key, table->file->scan_time());
+        if (!get_range_limit_read_cost(tab, table, nr, select_limit, 
+                                       &index_scan_time))
+        {
+          index_scan_time= select_limit/rec_per_key *
+                           MY_MIN(rec_per_key, table->file->scan_time());
+        }
         if ((ref_key < 0 && (group || table->force_index || is_covering)) ||
             index_scan_time < read_time)
         {

=== modified file 'sql/table.h'
--- sql/table.h	2014-06-05 22:07:27 +0000
+++ sql/table.h	2014-07-18 11:03:01 +0000
@@ -1113,6 +1113,7 @@ struct TABLE
     and max #key parts that range access would use.
   */
   ha_rows	quick_rows[MAX_KEY];
+  double 	quick_costs[MAX_KEY];
 
   /* 
     Bitmaps of key parts that =const for the duration of join execution. If

