summaryrefslogtreecommitdiff
path: root/sql/opt_range.cc
diff options
context:
space:
mode:
authorunknown <timour@mysql.com>2006-03-31 12:34:28 +0300
committerunknown <timour@mysql.com>2006-03-31 12:34:28 +0300
commita01d48f92e9c2eebe91e92962b5fdb075978c712 (patch)
tree69470df2afebeaffdacddbd994da021e73d309ae /sql/opt_range.cc
parent82f645531ca1843de7651102e8653fdee1faf5a6 (diff)
downloadmariadb-git-a01d48f92e9c2eebe91e92962b5fdb075978c712.tar.gz
Fix for BUG#16710.
The bug was due to a missed case in the detection of whether an index can be used for loose scan. More precisely, the range optimizer chose to use loose index scan for queries for which the condition(s) over an index key part could not be pushed to the index together with the loose scan. As a result, loose index scan was selecting the first row in the index with a given GROUP BY prefix, and was applying the WHERE clause after that, while it should have inspected all rows with the given prefix, and apply the WHERE clause to all of them. The fix detects and skips such cases. mysql-test/r/group_min_max.result: Added test for BUG#16710. mysql-test/t/group_min_max.test: Added test for BUG#16710. sql/item.cc: Added new method [Item | Item_field]::find_item_in_field_list_processor. sql/item.h: Added new method [Item | Item_field]::find_item_in_field_list_processor. sql/opt_range.cc: Handle the case when there is no MIN/MAX aggregate function, and a keypart of the index being considered, that is after the GROUP BY prefix, is used in the WHERE clause and the condition where it is used cannot be pushed to the index. If this is the case, we rule out this index.
Diffstat (limited to 'sql/opt_range.cc')
-rw-r--r--sql/opt_range.cc26
1 files changed, 26 insertions, 0 deletions
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 1b712700b18..da4b1288faf 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -6876,6 +6876,7 @@ cost_group_min_max(TABLE* table, KEY *index_info, uint used_key_parts,
bool have_min, bool have_max,
double *read_cost, ha_rows *records);
+
/*
Test if this access method is applicable to a GROUP query with MIN/MAX
functions, and if so, construct a new TRP object.
@@ -7282,11 +7283,36 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
}
else if (min_max_arg_part &&
(min_max_arg_part - first_non_group_part > 0))
+ {
/*
There is a gap but no range tree, thus no predicates at all for the
non-group keyparts.
*/
goto next_index;
+ }
+ else if (first_non_group_part && join->conds)
+ {
+ /*
+ If there is no MIN/MAX function in the query, but some index
+ key part is referenced in the WHERE clause, then this index
+ cannot be used because the WHERE condition over the keypart's
+ field cannot be 'pushed' to the index (because there is no
+ range 'tree'), and the WHERE clause must be evaluated before
+ GROUP BY/DISTINCT.
+ */
+ /*
+ Store the first and last keyparts that need to be analyzed
+ into one array that can be passed as parameter.
+ */
+ KEY_PART_INFO *key_part_range[2];
+ key_part_range[0]= first_non_group_part;
+ key_part_range[1]= last_part;
+
+ /* Check if cur_part is referenced in the WHERE clause. */
+ if (join->conds->walk(&Item::find_item_in_field_list_processor,
+ (byte*) key_part_range))
+ goto next_index;
+ }
}
/*