[Commits] 23e8c2f: MDEV-17631 select_handler for a full query pushdown

IgorBabaev igor at mariadb.com
Mon Jan 28 09:44:27 EET 2019


revision-id: 23e8c2f07473bb1bc7d5430e59f60729b9d92e56 (mariadb-10.3.6-132-g23e8c2f)
parent(s): a30776dd98d8e7b44e8b3e2bc07c23c0beed2434
author: Igor Babaev
committer: Igor Babaev
timestamp: 2019-01-27 23:44:27 -0800
message:

MDEV-17631 select_handler for a full query pushdown
MDEV-17096 Pushdown of simple derived tables to storage engines

Fixed leakage problems of the implementation of the interfaces
for FEDERATEDX.

---
 .../federated/federatedx_create_handlers.result    | 110 +++++++++++++++++++++
 .../federated/federatedx_create_handlers.test      |  50 +++++++++-
 sql/derived_handler.cc                             |  12 +++
 sql/derived_handler.h                              |   6 +-
 sql/select_handler.cc                              |  13 +++
 sql/select_handler.h                               |  10 +-
 sql/sql_explain.cc                                 |  12 ++-
 sql/sql_explain.h                                  |   1 +
 sql/sql_lex.cc                                     |   5 +-
 sql/sql_select.cc                                  |  27 +++--
 sql/sql_select.h                                   |   9 +-
 storage/federatedx/ha_federatedx.cc                |  58 ++++++-----
 storage/federatedx/ha_federatedx.h                 |   5 +-
 13 files changed, 265 insertions(+), 53 deletions(-)

diff --git a/mysql-test/suite/federated/federatedx_create_handlers.result b/mysql-test/suite/federated/federatedx_create_handlers.result
index d32853e..fdad44c 100644
--- a/mysql-test/suite/federated/federatedx_create_handlers.result
+++ b/mysql-test/suite/federated/federatedx_create_handlers.result
@@ -15,6 +15,9 @@ name varchar(16) NOT NULL default ''
 DEFAULT CHARSET=latin1;
 INSERT INTO federated.t1 VALUES
 (3,'xxx'), (7,'yyy'), (4,'xxx'), (1,'zzz'), (5,'yyy');
+DROP TABLE IF EXISTS federated.t2;
+Warnings:
+Note	1051	Unknown table 'federated.t2'
 CREATE TABLE federated.t2 (
 name varchar(16) NOT NULL default ''  
 )
@@ -31,6 +34,9 @@ name varchar(16) NOT NULL default ''
 )
 ENGINE="FEDERATED" DEFAULT CHARSET=latin1
 CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1';
+DROP TABLE IF EXISTS federated.t2;
+Warnings:
+Note	1051	Unknown table 'federated.t2'
 CREATE TABLE federated.t2 (
 name varchar(16) NOT NULL default ''  
 )
@@ -80,6 +86,110 @@ WHERE id IN (SELECT count(*) FROM federated.t2 GROUP BY name);
 id	name
 3	xxx
 1	zzz
