1
by brian
clean slate |
1 |
# row-based and statement have expected binlog difference in result files
|
2 |
||
3 |
# Test of replication of stored procedures (WL#2146 for MySQL 5.0)
|
|
4 |
# Modified by WL#2971.
|
|
5 |
||
6 |
source include/have_binlog_format_mixed.inc; |
|
7 |
source include/master-slave.inc; |
|
8 |
||
9 |
# we need a db != test, where we don't have automatic grants
|
|
10 |
--disable_warnings |
|
11 |
drop database if exists mysqltest1; |
|
12 |
--enable_warnings |
|
13 |
create database mysqltest1; |
|
14 |
use mysqltest1; |
|
15 |
create table t1 (a varchar(100)); |
|
16 |
sync_slave_with_master; |
|
17 |
use mysqltest1; |
|
18 |
||
19 |
# ********************** PART 1 : STORED PROCEDURES ***************
|
|
20 |
||
21 |
# Does the same proc as on master get inserted into mysql.proc ?
|
|
22 |
# (same definer, same properties...)
|
|
23 |
||
24 |
connection master; |
|
25 |
||
26 |
delimiter |; |
|
27 |
||
28 |
# Stored procedures don't have the limitations that functions have
|
|
29 |
# regarding binlogging: it's ok to create a procedure as not
|
|
30 |
# deterministic and updating data, while it's not ok to create such a
|
|
31 |
# function. We test this.
|
|
32 |
||
33 |
create procedure foo() |
|
34 |
begin
|
|
35 |
declare b int; |
|
36 |
set b = 8; |
|
37 |
insert into t1 values (b); |
|
38 |
insert into t1 values (unix_timestamp()); |
|
39 |
end| |
|
40 |
delimiter ;| |
|
41 |
||
42 |
# we replace columns having times
|
|
43 |
# (even with fixed timestamp displayed time may changed based on TZ)
|
|
44 |
--replace_result localhost.localdomain localhost 127.0.0.1 localhost |
|
45 |
--replace_column 13 # 14 # |
|
46 |
select * from mysql.proc where name='foo' and db='mysqltest1'; |
|
47 |
sync_slave_with_master; |
|
48 |
# You will notice in the result that the definer does not match what
|
|
49 |
# it is on master, it is a known bug on which Alik is working
|
|
50 |
--replace_result localhost.localdomain localhost 127.0.0.1 localhost |
|
51 |
--replace_column 13 # 14 # |
|
52 |
select * from mysql.proc where name='foo' and db='mysqltest1'; |
|
53 |
||
54 |
connection master; |
|
55 |
# see if timestamp used in SP on slave is same as on master
|
|
56 |
set timestamp=1000000000; |
|
57 |
call foo(); |
|
58 |
select * from t1; |
|
59 |
sync_slave_with_master; |
|
60 |
select * from t1; |
|
61 |
||
62 |
# Now a SP which is not updating tables
|
|
63 |
||
64 |
connection master; |
|
65 |
delete from t1; |
|
66 |
create procedure foo2() |
|
67 |
select * from mysqltest1.t1; |
|
68 |
call foo2(); |
|
69 |
||
70 |
# check that this is allowed (it's not for functions):
|
|
71 |
alter procedure foo2 contains sql; |
|
72 |
||
73 |
# SP with definer's right
|
|
74 |
||
75 |
drop table t1; |
|
76 |
create table t1 (a int); |
|
77 |
create table t2 like t1; |
|
78 |
||
79 |
create procedure foo3() |
|
80 |
deterministic
|
|
81 |
insert into t1 values (15); |
|
82 |
||
83 |
# let's create a non-privileged user
|
|
84 |
grant CREATE ROUTINE, EXECUTE on mysqltest1.* to "zedjzlcsjhd"@127.0.0.1; |
|
85 |
grant SELECT on mysqltest1.t1 to "zedjzlcsjhd"@127.0.0.1; |
|
86 |
grant SELECT, INSERT on mysqltest1.t2 to "zedjzlcsjhd"@127.0.0.1; |
|
87 |
||
88 |
# ToDo: BUG#14931: There is a race between the last grant binlogging, and
|
|
89 |
# the binlogging in the new connection made below, causing sporadic test
|
|
90 |
# failures due to switched statement order in binlog. To fix this we do
|
|
91 |
# SELECT 1 in the first connection before starting the second, ensuring
|
|
92 |
# that binlogging is done in the expected order.
|
|
93 |
# Please remove this SELECT 1 when BUG#14931 is fixed.
|
|
94 |
SELECT 1; |
|
95 |
||
96 |
connect (con1,127.0.0.1,zedjzlcsjhd,,mysqltest1,$MASTER_MYPORT,); |
|
97 |
connection con1; |
|
98 |
||
99 |
# this routine will fail in the second INSERT because of privileges
|
|
100 |
delimiter |; |
|
101 |
create procedure foo4() |
|
102 |
deterministic
|
|
103 |
begin
|
|
104 |
insert into t2 values(3); |
|
105 |
insert into t1 values (5); |
|
106 |
end| |
|
107 |
||
108 |
delimiter ;| |
|
109 |
||
110 |
# I add ,0 so that it does not print the error in the test output,
|
|
111 |
# because this error is hostname-dependent
|
|
112 |
--error 1142,0 |
|
113 |
call foo4(); # invoker has no INSERT grant on table t1 => failure |
|
114 |
||
115 |
connection master; |
|
116 |
call foo3(); # success (definer == root) |
|
117 |
show warnings; |
|
118 |
||
119 |
--error 1142,0 |
|
120 |
call foo4(); # definer's rights => failure |
|
121 |
||
122 |
# we test replication of ALTER PROCEDURE
|
|
123 |
alter procedure foo4 sql security invoker; |
|
124 |
call foo4(); # invoker's rights => success |
|
125 |
show warnings; |
|
126 |
||
127 |
# Note that half-failed procedure calls are ok with binlogging;
|
|
128 |
# if we compare t2 on master and slave we see they are identical:
|
|
129 |
||
130 |
select * from t1; |
|
131 |
select * from t2; |
|
132 |
sync_slave_with_master; |
|
133 |
select * from t1; |
|
134 |
select * from t2; |
|
135 |
||
136 |
# Let's check another failing-in-the-middle procedure
|
|
137 |
connection master; |
|
138 |
delete from t2; |
|
139 |
alter table t2 add unique (a); |
|
140 |
||
141 |
drop procedure foo4; |
|
142 |
delimiter |; |
|
143 |
create procedure foo4() |
|
144 |
deterministic
|
|
145 |
begin
|
|
146 |
insert into t2 values(20),(20); |
|
147 |
end| |
|
148 |
||
149 |
delimiter ;| |
|
150 |
||
151 |
--error ER_DUP_ENTRY |
|
152 |
call foo4(); |
|
153 |
show warnings; |
|
154 |
||
155 |
select * from t2; |
|
156 |
sync_slave_with_master; |
|
157 |
# check that this failed-in-the-middle replicated right:
|
|
158 |
select * from t2; |
|
159 |
||
160 |
# Test of DROP PROCEDURE
|
|
161 |
||
162 |
--replace_result localhost.localdomain localhost 127.0.0.1 localhost |
|
163 |
--replace_column 13 # 14 # |
|
164 |
select * from mysql.proc where name="foo4" and db='mysqltest1'; |
|
165 |
connection master; |
|
166 |
drop procedure foo4; |
|
167 |
select * from mysql.proc where name="foo4" and db='mysqltest1'; |
|
168 |
sync_slave_with_master; |
|
169 |
select * from mysql.proc where name="foo4" and db='mysqltest1'; |
|
170 |
||
171 |
# ********************** PART 2 : FUNCTIONS ***************
|
|
172 |
||
173 |
connection master; |
|
174 |
drop procedure foo; |
|
175 |
drop procedure foo2; |
|
176 |
drop procedure foo3; |
|
177 |
||
178 |
delimiter |; |
|
179 |
# check that needs "deterministic"
|
|
180 |
--error 1418 |
|
181 |
create function fn1(x int) |
|
182 |
returns int |
|
183 |
begin
|
|
184 |
insert into t1 values (x); |
|
185 |
return x+2; |
|
186 |
end| |
|
187 |
create function fn1(x int) |
|
188 |
returns int |
|
189 |
deterministic
|
|
190 |
begin
|
|
191 |
insert into t1 values (x); |
|
192 |
return x+2; |
|
193 |
end| |
|
194 |
||
195 |
delimiter ;| |
|
196 |
delete t1,t2 from t1,t2; |
|
197 |
select fn1(20); |
|
198 |
insert into t2 values(fn1(21)); |
|
199 |
select * from t1; |
|
200 |
select * from t2; |
|
201 |
sync_slave_with_master; |
|
202 |
select * from t1; |
|
203 |
select * from t2; |
|
204 |
||
205 |
connection master; |
|
206 |
delimiter |; |
|
207 |
||
208 |
drop function fn1; |
|
209 |
||
210 |
create function fn1() |
|
211 |
returns int |
|
212 |
no sql |
|
213 |
begin
|
|
214 |
return unix_timestamp(); |
|
215 |
end| |
|
216 |
||
217 |
delimiter ;| |
|
218 |
# check that needs "deterministic"
|
|
219 |
--error 1418 |
|
220 |
alter function fn1 contains sql; |
|
221 |
||
222 |
delete from t1; |
|
223 |
set timestamp=1000000000; |
|
224 |
insert into t1 values(fn1()); |
|
225 |
||
226 |
connection con1; |
|
227 |
||
228 |
delimiter |; |
|
229 |
--error 1419 # only full-global-privs user can create a function |
|
230 |
create function fn2() |
|
231 |
returns int |
|
232 |
no sql |
|
233 |
begin
|
|
234 |
return unix_timestamp(); |
|
235 |
end| |
|
236 |
delimiter ;| |
|
237 |
connection master; |
|
238 |
set global log_bin_trust_function_creators=0; |
|
239 |
set global log_bin_trust_function_creators=1; |
|
240 |
# slave needs it too otherwise will not execute what master allowed:
|
|
241 |
connection slave; |
|
242 |
set global log_bin_trust_function_creators=1; |
|
243 |
||
244 |
connection con1; |
|
245 |
||
246 |
delimiter |; |
|
247 |
create function fn2() |
|
248 |
returns int |
|
249 |
no sql |
|
250 |
begin
|
|
251 |
return unix_timestamp(); |
|
252 |
end| |
|
253 |
delimiter ;| |
|
254 |
||
255 |
connection master; |
|
256 |
||
257 |
# Now a function which is supposed to not update tables
|
|
258 |
# as it's "reads sql data", so should not give error even if
|
|
259 |
# non-deterministic.
|
|
260 |
||
261 |
delimiter |; |
|
262 |
create function fn3() |
|
263 |
returns int |
|
264 |
not deterministic |
|
265 |
reads sql data |
|
266 |
begin
|
|
267 |
return 0; |
|
268 |
end| |
|
269 |
delimiter ;| |
|
270 |
||
271 |
select fn3(); |
|
272 |
--replace_result localhost.localdomain localhost 127.0.0.1 localhost |
|
273 |
--replace_column 13 # 14 # |
|
274 |
select * from mysql.proc where db='mysqltest1'; |
|
275 |
select * from t1; |
|
276 |
||
277 |
sync_slave_with_master; |
|
278 |
use mysqltest1; |
|
279 |
select * from t1; |
|
280 |
--replace_result localhost.localdomain localhost 127.0.0.1 localhost |
|
281 |
--replace_column 13 # 14 # |
|
282 |
select * from mysql.proc where db='mysqltest1'; |
|
283 |
||
284 |
# Let's check a failing-in-the-middle function
|
|
285 |
connection master; |
|
286 |
delete from t2; |
|
287 |
alter table t2 add unique (a); |
|
288 |
||
289 |
drop function fn1; |
|
290 |
||
291 |
delimiter |; |
|
292 |
create function fn1(x int) |
|
293 |
returns int |
|
294 |
begin
|
|
295 |
insert into t2 values(x),(x); |
|
296 |
return 10; |
|
297 |
end| |
|
298 |
||
299 |
delimiter ;| |
|
300 |
||
301 |
do fn1(100); |
|
302 |
||
303 |
--error ER_DUP_ENTRY |
|
304 |
select fn1(20); |
|
305 |
||
306 |
select * from t2; |
|
307 |
sync_slave_with_master; |
|
308 |
||
309 |
# check that this failed-in-the-middle replicated right:
|
|
310 |
select * from t2; |
|
311 |
||
312 |
# ********************** PART 3 : TRIGGERS ***************
|
|
313 |
||
314 |
connection con1; |
|
315 |
# now fails due to missing trigger grant (err 1142 i/o 1227) due to new
|
|
316 |
# check in sql_trigger.cc (v1.44) by anozdrin on 2006/02/01 --azundris
|
|
317 |
--error ER_TABLEACCESS_DENIED_ERROR |
|
318 |
create trigger trg before insert on t1 for each row set new.a= 10; |
|
319 |
||
320 |
connection master; |
|
321 |
delete from t1; |
|
322 |
# TODO: when triggers can contain an update, test that this update
|
|
323 |
# does not go into binlog.
|
|
324 |
# I'm not setting user vars in the trigger, because replication of user vars
|
|
325 |
# would take care of propagating the user var's value to slave, so even if
|
|
326 |
# the trigger was not executed on slave it would not be discovered.
|
|
327 |
create trigger trg before insert on t1 for each row set new.a= 10; |
|
328 |
insert into t1 values (1); |
|
329 |
select * from t1; |
|
330 |
sync_slave_with_master; |
|
331 |
select * from t1; |
|
332 |
||
333 |
connection master; |
|
334 |
delete from t1; |
|
335 |
drop trigger trg; |
|
336 |
insert into t1 values (1); |
|
337 |
select * from t1; |
|
338 |
sync_slave_with_master; |
|
339 |
select * from t1; |
|
340 |
||
341 |
||
342 |
# ********************** PART 4 : RELATED FIXED BUGS ***************
|
|
343 |
||
344 |
||
345 |
#
|
|
346 |
# Test for bug #13969 "Routines which are replicated from master can't be
|
|
347 |
# executed on slave".
|
|
348 |
#
|
|
349 |
connection master; |
|
350 |
create procedure foo() |
|
351 |
not deterministic |
|
352 |
reads sql data |
|
353 |
select * from t1; |
|
354 |
sync_slave_with_master; |
|
355 |
# This should not fail
|
|
356 |
call foo(); |
|
357 |
connection master; |
|
358 |
drop procedure foo; |
|
359 |
sync_slave_with_master; |
|
360 |
||
361 |
||
362 |
# Clean up
|
|
363 |
connection master; |
|
364 |
drop function fn1; |
|
365 |
drop database mysqltest1; |
|
366 |
drop user "zedjzlcsjhd"@127.0.0.1; |
|
367 |
use test; |
|
368 |
sync_slave_with_master; |
|
369 |
use test; |
|
370 |
||
371 |
#
|
|
372 |
# Bug#14077 "Failure to replicate a stored function with a cursor":
|
|
373 |
# verify that stored routines with cursors work on slave.
|
|
374 |
#
|
|
375 |
connection master; |
|
376 |
--disable_warnings |
|
377 |
drop function if exists f1; |
|
378 |
--enable_warnings |
|
379 |
delimiter |; |
|
380 |
create function f1() returns int reads sql data |
|
381 |
begin
|
|
382 |
declare var integer; |
|
383 |
declare c cursor for select a from v1; |
|
384 |
open c; |
|
385 |
fetch c into var; |
|
386 |
close c; |
|
387 |
return var; |
|
388 |
end| |
|
389 |
delimiter ;| |
|
390 |
create view v1 as select 1 as a; |
|
391 |
create table t1 (a int); |
|
392 |
insert into t1 (a) values (f1()); |
|
393 |
select * from t1; |
|
394 |
drop view v1; |
|
395 |
drop function f1; |
|
396 |
sync_slave_with_master; |
|
397 |
connection slave; |
|
398 |
select * from t1; |
|
399 |
||
400 |
#
|
|
401 |
# Bug#16621 "INSERTs in Stored Procedures causes data corruption in the Binary
|
|
402 |
# Log for 5.0.18"
|
|
403 |
#
|
|
404 |
||
405 |
# Prepare environment.
|
|
406 |
||
407 |
connection master; |
|
408 |
||
409 |
--disable_warnings |
|
410 |
DROP PROCEDURE IF EXISTS p1; |
|
411 |
DROP TABLE IF EXISTS t1; |
|
412 |
--enable_warnings |
|
413 |
||
414 |
# Test case.
|
|
415 |
||
416 |
CREATE TABLE t1(col VARCHAR(10)); |
|
417 |
||
418 |
CREATE PROCEDURE p1(arg VARCHAR(10)) |
|
419 |
INSERT INTO t1 VALUES(arg); |
|
420 |
||
421 |
CALL p1('test'); |
|
422 |
||
423 |
SELECT * FROM t1; |
|
424 |
||
425 |
sync_slave_with_master; |
|
426 |
SELECT * FROM t1; |
|
427 |
||
428 |
# Cleanup
|
|
429 |
connection master; |
|
430 |
DROP PROCEDURE p1; |
|
431 |
||
432 |
||
433 |
#
|
|
434 |
# BUG#20438: CREATE statements for views, stored routines and triggers can be
|
|
435 |
# not replicable.
|
|
436 |
#
|
|
437 |
||
438 |
--echo |
|
439 |
--echo ---> Test for BUG#20438 |
|
440 |
||
441 |
# Prepare environment.
|
|
442 |
||
443 |
--echo |
|
444 |
--echo ---> Preparing environment... |
|
445 |
--echo ---> connection: master |
|
446 |
--connection master |
|
447 |
||
448 |
--disable_warnings |
|
449 |
DROP PROCEDURE IF EXISTS p1; |
|
450 |
DROP FUNCTION IF EXISTS f1; |
|
451 |
--enable_warnings |
|
452 |
||
453 |
--echo |
|
454 |
--echo ---> Synchronizing slave with master... |
|
455 |
||
456 |
--save_master_pos |
|
457 |
--connection slave |
|
458 |
--sync_with_master |
|
459 |
||
460 |
--echo |
|
461 |
--echo ---> connection: master |
|
462 |
--connection master |
|
463 |
||
464 |
# Test.
|
|
465 |
||
466 |
--echo |
|
467 |
--echo ---> Creating procedure... |
|
468 |
||
469 |
/*!50003 CREATE PROCEDURE p1() SET @a = 1 */; |
|
470 |
||
471 |
/*!50003 CREATE FUNCTION f1() RETURNS INT RETURN 0 */; |
|
472 |
||
473 |
--echo |
|
474 |
--echo ---> Checking on master... |
|
475 |
||
476 |
SHOW CREATE PROCEDURE p1; |
|
477 |
SHOW CREATE FUNCTION f1; |
|
478 |
||
479 |
--echo |
|
480 |
--echo ---> Synchronizing slave with master... |
|
481 |
||
482 |
--save_master_pos |
|
483 |
--connection slave |
|
484 |
--sync_with_master |
|
485 |
||
486 |
--echo ---> connection: master |
|
487 |
||
488 |
--echo |
|
489 |
--echo ---> Checking on slave... |
|
490 |
||
491 |
SHOW CREATE PROCEDURE p1; |
|
492 |
SHOW CREATE FUNCTION f1; |
|
493 |
||
494 |
# Cleanup.
|
|
495 |
||
496 |
--echo |
|
497 |
--echo ---> connection: master |
|
498 |
--connection master |
|
499 |
||
500 |
--echo |
|
501 |
--echo ---> Cleaning up... |
|
502 |
||
503 |
DROP PROCEDURE p1; |
|
504 |
DROP FUNCTION f1; |
|
505 |
||
506 |
--save_master_pos |
|
507 |
--connection slave |
|
508 |
--sync_with_master |
|
509 |
--connection master |
|
510 |
||
511 |
||
512 |
# cleanup
|
|
513 |
connection master; |
|
514 |
drop table t1; |
|
515 |
sync_slave_with_master; |
|
516 |
||
517 |
#
|
|
518 |
# Bug22043: MySQL don't add "USE <DATABASE>" before "DROP PROCEDURE IF EXISTS"
|
|
519 |
#
|
|
520 |
||
521 |
connection master; |
|
522 |
--disable_warnings |
|
523 |
drop database if exists mysqltest; |
|
524 |
drop database if exists mysqltest2; |
|
525 |
--enable_warnings |
|
526 |
create database mysqltest; |
|
527 |
create database mysqltest2; |
|
528 |
use mysqltest2; |
|
529 |
create table t ( t integer ); |
|
530 |
create procedure mysqltest.test() begin end; |
|
531 |
insert into t values ( 1 ); |
|
532 |
--error ER_BAD_DB_ERROR |
|
533 |
create procedure `\\`.test() begin end; |
|
534 |
||
535 |
#
|
|
536 |
# BUG#19725: Calls to stored function in other database are not
|
|
537 |
# replicated correctly in some cases
|
|
538 |
#
|
|
539 |
||
540 |
connection master; |
|
541 |
delimiter |; |
|
542 |
create function f1 () returns int |
|
543 |
begin
|
|
544 |
insert into t values (1); |
|
545 |
return 0; |
|
546 |
end| |
|
547 |
delimiter ;| |
|
548 |
sync_slave_with_master; |
|
549 |
# Let us test if we don't forget to binlog the function's database
|
|
550 |
connection master; |
|
551 |
use mysqltest; |
|
552 |
set @a:= mysqltest2.f1(); |
|
553 |
sync_slave_with_master; |
|
554 |
connection master; |
|
555 |
||
556 |
# Final inspection which verifies how all statements of this test file
|
|
557 |
# were written to the binary log.
|
|
558 |
source include/show_binlog_events.inc; |
|
559 |
||
560 |
||
561 |
# Restore log_bin_trust_function_creators to its original value.
|
|
562 |
# This is a cleanup for all parts above where we tested stored
|
|
563 |
# functions and triggers.
|
|
564 |
set global log_bin_trust_function_creators=0; |
|
565 |
connection master; |
|
566 |
set global log_bin_trust_function_creators=0; |
|
567 |
||
568 |
# Clean up
|
|
569 |
drop database mysqltest; |
|
570 |
drop database mysqltest2; |
|
571 |
sync_slave_with_master; |
|
572 |
||
573 |
--echo End of 5.0 tests |
|
574 |
--echo End of 5.1 tests |