revision-id: 84774c5dda7a4eaf4d8bc5a5ee5100a8286dc451 (mariadb-10.3.6-133-g84774c5) parent(s): 23e8c2f07473bb1bc7d5430e59f60729b9d92e56 author: Igor Babaev committer: Igor Babaev timestamp: 2019-01-28 19:24:00 -0800 message: MDEV-17631 select_handler for a full query pushdown MDEV-17096 Pushdown of simple derived tables to storage engines Put the implementation of the interfaces derived_handler and select_handler for FEDERATEDX into the new files federatedx_pushdown.h and federated_pushdown.cc. --- sql/select_handler.cc | 1 + sql/sql_derived.cc | 6 +- sql/sql_select.cc | 22 +-- storage/federatedx/federatedx_pushdown.cc | 273 ++++++++++++++++++++++++++++++ storage/federatedx/federatedx_pushdown.h | 63 +++++++ storage/federatedx/ha_federatedx.cc | 246 +-------------------------- storage/federatedx/ha_federatedx.h | 38 +---- 7 files changed, 356 insertions(+), 293 deletions(-) diff --git a/sql/select_handler.cc b/sql/select_handler.cc index da367f5..17475f4 100644 --- a/sql/select_handler.cc +++ b/sql/select_handler.cc @@ -13,6 +13,7 @@ Pushdown_select::Pushdown_select(SELECT_LEX *sel, select_handler *h) Pushdown_select::~Pushdown_select() { delete handler; + select->select_h= NULL; } bool Pushdown_select::init() diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 7e7ac02..9b17dd3 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -918,7 +918,11 @@ bool mysql_derived_optimize(THD *thd, LEX *lex, TABLE_LIST *derived) { if (!(derived->pushdown_derived= new (thd->mem_root) Pushdown_derived(derived, derived->dt_handler))) - DBUG_RETURN(1); + { + delete derived->dt_handler; + derived->dt_handler= NULL; + DBUG_RETURN(1); + } } lex->current_select= first_select; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 2753f1a..7c5287d 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -4065,18 +4065,11 @@ void JOIN::exec_inner() order != 0 && !skip_sort_order, select_distinct, !table_count ? "No tables used" : NullS); - if (select_lex->pushdown_select) - { - delete select_lex->pushdown_select; - select_lex->pushdown_select= NULL; - } DBUG_VOID_RETURN; } else if (select_lex->pushdown_select) { error= select_lex->pushdown_select->execute(); - delete select_lex->pushdown_select; - select_lex->pushdown_select= NULL; DBUG_VOID_RETURN; } else @@ -4290,16 +4283,18 @@ mysql_select(THD *thd, } } -#if 1 select_lex->select_h= select_lex->find_select_handler(thd); if (select_lex->select_h) { 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); + } } -#endif if ((err= join->optimize())) { @@ -4322,8 +4317,15 @@ mysql_select(THD *thd, select_lex->where= join->conds_history; select_lex->having= join->having_history; } - + err: + + if (select_lex->pushdown_select) + { + delete select_lex->pushdown_select; + select_lex->pushdown_select= NULL; + } + if (free_join) { THD_STAGE_INFO(thd, stage_end); diff --git a/storage/federatedx/federatedx_pushdown.cc b/storage/federatedx/federatedx_pushdown.cc new file mode 100644 index 0000000..bfe421c --- /dev/null +++ b/storage/federatedx/federatedx_pushdown.cc @@ -0,0 +1,273 @@ +/* + Copyright (c) 2019 MariaDB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +/* !!! For inclusion into ha_federatedx.cc */ + +static derived_handler* +create_federatedx_derived_handler(THD* thd, TABLE_LIST *derived) +{ + ha_federatedx_derived_handler* handler = NULL; + handlerton *ht= 0; + + SELECT_LEX_UNIT *unit= derived->derived; + + for (SELECT_LEX *sl= unit->first_select(); sl; sl= sl->next_select()) + { + if (!(sl->join)) + return 0; + for (TABLE_LIST *tbl= sl->join->tables_list; tbl; tbl= tbl->next_local) + { + if (!tbl->table) + return 0; + if (!ht) + ht= tbl->table->file->partition_ht(); + else if (ht != tbl->table->file->partition_ht()) + return 0; + } + } + + handler= new ha_federatedx_derived_handler(thd, derived); + + return handler; +} + + +/* + Implementation class of the derived_handler interface for FEDERATEDX: + class implementation +*/ + +ha_federatedx_derived_handler::ha_federatedx_derived_handler(THD *thd, + TABLE_LIST *dt) + : derived_handler(thd, federatedx_hton), + share(NULL), txn(NULL), iop(NULL), stored_result(NULL) +{ + derived= dt; +} + +ha_federatedx_derived_handler::~ha_federatedx_derived_handler() {} + +int ha_federatedx_derived_handler::init_scan() +{ + char query_buff[4096]; + THD *thd; + int rc= 0; + + DBUG_ENTER("ha_federatedx_derived_handler::init_scan"); + + TABLE *table= derived->get_first_table()->table; + ha_federatedx *h= (ha_federatedx *) table->file; + iop= &h->io; + share= get_share(table->s->table_name.str, table); + thd= table->in_use; + txn= h->get_txn(thd); + if ((rc= txn->acquire(share, thd, TRUE, iop))) + DBUG_RETURN(rc); + + String derived_query(query_buff, sizeof(query_buff), thd->charset()); + derived_query.length(0); + derived->derived->print(&derived_query, QT_ORDINARY); + + if ((*iop)->query(derived_query.ptr(), derived_query.length())) + goto err; + + stored_result= (*iop)->store_result(); + if (!stored_result) + goto err; + + DBUG_RETURN(0); + +err: + DBUG_RETURN(HA_FEDERATEDX_ERROR_WITH_REMOTE_SYSTEM); +} + +int ha_federatedx_derived_handler::next_row() +{ + int rc; + FEDERATEDX_IO_ROW *row; + ulong *lengths; + Field **field; + int column= 0; + Time_zone *saved_time_zone= table->in_use->variables.time_zone; + DBUG_ENTER("ha_federatedx_derived_handler::next_row"); + + if ((rc= txn->acquire(share, table->in_use, TRUE, iop))) + DBUG_RETURN(rc); + + if (!(row= (*iop)->fetch_row(stored_result))) + DBUG_RETURN(HA_ERR_END_OF_FILE); + + /* Convert row to internal format */ + table->in_use->variables.time_zone= UTC; + lengths= (*iop)->fetch_lengths(stored_result); + + for (field= table->field; *field; field++, column++) + { + if ((*iop)->is_column_null(row, column)) + (*field)->set_null(); + else + { + (*field)->set_notnull(); + (*field)->store((*iop)->get_column_data(row, column), + lengths[column], &my_charset_bin); + } + } + table->in_use->variables.time_zone= saved_time_zone; + + DBUG_RETURN(rc); +} + +int ha_federatedx_derived_handler::end_scan() +{ + DBUG_ENTER("ha_federatedx_derived_handler::end_scan"); + + (*iop)->free_result(stored_result); + + free_share(txn, share); + + DBUG_RETURN(0); +} + +void ha_federatedx_derived_handler::print_error(int, unsigned long) +{ +} + + +static select_handler* +create_federatedx_select_handler(THD* thd, SELECT_LEX *sel) +{ + ha_federatedx_select_handler* handler = NULL; + handlerton *ht= 0; + + for (TABLE_LIST *tbl= thd->lex->query_tables; tbl; tbl= tbl->next_global) + { + if (!tbl->table) + return 0; + if (!ht) + ht= tbl->table->file->partition_ht(); + else if (ht != tbl->table->file->partition_ht()) + return 0; + } + + handler= new ha_federatedx_select_handler(thd, sel); + + return handler; +} + +/* + Implementation class of the select_handler interface for FEDERATEDX: + class implementation +*/ + +ha_federatedx_select_handler::ha_federatedx_select_handler(THD *thd, + SELECT_LEX *sel) + : select_handler(thd, federatedx_hton), + share(NULL), txn(NULL), iop(NULL), stored_result(NULL) +{ + select= sel; +} + +ha_federatedx_select_handler::~ha_federatedx_select_handler() {} + +int ha_federatedx_select_handler::init_scan() +{ + int rc= 0; + + DBUG_ENTER("ha_federatedx_select_handler::init_scan"); + + TABLE *table= 0; + for (TABLE_LIST *tbl= thd->lex->query_tables; tbl; tbl= tbl->next_global) + { + if (!tbl->table) + continue; + table= tbl->table; + break; + } + ha_federatedx *h= (ha_federatedx *) table->file; + iop= &h->io; + share= get_share(table->s->table_name.str, table); + txn= h->get_txn(thd); + if ((rc= txn->acquire(share, thd, TRUE, iop))) + DBUG_RETURN(rc); + + if ((*iop)->query(thd->query(), thd->query_length())) + goto err; + + stored_result= (*iop)->store_result(); + if (!stored_result) + goto err; + + DBUG_RETURN(0); + +err: + DBUG_RETURN(HA_FEDERATEDX_ERROR_WITH_REMOTE_SYSTEM); +} + +int ha_federatedx_select_handler::next_row() +{ + int rc= 0; + FEDERATEDX_IO_ROW *row; + ulong *lengths; + Field **field; + int column= 0; + Time_zone *saved_time_zone= table->in_use->variables.time_zone; + DBUG_ENTER("ha_federatedx_select_handler::next_row"); + + if ((rc= txn->acquire(share, table->in_use, TRUE, iop))) + DBUG_RETURN(rc); + + if (!(row= (*iop)->fetch_row(stored_result))) + DBUG_RETURN(HA_ERR_END_OF_FILE); + + /* Convert row to internal format */ + table->in_use->variables.time_zone= UTC; + lengths= (*iop)->fetch_lengths(stored_result); + + for (field= table->field; *field; field++, column++) + { + if ((*iop)->is_column_null(row, column)) + (*field)->set_null(); + else + { + (*field)->set_notnull(); + (*field)->store((*iop)->get_column_data(row, column), + lengths[column], &my_charset_bin); + } + } + table->in_use->variables.time_zone= saved_time_zone; + + DBUG_RETURN(rc); +} + +int ha_federatedx_select_handler::end_scan() +{ + DBUG_ENTER("ha_federatedx_derived_handler::end_scan"); + + free_tmp_table(thd, table); + table= 0; + + (*iop)->free_result(stored_result); + + free_share(txn, share); + + DBUG_RETURN(0); +} + +void ha_federatedx_select_handler::print_error(int, unsigned long) +{ +} + + diff --git a/storage/federatedx/federatedx_pushdown.h b/storage/federatedx/federatedx_pushdown.h new file mode 100644 index 0000000..961571b --- /dev/null +++ b/storage/federatedx/federatedx_pushdown.h @@ -0,0 +1,63 @@ +/* + Copyright (c) 2019 MariaDB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include "derived_handler.h" +#include "select_handler.h" + +/* + Implementation class of the derived_handler interface for FEDERATEDX: + class declaration +*/ + +class ha_federatedx_derived_handler: public derived_handler +{ +private: + FEDERATEDX_SHARE *share; + federatedx_txn *txn; + federatedx_io **iop; + FEDERATEDX_IO_RESULT *stored_result; + +public: + ha_federatedx_derived_handler(THD* thd_arg, TABLE_LIST *tbl); + ~ha_federatedx_derived_handler(); + int init_scan(); + int next_row(); + int end_scan(); + void print_error(int, unsigned long); +}; + + +/* + Implementation class of the select_handler interface for FEDERATEDX: + class declaration +*/ + +class ha_federatedx_select_handler: public select_handler +{ +private: + FEDERATEDX_SHARE *share; + federatedx_txn *txn; + federatedx_io **iop; + FEDERATEDX_IO_RESULT *stored_result; + +public: + ha_federatedx_select_handler(THD* thd_arg, SELECT_LEX *sel); + ~ha_federatedx_select_handler(); + int init_scan(); + int next_row(); + int end_scan(); + void print_error(int, unsigned long); +}; diff --git a/storage/federatedx/ha_federatedx.cc b/storage/federatedx/ha_federatedx.cc index 174ee23..918fbef 100644 --- a/storage/federatedx/ha_federatedx.cc +++ b/storage/federatedx/ha_federatedx.cc @@ -3677,251 +3677,7 @@ int ha_federatedx::discover_assisted(handlerton *hton, THD* thd, return error; } - -static derived_handler* -create_federatedx_derived_handler(THD* thd, TABLE_LIST *derived) -{ - ha_federatedx_derived_handler* handler = NULL; - handlerton *ht= 0; - - SELECT_LEX_UNIT *unit= derived->derived; - - for (SELECT_LEX *sl= unit->first_select(); sl; sl= sl->next_select()) - { - if (!(sl->join)) - return 0; - for (TABLE_LIST *tbl= sl->join->tables_list; tbl; tbl= tbl->next_local) - { - if (!tbl->table) - return 0; - if (!ht) - ht= tbl->table->file->partition_ht(); - else if (ht != tbl->table->file->partition_ht()) - return 0; - } - } - - handler= new ha_federatedx_derived_handler(thd, derived); - - return handler; -} - - -ha_federatedx_derived_handler::ha_federatedx_derived_handler(THD *thd, - TABLE_LIST *dt) - : derived_handler(thd, federatedx_hton), - share(NULL), txn(NULL), iop(NULL), stored_result(NULL) -{ - derived= dt; -} - -ha_federatedx_derived_handler::~ha_federatedx_derived_handler() {} - -int ha_federatedx_derived_handler::init_scan() -{ - char query_buff[4096]; - THD *thd; - int rc= 0; - - DBUG_ENTER("ha_federatedx_derived_handler::init_scan"); - - TABLE *table= derived->get_first_table()->table; - ha_federatedx *h= (ha_federatedx *) table->file; - iop= &h->io; - share= get_share(table->s->table_name.str, table); - thd= table->in_use; - txn= h->get_txn(thd); - if ((rc= txn->acquire(share, thd, TRUE, iop))) - DBUG_RETURN(rc); - - String derived_query(query_buff, sizeof(query_buff), thd->charset()); - derived_query.length(0); - derived->derived->print(&derived_query, QT_ORDINARY); - - if ((*iop)->query(derived_query.ptr(), derived_query.length())) - goto err; - - stored_result= (*iop)->store_result(); - if (!stored_result) - goto err; - - DBUG_RETURN(0); - -err: - DBUG_RETURN(HA_FEDERATEDX_ERROR_WITH_REMOTE_SYSTEM); -} - -int ha_federatedx_derived_handler::next_row() -{ - int rc; - FEDERATEDX_IO_ROW *row; - ulong *lengths; - Field **field; - int column= 0; - Time_zone *saved_time_zone= table->in_use->variables.time_zone; - DBUG_ENTER("ha_federatedx_derived_handler::next_row"); - - if ((rc= txn->acquire(share, table->in_use, TRUE, iop))) - DBUG_RETURN(rc); - - if (!(row= (*iop)->fetch_row(stored_result))) - DBUG_RETURN(HA_ERR_END_OF_FILE); - - /* Convert row to internal format */ - table->in_use->variables.time_zone= UTC; - lengths= (*iop)->fetch_lengths(stored_result); - - for (field= table->field; *field; field++, column++) - { - if ((*iop)->is_column_null(row, column)) - (*field)->set_null(); - else - { - (*field)->set_notnull(); - (*field)->store((*iop)->get_column_data(row, column), - lengths[column], &my_charset_bin); - } - } - table->in_use->variables.time_zone= saved_time_zone; - - DBUG_RETURN(rc); -} - -int ha_federatedx_derived_handler::end_scan() -{ - DBUG_ENTER("ha_federatedx_derived_handler::end_scan"); - - (*iop)->free_result(stored_result); - - free_share(txn, share); - - DBUG_RETURN(0); -} - -void ha_federatedx_derived_handler::print_error(int, unsigned long) -{ -} - - -static select_handler* -create_federatedx_select_handler(THD* thd, SELECT_LEX *sel) -{ - ha_federatedx_select_handler* handler = NULL; - handlerton *ht= 0; - - for (TABLE_LIST *tbl= thd->lex->query_tables; tbl; tbl= tbl->next_global) - { - if (!tbl->table) - return 0; - if (!ht) - ht= tbl->table->file->partition_ht(); - else if (ht != tbl->table->file->partition_ht()) - return 0; - } - - handler= new ha_federatedx_select_handler(thd, sel); - - return handler; -} - -ha_federatedx_select_handler::ha_federatedx_select_handler(THD *thd, - SELECT_LEX *sel) - : select_handler(thd, federatedx_hton), - share(NULL), txn(NULL), iop(NULL), stored_result(NULL) -{ - select= sel; -} - -ha_federatedx_select_handler::~ha_federatedx_select_handler() {} - -int ha_federatedx_select_handler::init_scan() -{ - int rc= 0; - - DBUG_ENTER("ha_federatedx_select_handler::init_scan"); - - TABLE *table= 0; - for (TABLE_LIST *tbl= thd->lex->query_tables; tbl; tbl= tbl->next_global) - { - if (!tbl->table) - continue; - table= tbl->table; - break; - } - ha_federatedx *h= (ha_federatedx *) table->file; - iop= &h->io; - share= get_share(table->s->table_name.str, table); - txn= h->get_txn(thd); - if ((rc= txn->acquire(share, thd, TRUE, iop))) - DBUG_RETURN(rc); - - if ((*iop)->query(thd->query(), thd->query_length())) - goto err; - - stored_result= (*iop)->store_result(); - if (!stored_result) - goto err; - - DBUG_RETURN(0); - -err: - DBUG_RETURN(HA_FEDERATEDX_ERROR_WITH_REMOTE_SYSTEM); -} - -int ha_federatedx_select_handler::next_row() -{ - int rc= 0; - FEDERATEDX_IO_ROW *row; - ulong *lengths; - Field **field; - int column= 0; - Time_zone *saved_time_zone= table->in_use->variables.time_zone; - DBUG_ENTER("ha_federatedx_select_handler::next_row"); - - if ((rc= txn->acquire(share, table->in_use, TRUE, iop))) - DBUG_RETURN(rc); - - if (!(row= (*iop)->fetch_row(stored_result))) - DBUG_RETURN(HA_ERR_END_OF_FILE); - - /* Convert row to internal format */ - table->in_use->variables.time_zone= UTC; - lengths= (*iop)->fetch_lengths(stored_result); - - for (field= table->field; *field; field++, column++) - { - if ((*iop)->is_column_null(row, column)) - (*field)->set_null(); - else - { - (*field)->set_notnull(); - (*field)->store((*iop)->get_column_data(row, column), - lengths[column], &my_charset_bin); - } - } - table->in_use->variables.time_zone= saved_time_zone; - - DBUG_RETURN(rc); -} - -int ha_federatedx_select_handler::end_scan() -{ - DBUG_ENTER("ha_federatedx_derived_handler::end_scan"); - - free_tmp_table(thd, table); - table= 0; - - (*iop)->free_result(stored_result); - - free_share(txn, share); - - DBUG_RETURN(0); -} - -void ha_federatedx_select_handler::print_error(int, unsigned long) -{ -} - +#include "federatedx_pushdown.cc" struct st_mysql_storage_engine federatedx_storage_engine= { MYSQL_HANDLERTON_INTERFACE_VERSION }; diff --git a/storage/federatedx/ha_federatedx.h b/storage/federatedx/ha_federatedx.h index 3a5180f..c6af5f2 100644 --- a/storage/federatedx/ha_federatedx.h +++ b/storage/federatedx/ha_federatedx.h @@ -42,8 +42,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <my_global.h> #include <thr_lock.h> #include "handler.h" -#include "derived_handler.h" -#include "select_handler.h" class federatedx_io; @@ -468,40 +466,6 @@ extern federatedx_io *instantiate_io_mysql(MEM_ROOT *server_root, extern federatedx_io *instantiate_io_null(MEM_ROOT *server_root, FEDERATEDX_SERVER *server); - -class ha_federatedx_derived_handler: public derived_handler -{ -private: - FEDERATEDX_SHARE *share; - federatedx_txn *txn; - federatedx_io **iop; - FEDERATEDX_IO_RESULT *stored_result; - -public: - ha_federatedx_derived_handler(THD* thd_arg, TABLE_LIST *tbl); - ~ha_federatedx_derived_handler(); - int init_scan(); - int next_row(); - int end_scan(); - void print_error(int, unsigned long); -}; - - -class ha_federatedx_select_handler: public select_handler -{ -private: - FEDERATEDX_SHARE *share; - federatedx_txn *txn; - federatedx_io **iop; - FEDERATEDX_IO_RESULT *stored_result; - -public: - ha_federatedx_select_handler(THD* thd_arg, SELECT_LEX *sel); - ~ha_federatedx_select_handler(); - int init_scan(); - int next_row(); - int end_scan(); - void print_error(int, unsigned long); -}; +#include "federatedx_pushdown.h" #endif /* HA_FEDERATEDX_INCLUDED */