1call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); 2set sql_mode=no_engine_substitution; 3set default_storage_engine = InnoDB; 4set autocommit=1; 5drop table if exists t1; 6drop table if exists t2; 7drop table if exists t3; 8drop function if exists f2; 9drop procedure if exists bug12713_call; 10drop procedure if exists bug12713_dump_spvars; 11drop procedure if exists dummy; 12create table t1 (a int); 13create table t2 (a int unique); 14create table t3 (a int); 15set sql_mode=default; 16insert into t1 (a) values (1), (2); 17insert into t3 (a) values (1), (2); 18create function f2(x int) returns int 19begin 20insert into t2 (a) values (x); 21insert into t2 (a) values (x); 22return x; 23end| 24set autocommit=0; 25flush status; 26insert into t2 (a) values (1001); 27insert into t1 (a) values (f2(1)); 28ERROR 23000: Duplicate entry '1' for key 'a' 29select * from t2; 30a 311001 32rollback; 33select * from t2; 34a 35insert into t2 (a) values (1002); 36insert into t3 (a) select f2(2) from t1; 37ERROR 23000: Duplicate entry '2' for key 'a' 38select * from t2; 39a 401002 41rollback; 42select * from t2; 43a 44insert into t2 (a) values (1003); 45update t1 set a= a + f2(3); 46ERROR 23000: Duplicate entry '3' for key 'a' 47select * from t2; 48a 491003 50rollback; 51select * from t2; 52a 53insert into t2 (a) values (1004); 54update t1, t3 set t1.a = 0, t3.a = 0 where (f2(4) = 4) and (t1.a = t3.a); 55ERROR 23000: Duplicate entry '4' for key 'a' 56select * from t2; 57a 581004 59rollback; 60select * from t2; 61a 62insert into t2 (a) values (1005); 63delete from t1 where (a = f2(5)); 64ERROR 23000: Duplicate entry '5' for key 'a' 65select * from t2; 66a 671005 68rollback; 69select * from t2; 70a 71insert into t2 (a) values (1006); 72delete from t1, t3 using t1, t3 where (f2(6) = 6) ; 73ERROR 23000: Duplicate entry '6' for key 'a' 74select * from t2; 75a 761006 77rollback; 78select * from t2; 79a 80insert into t2 (a) values (1007); 81replace t1 values (f2(7)); 82ERROR 23000: Duplicate entry '7' for key 'a' 83select * from t2; 84a 851007 86rollback; 87select * from t2; 88a 89insert into t2 (a) values (1008); 90replace into t3 (a) select f2(8) from t1; 91ERROR 23000: Duplicate entry '8' for key 'a' 92select * from t2; 93a 941008 95rollback; 96select * from t2; 97a 98insert into t2 (a) values (1009); 99select f2(9) from t1 ; 100ERROR 23000: Duplicate entry '9' for key 'a' 101select * from t2; 102a 1031009 104rollback; 105select * from t2; 106a 107insert into t2 (a) values (1010); 108show databases where (f2(10) = 10); 109ERROR 23000: Duplicate entry '10' for key 'a' 110select * from t2; 111a 1121010 113rollback; 114select * from t2; 115a 116insert into t2 (a) values (1011); 117show tables where (f2(11) = 11); 118ERROR 23000: Duplicate entry '11' for key 'a' 119select * from t2; 120a 1211011 122rollback; 123select * from t2; 124a 125insert into t2 (a) values (1012); 126show triggers where (f2(12) = 12); 127ERROR 23000: Duplicate entry '12' for key 'a' 128select * from t2; 129a 1301012 131rollback; 132select * from t2; 133a 134insert into t2 (a) values (1013); 135show table status where (f2(13) = 13); 136ERROR 23000: Duplicate entry '13' for key 'a' 137select * from t2; 138a 1391013 140rollback; 141select * from t2; 142a 143insert into t2 (a) values (1014); 144show open tables where (f2(14) = 14); 145ERROR 23000: Duplicate entry '14' for key 'a' 146select * from t2; 147a 1481014 149rollback; 150select * from t2; 151a 152insert into t2 (a) values (1015); 153show columns in mysql.proc where (f2(15) = 15); 154ERROR 23000: Duplicate entry '15' for key 'a' 155select * from t2; 156a 1571015 158rollback; 159select * from t2; 160a 161insert into t2 (a) values (1016); 162show status where (f2(16) = 16); 163ERROR 23000: Duplicate entry '16' for key 'a' 164select * from t2; 165a 1661016 167rollback; 168select * from t2; 169a 170insert into t2 (a) values (1017); 171show variables where (f2(17) = 17); 172ERROR 23000: Duplicate entry '17' for key 'a' 173select * from t2; 174a 1751017 176rollback; 177select * from t2; 178a 179insert into t2 (a) values (1018); 180show charset where (f2(18) = 18); 181ERROR 23000: Duplicate entry '18' for key 'a' 182select * from t2; 183a 1841018 185rollback; 186select * from t2; 187a 188insert into t2 (a) values (1019); 189show collation where (f2(19) = 19); 190ERROR 23000: Duplicate entry '19' for key 'a' 191select * from t2; 192a 1931019 194rollback; 195select * from t2; 196a 197# We need at least one procedure to make sure the WHERE clause is 198# evaluated 199create procedure dummy() begin end; 200insert into t2 (a) values (1020); 201show procedure status where (f2(20) = 20); 202ERROR 23000: Duplicate entry '20' for key 'a' 203select * from t2; 204a 2051020 206rollback; 207select * from t2; 208a 209drop procedure dummy; 210insert into t2 (a) values (1021); 211show function status where (f2(21) = 21); 212ERROR 23000: Duplicate entry '21' for key 'a' 213select * from t2; 214a 2151021 216rollback; 217select * from t2; 218a 219insert into t2 (a) values (1022); 220prepare stmt from "insert into t1 (a) values (f2(22))"; 221execute stmt; 222ERROR 23000: Duplicate entry '22' for key 'a' 223select * from t2; 224a 2251022 226rollback; 227select * from t2; 228a 229insert into t2 (a) values (1023); 230do (f2(23)); 231Warnings: 232Error 1062 Duplicate entry '23' for key 'a' 233Note 4094 At line 4 in test.f2 234select * from t2; 235a 2361023 237rollback; 238select * from t2; 239a 240create procedure bug12713_call () 241begin 242insert into t2 (a) values (24); 243insert into t2 (a) values (24); 244end| 245insert into t2 (a) values (1024); 246call bug12713_call(); 247ERROR 23000: Duplicate entry '24' for key 'a' 248select * from t2; 249a 25024 2511024 252rollback; 253select * from t2; 254a 255======================================================================= 256Testing select_to_file 257======================================================================= 258insert into t2 (a) values (1025); 259select f2(25) into outfile "../tmp/dml.out" from t1; 260ERROR 23000: Duplicate entry '25' for key 'a' 261select * from t2; 262a 2631025 264rollback; 265select * from t2; 266a 267insert into t2 (a) values (1026); 268load data infile "../../std_data/words.dat" ignore into table t1 (a) set a:=f2(26); 269ERROR 23000: Duplicate entry '26' for key 'a' 270select * from t2; 271a 2721026 273rollback; 274select * from t2; 275a 276======================================================================= 277Testing select_dumpvar 278======================================================================= 279insert into t2 (a) values (1027); 280select f2(27) into @foo; 281ERROR 23000: Duplicate entry '27' for key 'a' 282select * from t2; 283a 2841027 285rollback; 286select * from t2; 287a 288======================================================================= 289Testing Select_fetch_into_spvars 290======================================================================= 291create procedure bug12713_dump_spvars () 292begin 293declare foo int; 294declare continue handler for sqlexception 295begin 296select "Exception trapped"; 297end; 298select f2(28) into foo; 299select * from t2; 300end| 301insert into t2 (a) values (1028); 302call bug12713_dump_spvars (); 303Exception trapped 304Exception trapped 305a 3061028 307rollback; 308select * from t2; 309a 310======================================================================= 311Cleanup 312======================================================================= 313set autocommit=default; 314drop table t1; 315drop table t2; 316drop table t3; 317drop function f2; 318drop procedure bug12713_call; 319drop procedure bug12713_dump_spvars; 320# 321# Bug#12713 Error in a stored function called from a SELECT doesn't 322# cause ROLLBACK of statem 323# 324# Verify that two-phase commit is not issued for read-only 325# transactions. 326# 327# Verify that two-phase commit is issued for read-write transactions, 328# even if the change is done inside a stored function called from 329# SELECT or SHOW statement. 330# 331set autocommit=0; 332drop table if exists t1; 333drop table if exists t2; 334drop function if exists f1; 335drop procedure if exists p_verify_status_increment; 336set @binlog_format=@@global.binlog_format; 337set sql_mode=no_engine_substitution; 338create table t1 (a int unique); 339create table t2 (a int) engine=myisam; 340set sql_mode=default; 341# 342# An auxiliary procedure to track Handler_prepare and Handler_commit 343# statistics. 344# 345create procedure 346p_verify_status_increment(commit_inc_mixed int, prepare_inc_mixed int, 347commit_inc_row int, prepare_inc_row int) 348begin 349declare commit_inc int; 350declare prepare_inc int; 351declare old_commit_count int default ifnull(@commit_count, 0); 352declare old_prepare_count int default ifnull(@prepare_count, 0); 353declare c_res int; 354# Use a cursor to have just one access to I_S instead of 2, it is very slow 355# and amounts for over 90% of test CPU time 356declare c cursor for 357select variable_value 358from information_schema.session_status 359where variable_name='Handler_commit' or variable_name='Handler_prepare' 360 order by variable_name; 361if @binlog_format = 'ROW' then 362set commit_inc= commit_inc_row; 363set prepare_inc= prepare_inc_row; 364else 365set commit_inc= commit_inc_mixed; 366set prepare_inc= prepare_inc_mixed; 367end if; 368open c; 369fetch c into c_res; 370set @commit_count=c_res; 371fetch c into c_res; 372set @prepare_count=c_res; 373close c; 374if old_commit_count + commit_inc <> @commit_count then 375select concat("Expected commit increment: ", commit_inc, 376" actual: ", @commit_count - old_commit_count) 377as 'ERROR'; 378elseif old_prepare_count + prepare_inc <> @prepare_count then 379select concat("Expected prepare increment: ", prepare_inc, 380" actual: ", @prepare_count - old_prepare_count) 381as 'ERROR'; 382else 383select '' as 'SUCCESS'; 384end if; 385end| 386# Reset Handler_commit and Handler_prepare counters 387flush status; 388# 389# Count of reading of p_verify_status_increment() from mysql.proc 390call p_verify_status_increment(2, 0, 2, 0); 391SUCCESS 392 393# 394# 1. Read-only statement: SELECT 395# 396select * from t1; 397a 398call p_verify_status_increment(1, 0, 1, 0); 399SUCCESS 400 401commit; 402call p_verify_status_increment(1, 0, 1, 0); 403SUCCESS 404 405# 2. Read-write statement: INSERT, insert 1 row. 406# 407insert into t1 (a) values (1); 408call p_verify_status_increment(2, 2, 2, 2); 409SUCCESS 410 411commit; 412call p_verify_status_increment(2, 2, 2, 2); 413SUCCESS 414 415# 3. Read-write statement: UPDATE, update 1 row. 416# 417update t1 set a=2; 418call p_verify_status_increment(2, 2, 2, 2); 419SUCCESS 420 421commit; 422call p_verify_status_increment(2, 2, 2, 2); 423SUCCESS 424 425# 4. Read-write statement: UPDATE, update 0 rows, 1 row matches WHERE 426# 427update t1 set a=2; 428call p_verify_status_increment(2, 0, 1, 0); 429SUCCESS 430 431commit; 432call p_verify_status_increment(2, 0, 1, 0); 433SUCCESS 434 435# 5. Read-write statement: UPDATE, update 0 rows, 0 rows match WHERE 436# 437# In mixed replication mode, there is a read-only transaction 438# in InnoDB and also the statement is written to the binary log. 439# So we have two commits but no 2pc, since the first engine's 440# transaction is read-only. 441# In the row level replication mode, we only have the read-only 442# transaction in InnoDB and nothing is written to the binary log. 443# 444update t1 set a=3 where a=1; 445call p_verify_status_increment(2, 0, 1, 0); 446SUCCESS 447 448commit; 449call p_verify_status_increment(2, 0, 1, 0); 450SUCCESS 451 452# 6. Read-write statement: DELETE, delete 0 rows. 453# 454delete from t1 where a=1; 455call p_verify_status_increment(2, 0, 1, 0); 456SUCCESS 457 458commit; 459call p_verify_status_increment(2, 0, 1, 0); 460SUCCESS 461 462# 7. Read-write statement: DELETE, delete 1 row. 463# 464delete from t1 where a=2; 465call p_verify_status_increment(2, 2, 2, 2); 466SUCCESS 467 468commit; 469call p_verify_status_increment(2, 2, 2, 2); 470SUCCESS 471 472# 8. Read-write statement: unqualified DELETE 473# 474# In statement or mixed replication mode, we call 475# handler::ha_delete_all_rows() and write statement text 476# to the binary log. This results in two read-write transactions. 477# In row level replication mode, we do not call 478# handler::ha_delete_all_rows(), but delete rows one by one. 479# Since there are no rows, nothing is written to the binary log. 480# Thus we have just one read-only transaction in InnoDB. 481delete from t1; 482call p_verify_status_increment(2, 2, 1, 0); 483SUCCESS 484 485commit; 486call p_verify_status_increment(2, 2, 1, 0); 487SUCCESS 488 489# 9. Read-write statement: REPLACE, change 1 row. 490# 491replace t1 set a=1; 492call p_verify_status_increment(2, 2, 2, 2); 493SUCCESS 494 495commit; 496call p_verify_status_increment(2, 2, 2, 2); 497SUCCESS 498 499# 10. Read-write statement: REPLACE, change 0 rows. 500# 501replace t1 set a=1; 502call p_verify_status_increment(2, 2, 1, 0); 503SUCCESS 504 505commit; 506call p_verify_status_increment(2, 2, 1, 0); 507SUCCESS 508 509# 11. Read-write statement: IODKU, change 1 row. 510# 511insert t1 set a=1 on duplicate key update a=a+1; 512call p_verify_status_increment(2, 2, 2, 2); 513SUCCESS 514 515select * from t1; 516a 5172 518call p_verify_status_increment(1, 0, 1, 0); 519SUCCESS 520 521commit; 522call p_verify_status_increment(2, 2, 2, 2); 523SUCCESS 524 525# 12. Read-write statement: IODKU, change 0 rows. 526# 527insert t1 set a=2 on duplicate key update a=2; 528call p_verify_status_increment(2, 2, 1, 0); 529SUCCESS 530 531commit; 532call p_verify_status_increment(2, 2, 1, 0); 533SUCCESS 534 535# 13. Read-write statement: INSERT IGNORE, change 0 rows. 536# 537insert ignore t1 set a=2; 538Warnings: 539Warning 1062 Duplicate entry '2' for key 'a' 540call p_verify_status_increment(2, 2, 1, 0); 541SUCCESS 542 543commit; 544call p_verify_status_increment(2, 2, 1, 0); 545SUCCESS 546 547# 14. Read-write statement: INSERT IGNORE, change 1 row. 548# 549insert ignore t1 set a=1; 550call p_verify_status_increment(2, 2, 2, 2); 551SUCCESS 552 553commit; 554call p_verify_status_increment(2, 2, 2, 2); 555SUCCESS 556 557# 15. Read-write statement: UPDATE IGNORE, change 0 rows. 558# 559update ignore t1 set a=2 where a=1; 560SUCCESS 561 562commit; 563SUCCESS 564 565# 566# Create a stored function that modifies a 567# non-transactional table. Demonstrate that changes in 568# non-transactional tables do not affect the two phase commit 569# algorithm. 570# 571create function f1() returns int 572begin 573insert t2 set a=2; 574return 2; 575end| 576call p_verify_status_increment(4, 0, 4, 0); 577SUCCESS 578 579# 16. A function changes non-trans-table. 580# 581# For row-based logging, there is an extra commit for the 582# non-transactional changes saved in the transaction cache to 583# the binary log. 584# 585select f1(); 586f1() 5872 588call p_verify_status_increment(3, 0, 3, 0); 589SUCCESS 590 591commit; 592call p_verify_status_increment(1, 0, 1, 0); 593SUCCESS 594 595# 17. Read-only statement, a function changes non-trans-table. 596# 597# For row-based logging, there is an extra commit for the 598# non-transactional changes saved in the transaction cache to 599# the binary log. 600# 601select f1() from t1; 602f1() 6032 6042 605call p_verify_status_increment(2, 0, 2, 0); 606SUCCESS 607 608commit; 609call p_verify_status_increment(2, 0, 2, 0); 610SUCCESS 611 612# 18. Read-write statement: UPDATE, change 0 (transactional) rows. 613# 614select count(*) from t2; 615count(*) 6163 617update t1 set a=2 where a=f1()+10; 618select count(*) from t2; 619count(*) 6205 621call p_verify_status_increment(2, 0, 2, 0); 622SUCCESS 623 624commit; 625call p_verify_status_increment(2, 0, 2, 0); 626SUCCESS 627 628# 629# Replace the non-transactional table with a temporary 630# transactional table. Demonstrate that a change to a temporary 631# transactional table does not provoke 2-phase commit, although 632# does trigger a commit and a binlog write (in statement mode). 633# 634drop table t2; 635set sql_mode=no_engine_substitution; 636create temporary table t2 (a int); 637call p_verify_status_increment(1, 0, 0, 0); 638SUCCESS 639 640set sql_mode=default; 641# 19. A function changes temp-trans-table. 642# 643select f1(); 644f1() 6452 646# Two commits because a binary log record is written 647call p_verify_status_increment(2, 0, 1, 0); 648SUCCESS 649 650commit; 651call p_verify_status_increment(2, 0, 1, 0); 652SUCCESS 653 654# 20. Read-only statement, a function changes non-trans-table. 655# 656select f1() from t1; 657f1() 6582 6592 660# Two commits because a binary log record is written 661call p_verify_status_increment(2, 0, 1, 0); 662SUCCESS 663 664commit; 665call p_verify_status_increment(2, 0, 1, 0); 666SUCCESS 667 668# 21. Read-write statement: UPDATE, change 0 (transactional) rows. 669# 670update t1 set a=2 where a=f1()+10; 671call p_verify_status_increment(2, 0, 1, 0); 672SUCCESS 673 674commit; 675call p_verify_status_increment(2, 0, 1, 0); 676SUCCESS 677 678# 22. DDL: ALTER TEMPORARY TABLE, should not cause a 2pc 679# 680alter table t2 add column b int default 5; 681# A commit is done internally by ALTER. 682call p_verify_status_increment(2, 0, 2, 0); 683SUCCESS 684 685commit; 686# There is nothing left to commit 687call p_verify_status_increment(0, 0, 0, 0); 688SUCCESS 689 690# 23. DDL: RENAME TEMPORARY TABLE, does not start a transaction 691 692# No test because of Bug#8729 "rename table fails on temporary table" 693# 24. DDL: TRUNCATE TEMPORARY TABLE 694 695truncate table t2; 696call p_verify_status_increment(2, 0, 2, 0); 697SUCCESS 698 699commit; 700# There is nothing left to commit 701call p_verify_status_increment(0, 0, 0, 0); 702SUCCESS 703 704# 25. Read-write statement: unqualified DELETE 705 706delete from t2; 707call p_verify_status_increment(2, 0, 1, 0); 708SUCCESS 709 710commit; 711# There is nothing left to commit 712call p_verify_status_increment(2, 0, 1, 0); 713SUCCESS 714 715# 25. DDL: DROP TEMPORARY TABLE, does not start a transaction 716# 717drop temporary table t2; 718call p_verify_status_increment(1, 0, 1, 0); 719SUCCESS 720 721commit; 722call p_verify_status_increment(1, 0, 1, 0); 723SUCCESS 724 725# 26. Verify that SET AUTOCOMMIT issues an implicit commit 726# 727insert t1 set a=3; 728call p_verify_status_increment(2, 2, 2, 2); 729SUCCESS 730 731set autocommit=1; 732call p_verify_status_increment(2, 2, 2, 2); 733SUCCESS 734 735rollback; 736select a from t1 where a=3; 737a 7383 739call p_verify_status_increment(1, 0, 1, 0); 740SUCCESS 741 742delete from t1 where a=3; 743call p_verify_status_increment(2, 2, 2, 2); 744SUCCESS 745 746commit; 747call p_verify_status_increment(0, 0, 0, 0); 748SUCCESS 749 750set autocommit=0; 751call p_verify_status_increment(0, 0, 0, 0); 752SUCCESS 753 754insert t1 set a=3; 755call p_verify_status_increment(2, 2, 2, 2); 756SUCCESS 757 758# Sic: not actually changing the value of autocommit 759set autocommit=0; 760call p_verify_status_increment(0, 0, 0, 0); 761SUCCESS 762 763rollback; 764select a from t1 where a=3; 765a 766call p_verify_status_increment(1, 0, 1, 0); 767SUCCESS 768 769# 27. Savepoint management 770# 771insert t1 set a=3; 772call p_verify_status_increment(2, 2, 2, 2); 773SUCCESS 774 775savepoint a; 776call p_verify_status_increment(1, 0, 1, 0); 777SUCCESS 778 779insert t1 set a=4; 780call p_verify_status_increment(2, 2, 2, 2); 781SUCCESS 782 783release savepoint a; 784rollback; 785call p_verify_status_increment(0, 0, 0, 0); 786SUCCESS 787 788select a from t1 where a=3; 789a 790call p_verify_status_increment(1, 0, 1, 0); 791SUCCESS 792 793commit; 794call p_verify_status_increment(1, 0, 1, 0); 795SUCCESS 796 797# 28. Read-write statement: DO 798# 799create table t2 (a int); 800call p_verify_status_increment(0, 0, 0, 0); 801SUCCESS 802 803do (select f1() from t1 where a=2); 804call p_verify_status_increment(2, 2, 2, 2); 805SUCCESS 806 807commit; 808call p_verify_status_increment(2, 2, 2, 2); 809SUCCESS 810 811# 29. Read-write statement: MULTI-DELETE 812# 813delete t1, t2 from t1 join t2 on (t1.a=t2.a) where t1.a=2; 814commit; 815call p_verify_status_increment(4, 4, 4, 4); 816SUCCESS 817 818# 30. Read-write statement: INSERT-SELECT, MULTI-UPDATE, REPLACE-SELECT 819# 820insert into t2 select a from t1; 821commit; 822replace into t2 select a from t1; 823commit; 824call p_verify_status_increment(8, 8, 8, 8); 825SUCCESS 826 827update t1, t2 set t1.a=4, t2.a=8 where t1.a=t2.a and t1.a=1; 828commit; 829call p_verify_status_increment(4, 4, 4, 4); 830SUCCESS 831 832# 31. DDL: various DDL with transactional tables 833# 834# Sic: no table is created. 835create table if not exists t2 (a int) select 6 union select 7; 836Warnings: 837Note 1050 Table 't2' already exists 838# Sic: first commits the statement, and then the transaction. 839call p_verify_status_increment(0, 0, 0, 0); 840SUCCESS 841 842create table t3 select a from t2; 843call p_verify_status_increment(2, 0, 4, 4); 844SUCCESS 845 846alter table t3 add column (b int); 847call p_verify_status_increment(2, 0, 2, 0); 848SUCCESS 849 850alter table t3 rename t4; 851call p_verify_status_increment(0, 0, 0, 0); 852SUCCESS 853 854rename table t4 to t3; 855call p_verify_status_increment(0, 0, 0, 0); 856SUCCESS 857 858truncate table t3; 859call p_verify_status_increment(2, 0, 2, 0); 860SUCCESS 861 862create view v1 as select * from t2; 863call p_verify_status_increment(4, 0, 4, 0); 864SUCCESS 865 866check table t1; 867Table Op Msg_type Msg_text 868test.t1 check status OK 869call p_verify_status_increment(2, 0, 2, 0); 870SUCCESS 871 872# Sic: after this bug is fixed, CHECK leaves no pending transaction 873commit; 874call p_verify_status_increment(0, 0, 0, 0); 875SUCCESS 876 877check table t1, t2, t3; 878Table Op Msg_type Msg_text 879test.t1 check status OK 880test.t2 check status OK 881test.t3 check status OK 882call p_verify_status_increment(4, 0, 4, 0); 883SUCCESS 884 885commit; 886call p_verify_status_increment(0, 0, 0, 0); 887SUCCESS 888 889drop view v1; 890call p_verify_status_increment(2, 0, 2, 0); 891SUCCESS 892 893# 894# Cleanup 895# 896drop table t1, t2, t3; 897drop procedure p_verify_status_increment; 898drop function f1; 899