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