+EXPLAIN
+SELECT id FROM federated.t1 WHERE id < 5;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	PUSHED SELECT	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL
+EXPLAIN EXTENDED
+SELECT id FROM federated.t1 WHERE id < 5;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
+1	PUSHED SELECT	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL
+Warnings:
+Note	1003	select `federated`.`t1`.`id` AS `id` from `federated`.`t1` where `federated`.`t1`.`id` < 5
+EXPLAIN FORMAT=JSON
+SELECT id FROM federated.t1 WHERE id < 5;
+EXPLAIN
+{
+  "query_block": {
+    "select_id": 1,
+    "table": {
+      "message": "Pushed select"
+    }
+  }
+}
+ANALYZE
+SELECT id FROM federated.t1 WHERE id < 5;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	r_rows	filtered	r_filtered	Extra
+1	PUSHED SELECT	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL
+ANALYZE FORMAT=JSON
+SELECT id FROM federated.t1 WHERE id < 5;
+ANALYZE
+{
+  "query_block": {
+    "select_id": 1,
+    "table": {
+      "message": "Pushed select"
+    }
+  }
+}
+CREATE TABLE federated.t3 (
+name varchar(16) NOT NULL default ''  
+)
+DEFAULT CHARSET=latin1;
+INSERT INTO federated.t3 VALUES
+('yyy'), ('www'), ('yyy'), ('xxx'), ('www'), ('yyy'), ('www');
+SELECT *
+FROM federated.t3, (SELECT * FROM federated.t1 WHERE id > 3) t
+WHERE federated.t3.name=t.name;
+name	id	name
+yyy	5	yyy
+yyy	7	yyy
+yyy	5	yyy
+yyy	7	yyy
+xxx	4	xxx
+yyy	5	yyy
+yyy	7	yyy
+EXPLAIN
+SELECT *
+FROM federated.t3, (SELECT * FROM federated.t1 WHERE id > 3) t
+WHERE federated.t3.name=t.name;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	PRIMARY	t3	ALL	NULL	NULL	NULL	NULL	7	
+1	PRIMARY	<derived2>	ref	key0	key0	18	federated.t3.name	2	
+2	PUSHED DERIVED	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL
+EXPLAIN FORMAT=JSON
+SELECT *
+FROM federated.t3, (SELECT * FROM federated.t1 WHERE id > 3) t
+WHERE federated.t3.name=t.name;
+EXPLAIN
+{
+  "query_block": {
+    "select_id": 1,
+    "table": {
+      "table_name": "t3",
+      "access_type": "ALL",
+      "rows": 7,
+      "filtered": 100
+    },
+    "table": {
+      "table_name": "<derived2>",
+      "access_type": "ref",
+      "possible_keys": ["key0"],
+      "key": "key0",
+      "key_length": "18",
+      "used_key_parts": ["name"],
+      "ref": ["federated.t3.name"],
+      "rows": 2,
+      "filtered": 100,
+      "materialized": {
+        "query_block": {
+          "select_id": 2,
+          "table": {
+            "message": "Pushed derived"
+          }
+        }
+      }
+    }
+  }
+}
+ANALYZE
+SELECT *
+FROM federated.t3, (SELECT * FROM federated.t1 WHERE id > 3) t
+WHERE federated.t3.name=t.name;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	r_rows	filtered	r_filtered	Extra
+1	PRIMARY	t3	ALL	NULL	NULL	NULL	NULL	7	7.00	100.00	100.00	
+1	PRIMARY	<derived2>	ref	key0	key0	18	federated.t3.name	2	0.00	100.00	100.00	
+2	PUSHED DERIVED	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL
 DROP TABLE federated.t1, federated.t2;
 connection slave;
 DROP TABLE federated.t1, federated.t2;
diff --git a/mysql-test/suite/federated/federatedx_create_handlers.test b/mysql-test/suite/federated/federatedx_create_handlers.test
index 92a6f3c..0e586da 100644
--- a/mysql-test/suite/federated/federatedx_create_handlers.test
+++ b/mysql-test/suite/federated/federatedx_create_handlers.test
@@ -2,6 +2,7 @@
 --source include/federated.inc
 
 connection slave;
+
 DROP TABLE IF EXISTS federated.t1;
 
 CREATE TABLE federated.t1 (
@@ -13,6 +14,8 @@ DEFAULT CHARSET=latin1;
 INSERT INTO federated.t1 VALUES
   (3,'xxx'), (7,'yyy'), (4,'xxx'), (1,'zzz'), (5,'yyy');
 
+DROP TABLE IF EXISTS federated.t2;
+
 CREATE TABLE federated.t2 (
   name varchar(16) NOT NULL default ''  
 )
@@ -23,6 +26,7 @@ INSERT INTO federated.t2 VALUES
 
 
 connection master;
+
 DROP TABLE IF EXISTS federated.t1;
 
 --replace_result $SLAVE_MYPORT SLAVE_PORT
@@ -34,6 +38,8 @@ CREATE TABLE federated.t1 (
 ENGINE="FEDERATED" DEFAULT CHARSET=latin1
 CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1';
 
+DROP TABLE IF EXISTS federated.t2;
+
 --replace_result $SLAVE_MYPORT SLAVE_PORT
 eval
 CREATE TABLE federated.t2 (
@@ -56,8 +62,50 @@ SELECT * FROM federated.t1 LEFT JOIN federated.t2
   WHERE federated.t1.id > 1;
 
 SELECT * FROM federated.t1
-  WHERE id IN (SELECT count(*) FROM federated.t2 GROUP BY name); 
+  WHERE id IN (SELECT count(*) FROM federated.t2 GROUP BY name);
+
+EXPLAIN
+SELECT id FROM federated.t1 WHERE id < 5;
  
+EXPLAIN EXTENDED
+SELECT id FROM federated.t1 WHERE id < 5;
+
+EXPLAIN FORMAT=JSON
+SELECT id FROM federated.t1 WHERE id < 5;
+
+ANALYZE
+SELECT id FROM federated.t1 WHERE id < 5;
+
+ANALYZE FORMAT=JSON
+SELECT id FROM federated.t1 WHERE id < 5;
+
+CREATE TABLE federated.t3 (
+  name varchar(16) NOT NULL default ''  
+)
+DEFAULT CHARSET=latin1;
+
+INSERT INTO federated.t3 VALUES
+  ('yyy'), ('www'), ('yyy'), ('xxx'), ('www'), ('yyy'), ('www');
+
+SELECT *
+FROM federated.t3, (SELECT * FROM federated.t1 WHERE id > 3) t
+WHERE federated.t3.name=t.name; 
+
+EXPLAIN
+SELECT *
+FROM federated.t3, (SELECT * FROM federated.t1 WHERE id > 3) t
+WHERE federated.t3.name=t.name; 
+
+EXPLAIN FORMAT=JSON
+SELECT *
+FROM federated.t3, (SELECT * FROM federated.t1 WHERE id > 3) t
+WHERE federated.t3.name=t.name; 
+
+ANALYZE
+SELECT *
+FROM federated.t3, (SELECT * FROM federated.t1 WHERE id > 3) t
+WHERE federated.t3.name=t.name; 
+
 DROP TABLE federated.t1, federated.t2;
 
 connection slave; 
diff --git a/sql/derived_handler.cc b/sql/derived_handler.cc
index dd017fd..561c18a 100644
--- a/sql/derived_handler.cc
+++ b/sql/derived_handler.cc
@@ -14,6 +14,12 @@ void derived_handler::set_derived(TABLE_LIST *tbl)
                    &select->join->tmp_table_param;
 }
 
+Pushdown_derived::Pushdown_derived(TABLE_LIST *tbl, derived_handler *h)
+ : derived(tbl), handler(h)
+{ 
+  is_analyze= handler->thd->lex->analyze_stmt;
+}
+
 Pushdown_derived::~Pushdown_derived()
 {
   delete handler;
@@ -31,6 +37,12 @@ int Pushdown_derived::execute()
   if ((err= handler->init_scan()))
     goto error;
 
+  if (is_analyze)
+  {
+    handler->end_scan();
+    DBUG_RETURN(0);
+  }
+  
   while (!(err= handler->next_row()))
   {
     if (unlikely(thd->check_killed()))
diff --git a/sql/derived_handler.h b/sql/derived_handler.h
index a7b1294..c312a93 100644
--- a/sql/derived_handler.h
+++ b/sql/derived_handler.h
@@ -6,6 +6,8 @@
 
 class TMP_TABLE_PARAM;
 
+typedef class st_select_lex_unit SELECT_LEX_UNIT;
+
 class derived_handler
 {
 public:
@@ -23,9 +25,9 @@ class derived_handler
 
   TMP_TABLE_PARAM *tmp_table_param;
 
-  struct st_select_lex_unit *unit;
+  SELECT_LEX_UNIT *unit;
 
-  struct st_select_lex *select;
+  SELECT_LEX *select;
 
   derived_handler(THD *thd_arg, handlerton *ht_arg)
     : thd(thd_arg), ht(ht_arg), derived(0),table(0), tmp_table_param(0),
diff --git a/sql/select_handler.cc b/sql/select_handler.cc
index f196678..da367f5 100644
--- a/sql/select_handler.cc
+++ b/sql/select_handler.cc
@@ -3,6 +3,13 @@
 #include "sql_select.h"
 #include "select_handler.h"
 
+
+Pushdown_select::Pushdown_select(SELECT_LEX *sel, select_handler *h)
+  : select(sel), handler(h)
+{ 
+  is_analyze= handler->thd->lex->analyze_stmt;
+}
+
 Pushdown_select::~Pushdown_select()
 {
   delete handler;
@@ -100,6 +107,12 @@ int Pushdown_select::execute()
   if ((err= handler->init_scan()))
     goto error;
 
+  if (is_analyze)
+  {
+    handler->end_scan();
+    DBUG_RETURN(0);
+  }
+  
   if (send_result_set_metadata())
     DBUG_RETURN(-1);
   
diff --git a/sql/select_handler.h b/sql/select_handler.h
index 68fca03..3b1347e 100644
--- a/sql/select_handler.h
+++ b/sql/select_handler.h
@@ -12,7 +12,7 @@ class select_handler
 
   SELECT_LEX *select;
 
-   /*
+  /*
     Temporary table where all results should be stored in record[0]
     The table has a field for every item from the select_lex::item_list.
   */
@@ -29,20 +29,20 @@ class select_handler
   */
 
   /* Initialize the process of producing rows of result set */
-  virtual int init_scan()= 0;
+  virtual int init_scan() = 0;
 
   /*
     Put the next produced row of the result set in table->record[0] 
     and return 0. Return HA_ERR_END_OF_FILE if there are no more rows,
     return other error number in case of fatal error.
   */
-  virtual int next_row()= 0;
+  virtual int next_row() = 0;
 
   /* Finish scanning */
-  virtual int end_scan()=0;
+  virtual int end_scan() = 0;
   
   /* Report errors */
-  virtual void print_error(int error, myf errflag)=0;
+  virtual void print_error(int error, myf errflag) = 0;
 };
 
 #endif /* SELECT_HANDLER_INCLUDED */
diff --git a/sql/sql_explain.cc b/sql/sql_explain.cc
index 3f1dc80..b8d80c7 100644
--- a/sql/sql_explain.cc
+++ b/sql/sql_explain.cc
@@ -35,6 +35,7 @@ const char *unit_operation_text[4]=
 };
 
 const char *pushed_derived_text= "PUSHED DERIVED";
+const char *pushed_select_text= "PUSHED SELECT";
 
 static void write_item(Json_writer *writer, Item *item);
 static void append_item_to_str(String *out, Item *item);
@@ -751,7 +752,7 @@ int Explain_select::print_explain(Explain_query *query,
   THD *thd= output->thd;
   MEM_ROOT *mem_root= thd->mem_root;
 
-  if (select_type == pushed_derived_text)
+  if (select_type == pushed_derived_text || select_type == pushed_select_text)
   {
      print_explain_message_line(output, explain_flags, is_analyze,
                                 select_id /*select number*/,
@@ -882,7 +883,9 @@ void Explain_select::print_explain_json(Explain_query *query,
   
   bool started_cache= print_explain_json_cache(writer, is_analyze);
 
-  if (message || select_type == pushed_derived_text)
+  if (message ||
+      select_type == pushed_derived_text ||
+      select_type == pushed_select_text)
   {
     writer->add_member("query_block").start_object();
     writer->add_member("select_id").add_ll(select_id);
@@ -890,7 +893,10 @@ void Explain_select::print_explain_json(Explain_query *query,
 
     writer->add_member("table").start_object();
     writer->add_member("message").add_str(select_type == pushed_derived_text ?
-                                          "Pushed derived" : message);
+                                          "Pushed derived" :
+                                          select_type == pushed_select_text ?
+                                          "Pushed select" :
+                                          message);
     writer->end_object();
 
     print_explain_json_for_children(query, writer, is_analyze);
diff --git a/sql/sql_explain.h b/sql/sql_explain.h
index 549b085..587ee53 100644
--- a/sql/sql_explain.h
+++ b/sql/sql_explain.h
@@ -329,6 +329,7 @@ class Explain_aggr_window_funcs : public Explain_aggr_node
 
 extern const char *unit_operation_text[4];
 extern const char *pushed_derived_text;
+extern const char *pushed_select_text;
 
 /*
   Explain structure for a UNION.
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 4c33091..87f50d4 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -4651,7 +4651,10 @@ void st_select_lex::set_explain_type(bool on_the_fly)
 
   if (master_unit()->thd->lex->first_select_lex() == this)
   {
-     type= is_primary ? "PRIMARY" : "SIMPLE";
+    if (pushdown_select)
+      type= pushed_select_text;
+    else
+      type= is_primary ? "PRIMARY" : "SIMPLE";
   }
   else
   {
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 4ac5ea1..2753f1a 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1440,7 +1440,8 @@ int JOIN::optimize()
   join_optimization_state init_state= optimization_state;
   if (select_lex->pushdown_select)
   {
-    res= select_lex->pushdown_select->init();
+    if (!(select_options & SELECT_DESCRIBE))
+      res= select_lex->pushdown_select->init();
     with_two_phase_optimization= false;
   }
   else if (optimization_state == JOIN::OPTIMIZATION_PHASE_1_DONE)
@@ -3940,13 +3941,6 @@ void JOIN::exec_inner()
     if (select_options & SELECT_DESCRIBE)
       select_describe(this, FALSE, FALSE, FALSE,
 		      (zero_result_cause?zero_result_cause:"No tables used"));
-
-    else if (select_lex->pushdown_select)
-    {
-      error= select_lex->pushdown_select->execute();
-      delete select_lex->pushdown_select; 
-      DBUG_VOID_RETURN;
-    }
     else
     {
       if (result->send_result_set_metadata(*columns_list,
@@ -4071,12 +4065,18 @@ 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; 
+    delete select_lex->pushdown_select;
+    select_lex->pushdown_select= NULL;
     DBUG_VOID_RETURN;
   }
   else
@@ -4290,6 +4290,7 @@ mysql_select(THD *thd,
     }
   }
 
+#if 1
   select_lex->select_h= select_lex->find_select_handler(thd);
   if (select_lex->select_h)
   {
@@ -4298,6 +4299,7 @@ mysql_select(THD *thd,
                                           select_lex->select_h)))
       DBUG_RETURN(TRUE);
   }
+#endif
       
   if ((err= join->optimize()))
   {
@@ -25748,6 +25750,13 @@ bool mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result)
                       first->options | thd->variables.option_bits | SELECT_DESCRIBE,
                       result, unit, first);
   }
+
+  if (unit->derived && unit->derived->pushdown_derived)
+  {
+    delete unit->derived->pushdown_derived;
+    unit->derived->pushdown_derived= NULL;
+  }
+
   DBUG_RETURN(res || thd->is_error());
 }
 
diff --git a/sql/sql_select.h b/sql/sql_select.h
index e9cf51b..bca2387 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -2449,12 +2449,13 @@ class derived_handler;
 
 class Pushdown_derived: public Sql_alloc
 {
+private:
+  bool is_analyze;
 public:
   TABLE_LIST *derived;
   derived_handler *handler;
 
-  Pushdown_derived(TABLE_LIST *tbl, derived_handler *h)
-    : derived(tbl), handler(h) {}
+  Pushdown_derived(TABLE_LIST *tbl, derived_handler *h);
 
   ~Pushdown_derived();
 
@@ -2468,6 +2469,7 @@ class select_handler;
 class Pushdown_select: public Sql_alloc
 {
 private:
+  bool is_analyze;
   List<Item> result_columns;
   bool send_result_set_metadata();
   bool send_data();
@@ -2477,8 +2479,7 @@ class Pushdown_select: public Sql_alloc
   SELECT_LEX *select;
   select_handler *handler;
 
-  Pushdown_select(SELECT_LEX *sel, select_handler *h)
-    : select(sel), handler(h) {}
+  Pushdown_select(SELECT_LEX *sel, select_handler *h);
 
   ~Pushdown_select();
 
diff --git a/storage/federatedx/ha_federatedx.cc b/storage/federatedx/ha_federatedx.cc
index ec96a24..174ee23 100644
--- a/storage/federatedx/ha_federatedx.cc
+++ b/storage/federatedx/ha_federatedx.cc
@@ -3677,6 +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)
 {
@@ -3708,7 +3709,8 @@ create_federatedx_derived_handler(THD* thd, TABLE_LIST *derived)
 
 ha_federatedx_derived_handler::ha_federatedx_derived_handler(THD *thd,
                                                              TABLE_LIST *dt)
-  : derived_handler(thd, federatedx_hton)
+  : derived_handler(thd, federatedx_hton),
+    share(NULL), txn(NULL), iop(NULL), stored_result(NULL)
 {
   derived= dt;
 }
@@ -3725,24 +3727,21 @@ int ha_federatedx_derived_handler::init_scan()
 
   TABLE *table= derived->get_first_table()->table;
   ha_federatedx *h= (ha_federatedx *) table->file;
-  io= h->io;
+  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, &io)))
+  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 (stored_result)
-  //    (void) free_result();
-
-  if (io->query(derived_query.ptr(), derived_query.length()))
+  if ((*iop)->query(derived_query.ptr(), derived_query.length()))
     goto err;
 
-  stored_result= io->store_result();
+  stored_result= (*iop)->store_result();
   if (!stored_result)
       goto err;
 
@@ -3762,24 +3761,24 @@ int ha_federatedx_derived_handler::next_row()
   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, &io)))
+  if ((rc= txn->acquire(share, table->in_use, TRUE, iop)))
     DBUG_RETURN(rc);
 
-  if (!(row= io->fetch_row(stored_result)))
+  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= io->fetch_lengths(stored_result);
+  lengths= (*iop)->fetch_lengths(stored_result);
 
   for (field= table->field; *field; field++, column++)
   {
-    if (io->is_column_null(row, column))
+    if ((*iop)->is_column_null(row, column))
        (*field)->set_null();
     else
     {
       (*field)->set_notnull();
-      (*field)->store(io->get_column_data(row, column),
+      (*field)->store((*iop)->get_column_data(row, column),
                       lengths[column], &my_charset_bin);
     }
   }
@@ -3791,6 +3790,11 @@ int ha_federatedx_derived_handler::next_row()
 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);
 }
 
@@ -3822,7 +3826,8 @@ create_federatedx_select_handler(THD* thd, SELECT_LEX *sel)
 
 ha_federatedx_select_handler::ha_federatedx_select_handler(THD *thd,
                                                            SELECT_LEX *sel)
-  : select_handler(thd, federatedx_hton)
+  : select_handler(thd, federatedx_hton),
+    share(NULL), txn(NULL), iop(NULL), stored_result(NULL) 
 {
   select= sel;
 }
@@ -3844,16 +3849,16 @@ int ha_federatedx_select_handler::init_scan()
     break;
   }
   ha_federatedx *h= (ha_federatedx *) table->file;
-  io= h->io;
+  iop= &h->io;
   share= get_share(table->s->table_name.str, table);
   txn= h->get_txn(thd);
-  if ((rc= txn->acquire(share, thd, TRUE, &io)))
+  if ((rc= txn->acquire(share, thd, TRUE, iop)))
     DBUG_RETURN(rc);
 
-  if (io->query(thd->query(), thd->query_length()))
+  if ((*iop)->query(thd->query(), thd->query_length()))
     goto err;
 
-  stored_result= io->store_result();
+  stored_result= (*iop)->store_result();
   if (!stored_result)
       goto err;
 
@@ -3865,7 +3870,7 @@ int ha_federatedx_select_handler::init_scan()
 
 int ha_federatedx_select_handler::next_row()
 {
-  int rc;
+  int rc= 0;
   FEDERATEDX_IO_ROW *row;
   ulong *lengths;
   Field **field;
@@ -3873,24 +3878,24 @@ int ha_federatedx_select_handler::next_row()
   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, &io)))
+  if ((rc= txn->acquire(share, table->in_use, TRUE, iop)))
     DBUG_RETURN(rc);
 
-  if (!(row= io->fetch_row(stored_result)))
+  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= io->fetch_lengths(stored_result);
+  lengths= (*iop)->fetch_lengths(stored_result);
 
   for (field= table->field; *field; field++, column++)
   {
-    if (io->is_column_null(row, column))
+    if ((*iop)->is_column_null(row, column))
        (*field)->set_null();
     else
     {
       (*field)->set_notnull();
-      (*field)->store(io->get_column_data(row, column),
+      (*field)->store((*iop)->get_column_data(row, column),
                       lengths[column], &my_charset_bin);
     }
   }
@@ -3906,8 +3911,9 @@ int ha_federatedx_select_handler::end_scan()
   free_tmp_table(thd, table);
   table= 0;
 
-  txn->release(&io);
-  DBUG_ASSERT(io == NULL);
+  (*iop)->free_result(stored_result);
+
+  free_share(txn, share);
 
   DBUG_RETURN(0);
 }
diff --git a/storage/federatedx/ha_federatedx.h b/storage/federatedx/ha_federatedx.h
index 4c721e5..3a5180f 100644
--- a/storage/federatedx/ha_federatedx.h
+++ b/storage/federatedx/ha_federatedx.h
@@ -468,12 +468,13 @@ 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 *io;
+  federatedx_io **iop;
   FEDERATEDX_IO_RESULT *stored_result;
 
 public:
@@ -491,7 +492,7 @@ class ha_federatedx_select_handler: public select_handler
 private:
   FEDERATEDX_SHARE *share;
   federatedx_txn *txn;
-  federatedx_io *io;
+  federatedx_io **iop;
   FEDERATEDX_IO_RESULT *stored_result;
 
 public:


More information about the commits mailing list