List:Commits« Previous MessageNext Message »
From:Sergei Golubchik Date:March 16 2007 7:33pm
Subject:bk commit into 5.1 tree (serg:1.2501)
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of serg. When serg does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2007-03-16 20:33:27+01:00, serg@stripped +9 -0
  Merge bk-internal.mysql.com:/home/bk/mysql-5.1
  into  janus.mylan:/usr/home/serg/Abk/mysql-5.1
  MERGE: 1.2494.1.2

  sql/mysql_priv.h@stripped, 2007-03-16 20:33:21+01:00, serg@stripped +0 -0
    Auto merged
    MERGE: 1.485.1.1

  sql/opt_range.cc@stripped, 2007-03-16 20:33:22+01:00, serg@stripped +0 -0
    Auto merged
    MERGE: 1.264.1.2

  sql/sql_acl.cc@stripped, 2007-03-16 20:33:22+01:00, serg@stripped +0 -0
    Auto merged
    MERGE: 1.228.1.4

  sql/sql_help.cc@stripped, 2007-03-16 20:33:22+01:00, serg@stripped +0 -0
    Auto merged
    MERGE: 1.54.1.2

  sql/sql_insert.cc@stripped, 2007-03-16 20:33:22+01:00, serg@stripped +0 -0
    Auto merged
    MERGE: 1.246.1.14

  sql/sql_select.cc@stripped, 2007-03-16 20:33:22+01:00, serg@stripped +0 -0
    Auto merged
    MERGE: 1.492.1.14

  sql/table.cc@stripped, 2007-03-16 20:33:22+01:00, serg@stripped +0 -0
    Auto merged
    MERGE: 1.275.1.7

  sql/table.h@stripped, 2007-03-16 20:33:23+01:00, serg@stripped +0 -0
    Auto merged
    MERGE: 1.158.1.9

  storage/myisam/ha_myisam.cc@stripped, 2007-03-16 20:33:23+01:00, serg@stripped +0 -0
    Auto merged
    MERGE: 1.209.1.3

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	serg
# Host:	janus.mylan
# Root:	/usr/home/serg/Abk/mysql-5.1/RESYNC

--- 1.212/storage/myisam/ha_myisam.cc	2007-03-16 20:33:35 +01:00
+++ 1.213/storage/myisam/ha_myisam.cc	2007-03-16 20:33:35 +01:00
@@ -1156,23 +1156,22 @@
   KEY_CACHE *new_key_cache= check_opt->key_cache;
   const char *errmsg= 0;
   int error= HA_ADMIN_OK;
-  ulonglong map= ~(ulonglong) 0;
+  ulonglong map;
   TABLE_LIST *table_list= table->pos_in_table_list;
   DBUG_ENTER("ha_myisam::assign_to_keycache");
 
-  /* Check validity of the index references */
-  if (table_list->use_index)
+  table->keys_in_use_for_query.clear_all();
+
+  if (table_list->process_index_hints(table))
   {
-    /* We only come here when the user did specify an index map */
-    key_map kmap;
-    if (get_key_map_from_key_list(&kmap, table, table_list->use_index))
-    {
-      errmsg= thd->net.last_error;
-      error= HA_ADMIN_FAILED;
-      goto err;
-    }
-    map= kmap.to_ulonglong();
+    errmsg= thd->net.last_error;
+    error= HA_ADMIN_FAILED;
+    goto err;
   }
+  map= ~(ulonglong) 0;
+  if (!table->keys_in_use_for_query.is_clear_all())
+    /* use all keys if there's no list specified by the user through hints */
+    map= table->keys_in_use_for_query.to_ulonglong();
 
   if ((error= mi_assign_to_key_cache(file, map, new_key_cache)))
   { 
@@ -1208,26 +1207,26 @@
 {
   int error;
   const char *errmsg;
-  ulonglong map= ~(ulonglong) 0;
+  ulonglong map;
   TABLE_LIST *table_list= table->pos_in_table_list;
   my_bool ignore_leaves= table_list->ignore_leaves;
 
   DBUG_ENTER("ha_myisam::preload_keys");
 
-  /* Check validity of the index references */
-  if (table_list->use_index)
+  table->keys_in_use_for_query.clear_all();
+
+  if (table_list->process_index_hints(table))
   {
-    key_map kmap;
-    get_key_map_from_key_list(&kmap, table, table_list->use_index);
-    if (kmap.is_set_all())
-    {
-      errmsg= thd->net.last_error;
-      error= HA_ADMIN_FAILED;
-      goto err;
-    }
-    if (!kmap.is_clear_all())
-      map= kmap.to_ulonglong();
+    errmsg= thd->net.last_error;
+    error= HA_ADMIN_FAILED;
+    goto err;
   }
+
+  map= ~(ulonglong) 0;
+  /* Check validity of the index references */
+  if (!table->keys_in_use_for_query.is_clear_all())
+    /* use all keys if there's no list specified by the user through hints */
+    map= table->keys_in_use_for_query.to_ulonglong();
 
   mi_extra(file, HA_EXTRA_PRELOAD_BUFFER_SIZE,
            (void *) &thd->variables.preload_buff_size);

--- 1.487/sql/mysql_priv.h	2007-03-16 20:33:35 +01:00
+++ 1.488/sql/mysql_priv.h	2007-03-16 20:33:35 +01:00
@@ -1493,7 +1493,7 @@
 void mysql_print_status();
 /* key.cc */
 int find_ref_key(KEY *key, uint key_count, byte *record, Field *field,
-                 uint *key_length);
+                 uint *key_length, uint *keypart);
 void key_copy(byte *to_key, byte *from_record, KEY *key_info, uint key_length);
 void key_restore(byte *to_record, byte *from_key, KEY *key_info,
                  uint key_length);

--- 1.266/sql/opt_range.cc	2007-03-16 20:33:35 +01:00
+++ 1.267/sql/opt_range.cc	2007-03-16 20:33:35 +01:00
@@ -2124,9 +2124,9 @@
     param.key_parts_end=key_parts;
 
     /* Calculate cost of full index read for the shortest covering index */
-    if (!head->used_keys.is_clear_all())
+    if (!head->covering_keys.is_clear_all())
     {
-      int key_for_use= find_shortest_key(head, &head->used_keys);
+      int key_for_use= find_shortest_key(head, &head->covering_keys);
       double key_read_time= (get_index_only_read_time(&param, records,
                                                      key_for_use) +
                              (double) records / TIME_FOR_COMPARE);
@@ -4663,7 +4663,7 @@
         param->needed_reg->set_bit(keynr);
 
       bool read_index_only= index_read_must_be_used ? TRUE :
-                            (bool) param->table->used_keys.is_set(keynr);
+                            (bool) param->table->covering_keys.is_set(keynr);
 
       found_records= check_quick_select(param, idx, *key, update_tbl_stats);
       if (param->is_ror_scan)
@@ -9055,7 +9055,7 @@
        cur_index_info++, cur_index++)
   {
     /* Check (B1) - if current index is covering. */
-    if (!table->used_keys.is_set(cur_index))
+    if (!table->covering_keys.is_set(cur_index))
       goto next_index;
 
     /*

--- 1.231/sql/sql_acl.cc	2007-03-16 20:33:35 +01:00
+++ 1.232/sql/sql_acl.cc	2007-03-16 20:33:35 +01:00
@@ -6079,6 +6079,8 @@
   char *curr_host= thd->security_ctx->priv_host_name();
   DBUG_ENTER("fill_schema_user_privileges");
 
+  if (!initialized)
+    DBUG_RETURN(0);
   pthread_mutex_lock(&acl_cache->lock);
 
   for (counter=0 ; counter < acl_users.elements ; counter++)
@@ -6138,6 +6140,8 @@
   char *curr_host= thd->security_ctx->priv_host_name();
   DBUG_ENTER("fill_schema_schema_privileges");
 
+  if (!initialized)
+    DBUG_RETURN(0);
   pthread_mutex_lock(&acl_cache->lock);
 
   for (counter=0 ; counter < acl_dbs.elements ; counter++)

--- 1.250/sql/sql_insert.cc	2007-03-16 20:33:35 +01:00
+++ 1.251/sql/sql_insert.cc	2007-03-16 20:33:35 +01:00
@@ -468,10 +468,15 @@
   thd->proc_info="init";
   thd->used_tables=0;
   values= its++;
+  value_count= values->elements;
 
   if (mysql_prepare_insert(thd, table_list, table, fields, values,
 			   update_fields, update_values, duplic, &unused_conds,
-                           FALSE))
+                           FALSE,
+                           (fields.elements || !value_count),
+                           !ignore && (thd->variables.sql_mode &
+                                       (MODE_STRICT_TRANS_TABLES |
+                                        MODE_STRICT_ALL_TABLES))))
     goto abort;
 
   /* mysql_prepare_insert set table_list->table if it was not set */
@@ -497,7 +502,6 @@
   table_list->next_local= 0;
   context->resolve_in_table_list_only(table_list);
 
-  value_count= values->elements;
   while ((values= its++))
   {
     counter++;
@@ -567,17 +571,9 @@
     table->file->ha_start_bulk_insert(values_list.elements);
 
   thd->no_trans_update= 0;
-  thd->abort_on_warning= (!ignore &&
-                          (thd->variables.sql_mode &
-                           (MODE_STRICT_TRANS_TABLES |
-                            MODE_STRICT_ALL_TABLES)));
-
-  if ((fields.elements || !value_count) &&
-      check_that_all_fields_are_given_values(thd, table, table_list))
-  {
-    /* thd->net.report_error is now set, which will abort the next loop */
-    error= 1;
-  }
+  thd->abort_on_warning= (!ignore && (thd->variables.sql_mode &
+                                       (MODE_STRICT_TRANS_TABLES |
+                                        MODE_STRICT_ALL_TABLES)));
 
   table->mark_columns_needed_for_insert();
 
@@ -954,6 +950,10 @@
 			be taken from table_list->table)    
     where		Where clause (for insert ... select)
     select_insert	TRUE if INSERT ... SELECT statement
+    check_fields        TRUE if need to check that all INSERT fields are 
+                        given values.
+    abort_on_warning    whether to report if some INSERT field is not 
+                        assigned as an error (TRUE) or as a warning (FALSE).
 
   TODO (in far future)
     In cases of:
@@ -974,7 +974,8 @@
                           TABLE *table, List<Item> &fields, List_item *values,
                           List<Item> &update_fields, List<Item> &update_values,
                           enum_duplicates duplic,
-                          COND **where, bool select_insert)
+                          COND **where, bool select_insert,
+                          bool check_fields, bool abort_on_warning)
 {
   SELECT_LEX *select_lex= &thd->lex->select_lex;
   Name_resolution_context *context= &select_lex->context;
@@ -1036,10 +1037,22 @@
     table_list->next_local= 0;
     context->resolve_in_table_list_only(table_list);
 
-    if (!(res= check_insert_fields(thd, context->table_list, fields, *values,
-                                 !insert_into_view, &map) ||
-          setup_fields(thd, 0, *values, MARK_COLUMNS_READ, 0, 0)) 
-        && duplic == DUP_UPDATE)
+    res= check_insert_fields(thd, context->table_list, fields, *values,
+                             !insert_into_view, &map) ||
+      setup_fields(thd, 0, *values, MARK_COLUMNS_READ, 0, 0);
+
+    if (!res && check_fields)
+    {
+      bool saved_abort_on_warning= thd->abort_on_warning;
+      thd->abort_on_warning= abort_on_warning;
+      res= check_that_all_fields_are_given_values(thd, 
+                                                  table ? table : 
+                                                  context->table_list->table,
+                                                  context->table_list);
+      thd->abort_on_warning= saved_abort_on_warning;
+    }
+
+    if (!res && duplic == DUP_UPDATE)
     {
       select_lex->no_wrap_view_item= TRUE;
       res= check_update_fields(thd, context->table_list, update_fields, &map);
@@ -2441,7 +2454,7 @@
                            lex->query_tables->table, lex->field_list, 0,
                            lex->update_list, lex->value_list,
                            lex->duplicates,
-                           &select_lex->where, TRUE))
+                           &select_lex->where, TRUE, FALSE, FALSE))
     DBUG_RETURN(TRUE);
 
   /*
@@ -2504,7 +2517,18 @@
                            !insert_into_view, &map) ||
        setup_fields(thd, 0, values, MARK_COLUMNS_READ, 0, 0);
 
-  if (info.handle_duplicates == DUP_UPDATE)
+  if (!res && fields->elements)
+  {
+    bool saved_abort_on_warning= thd->abort_on_warning;
+    thd->abort_on_warning= !info.ignore && (thd->variables.sql_mode &
+                                            (MODE_STRICT_TRANS_TABLES |
+                                             MODE_STRICT_ALL_TABLES));
+    res= check_that_all_fields_are_given_values(thd, table_list->table, 
+                                                table_list);
+    thd->abort_on_warning= saved_abort_on_warning;
+  }
+
+  if (info.handle_duplicates == DUP_UPDATE && !res)
   {
     Name_resolution_context *context= &lex->select_lex.context;
     Name_resolution_context_state ctx_state;
@@ -2615,9 +2639,7 @@
                           (thd->variables.sql_mode &
                            (MODE_STRICT_TRANS_TABLES |
                             MODE_STRICT_ALL_TABLES)));
-  res= ((fields->elements &&
-         check_that_all_fields_are_given_values(thd, table, table_list)) ||
-        table_list->prepare_where(thd, 0, TRUE) ||
+  res= (table_list->prepare_where(thd, 0, TRUE) ||
         table_list->prepare_check_option(thd));
 
   if (!res)

--- 1.496/sql/sql_select.cc	2007-03-16 20:33:35 +01:00
+++ 1.497/sql/sql_select.cc	2007-03-16 20:33:35 +01:00
@@ -163,13 +163,15 @@
 static Item* part_of_refkey(TABLE *form,Field *field);
 uint find_shortest_key(TABLE *table, const key_map *usable_keys);
 static bool test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,
-				    ha_rows select_limit, bool no_changes);
+				    ha_rows select_limit, bool no_changes,
+                                    key_map *map);
 static bool list_contains_unique_index(TABLE *table,
                           bool (*find_func) (Field *, void *), void *data);
 static bool find_field_in_item_list (Field *field, void *data);
 static bool find_field_in_order_list (Field *field, void *data);
 static int create_sort_index(THD *thd, JOIN *join, ORDER *order,
-			     ha_rows filesort_limit, ha_rows select_limit);
+			     ha_rows filesort_limit, ha_rows select_limit,
+                             bool is_order_by);
 static int remove_duplicates(JOIN *join,TABLE *entry,List<Item> &fields,
 			     Item *having);
 static int remove_dup_with_compare(THD *thd, TABLE *entry, Field **field,
@@ -652,7 +654,7 @@
 static void save_index_subquery_explain_info(JOIN_TAB *join_tab, Item* where)
 {
   join_tab->packed_info= TAB_INFO_HAVE_VALUE;
-  if (join_tab->table->used_keys.is_set(join_tab->ref.key))
+  if (join_tab->table->covering_keys.is_set(join_tab->ref.key))
     join_tab->packed_info |= TAB_INFO_USING_INDEX;
   if (where)
     join_tab->packed_info |= TAB_INFO_USING_WHERE;
@@ -1024,14 +1026,15 @@
     JOIN_TAB *tab= &join_tab[const_tables];
     bool all_order_fields_used;
     if (order)
-      skip_sort_order= test_if_skip_sort_order(tab, order, select_limit, 1);
+      skip_sort_order= test_if_skip_sort_order(tab, order, select_limit, 1, 
+        &tab->table->keys_in_use_for_order_by);
     if ((group_list=create_distinct_group(thd, select_lex->ref_pointer_array,
                                           order, fields_list,
 				          &all_order_fields_used)))
     {
       bool skip_group= (skip_sort_order &&
-			test_if_skip_sort_order(tab, group_list, select_limit,
-						1) != 0);
+        test_if_skip_sort_order(tab, group_list, select_limit, 1, 
+                                &tab->table->keys_in_use_for_group_by) != 0);
       if ((skip_group && all_order_fields_used) ||
 	  select_limit == HA_POS_ERROR ||
 	  (order && !skip_sort_order))
@@ -1229,7 +1232,9 @@
         ((group_list &&
           (!simple_group ||
            !test_if_skip_sort_order(&join_tab[const_tables], group_list,
-                                    unit->select_limit_cnt, 0))) ||
+                                    unit->select_limit_cnt, 0, 
+                                    &join_tab[const_tables].table->
+                                    keys_in_use_for_group_by))) ||
          select_distinct) &&
         tmp_table_param.quick_group && !procedure)
     {
@@ -1331,7 +1336,7 @@
       DBUG_PRINT("info",("Sorting for group"));
       thd->proc_info="Sorting for group";
       if (create_sort_index(thd, this, group_list,
-			    HA_POS_ERROR, HA_POS_ERROR) ||
+			    HA_POS_ERROR, HA_POS_ERROR, FALSE) ||
 	  alloc_group_fields(this, group_list) ||
           make_sum_func_list(all_fields, fields_list, 1) ||
           setup_sum_funcs(thd, sum_funcs))
@@ -1348,7 +1353,7 @@
 	DBUG_PRINT("info",("Sorting for order"));
 	thd->proc_info="Sorting for order";
 	if (create_sort_index(thd, this, order,
-                              HA_POS_ERROR, HA_POS_ERROR))
+                              HA_POS_ERROR, HA_POS_ERROR, TRUE))
 	  DBUG_RETURN(1);
 	order=0;
       }
@@ -1375,7 +1380,9 @@
       {
  	/* Should always succeed */
 	if (test_if_skip_sort_order(&join_tab[const_tables],
-				    order, unit->select_limit_cnt, 0))
+				    order, unit->select_limit_cnt, 0, 
+                                    &join_tab[const_tables].table->
+                                      keys_in_use_for_order_by))
 	  order=0;
       }
     }
@@ -1568,7 +1575,9 @@
 	(const_tables == tables ||
  	 ((simple_order || skip_sort_order) &&
 	  test_if_skip_sort_order(&join_tab[const_tables], order,
-				  select_limit, 0))))
+				  select_limit, 0, 
+                                  &join_tab[const_tables].table->
+                                    keys_in_use_for_order_by))))
       order=0;
     having= tmp_having;
     select_describe(this, need_tmp,
@@ -1744,7 +1753,7 @@
 	  DBUG_VOID_RETURN;
 	}
 	if (create_sort_index(thd, curr_join, curr_join->group_list,
-			      HA_POS_ERROR, HA_POS_ERROR) ||
+			      HA_POS_ERROR, HA_POS_ERROR, FALSE) ||
 	    make_group_fields(this, curr_join))
 	{
 	  DBUG_VOID_RETURN;
@@ -1960,7 +1969,8 @@
 			    curr_join->group_list : curr_join->order,
 			    curr_join->select_limit,
 			    (select_options & OPTION_FOUND_ROWS ?
-			     HA_POS_ERROR : unit->select_limit_cnt)))
+			     HA_POS_ERROR : unit->select_limit_cnt),
+                            curr_join->group_list ? TRUE : FALSE))
 	DBUG_VOID_RETURN;
       sortorder= curr_join->sortorder;
       if (curr_join->const_tables != curr_join->tables &&
@@ -3964,7 +3974,7 @@
             /* Limit the number of matched rows */
             tmp= records;
             set_if_smaller(tmp, (double) thd->variables.max_seeks_for_key);
-            if (table->used_keys.is_set(key))
+            if (table->covering_keys.is_set(key))
             {
               /* we can use only index tree */
               uint keys_per_block= table->file->stats.block_size/2/
@@ -4131,7 +4141,7 @@
 
             /* Limit the number of matched rows */
             set_if_smaller(tmp, (double) thd->variables.max_seeks_for_key);
-            if (table->used_keys.is_set(key))
+            if (table->covering_keys.is_set(key))
             {
               /* we can use only index tree */
               uint keys_per_block= table->file->stats.block_size/2/
@@ -4190,7 +4200,7 @@
       !(s->quick && best_key && s->quick->index == best_key->key &&      // (2)
         best_max_key_part >= s->table->quick_key_parts[best_key->key]) &&// (2)
       !((s->table->file->ha_table_flags() & HA_TABLE_SCAN_ON_INDEX) &&   // (3)
-        ! s->table->used_keys.is_clear_all() && best_key) &&             // (3)
+        ! s->table->covering_keys.is_clear_all() && best_key) &&         // (3)
       !(s->table->force_index && best_key && !s->quick))                 // (4)
   {                                             // Check full join
     ha_rows rnd_records= s->found_records;
@@ -6096,10 +6106,7 @@
     */
     if (!ordered_set && 
         (table == join->sort_by_table &&
-         (!join->order || join->skip_sort_order ||
-          test_if_skip_sort_order(tab, join->order, join->select_limit,
-                                  1))
-        ) ||
+         (!join->order || join->skip_sort_order)) ||
         (join->sort_by_table == (TABLE *) 1 && i != join->const_tables))
       ordered_set= 1;
 
@@ -6115,7 +6122,7 @@
       table->status=STATUS_NO_RECORD;
       tab->read_first_record= join_read_const;
       tab->read_record.read_record= join_no_more_records;
-      if (table->used_keys.is_set(tab->ref.key) &&
+      if (table->covering_keys.is_set(tab->ref.key) &&
           !table->no_keyread)
       {
         table->key_read=1;
@@ -6133,7 +6140,7 @@
       tab->quick=0;
       tab->read_first_record= join_read_key;
       tab->read_record.read_record= join_no_more_records;
-      if (table->used_keys.is_set(tab->ref.key) &&
+      if (table->covering_keys.is_set(tab->ref.key) &&
 	  !table->no_keyread)
       {
 	table->key_read=1;
@@ -6150,7 +6157,7 @@
       }
       delete tab->quick;
       tab->quick=0;
-      if (table->used_keys.is_set(tab->ref.key) &&
+      if (table->covering_keys.is_set(tab->ref.key) &&
 	  !table->no_keyread)
       {
 	table->key_read=1;
@@ -6236,15 +6243,15 @@
 	{
 	  if (tab->select && tab->select->quick &&
               tab->select->quick->index != MAX_KEY && //not index_merge
-	      table->used_keys.is_set(tab->select->quick->index))
+	      table->covering_keys.is_set(tab->select->quick->index))
 	  {
 	    table->key_read=1;
 	    table->file->extra(HA_EXTRA_KEYREAD);
 	  }
-	  else if (!table->used_keys.is_clear_all() &&
+	  else if (!table->covering_keys.is_clear_all() &&
 		   !(tab->select && tab->select->quick))
 	  {					// Only read index tree
-	    tab->index=find_shortest_key(table, & table->used_keys);
+	    tab->index=find_shortest_key(table, & table->covering_keys);
 	    tab->read_first_record= join_read_first;
 	    tab->type=JT_NEXT;		// Read with index_first / index_next
 	  }
@@ -9378,7 +9385,7 @@
   table->copy_blobs= 1;
   table->in_use= thd;
   table->quick_keys.init();
-  table->used_keys.init();
+  table->covering_keys.init();
   table->keys_in_use_for_query.init();
 
   table->s= share;
@@ -11004,7 +11011,7 @@
   }
   else
   {
-    if (!table->key_read && table->used_keys.is_set(tab->ref.key) &&
+    if (!table->key_read && table->covering_keys.is_set(tab->ref.key) &&
 	!table->no_keyread &&
         (int) table->reginfo.lock_type <= (int) TL_READ_HIGH_PRIORITY)
     {
@@ -11314,7 +11321,7 @@
 {
   int error;
   TABLE *table=tab->table;
-  if (!table->key_read && table->used_keys.is_set(tab->index) &&
+  if (!table->key_read && table->covering_keys.is_set(tab->index) &&
       !table->no_keyread)
   {
     table->key_read=1;
@@ -11353,7 +11360,7 @@
 {
   TABLE *table=tab->table;
   int error;
-  if (!table->key_read && table->used_keys.is_set(tab->index) &&
+  if (!table->key_read && table->covering_keys.is_set(tab->index) &&
       !table->no_keyread)
   {
     table->key_read=1;
@@ -12377,7 +12384,7 @@
 
 static bool
 test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
-			bool no_changes)
+			bool no_changes, key_map *map)
 {
   int ref_key;
   uint ref_key_parts;
@@ -12387,14 +12394,11 @@
   DBUG_ENTER("test_if_skip_sort_order");
   LINT_INIT(ref_key_parts);
 
-  /* Check which keys can be used to resolve ORDER BY. */
-  usable_keys= table->keys_in_use_for_query;
-
   /*
     Keys disabled by ALTER TABLE ... DISABLE KEYS should have already
     been taken into account.
   */
-  DBUG_ASSERT(usable_keys.is_subset(table->s->keys_in_use));
+  usable_keys= *map;
 
   for (ORDER *tmp_order=order; tmp_order ; tmp_order=tmp_order->next)
   {
@@ -12452,8 +12456,8 @@
 	If using index only read, only consider other possible index only
 	keys
       */
-      if (table->used_keys.is_set(ref_key))
-	usable_keys.intersect(table->used_keys);
+      if (table->covering_keys.is_set(ref_key))
+	usable_keys.intersect(table->covering_keys);
       if ((new_ref_key= test_if_subkey(order, table, ref_key, ref_key_parts,
 				       &usable_keys)) < MAX_KEY)
       {
@@ -12568,7 +12572,7 @@
     if (select_limit >= table->file->stats.records)
     {
       keys= *table->file->keys_to_use_for_scanning();
-      keys.merge(table->used_keys);
+      keys.merge(table->covering_keys);
 
       /*
 	We are adding here also the index specified in FORCE INDEX clause, 
@@ -12596,7 +12600,7 @@
 	    tab->read_first_record=  (flag > 0 ? join_read_first:
 				      join_read_last);
 	    tab->type=JT_NEXT;	// Read with index_first(), index_next()
-	    if (table->used_keys.is_set(nr))
+	    if (table->covering_keys.is_set(nr))
 	    {
 	      table->key_read=1;
 	      table->file->extra(HA_EXTRA_KEYREAD);
@@ -12622,6 +12626,8 @@
      filesort_limit	Max number of rows that needs to be sorted
      select_limit	Max number of rows in final output
 		        Used to decide if we should use index or not
+     is_order_by        true if we are sorting on ORDER BY, false if GROUP BY
+                        Used to decide if we should use index or not     
 
 
   IMPLEMENTATION
@@ -12640,7 +12646,8 @@
 
 static int
 create_sort_index(THD *thd, JOIN *join, ORDER *order,
-		  ha_rows filesort_limit, ha_rows select_limit)
+		  ha_rows filesort_limit, ha_rows select_limit,
+                  bool is_order_by)
 {
   uint length= 0;
   ha_rows examined_rows;
@@ -12661,7 +12668,9 @@
   */
   if ((order != join->group_list || 
        !(join->select_options & SELECT_BIG_RESULT)) &&
-      test_if_skip_sort_order(tab,order,select_limit,0))
+      test_if_skip_sort_order(tab,order,select_limit,0, 
+                              is_order_by ?  &table->keys_in_use_for_order_by :
+                              &table->keys_in_use_for_group_by))
     DBUG_RETURN(0);
   for (ORDER *ord= join->order; ord; ord= ord->next)
     length++;
@@ -15289,7 +15298,7 @@
       /* Build "Extra" field and add it to item_list. */
       my_bool key_read=table->key_read;
       if ((tab->type == JT_NEXT || tab->type == JT_CONST) &&
-          table->used_keys.is_set(tab->index))
+          table->covering_keys.is_set(tab->index))
 	key_read=1;
       if (quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT &&
           !((QUICK_ROR_INTERSECT_SELECT*)tab->select->quick)->need_to_fetch_row)

--- 1.278/sql/table.cc	2007-03-16 20:33:36 +01:00
+++ 1.279/sql/table.cc	2007-03-16 20:33:36 +01:00
@@ -1338,7 +1338,7 @@
   if (!(outparam->alias= my_strdup(alias, MYF(MY_WME))))
     goto err;
   outparam->quick_keys.init();
-  outparam->used_keys.init();
+  outparam->covering_keys.init();
   outparam->keys_in_use_for_query.init();
 
   /* Allocate handler */
@@ -4142,6 +4142,175 @@
 Item_subselect *st_table_list::containing_subselect()
 {    
   return (select_lex ? select_lex->master_unit()->item : 0);
+}
+
+/*
+  Compiles the tagged hints list and fills up the bitmasks.
+
+  SYNOPSIS
+    process_index_hints()
+      table         the TABLE to operate on.
+
+  DESCRIPTION
+    The parser collects the index hints for each table in a "tagged list" 
+    (st_table_list::index_hints). Using the information in this tagged list
+    this function sets the members st_table::keys_in_use_for_query, 
+    st_table::keys_in_use_for_group_by, st_table::keys_in_use_for_order_by,
+    st_table::force_index and st_table::covering_keys.
+
+    Current implementation of the runtime does not allow mixing FORCE INDEX
+    and USE INDEX, so this is checked here. Then the FORCE INDEX list 
+    (if non-empty) is appended to the USE INDEX list and a flag is set.
+
+    Multiple hints of the same kind are processed so that each clause 
+    is applied to what is computed in the previous clause.
+    For example:
+        USE INDEX (i1) USE INDEX (i2)
+    is equivalent to
+        USE INDEX (i1,i2)
+    and means "consider only i1 and i2".
+        
+    Similarly
+        USE INDEX () USE INDEX (i1)
+    is equivalent to
+        USE INDEX (i1)
+    and means "consider only the index i1"
+
+    It is OK to have the same index several times, e.g. "USE INDEX (i1,i1)" is
+    not an error.
+        
+    Different kind of hints (USE/FORCE/IGNORE) are processed in the following
+    order:
+      1. All indexes in USE (or FORCE) INDEX are added to the mask.
+      2. All IGNORE INDEX
+
+    e.g. "USE INDEX i1, IGNORE INDEX i1, USE INDEX i1" will not use i1 at all
+    as if we had "USE INDEX i1, USE INDEX i1, IGNORE INDEX i1".
+
+    As an optimization if there is a covering index, and we have 
+    IGNORE INDEX FOR GROUP/ORDER, and this index is used for the JOIN part, 
+    then we have to ignore the IGNORE INDEX FROM GROUP/ORDER.
+
+  RETURN VALUE
+    FALSE                no errors found
+    TRUE                 found and reported an error.
+*/
+bool st_table_list::process_index_hints(TABLE *table)
+{
+  /* initialize the result variables */
+  table->keys_in_use_for_query= table->keys_in_use_for_group_by= 
+    table->keys_in_use_for_order_by= table->s->keys_in_use;
+
+  /* index hint list processing */
+  if (index_hints)
+  {
+    key_map index_join[INDEX_HINT_FORCE + 1];
+    key_map index_order[INDEX_HINT_FORCE + 1];
+    key_map index_group[INDEX_HINT_FORCE + 1];
+    index_hint *hint;
+    int type;
+    bool have_empty_use_join= FALSE, have_empty_use_order= FALSE, 
+         have_empty_use_group= FALSE;
+    List_iterator <index_hint> iter(*index_hints);
+
+    /* initialize temporary variables used to collect hints of each kind */
+    for (type= INDEX_HINT_IGNORE; type <= INDEX_HINT_FORCE; type++)
+    {
+      index_join[type].clear_all();
+      index_order[type].clear_all();
+      index_group[type].clear_all();
+    }
+
+    /* iterate over the hints list */
+    while ((hint= iter++))
+    {
+      uint pos;
+
+      /* process empty USE INDEX () */
+      if (hint->type == INDEX_HINT_USE && !hint->key_name.str)
+      {
+        if (hint->clause & INDEX_HINT_MASK_JOIN)
+        {
+          index_join[hint->type].clear_all();
+          have_empty_use_join= TRUE;
+        }
+        if (hint->clause & INDEX_HINT_MASK_ORDER)
+        {
+          index_order[hint->type].clear_all();
+          have_empty_use_order= TRUE;
+        }
+        if (hint->clause & INDEX_HINT_MASK_GROUP)
+        {
+          index_group[hint->type].clear_all();
+          have_empty_use_group= TRUE;
+        }
+        continue;
+      }
+
+      /* 
+        Check if an index with the given name exists and get his offset in 
+        the keys bitmask for the table 
+      */
+      if (table->s->keynames.type_names == 0 ||
+          (pos= find_type(&table->s->keynames, hint->key_name.str,
+                          hint->key_name.length, 1)) <= 0)
+      {
+        my_error(ER_KEY_DOES_NOT_EXITS, MYF(0), hint->key_name.str, alias);
+        return 1;
+      }
+
+      pos--;
+
+      /* add to the appropriate clause mask */
+      if (hint->clause & INDEX_HINT_MASK_JOIN)
+        index_join[hint->type].set_bit (pos);
+      if (hint->clause & INDEX_HINT_MASK_ORDER)
+        index_order[hint->type].set_bit (pos);
+      if (hint->clause & INDEX_HINT_MASK_GROUP)
+        index_group[hint->type].set_bit (pos);
+    }
+
+    /* cannot mix USE INDEX and FORCE INDEX */
+    if ((!index_join[INDEX_HINT_FORCE].is_clear_all() ||
+         !index_order[INDEX_HINT_FORCE].is_clear_all() ||
+         !index_group[INDEX_HINT_FORCE].is_clear_all()) &&
+        (!index_join[INDEX_HINT_USE].is_clear_all() ||  have_empty_use_join ||
+         !index_order[INDEX_HINT_USE].is_clear_all() || have_empty_use_order ||
+         !index_group[INDEX_HINT_USE].is_clear_all() || have_empty_use_group))
+    {
+      my_error(ER_WRONG_USAGE, MYF(0), index_hint_type_name[INDEX_HINT_USE],
+               index_hint_type_name[INDEX_HINT_FORCE]);
+      return 1;
+    }
+
+    /* process FORCE INDEX as USE INDEX with a flag */
+    if (!index_join[INDEX_HINT_FORCE].is_clear_all() ||
+        !index_order[INDEX_HINT_FORCE].is_clear_all() ||
+        !index_group[INDEX_HINT_FORCE].is_clear_all())
+    {
+      table->force_index= TRUE;
+      index_join[INDEX_HINT_USE].merge(index_join[INDEX_HINT_FORCE]);
+      index_order[INDEX_HINT_USE].merge(index_order[INDEX_HINT_FORCE]);
+      index_group[INDEX_HINT_USE].merge(index_group[INDEX_HINT_FORCE]);
+    }
+
+    /* apply USE INDEX */
+    if (!index_join[INDEX_HINT_USE].is_clear_all() || have_empty_use_join)
+      table->keys_in_use_for_query.intersect(index_join[INDEX_HINT_USE]);
+    if (!index_order[INDEX_HINT_USE].is_clear_all() || have_empty_use_order)
+      table->keys_in_use_for_order_by.intersect (index_order[INDEX_HINT_USE]);
+    if (!index_group[INDEX_HINT_USE].is_clear_all() || have_empty_use_group)
+      table->keys_in_use_for_group_by.intersect (index_group[INDEX_HINT_USE]);
+
+    /* apply IGNORE INDEX */
+    table->keys_in_use_for_query.subtract (index_join[INDEX_HINT_IGNORE]);
+    table->keys_in_use_for_order_by.subtract (index_order[INDEX_HINT_IGNORE]);
+    table->keys_in_use_for_group_by.subtract (index_group[INDEX_HINT_IGNORE]);
+  }
+
+  /* make sure covering_keys don't include indexes disabled with a hint */
+  table->covering_keys.intersect(table->keys_in_use_for_query);
+  return 0;
 }
 
 /*****************************************************************************

--- 1.161/sql/table.h	2007-03-16 20:33:36 +01:00
+++ 1.162/sql/table.h	2007-03-16 20:33:36 +01:00
@@ -300,6 +300,12 @@
 
 
 /* Information for one open table */
+enum index_hint_type
+{
+  INDEX_HINT_IGNORE,
+  INDEX_HINT_USE,
+  INDEX_HINT_FORCE
+};
 
 struct st_table {
   st_table() {}                               /* Remove gcc warning */
@@ -319,8 +325,12 @@
   byte *write_row_record;		/* Used as optimisation in
 					   THD::write_row */
   byte *insert_values;                  /* used by INSERT ... UPDATE */
-  key_map quick_keys, used_keys;
-
+  /* 
+    Map of keys that can be used to retrieve all data from this table 
+    needed by the query without reading the row.
+  */
+  key_map covering_keys;
+  key_map quick_keys, merge_keys;
   /*
     A set of keys that can be used in the query that references this
     table.
@@ -333,7 +343,10 @@
     The set is implemented as a bitmap.
   */
   key_map keys_in_use_for_query;
-  key_map merge_keys;
+  /* Map of keys that can be used to calculate GROUP BY without sorting */
+  key_map keys_in_use_for_group_by;
+  /* Map of keys that can be used to calculate ORDER BY without sorting */
+  key_map keys_in_use_for_order_by;
   KEY  *key_info;			/* data of keys in database */
 
   Field *next_number_field;		/* Set if next_number is activated */
@@ -667,6 +680,7 @@
          (TABLE_LIST::join_using_fields != NULL)
 */
 
+class index_hint;
 typedef struct st_table_list
 {
   st_table_list() {}                          /* Remove gcc warning */
@@ -723,7 +737,7 @@
   */
   struct st_table_list *next_name_resolution_table;
   /* Index names in a "... JOIN ... USE/IGNORE INDEX ..." clause. */
-  List<String> *use_index, *ignore_index;
+  List<index_hint> *index_hints;
   TABLE        *table;                          /* opened table */
   uint          table_id; /* table id (from binlog) for opened table */
   /*
@@ -896,6 +910,13 @@
   */
   void reinit_before_use(THD *thd);
   Item_subselect *containing_subselect();
+
+  /* 
+    Compiles the tagged hints list and fills up st_table::keys_in_use_for_query,
+    st_table::keys_in_use_for_group_by, st_table::keys_in_use_for_order_by,
+    st_table::force_index and st_table::covering_keys.
+  */
+  bool process_index_hints(TABLE *table);
 
 private:
   bool prep_check_option(THD *thd, uint8 check_opt_type);

--- 1.56/sql/sql_help.cc	2007-03-16 20:33:36 +01:00
+++ 1.57/sql/sql_help.cc	2007-03-16 20:33:36 +01:00
@@ -566,7 +566,7 @@
     cond->fix_fields(thd, &cond);	// can never fail
 
   /* Assume that no indexes cover all required fields */
-  table->used_keys.clear_all();
+  table->covering_keys.clear_all();
 
   SQL_SELECT *res= make_select(table, 0, 0, cond, 0, error);
   if (*error || (res && res->check_quick(thd, 0, HA_POS_ERROR)) ||
Thread
bk commit into 5.1 tree (serg:1.2501)Sergei Golubchik16 Mar