List:Commits« Previous MessageNext Message »
From:Oystein Grovlen Date:September 27 2010 1:47pm
Subject:bzr commit into mysql-next-mr-bugfixing branch (oystein.grovlen:3245) WL#5559
View as plain text  
#At file:///home/og136792/mysql/mysql-next-mr-wl5559/ based on revid:oystein.grovlen@stripped

 3245 Oystein Grovlen	2010-09-27
      WL#5559 -  Factor tmp table out of optimizer.
        Patch 2: Remove curr_join references from JOIN::exec
      
      Most references in JOIN::exec to member fields are indirect
      through local variable curr_join, which may either refer to
      the original JOIN object or a temporary copy of it.  This
      complicates the code significantly.
      
      In order to simplify the code and ease further refactoring of 
      JOIN::exec, this removes the need for curr_join by, when a 
      temporary copy is used, executing the code directly on the
      temporary object.
      
      This is achieved by creating a private method, 
      JOIN::execute(JOIN *parent) to be called from JOIN::exec,
      and move all code after creation of the first temporary table
      to this method. If a temporary copy is needed, then 
      tmp_join->execute(this) is called. Otherwise, this->execute(NULL).
      
      The code makes sure that necessary execution data is copied
      from the temporary JOIN object and back to its parent in order
      to be able to reuse it for later executions as before.
      
      A limited number of example queries has been used to verify that
      there is no performance regression.  Also, using gprof it has been
      verified that the functions previously called from JOIN::exec, 
      is still called the same number of times with the new approach.
     @ sql/sql_select.cc
        Move code in JOIN::exec after creation of first temporary
        table to a new private method, JOIN::execute.  This way,
        is it possible to remove all references to curr_join by
        calling JOIN::execute directly on tmp_join instead.
        
        If exeuting on tmp_join, parameter parent of JOIN::execute
        will refer to the original JOIN object.  If this is set,
        it is made sure that execution data is copied back to 
        parent object for use in later executions.
        
        A local variable main_join has been added to JOIN::execute.
        It will allways refer to original JOIN object, and is used
        as parameter in method calls that previously was called with
        curr_join.
     @ sql/sql_select.h
        Add private method JOIN::execute to be called from JOIN::exec.
        Using this method, direct execution on a temporary copy of the
        JOIN object can be done, instead of using indirect references to
        all members variables.

    modified:
      sql/sql_select.cc
      sql/sql_select.h
=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc	2010-09-27 10:56:33 +0000
+++ b/sql/sql_select.cc	2010-09-27 13:47:23 +0000
@@ -2593,7 +2593,6 @@ void
 JOIN::exec()
 {
   List<Item> *columns_list= &fields_list;
-  int      tmp_error;
   DBUG_ENTER("JOIN::exec");
 
   thd_proc_info(thd, "executing");
@@ -2715,18 +2714,7 @@ JOIN::exec()
                     !tables ? "No tables used" : NullS);
     DBUG_VOID_RETURN;
   }
-
-  JOIN *curr_join= this;
-  List<Item> *curr_all_fields= &all_fields;
-  List<Item> *curr_fields_list= &fields_list;
-  TABLE *curr_tmp_table= 0;
-  /*
-    Initialize examined rows here because the values from all join parts
-    must be accumulated in examined_row_count. Hence every join
-    iteration must count from zero.
-  */
-  curr_join->examined_rows= 0;
-
+  
   /*
     The loose index scan access method guarantees that all grouping or
     duplicate row elimination (for distinct) is already performed
@@ -2739,7 +2727,7 @@ JOIN::exec()
     join_tab element of the plan for its access method.
   */
   if (join_tab && join_tab->is_using_loose_index_scan())
-    tmp_table_param.precomputed_group_by= 
+    tmp_table_param.precomputed_group_by=
       !join_tab->is_using_agg_loose_index_scan();
 
   /* Create a tmp table if distinct or if the sort is too complicated */
@@ -2750,18 +2738,47 @@ JOIN::exec()
       if (create_intermediate_table())
 	DBUG_VOID_RETURN;
     }
