diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index c9238c052a7..498fb3fe83f 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -1262,3 +1262,15 @@ id select_type table type possible_keys key key_len ref rows Extra 2 DEPENDENT SUBQUERY t1 ref a a 5 func 10 Using where 2 DEPENDENT SUBQUERY t3 index a a 5 NULL 3 Using where; Using index drop table t1, t2, t3; +create table t1 (a int, b int); +create table t2 (a int, b int); +create table t3 (a int, b int); +insert into t1 values (0,100),(1,2), (1,3), (2,2), (2,7), (2,-1), (3,10); +insert into t2 values (0,0), (1,1), (2,1), (3,1), (4,1); +insert into t3 values (3,3), (2,2), (1,1); +select a,(select count(distinct t1.b) as sum from t1,t2 where t1.a=t2.a and t2.b > 0 and t1.a <= t3.b group by t1.a order by sum limit 1) from t3; +a (select count(distinct t1.b) as sum from t1,t2 where t1.a=t2.a and t2.b > 0 and t1.a <= t3.b group by t1.a order by sum limit 1) +3 1 +2 2 +1 2 +drop table t1,t2,t3; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index e360f2bbd60..a6cbbf6330c 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -842,3 +842,14 @@ explain select * from t2 where t2.a in (select a from t1); select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a); explain select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a); drop table t1, t2, t3; +# +# alloc_group_fields() working +# +create table t1 (a int, b int); +create table t2 (a int, b int); +create table t3 (a int, b int); +insert into t1 values (0,100),(1,2), (1,3), (2,2), (2,7), (2,-1), (3,10); +insert into t2 values (0,0), (1,1), (2,1), (3,1), (4,1); +insert into t3 values (3,3), (2,2), (1,1); +select a,(select count(distinct t1.b) as sum from t1,t2 where t1.a=t2.a and t2.b > 0 and t1.a <= t3.b group by t1.a order by sum limit 1) from t3; +drop table t1,t2,t3;s diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 78ba3027d91..67299dc47c3 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -142,6 +142,7 @@ static ORDER *create_distinct_group(THD *thd, ORDER *order, static bool test_if_subpart(ORDER *a,ORDER *b); static TABLE *get_sort_by_table(ORDER *a,ORDER *b,TABLE_LIST *tables); static void calc_group_buffer(JOIN *join,ORDER *group); +static bool make_group_fields(JOIN *main_join, JOIN *curr_join); static bool alloc_group_fields(JOIN *join,ORDER *group); // Create list for using with tempory table static bool change_to_use_tmp_fields(THD *thd, Item **ref_pointer_array, @@ -1136,12 +1137,12 @@ JOIN::exec() DBUG_VOID_RETURN; curr_join->exec_tmp_table2= exec_tmp_table2; } - if (group_list) + if (curr_join->group_list) { thd->proc_info= "Creating sort index"; if (create_sort_index(thd, curr_join->join_tab, curr_join->group_list, HA_POS_ERROR, HA_POS_ERROR) || - alloc_group_fields(curr_join, curr_join->group_list)) + make_group_fields(this, curr_join)) { DBUG_VOID_RETURN; } @@ -1150,6 +1151,20 @@ JOIN::exec() thd->proc_info="Copying to group table"; tmp_error= -1; + if (curr_join != this) + { + if (sum_funcs2) + { + curr_join->sum_funcs= sum_funcs2; + curr_join->sum_funcs_end= sum_funcs_end2; + } + else + { + curr_join->alloc_func_list(); + sum_funcs2= curr_join->sum_funcs; + sum_funcs_end2= curr_join->sum_funcs_end; + } + } if (curr_join->make_sum_func_list(*curr_all_fields, *curr_fields_list, 1) || (tmp_error= do_select(curr_join, (List *) 0, curr_tmp_table, @@ -1208,7 +1223,10 @@ JOIN::exec() if (curr_join->group || curr_join->tmp_table_param.sum_func_count || (procedure && (procedure->flags & PROC_GROUP))) { - alloc_group_fields(curr_join, curr_join->group_list); + if (make_group_fields(this, curr_join)) + { + DBUG_VOID_RETURN; + } if (!items3) { if (!items0) @@ -7670,6 +7688,37 @@ calc_group_buffer(JOIN *join,ORDER *group) join->tmp_table_param.group_null_parts=null_parts; } +/* + alloc group fields or take prepared (chached) + + SYNOPSYS + make_group_fields() + main_join - join of current select + curr_join - current join (join of current select or temporary copy of it) + + RETURN + 0 - ok + 1 - failed +*/ + +static bool +make_group_fields(JOIN *main_join, JOIN *curr_join) +{ + if (main_join->group_fields_cache.elements) + { + curr_join->group_fields= main_join->group_fields_cache; + curr_join->sort_and_group= 1; + } + else + { + if (alloc_group_fields(curr_join, curr_join->group_list)) + { + return (1); + } + main_join->group_fields_cache= curr_join->group_fields; + } + return (0); +} /* Get a list of buffers for saveing last group @@ -7696,6 +7745,7 @@ alloc_group_fields(JOIN *join,ORDER *group) static int test_if_group_changed(List &list) { + DBUG_ENTER("test_if_group_changed"); List_iterator li(list); int idx= -1,i; Item_buff *buff; @@ -7705,7 +7755,8 @@ test_if_group_changed(List &list) if (buff->cmp()) idx=i; } - return idx; + DBUG_PRINT("info", ("idx: %d", idx)); + DBUG_RETURN(idx); } diff --git a/sql/sql_select.h b/sql/sql_select.h index a4554183312..40a097c10ad 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -140,12 +140,14 @@ class JOIN :public Sql_alloc POSITION positions[MAX_TABLES+1],best_positions[MAX_TABLES+1]; double best_read; List *fields; - List group_fields; + List group_fields, group_fields_cache; TABLE *tmp_table; // used to store 2 possible tmp table of SELECT TABLE *exec_tmp_table1, *exec_tmp_table2; THD *thd; Item_sum **sum_funcs, ***sum_funcs_end; + /* second copy of sumfuncs (for queries with 2 temporary tables */ + Item_sum **sum_funcs2, ***sum_funcs_end2; Procedure *procedure; Item *having; Item *tmp_having; // To store Having when processed temporary table @@ -212,7 +214,7 @@ class JOIN :public Sql_alloc exec_tmp_table1= 0; exec_tmp_table2= 0; thd= thd_arg; - sum_funcs= 0; + sum_funcs= sum_funcs2= 0; procedure= 0; having= 0; tmp_having= 0;