Commit 4a76ac5f authored by unknown's avatar unknown
Browse files

Bug #27395 OPTION_STATUS_NO_TRANS_UPDATE is not preserved at the end of SF()

thd->options' OPTION_STATUS_NO_TRANS_UPDATE bit was not restored at the end of SF() invocation, where
SF() modified non-ta table.
As the result of this artifact it was not possible to detect whether there were any side-effects when
top-level query ends. 
If the top level query table was not modified and the bit is lost there would be no binlogging.

Fixed with preserving the bit inside of thd->no_trans_update struct. The struct agregates two bool flags
telling whether the current query and the current transaction modified any non-ta table.
The flags stmt, all are dropped at the end of the query and the transaction.


mysql-test/r/sp_trans.result:
  results will be changed once again after bug#23333 will be fixed.
mysql-test/t/sp_trans.test:
  regression test added
sql/ha_ndbcluster.cc:
  replacing thd->options' OPTION_STATUS_NO_TRANS_UPDATE bit and bool thd->no_trans_update
  with thd->no_trans_update as struct
sql/handler.cc:
  replacing operations with thd->options' OPTION_STATUS_NO_TRANS_UPDATE bit
  with the member thd->no_trans_update.all;
  converting thd->no_trans_update into struct of bools.
sql/log.cc:
  replacing operations with thd->options' OPTION_STATUS_NO_TRANS_UPDATE bit
  with the member thd->no_trans_update.all;
  converting thd->no_trans_update into struct of bools.
sql/set_var.cc:
  replacing operations with thd->options' OPTION_STATUS_NO_TRANS_UPDATE bit
  with the member thd->no_trans_update.all;
  converting thd->no_trans_update into struct of bools.
sql/sp_head.cc:
  replacing operations with thd->options' OPTION_STATUS_NO_TRANS_UPDATE bit
  with the member thd->no_trans_update.all;
  converting thd->no_trans_update into struct of bools.
sql/sql_class.h:
  replacing operations with thd->options' OPTION_STATUS_NO_TRANS_UPDATE bit
  with the member thd->no_trans_update.all;
  converting thd->no_trans_update into struct of bools.
sql/sql_delete.cc:
  replacing operations with thd->options' OPTION_STATUS_NO_TRANS_UPDATE bit
  with the member thd->no_trans_update.all;
  converting thd->no_trans_update into struct of bools.
sql/sql_insert.cc:
  replacing operations with thd->options' OPTION_STATUS_NO_TRANS_UPDATE bit
  with the member thd->no_trans_update.all;
  converting thd->no_trans_update into struct of bools.
sql/sql_load.cc:
  replacing operations with thd->options' OPTION_STATUS_NO_TRANS_UPDATE bit
  with the member thd->no_trans_update.all;
  converting thd->no_trans_update into struct of bools.
sql/sql_parse.cc:
  replacing operations with thd->options' OPTION_STATUS_NO_TRANS_UPDATE bit
  with the member thd->no_trans_update.all;
  converting thd->no_trans_update into struct of bools.
sql/sql_table.cc:
  replacing operations with thd->options' OPTION_STATUS_NO_TRANS_UPDATE bit
  with the member thd->no_trans_update.all;
  converting thd->no_trans_update into struct of bools.
sql/sql_update.cc:
  replacing operations with thd->options' OPTION_STATUS_NO_TRANS_UPDATE bit
  with the member thd->no_trans_update.all;
  converting thd->no_trans_update into struct of bools.
parent b444f808
Loading
Loading
Loading
Loading
+32 −0
Original line number Diff line number Diff line
@@ -530,3 +530,35 @@ count(*)
drop table t3, t4|
drop procedure bug14210|
set @@session.max_heap_table_size=default|
drop function if exists bug23333|
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, b int, PRIMARY KEY (a)) ENGINE=InnoDB|
reset master|
insert into t2 values (1,1)|
create function bug23333() 
RETURNS int(11)
DETERMINISTIC
begin
insert into t1 values (null);
select count(*) from t1 into @a;
return @a;
end|
insert into t2 values (bug23333(),1)|
ERROR 23000: Duplicate entry '1' for key 1
show binlog events /* must show the insert */|
Log_name	Pos	Event_type	Server_id	End_log_pos	Info
master-bin.000001	4	Format_desc	1	98	Server ver: 5.0.40-debug-log, Binlog ver: 4
master-bin.000001	98	Query	1	90	use `test`; insert into t2 values (1,1)
master-bin.000001	188	Xid	1	215	COMMIT /* xid=1165 */
master-bin.000001	215	Query	1	446	use `test`; CREATE DEFINER=`root`@`localhost` function bug23333() 
RETURNS int(11)
DETERMINISTIC
begin
insert into t1 values (null);
select count(*) from t1 into @a;
return @a;
end
select count(*),@a from t1 /* must be 1,1 */|
count(*)	@a
1	1
+30 −0
Original line number Diff line number Diff line
@@ -553,6 +553,36 @@ drop procedure bug14210|
set @@session.max_heap_table_size=default|


#
# Bug #13270 INSERT,UPDATE,etc that calls func with side-effect does not binlog
# Bug #23333 stored function + non-transac table + transac table =
#            breaks stmt-based binlog
# Bug #27395 OPTION_STATUS_NO_TRANS_UPDATE is not preserved at the end of SF()
#
--disable_warnings
drop function if exists bug23333|
drop table if exists t1,t2|
--enable_warnings
 CREATE TABLE t1 (a int  NOT NULL auto_increment primary key) ENGINE=MyISAM|
 CREATE TABLE t2 (a int  NOT NULL auto_increment, b int, PRIMARY KEY (a)) ENGINE=InnoDB|

reset master|
insert into t2 values (1,1)|

create function bug23333() 
RETURNS int(11)
DETERMINISTIC
begin
  insert into t1 values (null);
  select count(*) from t1 into @a;
  return @a;
end|

--error ER_DUP_ENTRY
insert into t2 values (bug23333(),1)| 
show binlog events /* must show the insert */|
select count(*),@a from t1 /* must be 1,1 */|

#
# BUG#NNNN: New bug synopsis
#
+1 −2
Original line number Diff line number Diff line
@@ -3636,8 +3636,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->options|= OPTION_STATUS_NO_TRANS_UPDATE;
      thd->no_trans_update= TRUE;
      thd->no_trans_update= {TRUE, TRUE};
    }
    else if (!thd->transaction.on)
      m_transaction_on= FALSE;
+1 −1
Original line number Diff line number Diff line
@@ -830,7 +830,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->options & OPTION_STATUS_NO_TRANS_UPDATE) &&
  if (is_real_trans && thd->no_trans_update.all &&
      !thd->slave_thread)
    push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
                 ER_WARNING_NOT_COMPLETE_ROLLBACK,
+2 −2
Original line number Diff line number Diff line
@@ -162,7 +162,7 @@ static int binlog_rollback(THD *thd, bool all)
    table. Such cases should be rare (updating a
    non-transactional table inside a transaction...)
  */
  if (unlikely(thd->options & OPTION_STATUS_NO_TRANS_UPDATE))
  if (unlikely(thd->no_trans_update.all))
  {
    Query_log_event qev(thd, STRING_WITH_LEN("ROLLBACK"), TRUE, FALSE);
    qev.error_code= 0; // see comment in MYSQL_LOG::write(THD, IO_CACHE)
@@ -217,7 +217,7 @@ static int binlog_savepoint_rollback(THD *thd, void *sv)
    non-transactional table. Otherwise, truncate the binlog cache starting
    from the SAVEPOINT command.
  */
  if (unlikely(thd->options & OPTION_STATUS_NO_TRANS_UPDATE))
  if (unlikely(thd->no_trans_update.all))
  {
    Query_log_event qinfo(thd, thd->query, thd->query_length, TRUE, FALSE);
    DBUG_RETURN(mysql_bin_log.write(&qinfo));
Loading