summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <timour@mysql.com>2005-02-28 16:20:02 +0200
committerunknown <timour@mysql.com>2005-02-28 16:20:02 +0200
commit7a703d6acee84b845184f86e7d50865967308c77 (patch)
tree25102b84202ed8c9b4d5c0d16ddcf5d7271a0f94
parent108702a34e37bae22f117a3a7e18e7cead3e63c8 (diff)
downloadmariadb-git-7a703d6acee84b845184f86e7d50865967308c77.tar.gz
Fix for BUG#8532.
The problem was in that the code that analyses the applicability of the QUICK_GROUP_MIN_MAX access method for DISTINC queries assumed that there are no duplicate column references in the DISTINCT clause, and it added non-exiting key parts for the duplicate column references. The solution adds a test to check whether the select list already contained a field with the same name. If such field was already present, then it was already decided to use its key part for index access. In this such case we must skip the duplicate field instead of counting it as a new field. mysql-test/r/group_min_max.result: Added test results for BUG#8532. mysql-test/t/group_min_max.test: Added tests for BUG#8532. sql/opt_range.cc: The problem was in that the code that analyses the applicability of the QUICK_GROUP_MIN_MAX access method for DISTINC queries assumed that there are no duplicate column references in the DISTINCT clause, and it added non-exiting key parts for the duplicate column references. The solution adds a test to check whether the select list already contained a field with the same name. If such field was already present, then it was already decided to use its key part for index access. In this such case we must skip the duplicate field instead of counting it as a new field.
-rw-r--r--mysql-test/r/group_min_max.result38
-rw-r--r--mysql-test/t/group_min_max.test6
-rw-r--r--sql/opt_range.cc11
3 files changed, 53 insertions, 2 deletions
diff --git a/mysql-test/r/group_min_max.result b/mysql-test/r/group_min_max.result
index c7be93b0fd7..766e43b2299 100644
--- a/mysql-test/r/group_min_max.result
+++ b/mysql-test/r/group_min_max.result
@@ -1657,6 +1657,44 @@ a
b
c
d
+select distinct a1,a1 from t1;
+a1 a1
+a a
+b b
+c c
+d d
+select distinct a2,a1,a2,a1 from t1;
+a2 a1 a2 a1
+a a a a
+b a b a
+a b a b
+b b b b
+a c a c
+b c b c
+a d a d
+b d b d
+select distinct t1.a1,t2.a1 from t1,t2;
+a1 a1
+a a
+b a
+c a
+d a
+a b
+b b
+c b
+d b
+a c
+b c
+c c
+d c
+a d
+b d
+c d
+d d
+a e
+b e
+c e
+d e
explain select distinct a1,a2,b from t1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range NULL idx_t1_1 147 NULL 17 Using index for group-by
diff --git a/mysql-test/t/group_min_max.test b/mysql-test/t/group_min_max.test
index b42125566d5..d85b3395853 100644
--- a/mysql-test/t/group_min_max.test
+++ b/mysql-test/t/group_min_max.test
@@ -475,11 +475,15 @@ select distinct a1,a2,b,c from t2 where (a2 >= 'b') and (b = 'a') and (c = 'i121
select distinct a1,a2,b from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c');
select distinct b from t2 where (a2 >= 'b') and (b = 'a');
--- BUG 6303
+-- BUG #6303
select distinct t_00.a1
from t1 t_00
where exists ( select * from t2 where a1 = t_00.a1 );
+-- BUG #8532 - SELECT DISTINCT a, a causes server to crash
+select distinct a1,a1 from t1;
+select distinct a2,a1,a2,a1 from t1;
+select distinct t1.a1,t2.a1 from t1,t2;
--
-- DISTINCT queries with GROUP-BY
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 12e5c60312b..812d5a41cbc 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -6878,6 +6878,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
SEL_ARG *cur_index_tree= NULL;
ha_rows cur_quick_prefix_records= 0;
uint cur_param_idx;
+ key_map cur_used_key_parts;
for (uint cur_index= 0 ; cur_index_info != cur_index_info_end ;
cur_index_info++, cur_index++)
@@ -6925,17 +6926,25 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
else if (join->select_distinct)
{
select_items_it.rewind();
+ cur_used_key_parts.clear_all();
while ((item= select_items_it++))
{
item_field= (Item_field*) item; /* (SA5) already checked above. */
/* Find the order of the key part in the index. */
key_part_nr= get_field_keypart(cur_index_info, item_field->field);
+ /*
+ Check if this attribute was already present in the select list.
+ If it was present, then its corresponding key part was alredy used.
+ */
+ if (cur_used_key_parts.is_set(key_part_nr))
+ continue;
if (key_part_nr < 1 || key_part_nr > join->fields_list.elements)
goto next_index;
cur_part= cur_index_info->key_part + key_part_nr - 1;
cur_group_prefix_len+= cur_part->store_length;
+ cur_used_key_parts.set_bit(key_part_nr);
+ ++cur_group_key_parts;
}
- cur_group_key_parts= join->fields_list.elements;
}
else
DBUG_ASSERT(FALSE);