Commit 080522dc authored by Alexander Barkov's avatar Alexander Barkov

MDEV-23825 Join select_handler and Pushdown_select + XPand changes

parent d111e6ae
...@@ -21,10 +21,10 @@ ...@@ -21,10 +21,10 @@
/** /**
The methods of the Pushdown_select class. The methods of the select_handler class.
The objects of this class are used for pushdown of the select queries The objects of this class are used for pushdown of the select queries
into engines. The main method of the class is Pushdown_select::execute() into engines. The main method of the class is select_handler::execute()
that initiates execution of a select query by a foreign engine, receives the that initiates execution of a select query by a foreign engine, receives the
rows of the result set, put it in a buffer of a temporary table and send rows of the result set, put it in a buffer of a temporary table and send
them from the buffer directly into output. them from the buffer directly into output.
...@@ -36,51 +36,55 @@ ...@@ -36,51 +36,55 @@
*/ */
Pushdown_select::Pushdown_select(SELECT_LEX *sel, select_handler *h) select_handler::select_handler(THD *thd_arg, handlerton *ht_arg)
: select(sel), handler(h) : thd(thd_arg), ht(ht_arg), table(NULL),
{ is_analyze(thd_arg->lex->analyze_stmt)
is_analyze= handler->thd->lex->analyze_stmt; {}
}
Pushdown_select::~Pushdown_select() select_handler::~select_handler()
{ {
if (handler->table) if (table)
free_tmp_table(handler->thd, handler->table); free_tmp_table(thd, table);
delete handler;
select->select_h= NULL;
} }
bool Pushdown_select::init() TABLE *select_handler::create_tmp_table(THD *thd, SELECT_LEX *select)
{ {
DBUG_ENTER("select_handler::create_tmp_table");
List<Item> types; List<Item> types;
TMP_TABLE_PARAM tmp_table_param; TMP_TABLE_PARAM tmp_table_param;
THD *thd= handler->thd;
DBUG_ENTER("Pushdown_select::init");
if (select->master_unit()->join_union_item_types(thd, types, 1)) if (select->master_unit()->join_union_item_types(thd, types, 1))
DBUG_RETURN(true); DBUG_RETURN(NULL);
tmp_table_param.init(); tmp_table_param.init();
tmp_table_param.field_count= types.elements; tmp_table_param.field_count= types.elements;
handler->table= create_tmp_table(thd, &tmp_table_param, types, TABLE *table= ::create_tmp_table(thd, &tmp_table_param, types,
(ORDER *) 0, false, 0, (ORDER *) 0, false, 0,
TMP_TABLE_ALL_COLUMNS, 1, TMP_TABLE_ALL_COLUMNS, 1,
&empty_clex_str, true, false); &empty_clex_str, true, false);
if (!handler->table) DBUG_RETURN(table);
DBUG_RETURN(true); }
if (handler->table->fill_item_list(&result_columns))
bool select_handler::prepare()
{
DBUG_ENTER("select_handler::prepare");
/*
Some engines (e.g. XPand) initialize "table" on their own.
So we need to create a temporary table only if "table" is NULL.
*/
if (!table && !(table= create_tmp_table(thd, select)))
DBUG_RETURN(true); DBUG_RETURN(true);
DBUG_RETURN(false); DBUG_RETURN(table->fill_item_list(&result_columns));
} }
bool Pushdown_select::send_result_set_metadata() bool select_handler::send_result_set_metadata()
{ {
DBUG_ENTER("Pushdown_select::send_result_set_metadata"); DBUG_ENTER("select_handler::send_result_set_metadata");
#ifdef WITH_WSREP #ifdef WITH_WSREP
THD *thd= handler->thd;
if (WSREP(thd) && thd->wsrep_retry_query) if (WSREP(thd) && thd->wsrep_retry_query)
{ {
WSREP_DEBUG("skipping select metadata"); WSREP_DEBUG("skipping select metadata");
...@@ -96,7 +100,7 @@ bool Pushdown_select::send_result_set_metadata() ...@@ -96,7 +100,7 @@ bool Pushdown_select::send_result_set_metadata()
} }
bool Pushdown_select::send_data() bool select_handler::send_data()
{ {
DBUG_ENTER("Pushdown_select::send_data"); DBUG_ENTER("Pushdown_select::send_data");
...@@ -107,9 +111,9 @@ bool Pushdown_select::send_data() ...@@ -107,9 +111,9 @@ bool Pushdown_select::send_data()
} }
bool Pushdown_select::send_eof() bool select_handler::send_eof()
{ {
DBUG_ENTER("Pushdown_select::send_eof"); DBUG_ENTER("select_handler::send_eof");
if (select->join->result->send_eof()) if (select->join->result->send_eof())
DBUG_RETURN(true); DBUG_RETURN(true);
...@@ -117,30 +121,29 @@ bool Pushdown_select::send_eof() ...@@ -117,30 +121,29 @@ bool Pushdown_select::send_eof()
} }
int Pushdown_select::execute() int select_handler::execute()
{ {
int err; int err;
THD *thd= handler->thd;
DBUG_ENTER("Pushdown_select::execute"); DBUG_ENTER("select_handler::execute");
if ((err= handler->init_scan())) if ((err= init_scan()))
goto error; goto error;
if (is_analyze) if (is_analyze)
{ {
handler->end_scan(); end_scan();
DBUG_RETURN(0); DBUG_RETURN(0);
} }
if (send_result_set_metadata()) if (send_result_set_metadata())
DBUG_RETURN(-1); DBUG_RETURN(-1);
while (!(err= handler->next_row())) while (!(err= next_row()))
{ {
if (thd->check_killed() || send_data()) if (thd->check_killed() || send_data())
{ {
handler->end_scan(); end_scan();
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
} }
...@@ -148,7 +151,7 @@ int Pushdown_select::execute() ...@@ -148,7 +151,7 @@ int Pushdown_select::execute()
if (err != 0 && err != HA_ERR_END_OF_FILE) if (err != 0 && err != HA_ERR_END_OF_FILE)
goto error; goto error;
if ((err= handler->end_scan())) if ((err= end_scan()))
goto error_2; goto error_2;
if (send_eof()) if (send_eof())
...@@ -157,9 +160,9 @@ int Pushdown_select::execute() ...@@ -157,9 +160,9 @@ int Pushdown_select::execute()
DBUG_RETURN(0); DBUG_RETURN(0);
error: error:
handler->end_scan(); end_scan();
error_2: error_2:
handler->print_error(err, MYF(0)); print_error(err, MYF(0));
DBUG_RETURN(-1); // Error not sent to client DBUG_RETURN(-1); // Error not sent to client
} }
......
...@@ -41,12 +41,24 @@ class select_handler ...@@ -41,12 +41,24 @@ class select_handler
The table is actually never filled. Only its record buffer is used. The table is actually never filled. Only its record buffer is used.
*/ */
TABLE *table; TABLE *table;
List<Item> result_columns;
select_handler(THD *thd_arg, handlerton *ht_arg) bool is_analyze;
: thd(thd_arg), ht(ht_arg), table(0) {}
virtual ~select_handler() {} bool send_result_set_metadata();
bool send_data();
select_handler(THD *thd_arg, handlerton *ht_arg);
virtual ~select_handler();
int execute();
virtual bool prepare();
static TABLE *create_tmp_table(THD *thd, SELECT_LEX *sel);
protected:
/* /*
Functions to scan the select result set. Functions to scan the select result set.
All these returns 0 if ok, error code in case of error. All these returns 0 if ok, error code in case of error.
...@@ -67,6 +79,8 @@ class select_handler ...@@ -67,6 +79,8 @@ class select_handler
/* Report errors */ /* Report errors */
virtual void print_error(int error, myf errflag); virtual void print_error(int error, myf errflag);
bool send_eof();
}; };
#endif /* SELECT_HANDLER_INCLUDED */ #endif /* SELECT_HANDLER_INCLUDED */
...@@ -1334,10 +1334,8 @@ class st_select_lex: public st_select_lex_node ...@@ -1334,10 +1334,8 @@ class st_select_lex: public st_select_lex_node
table_value_constr *tvc; table_value_constr *tvc;
bool in_tvc; bool in_tvc;
/* The interface employed to execute the select query by a foreign engine */
select_handler *select_h;
/* The object used to organize execution of the query by a foreign engine */ /* The object used to organize execution of the query by a foreign engine */
Pushdown_select *pushdown_select; select_handler *pushdown_select;
/** System Versioning */ /** System Versioning */
public: public:
......
...@@ -1608,7 +1608,7 @@ int JOIN::optimize() ...@@ -1608,7 +1608,7 @@ int JOIN::optimize()
if (!(select_options & SELECT_DESCRIBE)) if (!(select_options & SELECT_DESCRIBE))
{ {
/* Prepare to execute the query pushed into a foreign engine */ /* Prepare to execute the query pushed into a foreign engine */
res= select_lex->pushdown_select->init(); res= select_lex->pushdown_select->prepare();
} }
with_two_phase_optimization= false; with_two_phase_optimization= false;
} }
...@@ -4632,19 +4632,7 @@ mysql_select(THD *thd, TABLE_LIST *tables, List<Item> &fields, COND *conds, ...@@ -4632,19 +4632,7 @@ mysql_select(THD *thd, TABLE_LIST *tables, List<Item> &fields, COND *conds,
} }
/* Look for a table owned by an engine with the select_handler interface */ /* Look for a table owned by an engine with the select_handler interface */
select_lex->select_h= select_lex->find_select_handler(thd); select_lex->pushdown_select= select_lex->find_select_handler(thd);
if (select_lex->select_h)
{
/* Create a Pushdown_select object for later execution of the query */
if (!(select_lex->pushdown_select=
new (thd->mem_root) Pushdown_select(select_lex,
select_lex->select_h)))
{
delete select_lex->select_h;
select_lex->select_h= NULL;
DBUG_RETURN(TRUE);
}
}
if ((err= join->optimize())) if ((err= join->optimize()))
{ {
......
...@@ -2517,29 +2517,6 @@ class Pushdown_derived: public Sql_alloc ...@@ -2517,29 +2517,6 @@ class Pushdown_derived: public Sql_alloc
class select_handler; class select_handler;
class Pushdown_select: public Sql_alloc
{
private:
bool is_analyze;
List<Item> result_columns;
bool send_result_set_metadata();
bool send_data();
bool send_eof();
public:
SELECT_LEX *select;
select_handler *handler;
Pushdown_select(SELECT_LEX *sel, select_handler *h);
~Pushdown_select();
bool init();
int execute();
};
bool test_if_order_compatible(SQL_I_List<ORDER> &a, SQL_I_List<ORDER> &b); bool test_if_order_compatible(SQL_I_List<ORDER> &a, SQL_I_List<ORDER> &b);
int test_if_group_changed(List<Cached_item> &list); int test_if_group_changed(List<Cached_item> &list);
int create_sort_index(THD *thd, JOIN *join, JOIN_TAB *tab, Filesort *fsort); int create_sort_index(THD *thd, JOIN *join, JOIN_TAB *tab, Filesort *fsort);
......
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