mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
move internal API out from group_by_handler
into a Pushdown_query object
This commit is contained in:
@ -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)
|
|||||||
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)
|
|||||||
/* 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)
|
|||||||
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)
|
|||||||
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 @@
|
|||||||
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 @@
|
|||||||
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 @@ public:
|
|||||||
/* 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
|
|||||||
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()
|
|||||||
(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,
|
|
||||||
conds, having)))
|
|
||||||
{
|
{
|
||||||
uint handler_flags= storage_handler_for_group_by->flags();
|
pushdown_query= new (thd->mem_root) Pushdown_query(select_lex, gbh);
|
||||||
|
uint handler_flags= gbh->flags();
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -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()
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
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)
|
|||||||
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,
|
|||||||
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 @@ public:
|
|||||||
JOIN_TAB *end;
|
JOIN_TAB *end;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Pushdown_query;
|
||||||
|
|
||||||
class JOIN :public Sql_alloc
|
class JOIN :public Sql_alloc
|
||||||
{
|
{
|
||||||
@ -1088,7 +1089,7 @@ public:
|
|||||||
|
|
||||||
/* 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 @@ public:
|
|||||||
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,
|
|||||||
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
|
|||||||
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 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
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,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 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;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user