diff --git a/mysql-test/main/information_schema_db.result b/mysql-test/main/information_schema_db.result index f86764f1be7..aa081171f3d 100644 --- a/mysql-test/main/information_schema_db.result +++ b/mysql-test/main/information_schema_db.result @@ -213,11 +213,8 @@ connection default; use test; drop view testdb_1.v1, v2, testdb_1.v3, v4; drop database testdb_1; -connection testdb_1; disconnect testdb_1; -connection testdb_2; disconnect testdb_2; -connection default; drop user testdb_1@localhost; drop user testdb_2@localhost; # @@ -249,18 +246,18 @@ ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for table ` connection default; drop user mysqltest_1@localhost; drop database testdb_1; -connection user1; disconnect user1; -connection default; set global sql_mode=default; # # MDEV-20549 SQL SECURITY DEFINER does not work for INFORMATION_SCHEMA tables # create user foo@localhost; grant select on test.* to foo@localhost; +connect foo,localhost,foo; +connection default; create procedure rootonly() select 1; -create sql security definer view v1d as select current_user(),user from information_schema.processlist where command!='daemon'; -create sql security invoker view v1i as select current_user(),user from information_schema.processlist where command!='daemon'; +create sql security definer view v1d as select current_user(),user from information_schema.processlist where id in($default_id, $foo_id) order by user; +create sql security invoker view v1i as select current_user(),user from information_schema.processlist where id in($default_id, $foo_id) order by user; create sql security definer view v2d as select table_name from information_schema.tables where table_schema='mysql' and table_name like '%user%'; create sql security invoker view v2i as select table_name from information_schema.tables where table_schema='mysql' and table_name like '%user%'; create sql security definer view v3d as select schema_name from information_schema.schemata where schema_name like '%mysql%'; @@ -269,7 +266,7 @@ create sql security definer view v4d as select routine_name from information_sch create sql security invoker view v4i as select routine_name from information_schema.routines where routine_schema='test'; create sql security definer view v5d as select view_definition > '' from information_schema.views where table_name='v1d'; create sql security invoker view v5i as select view_definition > '' from information_schema.views where table_name='v1d'; -connect foo,localhost,foo; +connection foo; select * from v1d; current_user() user root@localhost root diff --git a/mysql-test/main/information_schema_db.test b/mysql-test/main/information_schema_db.test index d367045e78d..6441d8ed6ee 100644 --- a/mysql-test/main/information_schema_db.test +++ b/mysql-test/main/information_schema_db.test @@ -207,13 +207,8 @@ connection default; use test; drop view testdb_1.v1, v2, testdb_1.v3, v4; drop database testdb_1; -connection testdb_1; disconnect testdb_1; ---source include/wait_until_disconnected.inc -connection testdb_2; disconnect testdb_2; ---source include/wait_until_disconnected.inc -connection default; drop user testdb_1@localhost; drop user testdb_2@localhost; @@ -244,10 +239,7 @@ show create view testdb_1.v1; connection default; drop user mysqltest_1@localhost; drop database testdb_1; -connection user1; disconnect user1; ---source include/wait_until_disconnected.inc -connection default; set global sql_mode=default; @@ -257,9 +249,13 @@ set global sql_mode=default; create user foo@localhost; grant select on test.* to foo@localhost; +let $default_id= `select connection_id()`; +connect foo,localhost,foo; +let $foo_id= `select connection_id()`; +connection default; create procedure rootonly() select 1; -create sql security definer view v1d as select current_user(),user from information_schema.processlist where command!='daemon'; -create sql security invoker view v1i as select current_user(),user from information_schema.processlist where command!='daemon'; +evalp create sql security definer view v1d as select current_user(),user from information_schema.processlist where id in($default_id, $foo_id) order by user; +evalp create sql security invoker view v1i as select current_user(),user from information_schema.processlist where id in($default_id, $foo_id) order by user; create sql security definer view v2d as select table_name from information_schema.tables where table_schema='mysql' and table_name like '%user%'; create sql security invoker view v2i as select table_name from information_schema.tables where table_schema='mysql' and table_name like '%user%'; create sql security definer view v3d as select schema_name from information_schema.schemata where schema_name like '%mysql%'; @@ -268,7 +264,7 @@ create sql security definer view v4d as select routine_name from information_sch create sql security invoker view v4i as select routine_name from information_schema.routines where routine_schema='test'; create sql security definer view v5d as select view_definition > '' from information_schema.views where table_name='v1d'; create sql security invoker view v5i as select view_definition > '' from information_schema.views where table_name='v1d'; -connect foo,localhost,foo; +connection foo; select * from v1d; select * from v1i; select * from v2d; diff --git a/mysql-test/main/limit_rows_examined.result b/mysql-test/main/limit_rows_examined.result index cd2f00fcec8..007b281001f 100644 --- a/mysql-test/main/limit_rows_examined.result +++ b/mysql-test/main/limit_rows_examined.result @@ -932,3 +932,14 @@ Warnings: Warning 1931 Query execution was interrupted. The query exceeded LIMIT ROWS EXAMINED 100. The query result may be incomplete DROP TABLE t1, t2; # End of 10.5 tests +# +# MDEV-22241: Assertion `0' failed in Protocol::end_statement after query with LIMIT ROWS EXAMINED +# +CREATE TABLE t1 (a int); +INSERT INTO t1 VALUES (1); +SELECT 1 FROM t1 +WHERE (1 IN (SELECT 8 UNION SELECT 5)) OR t1.a = 2 +LIMIT ROWS EXAMINED 1; +1 +DROP TABLE t1; +# End of 10.11 tests diff --git a/mysql-test/main/limit_rows_examined.test b/mysql-test/main/limit_rows_examined.test index e79f1fc0360..2fe7ef24fe8 100644 --- a/mysql-test/main/limit_rows_examined.test +++ b/mysql-test/main/limit_rows_examined.test @@ -658,3 +658,18 @@ SELECT COUNT(*) FROM t1 JOIN t2 ON (b = a) UNION DISTINCT SELECT COUNT(*) FROM t DROP TABLE t1, t2; --echo # End of 10.5 tests + +--echo # +--echo # MDEV-22241: Assertion `0' failed in Protocol::end_statement after query with LIMIT ROWS EXAMINED +--echo # + +CREATE TABLE t1 (a int); +INSERT INTO t1 VALUES (1); + +SELECT 1 FROM t1 +WHERE (1 IN (SELECT 8 UNION SELECT 5)) OR t1.a = 2 +LIMIT ROWS EXAMINED 1; + +DROP TABLE t1; + +--echo # End of 10.11 tests diff --git a/mysql-test/suite/encryption/r/recovery_memory.result b/mysql-test/suite/encryption/r/recovery_memory.result index 1b02fb6d31d..270c331e2f8 100644 --- a/mysql-test/suite/encryption/r/recovery_memory.result +++ b/mysql-test/suite/encryption/r/recovery_memory.result @@ -1,3 +1,5 @@ +SET GLOBAL innodb_encrypt_tables=ON,innodb_encryption_threads=1; +SET GLOBAL innodb_saved_page_number_debug=4,innodb_fil_make_page_dirty_debug=0; CREATE TABLE t1(f1 text, index idx(f1(20))) ENGINE INNODB; set global innodb_fast_shutdown=0; # restart: --debug_dbug=+d,ib_log_checkpoint_avoid_hard --innodb_flush_sync=0 diff --git a/mysql-test/suite/encryption/t/recovery_memory.combinations b/mysql-test/suite/encryption/t/recovery_memory.combinations new file mode 100644 index 00000000000..f985eb1f7d3 --- /dev/null +++ b/mysql-test/suite/encryption/t/recovery_memory.combinations @@ -0,0 +1,4 @@ +[full_crc32] +--innodb-checksum-algorithm=full_crc32 +[crc32] +--innodb-checksum-algorithm=crc32 diff --git a/mysql-test/suite/encryption/t/recovery_memory.test b/mysql-test/suite/encryption/t/recovery_memory.test index 64963c3e2e1..fc6f15f7ee2 100644 --- a/mysql-test/suite/encryption/t/recovery_memory.test +++ b/mysql-test/suite/encryption/t/recovery_memory.test @@ -5,6 +5,9 @@ let $basedir=$MYSQLTEST_VARDIR/tmp/backup; let MYSQLD_DATADIR=`select @@datadir`; +# Encrypt the change buffer root page +SET GLOBAL innodb_encrypt_tables=ON,innodb_encryption_threads=1; +SET GLOBAL innodb_saved_page_number_debug=4,innodb_fil_make_page_dirty_debug=0; CREATE TABLE t1(f1 text, index idx(f1(20))) ENGINE INNODB; diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def index 438b1e63cfd..bbcba108fee 100644 --- a/mysql-test/suite/galera/disabled.def +++ b/mysql-test/suite/galera/disabled.def @@ -12,7 +12,6 @@ galera_wan : MDEV-35940 Unallowed state transition: donor -> synced in galera_wan galera_vote_rejoin_ddl : MDEV-35940 Unallowed state transition: donor -> synced in galera_wan -MW-329 : MDEV-35951 Complete freeze during MW-329 test galera_vote_rejoin_dml : MDEV-35964 Assertion `ist_seqno >= cc_seqno' failed in galera_vote_rejoin_dml galera_var_notify_cmd : MDEV-37257 WSREP: Notification command failed: 1 (Operation not permitted) galera_var_notify_ssl_ipv6 : MDEV-37257 WSREP: Notification command failed: 1 (Operation not permitted) diff --git a/mysql-test/suite/galera/r/MW-329.result b/mysql-test/suite/galera/r/MW-329.result index 37a97f57f98..1a027e7c911 100644 --- a/mysql-test/suite/galera/r/MW-329.result +++ b/mysql-test/suite/galera/r/MW-329.result @@ -14,10 +14,11 @@ END| connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1; connection node_1b; connection node_1; +connect node_1c, 127.0.0.1, root, , test, $NODE_MYPORT_1; +connection node_1c; connection node_1b; connection node_1; DROP PROCEDURE proc_insert; DROP TABLE t1; disconnect node_1b; -CALL mtr.add_suppression("WSREP: .* conflict state after post commit "); -set global innodb_status_output=Default; +disconnect node_1c; diff --git a/mysql-test/suite/galera/r/galera_multi_level_fk_ddl_insert.result b/mysql-test/suite/galera/r/galera_multi_level_fk_ddl_insert.result new file mode 100644 index 00000000000..aa120e87cb9 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_multi_level_fk_ddl_insert.result @@ -0,0 +1,364 @@ +connection node_2; +connection node_1; +# +# 1. BF-BF conflict on MDL locks between: DROP TABLE t4 and INSERT t1 +# with foreign key references as below: +# - t1<-t2<-t3<-t4 +# +connection node_2; +SET GLOBAL wsrep_slave_threads=2; +CREATE TABLE t1 ( +id INTEGER PRIMARY KEY, +f2 INTEGER +); +CREATE TABLE t2 ( +id INT PRIMARY KEY, +t1_id INT NOT NULL, +f2 INTEGER NOT NULL, +KEY key_t1_id(t1_id), +CONSTRAINT key_t1_id FOREIGN KEY (t1_id) REFERENCES t1 (id) ON UPDATE CASCADE ON DELETE CASCADE +); +CREATE TABLE t3 ( +id INT PRIMARY KEY, +t2_id INT NOT NULL, +f2 INTEGER NOT NULL, +KEY key_t2_id(t2_id), +CONSTRAINT key_t2_id FOREIGN KEY (t2_id) REFERENCES t2 (id) ON UPDATE CASCADE ON DELETE CASCADE +); +CREATE TABLE t4 ( +id INT PRIMARY KEY, +t3_id INT NOT NULL, +f2 INTEGER NOT NULL, +KEY key_t3_id(t3_id), +CONSTRAINT key_t3_id FOREIGN KEY (t3_id) REFERENCES t3 (id) ON UPDATE CASCADE ON DELETE CASCADE +); +INSERT INTO t1 VALUES (1,0); +INSERT INTO t1 VALUES (2,0); +INSERT INTO t2 VALUES (1,1,1234); +INSERT INTO t2 VALUES (2,2,1234); +INSERT INTO t3 VALUES (1,1,1234); +INSERT INTO t3 VALUES (2,2,1234); +INSERT INTO t4 VALUES (1,1,1234); +INSERT INTO t4 VALUES (2,2,1234); +connection node_2; +SET GLOBAL DEBUG_DBUG = '+d,sync.wsrep_apply_toi'; +connection node_1; +DROP TABLE t4; +connection node_2; +SET DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_toi_reached"; +SET SESSION wsrep_sync_wait = 0; +connection node_1; +SET GLOBAL DEBUG_DBUG = '+d,wsrep_print_foreign_keys_table'; +START TRANSACTION; +INSERT INTO t1 VALUES (3,0); +COMMIT; +connection node_2; +SET GLOBAL DEBUG_DBUG = '-d,sync.wsrep_apply_toi'; +SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_toi"; +SET DEBUG_SYNC = 'RESET'; +SET GLOBAL DEBUG_DBUG = ""; +SET GLOBAL wsrep_slave_threads=DEFAULT; +connection node_1; +SET DEBUG_SYNC = 'RESET'; +SET GLOBAL DEBUG_DBUG = ""; +SET GLOBAL wsrep_slave_threads=DEFAULT; +connection node_1; +include/assert_grep.inc [Foreign key referenced table found: 2 tables] +include/assert_grep.inc [Foreign key referenced table found: test.t2] +include/assert_grep.inc [Foreign key referenced table found: test.t3] +connection node_2; +select * from t1; +id f2 +1 0 +2 0 +3 0 +select * from t2; +id t1_id f2 +1 1 1234 +2 2 1234 +select * from t3; +id t2_id f2 +1 1 1234 +2 2 1234 +select * from t4; +ERROR 42S02: Table 'test.t4' doesn't exist +connection node_1; +select * from t1; +id f2 +1 0 +2 0 +3 0 +select * from t2; +id t1_id f2 +1 1 1234 +2 2 1234 +select * from t3; +id t2_id f2 +1 1 1234 +2 2 1234 +select * from t4; +ERROR 42S02: Table 'test.t4' doesn't exist +DROP TABLE t3, t2, t1; +# +# 2. BF-BF conflict on MDL locks between: +# ALTER TABLE t4 (whose parent table are t4 -> t3 -> t2 -> t1), and +# INSERT on t1. +# +connection node_2; +SET GLOBAL wsrep_slave_threads=2; +CREATE TABLE t1 ( +id INTEGER PRIMARY KEY, +f2 INTEGER +); +CREATE TABLE t2 ( +id INT PRIMARY KEY, +t1_id INT NOT NULL, +f2 INTEGER NOT NULL, +KEY key_t1_id(t1_id), +CONSTRAINT key_t1_id FOREIGN KEY (t1_id) REFERENCES t1 (id) ON UPDATE CASCADE ON DELETE CASCADE +); +CREATE TABLE t3 ( +id INT PRIMARY KEY, +t2_id INT NOT NULL, +f2 INTEGER NOT NULL, +KEY key_t2_id(t2_id), +CONSTRAINT key_t2_id FOREIGN KEY (t2_id) REFERENCES t2 (id) ON UPDATE CASCADE ON DELETE CASCADE +); +CREATE TABLE t4 ( +id INT PRIMARY KEY, +t3_id INT NOT NULL, +f2 INTEGER NOT NULL, +KEY key_t3_id(t3_id) +); +INSERT INTO t1 VALUES (1,0); +INSERT INTO t1 VALUES (2,0); +INSERT INTO t2 VALUES (1,1,1234); +INSERT INTO t2 VALUES (2,2,1234); +INSERT INTO t3 VALUES (1,1,1234); +INSERT INTO t3 VALUES (2,2,1234); +INSERT INTO t4 VALUES (1,1,1234); +INSERT INTO t4 VALUES (2,2,1234); +connection node_2; +SET GLOBAL DEBUG_DBUG = '+d,sync.wsrep_apply_toi'; +connection node_1; +ALTER TABLE t4 ADD CONSTRAINT key_t3_id FOREIGN KEY (t3_id) REFERENCES t3 (id) ON UPDATE CASCADE ON DELETE CASCADE; +connection node_2; +SET DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_toi_reached"; +SET SESSION wsrep_sync_wait = 0; +connection node_1; +SET GLOBAL DEBUG_DBUG = '+d,wsrep_print_foreign_keys_table'; +START TRANSACTION; +INSERT INTO t1 VALUES (3,0); +COMMIT; +connection node_2; +SET GLOBAL DEBUG_DBUG = '-d,sync.wsrep_apply_toi'; +SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_toi"; +SET DEBUG_SYNC = 'RESET'; +SET GLOBAL DEBUG_DBUG = ""; +SET GLOBAL wsrep_slave_threads=DEFAULT; +connection node_1; +SET DEBUG_SYNC = 'RESET'; +SET GLOBAL DEBUG_DBUG = ""; +SET GLOBAL wsrep_slave_threads=DEFAULT; +connection node_1; +include/assert_grep.inc [Foreign key referenced table found: 3 tables] +include/assert_grep.inc [Foreign key referenced table found: test.t2] +include/assert_grep.inc [Foreign key referenced table found: test.t3] +include/assert_grep.inc [Foreign key referenced table found: test.t4] +connection node_2; +select * from t1; +id f2 +1 0 +2 0 +3 0 +select * from t2; +id t1_id f2 +1 1 1234 +2 2 1234 +select * from t3; +id t2_id f2 +1 1 1234 +2 2 1234 +connection node_1; +select * from t1; +id f2 +1 0 +2 0 +3 0 +select * from t2; +id t1_id f2 +1 1 1234 +2 2 1234 +select * from t3; +id t2_id f2 +1 1 1234 +2 2 1234 +DROP TABLE t4, t3, t2, t1; +# +# 3. BF-BF conflict on MDL locks between: +# CREATE TABLE t3 (whose parent table are t4 -> t3 -> t2 -> t1), and +# INSERT on t1. +# +connection node_2; +SET GLOBAL wsrep_slave_threads=2; +CREATE TABLE t1 ( +id INTEGER PRIMARY KEY, +f2 INTEGER +); +CREATE TABLE t2 ( +id INT PRIMARY KEY, +t1_id INT NOT NULL, +f2 INTEGER NOT NULL, +KEY key_t1_id(t1_id), +CONSTRAINT key_t1_id FOREIGN KEY (t1_id) REFERENCES t1 (id) ON UPDATE CASCADE ON DELETE CASCADE +); +CREATE TABLE t3 ( +id INT PRIMARY KEY, +t2_id INT NOT NULL, +f2 INTEGER NOT NULL, +KEY key_t2_id(t2_id), +CONSTRAINT key_t2_id FOREIGN KEY (t2_id) REFERENCES t2 (id) ON UPDATE CASCADE ON DELETE CASCADE +); +INSERT INTO t1 VALUES (1,0); +INSERT INTO t1 VALUES (2,0); +INSERT INTO t2 VALUES (1,1,1234); +INSERT INTO t2 VALUES (2,2,1234); +INSERT INTO t3 VALUES (1,1,1234); +INSERT INTO t3 VALUES (2,2,1234); +connection node_2; +SET GLOBAL DEBUG_DBUG = '+d,sync.wsrep_apply_toi'; +connection node_1; +CREATE TABLE t4 (id INT PRIMARY KEY, t3_id INT NOT NULL, f2 INTEGER NOT NULL, KEY key_t3_id(t3_id), CONSTRAINT key_t3_id FOREIGN KEY (t3_id) REFERENCES t3 (id) ON UPDATE CASCADE ON DELETE CASCADE); +connection node_2; +SET DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_toi_reached"; +SET SESSION wsrep_sync_wait = 0; +connection node_1; +SET GLOBAL DEBUG_DBUG = '+d,wsrep_print_foreign_keys_table'; +START TRANSACTION; +INSERT INTO t1 VALUES (3,0); +COMMIT; +connection node_2; +SET GLOBAL DEBUG_DBUG = '-d,sync.wsrep_apply_toi'; +SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_toi"; +SET DEBUG_SYNC = 'RESET'; +SET GLOBAL DEBUG_DBUG = ""; +SET GLOBAL wsrep_slave_threads=DEFAULT; +connection node_1; +SET DEBUG_SYNC = 'RESET'; +SET GLOBAL DEBUG_DBUG = ""; +SET GLOBAL wsrep_slave_threads=DEFAULT; +connection node_1; +include/assert_grep.inc [Foreign key referenced table found: 2 tables] +include/assert_grep.inc [Foreign key referenced table found: test.t2] +include/assert_grep.inc [Foreign key referenced table found: test.t3] +include/assert_grep.inc [Foreign key referenced table found: test.t4] +connection node_2; +select * from t1; +id f2 +1 0 +2 0 +3 0 +select * from t2; +id t1_id f2 +1 1 1234 +2 2 1234 +select * from t3; +id t2_id f2 +1 1 1234 +2 2 1234 +connection node_1; +select * from t1; +id f2 +1 0 +2 0 +3 0 +select * from t2; +id t1_id f2 +1 1 1234 +2 2 1234 +select * from t3; +id t2_id f2 +1 1 1234 +2 2 1234 +DROP TABLE t4, t3, t2, t1; +# +# 4. BF-BF conflict on MDL locks between: +# OPTIMIZE TABLE t2 (whose parent table are t2 -> t1), and +# INSERT t1. +# +connection node_2; +SET GLOBAL wsrep_slave_threads=2; +CREATE TABLE t1 ( +id INTEGER PRIMARY KEY, +f2 INTEGER +); +CREATE TABLE t2 ( +id INT PRIMARY KEY, +t1_id INT NOT NULL, +f2 INTEGER NOT NULL, +KEY key_t1_id(t1_id), +CONSTRAINT key_t1_id FOREIGN KEY (t1_id) REFERENCES t1 (id) ON UPDATE CASCADE ON DELETE CASCADE +); +CREATE TABLE t3 ( +id INT PRIMARY KEY, +t2_id INT NOT NULL, +f2 INTEGER NOT NULL, +KEY key_t2_id(t2_id), +CONSTRAINT key_t2_id FOREIGN KEY (t2_id) REFERENCES t2 (id) ON UPDATE CASCADE ON DELETE CASCADE +); +INSERT INTO t1 VALUES (1,0); +INSERT INTO t1 VALUES (2,0); +INSERT INTO t2 VALUES (1,1,1234); +INSERT INTO t2 VALUES (2,2,1234); +INSERT INTO t3 VALUES (1,1,1234); +INSERT INTO t3 VALUES (2,2,1234); +connection node_2; +SET GLOBAL DEBUG_DBUG = '+d,sync.wsrep_apply_toi'; +connection node_1; +OPTIMIZE TABLE t3; +Table Op Msg_type Msg_text +test.t3 optimize note Table does not support optimize, doing recreate + analyze instead +test.t3 optimize status OK +connection node_2; +SET DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_toi_reached"; +SET SESSION wsrep_sync_wait = 0; +connection node_1; +SET GLOBAL DEBUG_DBUG = '+d,wsrep_print_foreign_keys_table'; +START TRANSACTION; +INSERT INTO t1 VALUES (3,0); +COMMIT; +connection node_2; +SET GLOBAL DEBUG_DBUG = '-d,sync.wsrep_apply_toi'; +SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_toi"; +SET DEBUG_SYNC = 'RESET'; +SET GLOBAL DEBUG_DBUG = ""; +SET GLOBAL wsrep_slave_threads=DEFAULT; +connection node_1; +SET DEBUG_SYNC = 'RESET'; +SET GLOBAL DEBUG_DBUG = ""; +SET GLOBAL wsrep_slave_threads=DEFAULT; +connection node_1; +include/assert_grep.inc [Foreign key referenced table found: 1 tables] +include/assert_grep.inc [Foreign key referenced table found: test.t2] +include/assert_grep.inc [Foreign key referenced table found: test.t3] +connection node_2; +select * from t1; +id f2 +1 0 +2 0 +3 0 +select * from t2; +id t1_id f2 +1 1 1234 +2 2 1234 +connection node_1; +select * from t1; +id f2 +1 0 +2 0 +3 0 +select * from t2; +id t1_id f2 +1 1 1234 +2 2 1234 +DROP TABLE t3, t2, t1; diff --git a/mysql-test/suite/galera/t/MW-329.test b/mysql-test/suite/galera/t/MW-329.test index 7d132a7bfc0..9d05ab6cf10 100644 --- a/mysql-test/suite/galera/t/MW-329.test +++ b/mysql-test/suite/galera/t/MW-329.test @@ -83,7 +83,19 @@ while ($count) --connection node_1 --disable_query_log ---eval KILL CONNECTION $connection_id +--eval KILL HARD CONNECTION $connection_id +--enable_query_log +--connect node_1c, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--connection node_1c + +--disable_query_log +# Make sure connection is killed +while (`SELECT COUNT(*) > 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE ID = $connection_id`) +{ + SELECT SLEEP(1); +--error 0,ER_NO_SUCH_THREAD,ER_QUERY_INTERRUPTED,ER_CONNECTION_KILLED +--eval KILL HARD CONNECTION $connection_id +} --enable_query_log # @@ -101,8 +113,4 @@ DROP PROCEDURE proc_insert; DROP TABLE t1; --disconnect node_1b - -# Due to MW-330, Multiple "conflict state 3 after post commit" warnings if table is dropped while SP is running -CALL mtr.add_suppression("WSREP: .* conflict state after post commit "); - -set global innodb_status_output=Default; +--disconnect node_1c diff --git a/mysql-test/suite/galera/t/galera_multi_level_fk_ddl_insert.test b/mysql-test/suite/galera/t/galera_multi_level_fk_ddl_insert.test new file mode 100644 index 00000000000..78e5054a7cd --- /dev/null +++ b/mysql-test/suite/galera/t/galera_multi_level_fk_ddl_insert.test @@ -0,0 +1,454 @@ +# +# BF-BF conflict on MDL locks between DDL and insert query +# when multi-level foreign key like t3 -> t2 -> t1 +# are present. +# +# If bug is present, expect the wait condition +# to timeout and when the INSERT applies, it +# will be granted a MDL lock of type SHARED_READ +# for table t1. When resumed, the DROP/ALTER/CREATE/OPTIMIZE +# TABLE will also try to MDL lock t1, causing a BF-BF conflict +# on that MDL lock. + +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/have_debug_sync.inc + +--echo # +--echo # 1. BF-BF conflict on MDL locks between: DROP TABLE t4 and INSERT t1 +--echo # with foreign key references as below: +--echo # - t1<-t2<-t3<-t4 +--echo # + +# +# Setup +# +--connection node_2 +SET GLOBAL wsrep_slave_threads=2; + +CREATE TABLE t1 ( + id INTEGER PRIMARY KEY, + f2 INTEGER +); + +CREATE TABLE t2 ( + id INT PRIMARY KEY, + t1_id INT NOT NULL, + f2 INTEGER NOT NULL, + KEY key_t1_id(t1_id), + CONSTRAINT key_t1_id FOREIGN KEY (t1_id) REFERENCES t1 (id) ON UPDATE CASCADE ON DELETE CASCADE +); + +CREATE TABLE t3 ( + id INT PRIMARY KEY, + t2_id INT NOT NULL, + f2 INTEGER NOT NULL, + KEY key_t2_id(t2_id), + CONSTRAINT key_t2_id FOREIGN KEY (t2_id) REFERENCES t2 (id) ON UPDATE CASCADE ON DELETE CASCADE +); + +CREATE TABLE t4 ( + id INT PRIMARY KEY, + t3_id INT NOT NULL, + f2 INTEGER NOT NULL, + KEY key_t3_id(t3_id), + CONSTRAINT key_t3_id FOREIGN KEY (t3_id) REFERENCES t3 (id) ON UPDATE CASCADE ON DELETE CASCADE +); + +INSERT INTO t1 VALUES (1,0); +INSERT INTO t1 VALUES (2,0); + +INSERT INTO t2 VALUES (1,1,1234); +INSERT INTO t2 VALUES (2,2,1234); + +INSERT INTO t3 VALUES (1,1,1234); +INSERT INTO t3 VALUES (2,2,1234); + +INSERT INTO t4 VALUES (1,1,1234); +INSERT INTO t4 VALUES (2,2,1234); + + +--let $fk_parent_query = DROP TABLE t4 +--let $fk_child_query = INSERT INTO t1 VALUES (3,0) +--let $fk_mdl_lock_num = 3 +--source galera_multi_level_foreign_key.inc + + +# +# Verify Foreign key for referenced table added. +# +--connection node_1 +--let assert_text= Foreign key referenced table found: 2 tables +--let $assert_file= $MYSQLTEST_VARDIR/log/mysqld.1.err +--let assert_count= 2 +--let assert_select= Foreign key referenced table found: +--let assert_only_after= CURRENT_TEST: galera.galera_multi_level_fk_ddl_insert +--source include/assert_grep.inc + +--let assert_text= Foreign key referenced table found: test.t2 +--let $assert_file= $MYSQLTEST_VARDIR/log/mysqld.1.err +--let assert_count= 1 +--let assert_select= Foreign key referenced table found: test.t2 +--let assert_only_after= CURRENT_TEST: galera.galera_multi_level_fk_ddl_insert +--source include/assert_grep.inc + +--let assert_text= Foreign key referenced table found: test.t3 +--let $assert_file= $MYSQLTEST_VARDIR/log/mysqld.1.err +--let assert_count= 1 +--let assert_select= Foreign key referenced table found: test.t3 +--let assert_only_after= CURRENT_TEST: galera.galera_multi_level_fk_ddl_insert +--source include/assert_grep.inc + + +# +# Verify insert and drop table has succeded. +# +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 3 FROM test.t1 +--source include/wait_condition.inc + +select * from t1; +select * from t2; +select * from t3; +--error ER_NO_SUCH_TABLE +select * from t4; + +--connection node_1 +select * from t1; +select * from t2; +select * from t3; +--error ER_NO_SUCH_TABLE +select * from t4; + + +# +# Cleanup +# +DROP TABLE t3, t2, t1; + + +--echo # +--echo # 2. BF-BF conflict on MDL locks between: +--echo # ALTER TABLE t4 (whose parent table are t4 -> t3 -> t2 -> t1), and +--echo # INSERT on t1. +--echo # + +# +# Setup +# +--connection node_2 +SET GLOBAL wsrep_slave_threads=2; + +CREATE TABLE t1 ( + id INTEGER PRIMARY KEY, + f2 INTEGER +); + +CREATE TABLE t2 ( + id INT PRIMARY KEY, + t1_id INT NOT NULL, + f2 INTEGER NOT NULL, + KEY key_t1_id(t1_id), + CONSTRAINT key_t1_id FOREIGN KEY (t1_id) REFERENCES t1 (id) ON UPDATE CASCADE ON DELETE CASCADE +); + +CREATE TABLE t3 ( + id INT PRIMARY KEY, + t2_id INT NOT NULL, + f2 INTEGER NOT NULL, + KEY key_t2_id(t2_id), + CONSTRAINT key_t2_id FOREIGN KEY (t2_id) REFERENCES t2 (id) ON UPDATE CASCADE ON DELETE CASCADE +); + +CREATE TABLE t4 ( + id INT PRIMARY KEY, + t3_id INT NOT NULL, + f2 INTEGER NOT NULL, + KEY key_t3_id(t3_id) +); + + +INSERT INTO t1 VALUES (1,0); +INSERT INTO t1 VALUES (2,0); + +INSERT INTO t2 VALUES (1,1,1234); +INSERT INTO t2 VALUES (2,2,1234); + +INSERT INTO t3 VALUES (1,1,1234); +INSERT INTO t3 VALUES (2,2,1234); + +INSERT INTO t4 VALUES (1,1,1234); +INSERT INTO t4 VALUES (2,2,1234); + + +# +# ALTER TABLE t3 and wait for it to reach node_2 +# +--let $fk_parent_query = ALTER TABLE t4 ADD CONSTRAINT key_t3_id FOREIGN KEY (t3_id) REFERENCES t3 (id) ON UPDATE CASCADE ON DELETE CASCADE +# +# Issue a INSERT to table that references t1 +# +--let $fk_child_query = INSERT INTO t1 VALUES (3,0) +--let $fk_mdl_lock_num = 4 +--source galera_multi_level_foreign_key.inc + + +# +# Verify Foreign key for referenced table added. +# +--connection node_1 +--let assert_text= Foreign key referenced table found: 3 tables +--let $assert_file= $MYSQLTEST_VARDIR/log/mysqld.1.err +--let assert_count= 5 +--let assert_select= Foreign key referenced table found: +--let assert_only_after= CURRENT_TEST: galera.galera_multi_level_fk_ddl_insert +--source include/assert_grep.inc + +--let assert_text= Foreign key referenced table found: test.t2 +--let $assert_file= $MYSQLTEST_VARDIR/log/mysqld.1.err +--let assert_count= 2 +--let assert_select= Foreign key referenced table found: test.t2 +--let assert_only_after= CURRENT_TEST: galera.galera_multi_level_fk_ddl_insert +--source include/assert_grep.inc + +--let assert_text= Foreign key referenced table found: test.t3 +--let $assert_file= $MYSQLTEST_VARDIR/log/mysqld.1.err +--let assert_count= 2 +--let assert_select= Foreign key referenced table found: test.t3 +--let assert_only_after= CURRENT_TEST: galera.galera_multi_level_fk_ddl_insert +--source include/assert_grep.inc + +--let assert_text= Foreign key referenced table found: test.t4 +--let $assert_file= $MYSQLTEST_VARDIR/log/mysqld.1.err +--let assert_count= 1 +--let assert_select= Foreign key referenced table found: test.t4 +--let assert_only_after= CURRENT_TEST: galera.galera_multi_level_fk_ddl_insert +--source include/assert_grep.inc + + +# +# Verify insert has succeded. +# +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 3 FROM test.t1 +--source include/wait_condition.inc + +select * from t1; +select * from t2; +select * from t3; + +--connection node_1 +select * from t1; +select * from t2; +select * from t3; + + +# +# Cleanup +# +DROP TABLE t4, t3, t2, t1; + + +--echo # +--echo # 3. BF-BF conflict on MDL locks between: +--echo # CREATE TABLE t3 (whose parent table are t4 -> t3 -> t2 -> t1), and +--echo # INSERT on t1. +--echo # + +# +# Setup +# +--connection node_2 +SET GLOBAL wsrep_slave_threads=2; + +CREATE TABLE t1 ( + id INTEGER PRIMARY KEY, + f2 INTEGER +); + +CREATE TABLE t2 ( + id INT PRIMARY KEY, + t1_id INT NOT NULL, + f2 INTEGER NOT NULL, + KEY key_t1_id(t1_id), + CONSTRAINT key_t1_id FOREIGN KEY (t1_id) REFERENCES t1 (id) ON UPDATE CASCADE ON DELETE CASCADE +); + +CREATE TABLE t3 ( + id INT PRIMARY KEY, + t2_id INT NOT NULL, + f2 INTEGER NOT NULL, + KEY key_t2_id(t2_id), + CONSTRAINT key_t2_id FOREIGN KEY (t2_id) REFERENCES t2 (id) ON UPDATE CASCADE ON DELETE CASCADE +); + +INSERT INTO t1 VALUES (1,0); +INSERT INTO t1 VALUES (2,0); + +INSERT INTO t2 VALUES (1,1,1234); +INSERT INTO t2 VALUES (2,2,1234); + +INSERT INTO t3 VALUES (1,1,1234); +INSERT INTO t3 VALUES (2,2,1234); + + +--let $fk_parent_query = CREATE TABLE t4 (id INT PRIMARY KEY, t3_id INT NOT NULL, f2 INTEGER NOT NULL, KEY key_t3_id(t3_id), CONSTRAINT key_t3_id FOREIGN KEY (t3_id) REFERENCES t3 (id) ON UPDATE CASCADE ON DELETE CASCADE) +--let $fk_child_query = INSERT INTO t1 VALUES (3,0) +--let $fk_mdl_lock_num = 4 +--source galera_multi_level_foreign_key.inc + + +# +# Verify Foreign key for referenced table added. +# +--connection node_1 +--let assert_text= Foreign key referenced table found: 2 tables +--let $assert_file= $MYSQLTEST_VARDIR/log/mysqld.1.err +--let assert_count= 8 +--let assert_select= Foreign key referenced table found: +--let $assert_only_after = CURRENT_TEST: +--let assert_only_after= CURRENT_TEST: galera.galera_multi_level_fk_ddl_insert +--source include/assert_grep.inc + +--let assert_text= Foreign key referenced table found: test.t2 +--let $assert_file= $MYSQLTEST_VARDIR/log/mysqld.1.err +--let assert_count= 3 +--let assert_select= Foreign key referenced table found: test.t2 +--let assert_only_after= CURRENT_TEST: galera.galera_multi_level_fk_ddl_insert +--source include/assert_grep.inc + +--let assert_text= Foreign key referenced table found: test.t3 +--let $assert_file= $MYSQLTEST_VARDIR/log/mysqld.1.err +--let assert_count= 3 +--let assert_select= Foreign key referenced table found: test.t3 +--let assert_only_after= CURRENT_TEST: galera.galera_multi_level_fk_ddl_insert +--source include/assert_grep.inc + +--let assert_text= Foreign key referenced table found: test.t4 +--let $assert_file= $MYSQLTEST_VARDIR/log/mysqld.1.err +--let assert_count= 2 +--let assert_select= Foreign key referenced table found: test.t4 +--let assert_only_after= CURRENT_TEST: galera.galera_multi_level_fk_ddl_insert +--source include/assert_grep.inc + + +# +# Verify insert has succeded. +# +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 3 FROM test.t1 +--source include/wait_condition.inc + +select * from t1; +select * from t2; +select * from t3; + +--connection node_1 +select * from t1; +select * from t2; +select * from t3; + + +# +# Cleanup +# +DROP TABLE t4, t3, t2, t1; + + +--echo # +--echo # 4. BF-BF conflict on MDL locks between: +--echo # OPTIMIZE TABLE t2 (whose parent table are t2 -> t1), and +--echo # INSERT t1. +--echo # + +# +# Setup +# +--connection node_2 +SET GLOBAL wsrep_slave_threads=2; + +CREATE TABLE t1 ( + id INTEGER PRIMARY KEY, + f2 INTEGER +); + +CREATE TABLE t2 ( + id INT PRIMARY KEY, + t1_id INT NOT NULL, + f2 INTEGER NOT NULL, + KEY key_t1_id(t1_id), + CONSTRAINT key_t1_id FOREIGN KEY (t1_id) REFERENCES t1 (id) ON UPDATE CASCADE ON DELETE CASCADE +); + +CREATE TABLE t3 ( + id INT PRIMARY KEY, + t2_id INT NOT NULL, + f2 INTEGER NOT NULL, + KEY key_t2_id(t2_id), + CONSTRAINT key_t2_id FOREIGN KEY (t2_id) REFERENCES t2 (id) ON UPDATE CASCADE ON DELETE CASCADE +); + + +INSERT INTO t1 VALUES (1,0); +INSERT INTO t1 VALUES (2,0); + +INSERT INTO t2 VALUES (1,1,1234); +INSERT INTO t2 VALUES (2,2,1234); + +INSERT INTO t3 VALUES (1,1,1234); +INSERT INTO t3 VALUES (2,2,1234); + + +--let $fk_parent_query = OPTIMIZE TABLE t3 +--let $fk_child_query = INSERT INTO t1 VALUES (3,0) +--let $fk_mdl_lock_num = 3 +--source galera_multi_level_foreign_key.inc + + +# +# Verify Foreign key for referenced table added. +# +--connection node_1 +--let assert_text= Foreign key referenced table found: 1 tables +--let $assert_file= $MYSQLTEST_VARDIR/log/mysqld.1.err +--let assert_count= 10 +--let assert_select= Foreign key referenced table found: +--let $assert_only_after = CURRENT_TEST: +--let assert_only_after= CURRENT_TEST: galera.galera_multi_level_fk_ddl_insert +--source include/assert_grep.inc + +--let assert_text= Foreign key referenced table found: test.t2 +--let $assert_file= $MYSQLTEST_VARDIR/log/mysqld.1.err +--let assert_count= 4 +--let assert_select= Foreign key referenced table found: test.t2 +--let assert_only_after= CURRENT_TEST: galera.galera_multi_level_fk_ddl_insert +--source include/assert_grep.inc + +--let assert_text= Foreign key referenced table found: test.t3 +--let $assert_file= $MYSQLTEST_VARDIR/log/mysqld.1.err +--let assert_count= 4 +--let assert_select= Foreign key referenced table found: test.t3 +--let assert_only_after= CURRENT_TEST: galera.galera_multi_level_fk_ddl_insert +--source include/assert_grep.inc + + +# +# Verify insert has succeded. +# +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 3 FROM test.t1 +--source include/wait_condition.inc + +select * from t1; +select * from t2; + +--connection node_1 +select * from t1; +select * from t2; + + +# +# Cleanup +# +DROP TABLE t3, t2, t1; diff --git a/mysql-test/suite/galera_3nodes/r/galera_garbd_backup.result b/mysql-test/suite/galera_3nodes/r/galera_garbd_backup.result index 638b1553039..8180b7f6b53 100644 --- a/mysql-test/suite/galera_3nodes/r/galera_garbd_backup.result +++ b/mysql-test/suite/galera_3nodes/r/galera_garbd_backup.result @@ -4,25 +4,35 @@ connection node_1; connection node_2; connection node_3; connection node_1; +SET GLOBAL innodb_max_dirty_pages_pct=0.0; +SET GLOBAL innodb_max_dirty_pages_pct_lwm=0.0; SET GLOBAL innodb_max_dirty_pages_pct=99; SET GLOBAL innodb_max_dirty_pages_pct_lwm=99; -connection node_1; CREATE TABLE t1 (f1 INTEGER, f2 varchar(1024)) Engine=InnoDB; CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB; INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); INSERT INTO t1 (f2) SELECT REPEAT('x', 1024) FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4; +FLUSH TABLES WITH READ LOCK; +UNLOCK TABLES; +connection node_2; +SELECT COUNT(*) FROM t1; +COUNT(*) +10000 +SELECT COUNT(*) FROM ten; +COUNT(*) +10 Killing node #3 to free ports for garbd ... connection node_3; connection node_1; SET GLOBAL debug_dbug = "+d,sync.wsrep_donor_state"; Starting garbd ... SET SESSION debug_sync = "now WAIT_FOR sync.wsrep_donor_state_reached"; -SET GLOBAL innodb_max_dirty_pages_pct_lwm=0; -SET GLOBAL innodb_max_dirty_pages_pct=0; +SET GLOBAL innodb_max_dirty_pages_pct_lwm=0.0; +SET GLOBAL innodb_max_dirty_pages_pct=0.0; SET SESSION debug_sync = "now SIGNAL signal.wsrep_donor_state"; SET GLOBAL debug_dbug = ""; SET debug_sync='RESET'; -connection node_2; +connection node_1; Killing garbd ... connection node_1; connection node_2; @@ -31,9 +41,3 @@ DROP TABLE ten; Restarting node #3 to satisfy MTR's end-of-test checks connection node_3; connection node_1; -connection node_1; -CALL mtr.add_suppression("WSREP: Protocol violation\\. JOIN message sender 1\\.0( \\(.*\\))? is not in state transfer \\(SYNCED\\)\\. Message ignored\\."); -connection node_2; -CALL mtr.add_suppression("WSREP: Protocol violation\\. JOIN message sender 1\\.0( \\(.*\\))? is not in state transfer \\(SYNCED\\)\\. Message ignored\\."); -connection node_3; -CALL mtr.add_suppression("WSREP: Protocol violation\\. JOIN message sender 1\\.0( \\(.*\\))? is not in state transfer \\(SYNCED\\)\\. Message ignored\\."); diff --git a/mysql-test/suite/galera_3nodes/t/galera_garbd_backup.test b/mysql-test/suite/galera_3nodes/t/galera_garbd_backup.test index 61256642242..83f17c572f4 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_garbd_backup.test +++ b/mysql-test/suite/galera_3nodes/t/galera_garbd_backup.test @@ -32,14 +32,34 @@ --let $innodb_max_dirty_pages_pct = `SELECT @@innodb_max_dirty_pages_pct` --let $innodb_max_dirty_pages_pct_lwm = `SELECT @@innodb_max_dirty_pages_pct_lwm` +SET GLOBAL innodb_max_dirty_pages_pct=0.0; +SET GLOBAL innodb_max_dirty_pages_pct_lwm=0.0; + +--let $wait_condition = SELECT variable_value = 0 FROM information_schema.global_status WHERE variable_name = 'INNODB_BUFFER_POOL_PAGES_DIRTY' +--source include/wait_condition.inc + SET GLOBAL innodb_max_dirty_pages_pct=99; SET GLOBAL innodb_max_dirty_pages_pct_lwm=99; ---connection node_1 CREATE TABLE t1 (f1 INTEGER, f2 varchar(1024)) Engine=InnoDB; CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB; INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); INSERT INTO t1 (f2) SELECT REPEAT('x', 1024) FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4; +FLUSH TABLES WITH READ LOCK; +UNLOCK TABLES; + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1' +--source include/wait_condition.inc +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'ten' +--source include/wait_condition.inc +--let $wait_condition = SELECT COUNT(*) = 10 FROM ten +--source include/wait_condition.inc +--let $wait_condition = SELECT COUNT(*) = 10000 FROM t1 +--source include/wait_condition.inc + +SELECT COUNT(*) FROM t1; +SELECT COUNT(*) FROM ten; --echo Killing node #3 to free ports for garbd ... --connection node_3 @@ -60,24 +80,20 @@ SET SESSION debug_sync = "now WAIT_FOR sync.wsrep_donor_state_reached"; # # get hash of data directory contents before BP dirty page flushing # ---exec find $datadir -type f ! -name tables_flushed ! -name backup_sst_complete -exec md5sum {} \; | md5sum >$MYSQLTEST_VARDIR/tmp/innodb_before +--exec find $datadir -type f ! -name tables_flushed ! -name backup_sst_complete -print 0 -exec md5sum {} \; | sort -u | md5sum >$MYSQLTEST_VARDIR/tmp/innodb_before # this should force buffer pool flushing, if not already done by donor state change transfer -SET GLOBAL innodb_max_dirty_pages_pct_lwm=0; -SET GLOBAL innodb_max_dirty_pages_pct=0; +SET GLOBAL innodb_max_dirty_pages_pct_lwm=0.0; +SET GLOBAL innodb_max_dirty_pages_pct=0.0; ---disable_query_log ---disable_result_log -select f1 from t1; -select * from ten; ---enable_result_log ---enable_query_log +--let $wait_condition = SELECT variable_value = 0 FROM information_schema.global_status WHERE variable_name = 'INNODB_BUFFER_POOL_PAGES_DIRTY' +--source include/wait_condition.inc # # # record the hash of data directory contents after BP dirty page flushing # ---exec find $datadir -type f ! -name tables_flushed ! -name backup_sst_complete -exec md5sum {} \; | md5sum >$MYSQLTEST_VARDIR/tmp/innodb_after +--exec find $datadir -type f ! -name tables_flushed ! -name backup_sst_complete -print 0 -exec md5sum {} \; | sort -u | md5sum >$MYSQLTEST_VARDIR/tmp/innodb_after # there should be no disk writes --diff_files $MYSQLTEST_VARDIR/tmp/innodb_before $MYSQLTEST_VARDIR/tmp/innodb_after @@ -86,7 +102,7 @@ SET SESSION debug_sync = "now SIGNAL signal.wsrep_donor_state"; SET GLOBAL debug_dbug = ""; SET debug_sync='RESET'; ---connection node_2 +--connection node_1 # # garbd will die automatically, because of the backup SST script @@ -122,13 +138,3 @@ let $restart_noprint=2; # Restore original auto_increment_offset values. --source ../galera/include/auto_increment_offset_restore.inc -# Workaround for galera#101 - ---connection node_1 -CALL mtr.add_suppression("WSREP: Protocol violation\\. JOIN message sender 1\\.0( \\(.*\\))? is not in state transfer \\(SYNCED\\)\\. Message ignored\\."); - ---connection node_2 -CALL mtr.add_suppression("WSREP: Protocol violation\\. JOIN message sender 1\\.0( \\(.*\\))? is not in state transfer \\(SYNCED\\)\\. Message ignored\\."); - ---connection node_3 -CALL mtr.add_suppression("WSREP: Protocol violation\\. JOIN message sender 1\\.0( \\(.*\\))? is not in state transfer \\(SYNCED\\)\\. Message ignored\\."); diff --git a/mysys/crc32/crc32_arm64.c b/mysys/crc32/crc32_arm64.c index 6be2750ae08..2b2eb8860b3 100644 --- a/mysys/crc32/crc32_arm64.c +++ b/mysys/crc32/crc32_arm64.c @@ -143,9 +143,9 @@ asm(".arch_extension crypto"); #define CRC32C3X8(buffer, ITR) \ - __asm__("crc32cx %w[c1], %w[c1], %x[v]":[c1]"+r"(crc1):[v]"r"(*((const uint64_t *)buffer + 42*1 + (ITR))));\ - __asm__("crc32cx %w[c2], %w[c2], %x[v]":[c2]"+r"(crc2):[v]"r"(*((const uint64_t *)buffer + 42*2 + (ITR))));\ - __asm__("crc32cx %w[c0], %w[c0], %x[v]":[c0]"+r"(crc0):[v]"r"(*((const uint64_t *)buffer + 42*0 + (ITR)))); + __asm__("crc32cx %w[c1], %w[c1], %x[v]":[c1]"+r"(crc1):[v]"r"(uint8korr(buffer + (42*1 + (ITR)) * sizeof(uint64_t))));\ + __asm__("crc32cx %w[c2], %w[c2], %x[v]":[c2]"+r"(crc2):[v]"r"(uint8korr(buffer + (42*2 + (ITR)) * sizeof(uint64_t))));\ + __asm__("crc32cx %w[c0], %w[c0], %x[v]":[c0]"+r"(crc0):[v]"r"(uint8korr(buffer + (42*0 + (ITR)) * sizeof(uint64_t)))); #else /* HAVE_ARMV8_CRC_CRYPTO_INTRINSICS */ @@ -167,9 +167,9 @@ asm(".arch_extension crypto"); #define CRC32B(crc, value) (crc) = __crc32b((crc), (value)) #define CRC32C3X8(buffer, ITR) \ - crc1 = __crc32cd(crc1, *((const uint64_t *)buffer + 42*1 + (ITR)));\ - crc2 = __crc32cd(crc2, *((const uint64_t *)buffer + 42*2 + (ITR)));\ - crc0 = __crc32cd(crc0, *((const uint64_t *)buffer + 42*0 + (ITR))); + crc1 = __crc32cd(crc1, uint8korr(buffer + (42*1 + (ITR)) * sizeof(uint64_t)));\ + crc2 = __crc32cd(crc2, uint8korr(buffer + (42*2 + (ITR)) * sizeof(uint64_t)));\ + crc0 = __crc32cd(crc0, uint8korr(buffer + (42*0 + (ITR)) * sizeof(uint64_t))); #endif /* HAVE_ARMV8_CRC_CRYPTO_INTRINSICS */ @@ -234,20 +234,20 @@ static unsigned crc32c_aarch64(unsigned crc, const void *buf, size_t len) while ((length-= sizeof(uint64_t)) >= 0) { - CRC32CX(crc, *(uint64_t *)buffer); + CRC32CX(crc, uint8korr(buffer)); buffer+= sizeof(uint64_t); } /* The following is more efficient than the straight loop */ if (length & sizeof(uint32_t)) { - CRC32CW(crc, *(uint32_t *)buffer); + CRC32CW(crc, uint4korr(buffer)); buffer+= sizeof(uint32_t); } if (length & sizeof(uint16_t)) { - CRC32CH(crc, *(uint16_t *)buffer); + CRC32CH(crc, uint2korr(buffer)); buffer+= sizeof(uint16_t); } @@ -291,7 +291,7 @@ static unsigned crc32c_aarch64_pmull(unsigned crc, const void *buf, size_t len) /* Prefetch 3*1024 data for avoiding L2 cache miss */ PREF1KL2(buffer, 1024*3); /* Do first 8 bytes here for better pipelining */ - crc0= __crc32cd(crc, *(const uint64_t *)buffer); + crc0= __crc32cd(crc, uint8korr(buffer)); crc1= 0; crc2= 0; buffer+= sizeof(uint64_t); @@ -317,7 +317,7 @@ static unsigned crc32c_aarch64_pmull(unsigned crc, const void *buf, size_t len) */ t1= poly_mul(crc1, k2); t0= poly_mul(crc0, k1); - crc= __crc32cd(crc2, *(const uint64_t *)buffer); + crc= __crc32cd(crc2, uint8korr(buffer)); crc1= __crc32cd(0, t1); crc^= crc1; crc0= __crc32cd(0, t0); @@ -342,7 +342,7 @@ static unsigned crc32c_aarch64_pmull(unsigned crc, const void *buf, size_t len) PREF1KL2(buffer, 1024*3); __asm__("crc32cx %w[c0], %w[c], %x[v]\n\t" - :[c0]"=r"(crc0):[c]"r"(crc), [v]"r"(*(const uint64_t *)buffer):); + :[c0]"=r"(crc0):[c]"r"(crc), [v]"r"(uint8korr(buffer)):); crc1= 0; crc2= 0; buffer+= sizeof(uint64_t); @@ -368,7 +368,7 @@ static unsigned crc32c_aarch64_pmull(unsigned crc, const void *buf, size_t len) "crc32cx %w[c0], wzr, %x[c0] \n\t" "eor %w[c], %w[c], %w[c0] \n\t" :[c1]"+r"(crc1), [c0]"+r"(crc0), [c2]"+r"(crc2), [c]"+r"(crc) - :[v]"r"(*((const uint64_t *)buffer))); + :[v]"r"(uint8korr(buffer))); buffer+= sizeof(uint64_t); } # endif /* HAVE_ARMV8_CRC_CRYPTO_INTRINSICS */ @@ -379,20 +379,20 @@ static unsigned crc32c_aarch64_pmull(unsigned crc, const void *buf, size_t len) { while ((length-= sizeof(uint64_t)) >= 0) { - CRC32CX(crc, *(uint64_t *)buffer); + CRC32CX(crc, uint8korr(buffer)); buffer+= sizeof(uint64_t); } /* The following is more efficient than the straight loop */ if (length & sizeof(uint32_t)) { - CRC32CW(crc, *(uint32_t *)buffer); + CRC32CW(crc, uint4korr(buffer)); buffer+= sizeof(uint32_t); } if (length & sizeof(uint16_t)) { - CRC32CH(crc, *(uint16_t *)buffer); + CRC32CH(crc, uint2korr(buffer)); buffer+= sizeof(uint16_t); } @@ -426,8 +426,10 @@ unsigned int crc32_aarch64(unsigned int crc, const void *buf, size_t len) len--; } - for (; len >= 8; len-= 8) - CRC32X(crc, *buf8++); + for (; len >= 8; len-= 8) { + CRC32X(crc, uint8korr((uchar *)buf8)); + buf8++; + } buf1= (const uint8_t *) buf8; while (len--) diff --git a/plugin/auth_mysql_sha2/sha256crypt.c b/plugin/auth_mysql_sha2/sha256crypt.c index 7e4a2f285ca..aa75632452f 100644 --- a/plugin/auth_mysql_sha2/sha256crypt.c +++ b/plugin/auth_mysql_sha2/sha256crypt.c @@ -29,8 +29,11 @@ void sha256_crypt_r(const unsigned char *key, size_t key_len, unsigned char tmp[SHA256_DIGEST_LENGTH]; unsigned char alt[SHA256_DIGEST_LENGTH]; size_t cnt; - static const char b64t[64] = - "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + static const char b64t[64] +#if defined __GNUC__ && __GNUC__ > 7 + __attribute__((nonstring)) +#endif + = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; void *ctx = alloca(my_sha256_context_size()); unsigned char *p_bytes = alloca(key_len); unsigned char *s_bytes = alloca(salt_len); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 966b7c62939..e978c013d57 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -3985,6 +3985,15 @@ bool extend_table_list(THD *thd, TABLE_LIST *tables, (tables->updating && tables->lock_type >= TL_FIRST_WRITE) || thd->lex->default_used; +#ifdef WITH_WSREP + if (WSREP(thd) && !thd->wsrep_applier && + wsrep_is_active(thd) && + (sql_command_flags[thd->lex->sql_command] & CF_INSERTS_DATA) && + tables->lock_type == TL_READ) { + maybe_need_prelocking= true; + } +#endif + if (thd->locked_tables_mode <= LTM_LOCK_TABLES && ! has_prelocking_list && maybe_need_prelocking) { @@ -5115,6 +5124,7 @@ prepare_fk_prelocking_list(THD *thd, Query_tables_list *prelocking_ctx, Query_arena *arena, backup; TABLE *table= table_list->table; bool error= FALSE; + bool override_fk_ignore_table= FALSE; if (!table->file->referenced_by_foreign_key()) DBUG_RETURN(FALSE); @@ -5131,6 +5141,37 @@ prepare_fk_prelocking_list(THD *thd, Query_tables_list *prelocking_ctx, *need_prelocking= TRUE; +#ifdef WITH_WSREP + /* + MDL is enough for read-only FK checks, we don't need the table, + but on galera applier node lock_type is set to TL_FIRST_WRITE and not + TL_READ, which is due to Write_rows_log_event event logged for INSERT + is used to record insert, update and delete + (Write_rows_log_event::get_trg_event_map()), and therefore all child + tables will be opened and MDL locks will be taken on applier node, while + opening of multiple child tables is ignored on write node by setting + open_strategy= OPEN_STUB in init_one_table_for_prelocking(). + This difference in write and applier node can result in MDL deadlock. + Tables with foreign keys: t1<-t2<-t3<-t4 + Conflicting transactions: INSERT t1 and DROP TABLE t4 + Wsrep certification keys taken on write node: + - for INSERT t1: t1 and t2 + - for DROP TABLE t4: t4 + On applier node MDL deadlock happened between two transaction because + MDL locks for INSERT t1 were taken on t1, t2, t3 and t4, which conflicted + with MDL lock on t4 taken by DROP TABLE t4. + The Wsrep certification keys does helps in resolving in transactions + getting MDL deadlock. But to generate Wsrep certification keys it needs + to open and take MDL locks on all child tables. So that conflicting + transactions can be prioritize and scheduled. + */ + if (WSREP(thd) && !thd->wsrep_applier && + wsrep_is_active(thd) && + (sql_command_flags[thd->lex->sql_command] & CF_INSERTS_DATA)) { + override_fk_ignore_table= TRUE; + } +#endif // WITH_WSREP + while ((fk= fk_list_it++)) { // FK_OPTION_RESTRICT and FK_OPTION_NO_ACTION only need read access @@ -5149,13 +5190,15 @@ prepare_fk_prelocking_list(THD *thd, Query_tables_list *prelocking_ctx, TABLE_LIST *tl= thd->alloc(1); tl->init_one_table_for_prelocking(fk->foreign_db, fk->foreign_table, NULL, lock_type, TABLE_LIST::PRELOCK_FK, table_list->belong_to_view, - op, &prelocking_ctx->query_tables_last, table_list->for_insert_data); + op, &prelocking_ctx->query_tables_last, table_list->for_insert_data, + override_fk_ignore_table); #ifdef WITH_WSREP /* Append table level shared key for the referenced/foreign table for: - statement that updates existing rows (UPDATE, multi-update) - statement that deletes existing rows (DELETE, DELETE_MULTI) + - statement that inserts new rows (INSERT, REPLACE, LOAD, ALTER TABLE) This is done to avoid potential MDL conflicts with concurrent DDLs. */ if (wsrep_foreign_key_append(thd, fk)) @@ -5198,11 +5241,31 @@ bool DML_prelocking_strategy::handle_table(THD *thd, { DBUG_ENTER("handle_table"); TABLE *table= table_list->table; + bool trigger_prelocking_needed= + (table_list->lock_type >= TL_FIRST_WRITE) ? TRUE : FALSE; /* We rely on a caller to check that table is going to be changed. */ DBUG_ASSERT(table_list->lock_type >= TL_FIRST_WRITE || + ((sql_command_flags[thd->lex->sql_command] & CF_INSERTS_DATA) + && table_list->lock_type == TL_READ) || thd->lex->default_used); - if (table_list->trg_event_map && table_list->lock_type >= TL_FIRST_WRITE) +#ifdef WITH_WSREP + /* + Only do trigger prelocking for tables that are doing to be modified (with + a write lock), but ignore rest for Galera additional keys for the + referenced/foreign table are needed to avoid potential MDL conflicts with + concurrent update and DDLs. + */ + if (WSREP(thd) && !thd->wsrep_applier && + wsrep_is_active(thd) && + (sql_command_flags[thd->lex->sql_command] & CF_INSERTS_DATA) && + table_list->trg_event_map && !table->triggers) + { + trigger_prelocking_needed= TRUE; + } +#endif // WITH_WSREP + + if (table_list->trg_event_map && trigger_prelocking_needed) { if (table->triggers) { diff --git a/sql/sql_class.cc b/sql/sql_class.cc index b563925bd87..d76acf9640a 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -2482,7 +2482,7 @@ void THD::cleanup_after_query() if (!in_active_multi_stmt_transaction()) wsrep_affected_rows= 0; #endif /* WITH_WSREP */ - + gap_tracker_data.init(); DBUG_VOID_RETURN; } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index b3aaceb486a..3f630fa1b8e 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -3512,14 +3512,29 @@ public: static const ulong initial_gtid_domain_buffer_size= 16; uint32 gtid_domain_static_buffer[initial_gtid_domain_buffer_size]; - inline void set_limit_rows_examined() + /* + Activates enforcement of the LIMIT ROWS EXAMINED clause, if present + in the query. + */ + void set_limit_rows_examined() { if (limit_rows_examined) limit_rows_examined_cnt= limit_rows_examined->val_uint(); - else - limit_rows_examined_cnt= ULONGLONG_MAX; } + /** + Deactivates enforcement of the LIMIT ROWS EXAMINED clause and returns its + prior state. + Return value: + - false: LIMIT ROWS EXAMINED was not activated + - true: LIMIT ROWS EXAMINED was activated + */ + bool deactivate_limit_rows_examined() + { + bool was_activated= (limit_rows_examined_cnt != ULONGLONG_MAX); + limit_rows_examined_cnt= ULONGLONG_MAX; // Unreachable value + return was_activated; + } LEX_CSTRING *win_ref; Window_frame *win_frame; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 68131cf5880..4d4c8558902 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -665,8 +665,8 @@ bool handle_select(THD *thd, LEX *lex, select_result *result, thd->abort_on_warning= saved_abort_on_warning; thd->reset_killed(); } - /* Disable LIMIT ROWS EXAMINED after query execution. */ - thd->lex->limit_rows_examined_cnt= ULONGLONG_MAX; + /* Deactivate LIMIT ROWS EXAMINED after query execution. */ + thd->lex->deactivate_limit_rows_examined(); MYSQL_SELECT_DONE((int) res, (ulong) thd->limit_found_rows); DBUG_RETURN(res); @@ -4878,7 +4878,7 @@ int JOIN::exec_inner() THD_STAGE_INFO(thd, stage_executing); /* - Enable LIMIT ROWS EXAMINED during query execution if: + Activate enforcement of LIMIT ROWS EXAMINED during query execution if: (1) This JOIN is the outermost query (not a subquery or derived table) This ensures that the limit is enabled when actual execution begins, and not if a subquery is evaluated during optimization of the outer @@ -28052,10 +28052,10 @@ JOIN_TAB::remove_duplicates() sort_field_keylength+= ptr->length + (ptr->item->maybe_null() ? 1 : 0); /* - Disable LIMIT ROWS EXAMINED in order to avoid interrupting prematurely + Deactivate LIMIT ROWS EXAMINED in order to avoid interrupting prematurely duplicate removal, and produce a possibly incomplete query result. */ - thd->lex->limit_rows_examined_cnt= ULONGLONG_MAX; + thd->lex->deactivate_limit_rows_examined(); if (thd->killed == ABORT_QUERY) thd->reset_killed(); diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 0a3037d064e..0a7088e91bc 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -2373,8 +2373,14 @@ bool st_select_lex_unit::exec_inner() if (!saved_error && !was_executed) save_union_explain(thd->lex->explain); - if (unlikely(saved_error)) - return saved_error; + error= saved_error; + + if (unlikely(error)) + { + err: + thd->lex->current_select= lex_select_save; + return error; + } if (union_result) { @@ -2465,7 +2471,8 @@ bool st_select_lex_unit::exec_inner() { table->file->print_error(error, MYF(0)); DBUG_ASSERT(0); - return true; + error= true; + goto err; } table->no_keyread=1; } @@ -2473,24 +2480,24 @@ bool st_select_lex_unit::exec_inner() { if (union_result->flush()) { - thd->lex->current_select= lex_select_save; - return true; + error= true; + goto err; } } } if (unlikely(saved_error)) { - thd->lex->current_select= lex_select_save; - return saved_error; + error= saved_error; + goto err; } if (fake_select_lex != NULL) { /* Needed for the following test and for records_at_start in next loop */ - int error= table->file->info(HA_STATUS_VARIABLE); + error= table->file->info(HA_STATUS_VARIABLE); if (unlikely(error)) { table->file->print_error(error, MYF(0)); - return true; + goto err; } } if (found_rows_for_union && !sl->braces && @@ -2524,20 +2531,19 @@ bool st_select_lex_unit::exec_inner() DBUG_EXECUTE_IF("show_explain_probe_union_read", dbug_serve_apcs(thd, 1);); - { - List empty_list; - empty_list.empty(); - /* - Disable LIMIT ROWS EXAMINED in order to produce the possibly incomplete - result of the UNION without interruption due to exceeding the limit. - */ - thd->lex->limit_rows_examined_cnt= ULONGLONG_MAX; + /* + Temporarily deactivate LIMIT ROWS EXAMINED to avoid producing potentially + incomplete result of the UNION due to exceeding of the limit. It will be + re-activated upon the function exit (see SCOPE_EXIT macro above) + */ + const bool limit_rows_was_activated= + thd->lex->deactivate_limit_rows_examined(); - // Check if EOM - if (fake_select_lex != NULL && likely(!thd->is_fatal_error)) - { - /* Send result to 'result' */ - saved_error= true; + // Check if EOM + if (fake_select_lex != NULL && likely(!thd->is_fatal_error)) + { + /* Send result to 'result' */ + saved_error= true; set_limit(global_parameters()); JOIN *join= fake_select_lex->join; @@ -2591,10 +2597,10 @@ bool st_select_lex_unit::exec_inner() Mark for slow query log if any of the union parts didn't use indexes efficiently */ - } } thd->lex->current_select= lex_select_save; - thd->lex->set_limit_rows_examined(); + if (limit_rows_was_activated) + thd->lex->set_limit_rows_examined(); return saved_error; } @@ -2726,7 +2732,6 @@ bool st_select_lex_unit::exec_recursive() thd->lex->current_select= lex_select_save; err: - thd->lex->set_limit_rows_examined(); DBUG_RETURN(saved_error); } diff --git a/sql/table.h b/sql/table.h index 0245a5f5fe4..27edb817423 100644 --- a/sql/table.h +++ b/sql/table.h @@ -2522,15 +2522,11 @@ struct TABLE_LIST } inline void init_one_table_for_prelocking(const LEX_CSTRING *db_arg, - const LEX_CSTRING *table_name_arg, - const LEX_CSTRING *alias_arg, - enum thr_lock_type lock_type_arg, - prelocking_types prelocking_type, - TABLE_LIST *belong_to_view_arg, - uint8 trg_event_map_arg, - TABLE_LIST ***last_ptr, - my_bool insert_data) - + const LEX_CSTRING *table_name_arg, const LEX_CSTRING *alias_arg, + enum thr_lock_type lock_type_arg, prelocking_types prelocking_type, + TABLE_LIST *belong_to_view_arg, uint8 trg_event_map_arg, + TABLE_LIST ***last_ptr, my_bool insert_data, + my_bool override_fk_ignore_table= FALSE) { init_one_table(db_arg, table_name_arg, alias_arg, lock_type_arg); cacheable_table= 1; @@ -2541,7 +2537,8 @@ struct TABLE_LIST belong_to_view= belong_to_view_arg; trg_event_map= trg_event_map_arg; /* MDL is enough for read-only FK checks, we don't need the table */ - if (prelocking_type == PRELOCK_FK && lock_type < TL_FIRST_WRITE) + if (prelocking_type == PRELOCK_FK && lock_type < TL_FIRST_WRITE && + !override_fk_ignore_table) open_strategy= OPEN_STUB; **last_ptr= this; diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 37bfc386ac8..5a42fd1e2fb 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -4146,7 +4146,7 @@ bool wsrep_foreign_key_append(THD *thd, FOREIGN_KEY_INFO *fk) if (WSREP(thd) && !thd->wsrep_applier && wsrep_is_active(thd) && (sql_command_flags[thd->lex->sql_command] & - (CF_UPDATES_DATA | CF_DELETES_DATA))) + (CF_UPDATES_DATA | CF_DELETES_DATA | CF_INSERTS_DATA))) { wsrep::key key(wsrep::key::shared); key.append_key_part(fk->foreign_db->str, fk->foreign_db->length); diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc index f9c9d0dfc3c..f2c4f9bc0cd 100644 --- a/storage/innobase/ibuf/ibuf0ibuf.cc +++ b/storage/innobase/ibuf/ibuf0ibuf.cc @@ -1046,10 +1046,13 @@ dberr_t ibuf_upgrade_needed() if (!root) goto err_exit; + const size_t payload= fil_system.sys_space->full_crc32() || + !fil_system.sys_space->crypt_data + ? FIL_PAGE_TYPE : FIL_PAGE_SPACE_ID; + if (UNIV_LIKELY(!page_has_siblings(root->page.frame)) && - UNIV_LIKELY(!memcmp(root->page.frame + FIL_PAGE_TYPE, field_ref_zero, - srv_page_size - - (FIL_PAGE_DATA_END + FIL_PAGE_TYPE)))) + UNIV_LIKELY(!memcmp(root->page.frame + payload, field_ref_zero, + srv_page_size - (FIL_PAGE_DATA_END + payload)))) /* the change buffer was removed; no need to upgrade */; else if (page_is_comp(root->page.frame) || btr_page_get_index_id(root->page.frame) != ibuf_index_id || diff --git a/unittest/mysys/crc32-t.c b/unittest/mysys/crc32-t.c index 7079aeb614a..6b07bb07db3 100644 --- a/unittest/mysys/crc32-t.c +++ b/unittest/mysys/crc32-t.c @@ -136,7 +136,8 @@ int main(int argc __attribute__((unused)),char *argv[]) DO_TEST_CRC32C(0,STR,(sizeof(STR)-1)); ok(0 == my_crc32c(0, NULL, 0), "crc32c data = NULL, length = 0"); - memset(buf, 0x5a, sizeof buf); + for (size_t i = 0; i < sizeof buf; i++) + buf[i] = i % 251; ok(0 == test_buf(my_checksum, crc32), "crc32 with various lengths"); ok(0 == test_buf(my_crc32c, crc32c), "crc32c with various lengths");