-    curr_tmp_table= exec_tmp_table1;
 
     if (tmp_join)
     {
       /*
-        We are in a non-cacheable subquery. Get the saved join structure
-        after creation of temporary table.
-        (curr_join may have been modified during last exection and we need
-        to reset it)
+        We are in a non-cacheable subquery. Use the saved join
+        structure after creation of temporary table. (This join may
+        have been modified during last execution and we need to reset
+        it)
       */
-      curr_join= tmp_join;
+      tmp_join->execute(this);
+      error= tmp_join->error;
+      DBUG_VOID_RETURN;
     }
+  }
+
+  execute(NULL);
+  DBUG_VOID_RETURN;
+}
+
+void
+JOIN::execute(JOIN *parent)
+{
+  DBUG_ENTER("JOIN::execute");
+  int tmp_error;
+  List<Item> *curr_all_fields= &all_fields;
+  List<Item> *curr_fields_list= &fields_list;
+  TABLE *curr_tmp_table= 0;
+  JOIN *main_join= (parent) ? parent : this;
+
+  /*
+    Initialize examined rows here because the values from all join parts
+    must be accumulated in examined_row_count. Hence every join
+    iteration must count from zero.
+  */
+  examined_rows= 0;
+
+  /* Create a tmp table if distinct or if the sort is too complicated */
+  if (need_tmp)
+  {
+    DBUG_ASSERT(exec_tmp_table1);
+    curr_tmp_table= exec_tmp_table1;
 
     /* Copy data to the temporary table */
     thd_proc_info(thd, "Copying to tmp table");
@@ -2772,24 +2789,20 @@ JOIN::exec()
       order.  Exception: LooseScan strategy for semijoin requires
       sorted access even if final result is not to be sorted.
     */
-    if (!curr_join->sort_and_group &&
-        curr_join->const_tables != curr_join->tables && 
-        curr_join->best_positions[curr_join->const_tables].sj_strategy 
-          != SJ_OPT_LOOSE_SCAN)
-      curr_join->join_tab[curr_join->const_tables].sorted= 0;
-    if ((tmp_error= do_select(curr_join, (List<Item> *) 0, curr_tmp_table, 0)))
+    if (!sort_and_group && const_tables != tables && 
+        best_positions[const_tables].sj_strategy != SJ_OPT_LOOSE_SCAN)
+      join_tab[const_tables].sorted= 0;
+    if ((tmp_error= do_select(this, (List<Item> *) 0, curr_tmp_table, 0)))
     {
       error= tmp_error;
       DBUG_VOID_RETURN;
     }
     curr_tmp_table->file->info(HA_STATUS_VARIABLE);
     
-    if (curr_join->having)
-      curr_join->having= curr_join->tmp_having= 0; // Allready done
+    if (having)
+      having= tmp_having= 0; // Already done
     
     /* Change sum_fields reference to calculated fields in tmp_table */
-    if (curr_join != this)
-      curr_join->all_fields= *curr_all_fields;
     if (!items1)
     {
       items1= items0 + all_fields.elements;
@@ -2808,30 +2821,28 @@ JOIN::exec()
 				      fields_list.elements, all_fields))
 	  DBUG_VOID_RETURN;
       }
-      if (curr_join != this)
+      if (parent)
       {
-        curr_join->tmp_all_fields1= tmp_all_fields1;
-        curr_join->tmp_fields_list1= tmp_fields_list1;
+        parent->items1= items1;
+        parent->tmp_all_fields1= tmp_all_fields1;
+        parent->tmp_fields_list1= tmp_fields_list1;
       }
-      curr_join->items1= items1;
     }
     curr_all_fields= &tmp_all_fields1;
     curr_fields_list= &tmp_fields_list1;
-    curr_join->set_items_ref_array(items1);
+    set_items_ref_array(items1);
     
     if (sort_and_group || curr_tmp_table->group)
     {
-      curr_join->tmp_table_param.field_count+= 
-	curr_join->tmp_table_param.sum_func_count+
-	curr_join->tmp_table_param.func_count;
-      curr_join->tmp_table_param.sum_func_count= 
-	curr_join->tmp_table_param.func_count= 0;
+      tmp_table_param.field_count+= 
+        tmp_table_param.sum_func_count + tmp_table_param.func_count;
+      tmp_table_param.sum_func_count= 0;
+      tmp_table_param.func_count= 0;
     }
     else
     {
-      curr_join->tmp_table_param.field_count+= 
-	curr_join->tmp_table_param.func_count;
-      curr_join->tmp_table_param.func_count= 0;
+      tmp_table_param.field_count+= tmp_table_param.func_count;
+      tmp_table_param.func_count= 0;
     }
     
     // procedure can't be used inside subselect => we do nothing special for it
@@ -2840,9 +2851,9 @@ JOIN::exec()
     
     if (curr_tmp_table->group)
     {						// Already grouped
-      if (!curr_join->order && !curr_join->no_order && !skip_sort_order)
-	curr_join->order= curr_join->group_list;  /* order by group */
-      curr_join->group_list= 0;
+      if (!order && !no_order && !skip_sort_order)
+        order= group_list;  /* order by group */
+      group_list= 0;
     }
     
     /*
@@ -2853,25 +2864,21 @@ JOIN::exec()
       like SEC_TO_TIME(SUM(...)).
     */
 
-    if ((curr_join->group_list && (!test_if_subpart(curr_join->group_list,
-						   curr_join->order) || 
-				  curr_join->select_distinct)) ||
-	(curr_join->select_distinct &&
-	 curr_join->tmp_table_param.using_indirect_summary_function))
+    if ((group_list && 
+         (!test_if_subpart(group_list, order) || select_distinct)) ||
+        (select_distinct && tmp_table_param.using_indirect_summary_function))
     {					/* Must copy to another table */
       DBUG_PRINT("info",("Creating group table"));
       
       /* Free first data from old join */
-      curr_join->join_free();
-      if (curr_join->make_simple_join(this, curr_tmp_table))
+      join_free();
+      if (make_simple_join(main_join, curr_tmp_table))
 	DBUG_VOID_RETURN;
-      calc_group_buffer(curr_join, group_list);
-      count_field_types(select_lex, &curr_join->tmp_table_param,
-			curr_join->tmp_all_fields1,
-			curr_join->select_distinct && !curr_join->group_list);
-      curr_join->tmp_table_param.hidden_field_count= 
-	(curr_join->tmp_all_fields1.elements-
-	 curr_join->tmp_fields_list1.elements);
+      calc_group_buffer(this, group_list);
+      count_field_types(select_lex, &tmp_table_param, tmp_all_fields1,
+                        select_distinct && !group_list);
+      tmp_table_param.hidden_field_count= 
+        tmp_all_fields1.elements - tmp_fields_list1.elements;
       
       
       if (exec_tmp_table2)
@@ -2885,73 +2892,71 @@ JOIN::exec()
           functions are precomputed, and should be treated as regular
           functions. See extended comment in JOIN::exec.
         */
-        if (curr_join->join_tab->is_using_loose_index_scan())
-          curr_join->tmp_table_param.precomputed_group_by= TRUE;
+        if (join_tab->is_using_loose_index_scan())
+          tmp_table_param.precomputed_group_by= TRUE;
 
 	if (!(curr_tmp_table=
 	      exec_tmp_table2= create_tmp_table(thd,
-						&curr_join->tmp_table_param,
+                                                &tmp_table_param,
 						*curr_all_fields,
 						(ORDER*) 0,
-						curr_join->select_distinct && 
-						!curr_join->group_list,
-						1, curr_join->select_options,
+                                                select_distinct && !group_list,
+                                                1, select_options,
 						HA_POS_ERROR, "")))
 	  DBUG_VOID_RETURN;
-	curr_join->exec_tmp_table2= exec_tmp_table2;
+        if (parent)
+          parent->exec_tmp_table2= exec_tmp_table2;
       }
-      if (curr_join->group_list)
+      if (group_list)
       {
 	thd_proc_info(thd, "Creating sort index");
-	if (curr_join->join_tab == join_tab && save_join_tab())
+        if (join_tab == main_join->join_tab && main_join->save_join_tab())
 	{
 	  DBUG_VOID_RETURN;
 	}
-	if (create_sort_index(thd, curr_join, curr_join->group_list,
+        if (create_sort_index(thd, this, group_list,
 			      HA_POS_ERROR, HA_POS_ERROR, FALSE) ||
-	    make_group_fields(this, curr_join))
+            make_group_fields(main_join, this))
 	{
 	  DBUG_VOID_RETURN;
 	}
-        sortorder= curr_join->sortorder;
+        if (parent)
+          parent->sortorder= sortorder;
       }
       
       thd_proc_info(thd, "Copying to group table");
       DBUG_PRINT("info", ("%s", thd->proc_info));
       tmp_error= -1;
-      if (curr_join != this)
+      if (parent)
       {
-	if (sum_funcs2)
-	{
-	  curr_join->sum_funcs= sum_funcs2;
-	  curr_join->sum_funcs_end= sum_funcs_end2; 
-	}
-	else
-	{
-	  curr_join->alloc_func_list();
-	  sum_funcs2= curr_join->sum_funcs;
-	  sum_funcs_end2= curr_join->sum_funcs_end;
-	}
+        if (parent->sum_funcs2)
+        {
+          sum_funcs= parent->sum_funcs2;
+          sum_funcs_end= parent->sum_funcs_end2; 
+        }
+        else
+        {
+          alloc_func_list();
+          parent->sum_funcs2= sum_funcs;
+          parent->sum_funcs_end2= sum_funcs_end;
+        }
       }
-      if (curr_join->make_sum_func_list(*curr_all_fields, *curr_fields_list,
-					1, TRUE) ||
-        prepare_sum_aggregators(curr_join->sum_funcs,
-          !curr_join->join_tab->is_using_agg_loose_index_scan()))
+      if (make_sum_func_list(*curr_all_fields, *curr_fields_list, 1, TRUE) ||
+          prepare_sum_aggregators(sum_funcs,
+                                  !join_tab->is_using_agg_loose_index_scan()))
         DBUG_VOID_RETURN;
-      curr_join->group_list= 0;
-      if (!curr_join->sort_and_group &&
-          curr_join->const_tables != curr_join->tables)
-        curr_join->join_tab[curr_join->const_tables].sorted= 0;
-      if (setup_sum_funcs(curr_join->thd, curr_join->sum_funcs) ||
-	  (tmp_error= do_select(curr_join, (List<Item> *) 0, curr_tmp_table,
-				0)))
+      group_list= 0;
+      if (!sort_and_group && const_tables != tables)
+        join_tab[const_tables].sorted= 0;
+      if (setup_sum_funcs(thd, sum_funcs) ||
+          (tmp_error= do_select(this, (List<Item> *) 0, curr_tmp_table, 0)))
       {
 	error= tmp_error;
 	DBUG_VOID_RETURN;
       }
-      end_read_record(&curr_join->join_tab->read_record);
-      curr_join->const_tables= curr_join->tables; // Mark free for cleanup()
-      curr_join->join_tab[0].table= 0;           // Table is freed
+      end_read_record(&join_tab->read_record);
+      const_tables= tables; // Mark free for cleanup()
+      join_tab[0].table= 0;           // Table is freed
       
       // No sum funcs anymore
       if (!items2)
@@ -2961,51 +2966,47 @@ JOIN::exec()
 				     tmp_fields_list2, tmp_all_fields2, 
 				     fields_list.elements, tmp_all_fields1))
 	  DBUG_VOID_RETURN;
-        if (curr_join != this)
+        if (parent)
         {
-          curr_join->tmp_fields_list2= tmp_fields_list2;
-          curr_join->tmp_all_fields2= tmp_all_fields2;
+          parent->items2= items2;
+          parent->tmp_fields_list2= tmp_fields_list2;
+          parent->tmp_all_fields2= tmp_all_fields2;
         }
       }
-      curr_fields_list= &curr_join->tmp_fields_list2;
-      curr_all_fields= &curr_join->tmp_all_fields2;
-      curr_join->set_items_ref_array(items2);
-      curr_join->tmp_table_param.field_count+= 
-	curr_join->tmp_table_param.sum_func_count;
-      curr_join->tmp_table_param.sum_func_count= 0;
+      curr_fields_list= &tmp_fields_list2;
+      curr_all_fields= &tmp_all_fields2;
+      set_items_ref_array(items2);
+      tmp_table_param.field_count+= tmp_table_param.sum_func_count;
+      tmp_table_param.sum_func_count= 0;
     }
     if (curr_tmp_table->distinct)
