=== modified file 'sql/item.cc' --- old/sql/item.cc 2009-11-02 11:21:39 +0000 +++ new/sql/item.cc 2009-11-09 21:20:38 +0000 @@ -6375,6 +6375,16 @@ bool Item_outer_ref::fix_fields(THD *thd } +bool Item_outer_ref::walk(Item_processor processor, bool walk_subquery, + uchar *arg) +{ + if (processor == &Item::find_outer_ref_processor && this == (void *) arg) + return TRUE; // terminate search if we are seeking for this Item_outer_ref + + return (*ref)->walk(processor, walk_subquery, arg); +} + + /** Compare two view column references for equality. === modified file 'sql/item.h' --- old/sql/item.h 2009-11-02 11:21:39 +0000 +++ new/sql/item.h 2009-11-09 19:35:46 +0000 @@ -894,6 +894,7 @@ public: virtual bool change_context_processor(uchar *context) { return 0; } virtual bool reset_query_id_processor(uchar *query_id_arg) { return 0; } virtual bool is_expensive_processor(uchar *arg) { return 0; } + virtual bool find_outer_ref_processor(uchar *arg) { return 0; } virtual bool register_field_in_read_map(uchar *arg) { return 0; } /* Check if a partition function is allowed @@ -2367,6 +2368,7 @@ public: return (*ref)->const_item() ? 0 : OUTER_REF_TABLE_BIT; } virtual Ref_Type ref_type() { return OUTER_REF; } + bool walk(Item_processor processor, bool walk_subquery, uchar *arg); }; === modified file 'sql/mysql_priv.h' --- old/sql/mysql_priv.h 2009-10-27 13:20:34 +0000 +++ new/sql/mysql_priv.h 2009-11-09 17:50:19 +0000 @@ -1188,7 +1188,7 @@ int setup_group(THD *thd, Item **ref_poi List &fields, List &all_fields, ORDER *order, bool *hidden_group_fields); bool fix_inner_refs(THD *thd, List &all_fields, SELECT_LEX *select, - Item **ref_pointer_array); + Item **ref_pointer_array, ORDER *group_list= NULL); bool handle_select(THD *thd, LEX *lex, select_result *result, ulong setup_tables_done_option); === modified file 'sql/sql_select.cc' --- old/sql/sql_select.cc 2009-11-03 17:45:52 +0000 +++ new/sql/sql_select.cc 2009-11-09 21:32:58 +0000 @@ -287,6 +287,7 @@ bool handle_select(THD *thd, LEX *lex, s all_fields List of all fields used in select select Current select ref_pointer_array Array of references to Items used in current select + group_list GROUP BY list DESCRIPTION The function serves 3 purposes - adds fields referenced from inner @@ -305,6 +306,8 @@ bool handle_select(THD *thd, LEX *lex, s function is aggregated in the select where the outer field was resolved or in some more inner select then the Item_direct_ref class should be used. + Also it sould be used if we are grouping by a subquery containing + the outer field. The resolution is done here and not at the fix_fields() stage as it can be done only after sum functions are fixed and pulled up to selects where they are have to be aggregated. @@ -321,7 +324,7 @@ bool handle_select(THD *thd, LEX *lex, s bool fix_inner_refs(THD *thd, List &all_fields, SELECT_LEX *select, - Item **ref_pointer_array) + Item **ref_pointer_array, ORDER *group_list /*= NULL*/) { Item_outer_ref *ref; bool res= FALSE; @@ -371,6 +374,18 @@ fix_inner_refs(THD *thd, List &all } } } + else + { + for (ORDER *group= group_list; group; group= group->next) + { + if ((*group->item)->walk(&Item::find_outer_ref_processor, TRUE, + (uchar *) ref)) + { // grouping by a subquery containing the outer field + direct_ref= TRUE; + break; + } + } + } new_ref= direct_ref ? new Item_direct_ref(ref->context, item_ref, ref->table_name, ref->field_name, ref->alias_name_used) : @@ -564,7 +579,8 @@ JOIN::prepare(Item ***rref_pointer_array } if (select_lex->inner_refs_list.elements && - fix_inner_refs(thd, all_fields, select_lex, ref_pointer_array)) + fix_inner_refs(thd, all_fields, select_lex, ref_pointer_array, + group_list)) DBUG_RETURN(-1); if (group_list)