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 */