summaryrefslogtreecommitdiff
path: root/sql/sql_class.h
diff options
context:
space:
mode:
authorIgor Babaev <igor@askmonty.org>2014-10-14 09:36:50 -0700
committerIgor Babaev <igor@askmonty.org>2014-10-14 09:36:50 -0700
commit3c4bb0e8720b84a14fe4822d1986d01290b9ab44 (patch)
treee474ca9e76d09e770c4e3d5c37e3161d1cc42ace /sql/sql_class.h
parentfec5ab5a56cb9a45c621207620cc85079cddf537 (diff)
downloadmariadb-git-3c4bb0e8720b84a14fe4822d1986d01290b9ab44.tar.gz
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.
Diffstat (limited to 'sql/sql_class.h')
-rw-r--r--sql/sql_class.h124
1 files changed, 123 insertions, 1 deletions
diff --git a/sql/sql_class.h b/sql/sql_class.h
index d7bbfc3799d..9fe524b5fe6 100644
--- a/sql/sql_class.h
+++ b/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
{