Commit c65cce36 authored by Sergei Golubchik's avatar Sergei Golubchik

MDEV-12137 DELETE statement with the same source and target

* various cleanups (mostly cosmetic)
* remove useless tests (that were tesing the error condition)
* optimize delete_use_source test (from 6 mins to 50 seconds,
  mainly by removing two huge rollbacks at the end).
parent abf95afa
set sql_mode=oracle; create table t1(c1 integer not null,c2 integer not null, key (c1)) engine=InnoDb;
use test; create view v1 as select * from t1 where c1 in (0,1);
create or replace table tab_delete(c1 integer not null,c2 integer not null) engine=InnoDb; insert t1 select 0,seq from seq_1_to_500;
create index tab_delete_c1 on tab_delete(c1); insert t1 select 1,seq from seq_1_to_50;
create or replace view view_delete as select * from tab_delete where c1 in (0,1); insert t1 select 2,seq from seq_1_to_20;
CREATE or replace PROCEDURE gendata(a int, count int ) AS insert t1 select 3,seq from seq_1_to_20;
i INT:=0;
BEGIN
FOR i IN 1 .. count
LOOP
insert into tab_delete values (a,i);
END LOOP;
END;
/
create or replace trigger trg after delete on tab_delete for each row
begin
declare c int;
begin
if old.c1 = 1 then
select count(*) into c from tab_delete where c1!=old.c1;
SIGNAL SQLSTATE '45000' set table_name=c;
end if;
end;
end;
/
set @count=500;
call gendata(0,@count);
call gendata(1,50);
call gendata(2,20);
call gendata(3,20);
commit;
# #
# Delete with limit (quick select - range acces) # Delete with limit (quick select - range acces)
# #
start transaction; start transaction;
delete from tab_delete where (select count(*) from tab_delete b where b.c1=tab_delete.c1) = 500 limit 1; delete from t1 where (select count(*) from t1 b where b.c1=t1.c1) = 500 limit 1;
affected rows: 1 affected rows: 1
delete from tab_delete where (select count(*) from tab_delete b where b.c1=tab_delete.c1) = 500 limit 1; delete from t1 where (select count(*) from t1 b where b.c1=t1.c1) = 500 limit 1;
affected rows: 0 affected rows: 0
select count(*) from view_delete where c1=0; select count(*) from v1 where c1=0;
count(*) count(*)
499 499
rollback; rollback;
...@@ -45,21 +20,21 @@ rollback; ...@@ -45,21 +20,21 @@ rollback;
# Delete # Delete
# #
start transaction; start transaction;
delete from tab_delete where (select count(*) from tab_delete b where b.c1=tab_delete.c1) = 500 ; delete from t1 where (select count(*) from t1 b where b.c1=t1.c1) = 500 ;
affected rows: 500 affected rows: 500
rollback; rollback;
# #
# Delete with exists # Delete with exists
# #
start transaction; start transaction;
select count(*) from view_delete where c1=2; select count(*) from v1 where c1=2;
count(*) count(*)
0 0
delete from tab_delete where c1=2 and exists(select 'x' from tab_delete b where b.c2<10); delete from t1 where c1=2 and exists(select 'x' from t1 b where b.c2<10);
affected rows: 20 affected rows: 20
delete from tab_delete where c1=2 and exists(select 'x' from tab_delete b where b.c2<10); delete from t1 where c1=2 and exists(select 'x' from t1 b where b.c2<10);
affected rows: 0 affected rows: 0
select count(*) from view_delete where c1=2; select count(*) from v1 where c1=2;
count(*) count(*)
0 0
rollback; rollback;
...@@ -67,18 +42,15 @@ rollback; ...@@ -67,18 +42,15 @@ rollback;
# Delete throw a view with limit (range access) # Delete throw a view with limit (range access)
# #
start transaction; start transaction;
# Acces by range (quick_select), initied = INDEX explain delete from v1 where (select count(*) from t1 b where b.c1=v1.c1) = 500 limit 1;
# +------+--------------------+------------+-------+---------------+---------------+---------+--------------------+------+-------------+ id select_type table type possible_keys key key_len ref rows Extra
# | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | 1 PRIMARY t1 range c1 c1 4 NULL 550 Using where
# +------+--------------------+------------+-------+---------------+---------------+---------+--------------------+------+-------------+ 2 DEPENDENT SUBQUERY b ref c1 c1 4 test.t1.c1 82 Using index
# | 1 | PRIMARY | tab_delete | range | tab_delete_c1 | tab_delete_c1 | 4 | NULL | 550 | Using where | delete from v1 where (select count(*) from t1 b where b.c1=v1.c1) = 500 limit 1;
# | 2 | DEPENDENT SUBQUERY | b | ref | tab_delete_c1 | tab_delete_c1 | 4 | test.tab_delete.c1 | 73 | Using index |
# +------+--------------------+------------+-------+---------------+---------------+---------+--------------------+------+-------------+
delete from view_delete where (select count(*) from tab_delete b where b.c1=view_delete.c1) = 500 limit 1;
affected rows: 1 affected rows: 1
delete from view_delete where (select count(*) from tab_delete b where b.c1=view_delete.c1) = 500 limit 1; delete from v1 where (select count(*) from t1 b where b.c1=v1.c1) = 500 limit 1;
affected rows: 0 affected rows: 0
select count(*) from view_delete where c1=0; select count(*) from v1 where c1=0;
count(*) count(*)
499 499
rollback; rollback;
...@@ -86,41 +58,50 @@ rollback; ...@@ -86,41 +58,50 @@ rollback;
# Delete throw a view (ALL access) # Delete throw a view (ALL access)
# #
start transaction; start transaction;
# Acces by pointer, initied = RND explain delete from v1 where (select count(*) from t1 b where b.c1=v1.c1) = 500;
# +------+--------------------+------------+------+---------------+---------------+---------+--------------------+------+-------------+ id select_type table type possible_keys key key_len ref rows Extra
# | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | 1 PRIMARY t1 ALL c1 NULL NULL NULL 717 Using where
# +------+--------------------+------------+------+---------------+---------------+---------+--------------------+------+-------------+ 2 DEPENDENT SUBQUERY b ref c1 c1 4 test.t1.c1 82 Using index
# | 1 | PRIMARY | tab_delete | ALL | tab_delete_c1 | NULL | NULL | NULL | 589 | Using where | delete from v1 where (select count(*) from t1 b where b.c1=v1.c1) = 500 ;
# | 2 | DEPENDENT SUBQUERY | b | ref | tab_delete_c1 | tab_delete_c1 | 4 | test.tab_delete.c1 | 295 | Using index |
# +------+--------------------+------------+------+---------------+---------------+---------+--------------------+------+-------------+
delete from view_delete where (select count(*) from tab_delete b where b.c1=view_delete.c1) = 500 ;
affected rows: 500 affected rows: 500
select count(*) from view_delete where c1=0; select count(*) from v1 where c1=0;
count(*) count(*)
0 0
rollback; rollback;
# #
# Delete failed due to trigger # Delete failed due to trigger
# #
create trigger trg after delete on t1 for each row
begin
declare c int;
begin
if old.c1 = 1 then
select count(*) into c from t1 where c1!=old.c1;
SIGNAL SQLSTATE '45000' set table_name=c;
end if;
end;
end;
/
start transaction; start transaction;
delete from tab_delete where c1=1 and (select count(*) from tab_delete b where b.c1=tab_delete.c1) > 0 order by c2 asc limit 10; delete from t1 where c1=1 and (select count(*) from t1 b where b.c1=t1.c1) > 0 order by c2 asc limit 10;
ERROR 45000: Unhandled user-defined exception condition ERROR 45000: Unhandled user-defined exception condition
rollback; rollback;
start transaction; start transaction;
delete from tab_delete where (select count(*) from tab_delete b where b.c1=tab_delete.c1) > 0 order by c1 desc limit 100; delete from t1 where (select count(*) from t1 b where b.c1=t1.c1) > 0 order by c1 desc limit 100;
ERROR 45000: Unhandled user-defined exception condition ERROR 45000: Unhandled user-defined exception condition
select c1,count(*) from tab_delete group by c1; select c1,count(*) from t1 group by c1;
c1 count(*) c1 count(*)
0 500 0 500
1 50 1 50
2 20 2 20
3 20 3 20
rollback; rollback;
drop trigger trg;
# #
# Delete throw a view with returning # Delete throw a view with returning
# #
start transaction; start transaction;
delete from tab_delete where (select count(*) from tab_delete b where b.c1=tab_delete.c1) = 500 order by c2 asc limit 10 returning c1,c2; delete from t1 where (select count(*) from t1 b where b.c1=t1.c1) = 500 order by c2 asc limit 10 returning c1,c2;
c1 c2 c1 c2
0 1 0 1
0 2 0 2
...@@ -134,7 +115,7 @@ c1 c2 ...@@ -134,7 +115,7 @@ c1 c2
0 10 0 10
rollback; rollback;
start transaction; start transaction;
delete from tab_delete where (select count(*) from tab_delete b where b.c1=tab_delete.c1) = 500 order by c2 desc limit 10 returning c1,c2; delete from t1 where (select count(*) from t1 b where b.c1=t1.c1) = 500 order by c2 desc limit 10 returning c1,c2;
c1 c2 c1 c2
0 491 0 491
0 492 0 492
...@@ -147,32 +128,24 @@ c1 c2 ...@@ -147,32 +128,24 @@ c1 c2
0 499 0 499
0 500 0 500
rollback; rollback;
drop view v1;
drop table t1;
# #
# Delete from table with more than 150000 rows # Delete from table with more than 150000 rows
# #
insert into tab_delete select * from tab_delete; create table t1(c1 integer not null,c2 integer not null, key (c1));
insert into tab_delete select * from tab_delete; insert t1 select 0,seq from seq_1_to_128000;
insert into tab_delete select * from tab_delete; insert t1 select 1,seq from seq_1_to_25600;
insert into tab_delete select * from tab_delete; select count(*) from t1;
insert into tab_delete select * from tab_delete;
insert into tab_delete select * from tab_delete;
insert into tab_delete select * from tab_delete;
insert into tab_delete select * from tab_delete;
select count(*) from tab_delete;
count(*) count(*)
151040 153600
with high memory for sort_buffer_size # with a lot of memory for sort_buffer_size
SET SESSION sort_buffer_size = 1024000; set session sort_buffer_size = 1024000;
start transaction; delete from t1 where c1=0 and exists(select 'x' from t1 b where b.c1<10);
delete from tab_delete where c1=0 and exists(select 'x' from tab_delete b where b.c1<10);
affected rows: 128000 affected rows: 128000
rollback; # with little memory for sort_buffer_size
with few memory for sort_buffer_size insert t1 select 0,seq from seq_1_to_128000;
SET SESSION sort_buffer_size = 1024; set session sort_buffer_size = 1024;
start transaction; delete from t1 where c1=0 and exists(select 'x' from t1 b where b.c1<10);
delete from tab_delete where c1=0 and exists(select 'x' from tab_delete b where b.c1<10);
affected rows: 128000 affected rows: 128000
rollback; drop table t1;
drop procedure if exists gendata;
drop view if exists view_delete;
drop table if exists tab_delete;
...@@ -65,9 +65,6 @@ update v3aA set v3Aa.col1 = (select max(col1) from v2aA); ...@@ -65,9 +65,6 @@ update v3aA set v3Aa.col1 = (select max(col1) from v2aA);
ERROR HY000: The definition of table 'v2aA' prevents operation UPDATE on table 'v3aA' ERROR HY000: The definition of table 'v2aA' prevents operation UPDATE on table 'v3aA'
update v3aA set v3Aa.col1 = (select max(col1) from v3aA); update v3aA set v3Aa.col1 = (select max(col1) from v3aA);
ERROR HY000: Table 'v3aA' is specified twice, both as a target for 'UPDATE' and as a separate source for data ERROR HY000: Table 'v3aA' is specified twice, both as a target for 'UPDATE' and as a separate source for data
delete from v2Aa where col1 = (select max(col1) from v1Aa);
delete from v2aA where col1 = (select max(col1) from t1Aa);
delete from v2Aa where col1 = (select max(col1) from v2aA);
delete v2Aa from v2aA,t2Aa where (select max(col1) from v1aA) > 0 and v2Aa.col1 = t2aA.col1; delete v2Aa from v2aA,t2Aa where (select max(col1) from v1aA) > 0 and v2Aa.col1 = t2aA.col1;
ERROR HY000: The definition of table 'v1aA' prevents operation DELETE on table 'v2aA' ERROR HY000: The definition of table 'v1aA' prevents operation DELETE on table 'v2aA'
delete t1aA from t1Aa,t2Aa where (select max(col1) from v1Aa) > 0 and t1aA.col1 = t2aA.col1; delete t1aA from t1Aa,t2Aa where (select max(col1) from v1Aa) > 0 and t1aA.col1 = t2aA.col1;
......
...@@ -3742,48 +3742,6 @@ update m1 set a = ((select max(a) from v1)); ...@@ -3742,48 +3742,6 @@ update m1 set a = ((select max(a) from v1));
ERROR HY000: The definition of table 'v1' prevents operation UPDATE on table 'm1' ERROR HY000: The definition of table 'v1' prevents operation UPDATE on table 'm1'
update m1 set a = ((select max(a) from tmp, v1)); update m1 set a = ((select max(a) from tmp, v1));
ERROR HY000: The definition of table 'v1' prevents operation UPDATE on table 'm1' ERROR HY000: The definition of table 'v1' prevents operation UPDATE on table 'm1'
delete from m1 where a = (select max(a) from m1);
insert into t1 (a) values (1);
insert into t2 (a) values (1);
delete from m1 where a = (select max(a) from m2);
insert into t1 (a) values (1);
insert into t2 (a) values (1);
delete from m1 where a = (select max(a) from t1);
insert into t1 (a) values (1);
insert into t2 (a) values (1);
delete from m1 where a = (select max(a) from t2);
insert into t1 (a) values (1);
insert into t2 (a) values (1);
delete from m1 where a = (select max(a) from t3, m1);
insert into t1 (a) values (1);
insert into t2 (a) values (1);
delete from m1 where a = (select max(a) from t3, m2);
insert into t1 (a) values (1);
insert into t2 (a) values (1);
delete from m1 where a = (select max(a) from t3, t1);
insert into t1 (a) values (1);
insert into t2 (a) values (1);
delete from m1 where a = (select max(a) from t3, t2);
insert into t1 (a) values (1);
insert into t2 (a) values (1);
delete from m1 where a = (select max(a) from tmp, m1);
insert into t1 (a) values (1);
insert into t2 (a) values (1);
delete from m1 where a = (select max(a) from tmp, m2);
insert into t1 (a) values (1);
insert into t2 (a) values (1);
delete from m1 where a = (select max(a) from tmp, t1);
insert into t1 (a) values (1);
insert into t2 (a) values (1);
delete from m1 where a = (select max(a) from tmp, t2);
insert into t1 (a) values (1);
insert into t2 (a) values (1);
delete from m1 where a = (select max(a) from v1);
insert into t1 (a) values (1);
insert into t2 (a) values (1);
delete from m1 where a = (select max(a) from tmp, v1);
insert into t1 (a) values (1);
insert into t2 (a) values (1);
drop view v1; drop view v1;
drop temporary table tmp; drop temporary table tmp;
drop table t1, t2, t3, m1, m2; drop table t1, t2, t3, m1, m2;
......
...@@ -993,9 +993,6 @@ update v3 set v3.col1 = (select max(col1) from v2); ...@@ -993,9 +993,6 @@ update v3 set v3.col1 = (select max(col1) from v2);
ERROR HY000: The definition of table 'v2' prevents operation UPDATE on table 'v3' ERROR HY000: The definition of table 'v2' prevents operation UPDATE on table 'v3'
update v3 set v3.col1 = (select max(col1) from v3); update v3 set v3.col1 = (select max(col1) from v3);
ERROR HY000: Table 'v3' is specified twice, both as a target for 'UPDATE' and as a separate source for data ERROR HY000: Table 'v3' is specified twice, both as a target for 'UPDATE' and as a separate source for data
delete from v2 where col1 = (select max(col1) from v1);
delete from v2 where col1 = (select max(col1) from t1);
delete from v2 where col1 = (select max(col1) from v2);
delete v2 from v2,t2 where (select max(col1) from v1) > 0 and v2.col1 = t2.col1; delete v2 from v2,t2 where (select max(col1) from v1) > 0 and v2.col1 = t2.col1;
ERROR HY000: The definition of table 'v1' prevents operation DELETE on table 'v2' ERROR HY000: The definition of table 'v1' prevents operation DELETE on table 'v2'
delete t1 from t1,t2 where (select max(col1) from v1) > 0 and t1.col1 = t2.col1; delete t1 from t1,t2 where (select max(col1) from v1) > 0 and t1.col1 = t2.col1;
......
-- source include/have_innodb.inc --source include/have_sequence.inc
set sql_mode=oracle; --source include/have_innodb.inc
use test; create table t1(c1 integer not null,c2 integer not null, key (c1)) engine=InnoDb;
create or replace table tab_delete(c1 integer not null,c2 integer not null) engine=InnoDb; create view v1 as select * from t1 where c1 in (0,1);
create index tab_delete_c1 on tab_delete(c1);
create or replace view view_delete as select * from tab_delete where c1 in (0,1); insert t1 select 0,seq from seq_1_to_500;
delimiter /; insert t1 select 1,seq from seq_1_to_50;
CREATE or replace PROCEDURE gendata(a int, count int ) AS insert t1 select 2,seq from seq_1_to_20;
i INT:=0; insert t1 select 3,seq from seq_1_to_20;
BEGIN
FOR i IN 1 .. count
LOOP
insert into tab_delete values (a,i);
END LOOP;
END;
/
create or replace trigger trg after delete on tab_delete for each row
begin
declare c int;
begin
if old.c1 = 1 then
select count(*) into c from tab_delete where c1!=old.c1;
SIGNAL SQLSTATE '45000' set table_name=c;
end if;
end;
end;
/
delimiter ;/
set @count=500;
call gendata(0,@count);
call gendata(1,50);
call gendata(2,20);
call gendata(3,20);
commit;
--echo # --echo #
--echo # Delete with limit (quick select - range acces) --echo # Delete with limit (quick select - range acces)
...@@ -39,10 +14,10 @@ commit; ...@@ -39,10 +14,10 @@ commit;
start transaction; start transaction;
--enable_info --enable_info
delete from tab_delete where (select count(*) from tab_delete b where b.c1=tab_delete.c1) = 500 limit 1; delete from t1 where (select count(*) from t1 b where b.c1=t1.c1) = 500 limit 1;
delete from tab_delete where (select count(*) from tab_delete b where b.c1=tab_delete.c1) = 500 limit 1; delete from t1 where (select count(*) from t1 b where b.c1=t1.c1) = 500 limit 1;
--disable_info --disable_info
select count(*) from view_delete where c1=0; select count(*) from v1 where c1=0;
rollback; rollback;
--echo # --echo #
...@@ -50,9 +25,8 @@ rollback; ...@@ -50,9 +25,8 @@ rollback;
--echo # --echo #
start transaction; start transaction;
--enable_info --enable_info ONCE
delete from tab_delete where (select count(*) from tab_delete b where b.c1=tab_delete.c1) = 500 ; delete from t1 where (select count(*) from t1 b where b.c1=t1.c1) = 500 ;
--disable_info
rollback; rollback;
--echo # --echo #
...@@ -60,12 +34,12 @@ rollback; ...@@ -60,12 +34,12 @@ rollback;
--echo # --echo #
start transaction; start transaction;
select count(*) from view_delete where c1=2; select count(*) from v1 where c1=2;
--enable_info --enable_info
delete from tab_delete where c1=2 and exists(select 'x' from tab_delete b where b.c2<10); delete from t1 where c1=2 and exists(select 'x' from t1 b where b.c2<10);
delete from tab_delete where c1=2 and exists(select 'x' from tab_delete b where b.c2<10); delete from t1 where c1=2 and exists(select 'x' from t1 b where b.c2<10);
--disable_info --disable_info
select count(*) from view_delete where c1=2; select count(*) from v1 where c1=2;
rollback; rollback;
--echo # --echo #
...@@ -73,19 +47,12 @@ rollback; ...@@ -73,19 +47,12 @@ rollback;
--echo # --echo #
start transaction; start transaction;
--echo # Acces by range (quick_select), initied = INDEX explain delete from v1 where (select count(*) from t1 b where b.c1=v1.c1) = 500 limit 1;
--echo # +------+--------------------+------------+-------+---------------+---------------+---------+--------------------+------+-------------+
--echo # | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
--echo # +------+--------------------+------------+-------+---------------+---------------+---------+--------------------+------+-------------+
--echo # | 1 | PRIMARY | tab_delete | range | tab_delete_c1 | tab_delete_c1 | 4 | NULL | 550 | Using where |
--echo # | 2 | DEPENDENT SUBQUERY | b | ref | tab_delete_c1 | tab_delete_c1 | 4 | test.tab_delete.c1 | 73 | Using index |
--echo # +------+--------------------+------------+-------+---------------+---------------+---------+--------------------+------+-------------+
# explain delete from view_delete where (select count(*) from tab_delete b where b.c1=view_delete.c1) = 500 limit 1;
--enable_info --enable_info
delete from view_delete where (select count(*) from tab_delete b where b.c1=view_delete.c1) = 500 limit 1; delete from v1 where (select count(*) from t1 b where b.c1=v1.c1) = 500 limit 1;
delete from view_delete where (select count(*) from tab_delete b where b.c1=view_delete.c1) = 500 limit 1; delete from v1 where (select count(*) from t1 b where b.c1=v1.c1) = 500 limit 1;
--disable_info --disable_info
select count(*) from view_delete where c1=0; select count(*) from v1 where c1=0;
rollback; rollback;
--echo # --echo #
...@@ -93,80 +60,73 @@ rollback; ...@@ -93,80 +60,73 @@ rollback;
--echo # --echo #
start transaction; start transaction;
--echo # Acces by pointer, initied = RND explain delete from v1 where (select count(*) from t1 b where b.c1=v1.c1) = 500;
--echo # +------+--------------------+------------+------+---------------+---------------+---------+--------------------+------+-------------+ --enable_info ONCE
--echo # | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | delete from v1 where (select count(*) from t1 b where b.c1=v1.c1) = 500 ;
--echo # +------+--------------------+------------+------+---------------+---------------+---------+--------------------+------+-------------+ select count(*) from v1 where c1=0;
--echo # | 1 | PRIMARY | tab_delete | ALL | tab_delete_c1 | NULL | NULL | NULL | 589 | Using where |
--echo # | 2 | DEPENDENT SUBQUERY | b | ref | tab_delete_c1 | tab_delete_c1 | 4 | test.tab_delete.c1 | 295 | Using index |
--echo # +------+--------------------+------------+------+---------------+---------------+---------+--------------------+------+-------------+
# explain delete from view_delete where (select count(*) from tab_delete b where b.c1=view_delete.c1) = 500;
--enable_info
delete from view_delete where (select count(*) from tab_delete b where b.c1=view_delete.c1) = 500 ;
--disable_info
select count(*) from view_delete where c1=0;
rollback; rollback;
--echo # --echo #
--echo # Delete failed due to trigger --echo # Delete failed due to trigger
--echo # --echo #
delimiter /;
create trigger trg after delete on t1 for each row
begin
declare c int;
begin
if old.c1 = 1 then
select count(*) into c from t1 where c1!=old.c1;
SIGNAL SQLSTATE '45000' set table_name=c;
end if;
end;
end;
/
delimiter ;/
start transaction; start transaction;
--enable_info
--error ER_SIGNAL_EXCEPTION --error ER_SIGNAL_EXCEPTION
delete from tab_delete where c1=1 and (select count(*) from tab_delete b where b.c1=tab_delete.c1) > 0 order by c2 asc limit 10; delete from t1 where c1=1 and (select count(*) from t1 b where b.c1=t1.c1) > 0 order by c2 asc limit 10;
--disable_info
rollback; rollback;
start transaction; start transaction;
--enable_info
--error ER_SIGNAL_EXCEPTION --error ER_SIGNAL_EXCEPTION
delete from tab_delete where (select count(*) from tab_delete b where b.c1=tab_delete.c1) > 0 order by c1 desc limit 100; delete from t1 where (select count(*) from t1 b where b.c1=t1.c1) > 0 order by c1 desc limit 100;
--disable_info select c1,count(*) from t1 group by c1;
select c1,count(*) from tab_delete group by c1;
rollback; rollback;
drop trigger trg;
--echo # --echo #
--echo # Delete throw a view with returning --echo # Delete throw a view with returning
--echo # --echo #
start transaction; start transaction;
delete from tab_delete where (select count(*) from tab_delete b where b.c1=tab_delete.c1) = 500 order by c2 asc limit 10 returning c1,c2; delete from t1 where (select count(*) from t1 b where b.c1=t1.c1) = 500 order by c2 asc limit 10 returning c1,c2;
rollback; rollback;
start transaction; start transaction;
delete from tab_delete where (select count(*) from tab_delete b where b.c1=tab_delete.c1) = 500 order by c2 desc limit 10 returning c1,c2; delete from t1 where (select count(*) from t1 b where b.c1=t1.c1) = 500 order by c2 desc limit 10 returning c1,c2;
rollback; rollback;
drop view v1;
drop table t1;
--echo # --echo #
--echo # Delete from table with more than 150000 rows --echo # Delete from table with more than 150000 rows
--echo # --echo #
insert into tab_delete select * from tab_delete; create table t1(c1 integer not null,c2 integer not null, key (c1));
insert into tab_delete select * from tab_delete; insert t1 select 0,seq from seq_1_to_128000;
insert into tab_delete select * from tab_delete; insert t1 select 1,seq from seq_1_to_25600;
insert into tab_delete select * from tab_delete; select count(*) from t1;
insert into tab_delete select * from tab_delete;
insert into tab_delete select * from tab_delete;
insert into tab_delete select * from tab_delete;
insert into tab_delete select * from tab_delete;
select count(*) from tab_delete;
--echo with high memory for sort_buffer_size
SET SESSION sort_buffer_size = 1024000;
start transaction;
--enable_info
delete from tab_delete where c1=0 and exists(select 'x' from tab_delete b where b.c1<10);
--disable_info
rollback;
--echo with few memory for sort_buffer_size --echo # with a lot of memory for sort_buffer_size
SET SESSION sort_buffer_size = 1024; set session sort_buffer_size = 1024000;
start transaction; --enable_info ONCE
--enable_info delete from t1 where c1=0 and exists(select 'x' from t1 b where b.c1<10);
delete from tab_delete where c1=0 and exists(select 'x' from tab_delete b where b.c1<10);
--disable_info --echo # with little memory for sort_buffer_size
rollback; insert t1 select 0,seq from seq_1_to_128000;
set session sort_buffer_size = 1024;
--enable_info ONCE
delete from t1 where c1=0 and exists(select 'x' from t1 b where b.c1<10);
drop procedure if exists gendata; drop table t1;
drop view if exists view_delete;
drop table if exists tab_delete;
...@@ -73,10 +73,6 @@ update v3aA set v3Aa.col1 = (select max(col1) from t1aA); ...@@ -73,10 +73,6 @@ update v3aA set v3Aa.col1 = (select max(col1) from t1aA);
update v3aA set v3Aa.col1 = (select max(col1) from v2aA); update v3aA set v3Aa.col1 = (select max(col1) from v2aA);
-- error 1093 -- error 1093
update v3aA set v3Aa.col1 = (select max(col1) from v3aA); update v3aA set v3Aa.col1 = (select max(col1) from v3aA);
# Works since MDEV-12137 (no more error 1093)
delete from v2Aa where col1 = (select max(col1) from v1Aa);
delete from v2aA where col1 = (select max(col1) from t1Aa);
delete from v2Aa where col1 = (select max(col1) from v2aA);
-- error 1443 -- error 1443
delete v2Aa from v2aA,t2Aa where (select max(col1) from v1aA) > 0 and v2Aa.col1 = t2aA.col1; delete v2Aa from v2aA,t2Aa where (select max(col1) from v1aA) > 0 and v2Aa.col1 = t2aA.col1;
-- error 1443 -- error 1443
......
...@@ -2763,66 +2763,6 @@ update m1 set a = ((select max(a) from tmp, t2)); ...@@ -2763,66 +2763,6 @@ update m1 set a = ((select max(a) from tmp, t2));
update m1 set a = ((select max(a) from v1)); update m1 set a = ((select max(a) from v1));
--error ER_VIEW_PREVENT_UPDATE --error ER_VIEW_PREVENT_UPDATE
update m1 set a = ((select max(a) from tmp, v1)); update m1 set a = ((select max(a) from tmp, v1));
# Works since MDEV-12137
# previously :ER_UPDATE_TABLE_USED
delete from m1 where a = (select max(a) from m1);
insert into t1 (a) values (1);
insert into t2 (a) values (1);
# previously :ER_UPDATE_TABLE_USED
delete from m1 where a = (select max(a) from m2);
insert into t1 (a) values (1);
insert into t2 (a) values (1);
# previously :ER_UPDATE_TABLE_USED
delete from m1 where a = (select max(a) from t1);
insert into t1 (a) values (1);
insert into t2 (a) values (1);
# previously :ER_UPDATE_TABLE_USED
delete from m1 where a = (select max(a) from t2);
insert into t1 (a) values (1);
insert into t2 (a) values (1);
# previously :ER_UPDATE_TABLE_USED
delete from m1 where a = (select max(a) from t3, m1);
insert into t1 (a) values (1);
insert into t2 (a) values (1);
# previously :ER_UPDATE_TABLE_USED
delete from m1 where a = (select max(a) from t3, m2);
insert into t1 (a) values (1);
insert into t2 (a) values (1);
# previously :ER_UPDATE_TABLE_USED
delete from m1 where a = (select max(a) from t3, t1);
insert into t1 (a) values (1);
insert into t2 (a) values (1);
# previously :ER_UPDATE_TABLE_USED
delete from m1 where a = (select max(a) from t3, t2);
insert into t1 (a) values (1);
insert into t2 (a) values (1);
# previously :ER_UPDATE_TABLE_USED
delete from m1 where a = (select max(a) from tmp, m1);
insert into t1 (a) values (1);
insert into t2 (a) values (1);
# previously :ER_UPDATE_TABLE_USED
delete from m1 where a = (select max(a) from tmp, m2);
insert into t1 (a) values (1);
insert into t2 (a) values (1);
# previously :ER_UPDATE_TABLE_USED
delete from m1 where a = (select max(a) from tmp, t1);
insert into t1 (a) values (1);
insert into t2 (a) values (1);
# previously :ER_UPDATE_TABLE_USED
delete from m1 where a = (select max(a) from tmp, t2);
insert into t1 (a) values (1);
insert into t2 (a) values (1);
# previously : ER_VIEW_PREVENT_UPDATE
delete from m1 where a = (select max(a) from v1);
insert into t1 (a) values (1);
insert into t2 (a) values (1);
# previously : ER_VIEW_PREVENT_UPDATE
delete from m1 where a = (select max(a) from tmp, v1);
insert into t1 (a) values (1);
insert into t2 (a) values (1);
drop view v1; drop view v1;
drop temporary table tmp; drop temporary table tmp;
......
...@@ -914,13 +914,6 @@ update v3 set v3.col1 = (select max(col1) from t1); ...@@ -914,13 +914,6 @@ update v3 set v3.col1 = (select max(col1) from t1);
update v3 set v3.col1 = (select max(col1) from v2); update v3 set v3.col1 = (select max(col1) from v2);
-- error ER_UPDATE_TABLE_USED -- error ER_UPDATE_TABLE_USED
update v3 set v3.col1 = (select max(col1) from v3); update v3 set v3.col1 = (select max(col1) from v3);
# Works since MDEV-12137
# Previously error ER_VIEW_PREVENT_UPDATE
delete from v2 where col1 = (select max(col1) from v1);
# Previously error ER_VIEW_PREVENT_UPDATE
delete from v2 where col1 = (select max(col1) from t1);
# Previously error ER_UPDATE_TABLE_USED
delete from v2 where col1 = (select max(col1) from v2);
-- error ER_VIEW_PREVENT_UPDATE -- error ER_VIEW_PREVENT_UPDATE
delete v2 from v2,t2 where (select max(col1) from v1) > 0 and v2.col1 = t2.col1; delete v2 from v2,t2 where (select max(col1) from v1) > 0 and v2.col1 = t2.col1;
-- error ER_VIEW_PREVENT_UPDATE -- error ER_VIEW_PREVENT_UPDATE
......
...@@ -45,7 +45,7 @@ ...@@ -45,7 +45,7 @@
// end_read_record // end_read_record
#include "sql_partition.h" // make_used_partitions_str #include "sql_partition.h" // make_used_partitions_str
#define MEM_STRIP_BUF_SIZE current_thd->variables.sortbuff_size #define MEM_STRIP_BUF_SIZE thd->variables.sortbuff_size
/* /*
@brief @brief
...@@ -214,6 +214,22 @@ void Update_plan::save_explain_data_intern(MEM_ROOT *mem_root, ...@@ -214,6 +214,22 @@ void Update_plan::save_explain_data_intern(MEM_ROOT *mem_root,
} }
static bool record_should_be_deleted(THD *thd, TABLE *table, SQL_SELECT *sel,
Explain_delete *explain)
{
explain->tracker.on_record_read();
thd->inc_examined_row_count(1);
if (table->vfield)
(void) table->update_virtual_fields(table->file, VCOL_UPDATE_FOR_DELETE);
if (!sel || sel->skip_record(thd) > 0)
{
explain->tracker.on_record_after_where();
return true;
}
return false;
}
/** /**
Implement DELETE SQL word. Implement DELETE SQL word.
...@@ -246,13 +262,13 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ...@@ -246,13 +262,13 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
bool with_select= !select_lex->item_list.is_empty(); bool with_select= !select_lex->item_list.is_empty();
Explain_delete *explain; Explain_delete *explain;
Delete_plan query_plan(thd->mem_root); Delete_plan query_plan(thd->mem_root);
query_plan.index= MAX_KEY;
query_plan.using_filesort= FALSE;
Unique * deltempfile= NULL; Unique * deltempfile= NULL;
uint delete_while_scanning= 1; bool delete_record, delete_while_scanning;
uint delete_record= 0;
DBUG_ENTER("mysql_delete"); DBUG_ENTER("mysql_delete");
query_plan.index= MAX_KEY;
query_plan.using_filesort= FALSE;
create_explain_query(thd->lex, thd->mem_root); create_explain_query(thd->lex, thd->mem_root);
if (open_and_lock_tables(thd, table_list, TRUE, 0)) if (open_and_lock_tables(thd, table_list, TRUE, 0))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
...@@ -281,7 +297,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ...@@ -281,7 +297,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
if (mysql_prepare_delete(thd, table_list, select_lex->with_wild, if (mysql_prepare_delete(thd, table_list, select_lex->with_wild,
select_lex->item_list, &conds, select_lex->item_list, &conds,
delete_while_scanning)) &delete_while_scanning))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
if (with_select) if (with_select)
...@@ -562,28 +578,21 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ...@@ -562,28 +578,21 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
explain= (Explain_delete*)thd->lex->explain->get_upd_del_plan(); explain= (Explain_delete*)thd->lex->explain->get_upd_del_plan();
explain->tracker.on_scan_init(); explain->tracker.on_scan_init();
if (delete_while_scanning == 0) if (!delete_while_scanning)
{ {
/* /*
The table we are going to delete appears in join. The table we are going to delete appears in subqueries in the where
Instead of deleting the rows, first mark them deleted. clause. Instead of deleting the rows, first mark them deleted.
*/ */
ha_rows tmplimit=limit; ha_rows tmplimit=limit;
deltempfile= new Unique (refpos_order_cmp, deltempfile= new (thd->mem_root) Unique (refpos_order_cmp, table->file,
(void *) table->file,
table->file->ref_length, table->file->ref_length,
MEM_STRIP_BUF_SIZE); MEM_STRIP_BUF_SIZE);
while (!(error=info.read_record(&info)) && !thd->killed && while (!(error=info.read_record(&info)) && !thd->killed &&
! thd->is_error()) ! thd->is_error())
{ {
explain->tracker.on_record_read(); if (record_should_be_deleted(thd, table, select, explain))
thd->inc_examined_row_count(1);
if (table->vfield)
(void) table->update_virtual_fields(table->file,
VCOL_UPDATE_FOR_DELETE);
if (!select || select->skip_record(thd) > 0)
{ {
explain->tracker.on_record_after_where();
table->file->position(table->record[0]); table->file->position(table->record[0]);
if ((error= deltempfile->unique_add((char*) table->file->ref))) if ((error= deltempfile->unique_add((char*) table->file->ref)))
{ {
...@@ -591,38 +600,25 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ...@@ -591,38 +600,25 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
goto terminate_delete; goto terminate_delete;
} }
if (!--tmplimit && using_limit) if (!--tmplimit && using_limit)
{
break; break;
} }
} }
}
end_read_record(&info); end_read_record(&info);
if (deltempfile->get(table) || if (deltempfile->get(table) || table->file->ha_index_or_rnd_end() ||
table->file->ha_index_or_rnd_end() || init_read_record(&info, thd, table, 0, &deltempfile->sort, 0, 1, false))
init_read_record(&info, thd, table, NULL , &deltempfile->sort, 0, 1,
FALSE))
{ {
error= 1; error= 1;
goto terminate_delete; goto terminate_delete;
} }
delete_record= 1; delete_record= true;
} }
while (!(error=info.read_record(&info)) && !thd->killed && while (!(error=info.read_record(&info)) && !thd->killed &&
! thd->is_error()) ! thd->is_error())
{ {
if (delete_while_scanning == 1) if (delete_while_scanning)
{ delete_record= record_should_be_deleted(thd, table, select, explain);
explain->tracker.on_record_read();
thd->inc_examined_row_count(1);
if (table->vfield)
(void) table->update_virtual_fields(table->file,
VCOL_UPDATE_FOR_DELETE);
delete_record=(!select || select->skip_record(thd) > 0) ? 1 : 0;
if (delete_record) if (delete_record)
explain->tracker.on_record_after_where();
}
if (delete_record == 1)
{ {
if (table->triggers && if (table->triggers &&
table->triggers->process_triggers(thd, TRG_EVENT_DELETE, table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
...@@ -808,13 +804,14 @@ l ...@@ -808,13 +804,14 @@ l
*/ */
int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list,
uint wild_num, List<Item> &field_list, Item **conds, uint wild_num, List<Item> &field_list, Item **conds,
uint &delete_while_scanning) bool *delete_while_scanning)
{ {
Item *fake_conds= 0; Item *fake_conds= 0;
SELECT_LEX *select_lex= &thd->lex->select_lex; SELECT_LEX *select_lex= &thd->lex->select_lex;
DBUG_ENTER("mysql_prepare_delete"); DBUG_ENTER("mysql_prepare_delete");
List<Item> all_fields; List<Item> all_fields;
*delete_while_scanning= true;
thd->lex->allow_sum_func= 0; thd->lex->allow_sum_func= 0;
if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context, if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context,
&thd->lex->select_lex.top_join_list, &thd->lex->select_lex.top_join_list,
...@@ -834,11 +831,9 @@ l ...@@ -834,11 +831,9 @@ l
my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "DELETE"); my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "DELETE");
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
} }
{
TABLE_LIST *duplicate; if (unique_table(thd, table_list, table_list->next_global, 0))
if ((duplicate= unique_table(thd, table_list, table_list->next_global, 0))) *delete_while_scanning= false;
delete_while_scanning= 0;
}
if (select_lex->inner_refs_list.elements && if (select_lex->inner_refs_list.elements &&
fix_inner_refs(thd, all_fields, select_lex, select_lex->ref_pointer_array)) fix_inner_refs(thd, all_fields, select_lex, select_lex->ref_pointer_array))
...@@ -1002,7 +997,7 @@ multi_delete::initialize_tables(JOIN *join) ...@@ -1002,7 +997,7 @@ multi_delete::initialize_tables(JOIN *join)
DBUG_RETURN(1); DBUG_RETURN(1);
table_map tables_to_delete_from=0; table_map tables_to_delete_from=0;
delete_while_scanning= 1; delete_while_scanning= true;
for (walk= delete_tables; walk; walk= walk->next_local) for (walk= delete_tables; walk; walk= walk->next_local)
{ {
TABLE_LIST *tbl= walk->correspondent_table->find_table_for_update(); TABLE_LIST *tbl= walk->correspondent_table->find_table_for_update();
...@@ -1015,7 +1010,7 @@ multi_delete::initialize_tables(JOIN *join) ...@@ -1015,7 +1010,7 @@ multi_delete::initialize_tables(JOIN *join)
in join, we need to defer delete. So the delete in join, we need to defer delete. So the delete
doesn't interfers with the scaning of results. doesn't interfers with the scaning of results.
*/ */
delete_while_scanning= 0; delete_while_scanning= false;
} }
} }
...@@ -1051,7 +1046,7 @@ multi_delete::initialize_tables(JOIN *join) ...@@ -1051,7 +1046,7 @@ multi_delete::initialize_tables(JOIN *join)
case send_data() shouldn't delete any rows a we may touch case send_data() shouldn't delete any rows a we may touch
the rows in the deleted table many times the rows in the deleted table many times
*/ */
delete_while_scanning= 0; delete_while_scanning= false;
} }
} }
walk= delete_tables; walk= delete_tables;
...@@ -1064,8 +1059,7 @@ multi_delete::initialize_tables(JOIN *join) ...@@ -1064,8 +1059,7 @@ multi_delete::initialize_tables(JOIN *join)
for (;walk ;walk= walk->next_local) for (;walk ;walk= walk->next_local)
{ {
TABLE *table=walk->table; TABLE *table=walk->table;
*tempfiles_ptr++= new Unique (refpos_order_cmp, *tempfiles_ptr++= new (thd->mem_root) Unique (refpos_order_cmp, table->file,
(void *) table->file,
table->file->ref_length, table->file->ref_length,
MEM_STRIP_BUF_SIZE); MEM_STRIP_BUF_SIZE);
} }
......
...@@ -28,7 +28,7 @@ template <typename T> class SQL_I_List; ...@@ -28,7 +28,7 @@ template <typename T> class SQL_I_List;
int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list,
uint wild_num, List<Item> &field_list, Item **conds, uint wild_num, List<Item> &field_list, Item **conds,
uint &delete_while_scanning); bool *delete_while_scanning);
bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
SQL_I_List<ORDER> *order, ha_rows rows, SQL_I_List<ORDER> *order, ha_rows rows,
ulonglong options, select_result *result); ulonglong options, select_result *result);
......
...@@ -1496,7 +1496,7 @@ static bool mysql_test_delete(Prepared_statement *stmt, ...@@ -1496,7 +1496,7 @@ static bool mysql_test_delete(Prepared_statement *stmt,
uint table_count= 0; uint table_count= 0;
THD *thd= stmt->thd; THD *thd= stmt->thd;
LEX *lex= stmt->lex; LEX *lex= stmt->lex;
uint delete_while_scanning=1; bool delete_while_scanning;
DBUG_ENTER("mysql_test_delete"); DBUG_ENTER("mysql_test_delete");
if (delete_precheck(thd, table_list) || if (delete_precheck(thd, table_list) ||
...@@ -1526,7 +1526,7 @@ static bool mysql_test_delete(Prepared_statement *stmt, ...@@ -1526,7 +1526,7 @@ static bool mysql_test_delete(Prepared_statement *stmt,
lex->select_lex.with_wild, lex->select_lex.with_wild,
lex->select_lex.item_list, lex->select_lex.item_list,
&lex->select_lex.where, &lex->select_lex.where,
delete_while_scanning)); &delete_while_scanning));
error: error:
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment