diff options
author | Alexander Ivanov <alexi1952@yandex.ru> | 2009-10-16 15:58:16 +0400 |
---|---|---|
committer | Alexander Ivanov <alexi1952@yandex.ru> | 2009-10-16 15:58:16 +0400 |
commit | ef5874d154849a21fd5bd42124df31f4d35b558d (patch) | |
tree | 7f95a6506d343c92bf4e9c6f5f77c96c12963bee | |
parent | 6bc7eab161508115168359460b9d52aff153dbaf (diff) | |
download | mariadb-git-ef5874d154849a21fd5bd42124df31f4d35b558d.tar.gz |
MWL#36: Add a mysqlbinlog option to change the used database.
Add rewrite_db() member to the Table_map_log_event class.
Each RBR-event in binary log is preceded by a Table_map event
containing a (db_id, db_name) pair. The rewrite_db(new_name)
function replaces db_name by new_name in a buffer containing
Table_map event read from the binary log.
-rw-r--r-- | sql/log_event.cc | 94 | ||||
-rw-r--r-- | sql/log_event.h | 2 |
2 files changed, 96 insertions, 0 deletions
diff --git a/sql/log_event.cc b/sql/log_event.cc index f33ee8310cf..8c28903d9cc 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -8005,6 +8005,100 @@ Table_map_log_event::~Table_map_log_event() my_free(m_memory, MYF(MY_ALLOW_ZERO_PTR)); } + +#ifdef MYSQL_CLIENT +/* + 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. + On success returns 0, on failure return non-zero value. +*/ +int Table_map_log_event::rewrite_db( + const char* new_db, + size_t new_len, + const Format_description_log_event* desc) +{ + DBUG_ENTER("Table_map_log_event::rewrite_db"); + DBUG_ASSERT(temp_buf); + + uint header_len= min(desc->common_header_len, + LOG_EVENT_MINIMAL_HEADER_LEN) + TABLE_MAP_HEADER_LEN; + int len_diff; + + if (!(len_diff= new_len - m_dblen)) + { + memcpy((void*) (temp_buf + header_len + 1), new_db, m_dblen + 1); + memcpy((void*) m_dbnam, new_db, m_dblen + 1); + DBUG_RETURN(0); + } + + // Create new temp_buf + ulong event_cur_len= uint4korr(temp_buf + EVENT_LEN_OFFSET); + ulong event_new_len= event_cur_len + len_diff; + char* new_temp_buf= (char*) my_malloc(event_new_len, MYF(MY_WME)); + + if (!new_temp_buf) + { + sql_print_error("Table_map_log_event::rewrite_dbname: " + "failed to allocate new temp_buf (%d bytes required)", event_new_len); + DBUG_RETURN(-1); + } + + // Rewrite temp_buf + char* ptr= new_temp_buf; + ulong cnt= 0; + + // Copy header and change event length + memcpy(ptr, temp_buf, header_len); + int4store(ptr + EVENT_LEN_OFFSET, event_new_len); + ptr += header_len; + cnt += header_len; + + // Write new db name length and new name + *ptr++ = new_len; + memcpy(ptr, new_db, new_len + 1); + ptr += new_len + 1; + cnt += m_dblen + 2; + + // Copy rest part + memcpy(ptr, temp_buf + cnt, event_cur_len - cnt); + + // Reregister temp buf + free_temp_buf(); + register_temp_buf(new_temp_buf); + + // Reset m_dbnam and m_dblen members + m_dblen= new_len; + + // m_dbnam resides in m_memory together with m_tblnam and m_coltype + uchar* memory= m_memory; + char const* tblnam= m_tblnam; + uchar* coltype= m_coltype; + + m_memory= (uchar*) my_multi_malloc(MYF(MY_WME), + &m_dbnam, (uint) m_dblen + 1, + &m_tblnam, (uint) m_tbllen + 1, + &m_coltype, (uint) m_colcnt, + NullS); + + if (!m_memory) + { + sql_print_error("Table_map_log_event::rewrite_dbname: " + "failed to allocate new m_memory (%d + %d + %d bytes required)", + m_dblen + 1, m_tbllen + 1, m_colcnt); + DBUG_RETURN(-1); + } + + memcpy((void*)m_dbnam, new_db, m_dblen + 1); + memcpy((void*)m_tblnam, tblnam, m_tbllen + 1); + memcpy(m_coltype, coltype, m_colcnt); + + my_free(memory, MYF(MY_WME)); + DBUG_RETURN(0); +} +#endif /* MYSQL_CLIENT */ + + /* Return value is an error code, one of: diff --git a/sql/log_event.h b/sql/log_event.h index 13ab4330415..43e7b9e2205 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -3310,6 +3310,8 @@ public: ulong get_table_id() const { return m_table_id; } const char *get_table_name() const { return m_tblnam; } const char *get_db_name() const { return m_dbnam; } + int rewrite_db(const char* new_name, size_t new_name_len, + const Format_description_log_event*); #endif virtual Log_event_type get_type_code() { return TABLE_MAP_EVENT; } |