diff --git a/include/my_base.h b/include/my_base.h index b2a8b4b6b67..bb5fdfc8392 100644 --- a/include/my_base.h +++ b/include/my_base.h @@ -398,7 +398,10 @@ enum ha_base_keytype { #define HA_ERR_GENERIC 168 /* Generic error */ #define HA_ERR_RECORD_IS_THE_SAME 169 /* row not actually updated : new values same as the old values */ -#define HA_ERR_LAST 169 /*Copy last error nr.*/ + +#define HA_ERR_LOGGING_IMPOSSIBLE 170 /* It is not possible to log this + statement */ +#define HA_ERR_LAST 170 /*Copy last error nr.*/ /* Add error numbers before HA_ERR_LAST and change it accordingly. */ #define HA_ERR_ERRORS (HA_ERR_LAST - HA_ERR_FIRST + 1) diff --git a/mysql-test/extra/rpl_tests/rpl_ndb_apply_status.test b/mysql-test/extra/rpl_tests/rpl_ndb_apply_status.test new file mode 100644 index 00000000000..926c4106d6d --- /dev/null +++ b/mysql-test/extra/rpl_tests/rpl_ndb_apply_status.test @@ -0,0 +1,290 @@ +############################################# +#Authors: TU and Jeb +#Date: 2007/04 +#Purpose: Generic replication to cluster +# and ensuring that the ndb_apply_status +# table is updated. +############################################# +# Notes: +# include/select_ndb_apply_status.inc +# Selects out the log name, start & end pos +# from the ndb_apply_status table +# +# include/show_binlog_using_logname.inc +# To select out 1 row from offset 1 +# from the start position in the binlog whose +# name is = log_name +# +# include/tpcb.inc +# Creates DATABASE tpcb, the tables and +# stored procedures for loading the DB +# and for running transactions against DB. +############################################## + + +--echo +--echo *** Test 1 *** +--echo + +connection master; +create table t1 (a int key, b int) engine innodb; +create table t2 (a int key, b int) engine innodb; + +--echo + +--sync_slave_with_master +alter table t1 engine ndb; +alter table t2 engine ndb; + +--echo + +# check binlog position without begin +connection master; +insert into t1 values (1,2); + +--echo + +--sync_slave_with_master +--source include/select_ndb_apply_status.inc + +--echo + +connection master; +# here is actually a bug, since there is no begin statement, the +# query is autocommitted, and end_pos shows end of the insert and not +# end of the commit +--replace_result $start_pos +--replace_column 5 # +--eval show binlog events from $start_pos limit 1 +--echo +--replace_result $start_pos $end_pos +--replace_column 2 # +--replace_regex /\/\* xid=.* \*\//\/* XID *\// /table_id: [0-9]+/table_id: #/ +--eval show binlog events from $start_pos limit 1,1 + +--echo + +# check binlog position with begin +begin; +insert into t1 values (2,3); +insert into t2 values (3,4); +commit; + +--echo + +--sync_slave_with_master +--source include/select_ndb_apply_status.inc + +connection master; +--replace_result $start_pos +--replace_column 5 # +--eval show binlog events from $start_pos limit 1 +--echo +--replace_result $start_pos +--replace_column 2 # 4 # 5 # +--eval show binlog events from $start_pos limit 1,2 +--echo +--replace_result $start_pos $end_pos +--replace_column 2 # +--replace_regex /\/\* xid=.* \*\//\/* XID *\// /table_id: [0-9]+/table_id: #/ +--eval show binlog events from $start_pos limit 3,1 + +--echo + +connection master; +DROP TABLE test.t1, test.t2; +--sync_slave_with_master +SHOW TABLES; + +# Run in some transactions using stored procedures +# and ensure that the ndb_apply_status table is +# updated to show the transactions + + +--echo +--echo *** Test 2 *** +--echo + +# Create database/tables and stored procdures +connection master; +--source include/tpcb.inc + +# Switch tables on slave to use NDB +--sync_slave_with_master +USE tpcb; +ALTER TABLE account ENGINE NDB; +ALTER TABLE branch ENGINE NDB; +ALTER TABLE teller ENGINE NDB; +ALTER TABLE history ENGINE NDB; + +--echo + +# Load DB tpcb and run some transactions +connection master; +--disable_query_log +CALL tpcb.load(); +SET AUTOCOMMIT=0; +let $run= 5; +while ($run) +{ + START TRANSACTION; + --eval CALL tpcb.trans($rpl_format); + eval SET @my_errno= $mysql_errno; + let $run_good= `SELECT @my_errno = 0`; + let $run_bad= `SELECT @my_errno <> 0`; + if ($run_good) + { + COMMIT; + } + if ($run_bad) + { + ROLLBACK; + } + dec $run; +} + +SET AUTOCOMMIT=1; +--enable_query_log + +--sync_slave_with_master +--source include/select_ndb_apply_status.inc + +--echo + +connection master; +--source include/show_binlog_using_logname.inc + +# Flush the logs on the master moving all +# Transaction to a new binlog and ensure +# that the ndb_apply_status table is updated +# to show the use of the new binlog. + +--echo +--echo ** Test 3 ** +--echo + +# Flush logs on master which should force it +# to switch to binlog #2 + +FLUSH LOGS; + +# Run in some transaction to increase end pos in +# binlog + +--disable_query_log +SET AUTOCOMMIT=0; +let $run= 5; +while ($run) +{ + START TRANSACTION; + --eval CALL tpcb.trans($rpl_format); + eval SET @my_errno= $mysql_errno; + let $run_good= `SELECT @my_errno = 0`; + let $run_bad= `SELECT @my_errno <> 0`; + if ($run_good) + { + COMMIT; + } + if ($run_bad) + { + ROLLBACK; + } + dec $run; +} +SET AUTOCOMMIT=1; +--enable_query_log + +--echo + +--sync_slave_with_master +--source include/select_ndb_apply_status.inc + +--echo + +connection master; +--source include/show_binlog_using_logname.inc + +# Now we reset both the master and the slave +# Run some more transaction and ensure +# that the ndb_apply_status is updated +# correctly + +--echo +--echo ** Test 4 ** +--echo + +# Reset both slave and master +# This should reset binlog to #1 +--source include/master-slave-reset.inc + +--echo + +# Run in some transactions and check +connection master; +--disable_query_log +SET AUTOCOMMIT=0; +let $run= 5; +while ($run) +{ + START TRANSACTION; + --eval CALL tpcb.trans($rpl_format); + eval SET @my_errno= $mysql_errno; + let $run_good= `SELECT @my_errno = 0`; + let $run_bad= `SELECT @my_errno <> 0`; + if ($run_good) + { + COMMIT; + } + if ($run_bad) + { + ROLLBACK; + } + dec $run; +} +SET AUTOCOMMIT=1; +--enable_query_log + +--sync_slave_with_master +--source include/select_ndb_apply_status.inc + +--echo + +connection master; +--source include/show_binlog_using_logname.inc + +# Since we are doing replication, it is a good +# idea to check to make sure all data was +# Replicated correctly + +--echo +--echo *** DUMP MASTER & SLAVE FOR COMPARE ******** + +--exec $MYSQL_DUMP -n -t --compact --order-by-primary --skip-extended-insert tpcb account teller branch history > $MYSQLTEST_VARDIR/tmp/master_apply_status.sql + +--exec $MYSQL_DUMP_SLAVE -n -t --compact --order-by-primary --skip-extended-insert tpcb account teller branch history > $MYSQLTEST_VARDIR/tmp/slave_apply_status.sql + +connection master; +DROP DATABASE tpcb; + +--sync_slave_with_master + +####### Commenting out until decision on Bug#27960 ########### + +#--source include/select_ndb_apply_status.inc + +#connection master; +#--eval SHOW BINLOG EVENTS in '$log_name' from $start_pos +#--source include/show_binlog_using_logname.inc + +--echo ****** Do dumps compare ************ + + +diff_files $MYSQLTEST_VARDIR/tmp/master_apply_status.sql $MYSQLTEST_VARDIR/tmp/slave_apply_status.sql; + +## Note: Ths files should only get removed, if the above diff succeeds. + +--exec rm $MYSQLTEST_VARDIR/tmp/master_apply_status.sql +--exec rm $MYSQLTEST_VARDIR/tmp/slave_apply_status.sql + + +# End of 5.1 Test diff --git a/mysql-test/extra/rpl_tests/rpl_row_UUID.test b/mysql-test/extra/rpl_tests/rpl_row_UUID.test index ee2a29ac938..9f2dbb4ce4b 100644 --- a/mysql-test/extra/rpl_tests/rpl_row_UUID.test +++ b/mysql-test/extra/rpl_tests/rpl_row_UUID.test @@ -41,7 +41,7 @@ end| delimiter ;| # test both in SELECT and in INSERT select fn1(0); -create table t2 (a int); +eval create table t2 (a int) engine=$engine_type; insert into t2 values(fn1(2)); sync_slave_with_master; diff --git a/mysql-test/include/rpl_events.inc b/mysql-test/include/rpl_events.inc index bbe52d3628b..4b57468b2d7 100644 --- a/mysql-test/include/rpl_events.inc +++ b/mysql-test/include/rpl_events.inc @@ -13,52 +13,63 @@ drop table if exists t1,t2; # first, we need a table to record something from an event eval CREATE TABLE `t1` ( - `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `id` INT(10) UNSIGNED NOT NULL, `c` VARCHAR(50) NOT NULL, `ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=$engine_type DEFAULT CHARSET=utf8; -INSERT INTO t1 (c) VALUES ('manually'); +INSERT INTO t1 (id, c) VALUES (1, 'manually'); -# then, we create the event -CREATE EVENT test.justonce ON SCHEDULE AT NOW() + INTERVAL 2 SECOND DO INSERT INTO t1 -(c) VALUES ('from justonce'); +# We create the event so that it inserts exactly 1 row in the table +# A recuring event is used so that we can be sure the event will +# fire regardless of timing delays on the server. Otherwise, it is +# possible for the event to timeout before it has inserted a row. +--echo "Creating event test.justonce on the master" +CREATE EVENT test.justonce ON SCHEDULE EVERY 2 SECOND DO + INSERT IGNORE INTO t1 (id, c) VALUES (2, 'from justonce'); +# Show the event is alive and present on master +--echo "Checking event is active on master" SELECT db, name, status, originator FROM mysql.event WHERE db = 'test' AND name = 'justonce'; -# wait 3 seconds, so the event can trigger ---real_sleep 3 -let $wait_condition= - SELECT count(*) = 1 FROM t1 WHERE c = 'from justonce'; ---source include/wait_condition.inc +# Wait until event has fired. We know this because t1 will contain +# the row from the event. +let $wait_condition= + SELECT COUNT(*) = 1 FROM t1 WHERE c = 'from justonce'; +--source include/wait_condition.inc # check that table t1 contains something ---echo "in the master" +--echo "Checking event data on the master" --enable_info --replace_column 3 TIMESTAMP -SELECT * FROM t1 WHERE c = 'from justonce' OR c = 'manually' ORDER BY id; +SELECT * FROM t1 ORDER BY id; --disable_info sync_slave_with_master; ---echo "in the slave" +--echo "Checking event data on the slave" --enable_info --replace_column 3 TIMESTAMP -SELECT * FROM t1 WHERE c = 'from justonce' OR c = 'manually' ORDER BY id; +SELECT * FROM t1 ORDER BY id; --disable_info +--echo "Checking event is inactive on slave" SELECT db, name, status, originator FROM mysql.event WHERE db = 'test' AND name = 'justonce'; # Create an event on the slave and check to see what the originator is. +--echo "Dropping event test.slave_once on the slave" --disable_warnings DROP EVENT IF EXISTS test.slave_once; --enable_warnings CREATE EVENT test.slave_once ON SCHEDULE EVERY 5 MINUTE DO -INSERT INTO t1(c) VALUES ('from slave_once'); + INSERT IGNORE INTO t1(id, c) VALUES (3, 'from slave_once'); + +--echo "Checking event status on the slave for originator value = slave's server_id" SELECT db, name, status, originator FROM mysql.event WHERE db = 'test' AND name = 'slave_once'; +--echo "Dropping event test.slave_once on the slave" --disable_warnings DROP EVENT IF EXISTS test.slave_once; --enable_warnings @@ -66,57 +77,74 @@ DROP EVENT IF EXISTS test.slave_once; connection master; # BUG#20384 - disable events on slave +--echo "Dropping event test.justonce on the master" --disable_warnings DROP EVENT IF EXISTS test.justonce; --enable_warnings +--echo "Creating event test.er on the master" CREATE EVENT test.er ON SCHEDULE EVERY 3 SECOND DO -INSERT INTO t1(c) VALUES ('from er'); + INSERT IGNORE INTO t1(id, c) VALUES (4, 'from er'); + +--echo "Checking event status on the master" SELECT db, name, status, originator, body FROM mysql.event WHERE db = 'test' AND name = 'er'; sync_slave_with_master; ---echo "in the slave" +--echo "Checking event status on the slave" SELECT db, name, status, originator, body FROM mysql.event WHERE db = 'test' AND name = 'er'; connection master; ---echo "in the master" -ALTER EVENT test.er ON SCHEDULE EVERY 5 SECOND DO INSERT into t1(c) VALUES ('from alter er'); +--echo "Altering event test.er on the master" +ALTER EVENT test.er ON SCHEDULE EVERY 5 SECOND DO + INSERT IGNORE INTO t1(id, c) VALUES (5, 'from alter er'); + +--echo "Checking event status on the master" SELECT db, name, status, originator, body FROM mysql.event WHERE db = 'test' AND name = 'er'; sync_slave_with_master; ---echo "in the slave" +--echo "Checking event status on the slave" SELECT db, name, status, originator, body FROM mysql.event WHERE db = 'test' AND name = 'er'; connection master; ---echo "in the master" +--echo "Dropping event test.er on the master" DROP EVENT test.er; + +--echo "Checking event status on the master" SELECT db, name, status, originator FROM mysql.event WHERE db = 'test'; --disable_info sync_slave_with_master; ---echo "in the slave" +--echo "Checking event status on the slave" SELECT db, name, status, originator FROM mysql.event WHERE db = 'test'; # test the DISABLE ON SLAVE for setting event SLAVESIDE_DISABLED as status # on CREATE EVENT -CREATE EVENT test.slave_terminate ON SCHEDULE EVERY 3 SECOND -DO INSERT INTO t1(c) VALUES ('from slave_terminate'); +--echo "Creating event test.slave_terminate on the slave" +CREATE EVENT test.slave_terminate ON SCHEDULE EVERY 3 SECOND DO + INSERT IGNORE INTO t1(id, c) VALUES (6, 'from slave_terminate'); + +--echo "Checking event status on the slave" SELECT db, name, status, originator FROM mysql.event WHERE db = 'test' AND name = 'slave_terminate'; +--echo "Dropping event test.slave_terminate on the slave" DROP EVENT test.slave_terminate; -CREATE EVENT test.slave_terminate ON SCHEDULE EVERY 3 SECOND -DISABLE ON SLAVE DO INSERT INTO t1(c) VALUES ('from slave_terminate'); +--echo "Creating event test.slave_terminate with DISABLE ON SLAVE on the slave" +CREATE EVENT test.slave_terminate ON SCHEDULE EVERY 3 SECOND DISABLE ON SLAVE DO + INSERT IGNORE INTO t1(c) VALUES (7, 'from slave_terminate'); + +--echo "Checking event status on the slave" SELECT db, name, status, originator FROM mysql.event WHERE db = 'test' AND name = 'slave_terminate'; +--echo "Dropping event test.slave_terminate on the slave" DROP EVENT test.slave_terminate; ---echo "in the master" +--echo "Cleanup" connection master; DROP TABLE t1; diff --git a/mysql-test/include/select_ndb_apply_status.inc b/mysql-test/include/select_ndb_apply_status.inc new file mode 100644 index 00000000000..a676b7cfb06 --- /dev/null +++ b/mysql-test/include/select_ndb_apply_status.inc @@ -0,0 +1,13 @@ +################################################## +# Author: Jeb +# Date: 2007/04 +# Purpose: To select out log name, start and end +# positions from ndb_apply_status table +################################################## +--replace_column 1 2 3 +select @log_name:=log_name, @start_pos:=start_pos, @end_pos:=end_pos + from mysql.ndb_apply_status; +--let $start_pos = `select @start_pos` +--let $end_pos = `select @end_pos` +--let $log_name = `select @log_name` + diff --git a/mysql-test/include/show_binlog_using_logname.inc b/mysql-test/include/show_binlog_using_logname.inc new file mode 100644 index 00000000000..d78c28e5916 --- /dev/null +++ b/mysql-test/include/show_binlog_using_logname.inc @@ -0,0 +1,13 @@ +######################################################## +# Author: Jeb +# Date: 2007/04 +# Purpose: To select out 1 row from offset 1 +# from the start position in the binlog whose +# name is = log_name +######################################################## + +--replace_result $start_pos $end_pos +--replace_column 2 # +--replace_regex /\/\* xid=.* \*\//\/* XID *\// /table_id: [0-9]+/table_id: #/ +--eval show binlog events in '$log_name' from $start_pos limit $off_set,1 + diff --git a/mysql-test/include/tpcb.inc b/mysql-test/include/tpcb.inc new file mode 100644 index 00000000000..84a5c98f9c2 --- /dev/null +++ b/mysql-test/include/tpcb.inc @@ -0,0 +1,155 @@ +################################################## +# Author: Jeb +# Date: 2007/04 +# Purpose: To create a tpcb database, tables and +# stored procedures to load the database +# and run transactions against the DB +################################################## +--disable_warnings +DROP DATABASE IF EXISTS tpcb; +--enable_warnings +CREATE DATABASE tpcb; + +--echo +CREATE TABLE tpcb.account (id INT, bid INT, balance DECIMAL(10,2), + filler CHAR(255), PRIMARY KEY(id)); +--echo +CREATE TABLE tpcb.branch (bid INT, balance DECIMAL(10,2), filler VARCHAR(255), + PRIMARY KEY(bid)); +--echo +CREATE TABLE tpcb.teller (tid INT, balance DECIMAL(10,2), filler VARCHAR(255), + PRIMARY KEY(tid)); +--echo +CREATE TABLE tpcb.history (id MEDIUMINT NOT NULL AUTO_INCREMENT,aid INT, + tid INT, bid INT, amount DECIMAL(10,2), + tdate DATETIME, teller CHAR(20), uuidf LONGBLOB, + filler CHAR(80),PRIMARY KEY (id)); + +--echo +--echo --- Create stored procedures & functions --- +--echo + +--disable_query_log +delimiter |; +CREATE PROCEDURE tpcb.load() +BEGIN + DECLARE acct INT DEFAULT 100; + DECLARE brch INT DEFAULT 10; + DECLARE tell INT DEFAULT 100; + DECLARE tmp INT DEFAULT 10; + WHILE brch > 0 DO + SET tmp = 100; + WHILE tmp > 0 DO + INSERT INTO tpcb.account VALUES (acct, brch, 0.0, "FRESH ACCOUNT"); + SET acct = acct - 1; + SET tmp = tmp -1; + END WHILE; + INSERT INTO tpcb.branch VALUES (brch, 0.0, "FRESH BRANCH"); + SET brch = brch - 1; + END WHILE; + WHILE tell > 0 DO + INSERT INTO tpcb.teller VALUES (tell, 0.0, "FRESH TELLER"); + SET tell = tell - 1; + END WHILE; +END| + +CREATE FUNCTION tpcb.account_id () RETURNS INT +BEGIN + DECLARE num INT; + DECLARE ran INT; + SELECT RAND() * 10 INTO ran; + IF (ran < 5) + THEN + SELECT RAND() * 10 INTO num; + ELSE + SELECT RAND() * 100 INTO num; + END IF; + IF (num < 1) + THEN + RETURN 1; + END IF; + RETURN num; +END| + +CREATE FUNCTION tpcb.teller_id () RETURNS INT +BEGIN + DECLARE num INT; + DECLARE ran INT; + SELECT RAND() * 10 INTO ran; + IF (ran < 5) + THEN + SELECT RAND() * 10 INTO num; + ELSE + SELECT RAND() * 100 INTO num; + END IF; + IF (num < 1) + THEN + RETURN 1; + END IF; + RETURN num; +END| + +CREATE PROCEDURE tpcb.trans(in format varchar(3)) +BEGIN + DECLARE acct INT DEFAULT 0; + DECLARE brch INT DEFAULT 0; + DECLARE tell INT DEFAULT 0; + DECLARE bal DECIMAL(10,2) DEFAULT 0.0; + DECLARE amount DECIMAL(10,2) DEFAULT 1.00; + DECLARE test INT DEFAULT 0; + DECLARE bbal DECIMAL(10,2) DEFAULT 0.0; + DECLARE tbal DECIMAL(10,2) DEFAULT 0.0; + DECLARE local_uuid VARCHAR(255); + DECLARE local_user VARCHAR(255); + DECLARE local_time TIMESTAMP; + + SELECT RAND() * 10 INTO test; + SELECT tpcb.account_id() INTO acct; + SELECT tpcb.teller_id() INTO tell; + + SELECT account.balance INTO bal FROM tpcb.account WHERE id = acct; + SELECT account.bid INTO brch FROM tpcb.account WHERE id = acct; + SELECT teller.balance INTO tbal FROM tpcb.teller WHERE tid = tell; + SELECT branch.balance INTO bbal FROM tpcb.branch WHERE bid = brch; + + IF (test < 5) + THEN + SET bal = bal + amount; + SET bbal = bbal + amount; + SET tbal = tbal + amount; + UPDATE tpcb.account SET balance = bal, filler = 'account updated' + WHERE id = acct; + UPDATE tpcb.branch SET balance = bbal, filler = 'branch updated' + WHERE bid = brch; + UPDATE tpcb.teller SET balance = tbal, filler = 'teller updated' + WHERE tid = tell; + ELSE + SET bal = bal - amount; + SET bbal = bbal - amount; + SET tbal = tbal - amount; + UPDATE tpcb.account SET balance = bal, filler = 'account updated' + WHERE id = acct; + UPDATE tpcb.branch SET balance = bbal, filler = 'branch updated' + WHERE bid = brch; + UPDATE tpcb.teller SET balance = tbal, filler = 'teller updated' + WHERE tid = tell; + END IF; + + IF (format = 'SBR') + THEN + SET local_uuid=UUID(); + SET local_user=USER(); + SET local_time= NOW(); + INSERT INTO tpcb.history VALUES(NULL,acct,tell,brch,amount, local_time,local_user, + local_uuid,'completed trans'); + ELSE + INSERT INTO tpcb.history VALUES(NULL,acct,tell,brch,amount, NOW(), USER(), + UUID(),'completed trans'); + END IF; +END| +delimiter ;| +--enable_query_log +--echo +--echo *** Stored Procedures Created *** +--echo + diff --git a/mysql-test/include/tpcb_disk_data.inc b/mysql-test/include/tpcb_disk_data.inc new file mode 100644 index 00000000000..dbdf3766bbc --- /dev/null +++ b/mysql-test/include/tpcb_disk_data.inc @@ -0,0 +1,166 @@ +################################################## +# Author: Jeb +# Date: 2007/05 +# Purpose: To create a tpcb database using Disk Data, +# tables and stored procedures to load the database +# and run transactions against the DB +################################################## +--disable_warnings +DROP DATABASE IF EXISTS tpcb; +--enable_warnings +CREATE DATABASE tpcb; + +--echo +eval CREATE TABLE tpcb.account + (id INT, bid INT, balance DECIMAL(10,2), + filler CHAR(255), PRIMARY KEY(id)) + TABLESPACE $table_space STORAGE DISK + ENGINE=$engine_type; +--echo +eval CREATE TABLE tpcb.branch + (bid INT, balance DECIMAL(10,2), filler VARCHAR(255), + PRIMARY KEY(bid))TABLESPACE $table_space STORAGE DISK + ENGINE=$engine_type; +--echo +eval CREATE TABLE tpcb.teller + (tid INT, balance DECIMAL(10,2), filler VARCHAR(255), + PRIMARY KEY(tid)) TABLESPACE $table_space STORAGE DISK + ENGINE=$engine_type; + +--echo +eval CREATE TABLE tpcb.history + (id MEDIUMINT NOT NULL AUTO_INCREMENT,aid INT, + tid INT, bid INT, amount DECIMAL(10,2), + tdate DATETIME, teller CHAR(20), uuidf LONGBLOB, + filler CHAR(80),PRIMARY KEY (id)) + TABLESPACE $table_space STORAGE DISK + ENGINE=$engine_type; + +--echo +--echo --- Create stored procedures & functions --- +--echo + +--disable_query_log +delimiter |; +CREATE PROCEDURE tpcb.load() +BEGIN + DECLARE acct INT DEFAULT 100; + DECLARE brch INT DEFAULT 10; + DECLARE tell INT DEFAULT 100; + DECLARE tmp INT DEFAULT 10; + WHILE brch > 0 DO + SET tmp = 100; + WHILE tmp > 0 DO + INSERT INTO tpcb.account VALUES (acct, brch, 0.0, "FRESH ACCOUNT"); + SET acct = acct - 1; + SET tmp = tmp -1; + END WHILE; + INSERT INTO tpcb.branch VALUES (brch, 0.0, "FRESH BRANCH"); + SET brch = brch - 1; + END WHILE; + WHILE tell > 0 DO + INSERT INTO tpcb.teller VALUES (tell, 0.0, "FRESH TELLER"); + SET tell = tell - 1; + END WHILE; +END| + +CREATE FUNCTION tpcb.account_id () RETURNS INT +BEGIN + DECLARE num INT; + DECLARE ran INT; + SELECT RAND() * 10 INTO ran; + IF (ran < 5) + THEN + SELECT RAND() * 10 INTO num; + ELSE + SELECT RAND() * 100 INTO num; + END IF; + IF (num < 1) + THEN + RETURN 1; + END IF; + RETURN num; +END| + +CREATE FUNCTION tpcb.teller_id () RETURNS INT +BEGIN + DECLARE num INT; + DECLARE ran INT; + SELECT RAND() * 10 INTO ran; + IF (ran < 5) + THEN + SELECT RAND() * 10 INTO num; + ELSE + SELECT RAND() * 100 INTO num; + END IF; + IF (num < 1) + THEN + RETURN 1; + END IF; + RETURN num; +END| + +CREATE PROCEDURE tpcb.trans(in format varchar(3)) +BEGIN + DECLARE acct INT DEFAULT 0; + DECLARE brch INT DEFAULT 0; + DECLARE tell INT DEFAULT 0; + DECLARE bal DECIMAL(10,2) DEFAULT 0.0; + DECLARE amount DECIMAL(10,2) DEFAULT 1.00; + DECLARE test INT DEFAULT 0; + DECLARE bbal DECIMAL(10,2) DEFAULT 0.0; + DECLARE tbal DECIMAL(10,2) DEFAULT 0.0; + DECLARE local_uuid VARCHAR(255); + DECLARE local_user VARCHAR(255); + DECLARE local_time TIMESTAMP; + + SELECT RAND() * 10 INTO test; + SELECT tpcb.account_id() INTO acct; + SELECT tpcb.teller_id() INTO tell; + + SELECT account.balance INTO bal FROM tpcb.account WHERE id = acct; + SELECT account.bid INTO brch FROM tpcb.account WHERE id = acct; + SELECT teller.balance INTO tbal FROM tpcb.teller WHERE tid = tell; + SELECT branch.balance INTO bbal FROM tpcb.branch WHERE bid = brch; + + IF (test < 5) + THEN + SET bal = bal + amount; + SET bbal = bbal + amount; + SET tbal = tbal + amount; + UPDATE tpcb.account SET balance = bal, filler = 'account updated' + WHERE id = acct; + UPDATE tpcb.branch SET balance = bbal, filler = 'branch updated' + WHERE bid = brch; + UPDATE tpcb.teller SET balance = tbal, filler = 'teller updated' + WHERE tid = tell; + ELSE + SET bal = bal - amount; + SET bbal = bbal - amount; + SET tbal = tbal - amount; + UPDATE tpcb.account SET balance = bal, filler = 'account updated' + WHERE id = acct; + UPDATE tpcb.branch SET balance = bbal, filler = 'branch updated' + WHERE bid = brch; + UPDATE tpcb.teller SET balance = tbal, filler = 'teller updated' + WHERE tid = tell; + END IF; + + IF (format = 'SBR') + THEN + SET local_uuid=UUID(); + SET local_user=USER(); + SET local_time= NOW(); + INSERT INTO tpcb.history VALUES(NULL,acct,tell,brch,amount, local_time,local_user, + local_uuid,'completed trans'); + ELSE + INSERT INTO tpcb.history VALUES(NULL,acct,tell,brch,amount, NOW(), USER(), + UUID(),'completed trans'); + END IF; +END| +delimiter ;| +--enable_query_log +--echo +--echo *** Stored Procedures Created *** +--echo + diff --git a/mysql-test/lib/mtr_cases.pl b/mysql-test/lib/mtr_cases.pl index 11ff85818a7..120947c84a7 100644 --- a/mysql-test/lib/mtr_cases.pl +++ b/mysql-test/lib/mtr_cases.pl @@ -631,6 +631,7 @@ our @tags= ["include/big_test.inc", "big_test", 1], ["include/have_debug.inc", "need_debug", 1], ["include/have_ndb.inc", "ndb_test", 1], + ["include/have_multi_ndb.inc", "ndb_test", 1], ["include/have_ndb_extra.inc", "ndb_extra", 1], ["require_manager", "require_manager", 1], ); diff --git a/mysql-test/r/binlog_multi_engine.result b/mysql-test/r/binlog_multi_engine.result index 71b2d7b0c48..d605fbfaf67 100644 --- a/mysql-test/r/binlog_multi_engine.result +++ b/mysql-test/r/binlog_multi_engine.result @@ -30,8 +30,6 @@ master-bin.000001 # Query # # use `test`; TRUNCATE t1b master-bin.000001 # Query # # BEGIN master-bin.000001 # Table_map # # table_id: # (test.t1n) master-bin.000001 # Table_map # # table_id: # (mysql.ndb_apply_status) -master-bin.000001 # Write_rows # # table_id: # -master-bin.000001 # Write_rows # # table_id: # master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F master-bin.000001 # Query # # COMMIT master-bin.000001 # Query # # use `test`; TRUNCATE t1n @@ -41,8 +39,10 @@ INSERT INTO t1m VALUES (1,1), (1,2), (2,1), (2,2); INSERT INTO t1b VALUES (1,1), (1,2), (2,1), (2,2); INSERT INTO t1n VALUES (1,1), (1,2), (2,1), (2,2); UPDATE t1m, t1b SET m = 2, b = 3 WHERE n = c; +UPDATE t1m, t1n SET m = 2, e = 3 WHERE n = f; +ERROR HY000: Binary logging not possible. Message: Statement cannot be written atomically since more than one engine involved and at least one engine is self-logging UPDATE t1n, t1b SET e = 2, b = 3 WHERE f = c; -ERROR HY000: Binary logging not possible. Message: Statement cannot be logged to the binary log in row-based nor statement-based format +ERROR HY000: Binary logging not possible. Message: Statement cannot be written atomically since more than one engine involved and at least one engine is self-logging TRUNCATE t1m; TRUNCATE t1b; TRUNCATE t1n; @@ -69,8 +69,10 @@ ERROR HY000: Binary logging not possible. Message: Row-based format required for INSERT INTO t1n VALUES (1,1), (1,2), (2,1), (2,2); UPDATE t1m, t1b SET m = 2, b = 3 WHERE n = c; ERROR HY000: Binary logging not possible. Message: Row-based format required for this statement, but not allowed by this combination of engines +UPDATE t1m, t1n SET m = 2, e = 3 WHERE n = f; +ERROR HY000: Binary logging not possible. Message: Statement cannot be written atomically since more than one engine involved and at least one engine is self-logging UPDATE t1n, t1b SET e = 2, b = 3 WHERE f = c; -ERROR HY000: Binary logging not possible. Message: Statement cannot be logged to the binary log in row-based nor statement-based format +ERROR HY000: Binary logging not possible. Message: Row-based format required for this statement, but not allowed by this combination of engines show binlog events from ; Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 # Table_map # # table_id: # (test.t1m) diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result index fcfe5d6345b..6f1c9d3d52a 100644 --- a/mysql-test/r/ctype_ucs.result +++ b/mysql-test/r/ctype_ucs.result @@ -865,4 +865,25 @@ blob 65535 65535 text 65535 65535 text 65535 32767 drop table t1; +create table t1 (a char(1) character set ucs2); +insert into t1 values ('a'),('b'),('c'); +select hex(group_concat(a)) from t1; +hex(group_concat(a)) +0061002C0062002C0063 +select collation(group_concat(a)) from t1; +collation(group_concat(a)) +ucs2_general_ci +drop table t1; +set names latin1; +create table t1 (a char(1) character set latin1); +insert into t1 values ('a'),('b'),('c'); +set character_set_connection=ucs2; +select hex(group_concat(a separator ',')) from t1; +hex(group_concat(a separator ',')) +612C622C63 +select collation(group_concat(a separator ',')) from t1; +collation(group_concat(a separator ',')) +latin1_swedish_ci +drop table t1; +set names latin1; End of 5.0 tests diff --git a/mysql-test/r/ctype_ucs2_def.result b/mysql-test/r/ctype_ucs2_def.result index fb21fb4a6c1..6fd45428368 100644 --- a/mysql-test/r/ctype_ucs2_def.result +++ b/mysql-test/r/ctype_ucs2_def.result @@ -7,6 +7,13 @@ character_set_server ucs2 DROP TABLE IF EXISTS t1; create table t1 (a int); drop table t1; +End of 4.1 tests +create table t1 (a char(1) character set latin1); +insert into t1 values ('a'),('b'),('c'); +select hex(group_concat(a)) from t1; +hex(group_concat(a)) +612C622C63 +drop table t1; CREATE TABLE t1(col1 VARCHAR(32) CHARACTER SET ucs2 COLLATE ucs2_bin NOT NULL, col2 VARCHAR(32) CHARACTER SET ucs2 COLLATE ucs2_bin NOT NULL, UNIQUE KEY key1 USING HASH (col1, col2)) ENGINE=MEMORY; diff --git a/mysql-test/r/ndb_binlog_format.result b/mysql-test/r/ndb_binlog_format.result new file mode 100644 index 00000000000..ed26060e2a4 --- /dev/null +++ b/mysql-test/r/ndb_binlog_format.result @@ -0,0 +1,30 @@ +drop table if exists t1, t2, t3; +CREATE TABLE t1 (m INT, n INT) ENGINE=MYISAM; +CREATE TABLE t2 (b INT, c INT) ENGINE=BLACKHOLE; +CREATE TABLE t3 (e INT, f INT) ENGINE=NDB; +RESET MASTER; +SET SESSION BINLOG_FORMAT=STATEMENT; +INSERT INTO t1 VALUES (1,1), (1,2), (2,1), (2,2); +INSERT INTO t2 VALUES (1,1), (1,2), (2,1), (2,2); +UPDATE t1, t2 SET m = 2, b = 3 WHERE n = c; +START TRANSACTION; +INSERT INTO t3 VALUES (1,1), (1,2), (2,1), (2,2); +UPDATE t1, t3 SET m = 2, e = 3 WHERE n = f; +UPDATE t3, t2 SET e = 2, b = 3 WHERE f = c; +COMMIT; +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (1,1), (1,2), (2,1), (2,2) +master-bin.000001 # Query # # use `test`; INSERT INTO t2 VALUES (1,1), (1,2), (2,1), (2,2) +master-bin.000001 # Query # # use `test`; UPDATE t1, t2 SET m = 2, b = 3 WHERE n = c +master-bin.000001 # Query # # use `test`; BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO t3 VALUES (1,1), (1,2), (2,1), (2,2) +master-bin.000001 # Query # # use `test`; UPDATE t1, t3 SET m = 2, e = 3 WHERE n = f +master-bin.000001 # Query # # use `test`; UPDATE t3, t2 SET e = 2, b = 3 WHERE f = c +master-bin.000001 # Query # # use `test`; COMMIT +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Table_map # # table_id: # (test.t3) +master-bin.000001 # Table_map # # table_id: # (mysql.ndb_apply_status) +master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F +master-bin.000001 # Query # # COMMIT +DROP TABLE t1, t2, t3; diff --git a/mysql-test/r/ndb_read_multi_range.result b/mysql-test/r/ndb_read_multi_range.result index aef009212a4..8443d0473a8 100644 --- a/mysql-test/r/ndb_read_multi_range.result +++ b/mysql-test/r/ndb_read_multi_range.result @@ -451,7 +451,7 @@ CREATE TABLE t2 ( var1 int(2) NOT NULL, var2 int(2) NOT NULL, PRIMARY KEY (var1) -) ENGINE=MyISAM DEFAULT CHARSET=ascii CHECKSUM=1; +) ENGINE=ndbcluster DEFAULT CHARSET=ascii CHECKSUM=1; CREATE TRIGGER testtrigger AFTER UPDATE ON t1 FOR EACH ROW BEGIN REPLACE INTO t2 SELECT * FROM t1 WHERE t1.var1 = NEW.var1;END| diff --git a/mysql-test/r/ndb_trigger.result b/mysql-test/r/ndb_trigger.result index 28f9f9bdc37..d074ad01c22 100644 --- a/mysql-test/r/ndb_trigger.result +++ b/mysql-test/r/ndb_trigger.result @@ -1,7 +1,7 @@ drop table if exists t1, t2, t3, t4, t5; create table t1 (id int primary key, a int not null, b decimal (63,30) default 0) engine=ndb; -create table t2 (op char(1), a int not null, b decimal (63,30)); -create table t3 select 1 as i; +create table t2 (op char(1), a int not null, b decimal (63,30)) engine=ndb; +create table t3 engine=ndb select 1 as i; create table t4 (a int not null primary key, b int) engine=ndb; create table t5 (a int not null primary key, b int) engine=ndb; create trigger t1_bu before update on t1 for each row diff --git a/mysql-test/r/rpl_events.result b/mysql-test/r/rpl_events.result index 0d7e7bb28a7..18fe72a9879 100644 --- a/mysql-test/r/rpl_events.result +++ b/mysql-test/r/rpl_events.result @@ -9,153 +9,191 @@ set binlog_format=row; DROP EVENT IF EXISTS test.justonce; drop table if exists t1,t2; CREATE TABLE `t1` ( -`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, +`id` INT(10) UNSIGNED NOT NULL, `c` VARCHAR(50) NOT NULL, `ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; -INSERT INTO t1 (c) VALUES ('manually'); -CREATE EVENT test.justonce ON SCHEDULE AT NOW() + INTERVAL 2 SECOND DO INSERT INTO t1 -(c) VALUES ('from justonce'); +INSERT INTO t1 (id, c) VALUES (1, 'manually'); +"Creating event test.justonce on the master" +CREATE EVENT test.justonce ON SCHEDULE EVERY 2 SECOND DO +INSERT IGNORE INTO t1 (id, c) VALUES (2, 'from justonce'); +"Checking event is active on master" SELECT db, name, status, originator FROM mysql.event WHERE db = 'test' AND name = 'justonce'; db name status originator test justonce ENABLED 1 -"in the master" -SELECT * FROM t1 WHERE c = 'from justonce' OR c = 'manually' ORDER BY id; +"Checking event data on the master" +SELECT * FROM t1 ORDER BY id; id c ts 1 manually TIMESTAMP 2 from justonce TIMESTAMP affected rows: 2 -"in the slave" -SELECT * FROM t1 WHERE c = 'from justonce' OR c = 'manually' ORDER BY id; +"Checking event data on the slave" +SELECT * FROM t1 ORDER BY id; id c ts 1 manually TIMESTAMP 2 from justonce TIMESTAMP affected rows: 2 +"Checking event is inactive on slave" SELECT db, name, status, originator FROM mysql.event WHERE db = 'test' AND name = 'justonce'; db name status originator +test justonce SLAVESIDE_DISABLED 1 +"Dropping event test.slave_once on the slave" DROP EVENT IF EXISTS test.slave_once; CREATE EVENT test.slave_once ON SCHEDULE EVERY 5 MINUTE DO -INSERT INTO t1(c) VALUES ('from slave_once'); +INSERT IGNORE INTO t1(id, c) VALUES (3, 'from slave_once'); +"Checking event status on the slave for originator value = slave's server_id" SELECT db, name, status, originator FROM mysql.event WHERE db = 'test' AND name = 'slave_once'; db name status originator test slave_once ENABLED 2 +"Dropping event test.slave_once on the slave" DROP EVENT IF EXISTS test.slave_once; +"Dropping event test.justonce on the master" DROP EVENT IF EXISTS test.justonce; +"Creating event test.er on the master" CREATE EVENT test.er ON SCHEDULE EVERY 3 SECOND DO -INSERT INTO t1(c) VALUES ('from er'); +INSERT IGNORE INTO t1(id, c) VALUES (4, 'from er'); +"Checking event status on the master" SELECT db, name, status, originator, body FROM mysql.event WHERE db = 'test' AND name = 'er'; db name status originator body -test er ENABLED 1 INSERT INTO t1(c) VALUES ('from er') -"in the slave" +test er ENABLED 1 INSERT IGNORE INTO t1(id, c) VALUES (4, 'from er') +"Checking event status on the slave" SELECT db, name, status, originator, body FROM mysql.event WHERE db = 'test' AND name = 'er'; db name status originator body -test er SLAVESIDE_DISABLED 1 INSERT INTO t1(c) VALUES ('from er') -"in the master" -ALTER EVENT test.er ON SCHEDULE EVERY 5 SECOND DO INSERT into t1(c) VALUES ('from alter er'); +test er SLAVESIDE_DISABLED 1 INSERT IGNORE INTO t1(id, c) VALUES (4, 'from er') +"Altering event test.er on the master" +ALTER EVENT test.er ON SCHEDULE EVERY 5 SECOND DO +INSERT IGNORE INTO t1(id, c) VALUES (5, 'from alter er'); +"Checking event status on the master" SELECT db, name, status, originator, body FROM mysql.event WHERE db = 'test' AND name = 'er'; db name status originator body -test er ENABLED 1 INSERT into t1(c) VALUES ('from alter er') -"in the slave" +test er ENABLED 1 INSERT IGNORE INTO t1(id, c) VALUES (5, 'from alter er') +"Checking event status on the slave" SELECT db, name, status, originator, body FROM mysql.event WHERE db = 'test' AND name = 'er'; db name status originator body -test er SLAVESIDE_DISABLED 1 INSERT into t1(c) VALUES ('from alter er') -"in the master" +test er SLAVESIDE_DISABLED 1 INSERT IGNORE INTO t1(id, c) VALUES (5, 'from alter er') +"Dropping event test.er on the master" DROP EVENT test.er; +"Checking event status on the master" SELECT db, name, status, originator FROM mysql.event WHERE db = 'test'; db name status originator -"in the slave" +"Checking event status on the slave" SELECT db, name, status, originator FROM mysql.event WHERE db = 'test'; db name status originator -CREATE EVENT test.slave_terminate ON SCHEDULE EVERY 3 SECOND -DO INSERT INTO t1(c) VALUES ('from slave_terminate'); +"Creating event test.slave_terminate on the slave" +CREATE EVENT test.slave_terminate ON SCHEDULE EVERY 3 SECOND DO +INSERT IGNORE INTO t1(id, c) VALUES (6, 'from slave_terminate'); +"Checking event status on the slave" SELECT db, name, status, originator FROM mysql.event WHERE db = 'test' AND name = 'slave_terminate'; db name status originator test slave_terminate ENABLED 2 +"Dropping event test.slave_terminate on the slave" DROP EVENT test.slave_terminate; -CREATE EVENT test.slave_terminate ON SCHEDULE EVERY 3 SECOND -DISABLE ON SLAVE DO INSERT INTO t1(c) VALUES ('from slave_terminate'); +"Creating event test.slave_terminate with DISABLE ON SLAVE on the slave" +CREATE EVENT test.slave_terminate ON SCHEDULE EVERY 3 SECOND DISABLE ON SLAVE DO +INSERT IGNORE INTO t1(c) VALUES (7, 'from slave_terminate'); +"Checking event status on the slave" SELECT db, name, status, originator FROM mysql.event WHERE db = 'test' AND name = 'slave_terminate'; db name status originator test slave_terminate SLAVESIDE_DISABLED 2 +"Dropping event test.slave_terminate on the slave" DROP EVENT test.slave_terminate; -"in the master" +"Cleanup" DROP TABLE t1; set binlog_format=statement; DROP EVENT IF EXISTS test.justonce; drop table if exists t1,t2; CREATE TABLE `t1` ( -`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, +`id` INT(10) UNSIGNED NOT NULL, `c` VARCHAR(50) NOT NULL, `ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; -INSERT INTO t1 (c) VALUES ('manually'); -CREATE EVENT test.justonce ON SCHEDULE AT NOW() + INTERVAL 2 SECOND DO INSERT INTO t1 -(c) VALUES ('from justonce'); +INSERT INTO t1 (id, c) VALUES (1, 'manually'); +"Creating event test.justonce on the master" +CREATE EVENT test.justonce ON SCHEDULE EVERY 2 SECOND DO +INSERT IGNORE INTO t1 (id, c) VALUES (2, 'from justonce'); +"Checking event is active on master" SELECT db, name, status, originator FROM mysql.event WHERE db = 'test' AND name = 'justonce'; db name status originator test justonce ENABLED 1 -"in the master" -SELECT * FROM t1 WHERE c = 'from justonce' OR c = 'manually' ORDER BY id; +"Checking event data on the master" +SELECT * FROM t1 ORDER BY id; id c ts 1 manually TIMESTAMP 2 from justonce TIMESTAMP affected rows: 2 -"in the slave" -SELECT * FROM t1 WHERE c = 'from justonce' OR c = 'manually' ORDER BY id; +"Checking event data on the slave" +SELECT * FROM t1 ORDER BY id; id c ts 1 manually TIMESTAMP 2 from justonce TIMESTAMP affected rows: 2 +"Checking event is inactive on slave" SELECT db, name, status, originator FROM mysql.event WHERE db = 'test' AND name = 'justonce'; db name status originator +test justonce SLAVESIDE_DISABLED 1 +"Dropping event test.slave_once on the slave" DROP EVENT IF EXISTS test.slave_once; CREATE EVENT test.slave_once ON SCHEDULE EVERY 5 MINUTE DO -INSERT INTO t1(c) VALUES ('from slave_once'); +INSERT IGNORE INTO t1(id, c) VALUES (3, 'from slave_once'); +"Checking event status on the slave for originator value = slave's server_id" SELECT db, name, status, originator FROM mysql.event WHERE db = 'test' AND name = 'slave_once'; db name status originator test slave_once ENABLED 2 +"Dropping event test.slave_once on the slave" DROP EVENT IF EXISTS test.slave_once; +"Dropping event test.justonce on the master" DROP EVENT IF EXISTS test.justonce; +"Creating event test.er on the master" CREATE EVENT test.er ON SCHEDULE EVERY 3 SECOND DO -INSERT INTO t1(c) VALUES ('from er'); +INSERT IGNORE INTO t1(id, c) VALUES (4, 'from er'); +"Checking event status on the master" SELECT db, name, status, originator, body FROM mysql.event WHERE db = 'test' AND name = 'er'; db name status originator body -test er ENABLED 1 INSERT INTO t1(c) VALUES ('from er') -"in the slave" +test er ENABLED 1 INSERT IGNORE INTO t1(id, c) VALUES (4, 'from er') +"Checking event status on the slave" SELECT db, name, status, originator, body FROM mysql.event WHERE db = 'test' AND name = 'er'; db name status originator body -test er SLAVESIDE_DISABLED 1 INSERT INTO t1(c) VALUES ('from er') -"in the master" -ALTER EVENT test.er ON SCHEDULE EVERY 5 SECOND DO INSERT into t1(c) VALUES ('from alter er'); +test er SLAVESIDE_DISABLED 1 INSERT IGNORE INTO t1(id, c) VALUES (4, 'from er') +"Altering event test.er on the master" +ALTER EVENT test.er ON SCHEDULE EVERY 5 SECOND DO +INSERT IGNORE INTO t1(id, c) VALUES (5, 'from alter er'); +"Checking event status on the master" SELECT db, name, status, originator, body FROM mysql.event WHERE db = 'test' AND name = 'er'; db name status originator body -test er ENABLED 1 INSERT into t1(c) VALUES ('from alter er') -"in the slave" +test er ENABLED 1 INSERT IGNORE INTO t1(id, c) VALUES (5, 'from alter er') +"Checking event status on the slave" SELECT db, name, status, originator, body FROM mysql.event WHERE db = 'test' AND name = 'er'; db name status originator body -test er SLAVESIDE_DISABLED 1 INSERT into t1(c) VALUES ('from alter er') -"in the master" +test er SLAVESIDE_DISABLED 1 INSERT IGNORE INTO t1(id, c) VALUES (5, 'from alter er') +"Dropping event test.er on the master" DROP EVENT test.er; +"Checking event status on the master" SELECT db, name, status, originator FROM mysql.event WHERE db = 'test'; db name status originator -"in the slave" +"Checking event status on the slave" SELECT db, name, status, originator FROM mysql.event WHERE db = 'test'; db name status originator -CREATE EVENT test.slave_terminate ON SCHEDULE EVERY 3 SECOND -DO INSERT INTO t1(c) VALUES ('from slave_terminate'); +"Creating event test.slave_terminate on the slave" +CREATE EVENT test.slave_terminate ON SCHEDULE EVERY 3 SECOND DO +INSERT IGNORE INTO t1(id, c) VALUES (6, 'from slave_terminate'); +"Checking event status on the slave" SELECT db, name, status, originator FROM mysql.event WHERE db = 'test' AND name = 'slave_terminate'; db name status originator test slave_terminate ENABLED 2 +"Dropping event test.slave_terminate on the slave" DROP EVENT test.slave_terminate; -CREATE EVENT test.slave_terminate ON SCHEDULE EVERY 3 SECOND -DISABLE ON SLAVE DO INSERT INTO t1(c) VALUES ('from slave_terminate'); +"Creating event test.slave_terminate with DISABLE ON SLAVE on the slave" +CREATE EVENT test.slave_terminate ON SCHEDULE EVERY 3 SECOND DISABLE ON SLAVE DO +INSERT IGNORE INTO t1(c) VALUES (7, 'from slave_terminate'); +"Checking event status on the slave" SELECT db, name, status, originator FROM mysql.event WHERE db = 'test' AND name = 'slave_terminate'; db name status originator test slave_terminate SLAVESIDE_DISABLED 2 +"Dropping event test.slave_terminate on the slave" DROP EVENT test.slave_terminate; -"in the master" +"Cleanup" DROP TABLE t1; CREATE EVENT event1 ON SCHEDULE EVERY 1 YEAR DO BEGIN diff --git a/mysql-test/r/rpl_ndb_UUID.result b/mysql-test/r/rpl_ndb_UUID.result index 422379d4f55..6babf49dcaa 100644 --- a/mysql-test/r/rpl_ndb_UUID.result +++ b/mysql-test/r/rpl_ndb_UUID.result @@ -24,7 +24,7 @@ end| select fn1(0); fn1(0) 0 -create table t2 (a int); +create table t2 (a int) engine=NDB; insert into t2 values(fn1(2)); SHOW CREATE TABLE test.t1; Table Create Table diff --git a/mysql-test/r/rpl_ndb_ctype_ucs2_def.result b/mysql-test/r/rpl_ndb_ctype_ucs2_def.result new file mode 100644 index 00000000000..2f9dc4ae616 --- /dev/null +++ b/mysql-test/r/rpl_ndb_ctype_ucs2_def.result @@ -0,0 +1,9 @@ +show variables like 'collation_server'; +Variable_name Value +collation_server ucs2_unicode_ci +show variables like "%character_set_ser%"; +Variable_name Value +character_set_server ucs2 +DROP TABLE IF EXISTS t1; +create table t1 (a int); +drop table t1; diff --git a/mysql-test/r/rpl_ndb_dd_advance.result b/mysql-test/r/rpl_ndb_dd_advance.result index a4614b4b484..7f26313894c 100644 --- a/mysql-test/r/rpl_ndb_dd_advance.result +++ b/mysql-test/r/rpl_ndb_dd_advance.result @@ -56,6 +56,7 @@ undofile.dat UNDO LOG NULL lg1 undofile02.dat UNDO LOG NULL lg1 **** Do First Set of ALTERs in the master table **** CREATE INDEX t1_i ON t1(c2, c3); +CREATE UNIQUE INDEX t1_i2 ON t1(c2); ALTER TABLE t1 ADD c4 TIMESTAMP; ALTER TABLE t1 ADD c5 DOUBLE; ALTER TABLE t1 ADD INDEX (c5); @@ -68,6 +69,7 @@ t1 CREATE TABLE `t1` ( `c4` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `c5` double DEFAULT NULL, PRIMARY KEY (`c1`), + UNIQUE KEY `t1_i2` (`c2`), KEY `t1_i` (`c2`,`c3`), KEY `c5` (`c5`) ) /*!50100 TABLESPACE ts1 STORAGE DISK */ ENGINE=ndbcluster DEFAULT CHARSET=latin1 @@ -81,6 +83,7 @@ t1 CREATE TABLE `t1` ( `c4` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `c5` double DEFAULT NULL, PRIMARY KEY (`c1`), + UNIQUE KEY `t1_i2` (`c2`), KEY `t1_i` (`c2`,`c3`), KEY `c5` (`c5`) ) /*!50100 TABLESPACE ts1 STORAGE DISK */ ENGINE=ndbcluster DEFAULT CHARSET=latin1 @@ -101,6 +104,7 @@ t1 CREATE TABLE `t1` ( `c4` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `c5` double DEFAULT NULL, PRIMARY KEY (`c1`), + UNIQUE KEY `t1_i2` (`c2`), KEY `t1_i` (`c2`,`c3`) ) /*!50100 TABLESPACE ts1 STORAGE DISK */ ENGINE=ndbcluster DEFAULT CHARSET=latin1 **** Show second set of ALTERs on SLAVE **** @@ -113,6 +117,7 @@ t1 CREATE TABLE `t1` ( `c4` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `c5` double DEFAULT NULL, PRIMARY KEY (`c1`), + UNIQUE KEY `t1_i2` (`c2`), KEY `t1_i` (`c2`,`c3`) ) /*!50100 TABLESPACE ts1 STORAGE DISK */ ENGINE=ndbcluster DEFAULT CHARSET=latin1 **** Third and last set of alters for test1 **** @@ -135,6 +140,7 @@ t1 CREATE TABLE `t1` ( `c3` blob, `c5` double DEFAULT NULL, PRIMARY KEY (`c1`), + UNIQUE KEY `t1_i2` (`c2`), KEY `t1_i` (`c2`) ) /*!50100 TABLESPACE ts1 STORAGE DISK */ ENGINE=ndbcluster DEFAULT CHARSET=latin1 SELECT * FROM t1 ORDER BY c1 LIMIT 5; @@ -153,8 +159,16 @@ t1 CREATE TABLE `t1` ( `c3` blob, `c5` double DEFAULT NULL, PRIMARY KEY (`c1`), + UNIQUE KEY `t1_i2` (`c2`), KEY `t1_i` (`c2`) ) /*!50100 TABLESPACE ts1 STORAGE DISK */ ENGINE=ndbcluster DEFAULT CHARSET=latin1 +SELECT * FROM t1 ORDER BY c1 LIMIT 5; +c1 c2 c3 c5 +1 2.00 b1b1b1b1b1b1b1b1b1b1 NULL +2 4.00 b1b1b1b1b1b1b1b1b1b1 NULL +3 6.00 0000-00-00 00:00:00 NULL +4 8.00 0000-00-00 00:00:00 NULL +5 10.00 0000-00-00 00:00:00 NULL SELECT * FROM t1 where c1 = 1; c1 c2 c3 c5 1 2.00 b1b1b1b1b1b1b1b1b1b1 NULL @@ -167,148 +181,44 @@ START SLAVE; CREATE TABLESPACE ts2 ADD DATAFILE 'datafile03.dat' USE LOGFILE GROUP lg1 -INITIAL_SIZE 12M +INITIAL_SIZE 10M ENGINE=NDB; ALTER TABLESPACE ts2 ADD DATAFILE 'datafile04.dat' -INITIAL_SIZE 12M +INITIAL_SIZE 5M ENGINE=NDB; DROP DATABASE IF EXISTS tpcb; -Warnings: -Note 1008 Can't drop database 'tpcb'; database doesn't exist CREATE DATABASE tpcb; -*********** Create TPCB Tables ***************** -CREATE TABLE tpcb.account + +CREATE TABLE tpcb.account (id INT, bid INT, balance DECIMAL(10,2), filler CHAR(255), PRIMARY KEY(id)) -TABLESPACE ts1 STORAGE DISK -ENGINE=NDB; -CREATE TABLE tpcb.branch -(bid INT, balance DECIMAL(10,2), filler VARCHAR(255), -PRIMARY KEY(bid)) -ENGINE=NDB; -CREATE TABLE tpcb.teller -(tid INT, balance DECIMAL(10,2), filler VARCHAR(255), -PRIMARY KEY(tid)) TABLESPACE ts2 STORAGE DISK -ENGINE=NDB; -CREATE TABLE tpcb.history +ENGINE=NDBCLUSTER; + +CREATE TABLE tpcb.branch +(bid INT, balance DECIMAL(10,2), filler VARCHAR(255), +PRIMARY KEY(bid))TABLESPACE ts2 STORAGE DISK +ENGINE=NDBCLUSTER; + +CREATE TABLE tpcb.teller +(tid INT, balance DECIMAL(10,2), filler VARCHAR(255), +PRIMARY KEY(tid)) TABLESPACE ts2 STORAGE DISK +ENGINE=NDBCLUSTER; + +CREATE TABLE tpcb.history (id MEDIUMINT NOT NULL AUTO_INCREMENT,aid INT, tid INT, bid INT, amount DECIMAL(10,2), tdate DATETIME, teller CHAR(20), uuidf LONGBLOB, filler CHAR(80),PRIMARY KEY (id)) TABLESPACE ts2 STORAGE DISK -ENGINE=NDB; -********* Create Procedures and Functions ************ -CREATE PROCEDURE tpcb.load() -BEGIN -DECLARE acct INT DEFAULT 1000; -DECLARE brch INT DEFAULT 100; -DECLARE tell INT DEFAULT 1000; -DECLARE tmp INT DEFAULT 100; -WHILE brch > 0 DO -SET tmp = 100; -WHILE tmp > 0 DO -INSERT INTO tpcb.account VALUES (acct, brch, 0.0, "FRESH ACCOUNT"); -SET acct = acct - 1; -SET tmp = tmp -1; -END WHILE; -INSERT INTO tpcb.branch VALUES (brch, 0.0, "FRESH BRANCH"); -SET brch = brch - 1; -END WHILE; -WHILE tell > 0 DO -INSERT INTO tpcb.teller VALUES (tell, 0.0, "FRESH TELLER"); -SET tell = tell - 1; -END WHILE; -END| -CREATE FUNCTION tpcb.account_id () RETURNS INT -BEGIN -DECLARE num INT; -DECLARE ran INT; -SELECT RAND() * 10 INTO ran; -IF (ran < 2) -THEN -SELECT RAND() * 10 INTO num; -ELSEIF (ran < 4) -THEN -SELECT RAND() * 100 INTO num; -ELSE -SELECT RAND() * 1000 INTO num; -END IF; -IF (num < 1) -THEN -RETURN 1; -END IF; -RETURN num; -END| -CREATE FUNCTION tpcb.teller_id () RETURNS INT -BEGIN -DECLARE num INT; -DECLARE ran INT; -SELECT RAND() * 10 INTO ran; -IF (ran < 2) -THEN -SELECT RAND() * 10 INTO num; -ELSEIF (ran < 5) -THEN -SELECT RAND() * 100 INTO num; -ELSE -SELECT RAND() * 1000 INTO num; -END IF; -IF (num < 1) -THEN -RETURN 1; -END IF; -RETURN num; -END| -CREATE PROCEDURE tpcb.trans() -BEGIN -DECLARE acct INT DEFAULT 0; -DECLARE brch INT DEFAULT 0; -DECLARE tell INT DEFAULT 0; -DECLARE bal DECIMAL(10,2) DEFAULT 0.0; -DECLARE amount DECIMAL(10,2) DEFAULT 1.00; -DECLARE test INT DEFAULT 0; -DECLARE bbal DECIMAL(10,2) DEFAULT 0.0; -DECLARE tbal DECIMAL(10,2) DEFAULT 0.0; -DECLARE local_uuid VARCHAR(255); -DECLARE local_user VARCHAR(255); -DECLARE local_time TIMESTAMP; -SELECT RAND() * 10 INTO test; -SELECT tpcb.account_id() INTO acct; -SELECT tpcb.teller_id() INTO tell; -SELECT account.balance INTO bal FROM tpcb.account WHERE id = acct; -SELECT account.bid INTO brch FROM tpcb.account WHERE id = acct; -SELECT teller.balance INTO tbal FROM tpcb.teller WHERE tid = tell; -SELECT branch.balance INTO bbal FROM tpcb.branch WHERE bid = brch; -IF (test < 5) -THEN -SET bal = bal + amount; -SET bbal = bbal + amount; -SET tbal = tbal + amount; -UPDATE tpcb.account SET balance = bal, filler = 'account updated' - WHERE id = acct; -UPDATE tpcb.branch SET balance = bbal, filler = 'branch updated' - WHERE bid = brch; -UPDATE tpcb.teller SET balance = tbal, filler = 'teller updated' - WHERE tid = tell; -ELSE -SET bal = bal - amount; -SET bbal = bbal - amount; -SET tbal = tbal - amount; -UPDATE tpcb.account SET balance = bal, filler = 'account updated' - WHERE id = acct; -UPDATE tpcb.branch SET balance = bbal, filler = 'branch updated' - WHERE bid = brch; -UPDATE tpcb.teller SET balance = tbal, filler = 'teller updated' - WHERE tid = tell; -END IF; -SET local_uuid=UUID(); -SET local_user=USER(); -SET local_time= NOW(); -INSERT INTO tpcb.history VALUES(NULL,acct,tell,brch,amount, local_time,local_user, -local_uuid,'completed trans'); -END| +ENGINE=NDBCLUSTER; + +--- Create stored procedures & functions --- + + +*** Stored Procedures Created *** + ****** TEST 2 test time ********************************* USE tpcb; *********** Load up the database ****************** @@ -316,11 +226,11 @@ CALL tpcb.load(); ********** Check load master and slave ************** SELECT COUNT(*) FROM account; COUNT(*) -10000 +1000 USE tpcb; SELECT COUNT(*) FROM account; COUNT(*) -10000 +1000 ******** Run in some transactions *************** ***** Time to try slave sync *********** **** Must make sure slave is clean ***** @@ -351,10 +261,10 @@ DROP LOGFILE GROUP lg1 ENGINE=NDB; ********** Take a backup of the Master ************* SELECT COUNT(*) FROM history; COUNT(*) -1000 +100 SELECT COUNT(*) FROM history; COUNT(*) -2000 +200 CREATE TEMPORARY TABLE IF NOT EXISTS mysql.backup_info (id INT, backup_id INT) ENGINE = HEAP; DELETE FROM mysql.backup_info; LOAD DATA INFILE '../tmp.dat' INTO TABLE mysql.backup_info FIELDS TERMINATED BY ','; @@ -368,7 +278,7 @@ CREATE DATABASE tpcb; USE tpcb; SELECT COUNT(*) FROM account; COUNT(*) -10000 +1000 ***** Add some more records to master ********* ***** Finsh the slave sync process ******* @the_epoch:=MAX(epoch) @@ -384,12 +294,12 @@ START SLAVE; USE tpcb; SELECT COUNT(*) FROM history; COUNT(*) -4050 +400 ****** SLAVE ******** USE tpcb; SELECT COUNT(*) FROM history; COUNT(*) -4050 +400 *** DUMP MASTER & SLAVE FOR COMPARE ******** *************** TEST 2 CLEANUP SECTION ******************** DROP PROCEDURE IF EXISTS tpcb.load; diff --git a/mysql-test/r/rpl_ndb_mix_innodb.result b/mysql-test/r/rpl_ndb_mix_innodb.result new file mode 100644 index 00000000000..625d06de44b --- /dev/null +++ b/mysql-test/r/rpl_ndb_mix_innodb.result @@ -0,0 +1,129 @@ +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; + +*** Test 1 *** + +create table t1 (a int key, b int) engine innodb; +create table t2 (a int key, b int) engine innodb; + +alter table t1 engine ndb; +alter table t2 engine ndb; + +insert into t1 values (1,2); + +select @log_name:=log_name, @start_pos:=start_pos, @end_pos:=end_pos +from mysql.ndb_apply_status; +@log_name:=log_name @start_pos:=start_pos @end_pos:=end_pos + + +show binlog events from limit 1; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 Query 1 # use `test`; insert into t1 values (1,2) + +show binlog events from limit 1,1; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Xid 1 445 COMMIT /* XID */ + +begin; +insert into t1 values (2,3); +insert into t2 values (3,4); +commit; + +select @log_name:=log_name, @start_pos:=start_pos, @end_pos:=end_pos +from mysql.ndb_apply_status; +@log_name:=log_name @start_pos:=start_pos @end_pos:=end_pos + +show binlog events from limit 1; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 Query 1 # use `test`; BEGIN + +show binlog events from limit 1,2; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; insert into t1 values (2,3) +master-bin.000001 # Query # # use `test`; insert into t2 values (3,4) + +show binlog events from limit 3,1; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Xid 1 COMMIT /* XID */ + +DROP TABLE test.t1, test.t2; +SHOW TABLES; +Tables_in_test + +*** Test 2 *** + +DROP DATABASE IF EXISTS tpcb; +CREATE DATABASE tpcb; + +CREATE TABLE tpcb.account (id INT, bid INT, balance DECIMAL(10,2), +filler CHAR(255), PRIMARY KEY(id)); + +CREATE TABLE tpcb.branch (bid INT, balance DECIMAL(10,2), filler VARCHAR(255), +PRIMARY KEY(bid)); + +CREATE TABLE tpcb.teller (tid INT, balance DECIMAL(10,2), filler VARCHAR(255), +PRIMARY KEY(tid)); + +CREATE TABLE tpcb.history (id MEDIUMINT NOT NULL AUTO_INCREMENT,aid INT, +tid INT, bid INT, amount DECIMAL(10,2), +tdate DATETIME, teller CHAR(20), uuidf LONGBLOB, +filler CHAR(80),PRIMARY KEY (id)); + +--- Create stored procedures & functions --- + + +*** Stored Procedures Created *** + +USE tpcb; +ALTER TABLE account ENGINE NDB; +ALTER TABLE branch ENGINE NDB; +ALTER TABLE teller ENGINE NDB; +ALTER TABLE history ENGINE NDB; + +select @log_name:=log_name, @start_pos:=start_pos, @end_pos:=end_pos +from mysql.ndb_apply_status; +@log_name:=log_name @start_pos:=start_pos @end_pos:=end_pos + + +show binlog events in 'master-bin.000001' from limit 9,1; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Xid 1 COMMIT /* XID */ + +** Test 3 ** + +FLUSH LOGS; + +select @log_name:=log_name, @start_pos:=start_pos, @end_pos:=end_pos +from mysql.ndb_apply_status; +@log_name:=log_name @start_pos:=start_pos @end_pos:=end_pos + + +show binlog events in 'master-bin.000002' from limit 9,1; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000002 # Xid 1 COMMIT /* XID */ + +** Test 4 ** + +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; + +select @log_name:=log_name, @start_pos:=start_pos, @end_pos:=end_pos +from mysql.ndb_apply_status; +@log_name:=log_name @start_pos:=start_pos @end_pos:=end_pos + + +show binlog events in 'master-bin.000001' from limit 9,1; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Xid 1 COMMIT /* XID */ + +*** DUMP MASTER & SLAVE FOR COMPARE ******** +DROP DATABASE tpcb; +****** Do dumps compare ************ diff --git a/mysql-test/r/rpl_ndb_stm_innodb.result b/mysql-test/r/rpl_ndb_stm_innodb.result index 624439754b2..426a09f945c 100644 --- a/mysql-test/r/rpl_ndb_stm_innodb.result +++ b/mysql-test/r/rpl_ndb_stm_innodb.result @@ -4,37 +4,126 @@ reset master; reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; + +*** Test 1 *** + create table t1 (a int key, b int) engine innodb; create table t2 (a int key, b int) engine innodb; + alter table t1 engine ndb; alter table t2 engine ndb; -STOP SLAVE; -SET GLOBAL BINLOG_FORMAT=MIXED; -START SLAVE; + insert into t1 values (1,2); -select @start_pos:=start_pos, @end_pos:=end_pos from mysql.ndb_apply_status; -@start_pos:=start_pos @end_pos:=end_pos - + +select @log_name:=log_name, @start_pos:=start_pos, @end_pos:=end_pos +from mysql.ndb_apply_status; +@log_name:=log_name @start_pos:=start_pos @end_pos:=end_pos + + show binlog events from limit 1; Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 Query 1 # use `test`; insert into t1 values (1,2) + show binlog events from limit 1,1; Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 # Xid 1 445 COMMIT /* XID */ + begin; insert into t1 values (2,3); insert into t2 values (3,4); commit; -select @start_pos:=start_pos, @end_pos:=end_pos from mysql.ndb_apply_status; -@start_pos:=start_pos @end_pos:=end_pos - + +select @log_name:=log_name, @start_pos:=start_pos, @end_pos:=end_pos +from mysql.ndb_apply_status; +@log_name:=log_name @start_pos:=start_pos @end_pos:=end_pos + show binlog events from limit 1; Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 Query 1 # use `test`; BEGIN + show binlog events from limit 1,2; Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 # Query # # use `test`; insert into t1 values (2,3) master-bin.000001 # Query # # use `test`; insert into t2 values (3,4) + show binlog events from limit 3,1; Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 # Xid 1 COMMIT /* XID */ + +DROP TABLE test.t1, test.t2; +SHOW TABLES; +Tables_in_test + +*** Test 2 *** + +DROP DATABASE IF EXISTS tpcb; +CREATE DATABASE tpcb; + +CREATE TABLE tpcb.account (id INT, bid INT, balance DECIMAL(10,2), +filler CHAR(255), PRIMARY KEY(id)); + +CREATE TABLE tpcb.branch (bid INT, balance DECIMAL(10,2), filler VARCHAR(255), +PRIMARY KEY(bid)); + +CREATE TABLE tpcb.teller (tid INT, balance DECIMAL(10,2), filler VARCHAR(255), +PRIMARY KEY(tid)); + +CREATE TABLE tpcb.history (id MEDIUMINT NOT NULL AUTO_INCREMENT,aid INT, +tid INT, bid INT, amount DECIMAL(10,2), +tdate DATETIME, teller CHAR(20), uuidf LONGBLOB, +filler CHAR(80),PRIMARY KEY (id)); + +--- Create stored procedures & functions --- + + +*** Stored Procedures Created *** + +USE tpcb; +ALTER TABLE account ENGINE NDB; +ALTER TABLE branch ENGINE NDB; +ALTER TABLE teller ENGINE NDB; +ALTER TABLE history ENGINE NDB; + +select @log_name:=log_name, @start_pos:=start_pos, @end_pos:=end_pos +from mysql.ndb_apply_status; +@log_name:=log_name @start_pos:=start_pos @end_pos:=end_pos + + +show binlog events in 'master-bin.000001' from limit 6,1; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Xid 1 COMMIT /* XID */ + +** Test 3 ** + +FLUSH LOGS; + +select @log_name:=log_name, @start_pos:=start_pos, @end_pos:=end_pos +from mysql.ndb_apply_status; +@log_name:=log_name @start_pos:=start_pos @end_pos:=end_pos + + +show binlog events in 'master-bin.000002' from limit 6,1; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000002 # Xid 1 COMMIT /* XID */ + +** Test 4 ** + +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; + +select @log_name:=log_name, @start_pos:=start_pos, @end_pos:=end_pos +from mysql.ndb_apply_status; +@log_name:=log_name @start_pos:=start_pos @end_pos:=end_pos + + +show binlog events in 'master-bin.000001' from limit 6,1; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Xid 1 COMMIT /* XID */ + +*** DUMP MASTER & SLAVE FOR COMPARE ******** +DROP DATABASE tpcb; +****** Do dumps compare ************ diff --git a/mysql-test/r/rpl_row_UUID.result b/mysql-test/r/rpl_row_UUID.result index f56dc145901..02174a7ecae 100644 --- a/mysql-test/r/rpl_row_UUID.result +++ b/mysql-test/r/rpl_row_UUID.result @@ -24,7 +24,7 @@ end| select fn1(0); fn1(0) 0 -create table t2 (a int); +create table t2 (a int) engine=myisam; insert into t2 values(fn1(2)); SHOW CREATE TABLE test.t1; Table Create Table diff --git a/mysql-test/t/binlog_multi_engine.test b/mysql-test/t/binlog_multi_engine.test index 6614b9e5d44..058aca0f715 100644 --- a/mysql-test/t/binlog_multi_engine.test +++ b/mysql-test/t/binlog_multi_engine.test @@ -1,6 +1,11 @@ +# Test to test how logging is done depending on the capabilities of +# the engines. Unfortunately, we don't have a good row-only logging +# engine, and NDB does not really cut is since it is also +# self-logging. I'm using it nevertheless. + source include/have_blackhole.inc; source include/have_ndb.inc; -source include/have_binlog_format_mixed_or_row.inc; +source include/have_log_bin.inc; CREATE TABLE t1m (m INT, n INT) ENGINE=MYISAM; CREATE TABLE t1b (b INT, c INT) ENGINE=BLACKHOLE; @@ -15,9 +20,6 @@ INSERT INTO t1b VALUES (1,1), (1,2), (2,1), (2,2); UPDATE t1m, t1b SET m = 2, b = 3 WHERE n = c; -# I cannot use these statements since the rows logged to the NDB table -# eventually shows up in the binary log. I use them anyway, since once -# BUG#29222 is fixed, there will be a difference here. echo *** Please look in binlog_multi_engine.test if you have a diff here ****; START TRANSACTION; INSERT INTO t1n VALUES (1,1), (1,2), (2,1), (2,2); @@ -40,6 +42,8 @@ INSERT INTO t1b VALUES (1,1), (1,2), (2,1), (2,2); INSERT INTO t1n VALUES (1,1), (1,2), (2,1), (2,2); UPDATE t1m, t1b SET m = 2, b = 3 WHERE n = c; +error ER_BINLOG_LOGGING_IMPOSSIBLE; +UPDATE t1m, t1n SET m = 2, e = 3 WHERE n = f; # Not possible to test this since NDB writes its own binlog, which # might cause it to be out of sync with the results from MyISAM. @@ -67,6 +71,8 @@ INSERT INTO t1n VALUES (1,1), (1,2), (2,1), (2,2); error ER_BINLOG_LOGGING_IMPOSSIBLE; UPDATE t1m, t1b SET m = 2, b = 3 WHERE n = c; +error ER_BINLOG_LOGGING_IMPOSSIBLE; +UPDATE t1m, t1n SET m = 2, e = 3 WHERE n = f; # Not possible to test this since NDB writes its own binlog, which # might cause it to be out of sync with the results from MyISAM. diff --git a/mysql-test/t/ctype_ucs.test b/mysql-test/t/ctype_ucs.test index c3320159c41..8828cd10eec 100644 --- a/mysql-test/t/ctype_ucs.test +++ b/mysql-test/t/ctype_ucs.test @@ -594,4 +594,22 @@ select data_type, character_octet_length, character_maximum_length from information_schema.columns where table_name='t1'; drop table t1; +# +# Bug#28925 GROUP_CONCAT inserts wrong separators for a ucs2 column +# +create table t1 (a char(1) character set ucs2); +insert into t1 values ('a'),('b'),('c'); +select hex(group_concat(a)) from t1; +select collation(group_concat(a)) from t1; +drop table t1; + +set names latin1; +create table t1 (a char(1) character set latin1); +insert into t1 values ('a'),('b'),('c'); +set character_set_connection=ucs2; +select hex(group_concat(a separator ',')) from t1; +select collation(group_concat(a separator ',')) from t1; +drop table t1; +set names latin1; + --echo End of 5.0 tests diff --git a/mysql-test/t/ctype_ucs2_def.test b/mysql-test/t/ctype_ucs2_def.test index 050710b208b..c80444daddd 100644 --- a/mysql-test/t/ctype_ucs2_def.test +++ b/mysql-test/t/ctype_ucs2_def.test @@ -15,6 +15,16 @@ DROP TABLE IF EXISTS t1; create table t1 (a int); drop table t1; +--echo End of 4.1 tests + +# +# Bug #28925 GROUP_CONCAT inserts wrong separators for a ucs2 column +# Check that GROUP_CONCAT works fine with --default-character-set=ucs2 +# +create table t1 (a char(1) character set latin1); +insert into t1 values ('a'),('b'),('c'); +select hex(group_concat(a)) from t1; +drop table t1; # # Bug #27643: query failed : 1114 (The table '' is full) # diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index 32de2077e81..cdacb090a1b 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -19,7 +19,6 @@ im_instance_conf : Bug#20294 2007-05-30 alik Instance manager tests im_life_cycle : BUG#27851 Instance manager dies on ASSERT in ~Thread_registry() or from not being able to close a mysqld instance. im_instance_conf : BUG#28743 Instance manager generates warnings in test suite im_utils : BUG#28743 Instance manager generates warnings in test suite -innodb : Disabling test case awaiting reply from Innobase concurrent_innodb : BUG#21579 2006-08-11 mleich innodb_concurrent random failures with varying differences ndb_autodiscover : BUG#18952 2006-02-16 jmiller Needs to be fixed w.r.t binlog ndb_autodiscover2 : BUG#18952 2006-02-16 jmiller Needs to be fixed w.r.t binlog @@ -35,6 +34,8 @@ rpl_ndb_innodb2ndb : Bug #19710 Cluster replication to partition table fa rpl_ndb_myisam2ndb : Bug #19710 Cluster replication to partition table fails on DELETE FROM statement #rpl_row_blob_innodb : BUG#18980 2006-04-10 kent Test fails randomly rpl_ndb_ddl : BUG#28798 2007-05-31 lars Valgrind failure in NDB +rpl_ndb_mix_innodb : BUG#28123 rpl_ndb_mix_innodb.test casue slave to core on sol10-sparc-a +rpl_ndb_ctype_ucs2_def : BUG#27404 util thd mysql_parse sig11 when mysqld default multibyte charset rpl_invoked_features : BUG#29020 2007-06-21 Lars Non-deterministic test case ctype_big5 : BUG#26711 2007-06-21 Lars Test has never worked on Double Whopper @@ -52,5 +53,4 @@ im_options_set : Bug#20294: Instance manager tests fail randomly im_options_unset : Bug#20294: Instance manager tests fail randomly mysql_upgrade : Bug#28560 test links to /usr/local/mysql/lib libraries, causes non-determinism and failures on ABI breakage rpl_udf : Bug#28993 rpl_udf test causes server crash and valgrind warning in pushbuild -rpl_ndb_circular : Bug#29233 rpl_ndb_circular fails randomly ndb_dd_sql_features : Bug#29102 ndb_dd_sql_features fails in pushbuild diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test index 1ca6b8b4d98..321a1f4763a 100644 --- a/mysql-test/t/innodb.test +++ b/mysql-test/t/innodb.test @@ -13,6 +13,11 @@ -- source include/not_embedded.inc -- source include/have_innodb.inc +-- source include/have_log_bin.inc + +# Disabling it temporarily for statement-based logging since some +# tests are not safe while binlog is on. +-- source include/have_binlog_format_mixed_or_row.inc # # Small basic test with ignore @@ -774,7 +779,7 @@ CREATE TABLE `t2` ( insert into t1 values (1,1),(2,2); insert into t2 values (1,1),(4,4); reset master; ---error ER_DUP_ENTRY_WITH_KEY_NAME +--error ER_DUP_ENTRY UPDATE t2,t1 SET t2.a=t1.a+2; # check select * from t2 /* must be (3,1), (4,4) */; @@ -786,7 +791,7 @@ delete from t2; insert into t1 values (1,2),(3,4),(4,4); insert into t2 values (1,2),(3,4),(4,4); reset master; ---error ER_DUP_ENTRY_WITH_KEY_NAME +--error ER_DUP_ENTRY UPDATE t2,t1 SET t2.a=t2.b where t2.a=t1.a; show master status /* there must be no UPDATE query event */; diff --git a/mysql-test/t/loaddata_autocom_ndb.test b/mysql-test/t/loaddata_autocom_ndb.test index a6a3aec2c4e..f4a6743aabe 100644 --- a/mysql-test/t/loaddata_autocom_ndb.test +++ b/mysql-test/t/loaddata_autocom_ndb.test @@ -1,5 +1,4 @@ --source include/have_ndb.inc ---source include/have_binlog_format_mixed_or_row.inc let $engine_type=ndbcluster; --source include/loaddata_autocom.inc diff --git a/mysql-test/t/ndb_alter_table.test b/mysql-test/t/ndb_alter_table.test index d85e4900337..082fe726927 100644 --- a/mysql-test/t/ndb_alter_table.test +++ b/mysql-test/t/ndb_alter_table.test @@ -1,5 +1,3 @@ --- source include/have_ndb.inc --- source include/have_binlog_format_row.inc -- source include/have_multi_ndb.inc -- source include/not_embedded.inc diff --git a/mysql-test/t/ndb_alter_table2.test b/mysql-test/t/ndb_alter_table2.test index 654453cc4cf..f078ed6b479 100644 --- a/mysql-test/t/ndb_alter_table2.test +++ b/mysql-test/t/ndb_alter_table2.test @@ -1,5 +1,3 @@ --- source include/have_ndb.inc --- source include/have_binlog_format_row.inc -- source include/have_multi_ndb.inc -- source include/not_embedded.inc diff --git a/mysql-test/t/ndb_alter_table3.test b/mysql-test/t/ndb_alter_table3.test index 2f8f9ebcf89..86e664b23b0 100644 --- a/mysql-test/t/ndb_alter_table3.test +++ b/mysql-test/t/ndb_alter_table3.test @@ -1,5 +1,3 @@ --- source include/have_ndb.inc --- source include/have_binlog_format_row.inc -- source include/have_multi_ndb.inc -- source include/not_embedded.inc diff --git a/mysql-test/t/ndb_autodiscover.test b/mysql-test/t/ndb_autodiscover.test index 6e70b8f5979..06d47693c10 100644 --- a/mysql-test/t/ndb_autodiscover.test +++ b/mysql-test/t/ndb_autodiscover.test @@ -1,5 +1,4 @@ -- source include/have_ndb.inc --- source include/have_binlog_format_row.inc -- source include/not_embedded.inc --disable_warnings diff --git a/mysql-test/t/ndb_autodiscover2.test b/mysql-test/t/ndb_autodiscover2.test index 360ce7195a8..ebe14696cd2 100644 --- a/mysql-test/t/ndb_autodiscover2.test +++ b/mysql-test/t/ndb_autodiscover2.test @@ -1,5 +1,4 @@ -- source include/have_ndb.inc --- source include/have_binlog_format_row.inc -- source include/not_embedded.inc # diff --git a/mysql-test/t/ndb_autodiscover3.test b/mysql-test/t/ndb_autodiscover3.test index 36ee191c065..452ccc50b4d 100644 --- a/mysql-test/t/ndb_autodiscover3.test +++ b/mysql-test/t/ndb_autodiscover3.test @@ -1,5 +1,3 @@ --- source include/have_ndb.inc --- source include/have_binlog_format_row.inc -- source include/have_multi_ndb.inc -- source include/ndb_default_cluster.inc -- source include/not_embedded.inc @@ -11,6 +9,9 @@ drop table if exists t1, t2; --enable_warnings +connect (con1,127.0.0.1,root,,test,$MASTER_MYPORT,); +connect (con2,127.0.0.1,root,,test,$MASTER_MYPORT1,); + # Workaround for Bug#27644 # ndb: connecting api node/mysqld may "steal" node_id from running mysqld # - let ndb_waiter use a fixed node id so "steal" cannot happen @@ -28,8 +29,14 @@ insert into t1 values (1); --exec $NDB_MGM --no-defaults -e "all restart" >> $NDB_TOOLS_OUTPUT --exec $NDB_TOOLS_DIR/ndb_waiter --no-defaults -c $connect_str >> $NDB_TOOLS_OUTPUT # Wait for mysqld to reconnect and exit from readonly mode -# Should preferrably be a "while (!"select ndb_readonly")" loop -sleep 2; +--disable_query_log +--connection con1 +--source include/ndb_not_readonly.inc +--connection con2 +--source include/ndb_not_readonly.inc +--enable_query_log + +--connection server1 --error 1297 insert into t1 values (2); --error 1296 @@ -48,8 +55,13 @@ select * from t2 order by a limit 3; --exec $NDB_MGM --no-defaults -e "all restart -i" >> $NDB_TOOLS_OUTPUT --exec $NDB_TOOLS_DIR/ndb_waiter --no-defaults -c $connect_str >> $NDB_TOOLS_OUTPUT # to ensure mysqld has connected again, and recreated system tables ---exec $NDB_TOOLS_DIR/ndb_desc --no-defaults -r 30 -d cluster ndb_apply_status >> $NDB_TOOLS_OUTPUT -sleep 2; +--disable_query_log +--connection con1 +--source include/ndb_not_readonly.inc +--connection con2 +--source include/ndb_not_readonly.inc +--enable_query_log + --connection server2 --error ER_NO_SUCH_TABLE select * from t2; @@ -67,8 +79,13 @@ reset master; --exec $NDB_MGM --no-defaults -e "all restart -i" >> $NDB_TOOLS_OUTPUT --exec $NDB_TOOLS_DIR/ndb_waiter --no-defaults -c $connect_str >> $NDB_TOOLS_OUTPUT # to ensure mysqld has connected again, and recreated system tables ---exec $NDB_TOOLS_DIR/ndb_desc --no-defaults -r 30 -d cluster ndb_apply_status >> $NDB_TOOLS_OUTPUT -sleep 2; +--disable_query_log +--connection con1 +--source include/ndb_not_readonly.inc +--connection con2 +--source include/ndb_not_readonly.inc +--enable_query_log + --connection server1 --error ER_NO_SUCH_TABLE select * from t2; diff --git a/mysql-test/t/ndb_basic.test b/mysql-test/t/ndb_basic.test index 8ef231599fa..b9ccdf9fd0d 100644 --- a/mysql-test/t/ndb_basic.test +++ b/mysql-test/t/ndb_basic.test @@ -1,5 +1,4 @@ -- source include/have_ndb.inc --- source include/have_binlog_format_row.inc -- source include/not_embedded.inc --disable_warnings diff --git a/mysql-test/t/ndb_binlog_ddl_multi.test b/mysql-test/t/ndb_binlog_ddl_multi.test index 487dfbf16e5..e159fd6a24e 100644 --- a/mysql-test/t/ndb_binlog_ddl_multi.test +++ b/mysql-test/t/ndb_binlog_ddl_multi.test @@ -1,4 +1,3 @@ --- source include/have_ndb.inc -- source include/have_multi_ndb.inc -- source include/have_binlog_format_row.inc diff --git a/mysql-test/t/ndb_binlog_format.test b/mysql-test/t/ndb_binlog_format.test new file mode 100644 index 00000000000..acb34bb388c --- /dev/null +++ b/mysql-test/t/ndb_binlog_format.test @@ -0,0 +1,33 @@ +# +# test different behavior of ndb using different binlog formats +# + +-- source include/have_blackhole.inc +-- source include/have_ndb.inc +-- source include/have_log_bin.inc + +--disable_warnings +drop table if exists t1, t2, t3; +--enable_warnings + +# +# Bug #29222 Statement mode replicates both statement and +# rows when writing to an NDB table +# +CREATE TABLE t1 (m INT, n INT) ENGINE=MYISAM; +CREATE TABLE t2 (b INT, c INT) ENGINE=BLACKHOLE; +CREATE TABLE t3 (e INT, f INT) ENGINE=NDB; +RESET MASTER; +SET SESSION BINLOG_FORMAT=STATEMENT; +INSERT INTO t1 VALUES (1,1), (1,2), (2,1), (2,2); +INSERT INTO t2 VALUES (1,1), (1,2), (2,1), (2,2); +UPDATE t1, t2 SET m = 2, b = 3 WHERE n = c; +# A transaction here is not necessary, but I wanted to group the bad statements +START TRANSACTION; +INSERT INTO t3 VALUES (1,1), (1,2), (2,1), (2,2); +UPDATE t1, t3 SET m = 2, e = 3 WHERE n = f; +UPDATE t3, t2 SET e = 2, b = 3 WHERE f = c; +COMMIT; +--source include/show_binlog_events.inc +DROP TABLE t1, t2, t3; + diff --git a/mysql-test/t/ndb_binlog_log_bin.test b/mysql-test/t/ndb_binlog_log_bin.test index 63b84134824..921b8608795 100644 --- a/mysql-test/t/ndb_binlog_log_bin.test +++ b/mysql-test/t/ndb_binlog_log_bin.test @@ -1,5 +1,3 @@ --- source include/have_ndb.inc --- source include/have_binlog_format_row.inc -- source include/have_multi_ndb.inc -- source include/have_binlog_format_row.inc diff --git a/mysql-test/t/ndb_binlog_multi.test b/mysql-test/t/ndb_binlog_multi.test index 4256b0bf993..14bd7ef174b 100644 --- a/mysql-test/t/ndb_binlog_multi.test +++ b/mysql-test/t/ndb_binlog_multi.test @@ -1,5 +1,3 @@ --- source include/have_ndb.inc --- source include/have_binlog_format_row.inc -- source include/have_multi_ndb.inc -- source include/have_binlog_format_row.inc diff --git a/mysql-test/t/ndb_bitfield.test b/mysql-test/t/ndb_bitfield.test index c8454f38cca..de0ae23bfe6 100644 --- a/mysql-test/t/ndb_bitfield.test +++ b/mysql-test/t/ndb_bitfield.test @@ -1,5 +1,4 @@ -- source include/have_ndb.inc --- source include/have_binlog_format_row.inc -- source include/not_embedded.inc --disable_warnings diff --git a/mysql-test/t/ndb_blob.test b/mysql-test/t/ndb_blob.test index b565de74c26..b9a8c7e20ee 100644 --- a/mysql-test/t/ndb_blob.test +++ b/mysql-test/t/ndb_blob.test @@ -1,5 +1,4 @@ --source include/have_ndb.inc --- source include/have_binlog_format_row.inc -- source include/not_embedded.inc --disable_warnings diff --git a/mysql-test/t/ndb_blob_partition.test b/mysql-test/t/ndb_blob_partition.test index 13ad2ecc7c3..35df57b96ba 100644 --- a/mysql-test/t/ndb_blob_partition.test +++ b/mysql-test/t/ndb_blob_partition.test @@ -1,5 +1,4 @@ --source include/have_ndb.inc --- source include/have_binlog_format_row.inc -- source include/not_embedded.inc --disable_query_log diff --git a/mysql-test/t/ndb_cache.test b/mysql-test/t/ndb_cache.test index d8cb8b01e86..9c299b61c24 100644 --- a/mysql-test/t/ndb_cache.test +++ b/mysql-test/t/ndb_cache.test @@ -1,5 +1,4 @@ -- source include/have_query_cache.inc --- source include/have_binlog_format_row.inc -- source include/have_ndb.inc -- source include/not_embedded.inc diff --git a/mysql-test/t/ndb_cache2.test b/mysql-test/t/ndb_cache2.test index 27d39b09cf6..352b01ef73f 100644 --- a/mysql-test/t/ndb_cache2.test +++ b/mysql-test/t/ndb_cache2.test @@ -1,5 +1,4 @@ -- source include/have_query_cache.inc --- source include/have_binlog_format_row.inc -- source include/have_ndb.inc -- source include/not_embedded.inc diff --git a/mysql-test/t/ndb_cache_multi.test b/mysql-test/t/ndb_cache_multi.test index a7095139285..8c7f186b866 100644 --- a/mysql-test/t/ndb_cache_multi.test +++ b/mysql-test/t/ndb_cache_multi.test @@ -1,6 +1,4 @@ -- source include/have_query_cache.inc --- source include/have_binlog_format_row.inc --- source include/have_ndb.inc -- source include/have_multi_ndb.inc -- source include/not_embedded.inc diff --git a/mysql-test/t/ndb_cache_multi2.test b/mysql-test/t/ndb_cache_multi2.test index 40cc41f1c97..853e4090193 100644 --- a/mysql-test/t/ndb_cache_multi2.test +++ b/mysql-test/t/ndb_cache_multi2.test @@ -1,6 +1,4 @@ -- source include/have_query_cache.inc --- source include/have_binlog_format_row.inc --- source include/have_ndb.inc -- source include/have_multi_ndb.inc -- source include/not_embedded.inc diff --git a/mysql-test/t/ndb_charset.test b/mysql-test/t/ndb_charset.test index b36b70be94c..2d9f66564bc 100644 --- a/mysql-test/t/ndb_charset.test +++ b/mysql-test/t/ndb_charset.test @@ -1,5 +1,4 @@ --source include/have_ndb.inc --- source include/have_binlog_format_row.inc -- source include/not_embedded.inc --disable_warnings diff --git a/mysql-test/t/ndb_condition_pushdown.test b/mysql-test/t/ndb_condition_pushdown.test index 9df494aa3ab..ab56430ac1d 100644 --- a/mysql-test/t/ndb_condition_pushdown.test +++ b/mysql-test/t/ndb_condition_pushdown.test @@ -1,5 +1,4 @@ -- source include/have_ndb.inc --- source include/have_binlog_format_row.inc -- source include/not_embedded.inc --disable_warnings diff --git a/mysql-test/t/ndb_config.test b/mysql-test/t/ndb_config.test index eb52bd249d6..f63c0087c1e 100644 --- a/mysql-test/t/ndb_config.test +++ b/mysql-test/t/ndb_config.test @@ -1,5 +1,4 @@ -- source include/have_ndb.inc --- source include/have_binlog_format_row.inc -- source include/ndb_default_cluster.inc -- source include/not_embedded.inc diff --git a/mysql-test/t/ndb_config2.test b/mysql-test/t/ndb_config2.test index 20946b53552..170f1b2e5e7 100644 --- a/mysql-test/t/ndb_config2.test +++ b/mysql-test/t/ndb_config2.test @@ -1,5 +1,4 @@ -- source include/have_ndb.inc --- source include/have_binlog_format_row.inc -- source include/ndb_default_cluster.inc -- source include/not_embedded.inc diff --git a/mysql-test/t/ndb_cursor.test b/mysql-test/t/ndb_cursor.test index 1ef745a13f7..406f8629cfe 100644 --- a/mysql-test/t/ndb_cursor.test +++ b/mysql-test/t/ndb_cursor.test @@ -1,5 +1,4 @@ -- source include/have_ndb.inc --- source include/have_binlog_format_row.inc -- source include/not_embedded.inc --disable_warnings diff --git a/mysql-test/t/ndb_database.test b/mysql-test/t/ndb_database.test index 409ac33502a..8bfdf40de88 100644 --- a/mysql-test/t/ndb_database.test +++ b/mysql-test/t/ndb_database.test @@ -1,5 +1,4 @@ -- source include/have_ndb.inc --- source include/have_binlog_format_row.inc -- source include/not_embedded.inc --disable_warnings diff --git a/mysql-test/t/ndb_dd_alter.test b/mysql-test/t/ndb_dd_alter.test index ee58968247f..7635a8944da 100644 --- a/mysql-test/t/ndb_dd_alter.test +++ b/mysql-test/t/ndb_dd_alter.test @@ -40,7 +40,6 @@ ############################################################## -- source include/have_ndb.inc --- source include/have_binlog_format_row.inc -- source include/have_innodb.inc -- source include/not_embedded.inc diff --git a/mysql-test/t/ndb_dd_backuprestore.test b/mysql-test/t/ndb_dd_backuprestore.test index 156ff88718e..48db8ec3e0b 100644 --- a/mysql-test/t/ndb_dd_backuprestore.test +++ b/mysql-test/t/ndb_dd_backuprestore.test @@ -5,7 +5,6 @@ ######################################## -- source include/have_ndb.inc --- source include/have_binlog_format_row.inc -- source include/ndb_default_cluster.inc -- source include/not_embedded.inc diff --git a/mysql-test/t/ndb_dd_basic.test b/mysql-test/t/ndb_dd_basic.test index d20ffc6e4bd..3acf4669868 100644 --- a/mysql-test/t/ndb_dd_basic.test +++ b/mysql-test/t/ndb_dd_basic.test @@ -13,7 +13,6 @@ ################################# -- source include/have_ndb.inc --- source include/have_binlog_format_row.inc --disable_warnings DROP TABLE IF EXISTS t1; diff --git a/mysql-test/t/ndb_dd_ddl.test b/mysql-test/t/ndb_dd_ddl.test index 10229e4c0c2..aa692385b07 100644 --- a/mysql-test/t/ndb_dd_ddl.test +++ b/mysql-test/t/ndb_dd_ddl.test @@ -27,7 +27,6 @@ -- source include/have_ndb.inc --- source include/have_binlog_format_row.inc --disable_warnings DROP TABLE IF EXISTS t1; diff --git a/mysql-test/t/ndb_dd_disk2memory.test b/mysql-test/t/ndb_dd_disk2memory.test index 760a1377bdf..5975f44e087 100644 --- a/mysql-test/t/ndb_dd_disk2memory.test +++ b/mysql-test/t/ndb_dd_disk2memory.test @@ -6,7 +6,6 @@ ######################################## -- source include/have_ndb.inc --- source include/have_binlog_format_row.inc --disable_warnings DROP TABLE IF EXISTS test.t1; diff --git a/mysql-test/t/ndb_dd_dump.test b/mysql-test/t/ndb_dd_dump.test index 54128d075ca..38ceafb7d80 100644 --- a/mysql-test/t/ndb_dd_dump.test +++ b/mysql-test/t/ndb_dd_dump.test @@ -1,5 +1,4 @@ -- source include/have_ndb.inc --- source include/have_binlog_format_row.inc --disable_warnings DROP TABLE IF EXISTS t1, t2, t3; diff --git a/mysql-test/t/ndb_dd_sql_features.test b/mysql-test/t/ndb_dd_sql_features.test index ae8f6a7b9e7..f46cb217ab4 100644 --- a/mysql-test/t/ndb_dd_sql_features.test +++ b/mysql-test/t/ndb_dd_sql_features.test @@ -26,7 +26,6 @@ # gives a better idea of what the test is about ########################################################### -- source include/have_ndb.inc --- source include/have_binlog_format_row.inc --disable_warnings DROP TABLE IF EXISTS test.t1; diff --git a/mysql-test/t/ndb_gis.test b/mysql-test/t/ndb_gis.test index 104fdf41734..e14f462c32d 100644 --- a/mysql-test/t/ndb_gis.test +++ b/mysql-test/t/ndb_gis.test @@ -1,5 +1,4 @@ --source include/have_ndb.inc --- source include/have_binlog_format_row.inc SET storage_engine=ndbcluster; --source include/gis_generic.inc set engine_condition_pushdown = on; diff --git a/mysql-test/t/ndb_index.test b/mysql-test/t/ndb_index.test index fc284407973..272f30e3e6f 100644 --- a/mysql-test/t/ndb_index.test +++ b/mysql-test/t/ndb_index.test @@ -1,5 +1,4 @@ -- source include/have_ndb.inc --- source include/have_binlog_format_row.inc -- source include/not_embedded.inc --disable_warnings diff --git a/mysql-test/t/ndb_index_ordered.test b/mysql-test/t/ndb_index_ordered.test index 95b64eeef21..782f17ca5b2 100644 --- a/mysql-test/t/ndb_index_ordered.test +++ b/mysql-test/t/ndb_index_ordered.test @@ -1,5 +1,4 @@ -- source include/have_ndb.inc --- source include/have_binlog_format_row.inc -- source include/not_embedded.inc --disable_warnings diff --git a/mysql-test/t/ndb_index_unique.test b/mysql-test/t/ndb_index_unique.test index ecd4077bb56..78757c3bcf7 100644 --- a/mysql-test/t/ndb_index_unique.test +++ b/mysql-test/t/ndb_index_unique.test @@ -1,5 +1,4 @@ -- source include/have_ndb.inc --- source include/have_binlog_format_row.inc -- source include/not_embedded.inc --disable_warnings diff --git a/mysql-test/t/ndb_insert.test b/mysql-test/t/ndb_insert.test index 4b347e1a1ad..5b74cc9202c 100644 --- a/mysql-test/t/ndb_insert.test +++ b/mysql-test/t/ndb_insert.test @@ -1,5 +1,4 @@ -- source include/have_ndb.inc --- source include/have_binlog_format_row.inc -- source include/not_embedded.inc --disable_warnings diff --git a/mysql-test/t/ndb_limit.test b/mysql-test/t/ndb_limit.test index b0d189ff5d9..01613606d66 100644 --- a/mysql-test/t/ndb_limit.test +++ b/mysql-test/t/ndb_limit.test @@ -1,5 +1,4 @@ -- source include/have_ndb.inc --- source include/have_binlog_format_row.inc -- source include/not_embedded.inc --disable_warnings diff --git a/mysql-test/t/ndb_loaddatalocal.test b/mysql-test/t/ndb_loaddatalocal.test index 7453ae1bd64..3eae3891f43 100644 --- a/mysql-test/t/ndb_loaddatalocal.test +++ b/mysql-test/t/ndb_loaddatalocal.test @@ -1,5 +1,4 @@ -- source include/have_ndb.inc --- source include/have_binlog_format_row.inc -- source include/not_embedded.inc --disable_warnings diff --git a/mysql-test/t/ndb_lock.test b/mysql-test/t/ndb_lock.test index e677cba8e59..b6cd1ca7eb4 100644 --- a/mysql-test/t/ndb_lock.test +++ b/mysql-test/t/ndb_lock.test @@ -1,5 +1,4 @@ -- source include/have_ndb.inc --- source include/have_binlog_format_row.inc -- source include/not_embedded.inc connect (con1,localhost,root,,); diff --git a/mysql-test/t/ndb_minmax.test b/mysql-test/t/ndb_minmax.test index 4d9f132194a..a3ac677cd2a 100644 --- a/mysql-test/t/ndb_minmax.test +++ b/mysql-test/t/ndb_minmax.test @@ -1,5 +1,4 @@ -- source include/have_ndb.inc --- source include/have_binlog_format_row.inc -- source include/not_embedded.inc --disable_warnings diff --git a/mysql-test/t/ndb_multi.test b/mysql-test/t/ndb_multi.test index 3e25227ae80..3482db1d1b2 100644 --- a/mysql-test/t/ndb_multi.test +++ b/mysql-test/t/ndb_multi.test @@ -1,6 +1,5 @@ -- source include/have_ndb.inc -- source include/have_multi_ndb.inc --- source include/have_binlog_format_row.inc -- source include/not_embedded.inc --disable_warnings diff --git a/mysql-test/t/ndb_partition_error.test b/mysql-test/t/ndb_partition_error.test index ce25dfc0fd5..9db2a6a6f6d 100644 --- a/mysql-test/t/ndb_partition_error.test +++ b/mysql-test/t/ndb_partition_error.test @@ -1,5 +1,4 @@ -- source include/have_ndb.inc --- source include/have_binlog_format_row.inc #--disable_abort_on_error # # Simple test for the partition storage engine diff --git a/mysql-test/t/ndb_partition_key.test b/mysql-test/t/ndb_partition_key.test index 4760022d20f..78e2c9d15c2 100644 --- a/mysql-test/t/ndb_partition_key.test +++ b/mysql-test/t/ndb_partition_key.test @@ -1,5 +1,4 @@ -- source include/have_ndb.inc --- source include/have_binlog_format_row.inc --disable_warnings DROP TABLE IF EXISTS t1; diff --git a/mysql-test/t/ndb_partition_list.test b/mysql-test/t/ndb_partition_list.test index 35c7104ff92..ccfcdbc84f4 100644 --- a/mysql-test/t/ndb_partition_list.test +++ b/mysql-test/t/ndb_partition_list.test @@ -1,5 +1,4 @@ --source include/have_ndb.inc --- source include/have_binlog_format_row.inc # # Simple test for the partition storage engine # Focuses on range partitioning tests diff --git a/mysql-test/t/ndb_partition_range.test b/mysql-test/t/ndb_partition_range.test index e34cb92771c..7952ba502d2 100644 --- a/mysql-test/t/ndb_partition_range.test +++ b/mysql-test/t/ndb_partition_range.test @@ -1,5 +1,4 @@ -- source include/have_ndb.inc --- source include/have_binlog_format_row.inc #--disable_abort_on_error # # Simple test for the partition storage engine diff --git a/mysql-test/t/ndb_read_multi_range.test b/mysql-test/t/ndb_read_multi_range.test index b4e5943269c..ecca1f9862c 100644 --- a/mysql-test/t/ndb_read_multi_range.test +++ b/mysql-test/t/ndb_read_multi_range.test @@ -1,5 +1,4 @@ -- source include/have_ndb.inc --- source include/have_binlog_format_row.inc -- source include/not_embedded.inc --disable_warnings @@ -286,7 +285,7 @@ CREATE TABLE t2 ( var1 int(2) NOT NULL, var2 int(2) NOT NULL, PRIMARY KEY (var1) - ) ENGINE=MyISAM DEFAULT CHARSET=ascii CHECKSUM=1; + ) ENGINE=ndbcluster DEFAULT CHARSET=ascii CHECKSUM=1; DELIMITER |; diff --git a/mysql-test/t/ndb_rename.test b/mysql-test/t/ndb_rename.test index 1b2f6d72119..7f9fd0e6984 100644 --- a/mysql-test/t/ndb_rename.test +++ b/mysql-test/t/ndb_rename.test @@ -1,5 +1,4 @@ -- source include/have_ndb.inc --- source include/have_binlog_format_row.inc -- source include/not_embedded.inc --disable_warnings diff --git a/mysql-test/t/ndb_replace.test b/mysql-test/t/ndb_replace.test index cb5f1cc46cb..aa2072b98dd 100644 --- a/mysql-test/t/ndb_replace.test +++ b/mysql-test/t/ndb_replace.test @@ -1,5 +1,4 @@ -- source include/have_ndb.inc --- source include/have_binlog_format_row.inc -- source include/not_embedded.inc # diff --git a/mysql-test/t/ndb_restore.test b/mysql-test/t/ndb_restore.test index 2414e6b7268..7f0cafdfd77 100644 --- a/mysql-test/t/ndb_restore.test +++ b/mysql-test/t/ndb_restore.test @@ -1,5 +1,4 @@ -- source include/have_ndb.inc --- source include/have_binlog_format_row.inc -- source include/ndb_default_cluster.inc -- source include/not_embedded.inc diff --git a/mysql-test/t/ndb_restore_partition.test b/mysql-test/t/ndb_restore_partition.test index 0cddc38a876..f11324492c2 100644 --- a/mysql-test/t/ndb_restore_partition.test +++ b/mysql-test/t/ndb_restore_partition.test @@ -1,5 +1,4 @@ -- source include/have_ndb.inc --- source include/have_binlog_format_row.inc -- source include/ndb_default_cluster.inc -- source include/not_embedded.inc diff --git a/mysql-test/t/ndb_restore_print.test b/mysql-test/t/ndb_restore_print.test index d198623886b..6dbbfdf5933 100644 --- a/mysql-test/t/ndb_restore_print.test +++ b/mysql-test/t/ndb_restore_print.test @@ -1,5 +1,4 @@ -- source include/have_ndb.inc --- source include/have_binlog_format_row.inc -- source include/ndb_default_cluster.inc -- source include/not_embedded.inc diff --git a/mysql-test/t/ndb_row_format.test b/mysql-test/t/ndb_row_format.test index 49d771e4017..b1582cbe339 100644 --- a/mysql-test/t/ndb_row_format.test +++ b/mysql-test/t/ndb_row_format.test @@ -1,5 +1,4 @@ -- source include/have_ndb.inc --- source include/have_binlog_format_row.inc -- source include/not_embedded.inc --disable_warnings diff --git a/mysql-test/t/ndb_single_user.test b/mysql-test/t/ndb_single_user.test index 5d2ee0a3a8d..f059ea9ba23 100644 --- a/mysql-test/t/ndb_single_user.test +++ b/mysql-test/t/ndb_single_user.test @@ -1,5 +1,3 @@ --- source include/have_ndb.inc --- source include/have_binlog_format_row.inc -- source include/have_multi_ndb.inc -- source include/ndb_default_cluster.inc -- source include/not_embedded.inc diff --git a/mysql-test/t/ndb_sp.test b/mysql-test/t/ndb_sp.test index 703cb116c52..b833869cad0 100644 --- a/mysql-test/t/ndb_sp.test +++ b/mysql-test/t/ndb_sp.test @@ -1,5 +1,4 @@ -- source include/have_ndb.inc --- source include/have_binlog_format_row.inc -- source include/not_embedded.inc --disable_warnings diff --git a/mysql-test/t/ndb_subquery.test b/mysql-test/t/ndb_subquery.test index c8aec569de9..6282c31c922 100644 --- a/mysql-test/t/ndb_subquery.test +++ b/mysql-test/t/ndb_subquery.test @@ -1,5 +1,4 @@ -- source include/have_ndb.inc --- source include/have_binlog_format_row.inc -- source include/not_embedded.inc --disable_warnings diff --git a/mysql-test/t/ndb_temporary.test b/mysql-test/t/ndb_temporary.test index 3a9e7c94398..7f6902bf745 100644 --- a/mysql-test/t/ndb_temporary.test +++ b/mysql-test/t/ndb_temporary.test @@ -1,5 +1,4 @@ -- source include/have_ndb.inc --- source include/have_binlog_format_row.inc -- source include/not_embedded.inc --disable_warnings diff --git a/mysql-test/t/ndb_transaction.test b/mysql-test/t/ndb_transaction.test index dca1fde8fc7..d3ebadb1a78 100644 --- a/mysql-test/t/ndb_transaction.test +++ b/mysql-test/t/ndb_transaction.test @@ -1,5 +1,4 @@ -- source include/have_ndb.inc --- source include/have_binlog_format_row.inc -- source include/not_embedded.inc --disable_warnings diff --git a/mysql-test/t/ndb_trigger.test b/mysql-test/t/ndb_trigger.test index 00927f93d10..2e944174fd0 100644 --- a/mysql-test/t/ndb_trigger.test +++ b/mysql-test/t/ndb_trigger.test @@ -1,6 +1,5 @@ # Tests which involve triggers and NDB storage engine --source include/have_ndb.inc ---source include/have_binlog_format_row.inc --source include/not_embedded.inc # @@ -19,8 +18,8 @@ drop table if exists t1, t2, t3, t4, t5; --enable_warnings create table t1 (id int primary key, a int not null, b decimal (63,30) default 0) engine=ndb; -create table t2 (op char(1), a int not null, b decimal (63,30)); -create table t3 select 1 as i; +create table t2 (op char(1), a int not null, b decimal (63,30)) engine=ndb; +create table t3 engine=ndb select 1 as i; create table t4 (a int not null primary key, b int) engine=ndb; create table t5 (a int not null primary key, b int) engine=ndb; diff --git a/mysql-test/t/ndb_truncate.test b/mysql-test/t/ndb_truncate.test index a62fd43408d..a1ef4be0d48 100644 --- a/mysql-test/t/ndb_truncate.test +++ b/mysql-test/t/ndb_truncate.test @@ -1,5 +1,4 @@ -- source include/have_ndb.inc --- source include/have_binlog_format_row.inc -- source include/not_embedded.inc --disable_warnings diff --git a/mysql-test/t/ndb_types.test b/mysql-test/t/ndb_types.test index 9b395c12bf8..ab18817132e 100644 --- a/mysql-test/t/ndb_types.test +++ b/mysql-test/t/ndb_types.test @@ -1,5 +1,4 @@ --source include/have_ndb.inc --- source include/have_binlog_format_row.inc --source include/not_embedded.inc --disable_warnings diff --git a/mysql-test/t/ndb_update.test b/mysql-test/t/ndb_update.test index a864aa28dc3..73a0ebc69cb 100644 --- a/mysql-test/t/ndb_update.test +++ b/mysql-test/t/ndb_update.test @@ -1,5 +1,4 @@ -- source include/have_ndb.inc --- source include/have_binlog_format_row.inc -- source include/not_embedded.inc --disable_warnings diff --git a/mysql-test/t/ndb_view.test b/mysql-test/t/ndb_view.test index 4f2580ef15e..3b8fc330b40 100644 --- a/mysql-test/t/ndb_view.test +++ b/mysql-test/t/ndb_view.test @@ -1,5 +1,4 @@ -- source include/have_ndb.inc --- source include/have_binlog_format_row.inc -- source include/not_embedded.inc --disable_warnings diff --git a/mysql-test/t/ndbapi.test b/mysql-test/t/ndbapi.test index d58ed1c5ccd..3424513f8af 100644 --- a/mysql-test/t/ndbapi.test +++ b/mysql-test/t/ndbapi.test @@ -1,5 +1,4 @@ -- source include/have_ndb.inc --- source include/have_binlog_format_row.inc -- source include/have_ndbapi_examples.inc --disable_warnings diff --git a/mysql-test/t/ps_7ndb.test b/mysql-test/t/ps_7ndb.test index eb98a815d74..e3f65ec2c4e 100644 --- a/mysql-test/t/ps_7ndb.test +++ b/mysql-test/t/ps_7ndb.test @@ -11,7 +11,6 @@ use test; -- source include/have_ndb.inc --- source include/have_binlog_format_row.inc let $type= 'NDB' ; -- source include/ps_create.inc -- source include/ps_renew.inc diff --git a/mysql-test/t/rpl_ndb_commit_afterflush.test b/mysql-test/t/rpl_ndb_commit_afterflush.test index 5bbd7f0414e..7adb62d5668 100644 --- a/mysql-test/t/rpl_ndb_commit_afterflush.test +++ b/mysql-test/t/rpl_ndb_commit_afterflush.test @@ -5,7 +5,7 @@ # By JBM 2004-02-15 # ##################################### -- source include/have_ndb.inc --- source include/have_binlog_format_row.inc -- source include/ndb_master-slave.inc +-- source include/have_log_bin.inc let $engine_type=NDB; -- source extra/rpl_tests/rpl_commit_after_flush.test diff --git a/mysql-test/t/rpl_ndb_ctype_ucs2_def-master.opt b/mysql-test/t/rpl_ndb_ctype_ucs2_def-master.opt new file mode 100644 index 00000000000..84d2a52b639 --- /dev/null +++ b/mysql-test/t/rpl_ndb_ctype_ucs2_def-master.opt @@ -0,0 +1 @@ +--default-collation=ucs2_unicode_ci --default-character-set=ucs2,latin1 diff --git a/mysql-test/t/rpl_ndb_ctype_ucs2_def.test b/mysql-test/t/rpl_ndb_ctype_ucs2_def.test new file mode 100644 index 00000000000..be7fd1acd2e --- /dev/null +++ b/mysql-test/t/rpl_ndb_ctype_ucs2_def.test @@ -0,0 +1,42 @@ +--source include/have_ucs2.inc +--source include/have_ndb.inc +--source include/ndb_master-slave.inc + +# +# MySQL Bug#15276: MySQL ignores collation-server +# +show variables like 'collation_server'; + +# +# Check that NDB replication doesn't explode with default charset +# being multibyte. +# +# Theorised that this could be a problem when dealing with: +# Bug #27404 util thd mysql_parse sig11 when mysqld default multibyte charset +# +# Sort of related to: +# Bug#18004 Connecting crashes server when default charset is UCS2 +# +# +show variables like "%character_set_ser%"; +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings +create table t1 (a int) ENGINE=NDB; +drop table t1; + +--connection master +CREATE TABLE `t1` ( `nid` int(11) NOT NULL default '0', + `nom` char(4) default NULL, + `prenom` char(4) default NULL, + PRIMARY KEY (`nid`)) + ENGINE=ndbcluster; + +INSERT INTO t1 VALUES(1,"XYZ1","ABC1"); +select * from t1 order by nid; + +--sync_slave_with_master +# connect to slave and ensure data it there. +--connection slave +select * from t1 order by nid; + diff --git a/mysql-test/t/rpl_ndb_dd_advance.test b/mysql-test/t/rpl_ndb_dd_advance.test index 5e346d5fe3b..723672931ab 100644 --- a/mysql-test/t/rpl_ndb_dd_advance.test +++ b/mysql-test/t/rpl_ndb_dd_advance.test @@ -9,7 +9,7 @@ --source include/have_binlog_format_row.inc --source include/ndb_default_cluster.inc --source include/not_embedded.inc ---source include/big_test.inc +#--source include/big_test.inc #--source include/have_ndb_extra.inc --source include/ndb_master-slave.inc @@ -98,7 +98,7 @@ SELECT DISTINCT FILE_NAME, FILE_TYPE, TABLESPACE_NAME, LOGFILE_GROUP_NAME connection master; CREATE INDEX t1_i ON t1(c2, c3); #Bug 18039 -#CREATE UNIQUE INDEX t1_i2 ON t1(c2); +CREATE UNIQUE INDEX t1_i2 ON t1(c2); ALTER TABLE t1 ADD c4 TIMESTAMP; ALTER TABLE t1 ADD c5 DOUBLE; ALTER TABLE t1 ADD INDEX (c5); @@ -170,7 +170,7 @@ SELECT * FROM t1 ORDER BY c1 LIMIT 5; connection slave; SHOW CREATE TABLE t1; # Bug 18094 -#SELECT * FROM t1 ORDER BY c1 LIMIT 5; +SELECT * FROM t1 ORDER BY c1 LIMIT 5; SELECT * FROM t1 where c1 = 1; connection master; @@ -198,163 +198,19 @@ connection master; CREATE TABLESPACE ts2 ADD DATAFILE 'datafile03.dat' USE LOGFILE GROUP lg1 -INITIAL_SIZE 12M +INITIAL_SIZE 10M ENGINE=NDB; ALTER TABLESPACE ts2 ADD DATAFILE 'datafile04.dat' -INITIAL_SIZE 12M +INITIAL_SIZE 5M ENGINE=NDB; -###### CLEAN UP SECTION ############## -DROP DATABASE IF EXISTS tpcb; -CREATE DATABASE tpcb; -######## Creat Table Section ######### ---echo *********** Create TPCB Tables ***************** -CREATE TABLE tpcb.account - (id INT, bid INT, balance DECIMAL(10,2), - filler CHAR(255), PRIMARY KEY(id)) - TABLESPACE ts1 STORAGE DISK - ENGINE=NDB; +let engine_type=NDBCLUSTER; +let table_space=ts2; +let format='RBR'; -CREATE TABLE tpcb.branch - (bid INT, balance DECIMAL(10,2), filler VARCHAR(255), - PRIMARY KEY(bid)) - ENGINE=NDB; - -CREATE TABLE tpcb.teller - (tid INT, balance DECIMAL(10,2), filler VARCHAR(255), - PRIMARY KEY(tid)) - TABLESPACE ts2 STORAGE DISK - ENGINE=NDB; - -CREATE TABLE tpcb.history - (id MEDIUMINT NOT NULL AUTO_INCREMENT,aid INT, - tid INT, bid INT, amount DECIMAL(10,2), - tdate DATETIME, teller CHAR(20), uuidf LONGBLOB, - filler CHAR(80),PRIMARY KEY (id)) - TABLESPACE ts2 STORAGE DISK - ENGINE=NDB; - ---echo ********* Create Procedures and Functions ************ -delimiter |; -CREATE PROCEDURE tpcb.load() -BEGIN - DECLARE acct INT DEFAULT 1000; - DECLARE brch INT DEFAULT 100; - DECLARE tell INT DEFAULT 1000; - DECLARE tmp INT DEFAULT 100; - WHILE brch > 0 DO - SET tmp = 100; - WHILE tmp > 0 DO - INSERT INTO tpcb.account VALUES (acct, brch, 0.0, "FRESH ACCOUNT"); - SET acct = acct - 1; - SET tmp = tmp -1; - END WHILE; - INSERT INTO tpcb.branch VALUES (brch, 0.0, "FRESH BRANCH"); - SET brch = brch - 1; - END WHILE; - WHILE tell > 0 DO - INSERT INTO tpcb.teller VALUES (tell, 0.0, "FRESH TELLER"); - SET tell = tell - 1; - END WHILE; -END| - -CREATE FUNCTION tpcb.account_id () RETURNS INT -BEGIN - DECLARE num INT; - DECLARE ran INT; - SELECT RAND() * 10 INTO ran; - IF (ran < 2) - THEN - SELECT RAND() * 10 INTO num; - ELSEIF (ran < 4) - THEN - SELECT RAND() * 100 INTO num; - ELSE - SELECT RAND() * 1000 INTO num; - END IF; - IF (num < 1) - THEN - RETURN 1; - END IF; - RETURN num; -END| - -CREATE FUNCTION tpcb.teller_id () RETURNS INT -BEGIN - DECLARE num INT; - DECLARE ran INT; - SELECT RAND() * 10 INTO ran; - IF (ran < 2) - THEN - SELECT RAND() * 10 INTO num; - ELSEIF (ran < 5) - THEN - SELECT RAND() * 100 INTO num; - ELSE - SELECT RAND() * 1000 INTO num; - END IF; - IF (num < 1) - THEN - RETURN 1; - END IF; - RETURN num; -END| - -CREATE PROCEDURE tpcb.trans() -BEGIN - DECLARE acct INT DEFAULT 0; - DECLARE brch INT DEFAULT 0; - DECLARE tell INT DEFAULT 0; - DECLARE bal DECIMAL(10,2) DEFAULT 0.0; - DECLARE amount DECIMAL(10,2) DEFAULT 1.00; - DECLARE test INT DEFAULT 0; - DECLARE bbal DECIMAL(10,2) DEFAULT 0.0; - DECLARE tbal DECIMAL(10,2) DEFAULT 0.0; - DECLARE local_uuid VARCHAR(255); - DECLARE local_user VARCHAR(255); - DECLARE local_time TIMESTAMP; - - SELECT RAND() * 10 INTO test; - SELECT tpcb.account_id() INTO acct; - SELECT tpcb.teller_id() INTO tell; - - SELECT account.balance INTO bal FROM tpcb.account WHERE id = acct; - SELECT account.bid INTO brch FROM tpcb.account WHERE id = acct; - SELECT teller.balance INTO tbal FROM tpcb.teller WHERE tid = tell; - SELECT branch.balance INTO bbal FROM tpcb.branch WHERE bid = brch; - - IF (test < 5) - THEN - SET bal = bal + amount; - SET bbal = bbal + amount; - SET tbal = tbal + amount; - UPDATE tpcb.account SET balance = bal, filler = 'account updated' - WHERE id = acct; - UPDATE tpcb.branch SET balance = bbal, filler = 'branch updated' - WHERE bid = brch; - UPDATE tpcb.teller SET balance = tbal, filler = 'teller updated' - WHERE tid = tell; - ELSE - SET bal = bal - amount; - SET bbal = bbal - amount; - SET tbal = tbal - amount; - UPDATE tpcb.account SET balance = bal, filler = 'account updated' - WHERE id = acct; - UPDATE tpcb.branch SET balance = bbal, filler = 'branch updated' - WHERE bid = brch; - UPDATE tpcb.teller SET balance = tbal, filler = 'teller updated' - WHERE tid = tell; - END IF; - - SET local_uuid=UUID(); - SET local_user=USER(); - SET local_time= NOW(); - INSERT INTO tpcb.history VALUES(NULL,acct,tell,brch,amount, local_time,local_user, - local_uuid,'completed trans'); -END| -delimiter ;| +--source include/tpcb_disk_data.inc --echo ****** TEST 2 test time ********************************* USE tpcb; @@ -372,15 +228,16 @@ SELECT COUNT(*) FROM account; --echo ******** Run in some transactions *************** connection master; -let $j= 1000; +let $j= 100; --disable_query_log while ($j) { - CALL tpcb.trans(); + eval CALL tpcb.trans($format); dec $j; } --enable_query_log + --echo ***** Time to try slave sync *********** --echo **** Must make sure slave is clean ***** --connection slave @@ -421,11 +278,11 @@ connection master; SELECT COUNT(*) FROM history; -let $j= 1000; +let $j= 100; --disable_query_log while ($j) { - CALL tpcb.trans(); + eval CALL tpcb.trans($format); dec $j; } --enable_query_log @@ -464,11 +321,11 @@ SELECT COUNT(*) FROM account; --echo ***** Add some more records to master ********* connection master; -let $j= 1000; +let $j= 100; --disable_query_log while ($j) { - CALL tpcb.trans(); + eval CALL tpcb.trans($format); dec $j; } --enable_query_log @@ -484,17 +341,18 @@ while ($j) --echo ***** Finsh the slave sync process ******* --disable_query_log # 1. 2. 3. +--sync_slave_with_master --source include/ndb_setup_slave.inc --enable_query_log # 4. --echo * 4. * connection master; -let $j= 1000; +let $j= 100; --disable_query_log while ($j) { - CALL tpcb.trans(); + eval CALL tpcb.trans($format); dec $j; } --enable_query_log @@ -507,15 +365,6 @@ START SLAVE; --echo **** We should be ready to continue on ************* connection master; -let $j= 50; ---disable_query_log -while ($j) -{ - CALL tpcb.trans(); - dec $j; -} ---enable_query_log - --echo ****** Let's make sure we match ******* --echo ***** MASTER ******* USE tpcb; diff --git a/mysql-test/t/rpl_ndb_innodb_trans.test b/mysql-test/t/rpl_ndb_innodb_trans.test index efba6050554..63c5c5e93e3 100644 --- a/mysql-test/t/rpl_ndb_innodb_trans.test +++ b/mysql-test/t/rpl_ndb_innodb_trans.test @@ -2,8 +2,8 @@ -- source include/have_ndb.inc -- source include/have_innodb.inc --- source include/have_binlog_format_row.inc -- source include/ndb_master-slave.inc +-- source include/have_log_bin.inc create table t1 (a int, unique(a)) engine=ndbcluster; create table t2 (a int, unique(a)) engine=innodb; diff --git a/mysql-test/t/rpl_ndb_mix_innodb-master.opt b/mysql-test/t/rpl_ndb_mix_innodb-master.opt new file mode 100644 index 00000000000..3596fc4d3bd --- /dev/null +++ b/mysql-test/t/rpl_ndb_mix_innodb-master.opt @@ -0,0 +1 @@ +--innodb --default-storage-engine=innodb diff --git a/mysql-test/t/rpl_ndb_mix_innodb.test b/mysql-test/t/rpl_ndb_mix_innodb.test new file mode 100644 index 00000000000..b730bcc08e0 --- /dev/null +++ b/mysql-test/t/rpl_ndb_mix_innodb.test @@ -0,0 +1,36 @@ +############################################# +#Authors: TU and Jeb +#Date: 2007/04 +#Purpose: Generic replication to cluster +# and ensuring that the ndb_apply_status +# table is updated. +############################################# +# Notes: +# include/select_ndb_apply_status.inc +# Selects out the log name, start & end pos +# from the ndb_apply_status table +# +# include/show_binlog_using_logname.inc +# To select out 1 row from offset 1 +# from the start position in the binlog whose +# name is = log_name +# +# include/tpcb.inc +# Creates DATABASE tpcb, the tables and +# stored procedures for loading the DB +# and for running transactions against DB. +############################################## + + +## Includes ## + +--disable_query_log +--source include/have_ndb.inc +--source include/have_innodb.inc +--source include/have_binlog_format_mixed.inc +--source include/ndb_master-slave.inc +--enable_query_log +let $off_set = 9; +let $rpl_format = 'MIX'; +--source extra/rpl_tests/rpl_ndb_apply_status.test + diff --git a/mysql-test/t/rpl_ndb_stm_innodb-master.opt b/mysql-test/t/rpl_ndb_stm_innodb-master.opt index 627becdbfb5..3596fc4d3bd 100644 --- a/mysql-test/t/rpl_ndb_stm_innodb-master.opt +++ b/mysql-test/t/rpl_ndb_stm_innodb-master.opt @@ -1 +1 @@ ---innodb +--innodb --default-storage-engine=innodb diff --git a/mysql-test/t/rpl_ndb_stm_innodb.test b/mysql-test/t/rpl_ndb_stm_innodb.test index d43fafa8406..bf7f1eed7b2 100644 --- a/mysql-test/t/rpl_ndb_stm_innodb.test +++ b/mysql-test/t/rpl_ndb_stm_innodb.test @@ -1,70 +1,35 @@ +############################################# +#Authors: TU and Jeb +#Date: 2007/04 +#Purpose: Generic replication to cluster +# and ensuring that the ndb_apply_status +# table is updated. +############################################# +# Notes: +# include/select_ndb_apply_status.inc +# Selects out the log name, start & end pos +# from the ndb_apply_status table +# +# include/show_binlog_using_logname.inc +# To select out 1 row from offset 1 +# from the start position in the binlog whose +# name is = log_name +# +# include/tpcb.inc +# Creates DATABASE tpcb, the tables and +# stored procedures for loading the DB +# and for running transactions against DB. +############################################## + + +## Includes ## + +--disable_query_log --source include/have_ndb.inc --source include/have_innodb.inc ---source include/have_binlog_format_mixed_or_statement.inc +--source include/have_binlog_format_statement.inc --source include/ndb_master-slave.inc - ---connection master -create table t1 (a int key, b int) engine innodb; -create table t2 (a int key, b int) engine innodb; - ---sync_slave_with_master ---connection slave -alter table t1 engine ndb; -alter table t2 engine ndb; - -# We need MIXED mode on the slave in the event that there are -# statements coming in from the master. In this case, NDB can only -# handle row-based format, so it has to be possible to switch to -# this. -STOP SLAVE; -SET GLOBAL BINLOG_FORMAT=MIXED; -START SLAVE; - -# check binlog position without begin ---connection master -insert into t1 values (1,2); - ---sync_slave_with_master ---connection slave ---replace_column 1 2 -select @start_pos:=start_pos, @end_pos:=end_pos from mysql.ndb_apply_status; ---let $start_pos = `select @start_pos` ---let $end_pos = `select @end_pos` - ---connection master -# here is actually a bug, since there is no begin statement, the -# query is autocommitted, and end_pos shows end of the insert and not -# end of the commit ---replace_result $start_pos ---replace_column 5 # ---eval show binlog events from $start_pos limit 1 ---replace_result $start_pos $end_pos ---replace_column 2 # ---replace_regex /\/\* xid=.* \*\//\/* XID *\// /table_id: [0-9]+/table_id: #/ ---eval show binlog events from $start_pos limit 1,1 - -# check binlog position with begin ---connection master -begin; -insert into t1 values (2,3); -insert into t2 values (3,4); -commit; - ---sync_slave_with_master ---connection slave ---replace_column 1 2 -select @start_pos:=start_pos, @end_pos:=end_pos from mysql.ndb_apply_status; ---let $start_pos = `select @start_pos` ---let $end_pos = `select @end_pos` - ---connection master ---replace_result $start_pos ---replace_column 5 # ---eval show binlog events from $start_pos limit 1 ---replace_result $start_pos ---replace_column 2 # 4 # 5 # ---eval show binlog events from $start_pos limit 1,2 ---replace_result $start_pos $end_pos ---replace_column 2 # ---replace_regex /\/\* xid=.* \*\//\/* XID *\// /table_id: [0-9]+/table_id: #/ ---eval show binlog events from $start_pos limit 3,1 +--enable_query_log +let $off_set = 6; +let $rpl_format = 'SBR'; +--source extra/rpl_tests/rpl_ndb_apply_status.test diff --git a/mysql-test/t/strict_autoinc_5ndb.test b/mysql-test/t/strict_autoinc_5ndb.test index 819d0068148..9e2090fddef 100644 --- a/mysql-test/t/strict_autoinc_5ndb.test +++ b/mysql-test/t/strict_autoinc_5ndb.test @@ -1,5 +1,4 @@ -- source include/have_ndb.inc --- source include/have_binlog_format_row.inc # # Bug#20573 Strict mode auto-increment diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 102c21d19a0..c78cb4e65b4 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -2812,7 +2812,8 @@ int ha_ndbcluster::write_row(uchar *record) if (unlikely(m_slow_path)) { - if (!(thd->options & OPTION_BIN_LOG)) + Thd_ndb *thd_ndb= get_thd_ndb(thd); + if (thd_ndb->trans_options & TNTO_NO_LOGGING) op->setAnyValue(NDB_ANYVALUE_FOR_NOLOGGING); else if (thd->slave_thread) op->setAnyValue(thd->server_id); @@ -3101,7 +3102,8 @@ int ha_ndbcluster::update_row(const uchar *old_data, uchar *new_data) if (unlikely(m_slow_path)) { - if (!(thd->options & OPTION_BIN_LOG)) + Thd_ndb *thd_ndb= get_thd_ndb(thd); + if (thd_ndb->trans_options & TNTO_NO_LOGGING) op->setAnyValue(NDB_ANYVALUE_FOR_NOLOGGING); else if (thd->slave_thread) op->setAnyValue(thd->server_id); @@ -3168,7 +3170,8 @@ int ha_ndbcluster::delete_row(const uchar *record) if (unlikely(m_slow_path)) { - if (!(thd->options & OPTION_BIN_LOG)) + Thd_ndb *thd_ndb= get_thd_ndb(thd); + if (thd_ndb->trans_options & TNTO_NO_LOGGING) ((NdbOperation *)trans->getLastDefinedOperation())-> setAnyValue(NDB_ANYVALUE_FOR_NOLOGGING); else if (thd->slave_thread) @@ -3207,7 +3210,8 @@ int ha_ndbcluster::delete_row(const uchar *record) if (unlikely(m_slow_path)) { - if (!(thd->options & OPTION_BIN_LOG)) + Thd_ndb *thd_ndb= get_thd_ndb(thd); + if (thd_ndb->trans_options & TNTO_NO_LOGGING) op->setAnyValue(NDB_ANYVALUE_FOR_NOLOGGING); else if (thd->slave_thread) op->setAnyValue(thd->server_id); @@ -4385,8 +4389,13 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type) thd_ndb->query_state&= NDB_QUERY_NORMAL; thd_ndb->trans_options= 0; thd_ndb->m_slow_path= FALSE; - if (thd->slave_thread || - !(thd->options & OPTION_BIN_LOG)) + if (!(thd->options & OPTION_BIN_LOG) || + thd->variables.binlog_format == BINLOG_FORMAT_STMT) + { + thd_ndb->trans_options|= TNTO_NO_LOGGING; + thd_ndb->m_slow_path= TRUE; + } + else if (thd->slave_thread) thd_ndb->m_slow_path= TRUE; trans_register_ha(thd, FALSE, ndbcluster_hton); } @@ -4406,8 +4415,13 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type) thd_ndb->query_state&= NDB_QUERY_NORMAL; thd_ndb->trans_options= 0; thd_ndb->m_slow_path= FALSE; - if (thd->slave_thread || - !(thd->options & OPTION_BIN_LOG)) + if (!(thd->options & OPTION_BIN_LOG) || + thd->variables.binlog_format == BINLOG_FORMAT_STMT) + { + thd_ndb->trans_options|= TNTO_NO_LOGGING; + thd_ndb->m_slow_path= TRUE; + } + else if (thd->slave_thread) thd_ndb->m_slow_path= TRUE; trans_register_ha(thd, TRUE, ndbcluster_hton); @@ -8962,6 +8976,14 @@ pthread_handler_t ndb_util_thread_func(void *arg __attribute__((unused))) thd->main_security_ctx.master_access= ~0; thd->main_security_ctx.priv_user = 0; + CHARSET_INFO *charset_connection; + charset_connection= get_charset_by_csname("utf8", + MY_CS_PRIMARY, MYF(MY_WME)); + thd->variables.character_set_client= charset_connection; + thd->variables.character_set_results= charset_connection; + thd->variables.collation_connection= charset_connection; + thd->update_charset(); + /* Signal successful initialization */ ndb_util_thread_running= 1; pthread_cond_signal(&COND_ndb_util_ready); diff --git a/sql/ha_ndbcluster.h b/sql/ha_ndbcluster.h index 5c6646f68af..4f5a1359d2d 100644 --- a/sql/ha_ndbcluster.h +++ b/sql/ha_ndbcluster.h @@ -178,6 +178,7 @@ enum THD_NDB_OPTIONS enum THD_NDB_TRANS_OPTIONS { TNTO_INJECTED_APPLY_STATUS= 1 << 0 + ,TNTO_NO_LOGGING= 1 << 1 }; struct Ndb_local_table_statistics { diff --git a/sql/ha_ndbcluster_binlog.cc b/sql/ha_ndbcluster_binlog.cc index a724d1150dc..f388b60f3d5 100644 --- a/sql/ha_ndbcluster_binlog.cc +++ b/sql/ha_ndbcluster_binlog.cc @@ -3674,15 +3674,7 @@ pthread_handler_t ndb_binlog_thread_func(void *arg) if (opt_bin_log) { - if (global_system_variables.binlog_format == BINLOG_FORMAT_ROW || - global_system_variables.binlog_format == BINLOG_FORMAT_MIXED) - { - ndb_binlog_running= TRUE; - } - else - { - sql_print_error("NDB: only row based binary logging is supported"); - } + ndb_binlog_running= TRUE; } /* Thread start up completed */ diff --git a/sql/item_sum.cc b/sql/item_sum.cc index e2d4c02d986..0fa46d231a9 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -3230,6 +3230,27 @@ Item_func_group_concat::fix_fields(THD *thd, Item **ref) null_value= 1; max_length= thd->variables.group_concat_max_len; + uint32 offset; + if (separator->needs_conversion(separator->length(), separator->charset(), + collation.collation, &offset)) + { + uint32 buflen= collation.collation->mbmaxlen * separator->length(); + uint errors, conv_length; + char *buf; + String *new_separator; + + if (!(buf= (char*) thd->stmt_arena->alloc(buflen)) || + !(new_separator= new(thd->stmt_arena->mem_root) + String(buf, buflen, collation.collation))) + return TRUE; + + conv_length= copy_and_convert(buf, buflen, collation.collation, + separator->ptr(), separator->length(), + separator->charset(), &errors); + new_separator->length(conv_length); + separator= new_separator; + } + if (check_sum_func(thd, ref)) return TRUE; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 026e1c3b218..fb5fd2ec627 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -28,6 +28,8 @@ #include #endif +#define FLAGSTR(S,F) ((S) & (F) ? #F " " : "") + /** This internal handler is used to trap internally errors that can occur when executing open table @@ -3996,36 +3998,47 @@ int decide_logging_format(THD *thd, TABLE_LIST *tables) { if (mysql_bin_log.is_open() && (thd->options & OPTION_BIN_LOG)) { - handler::Table_flags binlog_flags= ~handler::Table_flags(); + handler::Table_flags flags_some_set= handler::Table_flags(); + handler::Table_flags flags_all_set= ~handler::Table_flags(); + my_bool multi_engine= FALSE; + void* prev_ht= NULL; for (TABLE_LIST *table= tables; table; table= table->next_global) + { if (!table->placeholder() && table->lock_type >= TL_WRITE_ALLOW_WRITE) { -#define FLAGSTR(S,F) ((S) & (F) ? #F " " : "") -#ifndef DBUG_OFF - ulonglong flags= table->table->file->ha_table_flags(); + ulonglong const flags= table->table->file->ha_table_flags(); DBUG_PRINT("info", ("table: %s; ha_table_flags: %s%s", table->table_name, FLAGSTR(flags, HA_BINLOG_STMT_CAPABLE), FLAGSTR(flags, HA_BINLOG_ROW_CAPABLE))); -#endif - binlog_flags &= table->table->file->ha_table_flags(); + if (prev_ht && prev_ht != table->table->file->ht) + multi_engine= TRUE; + prev_ht= table->table->file->ht; + flags_all_set &= flags; + flags_some_set |= flags; } - binlog_flags&= HA_BINLOG_FLAGS; - DBUG_PRINT("info", ("binlog_flags: %s%s", - FLAGSTR(binlog_flags, HA_BINLOG_STMT_CAPABLE), - FLAGSTR(binlog_flags, HA_BINLOG_ROW_CAPABLE))); + } + + DBUG_PRINT("info", ("flags_all_set: %s%s", + FLAGSTR(flags_all_set, HA_BINLOG_STMT_CAPABLE), + FLAGSTR(flags_all_set, HA_BINLOG_ROW_CAPABLE))); + DBUG_PRINT("info", ("flags_some_set: %s%s", + FLAGSTR(flags_some_set, HA_BINLOG_STMT_CAPABLE), + FLAGSTR(flags_some_set, HA_BINLOG_ROW_CAPABLE))); DBUG_PRINT("info", ("thd->variables.binlog_format: %ld", thd->variables.binlog_format)); + DBUG_PRINT("info", ("multi_engine: %s", + multi_engine ? "TRUE" : "FALSE")); int error= 0; - if (binlog_flags == 0) + if (flags_all_set == 0) { my_error((error= ER_BINLOG_LOGGING_IMPOSSIBLE), MYF(0), "Statement cannot be logged to the binary log in" " row-based nor statement-based format"); } else if (thd->variables.binlog_format == BINLOG_FORMAT_STMT && - (binlog_flags & HA_BINLOG_STMT_CAPABLE) == 0) + (flags_all_set & HA_BINLOG_STMT_CAPABLE) == 0) { my_error((error= ER_BINLOG_LOGGING_IMPOSSIBLE), MYF(0), "Statement-based format required for this statement," @@ -4033,13 +4046,29 @@ int decide_logging_format(THD *thd, TABLE_LIST *tables) } else if ((thd->variables.binlog_format == BINLOG_FORMAT_ROW || thd->lex->is_stmt_unsafe()) && - (binlog_flags & HA_BINLOG_ROW_CAPABLE) == 0) + (flags_all_set & HA_BINLOG_ROW_CAPABLE) == 0) { my_error((error= ER_BINLOG_LOGGING_IMPOSSIBLE), MYF(0), "Row-based format required for this statement," " but not allowed by this combination of engines"); } + /* + If more than one engine is involved in the statement and at + least one is doing it's own logging (is *self-logging*), the + statement cannot be logged atomically, so we generate an error + rather than allowing the binlog to become corrupt. + */ + if (multi_engine && + (flags_some_set & HA_HAS_OWN_BINLOGGING)) + { + error= ER_BINLOG_LOGGING_IMPOSSIBLE; + my_error(error, MYF(0), + "Statement cannot be written atomically since more" + " than one engine involved and at least one engine" + " is self-logging"); + } + DBUG_PRINT("info", ("error: %d", error)); if (error) @@ -4061,7 +4090,7 @@ int decide_logging_format(THD *thd, TABLE_LIST *tables) here. */ if (thd->lex->is_stmt_unsafe() || - (binlog_flags & HA_BINLOG_STMT_CAPABLE) == 0) + (flags_all_set & HA_BINLOG_STMT_CAPABLE) == 0) { thd->set_current_stmt_binlog_row_based_if_mixed(); } diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 3babaa2aa7a..04df3d7a48d 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -7116,8 +7116,11 @@ opt_distinct: |DISTINCT { $$ = 1; }; opt_gconcat_separator: - /* empty */ { $$ = new (YYTHD->mem_root) String(",",1,default_charset_info); } - |SEPARATOR_SYM text_string { $$ = $2; }; + /* empty */ + { + $$= new (YYTHD->mem_root) String(",", 1, &my_charset_latin1); + } + | SEPARATOR_SYM text_string { $$ = $2; }; opt_gorder_clause: diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index e2c16ca193a..65c3086a086 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -2276,35 +2276,11 @@ Get the table flags to use for the statement. */ handler::Table_flags ha_innobase::table_flags() const { - THD *const thd= current_thd; - /* We are using thd->variables.tx_isolation here instead of - trx->isolation_level since store_lock() has not been called - yet. - - The trx->isolation_level is set inside store_lock() (which - is called from mysql_lock_tables()) until after this - function has been called (which is called in lock_tables() - before that function calls mysql_lock_tables()). */ - ulong const tx_isolation= thd_tx_isolation(thd); + /* Need to use tx_isolation here since table flags is (also) + called before prebuilt is inited. */ + ulong const tx_isolation = thd_tx_isolation(current_thd); if (tx_isolation <= ISO_READ_COMMITTED) - { - ulong const binlog_format= thd->variables.binlog_format; - /* Statement based binlogging does not work in these - isolation levels since the necessary locks cannot - be taken */ - if (binlog_format == BINLOG_FORMAT_STMT) - { - char buf[256]; - my_snprintf(buf, sizeof(buf), - "Transaction level '%s' in InnoDB is" - " not safe for binlog mode '%s'", - tx_isolation_names[tx_isolation], - binlog_format_names[binlog_format]); - my_error(ER_BINLOG_LOGGING_IMPOSSIBLE, MYF(0), buf); - } return int_table_flags; - } - return int_table_flags | HA_BINLOG_STMT_CAPABLE; } @@ -6284,6 +6260,29 @@ ha_innobase::external_lock( update_thd(thd); + /* Statement based binlogging does not work in isolation level + READ UNCOMMITTED and READ COMMITTED since the necessary + locks cannot be taken. In this case, we print an + informative error message and return with an error. */ + if (lock_type == F_WRLCK) + { + ulong const binlog_format= thd->variables.binlog_format; + ulong const tx_isolation = thd_tx_isolation(current_thd); + if (tx_isolation <= ISO_READ_COMMITTED && + binlog_format == BINLOG_FORMAT_STMT) + { + char buf[256]; + my_snprintf(buf, sizeof(buf), + "Transaction level '%s' in" + " InnoDB is not safe for binlog mode '%s'", + tx_isolation_names[tx_isolation], + binlog_format_names[binlog_format]); + my_error(ER_BINLOG_LOGGING_IMPOSSIBLE, MYF(0), buf); + DBUG_RETURN(HA_ERR_LOGGING_IMPOSSIBLE); + } + } + + trx = prebuilt->trx; prebuilt->sql_stat_start = TRUE; diff --git a/storage/ndb/src/kernel/blocks/ERROR_codes.txt b/storage/ndb/src/kernel/blocks/ERROR_codes.txt index 17d6c9b0867..6f0cfbff7e9 100644 --- a/storage/ndb/src/kernel/blocks/ERROR_codes.txt +++ b/storage/ndb/src/kernel/blocks/ERROR_codes.txt @@ -4,8 +4,8 @@ Next NDBFS 2000 Next DBACC 3002 Next DBTUP 4029 Next DBLQH 5045 -Next DBDICT 6007 -Next DBDIH 7184 +Next DBDICT 6008 +Next DBDIH 7186 Next DBTC 8040 Next CMVMI 9000 Next BACKUP 10038 @@ -77,6 +77,10 @@ Delay GCP_SAVEREQ by 10 secs 7183: Crash when receiving COPY_GCIREQ +7184: Crash before starting next GCP after a node failure + +7185: Dont reply to COPY_GCI_REQ where reason == GCP + ERROR CODES FOR TESTING NODE FAILURE, LOCAL CHECKPOINT HANDLING: ----------------------------------------------------------------- @@ -503,6 +507,7 @@ Dbdict: 6003 Crash in participant @ CreateTabReq::Prepare 6004 Crash in participant @ CreateTabReq::Commit 6005 Crash in participant @ CreateTabReq::CreateDrop +6007 Fail on readTableFile for READ_TAB_FILE1 (28770) Dbtup: 4014 - handleInsert - Out of undo buffer diff --git a/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp b/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp index edc8c0131db..569958a6aa9 100644 --- a/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp +++ b/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp @@ -802,6 +802,15 @@ void Dbdict::execFSREADCONF(Signal* signal) readSchemaConf(signal ,fsPtr); break; case FsConnectRecord::READ_TAB_FILE1: + if(ERROR_INSERTED(6007)){ + jam(); + FsRef * const fsRef = (FsRef *)&signal->theData[0]; + fsRef->userPointer = fsConf->userPointer; + fsRef->setErrorCode(fsRef->errorCode, NDBD_EXIT_AFS_UNKNOWN); + fsRef->osErrorCode = ~0; // Indicate local error + execFSREADREF(signal); + return; + }//Testing how DICT behave if read of file 1 fails (Bug#28770) case FsConnectRecord::READ_TAB_FILE2: jam(); readTableConf(signal ,fsPtr); diff --git a/storage/ndb/src/kernel/blocks/dbdih/Dbdih.hpp b/storage/ndb/src/kernel/blocks/dbdih/Dbdih.hpp index b4dc445e94d..5bef13cd0b9 100644 --- a/storage/ndb/src/kernel/blocks/dbdih/Dbdih.hpp +++ b/storage/ndb/src/kernel/blocks/dbdih/Dbdih.hpp @@ -898,7 +898,7 @@ private: void ndbsttorry10Lab(Signal *, Uint32 _line); void createMutexes(Signal* signal, Uint32 no); void createMutex_done(Signal* signal, Uint32 no, Uint32 retVal); - void crashSystemAtGcpStop(Signal *); + void crashSystemAtGcpStop(Signal *, bool); void sendFirstDictfragsreq(Signal *, TabRecordPtr regTabPtr); void addtabrefuseLab(Signal *, ConnectRecordPtr regConnectPtr, Uint32 errorCode); void GCP_SAVEhandling(Signal *, Uint32 nodeId); diff --git a/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp b/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp index 4a103a76323..762d4ea5141 100644 --- a/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp +++ b/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp @@ -749,6 +749,12 @@ done: CRASH_INSERTION(7183); + if (ERROR_INSERTED(7185) && reason==CopyGCIReq::GLOBAL_CHECKPOINT) + { + jam(); + return; + } + /* ----------------------------------------------------------------------- */ /* WE START BY TRYING TO OPEN THE FIRST RESTORABLE GCI FILE. */ /* ----------------------------------------------------------------------- */ @@ -4152,6 +4158,11 @@ void Dbdih::execNODE_FAILREP(Signal* signal) CLEAR_ERROR_INSERT_VALUE; } + if (ERROR_INSERTED(7184)) + { + SET_ERROR_INSERT_VALUE(7000); + } + /*-------------------------------------------------------------------------*/ // The first step is to convert from a bit mask to an array of failed nodes. /*-------------------------------------------------------------------------*/ @@ -7826,7 +7837,7 @@ void Dbdih::checkGcpStopLab(Signal* signal) g_eventLogger.error("System crash due to GCP Stop in state = %u", (Uint32) cgcpStatus); #endif - crashSystemAtGcpStop(signal); + crashSystemAtGcpStop(signal, false); return; }//if } else { @@ -7840,7 +7851,7 @@ void Dbdih::checkGcpStopLab(Signal* signal) g_eventLogger.error("System crash due to GCP Stop in state = %u", (Uint32) cgcpStatus); #endif - crashSystemAtGcpStop(signal); + crashSystemAtGcpStop(signal, false); return; }//if } else { @@ -11196,41 +11207,132 @@ void Dbdih::tableCloseLab(Signal* signal, FileRecordPtr filePtr) * GCP stop detected, * send SYSTEM_ERROR to all other alive nodes */ -void Dbdih::crashSystemAtGcpStop(Signal* signal) +void Dbdih::crashSystemAtGcpStop(Signal* signal, bool local) { + if (local) + goto dolocal; + switch(cgcpStatus){ + case GCP_PREPARE_SENT: + { + jam(); + /** + * We're waiting for a GCP PREPARE CONF + */ + infoEvent("Detected GCP stop(%d)...sending kill to %s", + cgcpStatus, c_GCP_PREPARE_Counter.getText()); + ndbout_c("Detected GCP stop(%d)...sending kill to %s", + cgcpStatus, c_GCP_PREPARE_Counter.getText()); + + { + NodeReceiverGroup rg(DBDIH, c_GCP_PREPARE_Counter); + signal->theData[0] = 7022; + sendSignal(rg, GSN_DUMP_STATE_ORD, signal, 1, JBA); + } + + { + NodeReceiverGroup rg(NDBCNTR, c_GCP_PREPARE_Counter); + SystemError * const sysErr = (SystemError*)&signal->theData[0]; + sysErr->errorCode = SystemError::GCPStopDetected; + sysErr->errorRef = reference(); + sysErr->data1 = cgcpStatus; + sysErr->data2 = cgcpOrderBlocked; + sendSignal(rg, GSN_SYSTEM_ERROR, signal, + SystemError::SignalLength, JBA); + } + ndbrequire(!c_GCP_PREPARE_Counter.done()); + return; + } + case GCP_COMMIT_SENT: + { + jam(); + /** + * We're waiting for a GCP_NODEFINISH + */ + infoEvent("Detected GCP stop(%d)...sending kill to %s", + cgcpStatus, c_GCP_COMMIT_Counter.getText()); + ndbout_c("Detected GCP stop(%d)...sending kill to %s", + cgcpStatus, c_GCP_COMMIT_Counter.getText()); + + { + NodeReceiverGroup rg(DBDIH, c_GCP_COMMIT_Counter); + signal->theData[0] = 7022; + sendSignal(rg, GSN_DUMP_STATE_ORD, signal, 1, JBA); + } + + { + NodeReceiverGroup rg(NDBCNTR, c_GCP_COMMIT_Counter); + SystemError * const sysErr = (SystemError*)&signal->theData[0]; + sysErr->errorCode = SystemError::GCPStopDetected; + sysErr->errorRef = reference(); + sysErr->data1 = cgcpStatus; + sysErr->data2 = cgcpOrderBlocked; + sendSignal(rg, GSN_SYSTEM_ERROR, signal, + SystemError::SignalLength, JBA); + } + ndbrequire(!c_GCP_COMMIT_Counter.done()); + return; + } case GCP_NODE_FINISHED: { + jam(); /** * We're waiting for a GCP save conf */ - ndbrequire(!c_GCP_SAVEREQ_Counter.done()); NodeReceiverGroup rg(DBLQH, c_GCP_SAVEREQ_Counter); signal->theData[0] = 2305; sendSignal(rg, GSN_DUMP_STATE_ORD, signal, 1, JBB); - infoEvent("Detected GCP stop...sending kill to %s", - c_GCP_SAVEREQ_Counter.getText()); - g_eventLogger.error("Detected GCP stop...sending kill to %s", - c_GCP_SAVEREQ_Counter.getText()); + infoEvent("Detected GCP stop(%d)...sending kill to %s", + cgcpStatus, c_GCP_SAVEREQ_Counter.getText()); + ndbout_c("Detected GCP stop(%d)...sending kill to %s", + cgcpStatus, c_GCP_SAVEREQ_Counter.getText()); + ndbrequire(!c_GCP_SAVEREQ_Counter.done()); return; } case GCP_SAVE_LQH_FINISHED: - g_eventLogger.error("m_copyReason: %d m_waiting: %d", - c_copyGCIMaster.m_copyReason, - c_copyGCIMaster.m_waiting); - break; - case GCP_READY: // shut up lint - case GCP_PREPARE_SENT: - case GCP_COMMIT_SENT: - break; + { + jam(); + /** + * We're waiting for a COPY_GCICONF + */ + infoEvent("Detected GCP stop(%d)...sending kill to %s", + cgcpStatus, c_COPY_GCIREQ_Counter.getText()); + ndbout_c("Detected GCP stop(%d)...sending kill to %s", + cgcpStatus, c_COPY_GCIREQ_Counter.getText()); + + { + NodeReceiverGroup rg(DBDIH, c_COPY_GCIREQ_Counter); + signal->theData[0] = 7022; + sendSignal(rg, GSN_DUMP_STATE_ORD, signal, 1, JBA); + } + + { + NodeReceiverGroup rg(NDBCNTR, c_COPY_GCIREQ_Counter); + SystemError * const sysErr = (SystemError*)&signal->theData[0]; + sysErr->errorCode = SystemError::GCPStopDetected; + sysErr->errorRef = reference(); + sysErr->data1 = cgcpStatus; + sysErr->data2 = cgcpOrderBlocked; + sendSignal(rg, GSN_SYSTEM_ERROR, signal, + SystemError::SignalLength, JBA); + } + ndbrequire(!c_COPY_GCIREQ_Counter.done()); + return; } + case GCP_READY: (void)1; + } + +dolocal: + ndbout_c("m_copyReason: %d m_waiting: %d", + c_copyGCIMaster.m_copyReason, + c_copyGCIMaster.m_waiting); - g_eventLogger.error("c_copyGCISlave: sender{Data, Ref} %d %x reason: %d nextWord: %d", - c_copyGCISlave.m_senderData, - c_copyGCISlave.m_senderRef, - c_copyGCISlave.m_copyReason, - c_copyGCISlave.m_expectedNextWord); + ndbout_c("c_copyGCISlave: sender{Data, Ref} %d %x reason: %d nextWord: %d", + c_copyGCISlave.m_senderData, + c_copyGCISlave.m_senderRef, + c_copyGCISlave.m_copyReason, + c_copyGCISlave.m_expectedNextWord); FileRecordPtr file0Ptr; file0Ptr.i = crestartInfoFile[0]; @@ -11281,23 +11383,39 @@ void Dbdih::crashSystemAtGcpStop(Signal* signal) c_TCGETOPSIZEREQ_Counter.getText()); ndbout_c("c_UPDATE_TOREQ_Counter = %s", c_UPDATE_TOREQ_Counter.getText()); - NodeRecordPtr nodePtr; - for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) { + if (local == false) + { jam(); - ptrAss(nodePtr, nodeRecord); - if (nodePtr.p->nodeStatus == NodeRecord::ALIVE) { + NodeRecordPtr nodePtr; + for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) { jam(); - const BlockReference ref = - numberToRef(refToBlock(cntrlblockref), nodePtr.i); - SystemError * const sysErr = (SystemError*)&signal->theData[0]; - sysErr->errorCode = SystemError::GCPStopDetected; - sysErr->errorRef = reference(); - sysErr->data1 = cgcpStatus; - sysErr->data2 = cgcpOrderBlocked; - sendSignal(ref, GSN_SYSTEM_ERROR, signal, - SystemError::SignalLength, JBA); - }//if - }//for + ptrAss(nodePtr, nodeRecord); + if (nodePtr.p->nodeStatus == NodeRecord::ALIVE) { + jam(); + const BlockReference ref = + numberToRef(refToBlock(cntrlblockref), nodePtr.i); + SystemError * const sysErr = (SystemError*)&signal->theData[0]; + sysErr->errorCode = SystemError::GCPStopDetected; + sysErr->errorRef = reference(); + sysErr->data1 = cgcpStatus; + sysErr->data2 = cgcpOrderBlocked; + sendSignal(ref, GSN_SYSTEM_ERROR, signal, + SystemError::SignalLength, JBA); + }//if + }//for + } + else + { + jam(); + SystemError * const sysErr = (SystemError*)&signal->theData[0]; + sysErr->errorCode = SystemError::GCPStopDetected; + sysErr->errorRef = reference(); + sysErr->data1 = cgcpStatus; + sysErr->data2 = cgcpOrderBlocked; + EXECUTE_DIRECT(NDBCNTR, GSN_SYSTEM_ERROR, + signal, SystemError::SignalLength); + ndbrequire(false); + } return; }//Dbdih::crashSystemAtGcpStop() @@ -14392,6 +14510,12 @@ Dbdih::execDUMP_STATE_ORD(Signal* signal) infoEvent(buf); } } + + if (arg == 7022) + { + jam(); + crashSystemAtGcpStop(signal, true); + } }//Dbdih::execDUMP_STATE_ORD() void diff --git a/storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp b/storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp index 64d214d472b..6f8e5569831 100644 --- a/storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp +++ b/storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp @@ -1586,7 +1586,8 @@ public: ACTIVE_WRITE_LOG = 17, ///< A write operation during ///< writing of log READ_SR_INVALIDATE_PAGES = 18, - WRITE_SR_INVALIDATE_PAGES = 19 + WRITE_SR_INVALIDATE_PAGES = 19, + WRITE_SR_INVALIDATE_PAGES_UPDATE_PAGE0 = 20 }; /** * We have to remember the log pages read. @@ -2381,7 +2382,7 @@ private: void errorReport(Signal* signal, int place); void warningReport(Signal* signal, int place); void invalidateLogAfterLastGCI(Signal *signal); - void readFileInInvalidate(Signal *signal); + void readFileInInvalidate(Signal *signal, bool stepNext); void exitFromInvalidate(Signal* signal); Uint32 calcPageCheckSum(LogPageRecordPtr logP); Uint32 handleLongTupKey(Signal* signal, Uint32* dataPtr, Uint32 len); diff --git a/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp b/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp index 8f42a8039d8..8dd0de0deda 100644 --- a/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp +++ b/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp @@ -139,6 +139,10 @@ operator<<(NdbOut& out, Operation_t op) //#define MARKER_TRACE 1 //#define TRACE_SCAN_TAKEOVER 1 +#ifndef DEBUG_REDO +#define DEBUG_REDO 0 +#endif + const Uint32 NR_ScanNo = 0; #if defined VM_TRACE || defined ERROR_INSERT || defined NDBD_TRACENR @@ -12322,9 +12326,6 @@ void Dblqh::execFSCLOSECONF(Signal* signal) case LogFileRecord::CLOSE_SR_INVALIDATE_PAGES: jam(); logFilePtr.p->logFileStatus = LogFileRecord::CLOSED; - // Set the prev file to check if we shall close it. - logFilePtr.i = logFilePtr.p->prevLogFile; - ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord); logPartPtr.i = logFilePtr.p->logPartRec; ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord); @@ -12374,7 +12375,7 @@ void Dblqh::execFSOPENCONF(Signal* signal) case LogFileRecord::OPEN_SR_INVALIDATE_PAGES: jam(); logFilePtr.p->logFileStatus = LogFileRecord::OPEN; - readFileInInvalidate(signal); + readFileInInvalidate(signal, false); return; case LogFileRecord::OPENING_INIT: jam(); @@ -12574,6 +12575,7 @@ void Dblqh::execFSWRITECONF(Signal* signal) case LogFileOperationRecord::WRITE_SR_INVALIDATE_PAGES: jam(); invalidateLogAfterLastGCI(signal); + CRASH_INSERTION(5047); return; case LogFileOperationRecord::WRITE_PAGE_ZERO: jam(); @@ -12611,6 +12613,14 @@ void Dblqh::execFSWRITECONF(Signal* signal) jam(); firstPageWriteLab(signal); return; + case LogFileOperationRecord::WRITE_SR_INVALIDATE_PAGES_UPDATE_PAGE0: + jam(); + // We are done...send completed signal and exit this phase. + releaseLfo(signal); + signal->theData[0] = ZSR_FOURTH_COMP; + signal->theData[1] = logPartPtr.i; + sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB); + return; default: jam(); systemErrorLab(signal, __LINE__); @@ -13689,6 +13699,12 @@ void Dblqh::writeSinglePage(Signal* signal, Uint32 pageNo, signal->theData[6] = logPagePtr.i; signal->theData[7] = pageNo; sendSignal(NDBFS_REF, GSN_FSWRITEREQ, signal, 8, JBA); + + if (DEBUG_REDO) + ndbout_c("writeSingle 1 page at part: %u file: %u pos: %u", + logPartPtr.i, + logFilePtr.p->fileNo, + pageNo); }//Dblqh::writeSinglePage() /* ########################################################################## @@ -13754,6 +13770,12 @@ void Dblqh::openSrLastFileLab(Signal* signal) void Dblqh::readSrLastFileLab(Signal* signal) { logPartPtr.p->logLap = logPagePtr.p->logPageWord[ZPOS_LOG_LAP]; + if (DEBUG_REDO) + ndbout_c("readSrLastFileLab part: %u logExecState: %u logPartState: %u logLap: %u", + logPartPtr.i, + logPartPtr.p->logExecState, + logPartPtr.p->logPartState, + logPartPtr.p->logLap); if (logPartPtr.p->noLogFiles > cmaxLogFilesInPageZero) { jam(); initGciInLogFileRec(signal, cmaxLogFilesInPageZero); @@ -14825,6 +14847,20 @@ void Dblqh::srLogLimits(Signal* signal) break; }//if }//while + + if (DEBUG_REDO) + { + LogFileRecordPtr tmp; + tmp.i = logPartPtr.p->stopLogfile; + ptrCheckGuard(tmp, clogFileFileSize, logFileRecord); + ndbout_c("srLogLimits part: %u start file: %u mb: %u stop file: %u mb: %u", + logPartPtr.i, + tlastPrepRef >> 16, + tlastPrepRef & 65535, + tmp.p->fileNo, + logPartPtr.p->stopMbyte); + } + /* ------------------------------------------------------------------------ * WE HAVE NOW FOUND BOTH THE START AND THE STOP OF THE LOG. NOW START * EXECUTING THE LOG. THE FIRST ACTION IS TO OPEN THE LOG FILE WHERE TO @@ -15251,6 +15287,12 @@ void Dblqh::execSr(Signal* signal) case ZCOMPLETED_GCI_TYPE: jam(); logWord = readLogword(signal); + if (DEBUG_REDO) + ndbout_c("found gci: %u part: %u file: %u page: %u", + logWord, + logPartPtr.i, + logFilePtr.p->fileNo, + logFilePtr.p->currentFilepage); if (logWord == logPartPtr.p->logLastGci) { jam(); /*---------------------------------------------------------------------------*/ @@ -15267,6 +15309,10 @@ void Dblqh::execSr(Signal* signal) logPartPtr.p->headPageNo = logFilePtr.p->currentFilepage; logPartPtr.p->headPageIndex = logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX]; + logPartPtr.p->logLap = logPagePtr.p->logPageWord[ZPOS_LOG_LAP]; + if (DEBUG_REDO) + ndbout_c("execSr part: %u logLap: %u", + logPartPtr.i, logPartPtr.p->logLap); }//if /*---------------------------------------------------------------------------*/ /* THERE IS NO NEED OF EXECUTING PAST THIS LINE SINCE THERE WILL ONLY BE LOG */ @@ -15429,67 +15475,140 @@ void Dblqh::invalidateLogAfterLastGCI(Signal* signal) { } switch (lfoPtr.p->lfoState) { - case LogFileOperationRecord::WRITE_SR_INVALIDATE_PAGES: - jam(); - releaseLfo(signal); - releaseLogpage(signal); - if (logPartPtr.p->invalidatePageNo < (clogFileSize * ZPAGES_IN_MBYTE - 1)) { - // We continue in this file. - logPartPtr.p->invalidatePageNo++; - } else { - // We continue in the next file. - logFilePtr.i = logFilePtr.p->nextLogFile; - ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord); - logPartPtr.p->invalidateFileNo = logFilePtr.p->fileNo; - // Page 0 is used for file descriptors. - logPartPtr.p->invalidatePageNo = 1; - if (logFilePtr.p->logFileStatus != LogFileRecord::OPEN) { - jam(); - logFilePtr.p->logFileStatus = LogFileRecord::OPEN_SR_INVALIDATE_PAGES; - openFileRw(signal, logFilePtr); - return; - break; - } - } - // Read a page from the log file. - readFileInInvalidate(signal); - return; - break; - case LogFileOperationRecord::READ_SR_INVALIDATE_PAGES: jam(); - releaseLfo(signal); // Check if this page must be invalidated. // If the log lap number on a page after the head of the tail is the same // as the actual log lap number we must invalidate this page. Otherwise it // could be impossible to find the end of the log in a later system/node // restart. - if (logPagePtr.p->logPageWord[ZPOS_LOG_LAP] == logPartPtr.p->logLap) { + if (logPagePtr.p->logPageWord[ZPOS_LOG_LAP] == logPartPtr.p->logLap) + { // This page must be invalidated. - logPagePtr.p->logPageWord[ZPOS_LOG_LAP] = 0; - // Contact NDBFS. Real time break. - writeSinglePage(signal, logPartPtr.p->invalidatePageNo, - ZPAGE_SIZE - 1, __LINE__); - lfoPtr.p->lfoState = LogFileOperationRecord::WRITE_SR_INVALIDATE_PAGES; - } else { - // We are done with invalidating. Finish start phase 3.4. - exitFromInvalidate(signal); + // We search for end + // read next + releaseLfo(signal); + releaseLogpage(signal); + readFileInInvalidate(signal, true); + lfoPtr.p->lfoState = LogFileOperationRecord::READ_SR_INVALIDATE_PAGES; + return; } - return; - break; + /** + * We found the "last" page to invalidate... + * Invalidate backwards until head... + */ + + // Fall through... + case LogFileOperationRecord::WRITE_SR_INVALIDATE_PAGES: + jam(); + + releaseLfo(signal); + releaseLogpage(signal); + + // Step backwards... + logPartPtr.p->invalidatePageNo--; + + if (logPartPtr.p->invalidatePageNo == 0) + { + jam(); + + if (logFilePtr.p->fileNo == 0) + { + /** + * We're wrapping in the log... + * update logLap + */ + logPartPtr.p->logLap--; + ndbrequire(logPartPtr.p->logLap); // Should always be > 0 + if (DEBUG_REDO) + ndbout_c("invalidateLogAfterLastGCI part: %u wrap from file 0 -> logLap: %u", + logPartPtr.i, logPartPtr.p->logLap); + } + + /** + * Move to prev file + */ + logFilePtr.i = logFilePtr.p->prevLogFile; + ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord); + logPartPtr.p->invalidateFileNo = logFilePtr.p->fileNo; + logPartPtr.p->invalidatePageNo = clogFileSize * ZPAGES_IN_MBYTE - 1; + } + + if (logPartPtr.p->invalidateFileNo == logPartPtr.p->headFileNo && + logPartPtr.p->invalidatePageNo == logPartPtr.p->headPageNo) + { + /** + * Done... + */ + logFilePtr.i = logPartPtr.p->currentLogfile; + ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord); + + logFilePtr.i = logFilePtr.p->nextLogFile; + ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord); + + // Close files if necessary. Current file and the next file should be + // left open. + exitFromInvalidate(signal); + return; + } + + seizeLogpage(signal); + + /** + * Make page really empty + */ + bzero(logPagePtr.p, sizeof(LogPageRecord)); + writeSinglePage(signal, logPartPtr.p->invalidatePageNo, + ZPAGE_SIZE - 1, __LINE__); + + lfoPtr.p->lfoState = LogFileOperationRecord::WRITE_SR_INVALIDATE_PAGES; + return; default: jam(); systemError(signal, __LINE__); return; break; } - - return; }//Dblqh::invalidateLogAfterLastGCI -void Dblqh::readFileInInvalidate(Signal* signal) { +void Dblqh::readFileInInvalidate(Signal* signal, bool stepNext) +{ jam(); + + if (stepNext) + { + logPartPtr.p->invalidatePageNo++; + if (logPartPtr.p->invalidatePageNo == (clogFileSize * ZPAGES_IN_MBYTE)) + { + // We continue in the next file. + logFilePtr.i = logFilePtr.p->nextLogFile; + ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord); + logPartPtr.p->invalidateFileNo = logFilePtr.p->fileNo; + // Page 0 is used for file descriptors. + logPartPtr.p->invalidatePageNo = 1; + + if (logFilePtr.p->fileNo == 0) + { + /** + * We're wrapping in the log... + * update logLap + */ + logPartPtr.p->logLap++; + if (DEBUG_REDO) + ndbout_c("readFileInInvalidate part: %u wrap to file 0 -> logLap: %u", + logPartPtr.i, logPartPtr.p->logLap); + } + if (logFilePtr.p->logFileStatus != LogFileRecord::OPEN) + { + jam(); + logFilePtr.p->logFileStatus = LogFileRecord::OPEN_SR_INVALIDATE_PAGES; + openFileRw(signal, logFilePtr); + return; + } + } + } + // Contact NDBFS. Real time break. readSinglePage(signal, logPartPtr.p->invalidatePageNo); lfoPtr.p->lfoState = LogFileOperationRecord::READ_SR_INVALIDATE_PAGES; @@ -15497,35 +15616,58 @@ void Dblqh::readFileInInvalidate(Signal* signal) { void Dblqh::exitFromInvalidate(Signal* signal) { jam(); - // Close files if necessary. Current file and the next file should be - // left open. - if (logFilePtr.i != logPartPtr.p->currentLogfile) { - LogFileRecordPtr currentLogFilePtr; - LogFileRecordPtr nextAfterCurrentLogFilePtr; - currentLogFilePtr.i = logPartPtr.p->currentLogfile; - ptrCheckGuard(currentLogFilePtr, clogFileFileSize, logFileRecord); +loop: + logFilePtr.i = logFilePtr.p->nextLogFile; + ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord); - nextAfterCurrentLogFilePtr.i = currentLogFilePtr.p->nextLogFile; + if (logFilePtr.i == logPartPtr.p->currentLogfile) + { + jam(); + goto done; + } + + if (logFilePtr.p->fileNo == 0) + { + jam(); + /** + * Logfile 0 shoult *not* be closed + */ + goto loop; + } + + if (logFilePtr.p->logFileStatus == LogFileRecord::CLOSED) + { + jam(); + goto done; + } - if (logFilePtr.i != nextAfterCurrentLogFilePtr.i) { - // This file should be closed. - logFilePtr.p->logFileStatus = LogFileRecord::CLOSE_SR_INVALIDATE_PAGES; - closeFile(signal, logFilePtr, __LINE__); - // Return from this function and wait for close confirm. Then come back - // and test the previous file for closing. - return; - } - } + jam(); + ndbrequire(logFilePtr.p->logFileStatus == LogFileRecord::OPEN); + logFilePtr.p->logFileStatus = LogFileRecord::CLOSE_SR_INVALIDATE_PAGES; + closeFile(signal, logFilePtr, __LINE__); + return; - // We are done with closing files, send completed signal and exit this phase. - signal->theData[0] = ZSR_FOURTH_COMP; - signal->theData[1] = logPartPtr.i; - sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB); +done: + if (DEBUG_REDO) + ndbout_c("exitFromInvalidate part: %u head file: %u page: %u", + logPartPtr.i, + logPartPtr.p->headFileNo, + logPartPtr.p->headPageNo); + + logFilePtr.i = logPartPtr.p->firstLogfile; + ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord); + logPagePtr.i = logFilePtr.p->logPageZero; + ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord); + logPagePtr.p->logPageWord[ZPAGE_HEADER_SIZE + ZPOS_FILE_NO] = + logPartPtr.p->headFileNo; + writeSinglePage(signal, 0, ZPAGE_SIZE - 1, __LINE__); + + lfoPtr.p->logFileRec = logFilePtr.i; + lfoPtr.p->lfoState = LogFileOperationRecord::WRITE_SR_INVALIDATE_PAGES_UPDATE_PAGE0; return; } - /*---------------------------------------------------------------------------*/ /* THE EXECUTION OF A LOG RECORD IS COMPLETED. RELEASE PAGES IF THEY WERE */ /* READ FROM DISK FOR THIS PARTICULAR OPERATION. */ @@ -15916,20 +16058,10 @@ void Dblqh::readSrFourthZeroLab(Signal* signal) ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord); logPartPtr.p->invalidateFileNo = logPartPtr.p->headFileNo; logPartPtr.p->invalidatePageNo = logPartPtr.p->headPageNo; - logPartPtr.p->logExecState = LogPartRecord::LES_EXEC_LOG_INVALIDATE; - seizeLfo(signal); - initLfo(signal); - // The state here is a little confusing, but simulates that we return - // to invalidateLogAfterLastGCI() from an invalidate write and are ready - // to read a page from file. - lfoPtr.p->lfoState = LogFileOperationRecord::WRITE_SR_INVALIDATE_PAGES; - - /** - * Make sure we dont release zero page - */ - seizeLogpage(signal); - invalidateLogAfterLastGCI(signal); + + readFileInInvalidate(signal, true); + lfoPtr.p->lfoState = LogFileOperationRecord::READ_SR_INVALIDATE_PAGES; return; }//Dblqh::readSrFourthZeroLab() @@ -16442,6 +16574,14 @@ void Dblqh::completedLogPage(Signal* signal, Uint32 clpType, Uint32 place) signal->theData[4] = ZVAR_NO_LOG_PAGE_WORD; signal->theData[5] = twlpNoPages; sendSignal(NDBFS_REF, GSN_FSWRITEREQ, signal, 15, JBA); + + if (DEBUG_REDO) + ndbout_c("writing %d pages at part: %u file: %u pos: %u", + twlpNoPages, + logPartPtr.i, + logFilePtr.p->fileNo, + logFilePtr.p->filePosition); + if (twlpType == ZNORMAL) { jam(); lfoPtr.p->lfoState = LogFileOperationRecord::ACTIVE_WRITE_LOG; @@ -17601,6 +17741,14 @@ void Dblqh::readExecLog(Signal* signal) signal->theData[14] = lfoPtr.p->logPageArray[8]; signal->theData[15] = lfoPtr.p->logPageArray[9]; sendSignal(NDBFS_REF, GSN_FSREADREQ, signal, 16, JBA); + + if (DEBUG_REDO) + ndbout_c("readExecLog %u page at part: %u file: %u pos: %u", + lfoPtr.p->noPagesRw, + logPartPtr.i, + logFilePtr.p->fileNo, + logPartPtr.p->execSrStartPageNo); + }//Dblqh::readExecLog() /* ------------------------------------------------------------------------- */ @@ -17663,6 +17811,14 @@ void Dblqh::readExecSr(Signal* signal) signal->theData[13] = lfoPtr.p->logPageArray[7]; signal->theData[14] = tresPageid; sendSignal(NDBFS_REF, GSN_FSREADREQ, signal, 15, JBA); + + if (DEBUG_REDO) + ndbout_c("readExecSr %u page at part: %u file: %u pos: %u", + 8, + logPartPtr.i, + logFilePtr.p->fileNo, + tresPageid); + }//Dblqh::readExecSr() /* ------------------------------------------------------------------------- */ @@ -17818,6 +17974,13 @@ void Dblqh::readSinglePage(Signal* signal, Uint32 pageNo) signal->theData[6] = logPagePtr.i; signal->theData[7] = pageNo; sendSignal(NDBFS_REF, GSN_FSREADREQ, signal, 8, JBA); + + if (DEBUG_REDO) + ndbout_c("readSinglePage 1 page at part: %u file: %u pos: %u", + logPartPtr.i, + logFilePtr.p->fileNo, + pageNo); + }//Dblqh::readSinglePage() /* -------------------------------------------------------------------------- @@ -18301,8 +18464,17 @@ void Dblqh::writeCompletedGciLog(Signal* signal) jam(); changeMbyte(signal); }//if + logFilePtr.p->remainingWordsInMbyte = logFilePtr.p->remainingWordsInMbyte - ZCOMPLETED_GCI_LOG_SIZE; + + if (DEBUG_REDO) + ndbout_c("writeCompletedGciLog gci: %u part: %u file: %u page: %u", + cnewestCompletedGci, + logPartPtr.i, + logFilePtr.p->fileNo, + logFilePtr.p->currentFilepage); + writeLogWord(signal, ZCOMPLETED_GCI_TYPE); writeLogWord(signal, cnewestCompletedGci); logPartPtr.p->logPartNewestCompletedGCI = cnewestCompletedGci; @@ -18339,6 +18511,13 @@ void Dblqh::writeDirty(Signal* signal, Uint32 place) signal->theData[6] = logPagePtr.i; signal->theData[7] = logPartPtr.p->prevFilepage; sendSignal(NDBFS_REF, GSN_FSWRITEREQ, signal, 8, JBA); + + if (DEBUG_REDO) + ndbout_c("writeDirty 1 page at part: %u file: %u pos: %u", + logPartPtr.i, + logFilePtr.p->fileNo, + logPartPtr.p->prevFilepage); + }//Dblqh::writeDirty() /* -------------------------------------------------------------------------- diff --git a/storage/ndb/src/kernel/blocks/pgman.cpp b/storage/ndb/src/kernel/blocks/pgman.cpp index 5e40480f84f..d8e0c053984 100644 --- a/storage/ndb/src/kernel/blocks/pgman.cpp +++ b/storage/ndb/src/kernel/blocks/pgman.cpp @@ -694,7 +694,14 @@ Pgman::lirs_reference(Ptr ptr) if (state & Page_entry::ONSTACK) { jam(); + bool at_bottom = ! pl_stack.hasPrev(ptr); pl_stack.remove(ptr); + if (at_bottom) + { + jam(); + ndbassert(state & Page_entry::HOT); + lirs_stack_prune(); + } } pl_stack.add(ptr); state |= Page_entry::ONSTACK; @@ -1889,9 +1896,10 @@ Pgman::drop_page(Ptr ptr) bool at_bottom = ! pl_stack.hasPrev(ptr); pl_stack.remove(ptr); state &= ~ Page_entry::ONSTACK; - if (at_bottom && (state & Page_entry::HOT)) + if (at_bottom) { jam(); + ndbassert(state & Page_entry::HOT); lirs_stack_prune(); } } @@ -1903,6 +1911,7 @@ Pgman::drop_page(Ptr ptr) state &= ~ Page_entry::ONQUEUE; } + ndbassert(ptr.p->m_real_page_i != RNIL); if (ptr.p->m_real_page_i != RNIL) { jam(); diff --git a/storage/ndb/test/ndbapi/testSystemRestart.cpp b/storage/ndb/test/ndbapi/testSystemRestart.cpp index 8fada42697d..901c0e35568 100644 --- a/storage/ndb/test/ndbapi/testSystemRestart.cpp +++ b/storage/ndb/test/ndbapi/testSystemRestart.cpp @@ -1261,6 +1261,39 @@ runBug29167(NDBT_Context* ctx, NDBT_Step* step) return result; } +int +runBug28770(NDBT_Context* ctx, NDBT_Step* step) { + Ndb* pNdb = GETNDB(step); + NdbRestarter restarter; + int result = NDBT_OK; + int count = 0; + Uint32 i = 0; + Uint32 loops = ctx->getNumLoops(); + int records = ctx->getNumRecords(); + UtilTransactions utilTrans(*ctx->getTab()); + HugoTransactions hugoTrans(*ctx->getTab()); + + g_info << "Loading records..." << endl; hugoTrans.loadTable(pNdb, + records); + + + while(i<=loops && result != NDBT_FAILED){ + g_info << "Loop " << i << "/"<< loops <<" started" << endl; + CHECK(restarter.restartAll(false, true, false) == 0); + NdbSleep_SecSleep(3); + CHECK(restarter.waitClusterNoStart() == 0); + restarter.insertErrorInAllNodes(6007); + CHECK(restarter.startAll()== 0); + CHECK(restarter.waitClusterStarted() == 0); + CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0); + CHECK(count == records); + i++; + } + ndbout << " runBug28770 finished" << endl; + return result; +} + + NDBT_TESTSUITE(testSystemRestart); TESTCASE("SR1", "Basic system restart test. Focus on testing restart from REDO log.\n" @@ -1446,6 +1479,20 @@ TESTCASE("Bug29167", "") INITIALIZER(runWaitStarted); STEP(runBug29167); } +TESTCASE("Bug28770", + "Check readTableFile1 fails, readTableFile2 succeeds\n" + "1. Restart all node -nostart\n" + "2. Insert error 6100 into all nodes\n" + "3. Start all nodes\n" + "4. Ensure cluster start\n" + "5. Read and verify reocrds\n" + "6. Repeat until looping is completed\n"){ + INITIALIZER(runWaitStarted); + INITIALIZER(runClearTable); + STEP(runBug28770); + FINALIZER(runClearTable); +} + NDBT_TESTSUITE_END(testSystemRestart); diff --git a/storage/ndb/test/run-test/daily-basic-tests.txt b/storage/ndb/test/run-test/daily-basic-tests.txt index 2a52c2cbd59..91ce4ae54e3 100644 --- a/storage/ndb/test/run-test/daily-basic-tests.txt +++ b/storage/ndb/test/run-test/daily-basic-tests.txt @@ -489,6 +489,10 @@ max-time: 300 cmd: testSystemRestart args: -n Bug29167 T1 +max-time: 300 +cmd: testSystemRestart +args: -l 2 -n Bug28770 T1 + max-time: 1000 cmd: testNodeRestart args: -n Bug27283 T1