Commit 8867a499 authored by Sergei Golubchik's avatar Sergei Golubchik

MDEV-6050 MySQL Bug#13036505 62540: TABLE LOCKS WITHIN STORED FUNCTIONS ARE...

MDEV-6050 MySQL Bug#13036505 62540: TABLE LOCKS WITHIN STORED FUNCTIONS ARE BACK IN 5.5 WITH MIXED AND ROW BI

cherry-pick revno 4053
committer: Gopal Shankar <gopal.shankar@oracle.com>
branch nick: sf_mysql-5.6
timestamp: Fri 2012-07-20 12:25:34 +0530
message:
  Bug#13036505 62540: TABLE LOCKS WITHIN STORED FUNCTIONS ARE BACK IN
                      5.5 WITH MIXED AND ROW BI.
parent de4a3c2a
...@@ -331,13 +331,14 @@ Success: 'update v2 set j= j-10 where j = 3' takes shared row locks on 't1'. ...@@ -331,13 +331,14 @@ Success: 'update v2 set j= j-10 where j = 3' takes shared row locks on 't1'.
# 4.1 SELECT/SET with a stored function which does not # 4.1 SELECT/SET with a stored function which does not
# modify data and uses SELECT in its turn. # modify data and uses SELECT in its turn.
# #
# In theory there is no need to take row locks on the table # There is no need to take row locks on the table
# being selected from in SF as the call to such function # being selected from in SF as the call to such function
# won't get into the binary log. In practice, however, we # won't get into the binary log.
# discover that fact too late in the process to be able to #
# affect the decision what locks should be taken. # However in practice innodb takes strong lock on tables
# Hence, strong locks are taken in this case. # being selected from within SF, when SF is called from
Success: 'select f1()' takes shared row locks on 't1'. # non SELECT statements like 'set' statement below.
Success: 'select f1()' doesn't take row locks on 't1'.
Success: 'set @a:= f1()' takes shared row locks on 't1'. Success: 'set @a:= f1()' takes shared row locks on 't1'.
# #
# 4.2 INSERT (or other statement which modifies data) with # 4.2 INSERT (or other statement which modifies data) with
...@@ -364,13 +365,15 @@ Success: 'set @a:= f2()' takes shared row locks on 't1'. ...@@ -364,13 +365,15 @@ Success: 'set @a:= f2()' takes shared row locks on 't1'.
# modify data and reads a table through subselect # modify data and reads a table through subselect
# in a control construct. # in a control construct.
# #
# Again, in theory a call to this function won't get to the # Call to this function won't get to the
# binary log and thus no locking is needed. But in practice # binary log and thus no locking is needed.
# we don't detect this fact early enough (get_lock_type_for_table()) #
# to avoid taking row locks. # However in practice innodb takes strong lock on tables
Success: 'select f3()' takes shared row locks on 't1'. # being selected from within SF, when SF is called from
# non SELECT statements like 'set' statement below.
Success: 'select f3()' doesn't take row locks on 't1'.
Success: 'set @a:= f3()' takes shared row locks on 't1'. Success: 'set @a:= f3()' takes shared row locks on 't1'.
Success: 'select f4()' takes shared row locks on 't1'. Success: 'select f4()' doesn't take row locks on 't1'.
Success: 'set @a:= f4()' takes shared row locks on 't1'. Success: 'set @a:= f4()' takes shared row locks on 't1'.
# #
# 4.5. INSERT (or other statement which modifies data) with # 4.5. INSERT (or other statement which modifies data) with
...@@ -398,13 +401,15 @@ Success: 'set @a:= f5()' takes shared row locks on 't1'. ...@@ -398,13 +401,15 @@ Success: 'set @a:= f5()' takes shared row locks on 't1'.
# doesn't modify data and reads tables through # doesn't modify data and reads tables through
# a view. # a view.
# #
# Once again, in theory, calls to such functions won't # Calls to such functions won't get into
# get into the binary log and thus don't need row # the binary log and thus don't need row locks.
# locks. But in practice this fact is discovered #
# too late to have any effect. # However in practice innodb takes strong lock on tables
Success: 'select f6()' takes shared row locks on 't1'. # being selected from within SF, when SF is called from
# non SELECT statements like 'set' statement below.
Success: 'select f6()' doesn't take row locks on 't1'.
Success: 'set @a:= f6()' takes shared row locks on 't1'. Success: 'set @a:= f6()' takes shared row locks on 't1'.
Success: 'select f7()' takes shared row locks on 't1'. Success: 'select f7()' doesn't take row locks on 't1'.
Success: 'set @a:= f7()' takes shared row locks on 't1'. Success: 'set @a:= f7()' takes shared row locks on 't1'.
# #
# 4.8 INSERT which uses stored function which # 4.8 INSERT which uses stored function which
...@@ -431,10 +436,9 @@ Success: 'select f9()' takes shared row locks on 't1'. ...@@ -431,10 +436,9 @@ Success: 'select f9()' takes shared row locks on 't1'.
# data and reads a table indirectly, by calling another # data and reads a table indirectly, by calling another
# function. # function.
# #
# In theory, calls to such functions won't get into the binary # Calls to such functions won't get into the binary
# log and thus don't need to acquire row locks. But in practice # log and thus don't need to acquire row locks.
# this fact is discovered too late to have any effect. Success: 'select f10()' doesn't take row locks on 't1'.
Success: 'select f10()' takes shared row locks on 't1'.
# #
# 4.11 INSERT which uses a stored function which doesn't modify # 4.11 INSERT which uses a stored function which doesn't modify
# data and reads a table indirectly, by calling another # data and reads a table indirectly, by calling another
...@@ -494,10 +498,9 @@ Success: 'select f14()' takes shared row locks on 't1'. ...@@ -494,10 +498,9 @@ Success: 'select f14()' takes shared row locks on 't1'.
# 5.3 SELECT that calls a function that doesn't modify data and # 5.3 SELECT that calls a function that doesn't modify data and
# uses a CALL statement that reads a table via SELECT. # uses a CALL statement that reads a table via SELECT.
# #
# In theory, calls to such functions won't get into the binary # Calls to such functions won't get into the binary
# log and thus don't need to acquire row locks. But in practice # log and thus don't need to acquire row locks.
# this fact is discovered too late to have any effect. Success: 'select f15()' doesn't take row locks on 't1'.
Success: 'select f15()' takes shared row locks on 't1'.
# #
# 5.4 INSERT which calls function which doesn't modify data and # 5.4 INSERT which calls function which doesn't modify data and
# uses CALL statement which reads table through SELECT. # uses CALL statement which reads table through SELECT.
......
...@@ -27,6 +27,7 @@ drop table if exists t0, t1, t2, t3, t4, t5; ...@@ -27,6 +27,7 @@ drop table if exists t0, t1, t2, t3, t4, t5;
drop view if exists v1, v2; drop view if exists v1, v2;
drop procedure if exists p1; drop procedure if exists p1;
drop procedure if exists p2; drop procedure if exists p2;
drop procedure if exists p3;
drop function if exists f1; drop function if exists f1;
drop function if exists f2; drop function if exists f2;
drop function if exists f3; drop function if exists f3;
...@@ -42,6 +43,8 @@ drop function if exists f12; ...@@ -42,6 +43,8 @@ drop function if exists f12;
drop function if exists f13; drop function if exists f13;
drop function if exists f14; drop function if exists f14;
drop function if exists f15; drop function if exists f15;
drop function if exists f16;
drop function if exists f17;
create table t1 (i int primary key); create table t1 (i int primary key);
insert into t1 values (1), (2), (3), (4), (5); insert into t1 values (1), (2), (3), (4), (5);
create table t2 (j int primary key); create table t2 (j int primary key);
...@@ -146,6 +149,26 @@ declare k int; ...@@ -146,6 +149,26 @@ declare k int;
call p2(k); call p2(k);
return k; return k;
end| end|
create function f16() returns int
begin
create temporary table if not exists temp1 (a int);
insert into temp1 select * from t1;
drop temporary table temp1;
return 1;
end|
create function f17() returns int
begin
declare j int;
select i from t1 where i = 1 into j;
call p3;
return 1;
end|
create procedure p3()
begin
create temporary table if not exists temp1 (a int);
insert into temp1 select * from t1;
drop temporary table temp1;
end|
create trigger t4_bi before insert on t4 for each row create trigger t4_bi before insert on t4 for each row
begin begin
declare k int; declare k int;
...@@ -185,6 +208,7 @@ end| ...@@ -185,6 +208,7 @@ end|
# once during its execution. # once during its execution.
show create procedure p1; show create procedure p1;
show create procedure p2; show create procedure p2;
show create procedure p3;
show create function f1; show create function f1;
show create function f2; show create function f2;
show create function f3; show create function f3;
...@@ -200,6 +224,8 @@ show create function f12; ...@@ -200,6 +224,8 @@ show create function f12;
show create function f13; show create function f13;
show create function f14; show create function f14;
show create function f15; show create function f15;
show create function f16;
show create function f17;
# Switch back to connection 'default'. # Switch back to connection 'default'.
# #
# 1. Statements that read tables and do not use subqueries. # 1. Statements that read tables and do not use subqueries.
...@@ -359,14 +385,11 @@ Success: 'update v2 set j= j-10 where j = 3' doesn't allow concurrent inserts in ...@@ -359,14 +385,11 @@ Success: 'update v2 set j= j-10 where j = 3' doesn't allow concurrent inserts in
# 4.1 SELECT/SET with a stored function which does not # 4.1 SELECT/SET with a stored function which does not
# modify data and uses SELECT in its turn. # modify data and uses SELECT in its turn.
# #
# In theory there is no need to take strong locks on the table # There is no need to take strong locks on the table
# being selected from in SF as the call to such function # being selected from in SF as the call to such function
# won't get into the binary log. In practice, however, we # won't get into the binary log.
# discover that fact too late in the process to be able to Success: 'select f1()' allows concurrent inserts into 't1'.
# affect the decision what locks should be taken. Success: 'set @a:= f1()' allows concurrent inserts into 't1'.
# Hence, strong locks are taken in this case.
Success: 'select f1()' doesn't allow concurrent inserts into 't1'.
Success: 'set @a:= f1()' doesn't allow concurrent inserts into 't1'.
# #
# 4.2 INSERT (or other statement which modifies data) with # 4.2 INSERT (or other statement which modifies data) with
# a stored function which does not modify data and uses # a stored function which does not modify data and uses
...@@ -392,14 +415,12 @@ Success: 'set @a:= f2()' doesn't allow concurrent inserts into 't1'. ...@@ -392,14 +415,12 @@ Success: 'set @a:= f2()' doesn't allow concurrent inserts into 't1'.
# modify data and reads a table through subselect # modify data and reads a table through subselect
# in a control construct. # in a control construct.
# #
# Again, in theory a call to this function won't get to the # Call to this function won't get to the
# binary log and thus no strong lock is needed. But in practice # binary log and thus no strong lock is needed.
# we don't detect this fact early enough (get_lock_type_for_table()) Success: 'select f3()' allows concurrent inserts into 't1'.
# to avoid taking a strong lock. Success: 'set @a:= f3()' allows concurrent inserts into 't1'.
Success: 'select f3()' doesn't allow concurrent inserts into 't1'. Success: 'select f4()' allows concurrent inserts into 't1'.
Success: 'set @a:= f3()' doesn't allow concurrent inserts into 't1'. Success: 'set @a:= f4()' allows concurrent inserts into 't1'.
Success: 'select f4()' doesn't allow concurrent inserts into 't1'.
Success: 'set @a:= f4()' doesn't allow concurrent inserts into 't1'.
# #
# 4.5. INSERT (or other statement which modifies data) with # 4.5. INSERT (or other statement which modifies data) with
# a stored function which does not modify data and reads # a stored function which does not modify data and reads
...@@ -426,14 +447,13 @@ Success: 'set @a:= f5()' doesn't allow concurrent inserts into 't1'. ...@@ -426,14 +447,13 @@ Success: 'set @a:= f5()' doesn't allow concurrent inserts into 't1'.
# doesn't modify data and reads tables through # doesn't modify data and reads tables through
# a view. # a view.
# #
# Once again, in theory, calls to such functions won't # Calls to such functions won't get into
# get into the binary log and thus don't need strong # the binary log and thus don't need strong
# locks. But in practice this fact is discovered # locks.
# too late to have any effect. Success: 'select f6()' allows concurrent inserts into 't1'.
Success: 'select f6()' doesn't allow concurrent inserts into 't1'. Success: 'set @a:= f6()' allows concurrent inserts into 't1'.
Success: 'set @a:= f6()' doesn't allow concurrent inserts into 't1'. Success: 'select f7()' allows concurrent inserts into 't1'.
Success: 'select f7()' doesn't allow concurrent inserts into 't1'. Success: 'set @a:= f7()' allows concurrent inserts into 't1'.
Success: 'set @a:= f7()' doesn't allow concurrent inserts into 't1'.
# #
# 4.8 INSERT which uses stored function which # 4.8 INSERT which uses stored function which
# doesn't modify data and reads a table # doesn't modify data and reads a table
...@@ -459,10 +479,9 @@ Success: 'select f9()' doesn't allow concurrent inserts into 't1'. ...@@ -459,10 +479,9 @@ Success: 'select f9()' doesn't allow concurrent inserts into 't1'.
# data and reads a table indirectly, by calling another # data and reads a table indirectly, by calling another
# function. # function.
# #
# In theory, calls to such functions won't get into the binary # Calls to such functions won't get into the binary
# log and thus don't need to acquire strong locks. But in practice # log and thus don't need to acquire strong locks.
# this fact is discovered too late to have any effect. Success: 'select f10()' allows concurrent inserts into 't1'.
Success: 'select f10()' doesn't allow concurrent inserts into 't1'.
# #
# 4.11 INSERT which uses a stored function which doesn't modify # 4.11 INSERT which uses a stored function which doesn't modify
# data and reads a table indirectly, by calling another # data and reads a table indirectly, by calling another
...@@ -501,6 +520,26 @@ Success: 'select f12((select i+10 from t1 where i=1))' allows concurrent inserts ...@@ -501,6 +520,26 @@ Success: 'select f12((select i+10 from t1 where i=1))' allows concurrent inserts
# uses. Therefore it should take strong locks on the data it reads. # uses. Therefore it should take strong locks on the data it reads.
Success: 'insert into t2 values (f13((select i+10 from t1 where i=1)))' doesn't allow concurrent inserts into 't1'. Success: 'insert into t2 values (f13((select i+10 from t1 where i=1)))' doesn't allow concurrent inserts into 't1'.
# #
# 4.15 SELECT/SET with a stored function which
# inserts data into a temporary table using
# SELECT on t1.
#
# Since this statement is written to the binary log it should
# be serialized with concurrent statements affecting the data it
# uses. Therefore it should take strong locks on the data it reads.
Success: 'select f16()' doesn't allow concurrent inserts into 't1'.
Success: 'set @a:= f16()' doesn't allow concurrent inserts into 't1'.
#
# 4.16 SELECT/SET with a stored function which call procedure
# which inserts data into a temporary table using
# SELECT on t1.
#
# Since this statement is written to the binary log it should
# be serialized with concurrent statements affecting the data it
# uses. Therefore it should take strong locks on the data it reads.
Success: 'select f17()' doesn't allow concurrent inserts into 't1'.
Success: 'set @a:= f17()' doesn't allow concurrent inserts into 't1'.
#
# 5. Statements that read tables through stored procedures. # 5. Statements that read tables through stored procedures.
# #
# #
...@@ -522,10 +561,9 @@ Success: 'select f14()' doesn't allow concurrent inserts into 't1'. ...@@ -522,10 +561,9 @@ Success: 'select f14()' doesn't allow concurrent inserts into 't1'.
# 5.3 SELECT that calls a function that doesn't modify data and # 5.3 SELECT that calls a function that doesn't modify data and
# uses a CALL statement that reads a table via SELECT. # uses a CALL statement that reads a table via SELECT.
# #
# In theory, calls to such functions won't get into the binary # Calls to such functions won't get into the binary
# log and thus don't need to acquire strong locks. But in practice # log and thus don't need to acquire strong locks.
# this fact is discovered too late to have any effect. Success: 'select f15()' allows concurrent inserts into 't1'.
Success: 'select f15()' doesn't allow concurrent inserts into 't1'.
# #
# 5.4 INSERT which calls function which doesn't modify data and # 5.4 INSERT which calls function which doesn't modify data and
# uses CALL statement which reads table through SELECT. # uses CALL statement which reads table through SELECT.
...@@ -585,9 +623,12 @@ drop function f12; ...@@ -585,9 +623,12 @@ drop function f12;
drop function f13; drop function f13;
drop function f14; drop function f14;
drop function f15; drop function f15;
drop function f16;
drop function f17;
drop view v1, v2; drop view v1, v2;
drop procedure p1; drop procedure p1;
drop procedure p2; drop procedure p2;
drop procedure p3;
drop table t1, t2, t3, t4, t5; drop table t1, t2, t3, t4, t5;
set @@global.concurrent_insert= @old_concurrent_insert; set @@global.concurrent_insert= @old_concurrent_insert;
# #
......
...@@ -440,15 +440,16 @@ let $wait_statement= $statement; ...@@ -440,15 +440,16 @@ let $wait_statement= $statement;
--echo # 4.1 SELECT/SET with a stored function which does not --echo # 4.1 SELECT/SET with a stored function which does not
--echo # modify data and uses SELECT in its turn. --echo # modify data and uses SELECT in its turn.
--echo # --echo #
--echo # In theory there is no need to take row locks on the table --echo # There is no need to take row locks on the table
--echo # being selected from in SF as the call to such function --echo # being selected from in SF as the call to such function
--echo # won't get into the binary log. In practice, however, we --echo # won't get into the binary log.
--echo # discover that fact too late in the process to be able to --echo #
--echo # affect the decision what locks should be taken. --echo # However in practice innodb takes strong lock on tables
--echo # Hence, strong locks are taken in this case. --echo # being selected from within SF, when SF is called from
--echo # non SELECT statements like 'set' statement below.
let $statement= select f1(); let $statement= select f1();
let $wait_statement= select i from t1 where i = 1 into j; let $wait_statement= select i from t1 where i = 1 into j;
--source include/check_shared_row_lock.inc --source include/check_no_row_lock.inc
let $statement= set @a:= f1(); let $statement= set @a:= f1();
let $wait_statement= select i from t1 where i = 1 into j; let $wait_statement= select i from t1 where i = 1 into j;
--source include/check_shared_row_lock.inc --source include/check_shared_row_lock.inc
...@@ -486,19 +487,21 @@ let $wait_statement= select i from t1 where i = 1 into k; ...@@ -486,19 +487,21 @@ let $wait_statement= select i from t1 where i = 1 into k;
--echo # modify data and reads a table through subselect --echo # modify data and reads a table through subselect
--echo # in a control construct. --echo # in a control construct.
--echo # --echo #
--echo # Again, in theory a call to this function won't get to the --echo # Call to this function won't get to the
--echo # binary log and thus no locking is needed. But in practice --echo # binary log and thus no locking is needed.
--echo # we don't detect this fact early enough (get_lock_type_for_table()) --echo #
--echo # to avoid taking row locks. --echo # However in practice innodb takes strong lock on tables
--echo # being selected from within SF, when SF is called from
--echo # non SELECT statements like 'set' statement below.
let $statement= select f3(); let $statement= select f3();
let $wait_statement= $statement; let $wait_statement= $statement;
--source include/check_shared_row_lock.inc --source include/check_no_row_lock.inc
let $statement= set @a:= f3(); let $statement= set @a:= f3();
let $wait_statement= $statement; let $wait_statement= $statement;
--source include/check_shared_row_lock.inc --source include/check_shared_row_lock.inc
let $statement= select f4(); let $statement= select f4();
let $wait_statement= $statement; let $wait_statement= $statement;
--source include/check_shared_row_lock.inc --source include/check_no_row_lock.inc
let $statement= set @a:= f4(); let $statement= set @a:= f4();
let $wait_statement= $statement; let $wait_statement= $statement;
--source include/check_shared_row_lock.inc --source include/check_shared_row_lock.inc
...@@ -539,19 +542,21 @@ let $wait_statement= insert into t2 values ((select i from t1 where i = 1) + 5); ...@@ -539,19 +542,21 @@ let $wait_statement= insert into t2 values ((select i from t1 where i = 1) + 5);
--echo # doesn't modify data and reads tables through --echo # doesn't modify data and reads tables through
--echo # a view. --echo # a view.
--echo # --echo #
--echo # Once again, in theory, calls to such functions won't --echo # Calls to such functions won't get into
--echo # get into the binary log and thus don't need row --echo # the binary log and thus don't need row locks.
--echo # locks. But in practice this fact is discovered --echo #
--echo # too late to have any effect. --echo # However in practice innodb takes strong lock on tables
--echo # being selected from within SF, when SF is called from
--echo # non SELECT statements like 'set' statement below.
let $statement= select f6(); let $statement= select f6();
let $wait_statement= select i from v1 where i = 1 into k; let $wait_statement= select i from v1 where i = 1 into k;
--source include/check_shared_row_lock.inc --source include/check_no_row_lock.inc
let $statement= set @a:= f6(); let $statement= set @a:= f6();
let $wait_statement= select i from v1 where i = 1 into k; let $wait_statement= select i from v1 where i = 1 into k;
--source include/check_shared_row_lock.inc --source include/check_shared_row_lock.inc
let $statement= select f7(); let $statement= select f7();
let $wait_statement= select j from v2 where j = 1 into k; let $wait_statement= select j from v2 where j = 1 into k;
--source include/check_shared_row_lock.inc --source include/check_no_row_lock.inc
let $statement= set @a:= f7(); let $statement= set @a:= f7();
let $wait_statement= select j from v2 where j = 1 into k; let $wait_statement= select j from v2 where j = 1 into k;
--source include/check_shared_row_lock.inc --source include/check_shared_row_lock.inc
...@@ -592,12 +597,11 @@ let $wait_statement= update v2 set j=j+10 where j=1; ...@@ -592,12 +597,11 @@ let $wait_statement= update v2 set j=j+10 where j=1;
--echo # data and reads a table indirectly, by calling another --echo # data and reads a table indirectly, by calling another
--echo # function. --echo # function.
--echo # --echo #
--echo # In theory, calls to such functions won't get into the binary --echo # Calls to such functions won't get into the binary
--echo # log and thus don't need to acquire row locks. But in practice --echo # log and thus don't need to acquire row locks.
--echo # this fact is discovered too late to have any effect.
let $statement= select f10(); let $statement= select f10();
let $wait_statement= select i from t1 where i = 1 into j; let $wait_statement= select i from t1 where i = 1 into j;
--source include/check_shared_row_lock.inc --source include/check_no_row_lock.inc
--echo # --echo #
--echo # 4.11 INSERT which uses a stored function which doesn't modify --echo # 4.11 INSERT which uses a stored function which doesn't modify
...@@ -676,12 +680,11 @@ let $wait_statement= select i from t1 where i = 1 into p; ...@@ -676,12 +680,11 @@ let $wait_statement= select i from t1 where i = 1 into p;
--echo # 5.3 SELECT that calls a function that doesn't modify data and --echo # 5.3 SELECT that calls a function that doesn't modify data and
--echo # uses a CALL statement that reads a table via SELECT. --echo # uses a CALL statement that reads a table via SELECT.
--echo # --echo #
--echo # In theory, calls to such functions won't get into the binary --echo # Calls to such functions won't get into the binary
--echo # log and thus don't need to acquire row locks. But in practice --echo # log and thus don't need to acquire row locks.
--echo # this fact is discovered too late to have any effect.
let $statement= select f15(); let $statement= select f15();
let $wait_statement= select i from t1 where i = 1 into p; let $wait_statement= select i from t1 where i = 1 into p;
--source include/check_shared_row_lock.inc --source include/check_no_row_lock.inc
--echo # --echo #
--echo # 5.4 INSERT which calls function which doesn't modify data and --echo # 5.4 INSERT which calls function which doesn't modify data and
......
...@@ -49,6 +49,7 @@ drop table if exists t0, t1, t2, t3, t4, t5; ...@@ -49,6 +49,7 @@ drop table if exists t0, t1, t2, t3, t4, t5;
drop view if exists v1, v2; drop view if exists v1, v2;
drop procedure if exists p1; drop procedure if exists p1;
drop procedure if exists p2; drop procedure if exists p2;
drop procedure if exists p3;
drop function if exists f1; drop function if exists f1;
drop function if exists f2; drop function if exists f2;
drop function if exists f3; drop function if exists f3;
...@@ -64,6 +65,8 @@ drop function if exists f12; ...@@ -64,6 +65,8 @@ drop function if exists f12;
drop function if exists f13; drop function if exists f13;
drop function if exists f14; drop function if exists f14;
drop function if exists f15; drop function if exists f15;
drop function if exists f16;
drop function if exists f17;
--enable_warnings --enable_warnings
create table t1 (i int primary key); create table t1 (i int primary key);
insert into t1 values (1), (2), (3), (4), (5); insert into t1 values (1), (2), (3), (4), (5);
...@@ -170,6 +173,26 @@ begin ...@@ -170,6 +173,26 @@ begin
call p2(k); call p2(k);
return k; return k;
end| end|
create function f16() returns int
begin
create temporary table if not exists temp1 (a int);
insert into temp1 select * from t1;
drop temporary table temp1;
return 1;
end|
create function f17() returns int
begin
declare j int;
select i from t1 where i = 1 into j;
call p3;
return 1;
end|
create procedure p3()
begin
create temporary table if not exists temp1 (a int);
insert into temp1 select * from t1;
drop temporary table temp1;
end|
create trigger t4_bi before insert on t4 for each row create trigger t4_bi before insert on t4 for each row
begin begin
declare k int; declare k int;
...@@ -217,6 +240,7 @@ connection con1; ...@@ -217,6 +240,7 @@ connection con1;
--disable_result_log --disable_result_log
show create procedure p1; show create procedure p1;
show create procedure p2; show create procedure p2;
show create procedure p3;
show create function f1; show create function f1;
show create function f2; show create function f2;
show create function f3; show create function f3;
...@@ -232,6 +256,8 @@ show create function f12; ...@@ -232,6 +256,8 @@ show create function f12;
show create function f13; show create function f13;
show create function f14; show create function f14;
show create function f15; show create function f15;
show create function f16;
show create function f17;
--enable_result_log --enable_result_log
--echo # Switch back to connection 'default'. --echo # Switch back to connection 'default'.
connection default; connection default;
...@@ -492,18 +518,15 @@ let $restore_table= t2; ...@@ -492,18 +518,15 @@ let $restore_table= t2;
--echo # 4.1 SELECT/SET with a stored function which does not --echo # 4.1 SELECT/SET with a stored function which does not
--echo # modify data and uses SELECT in its turn. --echo # modify data and uses SELECT in its turn.
--echo # --echo #
--echo # In theory there is no need to take strong locks on the table --echo # There is no need to take strong locks on the table
--echo # being selected from in SF as the call to such function --echo # being selected from in SF as the call to such function
--echo # won't get into the binary log. In practice, however, we --echo # won't get into the binary log.
--echo # discover that fact too late in the process to be able to
--echo # affect the decision what locks should be taken.
--echo # Hence, strong locks are taken in this case.
let $statement= select f1(); let $statement= select f1();
let $restore_table= ; let $restore_table= ;
--source include/check_no_concurrent_insert.inc --source include/check_concurrent_insert.inc
let $statement= set @a:= f1(); let $statement= set @a:= f1();
let $restore_table= ; let $restore_table= ;
--source include/check_no_concurrent_insert.inc --source include/check_concurrent_insert.inc
--echo # --echo #
--echo # 4.2 INSERT (or other statement which modifies data) with --echo # 4.2 INSERT (or other statement which modifies data) with
...@@ -538,22 +561,20 @@ let $restore_table= t2; ...@@ -538,22 +561,20 @@ let $restore_table= t2;
--echo # modify data and reads a table through subselect --echo # modify data and reads a table through subselect
--echo # in a control construct. --echo # in a control construct.
--echo # --echo #
--echo # Again, in theory a call to this function won't get to the --echo # Call to this function won't get to the
--echo # binary log and thus no strong lock is needed. But in practice --echo # binary log and thus no strong lock is needed.
--echo # we don't detect this fact early enough (get_lock_type_for_table())
--echo # to avoid taking a strong lock.
let $statement= select f3(); let $statement= select f3();
let $restore_table= ; let $restore_table= ;
--source include/check_no_concurrent_insert.inc --source include/check_concurrent_insert.inc
let $statement= set @a:= f3(); let $statement= set @a:= f3();
let $restore_table= ; let $restore_table= ;
--source include/check_no_concurrent_insert.inc --source include/check_concurrent_insert.inc
let $statement= select f4(); let $statement= select f4();
let $restore_table= ; let $restore_table= ;
--source include/check_no_concurrent_insert.inc --source include/check_concurrent_insert.inc
let $statement= set @a:= f4(); let $statement= set @a:= f4();
let $restore_table= ; let $restore_table= ;
--source include/check_no_concurrent_insert.inc --source include/check_concurrent_insert.inc
--echo # --echo #
--echo # 4.5. INSERT (or other statement which modifies data) with --echo # 4.5. INSERT (or other statement which modifies data) with
...@@ -591,22 +612,21 @@ let $restore_table= t2; ...@@ -591,22 +612,21 @@ let $restore_table= t2;
--echo # doesn't modify data and reads tables through --echo # doesn't modify data and reads tables through
--echo # a view. --echo # a view.
--echo # --echo #
--echo # Once again, in theory, calls to such functions won't --echo # Calls to such functions won't get into
--echo # get into the binary log and thus don't need strong --echo # the binary log and thus don't need strong
--echo # locks. But in practice this fact is discovered --echo # locks.
--echo # too late to have any effect.
let $statement= select f6(); let $statement= select f6();
let $restore_table= t2; let $restore_table= t2;
--source include/check_no_concurrent_insert.inc --source include/check_concurrent_insert.inc
let $statement= set @a:= f6(); let $statement= set @a:= f6();
let $restore_table= t2; let $restore_table= t2;
--source include/check_no_concurrent_insert.inc --source include/check_concurrent_insert.inc
let $statement= select f7(); let $statement= select f7();
let $restore_table= t2; let $restore_table= t2;
--source include/check_no_concurrent_insert.inc --source include/check_concurrent_insert.inc
let $statement= set @a:= f7(); let $statement= set @a:= f7();
let $restore_table= t2; let $restore_table= t2;
--source include/check_no_concurrent_insert.inc --source include/check_concurrent_insert.inc
--echo # --echo #
--echo # 4.8 INSERT which uses stored function which --echo # 4.8 INSERT which uses stored function which
...@@ -644,12 +664,11 @@ let $restore_table= t2; ...@@ -644,12 +664,11 @@ let $restore_table= t2;
--echo # data and reads a table indirectly, by calling another --echo # data and reads a table indirectly, by calling another
--echo # function. --echo # function.
--echo # --echo #
--echo # In theory, calls to such functions won't get into the binary --echo # Calls to such functions won't get into the binary
--echo # log and thus don't need to acquire strong locks. But in practice --echo # log and thus don't need to acquire strong locks.
--echo # this fact is discovered too late to have any effect.
let $statement= select f10(); let $statement= select f10();
let $restore_table= ; let $restore_table= ;
--source include/check_no_concurrent_insert.inc --source include/check_concurrent_insert.inc
--echo # --echo #
--echo # 4.11 INSERT which uses a stored function which doesn't modify --echo # 4.11 INSERT which uses a stored function which doesn't modify
...@@ -700,6 +719,36 @@ let $statement= insert into t2 values (f13((select i+10 from t1 where i=1))); ...@@ -700,6 +719,36 @@ let $statement= insert into t2 values (f13((select i+10 from t1 where i=1)));
let $restore_table= t2; let $restore_table= t2;
--source include/check_no_concurrent_insert.inc --source include/check_no_concurrent_insert.inc
--echo #
--echo # 4.15 SELECT/SET with a stored function which
--echo # inserts data into a temporary table using
--echo # SELECT on t1.
--echo #
--echo # Since this statement is written to the binary log it should
--echo # be serialized with concurrent statements affecting the data it
--echo # uses. Therefore it should take strong locks on the data it reads.
let $statement= select f16();
let $restore_table= ;
--source include/check_no_concurrent_insert.inc
let $statement= set @a:= f16();
let $restore_table= ;
--source include/check_no_concurrent_insert.inc
--echo #
--echo # 4.16 SELECT/SET with a stored function which call procedure
--echo # which inserts data into a temporary table using
--echo # SELECT on t1.
--echo #
--echo # Since this statement is written to the binary log it should
--echo # be serialized with concurrent statements affecting the data it
--echo # uses. Therefore it should take strong locks on the data it reads.
let $statement= select f17();
let $restore_table= ;
--source include/check_no_concurrent_insert.inc
let $statement= set @a:= f17();
let $restore_table= ;
--source include/check_no_concurrent_insert.inc
--echo # --echo #
--echo # 5. Statements that read tables through stored procedures. --echo # 5. Statements that read tables through stored procedures.
...@@ -730,12 +779,11 @@ let $restore_table= t2; ...@@ -730,12 +779,11 @@ let $restore_table= t2;
--echo # 5.3 SELECT that calls a function that doesn't modify data and --echo # 5.3 SELECT that calls a function that doesn't modify data and
--echo # uses a CALL statement that reads a table via SELECT. --echo # uses a CALL statement that reads a table via SELECT.
--echo # --echo #
--echo # In theory, calls to such functions won't get into the binary --echo # Calls to such functions won't get into the binary
--echo # log and thus don't need to acquire strong locks. But in practice --echo # log and thus don't need to acquire strong locks.
--echo # this fact is discovered too late to have any effect.
let $statement= select f15(); let $statement= select f15();
let $restore_table= ; let $restore_table= ;
--source include/check_no_concurrent_insert.inc --source include/check_concurrent_insert.inc
--echo # --echo #
--echo # 5.4 INSERT which calls function which doesn't modify data and --echo # 5.4 INSERT which calls function which doesn't modify data and
...@@ -800,7 +848,6 @@ let $statement= update t5 set l= 2 where l = 1; ...@@ -800,7 +848,6 @@ let $statement= update t5 set l= 2 where l = 1;
let $restore_table= t5; let $restore_table= t5;
--source include/check_no_concurrent_insert.inc --source include/check_no_concurrent_insert.inc
--echo # Clean-up. --echo # Clean-up.
drop function f1; drop function f1;
drop function f2; drop function f2;
...@@ -817,9 +864,12 @@ drop function f12; ...@@ -817,9 +864,12 @@ drop function f12;
drop function f13; drop function f13;
drop function f14; drop function f14;
drop function f15; drop function f15;
drop function f16;
drop function f17;
drop view v1, v2; drop view v1, v2;
drop procedure p1; drop procedure p1;
drop procedure p2; drop procedure p2;
drop procedure p3;
drop table t1, t2, t3, t4, t5; drop table t1, t2, t3, t4, t5;
disconnect con1; disconnect con1;
......
...@@ -2323,6 +2323,11 @@ sp_head::restore_lex(THD *thd) ...@@ -2323,6 +2323,11 @@ sp_head::restore_lex(THD *thd)
*/ */
if (sp_update_sp_used_routines(&m_sroutines, &sublex->sroutines)) if (sp_update_sp_used_routines(&m_sroutines, &sublex->sroutines))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
/* If this substatement is a update query, then mark MODIFIES_DATA */
if (is_update_query(sublex->sql_command))
m_flags|= MODIFIES_DATA;
/* /*
Merge tables used by this statement (but not by its functions or Merge tables used by this statement (but not by its functions or
procedures) to multiset of tables used by this routine. procedures) to multiset of tables used by this routine.
......
...@@ -161,7 +161,21 @@ class sp_head :private Query_arena ...@@ -161,7 +161,21 @@ class sp_head :private Query_arena
LOG_SLOW_STATEMENTS= 256, // Used by events LOG_SLOW_STATEMENTS= 256, // Used by events
LOG_GENERAL_LOG= 512, // Used by events LOG_GENERAL_LOG= 512, // Used by events
HAS_SQLCOM_RESET= 1024, HAS_SQLCOM_RESET= 1024,
HAS_SQLCOM_FLUSH= 2048 HAS_SQLCOM_FLUSH= 2048,
/**
Marks routines that directly (i.e. not by calling other routines)
change tables. Note that this flag is set automatically based on
type of statements used in the stored routine and is different
from routine characteristic provided by user in a form of CONTAINS
SQL, READS SQL DATA, MODIFIES SQL DATA clauses. The latter are
accepted by parser but pretty much ignored after that.
We don't rely on them:
a) for compatibility reasons.
b) because in CONTAINS SQL case they don't provide enough
information anyway.
*/
MODIFIES_DATA= 4096
}; };
stored_procedure_type m_type; stored_procedure_type m_type;
...@@ -332,11 +346,17 @@ class sp_head :private Query_arena ...@@ -332,11 +346,17 @@ class sp_head :private Query_arena
int int
add_instr(sp_instr *instr); add_instr(sp_instr *instr);
inline uint /**
instructions() Returns true if any substatement in the routine directly
{ (not through another routine) modifies data/changes table.
return m_instr.elements;
} @sa Comment for MODIFIES_DATA flag.
*/
bool modifies_data() const
{ return m_flags & MODIFIES_DATA; }
inline uint instructions()
{ return m_instr.elements; }
inline sp_instr * inline sp_instr *
last_instruction() last_instruction()
......
...@@ -3520,6 +3520,9 @@ Open_table_context::recover_from_failed_open() ...@@ -3520,6 +3520,9 @@ Open_table_context::recover_from_failed_open()
@param thd Thread context @param thd Thread context
@param prelocking_ctx Prelocking context. @param prelocking_ctx Prelocking context.
@param table_list Table list element for table to be locked. @param table_list Table list element for table to be locked.
@param routine_modifies_data
Some routine that is invoked by statement
modifies data.
@remark Due to a statement-based replication limitation, statements such as @remark Due to a statement-based replication limitation, statements such as
INSERT INTO .. SELECT FROM .. and CREATE TABLE .. SELECT FROM need INSERT INTO .. SELECT FROM .. and CREATE TABLE .. SELECT FROM need
...@@ -3532,9 +3535,13 @@ Open_table_context::recover_from_failed_open() ...@@ -3532,9 +3535,13 @@ Open_table_context::recover_from_failed_open()
This also applies to SELECT/SET/DO statements which use stored This also applies to SELECT/SET/DO statements which use stored
functions. Calls to such functions are going to be logged as a functions. Calls to such functions are going to be logged as a
whole and thus should be serialized against concurrent changes whole and thus should be serialized against concurrent changes
to tables used by those functions. This can be avoided if functions to tables used by those functions. This is avoided when functions
only read data but doing so requires more complex analysis than it do not modify data but only read it, since in this case nothing is
is done now. written to the binary log. Argument routine_modifies_data
denotes the same. So effectively, if the statement is not a
update query and routine_modifies_data is false, then
prelocking_placeholder does not take importance.
Furthermore, this does not apply to I_S and log tables as it's Furthermore, this does not apply to I_S and log tables as it's
always unsafe to replicate such tables under statement-based always unsafe to replicate such tables under statement-based
replication as the table on the slave might contain other data replication as the table on the slave might contain other data
...@@ -3549,7 +3556,8 @@ Open_table_context::recover_from_failed_open() ...@@ -3549,7 +3556,8 @@ Open_table_context::recover_from_failed_open()
thr_lock_type read_lock_type_for_table(THD *thd, thr_lock_type read_lock_type_for_table(THD *thd,
Query_tables_list *prelocking_ctx, Query_tables_list *prelocking_ctx,
TABLE_LIST *table_list) TABLE_LIST *table_list,
bool routine_modifies_data)
{ {
/* /*
In cases when this function is called for a sub-statement executed in In cases when this function is called for a sub-statement executed in
...@@ -3564,7 +3572,7 @@ thr_lock_type read_lock_type_for_table(THD *thd, ...@@ -3564,7 +3572,7 @@ thr_lock_type read_lock_type_for_table(THD *thd,
(table_list->table->s->table_category == TABLE_CATEGORY_LOG) || (table_list->table->s->table_category == TABLE_CATEGORY_LOG) ||
(table_list->table->s->table_category == TABLE_CATEGORY_PERFORMANCE) || (table_list->table->s->table_category == TABLE_CATEGORY_PERFORMANCE) ||
!(is_update_query(prelocking_ctx->sql_command) || !(is_update_query(prelocking_ctx->sql_command) ||
table_list->prelocking_placeholder || (routine_modifies_data && table_list->prelocking_placeholder) ||
(thd->locked_tables_mode > LTM_LOCK_TABLES))) (thd->locked_tables_mode > LTM_LOCK_TABLES)))
return TL_READ; return TL_READ;
else else
...@@ -3590,6 +3598,8 @@ thr_lock_type read_lock_type_for_table(THD *thd, ...@@ -3590,6 +3598,8 @@ thr_lock_type read_lock_type_for_table(THD *thd,
@param[out] need_prelocking Set to TRUE if it was detected that this @param[out] need_prelocking Set to TRUE if it was detected that this
statement will require prelocked mode for statement will require prelocked mode for
its execution, not touched otherwise. its execution, not touched otherwise.
@param[out] routine_modifies_data Set to TRUE if it was detected that this
routine does modify table data.
@retval FALSE Success. @retval FALSE Success.
@retval TRUE Failure (Conflicting metadata lock, OOM, other errors). @retval TRUE Failure (Conflicting metadata lock, OOM, other errors).
...@@ -3601,11 +3611,13 @@ open_and_process_routine(THD *thd, Query_tables_list *prelocking_ctx, ...@@ -3601,11 +3611,13 @@ open_and_process_routine(THD *thd, Query_tables_list *prelocking_ctx,
Prelocking_strategy *prelocking_strategy, Prelocking_strategy *prelocking_strategy,
bool has_prelocking_list, bool has_prelocking_list,
Open_table_context *ot_ctx, Open_table_context *ot_ctx,
bool *need_prelocking) bool *need_prelocking, bool *routine_modifies_data)
{ {
MDL_key::enum_mdl_namespace mdl_type= rt->mdl_request.key.mdl_namespace(); MDL_key::enum_mdl_namespace mdl_type= rt->mdl_request.key.mdl_namespace();
DBUG_ENTER("open_and_process_routine"); DBUG_ENTER("open_and_process_routine");
*routine_modifies_data= false;
switch (mdl_type) switch (mdl_type)
{ {
case MDL_key::FUNCTION: case MDL_key::FUNCTION:
...@@ -3658,8 +3670,11 @@ open_and_process_routine(THD *thd, Query_tables_list *prelocking_ctx, ...@@ -3658,8 +3670,11 @@ open_and_process_routine(THD *thd, Query_tables_list *prelocking_ctx,
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
/* 'sp' is NULL when there is no such routine. */ /* 'sp' is NULL when there is no such routine. */
if (sp && !has_prelocking_list) if (sp)
{ {
*routine_modifies_data= sp->modifies_data();
if (!has_prelocking_list)
prelocking_strategy->handle_routine(thd, prelocking_ctx, rt, sp, prelocking_strategy->handle_routine(thd, prelocking_ctx, rt, sp,
need_prelocking); need_prelocking);
} }
...@@ -4006,16 +4021,7 @@ open_and_process_table(THD *thd, LEX *lex, TABLE_LIST *tables, ...@@ -4006,16 +4021,7 @@ open_and_process_table(THD *thd, LEX *lex, TABLE_LIST *tables,
goto end; goto end;
} }
if (tables->lock_type != TL_UNLOCK && ! thd->locked_tables_mode) /* Copy grant information from TABLE_LIST instance to TABLE one. */
{
if (tables->lock_type == TL_WRITE_DEFAULT)
tables->table->reginfo.lock_type= thd->update_lock_default;
else if (tables->lock_type == TL_READ_DEFAULT)
tables->table->reginfo.lock_type=
read_lock_type_for_table(thd, lex, tables);
else
tables->table->reginfo.lock_type= tables->lock_type;
}
tables->table->grant= tables->grant; tables->table->grant= tables->grant;
/* Check and update metadata version of a base table. */ /* Check and update metadata version of a base table. */
...@@ -4354,6 +4360,7 @@ bool open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags, ...@@ -4354,6 +4360,7 @@ bool open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags,
Open_table_context ot_ctx(thd, flags); Open_table_context ot_ctx(thd, flags);
bool error= FALSE; bool error= FALSE;
MEM_ROOT new_frm_mem; MEM_ROOT new_frm_mem;
bool some_routine_modifies_data= FALSE;
bool has_prelocking_list; bool has_prelocking_list;
DBUG_ENTER("open_tables"); DBUG_ENTER("open_tables");
...@@ -4526,11 +4533,16 @@ bool open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags, ...@@ -4526,11 +4533,16 @@ bool open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags,
sroutine_to_open= &rt->next, rt= rt->next) sroutine_to_open= &rt->next, rt= rt->next)
{ {
bool need_prelocking= false; bool need_prelocking= false;
bool routine_modifies_data;
TABLE_LIST **save_query_tables_last= thd->lex->query_tables_last; TABLE_LIST **save_query_tables_last= thd->lex->query_tables_last;
error= open_and_process_routine(thd, thd->lex, rt, prelocking_strategy, error= open_and_process_routine(thd, thd->lex, rt, prelocking_strategy,
has_prelocking_list, &ot_ctx, has_prelocking_list, &ot_ctx,
&need_prelocking); &need_prelocking,
&routine_modifies_data);
// Remember if any of SF modifies data.
some_routine_modifies_data|= routine_modifies_data;
if (need_prelocking && ! thd->lex->requires_prelocking()) if (need_prelocking && ! thd->lex->requires_prelocking())
thd->lex->mark_as_requiring_prelocking(save_query_tables_last); thd->lex->mark_as_requiring_prelocking(save_query_tables_last);
...@@ -4570,6 +4582,10 @@ bool open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags, ...@@ -4570,6 +4582,10 @@ bool open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags,
children, attach the children to their parents. At end of statement, children, attach the children to their parents. At end of statement,
the children are detached. Attaching and detaching are always done, the children are detached. Attaching and detaching are always done,
even under LOCK TABLES. even under LOCK TABLES.
We also convert all TL_WRITE_DEFAULT and TL_READ_DEFAULT locks to
appropriate "real" lock types to be used for locking and to be passed
to storage engine.
*/ */
for (tables= *start; tables; tables= tables->next_global) for (tables= *start; tables; tables= tables->next_global)
{ {
...@@ -4586,6 +4602,19 @@ bool open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags, ...@@ -4586,6 +4602,19 @@ bool open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags,
goto err; goto err;
} }
} }
/* Set appropriate TABLE::lock_type. */
if (tbl && tables->lock_type != TL_UNLOCK && !thd->locked_tables_mode)
{
if (tables->lock_type == TL_WRITE_DEFAULT)
tbl->reginfo.lock_type= thd->update_lock_default;
else if (tables->lock_type == TL_READ_DEFAULT)
tbl->reginfo.lock_type=
read_lock_type_for_table(thd, thd->lex, tables,
some_routine_modifies_data);
else
tbl->reginfo.lock_type= tables->lock_type;
}
} }
err: err:
...@@ -4847,11 +4876,15 @@ static bool check_lock_and_start_stmt(THD *thd, ...@@ -4847,11 +4876,15 @@ static bool check_lock_and_start_stmt(THD *thd,
engine is important as, for example, InnoDB uses it to determine engine is important as, for example, InnoDB uses it to determine
what kind of row locks should be acquired when executing statement what kind of row locks should be acquired when executing statement
in prelocked mode or under LOCK TABLES with @@innodb_table_locks = 0. in prelocked mode or under LOCK TABLES with @@innodb_table_locks = 0.
Last argument routine_modifies_data for read_lock_type_for_table()
is ignored, as prelocking placeholder will never be set here.
*/ */
DBUG_ASSERT(table_list->prelocking_placeholder == false);
if (table_list->lock_type == TL_WRITE_DEFAULT) if (table_list->lock_type == TL_WRITE_DEFAULT)
lock_type= thd->update_lock_default; lock_type= thd->update_lock_default;
else if (table_list->lock_type == TL_READ_DEFAULT) else if (table_list->lock_type == TL_READ_DEFAULT)
lock_type= read_lock_type_for_table(thd, prelocking_ctx, table_list); lock_type= read_lock_type_for_table(thd, prelocking_ctx, table_list, true);
else else
lock_type= table_list->lock_type; lock_type= table_list->lock_type;
......
...@@ -136,7 +136,8 @@ TABLE *find_write_locked_table(TABLE *list, const char *db, ...@@ -136,7 +136,8 @@ TABLE *find_write_locked_table(TABLE *list, const char *db,
const char *table_name); const char *table_name);
thr_lock_type read_lock_type_for_table(THD *thd, thr_lock_type read_lock_type_for_table(THD *thd,
Query_tables_list *prelocking_ctx, Query_tables_list *prelocking_ctx,
TABLE_LIST *table_list); TABLE_LIST *table_list,
bool routine_modifies_data);
my_bool mysql_rm_tmp_tables(void); my_bool mysql_rm_tmp_tables(void);
bool rm_temporary_table(handlerton *base, const char *path); bool rm_temporary_table(handlerton *base, const char *path);
......
...@@ -1431,11 +1431,15 @@ int mysql_multi_update_prepare(THD *thd) ...@@ -1431,11 +1431,15 @@ int mysql_multi_update_prepare(THD *thd)
another table instance used by this statement which is going to another table instance used by this statement which is going to
be write-locked (for example, trigger to be invoked might try be write-locked (for example, trigger to be invoked might try
to update this table). to update this table).
Last argument routine_modifies_data for read_lock_type_for_table()
is ignored, as prelocking placeholder will never be set here.
*/ */
DBUG_ASSERT(tl->prelocking_placeholder == false);
thr_lock_type lock_type= read_lock_type_for_table(thd, lex, tl, true);
if (using_lock_tables) if (using_lock_tables)
tl->lock_type= read_lock_type_for_table(thd, lex, tl); tl->lock_type= lock_type;
else else
tl->set_lock_type(thd, read_lock_type_for_table(thd, lex, tl)); tl->set_lock_type(thd, lock_type);
tl->updating= 0; tl->updating= 0;
} }
} }
......
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