mirror of
https://github.com/MariaDB/server.git
synced 2025-01-30 10:31:54 +01:00
Merge
This commit is contained in:
commit
efb077502d
16 changed files with 743 additions and 504 deletions
|
@ -55,7 +55,7 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \
|
||||||
ha_ndbcluster.h opt_range.h protocol.h \
|
ha_ndbcluster.h opt_range.h protocol.h \
|
||||||
sql_select.h structs.h table.h sql_udf.h hash_filo.h\
|
sql_select.h structs.h table.h sql_udf.h hash_filo.h\
|
||||||
lex.h lex_symbol.h sql_acl.h sql_crypt.h \
|
lex.h lex_symbol.h sql_acl.h sql_crypt.h \
|
||||||
log_event.h sql_repl.h slave.h \
|
log_event.h sql_repl.h slave.h rpl_filter.h \
|
||||||
stacktrace.h sql_sort.h sql_cache.h set_var.h \
|
stacktrace.h sql_sort.h sql_cache.h set_var.h \
|
||||||
spatial.h gstream.h client_settings.h tzfile.h \
|
spatial.h gstream.h client_settings.h tzfile.h \
|
||||||
tztime.h my_decimal.h\
|
tztime.h my_decimal.h\
|
||||||
|
@ -90,7 +90,8 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc \
|
||||||
sql_db.cc sql_table.cc sql_rename.cc sql_crypt.cc \
|
sql_db.cc sql_table.cc sql_rename.cc sql_crypt.cc \
|
||||||
sql_load.cc mf_iocache.cc field_conv.cc sql_show.cc \
|
sql_load.cc mf_iocache.cc field_conv.cc sql_show.cc \
|
||||||
sql_udf.cc sql_analyse.cc sql_analyse.h sql_cache.cc \
|
sql_udf.cc sql_analyse.cc sql_analyse.h sql_cache.cc \
|
||||||
slave.cc sql_repl.cc sql_union.cc sql_derived.cc \
|
slave.cc sql_repl.cc rpl_filter.cc \
|
||||||
|
sql_union.cc sql_derived.cc \
|
||||||
client.c sql_client.cc mini_client_errors.c pack.c\
|
client.c sql_client.cc mini_client_errors.c pack.c\
|
||||||
stacktrace.c repl_failsafe.h repl_failsafe.cc \
|
stacktrace.c repl_failsafe.h repl_failsafe.cc \
|
||||||
sql_olap.cc sql_view.cc \
|
sql_olap.cc sql_view.cc \
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
#include "mysql_priv.h"
|
#include "mysql_priv.h"
|
||||||
#include "sql_repl.h"
|
#include "sql_repl.h"
|
||||||
|
#include "rpl_filter.h"
|
||||||
|
|
||||||
#include <my_dir.h>
|
#include <my_dir.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
@ -1571,10 +1572,11 @@ bool MYSQL_LOG::write(Log_event *event_info)
|
||||||
binlog_[wild_]{do|ignore}_table?" (WL#1049)"
|
binlog_[wild_]{do|ignore}_table?" (WL#1049)"
|
||||||
*/
|
*/
|
||||||
if ((thd && !(thd->options & OPTION_BIN_LOG)) ||
|
if ((thd && !(thd->options & OPTION_BIN_LOG)) ||
|
||||||
(!db_ok(local_db, binlog_do_db, binlog_ignore_db)))
|
(!binlog_filter->db_ok(local_db)))
|
||||||
{
|
{
|
||||||
VOID(pthread_mutex_unlock(&LOCK_log));
|
VOID(pthread_mutex_unlock(&LOCK_log));
|
||||||
DBUG_PRINT("error",("!db_ok('%s')", local_db));
|
DBUG_PRINT("info",("db_ok('%s')==%d", local_db,
|
||||||
|
binlog_filter->db_ok(local_db)));
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
#endif /* HAVE_REPLICATION */
|
#endif /* HAVE_REPLICATION */
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#endif
|
#endif
|
||||||
#include "mysql_priv.h"
|
#include "mysql_priv.h"
|
||||||
#include "slave.h"
|
#include "slave.h"
|
||||||
|
#include "rpl_filter.h"
|
||||||
#include <my_dir.h>
|
#include <my_dir.h>
|
||||||
#endif /* MYSQL_CLIENT */
|
#endif /* MYSQL_CLIENT */
|
||||||
|
|
||||||
|
@ -1445,7 +1446,7 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli, const char *query
|
||||||
*/
|
*/
|
||||||
thd->catalog= (char*) catalog;
|
thd->catalog= (char*) catalog;
|
||||||
thd->db_length= db_len;
|
thd->db_length= db_len;
|
||||||
thd->db= (char*) rewrite_db(db, &thd->db_length);
|
thd->db= (char *) rpl_filter->get_rewrite_db(db, &thd->db_length);
|
||||||
thd->variables.auto_increment_increment= auto_increment_increment;
|
thd->variables.auto_increment_increment= auto_increment_increment;
|
||||||
thd->variables.auto_increment_offset= auto_increment_offset;
|
thd->variables.auto_increment_offset= auto_increment_offset;
|
||||||
|
|
||||||
|
@ -1464,7 +1465,7 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli, const char *query
|
||||||
|
|
||||||
clear_all_errors(thd, rli);
|
clear_all_errors(thd, rli);
|
||||||
|
|
||||||
if (db_ok(thd->db, replicate_do_db, replicate_ignore_db))
|
if (rpl_filter->db_ok(thd->db))
|
||||||
{
|
{
|
||||||
thd->set_time((time_t)when);
|
thd->set_time((time_t)when);
|
||||||
thd->query_length= q_len_arg;
|
thd->query_length= q_len_arg;
|
||||||
|
@ -2569,7 +2570,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
|
||||||
bool use_rli_only_for_errors)
|
bool use_rli_only_for_errors)
|
||||||
{
|
{
|
||||||
thd->db_length= db_len;
|
thd->db_length= db_len;
|
||||||
thd->db= (char*) rewrite_db(db, &thd->db_length);
|
thd->db= (char *) rpl_filter->get_rewrite_db(db, &thd->db_length);
|
||||||
DBUG_ASSERT(thd->query == 0);
|
DBUG_ASSERT(thd->query == 0);
|
||||||
thd->query_length= 0; // Should not be needed
|
thd->query_length= 0; // Should not be needed
|
||||||
thd->query_error= 0;
|
thd->query_error= 0;
|
||||||
|
@ -2598,7 +2599,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
|
||||||
al. Another way is do the filtering in the I/O thread (more efficient: no
|
al. Another way is do the filtering in the I/O thread (more efficient: no
|
||||||
disk writes at all).
|
disk writes at all).
|
||||||
*/
|
*/
|
||||||
if (db_ok(thd->db, replicate_do_db, replicate_ignore_db))
|
if (rpl_filter->db_ok(thd->db))
|
||||||
{
|
{
|
||||||
thd->set_time((time_t)when);
|
thd->set_time((time_t)when);
|
||||||
VOID(pthread_mutex_lock(&LOCK_thread_count));
|
VOID(pthread_mutex_lock(&LOCK_thread_count));
|
||||||
|
@ -2620,7 +2621,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
|
||||||
tables.updating= 1;
|
tables.updating= 1;
|
||||||
|
|
||||||
// the table will be opened in mysql_load
|
// the table will be opened in mysql_load
|
||||||
if (table_rules_on && !tables_ok(thd, &tables))
|
if (rpl_filter->is_on() && !rpl_filter->tables_ok(thd->db, &tables))
|
||||||
{
|
{
|
||||||
// TODO: this is a bug - this needs to be moved to the I/O thread
|
// TODO: this is a bug - this needs to be moved to the I/O thread
|
||||||
if (net)
|
if (net)
|
||||||
|
|
|
@ -1128,7 +1128,6 @@ extern KNOWN_DATE_TIME_FORMAT known_date_time_formats[];
|
||||||
extern String null_string;
|
extern String null_string;
|
||||||
extern HASH open_cache;
|
extern HASH open_cache;
|
||||||
extern TABLE *unused_tables;
|
extern TABLE *unused_tables;
|
||||||
extern I_List<i_string> binlog_do_db, binlog_ignore_db;
|
|
||||||
extern const char* any_db;
|
extern const char* any_db;
|
||||||
extern struct my_option my_long_options[];
|
extern struct my_option my_long_options[];
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include <my_dir.h>
|
#include <my_dir.h>
|
||||||
#include "slave.h"
|
#include "slave.h"
|
||||||
#include "sql_repl.h"
|
#include "sql_repl.h"
|
||||||
|
#include "rpl_filter.h"
|
||||||
#include "repl_failsafe.h"
|
#include "repl_failsafe.h"
|
||||||
#include "stacktrace.h"
|
#include "stacktrace.h"
|
||||||
#include "mysqld_suffix.h"
|
#include "mysqld_suffix.h"
|
||||||
|
@ -397,12 +398,10 @@ Le_creator le_creator;
|
||||||
FILE *bootstrap_file;
|
FILE *bootstrap_file;
|
||||||
int bootstrap_error;
|
int bootstrap_error;
|
||||||
|
|
||||||
I_List<i_string_pair> replicate_rewrite_db;
|
|
||||||
I_List<i_string> replicate_do_db, replicate_ignore_db;
|
|
||||||
// allow the user to tell us which db to replicate and which to ignore
|
|
||||||
I_List<i_string> binlog_do_db, binlog_ignore_db;
|
|
||||||
I_List<THD> threads,thread_cache;
|
I_List<THD> threads,thread_cache;
|
||||||
I_List<NAMED_LIST> key_caches;
|
I_List<NAMED_LIST> key_caches;
|
||||||
|
Rpl_filter* rpl_filter;
|
||||||
|
Rpl_filter* binlog_filter;
|
||||||
|
|
||||||
struct system_variables global_system_variables;
|
struct system_variables global_system_variables;
|
||||||
struct system_variables max_system_variables;
|
struct system_variables max_system_variables;
|
||||||
|
@ -1013,12 +1012,9 @@ void clean_up(bool print_message)
|
||||||
free_max_user_conn();
|
free_max_user_conn();
|
||||||
#ifdef HAVE_REPLICATION
|
#ifdef HAVE_REPLICATION
|
||||||
end_slave_list();
|
end_slave_list();
|
||||||
free_list(&replicate_do_db);
|
|
||||||
free_list(&replicate_ignore_db);
|
|
||||||
free_list(&binlog_do_db);
|
|
||||||
free_list(&binlog_ignore_db);
|
|
||||||
free_list(&replicate_rewrite_db);
|
|
||||||
#endif
|
#endif
|
||||||
|
delete binlog_filter;
|
||||||
|
delete rpl_filter;
|
||||||
#ifdef HAVE_OPENSSL
|
#ifdef HAVE_OPENSSL
|
||||||
if (ssl_acceptor_fd)
|
if (ssl_acceptor_fd)
|
||||||
my_free((gptr) ssl_acceptor_fd, MYF(MY_ALLOW_ZERO_PTR));
|
my_free((gptr) ssl_acceptor_fd, MYF(MY_ALLOW_ZERO_PTR));
|
||||||
|
@ -2970,9 +2966,16 @@ int win_main(int argc, char **argv)
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
|
||||||
DEBUGGER_OFF;
|
DEBUGGER_OFF;
|
||||||
|
|
||||||
|
rpl_filter= new Rpl_filter;
|
||||||
|
binlog_filter= new Rpl_filter;
|
||||||
|
if (!rpl_filter || !binlog_filter)
|
||||||
|
{
|
||||||
|
sql_perror("Could not allocate replication and binlog filters");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
MY_INIT(argv[0]); // init my_sys library & pthreads
|
MY_INIT(argv[0]); // init my_sys library & pthreads
|
||||||
|
|
||||||
#ifdef _CUSTOMSTARTUPCONFIG_
|
#ifdef _CUSTOMSTARTUPCONFIG_
|
||||||
|
@ -3309,7 +3312,6 @@ default_service_handling(char **argv,
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
|
||||||
/* When several instances are running on the same machine, we
|
/* When several instances are running on the same machine, we
|
||||||
need to have an unique named hEventShudown through the
|
need to have an unique named hEventShudown through the
|
||||||
application PID e.g.: MySQLShutdown1890; MySQLShutdown2342
|
application PID e.g.: MySQLShutdown1890; MySQLShutdown2342
|
||||||
|
@ -5882,13 +5884,6 @@ static void mysql_init_variables(void)
|
||||||
exit(1);
|
exit(1);
|
||||||
multi_keycache_init(); /* set key_cache_hash.default_value = dflt_key_cache */
|
multi_keycache_init(); /* set key_cache_hash.default_value = dflt_key_cache */
|
||||||
|
|
||||||
/* Initialize structures that is used when processing options */
|
|
||||||
replicate_rewrite_db.empty();
|
|
||||||
replicate_do_db.empty();
|
|
||||||
replicate_ignore_db.empty();
|
|
||||||
binlog_do_db.empty();
|
|
||||||
binlog_ignore_db.empty();
|
|
||||||
|
|
||||||
/* Set directory paths */
|
/* Set directory paths */
|
||||||
strmake(language, LANGUAGE, sizeof(language)-1);
|
strmake(language, LANGUAGE, sizeof(language)-1);
|
||||||
strmake(mysql_real_data_home, get_relative_path(DATADIR),
|
strmake(mysql_real_data_home, get_relative_path(DATADIR),
|
||||||
|
@ -6143,14 +6138,12 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
|
||||||
}
|
}
|
||||||
case (int)OPT_REPLICATE_IGNORE_DB:
|
case (int)OPT_REPLICATE_IGNORE_DB:
|
||||||
{
|
{
|
||||||
i_string *db = new i_string(argument);
|
rpl_filter->add_ignore_db(argument);
|
||||||
replicate_ignore_db.push_back(db);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (int)OPT_REPLICATE_DO_DB:
|
case (int)OPT_REPLICATE_DO_DB:
|
||||||
{
|
{
|
||||||
i_string *db = new i_string(argument);
|
rpl_filter->add_do_db(argument);
|
||||||
replicate_do_db.push_back(db);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (int)OPT_REPLICATE_REWRITE_DB:
|
case (int)OPT_REPLICATE_REWRITE_DB:
|
||||||
|
@ -6183,71 +6176,54 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
i_string_pair *db_pair = new i_string_pair(key, val);
|
rpl_filter->add_db_rewrite(key, val);
|
||||||
replicate_rewrite_db.push_back(db_pair);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case (int)OPT_BINLOG_IGNORE_DB:
|
case (int)OPT_BINLOG_IGNORE_DB:
|
||||||
{
|
{
|
||||||
i_string *db = new i_string(argument);
|
binlog_filter->add_ignore_db(argument);
|
||||||
binlog_ignore_db.push_back(db);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (int)OPT_BINLOG_DO_DB:
|
case (int)OPT_BINLOG_DO_DB:
|
||||||
{
|
{
|
||||||
i_string *db = new i_string(argument);
|
binlog_filter->add_do_db(argument);
|
||||||
binlog_do_db.push_back(db);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (int)OPT_REPLICATE_DO_TABLE:
|
case (int)OPT_REPLICATE_DO_TABLE:
|
||||||
{
|
{
|
||||||
if (!do_table_inited)
|
if (rpl_filter->add_do_table(argument))
|
||||||
init_table_rule_hash(&replicate_do_table, &do_table_inited);
|
|
||||||
if (add_table_rule(&replicate_do_table, argument))
|
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Could not add do table rule '%s'!\n", argument);
|
fprintf(stderr, "Could not add do table rule '%s'!\n", argument);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
table_rules_on = 1;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (int)OPT_REPLICATE_WILD_DO_TABLE:
|
case (int)OPT_REPLICATE_WILD_DO_TABLE:
|
||||||
{
|
{
|
||||||
if (!wild_do_table_inited)
|
if (rpl_filter->add_wild_do_table(argument))
|
||||||
init_table_rule_array(&replicate_wild_do_table,
|
|
||||||
&wild_do_table_inited);
|
|
||||||
if (add_wild_table_rule(&replicate_wild_do_table, argument))
|
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Could not add do table rule '%s'!\n", argument);
|
fprintf(stderr, "Could not add do table rule '%s'!\n", argument);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
table_rules_on = 1;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (int)OPT_REPLICATE_WILD_IGNORE_TABLE:
|
case (int)OPT_REPLICATE_WILD_IGNORE_TABLE:
|
||||||
{
|
{
|
||||||
if (!wild_ignore_table_inited)
|
if (rpl_filter->add_wild_ignore_table(argument))
|
||||||
init_table_rule_array(&replicate_wild_ignore_table,
|
|
||||||
&wild_ignore_table_inited);
|
|
||||||
if (add_wild_table_rule(&replicate_wild_ignore_table, argument))
|
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Could not add ignore table rule '%s'!\n", argument);
|
fprintf(stderr, "Could not add ignore table rule '%s'!\n", argument);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
table_rules_on = 1;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (int)OPT_REPLICATE_IGNORE_TABLE:
|
case (int)OPT_REPLICATE_IGNORE_TABLE:
|
||||||
{
|
{
|
||||||
if (!ignore_table_inited)
|
if (rpl_filter->add_ignore_table(argument))
|
||||||
init_table_rule_hash(&replicate_ignore_table, &ignore_table_inited);
|
|
||||||
if (add_table_rule(&replicate_ignore_table, argument))
|
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Could not add ignore table rule '%s'!\n", argument);
|
fprintf(stderr, "Could not add ignore table rule '%s'!\n", argument);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
table_rules_on = 1;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif /* HAVE_REPLICATION */
|
#endif /* HAVE_REPLICATION */
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "repl_failsafe.h"
|
#include "repl_failsafe.h"
|
||||||
#include "sql_repl.h"
|
#include "sql_repl.h"
|
||||||
#include "slave.h"
|
#include "slave.h"
|
||||||
|
#include "rpl_filter.h"
|
||||||
#include "log_event.h"
|
#include "log_event.h"
|
||||||
#include <mysql.h>
|
#include <mysql.h>
|
||||||
|
|
||||||
|
@ -735,14 +736,14 @@ static int fetch_db_tables(THD *thd, MYSQL *mysql, const char *db,
|
||||||
TABLE_LIST table;
|
TABLE_LIST table;
|
||||||
const char* table_name= row[0];
|
const char* table_name= row[0];
|
||||||
int error;
|
int error;
|
||||||
if (table_rules_on)
|
if (rpl_filter->is_on())
|
||||||
{
|
{
|
||||||
bzero((char*) &table, sizeof(table)); //just for safe
|
bzero((char*) &table, sizeof(table)); //just for safe
|
||||||
table.db= (char*) db;
|
table.db= (char*) db;
|
||||||
table.table_name= (char*) table_name;
|
table.table_name= (char*) table_name;
|
||||||
table.updating= 1;
|
table.updating= 1;
|
||||||
|
|
||||||
if (!tables_ok(thd, &table))
|
if (!rpl_filter->tables_ok(thd->db, &table))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* download master's table and overwrite slave's table */
|
/* download master's table and overwrite slave's table */
|
||||||
|
@ -860,8 +861,8 @@ bool load_master_data(THD* thd)
|
||||||
data from master
|
data from master
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!db_ok(db, replicate_do_db, replicate_ignore_db) ||
|
if (!rpl_filter->db_ok(db) ||
|
||||||
!db_ok_with_wild_table(db) ||
|
!rpl_filter->db_ok_with_wild_table(db) ||
|
||||||
!strcmp(db,"mysql"))
|
!strcmp(db,"mysql"))
|
||||||
{
|
{
|
||||||
*cur_table_res = 0;
|
*cur_table_res = 0;
|
||||||
|
|
539
sql/rpl_filter.cc
Normal file
539
sql/rpl_filter.cc
Normal file
|
@ -0,0 +1,539 @@
|
||||||
|
/* Copyright (C) 2000-2003 MySQL AB
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||||
|
|
||||||
|
#include "mysql_priv.h"
|
||||||
|
#include "rpl_filter.h"
|
||||||
|
|
||||||
|
#define TABLE_RULE_HASH_SIZE 16
|
||||||
|
#define TABLE_RULE_ARR_SIZE 16
|
||||||
|
|
||||||
|
Rpl_filter::Rpl_filter() :
|
||||||
|
table_rules_on(0), do_table_inited(0), ignore_table_inited(0),
|
||||||
|
wild_do_table_inited(0), wild_ignore_table_inited(0)
|
||||||
|
{
|
||||||
|
do_db.empty();
|
||||||
|
ignore_db.empty();
|
||||||
|
rewrite_db.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Rpl_filter::~Rpl_filter()
|
||||||
|
{
|
||||||
|
if (do_table_inited)
|
||||||
|
hash_free(&do_table);
|
||||||
|
if (ignore_table_inited)
|
||||||
|
hash_free(&ignore_table);
|
||||||
|
if (wild_do_table_inited)
|
||||||
|
free_string_array(&wild_do_table);
|
||||||
|
if (wild_ignore_table_inited)
|
||||||
|
free_string_array(&wild_ignore_table);
|
||||||
|
free_list(&do_db);
|
||||||
|
free_list(&ignore_db);
|
||||||
|
free_list(&rewrite_db);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Returns true if table should be logged/replicated
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
tables_ok()
|
||||||
|
db db to use if db in TABLE_LIST is undefined for a table
|
||||||
|
tables list of tables to check
|
||||||
|
|
||||||
|
NOTES
|
||||||
|
Changing table order in the list can lead to different results.
|
||||||
|
|
||||||
|
Note also order of precedence of do/ignore rules (see code). For
|
||||||
|
that reason, users should not set conflicting rules because they
|
||||||
|
may get unpredicted results (precedence order is explained in the
|
||||||
|
manual).
|
||||||
|
|
||||||
|
If no table in the list is marked "updating", then we always
|
||||||
|
return 0, because there is no reason to execute this statement on
|
||||||
|
slave if it updates nothing. (Currently, this can only happen if
|
||||||
|
statement is a multi-delete (SQLCOM_DELETE_MULTI) and "tables" are
|
||||||
|
the tables in the FROM):
|
||||||
|
|
||||||
|
In the case of SQLCOM_DELETE_MULTI, there will be a second call to
|
||||||
|
tables_ok(), with tables having "updating==TRUE" (those after the
|
||||||
|
DELETE), so this second call will make the decision (because
|
||||||
|
all_tables_not_ok() = !tables_ok(1st_list) &&
|
||||||
|
!tables_ok(2nd_list)).
|
||||||
|
|
||||||
|
TODO
|
||||||
|
"Include all tables like "abc.%" except "%.EFG"". (Can't be done now.)
|
||||||
|
If we supported Perl regexps, we could do it with pattern: /^abc\.(?!EFG)/
|
||||||
|
(I could not find an equivalent in the regex library MySQL uses).
|
||||||
|
|
||||||
|
RETURN VALUES
|
||||||
|
0 should not be logged/replicated
|
||||||
|
1 should be logged/replicated
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool
|
||||||
|
Rpl_filter::tables_ok(const char* db, TABLE_LIST* tables)
|
||||||
|
{
|
||||||
|
bool some_tables_updating= 0;
|
||||||
|
DBUG_ENTER("Rpl_filter::tables_ok");
|
||||||
|
|
||||||
|
for (; tables; tables= tables->next_global)
|
||||||
|
{
|
||||||
|
char hash_key[2*NAME_LEN+2];
|
||||||
|
char *end;
|
||||||
|
uint len;
|
||||||
|
|
||||||
|
if (!tables->updating)
|
||||||
|
continue;
|
||||||
|
some_tables_updating= 1;
|
||||||
|
end= strmov(hash_key, tables->db ? tables->db : db);
|
||||||
|
*end++= '.';
|
||||||
|
len= (uint) (strmov(end, tables->table_name) - hash_key);
|
||||||
|
if (do_table_inited) // if there are any do's
|
||||||
|
{
|
||||||
|
if (hash_search(&do_table, (byte*) hash_key, len))
|
||||||
|
DBUG_RETURN(1);
|
||||||
|
}
|
||||||
|
if (ignore_table_inited) // if there are any ignores
|
||||||
|
{
|
||||||
|
if (hash_search(&ignore_table, (byte*) hash_key, len))
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
if (wild_do_table_inited &&
|
||||||
|
find_wild(&wild_do_table, hash_key, len))
|
||||||
|
DBUG_RETURN(1);
|
||||||
|
if (wild_ignore_table_inited &&
|
||||||
|
find_wild(&wild_ignore_table, hash_key, len))
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
If no table was to be updated, ignore statement (no reason we play it on
|
||||||
|
slave, slave is supposed to replicate _changes_ only).
|
||||||
|
If no explicit rule found and there was a do list, do not replicate.
|
||||||
|
If there was no do list, go ahead
|
||||||
|
*/
|
||||||
|
DBUG_RETURN(some_tables_updating &&
|
||||||
|
!do_table_inited && !wild_do_table_inited);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Checks whether a db matches some do_db and ignore_db rules
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
db_ok()
|
||||||
|
db name of the db to check
|
||||||
|
|
||||||
|
RETURN VALUES
|
||||||
|
0 should not be logged/replicated
|
||||||
|
1 should be logged/replicated
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool
|
||||||
|
Rpl_filter::db_ok(const char* db)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("Rpl_filter::db_ok");
|
||||||
|
|
||||||
|
if (do_db.is_empty() && ignore_db.is_empty())
|
||||||
|
DBUG_RETURN(1); // Ok to replicate if the user puts no constraints
|
||||||
|
|
||||||
|
/*
|
||||||
|
If the user has specified restrictions on which databases to replicate
|
||||||
|
and db was not selected, do not replicate.
|
||||||
|
*/
|
||||||
|
if (!db)
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
|
||||||
|
if (!do_db.is_empty()) // if the do's are not empty
|
||||||
|
{
|
||||||
|
I_List_iterator<i_string> it(do_db);
|
||||||
|
i_string* tmp;
|
||||||
|
|
||||||
|
while ((tmp=it++))
|
||||||
|
{
|
||||||
|
if (!strcmp(tmp->ptr, db))
|
||||||
|
DBUG_RETURN(1); // match
|
||||||
|
}
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
else // there are some elements in the don't, otherwise we cannot get here
|
||||||
|
{
|
||||||
|
I_List_iterator<i_string> it(ignore_db);
|
||||||
|
i_string* tmp;
|
||||||
|
|
||||||
|
while ((tmp=it++))
|
||||||
|
{
|
||||||
|
if (!strcmp(tmp->ptr, db))
|
||||||
|
DBUG_RETURN(0); // match
|
||||||
|
}
|
||||||
|
DBUG_RETURN(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Checks whether a db matches wild_do_table and wild_ignore_table
|
||||||
|
rules (for replication)
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
db_ok_with_wild_table()
|
||||||
|
db name of the db to check.
|
||||||
|
Is tested with check_db_name() before calling this function.
|
||||||
|
|
||||||
|
NOTES
|
||||||
|
Here is the reason for this function.
|
||||||
|
We advise users who want to exclude a database 'db1' safely to do it
|
||||||
|
with replicate_wild_ignore_table='db1.%' instead of binlog_ignore_db or
|
||||||
|
replicate_ignore_db because the two lasts only check for the selected db,
|
||||||
|
which won't work in that case:
|
||||||
|
USE db2;
|
||||||
|
UPDATE db1.t SET ... #this will be replicated and should not
|
||||||
|
whereas replicate_wild_ignore_table will work in all cases.
|
||||||
|
With replicate_wild_ignore_table, we only check tables. When
|
||||||
|
one does 'DROP DATABASE db1', tables are not involved and the
|
||||||
|
statement will be replicated, while users could expect it would not (as it
|
||||||
|
rougly means 'DROP db1.first_table, DROP db1.second_table...').
|
||||||
|
In other words, we want to interpret 'db1.%' as "everything touching db1".
|
||||||
|
That is why we want to match 'db1' against 'db1.%' wild table rules.
|
||||||
|
|
||||||
|
RETURN VALUES
|
||||||
|
0 should not be logged/replicated
|
||||||
|
1 should be logged/replicated
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool
|
||||||
|
Rpl_filter::db_ok_with_wild_table(const char *db)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("Rpl_filter::db_ok_with_wild_table");
|
||||||
|
|
||||||
|
char hash_key[NAME_LEN+2];
|
||||||
|
char *end;
|
||||||
|
int len;
|
||||||
|
end= strmov(hash_key, db);
|
||||||
|
*end++= '.';
|
||||||
|
len= end - hash_key ;
|
||||||
|
if (wild_do_table_inited && find_wild(&wild_do_table, hash_key, len))
|
||||||
|
{
|
||||||
|
DBUG_PRINT("return",("1"));
|
||||||
|
DBUG_RETURN(1);
|
||||||
|
}
|
||||||
|
if (wild_ignore_table_inited && find_wild(&wild_ignore_table, hash_key, len))
|
||||||
|
{
|
||||||
|
DBUG_PRINT("return",("0"));
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
If no explicit rule found and there was a do list, do not replicate.
|
||||||
|
If there was no do list, go ahead
|
||||||
|
*/
|
||||||
|
DBUG_PRINT("return",("db=%s,retval=%d", db, !wild_do_table_inited));
|
||||||
|
DBUG_RETURN(!wild_do_table_inited);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
Rpl_filter::is_on()
|
||||||
|
{
|
||||||
|
return table_rules_on;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
Rpl_filter::add_do_table(const char* table_spec)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("Rpl_filter::add_do_table");
|
||||||
|
if (!do_table_inited)
|
||||||
|
init_table_rule_hash(&do_table, &do_table_inited);
|
||||||
|
table_rules_on= 1;
|
||||||
|
DBUG_RETURN(add_table_rule(&do_table, table_spec));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
Rpl_filter::add_ignore_table(const char* table_spec)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("Rpl_filter::add_ignore_table");
|
||||||
|
if (!ignore_table_inited)
|
||||||
|
init_table_rule_hash(&ignore_table, &ignore_table_inited);
|
||||||
|
table_rules_on= 1;
|
||||||
|
DBUG_RETURN(add_table_rule(&ignore_table, table_spec));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
Rpl_filter::add_wild_do_table(const char* table_spec)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("Rpl_filter::add_wild_do_table");
|
||||||
|
if (!wild_do_table_inited)
|
||||||
|
init_table_rule_array(&wild_do_table, &wild_do_table_inited);
|
||||||
|
table_rules_on= 1;
|
||||||
|
DBUG_RETURN(add_wild_table_rule(&wild_do_table, table_spec));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
Rpl_filter::add_wild_ignore_table(const char* table_spec)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("Rpl_filter::add_wild_ignore_table");
|
||||||
|
if (!wild_ignore_table_inited)
|
||||||
|
init_table_rule_array(&wild_ignore_table, &wild_ignore_table_inited);
|
||||||
|
table_rules_on= 1;
|
||||||
|
DBUG_RETURN(add_wild_table_rule(&wild_ignore_table, table_spec));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Rpl_filter::add_db_rewrite(const char* from_db, const char* to_db)
|
||||||
|
{
|
||||||
|
i_string_pair *db_pair = new i_string_pair(from_db, to_db);
|
||||||
|
rewrite_db.push_back(db_pair);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
Rpl_filter::add_table_rule(HASH* h, const char* table_spec)
|
||||||
|
{
|
||||||
|
const char* dot = strchr(table_spec, '.');
|
||||||
|
if (!dot) return 1;
|
||||||
|
// len is always > 0 because we know the there exists a '.'
|
||||||
|
uint len = (uint)strlen(table_spec);
|
||||||
|
TABLE_RULE_ENT* e = (TABLE_RULE_ENT*)my_malloc(sizeof(TABLE_RULE_ENT)
|
||||||
|
+ len, MYF(MY_WME));
|
||||||
|
if (!e) return 1;
|
||||||
|
e->db= (char*)e + sizeof(TABLE_RULE_ENT);
|
||||||
|
e->tbl_name= e->db + (dot - table_spec) + 1;
|
||||||
|
e->key_len= len;
|
||||||
|
memcpy(e->db, table_spec, len);
|
||||||
|
|
||||||
|
return my_hash_insert(h, (byte*)e);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Add table expression with wildcards to dynamic array
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
Rpl_filter::add_wild_table_rule(DYNAMIC_ARRAY* a, const char* table_spec)
|
||||||
|
{
|
||||||
|
const char* dot = strchr(table_spec, '.');
|
||||||
|
if (!dot) return 1;
|
||||||
|
uint len = (uint)strlen(table_spec);
|
||||||
|
TABLE_RULE_ENT* e = (TABLE_RULE_ENT*)my_malloc(sizeof(TABLE_RULE_ENT)
|
||||||
|
+ len, MYF(MY_WME));
|
||||||
|
if (!e) return 1;
|
||||||
|
e->db= (char*)e + sizeof(TABLE_RULE_ENT);
|
||||||
|
e->tbl_name= e->db + (dot - table_spec) + 1;
|
||||||
|
e->key_len= len;
|
||||||
|
memcpy(e->db, table_spec, len);
|
||||||
|
insert_dynamic(a, (gptr)&e);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Rpl_filter::add_do_db(const char* table_spec)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("Rpl_filter::add_do_db");
|
||||||
|
i_string *db = new i_string(table_spec);
|
||||||
|
do_db.push_back(db);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Rpl_filter::add_ignore_db(const char* table_spec)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("Rpl_filter::add_ignore_db");
|
||||||
|
i_string *db = new i_string(table_spec);
|
||||||
|
ignore_db.push_back(db);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static byte* get_table_key(const byte* a, uint* len,
|
||||||
|
my_bool __attribute__((unused)))
|
||||||
|
{
|
||||||
|
TABLE_RULE_ENT *e= (TABLE_RULE_ENT *) a;
|
||||||
|
|
||||||
|
*len= e->key_len;
|
||||||
|
return (byte*)e->db;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void free_table_ent(void* a)
|
||||||
|
{
|
||||||
|
TABLE_RULE_ENT *e= (TABLE_RULE_ENT *) a;
|
||||||
|
|
||||||
|
my_free((gptr) e, MYF(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Rpl_filter::init_table_rule_hash(HASH* h, bool* h_inited)
|
||||||
|
{
|
||||||
|
hash_init(h, system_charset_info,TABLE_RULE_HASH_SIZE,0,0,
|
||||||
|
get_table_key, free_table_ent, 0);
|
||||||
|
*h_inited = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Rpl_filter::init_table_rule_array(DYNAMIC_ARRAY* a, bool* a_inited)
|
||||||
|
{
|
||||||
|
my_init_dynamic_array(a, sizeof(TABLE_RULE_ENT*), TABLE_RULE_ARR_SIZE,
|
||||||
|
TABLE_RULE_ARR_SIZE);
|
||||||
|
*a_inited = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TABLE_RULE_ENT*
|
||||||
|
Rpl_filter::find_wild(DYNAMIC_ARRAY *a, const char* key, int len)
|
||||||
|
{
|
||||||
|
uint i;
|
||||||
|
const char* key_end= key + len;
|
||||||
|
|
||||||
|
for (i= 0; i < a->elements; i++)
|
||||||
|
{
|
||||||
|
TABLE_RULE_ENT* e ;
|
||||||
|
get_dynamic(a, (gptr)&e, i);
|
||||||
|
if (!my_wildcmp(system_charset_info, key, key_end,
|
||||||
|
(const char*)e->db,
|
||||||
|
(const char*)(e->db + e->key_len),
|
||||||
|
'\\',wild_one,wild_many))
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Rpl_filter::free_string_array(DYNAMIC_ARRAY *a)
|
||||||
|
{
|
||||||
|
uint i;
|
||||||
|
for (i= 0; i < a->elements; i++)
|
||||||
|
{
|
||||||
|
char* p;
|
||||||
|
get_dynamic(a, (gptr) &p, i);
|
||||||
|
my_free(p, MYF(MY_WME));
|
||||||
|
}
|
||||||
|
delete_dynamic(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Builds a String from a HASH of TABLE_RULE_ENT. Cannot be used for any other
|
||||||
|
hash, as it assumes that the hash entries are TABLE_RULE_ENT.
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
table_rule_ent_hash_to_str()
|
||||||
|
s pointer to the String to fill
|
||||||
|
h pointer to the HASH to read
|
||||||
|
|
||||||
|
RETURN VALUES
|
||||||
|
none
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
Rpl_filter::table_rule_ent_hash_to_str(String* s, HASH* h)
|
||||||
|
{
|
||||||
|
s->length(0);
|
||||||
|
for (uint i= 0; i < h->records; i++)
|
||||||
|
{
|
||||||
|
TABLE_RULE_ENT* e= (TABLE_RULE_ENT*) hash_element(h, i);
|
||||||
|
if (s->length())
|
||||||
|
s->append(',');
|
||||||
|
s->append(e->db,e->key_len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Rpl_filter::table_rule_ent_dynamic_array_to_str(String* s, DYNAMIC_ARRAY* a)
|
||||||
|
{
|
||||||
|
s->length(0);
|
||||||
|
for (uint i= 0; i < a->elements; i++)
|
||||||
|
{
|
||||||
|
TABLE_RULE_ENT* e;
|
||||||
|
get_dynamic(a, (gptr)&e, i);
|
||||||
|
if (s->length())
|
||||||
|
s->append(',');
|
||||||
|
s->append(e->db,e->key_len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Rpl_filter::get_do_table(String* str)
|
||||||
|
{
|
||||||
|
table_rule_ent_hash_to_str(str, &do_table);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Rpl_filter::get_ignore_table(String* str)
|
||||||
|
{
|
||||||
|
table_rule_ent_hash_to_str(str, &ignore_table);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Rpl_filter::get_wild_do_table(String* str)
|
||||||
|
{
|
||||||
|
table_rule_ent_dynamic_array_to_str(str, &wild_do_table);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Rpl_filter::get_wild_ignore_table(String* str)
|
||||||
|
{
|
||||||
|
table_rule_ent_dynamic_array_to_str(str, &wild_ignore_table);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char*
|
||||||
|
Rpl_filter::get_rewrite_db(const char* db, uint32 *new_len)
|
||||||
|
{
|
||||||
|
if (rewrite_db.is_empty() || !db)
|
||||||
|
return db;
|
||||||
|
I_List_iterator<i_string_pair> it(rewrite_db);
|
||||||
|
i_string_pair* tmp;
|
||||||
|
|
||||||
|
while ((tmp=it++))
|
||||||
|
{
|
||||||
|
if (!strcmp(tmp->key, db))
|
||||||
|
{
|
||||||
|
*new_len= strlen(tmp->val);
|
||||||
|
return tmp->val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return db;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
I_List<i_string>*
|
||||||
|
Rpl_filter::get_do_db()
|
||||||
|
{
|
||||||
|
return &do_db;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
I_List<i_string>*
|
||||||
|
Rpl_filter::get_ignore_db()
|
||||||
|
{
|
||||||
|
return &ignore_db;
|
||||||
|
}
|
110
sql/rpl_filter.h
Normal file
110
sql/rpl_filter.h
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
/* Copyright (C) 2000-2003 MySQL AB
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||||
|
|
||||||
|
#ifndef __RPL_FILTER_H__
|
||||||
|
#define __RPL_FILTER_H__
|
||||||
|
|
||||||
|
#include "mysql.h"
|
||||||
|
#include "my_list.h"
|
||||||
|
|
||||||
|
typedef struct st_table_rule_ent
|
||||||
|
{
|
||||||
|
char* db;
|
||||||
|
char* tbl_name;
|
||||||
|
uint key_len;
|
||||||
|
} TABLE_RULE_ENT;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Rpl_filter
|
||||||
|
|
||||||
|
Inclusion and exclusion rules of tables and databases.
|
||||||
|
Also handles rewrites of db.
|
||||||
|
Used for replication and binlogging.
|
||||||
|
*/
|
||||||
|
class Rpl_filter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Rpl_filter();
|
||||||
|
~Rpl_filter();
|
||||||
|
Rpl_filter(Rpl_filter const&);
|
||||||
|
Rpl_filter& operator=(Rpl_filter const&);
|
||||||
|
|
||||||
|
/* Checks - returns true if ok to replicate/log */
|
||||||
|
|
||||||
|
bool tables_ok(const char* db, TABLE_LIST* tables);
|
||||||
|
bool db_ok(const char* db);
|
||||||
|
bool db_ok_with_wild_table(const char *db);
|
||||||
|
|
||||||
|
bool is_on();
|
||||||
|
|
||||||
|
/* Setters - add filtering rules */
|
||||||
|
|
||||||
|
int add_do_table(const char* table_spec);
|
||||||
|
int add_ignore_table(const char* table_spec);
|
||||||
|
|
||||||
|
int add_wild_do_table(const char* table_spec);
|
||||||
|
int add_wild_ignore_table(const char* table_spec);
|
||||||
|
|
||||||
|
void add_do_db(const char* db_spec);
|
||||||
|
void add_ignore_db(const char* db_spec);
|
||||||
|
|
||||||
|
void add_db_rewrite(const char* from_db, const char* to_db);
|
||||||
|
|
||||||
|
/* Getters - to get information about current rules */
|
||||||
|
|
||||||
|
void get_do_table(String* str);
|
||||||
|
void get_ignore_table(String* str);
|
||||||
|
|
||||||
|
void get_wild_do_table(String* str);
|
||||||
|
void get_wild_ignore_table(String* str);
|
||||||
|
|
||||||
|
const char* get_rewrite_db(const char* db, uint32 *new_len);
|
||||||
|
|
||||||
|
I_List<i_string>* get_do_db();
|
||||||
|
I_List<i_string>* get_ignore_db();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool table_rules_on;
|
||||||
|
|
||||||
|
void init_table_rule_hash(HASH* h, bool* h_inited);
|
||||||
|
void init_table_rule_array(DYNAMIC_ARRAY* a, bool* a_inited);
|
||||||
|
|
||||||
|
int add_table_rule(HASH* h, const char* table_spec);
|
||||||
|
int add_wild_table_rule(DYNAMIC_ARRAY* a, const char* table_spec);
|
||||||
|
|
||||||
|
void free_string_array(DYNAMIC_ARRAY *a);
|
||||||
|
|
||||||
|
void table_rule_ent_hash_to_str(String* s, HASH* h);
|
||||||
|
void table_rule_ent_dynamic_array_to_str(String* s, DYNAMIC_ARRAY* a);
|
||||||
|
TABLE_RULE_ENT* find_wild(DYNAMIC_ARRAY *a, const char* key, int len);
|
||||||
|
|
||||||
|
HASH do_table;
|
||||||
|
HASH ignore_table;
|
||||||
|
DYNAMIC_ARRAY wild_do_table;
|
||||||
|
DYNAMIC_ARRAY wild_ignore_table;
|
||||||
|
|
||||||
|
bool do_table_inited;
|
||||||
|
bool ignore_table_inited;
|
||||||
|
bool wild_do_table_inited;
|
||||||
|
bool wild_ignore_table_inited;
|
||||||
|
|
||||||
|
I_List<i_string> do_db;
|
||||||
|
I_List<i_string> ignore_db;
|
||||||
|
|
||||||
|
I_List<i_string_pair> rewrite_db;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // __TABLE_FILTER_H__
|
390
sql/slave.cc
390
sql/slave.cc
|
@ -22,6 +22,7 @@
|
||||||
#include <myisam.h>
|
#include <myisam.h>
|
||||||
#include "slave.h"
|
#include "slave.h"
|
||||||
#include "sql_repl.h"
|
#include "sql_repl.h"
|
||||||
|
#include "rpl_filter.h"
|
||||||
#include "repl_failsafe.h"
|
#include "repl_failsafe.h"
|
||||||
#include <thr_alarm.h>
|
#include <thr_alarm.h>
|
||||||
#include <my_dir.h>
|
#include <my_dir.h>
|
||||||
|
@ -35,11 +36,7 @@ typedef bool (*CHECK_KILLED_FUNC)(THD*,void*);
|
||||||
volatile bool slave_sql_running = 0, slave_io_running = 0;
|
volatile bool slave_sql_running = 0, slave_io_running = 0;
|
||||||
char* slave_load_tmpdir = 0;
|
char* slave_load_tmpdir = 0;
|
||||||
MASTER_INFO *active_mi;
|
MASTER_INFO *active_mi;
|
||||||
HASH replicate_do_table, replicate_ignore_table;
|
bool replicate_same_server_id;
|
||||||
DYNAMIC_ARRAY replicate_wild_do_table, replicate_wild_ignore_table;
|
|
||||||
bool do_table_inited = 0, ignore_table_inited = 0;
|
|
||||||
bool wild_do_table_inited = 0, wild_ignore_table_inited = 0;
|
|
||||||
bool table_rules_on= 0, replicate_same_server_id;
|
|
||||||
ulonglong relay_log_space_limit = 0;
|
ulonglong relay_log_space_limit = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -193,20 +190,6 @@ err:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void free_table_ent(TABLE_RULE_ENT* e)
|
|
||||||
{
|
|
||||||
my_free((gptr) e, MYF(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static byte* get_table_key(TABLE_RULE_ENT* e, uint* len,
|
|
||||||
my_bool not_used __attribute__((unused)))
|
|
||||||
{
|
|
||||||
*len = e->key_len;
|
|
||||||
return (byte*)e->db;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Open the given relay log
|
Open the given relay log
|
||||||
|
|
||||||
|
@ -808,228 +791,6 @@ int start_slave_threads(bool need_slave_mutex, bool wait_for_start,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void init_table_rule_hash(HASH* h, bool* h_inited)
|
|
||||||
{
|
|
||||||
hash_init(h, system_charset_info,TABLE_RULE_HASH_SIZE,0,0,
|
|
||||||
(hash_get_key) get_table_key,
|
|
||||||
(hash_free_key) free_table_ent, 0);
|
|
||||||
*h_inited = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void init_table_rule_array(DYNAMIC_ARRAY* a, bool* a_inited)
|
|
||||||
{
|
|
||||||
my_init_dynamic_array(a, sizeof(TABLE_RULE_ENT*), TABLE_RULE_ARR_SIZE,
|
|
||||||
TABLE_RULE_ARR_SIZE);
|
|
||||||
*a_inited = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static TABLE_RULE_ENT* find_wild(DYNAMIC_ARRAY *a, const char* key, int len)
|
|
||||||
{
|
|
||||||
uint i;
|
|
||||||
const char* key_end = key + len;
|
|
||||||
|
|
||||||
for (i = 0; i < a->elements; i++)
|
|
||||||
{
|
|
||||||
TABLE_RULE_ENT* e ;
|
|
||||||
get_dynamic(a, (gptr)&e, i);
|
|
||||||
if (!my_wildcmp(system_charset_info, key, key_end,
|
|
||||||
(const char*)e->db,
|
|
||||||
(const char*)(e->db + e->key_len),
|
|
||||||
'\\',wild_one,wild_many))
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Checks whether tables match some (wild_)do_table and (wild_)ignore_table
|
|
||||||
rules (for replication)
|
|
||||||
|
|
||||||
SYNOPSIS
|
|
||||||
tables_ok()
|
|
||||||
thd thread (SQL slave thread normally)
|
|
||||||
tables list of tables to check
|
|
||||||
|
|
||||||
NOTES
|
|
||||||
Note that changing the order of the tables in the list can lead to
|
|
||||||
different results. Note also the order of precedence of the do/ignore
|
|
||||||
rules (see code below). For that reason, users should not set conflicting
|
|
||||||
rules because they may get unpredicted results (precedence order is
|
|
||||||
explained in the manual).
|
|
||||||
If no table of the list is marked "updating" (so far this can only happen
|
|
||||||
if the statement is a multi-delete (SQLCOM_DELETE_MULTI) and the "tables"
|
|
||||||
is the tables in the FROM): then we always return 0, because there is no
|
|
||||||
reason we play this statement on this slave if it updates nothing. In the
|
|
||||||
case of SQLCOM_DELETE_MULTI, there will be a second call to tables_ok(),
|
|
||||||
with tables having "updating==TRUE" (those after the DELETE), so this
|
|
||||||
second call will make the decision (because
|
|
||||||
all_tables_not_ok() = !tables_ok(1st_list) && !tables_ok(2nd_list)).
|
|
||||||
|
|
||||||
Thought which arose from a question of a big customer "I want to include
|
|
||||||
all tables like "abc.%" except the "%.EFG"". This can't be done now. If we
|
|
||||||
supported Perl regexps we could do it with this pattern: /^abc\.(?!EFG)/
|
|
||||||
(I could not find an equivalent in the regex library MySQL uses).
|
|
||||||
|
|
||||||
RETURN VALUES
|
|
||||||
0 should not be logged/replicated
|
|
||||||
1 should be logged/replicated
|
|
||||||
*/
|
|
||||||
|
|
||||||
bool tables_ok(THD* thd, TABLE_LIST* tables)
|
|
||||||
{
|
|
||||||
bool some_tables_updating= 0;
|
|
||||||
DBUG_ENTER("tables_ok");
|
|
||||||
|
|
||||||
for (; tables; tables= tables->next_global)
|
|
||||||
{
|
|
||||||
char hash_key[2*NAME_LEN+2];
|
|
||||||
char *end;
|
|
||||||
uint len;
|
|
||||||
|
|
||||||
if (!tables->updating)
|
|
||||||
continue;
|
|
||||||
some_tables_updating= 1;
|
|
||||||
end= strmov(hash_key, tables->db ? tables->db : thd->db);
|
|
||||||
*end++= '.';
|
|
||||||
len= (uint) (strmov(end, tables->table_name) - hash_key);
|
|
||||||
if (do_table_inited) // if there are any do's
|
|
||||||
{
|
|
||||||
if (hash_search(&replicate_do_table, (byte*) hash_key, len))
|
|
||||||
DBUG_RETURN(1);
|
|
||||||
}
|
|
||||||
if (ignore_table_inited) // if there are any ignores
|
|
||||||
{
|
|
||||||
if (hash_search(&replicate_ignore_table, (byte*) hash_key, len))
|
|
||||||
DBUG_RETURN(0);
|
|
||||||
}
|
|
||||||
if (wild_do_table_inited && find_wild(&replicate_wild_do_table,
|
|
||||||
hash_key, len))
|
|
||||||
DBUG_RETURN(1);
|
|
||||||
if (wild_ignore_table_inited && find_wild(&replicate_wild_ignore_table,
|
|
||||||
hash_key, len))
|
|
||||||
DBUG_RETURN(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
If no table was to be updated, ignore statement (no reason we play it on
|
|
||||||
slave, slave is supposed to replicate _changes_ only).
|
|
||||||
If no explicit rule found and there was a do list, do not replicate.
|
|
||||||
If there was no do list, go ahead
|
|
||||||
*/
|
|
||||||
DBUG_RETURN(some_tables_updating &&
|
|
||||||
!do_table_inited && !wild_do_table_inited);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Checks whether a db matches wild_do_table and wild_ignore_table
|
|
||||||
rules (for replication)
|
|
||||||
|
|
||||||
SYNOPSIS
|
|
||||||
db_ok_with_wild_table()
|
|
||||||
db name of the db to check.
|
|
||||||
Is tested with check_db_name() before calling this function.
|
|
||||||
|
|
||||||
NOTES
|
|
||||||
Here is the reason for this function.
|
|
||||||
We advise users who want to exclude a database 'db1' safely to do it
|
|
||||||
with replicate_wild_ignore_table='db1.%' instead of binlog_ignore_db or
|
|
||||||
replicate_ignore_db because the two lasts only check for the selected db,
|
|
||||||
which won't work in that case:
|
|
||||||
USE db2;
|
|
||||||
UPDATE db1.t SET ... #this will be replicated and should not
|
|
||||||
whereas replicate_wild_ignore_table will work in all cases.
|
|
||||||
With replicate_wild_ignore_table, we only check tables. When
|
|
||||||
one does 'DROP DATABASE db1', tables are not involved and the
|
|
||||||
statement will be replicated, while users could expect it would not (as it
|
|
||||||
rougly means 'DROP db1.first_table, DROP db1.second_table...').
|
|
||||||
In other words, we want to interpret 'db1.%' as "everything touching db1".
|
|
||||||
That is why we want to match 'db1' against 'db1.%' wild table rules.
|
|
||||||
|
|
||||||
RETURN VALUES
|
|
||||||
0 should not be logged/replicated
|
|
||||||
1 should be logged/replicated
|
|
||||||
*/
|
|
||||||
|
|
||||||
int db_ok_with_wild_table(const char *db)
|
|
||||||
{
|
|
||||||
char hash_key[NAME_LEN+2];
|
|
||||||
char *end;
|
|
||||||
int len;
|
|
||||||
end= strmov(hash_key, db);
|
|
||||||
*end++= '.';
|
|
||||||
len= end - hash_key ;
|
|
||||||
if (wild_do_table_inited && find_wild(&replicate_wild_do_table,
|
|
||||||
hash_key, len))
|
|
||||||
return 1;
|
|
||||||
if (wild_ignore_table_inited && find_wild(&replicate_wild_ignore_table,
|
|
||||||
hash_key, len))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
If no explicit rule found and there was a do list, do not replicate.
|
|
||||||
If there was no do list, go ahead
|
|
||||||
*/
|
|
||||||
return !wild_do_table_inited;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int add_table_rule(HASH* h, const char* table_spec)
|
|
||||||
{
|
|
||||||
const char* dot = strchr(table_spec, '.');
|
|
||||||
if (!dot) return 1;
|
|
||||||
// len is always > 0 because we know the there exists a '.'
|
|
||||||
uint len = (uint)strlen(table_spec);
|
|
||||||
TABLE_RULE_ENT* e = (TABLE_RULE_ENT*)my_malloc(sizeof(TABLE_RULE_ENT)
|
|
||||||
+ len, MYF(MY_WME));
|
|
||||||
if (!e) return 1;
|
|
||||||
e->db = (char*)e + sizeof(TABLE_RULE_ENT);
|
|
||||||
e->tbl_name = e->db + (dot - table_spec) + 1;
|
|
||||||
e->key_len = len;
|
|
||||||
memcpy(e->db, table_spec, len);
|
|
||||||
(void)my_hash_insert(h, (byte*)e);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Add table expression with wildcards to dynamic array
|
|
||||||
*/
|
|
||||||
|
|
||||||
int add_wild_table_rule(DYNAMIC_ARRAY* a, const char* table_spec)
|
|
||||||
{
|
|
||||||
const char* dot = strchr(table_spec, '.');
|
|
||||||
if (!dot) return 1;
|
|
||||||
uint len = (uint)strlen(table_spec);
|
|
||||||
TABLE_RULE_ENT* e = (TABLE_RULE_ENT*)my_malloc(sizeof(TABLE_RULE_ENT)
|
|
||||||
+ len, MYF(MY_WME));
|
|
||||||
if (!e) return 1;
|
|
||||||
e->db = (char*)e + sizeof(TABLE_RULE_ENT);
|
|
||||||
e->tbl_name = e->db + (dot - table_spec) + 1;
|
|
||||||
e->key_len = len;
|
|
||||||
memcpy(e->db, table_spec, len);
|
|
||||||
insert_dynamic(a, (gptr)&e);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void free_string_array(DYNAMIC_ARRAY *a)
|
|
||||||
{
|
|
||||||
uint i;
|
|
||||||
for (i = 0; i < a->elements; i++)
|
|
||||||
{
|
|
||||||
char* p;
|
|
||||||
get_dynamic(a, (gptr) &p, i);
|
|
||||||
my_free(p, MYF(MY_WME));
|
|
||||||
}
|
|
||||||
delete_dynamic(a);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef NOT_USED_YET
|
#ifdef NOT_USED_YET
|
||||||
static int end_slave_on_walk(MASTER_INFO* mi, gptr /*unused*/)
|
static int end_slave_on_walk(MASTER_INFO* mi, gptr /*unused*/)
|
||||||
{
|
{
|
||||||
|
@ -1065,14 +826,6 @@ void end_slave()
|
||||||
*/
|
*/
|
||||||
terminate_slave_threads(active_mi,SLAVE_FORCE_ALL);
|
terminate_slave_threads(active_mi,SLAVE_FORCE_ALL);
|
||||||
end_master_info(active_mi);
|
end_master_info(active_mi);
|
||||||
if (do_table_inited)
|
|
||||||
hash_free(&replicate_do_table);
|
|
||||||
if (ignore_table_inited)
|
|
||||||
hash_free(&replicate_ignore_table);
|
|
||||||
if (wild_do_table_inited)
|
|
||||||
free_string_array(&replicate_wild_do_table);
|
|
||||||
if (wild_ignore_table_inited)
|
|
||||||
free_string_array(&replicate_wild_ignore_table);
|
|
||||||
delete active_mi;
|
delete active_mi;
|
||||||
active_mi= 0;
|
active_mi= 0;
|
||||||
}
|
}
|
||||||
|
@ -1152,24 +905,6 @@ bool net_request_file(NET* net, const char* fname)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const char *rewrite_db(const char* db, uint32 *new_len)
|
|
||||||
{
|
|
||||||
if (replicate_rewrite_db.is_empty() || !db)
|
|
||||||
return db;
|
|
||||||
I_List_iterator<i_string_pair> it(replicate_rewrite_db);
|
|
||||||
i_string_pair* tmp;
|
|
||||||
|
|
||||||
while ((tmp=it++))
|
|
||||||
{
|
|
||||||
if (!strcmp(tmp->key, db))
|
|
||||||
{
|
|
||||||
*new_len= (uint32)strlen(tmp->val);
|
|
||||||
return tmp->val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return db;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
From other comments and tests in code, it looks like
|
From other comments and tests in code, it looks like
|
||||||
sometimes Query_log_event and Load_log_event can have db == 0
|
sometimes Query_log_event and Load_log_event can have db == 0
|
||||||
|
@ -1182,60 +917,6 @@ const char *print_slave_db_safe(const char* db)
|
||||||
return (db ? db : "");
|
return (db ? db : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
Checks whether a db matches some do_db and ignore_db rules
|
|
||||||
(for logging or replication)
|
|
||||||
|
|
||||||
SYNOPSIS
|
|
||||||
db_ok()
|
|
||||||
db name of the db to check
|
|
||||||
do_list either binlog_do_db or replicate_do_db
|
|
||||||
ignore_list either binlog_ignore_db or replicate_ignore_db
|
|
||||||
|
|
||||||
RETURN VALUES
|
|
||||||
0 should not be logged/replicated
|
|
||||||
1 should be logged/replicated
|
|
||||||
*/
|
|
||||||
|
|
||||||
int db_ok(const char* db, I_List<i_string> &do_list,
|
|
||||||
I_List<i_string> &ignore_list )
|
|
||||||
{
|
|
||||||
if (do_list.is_empty() && ignore_list.is_empty())
|
|
||||||
return 1; // ok to replicate if the user puts no constraints
|
|
||||||
|
|
||||||
/*
|
|
||||||
If the user has specified restrictions on which databases to replicate
|
|
||||||
and db was not selected, do not replicate.
|
|
||||||
*/
|
|
||||||
if (!db)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (!do_list.is_empty()) // if the do's are not empty
|
|
||||||
{
|
|
||||||
I_List_iterator<i_string> it(do_list);
|
|
||||||
i_string* tmp;
|
|
||||||
|
|
||||||
while ((tmp=it++))
|
|
||||||
{
|
|
||||||
if (!strcmp(tmp->ptr, db))
|
|
||||||
return 1; // match
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else // there are some elements in the don't, otherwise we cannot get here
|
|
||||||
{
|
|
||||||
I_List_iterator<i_string> it(ignore_list);
|
|
||||||
i_string* tmp;
|
|
||||||
|
|
||||||
while ((tmp=it++))
|
|
||||||
{
|
|
||||||
if (!strcmp(tmp->ptr, db))
|
|
||||||
return 0; // match
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int init_strvar_from_file(char *var, int max_size, IO_CACHE *f,
|
static int init_strvar_from_file(char *var, int max_size, IO_CACHE *f,
|
||||||
const char *default_val)
|
const char *default_val)
|
||||||
|
@ -2245,48 +1926,6 @@ int register_slave_on_master(MYSQL* mysql)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Builds a String from a HASH of TABLE_RULE_ENT. Cannot be used for any other
|
|
||||||
hash, as it assumes that the hash entries are TABLE_RULE_ENT.
|
|
||||||
|
|
||||||
SYNOPSIS
|
|
||||||
table_rule_ent_hash_to_str()
|
|
||||||
s pointer to the String to fill
|
|
||||||
h pointer to the HASH to read
|
|
||||||
|
|
||||||
RETURN VALUES
|
|
||||||
none
|
|
||||||
*/
|
|
||||||
|
|
||||||
void table_rule_ent_hash_to_str(String* s, HASH* h)
|
|
||||||
{
|
|
||||||
s->length(0);
|
|
||||||
for (uint i=0 ; i < h->records ; i++)
|
|
||||||
{
|
|
||||||
TABLE_RULE_ENT* e= (TABLE_RULE_ENT*) hash_element(h, i);
|
|
||||||
if (s->length())
|
|
||||||
s->append(',');
|
|
||||||
s->append(e->db,e->key_len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Mostly the same thing as above
|
|
||||||
*/
|
|
||||||
|
|
||||||
void table_rule_ent_dynamic_array_to_str(String* s, DYNAMIC_ARRAY* a)
|
|
||||||
{
|
|
||||||
s->length(0);
|
|
||||||
for (uint i=0 ; i < a->elements ; i++)
|
|
||||||
{
|
|
||||||
TABLE_RULE_ENT* e;
|
|
||||||
get_dynamic(a, (gptr)&e, i);
|
|
||||||
if (s->length())
|
|
||||||
s->append(',');
|
|
||||||
s->append(e->db,e->key_len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool show_master_info(THD* thd, MASTER_INFO* mi)
|
bool show_master_info(THD* thd, MASTER_INFO* mi)
|
||||||
{
|
{
|
||||||
// TODO: fix this for multi-master
|
// TODO: fix this for multi-master
|
||||||
|
@ -2381,23 +2020,18 @@ bool show_master_info(THD* thd, MASTER_INFO* mi)
|
||||||
protocol->store(mi->rli.group_master_log_name, &my_charset_bin);
|
protocol->store(mi->rli.group_master_log_name, &my_charset_bin);
|
||||||
protocol->store(mi->slave_running ? "Yes":"No", &my_charset_bin);
|
protocol->store(mi->slave_running ? "Yes":"No", &my_charset_bin);
|
||||||
protocol->store(mi->rli.slave_running ? "Yes":"No", &my_charset_bin);
|
protocol->store(mi->rli.slave_running ? "Yes":"No", &my_charset_bin);
|
||||||
protocol->store(&replicate_do_db);
|
protocol->store(rpl_filter->get_do_db());
|
||||||
protocol->store(&replicate_ignore_db);
|
protocol->store(rpl_filter->get_ignore_db());
|
||||||
/*
|
|
||||||
We can't directly use some protocol->store for
|
|
||||||
replicate_*_table,
|
|
||||||
as Protocol doesn't know the TABLE_RULE_ENT struct.
|
|
||||||
We first build Strings and then pass them to protocol->store.
|
|
||||||
*/
|
|
||||||
char buf[256];
|
char buf[256];
|
||||||
String tmp(buf, sizeof(buf), &my_charset_bin);
|
String tmp(buf, sizeof(buf), &my_charset_bin);
|
||||||
table_rule_ent_hash_to_str(&tmp, &replicate_do_table);
|
rpl_filter->get_do_table(&tmp);
|
||||||
protocol->store(&tmp);
|
protocol->store(&tmp);
|
||||||
table_rule_ent_hash_to_str(&tmp, &replicate_ignore_table);
|
rpl_filter->get_ignore_table(&tmp);
|
||||||
protocol->store(&tmp);
|
protocol->store(&tmp);
|
||||||
table_rule_ent_dynamic_array_to_str(&tmp, &replicate_wild_do_table);
|
rpl_filter->get_wild_do_table(&tmp);
|
||||||
protocol->store(&tmp);
|
protocol->store(&tmp);
|
||||||
table_rule_ent_dynamic_array_to_str(&tmp, &replicate_wild_ignore_table);
|
rpl_filter->get_wild_ignore_table(&tmp);
|
||||||
protocol->store(&tmp);
|
protocol->store(&tmp);
|
||||||
|
|
||||||
protocol->store((uint32) mi->rli.last_slave_errno);
|
protocol->store((uint32) mi->rli.last_slave_errno);
|
||||||
|
@ -3845,10 +3479,8 @@ static int process_io_create_file(MASTER_INFO* mi, Create_file_log_event* cev)
|
||||||
|
|
||||||
if (unlikely(!cev->is_valid()))
|
if (unlikely(!cev->is_valid()))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
/*
|
|
||||||
TODO: fix to honor table rules, not only db rules
|
if (!rpl_filter->db_ok(cev->db))
|
||||||
*/
|
|
||||||
if (!db_ok(cev->db, replicate_do_db, replicate_ignore_db))
|
|
||||||
{
|
{
|
||||||
skip_load_data_infile(net);
|
skip_load_data_infile(net);
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
|
|
39
sql/slave.h
39
sql/slave.h
|
@ -21,10 +21,14 @@
|
||||||
|
|
||||||
#include "mysql.h"
|
#include "mysql.h"
|
||||||
#include "my_list.h"
|
#include "my_list.h"
|
||||||
|
#include "rpl_filter.h"
|
||||||
|
|
||||||
#define SLAVE_NET_TIMEOUT 3600
|
#define SLAVE_NET_TIMEOUT 3600
|
||||||
#define MAX_SLAVE_ERRMSG 1024
|
#define MAX_SLAVE_ERRMSG 1024
|
||||||
#define MAX_SLAVE_ERROR 2000
|
#define MAX_SLAVE_ERROR 2000
|
||||||
|
|
||||||
|
extern Rpl_filter *rpl_filter;
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
|
||||||
MySQL Replication
|
MySQL Replication
|
||||||
|
@ -454,15 +458,6 @@ typedef struct st_master_info
|
||||||
|
|
||||||
int queue_event(MASTER_INFO* mi,const char* buf,ulong event_len);
|
int queue_event(MASTER_INFO* mi,const char* buf,ulong event_len);
|
||||||
|
|
||||||
typedef struct st_table_rule_ent
|
|
||||||
{
|
|
||||||
char* db;
|
|
||||||
char* tbl_name;
|
|
||||||
uint key_len;
|
|
||||||
} TABLE_RULE_ENT;
|
|
||||||
|
|
||||||
#define TABLE_RULE_HASH_SIZE 16
|
|
||||||
#define TABLE_RULE_ARR_SIZE 16
|
|
||||||
#define MAX_SLAVE_ERRMSG 1024
|
#define MAX_SLAVE_ERRMSG 1024
|
||||||
|
|
||||||
#define RPL_LOG_NAME (rli->group_master_log_name[0] ? rli->group_master_log_name :\
|
#define RPL_LOG_NAME (rli->group_master_log_name[0] ? rli->group_master_log_name :\
|
||||||
|
@ -516,27 +511,9 @@ int mysql_table_dump(THD* thd, const char* db,
|
||||||
int fetch_master_table(THD* thd, const char* db_name, const char* table_name,
|
int fetch_master_table(THD* thd, const char* db_name, const char* table_name,
|
||||||
MASTER_INFO* mi, MYSQL* mysql, bool overwrite);
|
MASTER_INFO* mi, MYSQL* mysql, bool overwrite);
|
||||||
|
|
||||||
void table_rule_ent_hash_to_str(String* s, HASH* h);
|
|
||||||
void table_rule_ent_dynamic_array_to_str(String* s, DYNAMIC_ARRAY* a);
|
|
||||||
bool show_master_info(THD* thd, MASTER_INFO* mi);
|
bool show_master_info(THD* thd, MASTER_INFO* mi);
|
||||||
bool show_binlog_info(THD* thd);
|
bool show_binlog_info(THD* thd);
|
||||||
|
|
||||||
/* See if the query uses any tables that should not be replicated */
|
|
||||||
bool tables_ok(THD* thd, TABLE_LIST* tables);
|
|
||||||
|
|
||||||
/*
|
|
||||||
Check to see if the database is ok to operate on with respect to the
|
|
||||||
do and ignore lists - used in replication
|
|
||||||
*/
|
|
||||||
int db_ok(const char* db, I_List<i_string> &do_list,
|
|
||||||
I_List<i_string> &ignore_list );
|
|
||||||
int db_ok_with_wild_table(const char *db);
|
|
||||||
|
|
||||||
int add_table_rule(HASH* h, const char* table_spec);
|
|
||||||
int add_wild_table_rule(DYNAMIC_ARRAY* a, const char* table_spec);
|
|
||||||
void init_table_rule_hash(HASH* h, bool* h_inited);
|
|
||||||
void init_table_rule_array(DYNAMIC_ARRAY* a, bool* a_inited);
|
|
||||||
const char *rewrite_db(const char* db, uint32 *new_db_len);
|
|
||||||
const char *print_slave_db_safe(const char *db);
|
const char *print_slave_db_safe(const char *db);
|
||||||
int check_expected_error(THD* thd, RELAY_LOG_INFO* rli, int error_code);
|
int check_expected_error(THD* thd, RELAY_LOG_INFO* rli, int error_code);
|
||||||
void skip_load_data_infile(NET* net);
|
void skip_load_data_infile(NET* net);
|
||||||
|
@ -569,11 +546,7 @@ extern "C" pthread_handler_decl(handle_slave_sql,arg);
|
||||||
extern bool volatile abort_loop;
|
extern bool volatile abort_loop;
|
||||||
extern MASTER_INFO main_mi, *active_mi; /* active_mi for multi-master */
|
extern MASTER_INFO main_mi, *active_mi; /* active_mi for multi-master */
|
||||||
extern LIST master_list;
|
extern LIST master_list;
|
||||||
extern HASH replicate_do_table, replicate_ignore_table;
|
extern bool replicate_same_server_id;
|
||||||
extern DYNAMIC_ARRAY replicate_wild_do_table, replicate_wild_ignore_table;
|
|
||||||
extern bool do_table_inited, ignore_table_inited,
|
|
||||||
wild_do_table_inited, wild_ignore_table_inited;
|
|
||||||
extern bool table_rules_on, replicate_same_server_id;
|
|
||||||
|
|
||||||
extern int disconnect_slave_event_count, abort_slave_event_count ;
|
extern int disconnect_slave_event_count, abort_slave_event_count ;
|
||||||
|
|
||||||
|
@ -587,8 +560,6 @@ extern my_bool master_ssl;
|
||||||
extern my_string master_ssl_ca, master_ssl_capath, master_ssl_cert,
|
extern my_string master_ssl_ca, master_ssl_capath, master_ssl_cert,
|
||||||
master_ssl_cipher, master_ssl_key;
|
master_ssl_cipher, master_ssl_key;
|
||||||
|
|
||||||
extern I_List<i_string> replicate_do_db, replicate_ignore_db;
|
|
||||||
extern I_List<i_string_pair> replicate_rewrite_db;
|
|
||||||
extern I_List<THD> threads;
|
extern I_List<THD> threads;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -27,9 +27,6 @@
|
||||||
|
|
||||||
#include "mysql_priv.h"
|
#include "mysql_priv.h"
|
||||||
#include "hash_filo.h"
|
#include "hash_filo.h"
|
||||||
#ifdef HAVE_REPLICATION
|
|
||||||
#include "sql_repl.h" //for tables_ok()
|
|
||||||
#endif
|
|
||||||
#include <m_ctype.h>
|
#include <m_ctype.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include "sp_head.h"
|
#include "sp_head.h"
|
||||||
|
@ -1499,7 +1496,7 @@ static bool update_user_table(THD *thd, const char *host, const char *user,
|
||||||
GRANT and REVOKE are applied the slave in/exclusion rules as they are
|
GRANT and REVOKE are applied the slave in/exclusion rules as they are
|
||||||
some kind of updates to the mysql.% tables.
|
some kind of updates to the mysql.% tables.
|
||||||
*/
|
*/
|
||||||
if (thd->slave_thread && table_rules_on)
|
if (thd->slave_thread && rpl_filter->is_on())
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
The tables must be marked "updating" so that tables_ok() takes them into
|
The tables must be marked "updating" so that tables_ok() takes them into
|
||||||
|
@ -1507,7 +1504,7 @@ static bool update_user_table(THD *thd, const char *host, const char *user,
|
||||||
*/
|
*/
|
||||||
tables.updating= 1;
|
tables.updating= 1;
|
||||||
/* Thanks to bzero, tables.next==0 */
|
/* Thanks to bzero, tables.next==0 */
|
||||||
if (!tables_ok(0, &tables))
|
if (!rpl_filter->tables_ok(0, &tables))
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -2670,14 +2667,14 @@ bool mysql_table_grant(THD *thd, TABLE_LIST *table_list,
|
||||||
GRANT and REVOKE are applied the slave in/exclusion rules as they are
|
GRANT and REVOKE are applied the slave in/exclusion rules as they are
|
||||||
some kind of updates to the mysql.% tables.
|
some kind of updates to the mysql.% tables.
|
||||||
*/
|
*/
|
||||||
if (thd->slave_thread && table_rules_on)
|
if (thd->slave_thread && rpl_filter->is_on())
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
The tables must be marked "updating" so that tables_ok() takes them into
|
The tables must be marked "updating" so that tables_ok() takes them into
|
||||||
account in tests.
|
account in tests.
|
||||||
*/
|
*/
|
||||||
tables[0].updating= tables[1].updating= tables[2].updating= 1;
|
tables[0].updating= tables[1].updating= tables[2].updating= 1;
|
||||||
if (!tables_ok(0, tables))
|
if (!rpl_filter->tables_ok(0, tables))
|
||||||
DBUG_RETURN(FALSE);
|
DBUG_RETURN(FALSE);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -2873,14 +2870,14 @@ bool mysql_procedure_grant(THD *thd, TABLE_LIST *table_list,
|
||||||
GRANT and REVOKE are applied the slave in/exclusion rules as they are
|
GRANT and REVOKE are applied the slave in/exclusion rules as they are
|
||||||
some kind of updates to the mysql.% tables.
|
some kind of updates to the mysql.% tables.
|
||||||
*/
|
*/
|
||||||
if (thd->slave_thread && table_rules_on)
|
if (thd->slave_thread && rpl_filter->is_on())
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
The tables must be marked "updating" so that tables_ok() takes them into
|
The tables must be marked "updating" so that tables_ok() takes them into
|
||||||
account in tests.
|
account in tests.
|
||||||
*/
|
*/
|
||||||
tables[0].updating= tables[1].updating= 1;
|
tables[0].updating= tables[1].updating= 1;
|
||||||
if (!tables_ok(0, tables))
|
if (!rpl_filter->tables_ok(0, tables))
|
||||||
DBUG_RETURN(FALSE);
|
DBUG_RETURN(FALSE);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -3002,14 +2999,14 @@ bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &list,
|
||||||
GRANT and REVOKE are applied the slave in/exclusion rules as they are
|
GRANT and REVOKE are applied the slave in/exclusion rules as they are
|
||||||
some kind of updates to the mysql.% tables.
|
some kind of updates to the mysql.% tables.
|
||||||
*/
|
*/
|
||||||
if (thd->slave_thread && table_rules_on)
|
if (thd->slave_thread && rpl_filter->is_on())
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
The tables must be marked "updating" so that tables_ok() takes them into
|
The tables must be marked "updating" so that tables_ok() takes them into
|
||||||
account in tests.
|
account in tests.
|
||||||
*/
|
*/
|
||||||
tables[0].updating= tables[1].updating= 1;
|
tables[0].updating= tables[1].updating= 1;
|
||||||
if (!tables_ok(0, tables))
|
if (!rpl_filter->tables_ok(0, tables))
|
||||||
DBUG_RETURN(FALSE);
|
DBUG_RETURN(FALSE);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -4210,7 +4207,7 @@ int open_grant_tables(THD *thd, TABLE_LIST *tables)
|
||||||
GRANT and REVOKE are applied the slave in/exclusion rules as they are
|
GRANT and REVOKE are applied the slave in/exclusion rules as they are
|
||||||
some kind of updates to the mysql.% tables.
|
some kind of updates to the mysql.% tables.
|
||||||
*/
|
*/
|
||||||
if (thd->slave_thread && table_rules_on)
|
if (thd->slave_thread && rpl_filter->is_on())
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
The tables must be marked "updating" so that tables_ok() takes them into
|
The tables must be marked "updating" so that tables_ok() takes them into
|
||||||
|
@ -4218,7 +4215,7 @@ int open_grant_tables(THD *thd, TABLE_LIST *tables)
|
||||||
*/
|
*/
|
||||||
tables[0].updating=tables[1].updating=tables[2].updating=
|
tables[0].updating=tables[1].updating=tables[2].updating=
|
||||||
tables[3].updating=tables[4].updating=1;
|
tables[3].updating=tables[4].updating=1;
|
||||||
if (!tables_ok(0, tables))
|
if (!rpl_filter->tables_ok(0, tables))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
tables[0].updating=tables[1].updating=tables[2].updating=
|
tables[0].updating=tables[1].updating=tables[2].updating=
|
||||||
tables[3].updating=tables[4].updating=0;;
|
tables[3].updating=tables[4].updating=0;;
|
||||||
|
|
|
@ -14,6 +14,9 @@
|
||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||||
|
|
||||||
|
#include "slave.h" // for tables_ok(), rpl_filter
|
||||||
|
extern Rpl_filter *rpl_filter;
|
||||||
|
|
||||||
#define SELECT_ACL (1L << 0)
|
#define SELECT_ACL (1L << 0)
|
||||||
#define INSERT_ACL (1L << 1)
|
#define INSERT_ACL (1L << 1)
|
||||||
#define UPDATE_ACL (1L << 2)
|
#define UPDATE_ACL (1L << 2)
|
||||||
|
|
|
@ -466,19 +466,20 @@ public:
|
||||||
class i_string: public ilink
|
class i_string: public ilink
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
char* ptr;
|
const char* ptr;
|
||||||
i_string():ptr(0) { }
|
i_string():ptr(0) { }
|
||||||
i_string(char* s) : ptr(s) {}
|
i_string(const char* s) : ptr(s) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* needed for linked list of two strings for replicate-rewrite-db */
|
/* needed for linked list of two strings for replicate-rewrite-db */
|
||||||
class i_string_pair: public ilink
|
class i_string_pair: public ilink
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
char* key;
|
const char* key;
|
||||||
char* val;
|
const char* val;
|
||||||
i_string_pair():key(0),val(0) { }
|
i_string_pair():key(0),val(0) { }
|
||||||
i_string_pair(char* key_arg, char* val_arg) : key(key_arg),val(val_arg) {}
|
i_string_pair(const char* key_arg, const char* val_arg) :
|
||||||
|
key(key_arg),val(val_arg) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
#include "mysql_priv.h"
|
#include "mysql_priv.h"
|
||||||
#include "sql_repl.h"
|
#include "sql_repl.h"
|
||||||
|
#include "rpl_filter.h"
|
||||||
#include "repl_failsafe.h"
|
#include "repl_failsafe.h"
|
||||||
#include <m_ctype.h>
|
#include <m_ctype.h>
|
||||||
#include <myisam.h>
|
#include <myisam.h>
|
||||||
|
@ -167,10 +168,12 @@ static bool begin_trans(THD *thd)
|
||||||
#ifdef HAVE_REPLICATION
|
#ifdef HAVE_REPLICATION
|
||||||
inline bool all_tables_not_ok(THD *thd, TABLE_LIST *tables)
|
inline bool all_tables_not_ok(THD *thd, TABLE_LIST *tables)
|
||||||
{
|
{
|
||||||
return (table_rules_on && tables && !tables_ok(thd,tables) &&
|
return (rpl_filter->is_on() && tables &&
|
||||||
|
!rpl_filter->tables_ok(thd->db, tables) &&
|
||||||
((thd->lex->sql_command != SQLCOM_DELETE_MULTI) ||
|
((thd->lex->sql_command != SQLCOM_DELETE_MULTI) ||
|
||||||
!tables_ok(thd,
|
!rpl_filter->tables_ok(thd->db,
|
||||||
(TABLE_LIST *)thd->lex->auxilliary_table_list.first)));
|
(TABLE_LIST *)
|
||||||
|
thd->lex->auxilliary_table_list.first)));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -3441,9 +3444,9 @@ unsent_create_error:
|
||||||
above was not called. So we have to check rules again here.
|
above was not called. So we have to check rules again here.
|
||||||
*/
|
*/
|
||||||
#ifdef HAVE_REPLICATION
|
#ifdef HAVE_REPLICATION
|
||||||
if (thd->slave_thread &&
|
if (thd->slave_thread &&
|
||||||
(!db_ok(lex->name, replicate_do_db, replicate_ignore_db) ||
|
(!rpl_filter->db_ok(lex->name) ||
|
||||||
!db_ok_with_wild_table(lex->name)))
|
!rpl_filter->db_ok_with_wild_table(lex->name)))
|
||||||
{
|
{
|
||||||
my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0));
|
my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0));
|
||||||
break;
|
break;
|
||||||
|
@ -3471,8 +3474,8 @@ unsent_create_error:
|
||||||
*/
|
*/
|
||||||
#ifdef HAVE_REPLICATION
|
#ifdef HAVE_REPLICATION
|
||||||
if (thd->slave_thread &&
|
if (thd->slave_thread &&
|
||||||
(!db_ok(lex->name, replicate_do_db, replicate_ignore_db) ||
|
(!rpl_filter->db_ok(lex->name) ||
|
||||||
!db_ok_with_wild_table(lex->name)))
|
!rpl_filter->db_ok_with_wild_table(lex->name)))
|
||||||
{
|
{
|
||||||
my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0));
|
my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0));
|
||||||
break;
|
break;
|
||||||
|
@ -3511,8 +3514,8 @@ unsent_create_error:
|
||||||
*/
|
*/
|
||||||
#ifdef HAVE_REPLICATION
|
#ifdef HAVE_REPLICATION
|
||||||
if (thd->slave_thread &&
|
if (thd->slave_thread &&
|
||||||
(!db_ok(db, replicate_do_db, replicate_ignore_db) ||
|
(!rpl_filter->db_ok(lex->name) ||
|
||||||
!db_ok_with_wild_table(db)))
|
!rpl_filter->db_ok_with_wild_table(lex->name)))
|
||||||
{
|
{
|
||||||
my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0));
|
my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0));
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#include "sql_repl.h"
|
#include "sql_repl.h"
|
||||||
#include "log_event.h"
|
#include "log_event.h"
|
||||||
|
#include "rpl_filter.h"
|
||||||
#include <my_dir.h>
|
#include <my_dir.h>
|
||||||
|
|
||||||
int max_binlog_dump_events = 0; // unlimited
|
int max_binlog_dump_events = 0; // unlimited
|
||||||
|
@ -1429,8 +1430,8 @@ bool show_binlog_info(THD* thd)
|
||||||
int dir_len = dirname_length(li.log_file_name);
|
int dir_len = dirname_length(li.log_file_name);
|
||||||
protocol->store(li.log_file_name + dir_len, &my_charset_bin);
|
protocol->store(li.log_file_name + dir_len, &my_charset_bin);
|
||||||
protocol->store((ulonglong) li.pos);
|
protocol->store((ulonglong) li.pos);
|
||||||
protocol->store(&binlog_do_db);
|
protocol->store(binlog_filter->get_do_db());
|
||||||
protocol->store(&binlog_ignore_db);
|
protocol->store(binlog_filter->get_ignore_db());
|
||||||
if (protocol->write())
|
if (protocol->write())
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,9 @@
|
||||||
#ifdef HAVE_REPLICATION
|
#ifdef HAVE_REPLICATION
|
||||||
#include "slave.h"
|
#include "slave.h"
|
||||||
|
|
||||||
|
extern Rpl_filter *binlog_filter;
|
||||||
|
extern Rpl_filter *rpl_filter;
|
||||||
|
|
||||||
typedef struct st_slave_info
|
typedef struct st_slave_info
|
||||||
{
|
{
|
||||||
uint32 server_id;
|
uint32 server_id;
|
||||||
|
@ -31,7 +34,6 @@ typedef struct st_slave_info
|
||||||
extern my_bool opt_show_slave_auth_info;
|
extern my_bool opt_show_slave_auth_info;
|
||||||
extern char *master_host, *master_info_file;
|
extern char *master_host, *master_info_file;
|
||||||
extern bool server_id_supplied;
|
extern bool server_id_supplied;
|
||||||
extern I_List<i_string> binlog_do_db, binlog_ignore_db;
|
|
||||||
|
|
||||||
extern int max_binlog_dump_events;
|
extern int max_binlog_dump_events;
|
||||||
extern my_bool opt_sporadic_binlog_dump_fail;
|
extern my_bool opt_sporadic_binlog_dump_fail;
|
||||||
|
|
Loading…
Add table
Reference in a new issue