Hi Zhenxing,
Thanks for these good comments. Most are applied.
Please review the updated patch:
http://lists.mysql.com/commits/110702
Best Regards,
Daogang
He Zhenxing wrote:
> Hi Daogang,
>
> Nice work! Patch looks good, please look for some comments!
>
> STATUS
> ------
> Not Approved!
>
> REQUIRED CHANGES
> -----------------
> RC1. The special comment will have a problem when there is also
> (special) comment in the original query, you could try the following,
> which will result in a syntax error:
>
> /*!50000 create /*!50000 table */ t1 (a int) */;
>
> Failed: 1064: You have an error in your SQL syntax; check the manual
> that corresponds to your MySQL server version for the right syntax to
> use near '*/' at line 1
>
> One suggestion is to output the query using '#' comment, and also use a
> BINLOG statement to ship the Rows_query_log_event so that it can be
> applied and relayed.
>
> # original query
> BINLOG '...'
>
> You may think of other alternatives.
>
> RC2. The handling of insert delayed is not correct, multiple insert
> delayed run in sequence or in parallel will result in wrong binlog.
>
> insert delayed into t1 values (1),(2);
> insert delayed into t1 values (3),(4),(5),(6)
>
> It seems that if multiple insert delayed are running in parallel the
> rows can be intermixed. So I think you need to have a logic to check if
> the new row is belong to the same query of the previous row, if it is
> not, then write a new Rows_query_log event before the new row.
>
> Please also look below for more comments.
>
>
> Dao-Gang.Qu@stripped wrote:
>
>> #At file:///home/daogangqu/mysql/bzrwork/wl4033_bug50935/mysql-5.1-rep%2B2/ based
> on revid:li-bing.song@stripped
>>
>> 3185 Dao-Gang.Qu@stripped 2010-05-28
>> WL #4033 Support for informational log events
>> Record original SQL statement in RBR binlog (Bug #50935)
>>
>> Adding a new ignorable event, and its incremental sub-hierarchy,
>> which have as default that if their type code are not recognized,
>> these events are just ignored and replication keeps going as usual.
>>
>>
>
> I'd suggest:
>
> Added ignorable event type, binary log events of this class or its
> subclasses will be silently ignored when applying by the slave SQL
> thread if it can not recognize them.
>
>
>> Record original SQL statement in RBR binlog by ignorable log event,
>> which can be displayed with its row event as comment by
>> "SHOW BINLOG EVENTS" and 'MYSQLBINLOG DUMP'.
>>
>
> This patch also added a rows query log event type, which is a subclass
> of the ignorable log event, to record the original query for the rows
> events in RBR. This event can be used to display the original query as
> comments by SHOW BINLOG EVENTS query, or mysqlbinlog client when the
> --verbose option is given twice.
>
> [snip]
>
>
>> === added file 'mysql-test/suite/rpl/t/rpl_ignorable_event.test'
>> --- a/mysql-test/suite/rpl/t/rpl_ignorable_event.test 1970-01-01 00:00:00 +0000
>> +++ b/mysql-test/suite/rpl/t/rpl_ignorable_event.test 2010-05-28 10:19:04 +0000
>> @@ -0,0 +1,60 @@
>> +#
>> +# WL#4033
>> +# This test verifies if the query is displayed
>> +# with its row event as comment in RBR by
>> +# SHOW BINLOG EVENTS.
>> +#
>>
>
> ... if the query of the rows event is displayed by ...
>
> And please also test mysqlbinlog
>
>
>> +
>> +source include/have_binlog_format_row.inc;
>> +source include/master-slave.inc;
>> +source include/have_innodb.inc;
>> +
>> +--echo # Test the binlog_comment_log_events is set to off by default
>> +select @@session.binlog_rows_query_log_events;
>> +set session binlog_rows_query_log_events= on;
>> +select @@session.binlog_rows_query_log_events;
>> +
>> +# Test non-transaction
>> +let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1);
>> +create table t1(i1 int not null auto_increment, a int, b int, primary key(i1));
>> +insert into t1(a,b) values(1,1),(2,1);
>> +update t1 set a = a + 5 where b = 1 LIMIT 1;
>> +delete from t1 where a = 6;
>> +insert into t1(a,b) values(1,2);
>> +insert into t1(a,b) values(1,3);
>> +insert into t1(a,b) values(1,4);
>> +insert delayed into t1(a,b) values(1,5);
>> +update t1 set a = a + 5 where b = 2;
>> +
>> +# Test transaction
>> +create table t2(a int, b int) engine=innodb;
>> +begin;
>> +insert into t2(a,b) values(2,1),(3,1);
>> +insert into t2(a,b) values(2,2);
>> +insert into t2(a,b) values(2,3);
>> +update t2 set a = a + 5 where b = 1;
>> +delete from t2 where a = 7;
>> +insert into t2(a,b) values(2,4);
>> +commit;
>> +
>> +# Test mixed transaction
>> +begin;
>> +insert into t1(a,b) values(1,5);
>> +insert into t1(a,b) values(1,6);
>> +insert into t2(a,b) values(2,4);
>> +insert into t2(a,b) values(2,5);
>> +insert into t1(a,b) values(1,7);
>> +insert delayed into t1(a,b) values(1,8);
>> +commit;
>> +
>> +# Test load data infile
>> +create table t3(a VARCHAR(60));
>> +load data infile '../../std_data/words.dat' into table t3;
>> +
>> +source include/show_binlog_events.inc;
>> +
>> +set session binlog_rows_query_log_events= off;
>> +
>> +drop table t1, t2, t3;
>> +sync_slave_with_master;
>> +
>>
>
> [snip]
>
>
>> === modified file 'sql/log.cc'
>> --- a/sql/log.cc 2010-03-17 11:31:50 +0000
>> +++ b/sql/log.cc 2010-05-28 10:19:04 +0000
>> @@ -4361,6 +4361,15 @@ int THD::binlog_write_table_map(TABLE *t
>> DBUG_ASSERT(is_current_stmt_binlog_format_row() &&
> mysql_bin_log.is_open());
>> DBUG_ASSERT(table->s->table_map_id != ULONG_MAX);
>>
>> + if (this->variables.binlog_rows_query_log_events &&
>> + is_current_stmt_binlog_format_row() && this->query())
>> + {
>> + /* Write the Rows_query_log_event into binlog before the table map */
>> + Rows_query_log_event* ev= new Rows_query_log_event(this, this->query(),
>> +
> this->query_length());
>> + mysql_bin_log.write(ev);
>> + }
>> +
>> Table_map_log_event
>> the_event(this, table, table->s->table_map_id, is_transactional);
>>
>>
>> === modified file 'sql/log_event.cc'
>> --- a/sql/log_event.cc 2010-03-03 14:43:35 +0000
>> +++ b/sql/log_event.cc 2010-05-28 10:19:04 +0000
>> @@ -644,6 +644,8 @@ const char* Log_event::get_type_str(Log_
>> case BEGIN_LOAD_QUERY_EVENT: return "Begin_load_query";
>> case EXECUTE_LOAD_QUERY_EVENT: return "Execute_load_query";
>> case INCIDENT_EVENT: return "Incident";
>> + case IGNORABLE_LOG_EVENT: return "Ignorable";
>> + case ROWS_QUERY_LOG_EVENT: return "Rows_query";
>> default: return "Unknown"; /* impossible */
>> }
>> }
>> @@ -1294,7 +1296,19 @@ Log_event* Log_event::read_log_event(con
>> case INCIDENT_EVENT:
>> ev = new Incident_log_event(buf, event_len, description_event);
>> break;
>> + case ROWS_QUERY_LOG_EVENT:
>> + ev= new Rows_query_log_event(buf, event_len, description_event);
>> + break;
>> default:
>> + /*
>> + Create an object of Ignorable_log_event for unrecognized sub-class.
>> + So that SLAVE SQL THREAD can ignore the unrecognized one.
>>
>
> so that SLAVE SQL THREAD will only update the position and continue.
>
>
>> + */
>> + if (uint2korr(buf + FLAGS_OFFSET) & LOG_EVENT_IGNORABLE_F)
>> + {
>> + ev= new Ignorable_log_event(buf, description_event);
>> + DBUG_RETURN(ev);
>> + }
>> DBUG_PRINT("error",("Unknown event code: %d",
>> (int) buf[EVENT_TYPE_OFFSET]));
>> ev= NULL;
>> @@ -3811,6 +3825,8 @@ Format_description_log_event(uint8 binlo
>> post_header_len[DELETE_ROWS_EVENT-1]= 6;);
>> post_header_len[INCIDENT_EVENT-1]= INCIDENT_HEADER_LEN;
>> post_header_len[HEARTBEAT_LOG_EVENT-1]= 0;
>> + post_header_len[IGNORABLE_LOG_EVENT-1]= IGNORABLE_HEADER_LEN;
>> + post_header_len[ROWS_QUERY_LOG_EVENT-1]= IGNORABLE_HEADER_LEN;
>>
>> // Sanity-check that all post header lengths are initialized.
>> IF_DBUG({
>> @@ -9639,6 +9655,107 @@ Incident_log_event::write_data_body(IO_C
>> }
>>
>>
>> +Ignorable_log_event::Ignorable_log_event(const char *buf,
>> + const Format_description_log_event
> *descr_event)
>> + : Log_event(buf, descr_event)
>> +{
>> + DBUG_ENTER("Ignorable_log_event::Ignorable_log_event");
>> + DBUG_VOID_RETURN;
>> +}
>> +
>> +Ignorable_log_event::~Ignorable_log_event()
>> +{
>> +}
>> +
>> +#ifndef MYSQL_CLIENT
>> +/* Pack info for its unrecognized ignorable event */
>> +void Ignorable_log_event::pack_info(Protocol *protocol)
>> +{
>> + char buf[256];
>> + size_t bytes;
>> + bytes= my_snprintf(buf, sizeof(buf), "# Unrecognized event");
>>
>
> Unrecognized ignorable event
>
> And I'd suggest to also include the type number like this:
>
> Unrecognized ignorable event: TYPE_NUMBER
>
>
>> + protocol->store(buf, bytes, &my_charset_bin);
>> +}
>> +#endif
>> +
>> +#ifdef MYSQL_CLIENT
>> +/* Print for its unrecognized ignorable event */
>> +void
>> +Ignorable_log_event::print(FILE *file,
>> + PRINT_EVENT_INFO *print_event_info)
>> +{
>> + if (print_event_info->short_form)
>> + return;
>> +
>> + Write_on_release_cache cache(&print_event_info->head_cache, file);
>> + print_header(&cache, print_event_info, FALSE);
>> + my_b_printf(&cache, "\tIgnorable\n");
>> + my_b_printf(&cache, "# Unrecognized event\n");
>>
>
> Unrecognized ignorable event
>
>
>> +}
>> +#endif
>> +
>> +
>> +Rows_query_log_event::Rows_query_log_event(const char *buf, uint event_len,
>> + const Format_description_log_event
> *descr_event)
>> + : Ignorable_log_event(buf, descr_event)
>> +{
>> + DBUG_ENTER("Rows_query_log_event::Rows_query_log_event");
>> + uint8 const common_header_len=
>> + descr_event->common_header_len;
>> + uint8 const post_header_len=
>> + descr_event->post_header_len[ROWS_QUERY_LOG_EVENT-1];
>> +
>> + DBUG_PRINT("info",("event_len: %u; common_header_len: %d; post_header_len:
> %d",
>> + event_len, common_header_len, post_header_len));
>> +
>> + char const *ptr= buf + common_header_len + post_header_len;
>> + char const *const str_end= buf + event_len;
>> + uint8 len= 0; // Assignment to keep compiler happy
>> + const char *str= NULL; // Assignment to keep compiler happy
>> + read_str(&ptr, str_end, &str, &len);
>> + if (!(m_rows_query= (char*) my_malloc(len+1, MYF(MY_WME))))
>> + return;
>> + my_snprintf(m_rows_query, len+1, "%s", str);
>> + DBUG_PRINT("info", ("m_rows_query: %s", m_rows_query));
>> + DBUG_VOID_RETURN;
>> +}
>> +
>> +Rows_query_log_event::~Rows_query_log_event()
>> +{
>> + my_free(m_rows_query, MYF(0));
>> +}
>> +
>> +#ifndef MYSQL_CLIENT
>> +void Rows_query_log_event::pack_info(Protocol *protocol)
>> +{
>> + protocol->store(m_rows_query, (uint) strlen(m_rows_query),
>> + &my_charset_bin);
>> +}
>> +#endif
>> +
>> +#ifdef MYSQL_CLIENT
>> +void
>> +Rows_query_log_event::print(FILE *file,
>> + PRINT_EVENT_INFO *print_event_info)
>> +{
>> + if (print_event_info->short_form)
>> + return;
>> +
>> + Write_on_release_cache cache(&print_event_info->head_cache, file);
>> + print_header(&cache, print_event_info, FALSE);
>> + my_b_printf(&cache, "\tRows_query\n");
>> + my_b_printf(&cache, "%s\n", m_rows_query);
>> +}
>> +#endif
>> +
>> +bool
>> +Rows_query_log_event::write_data_body(IO_CACHE *file)
>> +{
>> + DBUG_ENTER("Rows_query_log_event::Rows_query_log_event");
>> + DBUG_RETURN(write_str(file, m_rows_query, (uint) strlen(m_rows_query)));
>> +}
>> +
>> +
>> #ifdef MYSQL_CLIENT
>> /**
>> The default values for these variables should be values that are
>>
>> === modified file 'sql/log_event.h'
>> --- a/sql/log_event.h 2010-02-14 01:14:36 +0000
>> +++ b/sql/log_event.h 2010-05-28 10:19:04 +0000
>> @@ -251,6 +251,7 @@ struct sql_ex_info
>> #define EXECUTE_LOAD_QUERY_HEADER_LEN (QUERY_HEADER_LEN +
> EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN)
>> #define INCIDENT_HEADER_LEN 2
>> #define HEARTBEAT_HEADER_LEN 0
>> +#define IGNORABLE_HEADER_LEN 0
>> /*
>> Max number of possible extra bytes in a replication event compared to a
>> packet (i.e. a query) sent from client to master;
>> @@ -489,6 +490,13 @@ struct sql_ex_info
>> #define LOG_EVENT_RELAY_LOG_F 0x40
>>
>> /**
>> + @def LOG_EVENT_IGNORABLE_F
>> +
>> + Events with this flag set are ignorable on slave
>> +*/
>> +#define LOG_EVENT_IGNORABLE_F 0x80
>> +
>> +/**
>> @def OPTIONS_WRITTEN_TO_BIN_LOG
>>
>> OPTIONS_WRITTEN_TO_BIN_LOG are the bits of thd->options which must
>> @@ -585,7 +593,16 @@ enum Log_event_type
>> to ensure master's online status to slave
>> */
>> HEARTBEAT_LOG_EVENT= 27,
>> -
>> +
>> + /*
>> + In some situations, it is necessary to send over ignorable
>> + data to the slave: data that a slave can handle in case there
>> + is code for handling it, but which can be ignored if it is not
>> + recognized.
>> + */
>> + IGNORABLE_LOG_EVENT= 28,
>> + ROWS_QUERY_LOG_EVENT= 29,
>> +
>> /*
>> Add new events here - right above this comment!
>> Existing events (except ENUM_END_EVENT) should never change their numbers
>> @@ -1065,6 +1082,7 @@ public:
>> void set_relay_log_event() { flags |= LOG_EVENT_RELAY_LOG_F; }
>> bool is_artificial_event() const { return flags & LOG_EVENT_ARTIFICIAL_F;
> }
>> bool is_relay_log_event() const { return flags & LOG_EVENT_RELAY_LOG_F; }
>> + bool is_ignorable_event() const { return flags & LOG_EVENT_IGNORABLE_F; }
>> inline bool use_trans_cache() const
>> {
>> return (cache_type == Log_event::EVENT_TRANSACTIONAL_CACHE);
>> @@ -3994,6 +4012,93 @@ private:
>> LEX_STRING m_message;
>> };
>>
>> +
>> +/**
>> + @class Ignorable_log_event
>> + Ignorable log event to send over ignorable data to the slave,
>> + and its incremental sub-hierarchy, which have as default that if
>> + their type code are not recognized, these events are just ignored
>> + and replication keeps going as usual.
>> +**/
>> +class Ignorable_log_event : public Log_event {
>> +public:
>> +#ifndef MYSQL_CLIENT
>> + Ignorable_log_event(THD *thd_arg) : Log_event(thd_arg, 0, FALSE)
>> + {
>> + DBUG_ENTER("Ignorable_log_event::Ignorable_log_event");
>> + set_ignorable_event();
>> + DBUG_VOID_RETURN;
>> + }
>>
>
> You can pass in the flag directly when calling the constructor of
> Log_event.
>
>
>> +#endif
>> +
>> + Ignorable_log_event(const char *buf,
>> + const Format_description_log_event *descr_event);
>> +
>> + virtual ~Ignorable_log_event();
>> +
>> +#ifndef MYSQL_CLIENT
>> + void pack_info(Protocol*);
>> +#endif
>> +
>> +#ifdef MYSQL_CLIENT
>> + virtual void print(FILE *file, PRINT_EVENT_INFO *print_event_info);
>> +#endif
>> +
>> + virtual Log_event_type get_type_code() { return IGNORABLE_LOG_EVENT; }
>> +
>> + virtual bool is_valid() const { return 1; }
>> +
>> + virtual int get_data_size() { return IGNORABLE_HEADER_LEN; }
>> +
>> +private:
>> + void set_ignorable_event() { flags |= LOG_EVENT_IGNORABLE_F; }
>> +};
>> +
>> +
>> +class Rows_query_log_event : public Ignorable_log_event {
>> +public:
>> +#ifndef MYSQL_CLIENT
>> + Rows_query_log_event(THD *thd_arg, const char * query, ulong query_len)
>> + : Ignorable_log_event(thd_arg)
>> + {
>> + DBUG_ENTER("Rows_query_log_event::Rows_query_log_event");
>> + ulong len= sizeof("/*!50600<COMMENT> ") + query_len + sizeof(";*/") +
> 1;
>>
>
> I think we will have problem when there is comment in the original
> query.
>
>
>> + if (!(m_rows_query= (char*) my_malloc(len, MYF(MY_WME))))
>> + return;
>> + my_snprintf(m_rows_query, len, "/*!50600<COMMENT> %s;*/", query);
>> + DBUG_PRINT("enter", ("%s", m_rows_query));
>> + DBUG_VOID_RETURN;
>> + }
>> +#endif
>> +
>> +#ifndef MYSQL_CLIENT
>> + void pack_info(Protocol*);
>> +#endif
>> +
>> + Rows_query_log_event(const char *buf, uint event_len,
>> + const Format_description_log_event *descr_event);
>> +
>> + virtual ~Rows_query_log_event();
>> +
>> +#ifdef MYSQL_CLIENT
>> + virtual void print(FILE *file, PRINT_EVENT_INFO *print_event_info);
>> +#endif
>> + virtual bool write_data_body(IO_CACHE *file);
>> +
>> + virtual Log_event_type get_type_code() { return ROWS_QUERY_LOG_EVENT; }
>> +
>> + virtual int get_data_size()
>> + {
>> + return IGNORABLE_HEADER_LEN + 1 + (uint) strlen(m_rows_query);
>> + }
>> +
>> +private:
>> +
>> + char * m_rows_query;
>> +};
>> +
>> +
>> +
>> static inline bool copy_event_cache_to_file_and_reinit(IO_CACHE *cache,
>> FILE *file)
>> {
>>
>> === modified file 'sql/mysqld.cc'
>> --- a/sql/mysqld.cc 2010-03-03 14:43:35 +0000
>> +++ b/sql/mysqld.cc 2010-05-28 10:19:04 +0000
>> @@ -5739,7 +5739,8 @@ enum options_mysqld
>> OPT_SYNC_RELAY_LOG_INFO,
>> OPT_SYNC_MASTER_INFO,
>> OPT_BINLOG_DIRECT_NON_TRANS_UPDATE,
>> - OPT_DEFAULT_CHARACTER_SET_OLD
>> + OPT_DEFAULT_CHARACTER_SET_OLD,
>> + OPT_BINLOG_ROWS_QUERY_LOG_EVENT
>> };
>>
>>
>> @@ -7098,6 +7099,11 @@ The minimum value for this variable is 4
>> "t_innodb; otherwise, slaves may diverge from the master.",
>> (uchar**) &global_system_variables.binlog_direct_non_trans_update,
> (uchar**) &max_system_variables.binlog_direct_non_trans_update, 0, GET_BOOL, NO_ARG,
> 0,
>> 0, 0, 0, 0, 0},
>> + {"binlog-rows-query-log-events", OPT_BINLOG_ROWS_QUERY_LOG_EVENT,
>> + "Allow writing Rows_query_log events into binary log.",
>> + (uchar**) &global_system_variables.binlog_rows_query_log_events,
>> + (uchar**) &max_system_variables.binlog_rows_query_log_events,
>> + 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 1, 0},
>> {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
>> };
>>
>>
>> === modified file 'sql/set_var.cc'
>> --- a/sql/set_var.cc 2010-02-17 07:58:43 +0000
>> +++ b/sql/set_var.cc 2010-05-28 10:19:04 +0000
>> @@ -595,6 +595,9 @@ static sys_var_thd_enum sys_query_cache_
>> static sys_var_thd_bool
>> sys_query_cache_wlock_invalidate(&vars, "query_cache_wlock_invalidate",
>> &SV::query_cache_wlock_invalidate);
>> +static sys_var_thd_bool
>> +sys_binlog_rows_query_log_events(&vars, "binlog_rows_query_log_events",
>> + &SV::binlog_rows_query_log_events);
>> #endif /* HAVE_QUERY_CACHE */
>> static sys_var_bool_ptr sys_secure_auth(&vars, "secure_auth",
> &opt_secure_auth);
>> static sys_var_const_str_ptr sys_secure_file_priv(&vars,
> "secure_file_priv",
>>
>> === modified file 'sql/slave.cc'
>> --- a/sql/slave.cc 2010-02-12 23:30:44 +0000
>> +++ b/sql/slave.cc 2010-05-28 10:19:04 +0000
>> @@ -2369,6 +2369,50 @@ static int exec_relay_log_event(THD* thd
>> delete ev;
>> DBUG_RETURN(1);
>> }
>> +
>> + /*
>> + Every concrete sub-class of Ignorable_log_event will be handled
>> + according to its logic if the SLAVE SQL THREAD can recognize it.
>> + Else the unrecognized one is treated as an Ignorable_log_event
>> + and is ignored after update the positions of the relay log.
>> + */
>> + if (ev && ev->is_ignorable_event())
>> + {
>> + int err_update_pos= 0;
>> + pthread_mutex_unlock(&rli->data_lock);
>> + switch(ev->get_type_code()) {
>> + case IGNORABLE_LOG_EVENT:
>> + case ROWS_QUERY_LOG_EVENT:
>> + err_update_pos= ev->update_pos(rli);
>> + break;
>> + /*
>> + TODO: Added new ignorable event and handle it
>> + according to the concrete class
>> + case table_checksum_log_event:
>> + ......
>> + case lock_log_event:
>> + ......
>> + */
>> + default:
>> + rli->report(ERROR_LEVEL, ER_UNKNOWN_ERROR,
>> + "It should never be happened.");
>> + DBUG_RETURN(1);
>> + }
>> + if (err_update_pos)
>> + {
>> + char buf[22];
>> + rli->report(ERROR_LEVEL, ER_UNKNOWN_ERROR,
>> + "It was not possible to update the positions"
>> + " of the relay log information: the slave may"
>> + " be in an inconsistent state."
>> + " Stopped in %s position %s",
>> + rli->group_relay_log_name,
>> + llstr(rli->group_relay_log_pos, buf));
>> + DBUG_RETURN(1);
>> + }
>> + DBUG_RETURN(0);
>> + }
>> +
>>
>
> I think the logic of how to apply the ignorable event should be put in
> it's do_apply_event() method as what we do for normal events.0
>
>
>> if (ev)
>> {
>> int exec_res;
>>
>> === modified file 'sql/sql_class.h'
>> --- a/sql/sql_class.h 2010-03-17 11:31:50 +0000
>> +++ b/sql/sql_class.h 2010-05-28 10:19:04 +0000
>> @@ -412,6 +412,7 @@ struct system_variables
>> DATE_TIME_FORMAT *datetime_format;
>> DATE_TIME_FORMAT *time_format;
>> my_bool sysdate_is_now;
>> + my_bool binlog_rows_query_log_events;
>> };
>>
>>
>>
>> === modified file 'sql/sql_insert.cc'
>> --- a/sql/sql_insert.cc 2010-03-03 14:43:35 +0000
>> +++ b/sql/sql_insert.cc 2010-05-28 10:19:04 +0000
>> @@ -1701,7 +1701,7 @@ public:
>> time_t start_time;
>> ulong sql_mode;
>> bool auto_increment_field_not_null;
>> - bool query_start_used, ignore, log_query;
>> + bool query_start_used, ignore, log_query, binlog_rows_query_log_events;
>> bool stmt_depends_on_first_successful_insert_id_in_prev_stmt;
>> ulonglong first_successful_insert_id_in_prev_stmt;
>> ulonglong forced_insert_id;
>> @@ -1712,9 +1712,11 @@ public:
>> Time_zone *time_zone;
>>
>> delayed_row(LEX_STRING const query_arg, enum_duplicates dup_arg,
>> - bool ignore_arg, bool log_query_arg)
>> + bool ignore_arg, bool log_query_arg,
>> + bool binlog_rows_query_log_events_arg)
>> : record(0), dup(dup_arg), ignore(ignore_arg), log_query(log_query_arg),
>> - forced_insert_id(0), query(query_arg), time_zone(0)
>> + forced_insert_id(0), query(query_arg), time_zone(0),
>> + binlog_rows_query_log_events(binlog_rows_query_log_events_arg)
>> {}
>> ~delayed_row()
>> {
>> @@ -2191,7 +2193,8 @@ int write_delayed(THD *thd, TABLE *table
>> goto err;
>> query.str= str;
>> }
>> - row= new delayed_row(query, duplic, ignore, log_on);
>> + row= new delayed_row(query, duplic, ignore, log_on,
>> + thd->variables.binlog_rows_query_log_events);
>> if (row == NULL)
>> {
>> my_free(query.str, MYF(MY_WME));
>> @@ -2671,6 +2674,14 @@ bool Delayed_insert::handle_inserts(void
>> */
>> table->file->ha_release_auto_increment();
>> thd.auto_inc_intervals_in_cur_stmt_for_binlog.empty();
>> +
>> + if (row->binlog_rows_query_log_events &&
>> + thd.is_current_stmt_binlog_format_row())
>> + {
>> + /* Write the Rows_query_log_event into binlog with its row event for
> 'insert delayed ...'*/
>> + Rows_query_log_event* ev= new Rows_query_log_event(&thd,
> row->query.str, row->query.length);
>> + mysql_bin_log.write(ev);
>> + }
>> }
>> thd.first_successful_insert_id_in_prev_stmt=
>> row->first_successful_insert_id_in_prev_stmt;
>>
>
>
>
>
>