Commit daa5c203 authored by gkodinov/kgeorge@magare.gmz's avatar gkodinov/kgeorge@magare.gmz
Browse files

Merge gkodinov@bk-internal.mysql.com:/home/bk/mysql-5.0-opt

into  magare.gmz:/home/kgeorge/mysql/autopush/B27417-5.0-opt
parents 1717dbf8 500af554
Loading
Loading
Loading
Loading
+113 −0
Original line number Diff line number Diff line
@@ -280,3 +280,116 @@ select
@a like "%#%error_code=0%ROLLBACK/*!*/;%ROLLBACK /* added by mysqlbinlog */;%"	@a not like "%#%error_code=%error_code=%"
1	1
drop table t1, t2;
create temporary table tt (a int unique);
create table ti (a int) engine=innodb;
reset master;
show master status;
File	Position	Binlog_Do_DB	Binlog_Ignore_DB
master-bin.000001	98		
begin;
insert into ti values (1);
insert into ti values (2) ;
insert into tt select * from ti;
rollback;
Warnings:
Warning	1196	Some non-transactional changed tables couldn't be rolled back
select count(*) from tt /* 2 */;
count(*)
2
show master status;
File	Position	Binlog_Do_DB	Binlog_Ignore_DB
master-bin.000001	507		
show binlog events from 98;
Log_name	Pos	Event_type	Server_id	End_log_pos	Info
master-bin.000001	#	Query	1	#	use `test`; BEGIN
master-bin.000001	#	Query	1	#	use `test`; insert into ti values (1)
master-bin.000001	#	Query	1	#	use `test`; insert into ti values (2)
master-bin.000001	#	Query	1	#	use `test`; insert into tt select * from ti
master-bin.000001	#	Query	1	#	use `test`; ROLLBACK
select count(*) from ti /* zero */;
count(*)
0
insert into ti select * from tt;
select * from ti /* that is what slave would miss - a bug */;
a
1
2
delete from ti;
delete from tt where a=1;
reset master;
show master status;
File	Position	Binlog_Do_DB	Binlog_Ignore_DB
master-bin.000001	98		
begin;
insert into ti values (1);
insert into ti values (2) /* to make the dup error in the following */;
insert into tt select * from ti /* one affected and error */;
ERROR 23000: Duplicate entry '2' for key 1
rollback;
Warnings:
Warning	1196	Some non-transactional changed tables couldn't be rolled back
show master status;
File	Position	Binlog_Do_DB	Binlog_Ignore_DB
master-bin.000001	581		
show binlog events from 98;
Log_name	Pos	Event_type	Server_id	End_log_pos	Info
master-bin.000001	#	Query	1	#	use `test`; BEGIN
master-bin.000001	#	Query	1	#	use `test`; insert into ti values (1)
master-bin.000001	#	Query	1	#	use `test`; insert into ti values (2) /* to make the dup error in the following */
master-bin.000001	#	Query	1	#	use `test`; insert into tt select * from ti /* one affected and error */
master-bin.000001	#	Query	1	#	use `test`; ROLLBACK
select count(*) from ti /* zero */;
count(*)
0
insert into ti select * from tt;
select * from tt /* that is what otherwise slave missed - the bug */;
a
1
2
drop table ti;
drop function if exists bug27417;
drop table if exists t1,t2;
CREATE TABLE t1 (a int NOT NULL auto_increment primary key) ENGINE=MyISAM;
CREATE TABLE t2 (a int NOT NULL auto_increment, PRIMARY KEY (a));
create function bug27417(n int) 
RETURNS int(11)
begin
insert into t1 values (null);
return n;
end|
reset master;
insert into t2 values (bug27417(1));
insert into t2 select bug27417(2);
reset master;
insert into t2 values (bug27417(2));
ERROR 23000: Duplicate entry '2' for key 1
show master status;
File	Position	Binlog_Do_DB	Binlog_Ignore_DB
master-bin.000001	98		
/* only (!) with fixes for #23333 will show there is the query */;
select count(*) from t1 /* must be 3 */;
count(*)
3
reset master;
select count(*) from t2;
count(*)
2
delete from t2 where a=bug27417(3);
select count(*) from t2 /* nothing got deleted */;
count(*)
2
show master status;
File	Position	Binlog_Do_DB	Binlog_Ignore_DB
master-bin.000001	195		
/* the query must be in regardless of #23333 */;
select count(*) from t1 /* must be 5 */;
count(*)
5
delete t2 from t2 where t2.a=bug27417(100) /* must not affect t2 */;
affected rows: 0
select count(*) from t1 /* must be 7 */;
count(*)
7
drop function bug27417;
drop table t1,t2;
end of tests
+120 −2
Original line number Diff line number Diff line
@@ -233,8 +233,6 @@ source include/show_binlog_events.inc;
do release_lock("lock1");
drop table t0,t2;

# End of 4.1 tests

# Test for BUG#16559 (ROLLBACK should always have a zero error code in
# binlog). Has to be here and not earlier, as the SELECTs influence
# XIDs differently between normal and ps-protocol (and SHOW BINLOG
@@ -267,3 +265,123 @@ eval select
@a like "%#%error_code=0%ROLLBACK/*!*/;%ROLLBACK /* added by mysqlbinlog */;%",
@a not like "%#%error_code=%error_code=%";
drop table t1, t2;

#
# Bug #27417  	thd->no_trans_update.stmt lost value inside of SF-exec-stack
# bug #28960    non-trans temp table changes with insert .. select
#               not binlogged after rollback
#
# testing appearence of insert into temp_table in binlog.
# There are two branches of execution that require different setup.

## send_eof() branch

# prepare

create temporary table tt (a int unique);
create table ti (a int) engine=innodb;
reset master;
show master status;

# action

begin; 
insert into ti values (1); 
insert into ti values (2) ; 
insert into tt select * from ti;
rollback;

# check

select count(*) from tt /* 2 */;
show master status;
--replace_column 2 # 5 #
show binlog events from 98;
select count(*) from ti /* zero */;
insert into ti select * from tt;
select * from ti /* that is what slave would miss - a bug */;


## send_error() branch
delete from ti;
delete from tt where a=1;
reset master;
show master status;

# action

begin; 
insert into ti values (1); 
insert into ti values (2) /* to make the dup error in the following */; 
--error ER_DUP_ENTRY
insert into tt select * from ti /* one affected and error */;
rollback;

# check

show master status;
--replace_column 2 # 5 #
show binlog events from 98;
select count(*) from ti /* zero */;
insert into ti select * from tt;
select * from tt /* that is what otherwise slave missed - the bug */;

drop table ti;


#
# Bug #27417 thd->no_trans_update.stmt lost value inside of SF-exec-stack
#
# Testing asserts: if there is a side effect of modifying non-transactional
# table thd->no_trans_update.stmt must be TRUE;
# the assert is active with debug build
#

--disable_warnings
drop function if exists bug27417;
drop table if exists t1,t2;
--enable_warnings
# side effect table
CREATE TABLE t1 (a int NOT NULL auto_increment primary key) ENGINE=MyISAM;
# target tables
CREATE TABLE t2 (a int NOT NULL auto_increment, PRIMARY KEY (a));

delimiter |;
create function bug27417(n int) 
RETURNS int(11)
begin
  insert into t1 values (null);
  return n;
end|
delimiter ;|

reset master;

# execute

insert into t2 values (bug27417(1));
insert into t2 select bug27417(2);
reset master;

--error ER_DUP_ENTRY
insert into t2 values (bug27417(2)); 
show master status; /* only (!) with fixes for #23333 will show there is the query */;
select count(*) from t1 /* must be 3 */;

reset master;
select count(*) from t2;
delete from t2 where a=bug27417(3);
select count(*) from t2 /* nothing got deleted */; 
show master status; /* the query must be in regardless of #23333 */;
select count(*) from t1 /* must be 5 */;

--enable_info
delete t2 from t2 where t2.a=bug27417(100) /* must not affect t2 */;
--disable_info
select count(*) from t1 /* must be 7 */;

drop function bug27417;
drop table t1,t2;

--echo end of tests
+1 −1
Original line number Diff line number Diff line
@@ -3732,7 +3732,7 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type)
    {
      m_transaction_on= FALSE;
      /* Would be simpler if has_transactions() didn't always say "yes" */
      thd->no_trans_update.all= thd->no_trans_update.stmt= TRUE;
      thd->transaction.all.modified_non_trans_table= thd->transaction.stmt.modified_non_trans_table= TRUE;
    }
    else if (!thd->transaction.on)
      m_transaction_on= FALSE;
+1 −1
Original line number Diff line number Diff line
@@ -833,7 +833,7 @@ int ha_rollback_trans(THD *thd, bool all)
    the error log; but we don't want users to wonder why they have this
    message in the error log, so we don't send it.
  */
  if (is_real_trans && thd->no_trans_update.all &&
  if (is_real_trans && thd->transaction.all.modified_non_trans_table &&
      !thd->slave_thread)
    push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
                 ER_WARNING_NOT_COMPLETE_ROLLBACK,
+29 −0
Original line number Diff line number Diff line
@@ -420,6 +420,35 @@ typedef struct st_thd_trans
  bool        no_2pc;
  /* storage engines that registered themselves for this transaction */
  handlerton *ht[MAX_HA];
  /* 
    The purpose of this flag is to keep track of non-transactional
    tables that were modified in scope of:
    - transaction, when the variable is a member of
    THD::transaction.all
    - top-level statement or sub-statement, when the variable is a
    member of THD::transaction.stmt
    This member has the following life cycle:
    * stmt.modified_non_trans_table is used to keep track of
    modified non-transactional tables of top-level statements. At
    the end of the previous statement and at the beginning of the session,
    it is reset to FALSE.  If such functions
    as mysql_insert, mysql_update, mysql_delete etc modify a
    non-transactional table, they set this flag to TRUE.  At the
    end of the statement, the value of stmt.modified_non_trans_table 
    is merged with all.modified_non_trans_table and gets reset.
    * all.modified_non_trans_table is reset at the end of transaction
    
    * Since we do not have a dedicated context for execution of a
    sub-statement, to keep track of non-transactional changes in a
    sub-statement, we re-use stmt.modified_non_trans_table. 
    At entrance into a sub-statement, a copy of the value of
    stmt.modified_non_trans_table (containing the changes of the
    outer statement) is saved on stack. Then 
    stmt.modified_non_trans_table is reset to FALSE and the
    substatement is executed. Then the new value is merged with the
    saved value.
  */
  bool modified_non_trans_table;
} THD_TRANS;

enum enum_tx_isolation { ISO_READ_UNCOMMITTED, ISO_READ_COMMITTED,
Loading