Commit bd49cdd2 authored by tomas@poseidon.mysql.com's avatar tomas@poseidon.mysql.com

Merge poseidon.mysql.com:/home/tomas/mysql-5.0-telco-gca-ndb_restore

into  poseidon.mysql.com:/home/tomas/mysql-5.1-telco-gca-ndb_restore
parents f6845d14 a42d10a3
--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=
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 ndb;
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
);
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
<the_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
<the_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;
drop table t2;
drop table t3;
drop table t4;
-- 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 ndb;
# 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
);
--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
# clean up
drop table t1;
drop table t2;
drop table t3;
drop table t4;
......@@ -409,6 +409,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
......
......@@ -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, ...);
......
......@@ -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,56 @@ 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;
for (j = (length-1)/32 + 1; j > 0; j--)
if (*((Uint32*)r.aRef() + j - 1))
break;
if (j == 0)
{
out << "0x0";
break;
}
out << f.hex_prefix << "0x";
for (; j > 0; j--)
out.print("%X", *((Uint32*)r.aRef() + j - 1));
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::Smallunsigned:
out << r.u_short_value();
......@@ -219,25 +273,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 +432,28 @@ 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 +462,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
{
......
......@@ -27,6 +27,7 @@
#include <NdbAutoPtr.hpp>
#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 << "<NULL>";
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;
}
......
......@@ -25,8 +25,6 @@
#include <ndb_version.h>
#include <version.h>
static const char * delimiter = ";"; // Delimiter in file dump
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<FragmentInfo *> 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;
......
......@@ -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
......
......@@ -20,6 +20,7 @@
#include <NdbTCP.h>
#include <NdbMem.h>
#include <NdbOut.hpp>
#include <OutputStream.hpp>
#include <NDBT_ReturnCodes.h>
#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<class BackupConsumer *> 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<BaseString> g_databases;
Vector<BaseString> g_tables;
NdbRecordPrintFormat g_ndbrecord_print_format;
NDB_STD_OPTS_VARS;
/**
......@@ -61,6 +72,32 @@ 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
};
/*
the below formatting options follow the formatting from mysqldump
do not change unless to adopt to changes in mysqldump
*/
static const char *opt_fields_enclosed_by= "";
static const char *opt_fields_terminated_by= ";";
static const char *opt_fields_optionally_enclosed_by= "";
static const char *opt_lines_terminated_by= "\n";
static const char *tab_path= NULL;
static int opt_append;
static struct my_option my_long_options[] =
{
NDB_STD_OPTS("ndb_restore"),
......@@ -96,19 +133,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 +158,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 +323,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:
......@@ -331,9 +404,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)
BackupPrinter* 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 +414,8 @@ o verify nodegroup mapping
ga_nParallelism);
if (restore == NULL)
{
delete printer;
delete g_printer;
g_printer = NULL;
return false;
}
......@@ -349,22 +423,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 +464,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;
g_ndbrecord_print_format.fields_terminated_by=
opt_fields_terminated_by;
g_ndbrecord_print_format.fields_optionally_enclosed_by=
opt_fields_optionally_enclosed_by;
g_ndbrecord_print_format.lines_terminated_by=
opt_lines_terminated_by;
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 +546,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 +667,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,16 +738,49 @@ main(int argc, char** argv)
exitHandler(NDBT_FAILED);
}
}
debug << "Restoring tables" << endl;
Vector<OutputStream *> table_output(metaData.getNoOfTables());
debug << "Restoring tables" << endl;
for(i = 0; i<metaData.getNoOfTables(); i++)
{
if (checkSysTable(metaData, i))
const TableS *table= metaData[i];
table_output.push_back(NULL);
if (!checkDbAndTableName(table))
continue;
if (checkSysTable(table))
{
if (!tab_path || isBlobTable(table) || isIndex(table))
{
table_output[i]= ndbout.m_out;
}
else
{
FILE* res;
char filename[FN_REFLEN], tmp_path[FN_REFLEN];
const char *table_name;
table_name= table->getTableName();
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 {
......@@ -574,7 +791,6 @@ main(int argc, char** argv)
err << metaData[i]->getTableName() << " ... Exiting " << endl;
exitHandler(NDBT_FAILED);
}
}
}
debug << "Close tables" << endl;
......@@ -604,9 +820,15 @@ main(int argc, char** argv)
const TupleS* tuple;
while ((tuple = dataIter.getNextTuple(res= 1)) != 0)
{
if (checkSysTable(tuple->getTable()))
for(Uint32 i= 0; i < g_consumers.size(); i++)
g_consumers[i]->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 i= 0; i < g_consumers.size(); i++)
g_consumers[i]->tuple(* tuple, fragmentId);
ndbout.m_out = tmp;
} // while (tuple != NULL);
if (res < 0)
......@@ -648,9 +870,12 @@ main(int argc, char** argv)
const LogEntry * logEntry = 0;
while ((logEntry = logIter.getNextLogEntry(res= 0)) != 0)
{
if (checkSysTable(logEntry->m_table))
for(Uint32 i= 0; i < g_consumers.size(); i++)
g_consumers[i]->logEntry(* logEntry);
const TableS* table = logEntry->m_table;
OutputStream *output = table_output[table->getLocalId()];
if (!output)
continue;
for(Uint32 i= 0; i < g_consumers.size(); i++)
g_consumers[i]->logEntry(* logEntry);
}
if (res < 0)
{
......@@ -667,27 +892,27 @@ main(int argc, char** argv)
{
for(i = 0; i<metaData.getNoOfTables(); i++)
{
if (checkSysTable(metaData, i))
{
for(Uint32 j= 0; j < g_consumers.size(); j++)
if (!g_consumers[j]->finalize_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 +927,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<BackupConsumer*>;
template class Vector<OutputStream*>;
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment