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: