Commit 09838322 authored by mats@mats-laptop.(none)'s avatar mats@mats-laptop.(none)
Browse files

Merge mkindahl@bk-internal.mysql.com:/home/bk/mysql-5.1-bugteam

into  mats-laptop.(none):/home/bkroot/mysql-5.1-bugteam
parents 81b7dd73 87d7c13a
Loading
Loading
Loading
Loading
+0 −233
Original line number Diff line number Diff line
stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
==== 0. Setting it all up ====
SET BINLOG_FORMAT=STATEMENT;
**** On Master ****
CREATE TABLE t1 (a INT);
CREATE TABLE logtbl (sect INT, test INT, count INT);
INSERT INTO t1 VALUES (1),(2),(3);
INSERT INTO t1 SELECT 2*a+3 FROM t1;
INSERT INTO t1 SELECT 2*a+3 FROM t1;
INSERT INTO t1 SELECT 2*a+3 FROM t1;
INSERT INTO t1 SELECT 2*a+3 FROM t1;
INSERT INTO t1 SELECT 2*a+3 FROM t1;
INSERT INTO t1 SELECT 2*a+3 FROM t1;
#### 1. Using statement mode ####
==== 1.1. Simple test ====
SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a > 5 ORDER BY a LIMIT 1;
a
7
SELECT FOUND_ROWS() INTO @a;
INSERT INTO logtbl VALUES(1,1,@a);
SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a < 5 ORDER BY a LIMIT 1;
a
1
SELECT FOUND_ROWS() INTO @a;
INSERT INTO logtbl VALUES(1,2,@a);
SELECT * FROM logtbl WHERE sect = 1 ORDER BY sect,test;
sect	test	count
1	1	183
1	2	3
**** On Slave ****
SELECT * FROM logtbl WHERE sect = 1 ORDER BY sect,test;
sect	test	count
1	1	183
1	2	3
==== 1.2. Stored procedure ====
**** On Master ****
CREATE PROCEDURE calc_and_log(sect INT, test INT) BEGIN
DECLARE cnt INT;
SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a < 5 ORDER BY a LIMIT 1;
SELECT FOUND_ROWS() INTO cnt;
INSERT INTO logtbl VALUES(sect,test,cnt);
SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a > 5 ORDER BY a LIMIT 1;
SELECT FOUND_ROWS() INTO cnt;
INSERT INTO logtbl VALUES(sect,test+1,cnt);
END $$
CALL calc_and_log(2,1);
a
1
a
7
CREATE PROCEDURE just_log(sect INT, test INT, found_rows INT) BEGIN
INSERT INTO logtbl VALUES (sect,test,found_rows);
END $$
SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a > 5 ORDER BY a LIMIT 1;
a
7
SELECT FOUND_ROWS() INTO @found_rows;
CALL just_log(2,3,@found_rows);
SELECT * FROM logtbl WHERE sect = 2 ORDER BY sect,test;
sect	test	count
2	1	3
2	2	183
2	3	183
**** On Slave ****
SELECT * FROM logtbl WHERE sect = 2 ORDER BY sect,test;
sect	test	count
2	1	3
2	2	183
2	3	183
==== 1.3. Stored functions ====
**** On Master ****
CREATE FUNCTION log_rows(sect INT, test INT, found_rows INT)
RETURNS INT
BEGIN
INSERT INTO logtbl VALUES(sect,test,found_rows);
RETURN found_rows;
END $$
SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a > 5 ORDER BY a LIMIT 1;
a
7
SELECT FOUND_ROWS() INTO @found_rows;
SELECT log_rows(3,1,@found_rows), log_rows(3,2,@found_rows);
log_rows(3,1,@found_rows)	log_rows(3,2,@found_rows)
183	183
SELECT * FROM logtbl WHERE sect = 3 ORDER BY sect,test;
sect	test	count
3	1	183
3	2	183
**** On Slave ****
SELECT * FROM logtbl WHERE sect = 3 ORDER BY sect,test;
sect	test	count
3	1	183
3	2	183
==== 1.9. Cleanup ====
**** On Master ****
DELETE FROM logtbl;
DROP PROCEDURE just_log;
DROP PROCEDURE calc_and_log;
DROP FUNCTION log_rows;
**** Resetting master and slave ****
STOP SLAVE;
RESET SLAVE;
RESET MASTER;
START SLAVE;
#### 2. Using mixed mode ####
==== 2.1. Checking a procedure ====
**** On Master ****
SET BINLOG_FORMAT=MIXED;
CREATE PROCEDURE just_log(sect INT, test INT) BEGIN
INSERT INTO logtbl VALUES (sect,test,FOUND_ROWS());
END $$
**** On Master 1 ****
SET BINLOG_FORMAT=MIXED;
SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a > 5 ORDER BY a LIMIT 1;
a
7
CALL just_log(1,1);
**** On Master ****
SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a > 5 ORDER BY a LIMIT 1;
a
7
CALL just_log(1,2);
**** On Master 1 ****
SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a < 5 ORDER BY a LIMIT 1;
a
1
CALL just_log(1,3);
**** On Master ****
SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a > 5 ORDER BY a LIMIT 1;
a
7
CALL just_log(1,4);
SELECT * FROM logtbl WHERE sect = 1 ORDER BY sect,test;
sect	test	count
1	1	183
1	2	183
1	3	3
1	4	183
**** On Slave ****
SELECT * FROM logtbl WHERE sect = 1 ORDER BY sect,test;
sect	test	count
1	1	183
1	2	183
1	3	3
1	4	183
==== 2.1. Checking a stored function ====
**** On Master ****
CREATE FUNCTION log_rows(sect INT, test INT)
RETURNS INT
BEGIN
DECLARE found_rows INT;
SELECT FOUND_ROWS() INTO found_rows;
INSERT INTO logtbl VALUES(sect,test,found_rows);
RETURN found_rows;
END $$
SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a < 5 ORDER BY a LIMIT 1;
a
1
SELECT log_rows(2,1), log_rows(2,2);
log_rows(2,1)	log_rows(2,2)
3	3
CREATE TABLE t2 (a INT, b INT);
CREATE TRIGGER t2_tr BEFORE INSERT ON t2 FOR EACH ROW
BEGIN
INSERT INTO logtbl VALUES (NEW.a, NEW.b, FOUND_ROWS());
END $$
SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a < 5 ORDER BY a LIMIT 1;
a
1
INSERT INTO t2 VALUES (2,3), (2,4);
DROP TRIGGER t2_tr;
CREATE TRIGGER t2_tr BEFORE INSERT ON t2 FOR EACH ROW
BEGIN
DECLARE dummy INT;
SELECT log_rows(NEW.a, NEW.b) INTO dummy;
END $$
SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a > 5 ORDER BY a LIMIT 1;
a
7
INSERT INTO t2 VALUES (2,5), (2,6);
DROP TRIGGER t2_tr;
CREATE PROCEDURE log_me_inner(sect INT, test INT)
BEGIN
DECLARE dummy INT;
SELECT log_rows(sect, test) INTO dummy;
SELECT log_rows(sect, test+1) INTO dummy;
END $$
CREATE PROCEDURE log_me(sect INT, test INT)
BEGIN
CALL log_me_inner(sect,test);
END $$
CREATE TRIGGER t2_tr BEFORE INSERT ON t2 FOR EACH ROW
BEGIN
CALL log_me(NEW.a, NEW.b);
END $$
SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a > 5 ORDER BY a LIMIT 1;
a
7
INSERT INTO t2 VALUES (2,5), (2,6);
SELECT * FROM logtbl WHERE sect = 2 ORDER BY sect,test;
sect	test	count
2	1	3
2	2	3
2	3	3
2	4	3
2	5	183
2	5	183
2	6	183
2	6	0
2	6	183
2	7	0
SELECT * FROM logtbl WHERE sect = 2 ORDER BY sect,test;
sect	test	count
2	1	3
2	2	3
2	3	3
2	4	3
2	5	183
2	5	183
2	6	183
2	6	0
2	6	183
2	7	0
DROP TABLE t1, logtbl;
DROP PROCEDURE just_log;
DROP PROCEDURE log_me;
DROP PROCEDURE log_me_inner;
DROP FUNCTION log_rows;
+0 −59
Original line number Diff line number Diff line
stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
create table t1 (a int not null primary key);
insert into  t1 values (1);
create table t2 (a int);
insert into  t2 values (1);
update t1, t2 set t1.a = 0 where t1.a = t2.a;
show tables;
Tables_in_test
t1
select * from t1;
a
0
drop table t1;
insert into t1 values (1);
SHOW SLAVE STATUS;
Slave_IO_State	#
Master_Host	127.0.0.1
Master_User	root
Master_Port	MASTER_PORT
Connect_Retry	1
Master_Log_File	master-bin.000001
Read_Master_Log_Pos	1153
Relay_Log_File	#
Relay_Log_Pos	#
Relay_Master_Log_File	master-bin.000001
Slave_IO_Running	Yes
Slave_SQL_Running	No
Replicate_Do_DB	
Replicate_Ignore_DB	
Replicate_Do_Table	
Replicate_Ignore_Table	#
Replicate_Wild_Do_Table	
Replicate_Wild_Ignore_Table	
Last_Errno	1146
Last_Error	Error 'Table 'test.t1' doesn't exist' on opening table `test`.`t1`
Skip_Counter	0
Exec_Master_Log_Pos	941
Relay_Log_Space	#
Until_Condition	None
Until_Log_File	
Until_Log_Pos	0
Master_SSL_Allowed	No
Master_SSL_CA_File	
Master_SSL_CA_Path	
Master_SSL_Cert	
Master_SSL_Cipher	
Master_SSL_Key	
Seconds_Behind_Master	#
Master_SSL_Verify_Server_Cert	No
Last_IO_Errno	#
Last_IO_Error	#
Last_SQL_Errno	1146
Last_SQL_Error	Error 'Table 'test.t1' doesn't exist' on opening table `test`.`t1`
drop table t1, t2;
+0 −256
Original line number Diff line number Diff line
source include/master-slave.inc;

