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 @@
/**
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
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
rows of the result set, put it in a buffer of a temporary table and send
them from the buffer directly into output.
......@@ -36,51 +36,55 @@
*/
Pushdown_select::Pushdown_select(SELECT_LEX *sel, select_handler *h)
: select(sel), handler(h)
{
is_analyze= handler->thd->lex->analyze_stmt;
}
select_handler::select_handler(THD *thd_arg, handlerton *ht_arg)
: thd(thd_arg), ht(ht_arg), table(NULL),
is_analyze(thd_arg->lex->analyze_stmt)
{}
Pushdown_select::~Pushdown_select()
select_handler::~select_handler()
{
if (handler->table)
free_tmp_table(handler->thd, handler->table);
delete handler;
select->select_h= NULL;
if (table)
free_tmp_table(thd, table);
}
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;
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))
DBUG_RETURN(true);
DBUG_RETURN(NULL);
tmp_table_param.init();
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,
TMP_TABLE_ALL_COLUMNS, 1,
&empty_clex_str, true, false);
if (!handler->table)
DBUG_RETURN(true);
if (handler->table->fill_item_list(&result_columns))
DBUG_RETURN(table);
}
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(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
THD *thd= handler->thd;
if (WSREP(thd) && thd->wsrep_retry_query)
{
WSREP_DEBUG("skipping select 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");
......@@ -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())
DBUG_RETURN(true);
......@@ -117,30 +121,29 @@ bool Pushdown_select::send_eof()
}
int Pushdown_select::execute()
int select_handler::execute()
{
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;
if (is_analyze)
{
handler->end_scan();
end_scan();
DBUG_RETURN(0);
}
if (send_result_set_metadata())
DBUG_RETURN(-1);
while (!(err= handler->next_row()))
while (!(err= next_row()))
{
if (thd->check_killed() || send_data())
{
handler->end_scan();
end_scan();
DBUG_RETURN(-1);
}
}
......@@ -148,7 +151,7 @@ int Pushdown_select::execute()
if (err != 0 && err != HA_ERR_END_OF_FILE)
goto error;
if ((err= handler->end_scan()))
if ((err= end_scan()))
goto error_2;
if (send_eof())
......@@ -157,9 +160,9 @@ int Pushdown_select::execute()
DBUG_RETURN(0);
error:
handler->end_scan();
end_scan();
error_2:
handler->print_error(err, MYF(0));
print_error(err, MYF(0));
DBUG_RETURN(-1); // Error not sent to client
}
......
......@@ -41,12 +41,24 @@ class select_handler
The table is actually never filled. Only its record buffer is used.
*/
TABLE *table;
List<Item> result_columns;
select_handler(THD *thd_arg, handlerton *ht_arg)
: thd(thd_arg), ht(ht_arg), table(0) {}
bool is_analyze;
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.
All these returns 0 if ok, error code in case of error.
......@@ -67,6 +79,8 @@ class select_handler
/* Report errors */
virtual void print_error(int error, myf errflag);
bool send_eof();
};
#endif /* SELECT_HANDLER_INCLUDED */
......@@ -1334,10 +1334,8 @@ class st_select_lex: public st_select_lex_node
table_value_constr *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 */
Pushdown_select *pushdown_select;
select_handler *pushdown_select;
/** System Versioning */
public:
......
......@@ -1608,7 +1608,7 @@ int JOIN::optimize()
if (!(select_options & SELECT_DESCRIBE))
{
/* 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;
}
......@@ -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 */
select_lex->select_h= 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);
}
}
select_lex->pushdown_select= select_lex->find_select_handler(thd);
if ((err= join->optimize()))
{
......
......@@ -2517,29 +2517,6 @@ class Pushdown_derived: public Sql_alloc
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);
int test_if_group_changed(List<Cached_item> &list);
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