diff options
Diffstat (limited to 'sql/sql_select.cc')
-rw-r--r-- | sql/sql_select.cc | 37 |
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; } |