mirror of
https://github.com/MariaDB/server.git
synced 2026-10-23 18:49:29 +03:00
MDEV-37484: Sql_cmd_dml::execute_inner, Sql_cmd_update::execute_inner do not call Select handler for the engine involved
Problem: After the re-design of `UPDATE` and `DELETE` in MDEV-28883, the call to find select handler is missing. This prevents the server from handring over multi-update/multi-delete queries to storage engines capable of executng such queries on their own (e.g., ColumnStore). MDEV-32382 introduced a check in `find_select_handler_inner` function, that blocked pushdown of queries involving CTEs, without checking if the storage engine is capable of handling such queries. Fix: Add a call to find the select handler for the engine involved in the multi-update/multi-delete query, allowing the storage engines to execute such queries. Fix the `find_select_handler_inner` function by allowing the storage engine's create_select functions to decide the pushdown of queries involving CTEs.
This commit is contained in:
committed by
Raghunandan Bhat
parent
a61a746f08
commit
dcf59cc248
@@ -1350,6 +1350,229 @@ federated.t12, federated.t13, federated.t14;
|
||||
connection slave;
|
||||
DROP TABLES federated.t1, federated.t2, federated.t11, federated.t12,
|
||||
federated.t13, federated.t14;
|
||||
#
|
||||
# MDEV-37484: `Sql_cmd_dml::execute_inner`, `Sql_cmd_update::execute_inner` do not call Select handler for the engine involved
|
||||
#
|
||||
connection default;
|
||||
set global federated_pushdown=1;
|
||||
connection slave;
|
||||
create table federated.product_tag (product_id bigint);
|
||||
CREATE TABLE federated.product (
|
||||
`product_id` bigint(20) DEFAULT NULL,
|
||||
`price` bigint(20) DEFAULT NULL,
|
||||
`short_description` varchar(7998) DEFAULT NULL,
|
||||
`brand` varchar(254) DEFAULT NULL,
|
||||
`modified_dtm` datetime DEFAULT NULL,
|
||||
`created_dtm` datetime DEFAULT NULL,
|
||||
`modified_by` int(11) DEFAULT NULL
|
||||
) CHARSET=latin1;
|
||||
connection master;
|
||||
create table federated.product_tag (product_id bigint)
|
||||
ENGINE="FEDERATED"
|
||||
CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/product_tag';
|
||||
CREATE TABLE federated.product (
|
||||
`product_id` bigint(20) DEFAULT NULL,
|
||||
`price` bigint(20) DEFAULT NULL,
|
||||
`short_description` varchar(7998) DEFAULT NULL,
|
||||
`brand` varchar(254) DEFAULT NULL,
|
||||
`modified_dtm` datetime DEFAULT NULL,
|
||||
`created_dtm` datetime DEFAULT NULL,
|
||||
`modified_by` int(11) DEFAULT NULL
|
||||
)
|
||||
ENGINE="FEDERATED" DEFAULT CHARSET=latin1
|
||||
CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/product';
|
||||
insert into federated.product_tag values (1),(2),(3),(4);
|
||||
insert into federated.product values (1,22,'fes','rets','2011-12-12 12:12:12','2011-12-13 1:1:10',343);
|
||||
insert into federated.product values (3,22,'fes','rets','2011-12-12 12:12:12','2011-12-13 1:1:10',343);
|
||||
select * from federated.product order by product_id;
|
||||
product_id price short_description brand modified_dtm created_dtm modified_by
|
||||
1 22 fes rets 2011-12-12 12:12:12 2011-12-13 01:01:10 343
|
||||
3 22 fes rets 2011-12-12 12:12:12 2011-12-13 01:01:10 343
|
||||
explain format=json update
|
||||
federated.product p join
|
||||
(select product_id from federated.product_tag limit 1000) t using (product_id)
|
||||
set brand=p.product_id, price=555, modified_dtm='2011-12-15 15:15:30',
|
||||
short_description=concat(short_description,modified_by);
|
||||
EXPLAIN
|
||||
{
|
||||
"query_block": {
|
||||
"select_id": 1,
|
||||
"cost": 1000.010933,
|
||||
"nested_loop": [
|
||||
{
|
||||
"table": {
|
||||
"table_name": "p",
|
||||
"access_type": "ALL",
|
||||
"loops": 1,
|
||||
"rows": 2,
|
||||
"cost": 1000.010388,
|
||||
"filtered": 100,
|
||||
"attached_condition": "p.product_id is not null"
|
||||
}
|
||||
},
|
||||
{
|
||||
"table": {
|
||||
"table_name": "<derived2>",
|
||||
"access_type": "ref",
|
||||
"possible_keys": ["key0"],
|
||||
"key": "key0",
|
||||
"key_length": "9",
|
||||
"used_key_parts": ["product_id"],
|
||||
"ref": ["federated.p.product_id"],
|
||||
"loops": 2,
|
||||
"rows": 1,
|
||||
"cost": 0.000545388,
|
||||
"filtered": 100,
|
||||
"materialized": {
|
||||
"query_block": {
|
||||
"select_id": 2,
|
||||
"table": {
|
||||
"message": "Pushed derived"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
update
|
||||
federated.product p join
|
||||
(select product_id from federated.product_tag limit 1000) t using (product_id)
|
||||
set brand=p.product_id, price=555, modified_dtm='2011-12-15 15:15:30',
|
||||
short_description=concat(short_description,modified_by);
|
||||
select * from federated.product order by product_id;
|
||||
product_id price short_description brand modified_dtm created_dtm modified_by
|
||||
1 555 fes343 1 2011-12-15 15:15:30 2011-12-13 01:01:10 343
|
||||
3 555 fes343 3 2011-12-15 15:15:30 2011-12-13 01:01:10 343
|
||||
drop table federated.product_tag;
|
||||
drop table federated.product;
|
||||
connection slave;
|
||||
drop table federated.product_tag;
|
||||
drop table federated.product;
|
||||
# Setup
|
||||
create or replace table federated.t1 (id int);
|
||||
create or replace table federated.t2 (id int, op varchar(10), op_count int DEFAULT 0) CHARSET=latin1;
|
||||
connection master;
|
||||
create or replace table federated.t1 (id int)
|
||||
ENGINE="FEDERATED"
|
||||
CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1';
|
||||
create or replace table federated.t2 (id int, op varchar(10), op_count int DEFAULT 0)
|
||||
ENGINE="FEDERATED" DEFAULT CHARSET=latin1
|
||||
CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t2';
|
||||
insert into federated.t1 values (1),(2),(3),(4);
|
||||
insert into federated.t2 (id, op) values (1, 'inserted'), (2, 'inserted'), (3, 'inserted'), (4, 'inserted');
|
||||
select * from federated.t2 order by id;
|
||||
id op op_count
|
||||
1 inserted 0
|
||||
2 inserted 0
|
||||
3 inserted 0
|
||||
4 inserted 0
|
||||
# Update tests
|
||||
explain format=json update federated.t2 inner join federated.t1 on t2.id = t1.id
|
||||
set t2.op = 'updated', t2.op_count = t2.op_count + 1
|
||||
where t2.id in (1, 2);
|
||||
EXPLAIN
|
||||
{
|
||||
"query_block": {
|
||||
"select_id": 1,
|
||||
"cost": 2000.022975,
|
||||
"nested_loop": [
|
||||
{
|
||||
"table": {
|
||||
"table_name": "t2",
|
||||
"access_type": "ALL",
|
||||
"loops": 1,
|
||||
"rows": 4,
|
||||
"cost": 1000.010655,
|
||||
"filtered": 100,
|
||||
"attached_condition": "t2.`id` in (1,2)"
|
||||
}
|
||||
},
|
||||
{
|
||||
"table": {
|
||||
"table_name": "t1",
|
||||
"access_type": "ALL",
|
||||
"loops": 4,
|
||||
"rows": 4,
|
||||
"cost": 1000.012319,
|
||||
"filtered": 100,
|
||||
"attached_condition": "t1.`id` = t2.`id`"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
update federated.t2 inner join federated.t1 on t2.id = t1.id
|
||||
set t2.op = 'updated', t2.op_count = t2.op_count + 1
|
||||
where t2.id in (1, 2);
|
||||
select * from federated.t2 order by id;
|
||||
id op op_count
|
||||
1 updated 1
|
||||
2 updated 1
|
||||
3 inserted 0
|
||||
4 inserted 0
|
||||
# Prepared update stmt
|
||||
PREPARE stmt_update FROM
|
||||
'update federated.t2 inner join federated.t1 on t2.id = t1.id set t2.op_count = t2.op_count + 1, t2.op="updated" where t2.id in (1, 2)';
|
||||
EXECUTE stmt_update;
|
||||
DEALLOCATE PREPARE stmt_update;
|
||||
select * from federated.t2 order by id;
|
||||
id op op_count
|
||||
1 updated 2
|
||||
2 updated 2
|
||||
3 inserted 0
|
||||
4 inserted 0
|
||||
# Delete tests
|
||||
explain format=json
|
||||
delete federated.t2 from federated.t2 inner join federated.t1 on t2.id = t1.id and t2.op = 'updated';
|
||||
EXPLAIN
|
||||
{
|
||||
"query_block": {
|
||||
"select_id": 1,
|
||||
"cost": 2000.023025,
|
||||
"nested_loop": [
|
||||
{
|
||||
"table": {
|
||||
"table_name": "t2",
|
||||
"access_type": "ALL",
|
||||
"loops": 1,
|
||||
"rows": 4,
|
||||
"cost": 1000.010705,
|
||||
"filtered": 100,
|
||||
"attached_condition": "t2.op = 'updated'"
|
||||
}
|
||||
},
|
||||
{
|
||||
"table": {
|
||||
"table_name": "t1",
|
||||
"access_type": "ALL",
|
||||
"loops": 4,
|
||||
"rows": 4,
|
||||
"cost": 1000.012319,
|
||||
"filtered": 100,
|
||||
"attached_condition": "t1.`id` = t2.`id`"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
delete federated.t2 from federated.t2 inner join federated.t1 on t2.id = t1.id and t2.op = 'updated';
|
||||
select * from federated.t2 order by id;
|
||||
id op op_count
|
||||
3 inserted 0
|
||||
4 inserted 0
|
||||
# Prepared delete stmt
|
||||
PREPARE stmt_delete FROM
|
||||
'delete federated.t2 from federated.t2 inner join federated.t1 on t2.id = t1.id where t2.id = 3';
|
||||
EXECUTE stmt_delete;
|
||||
DEALLOCATE PREPARE stmt_delete;
|
||||
select * from federated.t2 order by id;
|
||||
id op op_count
|
||||
4 inserted 0
|
||||
drop table federated.t1, federated.t2;
|
||||
connection slave;
|
||||
drop table federated.t1, federated.t2;
|
||||
connection default;
|
||||
set global federated_pushdown=0;
|
||||
connection master;
|
||||
@@ -1358,3 +1581,4 @@ DROP DATABASE IF EXISTS federated;
|
||||
connection slave;
|
||||
DROP TABLE IF EXISTS federated.t1;
|
||||
DROP DATABASE IF EXISTS federated;
|
||||
# End of 11.4 tests
|
||||
|
||||
@@ -895,9 +895,133 @@ connection slave;
|
||||
DROP TABLES federated.t1, federated.t2, federated.t11, federated.t12,
|
||||
federated.t13, federated.t14;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-37484: `Sql_cmd_dml::execute_inner`, `Sql_cmd_update::execute_inner` do not call Select handler for the engine involved
|
||||
--echo #
|
||||
|
||||
connection default;
|
||||
set global federated_pushdown=1;
|
||||
|
||||
connection slave;
|
||||
create table federated.product_tag (product_id bigint);
|
||||
CREATE TABLE federated.product (
|
||||
`product_id` bigint(20) DEFAULT NULL,
|
||||
`price` bigint(20) DEFAULT NULL,
|
||||
`short_description` varchar(7998) DEFAULT NULL,
|
||||
`brand` varchar(254) DEFAULT NULL,
|
||||
`modified_dtm` datetime DEFAULT NULL,
|
||||
`created_dtm` datetime DEFAULT NULL,
|
||||
`modified_by` int(11) DEFAULT NULL
|
||||
) CHARSET=latin1;
|
||||
|
||||
connection master;
|
||||
--replace_result $SLAVE_MYPORT SLAVE_PORT
|
||||
eval
|
||||
create table federated.product_tag (product_id bigint)
|
||||
ENGINE="FEDERATED"
|
||||
CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/product_tag';
|
||||
|
||||
--replace_result $SLAVE_MYPORT SLAVE_PORT
|
||||
eval
|
||||
CREATE TABLE federated.product (
|
||||
`product_id` bigint(20) DEFAULT NULL,
|
||||
`price` bigint(20) DEFAULT NULL,
|
||||
`short_description` varchar(7998) DEFAULT NULL,
|
||||
`brand` varchar(254) DEFAULT NULL,
|
||||
`modified_dtm` datetime DEFAULT NULL,
|
||||
`created_dtm` datetime DEFAULT NULL,
|
||||
`modified_by` int(11) DEFAULT NULL
|
||||
)
|
||||
ENGINE="FEDERATED" DEFAULT CHARSET=latin1
|
||||
CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/product';
|
||||
|
||||
insert into federated.product_tag values (1),(2),(3),(4);
|
||||
insert into federated.product values (1,22,'fes','rets','2011-12-12 12:12:12','2011-12-13 1:1:10',343);
|
||||
insert into federated.product values (3,22,'fes','rets','2011-12-12 12:12:12','2011-12-13 1:1:10',343);
|
||||
select * from federated.product order by product_id;
|
||||
|
||||
let $query=
|
||||
update
|
||||
federated.product p join
|
||||
(select product_id from federated.product_tag limit 1000) t using (product_id)
|
||||
set brand=p.product_id, price=555, modified_dtm='2011-12-15 15:15:30',
|
||||
short_description=concat(short_description,modified_by);
|
||||
|
||||
eval explain format=json $query;
|
||||
eval $query;
|
||||
|
||||
select * from federated.product order by product_id;
|
||||
|
||||
drop table federated.product_tag;
|
||||
drop table federated.product;
|
||||
|
||||
connection slave;
|
||||
drop table federated.product_tag;
|
||||
drop table federated.product;
|
||||
|
||||
--echo # Setup
|
||||
create or replace table federated.t1 (id int);
|
||||
create or replace table federated.t2 (id int, op varchar(10), op_count int DEFAULT 0) CHARSET=latin1;
|
||||
|
||||
connection master;
|
||||
--replace_result $SLAVE_MYPORT SLAVE_PORT
|
||||
eval
|
||||
create or replace table federated.t1 (id int)
|
||||
ENGINE="FEDERATED"
|
||||
CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1';
|
||||
|
||||
--replace_result $SLAVE_MYPORT SLAVE_PORT
|
||||
eval
|
||||
create or replace table federated.t2 (id int, op varchar(10), op_count int DEFAULT 0)
|
||||
ENGINE="FEDERATED" DEFAULT CHARSET=latin1
|
||||
CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t2';
|
||||
|
||||
insert into federated.t1 values (1),(2),(3),(4);
|
||||
insert into federated.t2 (id, op) values (1, 'inserted'), (2, 'inserted'), (3, 'inserted'), (4, 'inserted');
|
||||
select * from federated.t2 order by id;
|
||||
|
||||
--echo # Update tests
|
||||
let $query=
|
||||
update federated.t2 inner join federated.t1 on t2.id = t1.id
|
||||
set t2.op = 'updated', t2.op_count = t2.op_count + 1
|
||||
where t2.id in (1, 2);
|
||||
|
||||
eval explain format=json $query;
|
||||
eval $query;
|
||||
|
||||
select * from federated.t2 order by id;
|
||||
|
||||
--echo # Prepared update stmt
|
||||
PREPARE stmt_update FROM
|
||||
'update federated.t2 inner join federated.t1 on t2.id = t1.id set t2.op_count = t2.op_count + 1, t2.op="updated" where t2.id in (1, 2)';
|
||||
EXECUTE stmt_update;
|
||||
DEALLOCATE PREPARE stmt_update;
|
||||
|
||||
select * from federated.t2 order by id;
|
||||
|
||||
--echo # Delete tests
|
||||
explain format=json
|
||||
delete federated.t2 from federated.t2 inner join federated.t1 on t2.id = t1.id and t2.op = 'updated';
|
||||
|
||||
delete federated.t2 from federated.t2 inner join federated.t1 on t2.id = t1.id and t2.op = 'updated';
|
||||
select * from federated.t2 order by id;
|
||||
|
||||
--echo # Prepared delete stmt
|
||||
PREPARE stmt_delete FROM
|
||||
'delete federated.t2 from federated.t2 inner join federated.t1 on t2.id = t1.id where t2.id = 3';
|
||||
EXECUTE stmt_delete;
|
||||
DEALLOCATE PREPARE stmt_delete;
|
||||
|
||||
select * from federated.t2 order by id;
|
||||
|
||||
drop table federated.t1, federated.t2;
|
||||
|
||||
connection slave;
|
||||
drop table federated.t1, federated.t2;
|
||||
|
||||
# cleanup
|
||||
connection default;
|
||||
set global federated_pushdown=0;
|
||||
|
||||
source include/federated_cleanup.inc;
|
||||
|
||||
--echo # End of 11.4 tests
|
||||
|
||||
@@ -1622,6 +1622,13 @@ bool Sql_cmd_delete::precheck(THD *thd)
|
||||
{
|
||||
if (multi_delete_precheck(thd, lex->query_tables))
|
||||
return true;
|
||||
|
||||
SELECT_LEX *select_lex= lex->first_select_lex();
|
||||
/* condition will be TRUE on SP re-excuting */
|
||||
if (select_lex->item_list.elements != 0)
|
||||
select_lex->item_list.empty();
|
||||
if (add_item_to_list(thd, new (thd->mem_root) Item_null(thd)))
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef WITH_WSREP
|
||||
|
||||
@@ -5218,15 +5218,9 @@ select_handler *find_select_handler_inner(THD *thd,
|
||||
SELECT_LEX *select_lex,
|
||||
SELECT_LEX_UNIT *select_lex_unit)
|
||||
{
|
||||
if (select_lex->master_unit()->outer_select() ||
|
||||
(select_lex_unit && select_lex->master_unit()->with_clause))
|
||||
{
|
||||
/*
|
||||
Pushdown is not supported neither for non-top-level SELECTs nor for parts
|
||||
of SELECT_LEX_UNITs that have CTEs (SELECT_LEX_UNIT::with_clause)
|
||||
*/
|
||||
// Pushdown is not supported for non-top-level SELECTs
|
||||
if (select_lex->master_unit()->outer_select())
|
||||
return 0;
|
||||
}
|
||||
|
||||
TABLE_LIST *tbl= nullptr;
|
||||
// For SQLCOM_INSERT_SELECT the server takes TABLE_LIST
|
||||
@@ -34603,6 +34597,9 @@ bool Sql_cmd_dml::execute_inner(THD *thd)
|
||||
SELECT_LEX *select_lex= unit->first_select();
|
||||
JOIN *join= select_lex->join;
|
||||
|
||||
// look for select_handler provided by engines
|
||||
select_lex->pushdown_select= find_single_select_handler(thd, select_lex);
|
||||
|
||||
if (join->optimize())
|
||||
goto err;
|
||||
|
||||
|
||||
@@ -239,6 +239,9 @@ create_federatedx_select_handler(THD *thd, SELECT_LEX *sel_lex,
|
||||
if (!use_pushdown || !is_supported_by_select_handler(thd->lex->sql_command))
|
||||
return nullptr;
|
||||
|
||||
if (lex_unit && sel_lex->master_unit()->with_clause)
|
||||
return nullptr;
|
||||
|
||||
auto tbl= get_fed_table_for_pushdown(sel_lex);
|
||||
if (!tbl)
|
||||
return nullptr;
|
||||
|
||||
118
storage/spider/mysql-test/spider/bugfix/r/mdev_37484.result
Normal file
118
storage/spider/mysql-test/spider/bugfix/r/mdev_37484.result
Normal file
@@ -0,0 +1,118 @@
|
||||
#
|
||||
# MDEV-37484: `Sql_cmd_dml::execute_inner`, `Sql_cmd_update::execute_inner` do not call Select handler for the engine involved
|
||||
#
|
||||
for master_1
|
||||
for child2
|
||||
for child3
|
||||
set spider_same_server_link=1;
|
||||
CREATE SERVER s FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test', user 'root');
|
||||
create table product_tag(product_id bigint);
|
||||
create table product (
|
||||
`product_id` bigint(20) DEFAULT NULL,
|
||||
`price` bigint(20) DEFAULT NULL,
|
||||
`short_description` varchar(7998) DEFAULT NULL,
|
||||
`brand` varchar(254) DEFAULT NULL,
|
||||
`modified_dtm` datetime DEFAULT NULL,
|
||||
`created_dtm` datetime DEFAULT NULL,
|
||||
`modified_by` int(11) DEFAULT NULL
|
||||
);
|
||||
insert into product_tag values (1),(2),(3),(4);
|
||||
insert into product values (1,22,'fes','rets','2011-12-12 12:12:12','2011-12-13 1:1:10',343);
|
||||
insert into product values (3,22,'fes','rets','2011-12-12 12:12:12','2011-12-13 1:1:10',343);
|
||||
create table product_tag_spider (product_id bigint) ENGINE=SPIDER REMOTE_SERVER=s REMOTE_TABLE=product_tag;
|
||||
create table product_spider (
|
||||
`product_id` bigint(20) DEFAULT NULL,
|
||||
`price` bigint(20) DEFAULT NULL,
|
||||
`short_description` varchar(7998) DEFAULT NULL,
|
||||
`brand` varchar(254) DEFAULT NULL,
|
||||
`modified_dtm` datetime DEFAULT NULL,
|
||||
`created_dtm` datetime DEFAULT NULL,
|
||||
`modified_by` int(11) DEFAULT NULL
|
||||
) ENGINE=SPIDER REMOTE_SERVER=s REMOTE_TABLE=product;
|
||||
select * from product_spider order by product_id;
|
||||
product_id price short_description brand modified_dtm created_dtm modified_by
|
||||
1 22 fes rets 2011-12-12 12:12:12 2011-12-13 01:01:10 343
|
||||
3 22 fes rets 2011-12-12 12:12:12 2011-12-13 01:01:10 343
|
||||
explain update
|
||||
product_spider p join
|
||||
(select product_id from product_tag_spider limit 1000) t using (product_id)
|
||||
set brand=p.product_id, price=555, modified_dtm='2011-12-15 15:15:30',
|
||||
short_description=concat(short_description,modified_by);
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 PRIMARY p ALL NULL NULL NULL NULL 2 Using where with pushed condition
|
||||
1 PRIMARY <derived2> ref key0 key0 9 test.p.product_id 1
|
||||
2 DERIVED product_tag_spider ALL NULL NULL NULL NULL 4
|
||||
update
|
||||
product_spider p join
|
||||
(select product_id from product_tag_spider limit 1000) t using (product_id)
|
||||
set brand=p.product_id, price=555, modified_dtm='2011-12-15 15:15:30',
|
||||
short_description=concat(short_description,modified_by);
|
||||
select * from product_spider order by product_id;
|
||||
product_id price short_description brand modified_dtm created_dtm modified_by
|
||||
1 555 fes343 1 2011-12-15 15:15:30 2011-12-13 01:01:10 343
|
||||
3 555 fes343 3 2011-12-15 15:15:30 2011-12-13 01:01:10 343
|
||||
drop table product, product_tag, product_spider, product_tag_spider;
|
||||
create table t1 (id int);
|
||||
create table t2 (id int, op varchar(10), op_count int DEFAULT 0);
|
||||
insert into t1 values (1),(2),(3),(4);
|
||||
insert into t2 (id, op) values (1, 'inserted'), (2, 'inserted'), (3, 'inserted'), (4, 'inserted');
|
||||
CREATE TABLE t1_SPIDER (id int) ENGINE=SPIDER REMOTE_SERVER=s REMOTE_TABLE=t1;
|
||||
CREATE TABLE t2_SPIDER (id int, op varchar(10), op_count int DEFAULT 0) ENGINE=SPIDER REMOTE_SERVER=s REMOTE_TABLE=t2;
|
||||
select * from t2_SPIDER order by id;
|
||||
id op op_count
|
||||
1 inserted 0
|
||||
2 inserted 0
|
||||
3 inserted 0
|
||||
4 inserted 0
|
||||
# Update tests
|
||||
explain update t2_SPIDER inner join t1_SPIDER on t2_SPIDER.id = t1_SPIDER.id
|
||||
set t2_SPIDER.op = 'updated', t2_SPIDER.op_count = t2_SPIDER.op_count + 1
|
||||
where t2_SPIDER.id in (1, 2);
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t2_SPIDER ALL NULL NULL NULL NULL 4 Using where with pushed condition
|
||||
1 SIMPLE t1_SPIDER ALL NULL NULL NULL NULL 4 Using where
|
||||
update t2_SPIDER inner join t1_SPIDER on t2_SPIDER.id = t1_SPIDER.id
|
||||
set t2_SPIDER.op = 'updated', t2_SPIDER.op_count = t2_SPIDER.op_count + 1
|
||||
where t2_SPIDER.id in (1, 2);
|
||||
select * from t2_SPIDER order by id;
|
||||
id op op_count
|
||||
1 updated 1
|
||||
2 updated 1
|
||||
3 inserted 0
|
||||
4 inserted 0
|
||||
PREPARE stmt_update FROM
|
||||
'update t2_SPIDER inner join t1_SPIDER on t2_SPIDER.id = t1_SPIDER.id set t2_SPIDER.op_count = t2_SPIDER.op_count + 1, t2_SPIDER.op="updated" where t2_SPIDER.id in (1, 2)';
|
||||
EXECUTE stmt_update;
|
||||
DEALLOCATE PREPARE stmt_update;
|
||||
select * from t2_SPIDER order by id;
|
||||
id op op_count
|
||||
1 updated 2
|
||||
2 updated 2
|
||||
3 inserted 0
|
||||
4 inserted 0
|
||||
# Delete tests
|
||||
explain
|
||||
delete t2_SPIDER from t2_SPIDER inner join t1_SPIDER on t2_SPIDER.id = t1_SPIDER.id and t2_SPIDER.op = 'updated';
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t2_SPIDER ALL NULL NULL NULL NULL 4 Using where with pushed condition
|
||||
1 SIMPLE t1_SPIDER ALL NULL NULL NULL NULL 4 Using where
|
||||
delete t2_SPIDER from t2_SPIDER inner join t1_SPIDER on t2_SPIDER.id = t1_SPIDER.id and t2_SPIDER.op = 'updated';
|
||||
select * from t2_SPIDER order by id;
|
||||
id op op_count
|
||||
3 inserted 0
|
||||
4 inserted 0
|
||||
PREPARE stmt_delete FROM
|
||||
'delete t2_SPIDER from t2_SPIDER inner join t1_SPIDER on t2_SPIDER.id = t1_SPIDER.id where t2_SPIDER.id = 3';
|
||||
EXECUTE stmt_delete;
|
||||
DEALLOCATE PREPARE stmt_delete;
|
||||
select * from t2_SPIDER order by id;
|
||||
id op op_count
|
||||
4 inserted 0
|
||||
drop table t1, t2, t1_SPIDER, t2_SPIDER;
|
||||
drop server s;
|
||||
for master_1
|
||||
for child2
|
||||
for child3
|
||||
#
|
||||
# end of test MDEV-37484
|
||||
#
|
||||
110
storage/spider/mysql-test/spider/bugfix/t/mdev_37484.test
Normal file
110
storage/spider/mysql-test/spider/bugfix/t/mdev_37484.test
Normal file
@@ -0,0 +1,110 @@
|
||||
--echo #
|
||||
--echo # MDEV-37484: `Sql_cmd_dml::execute_inner`, `Sql_cmd_update::execute_inner` do not call Select handler for the engine involved
|
||||
--echo #
|
||||
|
||||
--disable_query_log
|
||||
--disable_result_log
|
||||
--source ../../t/test_init.inc
|
||||
--enable_result_log
|
||||
--enable_query_log
|
||||
set spider_same_server_link=1;
|
||||
|
||||
evalp CREATE SERVER s FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test', user 'root');
|
||||
|
||||
create table product_tag(product_id bigint);
|
||||
create table product (
|
||||
`product_id` bigint(20) DEFAULT NULL,
|
||||
`price` bigint(20) DEFAULT NULL,
|
||||
`short_description` varchar(7998) DEFAULT NULL,
|
||||
`brand` varchar(254) DEFAULT NULL,
|
||||
`modified_dtm` datetime DEFAULT NULL,
|
||||
`created_dtm` datetime DEFAULT NULL,
|
||||
`modified_by` int(11) DEFAULT NULL
|
||||
);
|
||||
|
||||
insert into product_tag values (1),(2),(3),(4);
|
||||
insert into product values (1,22,'fes','rets','2011-12-12 12:12:12','2011-12-13 1:1:10',343);
|
||||
insert into product values (3,22,'fes','rets','2011-12-12 12:12:12','2011-12-13 1:1:10',343);
|
||||
|
||||
create table product_tag_spider (product_id bigint) ENGINE=SPIDER REMOTE_SERVER=s REMOTE_TABLE=product_tag;
|
||||
create table product_spider (
|
||||
`product_id` bigint(20) DEFAULT NULL,
|
||||
`price` bigint(20) DEFAULT NULL,
|
||||
`short_description` varchar(7998) DEFAULT NULL,
|
||||
`brand` varchar(254) DEFAULT NULL,
|
||||
`modified_dtm` datetime DEFAULT NULL,
|
||||
`created_dtm` datetime DEFAULT NULL,
|
||||
`modified_by` int(11) DEFAULT NULL
|
||||
) ENGINE=SPIDER REMOTE_SERVER=s REMOTE_TABLE=product;
|
||||
|
||||
select * from product_spider order by product_id;
|
||||
|
||||
let $query=
|
||||
update
|
||||
product_spider p join
|
||||
(select product_id from product_tag_spider limit 1000) t using (product_id)
|
||||
set brand=p.product_id, price=555, modified_dtm='2011-12-15 15:15:30',
|
||||
short_description=concat(short_description,modified_by);
|
||||
|
||||
eval explain $query;
|
||||
eval $query;
|
||||
|
||||
select * from product_spider order by product_id;
|
||||
|
||||
drop table product, product_tag, product_spider, product_tag_spider;
|
||||
|
||||
create table t1 (id int);
|
||||
create table t2 (id int, op varchar(10), op_count int DEFAULT 0);
|
||||
|
||||
insert into t1 values (1),(2),(3),(4);
|
||||
insert into t2 (id, op) values (1, 'inserted'), (2, 'inserted'), (3, 'inserted'), (4, 'inserted');
|
||||
|
||||
CREATE TABLE t1_SPIDER (id int) ENGINE=SPIDER REMOTE_SERVER=s REMOTE_TABLE=t1;
|
||||
CREATE TABLE t2_SPIDER (id int, op varchar(10), op_count int DEFAULT 0) ENGINE=SPIDER REMOTE_SERVER=s REMOTE_TABLE=t2;
|
||||
|
||||
select * from t2_SPIDER order by id;
|
||||
|
||||
--echo # Update tests
|
||||
let $query=
|
||||
update t2_SPIDER inner join t1_SPIDER on t2_SPIDER.id = t1_SPIDER.id
|
||||
set t2_SPIDER.op = 'updated', t2_SPIDER.op_count = t2_SPIDER.op_count + 1
|
||||
where t2_SPIDER.id in (1, 2);
|
||||
|
||||
eval explain $query;
|
||||
eval $query;
|
||||
|
||||
select * from t2_SPIDER order by id;
|
||||
|
||||
PREPARE stmt_update FROM
|
||||
'update t2_SPIDER inner join t1_SPIDER on t2_SPIDER.id = t1_SPIDER.id set t2_SPIDER.op_count = t2_SPIDER.op_count + 1, t2_SPIDER.op="updated" where t2_SPIDER.id in (1, 2)';
|
||||
EXECUTE stmt_update;
|
||||
DEALLOCATE PREPARE stmt_update;
|
||||
|
||||
select * from t2_SPIDER order by id;
|
||||
|
||||
--echo # Delete tests
|
||||
explain
|
||||
delete t2_SPIDER from t2_SPIDER inner join t1_SPIDER on t2_SPIDER.id = t1_SPIDER.id and t2_SPIDER.op = 'updated';
|
||||
|
||||
delete t2_SPIDER from t2_SPIDER inner join t1_SPIDER on t2_SPIDER.id = t1_SPIDER.id and t2_SPIDER.op = 'updated';
|
||||
select * from t2_SPIDER order by id;
|
||||
|
||||
PREPARE stmt_delete FROM
|
||||
'delete t2_SPIDER from t2_SPIDER inner join t1_SPIDER on t2_SPIDER.id = t1_SPIDER.id where t2_SPIDER.id = 3';
|
||||
EXECUTE stmt_delete;
|
||||
DEALLOCATE PREPARE stmt_delete;
|
||||
|
||||
select * from t2_SPIDER order by id;
|
||||
|
||||
drop table t1, t2, t1_SPIDER, t2_SPIDER;
|
||||
drop server s;
|
||||
|
||||
--disable_query_log
|
||||
--disable_result_log
|
||||
--source ../../t/test_deinit.inc
|
||||
--enable_result_log
|
||||
--enable_query_log
|
||||
|
||||
--echo #
|
||||
--echo # end of test MDEV-37484
|
||||
--echo #
|
||||
Reference in New Issue
Block a user