summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <lars@mysql.com>2005-03-21 23:05:55 +0100
committerunknown <lars@mysql.com>2005-03-21 23:05:55 +0100
commit69ca9a9416df9084c2a75aeb62a6979cecf4e5c6 (patch)
tree8b6efeea8d68c7888aaf78f4150376d941b923e5
parent796b352862a5c94ea2de1c5910ab45d2ca5eb8ae (diff)
parent03c42246a5a50ce62b49e8fce4b263b0468d5f46 (diff)
downloadmariadb-git-69ca9a9416df9084c2a75aeb62a6979cecf4e5c6.tar.gz
Merge
sql/log_event.cc: Auto merged sql/mysql_priv.h: Auto merged sql/mysqld.cc: Auto merged sql/slave.cc: Auto merged sql/slave.h: Auto merged sql/sql_acl.cc: Auto merged sql/sql_acl.h: Auto merged sql/sql_class.h: Auto merged sql/sql_parse.cc: Auto merged sql/sql_repl.cc: Auto merged sql/sql_repl.h: Auto merged sql/Makefile.am: Manual merge sql/log.cc: Manual merge
-rw-r--r--sql/Makefile.am5
-rw-r--r--sql/log.cc6
-rw-r--r--sql/log_event.cc11
-rw-r--r--sql/mysql_priv.h1
-rw-r--r--sql/mysqld.cc68
-rw-r--r--sql/repl_failsafe.cc9
-rw-r--r--sql/rpl_filter.cc539
-rw-r--r--sql/rpl_filter.h110
-rw-r--r--sql/slave.cc390
-rw-r--r--sql/slave.h39
-rw-r--r--sql/sql_acl.cc23
-rw-r--r--sql/sql_acl.h3
-rw-r--r--sql/sql_class.h11
-rw-r--r--sql/sql_parse.cc23
-rw-r--r--sql/sql_repl.cc5
-rw-r--r--sql/sql_repl.h4
16 files changed, 743 insertions, 504 deletions
diff --git a/sql/Makefile.am b/sql/Makefile.am
index bd371cd77bf..1f766564f56 100644
--- a/sql/Makefile.am
+++ b/sql/Makefile.am
@@ -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 \
sql_select.h structs.h table.h sql_udf.h hash_filo.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 \
spatial.h gstream.h client_settings.h tzfile.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_load.cc mf_iocache.cc field_conv.cc sql_show.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\
stacktrace.c repl_failsafe.h repl_failsafe.cc \
sql_olap.cc sql_view.cc \
diff --git a/sql/log.cc b/sql/log.cc
index 43786990797..f477faa4912 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -24,6 +24,7 @@
#include "mysql_priv.h"
#include "sql_repl.h"
+#include "rpl_filter.h"
#include <my_dir.h>
#include <stdarg.h>
@@ -1571,10 +1572,11 @@ bool MYSQL_LOG::write(Log_event *event_info)
binlog_[wild_]{do|ignore}_table?" (WL#1049)"
*/
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));
- 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);
}
#endif /* HAVE_REPLICATION */
diff --git a/sql/log_event.cc b/sql/log_event.cc
index ba018e859c1..7c05392a873 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -21,6 +21,7 @@
#endif
#include "mysql_priv.h"
#include "slave.h"
+#include "rpl_filter.h"
#include <my_dir.h>
#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->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_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);
- 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->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)
{
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);
thd->query_length= 0; // Should not be needed
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
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);
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;
// 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
if (net)
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index ba9f382fc33..07bc235e2eb 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -1128,7 +1128,6 @@ extern KNOWN_DATE_TIME_FORMAT known_date_time_formats[];
extern String null_string;
extern HASH open_cache;
extern TABLE *unused_tables;
-extern I_List<i_string> binlog_do_db, binlog_ignore_db;
extern const char* any_db;
extern struct my_option my_long_options[];
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 6747b79703b..682fe8b9cac 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -19,6 +19,7 @@
#include <my_dir.h>
#include "slave.h"
#include "sql_repl.h"
+#include "rpl_filter.h"
#include "repl_failsafe.h"
#include "stacktrace.h"
#include "mysqld_suffix.h"
@@ -397,12 +398,10 @@ Le_creator le_creator;
FILE *bootstrap_file;
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<NAMED_LIST> key_caches;
+Rpl_filter* rpl_filter;
+Rpl_filter* binlog_filter;
struct system_variables global_system_variables;
struct system_variables max_system_variables;
@@ -1013,12 +1012,9 @@ void clean_up(bool print_message)
free_max_user_conn();
#ifdef HAVE_REPLICATION
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
+ delete binlog_filter;
+ delete rpl_filter;
#ifdef HAVE_OPENSSL
if (ssl_acceptor_fd)
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)
#endif
{
-
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
#ifdef _CUSTOMSTARTUPCONFIG_
@@ -3309,7 +3312,6 @@ default_service_handling(char **argv,
int main(int argc, char **argv)
{
-
/* When several instances are running on the same machine, we
need to have an unique named hEventShudown through the
application PID e.g.: MySQLShutdown1890; MySQLShutdown2342
@@ -5882,13 +5884,6 @@ static void mysql_init_variables(void)
exit(1);
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 */
strmake(language, LANGUAGE, sizeof(language)-1);
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:
{
- i_string *db = new i_string(argument);
- replicate_ignore_db.push_back(db);
+ rpl_filter->add_ignore_db(argument);
break;
}
case (int)OPT_REPLICATE_DO_DB:
{
- i_string *db = new i_string(argument);
- replicate_do_db.push_back(db);
+ rpl_filter->add_do_db(argument);
break;
}
case (int)OPT_REPLICATE_REWRITE_DB:
@@ -6183,71 +6176,54 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
exit(1);
}
- i_string_pair *db_pair = new i_string_pair(key, val);
- replicate_rewrite_db.push_back(db_pair);
+ rpl_filter->add_db_rewrite(key, val);
break;
}
case (int)OPT_BINLOG_IGNORE_DB:
{
- i_string *db = new i_string(argument);
- binlog_ignore_db.push_back(db);
+ binlog_filter->add_ignore_db(argument);
break;
}
case (int)OPT_BINLOG_DO_DB:
{
- i_string *db = new i_string(argument);
- binlog_do_db.push_back(db);
+ binlog_filter->add_do_db(argument);
break;
}
case (int)OPT_REPLICATE_DO_TABLE:
{
- if (!do_table_inited)
- init_table_rule_hash(&replicate_do_table, &do_table_inited);
- if (add_table_rule(&replicate_do_table, argument))
+ if (rpl_filter->add_do_table(argument))
{
fprintf(stderr, "Could not add do table rule '%s'!\n", argument);
exit(1);
}
- table_rules_on = 1;
break;
}
case (int)OPT_REPLICATE_WILD_DO_TABLE:
{
- if (!wild_do_table_inited)
- init_table_rule_array(&replicate_wild_do_table,
- &wild_do_table_inited);
- if (add_wild_table_rule(&replicate_wild_do_table, argument))
+ if (rpl_filter->add_wild_do_table(argument))
{
fprintf(stderr, "Could not add do table rule '%s'!\n", argument);
exit(1);
}
- table_rules_on = 1;
break;
}
case (int)OPT_REPLICATE_WILD_IGNORE_TABLE:
{
- if (!wild_ignore_table_inited)
- init_table_rule_array(&replicate_wild_ignore_table,
- &wild_ignore_table_inited);
- if (add_wild_table_rule(&replicate_wild_ignore_table, argument))
+ if (rpl_filter->add_wild_ignore_table(argument))
{
fprintf(stderr, "Could not add ignore table rule '%s'!\n", argument);
exit(1);
}
- table_rules_on = 1;
break;
}
case (int)OPT_REPLICATE_IGNORE_TABLE:
{
- if (!ignore_table_inited)
- init_table_rule_hash(&replicate_ignore_table, &ignore_table_inited);
- if (add_table_rule(&replicate_ignore_table, argument))
+ if (rpl_filter->add_ignore_table(argument))
{
fprintf(stderr, "Could not add ignore table rule '%s'!\n", argument);
exit(1);
}
- table_rules_on = 1;
break;
}
#endif /* HAVE_REPLICATION */
diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc
index de4ad83fdbb..ec4682e37b5 100644
--- a/sql/repl_failsafe.cc
+++ b/sql/repl_failsafe.cc
@@ -20,6 +20,7 @@
#include "repl_failsafe.h"
#include "sql_repl.h"
#include "slave.h"
+#include "rpl_filter.h"
#include "log_event.h"
#include <mysql.h>
@@ -735,14 +736,14 @@ static int fetch_db_tables(THD *thd, MYSQL *mysql, const char *db,
TABLE_LIST table;
const char* table_name= row[0];
int error;
- if (table_rules_on)
+ if (rpl_filter->is_on())
{
bzero((char*) &table, sizeof(table)); //just for safe
table.db= (char*) db;
table.table_name= (char*) table_name;
table.updating= 1;
- if (!tables_ok(thd, &table))
+ if (!rpl_filter->tables_ok(thd->db, &table))
continue;
}
/* download master's table and overwrite slave's table */
@@ -860,8 +861,8 @@ bool load_master_data(THD* thd)
data from master
*/
- if (!db_ok(db, replicate_do_db, replicate_ignore_db) ||
- !db_ok_with_wild_table(db) ||
+ if (!rpl_filter->db_ok(db) ||
+ !rpl_filter->db_ok_with_wild_table(db) ||
!strcmp(db,"mysql"))
{
*cur_table_res = 0;
diff --git a/sql/rpl_filter.cc b/sql/rpl_filter.cc
new file mode 100644
index 00000000000..f9f8a3e98a7
--- /dev/null
+++ b/sql/rpl_filter.cc
@@ -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;
+}
diff --git a/sql/rpl_filter.h b/sql/rpl_filter.h
new file mode 100644
index 00000000000..70bb137790e
--- /dev/null
+++ b/sql/rpl_filter.h
@@ -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__
diff --git a/sql/slave.cc b/sql/slave.cc
index 73dd0fd13c3..838efae6d11 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -22,6 +22,7 @@
#include <myisam.h>
#include "slave.h"
#include "sql_repl.h"
+#include "rpl_filter.h"
#include "repl_failsafe.h"
#include <thr_alarm.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;
char* slave_load_tmpdir = 0;
MASTER_INFO *active_mi;
-HASH replicate_do_table, replicate_ignore_table;
-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;
+bool replicate_same_server_id;
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
@@ -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
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);
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;
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
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 : "");
}
-/*
- 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,
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)
{
// 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->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(&replicate_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.
- */
+ protocol->store(rpl_filter->get_do_db());
+ protocol->store(rpl_filter->get_ignore_db());
+
char buf[256];
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);
- table_rule_ent_hash_to_str(&tmp, &replicate_ignore_table);
+ rpl_filter->get_ignore_table(&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);
- table_rule_ent_dynamic_array_to_str(&tmp, &replicate_wild_ignore_table);
+ rpl_filter->get_wild_ignore_table(&tmp);
protocol->store(&tmp);
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()))
DBUG_RETURN(1);
- /*
- TODO: fix to honor table rules, not only db rules
- */
- if (!db_ok(cev->db, replicate_do_db, replicate_ignore_db))
+
+ if (!rpl_filter->db_ok(cev->db))
{
skip_load_data_infile(net);
DBUG_RETURN(0);
diff --git a/sql/slave.h b/sql/slave.h
index ee5541ffe08..a29315f7ae4 100644
--- a/sql/slave.h
+++ b/sql/slave.h
@@ -21,10 +21,14 @@
#include "mysql.h"
#include "my_list.h"
+#include "rpl_filter.h"
+
#define SLAVE_NET_TIMEOUT 3600
#define MAX_SLAVE_ERRMSG 1024
#define MAX_SLAVE_ERROR 2000
+extern Rpl_filter *rpl_filter;
+
/*****************************************************************************
MySQL Replication
@@ -454,15 +458,6 @@ typedef struct st_master_info
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 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,
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_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);
int check_expected_error(THD* thd, RELAY_LOG_INFO* rli, int error_code);
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 MASTER_INFO main_mi, *active_mi; /* active_mi for multi-master */
extern LIST master_list;
-extern HASH replicate_do_table, replicate_ignore_table;
-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 bool replicate_same_server_id;
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,
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;
#endif
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index b71b79cb1c6..3e6aba32feb 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -27,9 +27,6 @@
#include "mysql_priv.h"
#include "hash_filo.h"
-#ifdef HAVE_REPLICATION
-#include "sql_repl.h" //for tables_ok()
-#endif
#include <m_ctype.h>
#include <stdarg.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
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
@@ -1507,7 +1504,7 @@ static bool update_user_table(THD *thd, const char *host, const char *user,
*/
tables.updating= 1;
/* Thanks to bzero, tables.next==0 */
- if (!tables_ok(0, &tables))
+ if (!rpl_filter->tables_ok(0, &tables))
DBUG_RETURN(0);
}
#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
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
account in tests.
*/
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);
}
#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
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
account in tests.
*/
tables[0].updating= tables[1].updating= 1;
- if (!tables_ok(0, tables))
+ if (!rpl_filter->tables_ok(0, tables))
DBUG_RETURN(FALSE);
}
#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
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
account in tests.
*/
tables[0].updating= tables[1].updating= 1;
- if (!tables_ok(0, tables))
+ if (!rpl_filter->tables_ok(0, tables))
DBUG_RETURN(FALSE);
}
#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
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
@@ -4218,7 +4215,7 @@ int open_grant_tables(THD *thd, TABLE_LIST *tables)
*/
tables[0].updating=tables[1].updating=tables[2].updating=
tables[3].updating=tables[4].updating=1;
- if (!tables_ok(0, tables))
+ if (!rpl_filter->tables_ok(0, tables))
DBUG_RETURN(1);
tables[0].updating=tables[1].updating=tables[2].updating=
tables[3].updating=tables[4].updating=0;;
diff --git a/sql/sql_acl.h b/sql/sql_acl.h
index fd22da2a9fc..21f14fc3045 100644
--- a/sql/sql_acl.h
+++ b/sql/sql_acl.h
@@ -14,6 +14,9 @@
along with this program; if not, write to the Free Software
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 INSERT_ACL (1L << 1)
#define UPDATE_ACL (1L << 2)
diff --git a/sql/sql_class.h b/sql/sql_class.h
index ffb7a9ab12d..469eb86803a 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -466,19 +466,20 @@ public:
class i_string: public ilink
{
public:
- char* ptr;
+ const char* ptr;
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 */
class i_string_pair: public ilink
{
public:
- char* key;
- char* val;
+ const char* key;
+ const char* val;
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) {}
};
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index e8cc445e123..981013479df 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -16,6 +16,7 @@
#include "mysql_priv.h"
#include "sql_repl.h"
+#include "rpl_filter.h"
#include "repl_failsafe.h"
#include <m_ctype.h>
#include <myisam.h>
@@ -167,10 +168,12 @@ static bool begin_trans(THD *thd)
#ifdef HAVE_REPLICATION
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) ||
- !tables_ok(thd,
- (TABLE_LIST *)thd->lex->auxilliary_table_list.first)));
+ !rpl_filter->tables_ok(thd->db,
+ (TABLE_LIST *)
+ thd->lex->auxilliary_table_list.first)));
}
#endif
@@ -3441,9 +3444,9 @@ unsent_create_error:
above was not called. So we have to check rules again here.
*/
#ifdef HAVE_REPLICATION
- if (thd->slave_thread &&
- (!db_ok(lex->name, replicate_do_db, replicate_ignore_db) ||
- !db_ok_with_wild_table(lex->name)))
+ if (thd->slave_thread &&
+ (!rpl_filter->db_ok(lex->name) ||
+ !rpl_filter->db_ok_with_wild_table(lex->name)))
{
my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0));
break;
@@ -3471,8 +3474,8 @@ unsent_create_error:
*/
#ifdef HAVE_REPLICATION
if (thd->slave_thread &&
- (!db_ok(lex->name, replicate_do_db, replicate_ignore_db) ||
- !db_ok_with_wild_table(lex->name)))
+ (!rpl_filter->db_ok(lex->name) ||
+ !rpl_filter->db_ok_with_wild_table(lex->name)))
{
my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0));
break;
@@ -3511,8 +3514,8 @@ unsent_create_error:
*/
#ifdef HAVE_REPLICATION
if (thd->slave_thread &&
- (!db_ok(db, replicate_do_db, replicate_ignore_db) ||
- !db_ok_with_wild_table(db)))
+ (!rpl_filter->db_ok(lex->name) ||
+ !rpl_filter->db_ok_with_wild_table(lex->name)))
{
my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0));
break;
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index 634b6ab0995..b1e169b9427 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -19,6 +19,7 @@
#include "sql_repl.h"
#include "log_event.h"
+#include "rpl_filter.h"
#include <my_dir.h>
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);
protocol->store(li.log_file_name + dir_len, &my_charset_bin);
protocol->store((ulonglong) li.pos);
- protocol->store(&binlog_do_db);
- protocol->store(&binlog_ignore_db);
+ protocol->store(binlog_filter->get_do_db());
+ protocol->store(binlog_filter->get_ignore_db());
if (protocol->write())
DBUG_RETURN(TRUE);
}
diff --git a/sql/sql_repl.h b/sql/sql_repl.h
index 9eb6456ee20..eec85826da4 100644
--- a/sql/sql_repl.h
+++ b/sql/sql_repl.h
@@ -17,6 +17,9 @@
#ifdef HAVE_REPLICATION
#include "slave.h"
+extern Rpl_filter *binlog_filter;
+extern Rpl_filter *rpl_filter;
+
typedef struct st_slave_info
{
uint32 server_id;
@@ -31,7 +34,6 @@ typedef struct st_slave_info
extern my_bool opt_show_slave_auth_info;
extern char *master_host, *master_info_file;
extern bool server_id_supplied;
-extern I_List<i_string> binlog_do_db, binlog_ignore_db;
extern int max_binlog_dump_events;
extern my_bool opt_sporadic_binlog_dump_fail;