# It is not possible to replicate FOUND_ROWS() using statement-based
# replication, but there is a workaround that stores the result of
# FOUND_ROWS() into a user variable and then replicates this instead.

# The purpose of this test case is to test that the workaround
# function properly even when inside stored programs (i.e., stored
# routines and triggers).

--echo ==== 0. Setting it all up ====

SET BINLOG_FORMAT=STATEMENT;

--echo **** On Master ****
connection master;
CREATE TABLE t1 (a INT);
CREATE TABLE logtbl (sect INT, test INT, count INT);

INSERT INTO t1 VALUES (1),(2),(3);
INSERT INTO t1 SELECT 2*a+3 FROM t1;
INSERT INTO t1 SELECT 2*a+3 FROM t1;
INSERT INTO t1 SELECT 2*a+3 FROM t1;
INSERT INTO t1 SELECT 2*a+3 FROM t1;
INSERT INTO t1 SELECT 2*a+3 FROM t1;
INSERT INTO t1 SELECT 2*a+3 FROM t1;

--echo #### 1. Using statement mode ####

--echo ==== 1.1. Simple test ====

SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a > 5 ORDER BY a LIMIT 1;

# Instead of
#   INSERT INTO logtbl VALUES(1, 1, FOUND_ROWS());
# we write
SELECT FOUND_ROWS() INTO @a;
INSERT INTO logtbl VALUES(1,1,@a);

SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a < 5 ORDER BY a LIMIT 1;
# Instead of
#   INSERT INTO logtbl VALUES(1, 2, FOUND_ROWS());
# we write
SELECT FOUND_ROWS() INTO @a;
INSERT INTO logtbl VALUES(1,2,@a);

SELECT * FROM logtbl WHERE sect = 1 ORDER BY sect,test;
--echo **** On Slave ****
sync_slave_with_master;
SELECT * FROM logtbl WHERE sect = 1 ORDER BY sect,test;

--echo ==== 1.2. Stored procedure ====

# Here we do both the calculation and the logging. We also do it twice
# to make sure that there are no limitations on how many times it can
# be used.

--echo **** On Master ****
connection master;
--delimiter $$
CREATE PROCEDURE calc_and_log(sect INT, test INT) BEGIN
  DECLARE cnt INT;
  SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a < 5 ORDER BY a LIMIT 1;
  SELECT FOUND_ROWS() INTO cnt;
  INSERT INTO logtbl VALUES(sect,test,cnt);
  SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a > 5 ORDER BY a LIMIT 1;
  SELECT FOUND_ROWS() INTO cnt;
  INSERT INTO logtbl VALUES(sect,test+1,cnt);
END $$
--delimiter ;

CALL calc_and_log(2,1);

