MDEV-21887: federatedx crashes on SELECT ... INTO query in select_handler code
Backport to 10.4: - Don't try to push down SELECTs that have a side effect - In case the storage engine did support pushdown of SELECT with an INTO clause, write the rows we've got from it into select->join->result, and not thd->protocol. This way, SELECT ... INTO ... FROM smart_engine_table will put the result into where instructed, and NOT send it to the client.
This commit is contained in:
parent
1c8de231a3
commit
af4b2ae858
@ -299,7 +299,27 @@ id select_type table type possible_keys key key_len ref rows Extra
|
|||||||
1 PRIMARY t3 ALL NULL NULL NULL NULL 7
|
1 PRIMARY t3 ALL NULL NULL NULL NULL 7
|
||||||
1 PRIMARY <derived2> ref key0 key0 18 federated.t3.name 2
|
1 PRIMARY <derived2> ref key0 key0 18 federated.t3.name 2
|
||||||
2 PUSHED DERIVED NULL NULL NULL NULL NULL NULL NULL NULL
|
2 PUSHED DERIVED NULL NULL NULL NULL NULL NULL NULL NULL
|
||||||
DROP TABLE federated.t1, federated.t2, federated.t3;
|
#
|
||||||
|
# MDEV-21887: federatedx crashes on SELECT ... INTO query in select_handler code
|
||||||
|
#
|
||||||
|
CREATE TABLE federated.t4 (
|
||||||
|
id int(20) NOT NULL,
|
||||||
|
name varchar(16) NOT NULL default ''
|
||||||
|
) engine=myisam;
|
||||||
|
insert into federated.t4 select * from federated.t1;
|
||||||
|
select * from federated.t4;
|
||||||
|
id name
|
||||||
|
1 zzz
|
||||||
|
3 xxx
|
||||||
|
4 xxx
|
||||||
|
5 yyy
|
||||||
|
7 yyy
|
||||||
|
select name into @var from federated.t1 where id=3 limit 1 ;
|
||||||
|
select @var;
|
||||||
|
@var
|
||||||
|
xxx
|
||||||
|
select name into outfile 'tmp.txt' from federated.t1;
|
||||||
|
DROP TABLE federated.t1, federated.t2, federated.t3, federated.t4;
|
||||||
connection slave;
|
connection slave;
|
||||||
DROP TABLE federated.t1, federated.t2;
|
DROP TABLE federated.t1, federated.t2;
|
||||||
connection default;
|
connection default;
|
||||||
|
@ -147,8 +147,27 @@ FROM federated.t3,
|
|||||||
SELECT * FROM federated.t1 WHERE id >= 5) t
|
SELECT * FROM federated.t1 WHERE id >= 5) t
|
||||||
WHERE federated.t3.name=t.name;
|
WHERE federated.t3.name=t.name;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-21887: federatedx crashes on SELECT ... INTO query in select_handler code
|
||||||
|
--echo #
|
||||||
|
|
||||||
DROP TABLE federated.t1, federated.t2, federated.t3;
|
CREATE TABLE federated.t4 (
|
||||||
|
id int(20) NOT NULL,
|
||||||
|
name varchar(16) NOT NULL default ''
|
||||||
|
) engine=myisam;
|
||||||
|
insert into federated.t4 select * from federated.t1;
|
||||||
|
|
||||||
|
--sorted_result
|
||||||
|
select * from federated.t4;
|
||||||
|
|
||||||
|
select name into @var from federated.t1 where id=3 limit 1 ;
|
||||||
|
select @var;
|
||||||
|
select name into outfile 'tmp.txt' from federated.t1;
|
||||||
|
|
||||||
|
let $path=`select concat(@@datadir, 'test/tmp.txt')`;
|
||||||
|
remove_file $path;
|
||||||
|
|
||||||
|
DROP TABLE federated.t1, federated.t2, federated.t3, federated.t4;
|
||||||
|
|
||||||
connection slave;
|
connection slave;
|
||||||
DROP TABLE federated.t1, federated.t2;
|
DROP TABLE federated.t1, federated.t2;
|
||||||
|
@ -77,18 +77,17 @@ bool Pushdown_select::init()
|
|||||||
|
|
||||||
bool Pushdown_select::send_result_set_metadata()
|
bool Pushdown_select::send_result_set_metadata()
|
||||||
{
|
{
|
||||||
THD *thd= handler->thd;
|
|
||||||
Protocol *protocol= thd->protocol;
|
|
||||||
DBUG_ENTER("Pushdown_select::send_result_set_metadata");
|
DBUG_ENTER("Pushdown_select::send_result_set_metadata");
|
||||||
|
|
||||||
#ifdef WITH_WSREP
|
#ifdef WITH_WSREP
|
||||||
|
THD *thd= handler->thd;
|
||||||
if (WSREP(thd) && thd->wsrep_retry_query)
|
if (WSREP(thd) && thd->wsrep_retry_query)
|
||||||
{
|
{
|
||||||
WSREP_DEBUG("skipping select metadata");
|
WSREP_DEBUG("skipping select metadata");
|
||||||
DBUG_RETURN(false);
|
DBUG_RETURN(false);
|
||||||
}
|
}
|
||||||
#endif /* WITH_WSREP */
|
#endif /* WITH_WSREP */
|
||||||
if (protocol->send_result_set_metadata(&result_columns,
|
if (select->join->result->send_result_set_metadata(result_columns,
|
||||||
Protocol::SEND_NUM_ROWS |
|
Protocol::SEND_NUM_ROWS |
|
||||||
Protocol::SEND_EOF))
|
Protocol::SEND_EOF))
|
||||||
DBUG_RETURN(true);
|
DBUG_RETURN(true);
|
||||||
@ -100,23 +99,13 @@ bool Pushdown_select::send_result_set_metadata()
|
|||||||
bool Pushdown_select::send_data()
|
bool Pushdown_select::send_data()
|
||||||
{
|
{
|
||||||
THD *thd= handler->thd;
|
THD *thd= handler->thd;
|
||||||
Protocol *protocol= thd->protocol;
|
|
||||||
DBUG_ENTER("Pushdown_select::send_data");
|
DBUG_ENTER("Pushdown_select::send_data");
|
||||||
|
|
||||||
if (thd->killed == ABORT_QUERY)
|
if (thd->killed == ABORT_QUERY)
|
||||||
DBUG_RETURN(false);
|
DBUG_RETURN(false);
|
||||||
|
|
||||||
protocol->prepare_for_resend();
|
if (select->join->result->send_data(result_columns))
|
||||||
if (protocol->send_result_set_row(&result_columns))
|
|
||||||
{
|
|
||||||
protocol->remove_last_row();
|
|
||||||
DBUG_RETURN(true);
|
DBUG_RETURN(true);
|
||||||
}
|
|
||||||
|
|
||||||
thd->inc_sent_row_count(1);
|
|
||||||
|
|
||||||
if (thd->vio_ok())
|
|
||||||
DBUG_RETURN(protocol->write());
|
|
||||||
|
|
||||||
DBUG_RETURN(false);
|
DBUG_RETURN(false);
|
||||||
}
|
}
|
||||||
@ -124,16 +113,10 @@ bool Pushdown_select::send_data()
|
|||||||
|
|
||||||
bool Pushdown_select::send_eof()
|
bool Pushdown_select::send_eof()
|
||||||
{
|
{
|
||||||
THD *thd= handler->thd;
|
|
||||||
DBUG_ENTER("Pushdown_select::send_eof");
|
DBUG_ENTER("Pushdown_select::send_eof");
|
||||||
|
|
||||||
/*
|
if (select->join->result->send_eof())
|
||||||
Don't send EOF if we're in error condition (which implies we've already
|
|
||||||
sent or are sending an error)
|
|
||||||
*/
|
|
||||||
if (thd->is_error())
|
|
||||||
DBUG_RETURN(true);
|
DBUG_RETURN(true);
|
||||||
::my_eof(thd);
|
|
||||||
DBUG_RETURN(false);
|
DBUG_RETURN(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,6 +182,16 @@ create_federatedx_select_handler(THD* thd, SELECT_LEX *sel)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Currently, ha_federatedx_select_handler::init_scan just takes the
|
||||||
|
thd->query and sends it to the backend.
|
||||||
|
This obviously won't work if the SELECT uses an "INTO @var" or
|
||||||
|
"INTO OUTFILE". It is also unlikely to work if the select has some
|
||||||
|
other kind of side effect.
|
||||||
|
*/
|
||||||
|
if (sel->uncacheable & UNCACHEABLE_SIDEEFFECT)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
handler= new ha_federatedx_select_handler(thd, sel);
|
handler= new ha_federatedx_select_handler(thd, sel);
|
||||||
|
|
||||||
return handler;
|
return handler;
|
||||||
@ -286,8 +296,9 @@ int ha_federatedx_select_handler::end_scan()
|
|||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ha_federatedx_select_handler::print_error(int, unsigned long)
|
void ha_federatedx_select_handler::print_error(int error, myf error_flag)
|
||||||
{
|
{
|
||||||
|
select_handler::print_error(error, error_flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user