diff --git a/mysql-test/include/ndb_backup_print.inc b/mysql-test/include/ndb_backup_print.inc new file mode 100644 index 00000000000..57fb279491c --- /dev/null +++ b/mysql-test/include/ndb_backup_print.inc @@ -0,0 +1,6 @@ +--exec $NDB_TOOLS_DIR/ndb_restore --no-defaults $ndb_restore_opts -b $the_backup_id -n 1 $NDB_BACKUP_DIR/BACKUP/BACKUP-$the_backup_id $ndb_restore_filter > $MYSQLTEST_VARDIR/tmp/tmp.dat +--exec $NDB_TOOLS_DIR/ndb_restore --no-defaults $ndb_restore_opts -b $the_backup_id -n 2 $NDB_BACKUP_DIR/BACKUP/BACKUP-$the_backup_id $ndb_restore_filter >> $MYSQLTEST_VARDIR/tmp/tmp.dat +--exec sort $MYSQLTEST_VARDIR/tmp/tmp.dat +--exec rm -f $MYSQLTEST_VARDIR/tmp/tmp.dat +--let ndb_restore_opts= +--let ndb_restore_filter= diff --git a/mysql-test/r/ndb_restore_compat.result b/mysql-test/r/ndb_restore_compat.result index f580f680687..d495aa28135 100644 --- a/mysql-test/r/ndb_restore_compat.result +++ b/mysql-test/r/ndb_restore_compat.result @@ -45,8 +45,8 @@ SYSTEM_VALUES_ID VALUE 0 2039 1 3 SELECT * FROM mysql.ndb_apply_status WHERE server_id=0; -server_id epoch -0 151 +server_id epoch log_name start_pos end_pos +0 151 0 0 TRUNCATE GL; TRUNCATE ACCOUNT; TRUNCATE TRANSACTION; @@ -99,6 +99,6 @@ SYSTEM_VALUES_ID VALUE 0 2297 1 5 SELECT * FROM mysql.ndb_apply_status WHERE server_id=0; -server_id epoch -0 331 +server_id epoch log_name start_pos end_pos +0 331 0 0 DROP DATABASE BANK; diff --git a/mysql-test/r/ndb_restore_print.result b/mysql-test/r/ndb_restore_print.result new file mode 100644 index 00000000000..e05f8e43d1a --- /dev/null +++ b/mysql-test/r/ndb_restore_print.result @@ -0,0 +1,321 @@ +use test; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9,t10; +create table t1 +(pk int key +,a1 BIT(1), a2 BIT(5), a3 BIT(33), a4 BIT(63), a5 BIT(64) +,b1 TINYINT, b2 TINYINT UNSIGNED +,c1 SMALLINT, c2 SMALLINT UNSIGNED +,d1 INT, d2 INT UNSIGNED +,e1 BIGINT, e2 BIGINT UNSIGNED +,f1 CHAR(1) BINARY, f2 CHAR(32) BINARY, f3 CHAR(255) BINARY +,g1 VARCHAR(32) BINARY, g2 VARCHAR(255) BINARY, g3 VARCHAR(1000) BINARY +,h1 BINARY(1), h2 BINARY(8), h3 BINARY(255) +,i1 VARBINARY(32), i2 VARBINARY(255), i3 VARBINARY(1000) +) engine myisam; +insert into t1 values +(1 +,0x1, 0x17, 0x789a, 0x789abcde, 0xfedc0001 +,127, 255 +,32767, 65535 +,2147483647, 4294967295 +,9223372036854775807, 18446744073709551615 +,'1','12345678901234567890123456789012','123456789' + ,'1','12345678901234567890123456789012','123456789' + ,0x12,0x123456789abcdef0, 0x012345 +,0x12,0x123456789abcdef0, 0x00123450 +); +insert into t1 values +(2 +,0, 0, 0, 0, 0 +,-128, 0 +,-32768, 0 +,-2147483648, 0 +,-9223372036854775808, 0 +,'','','' + ,'','','' + ,0x0,0x0,0x0 +,0x0,0x0,0x0 +); +insert into t1 values +(3 +,NULL,NULL,NULL,NULL,NULL +,NULL,NULL +,NULL,NULL +,NULL,NULL +,NULL,NULL +,NULL,NULL,NULL +,NULL,NULL,NULL +,NULL,NULL,NULL +,NULL,NULL,NULL +); +select pk +,hex(a1), hex(a2), hex(a3), hex(a4), hex(a5) +,b1, b2 +,c1 , c2 +,d1 , d2 +,e1 , e2 +,f1 , f2, f3 +,g1 , g2, g3 +,hex(h1), hex(h2), hex(h3) +,hex(i1), hex(i2), hex(i3) +from t1 order by pk; +pk 1 +hex(a1) 1 +hex(a2) 17 +hex(a3) 789A +hex(a4) 789ABCDE +hex(a5) FEDC0001 +b1 127 +b2 255 +c1 32767 +c2 65535 +d1 2147483647 +d2 4294967295 +e1 9223372036854775807 +e2 18446744073709551615 +f1 1 +f2 12345678901234567890123456789012 +f3 123456789 +g1 1 +g2 12345678901234567890123456789012 +g3 123456789 +hex(h1) 12 +hex(h2) 123456789ABCDEF0 +hex(h3) 012345000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +hex(i1) 12 +hex(i2) 123456789ABCDEF0 +hex(i3) 00123450 +pk 2 +hex(a1) 0 +hex(a2) 0 +hex(a3) 0 +hex(a4) 0 +hex(a5) 0 +b1 -128 +b2 0 +c1 -32768 +c2 0 +d1 -2147483648 +d2 0 +e1 -9223372036854775808 +e2 0 +f1 +f2 +f3 +g1 +g2 +g3 +hex(h1) 00 +hex(h2) 0000000000000000 +hex(h3) 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +hex(i1) 00 +hex(i2) 00 +hex(i3) 00 +pk 3 +hex(a1) NULL +hex(a2) NULL +hex(a3) NULL +hex(a4) NULL +hex(a5) NULL +b1 NULL +b2 NULL +c1 NULL +c2 NULL +d1 NULL +d2 NULL +e1 NULL +e2 NULL +f1 NULL +f2 NULL +f3 NULL +g1 NULL +g2 NULL +g3 NULL +hex(h1) NULL +hex(h2) NULL +hex(h3) NULL +hex(i1) NULL +hex(i2) NULL +hex(i3) NULL +alter table t1 engine ndb; +select pk +,hex(a1), hex(a2), hex(a3), hex(a4), hex(a5) +,b1, b2 +,c1 , c2 +,d1 , d2 +,e1 , e2 +,f1 , f2, f3 +,g1 , g2, g3 +,hex(h1), hex(h2), hex(h3) +,hex(i1), hex(i2), hex(i3) +from t1 order by pk; +pk 1 +hex(a1) 1 +hex(a2) 17 +hex(a3) 789A +hex(a4) 789ABCDE +hex(a5) FEDC0001 +b1 127 +b2 255 +c1 32767 +c2 65535 +d1 2147483647 +d2 4294967295 +e1 9223372036854775807 +e2 18446744073709551615 +f1 1 +f2 12345678901234567890123456789012 +f3 123456789 +g1 1 +g2 12345678901234567890123456789012 +g3 123456789 +hex(h1) 12 +hex(h2) 123456789ABCDEF0 +hex(h3) 012345000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +hex(i1) 12 +hex(i2) 123456789ABCDEF0 +hex(i3) 00123450 +pk 2 +hex(a1) 0 +hex(a2) 0 +hex(a3) 0 +hex(a4) 0 +hex(a5) 0 +b1 -128 +b2 0 +c1 -32768 +c2 0 +d1 -2147483648 +d2 0 +e1 -9223372036854775808 +e2 0 +f1 +f2 +f3 +g1 +g2 +g3 +hex(h1) 00 +hex(h2) 0000000000000000 +hex(h3) 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +hex(i1) 00 +hex(i2) 00 +hex(i3) 00 +pk 3 +hex(a1) NULL +hex(a2) NULL +hex(a3) NULL +hex(a4) NULL +hex(a5) NULL +b1 NULL +b2 NULL +c1 NULL +c2 NULL +d1 NULL +d2 NULL +e1 NULL +e2 NULL +f1 NULL +f2 NULL +f3 NULL +g1 NULL +g2 NULL +g3 NULL +hex(h1) NULL +hex(h2) NULL +hex(h3) NULL +hex(i1) NULL +hex(i2) NULL +hex(i3) NULL +CREATE TEMPORARY TABLE IF NOT EXISTS test.backup_info (id INT, backup_id INT) ENGINE = HEAP; +DELETE FROM test.backup_info; +LOAD DATA INFILE '../tmp.dat' INTO TABLE test.backup_info FIELDS TERMINATED BY ','; +SELECT @the_backup_id:=backup_id FROM test.backup_info; +@the_backup_id:=backup_id + +DROP TABLE test.backup_info; +1;0x1;0x17;0x789A;0x789ABCDE;0xFEDC0001;127;255;32767;65535;2147483647;4294967295;9223372036854775807;18446744073709551615;1;12345678901234567890123456789012;123456789;1;12345678901234567890123456789012;123456789;0x12;0x123456789ABCDEF0;0x012345;0x12;0x123456789ABCDEF0;0x00123450 +2;0x0;0x0;0x0;0x0;0x0;-128;0;-32768;0;-2147483648;0;-9223372036854775808;0;;;;;;;0x0;0x0;0x0;0x0;0x0;0x0 +3;\N;\N;\N;\N;\N;\N;\N;\N;\N;\N;\N;\N;\N;\N;\N;\N;\N;\N;\N;\N;\N;\N;\N;\N;\N +1,0x1,0x17,0x789A,0x789ABCDE,0xFEDC0001,127,255,32767,65535,2147483647,4294967295,9223372036854775807,18446744073709551615,'1','12345678901234567890123456789012','123456789','1','12345678901234567890123456789012','123456789',0x12,0x123456789ABCDEF0,0x012345,0x12,0x123456789ABCDEF0,0x00123450 +2,0x0,0x0,0x0,0x0,0x0,-128,0,-32768,0,-2147483648,0,-9223372036854775808,0,'','','','','','',0x0,0x0,0x0,0x0,0x0,0x0 +3,,,,,,,,,,,,,,,,,,,,,,,,, +drop table t1; +create table t1 +(pk int key +,f1 CHAR(1) BINARY, f2 CHAR(32) BINARY, f3 CHAR(255) BINARY +,g1 VARCHAR(32) BINARY, g2 VARCHAR(255) BINARY, g3 VARCHAR(1000) BINARY +,h1 BINARY(1), h2 BINARY(9), h3 BINARY(255) +,i1 VARBINARY(32), i2 VARBINARY(255), i3 VARBINARY(1000) +) engine ndb; +insert into t1 values +(1 +,'1','12345678901234567890123456789012','123456789 ' + ,'1 ','12345678901234567890123456789012 ','123456789 ' + ,0x20,0x123456789abcdef020, 0x012345000020 +,0x1200000020,0x123456789abcdef000000020, 0x00123450000020 +); +create table t2 (pk int key, a int) engine ndb; +create table t3 (pk int key, a int) engine ndb; +create table t4 (pk int key, a int) engine ndb; +insert into t2 values (1,11),(2,12),(3,13),(4,14),(5,15); +insert into t3 values (1,21),(2,22),(3,23),(4,24),(5,25); +insert into t4 values (1,31),(2,32),(3,33),(4,34),(5,35); +CREATE TEMPORARY TABLE IF NOT EXISTS test.backup_info (id INT, backup_id INT) ENGINE = HEAP; +DELETE FROM test.backup_info; +LOAD DATA INFILE '../tmp.dat' INTO TABLE test.backup_info FIELDS TERMINATED BY ','; +SELECT @the_backup_id:=backup_id FROM test.backup_info; +@the_backup_id:=backup_id + +DROP TABLE test.backup_info; +'1' '1' '12345678901234567890123456789012' '123456789' '1' '12345678901234567890123456789012' '123456789' '0x20' '0x123456789ABCDEF020' '0x012345000020' '0x1200000020' '0x123456789ABCDEF000000020' '0x00123450000020' + +t1 +-- +1 1 12345678901234567890123456789012 123456789 1 12345678901234567890123456789012 123456789 0x20 0x123456789ABCDEF020 0x012345000020 0x1200000020 0x123456789ABCDEF000000020 0x00123450000020 + +t2 +-- +1 11 +2 12 +3 13 +4 14 +5 15 + +t3 +-- +1 21 +2 22 +3 23 +4 24 +5 25 + +t4 +-- +1 31 +2 32 +3 33 +4 34 +5 35 +drop table t1; +create table t1 +(pk int key +,a1 MEDIUMINT, a2 MEDIUMINT UNSIGNED +) engine ndb; +insert into t1 values(1, 8388607, 16777215); +insert into t1 values(2, -8388608, 0); +insert into t1 values(3, -1, 1); +CREATE TEMPORARY TABLE IF NOT EXISTS test.backup_info (id INT, backup_id INT) ENGINE = HEAP; +DELETE FROM test.backup_info; +LOAD DATA INFILE '../tmp.dat' INTO TABLE test.backup_info FIELDS TERMINATED BY ','; +SELECT @the_backup_id:=backup_id FROM test.backup_info; +@the_backup_id:=backup_id + +DROP TABLE test.backup_info; +1;8388607;16777215 +2;-8388608;0 +3;-1;1 +drop table t1; +drop table t2; +drop table t3; +drop table t4; diff --git a/mysql-test/r/rpl_ndb_log.result b/mysql-test/r/rpl_ndb_log.result index 543af3b9abe..c93af3441d8 100644 --- a/mysql-test/r/rpl_ndb_log.result +++ b/mysql-test/r/rpl_ndb_log.result @@ -87,12 +87,12 @@ master-bin.000002 # Write_rows 1 # table_id: # flags: STMT_END_F master-bin.000002 # Query 1 # COMMIT show binary logs; Log_name File_size -master-bin.000001 1702 -master-bin.000002 593 +master-bin.000001 1740 +master-bin.000002 612 start slave; show binary logs; Log_name File_size -slave-bin.000001 1797 +slave-bin.000001 1835 slave-bin.000002 198 show binlog events in 'slave-bin.000001' from 4; Log_name Pos Event_type Server_id End_log_pos Info @@ -126,7 +126,7 @@ slave-bin.000002 # Write_rows 2 # table_id: # flags: STMT_END_F slave-bin.000002 # Query 2 # COMMIT show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master -# 127.0.0.1 root MASTER_PORT 1 master-bin.000002 593 # # master-bin.000002 Yes Yes # 0 0 593 # None 0 No # +# 127.0.0.1 root MASTER_PORT 1 master-bin.000002 612 # # master-bin.000002 Yes Yes # 0 0 612 # None 0 No # show binlog events in 'slave-bin.000005' from 4; ERROR HY000: Error when executing command SHOW BINLOG EVENTS: Could not find target log DROP TABLE t1; diff --git a/mysql-test/r/rpl_truncate_7ndb.result b/mysql-test/r/rpl_truncate_7ndb.result index 63d4b0f9411..21399be4686 100644 --- a/mysql-test/r/rpl_truncate_7ndb.result +++ b/mysql-test/r/rpl_truncate_7ndb.result @@ -33,12 +33,12 @@ master-bin.000001 4 Format_desc 1 102 Server ver: SERVER_VERSION, Binlog ver: 4 master-bin.000001 102 Query 1 219 use `test`; CREATE TABLE t1 (a INT PRIMARY KEY, b LONG) ENGINE=NDB master-bin.000001 219 Query 1 283 BEGIN master-bin.000001 283 Table_map 1 40 table_id: # (test.t1) -master-bin.000001 323 Table_map 1 95 table_id: # (mysql.ndb_apply_status) -master-bin.000001 378 Write_rows 1 137 table_id: # -master-bin.000001 420 Write_rows 1 184 table_id: # flags: STMT_END_F -master-bin.000001 467 Query 1 532 COMMIT -master-bin.000001 532 Query 1 612 use `test`; TRUNCATE TABLE t1 -master-bin.000001 612 Query 1 688 use `test`; DROP TABLE t1 +master-bin.000001 323 Table_map 1 98 table_id: # (mysql.ndb_apply_status) +master-bin.000001 381 Write_rows 1 156 table_id: # +master-bin.000001 439 Write_rows 1 203 table_id: # flags: STMT_END_F +master-bin.000001 486 Query 1 551 COMMIT +master-bin.000001 551 Query 1 631 use `test`; TRUNCATE TABLE t1 +master-bin.000001 631 Query 1 707 use `test`; DROP TABLE t1 **** On Master **** CREATE TABLE t1 (a INT PRIMARY KEY, b LONG) ENGINE=NDB; INSERT INTO t1 VALUES (1,1), (2,2); @@ -69,23 +69,23 @@ master-bin.000001 4 Format_desc 1 102 Server ver: SERVER_VERSION, Binlog ver: 4 master-bin.000001 102 Query 1 219 use `test`; CREATE TABLE t1 (a INT PRIMARY KEY, b LONG) ENGINE=NDB master-bin.000001 219 Query 1 283 BEGIN master-bin.000001 283 Table_map 1 40 table_id: # (test.t1) -master-bin.000001 323 Table_map 1 95 table_id: # (mysql.ndb_apply_status) -master-bin.000001 378 Write_rows 1 137 table_id: # -master-bin.000001 420 Write_rows 1 184 table_id: # flags: STMT_END_F -master-bin.000001 467 Query 1 532 COMMIT -master-bin.000001 532 Query 1 612 use `test`; TRUNCATE TABLE t1 -master-bin.000001 612 Query 1 688 use `test`; DROP TABLE t1 -master-bin.000001 688 Query 1 805 use `test`; CREATE TABLE t1 (a INT PRIMARY KEY, b LONG) ENGINE=NDB -master-bin.000001 805 Query 1 869 BEGIN -master-bin.000001 869 Table_map 1 40 table_id: # (test.t1) -master-bin.000001 909 Table_map 1 95 table_id: # (mysql.ndb_apply_status) -master-bin.000001 964 Write_rows 1 137 table_id: # -master-bin.000001 1006 Write_rows 1 184 table_id: # flags: STMT_END_F -master-bin.000001 1053 Query 1 1118 COMMIT -master-bin.000001 1118 Query 1 1182 BEGIN -master-bin.000001 1182 Table_map 1 40 table_id: # (test.t1) -master-bin.000001 1222 Table_map 1 95 table_id: # (mysql.ndb_apply_status) -master-bin.000001 1277 Write_rows 1 137 table_id: # -master-bin.000001 1319 Delete_rows 1 176 table_id: # flags: STMT_END_F -master-bin.000001 1358 Query 1 1423 COMMIT -master-bin.000001 1423 Query 1 1499 use `test`; DROP TABLE t1 +master-bin.000001 323 Table_map 1 98 table_id: # (mysql.ndb_apply_status) +master-bin.000001 381 Write_rows 1 156 table_id: # +master-bin.000001 439 Write_rows 1 203 table_id: # flags: STMT_END_F +master-bin.000001 486 Query 1 551 COMMIT +master-bin.000001 551 Query 1 631 use `test`; TRUNCATE TABLE t1 +master-bin.000001 631 Query 1 707 use `test`; DROP TABLE t1 +master-bin.000001 707 Query 1 824 use `test`; CREATE TABLE t1 (a INT PRIMARY KEY, b LONG) ENGINE=NDB +master-bin.000001 824 Query 1 888 BEGIN +master-bin.000001 888 Table_map 1 40 table_id: # (test.t1) +master-bin.000001 928 Table_map 1 98 table_id: # (mysql.ndb_apply_status) +master-bin.000001 986 Write_rows 1 156 table_id: # +master-bin.000001 1044 Write_rows 1 203 table_id: # flags: STMT_END_F +master-bin.000001 1091 Query 1 1156 COMMIT +master-bin.000001 1156 Query 1 1220 BEGIN +master-bin.000001 1220 Table_map 1 40 table_id: # (test.t1) +master-bin.000001 1260 Table_map 1 98 table_id: # (mysql.ndb_apply_status) +master-bin.000001 1318 Write_rows 1 156 table_id: # +master-bin.000001 1376 Delete_rows 1 195 table_id: # flags: STMT_END_F +master-bin.000001 1415 Query 1 1480 COMMIT +master-bin.000001 1480 Query 1 1556 use `test`; DROP TABLE t1 diff --git a/mysql-test/t/ndb_restore_print.test b/mysql-test/t/ndb_restore_print.test new file mode 100644 index 00000000000..6dbbfdf5933 --- /dev/null +++ b/mysql-test/t/ndb_restore_print.test @@ -0,0 +1,189 @@ +-- source include/have_ndb.inc +-- source include/ndb_default_cluster.inc +-- source include/not_embedded.inc + +--disable_warnings +use test; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9,t10; +--enable_warnings + +# basic datatypes +create table t1 + (pk int key + ,a1 BIT(1), a2 BIT(5), a3 BIT(33), a4 BIT(63), a5 BIT(64) + ,b1 TINYINT, b2 TINYINT UNSIGNED + ,c1 SMALLINT, c2 SMALLINT UNSIGNED + ,d1 INT, d2 INT UNSIGNED + ,e1 BIGINT, e2 BIGINT UNSIGNED + ,f1 CHAR(1) BINARY, f2 CHAR(32) BINARY, f3 CHAR(255) BINARY + ,g1 VARCHAR(32) BINARY, g2 VARCHAR(255) BINARY, g3 VARCHAR(1000) BINARY + ,h1 BINARY(1), h2 BINARY(8), h3 BINARY(255) + ,i1 VARBINARY(32), i2 VARBINARY(255), i3 VARBINARY(1000) + ) engine myisam; + +# max values +insert into t1 values + (1 + ,0x1, 0x17, 0x789a, 0x789abcde, 0xfedc0001 + ,127, 255 + ,32767, 65535 + ,2147483647, 4294967295 + ,9223372036854775807, 18446744073709551615 + ,'1','12345678901234567890123456789012','123456789' + ,'1','12345678901234567890123456789012','123456789' + ,0x12,0x123456789abcdef0, 0x012345 + ,0x12,0x123456789abcdef0, 0x00123450 + ); + +# min values +insert into t1 values + (2 + ,0, 0, 0, 0, 0 + ,-128, 0 + ,-32768, 0 + ,-2147483648, 0 + ,-9223372036854775808, 0 + ,'','','' + ,'','','' + ,0x0,0x0,0x0 + ,0x0,0x0,0x0 + ); + +# null values +insert into t1 values + (3 + ,NULL,NULL,NULL,NULL,NULL + ,NULL,NULL + ,NULL,NULL + ,NULL,NULL + ,NULL,NULL + ,NULL,NULL,NULL + ,NULL,NULL,NULL + ,NULL,NULL,NULL + ,NULL,NULL,NULL + ); + +--vertical_results +select pk + ,hex(a1), hex(a2), hex(a3), hex(a4), hex(a5) + ,b1, b2 + ,c1 , c2 + ,d1 , d2 + ,e1 , e2 + ,f1 , f2, f3 + ,g1 , g2, g3 + ,hex(h1), hex(h2), hex(h3) + ,hex(i1), hex(i2), hex(i3) + from t1 order by pk; + +alter table t1 engine ndb; + +select pk + ,hex(a1), hex(a2), hex(a3), hex(a4), hex(a5) + ,b1, b2 + ,c1 , c2 + ,d1 , d2 + ,e1 , e2 + ,f1 , f2, f3 + ,g1 , g2, g3 + ,hex(h1), hex(h2), hex(h3) + ,hex(i1), hex(i2), hex(i3) + from t1 order by pk; +--horizontal_results + +--source include/ndb_backup.inc + +--let ndb_restore_filter=test t1 +--let ndb_restore_opts=--verbose=0 --print_data --hex --fields-terminated-by=";" +--source include/ndb_backup_print.inc + +--let ndb_restore_filter=test t1 +--let ndb_restore_opts=--verbose=0 --print_data --hex --fields-terminated-by="," --fields-optionally-enclosed-by="'" +--source include/ndb_backup_print.inc + + +drop table t1; + +# some binary char tests with trailing spaces +create table t1 + (pk int key + ,f1 CHAR(1) BINARY, f2 CHAR(32) BINARY, f3 CHAR(255) BINARY + ,g1 VARCHAR(32) BINARY, g2 VARCHAR(255) BINARY, g3 VARCHAR(1000) BINARY + ,h1 BINARY(1), h2 BINARY(9), h3 BINARY(255) + ,i1 VARBINARY(32), i2 VARBINARY(255), i3 VARBINARY(1000) + ) engine ndb; + +insert into t1 values + (1 + ,'1','12345678901234567890123456789012','123456789 ' + ,'1 ','12345678901234567890123456789012 ','123456789 ' + ,0x20,0x123456789abcdef020, 0x012345000020 + ,0x1200000020,0x123456789abcdef000000020, 0x00123450000020 + ); + +create table t2 (pk int key, a int) engine ndb; +create table t3 (pk int key, a int) engine ndb; +create table t4 (pk int key, a int) engine ndb; + +insert into t2 values (1,11),(2,12),(3,13),(4,14),(5,15); +insert into t3 values (1,21),(2,22),(3,23),(4,24),(5,25); +insert into t4 values (1,31),(2,32),(3,33),(4,34),(5,35); + +--source include/ndb_backup.inc +--let ndb_restore_opts=--verbose=0 --print_data --hex --fields-enclosed-by="'" --fields-optionally-enclosed-by="X" +--let ndb_restore_filter=test t1 +--source include/ndb_backup_print.inc + +--exec rm -f $MYSQLTEST_VARDIR/tmp/t1.txt +--exec rm -f $MYSQLTEST_VARDIR/tmp/t2.txt +--exec rm -f $MYSQLTEST_VARDIR/tmp/t3.txt +--exec rm -f $MYSQLTEST_VARDIR/tmp/t4.txt + +--let ndb_restore_opts=--verbose=0 --print_data --hex --tab $MYSQLTEST_VARDIR/tmp --append +--let ndb_restore_filter=test +--source include/ndb_backup_print.inc + +--let $message= t1 +--source include/show_msg.inc +--exec sort $MYSQLTEST_VARDIR/tmp/t1.txt +--let $message= t2 +--source include/show_msg.inc +--exec sort $MYSQLTEST_VARDIR/tmp/t2.txt +--let $message= t3 +--source include/show_msg.inc +--exec sort $MYSQLTEST_VARDIR/tmp/t3.txt +--let $message= t4 +--source include/show_msg.inc +--exec sort $MYSQLTEST_VARDIR/tmp/t4.txt + +--exec rm -f $MYSQLTEST_VARDIR/tmp/t1.txt +--exec rm -f $MYSQLTEST_VARDIR/tmp/t2.txt +--exec rm -f $MYSQLTEST_VARDIR/tmp/t3.txt +--exec rm -f $MYSQLTEST_VARDIR/tmp/t4.txt + +# now test some other datatypes +drop table t1; +create table t1 + (pk int key + ,a1 MEDIUMINT, a2 MEDIUMINT UNSIGNED + ) engine ndb; + +# max values +insert into t1 values(1, 8388607, 16777215); +# min values +insert into t1 values(2, -8388608, 0); +# small values +insert into t1 values(3, -1, 1); + +# backup and print +--source include/ndb_backup.inc + +--let ndb_restore_filter=test t1 +--let ndb_restore_opts=--verbose=0 --print_data --hex --fields-terminated-by=";" +--source include/ndb_backup_print.inc + +# clean up +drop table t1; +drop table t2; +drop table t3; +drop table t4; diff --git a/sql/ha_ndbcluster_binlog.cc b/sql/ha_ndbcluster_binlog.cc index 2615732e7ee..8b51ac68e66 100644 --- a/sql/ha_ndbcluster_binlog.cc +++ b/sql/ha_ndbcluster_binlog.cc @@ -729,6 +729,9 @@ static int ndbcluster_create_ndb_apply_status_table(THD *thd) NDB_REP_DB "." NDB_APPLY_TABLE " ( server_id INT UNSIGNED NOT NULL," " epoch BIGINT UNSIGNED NOT NULL, " + " log_name VARCHAR(255) BINARY NOT NULL, " + " start_pos BIGINT UNSIGNED NOT NULL, " + " end_pos BIGINT UNSIGNED NOT NULL, " " PRIMARY KEY USING HASH (server_id) ) ENGINE=NDB"); run_query(thd, buf, end, TRUE, TRUE); @@ -3898,6 +3901,9 @@ restart: bzero(table->record[0], table->s->null_bytes); table->field[0]->store((longlong)::server_id); table->field[1]->store((longlong)gci); + table->field[2]->store("", 0, &my_charset_bin); + table->field[3]->store((longlong)0); + table->field[4]->store((longlong)0); trans.write_row(::server_id, injector::transaction::table(table, TRUE), &table->s->all_set, table->s->fields, diff --git a/storage/ndb/include/ndbapi/NdbRecAttr.hpp b/storage/ndb/include/ndbapi/NdbRecAttr.hpp index 40d5b598c0c..fe903de6498 100644 --- a/storage/ndb/include/ndbapi/NdbRecAttr.hpp +++ b/storage/ndb/include/ndbapi/NdbRecAttr.hpp @@ -129,6 +129,13 @@ public: */ Int32 int32_value() const; + /** + * Get value stored in NdbRecAttr object. + * + * @return Medium value. + */ + Int32 medium_value() const; + /** * Get value stored in NdbRecAttr object. * @@ -157,6 +164,13 @@ public: */ Uint32 u_32_value() const; + /** + * Get value stored in NdbRecAttr object. + * + * @return Unsigned medium value. + */ + Uint32 u_medium_value() const; + /** * Get value stored in NdbRecAttr object. * @@ -287,6 +301,16 @@ NdbRecAttr::int32_value() const return *(Int32*)theRef; } +inline +Int32 +NdbRecAttr::medium_value() const +{ + Uint32 tmp = *(Uint32*)theRef; + if (tmp & (0x1<<23)) + tmp|= (0xFF<<24); + return (Int32)tmp; +} + inline short NdbRecAttr::short_value() const @@ -308,6 +332,13 @@ NdbRecAttr::u_32_value() const return *(Uint32*)theRef; } +inline +Uint32 +NdbRecAttr::u_medium_value() const +{ + return *(Uint32*)theRef; +} + inline Uint16 NdbRecAttr::u_short_value() const @@ -409,6 +440,25 @@ NdbRecAttr::setUNDEFINED() class NdbOut& operator <<(class NdbOut&, const NdbRecAttr &); +class NdbRecordPrintFormat +{ +public: + NdbRecordPrintFormat(); + virtual ~NdbRecordPrintFormat(); + const char *lines_terminated_by; + const char *fields_terminated_by; + const char *start_array_enclosure; + const char *end_array_enclosure; + const char *fields_enclosed_by; + const char *fields_optionally_enclosed_by; + const char *hex_prefix; + const char *null_string; + int hex_format; +}; +NdbOut& +ndbrecattr_print_formatted(NdbOut& out, const NdbRecAttr &r, + const NdbRecordPrintFormat &f); + #endif // ifndef DOXYGEN_SHOULD_SKIP_INTERNAL #endif diff --git a/storage/ndb/include/util/OutputStream.hpp b/storage/ndb/include/util/OutputStream.hpp index d56d04adc50..78072320493 100644 --- a/storage/ndb/include/util/OutputStream.hpp +++ b/storage/ndb/include/util/OutputStream.hpp @@ -36,6 +36,7 @@ class FileOutputStream : public OutputStream { public: FileOutputStream(FILE * file = stdout); virtual ~FileOutputStream() {} + FILE *getFile() { return f; } int print(const char * fmt, ...); int println(const char * fmt, ...); diff --git a/storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp b/storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp index dae8ee7e73b..a8a7c8f22c0 100644 --- a/storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp +++ b/storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp @@ -1840,9 +1840,14 @@ private: Uint32 transid2); void removeMarkerForFailedAPI(Signal* signal, Uint32 nodeId, Uint32 bucket); - bool getAllowStartTransaction() const { - if(getNodeState().getSingleUserMode()) - return true; + bool getAllowStartTransaction(Uint32 nodeId) const { + if (unlikely(getNodeState().getSingleUserMode())) + { + if (getNodeState().getSingleUserApi() == nodeId) + return true; + else + return false; + } return getNodeState().startLevel < NodeState::SL_STOPPING_2; } diff --git a/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp b/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp index 7ea6d3936b0..500048a7df9 100644 --- a/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp +++ b/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp @@ -1202,16 +1202,14 @@ void Dbtc::execTCSEIZEREQ(Signal* signal) const NodeId senderNodeId = refToNode(tapiBlockref); const bool local = senderNodeId == getOwnNodeId() || senderNodeId == 0; - if(!(senderNodeId == getNodeState().getSingleUserApi()) && - !getNodeState().getSingleUserMode()) { - if(!(sl==NodeState::SL_SINGLEUSER && - senderNodeId == getNodeState().getSingleUserApi())) { + { + { if (!(sl == NodeState::SL_STARTED || (sl == NodeState::SL_STARTING && local == true))) { jam(); - Uint32 errCode; - if(!(sl == NodeState::SL_SINGLEUSER && local)) + Uint32 errCode = 0; + if(!local) { switch(sl){ case NodeState::SL_STARTING: @@ -1219,6 +1217,9 @@ void Dbtc::execTCSEIZEREQ(Signal* signal) break; case NodeState::SL_STOPPING_1: case NodeState::SL_STOPPING_2: + if (getNodeState().getSingleUserMode() && + getNodeState().getSingleUserApi() == senderNodeId) + break; case NodeState::SL_STOPPING_3: case NodeState::SL_STOPPING_4: if(getNodeState().stopping.systemShutdown) @@ -1227,16 +1228,21 @@ void Dbtc::execTCSEIZEREQ(Signal* signal) errCode = ZNODE_SHUTDOWN_IN_PROGRESS; break; case NodeState::SL_SINGLEUSER: + if (getNodeState().getSingleUserApi() == senderNodeId) + break; errCode = ZCLUSTER_IN_SINGLEUSER_MODE; break; default: errCode = ZWRONG_STATE; break; } - signal->theData[0] = tapiPointer; - signal->theData[1] = errCode; - sendSignal(tapiBlockref, GSN_TCSEIZEREF, signal, 2, JBB); - return; + if (errCode) + { + signal->theData[0] = tapiPointer; + signal->theData[1] = errCode; + sendSignal(tapiBlockref, GSN_TCSEIZEREF, signal, 2, JBB); + return; + } }//if (!(sl == SL_SINGLEUSER)) } //if } @@ -1724,8 +1730,14 @@ Dbtc::TCKEY_abort(Signal* signal, int place) * Initialize object before starting error handling */ initApiConnectRec(signal, apiConnectptr.p, true); +start_failure: switch(getNodeState().startLevel){ case NodeState::SL_STOPPING_2: + if (getNodeState().getSingleUserMode()) + { + terrorCode = ZCLUSTER_IN_SINGLEUSER_MODE; + break; + } case NodeState::SL_STOPPING_3: case NodeState::SL_STOPPING_4: if(getNodeState().stopping.systemShutdown) @@ -1736,6 +1748,12 @@ Dbtc::TCKEY_abort(Signal* signal, int place) case NodeState::SL_SINGLEUSER: terrorCode = ZCLUSTER_IN_SINGLEUSER_MODE; break; + case NodeState::SL_STOPPING_1: + if (getNodeState().getSingleUserMode()) + { + terrorCode = ZCLUSTER_IN_SINGLEUSER_MODE; + break; + } default: terrorCode = ZWRONG_STATE; break; @@ -1757,6 +1775,13 @@ Dbtc::TCKEY_abort(Signal* signal, int place) return; } + case 60: + { + jam(); + initApiConnectRec(signal, apiConnectptr.p, true); + apiConnectptr.p->m_exec_flag = 1; + goto start_failure; + } default: jam(); systemErrorLab(signal, __LINE__); @@ -2486,6 +2511,7 @@ Dbtc::seizeCacheRecord(Signal* signal) /*****************************************************************************/ void Dbtc::execTCKEYREQ(Signal* signal) { + Uint32 sendersNodeId = refToNode(signal->getSendersBlockRef()); UintR compare_transid1, compare_transid2; UintR titcLenAiInTckeyreq; UintR TkeyLength; @@ -2531,7 +2557,7 @@ void Dbtc::execTCKEYREQ(Signal* signal) regApiPtr->m_exec_flag |= TexecFlag; switch (regApiPtr->apiConnectstate) { case CS_CONNECTED:{ - if (TstartFlag == 1 && getAllowStartTransaction() == true){ + if (TstartFlag == 1 && getAllowStartTransaction(sendersNodeId) == true){ //--------------------------------------------------------------------- // Initialise API connect record if transaction is started. //--------------------------------------------------------------------- @@ -2539,7 +2565,7 @@ void Dbtc::execTCKEYREQ(Signal* signal) initApiConnectRec(signal, regApiPtr); regApiPtr->m_exec_flag = TexecFlag; } else { - if(getAllowStartTransaction() == true){ + if(getAllowStartTransaction(sendersNodeId) == true){ /*------------------------------------------------------------------ * WE EXPECTED A START TRANSACTION. SINCE NO OPERATIONS HAVE BEEN * RECEIVED WE INDICATE THIS BY SETTING FIRST_TC_CONNECT TO RNIL TO @@ -2549,9 +2575,9 @@ void Dbtc::execTCKEYREQ(Signal* signal) return; } else { /** - * getAllowStartTransaction() == false + * getAllowStartTransaction(sendersNodeId) == false */ - TCKEY_abort(signal, 57); + TCKEY_abort(signal, TexecFlag ? 60 : 57); return; }//if } @@ -6154,9 +6180,11 @@ and otherwise we spread it out 310 ms. void Dbtc::timeOutLoopStartLab(Signal* signal, Uint32 api_con_ptr) { Uint32 end_ptr, time_passed, time_out_value, mask_value; + Uint32 old_mask_value= 0; const Uint32 api_con_sz= capiConnectFilesize; const Uint32 tc_timer= ctcTimer; const Uint32 time_out_param= ctimeOutValue; + const Uint32 old_time_out_param= c_abortRec.oldTimeOutValue; ctimeOutCheckHeartbeat = tc_timer; @@ -6177,11 +6205,39 @@ void Dbtc::timeOutLoopStartLab(Signal* signal, Uint32 api_con_ptr) jam(); mask_value= 31; } + if (time_out_param != old_time_out_param && + getNodeState().getSingleUserMode()) + { + // abort during single user mode, use old_mask_value as flag + // and calculate value to be used for connections with allowed api + if (old_time_out_param > 300) { + jam(); + old_mask_value= 63; + } else if (old_time_out_param < 30) { + jam(); + old_mask_value= 7; + } else { + jam(); + old_mask_value= 31; + } + } for ( ; api_con_ptr < end_ptr; api_con_ptr++) { Uint32 api_timer= getApiConTimer(api_con_ptr); jam(); if (api_timer != 0) { time_out_value= time_out_param + (api_con_ptr & mask_value); + if (unlikely(old_mask_value)) // abort during single user mode + { + apiConnectptr.i = api_con_ptr; + ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord); + if (getNodeState().getSingleUserApi() == + refToNode(apiConnectptr.p->ndbapiBlockref)) + { + // api allowed during single user, use original timeout + time_out_value= + old_time_out_param + (api_con_ptr & old_mask_value); + } + } time_passed= tc_timer - api_timer; if (time_passed > time_out_value) { @@ -6798,6 +6854,33 @@ void Dbtc::timeOutFoundFragLab(Signal* signal, UintR TscanConPtr) c_scan_frag_pool.getPtr(ptr, TscanConPtr); DEBUG(TscanConPtr << " timeOutFoundFragLab: scanFragState = "<< ptr.p->scanFragState); + const Uint32 time_out_param= ctimeOutValue; + const Uint32 old_time_out_param= c_abortRec.oldTimeOutValue; + + if (unlikely(time_out_param != old_time_out_param && + getNodeState().getSingleUserMode())) + { + jam(); + ScanRecordPtr scanptr; + scanptr.i = ptr.p->scanRec; + ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord); + ApiConnectRecordPtr TlocalApiConnectptr; + TlocalApiConnectptr.i = scanptr.p->scanApiRec; + ptrCheckGuard(TlocalApiConnectptr, capiConnectFilesize, apiConnectRecord); + + if (refToNode(TlocalApiConnectptr.p->ndbapiBlockref) == + getNodeState().getSingleUserApi()) + { + jam(); + Uint32 val = ctcTimer - ptr.p->scanFragTimer; + if (val <= old_time_out_param) + { + jam(); + goto next; + } + } + } + /*-------------------------------------------------------------------------*/ // The scan fragment has expired its timeout. Check its state to decide // what to do. @@ -6859,6 +6942,7 @@ void Dbtc::timeOutFoundFragLab(Signal* signal, UintR TscanConPtr) break; }//switch +next: signal->theData[0] = TcContinueB::ZCONTINUE_TIME_OUT_FRAG_CONTROL; signal->theData[1] = TscanConPtr + 1; sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB); @@ -8693,6 +8777,14 @@ void Dbtc::execSCAN_TABREQ(Signal* signal) } } + if (getNodeState().startLevel == NodeState::SL_SINGLEUSER && + getNodeState().getSingleUserApi() != + refToNode(apiConnectptr.p->ndbapiBlockref)) + { + errCode = ZCLUSTER_IN_SINGLEUSER_MODE; + goto SCAN_TAB_error; + } + seizeTcConnect(signal); tcConnectptr.p->apiConnect = apiConnectptr.i; tcConnectptr.p->tcConnectstate = OS_WAIT_SCAN; @@ -11012,7 +11104,7 @@ void Dbtc::execABORT_ALL_REQ(Signal* signal) const Uint32 senderData = req->senderData; const BlockReference senderRef = req->senderRef; - if(getAllowStartTransaction() == true && !getNodeState().getSingleUserMode()){ + if(getAllowStartTransaction(refToNode(senderRef)) == true && !getNodeState().getSingleUserMode()){ jam(); ref->senderData = senderData; @@ -11440,6 +11532,17 @@ void Dbtc::execTCINDXREQ(Signal* signal) regApiPtr->transid[1] = tcIndxReq->transId2; }//if + if (getNodeState().startLevel == NodeState::SL_SINGLEUSER && + getNodeState().getSingleUserApi() != + refToNode(regApiPtr->ndbapiBlockref)) + { + terrorCode = ZCLUSTER_IN_SINGLEUSER_MODE; + regApiPtr->m_exec_flag |= TcKeyReq::getExecuteFlag(tcIndxRequestInfo); + apiConnectptr = transPtr; + abortErrorLab(signal); + return; + } + if (ERROR_INSERTED(8036) || !seizeIndexOperation(regApiPtr, indexOpPtr)) { jam(); // Failed to allocate index operation diff --git a/storage/ndb/src/ndbapi/ClusterMgr.cpp b/storage/ndb/src/ndbapi/ClusterMgr.cpp index 2a794f69ecb..52c95df6d15 100644 --- a/storage/ndb/src/ndbapi/ClusterMgr.cpp +++ b/storage/ndb/src/ndbapi/ClusterMgr.cpp @@ -389,7 +389,7 @@ ClusterMgr::execAPI_REGCONF(const Uint32 * theData){ node.m_state = apiRegConf->nodeState; if (node.compatible && (node.m_state.startLevel == NodeState::SL_STARTED || - node.m_state.startLevel == NodeState::SL_SINGLEUSER)){ + node.m_state.getSingleUserMode())){ set_node_alive(node, true); } else { set_node_alive(node, false); diff --git a/storage/ndb/src/ndbapi/Ndb.cpp b/storage/ndb/src/ndbapi/Ndb.cpp index e90dfbfa959..495b848645f 100644 --- a/storage/ndb/src/ndbapi/Ndb.cpp +++ b/storage/ndb/src/ndbapi/Ndb.cpp @@ -58,6 +58,8 @@ NdbTransaction* Ndb::doConnect(Uint32 tConNode) // We have connections now to the desired node. Return //**************************************************************************** DBUG_RETURN(getConnectedNdbTransaction(tConNode)); + } else if (TretCode < 0) { + DBUG_RETURN(NULL); } else if (TretCode != 0) { tAnyAlive = 1; }//if @@ -81,6 +83,8 @@ NdbTransaction* Ndb::doConnect(Uint32 tConNode) // We have connections now to the desired node. Return //**************************************************************************** DBUG_RETURN(getConnectedNdbTransaction(tNode)); + } else if (TretCode < 0) { + DBUG_RETURN(NULL); } else if (TretCode != 0) { tAnyAlive= 1; }//if @@ -109,6 +113,8 @@ NdbTransaction* Ndb::doConnect(Uint32 tConNode) // We have connections now to the desired node. Return //**************************************************************************** DBUG_RETURN(getConnectedNdbTransaction(tNode)); + } else if (TretCode < 0) { + DBUG_RETURN(NULL); } else if (TretCode != 0) { tAnyAlive= 1; }//if @@ -195,6 +201,11 @@ Ndb::NDB_connect(Uint32 tNode) DBUG_PRINT("info", ("unsuccessful connect tReturnCode %d, tNdbCon->Status() %d", tReturnCode, tNdbCon->Status())); + if (theError.code == 299) + { + // single user mode so no need to retry with other node + DBUG_RETURN(-1); + } DBUG_RETURN(3); }//if }//Ndb::NDB_connect() diff --git a/storage/ndb/src/ndbapi/NdbRecAttr.cpp b/storage/ndb/src/ndbapi/NdbRecAttr.cpp index 188e718d968..0bd0cdf8572 100644 --- a/storage/ndb/src/ndbapi/NdbRecAttr.cpp +++ b/storage/ndb/src/ndbapi/NdbRecAttr.cpp @@ -138,8 +138,24 @@ NdbRecAttr::receive_data(const Uint32 * data, Uint32 sz) return false; } +NdbRecordPrintFormat::NdbRecordPrintFormat() +{ + fields_terminated_by= ";"; + start_array_enclosure= "["; + end_array_enclosure= "]"; + fields_enclosed_by= ""; + fields_optionally_enclosed_by= "\""; + lines_terminated_by= "\n"; + hex_prefix= "H'"; + null_string= "[NULL]"; + hex_format= 0; +} +NdbRecordPrintFormat::~NdbRecordPrintFormat() {} +static const NdbRecordPrintFormat default_print_format; + static void -ndbrecattr_print_string(NdbOut& out, const char *type, +ndbrecattr_print_string(NdbOut& out, const NdbRecordPrintFormat &f, + const char *type, bool is_binary, const char *aref, unsigned sz) { const unsigned char* ref = (const unsigned char*)aref; @@ -148,6 +164,25 @@ ndbrecattr_print_string(NdbOut& out, const char *type, for (i=sz-1; i >= 0; i--) if (ref[i] == 0) sz--; else break; + if (!is_binary) + { + // trailing spaces are not printed + for (i=sz-1; i >= 0; i--) + if (ref[i] == 32) sz--; + else break; + } + if (is_binary && f.hex_format) + { + if (sz == 0) + { + out.print("0x0"); + return; + } + out.print("0x"); + for (len = 0; len < (int)sz; len++) + out.print("%02X", (int)ref[len]); + return; + } if (sz == 0) return; // empty for (len=0; len < (int)sz && ref[i] != 0; len++) @@ -168,37 +203,68 @@ ndbrecattr_print_string(NdbOut& out, const char *type, for (i= len+1; ref[i] != 0; i++) out.print("%u]",len-i); assert((int)sz > i); - ndbrecattr_print_string(out,type,aref+i,sz-i); + ndbrecattr_print_string(out,f,type,is_binary,aref+i,sz-i); } } -NdbOut& operator<<(NdbOut& out, const NdbRecAttr &r) +NdbOut& +ndbrecattr_print_formatted(NdbOut& out, const NdbRecAttr &r, + const NdbRecordPrintFormat &f) { if (r.isNULL()) { - out << "[NULL]"; + out << f.null_string; return out; } const NdbDictionary::Column* c = r.getColumn(); uint length = c->getLength(); - if (length > 1) - out << "["; - - for (Uint32 j = 0; j < length; j++) { - if (j > 0) - out << " "; - + const char *fields_optionally_enclosed_by; + if (f.fields_enclosed_by[0] == '\0') + fields_optionally_enclosed_by= + f.fields_optionally_enclosed_by; + else + fields_optionally_enclosed_by= ""; + out << f.fields_enclosed_by; + Uint32 j; switch(r.getType()){ case NdbDictionary::Column::Bigunsigned: out << r.u_64_value(); break; case NdbDictionary::Column::Bit: - out << hex << "H'" << r.u_32_value() << dec; + out << f.hex_prefix << "0x"; + if (length < 33) + { + out.print("%X", r.u_32_value()); + } + else if (length < 65) + { + out.print("%llX", r.u_64_value()); + } + else + { + const unsigned char *buf = (unsigned char *)r.aRef(); + int k = 4*((length+31)/32); + while (k > 0 && (*(buf + --k) == 0)); + do + { + out.print("%X", (Uint32)*(buf + k--)); + } + while (k >= 0); + } break; case NdbDictionary::Column::Unsigned: - out << *((Uint32*)r.aRef() + j); + if (length > 1) + out << f.start_array_enclosure; + out << *(Uint32*)r.aRef(); + for (j = 1; j < length; j++) + out << " " << *((Uint32*)r.aRef() + j); + if (length > 1) + out << f.end_array_enclosure; + break; + case NdbDictionary::Column::Mediumunsigned: + out << r.u_medium_value(); break; case NdbDictionary::Column::Smallunsigned: out << r.u_short_value(); @@ -212,6 +278,9 @@ NdbOut& operator<<(NdbOut& out, const NdbRecAttr &r) case NdbDictionary::Column::Int: out << r.int32_value(); break; + case NdbDictionary::Column::Mediumint: + out << r.medium_value(); + break; case NdbDictionary::Column::Smallint: out << r.short_value(); break; @@ -219,25 +288,37 @@ NdbOut& operator<<(NdbOut& out, const NdbRecAttr &r) out << (int) r.char_value(); break; case NdbDictionary::Column::Binary: + if (!f.hex_format) + out << fields_optionally_enclosed_by; j = r.get_size_in_bytes(); - ndbrecattr_print_string(out,"Binary", r.aRef(), j); + ndbrecattr_print_string(out,f,"Binary", true, r.aRef(), j); + if (!f.hex_format) + out << fields_optionally_enclosed_by; break; case NdbDictionary::Column::Char: + out << fields_optionally_enclosed_by; j = r.get_size_in_bytes(); - ndbrecattr_print_string(out,"Char", r.aRef(), j); + ndbrecattr_print_string(out,f,"Char", false, r.aRef(), j); + out << fields_optionally_enclosed_by; break; case NdbDictionary::Column::Varchar: { + out << fields_optionally_enclosed_by; unsigned len = *(const unsigned char*)r.aRef(); - ndbrecattr_print_string(out,"Varchar", r.aRef()+1,len); + ndbrecattr_print_string(out,f,"Varchar", false, r.aRef()+1,len); j = length; + out << fields_optionally_enclosed_by; } break; case NdbDictionary::Column::Varbinary: { + if (!f.hex_format) + out << fields_optionally_enclosed_by; unsigned len = *(const unsigned char*)r.aRef(); - ndbrecattr_print_string(out,"Varbinary", r.aRef()+1,len); + ndbrecattr_print_string(out,f,"Varbinary", true, r.aRef()+1,len); j = length; + if (!f.hex_format) + out << fields_optionally_enclosed_by; } break; case NdbDictionary::Column::Float: @@ -366,16 +447,26 @@ NdbOut& operator<<(NdbOut& out, const NdbRecAttr &r) break; case NdbDictionary::Column::Longvarchar: { + out << fields_optionally_enclosed_by; unsigned len = uint2korr(r.aRef()); - ndbrecattr_print_string(out,"Longvarchar", r.aRef()+2,len); + ndbrecattr_print_string(out,f,"Longvarchar", false, r.aRef()+2,len); j = length; + out << fields_optionally_enclosed_by; + } + break; + case NdbDictionary::Column::Longvarbinary: + { + if (!f.hex_format) + out << fields_optionally_enclosed_by; + unsigned len = uint2korr(r.aRef()); + ndbrecattr_print_string(out,f,"Longvarbinary", true, r.aRef()+2,len); + j = length; + if (!f.hex_format) + out << fields_optionally_enclosed_by; } break; case NdbDictionary::Column::Undefined: - case NdbDictionary::Column::Mediumint: - case NdbDictionary::Column::Mediumunsigned: - case NdbDictionary::Column::Longvarbinary: unknown: //default: /* no print functions for the rest, just print type */ out << (int) r.getType(); @@ -384,16 +475,17 @@ NdbOut& operator<<(NdbOut& out, const NdbRecAttr &r) out << " " << j << " times"; break; } - } - - if (length > 1) - { - out << "]"; + out << f.fields_enclosed_by; } return out; } +NdbOut& operator<<(NdbOut& out, const NdbRecAttr &r) +{ + return ndbrecattr_print_formatted(out, r, default_print_format); +} + Int64 NdbRecAttr::int64_value() const { diff --git a/storage/ndb/src/ndbapi/TransporterFacade.hpp b/storage/ndb/src/ndbapi/TransporterFacade.hpp index d19974f8999..23fea8792f7 100644 --- a/storage/ndb/src/ndbapi/TransporterFacade.hpp +++ b/storage/ndb/src/ndbapi/TransporterFacade.hpp @@ -365,7 +365,8 @@ inline bool TransporterFacade::get_node_stopping(NodeId n) const { const ClusterMgr::Node & node = theClusterMgr->getNodeInfo(n); - return ((node.m_state.startLevel == NodeState::SL_STOPPING_1) || + return (!node.m_state.getSingleUserMode() && + (node.m_state.startLevel == NodeState::SL_STOPPING_1) || (node.m_state.startLevel == NodeState::SL_STOPPING_2)); } @@ -376,16 +377,9 @@ TransporterFacade::getIsNodeSendable(NodeId n) const { const Uint32 startLevel = node.m_state.startLevel; if (node.m_info.m_type == NodeInfo::DB) { - if(node.m_state.singleUserMode && - ownId() == node.m_state.singleUserApi) { - return (node.compatible && - (node.m_state.startLevel == NodeState::SL_STOPPING_1 || - node.m_state.startLevel == NodeState::SL_STARTED || - node.m_state.startLevel == NodeState::SL_SINGLEUSER)); - } - else - return node.compatible && (startLevel == NodeState::SL_STARTED || - startLevel == NodeState::SL_STOPPING_1); + return node.compatible && (startLevel == NodeState::SL_STARTED || + startLevel == NodeState::SL_STOPPING_1 || + node.m_state.getSingleUserMode()); } else { ndbout_c("TransporterFacade::getIsNodeSendable: Illegal node type: " "%d of node: %d", diff --git a/storage/ndb/tools/restore/Restore.cpp b/storage/ndb/tools/restore/Restore.cpp index 3d466384782..8b61c1e7055 100644 --- a/storage/ndb/tools/restore/Restore.cpp +++ b/storage/ndb/tools/restore/Restore.cpp @@ -27,6 +27,7 @@ #include #include "../../../../sql/ha_ndbcluster_tables.h" +extern NdbRecordPrintFormat g_ndbrecord_print_format; Uint16 Twiddle16(Uint16 in); // Byte shift 16-bit data Uint32 Twiddle32(Uint32 in); // Byte shift 32-bit data @@ -298,6 +299,7 @@ RestoreMetaData::markSysTables() Uint32 i; for (i = 0; i < getNoOfTables(); i++) { TableS* table = allTables[i]; + table->m_local_id = i; const char* tableName = table->getTableName(); if ( // XXX should use type strcmp(tableName, "SYSTAB_0") == 0 || @@ -313,6 +315,7 @@ RestoreMetaData::markSysTables() strcmp(tableName, "cluster/def/" OLD_NDB_APPLY_TABLE) == 0 || strcmp(tableName, NDB_REP_DB "/def/" NDB_APPLY_TABLE) == 0 || strcmp(tableName, NDB_REP_DB "/def/" NDB_SCHEMA_TABLE)== 0 ) + table->isSysTable = true; } for (i = 0; i < getNoOfTables(); i++) { @@ -330,6 +333,7 @@ RestoreMetaData::markSysTables() if (table->getTableId() == (Uint32) id1) { if (table->isSysTable) blobTable->isSysTable = true; + blobTable->m_main_table = table; break; } } @@ -427,6 +431,7 @@ TableS::TableS(Uint32 version, NdbTableImpl* tableImpl) m_noOfRecords= 0; backupVersion = version; isSysTable = false; + m_main_table = NULL; for (int i = 0; i < tableImpl->getNoOfColumns(); i++) createAttr(tableImpl->getColumn(i)); @@ -896,6 +901,7 @@ bool RestoreDataIterator::readFragmentHeader(int & ret, Uint32 *fragmentId) return false; } + info.setLevel(254); info << "_____________________________________________________" << endl << "Processing data in table: " << m_currentTable->getTableName() << "(" << Header.TableId << ") fragment " @@ -1153,14 +1159,14 @@ operator<<(NdbOut& ndbout, const AttributeS& attr){ if (data.null) { - ndbout << ""; + ndbout << g_ndbrecord_print_format.null_string; return ndbout; } NdbRecAttr tmprec(0); - tmprec.setup(desc.m_column, (char *)data.void_value); + tmprec.setup(desc.m_column, 0); tmprec.receive_data((Uint32*)data.void_value, data.size); - ndbout << tmprec; + ndbrecattr_print_formatted(ndbout, tmprec, g_ndbrecord_print_format); return ndbout; } @@ -1169,17 +1175,15 @@ operator<<(NdbOut& ndbout, const AttributeS& attr){ NdbOut& operator<<(NdbOut& ndbout, const TupleS& tuple) { - ndbout << tuple.getTable()->getTableName() << "; "; for (int i = 0; i < tuple.getNoOfAttributes(); i++) { + if (i > 0) + ndbout << g_ndbrecord_print_format.fields_terminated_by; AttributeData * attr_data = tuple.getData(i); const AttributeDesc * attr_desc = tuple.getDesc(i); const AttributeS attr = {attr_desc, *attr_data}; debug << i << " " << attr_desc->m_column->getName(); ndbout << attr; - - if (i != (tuple.getNoOfAttributes() - 1)) - ndbout << delimiter << " "; } // for return ndbout; } diff --git a/storage/ndb/tools/restore/Restore.hpp b/storage/ndb/tools/restore/Restore.hpp index 74834fe0abc..406899b2b4d 100644 --- a/storage/ndb/tools/restore/Restore.hpp +++ b/storage/ndb/tools/restore/Restore.hpp @@ -25,8 +25,6 @@ #include #include -#define delimiter ";" - const int FileNameLenC = 256; const int TableNameLenC = 256; const int AttrNameLenC = 256; @@ -142,6 +140,8 @@ class TableS { Uint64 m_max_auto_val; bool isSysTable; + TableS *m_main_table; + Uint32 m_local_id; Uint64 m_noOfRecords; Vector m_fragmentInfo; @@ -156,6 +156,9 @@ public: Uint32 getTableId() const { return m_dictTable->getTableId(); } + Uint32 getLocalId() const { + return m_local_id; + } Uint32 getNoOfRecords() const { return m_noOfRecords; } @@ -239,6 +242,10 @@ public: return isSysTable; } + const TableS *getMainTable() const { + return m_main_table; + } + TableS& operator=(TableS& org) ; }; // TableS; diff --git a/storage/ndb/tools/restore/consumer_printer.cpp b/storage/ndb/tools/restore/consumer_printer.cpp index dabd77f7358..721e0332381 100644 --- a/storage/ndb/tools/restore/consumer_printer.cpp +++ b/storage/ndb/tools/restore/consumer_printer.cpp @@ -14,6 +14,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "consumer_printer.hpp" +extern FilteredNdbOut info; +extern NdbRecordPrintFormat g_ndbrecord_print_format; +extern const char *tab_path; bool BackupPrinter::table(const TableS & tab) @@ -21,7 +24,8 @@ BackupPrinter::table(const TableS & tab) if (m_print || m_print_meta) { m_ndbout << tab; - ndbout_c("Successfully printed table: %s", tab.m_dictTable->getName()); + info.setLevel(254); + info << "Successfully printed table: ", tab.m_dictTable->getName(); } return true; } @@ -31,7 +35,14 @@ BackupPrinter::tuple(const TupleS & tup, Uint32 fragId) { m_dataCount++; if (m_print || m_print_data) - m_ndbout << tup << endl; + { + if (m_ndbout.m_out == info.m_out) + { + info.setLevel(254); + info << tup.getTable()->getTableName() << "; "; + } + m_ndbout << tup << g_ndbrecord_print_format.lines_terminated_by; + } } void @@ -47,9 +58,10 @@ BackupPrinter::endOfLogEntrys() { if (m_print || m_print_log) { - ndbout << "Printed " << m_dataCount << " tuples and " - << m_logCount << " log entries" - << " to stdout." << endl; + info.setLevel(254); + info << "Printed " << m_dataCount << " tuples and " + << m_logCount << " log entries" + << " to stdout." << endl; } } bool diff --git a/storage/ndb/tools/restore/consumer_restore.cpp b/storage/ndb/tools/restore/consumer_restore.cpp index 03cf3e6ddb7..88bcbc399aa 100644 --- a/storage/ndb/tools/restore/consumer_restore.cpp +++ b/storage/ndb/tools/restore/consumer_restore.cpp @@ -619,6 +619,7 @@ BackupRestore::update_apply_status(const RestoreMetaData &metaData) return true; bool result= false; + unsigned apply_table_format= 0; m_ndb->setDatabaseName(NDB_REP_DB); m_ndb->setSchemaName("def"); @@ -631,8 +632,33 @@ BackupRestore::update_apply_status(const RestoreMetaData &metaData) << dict->getNdbError() << endl; return false; } + if + (ndbtab->getColumn(0)->getType() == NdbDictionary::Column::Unsigned && + ndbtab->getColumn(1)->getType() == NdbDictionary::Column::Bigunsigned) + { + if (ndbtab->getNoOfColumns() == 2) + { + apply_table_format= 1; + } + else if + (ndbtab->getColumn(2)->getType() == NdbDictionary::Column::Varchar && + ndbtab->getColumn(3)->getType() == NdbDictionary::Column::Bigunsigned && + ndbtab->getColumn(4)->getType() == NdbDictionary::Column::Bigunsigned) + { + apply_table_format= 2; + } + } + if (apply_table_format == 0) + { + err << Ndb_apply_table << " has wrong format\n"; + return false; + } + Uint32 server_id= 0; Uint64 epoch= metaData.getStopGCP(); + Uint64 zero= 0; + char empty_string[1]; + empty_string[0]= 0; NdbTransaction * trans= m_ndb->startTransaction(); if (!trans) { @@ -655,6 +681,15 @@ BackupRestore::update_apply_status(const RestoreMetaData &metaData) << op->getNdbError() << endl; goto err; } + if ((apply_table_format == 2) && + (op->setValue(2u, (const char *)&empty_string, 1) || + op->setValue(3u, (const char *)&zero, sizeof(zero)) || + op->setValue(4u, (const char *)&zero, sizeof(zero)))) + { + err << Ndb_apply_table << ": " + << op->getNdbError() << endl; + goto err; + } if (trans->execute(NdbTransaction::Commit)) { err << Ndb_apply_table << ": " diff --git a/storage/ndb/tools/restore/restore_main.cpp b/storage/ndb/tools/restore/restore_main.cpp index 4734e9f609d..88511880480 100644 --- a/storage/ndb/tools/restore/restore_main.cpp +++ b/storage/ndb/tools/restore/restore_main.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include "consumer_restore.hpp" @@ -34,14 +35,24 @@ static int ga_nParallelism = 128; static int ga_backupId = 0; static bool ga_dont_ignore_systab_0 = false; static Vector g_consumers; +static BackupPrinter* g_printer = NULL; -static const char* ga_backupPath = "." DIR_SEPARATOR; +static const char* default_backupPath = "." DIR_SEPARATOR; +static const char* ga_backupPath = default_backupPath; static const char *opt_nodegroup_map_str= 0; static unsigned opt_nodegroup_map_len= 0; static NODE_GROUP_MAP opt_nodegroup_map[MAX_NODE_GROUP_MAPS]; #define OPT_NDB_NODEGROUP_MAP 'z' +const char *opt_ndb_database= NULL; +const char *opt_ndb_table= NULL; +unsigned int opt_verbose; +unsigned int opt_hex_format; +Vector g_databases; +Vector g_tables; +NdbRecordPrintFormat g_ndbrecord_print_format; + NDB_STD_OPTS_VARS; /** @@ -61,6 +72,28 @@ BaseString g_options("ndb_restore"); const char *load_default_groups[]= { "mysql_cluster","ndb_restore",0 }; +enum ndb_restore_options { + OPT_PRINT= NDB_STD_OPTIONS_LAST, + OPT_PRINT_DATA, + OPT_PRINT_LOG, + OPT_PRINT_META, + OPT_BACKUP_PATH, + OPT_HEX_FORMAT, + OPT_FIELDS_ENCLOSED_BY, + OPT_FIELDS_TERMINATED_BY, + OPT_FIELDS_OPTIONALLY_ENCLOSED_BY, + OPT_LINES_TERMINATED_BY, + OPT_APPEND, + OPT_VERBOSE +}; +static const char *opt_fields_enclosed_by= NULL; +static const char *opt_fields_terminated_by= NULL; +static const char *opt_fields_optionally_enclosed_by= NULL; +static const char *opt_lines_terminated_by= NULL; + +static const char *tab_path= NULL; +static int opt_append; + static struct my_option my_long_options[] = { NDB_STD_OPTS("ndb_restore"), @@ -96,19 +129,19 @@ static struct my_option my_long_options[] = "(parallelism can be 1 to 1024)", (gptr*) &ga_nParallelism, (gptr*) &ga_nParallelism, 0, GET_INT, REQUIRED_ARG, 128, 1, 1024, 0, 1, 0 }, - { "print", 256, "Print data and log to stdout", + { "print", OPT_PRINT, "Print data and log to stdout", (gptr*) &_print, (gptr*) &_print, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, - { "print_data", 257, "Print data to stdout", + { "print_data", OPT_PRINT_DATA, "Print data to stdout", (gptr*) &_print_data, (gptr*) &_print_data, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, - { "print_meta", 258, "Print meta data to stdout", + { "print_meta", OPT_PRINT_META, "Print meta data to stdout", (gptr*) &_print_meta, (gptr*) &_print_meta, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, - { "print_log", 259, "Print log to stdout", + { "print_log", OPT_PRINT_LOG, "Print log to stdout", (gptr*) &_print_log, (gptr*) &_print_log, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, - { "backup_path", 260, "Path to backup files", + { "backup_path", OPT_BACKUP_PATH, "Path to backup files", (gptr*) &ga_backupPath, (gptr*) &ga_backupPath, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, { "dont_ignore_systab_0", 'f', @@ -121,6 +154,37 @@ static struct my_option my_long_options[] = (gptr*) &opt_nodegroup_map_str, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + { "fields-enclosed-by", OPT_FIELDS_ENCLOSED_BY, + "Fields are enclosed by ...", + (gptr*) &opt_fields_enclosed_by, (gptr*) &opt_fields_enclosed_by, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + { "fields-terminated-by", OPT_FIELDS_TERMINATED_BY, + "Fields are terminated by ...", + (gptr*) &opt_fields_terminated_by, + (gptr*) &opt_fields_terminated_by, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + { "fields-optionally-enclosed-by", OPT_FIELDS_OPTIONALLY_ENCLOSED_BY, + "Fields are optionally enclosed by ...", + (gptr*) &opt_fields_optionally_enclosed_by, + (gptr*) &opt_fields_optionally_enclosed_by, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + { "hex", OPT_HEX_FORMAT, "print binary types in hex format", + (gptr*) &opt_hex_format, (gptr*) &opt_hex_format, 0, + GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, + { "tab", 'T', "Creates tab separated textfile for each table to " + "given path. (creates .txt files)", + (gptr*) &tab_path, (gptr*) &tab_path, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + { "append", OPT_APPEND, "for --tab append data to file", + (gptr*) &opt_append, (gptr*) &opt_append, 0, + GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, + { "lines-terminated-by", OPT_LINES_TERMINATED_BY, "", + (gptr*) &opt_lines_terminated_by, (gptr*) &opt_lines_terminated_by, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + { "verbose", OPT_VERBOSE, + "verbosity", + (gptr*) &opt_verbose, (gptr*) &opt_verbose, 0, + GET_INT, REQUIRED_ARG, 1, 0, 255, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; @@ -255,20 +319,25 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), #endif ndb_std_get_one_option(optid, opt, argument); switch (optid) { + case OPT_VERBOSE: + info.setThreshold(255-opt_verbose); + break; case 'n': if (ga_nodeId == 0) { - printf("Error in --nodeid,-n setting, see --help\n"); + err << "Error in --nodeid,-n setting, see --help"; exit(NDBT_ProgramExit(NDBT_WRONGARGS)); } + info.setLevel(254); info << "Nodeid = " << ga_nodeId << endl; break; case 'b': if (ga_backupId == 0) { - printf("Error in --backupid,-b setting, see --help\n"); + err << "Error in --backupid,-b setting, see --help"; exit(NDBT_ProgramExit(NDBT_WRONGARGS)); } + info.setLevel(254); info << "Backup Id = " << ga_backupId << endl; break; case OPT_NDB_NODEGROUP_MAP: @@ -277,6 +346,8 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), to nodegroup in new cluster. */ opt_nodegroup_map_len= 0; + + info.setLevel(254); info << "Analyse node group map" << endl; if (analyse_nodegroup_map(opt_nodegroup_map_str, &opt_nodegroup_map[0])) @@ -331,9 +402,9 @@ o verify nodegroup mapping exit(NDBT_ProgramExit(NDBT_WRONGARGS)); #endif - BackupPrinter* printer = new BackupPrinter(opt_nodegroup_map, - opt_nodegroup_map_len); - if (printer == NULL) + g_printer = new BackupPrinter(opt_nodegroup_map, + opt_nodegroup_map_len); + if (g_printer == NULL) return false; BackupRestore* restore = new BackupRestore(opt_nodegroup_map, @@ -341,7 +412,8 @@ o verify nodegroup mapping ga_nParallelism); if (restore == NULL) { - delete printer; + delete g_printer; + g_printer = NULL; return false; } @@ -349,22 +421,22 @@ o verify nodegroup mapping { ga_print = true; ga_restore = true; - printer->m_print = true; + g_printer->m_print = true; } if (_print_meta) { ga_print = true; - printer->m_print_meta = true; + g_printer->m_print_meta = true; } if (_print_data) { ga_print = true; - printer->m_print_data = true; + g_printer->m_print_data = true; } if (_print_log) { ga_print = true; - printer->m_print_log = true; + g_printer->m_print_log = true; } if (_restore_data) @@ -390,19 +462,64 @@ o verify nodegroup mapping } { - BackupConsumer * c = printer; + BackupConsumer * c = g_printer; g_consumers.push_back(c); } { BackupConsumer * c = restore; g_consumers.push_back(c); } - // Set backup file path - if (*pargv[0] != NULL) + for (;;) { - ga_backupPath = *pargv[0]; + int i= 0; + if (ga_backupPath == default_backupPath) + { + // Set backup file path + if ((*pargv)[i] == NULL) + break; + ga_backupPath = (*pargv)[i++]; + } + if ((*pargv)[i] == NULL) + break; + g_databases.push_back((*pargv)[i++]); + while ((*pargv)[i] != NULL) + { + g_tables.push_back((*pargv)[i++]); + } + break; } + info.setLevel(254); info << "backup path = " << ga_backupPath << endl; + if (g_databases.size() > 0) + { + info << "Restoring only from database " << g_databases[0].c_str() << endl; + if (g_tables.size() > 0) + info << "Restoring only tables:"; + for (unsigned i= 0; i < g_tables.size(); i++) + { + info << " " << g_tables[i].c_str(); + } + if (g_tables.size() > 0) + info << endl; + } + /* + the below formatting follows the formatting from mysqldump + do not change unless to adopt to changes in mysqldump + */ + g_ndbrecord_print_format.fields_enclosed_by= + opt_fields_enclosed_by ? opt_fields_enclosed_by : ""; + g_ndbrecord_print_format.fields_terminated_by= + opt_fields_terminated_by ? opt_fields_terminated_by : "\t"; + g_ndbrecord_print_format.fields_optionally_enclosed_by= + opt_fields_optionally_enclosed_by ? opt_fields_optionally_enclosed_by : ""; + g_ndbrecord_print_format.lines_terminated_by= + opt_lines_terminated_by ? opt_lines_terminated_by : "\n"; + if (g_ndbrecord_print_format.fields_optionally_enclosed_by[0] == '\0') + g_ndbrecord_print_format.null_string= "\\N"; + else + g_ndbrecord_print_format.null_string= ""; + g_ndbrecord_print_format.hex_prefix= ""; + g_ndbrecord_print_format.hex_format= opt_hex_format; return true; } @@ -427,6 +544,70 @@ checkSysTable(const RestoreMetaData& metaData, uint i) return checkSysTable(metaData[i]); } +static inline bool +isBlobTable(const TableS* table) +{ + return table->getMainTable() != NULL; +} + +static inline bool +isIndex(const TableS* table) +{ + const NdbTableImpl & tmptab = NdbTableImpl::getImpl(* table->m_dictTable); + return (int) tmptab.m_indexType != (int) NdbDictionary::Index::Undefined; +} + +static inline bool +checkDbAndTableName(const TableS* table) +{ + if (g_tables.size() == 0 && + g_databases.size() == 0) + return true; + if (g_databases.size() == 0) + g_databases.push_back("TEST_DB"); + + // Filter on the main table name for indexes and blobs + const char *table_name; + if (isBlobTable(table)) + table_name= table->getMainTable()->getTableName(); + else if (isIndex(table)) + table_name= + NdbTableImpl::getImpl(*table->m_dictTable).m_primaryTable.c_str(); + else + table_name= table->getTableName(); + + unsigned i; + for (i= 0; i < g_databases.size(); i++) + { + if (strncmp(table_name, g_databases[i].c_str(), + g_databases[i].length()) == 0 && + table_name[g_databases[i].length()] == '/') + { + // we have a match + if (g_databases.size() > 1 || g_tables.size() == 0) + return true; + break; + } + } + if (i == g_databases.size()) + return false; // no match found + + while (*table_name != '/') table_name++; + table_name++; + while (*table_name != '/') table_name++; + table_name++; + + for (i= 0; i < g_tables.size(); i++) + { + if (strcmp(table_name, g_tables[i].c_str()) == 0) + { + // we have a match + return true; + } + } + return false; +} + static void free_data_callback() { @@ -484,9 +665,10 @@ main(int argc, char** argv) const Uint32 version = tmp.NdbVersion; char buf[NDB_VERSION_STRING_BUF_SZ]; + info.setLevel(254); info << "Ndb version in backup files: " - << getVersionString(version, 0, buf, sizeof(buf)) << endl; - + << getVersionString(version, 0, buf, sizeof(buf)) << endl; + /** * check wheater we can restore the backup (right version). */ @@ -554,27 +736,59 @@ main(int argc, char** argv) exitHandler(NDBT_FAILED); } } - debug << "Restoring tables" << endl; + + Vector table_output(metaData.getNoOfTables()); + debug << "Restoring tables" << endl; for(i = 0; igetTableName(); + while (*table_name != '/') table_name++; + table_name++; + while (*table_name != '/') table_name++; + table_name++; + convert_dirname(tmp_path, tab_path, NullS); + res= my_fopen(fn_format(filename, table_name, tmp_path, ".txt", 4), + opt_append ? + O_WRONLY|O_APPEND|O_CREAT : + O_WRONLY|O_TRUNC|O_CREAT, + MYF(MY_WME)); + if (res == 0) + { + exitHandler(NDBT_FAILED); + } + FileOutputStream *f= new FileOutputStream(res); + table_output[i]= f; + } for(Uint32 j= 0; j < g_consumers.size(); j++) - if (!g_consumers[j]->table(* metaData[i])) + if (!g_consumers[j]->table(* table)) { err << "Restore: Failed to restore table: "; - err << metaData[i]->getTableName() << " ... Exiting " << endl; + err << table->getTableName() << " ... Exiting " << endl; exitHandler(NDBT_FAILED); } } else { for(Uint32 j= 0; j < g_consumers.size(); j++) - if (!g_consumers[j]->createSystable(* metaData[i])) + if (!g_consumers[j]->createSystable(* table)) { err << "Restore: Failed to restore system table: "; - err << metaData[i]->getTableName() << " ... Exiting " << endl; + err << table->getTableName() << " ... Exiting " << endl; exitHandler(NDBT_FAILED); } - } } debug << "Close tables" << endl; @@ -604,9 +818,15 @@ main(int argc, char** argv) const TupleS* tuple; while ((tuple = dataIter.getNextTuple(res= 1)) != 0) { - if (checkSysTable(tuple->getTable())) - for(Uint32 j= 0; j < g_consumers.size(); j++) - g_consumers[j]->tuple(* tuple, fragmentId); + const TableS* table = tuple->getTable(); + OutputStream *output = table_output[table->getLocalId()]; + if (!output) + continue; + OutputStream *tmp = ndbout.m_out; + ndbout.m_out = output; + for(Uint32 j= 0; j < g_consumers.size(); j++) + g_consumers[j]->tuple(* tuple, fragmentId); + ndbout.m_out = tmp; } // while (tuple != NULL); if (res < 0) @@ -648,9 +868,12 @@ main(int argc, char** argv) const LogEntry * logEntry = 0; while ((logEntry = logIter.getNextLogEntry(res= 0)) != 0) { - if (checkSysTable(logEntry->m_table)) - for(Uint32 j= 0; j < g_consumers.size(); j++) - g_consumers[j]->logEntry(* logEntry); + const TableS* table = logEntry->m_table; + OutputStream *output = table_output[table->getLocalId()]; + if (!output) + continue; + for(Uint32 j= 0; j < g_consumers.size(); j++) + g_consumers[j]->logEntry(* logEntry); } if (res < 0) { @@ -667,27 +890,27 @@ main(int argc, char** argv) { for(i = 0; ifinalize_table(* metaData[i])) - { - err << "Restore: Failed to finalize restore table: %s. "; - err << "Exiting... " << metaData[i]->getTableName() << endl; - exitHandler(NDBT_FAILED); - } - } + const TableS* table = metaData[i]; + OutputStream *output = table_output[table->getLocalId()]; + if (!output) + continue; + for(Uint32 j= 0; j < g_consumers.size(); j++) + if (!g_consumers[j]->finalize_table(*table)) + { + err << "Restore: Failed to finalize restore table: %s. "; + err << "Exiting... " << metaData[i]->getTableName() << endl; + exitHandler(NDBT_FAILED); + } } } } - if (ga_restore_epoch) { for (i= 0; i < g_consumers.size(); i++) if (!g_consumers[i]->update_apply_status(metaData)) { - err << "Restore: Failed to restore epoch" << endl; - return -1; + err << "Restore: Failed to restore epoch" << endl; + return -1; } } @@ -702,7 +925,23 @@ main(int argc, char** argv) } clearConsumers(); - return NDBT_ProgramExit(NDBT_OK); + + for(i = 0; i < metaData.getNoOfTables(); i++) + { + if (table_output[i] && + table_output[i] != ndbout.m_out) + { + my_fclose(((FileOutputStream *)table_output[i])->getFile(), MYF(MY_WME)); + delete table_output[i]; + table_output[i] = NULL; + } + } + + if (opt_verbose) + return NDBT_ProgramExit(NDBT_OK); + else + return 0; } // main template class Vector; +template class Vector;