Skip to content

Commit b99e11c

Browse files
author
konstantin@mysql.com
committed
A fix and a test case for Bug#17843 "Certain stored procedures fail to
run at startup" The server returned an error when trying to execute init-file with a stored procedure that could return multiple result sets to the client. A stored procedure can return multiple result sets if it contains PREPARE, SELECT, SHOW and similar statements. The fix is to set client_capabilites|=CLIENT_MULTI_RESULTS in sql_parse.cc:handle_bootstrap(). There is no "client" really, so nothing is ever sent. This makes init-file feature behave consistently: the prepared statements that can be called directly in the init-file can be used in a stored procedure too. Re-committed the patch originally submitted by Per-Erik after review.
1 parent e87278f commit b99e11c

File tree

8 files changed

+383
-8
lines changed

8 files changed

+383
-8
lines changed

mysql-test/Makefile.am

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -101,15 +101,15 @@ uninstall-local:
101101
@RM@ -f -r $(DESTDIR)$(testdir)
102102

103103
std_data/client-key.pem: $(top_srcdir)/SSL/$(@F)
104-
@CP@ $(top_srcdir)/SSL/$(@F) $(srcdir)/std_data
104+
@CP@ -f $(top_srcdir)/SSL/$(@F) $(srcdir)/std_data
105105
std_data/client-cert.pem: $(top_srcdir)/SSL/$(@F)
106-
@CP@ $(top_srcdir)/SSL/$(@F) $(srcdir)/std_data
106+
@CP@ -f $(top_srcdir)/SSL/$(@F) $(srcdir)/std_data
107107
std_data/cacert.pem: $(top_srcdir)/SSL/$(@F)
108-
@CP@ $(top_srcdir)/SSL/$(@F) $(srcdir)/std_data
108+
@CP@ -f $(top_srcdir)/SSL/$(@F) $(srcdir)/std_data
109109
std_data/server-cert.pem: $(top_srcdir)/SSL/$(@F)
110-
@CP@ $(top_srcdir)/SSL/$(@F) $(srcdir)/std_data
110+
@CP@ -f $(top_srcdir)/SSL/$(@F) $(srcdir)/std_data
111111
std_data/server-key.pem: $(top_srcdir)/SSL/$(@F)
112-
@CP@ $(top_srcdir)/SSL/$(@F) $(srcdir)/std_data
112+
@CP@ -f $(top_srcdir)/SSL/$(@F) $(srcdir)/std_data
113113

114114
SUFFIXES = .sh
115115

mysql-test/r/init_connect.result

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,117 @@ set GLOBAL init_connect="adsfsdfsdfs";
2222
select @a;
2323
Got one of the listed errors
2424
drop table t1;
25+
End of 4.1 tests
26+
create table t1 (x int);
27+
insert into t1 values (3), (5), (7);
28+
create table t2 (y int);
29+
create user mysqltest1@localhost;
30+
grant all privileges on test.* to mysqltest1@localhost;
31+
set global init_connect="create procedure p1() select * from t1";
32+
call p1();
33+
x
34+
3
35+
5
36+
7
37+
drop procedure p1;
38+
set global init_connect="create procedure p1(x int)\
39+
begin\
40+
select count(*) from t1;\
41+
select * from t1;\
42+
set @x = x;
43+
end";
44+
call p1(42);
45+
count(*)
46+
3
47+
x
48+
3
49+
5
50+
7
51+
select @x;
52+
@x
53+
42
54+
set global init_connect="call p1(4711)";
55+
select @x;
56+
@x
57+
4711
58+
set global init_connect="drop procedure if exists p1";
59+
call p1();
60+
ERROR 42000: PROCEDURE test.p1 does not exist
61+
create procedure p1(out sum int)
62+
begin
63+
declare n int default 0;
64+
declare c cursor for select * from t1;
65+
declare exit handler for not found
66+
begin
67+
close c;
68+
set sum = n;
69+
end;
70+
open c;
71+
loop
72+
begin
73+
declare x int;
74+
fetch c into x;
75+
if x > 3 then
76+
set n = n + x;
77+
end if;
78+
end;
79+
end loop;
80+
end|
81+
set global init_connect="call p1(@sum)";
82+
select @sum;
83+
@sum
84+
12
85+
drop procedure p1;
86+
create procedure p1(tbl char(10), v int)
87+
begin
88+
set @s = concat('insert into ', tbl, ' values (?)');
89+
set @v = v;
90+
prepare stmt1 from @s;
91+
execute stmt1 using @v;
92+
deallocate prepare stmt1;
93+
end|
94+
set global init_connect="call p1('t1', 11)";
95+
select * from t1;
96+
x
97+
3
98+
5
99+
7
100+
11
101+
drop procedure p1;
102+
create function f1() returns int
103+
begin
104+
declare n int;
105+
select count(*) into n from t1;
106+
return n;
107+
end|
108+
set global init_connect="set @x = f1()";
109+
select @x;
110+
@x
111+
4
112+
set global init_connect="create view v1 as select f1()";
113+
select * from v1;
114+
f1()
115+
4
116+
set global init_connect="drop view v1";
117+
select * from v1;
118+
ERROR 42S02: Table 'test.v1' doesn't exist
119+
drop function f1;
120+
create trigger trg1
121+
after insert on t2
122+
for each row
123+
insert into t1 values (new.y);
124+
set global init_connect="insert into t2 values (13), (17), (19)";
125+
select * from t1;
126+
x
127+
3
128+
5
129+
7
130+
11
131+
13
132+
17
133+
19
134+
drop trigger trg1;
135+
set global init_connect=default;
136+
revoke all privileges, grant option from mysqltest1@localhost;
137+
drop user mysqltest1@localhost;
138+
drop table t1, t2;

