Commit 2bc070a0 authored by Georgi Kodinov's avatar Georgi Kodinov

merged the fix for bug 41610 to 5.1-bugteam

parents 34143e4e 15760fe9
...@@ -2448,3 +2448,18 @@ id select_type table type possible_keys key key_len ref rows filtered Extra ...@@ -2448,3 +2448,18 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
Warnings: Warnings:
Note 1003 select sql_buffer_result `test`.`t1`.`a` AS `a`,(max(`test`.`t1`.`b`) + 1) AS `max(b)+1` from `test`.`t1` where (`test`.`t1`.`a` = 0) group by `test`.`t1`.`a` Note 1003 select sql_buffer_result `test`.`t1`.`a` AS `a`,(max(`test`.`t1`.`b`) + 1) AS `max(b)+1` from `test`.`t1` where (`test`.`t1`.`a` = 0) group by `test`.`t1`.`a`
drop table t1; drop table t1;
CREATE TABLE t1 (a int, b int, c int, d int,
KEY foo (c,d,a,b), KEY bar (c,a,b,d));
INSERT INTO t1 VALUES (1, 1, 1, 1), (1, 1, 1, 2), (1, 1, 1, 3), (1, 1, 1, 4);
INSERT INTO t1 SELECT * FROM t1;
INSERT INTO t1 SELECT * FROM t1;
INSERT INTO t1 SELECT a,b,c+1,d FROM t1;
EXPLAIN SELECT DISTINCT c FROM t1 WHERE d=4;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range NULL foo 10 NULL 9 Using where; Using index for group-by
SELECT DISTINCT c FROM t1 WHERE d=4;
c
1
2
DROP TABLE t1;
End of 5.0 tests
...@@ -961,3 +961,25 @@ insert into t1 (a,b) select a, max(b)+1 from t1 where a = 0 group by a; ...@@ -961,3 +961,25 @@ insert into t1 (a,b) select a, max(b)+1 from t1 where a = 0 group by a;
select * from t1; select * from t1;
explain extended select sql_buffer_result a, max(b)+1 from t1 where a = 0 group by a; explain extended select sql_buffer_result a, max(b)+1 from t1 where a = 0 group by a;
drop table t1; drop table t1;
#
# Bug #41610: key_infix_len can be overwritten causing some group by queries
# to return no rows
#
CREATE TABLE t1 (a int, b int, c int, d int,
KEY foo (c,d,a,b), KEY bar (c,a,b,d));
INSERT INTO t1 VALUES (1, 1, 1, 1), (1, 1, 1, 2), (1, 1, 1, 3), (1, 1, 1, 4);
INSERT INTO t1 SELECT * FROM t1;
INSERT INTO t1 SELECT * FROM t1;
INSERT INTO t1 SELECT a,b,c+1,d FROM t1;
#Should be non-empty
EXPLAIN SELECT DISTINCT c FROM t1 WHERE d=4;
SELECT DISTINCT c FROM t1 WHERE d=4;
DROP TABLE t1;
--echo End of 5.0 tests
...@@ -9239,32 +9239,37 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree) ...@@ -9239,32 +9239,37 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
*/ */
KEY *cur_index_info= table->key_info; KEY *cur_index_info= table->key_info;
KEY *cur_index_info_end= cur_index_info + table->s->keys; KEY *cur_index_info_end= cur_index_info + table->s->keys;
KEY_PART_INFO *cur_part= NULL;
KEY_PART_INFO *end_part; /* Last part for loops. */
/* Last index part. */
KEY_PART_INFO *last_part= NULL;
KEY_PART_INFO *first_non_group_part= NULL;
KEY_PART_INFO *first_non_infix_part= NULL;
uint key_infix_parts= 0;
uint cur_group_key_parts= 0;
uint cur_group_prefix_len= 0;
/* Cost-related variables for the best index so far. */ /* Cost-related variables for the best index so far. */
double best_read_cost= DBL_MAX; double best_read_cost= DBL_MAX;
ha_rows best_records= 0; ha_rows best_records= 0;
SEL_ARG *best_index_tree= NULL; SEL_ARG *best_index_tree= NULL;
ha_rows best_quick_prefix_records= 0; ha_rows best_quick_prefix_records= 0;
uint best_param_idx= 0; uint best_param_idx= 0;
double cur_read_cost= DBL_MAX;
ha_rows cur_records; const uint pk= param->table->s->primary_key;
SEL_ARG *cur_index_tree= NULL; SEL_ARG *cur_index_tree= NULL;
ha_rows cur_quick_prefix_records= 0; ha_rows cur_quick_prefix_records= 0;
uint cur_param_idx=MAX_KEY; uint cur_param_idx=MAX_KEY;
key_map cur_used_key_parts;
uint pk= param->table->s->primary_key;
for (uint cur_index= 0 ; cur_index_info != cur_index_info_end ; for (uint cur_index= 0 ; cur_index_info != cur_index_info_end ;
cur_index_info++, cur_index++) cur_index_info++, cur_index++)
{ {
KEY_PART_INFO *cur_part;
KEY_PART_INFO *end_part; /* Last part for loops. */
/* Last index part. */
KEY_PART_INFO *last_part;
KEY_PART_INFO *first_non_group_part;
KEY_PART_INFO *first_non_infix_part;
uint key_infix_parts;
uint cur_group_key_parts= 0;
uint cur_group_prefix_len= 0;
double cur_read_cost;
ha_rows cur_records;
key_map used_key_parts_map;
uint cur_key_infix_len= 0;
uchar cur_key_infix[MAX_KEY_LENGTH];
uint cur_used_key_parts;
/* Check (B1) - if current index is covering. */ /* Check (B1) - if current index is covering. */
if (!table->covering_keys.is_set(cur_index)) if (!table->covering_keys.is_set(cur_index))
goto next_index; goto next_index;
...@@ -9334,7 +9339,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree) ...@@ -9334,7 +9339,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
else if (join->select_distinct) else if (join->select_distinct)
{ {
select_items_it.rewind(); select_items_it.rewind();
cur_used_key_parts.clear_all(); used_key_parts_map.clear_all();
uint max_key_part= 0; uint max_key_part= 0;
while ((item= select_items_it++)) while ((item= select_items_it++))
{ {
...@@ -9345,13 +9350,13 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree) ...@@ -9345,13 +9350,13 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
Check if this attribute was already present in the select list. Check if this attribute was already present in the select list.
If it was present, then its corresponding key part was alredy used. If it was present, then its corresponding key part was alredy used.
*/ */
if (cur_used_key_parts.is_set(key_part_nr)) if (used_key_parts_map.is_set(key_part_nr))
continue; continue;
if (key_part_nr < 1 || key_part_nr > join->fields_list.elements) if (key_part_nr < 1 || key_part_nr > join->fields_list.elements)
goto next_index; goto next_index;
cur_part= cur_index_info->key_part + key_part_nr - 1; cur_part= cur_index_info->key_part + key_part_nr - 1;
cur_group_prefix_len+= cur_part->store_length; cur_group_prefix_len+= cur_part->store_length;
cur_used_key_parts.set_bit(key_part_nr); used_key_parts_map.set_bit(key_part_nr);
++cur_group_key_parts; ++cur_group_key_parts;
max_key_part= max(max_key_part,key_part_nr); max_key_part= max(max_key_part,key_part_nr);
} }
...@@ -9363,7 +9368,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree) ...@@ -9363,7 +9368,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
*/ */
ulonglong all_parts, cur_parts; ulonglong all_parts, cur_parts;
all_parts= (1<<max_key_part) - 1; all_parts= (1<<max_key_part) - 1;
cur_parts= cur_used_key_parts.to_ulonglong() >> 1; cur_parts= used_key_parts_map.to_ulonglong() >> 1;
if (all_parts != cur_parts) if (all_parts != cur_parts)
goto next_index; goto next_index;
} }
...@@ -9413,7 +9418,8 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree) ...@@ -9413,7 +9418,8 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
&dummy); &dummy);
if (!get_constant_key_infix(cur_index_info, index_range_tree, if (!get_constant_key_infix(cur_index_info, index_range_tree,
first_non_group_part, min_max_arg_part, first_non_group_part, min_max_arg_part,
last_part, thd, key_infix, &key_infix_len, last_part, thd, cur_key_infix,
&cur_key_infix_len,
&first_non_infix_part)) &first_non_infix_part))
goto next_index; goto next_index;
} }
...@@ -9467,9 +9473,9 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree) ...@@ -9467,9 +9473,9 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
} }
/* If we got to this point, cur_index_info passes the test. */ /* If we got to this point, cur_index_info passes the test. */
key_infix_parts= key_infix_len ? key_infix_parts= cur_key_infix_len ?
(first_non_infix_part - first_non_group_part) : 0; (first_non_infix_part - first_non_group_part) : 0;
used_key_parts= cur_group_key_parts + key_infix_parts; cur_used_key_parts= cur_group_key_parts + key_infix_parts;
/* Compute the cost of using this index. */ /* Compute the cost of using this index. */
if (tree) if (tree)
...@@ -9481,7 +9487,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree) ...@@ -9481,7 +9487,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
cur_quick_prefix_records= check_quick_select(param, cur_param_idx, cur_quick_prefix_records= check_quick_select(param, cur_param_idx,
cur_index_tree, TRUE); cur_index_tree, TRUE);
} }
cost_group_min_max(table, cur_index_info, used_key_parts, cost_group_min_max(table, cur_index_info, cur_used_key_parts,
cur_group_key_parts, tree, cur_index_tree, cur_group_key_parts, tree, cur_index_tree,
cur_quick_prefix_records, have_min, have_max, cur_quick_prefix_records, have_min, have_max,
&cur_read_cost, &cur_records); &cur_read_cost, &cur_records);
...@@ -9492,7 +9498,6 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree) ...@@ -9492,7 +9498,6 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
*/ */
if (cur_read_cost < best_read_cost - (DBL_EPSILON * cur_read_cost)) if (cur_read_cost < best_read_cost - (DBL_EPSILON * cur_read_cost))
{ {
DBUG_ASSERT(tree != 0 || cur_param_idx == MAX_KEY);
index_info= cur_index_info; index_info= cur_index_info;
index= cur_index; index= cur_index;
best_read_cost= cur_read_cost; best_read_cost= cur_read_cost;
...@@ -9502,11 +9507,13 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree) ...@@ -9502,11 +9507,13 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
best_param_idx= cur_param_idx; best_param_idx= cur_param_idx;
group_key_parts= cur_group_key_parts; group_key_parts= cur_group_key_parts;
group_prefix_len= cur_group_prefix_len; group_prefix_len= cur_group_prefix_len;
key_infix_len= cur_key_infix_len;
if (key_infix_len)
memcpy (key_infix, cur_key_infix, sizeof (key_infix));
used_key_parts= cur_used_key_parts;
} }
next_index: next_index:;
cur_group_key_parts= 0;
cur_group_prefix_len= 0;
} }
if (!index_info) /* No usable index found. */ if (!index_info) /* No usable index found. */
DBUG_RETURN(NULL); DBUG_RETURN(NULL);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment