Merge remote-tracking branch 'origin/bb-10.2-ext' into 10.3

This commit is contained in:
Alexander Barkov 2017-07-12 12:00:11 +04:00
commit e33bda183e
33 changed files with 605 additions and 312 deletions

View File

@ -0,0 +1,151 @@
create table t1(c1 integer not null,c2 integer not null, key (c1)) engine=InnoDb;
create view v1 as select * from t1 where c1 in (0,1);
insert t1 select 0,seq from seq_1_to_500;
insert t1 select 1,seq from seq_1_to_50;
insert t1 select 2,seq from seq_1_to_20;
insert t1 select 3,seq from seq_1_to_20;
#
# Delete with limit (quick select - range acces)
#
start transaction;
delete from t1 where (select count(*) from t1 b where b.c1=t1.c1) = 500 limit 1;
affected rows: 1
delete from t1 where (select count(*) from t1 b where b.c1=t1.c1) = 500 limit 1;
affected rows: 0
select count(*) from v1 where c1=0;
count(*)
499
rollback;
#
# Delete
#
start transaction;
delete from t1 where (select count(*) from t1 b where b.c1=t1.c1) = 500 ;
affected rows: 500
rollback;
#
# Delete with exists
#
start transaction;
select count(*) from v1 where c1=2;
count(*)
0
delete from t1 where c1=2 and exists(select 'x' from t1 b where b.c2<10);
affected rows: 20
delete from t1 where c1=2 and exists(select 'x' from t1 b where b.c2<10);
affected rows: 0
select count(*) from v1 where c1=2;
count(*)
0
rollback;
#
# Delete throw a view with limit (range access)
#
start transaction;
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
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
delete from v1 where (select count(*) from t1 b where b.c1=v1.c1) = 500 limit 1;
affected rows: 1
delete from v1 where (select count(*) from t1 b where b.c1=v1.c1) = 500 limit 1;
affected rows: 0
select count(*) from v1 where c1=0;
count(*)
499
rollback;
#
# Delete throw a view (ALL access)
#
start transaction;
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
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
delete from v1 where (select count(*) from t1 b where b.c1=v1.c1) = 500 ;
affected rows: 500
select count(*) from v1 where c1=0;
count(*)
0
rollback;
#
# 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;
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
rollback;
start transaction;
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
select c1,count(*) from t1 group by c1;
c1 count(*)
0 500
1 50
2 20
3 20
rollback;
drop trigger trg;
#
# Delete throw a view with returning
#
start transaction;
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
0 1
0 2
0 3
0 4
0 5
0 6
0 7
0 8
0 9
0 10
rollback;
start transaction;
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
0 491
0 492
0 493
0 494
0 495
0 496
0 497
0 498
0 499
0 500
rollback;
drop view v1;
drop table t1;
#
# Delete from table with more than 150000 rows
#
create table t1(c1 integer not null,c2 integer not null, key (c1));
insert t1 select 0,seq from seq_1_to_128000;
insert t1 select 1,seq from seq_1_to_25600;
select count(*) from t1;
count(*)
153600
# with a lot of memory for sort_buffer_size
set session sort_buffer_size = 1024000;
delete from t1 where c1=0 and exists(select 'x' from t1 b where b.c1<10);
affected rows: 128000
# with little memory for sort_buffer_size
insert t1 select 0,seq from seq_1_to_128000;
set session sort_buffer_size = 1024;
delete from t1 where c1=0 and exists(select 'x' from t1 b where b.c1<10);
affected rows: 128000
drop table t1;

View File

@ -65,12 +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);
ERROR HY000: The definition of table 'v1Aa' prevents operation DELETE on table 'v2Aa'
delete from v2aA where col1 = (select max(col1) from t1Aa);
ERROR HY000: The definition of table 'v2aA' prevents operation DELETE on table 'v2aA'
delete from v2Aa where col1 = (select max(col1) from v2aA);
ERROR HY000: Table 'v2Aa' is specified twice, both as a target for 'DELETE' and as a separate source for data
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;

View File

@ -3742,34 +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);
ERROR HY000: Table 'm1' is specified twice, both as a target for 'DELETE' and as a separate source for data
delete from m1 where a = (select max(a) from m2);
ERROR HY000: Table 'm1' is specified twice, both as a target for 'DELETE' and as a separate source for data
delete from m1 where a = (select max(a) from t1);
ERROR HY000: Table 'm1' is specified twice, both as a target for 'DELETE' and as a separate source for data
delete from m1 where a = (select max(a) from t2);
ERROR HY000: Table 'm1' is specified twice, both as a target for 'DELETE' and as a separate source for data
delete from m1 where a = (select max(a) from t3, m1);
ERROR HY000: Table 'm1' is specified twice, both as a target for 'DELETE' and as a separate source for data
delete from m1 where a = (select max(a) from t3, m2);
ERROR HY000: Table 'm1' is specified twice, both as a target for 'DELETE' and as a separate source for data
delete from m1 where a = (select max(a) from t3, t1);
ERROR HY000: Table 'm1' is specified twice, both as a target for 'DELETE' and as a separate source for data
delete from m1 where a = (select max(a) from t3, t2);
ERROR HY000: Table 'm1' is specified twice, both as a target for 'DELETE' and as a separate source for data
delete from m1 where a = (select max(a) from tmp, m1);
ERROR HY000: Table 'm1' is specified twice, both as a target for 'DELETE' and as a separate source for data
delete from m1 where a = (select max(a) from tmp, m2);
ERROR HY000: Table 'm1' is specified twice, both as a target for 'DELETE' and as a separate source for data
delete from m1 where a = (select max(a) from tmp, t1);
ERROR HY000: Table 'm1' is specified twice, both as a target for 'DELETE' and as a separate source for data
delete from m1 where a = (select max(a) from tmp, t2);
ERROR HY000: Table 'm1' is specified twice, both as a target for 'DELETE' and as a separate source for data
delete from m1 where a = (select max(a) from v1);
ERROR HY000: The definition of table 'v1' prevents operation DELETE on table 'm1'
delete from m1 where a = (select max(a) from tmp, v1);
ERROR HY000: The definition of table 'v1' prevents operation DELETE on table 'm1'
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;

View File

@ -607,11 +607,12 @@ select * from t1 where b = (select b from t2 where t1.a = t2.a);
a b a b
2 12 2 12
delete from t1 where b in (select b from t1); delete from t1 where b in (select b from t1);
ERROR HY000: Table 't1' is specified twice, both as a target for 'DELETE' and as a separate source for data affected rows: 3
insert into t1 values (0, 10),(1, 11),(2, 12);
delete from t1 where b = (select b from t2); delete from t1 where b = (select b from t2);
ERROR 21000: Subquery returns more than 1 row ERROR 21000: Subquery returns more than 1 row
delete from t1 where b = (select b from t2 where t1.a = t2.a); delete from t1 where b = (select b from t2 where t1.a = t2.a);
select * from t1; select * from t1 order by b;
a b a b
0 10 0 10
1 11 1 11

View File

@ -611,11 +611,12 @@ select * from t1 where b = (select b from t2 where t1.a = t2.a);
a b a b
2 12 2 12
delete from t1 where b in (select b from t1); delete from t1 where b in (select b from t1);
ERROR HY000: Table 't1' is specified twice, both as a target for 'DELETE' and as a separate source for data affected rows: 3
insert into t1 values (0, 10),(1, 11),(2, 12);
delete from t1 where b = (select b from t2); delete from t1 where b = (select b from t2);
ERROR 21000: Subquery returns more than 1 row ERROR 21000: Subquery returns more than 1 row
delete from t1 where b = (select b from t2 where t1.a = t2.a); delete from t1 where b = (select b from t2 where t1.a = t2.a);
select * from t1; select * from t1 order by b;
a b a b
0 10 0 10
1 11 1 11

View File

@ -614,11 +614,12 @@ select * from t1 where b = (select b from t2 where t1.a = t2.a);
a b a b
2 12 2 12
delete from t1 where b in (select b from t1); delete from t1 where b in (select b from t1);
ERROR HY000: Table 't1' is specified twice, both as a target for 'DELETE' and as a separate source for data affected rows: 3
insert into t1 values (0, 10),(1, 11),(2, 12);
delete from t1 where b = (select b from t2); delete from t1 where b = (select b from t2);
ERROR 21000: Subquery returns more than 1 row ERROR 21000: Subquery returns more than 1 row
delete from t1 where b = (select b from t2 where t1.a = t2.a); delete from t1 where b = (select b from t2 where t1.a = t2.a);
select * from t1; select * from t1 order by b;
a b a b
0 10 0 10
1 11 1 11

View File

@ -610,11 +610,12 @@ select * from t1 where b = (select b from t2 where t1.a = t2.a);
a b a b
2 12 2 12
delete from t1 where b in (select b from t1); delete from t1 where b in (select b from t1);
ERROR HY000: Table 't1' is specified twice, both as a target for 'DELETE' and as a separate source for data affected rows: 3
insert into t1 values (0, 10),(1, 11),(2, 12);
delete from t1 where b = (select b from t2); delete from t1 where b = (select b from t2);
ERROR 21000: Subquery returns more than 1 row ERROR 21000: Subquery returns more than 1 row
delete from t1 where b = (select b from t2 where t1.a = t2.a); delete from t1 where b = (select b from t2 where t1.a = t2.a);
select * from t1; select * from t1 order by b;
a b a b
0 10 0 10
1 11 1 11

View File

@ -613,11 +613,12 @@ select * from t1 where b = (select b from t2 where t1.a = t2.a);
a b a b
2 12 2 12
delete from t1 where b in (select b from t1); delete from t1 where b in (select b from t1);
ERROR HY000: Table 't1' is specified twice, both as a target for 'DELETE' and as a separate source for data affected rows: 3
insert into t1 values (0, 10),(1, 11),(2, 12);
delete from t1 where b = (select b from t2); delete from t1 where b = (select b from t2);
ERROR 21000: Subquery returns more than 1 row ERROR 21000: Subquery returns more than 1 row
delete from t1 where b = (select b from t2 where t1.a = t2.a); delete from t1 where b = (select b from t2 where t1.a = t2.a);
select * from t1; select * from t1 order by b;
a b a b
0 10 0 10
1 11 1 11

View File

@ -610,11 +610,12 @@ select * from t1 where b = (select b from t2 where t1.a = t2.a);
a b a b
2 12 2 12
delete from t1 where b in (select b from t1); delete from t1 where b in (select b from t1);
ERROR HY000: Table 't1' is specified twice, both as a target for 'DELETE' and as a separate source for data affected rows: 3
insert into t1 values (0, 10),(1, 11),(2, 12);
delete from t1 where b = (select b from t2); delete from t1 where b = (select b from t2);
ERROR 21000: Subquery returns more than 1 row ERROR 21000: Subquery returns more than 1 row
delete from t1 where b = (select b from t2 where t1.a = t2.a); delete from t1 where b = (select b from t2 where t1.a = t2.a);
select * from t1; select * from t1 order by b;
a b a b
0 10 0 10
1 11 1 11

View File

@ -993,12 +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);
ERROR HY000: The definition of table 'v1' prevents operation DELETE on table 'v2'
delete from v2 where col1 = (select max(col1) from t1);
ERROR HY000: The definition of table 'v2' prevents operation DELETE on table 'v2'
delete from v2 where col1 = (select max(col1) from v2);
ERROR HY000: Table 'v2' is specified twice, both as a target for 'DELETE' and as a separate source for data
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;

View File

@ -0,0 +1,132 @@
--source include/have_sequence.inc
--source include/have_innodb.inc
create table t1(c1 integer not null,c2 integer not null, key (c1)) engine=InnoDb;
create view v1 as select * from t1 where c1 in (0,1);
insert t1 select 0,seq from seq_1_to_500;
insert t1 select 1,seq from seq_1_to_50;
insert t1 select 2,seq from seq_1_to_20;
insert t1 select 3,seq from seq_1_to_20;
--echo #
--echo # Delete with limit (quick select - range acces)
--echo #
start transaction;
--enable_info
delete from t1 where (select count(*) from t1 b where b.c1=t1.c1) = 500 limit 1;
delete from t1 where (select count(*) from t1 b where b.c1=t1.c1) = 500 limit 1;
--disable_info
select count(*) from v1 where c1=0;
rollback;
--echo #
--echo # Delete
--echo #
start transaction;
--enable_info ONCE
delete from t1 where (select count(*) from t1 b where b.c1=t1.c1) = 500 ;
rollback;
--echo #
--echo # Delete with exists
--echo #
start transaction;
select count(*) from v1 where c1=2;
--enable_info
delete from t1 where c1=2 and exists(select 'x' from t1 b where b.c2<10);
delete from t1 where c1=2 and exists(select 'x' from t1 b where b.c2<10);
--disable_info
select count(*) from v1 where c1=2;
rollback;
--echo #
--echo # Delete throw a view with limit (range access)
--echo #
start transaction;
explain delete from v1 where (select count(*) from t1 b where b.c1=v1.c1) = 500 limit 1;
--enable_info
delete from v1 where (select count(*) from t1 b where b.c1=v1.c1) = 500 limit 1;
delete from v1 where (select count(*) from t1 b where b.c1=v1.c1) = 500 limit 1;
--disable_info
select count(*) from v1 where c1=0;
rollback;
--echo #
--echo # Delete throw a view (ALL access)
--echo #
start transaction;
explain delete from v1 where (select count(*) from t1 b where b.c1=v1.c1) = 500;
--enable_info ONCE
delete from v1 where (select count(*) from t1 b where b.c1=v1.c1) = 500 ;
select count(*) from v1 where c1=0;
rollback;
--echo #
--echo # Delete failed due to trigger
--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;
--error ER_SIGNAL_EXCEPTION
delete from t1 where c1=1 and (select count(*) from t1 b where b.c1=t1.c1) > 0 order by c2 asc limit 10;
rollback;
start transaction;
--error ER_SIGNAL_EXCEPTION
delete from t1 where (select count(*) from t1 b where b.c1=t1.c1) > 0 order by c1 desc limit 100;
select c1,count(*) from t1 group by c1;
rollback;
drop trigger trg;
--echo #
--echo # Delete throw a view with returning
--echo #
start transaction;
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;
start transaction;
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;
drop view v1;
drop table t1;
--echo #
--echo # Delete from table with more than 150000 rows
--echo #
create table t1(c1 integer not null,c2 integer not null, key (c1));
insert t1 select 0,seq from seq_1_to_128000;
insert t1 select 1,seq from seq_1_to_25600;
select count(*) from t1;
--echo # with a lot of memory for sort_buffer_size
set session sort_buffer_size = 1024000;
--enable_info ONCE
delete from t1 where c1=0 and exists(select 'x' from t1 b where b.c1<10);
--echo # with little memory for sort_buffer_size
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 table t1;

View File

@ -74,12 +74,6 @@ 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);
-- error 1443 -- error 1443
delete from v2Aa where col1 = (select max(col1) from v1Aa);
-- error 1443
delete from v2aA where col1 = (select max(col1) from t1Aa);
-- error 1093
delete from v2Aa where col1 = (select max(col1) from v2aA);
-- 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
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;

View File

@ -2764,39 +2764,6 @@ 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));
--error ER_UPDATE_TABLE_USED
delete from m1 where a = (select max(a) from m1);
--error ER_UPDATE_TABLE_USED
delete from m1 where a = (select max(a) from m2);
--error ER_UPDATE_TABLE_USED
delete from m1 where a = (select max(a) from t1);
--error ER_UPDATE_TABLE_USED
delete from m1 where a = (select max(a) from t2);
--error ER_UPDATE_TABLE_USED
delete from m1 where a = (select max(a) from t3, m1);
--error ER_UPDATE_TABLE_USED
delete from m1 where a = (select max(a) from t3, m2);
--error ER_UPDATE_TABLE_USED
delete from m1 where a = (select max(a) from t3, t1);
--error ER_UPDATE_TABLE_USED
delete from m1 where a = (select max(a) from t3, t2);
--error ER_UPDATE_TABLE_USED
delete from m1 where a = (select max(a) from tmp, m1);
--error ER_UPDATE_TABLE_USED
delete from m1 where a = (select max(a) from tmp, m2);
--error ER_UPDATE_TABLE_USED
delete from m1 where a = (select max(a) from tmp, t1);
--error ER_UPDATE_TABLE_USED
delete from m1 where a = (select max(a) from tmp, t2);
--error ER_VIEW_PREVENT_UPDATE
delete from m1 where a = (select max(a) from v1);
--error ER_VIEW_PREVENT_UPDATE
delete from m1 where a = (select max(a) from tmp, v1);
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;

View File

@ -340,12 +340,16 @@ insert into t1 values (0, 10),(1, 11),(2, 12);
insert into t2 values (1, 21),(2, 12),(3, 23); insert into t2 values (1, 21),(2, 12),(3, 23);
select * from t1; select * from t1;
select * from t1 where b = (select b from t2 where t1.a = t2.a); select * from t1 where b = (select b from t2 where t1.a = t2.a);
-- error ER_UPDATE_TABLE_USED # Works since MDEV-12137
# previously : ER_UPDATE_TABLE_USED
--enable_info
delete from t1 where b in (select b from t1); delete from t1 where b in (select b from t1);
--disable_info
insert into t1 values (0, 10),(1, 11),(2, 12);
-- error ER_SUBQUERY_NO_1_ROW -- error ER_SUBQUERY_NO_1_ROW
delete from t1 where b = (select b from t2); delete from t1 where b = (select b from t2);
delete from t1 where b = (select b from t2 where t1.a = t2.a); delete from t1 where b = (select b from t2 where t1.a = t2.a);
select * from t1; select * from t1 order by b;
drop table t1, t2; drop table t1, t2;
#multi-delete with subselects #multi-delete with subselects

View File

@ -915,12 +915,6 @@ 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);
-- error ER_VIEW_PREVENT_UPDATE -- error ER_VIEW_PREVENT_UPDATE
delete from v2 where col1 = (select max(col1) from v1);
-- error ER_VIEW_PREVENT_UPDATE
delete from v2 where col1 = (select max(col1) from t1);
-- error ER_UPDATE_TABLE_USED
delete from v2 where col1 = (select max(col1) from v2);
-- 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
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;

View File

@ -1426,7 +1426,13 @@ Event_job_data::execute(THD *thd, bool drop)
sphead->m_flags|= sp_head::LOG_SLOW_STATEMENTS; sphead->m_flags|= sp_head::LOG_SLOW_STATEMENTS;
sphead->m_flags|= sp_head::LOG_GENERAL_LOG; sphead->m_flags|= sp_head::LOG_GENERAL_LOG;
sphead->set_info(0, 0, &thd->lex->sp_chistics, sql_mode); /*
construct_sp_sql() + parse_sql() set suid to SP_IS_NOT_SUID,
because we have the security context already set to the event
definer here. See more comments in construct_sp_sql().
*/
DBUG_ASSERT(sphead->suid() == SP_IS_NOT_SUID);
sphead->m_sql_mode= sql_mode;
sphead->set_creation_ctx(creation_ctx); sphead->set_creation_ctx(creation_ctx);
sphead->optimize(); sphead->optimize();

View File

@ -818,6 +818,8 @@ public:
{ return store(ls->str, ls->length, cs); } { return store(ls->str, ls->length, cs); }
int store(const LEX_CSTRING *ls, CHARSET_INFO *cs) int store(const LEX_CSTRING *ls, CHARSET_INFO *cs)
{ return store(ls->str, ls->length, cs); } { return store(ls->str, ls->length, cs); }
int store(const LEX_CSTRING &ls, CHARSET_INFO *cs)
{ return store(ls.str, ls.length, cs); }
virtual double val_real(void)=0; virtual double val_real(void)=0;
virtual longlong val_int(void)=0; virtual longlong val_int(void)=0;
virtual bool val_bool(void)= 0; virtual bool val_bool(void)= 0;

View File

@ -1011,13 +1011,6 @@ bool Item_field::check_field_expression_processor(void *arg)
Field *org_field= (Field*) arg; Field *org_field= (Field*) arg;
if (field->flags & NO_DEFAULT_VALUE_FLAG) if (field->flags & NO_DEFAULT_VALUE_FLAG)
return 0; return 0;
if (field->flags & AUTO_INCREMENT_FLAG)
{
my_error(ER_EXPRESSION_REFERS_TO_UNINIT_FIELD,
MYF(0),
org_field->field_name.str, field->field_name.str);
return 1;
}
if ((field->default_value && field->default_value->flags) || field->vcol_info) if ((field->default_value && field->default_value->flags) || field->vcol_info)
{ {
if (field == org_field || if (field == org_field ||

View File

@ -6317,7 +6317,7 @@ Item_func_sp::init_result_field(THD *thd)
bool Item_func_sp::is_expensive() bool Item_func_sp::is_expensive()
{ {
return !m_sp->m_chistics->detistic || return !m_sp->detistic() ||
current_thd->locked_tables_mode < LTM_LOCK_TABLES; current_thd->locked_tables_mode < LTM_LOCK_TABLES;
} }
@ -6391,8 +6391,8 @@ Item_func_sp::execute_impl(THD *thd)
Sub_statement_state statement_state; Sub_statement_state statement_state;
Security_context *save_security_ctx= thd->security_ctx; Security_context *save_security_ctx= thd->security_ctx;
enum enum_sp_data_access access= enum enum_sp_data_access access=
(m_sp->m_chistics->daccess == SP_DEFAULT_ACCESS) ? (m_sp->daccess() == SP_DEFAULT_ACCESS) ?
SP_DEFAULT_ACCESS_MAPPING : m_sp->m_chistics->daccess; SP_DEFAULT_ACCESS_MAPPING : m_sp->daccess();
DBUG_ENTER("Item_func_sp::execute_impl"); DBUG_ENTER("Item_func_sp::execute_impl");
@ -6409,7 +6409,7 @@ Item_func_sp::execute_impl(THD *thd)
statement-based replication (SBR) is active. statement-based replication (SBR) is active.
*/ */
if (!m_sp->m_chistics->detistic && !trust_function_creators && if (!m_sp->detistic() && !trust_function_creators &&
(access == SP_CONTAINS_SQL || access == SP_MODIFIES_SQL_DATA) && (access == SP_CONTAINS_SQL || access == SP_MODIFIES_SQL_DATA) &&
(mysql_bin_log.is_open() && (mysql_bin_log.is_open() &&
thd->variables.binlog_format == BINLOG_FORMAT_STMT)) thd->variables.binlog_format == BINLOG_FORMAT_STMT))
@ -6591,7 +6591,7 @@ Item_func_sp::fix_fields(THD *thd, Item **ref)
#endif /* ! NO_EMBEDDED_ACCESS_CHECKS */ #endif /* ! NO_EMBEDDED_ACCESS_CHECKS */
} }
if (!m_sp->m_chistics->detistic) if (!m_sp->detistic())
{ {
used_tables_cache |= RAND_TABLE_BIT; used_tables_cache |= RAND_TABLE_BIT;
const_item_cache= FALSE; const_item_cache= FALSE;
@ -6605,7 +6605,7 @@ void Item_func_sp::update_used_tables()
{ {
Item_func::update_used_tables(); Item_func::update_used_tables();
if (!m_sp->m_chistics->detistic) if (!m_sp->detistic())
{ {
used_tables_cache |= RAND_TABLE_BIT; used_tables_cache |= RAND_TABLE_BIT;
const_item_cache= FALSE; const_item_cache= FALSE;

View File

@ -487,9 +487,8 @@ db_find_routine_aux(THD *thd, stored_procedure_type type, const sp_name *name,
*/ */
if (name->m_name.length > table->field[1]->field_length) if (name->m_name.length > table->field[1]->field_length)
DBUG_RETURN(SP_KEY_NOT_FOUND); DBUG_RETURN(SP_KEY_NOT_FOUND);
table->field[0]->store(name->m_db.str, name->m_db.length, &my_charset_bin); table->field[0]->store(name->m_db, &my_charset_bin);
table->field[1]->store(name->m_name.str, name->m_name.length, table->field[1]->store(name->m_name, &my_charset_bin);
&my_charset_bin);
table->field[2]->store((longlong) type, TRUE); table->field[2]->store((longlong) type, TRUE);
key_copy(key, table->record[0], table->key_info, key_copy(key, table->record[0], table->key_info,
table->key_info->key_length); table->key_info->key_length);
@ -533,7 +532,7 @@ db_find_routine(THD *thd, stored_procedure_type type, const sp_name *name,
const char *definer; const char *definer;
longlong created; longlong created;
longlong modified; longlong modified;
st_sp_chistics chistics; Sp_chistics chistics;
char *ptr; char *ptr;
uint length; uint length;
char buff[65]; char buff[65];
@ -567,7 +566,6 @@ db_find_routine(THD *thd, stored_procedure_type type, const sp_name *name,
goto done; goto done;
} }
bzero((char *)&chistics, sizeof(chistics));
if ((ptr= get_field(thd->mem_root, if ((ptr= get_field(thd->mem_root,
table->field[MYSQL_PROC_FIELD_ACCESS])) == NULL) table->field[MYSQL_PROC_FIELD_ACCESS])) == NULL)
{ {
@ -849,7 +847,7 @@ db_load_routine(THD *thd, stored_procedure_type type,
params, strlen(params), params, strlen(params),
returns, strlen(returns), returns, strlen(returns),
body, strlen(body), body, strlen(body),
&chistics, definer_user_name, definer_host_name, chistics, definer_user_name, definer_host_name,
sql_mode)) sql_mode))
{ {
ret= SP_INTERNAL_ERROR; ret= SP_INTERNAL_ERROR;
@ -902,7 +900,7 @@ db_load_routine(THD *thd, stored_procedure_type type,
} }
(*sphp)->set_definer(definer_user_name, definer_host_name); (*sphp)->set_definer(definer_user_name, definer_host_name);
(*sphp)->set_info(created, modified, &chistics, sql_mode); (*sphp)->set_info(created, modified, chistics, sql_mode);
(*sphp)->set_creation_ctx(creation_ctx); (*sphp)->set_creation_ctx(creation_ctx);
(*sphp)->optimize(); (*sphp)->optimize();
/* /*
@ -1139,11 +1137,11 @@ sp_create_routine(THD *thd, stored_procedure_type type, sp_head *sp)
store_failed= store_failed=
table->field[MYSQL_PROC_FIELD_DB]-> table->field[MYSQL_PROC_FIELD_DB]->
store(sp->m_db.str, sp->m_db.length, system_charset_info); store(sp->m_db, system_charset_info);
store_failed= store_failed || store_failed= store_failed ||
table->field[MYSQL_PROC_FIELD_NAME]-> table->field[MYSQL_PROC_FIELD_NAME]->
store(sp->m_name.str, sp->m_name.length, system_charset_info); store(sp->m_name, system_charset_info);
store_failed= store_failed || store_failed= store_failed ||
table->field[MYSQL_PROC_MYSQL_TYPE]-> table->field[MYSQL_PROC_MYSQL_TYPE]->
@ -1151,29 +1149,29 @@ sp_create_routine(THD *thd, stored_procedure_type type, sp_head *sp)
store_failed= store_failed || store_failed= store_failed ||
table->field[MYSQL_PROC_FIELD_SPECIFIC_NAME]-> table->field[MYSQL_PROC_FIELD_SPECIFIC_NAME]->
store(sp->m_name.str, sp->m_name.length, system_charset_info); store(sp->m_name, system_charset_info);
if (sp->m_chistics->daccess != SP_DEFAULT_ACCESS) if (sp->daccess() != SP_DEFAULT_ACCESS)
{ {
store_failed= store_failed || store_failed= store_failed ||
table->field[MYSQL_PROC_FIELD_ACCESS]-> table->field[MYSQL_PROC_FIELD_ACCESS]->
store((longlong)sp->m_chistics->daccess, TRUE); store((longlong)sp->daccess(), TRUE);
} }
store_failed= store_failed || store_failed= store_failed ||
table->field[MYSQL_PROC_FIELD_DETERMINISTIC]-> table->field[MYSQL_PROC_FIELD_DETERMINISTIC]->
store((longlong)(sp->m_chistics->detistic ? 1 : 2), TRUE); store((longlong)(sp->detistic() ? 1 : 2), TRUE);
if (sp->m_chistics->suid != SP_IS_DEFAULT_SUID) if (sp->suid() != SP_IS_DEFAULT_SUID)
{ {
store_failed= store_failed || store_failed= store_failed ||
table->field[MYSQL_PROC_FIELD_SECURITY_TYPE]-> table->field[MYSQL_PROC_FIELD_SECURITY_TYPE]->
store((longlong)sp->m_chistics->suid, TRUE); store((longlong)sp->suid(), TRUE);
} }
store_failed= store_failed || store_failed= store_failed ||
table->field[MYSQL_PROC_FIELD_PARAM_LIST]-> table->field[MYSQL_PROC_FIELD_PARAM_LIST]->
store(sp->m_params.str, sp->m_params.length, system_charset_info); store(sp->m_params, system_charset_info);
if (sp->m_type == TYPE_ENUM_FUNCTION) if (sp->m_type == TYPE_ENUM_FUNCTION)
{ {
@ -1186,11 +1184,11 @@ sp_create_routine(THD *thd, stored_procedure_type type, sp_head *sp)
store_failed= store_failed || store_failed= store_failed ||
table->field[MYSQL_PROC_FIELD_BODY]-> table->field[MYSQL_PROC_FIELD_BODY]->
store(sp->m_body.str, sp->m_body.length, system_charset_info); store(sp->m_body, system_charset_info);
store_failed= store_failed || store_failed= store_failed ||
table->field[MYSQL_PROC_FIELD_DEFINER]-> table->field[MYSQL_PROC_FIELD_DEFINER]->
store(definer.str, definer.length, system_charset_info); store(definer, system_charset_info);
((Field_timestamp *)table->field[MYSQL_PROC_FIELD_CREATED])->set_time(); ((Field_timestamp *)table->field[MYSQL_PROC_FIELD_CREATED])->set_time();
((Field_timestamp *)table->field[MYSQL_PROC_FIELD_MODIFIED])->set_time(); ((Field_timestamp *)table->field[MYSQL_PROC_FIELD_MODIFIED])->set_time();
@ -1199,26 +1197,25 @@ sp_create_routine(THD *thd, stored_procedure_type type, sp_head *sp)
table->field[MYSQL_PROC_FIELD_SQL_MODE]-> table->field[MYSQL_PROC_FIELD_SQL_MODE]->
store((longlong)saved_mode, TRUE); store((longlong)saved_mode, TRUE);
if (sp->m_chistics->comment.str) if (sp->comment().str)
{ {
store_failed= store_failed || store_failed= store_failed ||
table->field[MYSQL_PROC_FIELD_COMMENT]-> table->field[MYSQL_PROC_FIELD_COMMENT]->
store(sp->m_chistics->comment.str, sp->m_chistics->comment.length, store(sp->comment(), system_charset_info);
system_charset_info);
} }
if ((sp->m_type == TYPE_ENUM_FUNCTION) && if ((sp->m_type == TYPE_ENUM_FUNCTION) &&
!trust_function_creators && mysql_bin_log.is_open()) !trust_function_creators && mysql_bin_log.is_open())
{ {
if (!sp->m_chistics->detistic) if (!sp->detistic())
{ {
/* /*
Note that this test is not perfect; one could use Note that this test is not perfect; one could use
a non-deterministic read-only function in an update statement. a non-deterministic read-only function in an update statement.
*/ */
enum enum_sp_data_access access= enum enum_sp_data_access access=
(sp->m_chistics->daccess == SP_DEFAULT_ACCESS) ? (sp->daccess() == SP_DEFAULT_ACCESS) ?
SP_DEFAULT_ACCESS_MAPPING : sp->m_chistics->daccess; SP_DEFAULT_ACCESS_MAPPING : sp->daccess();
if (access == SP_CONTAINS_SQL || if (access == SP_CONTAINS_SQL ||
access == SP_MODIFIES_SQL_DATA) access == SP_MODIFIES_SQL_DATA)
{ {
@ -1255,7 +1252,7 @@ sp_create_routine(THD *thd, stored_procedure_type type, sp_head *sp)
table->field[MYSQL_PROC_FIELD_BODY_UTF8]->set_notnull(); table->field[MYSQL_PROC_FIELD_BODY_UTF8]->set_notnull();
store_failed= store_failed || store_failed= store_failed ||
table->field[MYSQL_PROC_FIELD_BODY_UTF8]->store( table->field[MYSQL_PROC_FIELD_BODY_UTF8]->store(
sp->m_body_utf8.str, sp->m_body_utf8.length, system_charset_info); sp->m_body_utf8, system_charset_info);
if (store_failed) if (store_failed)
{ {
@ -1291,7 +1288,7 @@ log:
sp->m_params.str, sp->m_params.length, sp->m_params.str, sp->m_params.length,
retstr.ptr(), retstr.length(), retstr.ptr(), retstr.length(),
sp->m_body.str, sp->m_body.length, sp->m_body.str, sp->m_body.length,
sp->m_chistics, &(thd->lex->definer->user), sp->chistics(), &(thd->lex->definer->user),
&(thd->lex->definer->host), &(thd->lex->definer->host),
saved_mode)) saved_mode))
{ {
@ -1448,8 +1445,7 @@ sp_update_routine(THD *thd, stored_procedure_type type, const sp_name *name,
table->field[MYSQL_PROC_FIELD_ACCESS]-> table->field[MYSQL_PROC_FIELD_ACCESS]->
store((longlong)chistics->daccess, TRUE); store((longlong)chistics->daccess, TRUE);
if (chistics->comment.str) if (chistics->comment.str)
table->field[MYSQL_PROC_FIELD_COMMENT]->store(chistics->comment.str, table->field[MYSQL_PROC_FIELD_COMMENT]->store(chistics->comment,
chistics->comment.length,
system_charset_info); system_charset_info);
if ((ret= table->file->ha_update_row(table->record[1],table->record[0])) && if ((ret= table->file->ha_update_row(table->record[1],table->record[0])) &&
ret != HA_ERR_RECORD_IS_THE_SAME) ret != HA_ERR_RECORD_IS_THE_SAME)
@ -1792,7 +1788,7 @@ sp_find_routine(THD *thd, stored_procedure_type type, const sp_name *name,
} }
if (db_load_routine(thd, type, name, &new_sp, if (db_load_routine(thd, type, name, &new_sp,
sp->m_sql_mode, sp->m_params.str, returns, sp->m_sql_mode, sp->m_params.str, returns,
sp->m_body.str, *sp->m_chistics, sp->m_body.str, sp->chistics(),
&sp->m_definer.user, &sp->m_definer.host, &sp->m_definer.user, &sp->m_definer.host,
sp->m_created, sp->m_modified, sp->m_created, sp->m_modified,
sp->get_creation_ctx()) == SP_OK) sp->get_creation_ctx()) == SP_OK)
@ -2201,7 +2197,7 @@ show_create_sp(THD *thd, String *buf,
const char *params, ulong paramslen, const char *params, ulong paramslen,
const char *returns, ulong returnslen, const char *returns, ulong returnslen,
const char *body, ulong bodylen, const char *body, ulong bodylen,
const st_sp_chistics *chistics, const st_sp_chistics &chistics,
const LEX_CSTRING *definer_user, const LEX_CSTRING *definer_user,
const LEX_CSTRING *definer_host, const LEX_CSTRING *definer_host,
sql_mode_t sql_mode) sql_mode_t sql_mode)
@ -2209,7 +2205,7 @@ show_create_sp(THD *thd, String *buf,
sql_mode_t old_sql_mode= thd->variables.sql_mode; sql_mode_t old_sql_mode= thd->variables.sql_mode;
/* Make some room to begin with */ /* Make some room to begin with */
if (buf->alloc(100 + dblen + 1 + namelen + paramslen + returnslen + bodylen + if (buf->alloc(100 + dblen + 1 + namelen + paramslen + returnslen + bodylen +
chistics->comment.length + 10 /* length of " DEFINER= "*/ + chistics.comment.length + 10 /* length of " DEFINER= "*/ +
USER_HOST_BUFF_SIZE)) USER_HOST_BUFF_SIZE))
return FALSE; return FALSE;
@ -2243,7 +2239,7 @@ show_create_sp(THD *thd, String *buf,
buf->append(returns, returnslen); buf->append(returns, returnslen);
} }
buf->append('\n'); buf->append('\n');
switch (chistics->daccess) { switch (chistics.daccess) {
case SP_NO_SQL: case SP_NO_SQL:
buf->append(STRING_WITH_LEN(" NO SQL\n")); buf->append(STRING_WITH_LEN(" NO SQL\n"));
break; break;
@ -2258,14 +2254,14 @@ show_create_sp(THD *thd, String *buf,
/* Do nothing */ /* Do nothing */
break; break;
} }
if (chistics->detistic) if (chistics.detistic)
buf->append(STRING_WITH_LEN(" DETERMINISTIC\n")); buf->append(STRING_WITH_LEN(" DETERMINISTIC\n"));
if (chistics->suid == SP_IS_NOT_SUID) if (chistics.suid == SP_IS_NOT_SUID)
buf->append(STRING_WITH_LEN(" SQL SECURITY INVOKER\n")); buf->append(STRING_WITH_LEN(" SQL SECURITY INVOKER\n"));
if (chistics->comment.length) if (chistics.comment.length)
{ {
buf->append(STRING_WITH_LEN(" COMMENT ")); buf->append(STRING_WITH_LEN(" COMMENT "));
append_unescaped(buf, chistics->comment.str, chistics->comment.length); append_unescaped(buf, chistics.comment.str, chistics.comment.length);
buf->append('\n'); buf->append('\n');
} }
buf->append(body, bodylen); buf->append(body, bodylen);
@ -2303,7 +2299,6 @@ sp_load_for_information_schema(THD *thd, TABLE *proc_table, String *db,
{ {
const char *sp_body; const char *sp_body;
String defstr; String defstr;
struct st_sp_chistics sp_chistics;
const LEX_CSTRING definer_user= {STRING_WITH_LEN("")}; const LEX_CSTRING definer_user= {STRING_WITH_LEN("")};
const LEX_CSTRING definer_host= {STRING_WITH_LEN("")}; const LEX_CSTRING definer_host= {STRING_WITH_LEN("")};
LEX_CSTRING sp_db_str; LEX_CSTRING sp_db_str;
@ -2326,7 +2321,6 @@ sp_load_for_information_schema(THD *thd, TABLE *proc_table, String *db,
Stored_program_creation_ctx *creation_ctx= Stored_program_creation_ctx *creation_ctx=
Stored_routine_creation_ctx::load_from_db(thd, &sp_name_obj, proc_table); Stored_routine_creation_ctx::load_from_db(thd, &sp_name_obj, proc_table);
sp_body= (type == TYPE_ENUM_FUNCTION ? "RETURN NULL" : "BEGIN END"); sp_body= (type == TYPE_ENUM_FUNCTION ? "RETURN NULL" : "BEGIN END");
bzero((char*) &sp_chistics, sizeof(sp_chistics));
defstr.set_charset(creation_ctx->get_client_cs()); defstr.set_charset(creation_ctx->get_client_cs());
if (!show_create_sp(thd, &defstr, type, if (!show_create_sp(thd, &defstr, type,
sp_db_str.str, sp_db_str.length, sp_db_str.str, sp_db_str.length,
@ -2334,7 +2328,7 @@ sp_load_for_information_schema(THD *thd, TABLE *proc_table, String *db,
params, strlen(params), params, strlen(params),
returns, strlen(returns), returns, strlen(returns),
sp_body, strlen(sp_body), sp_body, strlen(sp_body),
&sp_chistics, &definer_user, &definer_host, sql_mode)) Sp_chistics(), &definer_user, &definer_host, sql_mode))
return 0; return 0;
thd->lex= &newlex; thd->lex= &newlex;

View File

@ -240,7 +240,7 @@ bool show_create_sp(THD *thd, String *buf,
const char *params, ulong paramslen, const char *params, ulong paramslen,
const char *returns, ulong returnslen, const char *returns, ulong returnslen,
const char *body, ulong bodylen, const char *body, ulong bodylen,
const st_sp_chistics *chistics, const st_sp_chistics &chistics,
const LEX_CSTRING *definer_user, const LEX_CSTRING *definer_user,
const LEX_CSTRING *definer_host, const LEX_CSTRING *definer_host,
sql_mode_t sql_mode); sql_mode_t sql_mode);

View File

@ -540,15 +540,32 @@ sp_head::operator delete(void *ptr, size_t size) throw()
} }
sp_head::sp_head() sp_head::sp_head(stored_procedure_type type)
:Query_arena(&main_mem_root, STMT_INITIALIZED_FOR_SP), :Query_arena(&main_mem_root, STMT_INITIALIZED_FOR_SP),
Database_qualified_name(&null_clex_str, &null_clex_str), Database_qualified_name(&null_clex_str, &null_clex_str),
m_type(type),
m_flags(0), m_flags(0),
m_explicit_name(false),
/*
FIXME: the only use case when name is NULL is events, and it should
be rewritten soon. Remove the else part and replace 'if' with
an assert when this is done.
*/
m_qname(null_clex_str),
m_params(null_clex_str),
m_body(null_clex_str),
m_body_utf8(null_clex_str),
m_defstr(null_clex_str),
m_sp_cache_version(0), m_sp_cache_version(0),
m_creation_ctx(0), m_creation_ctx(0),
unsafe_flags(0), unsafe_flags(0),
m_created(0),
m_modified(0),
m_recursion_level(0), m_recursion_level(0),
m_next_cached_sp(0), m_next_cached_sp(0),
m_param_begin(NULL),
m_param_end(NULL),
m_body_begin(NULL),
m_cont_level(0) m_cont_level(0)
{ {
m_first_instance= this; m_first_instance= this;
@ -556,12 +573,6 @@ sp_head::sp_head()
m_last_cached_sp= this; m_last_cached_sp= this;
m_return_field_def.charset = NULL; m_return_field_def.charset = NULL;
/*
FIXME: the only use case when name is NULL is events, and it should
be rewritten soon. Remove the else part and replace 'if' with
an assert when this is done.
*/
m_qname= null_clex_str;
DBUG_ENTER("sp_head::sp_head"); DBUG_ENTER("sp_head::sp_head");
@ -573,9 +584,6 @@ sp_head::sp_head()
my_hash_init(&m_sroutines, system_charset_info, 0, 0, 0, sp_sroutine_key, my_hash_init(&m_sroutines, system_charset_info, 0, 0, 0, sp_sroutine_key,
0, 0); 0, 0);
m_body_utf8.str= NULL;
m_body_utf8.length= 0;
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
@ -597,33 +605,6 @@ sp_head::init(LEX *lex)
lex->trg_table_fields.empty(); lex->trg_table_fields.empty();
my_init_dynamic_array(&m_instr, sizeof(sp_instr *), 16, 8, MYF(0)); my_init_dynamic_array(&m_instr, sizeof(sp_instr *), 16, 8, MYF(0));
m_param_begin= NULL;
m_param_end= NULL;
m_body_begin= NULL ;
m_qname.str= NULL;
m_qname.length= 0;
m_explicit_name= false;
m_db.str= NULL;
m_db.length= 0;
m_name.str= NULL;
m_name.length= 0;
m_params.str= NULL;
m_params.length= 0;
m_body.str= NULL;
m_body.length= 0;
m_defstr.str= NULL;
m_defstr.length= 0;
m_return_field_def.charset= NULL;
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
@ -1429,7 +1410,7 @@ set_routine_security_ctx(THD *thd, sp_head *sp, bool is_proc,
Security_context **save_ctx) Security_context **save_ctx)
{ {
*save_ctx= 0; *save_ctx= 0;
if (sp->m_chistics->suid != SP_IS_NOT_SUID && if (sp->suid() != SP_IS_NOT_SUID &&
sp->m_security_ctx.change_security_context(thd, &sp->m_definer.user, sp->m_security_ctx.change_security_context(thd, &sp->m_definer.user,
&sp->m_definer.host, &sp->m_definer.host,
&sp->m_db, &sp->m_db,
@ -1541,7 +1522,7 @@ sp_head::execute_trigger(THD *thd,
Security_context *save_ctx= NULL; Security_context *save_ctx= NULL;
if (m_chistics->suid != SP_IS_NOT_SUID && if (suid() != SP_IS_NOT_SUID &&
m_security_ctx.change_security_context(thd, m_security_ctx.change_security_context(thd,
&m_definer.user, &m_definer.user,
&m_definer.host, &m_definer.host,
@ -2453,20 +2434,26 @@ sp_head::sp_add_instr_cpush_for_cursors(THD *thd, sp_pcontext *pcontext)
} }
void
sp_head::set_chistics(const st_sp_chistics &chistics)
{
m_chistics.set(chistics);
if (m_chistics.comment.length == 0)
m_chistics.comment.str= 0;
else
m_chistics.comment.str= strmake_root(mem_root,
m_chistics.comment.str,
m_chistics.comment.length);
}
void void
sp_head::set_info(longlong created, longlong modified, sp_head::set_info(longlong created, longlong modified,
const st_sp_chistics *chistics, sql_mode_t sql_mode) const st_sp_chistics &chistics, sql_mode_t sql_mode)
{ {
m_created= created; m_created= created;
m_modified= modified; m_modified= modified;
m_chistics= (st_sp_chistics *) memdup_root(mem_root, (char*) chistics, set_chistics(chistics);
sizeof(*chistics));
if (m_chistics->comment.length == 0)
m_chistics->comment.str= 0;
else
m_chistics->comment.str= strmake_root(mem_root,
m_chistics->comment.str,
m_chistics->comment.length);
m_sql_mode= sql_mode; m_sql_mode= sql_mode;
} }

View File

@ -179,7 +179,15 @@ public:
Column_definition m_return_field_def; /**< This is used for FUNCTIONs only. */ Column_definition m_return_field_def; /**< This is used for FUNCTIONs only. */
const char *m_tmp_query; ///< Temporary pointer to sub query string const char *m_tmp_query; ///< Temporary pointer to sub query string
st_sp_chistics *m_chistics; private:
/*
Private to guarantee that m_chistics.comment is properly set to:
- a string which is alloced on this->mem_root
- or (NULL,0)
set_chistics() makes sure this.
*/
Sp_chistics m_chistics;
public:
sql_mode_t m_sql_mode; ///< For SHOW CREATE and execution sql_mode_t m_sql_mode; ///< For SHOW CREATE and execution
bool m_explicit_name; /**< Prepend the db name? */ bool m_explicit_name; /**< Prepend the db name? */
LEX_CSTRING m_qname; ///< db.name LEX_CSTRING m_qname; ///< db.name
@ -189,6 +197,12 @@ public:
LEX_CSTRING m_defstr; LEX_CSTRING m_defstr;
AUTHID m_definer; AUTHID m_definer;
const st_sp_chistics &chistics() const { return m_chistics; }
const LEX_CSTRING &comment() const { return m_chistics.comment; }
void set_suid(enum_sp_suid_behaviour suid) { m_chistics.suid= suid; }
enum_sp_suid_behaviour suid() const { return m_chistics.suid; }
bool detistic() const { return m_chistics.detistic; }
enum_sp_data_access daccess() const { return m_chistics.daccess; }
/** /**
Is this routine being executed? Is this routine being executed?
*/ */
@ -303,7 +317,7 @@ public:
static void static void
operator delete(void *ptr, size_t size) throw (); operator delete(void *ptr, size_t size) throw ();
sp_head(); sp_head(stored_procedure_type type);
/// Initialize after we have reset mem_root /// Initialize after we have reset mem_root
void void
@ -671,8 +685,9 @@ public:
m_flags|= sp_head::HAS_COLUMN_TYPE_REFS; m_flags|= sp_head::HAS_COLUMN_TYPE_REFS;
} }
void set_chistics(const st_sp_chistics &chistics);
void set_info(longlong created, longlong modified, void set_info(longlong created, longlong modified,
const st_sp_chistics *chistics, sql_mode_t sql_mode); const st_sp_chistics &chistics, sql_mode_t sql_mode);
void set_definer(const char *definer, uint definerlen); void set_definer(const char *definer, uint definerlen);
void set_definer(const LEX_CSTRING *user_name, const LEX_CSTRING *host_name) void set_definer(const LEX_CSTRING *user_name, const LEX_CSTRING *host_name)

View File

@ -45,6 +45,8 @@
// 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 thd->variables.sortbuff_size
/* /*
@brief @brief
Print query plan of a single-table DELETE command Print query plan of a single-table DELETE command
@ -212,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.
@ -244,9 +262,12 @@ 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);
Unique * deltempfile= NULL;
bool delete_record, delete_while_scanning;
DBUG_ENTER("mysql_delete");
query_plan.index= MAX_KEY; query_plan.index= MAX_KEY;
query_plan.using_filesort= FALSE; query_plan.using_filesort= FALSE;
DBUG_ENTER("mysql_delete");
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))
@ -275,7 +296,8 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
query_plan.updating_a_view= MY_TEST(table_list->view); query_plan.updating_a_view= MY_TEST(table_list->view);
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))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
if (with_select) if (with_select)
@ -556,16 +578,48 @@ 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();
while (!(error=info.read_record(&info)) && !thd->killed && if (!delete_while_scanning)
! thd->is_error())
{ {
explain->tracker.on_record_read(); /*
thd->inc_examined_row_count(1); The table we are going to delete appears in subqueries in the where
if (table->vfield) clause. Instead of deleting the rows, first mark them deleted.
(void) table->update_virtual_fields(table->file, VCOL_UPDATE_FOR_DELETE); */
if (!select || select->skip_record(thd) > 0) ha_rows tmplimit=limit;
deltempfile= new (thd->mem_root) Unique (refpos_order_cmp, table->file,
table->file->ref_length,
MEM_STRIP_BUF_SIZE);
while (!(error=info.read_record(&info)) && !thd->killed &&
! thd->is_error())
{
if (record_should_be_deleted(thd, table, select, explain))
{
table->file->position(table->record[0]);
if ((error= deltempfile->unique_add((char*) table->file->ref)))
{
error= 1;
goto terminate_delete;
}
if (!--tmplimit && using_limit)
break;
}
}
end_read_record(&info);
if (deltempfile->get(table) || table->file->ha_index_or_rnd_end() ||
init_read_record(&info, thd, table, 0, &deltempfile->sort, 0, 1, false))
{
error= 1;
goto terminate_delete;
}
delete_record= true;
}
while (!(error=info.read_record(&info)) && !thd->killed &&
! thd->is_error())
{
if (delete_while_scanning)
delete_record= record_should_be_deleted(thd, table, select, explain);
if (delete_record)
{ {
explain->tracker.on_record_after_where();
if (table->triggers && if (table->triggers &&
table->triggers->process_triggers(thd, TRG_EVENT_DELETE, table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
TRG_ACTION_BEFORE, FALSE)) TRG_ACTION_BEFORE, FALSE))
@ -616,6 +670,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
else else
break; break;
} }
terminate_delete:
killed_status= thd->killed; killed_status= thd->killed;
if (killed_status != NOT_KILLED || thd->is_error()) if (killed_status != NOT_KILLED || thd->is_error())
error= 1; // Aborted error= 1; // Aborted
@ -647,6 +702,8 @@ cleanup:
thd->lex->current_select->first_cond_optimization= 0; thd->lex->current_select->first_cond_optimization= 0;
} }
delete deltempfile;
deltempfile=NULL;
delete select; delete select;
select= NULL; select= NULL;
transactional_table= table->file->has_transactions(); transactional_table= table->file->has_transactions();
@ -746,13 +803,15 @@ l
TRUE error TRUE error
*/ */
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,
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,
@ -772,14 +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;
{
update_non_unique_table_error(table_list, "DELETE", duplicate);
DBUG_RETURN(TRUE);
}
}
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))
@ -794,7 +848,6 @@ l
Delete multiple tables from join Delete multiple tables from join
***************************************************************************/ ***************************************************************************/
#define MEM_STRIP_BUF_SIZE current_thd->variables.sortbuff_size
extern "C" int refpos_order_cmp(void* arg, const void *a,const void *b) extern "C" int refpos_order_cmp(void* arg, const void *a,const void *b)
{ {
@ -944,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();
@ -957,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;
} }
} }
@ -993,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;
@ -1006,10 +1059,9 @@ 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);
} }
init_ftfuncs(thd, thd->lex->current_select, 1); init_ftfuncs(thd, thd->lex->current_select, 1);
DBUG_RETURN(thd->is_fatal_error != 0); DBUG_RETURN(thd->is_fatal_error != 0);

View File

@ -27,7 +27,8 @@ typedef class Item COND;
template <typename T> class SQL_I_List; 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,
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);

View File

@ -5825,17 +5825,15 @@ sp_head *LEX::make_sp_head(THD *thd, sp_name *name,
sp_head *sp; sp_head *sp;
/* Order is important here: new - reset - init */ /* Order is important here: new - reset - init */
if ((sp= new sp_head())) if ((sp= new sp_head(type)))
{ {
sp->reset_thd_mem_root(thd); sp->reset_thd_mem_root(thd);
sp->init(this); sp->init(this);
sp->m_type= type;
if (name) if (name)
sp->init_sp_name(thd, name); sp->init_sp_name(thd, name);
sp->m_chistics= &sp_chistics;
sphead= sp; sphead= sp;
} }
bzero(&sp_chistics, sizeof(sp_chistics)); sp_chistics.init();
return sp; return sp;
} }
@ -6125,7 +6123,7 @@ bool LEX::maybe_start_compound_statement(THD *thd)
{ {
if (!make_sp_head(thd, NULL, TYPE_ENUM_PROCEDURE)) if (!make_sp_head(thd, NULL, TYPE_ENUM_PROCEDURE))
return true; return true;
sp_chistics.suid= SP_IS_NOT_SUID; sphead->set_suid(SP_IS_NOT_SUID);
sphead->set_body_start(thd, thd->m_parser_state->m_lip.get_cpp_ptr()); sphead->set_body_start(thd, thd->m_parser_state->m_lip.get_cpp_ptr());
} }
return false; return false;

View File

@ -1285,9 +1285,17 @@ struct st_sp_chistics
enum enum_sp_suid_behaviour suid; enum enum_sp_suid_behaviour suid;
bool detistic; bool detistic;
enum enum_sp_data_access daccess; enum enum_sp_data_access daccess;
void init() { bzero(this, sizeof(*this)); }
void set(const st_sp_chistics &other) { *this= other; }
}; };
class Sp_chistics: public st_sp_chistics
{
public:
Sp_chistics() { init(); }
};
struct st_trg_chistics: public st_trg_execution_order struct st_trg_chistics: public st_trg_execution_order
{ {

View File

@ -2710,7 +2710,7 @@ bool sp_process_definer(THD *thd)
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
if (thd->slave_thread && lex->sphead) if (thd->slave_thread && lex->sphead)
lex->sphead->m_chistics->suid= SP_IS_NOT_SUID; lex->sphead->set_suid(SP_IS_NOT_SUID);
} }
else else
{ {

View File

@ -1496,6 +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;
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) ||
@ -1524,7 +1525,8 @@ static bool mysql_test_delete(Prepared_statement *stmt,
DBUG_RETURN(mysql_prepare_delete(thd, table_list, DBUG_RETURN(mysql_prepare_delete(thd, table_list,
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));
error: error:
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
} }

View File

@ -663,7 +663,7 @@ static void build_trig_stmt_query(THD *thd, TABLE_LIST *tables,
if (lex->create_info.or_replace()) if (lex->create_info.or_replace())
stmt_query->append(STRING_WITH_LEN("OR REPLACE ")); stmt_query->append(STRING_WITH_LEN("OR REPLACE "));
if (lex->sphead->m_chistics->suid != SP_IS_NOT_SUID) if (lex->sphead->suid() != SP_IS_NOT_SUID)
{ {
/* SUID trigger */ /* SUID trigger */
lex->definer->set_lex_string(trg_definer, trg_definer_holder); lex->definer->set_lex_string(trg_definer, trg_definer_holder);
@ -1431,7 +1431,7 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
lex.set_trg_event_type_for_tables(); lex.set_trg_event_type_for_tables();
if (lex.sphead) if (lex.sphead)
lex.sphead->set_info(0, 0, &lex.sp_chistics, sql_mode); lex.sphead->m_sql_mode= sql_mode;
if (unlikely(!(trigger= (new (&table->mem_root) if (unlikely(!(trigger= (new (&table->mem_root)
Trigger(trigger_list, lex.sphead))))) Trigger(trigger_list, lex.sphead)))))
@ -1489,7 +1489,7 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
continue; continue;
} }
sp->set_info(0, 0, &lex.sp_chistics, sql_mode); sp->m_sql_mode= sql_mode;
sp->set_creation_ctx(creation_ctx); sp->set_creation_ctx(creation_ctx);
if (!trg_definer || !trg_definer->length) if (!trg_definer || !trg_definer->length)
@ -1519,7 +1519,7 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
authorization of the invoker. authorization of the invoker.
*/ */
sp->m_chistics->suid= SP_IS_NOT_SUID; sp->set_suid(SP_IS_NOT_SUID);
} }
else else
{ {
@ -1691,7 +1691,7 @@ void Trigger::get_trigger_info(LEX_CSTRING *trigger_stmt,
} }
*trigger_body= body->m_body_utf8; *trigger_body= body->m_body_utf8;
if (body->m_chistics->suid == SP_IS_NOT_SUID) if (body->suid() == SP_IS_NOT_SUID)
{ {
*definer= empty_lex_str; *definer= empty_lex_str;
} }

View File

@ -2951,7 +2951,6 @@ ev_sql_stmt:
TYPE_ENUM_PROCEDURE)) TYPE_ENUM_PROCEDURE))
MYSQL_YYABORT; MYSQL_YYABORT;
lex->sp_chistics.suid= SP_IS_SUID; //always the definer!
lex->sphead->set_body_start(thd, lip->get_cpp_ptr()); lex->sphead->set_body_start(thd, lip->get_cpp_ptr());
} }
sp_proc_stmt sp_proc_stmt
@ -3257,7 +3256,7 @@ row_field_definition_list:
; ;
row_type_body: row_type_body:
'(' row_field_definition_list ')' { $$= $2; } '(' row_field_definition_list ')' { $$= $2; }
; ;
sp_decl_idents_init_vars: sp_decl_idents_init_vars:
@ -7231,7 +7230,7 @@ alter:
if (lex->sphead) if (lex->sphead)
my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "PROCEDURE")); my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "PROCEDURE"));
bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics)); lex->sp_chistics.init();
} }
sp_a_chistics sp_a_chistics
{ {
@ -7246,7 +7245,7 @@ alter:
if (lex->sphead) if (lex->sphead)
my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "FUNCTION")); my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "FUNCTION"));
bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics)); lex->sp_chistics.init();
} }
sp_a_chistics sp_a_chistics
{ {
@ -14549,27 +14548,23 @@ user: user_maybe_role
/* Keyword that we allow for identifiers (except SP labels) */ /* Keyword that we allow for identifiers (except SP labels) */
keyword: keyword:
keyword_sp {} keyword_sp {}
| keyword_sp_verb_clause{}
| ASCII_SYM {} | ASCII_SYM {}
| BACKUP_SYM {} | BACKUP_SYM {}
| BEGIN_SYM {}
| BINLOG_SYM {} | BINLOG_SYM {}
| BYTE_SYM {} | BYTE_SYM {}
| CACHE_SYM {} | CACHE_SYM {}
| CHARSET {} | CHARSET {}
| CHECKSUM_SYM {} | CHECKSUM_SYM {}
| CHECKPOINT_SYM {} | CHECKPOINT_SYM {}
| CLOSE_SYM {}
| COLUMN_ADD_SYM {} | COLUMN_ADD_SYM {}
| COLUMN_CHECK_SYM {} | COLUMN_CHECK_SYM {}
| COLUMN_CREATE_SYM {} | COLUMN_CREATE_SYM {}
| COLUMN_DELETE_SYM {} | COLUMN_DELETE_SYM {}
| COLUMN_GET_SYM {} | COLUMN_GET_SYM {}
| COMMENT_SYM {} | COMMENT_SYM {}
| COMMIT_SYM {}
| CONTAINS_SYM {} | CONTAINS_SYM {}
| DEALLOCATE_SYM {} | DEALLOCATE_SYM {}
| DO_SYM {}
| END {}
| EXAMINED_SYM {} | EXAMINED_SYM {}
| EXCLUDE_SYM {} | EXCLUDE_SYM {}
| EXECUTE_SYM {} | EXECUTE_SYM {}
@ -14578,13 +14573,11 @@ keyword:
| FOLLOWING_SYM {} | FOLLOWING_SYM {}
| FORMAT_SYM {} | FORMAT_SYM {}
| GET_SYM {} | GET_SYM {}
| HANDLER_SYM {}
| HELP_SYM {} | HELP_SYM {}
| HOST_SYM {} | HOST_SYM {}
| INSTALL_SYM {} | INSTALL_SYM {}
| LANGUAGE_SYM {} | LANGUAGE_SYM {}
| NO_SYM {} | NO_SYM {}
| OPEN_SYM {}
| OPTION {} | OPTION {}
| OPTIONS_SYM {} | OPTIONS_SYM {}
| OTHERS_SYM {} | OTHERS_SYM {}
@ -14595,14 +14588,10 @@ keyword:
| PRECEDING_SYM {} | PRECEDING_SYM {}
| PREPARE_SYM {} | PREPARE_SYM {}
| REMOVE_SYM {} | REMOVE_SYM {}
| REPAIR {}
| RESET_SYM {} | RESET_SYM {}
| RESTORE_SYM {} | RESTORE_SYM {}
| ROLLBACK_SYM {}
| SAVEPOINT_SYM {}
| SECURITY_SYM {} | SECURITY_SYM {}
| SERVER_SYM {} | SERVER_SYM {}
| SHUTDOWN {}
| SIGNED_SYM {} | SIGNED_SYM {}
| SOCKET_SYM {} | SOCKET_SYM {}
| SLAVE {} | SLAVE {}
@ -14612,7 +14601,6 @@ keyword:
| STOP_SYM {} | STOP_SYM {}
| STORED_SYM {} | STORED_SYM {}
| TIES_SYM {} | TIES_SYM {}
| TRUNCATE_SYM {}
| UNICODE_SYM {} | UNICODE_SYM {}
| UNINSTALL_SYM {} | UNINSTALL_SYM {}
| UNBOUNDED_SYM {} | UNBOUNDED_SYM {}
@ -14633,6 +14621,29 @@ keyword_sp:
; ;
/*
Keywords that start a statement.
Generally allowed as identifiers (e.g. table, column names)
- not allowed as SP label names
- not allowed as variable names in Oracle-style assignments:
xxx:=10
*/
keyword_sp_verb_clause:
BEGIN_SYM { /* Compound. Reserved in Oracle */ }
| CLOSE_SYM { /* Verb clause. Reserved in Oracle */ }
| COMMIT_SYM { /* Verb clause. Reserved in Oracle */ }
| DO_SYM { /* Verb clause */ }
| END { /* Compound. Reserved in Oracle */ }
| HANDLER_SYM { /* Verb clause */ }
| OPEN_SYM { /* Verb clause. Reserved in Oracle */ }
| REPAIR { /* Verb clause */ }
| ROLLBACK_SYM { /* Verb clause. Reserved in Oracle */ }
| SAVEPOINT_SYM { /* Verb clause. Reserved in Oracle */ }
| SHUTDOWN { /* Verb clause */ }
| TRUNCATE_SYM { /* Verb clause. Reserved in Oracle */ }
;
/* /*
These keywords are generally allowed as identifiers, These keywords are generally allowed as identifiers,
but not allowed as non-delimited SP variable names in sql_mode=ORACLE. but not allowed as non-delimited SP variable names in sql_mode=ORACLE.
@ -14648,6 +14659,7 @@ keyword_sp_data_type:
| FIXED_SYM {} | FIXED_SYM {}
| GEOMETRYCOLLECTION {} | GEOMETRYCOLLECTION {}
| GEOMETRY_SYM {} | GEOMETRY_SYM {}
| JSON_SYM {}
| LINESTRING {} | LINESTRING {}
| MEDIUM_SYM {} | MEDIUM_SYM {}
| MULTILINESTRING {} | MULTILINESTRING {}
@ -14786,7 +14798,6 @@ keyword_sp_not_data_type:
| ISOLATION {} | ISOLATION {}
| ISOPEN_SYM {} | ISOPEN_SYM {}
| ISSUER_SYM {} | ISSUER_SYM {}
| JSON_SYM {}
| INSERT_METHOD {} | INSERT_METHOD {}
| KEY_BLOCK_SIZE {} | KEY_BLOCK_SIZE {}
| LAST_VALUE {} | LAST_VALUE {}
@ -16681,6 +16692,7 @@ sf_tail:
LEX *lex= thd->lex; LEX *lex= thd->lex;
Lex_input_stream *lip= YYLIP; Lex_input_stream *lip= YYLIP;
lex->sphead->set_chistics(lex->sp_chistics);
lex->sphead->set_body_start(thd, lip->get_cpp_tok_start()); lex->sphead->set_body_start(thd, lip->get_cpp_tok_start());
} }
sp_proc_stmt_in_returns_clause sp_proc_stmt_in_returns_clause
@ -16712,6 +16724,7 @@ sp_tail:
sp_parenthesized_pdparam_list sp_parenthesized_pdparam_list
sp_c_chistics sp_c_chistics
{ {
Lex->sphead->set_chistics(Lex->sp_chistics);
Lex->sphead->set_body_start(thd, YYLIP->get_cpp_tok_start()); Lex->sphead->set_body_start(thd, YYLIP->get_cpp_tok_start());
} }
sp_proc_stmt sp_proc_stmt

View File

@ -1096,7 +1096,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
case_stmt_body opt_bin_mod case_stmt_body opt_bin_mod
opt_if_exists_table_element opt_if_not_exists_table_element opt_if_exists_table_element opt_if_not_exists_table_element
opt_recursive opt_recursive
type_or_rowtype
%type <object_ddl_options> %type <object_ddl_options>
create_or_replace create_or_replace
@ -1354,7 +1353,8 @@ END_OF_INPUT
%type <num> view_algorithm view_check_option %type <num> view_algorithm view_check_option
%type <view_suid> view_suid opt_view_suid %type <view_suid> view_suid opt_view_suid
%type <num> sp_decl_idents sp_handler_type sp_hcond_list %type <num> sp_decl_idents sp_decl_idents_init_vars
%type <num> sp_handler_type sp_hcond_list
%type <spcondvalue> sp_cond sp_hcond sqlstate signal_value opt_signal_value %type <spcondvalue> sp_cond sp_hcond sqlstate signal_value opt_signal_value
%type <spblock> sp_decl_body_list opt_sp_decl_body_list %type <spblock> sp_decl_body_list opt_sp_decl_body_list
%type <spblock> sp_decl_non_handler sp_decl_non_handler_list %type <spblock> sp_decl_non_handler sp_decl_non_handler_list
@ -1389,7 +1389,7 @@ END_OF_INPUT
%type <cond_info_list> condition_information; %type <cond_info_list> condition_information;
%type <spvar_definition> row_field_name row_field_definition %type <spvar_definition> row_field_name row_field_definition
%type <spvar_definition_list> row_field_definition_list field_type_row %type <spvar_definition_list> row_field_definition_list row_type_body
%type <NONE> opt_window_clause window_def_list window_def window_spec %type <NONE> opt_window_clause window_def_list window_def window_spec
%type <lex_str_ptr> window_name %type <lex_str_ptr> window_name
@ -2392,7 +2392,6 @@ ev_sql_stmt:
TYPE_ENUM_PROCEDURE)) TYPE_ENUM_PROCEDURE))
MYSQL_YYABORT; MYSQL_YYABORT;
lex->sp_chistics.suid= SP_IS_SUID; //always the definer!
lex->sphead->set_body_start(thd, lip->get_cpp_ptr()); lex->sphead->set_body_start(thd, lip->get_cpp_ptr());
} }
sp_proc_stmt sp_proc_stmt
@ -2549,13 +2548,13 @@ sp_param_name_and_type:
{ {
Lex->sphead->fill_spvar_using_type_reference($$= $1, $2); Lex->sphead->fill_spvar_using_type_reference($$= $1, $2);
} }
| sp_param_name field_type_row | sp_param_name ROW_SYM row_type_body
{ {
$$= $1; $$= $1;
$$->field_def.field_name= $$->name; $$->field_def.field_name= $$->name;
Lex->sphead->fill_spvar_definition(thd, &$$->field_def); Lex->sphead->fill_spvar_definition(thd, &$$->field_def);
Lex->sphead->row_fill_field_definitions(thd, $2); Lex->sphead->row_fill_field_definitions(thd, $3);
$$->field_def.set_row_field_definitions($2); $$->field_def.set_row_field_definitions($3);
} }
; ;
@ -2581,13 +2580,13 @@ sp_pdparam:
{ {
Lex->sphead->fill_spvar_using_type_reference($1, $3); Lex->sphead->fill_spvar_using_type_reference($1, $3);
} }
| sp_param_name sp_opt_inout field_type_row | sp_param_name sp_opt_inout ROW_SYM row_type_body
{ {
$1->mode= $2; $1->mode= $2;
$1->field_def.field_name= $1->name; $1->field_def.field_name= $1->name;
Lex->sphead->fill_spvar_definition(thd, &$1->field_def); Lex->sphead->fill_spvar_definition(thd, &$1->field_def);
Lex->sphead->row_fill_field_definitions(thd, $3); Lex->sphead->row_fill_field_definitions(thd, $4);
$1->field_def.set_row_field_definitions($3); $1->field_def.set_row_field_definitions($4);
} }
; ;
@ -2770,46 +2769,45 @@ row_field_definition_list:
} }
; ;
field_type_row: row_type_body:
ROW_SYM '(' row_field_definition_list ')' { $$= $3; } '(' row_field_definition_list ')' { $$= $2; }
; ;
type_or_rowtype: sp_decl_idents_init_vars:
TYPE_SYM { $$= 0; }
| ROWTYPE_SYM { $$= 1; }
;
sp_decl_non_handler:
sp_decl_idents sp_decl_idents
{ {
Lex->sp_variable_declarations_init(thd, $1); Lex->sp_variable_declarations_init(thd, $1);
} }
;
sp_decl_non_handler:
sp_decl_idents_init_vars
type_with_opt_collate type_with_opt_collate
sp_opt_default sp_opt_default
{ {
if (Lex->sp_variable_declarations_finalize(thd, $1, if (Lex->sp_variable_declarations_finalize(thd, $1,
&Lex->last_field[0], $4)) &Lex->last_field[0], $3))
MYSQL_YYABORT; MYSQL_YYABORT;
$$.init_using_vars($1); $$.init_using_vars($1);
} }
| sp_decl_idents | sp_decl_idents_init_vars
{ optionally_qualified_column_ident '%' TYPE_SYM
Lex->sp_variable_declarations_init(thd, $1);
}
optionally_qualified_column_ident '%' type_or_rowtype
sp_opt_default sp_opt_default
{ {
if ($5 ? if (Lex->sp_variable_declarations_with_ref_finalize(thd, $1, $2, $5))
Lex->sp_variable_declarations_rowtype_finalize(thd, $1, $3, $6) :
Lex->sp_variable_declarations_with_ref_finalize(thd, $1, $3, $6))
MYSQL_YYABORT; MYSQL_YYABORT;
$$.init_using_vars($1); $$.init_using_vars($1);
} }
| sp_decl_idents | sp_decl_idents_init_vars
optionally_qualified_column_ident '%' ROWTYPE_SYM
sp_opt_default
{ {
Lex->sp_variable_declarations_init(thd, $1); if (Lex->sp_variable_declarations_rowtype_finalize(thd, $1, $2, $5))
MYSQL_YYABORT;
$$.init_using_vars($1);
} }
field_type_row | sp_decl_idents_init_vars
ROW_SYM row_type_body
sp_opt_default sp_opt_default
{ {
if (Lex->sp_variable_declarations_row_finalize(thd, $1, $3, $4)) if (Lex->sp_variable_declarations_row_finalize(thd, $1, $3, $4))
@ -4652,9 +4650,11 @@ size_number:
case 'g': case 'g':
case 'G': case 'G':
text_shift_number+=10; text_shift_number+=10;
/* fall through */
case 'm': case 'm':
case 'M': case 'M':
text_shift_number+=10; text_shift_number+=10;
/* fall through */
case 'k': case 'k':
case 'K': case 'K':
text_shift_number+=10; text_shift_number+=10;
@ -7211,7 +7211,7 @@ alter:
if (lex->sphead) if (lex->sphead)
my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "PROCEDURE")); my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "PROCEDURE"));
bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics)); lex->sp_chistics.init();
} }
sp_a_chistics sp_a_chistics
{ {
@ -7226,7 +7226,7 @@ alter:
if (lex->sphead) if (lex->sphead)
my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "FUNCTION")); my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "FUNCTION"));
bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics)); lex->sp_chistics.init();
} }
sp_a_chistics sp_a_chistics
{ {
@ -14796,24 +14796,13 @@ keyword_directly_assignable:
CREATE TRIGGER .. FOR EACH ROW FOLLOWS tr1 a:= 10; CREATE TRIGGER .. FOR EACH ROW FOLLOWS tr1 a:= 10;
*/ */
keyword_directly_not_assignable: keyword_directly_not_assignable:
CONTAINS_SYM { /* SP characteristic */ } CONTAINS_SYM { /* SP characteristic */ }
| LANGUAGE_SYM { /* SP characteristic */ } | LANGUAGE_SYM { /* SP characteristic */ }
| NO_SYM { /* SP characteristic */ } | NO_SYM { /* SP characteristic */ }
| CHARSET { /* SET CHARSET utf8; */ } | CHARSET { /* SET CHARSET utf8; */ }
| DO_SYM { /* Verb clause */ } | FOLLOWS_SYM { /* Conflicts with assignment in FOR EACH */}
| REPAIR { /* Verb clause */ } | PRECEDES_SYM { /* Conflicts with assignment in FOR EACH */}
| HANDLER_SYM { /* Verb clause */ } | keyword_sp_verb_clause { }
| CLOSE_SYM { /* Verb clause. Reserved in Oracle */ }
| OPEN_SYM { /* Verb clause. Reserved in Oracle */ }
| SAVEPOINT_SYM { /* Verb clause. Reserved in Oracle */ }
| TRUNCATE_SYM { /* Verb clause. Reserved in Oracle */ }
| BEGIN_SYM { /* Compound. Reserved in Oracle */ }
| END { /* Compound. Reserved in Oracle */ }
| FOLLOWS_SYM { /* Conflicts with assignment in FOR EACH */}
| PRECEDES_SYM { /* Conflicts with assignment in FOR EACH */}
| COMMIT_SYM { /* Verb clause. Reserved in Oracle */ }
| ROLLBACK_SYM { /* Verb clause. Reserver in Oracle */ }
| SHUTDOWN { /* Verb clause */ }
; ;
/* /*
@ -14828,6 +14817,29 @@ keyword_sp:
; ;
/*
Keywords that start a statement.
Generally allowed as identifiers (e.g. table, column names)
- not allowed as SP label names
- not allowed as variable names in Oracle-style assignments:
xxx:=10
*/
keyword_sp_verb_clause:
BEGIN_SYM { /* Compound. Reserved in Oracle */ }
| CLOSE_SYM { /* Verb clause. Reserved in Oracle */ }
| COMMIT_SYM { /* Verb clause. Reserved in Oracle */ }
| DO_SYM { /* Verb clause */ }
| END { /* Compound. Reserved in Oracle */ }
| HANDLER_SYM { /* Verb clause */ }
| OPEN_SYM { /* Verb clause. Reserved in Oracle */ }
| REPAIR { /* Verb clause */ }
| ROLLBACK_SYM { /* Verb clause. Reserved in Oracle */ }
| SAVEPOINT_SYM { /* Verb clause. Reserved in Oracle */ }
| SHUTDOWN { /* Verb clause */ }
| TRUNCATE_SYM { /* Verb clause. Reserved in Oracle */ }
;
/* /*
These keywords are generally allowed as identifiers, These keywords are generally allowed as identifiers,
but not allowed as non-delimited SP variable names in sql_mode=ORACLE. but not allowed as non-delimited SP variable names in sql_mode=ORACLE.
@ -16919,6 +16931,7 @@ sf_tail:
LEX *lex= thd->lex; LEX *lex= thd->lex;
Lex_input_stream *lip= YYLIP; Lex_input_stream *lip= YYLIP;
lex->sphead->set_chistics(lex->sp_chistics);
lex->sphead->set_body_start(thd, lip->get_cpp_tok_start()); lex->sphead->set_body_start(thd, lip->get_cpp_tok_start());
} }
sp_tail_is sp_tail_is
@ -16953,6 +16966,7 @@ sp_tail:
opt_sp_parenthesized_pdparam_list opt_sp_parenthesized_pdparam_list
sp_c_chistics sp_c_chistics
{ {
Lex->sphead->set_chistics(Lex->sp_chistics);
Lex->sphead->set_body_start(thd, YYLIP->get_cpp_tok_start()); Lex->sphead->set_body_start(thd, YYLIP->get_cpp_tok_start());
} }
sp_tail_is sp_tail_is

View File

@ -2253,7 +2253,7 @@ static int wsrep_create_sp(THD *thd, uchar** buf, size_t* buf_len)
sp->m_params.str, sp->m_params.length, sp->m_params.str, sp->m_params.length,
retstr.c_ptr(), retstr.length(), retstr.c_ptr(), retstr.length(),
sp->m_body.str, sp->m_body.length, sp->m_body.str, sp->m_body.length,
sp->m_chistics, &(thd->lex->definer->user), sp->chistics(), &(thd->lex->definer->user),
&(thd->lex->definer->host), &(thd->lex->definer->host),
saved_mode)) saved_mode))
{ {