Below is the list of changes that have just been committed into a local
5.1 repository of mats. When mats does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://www.mysql.com/doc/I/n/Installing_source_tree.html
ChangeSet
1.1789 05/03/14 15:07:21 mats@stripped +60 -0
Merged WL#1012 into 5.1 tree.
sql/sql_delete.cc
1.142 05/03/14 15:07:16 mats@stripped +0 -0
Merged WL#1012 into 5.1 tree.
sql/sql_class.cc
1.170 05/03/14 15:07:16 mats@stripped +0 -0
Merged WL#1012 into 5.1 tree.
sql/slave.h
1.86 05/03/14 15:07:16 mats@stripped +0 -0
Merged WL#1012 into 5.1 tree.
sql/mysqld.cc
1.440 05/03/14 15:07:16 mats@stripped +0 -0
Merged WL#1012 into 5.1 tree.
sql/log_event.h
1.105 05/03/14 15:07:16 mats@stripped +0 -1
Merged WL#1012 into 5.1 tree.
sql/log_event.cc
1.166 05/03/14 15:07:16 mats@stripped +1 -4
Merged WL#1012 into 5.1 tree.
sql/log.cc
1.153 05/03/14 15:07:16 mats@stripped +3 -21
Merged WL#1012 into 5.1 tree.
sql/handler.h
1.130 05/03/14 15:07:16 mats@stripped +16 -62
Merged WL#1012 into 5.1 tree.
mysql-test/t/user_var.test
1.23 05/03/14 15:07:16 mats@stripped +1 -2
Merged WL#1012 into 5.1 tree.
mysql-test/t/rpl_user_variables.test
1.11 05/03/14 15:07:16 mats@stripped +1 -2
Merged WL#1012 into 5.1 tree.
mysql-test/t/rpl_log_pos.test
1.33 05/03/14 15:07:16 mats@stripped +1 -2
Merged WL#1012 into 5.1 tree.
mysql-test/t/rpl_log.test
1.25 05/03/14 15:07:16 mats@stripped +3 -6
Merged WL#1012 into 5.1 tree.
mysql-test/t/rpl_loaddata_rule_s.test
1.6 05/03/14 15:07:16 mats@stripped +1 -2
Merged WL#1012 into 5.1 tree.
mysql-test/t/rpl_loaddata_rule_m.test
1.8 05/03/14 15:07:16 mats@stripped +1 -2
Merged WL#1012 into 5.1 tree.
mysql-test/t/rpl_error_ignored_table.test
1.13 05/03/14 15:07:16 mats@stripped +1 -2
Merged WL#1012 into 5.1 tree.
mysql-test/t/rpl_charset.test
1.15 05/03/14 15:07:16 mats@stripped +1 -4
Merged WL#1012 into 5.1 tree.
mysql-test/t/mysqlbinlog2.test
1.4 05/03/14 15:07:16 mats@stripped +8 -16
Merged WL#1012 into 5.1 tree.
mysql-test/t/mysqlbinlog.test
1.15 05/03/14 15:07:16 mats@stripped +3 -5
Merged WL#1012 into 5.1 tree.
mysql-test/t/mix_innodb_myisam_binlog.test
1.13 05/03/14 15:07:16 mats@stripped +12 -24
Merged WL#1012 into 5.1 tree.
mysql-test/t/ctype_ucs.test
1.26 05/03/14 15:07:16 mats@stripped +1 -2
Merged WL#1012 into 5.1 tree.
mysql-test/r/user_var.result
1.28 05/03/14 15:07:16 mats@stripped +0 -6
Merged WL#1012 into 5.1 tree.
mysql-test/r/rpl_user_variables.result
1.14 05/03/14 15:07:16 mats@stripped +0 -28
Merged WL#1012 into 5.1 tree.
mysql-test/r/rpl_until.result
1.20 05/03/14 15:07:16 mats@stripped +9 -19
Merged WL#1012 into 5.1 tree.
mysql-test/r/rpl_timezone.result
1.8 05/03/14 15:07:16 mats@stripped +0 -7
Merged WL#1012 into 5.1 tree.
mysql-test/r/rpl_temporary.result
1.17 05/03/14 15:07:16 mats@stripped +0 -13
Merged WL#1012 into 5.1 tree.
mysql-test/r/rpl_server_id2.result
1.8 05/03/14 15:07:16 mats@stripped +0 -1
Merged WL#1012 into 5.1 tree.
mysql-test/r/rpl_server_id1.result
1.7 05/03/14 15:07:16 mats@stripped +0 -1
Merged WL#1012 into 5.1 tree.
mysql-test/r/rpl_rotate_logs.result
1.66 05/03/14 15:07:16 mats@stripped +0 -4
Merged WL#1012 into 5.1 tree.
mysql-test/r/rpl_reset_slave.result
1.13 05/03/14 15:07:16 mats@stripped +0 -3
Merged WL#1012 into 5.1 tree.
mysql-test/r/rpl_replicate_do.result
1.28 05/03/14 15:07:16 mats@stripped +0 -1
Merged WL#1012 into 5.1 tree.
mysql-test/r/rpl_relayrotate.result
1.16 05/03/14 15:07:16 mats@stripped +0 -1
Merged WL#1012 into 5.1 tree.
mysql-test/r/rpl_max_relay_size.result
1.19 05/03/14 15:07:15 mats@stripped +0 -6
Merged WL#1012 into 5.1 tree.
mysql-test/r/rpl_log_pos.result
1.42 05/03/14 15:07:15 mats@stripped +6 -10
Merged WL#1012 into 5.1 tree.
mysql-test/r/rpl_log.result
1.56 05/03/14 15:07:15 mats@stripped +0 -51
Merged WL#1012 into 5.1 tree.
mysql-test/r/rpl_loaddata_rule_s.result
1.7 05/03/14 15:07:15 mats@stripped +0 -1
Merged WL#1012 into 5.1 tree.
mysql-test/r/rpl_loaddata_rule_m.result
1.13 05/03/14 15:07:15 mats@stripped +0 -3
Merged WL#1012 into 5.1 tree.
mysql-test/r/rpl_loaddata.result
1.27 05/03/14 15:07:15 mats@stripped +0 -4
Merged WL#1012 into 5.1 tree.
mysql-test/r/rpl_flush_tables.result
1.11 05/03/14 15:07:15 mats@stripped +0 -17
Merged WL#1012 into 5.1 tree.
mysql-test/r/rpl_flush_log_loop.result
1.22 05/03/14 15:07:15 mats@stripped +0 -1
Merged WL#1012 into 5.1 tree.
mysql-test/r/rpl_error_ignored_table.result
1.19 05/03/14 15:07:15 mats@stripped +0 -11
Merged WL#1012 into 5.1 tree.
mysql-test/r/rpl_charset.result
1.18 05/03/14 15:07:15 mats@stripped +0 -3
Merged WL#1012 into 5.1 tree.
mysql-test/r/rpl_change_master.result
1.16 05/03/14 15:07:15 mats@stripped +0 -2
Merged WL#1012 into 5.1 tree.
mysql-test/r/rpl000015.result
1.34 05/03/14 15:07:15 mats@stripped +0 -2
Merged WL#1012 into 5.1 tree.
mysql-test/r/mix_innodb_myisam_binlog.result
1.20 05/03/14 15:07:15 mats@stripped +0 -59
Merged WL#1012 into 5.1 tree.
mysql-test/r/insert_select.result
1.26 05/03/14 15:07:15 mats@stripped +0 -3
Merged WL#1012 into 5.1 tree.
mysql-test/r/drop_temp_table.result
1.16 05/03/14 15:07:15 mats@stripped +0 -5
Merged WL#1012 into 5.1 tree.
mysql-test/r/ctype_ucs.result
1.31 05/03/14 15:07:15 mats@stripped +0 -3
Merged WL#1012 into 5.1 tree.
sql/sql_update.cc
1.150 05/03/14 14:53:51 mats@stripped +0 -0
Auto merged
sql/sql_udf.cc
1.43 05/03/14 14:53:51 mats@stripped +0 -0
Auto merged
sql/sql_table.cc
1.223 05/03/14 14:53:51 mats@stripped +0 -0
Auto merged
sql/sql_show.cc
1.223 05/03/14 14:53:51 mats@stripped +0 -0
Auto merged
sql/sql_select.cc
1.294 05/03/14 14:53:51 mats@stripped +0 -0
Auto merged
sql/sql_insert.cc
1.144 05/03/14 14:53:50 mats@stripped +0 -0
Auto merged
sql/sql_class.h
1.223 05/03/14 14:53:50 mats@stripped +0 -0
Auto merged
sql/sql_acl.cc
1.132 05/03/14 14:53:49 mats@stripped +0 -0
Auto merged
sql/sp.cc
1.70 05/03/14 14:53:49 mats@stripped +0 -0
Auto merged
sql/slave.cc
1.241 05/03/14 14:53:49 mats@stripped +0 -0
Auto merged
sql/mysql_priv.h
1.272 05/03/14 14:53:48 mats@stripped +0 -0
Auto merged
sql/item_sum.cc
1.126 05/03/14 14:53:48 mats@stripped +0 -0
Auto merged
sql/handler.cc
1.144 05/03/14 14:53:47 mats@stripped +0 -0
Auto merged
# This is a BitKeeper patch. What follows are the unified diffs for the
# set of deltas contained in the patch. The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User: mats
# Host: romeo.kindahl.net
# Root: /home/bk/w1012-mysql-5.1/RESYNC
--- 1.143/sql/handler.cc 2005-03-02 17:04:23 +01:00
+++ 1.144/sql/handler.cc 2005-03-14 14:53:47 +01:00
@@ -2256,3 +2256,322 @@
}
return &known_extensions;
}
+
+/**************************************************************************
+ Pending_rows_events member functions
+**************************************************************************/
+
+int Pending_rows_events::
+set(THD* thd, Rows_log_event* ev)
+{
+ DBUG_ENTER("Pending_rows_events::set(THD*, Rows_log_event*)");
+ thd->transaction.m_pending_rows_event = ev;
+ DBUG_RETURN(0); // Ok
+}
+
+Rows_log_event* Pending_rows_events::
+get(THD* thd) const
+{
+ DBUG_ENTER("Pending_rows_events::get(THD*)");
+ Rows_log_event* ev = thd->transaction.m_pending_rows_event;
+ DBUG_RETURN(ev);
+}
+
+/**************************************************************************
+ Row_rw_base member functions
+**************************************************************************/
+
+size_t Row_rw_base::
+max_row_length(const byte * const record) const
+{
+ DBUG_ENTER("Row_rw_base::max_row_length");
+ DBUG_PRINT("enter", ("record = 0x%0x", record));
+
+ size_t length = m_table->s->reclength + 2 * m_table->s->fields;
+ uint* const beg = m_table->s->blob_field;
+ uint* const end = beg + m_table->s->blob_fields;
+
+ for (uint *ptr = beg ; ptr != end ; ++ptr)
+ {
+ Field_blob* const blob = (Field_blob*) m_table->field[*ptr];
+ length += blob->get_length(record + blob->offset()) + 2;
+ }
+
+ DBUG_RETURN(length);
+}
+
+size_t Row_rw_base::
+pack_row(byte *row_data, size_t max_size, const byte *record) const
+{
+ DBUG_ENTER("Row_rw_base::pack_row");
+ DBUG_PRINT("enter", ("row_data = %p, max_size = %lu, record = %p",
+ row_data, max_size, record));
+
+ byte *ptr = row_data;
+
+ bzero(row_data, max_size);
+
+ memcpy(row_data, record, m_table->s->null_bytes);
+ ptr += m_table->s->null_bytes;
+
+ for ( Field **field = m_table->field ; *field ; ++field)
+ {
+ ptrdiff_t const offset = (*field)->offset();
+ ptr = (*field)->pack(ptr, record + offset);
+ DBUG_PRINT("info", ("Packing length %d field '%s' from %p to %p + %d",
+ (*field)->field_length, (*field)->field_name,
+ ptr, record, offset));
+ }
+
+ // ptrdiff_t is signed, size_t is unsigned. Check that the conversion
+ // will work correctly.
+ DBUG_ASSERT(ptr - row_data >= 0);
+ size_t const size = (size_t) (ptr - row_data);
+ DBUG_PRINT("return", ("size = %lu", size));
+ DBUG_RETURN(size);
+}
+
+/**************************************************************************
+ Row_writer member functions
+**************************************************************************/
+
+extern ulong opt_binlog_rows_event_max_size;
+
+/*
+ Template member function for ensuring that there is an rows log
+ event of the apropriate type before proceeding.
+
+ PRE CONDITION:
+ - Events of type 'RowEventT' have the type code 'type_code'.
+
+ POST CONDITION:
+ If a non-NULL pointer is returned, the pending event for thread
+ 'thd' will be an event of type 'RowEventT' (which have the type
+ code 'type_code') will either empty or have enough space to hold
+ 'needed' bytes.
+ */
+
+template <class RowsEventT>
+Rows_log_event* Row_writer::
+prepare_pending(THD* thd, size_t needed)
+{
+ // Fetch the type code for the RowsEventT template parameter
+ int const type_code = RowsEventT::TYPE_CODE;
+
+ Rows_log_event* pending = m_pending.get(thd);
+ DBUG_ENTER("Row_writer::prepare_pending<RowsEventT>(THD*,size_t)");
+ DBUG_PRINT("enter", ("type_code=%d, needed=%d", type_code, needed));
+
+ if (pending)
+ {
+ DBUG_PRINT("info", ("pending=0x%08x [type_code=%d, size=%d]",
+ pending,
+ pending->get_type_code(),
+ pending->get_data_size()));
+ }
+ else
+ {
+ DBUG_PRINT("info", ("pending=0x%08x", pending));
+ }
+
+ DBUG_PRINT("info", ("opt_binlog_rows_event_max_size=%d",
+ opt_binlog_rows_event_max_size));
+
+ // Check if the current event is non-NULL and a write-rows event.
+ if (!pending
+ || pending->get_type_code() != type_code
+ || pending->get_data_size() + needed > opt_binlog_rows_event_max_size)
+ {
+ // If not, flush the event and create a new Write_rows_log_event.
+ Rows_log_event* ev = new RowsEventT(thd, m_table, m_tid, m_has_trans);
+ if (flush_and_set_event(thd, ev))
+ DBUG_RETURN(NULL);
+ DBUG_RETURN(ev);
+ }
+ DBUG_RETURN(pending);
+}
+
+/*
+ Instansiate the versions we need, we have -fno-implicit-template as
+ compiling option.
+*/
+
+template Rows_log_event* Row_writer::
+prepare_pending<Write_rows_log_event>(THD*, size_t);
+
+template Rows_log_event* Row_writer::
+prepare_pending<Delete_rows_log_event>(THD*, size_t);
+
+template Rows_log_event* Row_writer::
+prepare_pending<Update_rows_log_event>(THD*, size_t);
+
+
+int Row_writer::
+flush_and_set_event(THD* thd, Rows_log_event* event)
+{
+ DBUG_ENTER("Row_writer::flush_and_set_event");
+ DBUG_PRINT("enter", ("thd = 0x%0x (%s event)",
+ thd,
+ (event ? event->get_type_str() : "No")));
+
+ DBUG_ASSERT(opt_binlog_row_level);
+ DBUG_ASSERT(mysql_bin_log.is_open());
+
+ if (Rows_log_event* pending = m_pending.get(thd)) {
+ if (mysql_bin_log.write(pending)) {
+ DBUG_PRINT("exit", ("1"));
+ DBUG_RETURN(1); // Something failed
+ }
+
+ delete pending;
+ }
+
+ m_pending.set(thd, event);
+
+ DBUG_PRINT("exit", ("0"));
+ DBUG_RETURN(0); // All OK
+}
+
+int Row_writer::
+write_row(byte const *record)
+{
+ DBUG_ENTER("Row_writer::write_row");
+ DBUG_PRINT("enter", ("record = 0x%0x", record));
+
+ if (!opt_binlog_row_level || !mysql_bin_log.is_open())
+ DBUG_RETURN(0);
+
+ THD* const thd = current_thd;
+
+ /*
+ Pack records into format for transfer. We are allocating more
+ memory than needed, but that doesn't matter.
+ */
+ size_t const max_len = max_row_length(record);
+ byte* const row_data = my_malloc(max_len, MYF(MY_WME));
+ size_t const len = pack_row(row_data, max_len, record);
+
+ Rows_log_event* const
+ ev = prepare_pending<Write_rows_log_event>(thd, len);
+
+ if (ev == NULL)
+ DBUG_RETURN(1);
+
+ ev->add_row_data(row_data,len);
+
+ // add_row_data copies row_data to internal buffer
+ my_free(row_data, MYF(MY_WME));
+
+ DBUG_RETURN(0);
+}
+
+int Row_writer::
+update_row(const byte *before_record, const byte *after_record)
+{
+ DBUG_ENTER("Row_writer::update_row");
+ DBUG_PRINT("enter", ("before: 0x%0x; after: 0x%0x",
+ before_record, after_record));
+
+ if (!opt_binlog_row_level || !mysql_bin_log.is_open())
+ DBUG_RETURN(0);
+
+ THD* const thd = current_thd;
+
+ size_t const before_maxlen = max_row_length(before_record);
+ size_t const after_maxlen = max_row_length(after_record);
+
+ byte *before_row, *after_row;
+ byte* const memory = my_multi_malloc(MYF(MY_WME),
+ &before_row, before_maxlen,
+ &after_row, after_maxlen,
+ NULL);
+
+ size_t const before_size = pack_row(before_row, before_maxlen, before_record);
+ size_t const after_size = pack_row(after_row, after_maxlen, after_record);
+
+ Rows_log_event* const
+ ev = prepare_pending<Update_rows_log_event>(thd, before_size + after_size);
+
+ if (ev == NULL)
+ DBUG_RETURN(1);
+
+ ev->add_row_data(before_row, before_size);
+ ev->add_row_data(after_row, after_size);
+
+ // add_row_data copies row_data to internal buffer
+ my_free(memory, MYF(MY_WME));
+
+
+ DBUG_RETURN(0);
+}
+
+int Row_writer::
+delete_row(byte const *record)
+{
+ DBUG_ENTER("Row_writer::delete_row");
+ DBUG_PRINT("enter", ("record = 0x%0x", record));
+
+ if (!opt_binlog_row_level || !mysql_bin_log.is_open())
+ DBUG_RETURN(0);
+
+ THD* const thd = current_thd;
+
+ /*
+ Pack records into format for transfer. We are allocating more
+ memory than needed, but that doesn't matter.
+ */
+ size_t const max_len = max_row_length(record);
+ byte* const row_data = my_malloc(max_len, MYF(MY_WME));
+ size_t const len = pack_row(row_data, max_len, record);
+
+ Rows_log_event* const
+ ev = prepare_pending<Delete_rows_log_event>(thd, len);
+
+ if (ev == NULL)
+ DBUG_RETURN(1);
+
+ ev->add_row_data(row_data, len);
+
+ // add_row_data copies row_data
+ my_free(row_data, MYF(MY_WME));
+
+ DBUG_RETURN(0);
+}
+
+int Row_writer::
+write_table_map()
+{
+ DBUG_ENTER("Row_writer::write_table_map()");
+ if (!opt_binlog_row_level || !mysql_bin_log.is_open())
+ DBUG_RETURN(0);
+
+ THD* const thd = current_thd;
+ Table_map_log_event ev(thd, m_table, m_tid, m_has_trans);
+ if (mysql_bin_log.write(&ev))
+ DBUG_RETURN(1);
+ DBUG_RETURN(0);
+}
+
+
+int Row_writer::
+flush_pending_event(bool stmt_end)
+{
+ DBUG_ENTER("Row_writer::flush_pending_event(bool)");
+ if (!opt_binlog_row_level || !mysql_bin_log.is_open())
+ DBUG_RETURN(0);
+
+ THD* const thd = current_thd;
+ /*
+ Mark the event as the last event of a statement if the stmt_end flag is
+ set.
+ */
+ if (stmt_end) {
+ if (Rows_log_event* pending = m_pending.get(thd)) {
+ pending->set_flags(Rows_log_event::STMT_END_F);
+ }
+ }
+
+ DBUG_PRINT("flush", ("thd = 0x%0x", thd));
+ int const error = flush_and_set_event(thd, 0);
+ DBUG_RETURN(error);
+}
--- 1.129/sql/handler.h 2005-02-24 06:21:51 +01:00
+++ 1.130/sql/handler.h 2005-03-14 15:07:16 +01:00
@@ -402,6 +402,161 @@
} HANDLER_BUFFER;
+class Rows_log_event;
+
+/*****************************************************************************
+
+ Row event reader/writer base class.
+
+ The row event reader/writer base class contain support utilities to
+ help the row reader and row writer to perform its tasks.
+
+ The responsibilities are:
+ - Provide packing and unpacking utilities for subclasses.
+
+*****************************************************************************/
+
+class Row_rw_base {
+public:
+ typedef uint16 table_id;
+
+ Row_rw_base(THD *thd, TABLE *table)
+ : m_thd(thd), m_table(table), m_tid(4711 /* !!! dummy table id !!! */)
+ {
+ }
+
+ virtual ~Row_rw_base() { }
+
+protected:
+ size_t max_row_length(const byte *data) const;
+ size_t pack_row(byte *row_data, size_t max_len, const byte *data) const;
+
+protected:
+ // These are declared 'const' since you're not supposed to change
+ // them for the lifetime of the object.
+ THD *const m_thd;
+ TABLE *const m_table;
+ table_id const m_tid;
+};
+
+
+/*****************************************************************************
+
+ Pending rows event class
+
+ RESPONSIBILITIES
+
+ The pending rows event class will keep track of the pending rows
+ events based on the thread id.
+
+ One pending event will be available for each thread.
+
+ COLLABORATION
+
+ THD
+
+ *****************************************************************************/
+
+class Pending_rows_events {
+public:
+ Rows_log_event* get(THD* thd) const;
+ int set(THD* thd, Rows_log_event* ev);
+};
+
+
+/*****************************************************************************
+
+ Row event writer class.
+
+ The row event writer serves as a facade to the real row-level
+ events. It takes care of writing row log events at the apropriate
+ times, creating new row-level events when needed and writes them to
+ the binary log when required.
+
+ RESPONSIBILITIES
+
+ - Keeping a mapping from tables to table ids.
+ - Packing rows for transmission to the slave.
+ - Creating events and store the received rows in the event.
+ - Keeping track of the size of the event and ensure that the events
+ are within correct bounds.
+ - Sending events to the binary log.
+
+ COLLABORATION
+
+ Write_rows_log_event
+ Delete_rows_log_event
+ Update_rows_log_event
+
+ ****************************************************************************/
+
+class handler;
+
+class Row_writer : public Row_rw_base
+{
+public:
+ Row_writer(THD *thd, TABLE *table, bool has_trans)
+ : Row_rw_base(thd, table), m_has_trans(has_trans)
+ {
+ }
+
+ ~Row_writer() {}
+
+ /* Get table id for a table */
+ table_id get_table_id(TABLE* tbl) const;
+
+ int write_row(const byte *buf);
+ int update_row(const byte *old_data, const byte *new_data);
+ int delete_row(const byte *buf);
+
+ int stmt_begin() {
+ return write_table_map();
+ }
+
+ int stmt_end() {
+ return flush_pending_event(true);
+ }
+
+private:
+ int flush_pending_event(bool stmt_end);
+ int write_table_map();
+
+ int flush_and_set_event(THD*, Rows_log_event*);
+
+ template <class RowsEventT>
+ Rows_log_event* prepare_pending(THD* thd, size_t needed);
+
+ Pending_rows_events m_pending;
+ bool m_has_trans;
+};
+
+#if 0
+/*****************************************************************************
+
+ Row event reader class
+
+ The row event reader serves as a facade to the real row-level
+ events. It takes care of reading events from the binary log.
+
+ RESPONSIBILITIES
+
+ - keeping a mapping from tables to table ids
+ - unpacking rows into record format
+
+ ****************************************************************************/
+
+class Row_reader : public Row_rw_base
+{
+public:
+ Row_reader(THD *thd, TABLE *table)
+ : Row_rw_base(thd, table)
+ {
+ }
+
+ virtual ~Row_reader() {}
+};
+#endif
+
class handler :public Sql_alloc
{
protected:
@@ -469,7 +624,8 @@
key_used_on_scan(MAX_KEY), active_index(MAX_KEY),
ref_length(sizeof(my_off_t)), block_size(0),
raid_type(0), ft_handler(0), inited(NONE), implicit_emptied(0),
- pushed_cond(NULL)
+ pushed_cond(NULL),
+ m_row_writer(current_thd, table_arg, has_transactions())
{}
virtual ~handler(void) { /* TODO: DBUG_ASSERT(inited == NONE); */ }
int ha_open(const char *name, int mode, int test_if_locked);
@@ -539,11 +695,52 @@
uint get_index(void) const { return active_index; }
virtual int open(const char *name, int mode, uint test_if_locked)=0;
virtual int close(void)=0;
- virtual int write_row(byte * buf) { return HA_ERR_WRONG_COMMAND; }
- virtual int update_row(const byte * old_data, byte * new_data)
- { return HA_ERR_WRONG_COMMAND; }
- virtual int delete_row(const byte * buf)
- { return HA_ERR_WRONG_COMMAND; }
+
+ int ha_write_row(byte *buf)
+ {
+ DBUG_ENTER("ha_write_row");
+ DBUG_PRINT("enter", ("row: 0x%0x", buf));
+ if (int error = write_row(buf))
+ {
+ DBUG_PRINT("exit", ("error = %d", error));
+ DBUG_RETURN(error);
+ }
+ m_row_writer.write_row(buf);
+ DBUG_PRINT("exit", ("error = %d", 0));
+ DBUG_RETURN(0);
+ }
+
+ int ha_update_row(const byte *old_data, byte *new_data)
+ {
+ DBUG_ENTER("ha_update_row");
+ DBUG_PRINT("enter", ("before: 0x%0x; after: 0x%0x", old_data, new_data));
+ if (int error = update_row(old_data, new_data))
+ {
+ DBUG_PRINT("exit", ("error = %d", error));
+ DBUG_RETURN(error);
+ }
+ m_row_writer.update_row(old_data, new_data);
+ DBUG_PRINT("exit", ("error = %d", 0));
+ DBUG_RETURN(0);
+ }
+
+ int ha_delete_row(const byte *buf)
+ {
+ DBUG_ENTER("ha_delete_row");
+ DBUG_PRINT("enter", ("row: 0x%0x", buf));
+ if (int error = delete_row(buf))
+ {
+ DBUG_PRINT("exit", ("error = %d", error));
+ DBUG_RETURN(error);
+ }
+ m_row_writer.delete_row(buf);
+ DBUG_PRINT("exit", ("error = %d", 0));
+ DBUG_RETURN(0);
+ }
+
+ int ha_stmt_begin() { return m_row_writer.stmt_begin(); }
+ int ha_stmt_end() { return m_row_writer.stmt_end(); }
+
virtual int index_read(byte * buf, const byte * key,
uint key_len, enum ha_rkey_function find_flag)
{ return HA_ERR_WRONG_COMMAND; }
@@ -728,7 +925,7 @@
{
return memcmp(ref1, ref2, ref_length);
}
-
+
/*
Condition pushdown to storage engines
*/
@@ -762,6 +959,20 @@
Pops the top if condition stack, if stack is not empty
*/
virtual void cond_pop() { return; };
+
+private:
+ /*
+ Row-level primitives for storage engines.
+ These should be overridden by the storage engine class. To call
+ these methods, use the corresponding 'ha_*' method above.
+ */
+ virtual int write_row(byte * buf) { return HA_ERR_WRONG_COMMAND; }
+ virtual int update_row(const byte * old_data, byte * new_data)
+ { return HA_ERR_WRONG_COMMAND; }
+ virtual int delete_row(const byte * buf)
+ { return HA_ERR_WRONG_COMMAND; }
+
+ Row_writer m_row_writer;
};
/* Some extern variables used with handlers */
--- 1.125/sql/item_sum.cc 2005-03-01 21:19:14 +01:00
+++ 1.126/sql/item_sum.cc 2005-03-14 14:53:48 +01:00
@@ -2142,7 +2142,7 @@
restore_record(table,default_values) in setup()
*/
memcpy(buf + item->rec_offset, key, item->tree->size_of_element);
- if ((error = item->table->file->write_row(buf)))
+ if ((error = item->table->file->ha_write_row(buf)))
{
if (error != HA_ERR_FOUND_DUPP_KEY &&
error != HA_ERR_FOUND_DUPP_UNIQUE)
@@ -2394,7 +2394,7 @@
tree->custom_arg))
return 1;
}
- else if ((error=table->file->write_row(table->record[0])))
+ else if ((error=table->file->ha_write_row(table->record[0])))
{
if (error != HA_ERR_FOUND_DUPP_KEY &&
error != HA_ERR_FOUND_DUPP_UNIQUE)
--- 1.152/sql/log.cc 2005-03-03 17:29:20 +01:00
+++ 1.153/sql/log.cc 2005-03-14 15:07:16 +01:00
@@ -1550,9 +1550,15 @@
bool MYSQL_LOG::write(Log_event *event_info)
{
- THD *thd= event_info->thd;
+ THD *thd=event_info->thd;
bool error= 1;
- DBUG_ENTER("MYSQL_LOG::write(Log_event *)");
+ DBUG_ENTER("MYSQL_LOG::write(Log_event*)");
+
+ /*
+ Let the event decide if it want to go to the binlog.
+ */
+ if (!event_info->write_to_binlog())
+ DBUG_RETURN(0); // Silently succeed
pthread_mutex_lock(&LOCK_log);
--- 1.165/sql/log_event.cc 2005-03-02 16:39:58 +01:00
+++ 1.166/sql/log_event.cc 2005-03-14 15:07:16 +01:00
@@ -272,7 +272,11 @@
case XID_EVENT: return "Xid";
case USER_VAR_EVENT: return "User var";
case FORMAT_DESCRIPTION_EVENT: return "Format_desc";
- default: return "Unknown"; /* impossible */
+ case TABLE_MAP_EVENT: return "Table_map";
+ case WRITE_ROWS_EVENT: return "Write_rows";
+ case UPDATE_ROWS_EVENT: return "Update_rows";
+ case DELETE_ROWS_EVENT: return "Delete_rows";
+ default: return "Unknown"; /* impossible */
}
}
@@ -519,6 +523,9 @@
/* Store number of bytes that will be written by this event */
data_written= event_data_length + sizeof(header);
+ DBUG_PRINT("info", ("event length is %d (header) + %d (data) = %d bytes",
+ sizeof(header), event_data_length, data_written));
+
/*
log_pos != 0 if this is relay-log event. In this case we should not
change the position
@@ -709,6 +716,10 @@
uint max_allowed_packet= thd ? thd->variables.max_allowed_packet : ~0;
#endif
+ DBUG_PRINT("info", ("event length is %d bytes", data_len));
+ DBUG_PRINT("info", ("max_allowed_packet=%d, header_size=%d",
+ max_allowed_packet, header_size));
+
if (data_len > max_allowed_packet)
{
error = "Event too big";
@@ -832,8 +843,22 @@
case FORMAT_DESCRIPTION_EVENT:
ev = new Format_description_log_event(buf, event_len, description_event);
break;
+#ifdef HAVE_REPLICATION
+ case WRITE_ROWS_EVENT:
+ ev = new Write_rows_log_event(buf, event_len, description_event);
+ break;
+ case UPDATE_ROWS_EVENT:
+ ev = new Update_rows_log_event(buf, event_len, description_event);
+ break;
+ case DELETE_ROWS_EVENT:
+ ev = new Delete_rows_log_event(buf, event_len, description_event);
+ break;
+ case TABLE_MAP_EVENT:
+ ev = new Table_map_log_event(buf, event_len, description_event);
+ break;
+#endif
default:
- DBUG_PRINT("error",("Unknown evernt code: %d",(int) buf[EVENT_TYPE_OFFSET]));
+ DBUG_PRINT("error",("Unknown event code: %d",(int) buf[EVENT_TYPE_OFFSET]));
ev= NULL;
break;
}
@@ -1866,6 +1891,10 @@
post_header_len[DELETE_FILE_EVENT-1]= DELETE_FILE_HEADER_LEN;
post_header_len[NEW_LOAD_EVENT-1]= post_header_len[LOAD_EVENT-1];
post_header_len[FORMAT_DESCRIPTION_EVENT-1]= FORMAT_DESCRIPTION_HEADER_LEN;
+ post_header_len[TABLE_MAP_EVENT-1] = TABLE_MAP_HEADER_LEN;
+ post_header_len[WRITE_ROWS_EVENT-1] = ROWS_HEADER_LEN;
+ post_header_len[UPDATE_ROWS_EVENT-1] = ROWS_HEADER_LEN;
+ post_header_len[DELETE_ROWS_EVENT-1] = ROWS_HEADER_LEN;
}
break;
@@ -4416,3 +4445,915 @@
}
return buf;
}
+
+
+
+/**************************************************************************
+ Rows_log_event member functions
+**************************************************************************/
+
+#ifndef MYSQL_CLIENT
+Rows_log_event::
+Rows_log_event(THD* thd_arg, TABLE* tbl_arg, table_id tid, bool using_trans)
+ : Log_event(thd_arg, 0, using_trans),
+ m_dbnam(thd_arg->db), m_dblen(m_dbnam ? strlen(m_dbnam) : 0),
+ m_table(tbl_arg),
+ m_tblnam(tbl_arg->s->table_name),
+ m_tbllen(strlen(tbl_arg->s->table_name)),
+ m_table_id(tid),
+ m_width(tbl_arg->s->fields),
+ m_thread_id(thd_arg->thread_id),
+ m_rows_buf(my_malloc(1024 * sizeof(*m_rows_buf), MYF(MY_WME))),
+ m_rows_cur(m_rows_buf),
+ m_rows_end(m_rows_buf + 1024),
+ m_rows_flags(0)
+{
+ memset(m_cols, 0xFF, (m_width + 7)/8);
+}
+#endif
+
+Rows_log_event::
+Rows_log_event(const char* buf, uint event_len, Log_event_type event_type,
+ const Format_description_log_event *description_event)
+ : Log_event(buf, description_event),
+ m_rows_buf(0), m_rows_cur(0), m_rows_end(0)
+{
+ DBUG_ENTER("Rows_log_event::Rows_log_event(const char*,...)");
+ uint8 const common_header_len = description_event->common_header_len;
+ uint8 const post_header_len = description_event->post_header_len[event_type-1];
+
+ DBUG_PRINT("enter",("event_len=%ld, common_header_len=%d, "
+ "post_header_len=%d",
+ event_len, common_header_len,
+ post_header_len));
+
+ char const* const post_begin = buf + common_header_len;
+ m_table_id = uint4korr(post_begin + RW_MAPID_OFFSET);
+ DBUG_PRINT("info",("m_table_id=%d", m_table_id));
+
+ m_rows_flags = uint2korr(post_begin + RW_FLAGS_OFFSET);
+ DBUG_PRINT("info",("m_rows_flags=%d", m_rows_flags));
+
+ byte const* const var_begin = post_begin + ROWS_HEADER_LEN;
+
+ byte const* const ptr_width = var_begin;
+ m_width = *(unsigned char*) ptr_width;
+ DBUG_PRINT("info",("m_width=%d", m_width));
+
+ const char* const ptr_rows_data = var_begin + (m_width + 7) / 8 + 1;
+
+ size_t const data_size = event_len - (ptr_rows_data - buf);
+ DBUG_PRINT("info",("data_size=%lu", data_size));
+
+ if ((m_rows_buf = my_malloc(data_size, MYF(0))))
+ {
+ memcpy(m_cols, ptr_width + 1, (m_width + 7)/8);
+ DBUG_PRINT("info",("m_cols[0]=%lx", m_cols[0]));
+
+ m_rows_end = m_rows_buf + data_size;
+ m_rows_cur = m_rows_end;
+ memcpy(m_rows_buf, ptr_rows_data, data_size);
+ DBUG_PRINT("info",("m_rows_buf=%p, m_rows_cur=%p, m_rows_end=%p",
+ m_rows_buf, m_rows_cur, m_rows_end));
+ }
+
+ DBUG_VOID_RETURN;
+}
+
+Rows_log_event::
+~Rows_log_event()
+{
+ my_free(m_rows_buf, MYF(MY_WME));
+ m_rows_buf = m_rows_cur = m_rows_end = NULL;
+}
+
+void Rows_log_event::
+do_add_row_data(byte *const row_data, size_t const length)
+{
+ DBUG_ENTER("Rows_log_event::do_add_row_data(byte* data, size_t length)");
+ DBUG_PRINT("enter", ("row_data = %p, length = %lu", row_data, length));
+ DBUG_ASSERT(m_rows_buf <= m_rows_cur);
+ DBUG_ASSERT(m_rows_buf < m_rows_end);
+ DBUG_ASSERT(m_rows_cur <= m_rows_end);
+
+ // The cast will work since m_rows_cur <= m_rows_end
+ if ((size_t) (m_rows_end - m_rows_cur) < length) {
+ ptrdiff_t const old_alloc = m_rows_end - m_rows_buf;
+ ptrdiff_t const new_alloc = old_alloc + 1024;
+ ptrdiff_t const cur_size = m_rows_cur - m_rows_buf;
+
+ byte* const new_buf = my_realloc(m_rows_buf, new_alloc, MYF(MY_WME));
+
+ // If the memory moved, we need to move the pointers
+ if (new_buf != m_rows_buf) {
+ m_rows_buf = new_buf;
+ m_rows_end = m_rows_buf + new_alloc;
+ m_rows_cur = m_rows_buf + cur_size;
+ }
+ }
+
+ memcpy(m_rows_cur, row_data, length);
+ m_rows_cur += length;
+ DBUG_PRINT("info", ("rows event body is now %lu bytes",
+ m_rows_cur - m_rows_buf));
+ DBUG_VOID_RETURN;
+}
+
+#ifndef MYSQL_CLIENT
+/*
+ Get the value of the bit at position 'pos' in the array of bytes 'bits'.
+ Bit number 0 is the most significant bit of the byte 'bits[0]'.
+*/
+static inline bool
+bitpos(byte* const bits, size_t const pos)
+{
+ byte const mask = (1 << (7 - (pos % 8)));
+ if (bits[pos / 8] & mask)
+ return true;
+ else
+ return false;
+}
+
+/*
+ Unpack a row into a record. The row is assumed to only consist of the fields
+ for which the bitset represented by 'arr' and 'bits'; the other parts of the
+ record are left alone.
+ */
+static char const*
+unpack_row(TABLE* table,
+ char* record,
+ char const* row,
+ byte *arr, size_t const bits)
+{
+ DBUG_ENTER("unpack_row(char* record, char const* row, TABLE* table)");
+ DBUG_PRINT("enter", ("record = %p, row = %p, table = %p (%s)",
+ record, row, table, table->s->table_name));
+ DBUG_PRINT("info", ("table->null_bytes = %d, table->fields = %d",
+ table->s->null_bytes, table->s->fields));
+ DBUG_ASSERT(record && row);
+ char const* ptr = row;
+ memcpy(record, ptr, table->s->null_bytes);
+ ptr += table->s->null_bytes;
+ for (size_t i = 0 ; i < table->s->fields ; ++i)
+ {
+ DBUG_ASSERT(i < bits);
+ if (bitpos(arr,i)) {
+ int const offset = table->field[i]->offset();
+ DBUG_PRINT("info", ("Unpacking length %d field '%s' from %p to %p + %d",
+ table->field[i]->field_length,
+ table->field[i]->field_name,
+ ptr, record, offset));
+ ptr = table->field[i]->unpack(record + offset, ptr);
+ }
+ }
+ DBUG_RETURN(ptr);
+}
+
+/*
+ Tag fields as new fields based on the supplied sequence of bits. The bits
+ are supplied as an array of bytes, where the first byte is the first 8
+ fields. The number of bits used is given by the 'bits' parameter and is
+ really only used as a security. The fields are tagged by setting the
+ 'query_id' value of the field to the value of the 'query_id' field of the
+ thread 'thd'.
+*/
+static void
+tag_new_fields(THD* thd, TABLE* table, byte *arr, size_t const bits)
+{
+ for (size_t i = 0 ; i < table->s->fields ; ++i) {
+ DBUG_ASSERT(i < bits);
+ if (bitpos(arr,i) == true) {
+#if 0
+ // This does not work currently, I've propably got something wrong.
+ DBUG_ASSERT(table->field[i]->query_id != thd->query_id);
+#endif
+ table->field[i]->query_id = thd->query_id;
+ }
+ }
+}
+
+
+int Rows_log_event::
+exec_event(st_relay_log_info* rli)
+{
+ DBUG_ENTER("Rows_log_event::exec_event(st_relay_log_info*)");
+ int error = 0;
+ TABLE* const table = rli->get_table(m_table_id);
+ THD* const thd = current_thd;
+ char const* row_start = m_rows_buf;
+
+ do_before_row_operations(table);
+ while (error == 0 && row_start < m_rows_end) {
+ DBUG_PRINT("info", ("row_start = %p, m_rows_end = %p",
+ row_start, m_rows_end));
+ char const* row_end = do_prepare_row(table, row_start);
+ DBUG_ASSERT(row_end != NULL);
+ DBUG_PRINT("info", ("row_start = %p, row_end = %p, (length %u)",
+ row_start, row_end, row_end - row_start));
+ tag_new_fields(thd, table, m_cols, m_width);
+ error = do_exec_row(table, rli);
+ DBUG_PRINT("info", ("error = %d", error));
+ row_start = row_end;
+ }
+ do_after_row_operations(table);
+
+ if (m_rows_flags & STMT_END_F) {
+ // This is the end of a statement, so close (and unlock) the tables we
+ // opened when processing the Table_map_log_event starting the statement.
+
+ // !!! This will clear *all* mappings, not only those that are open for
+ // !!! the thread. There is not good handle for on-close actions for
+ // !!! tables.
+ rli->clear_tables();
+ close_thread_tables(thd);
+ }
+
+ DBUG_RETURN(error || Log_event::exec_event(rli));
+}
+#endif
+
+bool Rows_log_event::
+write_data_header(IO_CACHE* file)
+{
+ byte buf[ROWS_HEADER_LEN]; // No need to init the buffer
+ DBUG_ENTER("Rows_log_event::write_data_header(IO_CACHE*)");
+ DBUG_PRINT("info", ("writing MAPID %d (4 bytes)", m_table_id));
+ int4store(buf + RW_MAPID_OFFSET, m_table_id);
+ DBUG_PRINT("info", ("writing FLAGS %d (2 bytes)", m_table_id));
+ int2store(buf + RW_FLAGS_OFFSET, m_rows_flags);
+ bool result = my_b_safe_write(file, buf, ROWS_HEADER_LEN);
+ DBUG_RETURN(result);
+}
+
+bool Rows_log_event::
+write_data_body(IO_CACHE* file)
+{
+ DBUG_ENTER("Rows_log_event::write_data_body(IO_CACHE*)");
+ byte const wbuf[] = { m_width };
+ DBUG_PRINT("info", ("writing %d bytes",
+ sizeof(wbuf) + (m_width + 7) / 8
+ + (m_rows_cur - m_rows_buf)));
+ DBUG_ASSERT(m_width < 128);
+ DBUG_RETURN(my_b_safe_write(file, wbuf, sizeof(wbuf))
+ || my_b_safe_write(file, m_cols, (m_width + 7)/8)
+ || my_b_safe_write(file, m_rows_buf, m_rows_cur - m_rows_buf));
+}
+
+#ifdef MYSQL_CLIENT
+void Rows_log_event::
+print(FILE* file, bool short_form,
+ LAST_EVENT_INFO* last_event_info)
+{
+ if (!short_form)
+ {
+ print_header(file);
+ fprintf(file, "\n# %s\tthread_id=%lu\n", get_type_str(), m_thread_id);
+ }
+}
+#endif
+
+/**************************************************************************
+ Table_map_log_event member functions
+**************************************************************************/
+
+/*
+ Constructor used to build an event for writing to the binary log.
+ */
+#ifndef MYSQL_CLIENT
+Table_map_log_event::
+Table_map_log_event(THD* thd, TABLE* tbl, table_id tid, bool using_trans)
+ : Log_event(thd, 0, using_trans),
+ m_table(tbl),
+ m_dbnam(thd->db),
+ m_dblen(m_dbnam ? strlen(m_dbnam) : 0),
+ m_tblnam(tbl->s->table_name), // Do I need to take a copy???
+ m_tbllen(strlen(m_tblnam)),
+ m_colcnt(tbl->s->fields), m_coltype(0),
+ m_memory(0),
+ m_table_id(tid)
+{
+ DBUG_ENTER("Table_map_log_event::Table_map_log_event(THD*,...)");
+
+ m_data_size = TABLE_MAP_HEADER_LEN;
+ m_data_size += m_dblen + 2; // Include length and terminating \0
+ m_data_size += m_tbllen + 2; // Include length and terminating \0
+ m_data_size += 1 + m_colcnt; // COLCNT and column types
+
+ if ((m_memory = my_multi_malloc(MYF(0),
+ &m_coltype, m_colcnt,
+ NULL)))
+ {
+ for (unsigned int i = 0 ; i < m_table->s->fields ; ++i)
+ m_coltype[i] = m_table->field[i]->type();
+ }
+
+ DBUG_VOID_RETURN;
+}
+#endif
+
+/*
+ Constructor used by slave to read the event from the binary log.
+ */
+Table_map_log_event::
+Table_map_log_event(const char* buf, uint event_len,
+ const Format_description_log_event *description_event)
+#ifdef MYSQL_CLIENT
+ : Log_event(buf, description_event)
+#else
+ : Log_event(buf, description_event), m_table(NULL), m_memory(NULL)
+#endif
+
+{
+ DBUG_ENTER("Table_map_log_event::Table_map_log_event(const char*,uint,...)");
+
+ uint8 common_header_len= description_event->common_header_len;
+ uint8 post_header_len= description_event->post_header_len[TABLE_MAP_EVENT-1];
+ DBUG_PRINT("info",("event_len=%ld, common_header_len=%d, post_header_len=%d",
+ event_len, common_header_len, post_header_len));
+
+ /* Read the post-header */
+ const char* const post_start = buf + common_header_len;
+
+ m_table_id = uint4korr(post_start + TM_MAPID_OFFSET);
+
+ /* Read the variable part of the event */
+ const char* const vpart = post_start + TABLE_MAP_HEADER_LEN;
+
+ /* Extract the length of the various parts from the buffer */
+ byte const* const ptr_dblen = vpart + 0;
+ m_dblen = *(unsigned char*) ptr_dblen;
+
+ // Length of database name + counter + terminating null
+ byte const* const ptr_tbllen = ptr_dblen + m_dblen + 2;
+ m_tbllen = *(unsigned char*) ptr_tbllen;
+
+ // Length of table name + counter + terminating null
+ byte const* const ptr_colcnt = ptr_tbllen + m_tbllen + 2;
+ m_colcnt = *(unsigned char*) ptr_colcnt;
+
+ DBUG_PRINT("info",("m_dblen = %d offset %d", m_dblen, ptr_dblen-vpart));
+ DBUG_PRINT("info",("m_tbllen = %d offset %d", m_tbllen, ptr_tbllen-vpart));
+ DBUG_PRINT("info",("m_colcnt = %d; offset %d", m_colcnt, ptr_colcnt-vpart));
+
+ /* Allocate memory for all fields in one go */
+ m_memory= my_multi_malloc(MYF(0),
+ &m_dbnam, m_dblen + 1,
+ &m_tblnam, m_tbllen + 1,
+ &m_coltype, m_colcnt,
+ NULL);
+
+ if (m_memory) {
+ /* Copy the different parts into their memory */
+ strncpy(const_cast<char*>(m_dbnam), ptr_dblen + 1, m_dblen + 1);
+ strncpy(const_cast<char*>(m_tblnam), ptr_tbllen + 1, m_tbllen + 1);
+ memcpy(m_coltype, ptr_colcnt + 1, m_colcnt);
+
+ DBUG_PRINT("info", ("m_dblen = %d; m_dbnam = \"%s\"",
+ m_dblen, m_dbnam));
+ DBUG_PRINT("info", ("m_tbllen = %d; m_tblnam = \"%s\"",
+ m_tbllen, m_tblnam));
+ DBUG_PRINT("info", ("m_colcnt = %d", m_colcnt));
+ }
+
+ DBUG_VOID_RETURN;
+}
+
+Table_map_log_event::
+~Table_map_log_event()
+{
+ my_free(m_memory, MYF(0));
+}
+
+#ifndef MYSQL_CLIENT
+int Table_map_log_event::
+exec_event(st_relay_log_info* rli)
+{
+ DBUG_ENTER("Table_map_log_event::exec_event(st_relay_log_info*)");
+
+ // Open and lock the table
+ THD* const thd = current_thd;
+ TABLE_LIST table_list;
+ bzero(&table_list, sizeof(table_list));
+ table_list.db = const_cast<char*>(m_dbnam);
+ table_list.alias = table_list.table_name = const_cast<char*>(m_tblnam);
+ if (open_ltable(thd, &table_list, TL_WRITE) == NULL)
+ DBUG_RETURN(1); // Failed to open and lock table
+ m_table = table_list.table;
+
+ int error = rli->set_table(m_table_id, m_table);
+ DBUG_RETURN(error || Log_event::exec_event(rli));
+}
+#endif
+
+#ifndef MYSQL_CLIENT
+bool Table_map_log_event::
+write_data_header(IO_CACHE* file)
+{
+ DBUG_ENTER("Table_map_log_event::write_data_header(IO_CACHE*)");
+
+ byte buf[TABLE_MAP_HEADER_LEN];
+ int4store(buf + TM_MAPID_OFFSET, m_table_id);
+
+ DBUG_RETURN(my_b_safe_write(file, buf, TABLE_MAP_HEADER_LEN));
+}
+
+bool Table_map_log_event::
+write_data_body(IO_CACHE* file)
+{
+ DBUG_ENTER("Table_map_log_event::write_data_body(IO_CACHE*)");
+ // To ensure that we can use VLE in the future.
+ DBUG_ASSERT(m_dblen < 128);
+ DBUG_ASSERT(m_tbllen < 128);
+ DBUG_ASSERT(m_colcnt < 128);
+
+ DBUG_PRINT("info", ("m_dblen = %d; m_dbnam = %s",
+ m_dblen, m_dbnam));
+ DBUG_PRINT("info", ("m_tbllen = %d; m_tblnam = %s",
+ m_tbllen, m_tblnam));
+
+ byte const dbuf[] = { m_dblen };
+ byte const tbuf[] = { m_tbllen };
+ byte const cbuf[] = { m_colcnt };
+
+ DBUG_RETURN( my_b_safe_write(file, dbuf, sizeof(dbuf))
+ || my_b_safe_write(file, m_dbnam, m_dblen+1)
+ || my_b_safe_write(file, tbuf, sizeof(tbuf))
+ || my_b_safe_write(file, m_tblnam, m_tbllen+1)
+ || my_b_safe_write(file, cbuf, sizeof(cbuf))
+ || my_b_safe_write(file, m_coltype, m_colcnt));
+}
+#else
+/*
+ Dummy functions to satisfy linking dependencies
+*/
+bool Table_map_log_event::
+write_data_header(IO_CACHE* file)
+{
+ DBUG_ASSERT(0); // Shouldn't come here!
+ return 1;
+}
+
+bool Table_map_log_event::
+write_data_body(IO_CACHE* file)
+{
+ DBUG_ASSERT(0); // Shouldn't come here!
+ return 1;
+}
+#endif
+
+#ifdef MYSQL_CLIENT
+void Table_map_log_event::
+print(FILE* file, bool short_form,
+ LAST_EVENT_INFO* last_event_info)
+{
+ if (!short_form)
+ {
+ print_header(file);
+ fprintf(file, "\n# %s\tthread_id=%lu\n", "Table_map_log_event", m_thread_id);
+ }
+}
+#endif
+
+/**************************************************************************
+ Write_rows_log_event member functions
+**************************************************************************/
+
+/*
+ Constructor used to build an event for writing to the binary log.
+ */
+#ifndef MYSQL_CLIENT
+Write_rows_log_event::
+Write_rows_log_event(THD* thd_arg, TABLE* tbl_arg,
+ table_id tid, bool using_trans)
+ : Rows_log_event(thd_arg, tbl_arg, tid, using_trans)
+{
+}
+#endif
+
+/*
+ Constructor used by slave to read the event from the binary log.
+ */
+Write_rows_log_event::
+Write_rows_log_event(const char* buf, uint event_len,
+ const Format_description_log_event *description_event)
+: Rows_log_event(buf, event_len, WRITE_ROWS_EVENT, description_event)
+{
+ DBUG_ENTER("Write_rows_log_event::Write_rows_log_event(char*,...)");
+ DBUG_VOID_RETURN;
+}
+
+#ifndef MYSQL_CLIENT
+int Write_rows_log_event::
+do_before_row_operations(TABLE* table)
+{
+ return 0;
+}
+
+void Write_rows_log_event::
+do_after_row_operations(TABLE* table)
+{
+}
+
+char const* Write_rows_log_event::
+do_prepare_row(TABLE* table, char const* row_start)
+{
+ DBUG_ENTER("Write_rows_log_event::do_prepare_row(TABLE*,...)");
+ char const* ptr = row_start;
+ ptr = unpack_row(table, table->record[0], ptr, m_cols, m_width);
+ DBUG_RETURN(ptr);
+}
+
+int Write_rows_log_event::
+do_exec_row(TABLE* table, st_relay_log_info* rli)
+{
+ DBUG_ENTER("Write_rows_log_event::do_exec_row(TABLE*,...)");
+ int error = table->file->ha_write_row(table->record[0]);
+ DBUG_RETURN(error);
+}
+#endif
+
+#ifdef MYSQL_CLIENT
+void Write_rows_log_event::
+print(FILE* file, bool short_form,
+ LAST_EVENT_INFO* last_event_info)
+{
+ if (!short_form) {
+ print_header(file);
+ fprintf(file, "\nINSERT INTO %s VALUES ", "`NYI`");
+ }
+}
+#endif
+
+/**************************************************************************
+ Delete_rows_log_event member functions
+**************************************************************************/
+
+#ifndef MYSQL_CLIENT
+static int record_compare(TABLE* table, byte const *a, byte const *b)
+{
+ for (size_t i = 0 ; i < table->s->fields ; ++i)
+ {
+ int const off = table->field[i]->offset();
+ DBUG_PRINT("info", ("Comparing %02x ('%c') with %02x ('%c')",
+ a[off], a[off], b[off], b[off]));
+ int const res = table->field[i]->cmp_binary(a + off, b + off);
+ if (res != 0)
+ return res;
+ }
+ return 0;
+}
+#endif
+
+/*
+ Constructor used to build an event for writing to the binary log.
+ */
+#ifndef MYSQL_CLIENT
+Delete_rows_log_event::
+Delete_rows_log_event(THD* thd_arg, TABLE* tbl_arg,
+ table_id tid, bool using_trans)
+ : Rows_log_event(thd_arg, tbl_arg, tid, using_trans),
+ m_search_record(NULL), m_key(NULL)
+{
+}
+
+Delete_rows_log_event::
+~Delete_rows_log_event()
+{
+}
+#endif
+
+/*
+ Constructor used by slave to read the event from the binary log.
+ */
+Delete_rows_log_event::
+Delete_rows_log_event(const char* buf, uint event_len,
+ const Format_description_log_event *description_event)
+#ifdef MYSQL_CLIENT
+ : Rows_log_event(buf, event_len, DELETE_ROWS_EVENT, description_event)
+#else
+ : Rows_log_event(buf, event_len, DELETE_ROWS_EVENT, description_event),
+ m_search_record(NULL), m_key(NULL)
+#endif
+{
+ DBUG_ENTER("Delete_rows_log_event::Delete_rows_log_event(char*,...)");
+ DBUG_VOID_RETURN;
+}
+
+
+#ifndef MYSQL_CLIENT
+int Delete_rows_log_event::
+do_before_row_operations(TABLE* table)
+{
+ DBUG_ENTER("Delete_rows_log_event::do_before_row_operations(TABLE*)");
+ DBUG_PRINT("info", ("key_length = %u", table->key_info->key_length));
+ DBUG_PRINT("info", ("keys = %u", table->s->keys));
+ m_memory =
+ my_multi_malloc(MYF(0),
+ &m_search_record, table->s->reclength,
+ // Just to get a sensible value when there are no keys
+ &m_key, table->s->keys > 0 ? table->key_info->key_length : 1,
+ NULL);
+ if (!m_memory)
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ if (table->s->keys > 0)
+ {
+ // We have a key: search the table using the index
+ if (!table->file->inited)
+ table->file->ha_index_init(0);
+ }
+ else
+ {
+ // We doesn't have a key: search the table using rnd_next()
+ table->file->ha_rnd_init(1);
+ }
+
+ DBUG_RETURN(0);
+}
+
+void Delete_rows_log_event::
+do_after_row_operations(TABLE* table)
+{
+ DBUG_ENTER("Delete_rows_log_event::do_after_row_operations(TABLE*)");
+
+ table->file->ha_index_or_rnd_end();
+ my_free(m_memory, MYF(MY_WME)); // Free for multi_malloc
+ m_search_record = m_key = NULL;
+
+ DBUG_VOID_RETURN;
+}
+
+char const* Delete_rows_log_event::
+do_prepare_row(TABLE* table, char const* row_start)
+{
+ DBUG_ENTER("Delete_rows_log_event::do_prepare_row(TABLE*,...)");
+ DBUG_ASSERT(m_search_record);
+
+ char const* ptr = row_start;
+
+ DBUG_ASSERT(ptr != NULL);
+ ptr = unpack_row(table, table->record[0], ptr, m_cols, m_width);
+
+ if (table->s->keys > 0)
+ {
+ // We have a key, let's use the primary key if there is one.
+ // Otherwise, we use the first key (index) we find for the table.
+ uint const pk = table->s->primary_key;
+ KEY *const key_info = table->key_info + (pk != MAX_KEY ? pk : 0);
+
+ key_copy(m_key, table->record[0], key_info, 0);
+ }
+
+ DBUG_RETURN(ptr);
+}
+
+int Delete_rows_log_event::
+do_exec_row(TABLE* table, st_relay_log_info* rli)
+{
+ DBUG_ENTER("Delete_rows_log_event::do_exec_row(TABLE*,...)");
+
+ if (table->s->keys > 0) {
+ if (int error = table->file->index_read(m_search_record, m_key,
+ table->key_info->key_length,
+ HA_READ_KEY_EXACT))
+ {
+ DBUG_PRINT("return", ("error = %d", error));
+ DBUG_RETURN(error);
+ }
+
+ while (record_compare(table, table->record[0], m_search_record) != 0)
+ {
+ if (int error = table->file->index_next(m_search_record))
+ {
+ DBUG_PRINT("return", ("error = %d", error));
+ DBUG_RETURN(error);
+ }
+ }
+ }
+ else
+ {
+ if (int const error = table->file->rnd_next(m_search_record))
+ {
+ DBUG_PRINT("return", ("error = %d", error));
+ DBUG_RETURN(error);
+ }
+
+ // Save the position
+ table->file->position(m_search_record);
+ byte* const last_rowid = table->file->ref;
+
+ // Continue until we find the right record or have made a full loop
+ while (record_compare(table, table->record[0], m_search_record) != 0)
+ {
+ if (int const error = table->file->rnd_next(m_search_record))
+ {
+ switch (error) {
+ case HA_ERR_END_OF_FILE:
+ table->file->ha_rnd_init(1);
+ continue;
+ case HA_ERR_RECORD_DELETED:
+ continue;
+ default:
+ DBUG_PRINT("return", ("error = %d", error));
+ DBUG_RETURN(error);
+ }
+ }
+
+#if 0
+ // !!! Need to test if we have searched the entire table
+ table->file->position(m_search_record);
+ if (memcmp(table->file->ref, last_rowid, ) == 0) {
+ int const error = HA_ERR_END_OF_FILE;
+ DBUG_PRINT("return", ("error = %d", error));
+ DBUG_RETURN(error);
+ }
+#endif
+ }
+ }
+
+ // Now we should have the right row to delete
+
+ int const error = table->file->ha_delete_row(m_search_record);
+
+ DBUG_PRINT("return", ("error = %d", error));
+ DBUG_RETURN(error);
+}
+#endif
+
+/**************************************************************************
+ Update_rows_log_event member functions
+**************************************************************************/
+
+/*
+ Constructor used to build an event for writing to the binary log.
+ */
+#ifndef MYSQL_CLIENT
+Update_rows_log_event::
+Update_rows_log_event(THD* thd_arg, TABLE* tbl_arg,
+ table_id tid, bool using_trans)
+: Rows_log_event(thd_arg, tbl_arg, tid, using_trans),
+ m_key(NULL)
+{
+}
+#endif
+
+/*
+ Constructor used by slave to read the event from the binary log.
+ */
+Update_rows_log_event::
+Update_rows_log_event(const char* buf, uint event_len,
+ const Format_description_log_event *description_event)
+#ifdef MYSQL_CLIENT
+ : Rows_log_event(buf, event_len, UPDATE_ROWS_EVENT, description_event)
+#else
+ : Rows_log_event(buf, event_len, UPDATE_ROWS_EVENT, description_event),
+ m_key(NULL)
+#endif
+{
+ DBUG_ENTER("Update_rows_log_event::Update_rows_log_event(char*,...)");
+ DBUG_VOID_RETURN;
+}
+
+#ifndef MYSQL_CLIENT
+int Update_rows_log_event::
+do_before_row_operations(TABLE* table)
+{
+ DBUG_ENTER("Update_rows_log_event::do_before_row_operations(TABLE*)");
+ DBUG_PRINT("info", ("key_length = %u", table->key_info->key_length));
+ DBUG_PRINT("info", ("keys = %u", table->s->keys));
+
+ m_memory
+ = my_multi_malloc(MYF(0),
+ &m_search_record, table->s->reclength,
+ // Just to get a sensible value when there are no keys
+ &m_key, table->s->keys > 0 ? table->key_info->key_length : 1,
+ NULL);
+ if (!m_memory)
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ if (table->s->keys > 0)
+ {
+ // We have a key: search the table using the index
+ if (!table->file->inited)
+ table->file->ha_index_init(0);
+ }
+ else
+ {
+ // We doesn't have a key: search the table using rnd_next()
+ table->file->ha_rnd_init(1);
+ }
+
+ DBUG_RETURN(0);
+}
+
+void Update_rows_log_event::
+do_after_row_operations(TABLE* table)
+{
+ DBUG_ENTER("Update_rows_log_event::do_after_row_operations(TABLE*)");
+
+ table->file->ha_index_or_rnd_end();
+ my_free(m_memory, MYF(MY_WME)); // Free for multi_malloc
+ m_search_record = m_key = NULL;
+
+ DBUG_VOID_RETURN;
+}
+
+char const* Update_rows_log_event::
+do_prepare_row(TABLE* table, char const* row_start)
+{
+ DBUG_ENTER("Update_rows_log_event::do_prepare_row(TABLE*,...)");
+ DBUG_ASSERT(m_search_record);
+
+ char const* ptr = row_start;
+
+ DBUG_ASSERT(ptr != NULL);
+ // record[0] is the before image for the update
+ ptr = unpack_row(table, table->record[0], ptr, m_cols, m_width);
+ DBUG_ASSERT(ptr != NULL);
+ // record[1] is the after image for the update
+ ptr = unpack_row(table, table->record[1], ptr, m_cols, m_width);
+
+ if (table->s->keys > 0)
+ {
+ // We have a key, let's use the primary key if there is one.
+ // Otherwise, we use the first key (index) we find for the table.
+ uint const pk = table->s->primary_key;
+ KEY *const key_info = table->key_info + (pk != MAX_KEY ? pk : 0);
+
+ key_copy(m_key, table->record[0], key_info, 0);
+ }
+
+ DBUG_RETURN(ptr);
+}
+
+int Update_rows_log_event::
+do_exec_row(TABLE* table, st_relay_log_info* rli)
+{
+ DBUG_ENTER("Update_rows_log_event::do_exec_row(TABLE*,...)");
+ if (table->s->keys > 0) {
+ if (int error = table->file
+ ->index_read(m_search_record, m_key,
+ table->key_info->key_length,
+ HA_READ_KEY_EXACT))
+ {
+ DBUG_PRINT("return", ("error = %d", error));
+ DBUG_RETURN(error);
+ }
+
+ while (record_compare(table, table->record[0], m_search_record) != 0)
+ {
+ if (int error = table->file->index_next(m_search_record))
+ {
+ DBUG_PRINT("return", ("error = %d", error));
+ DBUG_RETURN(error);
+ }
+ }
+ }
+ else
+ {
+ if (int const error = table->file->rnd_next(m_search_record))
+ {
+ DBUG_PRINT("return", ("error = %d", error));
+ DBUG_RETURN(error);
+ }
+
+ // Save the position
+ table->file->position(m_search_record);
+ byte* const last_rowid = table->file->ref;
+
+ // Continue until we find the right record or have made a full loop
+ while (record_compare(table, table->record[0], m_search_record) != 0)
+ {
+ if (int const error = table->file->rnd_next(m_search_record))
+ {
+ switch (error) {
+ case HA_ERR_END_OF_FILE:
+ table->file->ha_rnd_init(1);
+ continue;
+ case HA_ERR_RECORD_DELETED:
+ continue;
+ default:
+ DBUG_PRINT("return", ("error = %d", error));
+ DBUG_RETURN(error);
+ }
+ }
+
+#if 0
+ // !!! Need to test if we have searched all records
+ table->file->position(m_search_record);
+ if (table->file->ref == last_rowid) {
+ int const error = HA_ERR_END_OF_FILE;
+ DBUG_PRINT("return", ("error = %d", error));
+ DBUG_RETURN(error);
+ }
+#endif
+ }
+ }
+
+ // Now we should have the right row to delete
+ int const error = table->file->ha_update_row(table->record[0],
+ table->record[1]);
+
+ DBUG_PRINT("return", ("error = %d", error));
+ DBUG_RETURN(error);
+}
+#endif
+
--- 1.104/sql/log_event.h 2005-02-23 18:26:33 +01:00
+++ 1.105/sql/log_event.h 2005-03-14 15:07:16 +01:00
@@ -26,6 +26,11 @@
#pragma interface /* gcc class implementation */
#endif
+#ifndef MYSQL_CLIENT
+extern my_bool opt_binlog_row_level;
+extern ulong opt_binlog_row_event_max_size;
+#endif
+
#define LOG_READ_EOF -1
#define LOG_READ_BOGUS -2
#define LOG_READ_IO -3
@@ -194,6 +199,8 @@
#define EXEC_LOAD_HEADER_LEN 4
#define DELETE_FILE_HEADER_LEN 4
#define FORMAT_DESCRIPTION_HEADER_LEN (START_V3_HEADER_LEN+1+LOG_EVENT_TYPES)
+#define ROWS_HEADER_LEN 6
+#define TABLE_MAP_HEADER_LEN 4
/*
Event header offsets;
@@ -284,6 +291,13 @@
/* DF = "Delete File" */
#define DF_FILE_ID_OFFSET 0
+/* TM = "Table Map" */
+#define TM_MAPID_OFFSET 0
+
+/* RW = "RoWs" */
+#define RW_MAPID_OFFSET 0
+#define RW_FLAGS_OFFSET 4
+
/* 4 bytes which all binlogs should begin with */
#define BINLOG_MAGIC "\xfe\x62\x69\x6e"
@@ -386,6 +400,10 @@
NEW_LOAD_EVENT,
RAND_EVENT, USER_VAR_EVENT,
FORMAT_DESCRIPTION_EVENT,
+ TABLE_MAP_EVENT,
+ WRITE_ROWS_EVENT,
+ UPDATE_ROWS_EVENT,
+ DELETE_ROWS_EVENT,
XID_EVENT,
/*
@@ -608,6 +626,53 @@
*description_event);
/* returns the human readable name of the event's type */
const char* get_type_str();
+
+ /*
+ Predicate to check if this event should be written to the binary
+ log. This function is called by MYSQL_LOG to decide if this event
+ should be written to the binary log at all.
+
+ Return 'true' if the event should be written to the binary log,
+ 'false' if it should not be written to the binary log.
+ */
+ bool write_to_binlog() const {
+ return do_write_to_binlog();
+ }
+
+ /*
+ Predicate to check if this statement can be cached at all or should go
+ directly into the binary log.
+
+ Observe that even if an event can be cached, it might not go to the cache
+ for other reasons. This predicate is mainly used to get row-level events
+ for non-transactional tables written directly to the log file, bypassing
+ any caching resulting from, e.g., transactions.
+
+ Return 'true' if this event can be put in the cache, 'false' otherwise.
+ */
+ bool can_be_cached() const {
+ return do_can_be_cached();
+ }
+
+private:
+ /*
+ Primitive for testing if the event should be written to the binary log.
+ The subclasses should override this if they do not want to be written to
+ the binary log. By default, everything goes to the binary log.
+
+ Return 'true' if the event should be written to the binary log, 'false'
+ otherwise.
+ */
+ virtual bool do_write_to_binlog() const {
+ return true;
+ }
+
+ /*
+ Primitive for testing if the event can be cached at all.
+ */
+ virtual bool do_can_be_cached() const {
+ return true;
+ }
};
/*
@@ -1353,7 +1418,7 @@
Delete_file_log_event(const char* buf, uint event_len,
const Format_description_log_event* description_event);
- ~Delete_file_log_event() {}
+ ~Delete_file_log_event() {};
Log_event_type get_type_code() { return DELETE_FILE_EVENT;}
int get_data_size() { return DELETE_FILE_HEADER_LEN ;}
bool is_valid() const { return file_id != 0; }
@@ -1413,5 +1478,373 @@
bool is_valid() const { return 1; }
};
#endif
+
+/*****************************************************************************
+
+ Table map log event class
+
+ Create a mapping from an id to a table name and a set of columns.
+
+ ****************************************************************************/
+
+class Table_map_log_event : public Log_event
+{
+public:
+ typedef uint16 table_id;
+
+ // Constants
+ enum {
+ TYPE_CODE = TABLE_MAP_EVENT
+ };
+
+#ifndef MYSQL_CLIENT
+ Table_map_log_event(THD *thd, TABLE* tbl, table_id tid, bool using_trans);
+#endif
+ Table_map_log_event(const char* buf, uint event_len,
+ const Format_description_log_event *description_event);
+
+ ~Table_map_log_event();
+
+ virtual Log_event_type get_type_code() { return TABLE_MAP_EVENT; }
+ virtual bool is_valid() const { return 1; }
+
+ virtual int get_data_size() { return m_data_size; }
+
+ virtual bool write_data_header(IO_CACHE* file);
+ virtual bool write_data_body(IO_CACHE* file);
+
+#ifndef MYSQL_CLIENT
+ virtual int exec_event(struct st_relay_log_info* rli);
+#endif
+
+#ifdef MYSQL_CLIENT
+ virtual void print(FILE* file, bool short_form = 0,
+ LAST_EVENT_INFO* last_event_info= 0);
+#endif
+
+private:
+#ifndef MYSQL_CLIENT
+ TABLE *m_table;
+#endif
+ char const *m_dbnam;
+ size_t m_dblen;
+ char const *m_tblnam;
+ size_t m_tbllen;
+ size_t m_colcnt;
+ byte *m_coltype;
+
+ gptr m_memory;
+ table_id m_table_id;
+
+ size_t m_data_size;
+ ulong m_thread_id;
+
+private:
+#ifndef MYSQL_CLIENT
+ virtual bool do_write_to_binlog() const {
+ return opt_binlog_row_level;
+ }
+#endif
+};
+
+
+/*****************************************************************************
+
+ Row level log event class.
+
+ Common base class for all row-level log events.
+
+ RESPONSABILITIES
+ Encode the common parts of all events containing rows, which are:
+ - Write data header and data body to an IO_CACHE.
+ - Provide an interface for adding an individual row to the event.
+
+
+ COLLABORATION
+
+ ****************************************************************************/
+
+class Rows_log_event : public Log_event
+{
+public:
+ typedef Table_map_log_event::table_id table_id;
+
+ enum enum_flags {
+ STMT_END_F = (1 << 0), // Last event of a statement
+ TRANS_END_F = (1 << 1) // Last event of a transaction
+ };
+
+ virtual ~Rows_log_event();
+
+ void set_flags(enum_flags flags) {
+ m_rows_flags |= flags;
+ }
+
+ void clear_flags(enum_flags flags) {
+ m_rows_flags &= ~flags;
+ }
+
+#ifndef MYSQL_CLIENT
+ virtual int exec_event(struct st_relay_log_info* rli);
+#endif
+
+#ifdef MYSQL_CLIENT
+ virtual void print(FILE* file, bool short_form = 0,
+ LAST_EVENT_INFO* last_event_info= 0);
+#endif
+
+ void add_row_data(byte *data, size_t length) {
+ do_add_row_data(data,length);
+ }
+
+ // Member functions to implement superclass interface
+ virtual int get_data_size() {
+ return
+ ROWS_HEADER_LEN + 1 + (m_width + 7) / 8
+ + (m_rows_cur - m_rows_buf);
+ }
+
+ virtual bool write_data_header(IO_CACHE* file);
+ virtual bool write_data_body(IO_CACHE* file);
+
+protected:
+ // The constructors are protected since you're supposed to inherit
+ // this class, not create instances of this class.
+#ifndef MYSQL_CLIENT
+ Rows_log_event(THD*, TABLE*, table_id, bool using_trans);
+#endif
+ Rows_log_event(const char* row_data, uint event_len,
+ Log_event_type event_type,
+ const Format_description_log_event *description_event);
+
+ virtual void do_add_row_data(byte* data, size_t length);
+
+ char const *m_dbnam; // Database name
+ size_t m_dblen; // Length of database name in bytes
+
+#ifndef MYSQL_CLIENT
+ TABLE* m_table; // The table the rows belong to
+#endif
+ char const *m_tblnam;
+ size_t m_tbllen;
+ table_id m_table_id; // Table ID
+ size_t m_width; // Width of table, on the master [1..127]
+ byte m_cols[128/8]; // Bitmask denoting columns available
+
+ ulong m_thread_id; // Thread ID
+
+ byte* m_rows_buf; // The rows in packed format
+ byte* m_rows_cur; // One-after the end of the data
+ byte* m_rows_end; // One-after the end of the allocated space
+
+ uint16 m_rows_flags; // Flags for row-level events
+
+private:
+#ifndef MYSQL_CLIENT
+ virtual bool do_write_to_binlog() const {
+ return opt_binlog_row_level;
+ }
+
+ virtual bool do_can_be_cached() const {
+ return opt_binlog_row_level && m_table->file->has_transactions();
+ }
+
+ /*
+ Primitive to prepare for a sequence of row executions.
+
+ DESCRIPTION
+
+ Before doing a sequence of do_prepare_row() and do_exec_row() calls,
+ this member function should be called to prepare for the entire
+ sequence. Typically, this member function will allocate space for any
+ buffers that are needed for the two member functions mentioned above.
+
+ RETURN VALUE
+
+ The member function will return 0 if all went ok, or a non-zero error
+ code otherwise.
+ */
+ virtual int do_before_row_operations(TABLE* table) = 0;
+
+ /*
+ Primitive to clean up after a sequence of row executions.
+
+ DESCRIPTION
+
+ After doing a sequence of do_prepare_row() and do_exec_row(), this
+ member function should be called to clean up and release any allocated
+ buffers. This member function cannot fail, so make sure to recover after
+ any potential problems that might occur.
+ */
+ virtual void do_after_row_operations(TABLE* table) = 0;
+
+ /*
+ Primitive to prepare for handling one row in a row-level event.
+
+ DESCRIPTION
+
+ The member function prepares for execution of operations needed for one
+ row in a row-level event by reading up data from the buffer containing
+ the row. No specific interpretation of the data is normally done here,
+ since SQL thread specific data is not available: that data is made
+ available for the do_exec function.
+
+ RETURN VALUE
+ A pointer to the start of the next row, or NULL if the preparation
+ failed. Currently, preparation cannot fail, but don't rely on this
+ behaviour.
+ */
+ virtual char const* do_prepare_row(TABLE* table, char const* row_start) = 0;
+
+ /*
+ Primitive to do the actual execution necessary for a row.
+
+ DESCRIPTION
+ The member function will do the actual execution needed to handle a row,
+ and potentially change the state of the SQL thread specific data
+ supplied in the 'rli' parameter.
+
+ RETURN VALUE
+ 0 if execution succeeded, 1 if execution failed.
+
+ */
+ virtual int do_exec_row(TABLE* table, st_relay_log_info* rli) = 0;
+#endif
+};
+
+
+/*****************************************************************************
+
+ Write row log event class
+
+ Log row insertions and updates. The event contain several
+ insert/update rows for a table. Note that each event contains only
+ rows for one table.
+
+ ****************************************************************************/
+class Write_rows_log_event : public Rows_log_event
+{
+public:
+ enum {
+ TYPE_CODE = WRITE_ROWS_EVENT // Support interface to prepare_pending
+ };
+
+#ifndef MYSQL_CLIENT
+ Write_rows_log_event(THD*, TABLE*, table_id, bool using_trans);
+#endif
+ Write_rows_log_event(const char* buf, uint event_len,
+ const Format_description_log_event *description_event);
+
+private:
+ virtual Log_event_type get_type_code() { return WRITE_ROWS_EVENT; }
+ virtual bool is_valid() const { return 1; }
+
+#ifdef MYSQL_CLIENT
+ void print(FILE* file, bool short_form, LAST_EVENT_INFO* last_event_info);
+#endif
+
+#ifndef MYSQL_CLIENT
+ gptr m_memory;
+ byte* m_search_record;
+
+ virtual int do_before_row_operations(TABLE* table);
+ virtual void do_after_row_operations(TABLE* table);
+ virtual char const* do_prepare_row(TABLE* table, char const* row_start);
+ virtual int do_exec_row(TABLE* table, st_relay_log_info* rli);
+#endif
+};
+
+
+/*****************************************************************************
+
+ Update rows log event class
+
+ Log row updates with a before image. The event contain several
+ update rows for a table. Note that each event contains only rows for
+ one table.
+
+ Also note that the row data consists of pairs of row data: one row
+ for the old data and one row for the new data.
+
+ ****************************************************************************/
+class Update_rows_log_event : public Rows_log_event
+{
+public:
+ enum {
+ TYPE_CODE = UPDATE_ROWS_EVENT // Support interface to prepare_pending
+ };
+
+#ifndef MYSQL_CLIENT
+ Update_rows_log_event(THD*, TABLE*, table_id, bool using_trans);
+#endif
+ Update_rows_log_event(const char* buf, uint event_len,
+ const Format_description_log_event *description_event);
+
+private:
+ virtual Log_event_type get_type_code() { return UPDATE_ROWS_EVENT; }
+ virtual bool is_valid() const { return 1; }
+
+#ifndef MYSQL_CLIENT
+ gptr m_memory;
+ byte* m_search_record;
+ byte* m_key;
+
+ virtual int do_before_row_operations(TABLE* table);
+ virtual void do_after_row_operations(TABLE* table);
+ virtual char const* do_prepare_row(TABLE* table, char const* row_start);
+ virtual int do_exec_row(TABLE* table, st_relay_log_info* rli);
+#endif
+};
+
+/*****************************************************************************
+
+ Delete rows log event class.
+
+ Log row deletions. The event contain several delete rows for a
+ table. Note that each event contains only rows for one table.
+
+ RESPONSABILITIES
+
+ - Act as a container for rows that has been deleted on the master
+ and should be deleted on the slave.
+
+ COLLABORATION
+
+ Row_writer
+ Create the event and add rows to the event.
+ Row_reader
+ Extract the rows from the event.
+
+ ****************************************************************************/
+class Delete_rows_log_event : public Rows_log_event
+{
+public:
+ enum {
+ TYPE_CODE = DELETE_ROWS_EVENT // Support interface to prepare_pending
+ };
+
+#ifndef MYSQL_CLIENT
+ Delete_rows_log_event(THD*, TABLE*, table_id, bool using_trans);
+ virtual ~Delete_rows_log_event();
+#endif
+ Delete_rows_log_event(const char* buf, uint event_len,
+ const Format_description_log_event *description_event);
+
+private:
+ virtual Log_event_type get_type_code() { return DELETE_ROWS_EVENT; }
+ virtual bool is_valid() const { return 1; }
+
+#ifndef MYSQL_CLIENT
+ gptr m_memory;
+ byte* m_search_record;
+ byte* m_key;
+
+ virtual int do_before_row_operations(TABLE* table);
+ virtual void do_after_row_operations(TABLE* table);
+ virtual char const* do_prepare_row(TABLE* table, char const* row_start);
+ virtual int do_exec_row(TABLE* table, st_relay_log_info* rli);
+#endif
+};
+
#endif /* _log_event_h */
--- 1.271/sql/mysql_priv.h 2005-03-05 12:34:18 +01:00
+++ 1.272/sql/mysql_priv.h 2005-03-14 14:53:48 +01:00
@@ -1045,6 +1045,8 @@
extern ulong query_buff_size, thread_stack,thread_stack_min;
extern ulong binlog_cache_size, max_binlog_cache_size, open_files_limit;
extern ulong max_binlog_size, max_relay_log_size;
+extern my_bool opt_binlog_row_level;
+extern ulong opt_binlog_row_event_max_size;
extern ulong rpl_recovery_rank, thread_cache_size;
extern ulong back_log;
extern ulong specialflag, current_pid;
--- 1.439/sql/mysqld.cc 2005-03-08 10:34:45 +01:00
+++ 1.440/sql/mysqld.cc 2005-03-14 15:07:16 +01:00
@@ -321,6 +321,9 @@
volatile bool mqh_used = 0;
my_bool sp_automatic_privileges= 1;
+my_bool opt_binlog_row_level = FALSE; // Statement-level is default
+unsigned long opt_binlog_rows_event_max_size = 1024;
+
#ifdef HAVE_INITGROUPS
static bool calling_initgroups= FALSE; /* Used in SIGSEGV handler. */
#endif
@@ -4119,6 +4122,7 @@
OPT_SQL_BIN_UPDATE_SAME, OPT_REPLICATE_DO_DB,
OPT_REPLICATE_IGNORE_DB, OPT_LOG_SLAVE_UPDATES,
OPT_BINLOG_DO_DB, OPT_BINLOG_IGNORE_DB,
+ OPT_BINLOG_FORMAT, OPT_BINLOG_ROWS_EVENT_MAX_SIZE,
OPT_WANT_CORE, OPT_CONCURRENT_INSERT,
OPT_MEMLOCK, OPT_MYISAM_RECOVER,
OPT_REPLICATE_REWRITE_DB, OPT_SERVER_ID,
@@ -4326,12 +4330,27 @@
{"bind-address", OPT_BIND_ADDRESS, "IP address to bind to.",
(gptr*) &my_bind_addr_str, (gptr*) &my_bind_addr_str, 0, GET_STR,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"binlog-format", OPT_BINLOG_FORMAT,
+ "Tell the master the form of logging to use: "
+ "either 'row' for row-level logging or "
+ "'statement' for statement-level logging.",
+ 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
{"binlog-do-db", OPT_BINLOG_DO_DB,
"Tells the master it should log updates for the specified database, and exclude all others not explicitly mentioned.",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"binlog-ignore-db", OPT_BINLOG_IGNORE_DB,
"Tells the master that updates to the given database should not be logged tothe binary log.",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"binlog-row-event-max-size", OPT_BINLOG_ROWS_EVENT_MAX_SIZE,
+ "The maximum size of a row-level event in bytes. "
+ "The value have to be an even multiple of 256.",
+ (gptr*) &opt_binlog_rows_event_max_size,
+ (gptr*) &opt_binlog_rows_event_max_size, 0,
+ GET_ULONG, REQUIRED_ARG,
+ /* def_value */ 1024, /* min_value */ 256, /* max_value */ ULONG_MAX,
+ /* sub_size */ 0, /* block_size */ 256,
+ /* app_type */ 0
+ },
{"bootstrap", OPT_BOOTSTRAP, "Used by mysql installation scripts.", 0, 0, 0,
GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"character-set-server", 'C', "Set the default character set.",
@@ -6178,6 +6197,26 @@
binlog_ignore_db.push_back(db);
break;
}
+ case OPT_BINLOG_FORMAT:
+ if (strcmp(argument,"row") == 0)
+ {
+ opt_binlog_row_level = TRUE;
+ }
+ else if (strcmp(argument, "statement") == 0)
+ {
+ opt_binlog_row_level = FALSE;
+ }
+ else
+ {
+ fprintf(stderr,
+ "Unknown binary log format: '%s' "
+ "(Should be 'row' or 'statement')\n",
+ argument);
+ exit(1);
+ }
+
+ break;
+
case (int)OPT_BINLOG_DO_DB:
{
i_string *db = new i_string(argument);
--- 1.240/sql/slave.cc 2005-03-02 16:37:40 +01:00
+++ 1.241/sql/slave.cc 2005-03-14 14:53:49 +01:00
@@ -2529,12 +2529,13 @@
ignore_log_space_limit(0), last_master_timestamp(0), slave_skip_counter(0),
abort_pos_wait(0), slave_run_id(0), sql_thd(0), last_slave_errno(0),
inited(0), abort_slave(0), slave_running(0), until_condition(UNTIL_NONE),
- until_log_pos(0)
+ until_log_pos(0), table_array(0), table_count(0), table_reserve(16)
{
group_relay_log_name[0]= event_relay_log_name[0]=
group_master_log_name[0]= 0;
last_slave_error[0]=0; until_log_name[0]= 0;
-
+ table_array = (table_entry*) my_malloc(table_reserve * sizeof(*table_array), MYF(MY_WME));
+ bzero(table_array, table_reserve * sizeof(*table_array));
bzero((char*) &info_file, sizeof(info_file));
bzero((char*) &cache_buf, sizeof(cache_buf));
cached_charset_invalidate();
@@ -2551,6 +2552,8 @@
st_relay_log_info::~st_relay_log_info()
{
+ my_free(reinterpret_cast<char*>(table_array), MYF(MY_WME));
+
pthread_mutex_destroy(&run_lock);
pthread_mutex_destroy(&data_lock);
pthread_mutex_destroy(&log_space_lock);
@@ -3088,6 +3091,82 @@
until_log_names_cmp_result == UNTIL_LOG_NAMES_CMP_GREATER);
}
+ulong st_relay_log_info::
+find_pos(ulong table_id) const
+{
+ // !!! This is a linear search, it will be infeasible to use for larger
+ // !!! number of tables in the air at the same time. Switch to a binary
+ // !!! search later.
+ for (ulong i = 0 ; i < table_count ; ++i) {
+ if (table_array[i].table_id == table_id)
+ return i;
+ }
+ return table_count;
+}
+
+TABLE* st_relay_log_info::
+get_table(ulong table_id)
+{
+ DBUG_ENTER("st_relay_log_info::get_table(ulong)");
+ ulong const pos = find_pos(table_id);
+ if (pos < table_count) {
+ DBUG_PRINT("info", ("tid %d -> table %p (%s)",
+ table_id, table_array[pos].table,
+ table_array[pos].table->s->table_name));
+ DBUG_RETURN(table_array[pos].table);
+ }
+ DBUG_RETURN(NULL);
+}
+
+int st_relay_log_info::
+set_table(ulong table_id, TABLE* table)
+{
+ DBUG_ENTER("st_relay_log_info::set_table(ulong,TABLE*)");
+ ulong const pos = find_pos(table_id);
+
+ // See if we need to allocate a larger array
+ if (pos == table_count && table_reserve == table_count) {
+ if (table_reserve > ULONG_MAX/2)
+ DBUG_RETURN(1); // Table upper limit exceeded
+
+ int const reserve = 2*table_reserve;
+ table_entry* const
+ array = (table_entry*) my_realloc((char*) table_array,
+ reserve*sizeof(*table_array),
+ MYF(MY_WME));
+ if (array == NULL)
+ return 1; // Memory allocation failed
+ table_reserve = reserve;
+ table_array = array;
+ }
+
+ table_array[pos].table_id = table_id;
+ table_array[pos].table = table;
+ ++table_count;
+ DBUG_PRINT("info", ("tid %d -> table %p (%s)",
+ table_id, table_array[pos].table,
+ table_array[pos].table->s->table_name));
+ DBUG_RETURN(0); // All OK
+}
+
+int st_relay_log_info::
+remove_table(ulong table_id)
+{
+ ulong pos = find_pos(table_id);
+ if (pos < table_count) {
+ while (++pos < table_count)
+ table_array[pos-1] = table_array[pos];
+ --table_count;
+ return 0; // All OK
+ }
+ return 1; // No table to remove
+}
+
+void st_relay_log_info::
+clear_tables()
+{
+ table_count = 0;
+}
void st_relay_log_info::cached_charset_invalidate()
{
@@ -3217,6 +3296,7 @@
ev->when = time(NULL);
ev->thd = thd;
exec_res = ev->exec_event(rli);
+ DBUG_PRINT("info", ("exec_event result = %d", exec_res));
DBUG_ASSERT(rli->sql_thd==thd);
/*
Format_description_log_event should not be deleted because it will be
--- 1.131/sql/sql_acl.cc 2005-03-08 10:34:46 +01:00
+++ 1.132/sql/sql_acl.cc 2005-03-14 14:53:49 +01:00
@@ -1530,7 +1530,7 @@
}
store_record(table,record[1]);
table->field[2]->store(new_password, new_password_len, system_charset_info);
- if ((error=table->file->update_row(table->record[1],table->record[0])))
+ if ((error=table->file->ha_update_row(table->record[1],table->record[0])))
{
table->file->print_error(error,MYF(0)); /* purecov: deadcode */
goto end; /* purecov: deadcode */
@@ -1744,14 +1744,14 @@
*/
table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
if (cmp_record(table,record[1]) &&
- (error=table->file->update_row(table->record[1],table->record[0])))
+ (error=table->file->ha_update_row(table->record[1],table->record[0])))
{ // This should never happen
table->file->print_error(error,MYF(0)); /* purecov: deadcode */
error= -1; /* purecov: deadcode */
goto end; /* purecov: deadcode */
}
}
- else if ((error=table->file->write_row(table->record[0]))) // insert
+ else if ((error=table->file->ha_write_row(table->record[0]))) // insert
{ // This should never happen
if (error && error != HA_ERR_FOUND_DUPP_KEY &&
error != HA_ERR_FOUND_DUPP_UNIQUE) /* purecov: inspected */
@@ -1861,16 +1861,16 @@
if (rights)
{
table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
- if ((error=table->file->update_row(table->record[1],table->record[0])))
+ if ((error=table->file->ha_update_row(table->record[1],table->record[0])))
goto table_error; /* purecov: deadcode */
}
else /* must have been a revoke of all privileges */
{
- if ((error = table->file->delete_row(table->record[1])))
+ if ((error = table->file->ha_delete_row(table->record[1])))
goto table_error; /* purecov: deadcode */
}
}
- else if (rights && (error=table->file->write_row(table->record[0])))
+ else if (rights && (error=table->file->ha_write_row(table->record[0])))
{
if (error && error != HA_ERR_FOUND_DUPP_KEY) /* purecov: inspected */
goto table_error; /* purecov: deadcode */
@@ -2231,9 +2231,9 @@
if (old_row_exists)
{
if (privileges)
- error=table->file->update_row(table->record[1],table->record[0]);
+ error=table->file->ha_update_row(table->record[1],table->record[0]);
else
- error=table->file->delete_row(table->record[1]);
+ error=table->file->ha_delete_row(table->record[1]);
if (error)
{
table->file->print_error(error,MYF(0)); /* purecov: inspected */
@@ -2248,7 +2248,7 @@
}
else // new grant
{
- if ((error=table->file->write_row(table->record[0])))
+ if ((error=table->file->ha_write_row(table->record[0])))
{
table->file->print_error(error,MYF(0)); /* purecov: inspected */
result= -1; /* purecov: inspected */
@@ -2300,8 +2300,8 @@
if (privileges)
{
int tmp_error;
- if ((tmp_error=table->file->update_row(table->record[1],
- table->record[0])))
+ if ((tmp_error=table->file->ha_update_row(table->record[1],
+ table->record[0])))
{ /* purecov: deadcode */
table->file->print_error(tmp_error,MYF(0)); /* purecov: deadcode */
result= -1; /* purecov: deadcode */
@@ -2313,7 +2313,7 @@
else
{
int tmp_error;
- if ((tmp_error = table->file->delete_row(table->record[1])))
+ if ((tmp_error = table->file->ha_delete_row(table->record[1])))
{ /* purecov: deadcode */
table->file->print_error(tmp_error,MYF(0)); /* purecov: deadcode */
result= -1; /* purecov: deadcode */
@@ -2420,15 +2420,15 @@
{
if (store_table_rights || store_col_rights)
{
- if ((error=table->file->update_row(table->record[1],table->record[0])))
+ if ((error=table->file->ha_update_row(table->record[1],table->record[0])))
goto table_error; /* purecov: deadcode */
}
- else if ((error = table->file->delete_row(table->record[1])))
+ else if ((error = table->file->ha_delete_row(table->record[1])))
goto table_error; /* purecov: deadcode */
}
else
{
- error=table->file->write_row(table->record[0]);
+ error=table->file->ha_write_row(table->record[0]);
if (error && error != HA_ERR_FOUND_DUPP_KEY)
goto table_error; /* purecov: deadcode */
}
@@ -2532,15 +2532,15 @@
{
if (store_proc_rights)
{
- if ((error=table->file->update_row(table->record[1],table->record[0])))
+ if ((error=table->file->ha_update_row(table->record[1],table->record[0])))
goto table_error;
}
- else if ((error= table->file->delete_row(table->record[1])))
+ else if ((error= table->file->ha_delete_row(table->record[1])))
goto table_error;
}
else
{
- error=table->file->write_row(table->record[0]);
+ error=table->file->ha_write_row(table->record[0]);
if (error && error != HA_ERR_FOUND_DUPP_KEY)
goto table_error;
}
@@ -4305,13 +4305,13 @@
system_charset_info);
user_field->store(user_to->user.str, user_to->user.length,
system_charset_info);
- if ((error= table->file->update_row(table->record[1], table->record[0])))
+ if ((error= table->file->ha_update_row(table->record[1], table->record[0])))
table->file->print_error(error, MYF(0));
}
else
{
/* delete */
- if ((error=table->file->delete_row(table->record[0])))
+ if ((error=table->file->ha_delete_row(table->record[0])))
table->file->print_error(error, MYF(0));
}
@@ -5311,7 +5311,7 @@
table->field[i++]->store(column, col_length, cs);
table->field[i++]->store(priv, priv_length, cs);
table->field[i]->store(is_grantable, strlen(is_grantable), cs);
- table->file->write_row(table->record[0]);
+ table->file->ha_write_row(table->record[0]);
}
--- 1.169/sql/sql_class.cc 2005-03-04 15:46:41 +01:00
+++ 1.170/sql/sql_class.cc 2005-03-14 15:07:16 +01:00
@@ -207,6 +207,7 @@
ull=0;
system_thread= cleanup_done= abort_on_warning= no_warnings_for_error= 0;
peer_port= 0; // For SHOW PROCESSLIST
+ transaction.m_pending_rows_event = 0;
#ifdef __WIN__
real_id = 0;
#endif
--- 1.222/sql/sql_class.h 2005-03-08 17:12:08 +01:00
+++ 1.223/sql/sql_class.h 2005-03-14 14:53:50 +01:00
@@ -1080,6 +1080,11 @@
XID xid; // transaction identifier
enum xa_states xa_state; // used by external XA only
/*
+ Pending event for row-level logging.
+ */
+ Rows_log_event* m_pending_rows_event;
+
+ /*
Tables changed in transaction (that must be invalidated in query cache).
List contain only transactional tables, that not invalidated in query
cache (instead of full list of changed in transaction tables).
--- 1.141/sql/sql_delete.cc 2005-03-05 20:44:02 +01:00
+++ 1.142/sql/sql_delete.cc 2005-03-14 15:07:16 +01:00
@@ -70,6 +70,8 @@
select_lex->no_error= thd->lex->ignore;
+ table->file->ha_stmt_begin();
+
/*
Test if the user wants to delete all rows and deletion doesn't have
any side-effects (because of triggers), so we can use optimized
@@ -182,7 +184,7 @@
table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
TRG_ACTION_BEFORE);
- if (!(error=table->file->delete_row(table->record[0])))
+ if (!(error=table->file->ha_delete_row(table->record[0])))
{
deleted++;
if (!--limit && using_limit)
@@ -222,6 +224,7 @@
(void) table->file->extra(HA_EXTRA_NORMAL);
cleanup:
+
/*
Invalidate the table in the query cache if something changed. This must
be before binlog writing and ha_autocommit_...
@@ -233,6 +236,9 @@
delete select;
transactional_table= table->file->has_transactions();
+
+ table->file->ha_stmt_end();
+
/*
We write to the binary log even if we deleted no row, because maybe the
user is using this command to ensure that a table is clean on master *and
@@ -243,7 +249,7 @@
*/
if ((deleted || (error < 0)) && (error <= 0 || !transactional_table))
{
- if (mysql_bin_log.is_open())
+ if (!opt_binlog_row_level && mysql_bin_log.is_open())
{
if (error <= 0)
thd->clear_error();
@@ -505,7 +511,7 @@
{
/* If this is the table we are scanning */
table->status|= STATUS_DELETED;
- if (!(error=table->file->delete_row(table->record[0])))
+ if (!(error=table->file->ha_delete_row(table->record[0])))
deleted++;
else if (!table_being_deleted->next_local ||
table_being_deleted->table->file->has_transactions())
@@ -609,7 +615,7 @@
info.ignore_not_found_rows= 1;
while (!(local_error=info.read_record(&info)) && !thd->killed)
{
- if ((local_error=table->file->delete_row(table->record[0])))
+ if ((local_error=table->file->ha_delete_row(table->record[0])))
{
table->file->print_error(local_error,MYF(0));
break;
--- 1.143/sql/sql_insert.cc 2005-02-28 15:22:22 +01:00
+++ 1.144/sql/sql_insert.cc 2005-03-14 14:53:50 +01:00
@@ -311,6 +311,8 @@
(MODE_STRICT_TRANS_TABLES |
MODE_STRICT_ALL_TABLES)));
+ table->file->ha_stmt_begin();
+
if (fields.elements && check_that_all_fields_are_given_values(thd, table))
{
/* thd->net.report_error is now set, which will abort the next loop */
@@ -402,6 +404,8 @@
table->triggers->process_triggers(thd, TRG_EVENT_INSERT, TRG_ACTION_AFTER);
}
+ table->file->ha_stmt_end();
+
/*
Now all rows are inserted. Time to update logs and sends response to
user
@@ -445,7 +449,7 @@
if ((info.copied || info.deleted || info.updated) &&
(error <= 0 || !transactional_table))
{
- if (mysql_bin_log.is_open())
+ if (!opt_binlog_row_level && mysql_bin_log.is_open())
{
if (error <= 0)
thd->clear_error();
@@ -741,10 +745,11 @@
DBUG_ENTER("write_record");
info->records++;
+
if (info->handle_duplicates == DUP_REPLACE ||
info->handle_duplicates == DUP_UPDATE)
{
- while ((error=table->file->write_row(table->record[0])))
+ while ((error=table->file->ha_write_row(table->record[0])))
{
uint key_nr;
if (error != HA_WRITE_SKIP)
@@ -818,7 +823,7 @@
if (res == VIEW_CHECK_ERROR)
goto err;
- if ((error=table->file->update_row(table->record[1],table->record[0])))
+ if ((error=table->file->ha_update_row(table->record[1],table->record[0])))
goto err;
info->updated++;
break;
@@ -838,13 +843,13 @@
(table->timestamp_field_type == TIMESTAMP_NO_AUTO_SET ||
table->timestamp_field_type == TIMESTAMP_AUTO_SET_ON_BOTH))
{
- if ((error=table->file->update_row(table->record[1],
- table->record[0])))
+ if ((error=table->file->ha_update_row(table->record[1],
+ table->record[0])))
goto err;
info->deleted++;
break; /* Update logfile and count */
}
- else if ((error=table->file->delete_row(table->record[1])))
+ else if ((error=table->file->ha_delete_row(table->record[1])))
goto err;
info->deleted++;
if (!table->file->has_transactions())
@@ -853,7 +858,7 @@
}
info->copied++;
}
- else if ((error=table->file->write_row(table->record[0])))
+ else if ((error=table->file->ha_write_row(table->record[0])))
{
if (!info->ignore ||
(error != HA_ERR_FOUND_DUPP_KEY && error != HA_ERR_FOUND_DUPP_UNIQUE))
--- 1.293/sql/sql_select.cc 2005-03-03 14:39:23 +01:00
+++ 1.294/sql/sql_select.cc 2005-03-14 14:53:51 +01:00
@@ -8581,11 +8581,11 @@
/* copy all old rows */
while (!table->file->rnd_next(new_table.record[1]))
{
- if ((write_err=new_table.file->write_row(new_table.record[1])))
+ if ((write_err=new_table.file->ha_write_row(new_table.record[1])))
goto err;
}
/* copy row that filled HEAP table */
- if ((write_err=new_table.file->write_row(table->record[0])))
+ if ((write_err=new_table.file->ha_write_row(table->record[0])))
{
if (write_err != HA_ERR_FOUND_DUPP_KEY &&
write_err != HA_ERR_FOUND_DUPP_UNIQUE || !ignore_last_dupp_key_error)
@@ -9848,7 +9848,7 @@
if (!join->having || join->having->val_int())
{
join->found_records++;
- if ((error=table->file->write_row(table->record[0])))
+ if ((error=table->file->ha_write_row(table->record[0])))
{
if (error == HA_ERR_FOUND_DUPP_KEY ||
error == HA_ERR_FOUND_DUPP_UNIQUE)
@@ -9910,8 +9910,8 @@
{ /* Update old record */
restore_record(table,record[1]);
update_tmptable_sum_func(join->sum_funcs,table);
- if ((error=table->file->update_row(table->record[1],
- table->record[0])))
+ if ((error=table->file->ha_update_row(table->record[1],
+ table->record[0])))
{
table->file->print_error(error,MYF(0)); /* purecov: inspected */
DBUG_RETURN(-1); /* purecov: inspected */
@@ -9934,7 +9934,7 @@
}
init_tmptable_sum_functions(join->sum_funcs);
copy_funcs(join->tmp_table_param.items_to_copy);
- if ((error=table->file->write_row(table->record[0])))
+ if ((error=table->file->ha_write_row(table->record[0])))
{
if (create_myisam_from_heap(join->thd, table, &join->tmp_table_param,
error, 0))
@@ -9970,7 +9970,7 @@
copy_fields(&join->tmp_table_param); // Groups are copied twice.
copy_funcs(join->tmp_table_param.items_to_copy);
- if (!(error=table->file->write_row(table->record[0])))
+ if (!(error=table->file->ha_write_row(table->record[0])))
join->send_records++; // New group
else
{
@@ -9986,8 +9986,8 @@
}
restore_record(table,record[1]);
update_tmptable_sum_func(join->sum_funcs,table);
- if ((error=table->file->update_row(table->record[1],
- table->record[0])))
+ if ((error=table->file->ha_update_row(table->record[1],
+ table->record[0])))
{
table->file->print_error(error,MYF(0)); /* purecov: inspected */
DBUG_RETURN(-1); /* purecov: inspected */
@@ -10029,7 +10029,7 @@
copy_sum_funcs(join->sum_funcs);
if (!join->having || join->having->val_int())
{
- if ((error=table->file->write_row(table->record[0])))
+ if ((error=table->file->ha_write_row(table->record[0])))
{
if (create_myisam_from_heap(join->thd, table,
&join->tmp_table_param,
@@ -10870,7 +10870,7 @@
}
if (having && !having->val_int())
{
- if ((error=file->delete_row(record)))
+ if ((error=file->ha_delete_row(record)))
goto err;
error=file->rnd_next(record);
continue;
@@ -10897,7 +10897,7 @@
}
if (compare_record(table, first_field) == 0)
{
- if ((error=file->delete_row(record)))
+ if ((error=file->ha_delete_row(record)))
goto err;
}
else if (!found)
@@ -10994,7 +10994,7 @@
}
if (having && !having->val_int())
{
- if ((error=file->delete_row(record)))
+ if ((error=file->ha_delete_row(record)))
goto err;
continue;
}
@@ -11011,7 +11011,7 @@
if (hash_search(&hash, org_key_pos, key_length))
{
/* Duplicated found ; Remove the row */
- if ((error=file->delete_row(record)))
+ if ((error=file->ha_delete_row(record)))
goto err;
}
else
--- 1.222/sql/sql_show.cc 2005-03-05 12:34:18 +01:00
+++ 1.223/sql/sql_show.cc 2005-03-14 14:53:51 +01:00
@@ -1525,7 +1525,7 @@
table->field[0]->store(name_buffer, strlen(name_buffer),
system_charset_info);
table->field[1]->store(pos, (uint32) (end - pos), system_charset_info);
- table->file->write_row(table->record[0]);
+ table->file->ha_write_row(table->record[0]);
}
}
}
@@ -1904,7 +1904,7 @@
}
}
}
- table->file->write_row(table->record[0]);
+ table->file->ha_write_row(table->record[0]);
}
else
{
@@ -1947,7 +1947,7 @@
restore_record(table, s->default_values);
table->field[1]->store(db_name, strlen(db_name), system_charset_info);
table->field[2]->store(cs_name, strlen(cs_name), system_charset_info);
- table->file->write_row(table->record[0]);
+ table->file->ha_write_row(table->record[0]);
}
@@ -2185,7 +2185,7 @@
}
}
}
- table->file->write_row(table->record[0]);
+ table->file->ha_write_row(table->record[0]);
DBUG_RETURN(0);
}
@@ -2364,7 +2364,7 @@
#endif
table->field[17]->store(tmp+1,end == tmp ? 0 : (uint) (end-tmp-1), cs);
table->field[18]->store(field->comment.str, field->comment.length, cs);
- table->file->write_row(table->record[0]);
+ table->file->ha_write_row(table->record[0]);
}
}
DBUG_RETURN(0);
@@ -2393,7 +2393,7 @@
strlen(tmp_cs->comment ? tmp_cs->comment : ""),
scs);
table->field[3]->store((longlong) tmp_cs->mbmaxlen);
- table->file->write_row(table->record[0]);
+ table->file->ha_write_row(table->record[0]);
}
}
return 0;
@@ -2432,7 +2432,7 @@
tmp_buff= (tmp_cl->state & MY_CS_COMPILED)? "Yes" : "";
table->field[4]->store(tmp_buff, strlen(tmp_buff), scs);
table->field[5]->store((longlong) tmp_cl->strxfrm_multiply);
- table->file->write_row(table->record[0]);
+ table->file->ha_write_row(table->record[0]);
}
}
}
@@ -2461,7 +2461,7 @@
restore_record(table, s->default_values);
table->field[0]->store(tmp_cl->name, strlen(tmp_cl->name), scs);
table->field[1]->store(tmp_cl->csname , strlen(tmp_cl->csname), scs);
- table->file->write_row(table->record[0]);
+ table->file->ha_write_row(table->record[0]);
}
}
return 0;
@@ -2544,7 +2544,7 @@
get_field(thd->mem_root, proc_table->field[15], &tmp_string);
table->field[18]->store(tmp_string.ptr(), tmp_string.length(), cs);
table->field[19]->store(definer, strlen(definer), cs);
- table->file->write_row(table->record[0]);
+ table->file->ha_write_row(table->record[0]);
}
}
}
@@ -2671,7 +2671,7 @@
else
table->field[14]->store("", 0, cs);
table->field[14]->set_notnull();
- table->file->write_row(table->record[0]);
+ table->file->ha_write_row(table->record[0]);
}
}
}
@@ -2710,7 +2710,7 @@
table->field[5]->store("YES", 3, cs);
else
table->field[5]->store("NO", 2, cs);
- table->file->write_row(table->record[0]);
+ table->file->ha_write_row(table->record[0]);
}
}
else
@@ -2735,7 +2735,7 @@
table->field[3]->store(db, strlen(db), cs);
table->field[4]->store(tname, strlen(tname), cs);
table->field[5]->store(con_type, con_len, cs);
- table->file->write_row(table->record[0]);
+ table->file->ha_write_row(table->record[0]);
}
@@ -2844,7 +2844,7 @@
key_part->field->field_name,
strlen(key_part->field->field_name),
(longlong) f_idx);
- table->file->write_row(table->record[0]);
+ table->file->ha_write_row(table->record[0]);
}
}
}
@@ -2870,7 +2870,7 @@
(longlong) f_idx);
table->field[8]->store((longlong) f_idx);
table->field[8]->set_notnull();
- table->file->write_row(table->record[0]);
+ table->file->ha_write_row(table->record[0]);
}
}
}
@@ -2895,7 +2895,7 @@
table->field[1]->store(open_list->table, strlen(open_list->table), cs);
table->field[2]->store((longlong) open_list->in_use);
table->field[3]->store((longlong) open_list->locked);
- table->file->write_row(table->record[0]);
+ table->file->ha_write_row(table->record[0]);
}
DBUG_RETURN(0);
}
--- 1.222/sql/sql_table.cc 2005-02-25 15:53:16 +01:00
+++ 1.223/sql/sql_table.cc 2005-03-14 14:53:51 +01:00
@@ -3707,7 +3707,7 @@
{
copy_ptr->do_copy(copy_ptr);
}
- if ((error=to->file->write_row((byte*) to->record[0])))
+ if ((error=to->file->ha_write_row((byte*) to->record[0])))
{
if ((!ignore &&
handle_duplicates != DUP_REPLACE) ||
--- 1.42/sql/sql_udf.cc 2005-03-05 19:41:39 +01:00
+++ 1.43/sql/sql_udf.cc 2005-03-14 14:53:51 +01:00
@@ -473,7 +473,7 @@
table->field[2]->store(u_d->dl,(uint) strlen(u_d->dl), system_charset_info);
if (table->s->fields >= 4) // If not old func format
table->field[3]->store((longlong) u_d->type);
- error = table->file->write_row(table->record[0]);
+ error = table->file->ha_write_row(table->record[0]);
close_thread_tables(thd);
if (error)
@@ -529,7 +529,7 @@
HA_READ_KEY_EXACT))
{
int error;
- if ((error = table->file->delete_row(table->record[0])))
+ if ((error = table->file->ha_delete_row(table->record[0])))
table->file->print_error(error, MYF(0));
}
close_thread_tables(thd);
--- 1.149/sql/sql_update.cc 2005-03-04 15:01:01 +01:00
+++ 1.150/sql/sql_update.cc 2005-03-14 14:53:51 +01:00
@@ -398,6 +398,8 @@
(MODE_STRICT_TRANS_TABLES |
MODE_STRICT_ALL_TABLES)));
+ table->file->ha_stmt_begin();
+
while (!(error=info.read_record(&info)) && !thd->killed)
{
if (!(select && select->skip_record()))
@@ -425,8 +427,8 @@
break;
}
}
- if (!(error=table->file->update_row((byte*) table->record[1],
- (byte*) table->record[0])))
+ if (!(error=table->file->ha_update_row((byte*) table->record[1],
+ (byte*) table->record[0])))
{
updated++;
thd->no_trans_update= !transactional_table;
@@ -461,6 +463,8 @@
thd->proc_info="end";
VOID(table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY));
+ table->file->ha_stmt_end();
+
/*
Invalidate the table in the query cache if something changed.
This must be before binlog writing and ha_autocommit_...
@@ -472,7 +476,7 @@
if ((updated || (error < 0)) && (error <= 0 || !transactional_table))
{
- if (mysql_bin_log.is_open())
+ if (!opt_binlog_row_level && mysql_bin_log.is_open())
{
if (error <= 0)
thd->clear_error();
@@ -1196,8 +1200,8 @@
*/
main_table->file->extra(HA_EXTRA_PREPARE_FOR_UPDATE);
}
- if ((error=table->file->update_row(table->record[1],
- table->record[0])))
+ if ((error=table->file->ha_update_row(table->record[1],
+ table->record[0])))
{
updated--;
if (!ignore || error != HA_ERR_FOUND_DUPP_KEY)
@@ -1221,7 +1225,7 @@
memcpy((char*) tmp_table->field[0]->ptr,
(char*) table->file->ref, table->file->ref_length);
/* Write row, ignoring duplicated updates to a row */
- if ((error= tmp_table->file->write_row(tmp_table->record[0])) &&
+ if ((error= tmp_table->file->ha_write_row(tmp_table->record[0])) &&
(error != HA_ERR_FOUND_DUPP_KEY &&
error != HA_ERR_FOUND_DUPP_UNIQUE))
{
@@ -1331,8 +1335,8 @@
if (compare_record(table, thd->query_id))
{
- if ((local_error=table->file->update_row(table->record[1],
- table->record[0])))
+ if ((local_error=table->file->ha_update_row(table->record[1],
+ table->record[0])))
{
if (!ignore || local_error != HA_ERR_FOUND_DUPP_KEY)
goto err;
--- 1.25/mysql-test/t/ctype_ucs.test 2005-02-17 14:00:29 +01:00
+++ 1.26/mysql-test/t/ctype_ucs.test 2005-03-14 15:07:16 +01:00
@@ -338,7 +338,7 @@
set @v=convert('abc' using ucs2);
reset master;
insert into t2 values (@v);
-show binlog events from 96;
+show binlog events from 100;
# more important than SHOW BINLOG EVENTS, mysqlbinlog (where we
# absolutely need variables names to be quoted and strings to be
# escaped).
--- 1.14/mysql-test/t/mysqlbinlog.test 2005-02-14 21:49:58 +01:00
+++ 1.15/mysql-test/t/mysqlbinlog.test 2005-03-14 15:07:16 +01:00
@@ -61,7 +61,7 @@
select "--- --position --" as "";
--enable_query_log
--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
---exec $MYSQL_BINLOG --short-form --local-load=$MYSQL_TEST_DIR/var/tmp/ --position=119 $MYSQL_TEST_DIR/var/log/master-bin.000002
+--exec $MYSQL_BINLOG --short-form --local-load=$MYSQL_TEST_DIR/var/tmp/ --position=123 $MYSQL_TEST_DIR/var/log/master-bin.000002
# These are tests for remote binlog.
# They should return the same as previous test.
@@ -93,7 +93,7 @@
select "--- --position --" as "";
--enable_query_log
--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
---exec $MYSQL_BINLOG --short-form --local-load=$MYSQL_TEST_DIR/var/tmp/ --read-from-remote-server --position=119 --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000002
+--exec $MYSQL_BINLOG --short-form --local-load=$MYSQL_TEST_DIR/var/tmp/ --read-from-remote-server --position=123 --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000002
# Bug#7853 (mysqlbinlog does not accept input from stdin)
--disable_query_log
@@ -103,7 +103,7 @@
--exec cat $MYSQL_TEST_DIR/std_data/trunc_binlog.000001 | $MYSQL_BINLOG --short-form -
--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
---exec cat $MYSQL_TEST_DIR/std_data/trunc_binlog.000001 | $MYSQL_BINLOG --short-form --position=79 -
+--exec cat $MYSQL_TEST_DIR/std_data/trunc_binlog.000001 | $MYSQL_BINLOG --short-form --position=83 -
# clean up
drop table t1, t2;
--- 1.10/mysql-test/t/rpl_user_variables.test 2005-02-14 21:49:58 +01:00
+++ 1.11/mysql-test/t/rpl_user_variables.test 2005-03-14 15:07:16 +01:00
@@ -46,7 +46,7 @@
connection slave;
sync_with_master;
select * from t1;
-show binlog events from 96;
+show binlog events from 100;
connection master;
drop table t1;
save_master_pos;
--- 1.12/mysql-test/t/mix_innodb_myisam_binlog.test 2005-02-17 13:52:07 +01:00
+++ 1.13/mysql-test/t/mix_innodb_myisam_binlog.test 2005-03-14 15:07:16 +01:00
@@ -27,7 +27,7 @@
--replace_column 5 #
--replace_result "xid=12" "xid=7"
-show binlog events from 96;
+show binlog events from 100;
delete from t1;
delete from t2;
@@ -40,7 +40,7 @@
rollback;
--replace_column 5 #
-show binlog events from 96;
+show binlog events from 100;
delete from t1;
delete from t2;
@@ -56,7 +56,7 @@
--replace_column 5 #
--replace_result "xid=45" "xid=24"
-show binlog events from 96;
+show binlog events from 100;
delete from t1;
delete from t2;
@@ -74,7 +74,7 @@
--replace_column 5 #
--replace_result "xid=67" "xid=36"
-show binlog events from 96;
+show binlog events from 100;
# and when ROLLBACK is not explicit?
delete from t1;
@@ -95,7 +95,7 @@
# logging has been done, we use a user lock.
select get_lock("a",10);
--replace_column 5 #
-show binlog events from 96;
+show binlog events from 100;
# and when not in a transact1on?
delete from t1;
@@ -107,7 +107,7 @@
--replace_column 5 #
--replace_result "xid=116" "xid=59"
-show binlog events from 96;
+show binlog events from 100;
# Check that when the query updat1ng the MyISAM table is the first in the
# transaction, we log it immediately.
@@ -120,13 +120,13 @@
insert into t2 select * from t1;
--replace_column 5 #
--replace_result "xid=130" "xid=65"
-show binlog events from 96;
+show binlog events from 100;
insert into t1 values(11);
commit;
--replace_column 5 #
--replace_result "xid=130" "xid=65" "xid=133" "xid=67"
-show binlog events from 96;
+show binlog events from 100;
# Check that things work like before this BEGIN/ROLLBACK code was added,
@@ -145,7 +145,7 @@
--replace_column 5 #
--replace_result "xid=152" "xid=77"
-show binlog events from 96;
+show binlog events from 100;
delete from t1;
delete from t2;
@@ -157,7 +157,7 @@
rollback;
--replace_column 5 #
-show binlog events from 96;
+show binlog events from 100;
delete from t1;
delete from t2;
@@ -173,7 +173,7 @@
--replace_column 5 #
--replace_result "xid=184" "xid=93"
-show binlog events from 96;
+show binlog events from 100;
delete from t1;
delete from t2;
@@ -191,7 +191,7 @@
--replace_column 5 #
--replace_result "xid=205" "xid=104"
-show binlog events from 96;
+show binlog events from 100;
# Test for BUG#5714, where a MyISAM update in the transaction used to
# release row-level locks in InnoDB
--- 1.3/mysql-test/t/mysqlbinlog2.test 2005-01-16 13:16:10 +01:00
+++ 1.4/mysql-test/t/mysqlbinlog2.test 2005-03-14 15:07:16 +01:00
@@ -46,11 +46,11 @@
--disable_query_log
select "--- start-position --" as "";
--enable_query_log
---exec $MYSQL_BINLOG --short-form --start-position=602 $MYSQL_TEST_DIR/var/log/master-bin.000001
+--exec $MYSQL_BINLOG --short-form --start-position=606 $MYSQL_TEST_DIR/var/log/master-bin.000001
--disable_query_log
select "--- stop-position --" as "";
--enable_query_log
---exec $MYSQL_BINLOG --short-form --stop-position=602 $MYSQL_TEST_DIR/var/log/master-bin.000001
+--exec $MYSQL_BINLOG --short-form --stop-position=606 $MYSQL_TEST_DIR/var/log/master-bin.000001
--disable_query_log
select "--- start-datetime --" as "";
--enable_query_log
@@ -75,11 +75,11 @@
--disable_query_log
select "--- start-position --" as "";
--enable_query_log
---exec $MYSQL_BINLOG --short-form --start-position=602 $MYSQL_TEST_DIR/var/log/master-bin.000001 $MYSQL_TEST_DIR/var/log/master-bin.000002
+--exec $MYSQL_BINLOG --short-form --start-position=606 $MYSQL_TEST_DIR/var/log/master-bin.000001 $MYSQL_TEST_DIR/var/log/master-bin.000002
--disable_query_log
select "--- stop-position --" as "";
--enable_query_log
---exec $MYSQL_BINLOG --short-form --stop-position=124 $MYSQL_TEST_DIR/var/log/master-bin.000001 $MYSQL_TEST_DIR/var/log/master-bin.000002
+--exec $MYSQL_BINLOG --short-form --stop-position=128 $MYSQL_TEST_DIR/var/log/master-bin.000001 $MYSQL_TEST_DIR/var/log/master-bin.000002
--disable_query_log
select "--- start-datetime --" as "";
--enable_query_log
@@ -102,11 +102,11 @@
--disable_query_log
select "--- start-position --" as "";
--enable_query_log
---exec $MYSQL_BINLOG --short-form --start-position=602 --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001
+--exec $MYSQL_BINLOG --short-form --start-position=606 --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001
--disable_query_log
select "--- stop-position --" as "";
--enable_query_log
---exec $MYSQL_BINLOG --short-form --stop-position=602 --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001
+--exec $MYSQL_BINLOG --short-form --stop-position=606 --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001
--disable_query_log
select "--- start-datetime --" as "";
--enable_query_log
@@ -129,11 +129,11 @@
--disable_query_log
select "--- start-position --" as "";
--enable_query_log
---exec $MYSQL_BINLOG --short-form --start-position=602 --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 master-bin.000002
+--exec $MYSQL_BINLOG --short-form --start-position=606 --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 master-bin.000002
--disable_query_log
select "--- stop-position --" as "";
--enable_query_log
---exec $MYSQL_BINLOG --short-form --stop-position=124 --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 master-bin.000002
+--exec $MYSQL_BINLOG --short-form --stop-position=128 --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 master-bin.000002
--disable_query_log
select "--- start-datetime --" as "";
--enable_query_log
--- 1.14/mysql-test/t/rpl_charset.test 2005-02-23 00:48:31 +01:00
+++ 1.15/mysql-test/t/rpl_charset.test 2005-03-14 15:07:16 +01:00
@@ -107,7 +107,7 @@
drop database mysqltest2;
drop database mysqltest3;
--replace_column 2 # 5 #
-show binlog events from 96;
+show binlog events from 100;
sync_slave_with_master;
# Check that we can change global.collation_server (since 5.0.3)
--- 1.12/mysql-test/t/rpl_error_ignored_table.test 2005-01-16 13:16:10 +01:00
+++ 1.13/mysql-test/t/rpl_error_ignored_table.test 2005-03-14 15:07:16 +01:00
@@ -48,7 +48,7 @@
--error 0,1053;
reap;
connection master1;
-show binlog events from 96;
+show binlog events from 100;
save_master_pos;
connection slave;
# SQL slave thread should not have stopped (because table of the killed
--- 1.7/mysql-test/t/rpl_loaddata_rule_m.test 2005-01-16 13:16:10 +01:00
+++ 1.8/mysql-test/t/rpl_loaddata_rule_m.test 2005-03-14 15:07:16 +01:00
@@ -19,5 +19,5 @@
create table t1(a int, b int, unique(b));
use mysqltest;
load data infile '../../std_data/rpl_loaddata.dat' into table test.t1;
-show binlog events from 96; # should be nothing
+show binlog events from 100; # should be nothing
drop database mysqltest;
--- 1.5/mysql-test/t/rpl_loaddata_rule_s.test 2005-01-16 13:16:10 +01:00
+++ 1.6/mysql-test/t/rpl_loaddata_rule_s.test 2005-03-14 15:07:16 +01:00
@@ -17,4 +17,4 @@
connection slave;
sync_with_master;
select count(*) from t1; # check that LOAD was replicated
-show binlog events from 96; # should be nothing
+show binlog events from 100; # should be nothing
--- 1.69/sql/sp.cc 2005-03-05 14:31:44 +01:00
+++ 1.70/sql/sp.cc 2005-03-14 14:53:49 +01:00
@@ -405,7 +405,7 @@
system_charset_info);
ret= SP_OK;
- if (table->file->write_row(table->record[0]))
+ if (table->file->ha_write_row(table->record[0]))
ret= SP_WRITE_ROW_FAILED;
}
@@ -430,7 +430,7 @@
ret= db_find_routine_aux(thd, type, name, TL_WRITE, &table, &opened);
if (ret == SP_OK)
{
- if (table->file->delete_row(table->record[0]))
+ if (table->file->ha_delete_row(table->record[0]))
ret= SP_DELETE_ROW_FAILED;
}
@@ -466,7 +466,7 @@
table->field[MYSQL_PROC_FIELD_COMMENT]->store(chistics->comment.str,
chistics->comment.length,
system_charset_info);
- if ((table->file->update_row(table->record[1],table->record[0])))
+ if ((table->file->ha_update_row(table->record[1],table->record[0])))
ret= SP_WRITE_ROW_FAILED;
}
if (opened)
@@ -691,7 +691,7 @@
bool deleted= FALSE;
do {
- if (! table->file->delete_row(table->record[0]))
+ if (! table->file->ha_delete_row(table->record[0]))
deleted= TRUE; /* We deleted something */
else
{
--- 1.85/sql/slave.h 2005-03-02 14:46:13 +01:00
+++ 1.86/sql/slave.h 2005-03-14 15:07:16 +01:00
@@ -337,6 +337,17 @@
return ((until_condition == UNTIL_MASTER_POS) ? group_master_log_pos :
group_relay_log_pos);
}
+
+ /*
+
+ */
+ struct table_entry { ulong table_id; TABLE* table; } *table_array;
+ ulong table_count, table_reserve;
+ ulong find_pos(ulong table_id) const;
+ TABLE* get_table(ulong table_id);
+ int set_table(ulong table_id, TABLE* table);
+ int remove_table(ulong table_id);
+ void clear_tables();
/*
Last charset (6 bytes) seen by slave SQL thread is cached here; it helps
the thread save 3 get_charset() per Query_log_event if the charset is not
--- 1.32/mysql-test/t/rpl_log_pos.test 2005-01-16 13:16:10 +01:00
+++ 1.33/mysql-test/t/rpl_log_pos.test 2005-03-14 15:07:16 +01:00
@@ -8,12 +8,12 @@
--replace_column 1 # 8 # 9 # 23 # 33 #
show slave status;
stop slave;
-change master to master_log_pos=73;
+change master to master_log_pos=74;
start slave;
sleep 5;
stop slave;
-change master to master_log_pos=73;
+change master to master_log_pos=74;
--replace_result $MASTER_MYPORT MASTER_PORT
--replace_column 1 # 8 # 9 # 23 # 33 #
show slave status;
@@ -23,7 +23,7 @@
--replace_column 1 # 8 # 9 # 23 # 33 #
show slave status;
stop slave;
-change master to master_log_pos=173;
+change master to master_log_pos=177;
start slave;
sleep 2;
--replace_result $MASTER_MYPORT MASTER_PORT
@@ -38,7 +38,7 @@
save_master_pos;
connection slave;
stop slave;
-change master to master_log_pos=96;
+change master to master_log_pos=100;
start slave;
sync_with_master;
select * from t1;
--- 1.24/mysql-test/t/rpl_log.test 2005-01-16 13:16:10 +01:00
+++ 1.25/mysql-test/t/rpl_log.test 2005-03-14 15:07:16 +01:00
@@ -38,9 +38,9 @@
drop table t1;
--replace_result $VERSION VERSION
show binlog events;
-show binlog events from 96 limit 1;
-show binlog events from 96 limit 2;
-show binlog events from 96 limit 2,1;
+show binlog events from 100 limit 1;
+show binlog events from 100 limit 2;
+show binlog events from 100 limit 2,1;
flush logs;
# We need an extra update before doing save_master_pos.
--- 1.22/mysql-test/t/user_var.test 2005-02-22 14:14:13 +01:00
+++ 1.23/mysql-test/t/user_var.test 2005-03-14 15:07:16 +01:00
@@ -108,7 +108,7 @@
set @var1= "';aaa";
SET @var2=char(ascii('a'));
insert into t1 values (@var1),(@var2);
-show binlog events from 96;
+show binlog events from 100;
# more important than SHOW BINLOG EVENTS, mysqlbinlog (where we
# absolutely need variables names to be quoted and strings to be
# escaped).
| Thread |
|---|
| • bk commit into 5.1 tree (mats:1.1789) | Mats Kindahl | 14 Mar |