mysql-test/r/init_file.result

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,16 @@
11
ok
2+
end of 4.1 tests
3+
select * from t1;
4+
x
5+
3
6+
5
7+
7
8+
11
9+
13
10+
select * from t2;
11+
y
12+
30
13+
3
14+
11
15+
13
16+
drop table t1, t2;

mysql-test/std_data/init_file.dat

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,29 @@
11
select * from mysql.user as t1, mysql.user as t2, mysql.user as t3;
2+
use test;
3+
4+
drop table if exists t1;
5+
create table t1 (x int);
6+
drop table if exists t2;
7+
create table t2 (y int);
8+
9+
drop procedure if exists p1;
10+
create definer=root@localhost procedure p1() select * from t1;
11+
call p1();
12+
drop procedure p1;
13+
14+
create definer=root@localhost procedure p1() insert into t1 values (3),(5),(7);
15+
call p1();
16+
17+
drop function if exists f1;
18+
create definer=root@localhost function f1() returns int return (select count(*) from t1);
19+
insert into t2 set y = f1()*10;
20+
21+
drop view if exists v1;
22+
create definer=root@localhost view v1 as select f1();
23+
insert into t2 (y) select * from v1;
24+
25+
create trigger trg1 after insert on t2 for each row insert into t1 values (new.y);
26+
insert into t2 values (11), (13);
27+
drop procedure p1;
28+
drop function f1;
29+
drop view v1;

mysql-test/t/init_connect.test

Lines changed: 202 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,205 @@ select @a;
3535
connection con0;
3636
drop table t1;
3737

38-
# End of 4.1 tests
38+
disconnect con1;
39+
disconnect con2;
40+
disconnect con3;
41+
disconnect con4;
42+
disconnect con5;
43+
44+
--echo End of 4.1 tests
45+
#
46+
# Test 5.* features
47+
#
48+
49+
create table t1 (x int);
50+
insert into t1 values (3), (5), (7);
51+
create table t2 (y int);
52+
53+
create user mysqltest1@localhost;
54+
grant all privileges on test.* to mysqltest1@localhost;
55+
#
56+
# Create a simple procedure
57+
#
58+
set global init_connect="create procedure p1() select * from t1";
59+
connect (con1,localhost,mysqltest1,,);
60+
connection con1;
61+
call p1();
62+
drop procedure p1;
63+
64+
connection con0;
65+
disconnect con1;
66+
#
67+
# Create a multi-result set procedure
68+
#
69+
set global init_connect="create procedure p1(x int)\
70+
begin\
71+
select count(*) from t1;\
72+
select * from t1;\
73+
set @x = x;
74+
end";
75+
connect (con1,localhost,mysqltest1,,);
76+
connection con1;
77+
call p1(42);
78+
select @x;
79+
80+
connection con0;
81+
disconnect con1;
82+
#
83+
# Just call it - this will not generate any output
84+
#
85+
set global init_connect="call p1(4711)";
86+
connect (con1,localhost,mysqltest1,,);
87+
connection con1;
88+
select @x;
89+
90+
connection con0;
91+
disconnect con1;
92+
#
93+
# Drop the procedure
94+
#
95+
set global init_connect="drop procedure if exists p1";
96+
connect (con1,localhost,mysqltest1,,);
97+
connection con1;
98+
--error ER_SP_DOES_NOT_EXIST
99+
call p1();
100+
101+
connection con0;
102+
disconnect con1;
103+
#
104+
# Execution of a more complex procedure
105+
#
106+
delimiter |;
107+
create procedure p1(out sum int)
108+
begin
109+
declare n int default 0;
110+
declare c cursor for select * from t1;
111+
declare exit handler for not found
112+
begin
113+
close c;
114+
set sum = n;
115+
end;
116+
117+
open c;
118+
loop
119+
begin
120+
declare x int;
121+
122+
fetch c into x;
123+
if x > 3 then
124+
set n = n + x;
125+
end if;
126+
end;
127+
end loop;
128+
end|
129+
delimiter ;|
130+
# Call the procedure with a cursor
131+
set global init_connect="call p1(@sum)";
132+
connect (con1,localhost,mysqltest1,,);
133+
connection con1;
134+
select @sum;
135+
136+
connection con0;
137+
disconnect con1;
138+
drop procedure p1;
139+
#
140+
# Test Dynamic SQL
141+
#
142+
delimiter |;
143+
create procedure p1(tbl char(10), v int)
144+
begin
145+
set @s = concat('insert into ', tbl, ' values (?)');
146+
set @v = v;
147+
prepare stmt1 from @s;
148+
execute stmt1 using @v;
149+
deallocate prepare stmt1;
150+
end|
151+
delimiter ;|
152+
# Call the procedure with prepared statements
153+
set global init_connect="call p1('t1', 11)";
154+
connect (con1,localhost,mysqltest1,,);
155+
connection con1;
156+
select * from t1;
157+
158+
connection con0;
159+
disconnect con1;
160+
drop procedure p1;
161+
#
162+
# Stored functions
163+
#
164+
delimiter |;
165+
create function f1() returns int
166+
begin
167+
declare n int;
168+
169+
select count(*) into n from t1;
170+
return n;
171+
end|
172+
delimiter ;|
173+
# Invoke a function
174+
set global init_connect="set @x = f1()";
175+
connect (con1,localhost,mysqltest1,,);
176+
connection con1;
177+
select @x;
178+
179+
connection con0;
180+
disconnect con1;
181+
#
182+
# Create a view
183+
#
184+
set global init_connect="create view v1 as select f1()";
185+
connect (con1,localhost,mysqltest1,,);
186+
connection con1;
187+
select * from v1;
188+
189+
connection con0;
190+
disconnect con1;
191+
#
192+
# Drop the view
193+
#
194+
set global init_connect="drop view v1";
195+
connect (con1,localhost,mysqltest1,,);
196+
connection con1;
197+
--error ER_NO_SUCH_TABLE
198+
select * from v1;
199+
200+
connection con0;
201+
disconnect con1;
202+
drop function f1;
203+
204+
# We can't test "create trigger", since this requires super privileges
205+
# in 5.0, but with super privileges, init_connect is not executed.
206+
# (However, this can be tested in 5.1)
207+
#
208+
#set global init_connect="create trigger trg1\
209+
# after insert on t2\
210+
# for each row\
211+
# insert into t1 values (new.y)";
212+
#connect (con1,localhost,mysqltest1,,);
213+
#connection con1;
214+
#insert into t2 values (2), (4);
215+
#select * from t1;
216+
#
217+
#connection con0;
218+
#disconnect con1;
219+
220+
create trigger trg1
221+
after insert on t2
222+
for each row
223+
insert into t1 values (new.y);
224+
225+
# Invoke trigger
226+
set global init_connect="insert into t2 values (13), (17), (19)";
227+
connect (con1,localhost,mysqltest1,,);
228+
connection con1;
229+
select * from t1;
230+
231+
connection con0;
232+
disconnect con1;
233+
234+
drop trigger trg1;
235+
set global init_connect=default;
236+
237+
revoke all privileges, grant option from mysqltest1@localhost;
238+
drop user mysqltest1@localhost;
239+
drop table t1, t2;

0 commit comments

Comments
 (0)