@@ -2100,13 +2100,22 @@ bool JOIN::make_aggr_tables_info()
2100
2100
2101
2101
sort_and_group_aggr_tab= NULL;
2102
2102
2103
- /*
2103
+
2104
+ /*
2105
+ Setup last table to provide fields and all_fields lists to the next
2106
+ node in the plan.
2107
+ */
2108
+ if (join_tab)
2109
+ {
2110
+ join_tab[top_join_tab_count - 1].fields= &fields_list;
2111
+ join_tab[top_join_tab_count - 1].all_fields= &all_fields;
2112
+ }
2113
+
2114
+ /*
2104
2115
All optimization is done. Check if we can use the storage engines
2105
2116
group by handler to evaluate the group by
2106
2117
*/
2107
-
2108
2118
group_by_handler *gbh= NULL;
2109
- #if 0
2110
2119
if ((tmp_table_param.sum_func_count || group_list) && !procedure)
2111
2120
{
2112
2121
/*
@@ -2127,10 +2136,10 @@ bool JOIN::make_aggr_tables_info()
2127
2136
Query query= {&all_fields, select_distinct, tables_list, conds,
2128
2137
group_list, order ? order : group_list, having};
2129
2138
group_by_handler *gbh= ht->create_group_by(thd, &query);
2139
+
2130
2140
if (gbh)
2131
2141
{
2132
2142
pushdown_query= new (thd->mem_root) Pushdown_query(select_lex, gbh);
2133
-
2134
2143
/*
2135
2144
We must store rows in the tmp table if we need to do an ORDER BY
2136
2145
or DISTINCT and the storage handler can't handle it.
@@ -2139,31 +2148,75 @@ bool JOIN::make_aggr_tables_info()
2139
2148
distinct= query.distinct;
2140
2149
keep_row_order= query.order_by || query.group_by;
2141
2150
2151
+ order= query.order_by;
2152
+
2153
+ aggr_tables++;
2154
+ curr_tab= join_tab + top_join_tab_count;
2155
+ bzero(curr_tab, sizeof(JOIN_TAB));
2156
+ curr_tab->ref.key= -1;
2157
+ curr_tab->join= this;
2158
+
2159
+ curr_tab->tmp_table_param= new TMP_TABLE_PARAM(tmp_table_param);
2160
+ TABLE* table= create_tmp_table(thd, curr_tab->tmp_table_param,
2161
+ all_fields,
2162
+ NULL, query.distinct,
2163
+ TRUE, select_options, HA_POS_ERROR,
2164
+ "", !need_tmp,
2165
+ query.order_by || query.group_by);
2166
+ if (!table)
2167
+ DBUG_RETURN(1);
2168
+
2169
+ curr_tab->aggr= new (thd->mem_root) AGGR_OP(curr_tab);
2170
+ curr_tab->aggr->set_write_func(::end_send);
2171
+ curr_tab->table= table;
2172
+ /*
2173
+ Setup reference fields, used by summary functions and group by fields,
2174
+ to point to the temporary table.
2175
+ The actual switching to the temporary tables fields for HAVING
2176
+ and ORDER BY is done in do_select() by calling
2177
+ set_items_ref_array(items1).
2178
+ */
2179
+ init_items_ref_array();
2180
+ items1= ref_ptr_array_slice(2);
2181
+ //items1= items0 + all_fields.elements;
2182
+ if (change_to_use_tmp_fields(thd, items1,
2183
+ tmp_fields_list1, tmp_all_fields1,
2184
+ fields_list.elements, all_fields))
2185
+ DBUG_RETURN(1);
2186
+
2187
+ /* Give storage engine access to temporary table */
2188
+ gbh->table= table;
2142
2189
pushdown_query->store_data_in_temp_table= need_tmp;
2143
2190
pushdown_query->having= having;
2191
+
2144
2192
/*
2145
2193
Group by and having is calculated by the group_by handler.
2146
2194
Reset the group by and having
2147
2195
*/
2148
2196
DBUG_ASSERT(query.group_by == NULL);
2149
2197
group= 0; group_list= 0;
2150
2198
having= tmp_having= 0;
2151
-
2199
+ /*
2200
+ Select distinct is handled by handler or by creating an unique index
2201
+ over all fields in the temporary table
2202
+ */
2203
+ select_distinct= 0;
2152
2204
order= query.order_by;
2205
+ tmp_table_param.field_count+= tmp_table_param.sum_func_count;
2206
+ tmp_table_param.sum_func_count= 0;
2207
+
2208
+ fields= curr_fields_list;
2209
+
2210
+ //todo: new:
2211
+ curr_tab->ref_array= &items1;
2212
+ curr_tab->all_fields= &tmp_all_fields1;
2213
+ curr_tab->fields= &tmp_fields_list1;
2214
+
2215
+ DBUG_RETURN(thd->is_fatal_error);
2153
2216
}
2154
2217
}
2155
2218
}
2156
- #endif
2157
2219
2158
- /*
2159
- Setup last table to provide fields and all_fields lists to the next
2160
- node in the plan.
2161
- */
2162
- if (join_tab)
2163
- {
2164
- join_tab[top_join_tab_count - 1].fields= &fields_list;
2165
- join_tab[top_join_tab_count - 1].all_fields= &all_fields;
2166
- }
2167
2220
2168
2221
/*
2169
2222
The loose index scan access method guarantees that all grouping or
@@ -3206,8 +3259,6 @@ void JOIN::exec_inner()
3206
3259
3207
3260
if (select_options & SELECT_DESCRIBE)
3208
3261
{
3209
- do_select_call_count= 0;
3210
-
3211
3262
select_describe(this, need_tmp,
3212
3263
order != 0 && !skip_sort_order,
3213
3264
select_distinct,
@@ -8495,6 +8546,9 @@ bool JOIN::get_best_combination()
8495
8546
(order ? 1 : 0) +
8496
8547
(select_options & (SELECT_BIG_RESULT | OPTION_BUFFER_RESULT) ? 1 : 0) ;
8497
8548
8549
+ if (aggr_tables == 0)
8550
+ aggr_tables= 1; /* For group by pushdown */
8551
+
8498
8552
if (select_lex->window_specs.elements)
8499
8553
aggr_tables++;
8500
8554
@@ -17613,16 +17667,33 @@ do_select(JOIN *join, Procedure *procedure)
17613
17667
enum_nested_loop_state error= NESTED_LOOP_OK;
17614
17668
DBUG_ENTER("do_select");
17615
17669
17616
- join->do_select_call_count++;
17617
-
17618
- if (join->pushdown_query && join->do_select_call_count == 1)
17670
+ if (join->pushdown_query)
17619
17671
{
17620
17672
/* Select fields are in the temporary table */
17621
17673
join->fields= &join->tmp_fields_list1;
17622
17674
/* Setup HAVING to work with fields in temporary table */
17623
17675
join->set_items_ref_array(join->items1);
17624
17676
/* The storage engine will take care of the group by query result */
17625
17677
int res= join->pushdown_query->execute(join);
17678
+
17679
+ if (res)
17680
+ DBUG_RETURN(res);
17681
+
17682
+ if (join->pushdown_query->store_data_in_temp_table)
17683
+ {
17684
+ JOIN_TAB *last_tab= join->join_tab + join->table_count;
17685
+ last_tab->next_select= end_send;
17686
+
17687
+ enum_nested_loop_state state= last_tab->aggr->end_send();
17688
+ if (state >= NESTED_LOOP_OK)
17689
+ state= sub_select(join, last_tab, true);
17690
+
17691
+ if (state < NESTED_LOOP_OK)
17692
+ res= 1;
17693
+
17694
+ if (join->result->send_eof())
17695
+ res= 1;
17696
+ }
17626
17697
DBUG_RETURN(res);
17627
17698
}
17628
17699
0 commit comments