summaryrefslogtreecommitdiff
path: root/sql/sql_select.cc
diff options
context:
space:
mode:
authorMartin Hansson <martin.hansson@oracle.com>2011-02-18 11:50:06 +0100
committerMartin Hansson <martin.hansson@oracle.com>2011-02-18 11:50:06 +0100
commit61b256177bc9876d05ac807a98cb141c70d9357e (patch)
treee6dd2b9774801c002ddb2ad8d9825ac13c1b0146 /sql/sql_select.cc
parentcc7b3de9fcbb6be5a6759ba5f27c3ed08420fc87 (diff)
downloadmariadb-git-61b256177bc9876d05ac807a98cb141c70d9357e.tar.gz
Bug#11766675 - 59839: Aggregation followed by subquery yields wrong result
The loop that was looping over subqueries' references to outer field used a local boolean variable to tell whether the field was grouped or not. But the implementor failed to reset the variable after each iteration. Thus a field that was not directly aggregated appeared to be. Fixed by resetting the variable upon each new iteration.
Diffstat (limited to 'sql/sql_select.cc')
-rw-r--r--sql/sql_select.cc66
1 files changed, 35 insertions, 31 deletions
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 869fd01ac60..eb2559fc600 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -278,61 +278,65 @@ bool handle_select(THD *thd, LEX *lex, select_result *result,
}
-/*
+/**
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
- group_list GROUP BY list (is NULL by default)
+ @param thd Thread handle
+ @param all_fields List of all fields used in select
+ @param select Current select
+ @param ref_pointer_array Array of references to Items used in current select
+ @param group_list GROUP BY list (is NULL by default)
- DESCRIPTION
- The function serves 3 purposes - adds fields referenced from inner
- selects to the current select list, resolves which class to use
- to access referenced item (Item_ref of Item_direct_ref) and fixes
- references (Item_ref objects) to these fields.
+ @details
+ The function serves 3 purposes
+
+ - adds fields referenced from inner query blocks to the current select list
+
+ - Decides which class to use to reference the items (Item_ref or
+ Item_direct_ref)
- If a field isn't already in the select list and the ref_pointer_array
+ - fixes references (Item_ref objects) to these fields.
+
+ If a field isn't already on the select list and the ref_pointer_array
is provided then it is added to the all_fields list and the pointer to
it is saved in the ref_pointer_array.
The class to access the outer field is determined by the following rules:
- 1. If the outer field isn't used under an aggregate function
- then the Item_ref class should be used.
- 2. If the outer field is used under an aggregate function and this
- 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 should be used if we are grouping by a subquery containing
- the outer field.
+
+ -#. If the outer field isn't used under an aggregate function then the
+ Item_ref class should be used.
+
+ -#. If the outer field is used under an aggregate function and this
+ function is, in turn, aggregated in the query block where the outer
+ field was resolved or some query nested therein, then the
+ Item_direct_ref class should be used. Also it should 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.
+ it can be done only after aggregate functions are fixed and pulled up to
+ selects where they are to be aggregated.
+
When the class is chosen it substitutes the original field in the
Item_outer_ref object.
After this we proceed with fixing references (Item_outer_ref objects) to
this field from inner subqueries.
- RETURN
- TRUE an error occured
- FALSE ok
-*/
+ @return Status
+ @retval true An error occured.
+ @retval false OK.
+ */
bool
fix_inner_refs(THD *thd, List<Item> &all_fields, SELECT_LEX *select,
Item **ref_pointer_array, ORDER *group_list)
{
Item_outer_ref *ref;
- bool res= FALSE;
- bool direct_ref= FALSE;
List_iterator<Item_outer_ref> ref_it(select->inner_refs_list);
while ((ref= ref_it++))
{
+ bool direct_ref= false;
Item *item= ref->outer_ref;
Item **item_ref= ref->ref;
Item_ref *new_ref;
@@ -404,7 +408,7 @@ fix_inner_refs(THD *thd, List<Item> &all_fields, SELECT_LEX *select,
return TRUE;
thd->used_tables|= item->used_tables();
}
- return res;
+ return false;
}
/**