📄 sp.test
字号:
--error ER_SP_NO_RECURSIONselect f5(2)|--error ER_SP_NO_RECURSIONselect f5(3)|# OTOH this should work create function f6() returns intbegin declare n int; set n:= f1(); return (select count(*) from t1 where data <= f7() and data <= n);end|create function f7() returns int return (select sum(data) from t1 where data <= f1())|select f6()|select id, f6() from t1|## Let us test how new locking work with views## The most trivial viewcreate view v1 (a) as select f1()|select * from v1|select id, a from t1, v1|select * from v1, v1 as v|# A bit more complex constructioncreate view v2 (a) as select a*10 from v1|select * from v2|select id, a from t1, v2|select * from v1, v2|# Nice example where the same view is used on# on different expression levelscreate function f8 () returns int return (select count(*) from v2)|select *, f8() from v1|# Let us test what will happen if function is missingdrop function f1|--error 1356select * from v1|# And what will happen if we have recursion which involves# views and functions ?create function f1() returns int return (select sum(data) from t1) + (select sum(data) from v1)|--error ER_SP_NO_RECURSIONselect f1()|--error ER_SP_NO_RECURSIONselect * from v1|--error ER_SP_NO_RECURSIONselect * from v2|# Back to the normal casesdrop function f1|create function f1() returns int return (select sum(data) from t1)|# Let us also test some weird cases where no real tables is usedcreate function f0() returns int return (select * from (select 100) as r)|select f0()|select *, f0() from (select 1) as t|create view v0 as select f0()|select * from v0|select *, f0() from v0|## Let us test how well prelocking works with explicit LOCK TABLES.#lock tables t1 read, t1 as t11 read|# These should work wellselect f3()|select id, f3() from t1 as t11|# Degenerate cases work too :)select f0()|select * from v0|select *, f0() from v0, (select 123) as d1|# But these should not !--error 1100select id, f3() from t1|--error 1100select f4()|unlock tables|# Let us test how LOCK TABLES which implicitly depends on functions# workslock tables v2 read, mysql.proc read|select * from v2|select * from v1|# These should not work as we have too little instances of tables locked--error 1100select * from v1, t1|--error 1100select f4()|unlock tables|# Tests for handling of temporary tables in functions.## Unlike for permanent tables we should be able to create, use# and drop such tables in functions.# # Simplest function using temporary table. It is also test case for bug # #12198 "Temporary table aliasing does not work inside stored functions"create function f9() returns intbegin declare a, b int; drop temporary table if exists t3; create temporary table t3 (id int); insert into t3 values (1), (2), (3); set a:= (select count(*) from t3); set b:= (select count(*) from t3 t3_alias); return a + b;end|# This will emit warning as t3 was not existing before.select f9()|select f9() from t1 limit 1|# Function which uses both temporary and permanent tables.create function f10() returns intbegin drop temporary table if exists t3; create temporary table t3 (id int); insert into t3 select id from t4; return (select count(*) from t3);end|# Check that we don't ignore completely tables used in function--error ER_NO_SUCH_TABLEselect f10()|create table t4 as select 1 as id|select f10()|# Practical cases which we don't handle well (yet)## Function which does not work because of well-known and documented# limitation of MySQL. We can't use the several instances of the# same temporary table in statement.create function f11() returns intbegin drop temporary table if exists t3; create temporary table t3 (id int); insert into t3 values (1), (2), (3); return (select count(*) from t3 as a, t3 as b);end|--error ER_CANT_REOPEN_TABLEselect f11()|--error ER_CANT_REOPEN_TABLEselect f11() from t1|# We don't handle temporary tables used by nested functions wellcreate function f12_1() returns intbegin drop temporary table if exists t3; create temporary table t3 (id int); insert into t3 values (1), (2), (3); return f12_2();end|create function f12_2() returns int return (select count(*) from t3)|# We need clean start to get errordrop temporary table t3|--error ER_NO_SUCH_TABLEselect f12_1()|--error ER_NO_SUCH_TABLEselect f12_1() from t1 limit 1|# Cleanupdrop function f0|drop function f1|drop function f2|drop function f3|drop function f4|drop function f5|drop function f6|drop function f7|drop function f8|drop function f9|drop function f10|drop function f11|drop function f12_1|drop function f12_2|drop view v0|drop view v1|drop view v2|delete from t1 |delete from t2 |drop table t4|# End of non-bug tests## Some "real" examples## fac--disable_warningsdrop table if exists t3|--enable_warningscreate table t3 (n int unsigned not null primary key, f bigint unsigned)|--disable_warningsdrop procedure if exists ifac|--enable_warningscreate procedure ifac(n int unsigned)begin declare i int unsigned default 1; if n > 20 then set n = 20; # bigint overflow otherwise end if; while i <= n do begin insert into test.t3 values (i, fac(i)); set i = i + 1; end; end while;end|call ifac(20)|select * from t3|drop table t3|--replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'show function status like '%f%'|drop procedure ifac|drop function fac|--replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'show function status like '%f%'|# primes--disable_warningsdrop table if exists t3|--enable_warningscreate table t3 ( i int unsigned not null primary key, p bigint unsigned not null)|insert into t3 values ( 0, 3), ( 1, 5), ( 2, 7), ( 3, 11), ( 4, 13), ( 5, 17), ( 6, 19), ( 7, 23), ( 8, 29), ( 9, 31), (10, 37), (11, 41), (12, 43), (13, 47), (14, 53), (15, 59), (16, 61), (17, 67), (18, 71), (19, 73), (20, 79), (21, 83), (22, 89), (23, 97), (24, 101), (25, 103), (26, 107), (27, 109), (28, 113), (29, 127), (30, 131), (31, 137), (32, 139), (33, 149), (34, 151), (35, 157), (36, 163), (37, 167), (38, 173), (39, 179), (40, 181), (41, 191), (42, 193), (43, 197), (44, 199)|--disable_warningsdrop procedure if exists opp|--enable_warningscreate procedure opp(n bigint unsigned, out pp bool)begin declare r double; declare b, s bigint unsigned default 0; set r = sqrt(n); again: loop if s = 45 then set b = b+200, s = 0; else begin declare p bigint unsigned; select t.p into p from test.t3 t where t.i = s; if b+p > r then set pp = 1; leave again; end if; if mod(n, b+p) = 0 then set pp = 0; leave again; end if; set s = s+1; end; end if; end loop;end|--disable_warningsdrop procedure if exists ip|--enable_warningscreate procedure ip(m int unsigned)begin declare p bigint unsigned; declare i int unsigned; set i=45, p=201; while i < m do begin declare pp bool default 0; call opp(p, pp); if pp then insert into test.t3 values (i, p); set i = i+1; end if; set p = p+2; end; end while;end|show create procedure opp|--replace_column 4 'root@localhost' 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'show procedure status like '%p%'|# This isn't the fastest way in the world to compute prime numbers, so# don't be too ambitious. ;-)call ip(200)|# We don't want to select the entire table here, just pick a few# examples.# The expected result is:# i p# --- ----# 45 211# 100 557# 199 1229select * from t3 where i=45 or i=100 or i=199|drop table t3|drop procedure opp|drop procedure ip|--replace_column 4 'root@localhost' 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'show procedure status like '%p%'|# Fibonacci, for recursion test. (Yet Another Numerical series :)#--disable_warningsdrop table if exists t3|--enable_warningscreate table t3 ( f bigint unsigned not null )|# We deliberately do it the awkward way, fetching the last two# values from the table, in order to exercise various statements# and table accesses at each turn.--disable_warningsdrop procedure if exists fib|--enable_warningscreate procedure fib(n int unsigned)begin if n > 1 then begin declare x, y bigint unsigned; declare c cursor for select f from t3 order by f desc limit 2; open c; fetch c into y; fetch c into x; close c; insert into t3 values (x+y); call fib(n-1); end; end if;end|# Enable recursionset @@max_sp_recursion_depth= 20|# Minimum test: recursion of 3 levelsinsert into t3 values (0), (1)|call fib(3)|select * from t3 order by f asc|delete from t3|# The original test, 20 levels, ran into memory limits on some machines# and builds. Try 10 instead...insert into t3 values (0), (1)|call fib(10)|select * from t3 order by f asc|drop table t3|drop procedure fib|set @@max_sp_recursion_depth= 0|## Comment & suid#--disable_warningsdrop procedure if exists bar|--enable_warningscreate procedure bar(x char(16), y int) comment "111111111111" sql security invoker insert into test.t1 values (x, y)|--replace_column 4 'root@localhost' 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'show procedure status like 'bar'|alter procedure bar comment "2222222222" sql security definer|alter procedure bar comment "3333333333"|alter procedure bar|show create procedure bar|--replace_column 4 'root@localhost' 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'show procedure status like 'bar'|drop procedure bar|## rexecution#--disable_warningsdrop procedure if exists p1|--enable_warningscreate procedure p1 () select (select s1 from t3) from t3|create table t3 (s1 int)|call p1()|insert into t3 values (1)|call p1()|drop procedure p1|drop table t3|## backticks#--disable_warningsdrop function if exists foo|--enable_warningscreate function `foo` () returns int return 5|select `foo` ()|drop function `foo`|## Implicit LOCK/UNLOCK TABLES for table access in functions#--disable_warningsdrop function if exists t1max|--enable_warningscreate function t1max() returns intbegin declare x int; select max(data) into x from t1; return x;end|insert into t1 values ("foo", 3), ("bar", 2), ("zip", 5), ("zap", 1)|select t1max()|drop function t1max|create table t3 ( v char(16) not null primary key, c int unsigned not null)|create function getcount(s char(16)) returns intbegin declare x int; select count(*) into x from t3 where v = s; if x = 0 then insert into t3 values (s, 1); else update t3 set c = c+1 where v = s; end if; return x;end|select * from t1 where data = getcount("bar")|select * from t3|select getcount("zip")|select getcount("zip")|select * from t3|select getcount(id) from t1 where data = 3|select getcount(id) from t1 where data = 5|select * from t3|drop table t3|drop function getcount|# Test cases for different combinations of condition handlers in nested# begin-end blocks in stored procedures.## Note that the standard specifies that the most specific handler should# be triggered even if it's an outer handler masked by a less specific# handler in an inner block.# Note also that '02000' is more specific than NOT FOUND; there might be# other '02xxx' states, even if we currently do not issue them in any# situation (e.g. '02001').## The combinations we test are these:## Inner# errcode sqlstate not found sqlwarning sqlexception# Outer +------------+------------+------------+------------+------------+#errcode | h_ee (i) | h_es (o) | h_en (o) | h_ew (o) | h_ex (o) |#sqlstate | h_se (i) | h_ss (i) | h_sn (o) | h_sw (o) | h_sx (o) |#not found | h_ne (i) | h_ns (i) | h_nn (i) | | |#sqlwarning | h_we (i) | h_ws (i) | | h_ww (i) | |#sqlexception | h_xe (i) | h_xs (i) | | | h_xx (i) |# +------------+---------------------------------------------------+## (i) means that the inner handler is the one that should be invoked,# (o) means that the outer handler should be invoked.## ('not found', 'sqlwarning' and 'sqlexception' are mutually exclusive, hence# no tests for those combinations.)#--disable_warningsdrop table if exists t3|drop procedure if exists h_ee|drop procedure if exists h_es|drop procedure if exists h_en|drop procedure if exists h_ew|drop procedure if exists h_ex|drop procedure if exists h_se|drop procedure if exists h_ss|drop procedure if exists h_sn|drop procedure if exists h_sw|drop procedure if exists h_sx|drop procedure if exists h_ne|drop procedure if exists h_ns|drop procedure if exists h_nn|drop procedure if exists h_we|drop procedure if exists h_ws|drop procedure if exists h_ww|drop procedure if exists h_xe|drop procedure if exists h_xs|drop procedure if exists h_xx|--enable_warnings# smallint - to get out of range warnings# primary key - to get constraint errorscreate table t3 (a smallint primary key)|insert into t3 (a) values (1)|create procedure h_ee() deterministicbegin declare continue handler for 1062 -- ER_DUP_ENTRY select 'Outer (bad)' as 'h_ee'; begin declare continue handler for 1062 -- ER_DUP_ENTRY select 'Inner (good)' as 'h_ee'; insert into t3 values (1); end;end|create procedure h_es() deterministicbegin declare continue handler for 1062 -- ER_DUP_ENTRY select 'Outer (good)' as 'h_es'; begin -- integrity constraint violation declare continue handler for sqlstate '23000' select 'Inner (bad)' as 'h_es'; insert into t3 values (1); end;end|create procedure h_en() deterministicbegin declare continue handler for 1329 -- ER_SP_FETCH_NO_DATA select 'Outer (good)' as 'h_en'; begin declare x int; declare continue handler for sqlstate '02000' -- no data select 'Inner (bad)' as 'h_en'; select a into x from t3 where a = 42; end;end|create procedure h_ew() deterministicbegin declare continue handler for 1264 -- ER_WARN_DATA_OUT_OF_RANGE select 'Outer (good)' as 'h_ew'; begin declare continue handler for sqlwarning select 'Inner (bad)' as 'h_ew'; insert into t3 values (123456789012); end; delete from t3; insert into t3 values (1);end|create procedure h_ex() deterministicbegin declare continue handler for 1062 -- ER_DUP_ENTRY select 'Outer (good)' as 'h_ex'; begin declare continue handler for sqlexception select 'Inner (bad)' as 'h_ex'; insert into t3 values (1); end;end|
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -