diff options
author | Igor Babaev <igor@askmonty.org> | 2014-10-14 09:36:50 -0700 |
---|---|---|
committer | Igor Babaev <igor@askmonty.org> | 2014-10-14 09:36:50 -0700 |
commit | 3c4bb0e8720b84a14fe4822d1986d01290b9ab44 (patch) | |
tree | e474ca9e76d09e770c4e3d5c37e3161d1cc42ace /sql/sql_class.h | |
parent | fec5ab5a56cb9a45c621207620cc85079cddf537 (diff) | |
download | mariadb-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.h | 124 |
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 { |