summaryrefslogtreecommitdiff
path: root/sql/sql_select.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_select.cc')
-rw-r--r--sql/sql_select.cc37
1 files changed, 31 insertions, 6 deletions
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 0cb6981bfd8..fbb5d00e7a8 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -4204,8 +4204,23 @@ static void optimize_keyuse(JOIN *join, DYNAMIC_ARRAY *keyuse_array)
Optionally (if out_args is supplied) will push the arguments of
AGGFN(DISTINCT) to the list
+ Check for every COUNT(DISTINCT), AVG(DISTINCT) or
+ SUM(DISTINCT). These can be resolved by Loose Index Scan as long
+ as all the aggregate distinct functions refer to the same
+ fields. Thus:
+
+ SELECT AGGFN(DISTINCT a, b), AGGFN(DISTINCT b, a)... => can use LIS
+ SELECT AGGFN(DISTINCT a), AGGFN(DISTINCT a) ... => can use LIS
+ SELECT AGGFN(DISTINCT a, b), AGGFN(DISTINCT a) ... => cannot use LIS
+ SELECT AGGFN(DISTINCT a), AGGFN(DISTINCT b) ... => cannot use LIS
+ etc.
+
@param join the join to check
- @param[out] out_args list of aggregate function arguments
+ @param[out] out_args Collect the arguments of the aggregate functions
+ to a list. We don't worry about duplicates as
+ these will be sorted out later in
+ get_best_group_min_max.
+
@return does the query qualify for indexed AGGFN(DISTINCT)
@retval true it does
@retval false AGGFN(DISTINCT) must apply distinct in it.
@@ -4216,6 +4231,7 @@ is_indexed_agg_distinct(JOIN *join, List<Item_field> *out_args)
{
Item_sum **sum_item_ptr;
bool result= false;
+ Field_map first_aggdistinct_fields;
if (join->tables != 1 || /* reference more than 1 table */
join->select_distinct || /* or a DISTINCT */
@@ -4228,6 +4244,7 @@ is_indexed_agg_distinct(JOIN *join, List<Item_field> *out_args)
for (sum_item_ptr= join->sum_funcs; *sum_item_ptr; sum_item_ptr++)
{
Item_sum *sum_item= *sum_item_ptr;
+ Field_map cur_aggdistinct_fields;
Item *expr;
/* aggregate is not AGGFN(DISTINCT) or more than 1 argument to it */
switch (sum_item->sum_func())
@@ -4257,15 +4274,23 @@ is_indexed_agg_distinct(JOIN *join, List<Item_field> *out_args)
if (expr->real_item()->type() != Item::FIELD_ITEM)
return false;
- /*
- If we came to this point the AGGFN(DISTINCT) loose index scan
- optimization is applicable
- */
+ Item_field* item= static_cast<Item_field*>(expr->real_item());
if (out_args)
- out_args->push_back((Item_field *) expr->real_item());
+ out_args->push_back(item);
+
+ cur_aggdistinct_fields.set_bit(item->field->field_index);
result= true;
}
+ /*
+ If there are multiple aggregate functions, make sure that they all
+ refer to exactly the same set of columns.
+ */
+ if (first_aggdistinct_fields.is_clear_all())
+ first_aggdistinct_fields.merge(cur_aggdistinct_fields);
+ else if (first_aggdistinct_fields != cur_aggdistinct_fields)
+ return false;
}
+
return result;
}