-      curr_join->select_distinct=0;		/* Each row is unique */
+      select_distinct=0;                /* Each row is unique */
     
-    curr_join->join_free();			/* Free quick selects */
-    if (curr_join->select_distinct && ! curr_join->group_list)
+    join_free();                        /* Free quick selects */
+    if (select_distinct && ! group_list)
     {
       thd_proc_info(thd, "Removing duplicates");
-      if (curr_join->tmp_having)
-	curr_join->tmp_having->update_used_tables();
-      if (remove_duplicates(curr_join, curr_tmp_table,
-			    *curr_fields_list, curr_join->tmp_having))
+      if (tmp_having)
+        tmp_having->update_used_tables();
+      if (remove_duplicates(this, curr_tmp_table, *curr_fields_list, tmp_having))
 	DBUG_VOID_RETURN;
-      curr_join->tmp_having=0;
-      curr_join->select_distinct=0;
+      tmp_having=0;
+      select_distinct=0;
     }
     curr_tmp_table->reginfo.lock_type= TL_UNLOCK;
-    if (curr_join->make_simple_join(this, curr_tmp_table))
+    if (make_simple_join(main_join, curr_tmp_table))
       DBUG_VOID_RETURN;
-    calc_group_buffer(curr_join, curr_join->group_list);
-    count_field_types(select_lex, &curr_join->tmp_table_param, 
-                      *curr_all_fields, 0);
+    calc_group_buffer(this, group_list);
+    count_field_types(select_lex, &tmp_table_param, *curr_all_fields, 0);
     
   }
   if (procedure)
-    count_field_types(select_lex, &curr_join->tmp_table_param, 
-                      *curr_all_fields, 0);
+    count_field_types(select_lex, &tmp_table_param, *curr_all_fields, 0);
   
