Commit b027072e authored by Sergey Petrunya's avatar Sergey Petrunya

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

- Review fixes

client/Makefile.am:
  - Make it build on Linux
client/mysqlbinlog.cc:
  - Coding style fixes
  - Better/more comments
  - Use client/sql_string.*, not server's sql/sql_string.*.
  - Don't declare a dummy TABLE_LIST structure in the client.
client/sql_string.h:
  - Use client/sql_string.*, not server's sql/sql_string.*.
sql/log_event.cc:
  = Fix coding style
  = Introduce Log_event::event_owns_temp_buf which tells whether Log_event::temp_buf is 'owned' by the Log_event object and should be my_free'd on return. 
  This is needed because rewrite_db() needs to dispose of the buffer, and 
  - when mysqlbinlog is reading directly from binlog file, the buffer 
    should be freed
  - when mysqlbinlog is reading from a server, the buffer is a part of network
    buffer and shouldn't be freed.
sql/log_event.h:
  Introduce Log_event::event_owns_temp_buf which tells whether Log_event::temp_buf is 'owned' by the Log_event object and should be my_free'd on return. 
  This is needed because rewrite_db() needs to dispose of the buffer, and 
  - when mysqlbinlog is reading directly from binlog file, the buffer 
    should be freed
  - when mysqlbinlog is reading from a server, the buffer is a part of network
    buffer and shouldn't be freed.
sql/mysqld.cc:
  - Better/more comments
sql/rpl_filter.cc:
  - #ifdef-out Rpl_filter::tables_ok from the client. This allows not 
    to define dummy TABLE_LIST on the client
sql/rpl_filter.h:
  - #ifdef-out Rpl_filter::tables_ok from the client. This allows not 
    to define dummy TABLE_LIST on the client
sql/sql_string.cc:
  - Use client/sql_string.*, not server's sql/sql_string.*.
sql/sql_string.h:
  - Use client/sql_string.*, not server's sql/sql_string.*.
