mirror of
https://github.com/MariaDB/server.git
synced 2025-07-27 18:02:13 +03:00
MDEV-334: Backport of UNION ALL optimization from mysql-5.7.
Although the original code of mysql-5.7 was adjusted to the current MariaDB code the main ideas of the optimization were preserved.
This commit is contained in:
124
sql/sql_class.h
124
sql/sql_class.h
@ -3914,6 +3914,23 @@ protected:
|
||||
public:
|
||||
select_result();
|
||||
virtual ~select_result() {};
|
||||
/**
|
||||
Change wrapped select_result.
|
||||
|
||||
Replace the wrapped result object with new_result and call
|
||||
prepare() and prepare2() on new_result.
|
||||
|
||||
This base class implementation doesn't wrap other select_results.
|
||||
|
||||
@param new_result The new result object to wrap around
|
||||
|
||||
@retval false Success
|
||||
@retval true Error
|
||||
*/
|
||||
virtual bool change_result(select_result *new_result)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
virtual int prepare(List<Item> &list, SELECT_LEX_UNIT *u)
|
||||
{
|
||||
unit= u;
|
||||
@ -4321,9 +4338,19 @@ public:
|
||||
|
||||
select_union() :write_err(0), table(0), records(0) { tmp_table_param.init(); }
|
||||
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
|
||||
/**
|
||||
Do prepare() and prepare2() if they have been postponed until
|
||||
column type information is computed (used by select_union_direct).
|
||||
|
||||
@param types Column types
|
||||
|
||||
@return false on success, true on failure
|
||||
*/
|
||||
virtual bool postponed_prepare(List<Item> &types)
|
||||
{ return false; }
|
||||
int send_data(List<Item> &items);
|
||||
bool send_eof();
|
||||
bool flush();
|
||||
virtual bool flush();
|
||||
void cleanup();
|
||||
virtual bool create_result_table(THD *thd, List<Item> *column_types,
|
||||
bool is_distinct, ulonglong options,
|
||||
@ -4334,6 +4361,101 @@ public:
|
||||
TMP_TABLE_PARAM *get_tmp_table_param() { return &tmp_table_param; }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
UNION result that is passed directly to the receiving select_result
|
||||
without filling a temporary table.
|
||||
|
||||
Function calls are forwarded to the wrapped select_result, but some
|
||||
functions are expected to be called only once for each query, so
|
||||
they are only executed for the first SELECT in the union (execept
|
||||
for send_eof(), which is executed only for the last SELECT).
|
||||
|
||||
This select_result is used when a UNION is not DISTINCT and doesn't
|
||||
have a global ORDER BY clause. @see st_select_lex_unit::prepare().
|
||||
*/
|
||||
|
||||
class select_union_direct :public select_union
|
||||
{
|
||||
private:
|
||||
/* Result object that receives all rows */
|
||||
select_result *result;
|
||||
/* The last SELECT_LEX of the union */
|
||||
SELECT_LEX *last_select_lex;
|
||||
|
||||
/* Wrapped result has received metadata */
|
||||
bool done_send_result_set_metadata;
|
||||
/* Wrapped result has initialized tables */
|
||||
bool done_initialize_tables;
|
||||
|
||||
/* Accumulated limit_found_rows */
|
||||
ulonglong limit_found_rows;
|
||||
|
||||
/* Number of rows offset */
|
||||
ha_rows offset;
|
||||
/* Number of rows limit + offset, @see select_union_direct::send_data() */
|
||||
ha_rows limit;
|
||||
|
||||
public:
|
||||
select_union_direct(select_result *result, SELECT_LEX *last_select_lex)
|
||||
:result(result), last_select_lex(last_select_lex),
|
||||
done_send_result_set_metadata(false), done_initialize_tables(false),
|
||||
limit_found_rows(0)
|
||||
{}
|
||||
bool change_result(select_result *new_result);
|
||||
uint field_count(List<Item> &fields) const
|
||||
{
|
||||
// Only called for top-level select_results, usually select_send
|
||||
DBUG_ASSERT(false); /* purecov: inspected */
|
||||
return 0; /* purecov: inspected */
|
||||
}
|
||||
bool postponed_prepare(List<Item> &types);
|
||||
bool send_result_set_metadata(List<Item> &list, uint flags);
|
||||
int send_data(List<Item> &items);
|
||||
bool initialize_tables (JOIN *join= NULL);
|
||||
bool send_eof();
|
||||
bool flush() { return false; }
|
||||
bool check_simple_select() const
|
||||
{
|
||||
/* Only called for top-level select_results, usually select_send */
|
||||
DBUG_ASSERT(false); /* purecov: inspected */
|
||||
return false; /* purecov: inspected */
|
||||
}
|
||||
void abort_result_set()
|
||||
{
|
||||
result->abort_result_set(); /* purecov: inspected */
|
||||
}
|
||||
void cleanup()
|
||||
{
|
||||
/*
|
||||
Only called for top-level select_results, usually select_send,
|
||||
and for the results of subquery engines
|
||||
(select_<something>_subselect).
|
||||
*/
|
||||
DBUG_ASSERT(false); /* purecov: inspected */
|
||||
}
|
||||
void set_thd(THD *thd_arg)
|
||||
{
|
||||
/*
|
||||
Only called for top-level select_results, usually select_send,
|
||||
and for the results of subquery engines
|
||||
(select_<something>_subselect).
|
||||
*/
|
||||
DBUG_ASSERT(false); /* purecov: inspected */
|
||||
}
|
||||
void reset_offset_limit_cnt()
|
||||
{
|
||||
// EXPLAIN should never output to a select_union_direct
|
||||
DBUG_ASSERT(false); /* purecov: inspected */
|
||||
}
|
||||
void begin_dataset()
|
||||
{
|
||||
// Only called for sp_cursor::Select_fetch_into_spvars
|
||||
DBUG_ASSERT(false); /* purecov: inspected */
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/* Base subselect interface class */
|
||||
class select_subselect :public select_result_interceptor
|
||||
{
|
||||
|
Reference in New Issue
Block a user