-  if (curr_join->group || curr_join->implicit_grouping ||
-      curr_join->tmp_table_param.sum_func_count ||
+  if (group || implicit_grouping || tmp_table_param.sum_func_count ||
       (procedure && (procedure->flags & PROC_GROUP)))
   {
-    if (make_group_fields(this, curr_join))
+    if (make_group_fields(main_join, this))
     {
       DBUG_VOID_RETURN;
     }
@@ -3014,56 +3015,51 @@ JOIN::exec()
       if (!items0)
 	init_items_ref_array();
       items3= ref_pointer_array + (all_fields.elements*4);
-      setup_copy_fields(thd, &curr_join->tmp_table_param,
+      setup_copy_fields(thd, &tmp_table_param,
 			items3, tmp_fields_list3, tmp_all_fields3,
 			curr_fields_list->elements, *curr_all_fields);
-      tmp_table_param.save_copy_funcs= curr_join->tmp_table_param.copy_funcs;
-      tmp_table_param.save_copy_field= curr_join->tmp_table_param.copy_field;
-      tmp_table_param.save_copy_field_end=
-	curr_join->tmp_table_param.copy_field_end;
-      if (curr_join != this)
+      if (parent)
       {
-        curr_join->tmp_all_fields3= tmp_all_fields3;
-        curr_join->tmp_fields_list3= tmp_fields_list3;
-      }
-    }
-    else
-    {
-      curr_join->tmp_table_param.copy_funcs= tmp_table_param.save_copy_funcs;
-      curr_join->tmp_table_param.copy_field= tmp_table_param.save_copy_field;
-      curr_join->tmp_table_param.copy_field_end=
-	tmp_table_param.save_copy_field_end;
+        parent->tmp_table_param.save_copy_funcs= tmp_table_param.copy_funcs;
+        parent->tmp_table_param.save_copy_field= tmp_table_param.copy_field;
+        parent->tmp_table_param.save_copy_field_end= 
+          tmp_table_param.copy_field_end;
+        parent->tmp_all_fields3= tmp_all_fields3;
+        parent->tmp_fields_list3= tmp_fields_list3;
+      }
+    }
+    else if (parent)
+    {
+      tmp_table_param.copy_funcs= parent->tmp_table_param.save_copy_funcs;
+      tmp_table_param.copy_field= parent->tmp_table_param.save_copy_field;
+      tmp_table_param.copy_field_end= 
+        parent->tmp_table_param.save_copy_field_end;
     }
     curr_fields_list= &tmp_fields_list3;
     curr_all_fields= &tmp_all_fields3;
-    curr_join->set_items_ref_array(items3);
+    set_items_ref_array(items3);
 
-    if (curr_join->make_sum_func_list(*curr_all_fields, *curr_fields_list,
-				      1, TRUE) || 
-        prepare_sum_aggregators(curr_join->sum_funcs,
-                                !curr_join->join_tab ||
-                                !curr_join->join_tab->
-                                  is_using_agg_loose_index_scan()) ||
-        setup_sum_funcs(curr_join->thd, curr_join->sum_funcs) ||
+    if (make_sum_func_list(*curr_all_fields, *curr_fields_list, 1, TRUE) || 
+        prepare_sum_aggregators(sum_funcs,
+                                !join_tab ||
+                                !join_tab->is_using_agg_loose_index_scan()) ||
+        setup_sum_funcs(thd, sum_funcs) ||
         thd->is_fatal_error)
       DBUG_VOID_RETURN;
   }
-  if (curr_join->group_list || curr_join->order)
+  if (group_list || order)
   {
     DBUG_PRINT("info",("Sorting for send_result_set_metadata"));
     thd_proc_info(thd, "Sorting result");
     /* If we have already done the group, add HAVING to sorted table */
-    if (curr_join->tmp_having && ! curr_join->group_list && 
-	! curr_join->sort_and_group)
+    if (tmp_having && ! group_list && ! sort_and_group)
     {
       // Some tables may have been const
-      curr_join->tmp_having->update_used_tables();
-      JOIN_TAB *curr_table= &curr_join->join_tab[curr_join->const_tables];
-      table_map used_tables= (curr_join->const_table_map |
-			      curr_table->table->map);
+      tmp_having->update_used_tables();
+      JOIN_TAB *curr_table= &join_tab[const_tables];
+      table_map used_tables= (const_table_map | curr_table->table->map);
 
-      Item* sort_table_cond= make_cond_for_table(curr_join->tmp_having,
-						 used_tables,
+      Item* sort_table_cond= make_cond_for_table(tmp_having, used_tables,
 						 used_tables, 0);
       if (sort_table_cond)
       {
@@ -3085,25 +3081,23 @@ JOIN::exec()
 	DBUG_EXECUTE("where",print_where(curr_table->select->cond,
 					 "select and having",
                                          QT_ORDINARY););
-	curr_join->tmp_having= make_cond_for_table(curr_join->tmp_having,
-						   ~ (table_map) 0,
-						   ~used_tables, 0);
-	DBUG_EXECUTE("where",print_where(curr_join->tmp_having,
-                                         "having after sort",
-                                         QT_ORDINARY););
+        tmp_having= make_cond_for_table(tmp_having, ~ (table_map) 0,
+                                        ~used_tables, 0);
+        DBUG_EXECUTE("where",
+                     print_where(tmp_having, "having after sort", QT_ORDINARY););
       }
     }
     {
       if (group)
-	curr_join->select_limit= HA_POS_ERROR;
+        select_limit= HA_POS_ERROR;
       else
       {
 	/*
 	  We can abort sorting after thd->select_limit rows if we there is no
 	  WHERE clause for any tables after the sorted one.
 	*/
-	JOIN_TAB *curr_table= &curr_join->join_tab[curr_join->const_tables+1];
-	JOIN_TAB *end_table= &curr_join->join_tab[curr_join->tables];
+        JOIN_TAB *curr_table= &join_tab[const_tables+1];
+        JOIN_TAB *end_table= &join_tab[tables];
 	for (; curr_table < end_table ; curr_table++)
 	{
 	  /*
@@ -3114,12 +3108,12 @@ JOIN::exec()
 	      (curr_table->keyuse && !curr_table->first_inner))
 	  {
 	    /* We have to sort all rows */
-	    curr_join->select_limit= HA_POS_ERROR;
+            select_limit= HA_POS_ERROR;
 	    break;
 	  }
 	}
       }
-      if (curr_join->join_tab == join_tab && save_join_tab())
+      if (join_tab == main_join->join_tab && main_join->save_join_tab())
       {
 	DBUG_VOID_RETURN;
       }
@@ -3132,17 +3126,16 @@ JOIN::exec()
 	the query. XXX: it's never shown in EXPLAIN!
 	OPTION_FOUND_ROWS supersedes LIMIT and is taken into account.
       */
-      if (create_sort_index(thd, curr_join,
-			    curr_join->group_list ? 
-			    curr_join->group_list : curr_join->order,
-			    curr_join->select_limit,
+      if (create_sort_index(thd, this,
+                            group_list ? group_list : order,
+                            select_limit,
 			    (select_options & OPTION_FOUND_ROWS ?
 			     HA_POS_ERROR : unit->select_limit_cnt),
-                            curr_join->group_list ? FALSE : TRUE))
+                            group_list ? FALSE : TRUE))
 	DBUG_VOID_RETURN;
-      sortorder= curr_join->sortorder;
-      if (curr_join->const_tables != curr_join->tables &&
-          !curr_join->join_tab[curr_join->const_tables].table->sort.io_cache)
+      if (parent)
+        parent->sortorder= sortorder;
+      if (const_tables != tables && !join_tab[const_tables].table->sort.io_cache)
       {
         /*
           If no IO cache exists for the first table then we are using an
@@ -3159,20 +3152,19 @@ JOIN::exec()
     error= thd->is_error();
     DBUG_VOID_RETURN;
   }
-  curr_join->having= curr_join->tmp_having;
-  curr_join->fields= curr_fields_list;
-  curr_join->procedure= procedure;
+  having= tmp_having;
+  fields= curr_fields_list;
 
   thd_proc_info(thd, "Sending data");
   DBUG_PRINT("info", ("%s", thd->proc_info));
-  result->send_result_set_metadata((procedure ? curr_join->procedure_fields_list :
+  result->send_result_set_metadata((procedure ? procedure_fields_list :
                                     *curr_fields_list),
                                    Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF);
-  error= do_select(curr_join, curr_fields_list, NULL, procedure);
-  thd->limit_found_rows= curr_join->send_records;
+  error= do_select(this, curr_fields_list, NULL, procedure);
+  thd->limit_found_rows= send_records;
 
   /* Accumulate the counts from all join iterations of all join parts. */
-  thd->examined_row_count+= curr_join->examined_rows;
+  thd->examined_row_count+= examined_rows;
   DBUG_PRINT("counts", ("thd->examined_row_count: %lu",
                         (ulong) thd->examined_row_count));
 
@@ -3192,7 +3184,7 @@ JOIN::exec()
 
 /**
   @todo Investigate how to unify this code with the code for creating a
-        second temporary table, @c exec_tmp_table2. @see JOIN::exec
+        second temporary table, @c exec_tmp_table2. @see JOIN::execute
 */
 int
 JOIN::create_intermediate_table()

=== modified file 'sql/sql_select.h'
--- a/sql/sql_select.h	2010-09-27 10:56:33 +0000
+++ b/sql/sql_select.h	2010-09-27 13:47:23 +0000
@@ -1935,6 +1935,20 @@ public:
   }
 private:
   /**
+    Execute current query. To be called from @c JOIN::exec.
+
+    If current query is a dependent subquery, this execution is performed on a
+    temporary copy of the original JOIN object in order to be able to restore
+    the original content for re-execution and EXPLAIN. (@note Subqueries may
+    be executed as part of EXPLAIN.) In such cases, JOIN::execute makes sure to
+    copy execution data that may be reused for later executions to the original
+    JOIN object (@c parent).
+
+    @param parent Original JOIN when current object is a temporary copy of it.
+  */
+  void execute(JOIN *parent);
+  
+  /**
     Create table to be used for processing DISTINCT/ORDER BY/GROUP BY.
     This creates the table referred to by @c exec_tmp_table1.
 


Attachment: [text/bzr-bundle] bzr/oystein.grovlen@oracle.com-20100927134723-f4dq4dcv07dvbj10.bundle
Thread
bzr commit into mysql-next-mr-bugfixing branch (oystein.grovlen:3245) WL#5559Oystein Grovlen27 Sep