summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Ivanov <alexi1952@yandex.ru>2009-10-16 15:58:16 +0400
committerAlexander Ivanov <alexi1952@yandex.ru>2009-10-16 15:58:16 +0400
commitef5874d154849a21fd5bd42124df31f4d35b558d (patch)
tree7f95a6506d343c92bf4e9c6f5f77c96c12963bee
parent6bc7eab161508115168359460b9d52aff153dbaf (diff)
downloadmariadb-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.cc94
-rw-r--r--sql/log_event.h2
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; }