Commit 5485e447 authored by Alexander Nozdrin's avatar Alexander Nozdrin

Merge from mysql-next-mr.

parents de0285a2 3f7624fc
...@@ -5085,7 +5085,6 @@ sub valgrind_arguments { ...@@ -5085,7 +5085,6 @@ sub valgrind_arguments {
else else
{ {
mtr_add_arg($args, "--tool=memcheck"); # From >= 2.1.2 needs this option mtr_add_arg($args, "--tool=memcheck"); # From >= 2.1.2 needs this option
mtr_add_arg($args, "--alignment=8");
mtr_add_arg($args, "--leak-check=yes"); mtr_add_arg($args, "--leak-check=yes");
mtr_add_arg($args, "--num-callers=16"); mtr_add_arg($args, "--num-callers=16");
mtr_add_arg($args, "--suppressions=%s/valgrind.supp", $glob_mysql_test_dir) mtr_add_arg($args, "--suppressions=%s/valgrind.supp", $glob_mysql_test_dir)
......
...@@ -5,7 +5,7 @@ count(distinct n) ...@@ -5,7 +5,7 @@ count(distinct n)
100 100
explain extended select count(distinct n) from t1; explain extended select count(distinct n) from t1;
id select_type table type possible_keys key key_len ref rows filtered Extra id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 index NULL n 4 NULL 200 100.00 Using index 1 SIMPLE t1 range NULL n 4 NULL 10 100.00 Using index for group-by
Warnings: Warnings:
Note 1003 select count(distinct `test`.`t1`.`n`) AS `count(distinct n)` from `test`.`t1` Note 1003 select count(distinct `test`.`t1`.`n`) AS `count(distinct n)` from `test`.`t1`
drop table t1; drop table t1;
This diff is collapsed.
...@@ -570,13 +570,13 @@ explain select count(distinct a1,a2,b) from t1 where (a2 >= 'b') and (b = 'a'); ...@@ -570,13 +570,13 @@ explain select count(distinct a1,a2,b) from t1 where (a2 >= 'b') and (b = 'a');
explain select count(distinct a1,a2,b,c) from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121'); explain select count(distinct a1,a2,b,c) from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121');
explain extended select count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c'); explain extended select count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c');
explain select count(distinct b) from t1 where (a2 >= 'b') and (b = 'a'); explain select count(distinct b) from t1 where (a2 >= 'b') and (b = 'a');
explain extended select ord(a1) + count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a'); explain extended select 98 + count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a');
select count(distinct a1,a2,b) from t1 where (a2 >= 'b') and (b = 'a'); select count(distinct a1,a2,b) from t1 where (a2 >= 'b') and (b = 'a');
select count(distinct a1,a2,b,c) from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121'); select count(distinct a1,a2,b,c) from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121');
select count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c'); select count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c');
select count(distinct b) from t1 where (a2 >= 'b') and (b = 'a'); select count(distinct b) from t1 where (a2 >= 'b') and (b = 'a');
select ord(a1) + count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a'); select 98 + count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a');
# #
# Queries with expressions in the select clause # Queries with expressions in the select clause
...@@ -1033,3 +1033,124 @@ SELECT a, MAX(b) FROM t WHERE b GROUP BY a; ...@@ -1033,3 +1033,124 @@ SELECT a, MAX(b) FROM t WHERE b GROUP BY a;
DROP TABLE t; DROP TABLE t;
--echo End of 5.1 tests --echo End of 5.1 tests
--echo #
--echo # WL#3220 (Loose index scan for COUNT DISTINCT)
--echo #
CREATE TABLE t1 (a INT, b INT, c INT, KEY (a,b));
INSERT INTO t1 VALUES (1,1,1), (1,2,1), (1,3,1), (1,4,1);
INSERT INTO t1 SELECT a, b + 4, 1 FROM t1;
INSERT INTO t1 SELECT a + 1, b, 1 FROM t1;
CREATE TABLE t2 (a INT, b INT, c INT, d INT, e INT, f INT, KEY (a,b,c));
INSERT INTO t2 VALUES (1,1,1,1,1,1), (1,2,1,1,1,1), (1,3,1,1,1,1),
(1,4,1,1,1,1);
INSERT INTO t2 SELECT a, b + 4, c,d,e,f FROM t2;
INSERT INTO t2 SELECT a + 1, b, c,d,e,f FROM t2;
EXPLAIN SELECT COUNT(DISTINCT a) FROM t1;
SELECT COUNT(DISTINCT a) FROM t1;
EXPLAIN SELECT COUNT(DISTINCT a,b) FROM t1;
SELECT COUNT(DISTINCT a,b) FROM t1;
EXPLAIN SELECT COUNT(DISTINCT b,a) FROM t1;
SELECT COUNT(DISTINCT b,a) FROM t1;
EXPLAIN SELECT COUNT(DISTINCT b) FROM t1;
SELECT COUNT(DISTINCT b) FROM t1;
EXPLAIN SELECT COUNT(DISTINCT a) FROM t1 GROUP BY a;
SELECT COUNT(DISTINCT a) FROM t1 GROUP BY a;
EXPLAIN SELECT COUNT(DISTINCT b) FROM t1 GROUP BY a;
SELECT COUNT(DISTINCT b) FROM t1 GROUP BY a;
EXPLAIN SELECT COUNT(DISTINCT a) FROM t1 GROUP BY b;
SELECT COUNT(DISTINCT a) FROM t1 GROUP BY b;
EXPLAIN SELECT DISTINCT COUNT(DISTINCT a) FROM t1;
SELECT DISTINCT COUNT(DISTINCT a) FROM t1;
EXPLAIN SELECT COUNT(DISTINCT a, b + 0) FROM t1;
SELECT COUNT(DISTINCT a, b + 0) FROM t1;
EXPLAIN SELECT COUNT(DISTINCT a) FROM t1 HAVING COUNT(DISTINCT b) < 10;
SELECT COUNT(DISTINCT a) FROM t1 HAVING COUNT(DISTINCT b) < 10;
EXPLAIN SELECT COUNT(DISTINCT a) FROM t1 HAVING COUNT(DISTINCT c) < 10;
SELECT COUNT(DISTINCT a) FROM t1 HAVING COUNT(DISTINCT c) < 10;
EXPLAIN SELECT 1 FROM t1 HAVING COUNT(DISTINCT a) < 10;
SELECT 1 FROM t1 HAVING COUNT(DISTINCT a) < 10;
EXPLAIN SELECT 1 FROM t1 GROUP BY a HAVING COUNT(DISTINCT b) > 1;
SELECT 1 FROM t1 GROUP BY a HAVING COUNT(DISTINCT b) > 1;
EXPLAIN SELECT COUNT(DISTINCT t1_1.a) FROM t1 t1_1, t1 t1_2 GROUP BY t1_1.a;
SELECT COUNT(DISTINCT t1_1.a) FROM t1 t1_1, t1 t1_2 GROUP BY t1_1.a;
EXPLAIN SELECT COUNT(DISTINCT a), 12 FROM t1;
SELECT COUNT(DISTINCT a), 12 FROM t1;
EXPLAIN SELECT COUNT(DISTINCT a, b, c) FROM t2;
SELECT COUNT(DISTINCT a, b, c) FROM t2;
EXPLAIN SELECT COUNT(DISTINCT a), SUM(DISTINCT a), AVG(DISTINCT a) FROM t2;
SELECT COUNT(DISTINCT a), SUM(DISTINCT a), AVG(DISTINCT a) FROM t2;
EXPLAIN SELECT COUNT(DISTINCT a), SUM(DISTINCT a), AVG(DISTINCT f) FROM t2;
SELECT COUNT(DISTINCT a), SUM(DISTINCT a), AVG(DISTINCT f) FROM t2;
EXPLAIN SELECT COUNT(DISTINCT a, b), COUNT(DISTINCT b, a) FROM t2;
SELECT COUNT(DISTINCT a, b), COUNT(DISTINCT b, a) FROM t2;
EXPLAIN SELECT COUNT(DISTINCT a, b), COUNT(DISTINCT b, f) FROM t2;
SELECT COUNT(DISTINCT a, b), COUNT(DISTINCT b, f) FROM t2;
EXPLAIN SELECT COUNT(DISTINCT a, b), COUNT(DISTINCT b, d) FROM t2;
SELECT COUNT(DISTINCT a, b), COUNT(DISTINCT b, d) FROM t2;
EXPLAIN SELECT a, c, COUNT(DISTINCT c, a, b) FROM t2 GROUP BY a, b, c;
SELECT a, c, COUNT(DISTINCT c, a, b) FROM t2 GROUP BY a, b, c;
EXPLAIN SELECT COUNT(DISTINCT c, a, b) FROM t2
WHERE a > 5 AND b BETWEEN 10 AND 20 GROUP BY a, b, c;
SELECT COUNT(DISTINCT c, a, b) FROM t2
WHERE a > 5 AND b BETWEEN 10 AND 20 GROUP BY a, b, c;
EXPLAIN SELECT COUNT(DISTINCT b), SUM(DISTINCT b) FROM t2 WHERE a = 5
GROUP BY b;
SELECT COUNT(DISTINCT b), SUM(DISTINCT b) FROM t2 WHERE a = 5
GROUP BY b;
EXPLAIN SELECT a, COUNT(DISTINCT b), SUM(DISTINCT b) FROM t2 GROUP BY a;
SELECT a, COUNT(DISTINCT b), SUM(DISTINCT b) FROM t2 GROUP BY a;
EXPLAIN SELECT COUNT(DISTINCT b), SUM(DISTINCT b) FROM t2 GROUP BY a;
SELECT COUNT(DISTINCT b), SUM(DISTINCT b) FROM t2 GROUP BY a;
EXPLAIN SELECT COUNT(DISTINCT a, b) FROM t2 WHERE c = 13 AND d = 42;
SELECT COUNT(DISTINCT a, b) FROM t2 WHERE c = 13 AND d = 42;
EXPLAIN SELECT a, COUNT(DISTINCT a), SUM(DISTINCT a) FROM t2
WHERE b = 13 AND c = 42 GROUP BY a;
SELECT a, COUNT(DISTINCT a), SUM(DISTINCT a) FROM t2
WHERE b = 13 AND c = 42 GROUP BY a;
EXPLAIN SELECT COUNT(DISTINCT a, b), SUM(DISTINCT a) FROM t2 WHERE b = 42;
SELECT COUNT(DISTINCT a, b), SUM(DISTINCT a) FROM t2 WHERE b = 42;
EXPLAIN SELECT SUM(DISTINCT a), MAX(b) FROM t2 GROUP BY a;
SELECT SUM(DISTINCT a), MAX(b) FROM t2 GROUP BY a;
EXPLAIN SELECT 42 * (a + c + COUNT(DISTINCT c, a, b)) FROM t2 GROUP BY a, b, c;
SELECT 42 * (a + c + COUNT(DISTINCT c, a, b)) FROM t2 GROUP BY a, b, c;
EXPLAIN SELECT (SUM(DISTINCT a) + MAX(b)) FROM t2 GROUP BY a;
SELECT (SUM(DISTINCT a) + MAX(b)) FROM t2 GROUP BY a;
DROP TABLE t1,t2;
--echo # end of WL#3220 tests
...@@ -1934,9 +1934,12 @@ class Field_bit :public Field { ...@@ -1934,9 +1934,12 @@ class Field_bit :public Field {
virtual bool str_needs_quotes() { return TRUE; } virtual bool str_needs_quotes() { return TRUE; }
my_decimal *val_decimal(my_decimal *); my_decimal *val_decimal(my_decimal *);
int cmp(const uchar *a, const uchar *b) int cmp(const uchar *a, const uchar *b)
{ {
DBUG_ASSERT(ptr == a); DBUG_ASSERT(ptr == a || ptr == b);
return Field_bit::key_cmp(b, bytes_in_rec+test(bit_len)); if (ptr == a)
return Field_bit::key_cmp(b, bytes_in_rec+test(bit_len));
else
return Field_bit::key_cmp(a, bytes_in_rec+test(bit_len)) * -1;
} }
int cmp_binary_offset(uint row_offset) int cmp_binary_offset(uint row_offset)
{ return cmp_offset(row_offset); } { return cmp_offset(row_offset); }
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -616,6 +616,7 @@ class QUICK_GROUP_MIN_MAX_SELECT : public QUICK_SELECT_I ...@@ -616,6 +616,7 @@ class QUICK_GROUP_MIN_MAX_SELECT : public QUICK_SELECT_I
uchar *last_prefix; /* Prefix of the last group for detecting EOF. */ uchar *last_prefix; /* Prefix of the last group for detecting EOF. */
bool have_min; /* Specify whether we are computing */ bool have_min; /* Specify whether we are computing */
bool have_max; /* a MIN, a MAX, or both. */ bool have_max; /* a MIN, a MAX, or both. */
bool have_agg_distinct;/* aggregate_function(DISTINCT ...). */
bool seen_first_key; /* Denotes whether the first key was retrieved.*/ bool seen_first_key; /* Denotes whether the first key was retrieved.*/
KEY_PART_INFO *min_max_arg_part; /* The keypart of the only argument field */ KEY_PART_INFO *min_max_arg_part; /* The keypart of the only argument field */
/* of all MIN/MAX functions. */ /* of all MIN/MAX functions. */
...@@ -629,6 +630,11 @@ class QUICK_GROUP_MIN_MAX_SELECT : public QUICK_SELECT_I ...@@ -629,6 +630,11 @@ class QUICK_GROUP_MIN_MAX_SELECT : public QUICK_SELECT_I
List<Item_sum> *max_functions; List<Item_sum> *max_functions;
List_iterator<Item_sum> *min_functions_it; List_iterator<Item_sum> *min_functions_it;
List_iterator<Item_sum> *max_functions_it; List_iterator<Item_sum> *max_functions_it;
/*
Use index scan to get the next different key instead of jumping into it
through index read
*/
bool is_index_scan;
public: public:
/* /*
The following two members are public to allow easy access from The following two members are public to allow easy access from
...@@ -646,12 +652,13 @@ class QUICK_GROUP_MIN_MAX_SELECT : public QUICK_SELECT_I ...@@ -646,12 +652,13 @@ class QUICK_GROUP_MIN_MAX_SELECT : public QUICK_SELECT_I
void update_max_result(); void update_max_result();
public: public:
QUICK_GROUP_MIN_MAX_SELECT(TABLE *table, JOIN *join, bool have_min, QUICK_GROUP_MIN_MAX_SELECT(TABLE *table, JOIN *join, bool have_min,
bool have_max, KEY_PART_INFO *min_max_arg_part, bool have_max, bool have_agg_distinct,
KEY_PART_INFO *min_max_arg_part,
uint group_prefix_len, uint group_key_parts, uint group_prefix_len, uint group_key_parts,
uint used_key_parts, KEY *index_info, uint uint used_key_parts, KEY *index_info, uint
use_index, double read_cost, ha_rows records, uint use_index, double read_cost, ha_rows records, uint
key_infix_len, uchar *key_infix, MEM_ROOT key_infix_len, uchar *key_infix, MEM_ROOT
*parent_alloc); *parent_alloc, bool is_index_scan);
~QUICK_GROUP_MIN_MAX_SELECT(); ~QUICK_GROUP_MIN_MAX_SELECT();
bool add_range(SEL_ARG *sel_range); bool add_range(SEL_ARG *sel_range);
void update_key_stat(); void update_key_stat();
...@@ -667,6 +674,12 @@ class QUICK_GROUP_MIN_MAX_SELECT : public QUICK_SELECT_I ...@@ -667,6 +674,12 @@ class QUICK_GROUP_MIN_MAX_SELECT : public QUICK_SELECT_I
#ifndef DBUG_OFF #ifndef DBUG_OFF
void dbug_dump(int indent, bool verbose); void dbug_dump(int indent, bool verbose);
#endif #endif
bool is_agg_distinct() { return have_agg_distinct; }
virtual void append_loose_scan_type(String *str)
{
if (is_index_scan)
str->append(STRING_WITH_LEN(" (scanning)"));
}
}; };
......
...@@ -355,10 +355,13 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds) ...@@ -355,10 +355,13 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
const_result= 0; const_result= 0;
break; break;
} }
item_sum->set_aggregator (item_sum->with_distinct ?
Aggregator::DISTINCT_AGGREGATOR :
Aggregator::SIMPLE_AGGREGATOR);
if (!count) if (!count)
{ {
/* If count == 0, then we know that is_exact_count == TRUE. */ /* If count == 0, then we know that is_exact_count == TRUE. */
((Item_sum_min*) item_sum)->clear(); /* Set to NULL. */ ((Item_sum_min*) item_sum)->aggregator_clear(); /* Set to NULL. */
} }
else else
((Item_sum_min*) item_sum)->reset(); /* Set to the constant value. */ ((Item_sum_min*) item_sum)->reset(); /* Set to the constant value. */
...@@ -443,10 +446,13 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds) ...@@ -443,10 +446,13 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
const_result= 0; const_result= 0;
break; break;
} }
item_sum->set_aggregator (item_sum->with_distinct ?
Aggregator::DISTINCT_AGGREGATOR :
Aggregator::SIMPLE_AGGREGATOR);
if (!count) if (!count)
{ {
/* If count != 1, then we know that is_exact_count == TRUE. */ /* If count != 1, then we know that is_exact_count == TRUE. */
((Item_sum_max*) item_sum)->clear(); /* Set to NULL. */ ((Item_sum_max*) item_sum)->aggregator_clear(); /* Set to NULL. */
} }
else else
((Item_sum_max*) item_sum)->reset(); /* Set to the constant value. */ ((Item_sum_max*) item_sum)->reset(); /* Set to the constant value. */
......
...@@ -54,6 +54,7 @@ ...@@ -54,6 +54,7 @@
class Reprepare_observer class Reprepare_observer
{ {
public: public:
Reprepare_observer() {}
/** /**
Check if a change of metadata is OK. In future Check if a change of metadata is OK. In future
the signature of this method may be extended to accept the old the signature of this method may be extended to accept the old
......
...@@ -222,6 +222,7 @@ static void update_tmptable_sum_func(Item_sum **func,TABLE *tmp_table); ...@@ -222,6 +222,7 @@ static void update_tmptable_sum_func(Item_sum **func,TABLE *tmp_table);
static void copy_sum_funcs(Item_sum **func_ptr, Item_sum **end); static void copy_sum_funcs(Item_sum **func_ptr, Item_sum **end);
static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab); static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab);
static bool setup_sum_funcs(THD *thd, Item_sum **func_ptr); static bool setup_sum_funcs(THD *thd, Item_sum **func_ptr);
static bool prepare_sum_aggregators(Item_sum **func_ptr, bool need_distinct);
static bool init_sum_functions(Item_sum **func, Item_sum **end); static bool init_sum_functions(Item_sum **func, Item_sum **end);
static bool update_sum_func(Item_sum **func); static bool update_sum_func(Item_sum **func);
static void select_describe(JOIN *join, bool need_tmp_table,bool need_order, static void select_describe(JOIN *join, bool need_tmp_table,bool need_order,
...@@ -1232,7 +1233,11 @@ JOIN::optimize() ...@@ -1232,7 +1233,11 @@ JOIN::optimize()
if (test_if_subpart(group_list, order) || if (test_if_subpart(group_list, order) ||
(!group_list && tmp_table_param.sum_func_count)) (!group_list && tmp_table_param.sum_func_count))
{
order=0; order=0;
if (is_indexed_agg_distinct(this, NULL))
sort_and_group= 0;
}
// Can't use sort on head table if using row cache // Can't use sort on head table if using row cache
if (full_join) if (full_join)
...@@ -1410,8 +1415,16 @@ JOIN::optimize() ...@@ -1410,8 +1415,16 @@ JOIN::optimize()
single table queries, thus it is sufficient to test only the first single table queries, thus it is sufficient to test only the first
join_tab element of the plan for its access method. join_tab element of the plan for its access method.
*/ */
bool need_distinct= TRUE;
if (join_tab->is_using_loose_index_scan()) if (join_tab->is_using_loose_index_scan())
{
tmp_table_param.precomputed_group_by= TRUE; tmp_table_param.precomputed_group_by= TRUE;
if (join_tab->is_using_agg_loose_index_scan())
{
need_distinct= FALSE;
tmp_table_param.precomputed_group_by= FALSE;
}
}
/* Create a tmp table if distinct or if the sort is too complicated */ /* Create a tmp table if distinct or if the sort is too complicated */
if (need_tmp) if (need_tmp)
...@@ -1472,6 +1485,7 @@ JOIN::optimize() ...@@ -1472,6 +1485,7 @@ JOIN::optimize()
HA_POS_ERROR, HA_POS_ERROR, FALSE) || HA_POS_ERROR, HA_POS_ERROR, FALSE) ||
alloc_group_fields(this, group_list) || alloc_group_fields(this, group_list) ||
make_sum_func_list(all_fields, fields_list, 1) || make_sum_func_list(all_fields, fields_list, 1) ||
prepare_sum_aggregators(sum_funcs, need_distinct) ||
setup_sum_funcs(thd, sum_funcs)) setup_sum_funcs(thd, sum_funcs))
{ {
DBUG_RETURN(1); DBUG_RETURN(1);
...@@ -1481,6 +1495,7 @@ JOIN::optimize() ...@@ -1481,6 +1495,7 @@ JOIN::optimize()
else else
{ {
if (make_sum_func_list(all_fields, fields_list, 0) || if (make_sum_func_list(all_fields, fields_list, 0) ||
prepare_sum_aggregators(sum_funcs, need_distinct) ||
setup_sum_funcs(thd, sum_funcs)) setup_sum_funcs(thd, sum_funcs))
{ {
DBUG_RETURN(1); DBUG_RETURN(1);
...@@ -1953,7 +1968,9 @@ JOIN::exec() ...@@ -1953,7 +1968,9 @@ JOIN::exec()
} }
} }
if (curr_join->make_sum_func_list(*curr_all_fields, *curr_fields_list, if (curr_join->make_sum_func_list(*curr_all_fields, *curr_fields_list,
1, TRUE)) 1, TRUE) ||
prepare_sum_aggregators(curr_join->sum_funcs,
!curr_join->join_tab->is_using_agg_loose_index_scan()))
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
curr_join->group_list= 0; curr_join->group_list= 0;
if (!curr_join->sort_and_group && if (!curr_join->sort_and_group &&
...@@ -2056,6 +2073,8 @@ JOIN::exec() ...@@ -2056,6 +2073,8 @@ JOIN::exec()
if (curr_join->make_sum_func_list(*curr_all_fields, *curr_fields_list, if (curr_join->make_sum_func_list(*curr_all_fields, *curr_fields_list,
1, TRUE) || 1, TRUE) ||
prepare_sum_aggregators (curr_join->sum_funcs, !curr_join->join_tab ||
!curr_join->join_tab->is_using_agg_loose_index_scan()) ||
setup_sum_funcs(curr_join->thd, curr_join->sum_funcs) || setup_sum_funcs(curr_join->thd, curr_join->sum_funcs) ||
thd->is_fatal_error) thd->is_fatal_error)
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
...@@ -3937,6 +3956,82 @@ static void optimize_keyuse(JOIN *join, DYNAMIC_ARRAY *keyuse_array) ...@@ -3937,6 +3956,82 @@ static void optimize_keyuse(JOIN *join, DYNAMIC_ARRAY *keyuse_array)
} }
/**
Check for the presence of AGGFN(DISTINCT a) queries that may be subject
to loose index scan.
Check if the query is a subject to AGGFN(DISTINCT) using loose index scan
(QUICK_GROUP_MIN_MAX_SELECT).
Optionally (if out_args is supplied) will push the arguments of
AGGFN(DISTINCT) to the list
@param join the join to check
@param[out] out_args list of aggregate function arguments
@return does the query qualify for indexed AGGFN(DISTINCT)
@retval true it does
@retval false AGGFN(DISTINCT) must apply distinct in it.
*/
bool
is_indexed_agg_distinct(JOIN *join, List<Item_field> *out_args)
{
Item_sum **sum_item_ptr;
bool result= false;
if (join->tables != 1 || /* reference more than 1 table */
join->select_distinct || /* or a DISTINCT */
join->select_lex->olap == ROLLUP_TYPE) /* Check (B3) for ROLLUP */
return false;
if (join->make_sum_func_list(join->all_fields, join->fields_list, 1))
return false;
for (sum_item_ptr= join->sum_funcs; *sum_item_ptr; sum_item_ptr++)
{
Item_sum *sum_item= *sum_item_ptr;
Item *expr;
/* aggregate is not AGGFN(DISTINCT) or more than 1 argument to it */
switch (sum_item->sum_func())
{
case Item_sum::MIN_FUNC:
case Item_sum::MAX_FUNC:
continue;
case Item_sum::COUNT_DISTINCT_FUNC:
break;
case Item_sum::AVG_DISTINCT_FUNC:
case Item_sum::SUM_DISTINCT_FUNC:
if (sum_item->get_arg_count() == 1)
break;
/* fall through */
default: return false;
}
/*
We arrive here for every COUNT(DISTINCT),AVG(DISTINCT) or SUM(DISTINCT).
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
*/
for (uint i= 0; i < sum_item->get_arg_count(); i++)
{
expr= sum_item->get_arg(i);
/* The AGGFN(DISTINCT) arg is not an attribute? */
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
*/
if (out_args)
out_args->push_back((Item_field *) expr);
result= true;
}
}
return result;
}
/** /**
Discover the indexes that can be used for GROUP BY or DISTINCT queries. Discover the indexes that can be used for GROUP BY or DISTINCT queries.
...@@ -3979,6 +4074,10 @@ add_group_and_distinct_keys(JOIN *join, JOIN_TAB *join_tab) ...@@ -3979,6 +4074,10 @@ add_group_and_distinct_keys(JOIN *join, JOIN_TAB *join_tab)
item->walk(&Item::collect_item_field_processor, 0, item->walk(&Item::collect_item_field_processor, 0,
(uchar*) &indexed_fields); (uchar*) &indexed_fields);
} }
else if (is_indexed_agg_distinct(join, &indexed_fields))
{
join->sort_and_group= 1;
}
else else
return; return;
...@@ -10377,6 +10476,7 @@ TABLE *create_virtual_tmp_table(THD *thd, List<Create_field> &field_list) ...@@ -10377,6 +10476,7 @@ TABLE *create_virtual_tmp_table(THD *thd, List<Create_field> &field_list)
bzero(share, sizeof(*share)); bzero(share, sizeof(*share));
table->field= field; table->field= field;
table->s= share; table->s= share;
table->temp_pool_slot= MY_BIT_NONE;
share->blob_field= blob_field; share->blob_field= blob_field;
share->fields= field_count; share->fields= field_count;
share->blob_ptr_size= portable_sizeof_char_ptr; share->blob_ptr_size= portable_sizeof_char_ptr;
...@@ -14532,7 +14632,7 @@ setup_new_fields(THD *thd, List<Item> &fields, ...@@ -14532,7 +14632,7 @@ setup_new_fields(THD *thd, List<Item> &fields,
optimize away 'order by'. optimize away 'order by'.
*/ */
static ORDER * ORDER *
create_distinct_group(THD *thd, Item **ref_pointer_array, create_distinct_group(THD *thd, Item **ref_pointer_array,
ORDER *order_list, List<Item> &fields, ORDER *order_list, List<Item> &fields,
List<Item> &all_fields, List<Item> &all_fields,
...@@ -15334,7 +15434,22 @@ static bool setup_sum_funcs(THD *thd, Item_sum **func_ptr) ...@@ -15334,7 +15434,22 @@ static bool setup_sum_funcs(THD *thd, Item_sum **func_ptr)
DBUG_ENTER("setup_sum_funcs"); DBUG_ENTER("setup_sum_funcs");
while ((func= *(func_ptr++))) while ((func= *(func_ptr++)))
{ {
if (func->setup(thd)) if (func->aggregator_setup(thd))
DBUG_RETURN(TRUE);
}
DBUG_RETURN(FALSE);
}
static bool prepare_sum_aggregators(Item_sum **func_ptr, bool need_distinct)
{
Item_sum *func;
DBUG_ENTER("setup_sum_funcs");
while ((func= *(func_ptr++)))
{
if (func->set_aggregator(need_distinct && func->with_distinct ?
Aggregator::DISTINCT_AGGREGATOR :
Aggregator::SIMPLE_AGGREGATOR))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
} }
DBUG_RETURN(FALSE); DBUG_RETURN(FALSE);
...@@ -15384,7 +15499,7 @@ init_sum_functions(Item_sum **func_ptr, Item_sum **end_ptr) ...@@ -15384,7 +15499,7 @@ init_sum_functions(Item_sum **func_ptr, Item_sum **end_ptr)
/* If rollup, calculate the upper sum levels */ /* If rollup, calculate the upper sum levels */
for ( ; *func_ptr ; func_ptr++) for ( ; *func_ptr ; func_ptr++)
{ {
if ((*func_ptr)->add()) if ((*func_ptr)->aggregator_add())
return 1; return 1;
} }
return 0; return 0;
...@@ -15396,7 +15511,7 @@ update_sum_func(Item_sum **func_ptr) ...@@ -15396,7 +15511,7 @@ update_sum_func(Item_sum **func_ptr)
{ {
Item_sum *func; Item_sum *func;
for (; (func= (Item_sum*) *func_ptr) ; func_ptr++) for (; (func= (Item_sum*) *func_ptr) ; func_ptr++)
if (func->add()) if (func->aggregator_add())
return 1; return 1;
return 0; return 0;
} }
...@@ -16313,7 +16428,12 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, ...@@ -16313,7 +16428,12 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
if (key_read) if (key_read)
{ {
if (quick_type == QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX) if (quick_type == QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX)
{
QUICK_GROUP_MIN_MAX_SELECT *qgs=
(QUICK_GROUP_MIN_MAX_SELECT *) tab->select->quick;
extra.append(STRING_WITH_LEN("; Using index for group-by")); extra.append(STRING_WITH_LEN("; Using index for group-by"));
qgs->append_loose_scan_type(&extra);
}
else else
extra.append(STRING_WITH_LEN("; Using index")); extra.append(STRING_WITH_LEN("; Using index"));
} }
......
...@@ -218,6 +218,11 @@ typedef struct st_join_table { ...@@ -218,6 +218,11 @@ typedef struct st_join_table {
(select->quick->get_type() == (select->quick->get_type() ==
QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX)); QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX));
} }
bool is_using_agg_loose_index_scan ()
{
return (is_using_loose_index_scan() &&
((QUICK_GROUP_MIN_MAX_SELECT *)select->quick)->is_agg_distinct());
}
} JOIN_TAB; } JOIN_TAB;
enum_nested_loop_state sub_select_cache(JOIN *join, JOIN_TAB *join_tab, bool enum_nested_loop_state sub_select_cache(JOIN *join, JOIN_TAB *join_tab, bool
...@@ -564,6 +569,8 @@ Field* create_tmp_field_from_field(THD *thd, Field* org_field, ...@@ -564,6 +569,8 @@ Field* create_tmp_field_from_field(THD *thd, Field* org_field,
const char *name, TABLE *table, const char *name, TABLE *table,
Item_field *item, uint convert_blob_length); Item_field *item, uint convert_blob_length);
bool is_indexed_agg_distinct(JOIN *join, List<Item_field> *out_args);
/* functions from opt_sum.cc */ /* functions from opt_sum.cc */
bool simple_pred(Item_func *func_item, Item **args, bool *inv_order); bool simple_pred(Item_func *func_item, Item **args, bool *inv_order);
int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds); int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds);
......
...@@ -8182,7 +8182,7 @@ sum_expr: ...@@ -8182,7 +8182,7 @@ sum_expr:
} }
| AVG_SYM '(' DISTINCT in_sum_expr ')' | AVG_SYM '(' DISTINCT in_sum_expr ')'
{ {
$$= new (YYTHD->mem_root) Item_sum_avg_distinct($4); $$= new (YYTHD->mem_root) Item_sum_avg($4, TRUE);
if ($$ == NULL) if ($$ == NULL)
MYSQL_YYABORT; MYSQL_YYABORT;
} }
...@@ -8225,7 +8225,7 @@ sum_expr: ...@@ -8225,7 +8225,7 @@ sum_expr:
{ Select->in_sum_expr--; } { Select->in_sum_expr--; }
')' ')'
{ {
$$= new (YYTHD->mem_root) Item_sum_count_distinct(* $5); $$= new (YYTHD->mem_root) Item_sum_count(* $5);
if ($$ == NULL) if ($$ == NULL)
MYSQL_YYABORT; MYSQL_YYABORT;
} }
...@@ -8290,7 +8290,7 @@ sum_expr: ...@@ -8290,7 +8290,7 @@ sum_expr:
} }
| SUM_SYM '(' DISTINCT in_sum_expr ')' | SUM_SYM '(' DISTINCT in_sum_expr ')'
{ {
$$= new (YYTHD->mem_root) Item_sum_sum_distinct($4); $$= new (YYTHD->mem_root) Item_sum_sum($4, TRUE);
if ($$ == NULL) if ($$ == NULL)
MYSQL_YYABORT; MYSQL_YYABORT;
} }
......
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