parent 3ea974ad
...@@ -107,7 +107,8 @@ sql_src=log_event.h mysql_priv.h rpl_constants.h \ ...@@ -107,7 +107,8 @@ sql_src=log_event.h mysql_priv.h rpl_constants.h \
rpl_utility.h rpl_tblmap.h rpl_tblmap.cc \ rpl_utility.h rpl_tblmap.h rpl_tblmap.cc \
log_event.cc my_decimal.h my_decimal.cc \ log_event.cc my_decimal.h my_decimal.cc \
log_event_old.h log_event_old.cc \ log_event_old.h log_event_old.cc \
rpl_record_old.h rpl_record_old.cc rpl_record_old.h rpl_record_old.cc \
sql_list.h rpl_filter.h sql_list.cc rpl_filter.cc
strings_src=decimal.c strings_src=decimal.c
link_sources: link_sources:
......
...@@ -35,13 +35,10 @@ ...@@ -35,13 +35,10 @@
#include "log_event.h" #include "log_event.h"
#include "sql_common.h" #include "sql_common.h"
/* Needed for Rlp_filter */
struct TABLE_LIST;
/* Needed for Rpl_filter */ /* Needed for Rpl_filter */
CHARSET_INFO* system_charset_info= &my_charset_utf8_general_ci; CHARSET_INFO* system_charset_info= &my_charset_utf8_general_ci;
#include "../sql/sql_string.h" // needed for Rpl_filter #include "sql_string.h" // needed for Rpl_filter
#include "sql_list.h" // needed for Rpl_filter #include "sql_list.h" // needed for Rpl_filter
#include "rpl_filter.h" #include "rpl_filter.h"
...@@ -628,12 +625,13 @@ static bool shall_skip_database(const char *log_dbname) ...@@ -628,12 +625,13 @@ static bool shall_skip_database(const char *log_dbname)
/** /**
Prints "use <db>" statement when current db is to be changed. Print "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 control emiting USE statements according to rewrite-db options.
We have to do it here (see process_event() below) and to suppress We have to do it here (see process_event() below) and to suppress
producing USE statements by corresponding log event print-functions. producing USE statements by corresponding log event print-functions.
*/ */
void print_use_stmt(PRINT_EVENT_INFO* pinfo, const char* db, size_t db_len) void print_use_stmt(PRINT_EVENT_INFO* pinfo, const char* db, size_t db_len)
{ {
// pinfo->db is the current db. // pinfo->db is the current db.
...@@ -1021,14 +1019,16 @@ err: ...@@ -1021,14 +1019,16 @@ err:
retval= ERROR_STOP; retval= ERROR_STOP;
end: end:
rec_count++; rec_count++;
/* /*
Destroy the log_event object. If reading from a remote host, Destroy the log_event object.
set the temp_buf to NULL so that memory isn't freed twice. MariaDB MWL#36: mainline does this:
If reading from a remote host,
set the temp_buf to NULL so that memory isn't freed twice.
We no longer do that, we use Rpl_filter::event_owns_temp_buf instead.
*/ */
if (ev) if (ev)
{ {
if (remote_opt)
ev->temp_buf= 0;
if (destroy_evt) /* destroy it later if not set (ignored table map) */ if (destroy_evt) /* destroy it later if not set (ignored table map) */
delete ev; delete ev;
} }
...@@ -1385,6 +1385,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), ...@@ -1385,6 +1385,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
break; break;
case OPT_REWRITE_DB: // db_from->db_to case OPT_REWRITE_DB: // db_from->db_to
{ {
/* See also handling of OPT_REPLICATE_REWRITE_DB in sql/mysqld.cc */
char* ptr; char* ptr;
char* key= argument; // db-from char* key= argument; // db-from
char* val; // db-to char* val; // db-to
...@@ -1395,20 +1396,22 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), ...@@ -1395,20 +1396,22 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
// Where val begins // Where val begins
if (!(ptr= strstr(argument, "->"))) if (!(ptr= strstr(argument, "->")))
{ sql_print_error("Bad syntax in rewrite-db: missing '->'!\n"); {
sql_print_error("Bad syntax in rewrite-db: missing '->'!\n");
return 1; return 1;
} }
val= ptr + 2; val= ptr + 2;
while (*val && my_isspace(&my_charset_latin1, *val)) while (*val && my_isspace(&my_charset_latin1, *val))
val++; val++;
// Write /0 and skip blanks at the end of key // Write \0 and skip blanks at the end of key
*ptr-- = 0; *ptr-- = 0;
while (my_isspace(&my_charset_latin1, *ptr) && ptr > argument) while (my_isspace(&my_charset_latin1, *ptr) && ptr > argument)
*ptr-- = 0; *ptr-- = 0;
if (!*key) if (!*key)
{ sql_print_error("Bad syntax in rewrite-db: empty db-from!\n"); {
sql_print_error("Bad syntax in rewrite-db: empty db-from!\n");
return 1; return 1;
} }
...@@ -1419,7 +1422,8 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), ...@@ -1419,7 +1422,8 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
*ptr= 0; *ptr= 0;
if (!*val) if (!*val)
{ sql_print_error("Bad syntax in rewrite-db: empty db-to!\n"); {
sql_print_error("Bad syntax in rewrite-db: empty db-to!\n");
return 1; return 1;
} }
...@@ -1691,7 +1695,7 @@ static Exit_status dump_remote_log_entries(PRINT_EVENT_INFO *print_event_info, ...@@ -1691,7 +1695,7 @@ static Exit_status dump_remote_log_entries(PRINT_EVENT_INFO *print_event_info,
If reading from a remote host, ensure the temp_buf for the If reading from a remote host, ensure the temp_buf for the
Log_event class is pointing to the incoming stream. Log_event class is pointing to the incoming stream.
*/ */
ev->register_temp_buf((char *) net->read_pos + 1); ev->register_temp_buf((char *) net->read_pos + 1, FALSE);
Log_event_type type= ev->get_type_code(); Log_event_type type= ev->get_type_code();
if (glob_description_event->binlog_version >= 3 || if (glob_description_event->binlog_version >= 3 ||
...@@ -2211,15 +2215,6 @@ int main(int argc, char** argv) ...@@ -2211,15 +2215,6 @@ int main(int argc, char** argv)
DBUG_RETURN(retval == ERROR_STOP ? 1 : 0); DBUG_RETURN(retval == ERROR_STOP ? 1 : 0);
} }
/* Redefinition for Rpl_filter::tables_ok() */
struct TABLE_LIST
{
TABLE_LIST() {}
TABLE_LIST *next_global, **prev_global;
bool updating;
char* db;
char* table_name;
};
void *sql_alloc(size_t size) void *sql_alloc(size_t size)
{ {
...@@ -2236,7 +2231,7 @@ void *sql_alloc(size_t size) ...@@ -2236,7 +2231,7 @@ void *sql_alloc(size_t size)
#include "my_decimal.cc" #include "my_decimal.cc"
#include "log_event.cc" #include "log_event.cc"
#include "log_event_old.cc" #include "log_event_old.cc"
#include "../sql/sql_string.cc" #include "sql_string.cc"
#include "sql_list.cc" #include "sql_list.cc"
#include "rpl_filter.cc" #include "rpl_filter.cc"
...@@ -15,6 +15,9 @@ ...@@ -15,6 +15,9 @@
/* This file is originally from the mysql distribution. Coded by monty */ /* This file is originally from the mysql distribution. Coded by monty */
#ifndef CLIENT_SQL_STRING_H
#define CLIENT_SQL_STRING_H
#ifdef USE_PRAGMA_INTERFACE #ifdef USE_PRAGMA_INTERFACE
#pragma interface /* gcc class implementation */ #pragma interface /* gcc class implementation */
#endif #endif
...@@ -353,3 +356,5 @@ public: ...@@ -353,3 +356,5 @@ public:
return (s->alloced && Ptr >= s->Ptr && Ptr < s->Ptr + s->str_length); return (s->alloced && Ptr >= s->Ptr && Ptr < s->Ptr + s->str_length);
} }
}; };
#endif
...@@ -1121,7 +1121,7 @@ failed my_b_read")); ...@@ -1121,7 +1121,7 @@ failed my_b_read"));
goto err; goto err;
} }
if ((res= read_log_event(buf, data_len, &error, description_event))) if ((res= read_log_event(buf, data_len, &error, description_event)))
res->register_temp_buf(buf); res->register_temp_buf(buf, TRUE);
err: err:
UNLOCK_MUTEX; UNLOCK_MUTEX;
...@@ -8007,16 +8007,26 @@ Table_map_log_event::~Table_map_log_event() ...@@ -8007,16 +8007,26 @@ Table_map_log_event::~Table_map_log_event()
#ifdef MYSQL_CLIENT #ifdef MYSQL_CLIENT
/* /*
Reset db name. This function assumes that temp_buf member contains event Rewrite database name for the event to name specified by new_db
representation taken from a binary log. It resets m_dbnam and m_dblen and SYNOPSIS
rewrites temp_buf with new db name. new_db Database name to change to
On success returns 0, on failure return non-zero value. new_len Length
desc Event describing binlog that we're writing to.
DESCRIPTION
Reset db name. This function assumes that temp_buf member contains event
representation taken from a binary log. It resets m_dbnam and m_dblen and
rewrites temp_buf with new db name.
RETURN
0 - Success
other - Error
*/ */
int Table_map_log_event::rewrite_db(
const char* new_db, int Table_map_log_event::rewrite_db(const char* new_db, size_t new_len,
size_t new_len, const Format_description_log_event* desc)
const Format_description_log_event* desc)
{ {
DBUG_ENTER("Table_map_log_event::rewrite_db"); DBUG_ENTER("Table_map_log_event::rewrite_db");
DBUG_ASSERT(temp_buf); DBUG_ASSERT(temp_buf);
...@@ -8039,8 +8049,9 @@ int Table_map_log_event::rewrite_db( ...@@ -8039,8 +8049,9 @@ int Table_map_log_event::rewrite_db(
if (!new_temp_buf) if (!new_temp_buf)
{ {
sql_print_error("Table_map_log_event::rewrite_dbname: " sql_print_error("Table_map_log_event::rewrite_db: "
"failed to allocate new temp_buf (%d bytes required)", event_new_len); "failed to allocate new temp_buf (%d bytes required)",
event_new_len);
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
...@@ -8065,7 +8076,7 @@ int Table_map_log_event::rewrite_db( ...@@ -8065,7 +8076,7 @@ int Table_map_log_event::rewrite_db(
// Reregister temp buf // Reregister temp buf
free_temp_buf(); free_temp_buf();
register_temp_buf(new_temp_buf); register_temp_buf(new_temp_buf, TRUE);
// Reset m_dbnam and m_dblen members // Reset m_dbnam and m_dblen members
m_dblen= new_len; m_dblen= new_len;
...@@ -8083,9 +8094,9 @@ int Table_map_log_event::rewrite_db( ...@@ -8083,9 +8094,9 @@ int Table_map_log_event::rewrite_db(
if (!m_memory) if (!m_memory)
{ {
sql_print_error("Table_map_log_event::rewrite_dbname: " sql_print_error("Table_map_log_event::rewrite_db: "
"failed to allocate new m_memory (%d + %d + %d bytes required)", "failed to allocate new m_memory (%d + %d + %d bytes required)",
m_dblen + 1, m_tbllen + 1, m_colcnt); m_dblen + 1, m_tbllen + 1, m_colcnt);
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
......
...@@ -873,6 +873,13 @@ public: ...@@ -873,6 +873,13 @@ public:
event's type, and its content is distributed in the event-specific fields. event's type, and its content is distributed in the event-specific fields.
*/ */
char *temp_buf; char *temp_buf;
/*
TRUE <=> this event 'owns' temp_buf and should call my_free() when done
with it
*/
bool event_owns_temp_buf;
/* /*
Timestamp on the master(for debugging and replication of Timestamp on the master(for debugging and replication of
NOW()/TIMESTAMP). It is important for queries and LOAD DATA NOW()/TIMESTAMP). It is important for queries and LOAD DATA
...@@ -1014,12 +1021,17 @@ public: ...@@ -1014,12 +1021,17 @@ public:
Log_event(const char* buf, const Format_description_log_event Log_event(const char* buf, const Format_description_log_event
*description_event); *description_event);
virtual ~Log_event() { free_temp_buf();} virtual ~Log_event() { free_temp_buf();}
void register_temp_buf(char* buf) { temp_buf = buf; } void register_temp_buf(char* buf, bool must_free)
{
temp_buf= buf;
event_owns_temp_buf= must_free;
}
void free_temp_buf() void free_temp_buf()
{ {
if (temp_buf) if (temp_buf)
{ {
my_free(temp_buf, MYF(0)); if (event_owns_temp_buf)
my_free(temp_buf, MYF(0));
temp_buf = 0; temp_buf = 0;
} }
} }
......
...@@ -8188,6 +8188,7 @@ mysqld_get_one_option(int optid, ...@@ -8188,6 +8188,7 @@ mysqld_get_one_option(int optid,
} }
case (int)OPT_REPLICATE_REWRITE_DB: case (int)OPT_REPLICATE_REWRITE_DB:
{ {
/* See also OPT_REWRITE_DB handling in client/mysqlbinlog.cc */
char* key = argument,*p, *val; char* key = argument,*p, *val;
if (!(p= strstr(argument, "->"))) if (!(p= strstr(argument, "->")))
......
...@@ -45,6 +45,7 @@ Rpl_filter::~Rpl_filter() ...@@ -45,6 +45,7 @@ Rpl_filter::~Rpl_filter()
} }
#ifndef MYSQL_CLIENT
/* /*
Returns true if table should be logged/replicated Returns true if table should be logged/replicated
...@@ -129,6 +130,7 @@ Rpl_filter::tables_ok(const char* db, TABLE_LIST* tables) ...@@ -129,6 +130,7 @@ Rpl_filter::tables_ok(const char* db, TABLE_LIST* tables)
!do_table_inited && !wild_do_table_inited); !do_table_inited && !wild_do_table_inited);
} }
#endif
/* /*
Checks whether a db matches some do_db and ignore_db rules Checks whether a db matches some do_db and ignore_db rules
......
...@@ -42,7 +42,9 @@ public: ...@@ -42,7 +42,9 @@ public:
/* Checks - returns true if ok to replicate/log */ /* Checks - returns true if ok to replicate/log */
bool tables_ok(const char* db, TABLE_LIST* tables); #ifndef MYSQL_CLIENT
bool tables_ok(const char* db, TABLE_LIST *tables);
#endif
bool db_ok(const char* db); bool db_ok(const char* db);
bool db_ok_with_wild_table(const char *db); bool db_ok_with_wild_table(const char *db);
......
...@@ -28,6 +28,9 @@ ...@@ -28,6 +28,9 @@
#endif #endif
#include "sql_string.h" #include "sql_string.h"
#ifdef MYSQL_CLIENT
#error Attempt to use server-side sql_string on client. Use client/sql_string.cc
#endif
/***************************************************************************** /*****************************************************************************
** String functions ** String functions
*****************************************************************************/ *****************************************************************************/
......
...@@ -25,6 +25,10 @@ ...@@ -25,6 +25,10 @@
#define NOT_FIXED_DEC 31 #define NOT_FIXED_DEC 31
#endif #endif
#ifdef MYSQL_CLIENT
#error Attempt to use server-side sql_string on client. Use client/sql_string.h
#endif
class String; class String;
int sortcmp(const String *a,const String *b, CHARSET_INFO *cs); int sortcmp(const String *a,const String *b, CHARSET_INFO *cs);
String *copy_if_not_alloced(String *a,String *b,uint32 arg_length); String *copy_if_not_alloced(String *a,String *b,uint32 arg_length);
......
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