List:Commits« Previous MessageNext Message »
From:Sergei Golubchik Date:March 6 2007 1:45pm
Subject:bk commit into 5.1 tree (serg:1.2454)
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-06 13:44:57+01:00, serg@stripped +11 -0
  Merge bk-internal.mysql.com:/home/bk/mysql-5.1
  into  janus.mylan:/usr/home/serg/Abk/mysql-5.1
  MERGE: 1.2451.1.14

  sql/ha_ndbcluster.cc@stripped, 2007-03-06 13:44:51+01:00, serg@stripped +0 -0
    Auto merged
    MERGE: 1.411.1.5

  sql/ha_partition.cc@stripped, 2007-03-06 13:44:51+01:00, serg@stripped +0 -0
    Auto merged
    MERGE: 1.83.1.2

  sql/ha_partition.h@stripped, 2007-03-06 13:44:51+01:00, serg@stripped +0 -0
    Auto merged
    MERGE: 1.32.1.1

  sql/log.cc@stripped, 2007-03-06 13:44:51+01:00, serg@stripped +0 -0
    Auto merged
    MERGE: 1.255.1.2

  sql/mysql_priv.h@stripped, 2007-03-06 13:44:51+01:00, serg@stripped +0 -0
    Auto merged
    MERGE: 1.482.1.4

  sql/opt_range.cc@stripped, 2007-03-06 13:44:51+01:00, serg@stripped +0 -0
    Auto merged
    MERGE: 1.262.1.3

  sql/sql_help.cc@stripped, 2007-03-06 13:44:51+01:00, serg@stripped +0 -0
    Auto merged
    MERGE: 1.54.1.1

  sql/sql_insert.cc@stripped, 2007-03-06 13:44:51+01:00, serg@stripped +0 -0
    Auto merged
    MERGE: 1.246.1.4

  sql/sql_select.cc@stripped, 2007-03-06 13:44:52+01:00, serg@stripped +0 -0
    Auto merged
    MERGE: 1.492.1.5

  storage/blackhole/ha_blackhole.cc@stripped, 2007-03-06 13:44:52+01:00, serg@stripped +0 -0
    Auto merged
    MERGE: 1.46.1.1

  storage/myisammrg/ha_myisammrg.cc@stripped, 2007-03-06 13:44:52+01:00, serg@stripped +0 -0
    Auto merged
    MERGE: 1.114.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.116/storage/myisammrg/ha_myisammrg.cc	2007-03-06 13:45:06 +01:00
+++ 1.117/storage/myisammrg/ha_myisammrg.cc	2007-03-06 13:45:06 +01:00
@@ -463,6 +463,7 @@
     {
       TABLE_LIST *ptr;
       LEX_STRING db, name;
+      LINT_INIT(db.str);
 
       if (!(ptr = (TABLE_LIST *) thd->calloc(sizeof(TABLE_LIST))))
 	goto err;
@@ -573,6 +574,8 @@
        open_table++)
   {
     LEX_STRING db, name;
+    LINT_INIT(db.str);
+
     split_file_name(open_table->table->filename, &db, &name);
     if (open_table != first)
       packet->append(',');

--- 1.257/sql/log.cc	2007-03-06 13:45:06 +01:00
+++ 1.258/sql/log.cc	2007-03-06 13:45:06 +01:00
@@ -1742,7 +1742,7 @@
 
   /* Register EventMessageFile */
   dwError = RegSetValueEx(hRegKey, "EventMessageFile", 0, REG_EXPAND_SZ,
-                          (PBYTE) szPath, strlen(szPath)+1);
+                          (PBYTE) szPath, (DWORD) (strlen(szPath) + 1));
 
   /* Register supported event types */
   dwTypes= (EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE |

--- 1.484/sql/mysql_priv.h	2007-03-06 13:45:06 +01:00
+++ 1.485/sql/mysql_priv.h	2007-03-06 13:45:06 +01:00
@@ -915,6 +915,8 @@
 int setup_group(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
 		List<Item> &fields, List<Item> &all_fields, ORDER *order,
 		bool *hidden_group_fields);
+bool fix_inner_refs(THD *thd, List<Item> &all_fields, SELECT_LEX *select,
+                   Item **ref_pointer_array);
 
 bool handle_select(THD *thd, LEX *lex, select_result *result,
                    ulong setup_tables_done_option);

--- 1.264/sql/opt_range.cc	2007-03-06 13:45:06 +01:00
+++ 1.265/sql/opt_range.cc	2007-03-06 13:45:06 +01:00
@@ -312,7 +312,7 @@
     min_value=arg->max_value;
     min_flag=arg->max_flag & NEAR_MAX ? 0 : NEAR_MIN;
   }
-  void store_min(uint length,char **min_key,uint min_key_flag)
+  int store_min(uint length,char **min_key,uint min_key_flag)
   {
     if ((min_flag & GEOM_FLAG) ||
         (!(min_flag & NO_MIN_RANGE) &&
@@ -326,12 +326,12 @@
       else
 	memcpy(*min_key,min_value,length);
       (*min_key)+= length;
+      return 1;
     }
+    return 0;
   }
-  void store(uint length,char **min_key,uint min_key_flag,
-	     char **max_key, uint max_key_flag)
+  int store_max(uint length,char **max_key, uint max_key_flag)
   {
-    store_min(length, min_key, min_key_flag);
     if (!(max_flag & NO_MAX_RANGE) &&
 	!(max_key_flag & (NO_MAX_RANGE | NEAR_MAX)))
     {
@@ -343,33 +343,45 @@
       else
 	memcpy(*max_key,max_value,length);
       (*max_key)+= length;
+      return 1;
     }
+    return 0;
   }
+  /*void store(uint length,char **min_key,uint min_key_flag,
+	     char **max_key, uint max_key_flag)
+  {
+    store_min(length, min_key, min_key_flag);
+    store_max(length, max_key, max_key_flag);
+  }*/
 
-  void store_min_key(KEY_PART *key,char **range_key, uint *range_key_flag)
+  int store_min_key(KEY_PART *key,char **range_key, uint *range_key_flag)
   {
     SEL_ARG *key_tree= first();
-    key_tree->store(key[key_tree->part].store_length,
-		    range_key,*range_key_flag,range_key,NO_MAX_RANGE);
+    uint res= key_tree->store_min(key[key_tree->part].store_length,
+                                  range_key, *range_key_flag);
     *range_key_flag|= key_tree->min_flag;
     if (key_tree->next_key_part &&
 	key_tree->next_key_part->part == key_tree->part+1 &&
 	!(*range_key_flag & (NO_MIN_RANGE | NEAR_MIN)) &&
 	key_tree->next_key_part->type == SEL_ARG::KEY_RANGE)
-      key_tree->next_key_part->store_min_key(key,range_key, range_key_flag);
+      res+= key_tree->next_key_part->store_min_key(key, range_key,
+                                                   range_key_flag);
+    return res;
   }
 
-  void store_max_key(KEY_PART *key,char **range_key, uint *range_key_flag)
+  int store_max_key(KEY_PART *key,char **range_key, uint *range_key_flag)
   {
     SEL_ARG *key_tree= last();
-    key_tree->store(key[key_tree->part].store_length,
-		    range_key, NO_MIN_RANGE, range_key,*range_key_flag);
+    uint res=key_tree->store_max(key[key_tree->part].store_length,
+                                 range_key, *range_key_flag);
     (*range_key_flag)|= key_tree->max_flag;
     if (key_tree->next_key_part &&
 	key_tree->next_key_part->part == key_tree->part+1 &&
 	!(*range_key_flag & (NO_MAX_RANGE | NEAR_MAX)) &&
 	key_tree->next_key_part->type == SEL_ARG::KEY_RANGE)
-      key_tree->next_key_part->store_max_key(key,range_key, range_key_flag);
+      res+= key_tree->next_key_part->store_max_key(key, range_key,
+                                                   range_key_flag);
+    return res;
   }
 
   SEL_ARG *insert(SEL_ARG *key);
@@ -586,8 +598,8 @@
 static ha_rows check_quick_select(PARAM *param,uint index,SEL_ARG *key_tree, 
                                   bool update_tbl_stats);
 static ha_rows check_quick_keys(PARAM *param,uint index,SEL_ARG *key_tree,
-				char *min_key,uint min_key_flag,
-				char *max_key, uint max_key_flag);
+                                char *min_key, uint min_key_flag, int,
+                                char *max_key, uint max_key_flag, int);
 
 QUICK_RANGE_SELECT *get_quick_select(PARAM *param,uint index,
                                      SEL_ARG *key_tree,
@@ -1453,6 +1465,7 @@
 
 QUICK_RANGE::QUICK_RANGE()
   :min_key(0),max_key(0),min_length(0),max_length(0),
+  min_keypart_map(0), max_keypart_map(0),
    flag(NO_MIN_RANGE | NO_MAX_RANGE)
 {}
 
@@ -4031,9 +4044,9 @@
     The calculation is conducted as follows:
     Lets denote #records(keypart1, ... keypartK) as n_k. We need to calculate
 
-     n_{k1}      n_{k_2}
+     n_{k1}      n_{k2}
     --------- * ---------  * .... (3)
-     n_{k1-1}    n_{k2_1}
+     n_{k1-1}    n_{k2-1}
 
     where k1,k2,... are key parts which fields were not yet marked as fixed
     ( this is result of application of option b) of the recursion step for
@@ -4041,9 +4054,9 @@
     Since it is reasonable to expect that most of the fields are not marked
     as fixed, we calculate (3) as
 
-                                  n_{i1}      n_{i_2}
+                                  n_{i1}      n_{i2}
     (3) = n_{max_key_part}  / (   --------- * ---------  * ....  )
-                                  n_{i1-1}    n_{i2_1}
+                                  n_{i1-1}    n_{i2-1}
 
     where i1,i2, .. are key parts that were already marked as fixed.
 
@@ -4052,7 +4065,6 @@
 
   RETURN
     Selectivity of given ROR scan.
-    
 */
 
 static double ror_scan_selectivity(const ROR_INTERSECT_INFO *info, 
@@ -4063,6 +4075,7 @@
   byte key_val[MAX_KEY_LENGTH+MAX_FIELD_WIDTH]; /* key values tuple */
   char *key_ptr= (char*) key_val;
   SEL_ARG *sel_arg, *tuple_arg= NULL;
+  ulonglong keypart_map= 0;
   bool cur_covered;
   bool prev_covered= test(bitmap_is_set(&info->covered_fields,
                                         key_part->fieldnr-1));
@@ -4073,7 +4086,7 @@
   max_range.key= (byte*) key_val;
   max_range.flag= HA_READ_AFTER_KEY;
   ha_rows prev_records= info->param->table->file->stats.records;
-  DBUG_ENTER("ror_intersect_selectivity");
+  DBUG_ENTER("ror_scan_selectivity");
 
   for (sel_arg= scan->sel_arg; sel_arg;
        sel_arg= sel_arg->next_key_part)
@@ -4090,13 +4103,17 @@
         tuple_arg= scan->sel_arg;
         /* Here we use the length of the first key part */
         tuple_arg->store_min(key_part->store_length, &key_ptr, 0);
+        keypart_map= 1;
       }
       while (tuple_arg->next_key_part != sel_arg)
       {
         tuple_arg= tuple_arg->next_key_part;
-        tuple_arg->store_min(key_part[tuple_arg->part].store_length, &key_ptr, 0);
+        tuple_arg->store_min(key_part[tuple_arg->part].store_length,
+                             &key_ptr, 0);
+        keypart_map= (keypart_map << 1) | 1;
       }
       min_range.length= max_range.length= ((char*) key_ptr - (char*) key_val);
+      min_range.keypart_map= max_range.keypart_map= keypart_map;
       records= (info->param->table->file->
                 records_in_range(scan->keynr, &min_range, &max_range));
       if (cur_covered)
@@ -5305,12 +5322,11 @@
     */
     for (uint i= 1 ; i < cond_func->arg_count ; i++)
     {
-     
       if (cond_func->arguments()[i]->real_item()->type() == Item::FIELD_ITEM)
       {
         field_item= (Item_field*) (cond_func->arguments()[i]->real_item());
         SEL_TREE *tmp= get_full_func_mm_tree(param, cond_func, 
-                                    field_item, (Item*) i, inv);
+                                    field_item, (Item*)(intptr)i, inv);
         if (inv)
           tree= !tree ? tmp : tree_or(param, tree, tmp);
         else 
@@ -7057,7 +7073,9 @@
   }
   param->n_ranges= 0;
 
-  records=check_quick_keys(param,idx,tree,param->min_key,0,param->max_key,0);
+  records= check_quick_keys(param, idx, tree,
+                            param->min_key, 0, -1,
+                            param->max_key, 0, -1);
   if (records != HA_POS_ERROR)
   {
     if (update_tbl_stats)
@@ -7120,12 +7138,13 @@
 */
 
 static ha_rows
-check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree,
-		 char *min_key,uint min_key_flag, char *max_key,
-		 uint max_key_flag)
+check_quick_keys(PARAM *param, uint idx, SEL_ARG *key_tree,
+		 char *min_key, uint min_key_flag, int min_keypart,
+                 char *max_key, uint max_key_flag, int max_keypart)
 {
   ha_rows records=0, tmp;
   uint tmp_min_flag, tmp_max_flag, keynr, min_key_length, max_key_length;
+  uint tmp_min_keypart= min_keypart, tmp_max_keypart= max_keypart;
   char *tmp_min_key, *tmp_max_key;
   uint8 save_first_null_comp= param->first_null_comp;
 
@@ -7139,18 +7158,21 @@
       This is not a ROR scan if the key is not Clustered Primary Key.
     */
     param->is_ror_scan= FALSE;
-    records=check_quick_keys(param,idx,key_tree->left,min_key,min_key_flag,
-			     max_key,max_key_flag);
+    records=check_quick_keys(param, idx, key_tree->left,
+                             min_key, min_key_flag, min_keypart,
+			     max_key, max_key_flag, max_keypart);
     if (records == HA_POS_ERROR)			// Impossible
       return records;
   }
 
   tmp_min_key= min_key;
   tmp_max_key= max_key;
-  key_tree->store(param->key[idx][key_tree->part].store_length,
-		  &tmp_min_key,min_key_flag,&tmp_max_key,max_key_flag);
-  min_key_length= (uint) (tmp_min_key- param->min_key);
-  max_key_length= (uint) (tmp_max_key- param->max_key);
+  tmp_min_keypart+= key_tree->store_min(param->key[idx][key_tree->part].store_length,
+                                        &tmp_min_key, min_key_flag);
+  tmp_max_keypart+= key_tree->store_max(param->key[idx][key_tree->part].store_length,
+                                        &tmp_max_key, max_key_flag);
+  min_key_length= (uint) (tmp_min_key - param->min_key);
+  max_key_length= (uint) (tmp_max_key - param->max_key);
 
   if (param->is_ror_scan)
   {
@@ -7173,12 +7195,13 @@
       key_tree->next_key_part->type == SEL_ARG::KEY_RANGE)
   {						// const key as prefix
     if (min_key_length == max_key_length &&
-	!memcmp(min_key,max_key, (uint) (tmp_max_key - max_key)) &&
+	!memcmp(min_key, max_key, (uint) (tmp_max_key - max_key)) &&
 	!key_tree->min_flag && !key_tree->max_flag)
     {
-      tmp=check_quick_keys(param,idx,key_tree->next_key_part,
-			   tmp_min_key, min_key_flag | key_tree->min_flag,
-			   tmp_max_key, max_key_flag | key_tree->max_flag);
+      tmp=check_quick_keys(param,idx,key_tree->next_key_part, tmp_min_key,
+                           min_key_flag | key_tree->min_flag, tmp_min_keypart,
+                           tmp_max_key, max_key_flag | key_tree->max_flag,
+                           tmp_max_keypart);
       goto end;					// Ugly, but efficient
     }
     else
@@ -7190,18 +7213,20 @@
     tmp_min_flag=key_tree->min_flag;
     tmp_max_flag=key_tree->max_flag;
     if (!tmp_min_flag)
+      tmp_min_keypart+=
       key_tree->next_key_part->store_min_key(param->key[idx], &tmp_min_key,
 					     &tmp_min_flag);
     if (!tmp_max_flag)
+      tmp_max_keypart+=
       key_tree->next_key_part->store_max_key(param->key[idx], &tmp_max_key,
 					     &tmp_max_flag);
-    min_key_length= (uint) (tmp_min_key- param->min_key);
-    max_key_length= (uint) (tmp_max_key- param->max_key);
+    min_key_length= (uint) (tmp_min_key - param->min_key);
+    max_key_length= (uint) (tmp_max_key - param->max_key);
   }
   else
   {
-    tmp_min_flag=min_key_flag | key_tree->min_flag;
-    tmp_max_flag=max_key_flag | key_tree->max_flag;
+    tmp_min_flag= min_key_flag | key_tree->min_flag;
+    tmp_max_flag= max_key_flag | key_tree->max_flag;
   }
 
   keynr=param->real_keynr[idx];
@@ -7209,9 +7234,8 @@
   if (!tmp_min_flag && ! tmp_max_flag &&
       (uint) key_tree->part+1 == param->table->key_info[keynr].key_parts &&
       (param->table->key_info[keynr].flags & (HA_NOSAME | HA_END_SPACE_KEY)) ==
-      HA_NOSAME &&
-      min_key_length == max_key_length &&
-      !memcmp(param->min_key,param->max_key,min_key_length) &&
+      HA_NOSAME && min_key_length == max_key_length &&
+      !memcmp(param->min_key, param->max_key, min_key_length) &&
       !param->first_null_comp)
   {
     tmp=1;					// Max one record
@@ -7231,7 +7255,7 @@
           first members of clustered primary key.
       */
       if (!(min_key_length == max_key_length &&
-            !memcmp(min_key,max_key, (uint) (tmp_max_key - max_key)) &&
+            !memcmp(min_key, max_key, (uint) (tmp_max_key - max_key)) &&
             !key_tree->min_flag && !key_tree->max_flag &&
             is_key_scan_ror(param, keynr, key_tree->part + 1)))
         param->is_ror_scan= FALSE;
@@ -7243,11 +7267,12 @@
       key_range min_range;
       min_range.key=    (byte*) param->min_key;
       min_range.length= min_key_length;
+      min_range.keypart_map= make_keypart_map(tmp_min_keypart);
       /* In this case tmp_min_flag contains the handler-read-function */
       min_range.flag=   (ha_rkey_function) (tmp_min_flag ^ GEOM_FLAG);
 
-      tmp= param->table->file->records_in_range(keynr, &min_range,
-                                                (key_range*) 0);
+      tmp= param->table->file->records_in_range(keynr,
+                                                &min_range, (key_range*) 0);
     }
     else
     {
@@ -7257,10 +7282,12 @@
       min_range.length= min_key_length;
       min_range.flag=   (tmp_min_flag & NEAR_MIN ? HA_READ_AFTER_KEY :
                          HA_READ_KEY_EXACT);
+      min_range.keypart_map= make_keypart_map(tmp_min_keypart);
       max_range.key=    (byte*) param->max_key;
       max_range.length= max_key_length;
       max_range.flag=   (tmp_max_flag & NEAR_MAX ?
                          HA_READ_BEFORE_KEY : HA_READ_AFTER_KEY);
+      max_range.keypart_map= make_keypart_map(tmp_max_keypart);
       tmp=param->table->file->records_in_range(keynr,
                                                (min_key_length ? &min_range :
                                                 (key_range*) 0),
@@ -7281,8 +7308,9 @@
       This is not a ROR scan if the key is not Clustered Primary Key.
     */
     param->is_ror_scan= FALSE;
-    tmp=check_quick_keys(param,idx,key_tree->right,min_key,min_key_flag,
-			 max_key,max_key_flag);
+    tmp=check_quick_keys(param, idx, key_tree->right,
+                         min_key, min_key_flag, min_keypart,
+                         max_key, max_key_flag, max_keypart);
     if (tmp == HA_POS_ERROR)
       return tmp;
     records+=tmp;
@@ -7429,6 +7457,7 @@
 {
   QUICK_RANGE *range;
   uint flag;
+  int min_part= key_tree->part-1, max_part=key_tree->part-1;
 
   if (key_tree->left != &null_element)
   {
@@ -7437,16 +7466,18 @@
       return 1;
   }
   char *tmp_min_key=min_key,*tmp_max_key=max_key;
-  key_tree->store(key[key_tree->part].store_length,
-		  &tmp_min_key,min_key_flag,&tmp_max_key,max_key_flag);
+  min_part+= key_tree->store_min(key[key_tree->part].store_length,
+                                 &tmp_min_key,min_key_flag);
+  max_part+= key_tree->store_max(key[key_tree->part].store_length,
+                                 &tmp_max_key,max_key_flag);
 
   if (key_tree->next_key_part &&
       key_tree->next_key_part->part == key_tree->part+1 &&
       key_tree->next_key_part->type == SEL_ARG::KEY_RANGE)
   {						  // const key as prefix
-    if (!((tmp_min_key - min_key) != (tmp_max_key - max_key) ||
-	  memcmp(min_key,max_key, (uint) (tmp_max_key - max_key)) ||
-	  key_tree->min_flag || key_tree->max_flag))
+    if ((tmp_min_key - min_key) == (tmp_max_key - max_key) &&
+         memcmp(min_key, max_key, (uint)(tmp_max_key - max_key))==0 &&
+	 key_tree->min_flag==0 && key_tree->max_flag==0)
     {
       if (get_quick_keys(param,quick,key,key_tree->next_key_part,
 			 tmp_min_key, min_key_flag | key_tree->min_flag,
@@ -7457,11 +7488,15 @@
     {
       uint tmp_min_flag=key_tree->min_flag,tmp_max_flag=key_tree->max_flag;
       if (!tmp_min_flag)
-	key_tree->next_key_part->store_min_key(key, &tmp_min_key,
+      {
+        min_part+= key_tree->next_key_part->store_min_key(key, &tmp_min_key,
 					       &tmp_min_flag);
+      }
       if (!tmp_max_flag)
-	key_tree->next_key_part->store_max_key(key, &tmp_max_key,
+      {
+        max_part+= key_tree->next_key_part->store_max_key(key, &tmp_max_key,
 					       &tmp_max_flag);
+      }
       flag=tmp_min_flag | tmp_max_flag;
     }
   }
@@ -7511,13 +7546,15 @@
   /* Get range for retrieving rows in QUICK_SELECT::get_next */
   if (!(range= new QUICK_RANGE((const char *) param->min_key,
 			       (uint) (tmp_min_key - param->min_key),
+                               min_part >=0 ? make_keypart_map(min_part) : 0,
 			       (const char *) param->max_key,
 			       (uint) (tmp_max_key - param->max_key),
+                               max_part >=0 ? make_keypart_map(max_part) : 0,
 			       flag)))
     return 1;			// out of memory
 
-  set_if_bigger(quick->max_used_key_length,range->min_length);
-  set_if_bigger(quick->max_used_key_length,range->max_length);
+  set_if_bigger(quick->max_used_key_length, range->min_length);
+  set_if_bigger(quick->max_used_key_length, range->max_length);
   set_if_bigger(quick->used_key_parts, (uint) key_tree->part+1);
   if (insert_dynamic(&quick->ranges, (gptr)&range))
     return 1;
@@ -7659,6 +7696,7 @@
 
   range->min_key=range->max_key=(char*) ref->key_buff;
   range->min_length=range->max_length=ref->key_length;
+  range->min_keypart_map= range->max_keypart_map= (1 << ref->key_parts) - 1;
   range->flag= ((ref->key_length == key_info->key_length &&
 		 (key_info->flags & (HA_NOSAME | HA_END_SPACE_KEY)) ==
 		 HA_NOSAME) ? EQ_RANGE : 0);
@@ -7692,8 +7730,10 @@
     *ref->null_ref_key= 1;		// Set null byte then create a range
     if (!(null_range= new (alloc) QUICK_RANGE((char*)ref->key_buff,
                                               ref->key_length,
+                                              (1 << ref->key_parts) - 1,
                                               (char*)ref->key_buff,
                                               ref->key_length,
+                                              (1 << ref->key_parts) - 1,
                                               EQ_RANGE)))
       goto err;
     *ref->null_ref_key= 0;		// Clear null byte
@@ -8146,6 +8186,7 @@
       start_key->flag=   ((last_range->flag & NEAR_MIN) ? HA_READ_AFTER_KEY :
                           (last_range->flag & EQ_RANGE) ?
                           HA_READ_KEY_EXACT : HA_READ_KEY_OR_NEXT);
+      start_key->keypart_map= last_range->min_keypart_map;
       end_key->key=      (const byte*) last_range->max_key;
       end_key->length=   last_range->max_length;
       /*
@@ -8154,6 +8195,7 @@
       */
       end_key->flag=     (last_range->flag & NEAR_MAX ? HA_READ_BEFORE_KEY :
                           HA_READ_AFTER_KEY);
+      end_key->keypart_map= last_range->max_keypart_map;
 
       mrange_slot->range_flag= last_range->flag;
     }
@@ -8203,7 +8245,9 @@
     other              if some error occurred
 */
 
-int QUICK_RANGE_SELECT::get_next_prefix(uint prefix_length, byte *cur_prefix)
+int QUICK_RANGE_SELECT::get_next_prefix(uint prefix_length,
+                                        ulonglong keypart_map,
+                                        byte *cur_prefix)
 {
   DBUG_ENTER("QUICK_RANGE_SELECT::get_next_prefix");
 
@@ -8215,8 +8259,7 @@
     {
       /* Read the next record in the same range with prefix after cur_prefix. */
       DBUG_ASSERT(cur_prefix != 0);
-      result= file->index_read(record, cur_prefix, prefix_length,
-                               HA_READ_AFTER_KEY);
+      result= file->index_read(record, cur_prefix, keypart_map, HA_READ_AFTER_KEY);
       if (result || (file->compare_key(file->end_range) <= 0))
         DBUG_RETURN(result);
     }
@@ -8232,11 +8275,13 @@
 
     start_key.key=    (const byte*) last_range->min_key;
     start_key.length= min(last_range->min_length, prefix_length);
+    start_key.keypart_map= last_range->min_keypart_map & keypart_map;
     start_key.flag=   ((last_range->flag & NEAR_MIN) ? HA_READ_AFTER_KEY :
 		       (last_range->flag & EQ_RANGE) ?
 		       HA_READ_KEY_EXACT : HA_READ_KEY_OR_NEXT);
     end_key.key=      (const byte*) last_range->max_key;
     end_key.length=   min(last_range->max_length, prefix_length);
+    end_key.keypart_map= last_range->max_keypart_map & keypart_map;
     /*
       We use READ_AFTER_KEY here because if we are reading on a key
       prefix we want to find all keys with this prefix
@@ -8244,8 +8289,8 @@
     end_key.flag=     (last_range->flag & NEAR_MAX ? HA_READ_BEFORE_KEY :
 		       HA_READ_AFTER_KEY);
 
-    result= file->read_range_first(last_range->min_length ? &start_key : 0,
-				   last_range->max_length ? &end_key : 0,
+    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),
 				   sorted);
     if (last_range->flag == (UNIQUE_RANGE | EQ_RANGE))
@@ -8285,9 +8330,8 @@
     }
     last_range= *(cur_range++);
 
-    result= file->index_read(record,
-			     (byte*) last_range->min_key,
-			     last_range->min_length,
+    result= file->index_read(record, (byte*) last_range->min_key,
+			     last_range->min_keypart_map,
 			     (ha_rkey_function)(last_range->flag ^ GEOM_FLAG));
     if (result != HA_ERR_KEY_NOT_FOUND && result != HA_ERR_END_OF_FILE)
       DBUG_RETURN(result);
@@ -8419,15 +8463,15 @@
 
     if (last_range->flag & EQ_RANGE)
     {
-      result= file->index_read(record, (byte*) last_range->max_key,
-                               last_range->max_length, HA_READ_KEY_EXACT);
+      result = file->index_read(record, (byte*) last_range->max_key,
+				last_range->max_keypart_map, HA_READ_KEY_EXACT);
     }
     else
     {
       DBUG_ASSERT(last_range->flag & NEAR_MAX ||
                   range_reads_after_key(last_range));
       result=file->index_read(record, (byte*) last_range->max_key,
-			      last_range->max_length,
+			      last_range->max_keypart_map,
 			      ((last_range->flag & NEAR_MAX) ?
 			       HA_READ_BEFORE_KEY :
                                HA_READ_PREFIX_LAST_OR_PREV));
@@ -8747,8 +8791,7 @@
 static inline uint get_field_keypart(KEY *index, Field *field);
 static inline SEL_ARG * get_index_range_tree(uint index, SEL_TREE* range_tree,
                                              PARAM *param, uint *param_idx);
-static bool
-get_constant_key_infix(KEY *index_info, SEL_ARG *index_range_tree,
+static bool get_constant_key_infix(KEY *index_info, SEL_ARG *index_range_tree,
                        KEY_PART_INFO *first_non_group_part,
                        KEY_PART_INFO *min_max_arg_part,
                        KEY_PART_INFO *last_part, THD *thd,
@@ -9146,7 +9189,7 @@
                           NULL;
     first_non_infix_part= min_max_arg_part ?
                           (min_max_arg_part < last_part) ?
-                             min_max_arg_part + 1 :
+                             min_max_arg_part :
                              NULL :
                            NULL;
     if (first_non_group_part &&
@@ -9203,7 +9246,9 @@
     */
     if (first_non_infix_part)
     {
-      for (cur_part= first_non_infix_part; cur_part != last_part; cur_part++)
+      cur_part= first_non_infix_part +
+                (min_max_arg_part && (min_max_arg_part < last_part));
+      for (; cur_part != last_part; cur_part++)
       {
         if (bitmap_is_set(table->read_set, cur_part->field->field_index))
           goto next_index;
@@ -9749,7 +9794,7 @@
 
   RETURN
     New QUICK_GROUP_MIN_MAX_SELECT object if successfully created,
-    NULL o/w.
+    NULL otherwise.
 */
 
 QUICK_SELECT_I *
@@ -9762,10 +9807,10 @@
   quick= new QUICK_GROUP_MIN_MAX_SELECT(param->table,
                                         param->thd->lex->current_select->join,
                                         have_min, have_max, min_max_arg_part,
-                                        group_prefix_len, used_key_parts,
-                                        index_info, index, read_cost, records,
-                                        key_infix_len, key_infix,
-                                        parent_alloc);
+                                        group_prefix_len, group_key_parts,
+                                        used_key_parts, index_info, index,
+                                        read_cost, records, key_infix_len,
+                                        key_infix, parent_alloc);
   if (!quick)
     DBUG_RETURN(NULL);
 
@@ -9854,7 +9899,7 @@
 QUICK_GROUP_MIN_MAX_SELECT(TABLE *table, JOIN *join_arg, bool have_min_arg,
                            bool have_max_arg,
                            KEY_PART_INFO *min_max_arg_part_arg,
-                           uint group_prefix_len_arg,
+                           uint group_prefix_len_arg, uint group_key_parts_arg,
                            uint used_key_parts_arg, KEY *index_info_arg,
                            uint use_index, double read_cost_arg,
                            ha_rows records_arg, uint key_infix_len_arg,
@@ -9864,7 +9909,7 @@
    have_max(have_max_arg), seen_first_key(FALSE),
    min_max_arg_part(min_max_arg_part_arg), key_infix(key_infix_arg),
    key_infix_len(key_infix_len_arg), min_functions_it(NULL),
-   max_functions_it(NULL)
+   max_functions_it(NULL), group_key_parts(group_key_parts_arg)
 {
   head=       table;
   file=       head->file;
@@ -9874,6 +9919,7 @@
   read_time= read_cost_arg;
   records= records_arg;
   used_key_parts= used_key_parts_arg;
+  real_key_parts= used_key_parts_arg;
   real_prefix_len= group_prefix_len + key_infix_len;
   group_prefix= NULL;
   min_max_arg_len= min_max_arg_part ? min_max_arg_part->store_length : 0;
@@ -10040,7 +10086,9 @@
       range_flag|= EQ_RANGE;  /* equality condition */
   }
   range= new QUICK_RANGE(sel_range->min_value, min_max_arg_len,
+                         make_keypart_map(sel_range->part),
                          sel_range->max_value, min_max_arg_len,
+                         make_keypart_map(sel_range->part),
                          range_flag);
   if (!range)
     return TRUE;
@@ -10279,7 +10327,8 @@
       first sub-group with the extended prefix.
     */
     if (!have_min && !have_max && key_infix_len > 0)
-      result= file->index_read(record, group_prefix, real_prefix_len,
+      result= file->index_read(record, group_prefix,
+                               make_prev_keypart_map(real_key_parts),
                                HA_READ_KEY_EXACT);
 
     result= have_min ? min_res : have_max ? max_res : result;
@@ -10342,7 +10391,8 @@
     /* Apply the constant equality conditions to the non-group select fields */
     if (key_infix_len > 0)
     {
-      if ((result= file->index_read(record, group_prefix, real_prefix_len,
+      if ((result= file->index_read(record, group_prefix,
+                                    make_prev_keypart_map(real_key_parts),
                                     HA_READ_KEY_EXACT)))
         DBUG_RETURN(result);
     }
@@ -10359,7 +10409,7 @@
       /* Find the first subsequent record without NULL in the MIN/MAX field. */
       key_copy(tmp_record, record, index_info, 0);
       result= file->index_read(record, tmp_record,
-                               real_prefix_len + min_max_arg_len,
+                               make_keypart_map(real_key_parts),
                                HA_READ_AFTER_KEY);
       /*
         Check if the new record belongs to the current group by comparing its
@@ -10415,7 +10465,8 @@
   if (min_max_ranges.elements > 0)
     result= next_max_in_range();
   else
-    result= file->index_read(record, group_prefix, real_prefix_len,
+    result= file->index_read(record, group_prefix,
+                             make_prev_keypart_map(real_key_parts),
                              HA_READ_PREFIX_LAST);
   DBUG_RETURN(result);
 }
@@ -10451,7 +10502,7 @@
   {
     byte *cur_prefix= seen_first_key ? group_prefix : NULL;
     if ((result= quick_prefix_select->get_next_prefix(group_prefix_len,
-                                                      cur_prefix)))
+                         (ULL(1) << group_key_parts) - 1, cur_prefix)))
       DBUG_RETURN(result);
     seen_first_key= TRUE;
   }
@@ -10467,7 +10518,8 @@
     else
     {
       /* Load the first key in this group into record. */
-      result= file->index_read(record, group_prefix, group_prefix_len,
+      result= file->index_read(record, group_prefix,
+                               make_prev_keypart_map(group_key_parts),
                                HA_READ_AFTER_KEY);
       if (result)
         DBUG_RETURN(result);
@@ -10510,6 +10562,7 @@
 {
   ha_rkey_function find_flag;
   uint search_prefix_len;
+  ulonglong keypart_map;
   QUICK_RANGE *cur_range;
   bool found_null= FALSE;
   int result= HA_ERR_KEY_NOT_FOUND;
@@ -10531,8 +10584,9 @@
 
     if (cur_range->flag & NO_MIN_RANGE)
     {
-      find_flag= HA_READ_KEY_EXACT;
       search_prefix_len= real_prefix_len;
+      keypart_map= (ULL(1) << real_key_parts) - 1;
+      find_flag= HA_READ_KEY_EXACT;
     }
     else
     {
@@ -10540,13 +10594,13 @@
       memcpy(group_prefix + real_prefix_len, cur_range->min_key,
              cur_range->min_length);
       search_prefix_len= real_prefix_len + min_max_arg_len;
+      keypart_map= (ULL(2) << real_key_parts) - 1;
       find_flag= (cur_range->flag & (EQ_RANGE | NULL_RANGE)) ?
                  HA_READ_KEY_EXACT : (cur_range->flag & NEAR_MIN) ?
                  HA_READ_AFTER_KEY : HA_READ_KEY_OR_NEXT;
     }
 
-    result= file->index_read(record, group_prefix, search_prefix_len,
-                             find_flag);
+    result= file->index_read(record, group_prefix, keypart_map, find_flag);
     if (result)
     {
       if ((result == HA_ERR_KEY_NOT_FOUND || result == HA_ERR_END_OF_FILE) &&
@@ -10644,6 +10698,7 @@
 {
   ha_rkey_function find_flag;
   uint search_prefix_len;
+  ulonglong keypart_map;
   QUICK_RANGE *cur_range;
   int result;
 
@@ -10665,8 +10720,9 @@
 
     if (cur_range->flag & NO_MAX_RANGE)
     {
-      find_flag= HA_READ_PREFIX_LAST;
       search_prefix_len= real_prefix_len;
+      keypart_map= (ULL(1) << real_key_parts) - 1;
+      find_flag= HA_READ_PREFIX_LAST;
     }
     else
     {
@@ -10674,13 +10730,13 @@
       memcpy(group_prefix + real_prefix_len, cur_range->max_key,
              cur_range->max_length);
       search_prefix_len= real_prefix_len + min_max_arg_len;
+      keypart_map= (ULL(2) << real_key_parts) - 1;
       find_flag= (cur_range->flag & EQ_RANGE) ?
                  HA_READ_KEY_EXACT : (cur_range->flag & NEAR_MAX) ?
                  HA_READ_BEFORE_KEY : HA_READ_PREFIX_LAST_OR_PREV;
     }
 
-    result= file->index_read(record, group_prefix, search_prefix_len,
-                             find_flag);
+    result= file->index_read(record, group_prefix, keypart_map, find_flag);
 
     if (result)
     {

--- 1.248/sql/sql_insert.cc	2007-03-06 13:45:06 +01:00
+++ 1.249/sql/sql_insert.cc	2007-03-06 13:45:06 +01:00
@@ -947,6 +947,8 @@
   DBUG_PRINT("enter", ("table_list 0x%lx, table 0x%lx, view %d",
 		       (ulong)table_list, (ulong)table,
 		       (int)insert_into_view));
+  /* INSERT should have a SELECT or VALUES clause */
+  DBUG_ASSERT (!select_insert || !values);
 
   /*
     For subqueries in VALUES() we should not see the table in which we are
@@ -978,44 +980,40 @@
   if (mysql_prepare_insert_check_table(thd, table_list, fields, select_insert))
     DBUG_RETURN(TRUE);
 
-  /* Save the state of the current name resolution context. */
-  ctx_state.save_state(context, table_list);
-
-  /*
-    Perform name resolution only in the first table - 'table_list',
-    which is the table that is inserted into.
-  */
-  table_list->next_local= 0;
-  context->resolve_in_table_list_only(table_list);
 
   /* Prepare the fields in the statement. */
-  if (values &&
-      !(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)
+  if (values)
   {
-    select_lex->no_wrap_view_item= TRUE;
-    res= check_update_fields(thd, context->table_list, update_fields, &map);
-    select_lex->no_wrap_view_item= FALSE;
+    /* if we have INSERT ... VALUES () we cannot have a GROUP BY clause */
+    DBUG_ASSERT (!select_lex->group_list.elements);
+
+    /* Save the state of the current name resolution context. */
+    ctx_state.save_state(context, table_list);
+
     /*
-      When we are not using GROUP BY we can refer to other tables in the
-      ON DUPLICATE KEY part.
-    */       
-    if (select_lex->group_list.elements == 0)
-    {
-      context->table_list->next_local=       ctx_state.save_next_local;
-      /* first_name_resolution_table was set by resolve_in_table_list_only() */
-      context->first_name_resolution_table->
-        next_name_resolution_table=          ctx_state.save_next_local;
+      Perform name resolution only in the first table - 'table_list',
+      which is the table that is inserted into.
+     */
+    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)
+    {
+      select_lex->no_wrap_view_item= TRUE;
+      res= check_update_fields(thd, context->table_list, update_fields, &map);
+      select_lex->no_wrap_view_item= FALSE;
     }
+
+    /* Restore the current context. */
+    ctx_state.restore_state(context, table_list);
+
     if (!res)
       res= setup_fields(thd, 0, update_values, MARK_COLUMNS_READ, 0, 0);
   }
 
-  /* Restore the current context. */
-  ctx_state.restore_state(context, table_list);
-
   if (res)
     DBUG_RETURN(res);
 
@@ -2470,7 +2468,6 @@
 
   if (info.handle_duplicates == DUP_UPDATE)
   {
-    /* Save the state of the current name resolution context. */
     Name_resolution_context *context= &lex->select_lex.context;
     Name_resolution_context_state ctx_state;
 
@@ -2486,18 +2483,40 @@
                                     *info.update_fields, &map);
     lex->select_lex.no_wrap_view_item= FALSE;
     /*
-      When we are not using GROUP BY we can refer to other tables in the
-      ON DUPLICATE KEY part
-    */       
-    if (lex->select_lex.group_list.elements == 0)
-    {
-      context->table_list->next_local=       ctx_state.save_next_local;
-      /* first_name_resolution_table was set by resolve_in_table_list_only() */
-      context->first_name_resolution_table->
-        next_name_resolution_table=          ctx_state.save_next_local;
+      When we are not using GROUP BY and there are no ungrouped aggregate functions 
+      we can refer to other tables in the ON DUPLICATE KEY part.
+      We use next_name_resolution_table descructively, so check it first (views?)
+    */
+    DBUG_ASSERT (!table_list->next_name_resolution_table);
+    if (lex->select_lex.group_list.elements == 0 &&
+        !lex->select_lex.with_sum_func)
+      /*
+        We must make a single context out of the two separate name resolution contexts :
+        the INSERT table and the tables in the SELECT part of INSERT ... SELECT.
+        To do that we must concatenate the two lists
+      */  
+      table_list->next_name_resolution_table= 
+        ctx_state.get_first_name_resolution_table();
+
+    res= res || setup_fields(thd, 0, *info.update_values,
+                             MARK_COLUMNS_READ, 0, 0);
+    if (!res)
+    {
+      /*
+        Traverse the update values list and substitute fields from the
+        select for references (Item_ref objects) to them. This is done in
+        order to get correct values from those fields when the select
+        employs a temporary table.
+      */
+      List_iterator<Item> li(*info.update_values);
+      Item *item;
+
+      while ((item= li++))
+      {
+        item->transform(&Item::update_value_transformer,
+                        (byte*)lex->current_select);
+      }
     }
-    res= res || setup_fields(thd, 0, *info.update_values, MARK_COLUMNS_READ,
-                             0, 0);
 
     /* Restore the current context. */
     ctx_state.restore_state(context, table_list);

--- 1.494/sql/sql_select.cc	2007-03-06 13:45:06 +01:00
+++ 1.495/sql/sql_select.cc	2007-03-06 13:45:06 +01:00
@@ -268,6 +268,70 @@
 
 
 /*
+  Fix fields referenced from inner selects.
+
+  SYNOPSIS
+    fix_inner_refs()
+    thd               Thread handle
+    all_fields        List of all fields used in select
+    select            Current select
+    ref_pointer_array Array of references to Items used in current select
+
+  DESCRIPTION
+    The function fixes fields referenced from inner selects and
+    also fixes references (Item_ref objects) to these fields. Each field
+    is fixed as a usual hidden field of the current select - it is added
+    to the all_fields list and the pointer to it is saved in the
+    ref_pointer_array if latter is provided.
+    After the field has been fixed we proceed with fixing references
+    (Item_ref objects) to this field from inner subqueries. If the
+    ref_pointer_array is provided then Item_ref objects is set to
+    reference element in that array with the pointer to the field.
+
+  RETURN
+    TRUE  an error occured
+    FALSE ok
+*/
+
+bool
+fix_inner_refs(THD *thd, List<Item> &all_fields, SELECT_LEX *select,
+                 Item **ref_pointer_array)
+{
+  Item_outer_ref *ref;
+  bool res= FALSE;
+  List_iterator<Item_outer_ref> ref_it(select->inner_refs_list);
+  while ((ref= ref_it++))
+  {
+    Item_field *item= ref->outer_field;
+    /*
+      TODO: this field item already might be present in the select list.
+      In this case instead of adding new field item we could use an
+      existing one. The change will lead to less operations for copying fields,
+      smaller temporary tables and less data passed through filesort.
+    */
+    if (ref_pointer_array)
+    {
+      int el= all_fields.elements;
+      ref_pointer_array[el]= (Item*)item;
+      /* Add the field item to the select list of the current select. */
+      all_fields.push_front((Item*)item);
+      /*
+        If it's needed reset each Item_ref item that refers this field with
+        a new reference taken from ref_pointer_array.
+      */
+      ref->ref= ref_pointer_array + el;
+    }
+    if (!ref->fixed && ref->fix_fields(thd, 0))
+    {
+      res= TRUE;
+      break;
+    }
+    thd->used_tables|= item->used_tables();
+  }
+  return res;
+}
+
+/*
   Function to setup clauses without sum functions
 */
 inline int setup_without_group(THD *thd, Item **ref_pointer_array,
@@ -394,6 +458,10 @@
   if (having && having->with_sum_func)
     having->split_sum_func2(thd, ref_pointer_array, all_fields,
                             &having, TRUE);
+  if (select_lex->inner_refs_list.elements &&
+      fix_inner_refs(thd, all_fields, select_lex, ref_pointer_array))
+    DBUG_RETURN(-1);
+
   if (select_lex->inner_sum_func_list)
   {
     Item_sum *end=select_lex->inner_sum_func_list;
@@ -474,6 +542,9 @@
     }
   }
 
+  if (!procedure && result && result->prepare(fields_list, unit_arg))
+    goto err;					/* purecov: inspected */
+
   /* Init join struct */
   count_field_types(&tmp_table_param, all_fields, 0);
   ref_pointer_array_size= all_fields.elements*sizeof(Item*);
@@ -487,9 +558,6 @@
     goto err;
   }
 #endif
-  if (!procedure && result && result->prepare(fields_list, unit_arg))
-    goto err;					/* purecov: inspected */
-
   if (select_lex->olap == ROLLUP_TYPE && rollup_init())
     goto err;
   if (alloc_func_list())
@@ -2884,15 +2952,9 @@
           /*
             We can't use indexes if the effective collation
             of the operation differ from the field collation.
-
-            We also cannot use index on a text column, as the column may
-            contain 'x' 'x\t' 'x ' and 'read_next_same' will stop after
-            'x' when searching for WHERE col='x '
           */
           if (field->cmp_type() == STRING_RESULT &&
-              (((Field_str*)field)->charset() != cond->compare_collation() ||
-               ((*value)->type() != Item::NULL_ITEM &&
-                (field->flags & BLOB_FLAG) && !field->binary())))
+              ((Field_str*)field)->charset() != cond->compare_collation())
             return;
         }
       }
@@ -5287,13 +5349,15 @@
 				    key_part->length,
 				    keyuse->val);
   }
-  else if (keyuse->val->type() == Item::FIELD_ITEM)
+  else if (keyuse->val->type() == Item::FIELD_ITEM ||
+           (keyuse->val->type() == Item::REF_ITEM &&
+            ((Item_ref*)keyuse->val)->ref_type() == Item_ref::OUTER_REF) )
     return new store_key_field(thd,
 			       key_part->field,
 			       key_buff + maybe_null,
 			       maybe_null ? key_buff : 0,
 			       key_part->length,
-			       ((Item_field*) keyuse->val)->field,
+			       ((Item_field*) keyuse->val->real_item())->field,
 			       keyuse->val->full_name());
   return new store_key_item(thd,
 			    key_part->field,
@@ -8887,7 +8951,8 @@
       type they needed to be handled separately.
     */
     if ((type= item->field_type()) == MYSQL_TYPE_DATETIME ||
-        type == MYSQL_TYPE_TIME || type == MYSQL_TYPE_DATE)
+        type == MYSQL_TYPE_TIME || type == MYSQL_TYPE_DATE ||
+        type == MYSQL_TYPE_TIMESTAMP)
       new_field= item->tmp_table_field_from_field_type(table, 1);
     /* 
       Make sure that the blob fits into a Field_varstring which has 
@@ -9003,8 +9068,7 @@
   Item *orig_item= 0;
 
   if (type != Item::FIELD_ITEM &&
-      item->real_item()->type() == Item::FIELD_ITEM &&
-      !((Item_ref *) item)->depended_from)
+      item->real_item()->type() == Item::FIELD_ITEM)
   {
     orig_item= item;
     item= item->real_item();
@@ -13723,10 +13787,8 @@
   param->quick_group=1;
   while ((field=li++))
   {
-    Item::Type type=field->type();
     Item::Type real_type= field->real_item()->type();
-    if (type == Item::FIELD_ITEM || (real_type == Item::FIELD_ITEM &&
-        !((Item_ref *) field)->depended_from))
+    if (real_type == Item::FIELD_ITEM)
       param->field_count++;
     else if (real_type == Item::SUM_FUNC_ITEM)
     {

--- 1.47/storage/blackhole/ha_blackhole.cc	2007-03-06 13:45:06 +01:00
+++ 1.48/storage/blackhole/ha_blackhole.cc	2007-03-06 13:45:06 +01:00
@@ -156,7 +156,7 @@
                              enum ha_rkey_function find_flag)
 {
   DBUG_ENTER("ha_blackhole::index_read");
-  DBUG_RETURN(0);
+  DBUG_RETURN(HA_ERR_END_OF_FILE);
 }
 
 

--- 1.413/sql/ha_ndbcluster.cc	2007-03-06 13:45:06 +01:00
+++ 1.414/sql/ha_ndbcluster.cc	2007-03-06 13:45:06 +01:00
@@ -2764,10 +2764,12 @@
   {
     Ndb *ndb= get_ndb();
     Uint64 next_val= (Uint64) table->next_number_field->val_int() + 1;
+#ifndef DBUG_OFF
     char buff[22];
     DBUG_PRINT("info", 
                ("Trying to set next auto increment value to %s",
                 llstr(next_val, buff)));
+#endif
     Ndb_tuple_id_range_guard g(m_share);
     if (ndb->setAutoIncrementValue(m_table, g.range, next_val, TRUE)
         == -1)
@@ -3986,7 +3988,7 @@
       }
       else
       {
-        int res= trans->restart();
+        IF_DBUG(int res=) trans->restart();
         DBUG_ASSERT(res == 0);
       }
     }
@@ -4704,7 +4706,9 @@
   // Set autoincrement
   if (field->flags & AUTO_INCREMENT_FLAG) 
   {
+#ifndef DBUG_OFF
     char buff[22];
+#endif
     col.setAutoIncrement(TRUE);
     ulonglong value= info->auto_increment_value ?
       info->auto_increment_value : (ulonglong) 1;
@@ -5375,7 +5379,7 @@
   {
     DBUG_PRINT("NDB_SHARE", ("%s temporary  use_count: %u",
                              share->key, share->use_count));
-    int r= rename_share(share, to);
+    IF_DBUG(int r=) rename_share(share, to);
     DBUG_ASSERT(r == 0);
   }
 #endif
@@ -5396,8 +5400,8 @@
 #ifdef HAVE_NDB_BINLOG
     if (share)
     {
-      int r= rename_share(share, from);
-      DBUG_ASSERT(r == 0);
+      IF_DBUG(int ret=) rename_share(share, from);
+      DBUG_ASSERT(ret == 0);
       /* ndb_share reference temporary free */
       DBUG_PRINT("NDB_SHARE", ("%s temporary free  use_count: %u",
                                share->key, share->use_count));
@@ -7255,7 +7259,9 @@
     if (share->commit_count != 0)
     {
       *commit_count= share->commit_count;
+#ifndef DBUG_OFF
       char buff[22];
+#endif
       DBUG_PRINT("info", ("Getting commit_count: %s from share",
                           llstr(share->commit_count, buff)));
       pthread_mutex_unlock(&share->mutex);
@@ -7291,7 +7297,9 @@
   pthread_mutex_lock(&share->mutex);
   if (share->commit_count_lock == lock)
   {
+#ifndef DBUG_OFF
     char buff[22];
+#endif
     DBUG_PRINT("info", ("Setting commit_count to %s",
                         llstr(stat.commit_count, buff)));
     share->commit_count= stat.commit_count;
@@ -7350,7 +7358,9 @@
   bool is_autocommit= !(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN));
   char *dbname= full_name;
   char *tabname= dbname+strlen(dbname)+1;
+#ifndef DBUG_OFF
   char buff[22], buff2[22];
+#endif
   DBUG_ENTER("ndbcluster_cache_retrieval_allowed");
   DBUG_PRINT("enter", ("dbname: %s, tabname: %s, is_autocommit: %d",
                        dbname, tabname, is_autocommit));
@@ -7417,7 +7427,9 @@
                                           ulonglong *engine_data)
 {
   Uint64 commit_count;
+#ifndef DBUG_OFF
   char buff[22];
+#endif
   bool is_autocommit= !(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN));
   DBUG_ENTER("ha_ndbcluster::register_query_cache_table");
   DBUG_PRINT("enter",("dbname: %s, tabname: %s, is_autocommit: %d",
@@ -7862,7 +7874,9 @@
   int retries= 10;
   int reterr= 0;
   int retry_sleep= 30 * 1000; /* 30 milliseconds */
+#ifndef DBUG_OFF
   char buff[22], buff2[22], buff3[22], buff4[22];
+#endif
   DBUG_ENTER("ndb_get_table_statistics");
   DBUG_PRINT("enter", ("table: %s", ndbtab->getName()));
 
@@ -8680,7 +8694,9 @@
             ndb_get_table_statistics(NULL, FALSE, ndb,
                                      ndbtab_g.get_table(), &stat) == 0)
         {
+#ifndef DBUG_OFF
           char buff[22], buff2[22];
+#endif
           DBUG_PRINT("info",
                      ("Table: %s  commit_count: %s  rows: %s",
                       share->key,
@@ -9532,8 +9548,8 @@
           DBUG_PRINT("info", ("INT_ITEM"));
           if (context->expecting(Item::INT_ITEM)) 
           {
-            Item_int *int_item= (Item_int *) item;      
-            DBUG_PRINT("info", ("value %ld", (long) int_item->value));
+            DBUG_PRINT("info", ("value %ld",
+                                (long) ((Item_int*) item)->value));
             NDB_ITEM_QUALIFICATION q;
             q.value_type= Item::INT_ITEM;
             curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item);
@@ -9559,8 +9575,7 @@
           DBUG_PRINT("info", ("REAL_ITEM"));
           if (context->expecting(Item::REAL_ITEM)) 
           {
-            Item_float *float_item= (Item_float *) item;      
-            DBUG_PRINT("info", ("value %f", float_item->value));
+            DBUG_PRINT("info", ("value %f", ((Item_float*) item)->value));
             NDB_ITEM_QUALIFICATION q;
             q.value_type= Item::REAL_ITEM;
             curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item);
@@ -9607,8 +9622,8 @@
           DBUG_PRINT("info", ("DECIMAL_ITEM"));
           if (context->expecting(Item::DECIMAL_ITEM)) 
           {
-            Item_decimal *decimal_item= (Item_decimal *) item;      
-            DBUG_PRINT("info", ("value %f", decimal_item->val_real()));
+            DBUG_PRINT("info", ("value %f",
+                                ((Item_decimal*) item)->val_real()));
             NDB_ITEM_QUALIFICATION q;
             q.value_type= Item::DECIMAL_ITEM;
             curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item);

--- 1.84/sql/ha_partition.cc	2007-03-06 13:45:06 +01:00
+++ 1.85/sql/ha_partition.cc	2007-03-06 13:45:06 +01:00
@@ -158,7 +158,7 @@
 
 ha_partition::ha_partition(handlerton *hton, TABLE_SHARE *share)
   :handler(hton, share), m_part_info(NULL), m_create_handler(FALSE),
-   m_is_sub_partitioned(0)
+   m_is_sub_partitioned(0), is_clone(FALSE)
 {
   DBUG_ENTER("ha_partition::ha_partition(table)");
   init_handler_variables();
@@ -180,8 +180,7 @@
 ha_partition::ha_partition(handlerton *hton, partition_info *part_info)
   :handler(hton, NULL), m_part_info(part_info),
    m_create_handler(TRUE),
-   m_is_sub_partitioned(m_part_info->is_sub_partitioned())
-
+   m_is_sub_partitioned(m_part_info->is_sub_partitioned()), is_clone(FALSE)
 {
   DBUG_ENTER("ha_partition::ha_partition(part_info)");
   init_handler_variables();
@@ -2262,9 +2261,12 @@
   }
 
   /* Initialise the bitmap we use to determine what partitions are used */
-  if (bitmap_init(&(m_part_info->used_partitions), NULL, m_tot_parts, TRUE))
-    DBUG_RETURN(1);
-  bitmap_set_all(&(m_part_info->used_partitions));
+  if (!is_clone)
+  {
+    if (bitmap_init(&(m_part_info->used_partitions), NULL, m_tot_parts, TRUE))
+      DBUG_RETURN(1);
+    bitmap_set_all(&(m_part_info->used_partitions));
+  }
 
   /* Recalculate table flags as they may change after open */
   m_table_flags= m_file[0]->table_flags();
@@ -2320,6 +2322,19 @@
   DBUG_RETURN(error);
 }
 
+handler *ha_partition::clone(MEM_ROOT *mem_root)
+{
+  handler *new_handler= get_new_handler(table->s, mem_root, table->s->db_type);
+  ((ha_partition*)new_handler)->m_part_info= m_part_info;
+  ((ha_partition*)new_handler)->is_clone= TRUE;
+  if (new_handler && !new_handler->ha_open(table,
+                                           table->s->normalized_path.str,
+                                           table->db_stat,
+                                           HA_OPEN_IGNORE_IF_LOCKED))
+    return new_handler;
+  return NULL;
+}
+
 
 /*
   Close handler object
@@ -2346,7 +2361,8 @@
   DBUG_ENTER("ha_partition::close");
 
   delete_queue(&m_queue);
-  bitmap_free(&(m_part_info->used_partitions));
+  if (!is_clone)
+    bitmap_free(&(m_part_info->used_partitions));
   file= m_file;
 
 repeat:

--- 1.33/sql/ha_partition.h	2007-03-06 13:45:06 +01:00
+++ 1.34/sql/ha_partition.h	2007-03-06 13:45:06 +01:00
@@ -132,7 +132,13 @@
   THR_LOCK_DATA lock;                   /* MySQL lock */
   PARTITION_SHARE *share;               /* Shared lock info */
 
+  /* 
+    TRUE <=> this object was created with ha_partition::clone and doesn't
+    "own" the m_part_info structure.
+  */
+  bool is_clone;
 public:
+  handler *clone(MEM_ROOT *mem_root);
   virtual void set_part_info(partition_info *part_info)
   {
      m_part_info= part_info;

--- 1.55/sql/sql_help.cc	2007-03-06 13:45:06 +01:00
+++ 1.56/sql/sql_help.cc	2007-03-06 13:45:06 +01:00
@@ -661,6 +661,8 @@
     Init tables and fields to be usable from items
     tables do not contain VIEWs => we can pass 0 as conds
   */
+  thd->lex->select_lex.context.table_list=
+    thd->lex->select_lex.context.first_name_resolution_table= &tables[0];
   if (setup_tables(thd, &thd->lex->select_lex.context,
                    &thd->lex->select_lex.top_join_list,
                    tables, &leaves, FALSE))
Thread
bk commit into 5.1 tree (serg:1.2454)Sergei Golubchik6 Mar