Below is the list of changes that have just been committed into a local
5.0 repository of elkin. When elkin does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet@stripped, 2007-06-23 16:33:39+03:00, aelkin@stripped
+7 -0
Bug #29136 erred multi-delete on trans table does not rollback the statement
similar to bug_27716, but it was stressed on in the synopsis on that there is another
side of the artifact affecting behaviour in transaction.
Fixed with deploying multi_delete::send_error() - otherwise never called - and refining
its logic
to perform binlogging job if needed.
A small refinement for the related bug's fix
mysql-test/r/innodb.result@stripped, 2007-06-23 16:33:33+03:00,
aelkin@stripped +18 -5
results changed
mysql-test/r/multi_update.result@stripped, 2007-06-23 16:33:33+03:00,
aelkin@stripped +15 -0
results changed
mysql-test/t/innodb.test@stripped, 2007-06-23 16:33:33+03:00,
aelkin@stripped +32 -0
trans engine specific test added
mysql-test/t/multi_update.test@stripped, 2007-06-23 16:33:33+03:00,
aelkin@stripped +32 -0
the schedule: send_eof() (binloggin there), send_error (early return)
sql/sql_delete.cc@stripped, 2007-06-23 16:33:33+03:00,
aelkin@stripped +29 -5
expanding multi_delete::send_error to
1. early return if binlogged == t
2. binlog locally if there were non-trans table modified side effect
sql/sql_parse.cc@stripped, 2007-06-23 16:33:34+03:00,
aelkin@stripped +7 -0
adding multi_update::send_error which can perform binlogging and rollback job in
needed
sql/sql_update.cc@stripped, 2007-06-23 16:33:34+03:00,
aelkin@stripped +2 -2
a minor issue relating to bug_27716 with zeroing inside of binlogging branch. Moved
outside to avoid double work in ::send_error()
when binlog is off.
# This is a BitKeeper patch. What follows are the unified diffs for the
# set of deltas contained in the patch. The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User: aelkin
# Host: dsl-hkibras1-ff5dc300-70.dhcp.inet.fi
# Root: /home/elkin/MySQL/TEAM/FIXES/5.0/bug29136-mdelete
--- 1.198/sql/sql_delete.cc 2007-04-20 13:30:47 +03:00
+++ 1.199/sql/sql_delete.cc 2007-06-23 16:33:33 +03:00
@@ -678,13 +678,16 @@ void multi_delete::send_error(uint errco
/* First send error what ever it is ... */
my_message(errcode, err, MYF(0));
-
- /* If nothing deleted return */
- if (!deleted)
+ // TODO: merge with bug#27417,23333
+ //thd->no_trans_update.top |= thd->no_trans_update.stmt;
+ /* If nothing deleted and no side effects return */
+ //if ((!thd->no_trans_update.top && !deleted) || binlogged)
+ if (deleted == 0)
DBUG_VOID_RETURN;
/* Something already deleted so we have to invalidate cache */
- query_cache_invalidate3(thd, delete_tables, 1);
+ if (deleted)
+ query_cache_invalidate3(thd, delete_tables, 1);
/*
If rows from the first table only has been deleted and it is
@@ -703,8 +706,22 @@ void multi_delete::send_error(uint errco
error log
*/
error= 1;
- send_eof();
+ send_eof(); // deleted sets to zero
}
+ //TODO the merge: if (thd->no_trans_update.top)
+ if (deleted != 0 && normal_tables)
+ {
+ /* if there is side effect - binlog with the error */
+ if (mysql_bin_log.is_open())
+ {
+ Query_log_event qinfo(thd, thd->query, thd->query_length,
+ transactional_tables, FALSE);
+ mysql_bin_log.write(&qinfo);
+ }
+ if (thd->no_trans_update.stmt)
+ thd->no_trans_update.all= TRUE;
+ }
+ DBUG_ASSERT(!normal_tables || !deleted || thd->no_trans_update.stmt);
DBUG_VOID_RETURN;
}
@@ -819,9 +836,16 @@ bool multi_delete::send_eof()
if (mysql_bin_log.write(&qinfo) && !normal_tables)
local_error=1; // Log write failed: roll back the SQL statement
}
+ /*
+ flag the fact so that there will be the early return from
+ send_error() if one will be called
+ */
if (!transactional_tables)
thd->no_trans_update.all= TRUE;
}
+ if (local_error)
+ deleted= 0; // to force early leave from ::send_error()
+
/* Commit or rollback the current SQL statement */
if (transactional_tables)
if (ha_autocommit_or_rollback(thd,local_error > 0))
--- 1.623/sql/sql_parse.cc 2007-06-05 18:28:42 +03:00
+++ 1.624/sql/sql_parse.cc 2007-06-23 16:33:34 +03:00
@@ -3684,6 +3684,13 @@ end_with_restore_list:
SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK |
OPTION_SETUP_TABLES_DONE,
del_result, unit, select_lex);
+ res|= thd->net.report_error;
+ if (unlikely(res))
+ {
+ /* If we had a another error reported earlier then this will be ignored */
+ del_result->send_error(ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR));
+ del_result->abort();
+ }
delete del_result;
}
else
--- 1.220/sql/sql_update.cc 2007-06-05 02:14:07 +03:00
+++ 1.221/sql/sql_update.cc 2007-06-23 16:33:34 +03:00
@@ -1739,8 +1739,6 @@ bool multi_update::send_eof()
{
if (local_error == 0)
thd->clear_error();
- else
- updated= 0; /* if there's an error binlog it here not in ::send_error */
Query_log_event qinfo(thd, thd->query, thd->query_length,
transactional_tables, FALSE);
if (mysql_bin_log.write(&qinfo) && trans_safe)
@@ -1749,6 +1747,8 @@ bool multi_update::send_eof()
if (!trans_safe)
thd->no_trans_update.all= TRUE;
}
+ if (local_error)
+ updated= 0; // to force early leave from ::send_error()
if (transactional_tables)
{
--- 1.168/mysql-test/r/innodb.result 2007-06-01 13:22:47 +03:00
+++ 1.169/mysql-test/r/innodb.result 2007-06-23 16:33:33 +03:00
@@ -1119,6 +1119,19 @@ show master status /* there must be no U
File Position Binlog_Do_DB Binlog_Ignore_DB
master-bin.000001 98
drop table t1, t2;
+drop table if exists t1, t2;
+CREATE TABLE t1 (a int, PRIMARY KEY (a));
+CREATE TABLE t2 (a int, PRIMARY KEY (a)) ENGINE=InnoDB;
+create trigger trg_del_t2 after delete on t2 for each row
+insert into t1 values (1);
+insert into t1 values (1);
+insert into t2 values (1),(2);
+delete t2 from t2;
+ERROR 23000: Duplicate entry '1' for key 1
+select count(*) from t2 /* must be 2 as restored after rollback caused by the error */;
+count(*)
+2
+drop table t1, t2;
create table t1 (a int, b int) engine=innodb;
insert into t1 values(20,null);
select t2.b, ifnull(t2.b,"this is null") from t1 as t2 left join t1 as t3 on
@@ -1675,14 +1688,14 @@ t2 CREATE TABLE `t2` (
drop table t2, t1;
show status like "binlog_cache_use";
Variable_name Value
-Binlog_cache_use 158
+Binlog_cache_use 159
show status like "binlog_cache_disk_use";
Variable_name Value
Binlog_cache_disk_use 0
create table t1 (a int) engine=innodb;
show status like "binlog_cache_use";
Variable_name Value
-Binlog_cache_use 159
+Binlog_cache_use 160
show status like "binlog_cache_disk_use";
Variable_name Value
Binlog_cache_disk_use 1
@@ -1691,7 +1704,7 @@ delete from t1;
commit;
show status like "binlog_cache_use";
Variable_name Value
-Binlog_cache_use 160
+Binlog_cache_use 161
show status like "binlog_cache_disk_use";
Variable_name Value
Binlog_cache_disk_use 1
@@ -1815,10 +1828,10 @@ Variable_name Value
Innodb_page_size 16384
show status like "Innodb_rows_deleted";
Variable_name Value
-Innodb_rows_deleted 2072
+Innodb_rows_deleted 2073
show status like "Innodb_rows_inserted";
Variable_name Value
-Innodb_rows_inserted 31732
+Innodb_rows_inserted 31734
show status like "Innodb_rows_updated";
Variable_name Value
Innodb_rows_updated 29532
--- 1.141/mysql-test/t/innodb.test 2007-06-01 13:22:48 +03:00
+++ 1.142/mysql-test/t/innodb.test 2007-06-23 16:33:33 +03:00
@@ -793,6 +793,38 @@ show master status /* there must be no U
drop table t1, t2;
#
+# Bug #29136 erred multi-delete on trans table does not rollback
+#
+
+# prepare
+--disable_warnings
+drop table if exists t1, t2;
+--enable_warnings
+CREATE TABLE t1 (a int, PRIMARY KEY (a));
+CREATE TABLE t2 (a int, PRIMARY KEY (a)) ENGINE=InnoDB;
+create trigger trg_del_t2 after delete on t2 for each row
+ insert into t1 values (1);
+insert into t1 values (1);
+insert into t2 values (1),(2);
+
+
+# exec cases A, B - see multi_update.test
+
+# A. send_error() w/o send_eof() previously branch
+
+--error ER_DUP_ENTRY
+delete t2 from t2;
+
+# check
+
+select count(*) from t2 /* must be 2 as restored after rollback caused by the error */;
+
+# cleanup bug#29136
+
+drop table t1, t2;
+
+
+#
# Testing of IFNULL
#
create table t1 (a int, b int) engine=innodb;
--- 1.46/mysql-test/r/multi_update.result 2007-06-01 11:14:01 +03:00
+++ 1.47/mysql-test/r/multi_update.result 2007-06-23 16:33:33 +03:00
@@ -557,4 +557,19 @@ show master status /* there must be the
File Position Binlog_Do_DB Binlog_Ignore_DB
master-bin.000001 204
drop table t1, t2;
+drop table if exists t1, t2, t3;
+CREATE TABLE t1 (a int, PRIMARY KEY (a));
+CREATE TABLE t2 (a int, PRIMARY KEY (a));
+CREATE TABLE t3 (a int, PRIMARY KEY (a)) ENGINE=MyISAM;
+create trigger trg_del_t3 after delete on t3 for each row
+insert into t1 values (1);
+insert into t2 values (1),(2);
+insert into t3 values (1),(2);
+reset master;
+delete t3.* from t2,t3 where t2.a=t3.a;
+ERROR 23000: Duplicate entry '1' for key 1
+show master status /* the query must be in binlog */;
+File Position Binlog_Do_DB Binlog_Ignore_DB
+master-bin.000001 199
+drop table t1, t2, t3;
end of tests
--- 1.50/mysql-test/t/multi_update.test 2007-06-01 11:14:01 +03:00
+++ 1.51/mysql-test/t/multi_update.test 2007-06-23 16:33:33 +03:00
@@ -574,4 +574,36 @@ show master status /* there must be the
# cleanup bug#27716
drop table t1, t2;
+#
+# Bug #29136 erred multi-delete on trans table does not rollback
+#
+
+# prepare
+--disable_warnings
+drop table if exists t1, t2, t3;
+--enable_warnings
+CREATE TABLE t1 (a int, PRIMARY KEY (a));
+CREATE TABLE t2 (a int, PRIMARY KEY (a));
+CREATE TABLE t3 (a int, PRIMARY KEY (a)) ENGINE=MyISAM;
+create trigger trg_del_t3 after delete on t3 for each row
+insert into t1 values (1);
+insert into t2 values (1),(2);
+insert into t3 values (1),(2);
+reset master;
+
+# exec cases B, A - see innodb.test
+
+# B. send_eof() and send_error() afterward
+
+--error ER_DUP_ENTRY
+delete t3.* from t2,t3 where t2.a=t3.a;
+
+# check
+
+show master status /* the query must be in binlog */;
+
+# cleanup bug#29136
+drop table t1, t2, t3;
+
+
--echo end of tests