1
by brian
clean slate |
1 |
## Bug#12713 (Error in a stored function called from a SELECT doesn't cause |
2 |
## ROLLBACK of statem) |
|
3 |
||
4 |
##
|
|
5 |
## Pre-Requisites : |
|
6 |
## - $engine_type should be set |
|
7 |
##
|
|
8 |
||
9 |
set sql_mode=no_engine_substitution; |
|
10 |
eval set storage_engine = $engine_type; |
|
11 |
set autocommit=1; |
|
12 |
||
13 |
--disable_warnings |
|
14 |
drop table if exists t1; |
|
15 |
drop table if exists t2; |
|
16 |
drop table if exists t3; |
|
17 |
drop function if exists f2; |
|
18 |
drop procedure if exists bug12713_call; |
|
19 |
drop procedure if exists bug12713_dump_spvars; |
|
20 |
drop procedure if exists dummy; |
|
21 |
--enable_warnings |
|
22 |
||
23 |
create table t1 (a int); |
|
24 |
create table t2 (a int unique); |
|
25 |
create table t3 (a int); |
|
26 |
||
27 |
# a workaround for Bug#32633: Can not create any routine if |
|
28 |
# SQL_MODE=no_engine_substitution |
|
29 |
||
30 |
set sql_mode=default; |
|
31 |
||
32 |
insert into t1 (a) values (1), (2); |
|
33 |
insert into t3 (a) values (1), (2); |
|
34 |
||
35 |
delimiter |; |
|
36 |
||
37 |
## Cause a failure every time |
|
38 |
create function f2(x int) returns int |
|
39 |
begin
|
|
40 |
insert into t2 (a) values (x); |
|
41 |
insert into t2 (a) values (x); |
|
42 |
return x; |
|
43 |
end| |
|
44 |
||
45 |
delimiter ;| |
|
46 |
||
47 |
set autocommit=0; |
|
48 |
||
49 |
flush status; |
|
50 |
##============================================================================ |
|
51 |
## Design notes |
|
52 |
##
|
|
53 |
## In each case, statement rollback is expected. |
|
54 |
## for transactional engines, the rollback should be properly executed |
|
55 |
## for non transactional engines, the rollback may cause warnings. |
|
56 |
##
|
|
57 |
## The test pattern is as follows |
|
58 |
## - insert 1000+N |
|
59 |
## - statement with a side effect, that fails to insert N twice |
|
60 |
## - a statement rollback is expected (expecting 1 row 1000+N only) in t2 |
|
61 |
## - a rollback is performed |
|
62 |
## - expecting a clean table t2. |
|
63 |
##============================================================================ |
|
64 |
||
65 |
insert into t2 (a) values (1001); |
|
66 |
--error ER_DUP_ENTRY |
|
67 |
insert into t1 (a) values (f2(1)); |
|
68 |
select * from t2; |
|
69 |
rollback; |
|
70 |
select * from t2; |
|
71 |
||
72 |
insert into t2 (a) values (1002); |
|
73 |
--error ER_DUP_ENTRY |
|
74 |
insert into t3 (a) select f2(2) from t1; |
|
75 |
select * from t2; |
|
76 |
rollback; |
|
77 |
select * from t2; |
|
78 |
||
79 |
insert into t2 (a) values (1003); |
|
80 |
--error ER_DUP_ENTRY |
|
81 |
update t1 set a= a + f2(3); |
|
82 |
select * from t2; |
|
83 |
rollback; |
|
84 |
select * from t2; |
|
85 |
||
86 |
insert into t2 (a) values (1004); |
|
87 |
--error ER_DUP_ENTRY |
|
88 |
update t1, t3 set t1.a = 0, t3.a = 0 where (f2(4) = 4) and (t1.a = t3.a); |
|
89 |
select * from t2; |
|
90 |
rollback; |
|
91 |
select * from t2; |
|
92 |
||
93 |
insert into t2 (a) values (1005); |
|
94 |
--error ER_DUP_ENTRY |
|
95 |
delete from t1 where (a = f2(5)); |
|
96 |
select * from t2; |
|
97 |
rollback; |
|
98 |
select * from t2; |
|
99 |
||
100 |
insert into t2 (a) values (1006); |
|
101 |
--error ER_DUP_ENTRY |
|
102 |
delete from t1, t3 using t1, t3 where (f2(6) = 6) ; |
|
103 |
select * from t2; |
|
104 |
rollback; |
|
105 |
select * from t2; |
|
106 |
||
107 |
insert into t2 (a) values (1007); |
|
108 |
--error ER_DUP_ENTRY |
|
109 |
replace t1 values (f2(7)); |
|
110 |
select * from t2; |
|
111 |
rollback; |
|
112 |
select * from t2; |
|
113 |
||
114 |
insert into t2 (a) values (1008); |
|
115 |
--error ER_DUP_ENTRY |
|
116 |
replace into t3 (a) select f2(8) from t1; |
|
117 |
select * from t2; |
|
118 |
rollback; |
|
119 |
select * from t2; |
|
120 |
||
121 |
insert into t2 (a) values (1009); |
|
122 |
--error ER_DUP_ENTRY |
|
123 |
select f2(9) from t1 ; |
|
124 |
select * from t2; |
|
125 |
rollback; |
|
126 |
select * from t2; |
|
127 |
||
128 |
insert into t2 (a) values (1010); |
|
129 |
--error ER_DUP_ENTRY |
|
130 |
show databases where (f2(10) = 10); |
|
131 |
select * from t2; |
|
132 |
rollback; |
|
133 |
select * from t2; |
|
134 |
||
135 |
insert into t2 (a) values (1011); |
|
136 |
--error ER_DUP_ENTRY |
|
137 |
show tables where (f2(11) = 11); |
|
138 |
select * from t2; |
|
139 |
rollback; |
|
140 |
select * from t2; |
|
141 |
||
142 |
insert into t2 (a) values (1012); |
|
143 |
--error ER_DUP_ENTRY |
|
144 |
show triggers where (f2(12) = 12); |
|
145 |
select * from t2; |
|
146 |
rollback; |
|
147 |
select * from t2; |
|
148 |
||
149 |
insert into t2 (a) values (1013); |
|
150 |
--error ER_DUP_ENTRY |
|
151 |
show table status where (f2(13) = 13); |
|
152 |
select * from t2; |
|
153 |
rollback; |
|
154 |
select * from t2; |
|
155 |
||
156 |
insert into t2 (a) values (1014); |
|
157 |
--error ER_DUP_ENTRY |
|
158 |
show open tables where (f2(14) = 14); |
|
159 |
select * from t2; |
|
160 |
rollback; |
|
161 |
select * from t2; |
|
162 |
||
163 |
insert into t2 (a) values (1015); |
|
164 |
--error ER_DUP_ENTRY |
|
165 |
show columns in mysql.proc where (f2(15) = 15); |
|
166 |
select * from t2; |
|
167 |
rollback; |
|
168 |
select * from t2; |
|
169 |
||
170 |
insert into t2 (a) values (1016); |
|
171 |
--error ER_DUP_ENTRY |
|
172 |
show status where (f2(16) = 16); |
|
173 |
select * from t2; |
|
174 |
rollback; |
|
175 |
select * from t2; |
|
176 |
||
177 |
insert into t2 (a) values (1017); |
|
178 |
--error ER_DUP_ENTRY |
|
179 |
show variables where (f2(17) = 17); |
|
180 |
select * from t2; |
|
181 |
rollback; |
|
182 |
select * from t2; |
|
183 |
||
184 |
insert into t2 (a) values (1018); |
|
185 |
--error ER_DUP_ENTRY |
|
186 |
show charset where (f2(18) = 18); |
|
187 |
select * from t2; |
|
188 |
rollback; |
|
189 |
select * from t2; |
|
190 |
||
191 |
insert into t2 (a) values (1019); |
|
192 |
--error ER_DUP_ENTRY |
|
193 |
show collation where (f2(19) = 19); |
|
194 |
select * from t2; |
|
195 |
rollback; |
|
196 |
select * from t2; |
|
197 |
||
198 |
--echo # We need at least one procedure to make sure the WHERE clause is |
|
199 |
--echo # evaluated |
|
200 |
create procedure dummy() begin end; |
|
201 |
insert into t2 (a) values (1020); |
|
202 |
--error ER_DUP_ENTRY |
|
203 |
show procedure status where (f2(20) = 20); |
|
204 |
select * from t2; |
|
205 |
rollback; |
|
206 |
select * from t2; |
|
207 |
drop procedure dummy; |
|
208 |
||
209 |
insert into t2 (a) values (1021); |
|
210 |
--error ER_DUP_ENTRY |
|
211 |
show function status where (f2(21) = 21); |
|
212 |
select * from t2; |
|
213 |
rollback; |
|
214 |
select * from t2; |
|
215 |
||
216 |
insert into t2 (a) values (1022); |
|
217 |
prepare stmt from "insert into t1 (a) values (f2(22))"; |
|
218 |
--error ER_DUP_ENTRY |
|
219 |
execute stmt; |
|
220 |
select * from t2; |
|
221 |
rollback; |
|
222 |
select * from t2; |
|
223 |
||
224 |
insert into t2 (a) values (1023); |
|
225 |
do (f2(23)); |
|
226 |
select * from t2; |
|
227 |
rollback; |
|
228 |
select * from t2; |
|
229 |
||
230 |
## Please note : |
|
231 |
## This will insert a record 1024 in t1 (statement commit) |
|
232 |
## This will insert a record 24 in t1 (statement commit) |
|
233 |
## then will rollback the second insert only (24) (statement rollback) |
|
234 |
## then will rollback the complete transaction (transaction rollback) |
|
235 |
||
236 |
delimiter |; |
|
237 |
||
238 |
create procedure bug12713_call () |
|
239 |
begin
|
|
240 |
insert into t2 (a) values (24); |
|
241 |
insert into t2 (a) values (24); |
|
242 |
end| |
|
243 |
||
244 |
delimiter ;| |
|
245 |
||
246 |
insert into t2 (a) values (1024); |
|
247 |
--error ER_DUP_ENTRY |
|
248 |
call bug12713_call(); |
|
249 |
select * from t2; |
|
250 |
rollback; |
|
251 |
select * from t2; |
|
252 |
||
253 |
--echo ======================================================================= |
|
254 |
--echo Testing select_to_file |
|
255 |
--echo ======================================================================= |
|
256 |
||
257 |
insert into t2 (a) values (1025); |
|
258 |
||
259 |
--replace_result $MYSQLTEST_VARDIR .. |
|
260 |
--error ER_DUP_ENTRY |
|
261 |
eval select f2(25) into outfile "$MYSQLTEST_VARDIR/tmp/dml.out" from t1; |
|
262 |
select * from t2; |
|
263 |
rollback; |
|
264 |
select * from t2; |
|
265 |
--remove_file $MYSQLTEST_VARDIR/tmp/dml.out |
|
266 |
||
267 |
insert into t2 (a) values (1026); |
|
268 |
--replace_result $MYSQLTEST_VARDIR .. |
|
269 |
--error ER_DUP_ENTRY |
|
270 |
eval load data infile "../std_data_ln/words.dat" into table t1 (a) set a:=f2(26); |
|
271 |
||
272 |
select * from t2; |
|
273 |
rollback; |
|
274 |
select * from t2; |
|
275 |
||
276 |
--echo ======================================================================= |
|
277 |
--echo Testing select_dumpvar |
|
278 |
--echo ======================================================================= |
|
279 |
||
280 |
insert into t2 (a) values (1027); |
|
281 |
--error ER_DUP_ENTRY |
|
282 |
select f2(27) into @foo; |
|
283 |
select * from t2; |
|
284 |
rollback; |
|
285 |
select * from t2; |
|
286 |
||
287 |
--echo ======================================================================= |
|
288 |
--echo Testing Select_fetch_into_spvars |
|
289 |
--echo ======================================================================= |
|
290 |
||
291 |
delimiter |; |
|
292 |
||
293 |
create procedure bug12713_dump_spvars () |
|
294 |
begin
|
|
295 |
declare foo int; |
|
296 |
||
297 |
declare continue handler for sqlexception |
|
298 |
begin
|
|
299 |
select "Exception trapped"; |
|
300 |
end; |
|
301 |
||
302 |
select f2(28) into foo; |
|
303 |
select * from t2; |
|
304 |
end| |
|
305 |
||
306 |
delimiter ;| |
|
307 |
||
308 |
insert into t2 (a) values (1028); |
|
309 |
call bug12713_dump_spvars (); |
|
310 |
rollback; |
|
311 |
select * from t2; |
|
312 |
||
313 |
--echo ======================================================================= |
|
314 |
--echo Cleanup |
|
315 |
--echo ======================================================================= |
|
316 |
||
317 |
set autocommit=default; |
|
318 |
||
319 |
drop table t1; |
|
320 |
drop table t2; |
|
321 |
drop table t3; |
|
322 |
drop function f2; |
|
323 |
drop procedure bug12713_call; |
|
324 |
drop procedure bug12713_dump_spvars; |
|
325 |
--echo # |
|
326 |
--echo # Bug#12713 Error in a stored function called from a SELECT doesn't |
|
327 |
--echo # cause ROLLBACK of statem |
|
328 |
--echo # |
|
329 |
--echo # Verify that two-phase commit is not issued for read-only |
|
330 |
--echo # transactions. |
|
331 |
--echo # |
|
332 |
--echo # Verify that two-phase commit is issued for read-write transactions, |
|
333 |
--echo # even if the change is done inside a stored function called from |
|
334 |
--echo # SELECT or SHOW statement. |
|
335 |
--echo # |
|
336 |
set autocommit=0; |
|
337 |
--disable_warnings |
|
338 |
drop table if exists t1; |
|
339 |
drop table if exists t2; |
|
340 |
drop function if exists f1; |
|
341 |
drop procedure if exists p_verify_status_increment; |
|
342 |
--enable_warnings |
|
343 |
||
344 |
# Save binlog_format in a user variable. References to system |
|
345 |
# variables are "unsafe", meaning they are written as rows instead of |
|
346 |
# as statements to the binlog, if the loggging mode is 'mixed'. But |
|
347 |
# we don't want p_verify_status_increment to affect the logging mode. |
|
348 |
# Hence, we save binlog_format in a user variable (which is not |
|
349 |
# unsafe) and use that inside p_verify_status_increment. |
|
350 |
set @binlog_format=@@global.binlog_format; |
|
351 |
||
352 |
set sql_mode=no_engine_substitution; |
|
353 |
create table t1 (a int unique); |
|
354 |
create table t2 (a int) engine=myisam; |
|
355 |
set sql_mode=default; |
|
356 |
--echo # |
|
357 |
--echo # An auxiliary procedure to track Handler_prepare and Handler_commit |
|
358 |
--echo # statistics. |
|
359 |
--echo # |
|
360 |
delimiter |; |
|
361 |
create procedure |
|
362 |
p_verify_status_increment(commit_inc_mixed int, prepare_inc_mixed int, |
|
363 |
commit_inc_row int, prepare_inc_row int) |
|
364 |
begin
|
|
365 |
declare commit_inc int; |
|
366 |
declare prepare_inc int; |
|
367 |
declare old_commit_count int default ifnull(@commit_count, 0); |
|
368 |
declare old_prepare_count int default ifnull(@prepare_count, 0); |
|
369 |
declare c_res int; |
|
370 |
# Use a cursor to have just one access to I_S instead of 2, it is very slow |
|
371 |
# and amounts for over 90% of test CPU time |
|
372 |
declare c cursor for |
|
373 |
select variable_value |
|
374 |
from information_schema.session_status |
|
375 |
where variable_name='Handler_commit' or variable_name='Handler_prepare' |
|
376 |
order by variable_name; |
|
377 |
||
378 |
if @binlog_format = 'ROW' then |
|
379 |
set commit_inc= commit_inc_row; |
|
380 |
set prepare_inc= prepare_inc_row; |
|
381 |
else
|
|
382 |
set commit_inc= commit_inc_mixed; |
|
383 |
set prepare_inc= prepare_inc_mixed; |
|
384 |
end if; |
|
385 |
||
386 |
open c; |
|
387 |
fetch c into c_res; |
|
388 |
set @commit_count=c_res; |
|
389 |
fetch c into c_res; |
|
390 |
set @prepare_count=c_res; |
|
391 |
close c; |
|
392 |
||
393 |
if old_commit_count + commit_inc <> @commit_count then |
|
394 |
select concat("Expected commit increment: ", commit_inc, |
|
395 |
" actual: ", @commit_count - old_commit_count) |
|
396 |
as 'ERROR'; |
|
397 |
elseif old_prepare_count + prepare_inc <> @prepare_count then |
|
398 |
select concat("Expected prepare increment: ", prepare_inc, |
|
399 |
" actual: ", @prepare_count - old_prepare_count) |
|
400 |
as 'ERROR'; |
|
401 |
else
|
|
402 |
select '' as 'SUCCESS'; |
|
403 |
end if; |
|
404 |
end| |
|
405 |
delimiter ;| |
|
406 |
--echo # Reset Handler_commit and Handler_prepare counters |
|
407 |
flush status; |
|
408 |
--echo # |
|
409 |
--echo # 1. Read-only statement: SELECT |
|
410 |
--echo # |
|
411 |
select * from t1; |
|
412 |
call p_verify_status_increment(1, 0, 1, 0); |
|
413 |
commit; |
|
414 |
call p_verify_status_increment(1, 0, 1, 0); |
|
415 |
||
416 |
--echo # 2. Read-write statement: INSERT, insert 1 row. |
|
417 |
--echo # |
|
418 |
insert into t1 (a) values (1); |
|
419 |
call p_verify_status_increment(2, 2, 2, 2); |
|
420 |
commit; |
|
421 |
call p_verify_status_increment(2, 2, 2, 2); |
|
422 |
||
423 |
--echo # 3. Read-write statement: UPDATE, update 1 row. |
|
424 |
--echo # |
|
425 |
update t1 set a=2; |
|
426 |
call p_verify_status_increment(2, 2, 2, 2); |
|
427 |
commit; |
|
428 |
call p_verify_status_increment(2, 2, 2, 2); |
|
429 |
||
430 |
--echo # 4. Read-write statement: UPDATE, update 0 rows, 1 row matches WHERE |
|
431 |
--echo # |
|
432 |
update t1 set a=2; |
|
433 |
call p_verify_status_increment(2, 2, 1, 0); |
|
434 |
commit; |
|
435 |
call p_verify_status_increment(2, 2, 1, 0); |
|
436 |
||
437 |
--echo # 5. Read-write statement: UPDATE, update 0 rows, 0 rows match WHERE |
|
438 |
--echo # |
|
439 |
--echo # In mixed replication mode, there is a read-only transaction |
|
440 |
--echo # in InnoDB and also the statement is written to the binary log. |
|
441 |
--echo # So we have two commits but no 2pc, since the first engine's |
|
442 |
--echo # transaction is read-only. |
|
443 |
--echo # In the row level replication mode, we only have the read-only |
|
444 |
--echo # transaction in InnoDB and nothing is written to the binary log. |
|
445 |
--echo # |
|
446 |
update t1 set a=3 where a=1; |
|
447 |
call p_verify_status_increment(2, 0, 1, 0); |
|
448 |
commit; |
|
449 |
call p_verify_status_increment(2, 0, 1, 0); |
|
450 |
||
451 |
--echo # 6. Read-write statement: DELETE, delete 0 rows. |
|
452 |
--echo # |
|
453 |
delete from t1 where a=1; |
|
454 |
call p_verify_status_increment(2, 0, 1, 0); |
|
455 |
commit; |
|
456 |
call p_verify_status_increment(2, 0, 1, 0); |
|
457 |
||
458 |
--echo # 7. Read-write statement: DELETE, delete 1 row. |
|
459 |
--echo # |
|
460 |
delete from t1 where a=2; |
|
461 |
call p_verify_status_increment(2, 2, 2, 2); |
|
462 |
commit; |
|
463 |
call p_verify_status_increment(2, 2, 2, 2); |
|
464 |
||
465 |
--echo # 8. Read-write statement: unqualified DELETE |
|
466 |
--echo # |
|
467 |
--echo # In statement or mixed replication mode, we call |
|
468 |
--echo # handler::ha_delete_all_rows() and write statement text |
|
469 |
--echo # to the binary log. This results in two read-write transactions. |
|
470 |
--echo # In row level replication mode, we do not call |
|
471 |
--echo # handler::ha_delete_all_rows(), but delete rows one by one. |
|
472 |
--echo # Since there are no rows, nothing is written to the binary log. |
|
473 |
--echo # Thus we have just one read-only transaction in InnoDB. |
|
474 |
delete from t1; |
|
475 |
call p_verify_status_increment(2, 2, 1, 0); |
|
476 |
commit; |
|
477 |
call p_verify_status_increment(2, 2, 1, 0); |
|
478 |
||
479 |
--echo # 9. Read-write statement: REPLACE, change 1 row. |
|
480 |
--echo # |
|
481 |
replace t1 set a=1; |
|
482 |
call p_verify_status_increment(2, 2, 2, 2); |
|
483 |
commit; |
|
484 |
call p_verify_status_increment(2, 2, 2, 2); |
|
485 |
||
486 |
--echo # 10. Read-write statement: REPLACE, change 0 rows. |
|
487 |
--echo # |
|
488 |
replace t1 set a=1; |
|
489 |
call p_verify_status_increment(2, 2, 1, 0); |
|
490 |
commit; |
|
491 |
call p_verify_status_increment(2, 2, 1, 0); |
|
492 |
||
493 |
--echo # 11. Read-write statement: IODKU, change 1 row. |
|
494 |
--echo # |
|
495 |
insert t1 set a=1 on duplicate key update a=a+1; |
|
496 |
call p_verify_status_increment(2, 2, 2, 2); |
|
497 |
select * from t1; |
|
498 |
call p_verify_status_increment(1, 0, 1, 0); |
|
499 |
commit; |
|
500 |
call p_verify_status_increment(2, 2, 2, 2); |
|
501 |
||
502 |
--echo # 12. Read-write statement: IODKU, change 0 rows. |
|
503 |
--echo # |
|
504 |
insert t1 set a=2 on duplicate key update a=2; |
|
505 |
call p_verify_status_increment(1, 0, 1, 0); |
|
506 |
commit; |
|
507 |
call p_verify_status_increment(1, 0, 1, 0); |
|
508 |
||
509 |
--echo # 13. Read-write statement: INSERT IGNORE, change 0 rows. |
|
510 |
--echo # |
|
511 |
insert ignore t1 set a=2; |
|
512 |
call p_verify_status_increment(1, 0, 1, 0); |
|
513 |
commit; |
|
514 |
call p_verify_status_increment(1, 0, 1, 0); |
|
515 |
||
516 |
--echo # 14. Read-write statement: INSERT IGNORE, change 1 row. |
|
517 |
--echo # |
|
518 |
insert ignore t1 set a=1; |
|
519 |
call p_verify_status_increment(2, 2, 2, 2); |
|
520 |
commit; |
|
521 |
call p_verify_status_increment(2, 2, 2, 2); |
|
522 |
--echo # 15. Read-write statement: UPDATE IGNORE, change 0 rows. |
|
523 |
--echo # |
|
524 |
update ignore t1 set a=2 where a=1; |
|
525 |
call p_verify_status_increment(2, 2, 1, 0); |
|
526 |
commit; |
|
527 |
call p_verify_status_increment(2, 2, 1, 0); |
|
528 |
--echo # |
|
529 |
--echo # Create a stored function that modifies a |
|
530 |
--echo # non-transactional table. Demonstrate that changes in |
|
531 |
--echo # non-transactional tables do not affect the two phase commit |
|
532 |
--echo # algorithm. |
|
533 |
--echo # |
|
534 |
delimiter |; |
|
535 |
create function f1() returns int |
|
536 |
begin
|
|
537 |
insert t2 set a=2; |
|
538 |
return 2; |
|
539 |
end| |
|
540 |
delimiter ;| |
|
541 |
call p_verify_status_increment(0, 0, 0, 0); |
|
542 |
||
543 |
--echo # 16. A function changes non-trans-table. |
|
544 |
--echo # |
|
545 |
--echo # For row-based logging, there is an extra commit for the |
|
546 |
--echo # non-transactional changes saved in the transaction cache to |
|
547 |
--echo # the binary log. |
|
548 |
--echo # |
|
549 |
select f1(); |
|
550 |
call p_verify_status_increment(0, 0, 1, 0); |
|
551 |
commit; |
|
552 |
call p_verify_status_increment(0, 0, 1, 0); |
|
553 |
||
554 |
--echo # 17. Read-only statement, a function changes non-trans-table. |
|
555 |
--echo # |
|
556 |
--echo # For row-based logging, there is an extra commit for the |
|
557 |
--echo # non-transactional changes saved in the transaction cache to |
|
558 |
--echo # the binary log. |
|
559 |
--echo # |
|
560 |
select f1() from t1; |
|
561 |
call p_verify_status_increment(1, 0, 2, 0); |
|
562 |
commit; |
|
563 |
call p_verify_status_increment(1, 0, 2, 0); |
|
564 |
||
565 |
--echo # 18. Read-write statement: UPDATE, change 0 (transactional) rows. |
|
566 |
--echo # |
|
567 |
select count(*) from t2; |
|
568 |
update t1 set a=2 where a=f1()+10; |
|
569 |
select count(*) from t2; |
|
570 |
call p_verify_status_increment(2, 0, 2, 0); |
|
571 |
commit; |
|
572 |
call p_verify_status_increment(2, 0, 2, 0); |
|
573 |
--echo # |
|
574 |
--echo # Replace the non-transactional table with a temporary |
|
575 |
--echo # transactional table. Demonstrate that a change to a temporary |
|
576 |
--echo # transactional table does not provoke 2-phase commit, although |
|
577 |
--echo # does trigger a commit and a binlog write (in statement mode). |
|
578 |
--echo # |
|
579 |
drop table t2; |
|
580 |
set sql_mode=no_engine_substitution; |
|
581 |
create temporary table t2 (a int); |
|
582 |
call p_verify_status_increment(0, 0, 0, 0); |
|
583 |
set sql_mode=default; |
|
584 |
--echo # 19. A function changes temp-trans-table. |
|
585 |
--echo # |
|
586 |
select f1(); |
|
587 |
--echo # Two commits because a binary log record is written |
|
588 |
call p_verify_status_increment(2, 0, 1, 0); |
|
589 |
commit; |
|
590 |
call p_verify_status_increment(2, 0, 1, 0); |
|
591 |
||
592 |
--echo # 20. Read-only statement, a function changes non-trans-table. |
|
593 |
--echo # |
|
594 |
select f1() from t1; |
|
595 |
--echo # Two commits because a binary log record is written |
|
596 |
call p_verify_status_increment(2, 0, 1, 0); |
|
597 |
commit; |
|
598 |
call p_verify_status_increment(2, 0, 1, 0); |
|
599 |
||
600 |
--echo # 21. Read-write statement: UPDATE, change 0 (transactional) rows. |
|
601 |
--echo # |
|
602 |
update t1 set a=2 where a=f1()+10; |
|
603 |
call p_verify_status_increment(2, 0, 1, 0); |
|
604 |
commit; |
|
605 |
call p_verify_status_increment(2, 0, 1, 0); |
|
606 |
||
607 |
--echo # 22. DDL: ALTER TEMPORARY TABLE, should not cause a 2pc |
|
608 |
--echo # |
|
609 |
alter table t2 add column b int default 5; |
|
610 |
--echo # A commit is done internally by ALTER. |
|
611 |
call p_verify_status_increment(2, 0, 2, 0); |
|
612 |
commit; |
|
613 |
--echo # There is nothing left to commit |
|
614 |
call p_verify_status_increment(0, 0, 0, 0); |
|
615 |
||
616 |
--echo # 23. DDL: RENAME TEMPORARY TABLE, does not start a transaction |
|
617 |
--echo |
|
618 |
--echo # No test because of Bug#8729 "rename table fails on temporary table" |
|
619 |
||
620 |
--echo # 24. DDL: TRUNCATE TEMPORARY TABLE, does not start a transaction |
|
621 |
--echo |
|
622 |
truncate table t2; |
|
623 |
call p_verify_status_increment(2, 0, 2, 0); |
|
624 |
commit; |
|
625 |
--echo # There is nothing left to commit |
|
626 |
call p_verify_status_increment(0, 0, 0, 0); |
|
627 |
||
628 |
--echo # 25. Read-write statement: unqualified DELETE |
|
629 |
--echo |
|
630 |
delete from t2; |
|
631 |
call p_verify_status_increment(2, 0, 1, 0); |
|
632 |
commit; |
|
633 |
--echo # There is nothing left to commit |
|
634 |
call p_verify_status_increment(2, 0, 1, 0); |
|
635 |
||
636 |
--echo # 25. DDL: DROP TEMPORARY TABLE, does not start a transaction |
|
637 |
--echo # |
|
638 |
drop temporary table t2; |
|
639 |
call p_verify_status_increment(0, 0, 0, 0); |
|
640 |
commit; |
|
641 |
call p_verify_status_increment(0, 0, 0, 0); |
|
642 |
||
643 |
--echo # 26. Verify that SET AUTOCOMMIT issues an implicit commit |
|
644 |
--echo # |
|
645 |
insert t1 set a=3; |
|
646 |
call p_verify_status_increment(2, 2, 2, 2); |
|
647 |
set autocommit=1; |
|
648 |
call p_verify_status_increment(2, 2, 2, 2); |
|
649 |
rollback; |
|
650 |
select a from t1 where a=3; |
|
651 |
call p_verify_status_increment(1, 0, 1, 0); |
|
652 |
delete from t1 where a=3; |
|
653 |
call p_verify_status_increment(2, 2, 2, 2); |
|
654 |
commit; |
|
655 |
call p_verify_status_increment(0, 0, 0, 0); |
|
656 |
set autocommit=0; |
|
657 |
call p_verify_status_increment(0, 0, 0, 0); |
|
658 |
insert t1 set a=3; |
|
659 |
call p_verify_status_increment(2, 2, 2, 2); |
|
660 |
--echo # Sic: not actually changing the value of autocommit |
|
661 |
set autocommit=0; |
|
662 |
call p_verify_status_increment(0, 0, 0, 0); |
|
663 |
rollback; |
|
664 |
select a from t1 where a=3; |
|
665 |
call p_verify_status_increment(1, 0, 1, 0); |
|
666 |
||
667 |
--echo # 27. Savepoint management |
|
668 |
--echo # |
|
669 |
insert t1 set a=3; |
|
670 |
call p_verify_status_increment(2, 2, 2, 2); |
|
671 |
savepoint a; |
|
672 |
call p_verify_status_increment(0, 0, 0, 0); |
|
673 |
insert t1 set a=4; |
|
674 |
--echo # Sic: a bug. Binlog did not register itself this time. |
|
675 |
call p_verify_status_increment(1, 0, 1, 0); |
|
676 |
release savepoint a; |
|
677 |
rollback; |
|
678 |
call p_verify_status_increment(0, 0, 0, 0); |
|
679 |
select a from t1 where a=3; |
|
680 |
call p_verify_status_increment(1, 0, 1, 0); |
|
681 |
commit; |
|
682 |
call p_verify_status_increment(1, 0, 1, 0); |
|
683 |
||
684 |
--echo # 28. Read-write statement: DO |
|
685 |
--echo # |
|
686 |
create table t2 (a int); |
|
687 |
call p_verify_status_increment(0, 0, 0, 0); |
|
688 |
do (select f1() from t1 where a=2); |
|
689 |
call p_verify_status_increment(2, 2, 2, 2); |
|
690 |
commit; |
|
691 |
call p_verify_status_increment(2, 2, 2, 2); |
|
692 |
||
693 |
--echo # 29. Read-write statement: MULTI-DELETE |
|
694 |
--echo # |
|
695 |
delete t1, t2 from t1 join t2 on (t1.a=t2.a) where t1.a=2; |
|
696 |
commit; |
|
697 |
call p_verify_status_increment(4, 4, 4, 4); |
|
698 |
||
699 |
--echo # 30. Read-write statement: INSERT-SELECT, MULTI-UPDATE, REPLACE-SELECT |
|
700 |
--echo # |
|
701 |
insert into t2 select a from t1; |
|
702 |
commit; |
|
703 |
replace into t2 select a from t1; |
|
704 |
commit; |
|
705 |
call p_verify_status_increment(8, 8, 8, 8); |
|
706 |
#
|
|
707 |
# Multi-update is one of the few remaining statements that still |
|
708 |
# locks the tables at prepare step (and hence starts the transaction. |
|
709 |
# Disable the PS protocol, since in this protocol we get a different |
|
710 |
# number of commmits (there is an extra commit after prepare |
|
711 |
#
|
|
712 |
--disable_ps_protocol |
|
713 |
update t1, t2 set t1.a=4, t2.a=8 where t1.a=t2.a and t1.a=1; |
|
714 |
--enable_ps_protocol |
|
715 |
commit; |
|
716 |
call p_verify_status_increment(4, 4, 4, 4); |
|
717 |
||
718 |
--echo # 31. DDL: various DDL with transactional tables |
|
719 |
--echo # |
|
720 |
--echo # Sic: no table is created. |
|
721 |
create table if not exists t2 (a int) select 6 union select 7; |
|
722 |
--echo # Sic: first commits the statement, and then the transaction. |
|
723 |
call p_verify_status_increment(4, 4, 4, 4); |
|
724 |
create table t3 select a from t2; |
|
725 |
call p_verify_status_increment(4, 4, 4, 4); |
|
726 |
alter table t3 add column (b int); |
|
727 |
call p_verify_status_increment(2, 0, 2, 0); |
|
728 |
alter table t3 rename t4; |
|
729 |
call p_verify_status_increment(1, 0, 1, 0); |
|
730 |
rename table t4 to t3; |
|
731 |
call p_verify_status_increment(1, 0, 1, 0); |
|
732 |
truncate table t3; |
|
733 |
call p_verify_status_increment(2, 2, 2, 2); |
|
734 |
create view v1 as select * from t2; |
|
735 |
call p_verify_status_increment(1, 0, 1, 0); |
|
736 |
check table t1; |
|
737 |
call p_verify_status_increment(3, 0, 3, 0); |
|
738 |
--echo # Sic: after this bug is fixed, CHECK leaves no pending transaction |
|
739 |
commit; |
|
740 |
call p_verify_status_increment(0, 0, 0, 0); |
|
741 |
check table t1, t2, t3; |
|
742 |
call p_verify_status_increment(6, 0, 6, 0); |
|
743 |
commit; |
|
744 |
call p_verify_status_increment(0, 0, 0, 0); |
|
745 |
drop view v1; |
|
746 |
call p_verify_status_increment(0, 0, 0, 0); |
|
747 |
||
748 |
--echo # |
|
749 |
--echo # Cleanup |
|
750 |
--echo # |
|
751 |
drop table t1, t2, t3; |
|
752 |
drop procedure p_verify_status_increment; |
|
753 |
drop function f1; |