=== modified file 'storage/ndb/tools/restore/restore_main.cpp' --- storage/ndb/tools/restore/restore_main.cpp 2008-09-19 06:45:00 +0000 +++ storage/ndb/tools/restore/restore_main.cpp 2008-12-07 20:51:08 +0000 @@ -55,6 +55,8 @@ unsigned int g_report_next; Vector g_databases; Vector g_tables; +Vector g_include_tables, g_exclude_tables; +Vector g_include_databases, g_exclude_databases; NdbRecordPrintFormat g_ndbrecord_print_format; unsigned int opt_no_binlog; @@ -93,7 +95,11 @@ OPT_APPEND, OPT_PROGRESS_FREQUENCY, OPT_NO_BINLOG, - OPT_VERBOSE + OPT_VERBOSE, + OPT_INCLUDE_TABLES, + OPT_EXCLUDE_TABLES, + OPT_INCLUDE_DATABASES, + OPT_EXCLUDE_DATABASES }; static const char *opt_fields_enclosed_by= NULL; static const char *opt_fields_terminated_by= NULL; @@ -102,6 +108,10 @@ static const char *tab_path= NULL; static int opt_append; +static const char *opt_exclude_tables= NULL; +static const char *opt_include_tables= NULL; +static const char *opt_exclude_databases= NULL; +static const char *opt_include_databases= NULL; static struct my_option my_long_options[] = { @@ -217,6 +227,23 @@ "verbosity", (uchar**) &opt_verbose, (uchar**) &opt_verbose, 0, GET_INT, REQUIRED_ARG, 1, 0, 255, 0, 0, 0 }, + { "include-databases", OPT_INCLUDE_DATABASES, + "Comma separated list of tables to restore. Example: db1,db3", + (uchar**) &opt_include_databases, (uchar**) &opt_include_databases, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + { "exclude-databases", OPT_EXCLUDE_DATABASES, + "Comma separated list of tables to not restore. Example: db1,db3", + (uchar**) &opt_exclude_databases, (uchar**) &opt_exclude_databases, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + { "include-tables", OPT_INCLUDE_TABLES, "Comma separated list of tables to " + "restore. Table name should include database name. Example: db1.t1,db3.t1", + (uchar**) &opt_include_tables, (uchar**) &opt_include_tables, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + { "exclude-tables", OPT_EXCLUDE_TABLES, "Comma separated list of tables to " + "not restore. Table name should include database name. " + "Example: db1.t1,db3.t1", + (uchar**) &opt_exclude_tables, (uchar**) &opt_exclude_tables, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; @@ -390,10 +417,67 @@ } return 0; } + +char* +ndb_table_name(const BaseString &table_name) +{ + // Make dbname.table1 into dbname/def/table1 + BaseString tblname(""); + Vector tmp; + + // Must contain a dot + if (table_name.indexOf('.') == -1) + return NULL; + table_name.split(tmp,"."); + // .. and only 1 dot + if (tmp.size() != 2) + return NULL; + tblname.append(tmp[0]); + tblname.append("/def/"); + tblname.append(tmp[1]); + return (char*)tblname.c_str(); +} + +void +process_table_list(const char* str, Vector &lst) +{ + // Process tables list like db1.t1,db2.t1 and exists when + // it finds problems. + int i; + char *tmp; + BaseString(str).split(lst,","); + for (i=0; i < lst.size(); i++) + { + tmp = ndb_table_name(lst[i]); + if (tmp == NULL) + { + info << "`" << lst[i] << "` is not a valid tablename!" << endl; + exit(NDBT_ProgramExit(NDBT_WRONGARGS)); + } + lst[i] = BaseString(tmp); + } +} + +char* +clean_table_name(const BaseString &table_name) +{ + // Make dbname/def/table1 into dbname.table1 + int idx; + BaseString tblname(table_name); + BaseString tmp(""); + + idx = tblname.indexOf('/'); + tmp = tblname.substr(0,idx); + tmp.append("."); + tmp.append(tblname.substr(idx+5,tblname.length())); + return (char*)tmp.c_str(); +} + bool readArguments(int *pargc, char*** pargv) { Uint32 i; + BaseString tmp; debug << "Load defaults" << endl; const char *load_default_groups[]= { "mysql_cluster","ndb_restore",0 }; @@ -537,11 +621,16 @@ } info.setLevel(254); info << "backup path = " << ga_backupPath << endl; + if (g_databases.size() > 0) { + info << "WARNING! Using depricated syntax for selective object restauration." << endl; + info << "Please use --include-*/--exclude-* options in future." << endl; info << "Restoring only from database " << g_databases[0].c_str() << endl; if (g_tables.size() > 0) - info << "Restoring only tables:"; + { + info << "Restoring tables:"; + } for (unsigned i= 0; i < g_tables.size(); i++) { info << " " << g_tables[i].c_str(); @@ -549,6 +638,53 @@ if (g_tables.size() > 0) info << endl; } + + if (opt_include_databases) + { + tmp = BaseString(opt_include_databases); + tmp.split(g_include_databases,","); + info << "Including databases: "; + for (i= 0; i < g_include_databases.size(); i++) + { + info << g_include_databases[i] << " "; + } + info << endl; + } + + if (opt_exclude_databases) + { + tmp = BaseString(opt_exclude_databases); + tmp.split(g_exclude_databases,","); + info << "Excluding databases: "; + for (i= 0; i < g_exclude_databases.size(); i++) + { + info << g_exclude_databases[i] << " "; + } + info << endl; + } + + if (opt_include_tables) + { + process_table_list(opt_include_tables, g_include_tables); + info << "Including tables: "; + for (i= 0; i < g_include_tables.size(); i++) + { + info << clean_table_name(g_include_tables[i]) << " "; + } + info << endl; + } + + if (opt_exclude_tables) + { + process_table_list(opt_exclude_tables, g_exclude_tables); + info << "Excluding tables: "; + for (i= 0; i < g_exclude_tables.size(); i++) + { + info << clean_table_name(g_exclude_tables[i]) << " "; + } + info << endl; + } + /* the below formatting follows the formatting from mysqldump do not change unless to adopt to changes in mysqldump @@ -605,11 +741,80 @@ } static inline bool +isInList(BaseString &needle, Vector &lst) +{ + int i= 0; + for (i= 0; i < lst.size(); i++) + { + if (strcmp(needle.c_str(), lst[i].c_str()) == 0) + return true; + } + return false; +} + +const char* +get_table_name(const TableS* table) +{ + 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(); + + return table_name; +} + +static inline bool +checkDoRestore(const TableS* table) +{ + int idx; + bool ret = true; + BaseString db, tbl; + + tbl = BaseString(get_table_name(table)); + idx = tbl.indexOf('/'); + db = tbl.substr(0, idx); + + if (g_exclude_databases.size() != 0) { + if (isInList(db, g_exclude_databases)) + ret = false; + } + if (g_include_databases.size() != 0) { + if (isInList(db, g_include_databases)) + ret = true; + else + ret = false; + } + + if (g_exclude_tables.size() != 0) { + if (isInList(tbl, g_exclude_tables)) + ret = false; + } + if (g_include_tables.size() != 0) { + if (isInList(tbl, g_include_tables)) + ret = true; + else + ret = false; + } + + return ret; +} + +static inline bool checkDbAndTableName(const TableS* table) { - if (g_tables.size() == 0 && - g_databases.size() == 0) + // If new options are given, ignore the old format + if (opt_include_tables || opt_exclude_tables || + opt_include_databases || opt_exclude_databases ) { + return (checkDoRestore(table)); + } + + if (g_tables.size() == 0 && g_databases.size() == 0) return true; + if (g_databases.size() == 0) g_databases.push_back("TEST_DB"); @@ -644,13 +849,11 @@ while (*table_name != '/') table_name++; table_name++; + // Check if table should be restored 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; }