Commit 8e160e2f authored by Alexander Ivanov's avatar Alexander Ivanov

MWL#36: Add a mysqlbinlog option to change the used database.

Add --rewrite-db option to mysqlbinlog.
parent ab2fdf78
...@@ -81,5 +81,6 @@ enum options_client ...@@ -81,5 +81,6 @@ enum options_client
OPT_DEBUG_INFO, OPT_DEBUG_CHECK, OPT_COLUMN_TYPES, OPT_ERROR_LOG_FILE, OPT_DEBUG_INFO, OPT_DEBUG_CHECK, OPT_COLUMN_TYPES, OPT_ERROR_LOG_FILE,
OPT_WRITE_BINLOG, OPT_DUMP_DATE, OPT_WRITE_BINLOG, OPT_DUMP_DATE,
OPT_ABORT_SOURCE_ON_ERROR, OPT_ABORT_SOURCE_ON_ERROR,
OPT_REWRITE_DB,
OPT_MAX_CLIENT_OPTION OPT_MAX_CLIENT_OPTION
}; };
...@@ -627,6 +627,41 @@ static bool shall_skip_database(const char *log_dbname) ...@@ -627,6 +627,41 @@ static bool shall_skip_database(const char *log_dbname)
} }
/**
Prints "use <db>" statement when current db is to be changed.
We have to control emiting USE statements according to rewrite-db options.
We have to do it here (see process_event() below) and to suppress
producing USE statements by corresponding log event print-functions.
*/
void print_use_stmt(PRINT_EVENT_INFO* pinfo, const char* db, size_t db_len)
{
// pinfo->db is the current db.
// If current db is the same as required db, do nothing.
if (!db || !memcmp(pinfo->db, db, db_len + 1))
return;
// Current db and required db are different.
// Check for rewrite rule for required db. (Note that in a rewrite rule
// neither db_from nor db_to part can be empty).
size_t len_to= 0;
const char *db_to= binlog_filter->get_rewrite_db(db, &len_to);
// If there is no rewrite rule for db (in this case len_to is left = 0),
// printing of the corresponding USE statement is left for log event
// print-function.
if (!len_to)
return;
// In case of rewrite rule print USE statement for db_to
fprintf(result_file, "use %s%s\n", db_to, pinfo->delimiter);
// Copy the *original* db to pinfo to suppress emiting
// of USE stmts by log_event print-functions.
memcpy(pinfo->db, db, db_len + 1);
}
/** /**
Prints the given event in base64 format. Prints the given event in base64 format.
...@@ -738,8 +773,11 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev, ...@@ -738,8 +773,11 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
switch (ev_type) { switch (ev_type) {
case QUERY_EVENT: case QUERY_EVENT:
if (shall_skip_database(((Query_log_event*)ev)->db)) {
Query_log_event *qe= (Query_log_event*)ev;
if (shall_skip_database(qe->db))
goto end; goto end;
print_use_stmt(print_event_info, qe->db, qe->db_len);
if (opt_base64_output_mode == BASE64_OUTPUT_ALWAYS) if (opt_base64_output_mode == BASE64_OUTPUT_ALWAYS)
{ {
if ((retval= write_event_header_and_base64(ev, result_file, if ((retval= write_event_header_and_base64(ev, result_file,
...@@ -750,6 +788,7 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev, ...@@ -750,6 +788,7 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
else else
ev->print(result_file, print_event_info); ev->print(result_file, print_event_info);
break; break;
}
case CREATE_FILE_EVENT: case CREATE_FILE_EVENT:
{ {
...@@ -867,6 +906,7 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev, ...@@ -867,6 +906,7 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
if (!shall_skip_database(exlq->db)) if (!shall_skip_database(exlq->db))
{ {
print_use_stmt(print_event_info, exlq->db, exlq->db_len);
if (fname) if (fname)
{ {
convert_path_to_forward_slashes(fname); convert_path_to_forward_slashes(fname);
...@@ -890,6 +930,13 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev, ...@@ -890,6 +930,13 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
destroy_evt= FALSE; destroy_evt= FALSE;
goto end; goto end;
} }
size_t len_to= 0;
const char* db_to= binlog_filter->get_rewrite_db(map->get_db_name(), &len_to);
if (len_to && map->rewrite_db(db_to, len_to, glob_description_event))
{
error("Could not rewrite database name");
goto err;
}
} }
case WRITE_ROWS_EVENT: case WRITE_ROWS_EVENT:
case DELETE_ROWS_EVENT: case DELETE_ROWS_EVENT:
...@@ -1142,6 +1189,9 @@ that may lead to an endless loop.", ...@@ -1142,6 +1189,9 @@ that may lead to an endless loop.",
"Used to reserve file descriptors for usage by this program", "Used to reserve file descriptors for usage by this program",
(uchar**) &open_files_limit, (uchar**) &open_files_limit, 0, GET_ULONG, (uchar**) &open_files_limit, (uchar**) &open_files_limit, 0, GET_ULONG,
REQUIRED_ARG, MY_NFILE, 8, OS_FILE_LIMIT, 0, 1, 0}, REQUIRED_ARG, MY_NFILE, 8, OS_FILE_LIMIT, 0, 1, 0},
{"rewrite-db", OPT_REWRITE_DB,
"Updates to a database with a different name than the original.",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
}; };
...@@ -1333,6 +1383,49 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), ...@@ -1333,6 +1383,49 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
(find_type_or_exit(argument, &base64_output_mode_typelib, opt->name)-1); (find_type_or_exit(argument, &base64_output_mode_typelib, opt->name)-1);
} }
break; break;
case OPT_REWRITE_DB: // db_from->db_to
{
char* ptr;
char* key= argument; // db-from
char* val; // db-to
// Where key begins
while (*key && my_isspace(&my_charset_latin1, *key))
key++;
// Where val begins
if (!(ptr= strstr(argument, "->")))
{ sql_print_error("Bad syntax in rewrite-db: missing '->'!\n");
return 1;
}
val= ptr + 2;
while (*val && my_isspace(&my_charset_latin1, *val))
val++;
// Write /0 and skip blanks at the end of key
*ptr-- = 0;
while (my_isspace(&my_charset_latin1, *ptr) && ptr > argument)
*ptr-- = 0;
if (!*key)
{ sql_print_error("Bad syntax in rewrite-db: empty db-from!\n");
return 1;
}
// Skip blanks at the end of val
ptr= val;
while (*ptr && !my_isspace(&my_charset_latin1, *ptr))
ptr++;
*ptr= 0;
if (!*val)
{ sql_print_error("Bad syntax in rewrite-db: empty db-to!\n");
return 1;
}
binlog_filter->add_db_rewrite(key, val);
break;
}
case 'v': case 'v':
if (argument == disabled_my_option) if (argument == disabled_my_option)
verbose= 0; verbose= 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment