Commit 7ca8b4bb authored by Sergei Golubchik's avatar Sergei Golubchik

move internal API out from group_by_handler

into a Pushdown_query object
parent 9ca3d9ea
......@@ -35,15 +35,17 @@
-1 if error should be sent
*/
int group_by_handler::execute(JOIN *join)
int Pushdown_query::execute(JOIN *join)
{
int err;
ha_rows max_limit;
ha_rows *reset_limit= 0;
Item **reset_item= 0;
DBUG_ENTER("group_by_handler::execute");
THD *thd= handler->thd;
TABLE *table= handler->table;
DBUG_ENTER("Pushdown_query::execute");
if ((err= init_scan()))
if ((err= handler->init_scan()))
goto error;
if (store_data_in_temp_table)
......@@ -58,17 +60,17 @@ int group_by_handler::execute(JOIN *join)
reset_item= &join->unit->fake_select_lex->select_limit;
}
while (!(err= next_row()))
while (!(err= handler->next_row()))
{
if (thd->check_killed())
{
thd->send_kill_message();
(void) end_scan();
handler->end_scan();
DBUG_RETURN(-1);
}
/* Check if we can accept the row */
if (!having || having->val_bool())
if (!handler->having || handler->having->val_bool())
{
if (store_data_in_temp_table)
{
......@@ -97,7 +99,7 @@ int group_by_handler::execute(JOIN *join)
/* result < 0 if row was not accepted and should not be counted */
if ((error= join->result->send_data(*join->fields)))
{
(void) end_scan();
handler->end_scan();
DBUG_RETURN(error < 0 ? 0 : -1);
}
}
......@@ -119,7 +121,7 @@ int group_by_handler::execute(JOIN *join)
if (err != 0 && err != HA_ERR_END_OF_FILE)
goto error;
if ((err= end_scan()))
if ((err= handler->end_scan()))
goto error_2;
if (!store_data_in_temp_table && join->result->send_eof())
DBUG_RETURN(1); // Don't send error to client
......@@ -127,9 +129,9 @@ int group_by_handler::execute(JOIN *join)
DBUG_RETURN(0);
error:
(void) end_scan();
handler->end_scan();
error_2:
print_error(err, MYF(0));
handler->print_error(err, MYF(0));
DBUG_RETURN(-1); // Error not sent to client
}
......
......@@ -18,7 +18,7 @@
This file implements the group_by_handler interface. This interface
can be used by storage handlers that can intercept summary or GROUP
BY queries from MariaDB and itself return the result to the user or
upper level.
upper level. It is part of the Storage Engine API
Both main and sub queries are supported. Here are some examples of what the
storage engine could intersept:
......@@ -30,35 +30,26 @@
SELECT a, (select sum(*) from t2 where t1.a=t2.a) from t2;
*/
class JOIN;
class group_by_handler
{
public:
/* Arguments for group_by_handler, for usage later */
THD *thd;
SELECT_LEX *select_lex;
List<Item> *fields;
TABLE_LIST *table_list;
ORDER *group_by, *order_by;
Item *where, *having;
handlerton *ht; /* storage engine of this handler */
handlerton *ht;
/* Temporary table where all results should be stored in record[0] */
TABLE *table;
bool store_data_in_temp_table; /* Set by mariadb */
group_by_handler(THD *thd_arg, SELECT_LEX *select_lex_arg,
List<Item> *fields_arg,
group_by_handler(THD *thd_arg, List<Item> *fields_arg,
TABLE_LIST *table_list_arg, ORDER *group_by_arg,
ORDER *order_by_arg, Item *where_arg,
Item *having_arg, handlerton *ht_arg)
: thd(thd_arg), select_lex(select_lex_arg), fields(fields_arg),
table_list(table_list_arg), group_by(group_by_arg),
order_by(order_by_arg), where(where_arg), having(having_arg),
ht(ht_arg), table(0), store_data_in_temp_table(0)
{}
ORDER *order_by_arg, Item *where_arg, Item *having_arg,
handlerton *ht_arg)
: thd(thd_arg), fields(fields_arg), table_list(table_list_arg),
group_by(group_by_arg), order_by(order_by_arg), where(where_arg),
having(having_arg), ht(ht_arg), table(0) {}
virtual ~group_by_handler() {}
/*
......@@ -118,9 +109,7 @@ class group_by_handler
/* End scanning */
virtual int end_scan()=0;
/* Function that calls the above scan functions */
int execute(JOIN *join);
/* Report errors */
virtual void print_error(int error, myf errflag);
};
......@@ -1267,8 +1267,7 @@ struct handlerton
The server guaranteeds that all tables in the list belong to this
storage engine.
*/
group_by_handler *(*create_group_by)(THD *thd, SELECT_LEX *select_lex,
List<Item> *fields,
group_by_handler *(*create_group_by)(THD *thd, List<Item> *fields,
TABLE_LIST *table_list, ORDER *group_by,
ORDER *order_by, Item *where,
Item *having);
......
......@@ -1918,14 +1918,12 @@ JOIN::optimize_inner()
(one_storage_engine && one_storage_engine->create_group_by))
{
/* Check if the storage engine can intercept the query */
if ((storage_handler_for_group_by=
(one_storage_engine->create_group_by)(thd, select_lex,
&all_fields,
tables_list,
group_list, order,
conds, having)))
{
uint handler_flags= storage_handler_for_group_by->flags();
group_by_handler *gbh= one_storage_engine->create_group_by(thd, &all_fields,
tables_list, group_list, order, conds, having);
if (gbh)
{
pushdown_query= new (thd->mem_root) Pushdown_query(select_lex, gbh);
uint handler_flags= gbh->flags();
int err;
/*
......@@ -1962,13 +1960,13 @@ JOIN::optimize_inner()
DBUG_RETURN(1);
/* Give storage engine access to temporary table */
if ((err= storage_handler_for_group_by->init(exec_tmp_table1,
if ((err= gbh->init(exec_tmp_table1,
having, order)))
{
storage_handler_for_group_by->print_error(err, MYF(0));
gbh->print_error(err, MYF(0));
DBUG_RETURN(1);
}
storage_handler_for_group_by->store_data_in_temp_table= need_tmp;
pushdown_query->store_data_in_temp_table= need_tmp;
/*
If no ORDER BY clause was specified explicitly, we should sort things
according to the group_by
......@@ -2082,7 +2080,7 @@ int JOIN::init_execution()
thd->lex->set_limit_rows_examined();
/* Create a tmp table if distinct or if the sort is too complicated */
if (need_tmp && ! storage_handler_for_group_by)
if (need_tmp && !pushdown_query)
{
DBUG_PRINT("info",("Creating tmp table"));
THD_STAGE_INFO(thd, stage_copying_to_tmp_table);
......@@ -12053,8 +12051,8 @@ void JOIN::cleanup(bool full)
}
tmp_table_param.cleanup();
delete storage_handler_for_group_by;
storage_handler_for_group_by= 0;
delete pushdown_query;
pushdown_query= 0;
if (!join_tab)
{
......@@ -17854,15 +17852,14 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
join->fields= fields;
join->do_select_call_count++;
if (join->storage_handler_for_group_by &&
join->do_select_call_count == 1)
if (join->pushdown_query && join->do_select_call_count == 1)
{
/* Select fields are in the temporary table */
join->fields= &join->tmp_fields_list1;
/* Setup HAVING to work with fields in temporary table */
join->set_items_ref_array(join->items1);
/* The storage engine will take care of the group by query result */
int res= join->storage_handler_for_group_by->execute(join);
int res= join->pushdown_query->execute(join);
DBUG_RETURN(res);
}
......@@ -24330,7 +24327,7 @@ int JOIN::save_explain_data_intern(Explain_query *output, bool need_tmp_table,
explain->connection_type= Explain_node::EXPLAIN_NODE_DERIVED;
output->add_node(explain);
}
else if (storage_handler_for_group_by)
else if (pushdown_query)
{
explain= new (output->mem_root) Explain_select(output->mem_root,
thd->lex->analyze_stmt);
......
......@@ -884,6 +884,7 @@ class JOIN_TAB_RANGE: public Sql_alloc
JOIN_TAB *end;
};
class Pushdown_query;
class JOIN :public Sql_alloc
{
......@@ -1088,7 +1089,7 @@ class JOIN :public Sql_alloc
/* points to a storage engine if all tables comes from the storage engine */
handlerton *one_storage_engine;
group_by_handler *storage_handler_for_group_by;
Pushdown_query *pushdown_query;
JOIN_TAB *original_join_tab;
uint original_table_count;
......@@ -1391,7 +1392,7 @@ class JOIN :public Sql_alloc
no_rows_in_result_called= 0;
positions= best_positions= 0;
one_storage_engine= 0;
storage_handler_for_group_by= 0;
pushdown_query= 0;
original_join_tab= 0;
do_select_call_count= 0;
......@@ -1964,5 +1965,21 @@ ulong check_selectivity(THD *thd,
TABLE *table,
List<COND_STATISTIC> *conds);
class Pushdown_query: public Sql_alloc
{
public:
SELECT_LEX *select_lex;
bool store_data_in_temp_table;
group_by_handler *handler;
Pushdown_query(SELECT_LEX *select_lex_arg, group_by_handler *handler_arg)
: select_lex(select_lex_arg), store_data_in_temp_table(0),
handler(handler_arg) {}
~Pushdown_query() { delete handler; }
/* Function that calls the above scan functions */
int execute(JOIN *join);
};
#endif /* SQL_SELECT_INCLUDED */
......@@ -362,15 +362,12 @@ class ha_seq_group_by_handler: public group_by_handler
bool first_row;
public:
ha_seq_group_by_handler(THD *thd, SELECT_LEX *select_lex,
List<Item> *fields,
TABLE_LIST *table_list, ORDER *group_by,
ORDER *order_by, Item *where,
Item *having)
:group_by_handler(thd, select_lex, fields, table_list, group_by,
order_by, where, having, sequence_hton)
{
}
ha_seq_group_by_handler(THD *thd_arg, List<Item> *fields_arg,
TABLE_LIST *table_list_arg, ORDER *group_by_arg,
ORDER *order_by_arg, Item *where_arg,
Item *having_arg)
:group_by_handler(thd_arg, fields_arg, table_list_arg, group_by_arg,
order_by_arg, where_arg, having_arg, sequence_hton) {}
~ha_seq_group_by_handler() {}
bool init(TABLE *temporary_table, Item *having_arg,
ORDER *order_by_arg);
......@@ -380,10 +377,8 @@ class ha_seq_group_by_handler: public group_by_handler
};
static group_by_handler *
create_group_by_handler(THD *thd, SELECT_LEX *select_lex,
List<Item> *fields,
TABLE_LIST *table_list, ORDER *group_by,
ORDER *order_by, Item *where,
create_group_by_handler(THD *thd, List<Item> *fields, TABLE_LIST *table_list,
ORDER *group_by, ORDER *order_by, Item *where,
Item *having)
{
ha_seq_group_by_handler *handler;
......@@ -432,8 +427,7 @@ create_group_by_handler(THD *thd, SELECT_LEX *select_lex,
}
/* Create handler and return it */
handler= new ha_seq_group_by_handler(thd, select_lex, fields, table_list,
group_by,
handler= new ha_seq_group_by_handler(thd, fields, table_list, group_by,
order_by, where, having);
return handler;
}
......
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