--delimiter $$
CREATE PROCEDURE just_log(sect INT, test INT, found_rows INT) BEGIN
  INSERT INTO logtbl VALUES (sect,test,found_rows);
END $$
--delimiter ;

SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a > 5 ORDER BY a LIMIT 1;
SELECT FOUND_ROWS() INTO @found_rows;
CALL just_log(2,3,@found_rows);

SELECT * FROM logtbl WHERE sect = 2 ORDER BY sect,test;
--echo **** On Slave ****
sync_slave_with_master;
SELECT * FROM logtbl WHERE sect = 2 ORDER BY sect,test;

--echo ==== 1.3. Stored functions ====
--echo **** On Master ****
connection master;
--delimiter $$
CREATE FUNCTION log_rows(sect INT, test INT, found_rows INT)
  RETURNS INT
BEGIN
  INSERT INTO logtbl VALUES(sect,test,found_rows);
  RETURN found_rows;
END $$
--delimiter ;

SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a > 5 ORDER BY a LIMIT 1;
SELECT FOUND_ROWS() INTO @found_rows;
SELECT log_rows(3,1,@found_rows), log_rows(3,2,@found_rows);

SELECT * FROM logtbl WHERE sect = 3 ORDER BY sect,test;
--echo **** On Slave ****
sync_slave_with_master;
SELECT * FROM logtbl WHERE sect = 3 ORDER BY sect,test;

--echo ==== 1.9. Cleanup ====
--echo **** On Master ****
connection master;
DELETE FROM logtbl;
DROP PROCEDURE just_log;
DROP PROCEDURE calc_and_log;
DROP FUNCTION log_rows;
sync_slave_with_master;

source include/reset_master_and_slave.inc;

--echo #### 2. Using mixed mode ####

--echo ==== 2.1. Checking a procedure ====

--echo **** On Master ****
connection master;
SET BINLOG_FORMAT=MIXED;

# We will now check some stuff that will not work in statement-based
# replication, but which should cause the binary log to switch to
# row-based logging.

--delimiter $$
CREATE PROCEDURE just_log(sect INT, test INT) BEGIN
  INSERT INTO logtbl VALUES (sect,test,FOUND_ROWS());
END $$
--delimiter ;
sync_slave_with_master;

--echo **** On Master 1 ****
connection master1;
SET BINLOG_FORMAT=MIXED;
SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a > 5 ORDER BY a LIMIT 1;
CALL just_log(1,1);

--echo **** On Master ****
connection master;
SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a > 5 ORDER BY a LIMIT 1;
CALL just_log(1,2);

--echo **** On Master 1 ****

connection master1;
SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a < 5 ORDER BY a LIMIT 1;
CALL just_log(1,3);
sync_slave_with_master;

--echo **** On Master ****
connection master;
SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a > 5 ORDER BY a LIMIT 1;
CALL just_log(1,4);
sync_slave_with_master;

connection master;
SELECT * FROM logtbl WHERE sect = 1 ORDER BY sect,test;
--echo **** On Slave ****
sync_slave_with_master;
SELECT * FROM logtbl WHERE sect = 1 ORDER BY sect,test;

--echo ==== 2.1. Checking a stored function ====
--echo **** On Master ****
connection master;
--delimiter $$
CREATE FUNCTION log_rows(sect INT, test INT)
  RETURNS INT
BEGIN
  DECLARE found_rows INT;
  SELECT FOUND_ROWS() INTO found_rows;
  INSERT INTO logtbl VALUES(sect,test,found_rows);
  RETURN found_rows;
END $$
--delimiter ;

SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a < 5 ORDER BY a LIMIT 1;
SELECT log_rows(2,1), log_rows(2,2);

CREATE TABLE t2 (a INT, b INT);

# Trying with referencing FOUND_ROWS() directly in the trigger.

--delimiter $$
CREATE TRIGGER t2_tr BEFORE INSERT ON t2 FOR EACH ROW
BEGIN
  INSERT INTO logtbl VALUES (NEW.a, NEW.b, FOUND_ROWS());
END $$
--delimiter ;

SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a < 5 ORDER BY a LIMIT 1;
INSERT INTO t2 VALUES (2,3), (2,4);

# Referencing FOUND_ROWS() indirectly.

DROP TRIGGER t2_tr;

--delimiter $$
CREATE TRIGGER t2_tr BEFORE INSERT ON t2 FOR EACH ROW
BEGIN
  DECLARE dummy INT;
  SELECT log_rows(NEW.a, NEW.b) INTO dummy;
END $$
--delimiter ;

SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a > 5 ORDER BY a LIMIT 1;
INSERT INTO t2 VALUES (2,5), (2,6);

# Putting FOUND_ROWS() even lower in the call chain.

connection master;
DROP TRIGGER t2_tr;

--delimiter $$
CREATE PROCEDURE log_me_inner(sect INT, test INT)
BEGIN
  DECLARE dummy INT;
  SELECT log_rows(sect, test) INTO dummy;
  SELECT log_rows(sect, test+1) INTO dummy;
END $$

CREATE PROCEDURE log_me(sect INT, test INT)
BEGIN
  CALL log_me_inner(sect,test);
END $$
--delimiter ;

--delimiter $$
CREATE TRIGGER t2_tr BEFORE INSERT ON t2 FOR EACH ROW
BEGIN
  CALL log_me(NEW.a, NEW.b);
END $$
--delimiter ;

SELECT SQL_CALC_FOUND_ROWS * FROM t1 WHERE a > 5 ORDER BY a LIMIT 1;
INSERT INTO t2 VALUES (2,5), (2,6);

SELECT * FROM logtbl WHERE sect = 2 ORDER BY sect,test;
sync_slave_with_master;
SELECT * FROM logtbl WHERE sect = 2 ORDER BY sect,test;

connection master;
DROP TABLE t1, logtbl;
DROP PROCEDURE just_log;
DROP PROCEDURE log_me;
DROP PROCEDURE log_me_inner;
DROP FUNCTION log_rows;
sync_slave_with_master;
+0 −59
Original line number Diff line number Diff line
--source include/master-slave.inc

############################################################################
# Test case for BUG#10780
#
# REQUIREMENT
#   A slave without replication privileges should have Slave_IO_Running = No

# 1. Create new replication user
connection master;
grant replication slave on *.* to rpl@127.0.0.1 identified by 'rpl';

connection slave;
stop slave;
change master to master_user='rpl',master_password='rpl';
start slave;

# 2. Do replication as new user
connection master;
--disable_warnings
drop table if exists t1;
--enable_warnings
create table t1 (n int);
insert into t1 values (1);
save_master_pos;
connection slave;
sync_with_master;
select * from t1;

# 3. Delete new replication user
connection master;
delete from mysql.user where user='rpl';
flush privileges;
connection slave;

# 4. Restart slave without privileges
# (slave.err will contain access denied error for this START SLAVE command)
stop slave;
start slave;

# 5. Make sure Slave_IO_Running = No
--replace_result $MASTER_MYPORT MASTER_MYPORT
# Column 1 is replaced, since the output can be either
# "Connecting to master" or "Waiting for master update"
--replace_column 1 # 7 # 8 # 9 # 22 # 23 # 35 # 36 #
--vertical_results
show slave status;

# Cleanup (Note that slave IO thread is not running)
connection slave;
drop table t1;
delete from mysql.user where user='rpl';
# cleanup: slave io thread has been stopped "irrecoverably"
# so we clean up mess manually

connection master;
drop table t1;

# end of 4.1 tests
+36 −137
Original line number Diff line number Diff line
@@ -6425,15 +6425,29 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli)
  */
  if (!thd->lock)
  {
    bool need_reopen= 1; /* To execute the first lap of the loop below */

    /*
      lock_tables() reads the contents of thd->lex, so they must be
      initialized. Contrary to in
      Table_map_log_event::do_apply_event() we don't call
      mysql_init_query() as that may reset the binlog format.
      Lock_tables() reads the contents of thd->lex, so they must be
      initialized.

      We also call the mysql_reset_thd_for_next_command(), since this
      is the logical start of the next "statement". Note that this
      call might reset the value of current_stmt_binlog_row_based, so
      we need to do any changes to that value after this function.
    */
    lex_start(thd);
    mysql_reset_thd_for_next_command(thd);

    /*
      Check if the slave is set to use SBR.  If so, it should switch
      to using RBR until the end of the "statement", i.e., next
      STMT_END_F or next error.
    */
    if (!thd->current_stmt_binlog_row_based &&
        mysql_bin_log.is_open() && (thd->options & OPTION_BIN_LOG))
    {
      thd->set_current_stmt_binlog_row_based();
    }


    /*
      There are a few flags that are replicated with each row event.
@@ -6452,72 +6466,23 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli)
    /* A small test to verify that objects have consistent types */
    DBUG_ASSERT(sizeof(thd->options) == sizeof(OPTION_RELAXED_UNIQUE_CHECKS));


    while ((error= lock_tables(thd, rli->tables_to_lock,
                               rli->tables_to_lock_count, &need_reopen)))
    {
      if (!need_reopen)
    if (simple_open_n_lock_tables(thd, rli->tables_to_lock))
    {
        if (thd->is_slave_error || thd->is_fatal_error)
        {
          /*
            Error reporting borrowed from Query_log_event with many excessive
            simplifications (we don't honour --slave-skip-errors)
          */
      uint actual_error= thd->main_da.sql_errno();
          rli->report(ERROR_LEVEL, actual_error,
                      "Error '%s' in %s event: when locking tables",
                      (actual_error ? thd->main_da.message():
                       "unexpected success or fatal error"),
                      get_type_str());
          thd->is_fatal_error= 1;
        }
        else
        {
          rli->report(ERROR_LEVEL, error,
                      "Error in %s event: when locking tables",
                      get_type_str());
        }
        const_cast<Relay_log_info*>(rli)->clear_tables_to_lock();
        DBUG_RETURN(error);
      }

      /*
        So we need to reopen the tables.

        We need to flush the pending RBR event, since it keeps a
        pointer to an open table.

        ALTERNATIVE SOLUTION (not implemented): Extract a pointer to
        the pending RBR event and reset the table pointer after the
        tables has been reopened.

        NOTE: For this new scheme there should be no pending event:
        need to add code to assert that is the case.
       */
      thd->binlog_flush_pending_rows_event(false);
      TABLE_LIST *tables= rli->tables_to_lock;
      close_tables_for_reopen(thd, &tables);

      uint tables_count= rli->tables_to_lock_count;
      if ((error= open_tables(thd, &tables, &tables_count, 0)))
      {
      if (thd->is_slave_error || thd->is_fatal_error)
      {
        /*
          Error reporting borrowed from Query_log_event with many excessive
          simplifications (we don't honour --slave-skip-errors)
        */
          uint actual_error= thd->main_da.sql_errno();
        rli->report(ERROR_LEVEL, actual_error,
                      "Error '%s' on reopening tables",
                    "Error '%s' on opening tables",
                    (actual_error ? thd->main_da.message() :
                     "unexpected success or fatal error"));
        thd->is_slave_error= 1;
      }
      const_cast<Relay_log_info*>(rli)->clear_tables_to_lock();
        DBUG_RETURN(error);
      }
      DBUG_RETURN(actual_error);
    }

    /*
@@ -6570,6 +6535,8 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli)
    table= 
    m_table= const_cast<Relay_log_info*>(rli)->m_table_map.get_table(m_table_id);

  DBUG_PRINT("debug", ("m_table: 0x%lx, m_table_id: %lu", (ulong) m_table, m_table_id));

  if (table)
  {
    /*
@@ -7293,71 +7260,7 @@ int Table_map_log_event::do_apply_event(Relay_log_info const *rli)
  }
  else
  {
    /*
      open_tables() reads the contents of thd->lex, so they must be
      initialized, so we should call lex_start(); to be even safer, we
      call mysql_init_query() which does a more complete set of inits.
    */
    lex_start(thd);
    mysql_reset_thd_for_next_command(thd);
    /*
      Check if the slave is set to use SBR.  If so, it should switch
      to using RBR until the end of the "statement", i.e., next
      STMT_END_F or next error.
    */
    if (!thd->current_stmt_binlog_row_based &&
        mysql_bin_log.is_open() && (thd->options & OPTION_BIN_LOG))
    {
      thd->set_current_stmt_binlog_row_based();
    }

    /*
      Open the table if it is not already open and add the table to
      table map.  Note that for any table that should not be
      replicated, a filter is needed.

      The creation of a new TABLE_LIST is used to up-cast the
      table_list consisting of RPL_TABLE_LIST items. This will work
      since the only case where the argument to open_tables() is
      changed, is when thd->lex->query_tables == table_list, i.e.,
      when the statement requires prelocking. Since this is not
      executed when a statement is executed, this case will not occur.
      As a precaution, an assertion is added to ensure that the bad
      case is not a fact.

      Either way, the memory in the list is *never* released
      internally in the open_tables() function, hence we take a copy
      of the pointer to make sure that it's not lost.
    */
    uint count;
    DBUG_ASSERT(thd->lex->query_tables != table_list);
    TABLE_LIST *tmp_table_list= table_list;
    if ((error= open_tables(thd, &tmp_table_list, &count, 0)))
    {
      if (thd->is_slave_error || thd->is_fatal_error)
      {
        /*
          Error reporting borrowed from Query_log_event with many excessive
          simplifications (we don't honour --slave-skip-errors)
        */
        uint actual_error= thd->main_da.sql_errno();
        rli->report(ERROR_LEVEL, actual_error,
                    "Error '%s' on opening table `%s`.`%s`",
                    (actual_error ? thd->main_da.message() :
                     "unexpected success or fatal error"),
                    table_list->db, table_list->table_name);
        thd->is_slave_error= 1;
      }
      goto err;
    }

    m_table= table_list->table;

    /*
      This will fail later otherwise, the 'in_use' field should be
      set to the current thread.
    */
    DBUG_ASSERT(m_table->in_use);

    /*
      Use placement new to construct the table_def instance in the
@@ -7383,10 +7286,6 @@ int Table_map_log_event::do_apply_event(Relay_log_info const *rli)
  }

  DBUG_RETURN(error);

err:
  my_free(memory, MYF(MY_WME));
  DBUG_RETURN(error);
}

Log_event::enum_skip_reason
Loading