Commit 9286d1c1 authored by unknown's avatar unknown
Browse files

Prevent adding 'CREATE TABLE .. SELECT' query to the binary log when the

insertion of new records partially failed. It would get logged because of the
logic to log a partially-failed 'INSERT ... SELECT' (which can't be rolled back
in non-transactional tables), but 'CREATE TABLE ... SELECT' is always rolled
back on failure, even for non-transactional tables. (Bug #6682)
(Original fix reimplemented after review by Serg and Guilhem.)


mysql-test/t/insert_select.test:
  Add test case for Bug #6682
mysql-test/r/insert_select.result:
  Add results for test case for Bug #6682
sql/sql_table.cc:
  moved tmp_disable_binlog() and reenable_binlog macros to sql/sql_class.h
sql/sql_insert.cc:
  disable binlog during call to super's ::send_error in select_create class
sql/sql_class.h:
  add select_create::send_error()
BitKeeper/etc/logging_ok:
  Logging to logging@openlogging.org accepted
parent a845e882
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -64,6 +64,7 @@ jcole@main.burghcom.com
jcole@mugatu.spaceapes.com
jcole@sarvik.tfr.cafe.ee
jcole@tetra.spaceapes.com
jimw@mysql.com
joerg@mysql.com
jorge@linux.jorge.mysql.com
kaj@work.mysql.com
+9 −0
Original line number Diff line number Diff line
@@ -78,6 +78,15 @@ master-bin.001 4 Start 1 4 Server ver: VERSION, Binlog ver: 3
master-bin.001	79	Query	1	79	use `test`; insert into t1 select * from t2
drop table t1, t2;
drop table if exists t1, t2;
create table t1(a int);
insert into t1 values(1),(1);
reset master;
create table t2(unique(a)) select a from t1;
Duplicate entry '1' for key 1
show binlog events;
Log_name	Pos	Event_type	Server_id	Orig_log_pos	Info
master-bin.001	4	Start	1	4	Server ver: VERSION, Binlog ver: 3
drop table t1;
create table t1 (a int not null);
create table t2 (a int not null);
insert into t1 values (1);
+13 −0
Original line number Diff line number Diff line
@@ -86,6 +86,19 @@ show binlog events;
drop table t1, t2;
drop table if exists t1, t2;

# Verify that a partly-completed CREATE TABLE .. SELECT does not
# get into the binlog (Bug #6682)
create table t1(a int);
insert into t1 values(1),(1);
reset master;
--error 1062
create table t2(unique(a)) select a from t1;
# The above should produce an error, *and* not appear in the binlog
let $VERSION=`select version()`;
--replace_result $VERSION VERSION
show binlog events;
drop table t1;

#
# Test of insert ... select from same table
#
+10 −0
Original line number Diff line number Diff line
@@ -637,6 +637,15 @@ class THD :public ilink
#endif
};

# define tmp_disable_binlog(A)                                          \
  ulong save_options= (A)->options, save_master_access= (A)->master_access; \
  (A)->options&= ~OPTION_BIN_LOG;                                       \
  (A)->master_access|= SUPER_ACL; /* unneeded in 4.1 */                 

#define reenable_binlog(A)                      \
  (A)->options= save_options;                   \
  (A)->master_access= save_master_access;       

/* Flags for the THD::system_thread (bitmap) variable */
#define SYSTEM_THREAD_DELAYED_INSERT 1
#define SYSTEM_THREAD_SLAVE_IO 2
@@ -781,6 +790,7 @@ class select_create: public select_insert {
    {}
  int prepare(List<Item> &list);
  bool send_data(List<Item> &values);
  void send_error(uint errcode,const char *err);
  bool send_eof();
  void abort();
};
+13 −0
Original line number Diff line number Diff line
@@ -1505,6 +1505,19 @@ bool select_create::send_data(List<Item> &values)
  return 0;
}


void select_create::send_error(uint errcode,const char *err)
{
  /*
   Disable binlog, because we "roll back" partial inserts in ::abort
   by removing the table, even for non-transactional tables.
  */
  tmp_disable_binlog(thd);
  select_insert::send_error(errcode, err);
  reenable_binlog(thd);
}


extern HASH open_cache;


Loading