Ok to push.
> -----Original Message-----
> From: Andrei Elkin [mailto:aelkin@stripped]
> Sent: Tuesday, October 09, 2007 8:20 AM
> To: commits@stripped
> Subject: bk commit into 5.0 tree (aelkin:1.2541) BUG#29136
>
> 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-10-09 15:19:53+03:00,
> aelkin@stripped +10 -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.
>
> The changeset includes the following side effects:
> - added tests to check bug_23333's scenarios on the mixture
> of tables for multi_update;
> - fixes bug@30763 with two-liner patch and a test
> coinciding to one added for bug_23333.
>
> mysql-test/r/innodb.result@stripped, 2007-10-09
> 15:19:49+03:00, aelkin@stripped +15 -2
> results changed
>
> mysql-test/r/mix_innodb_myisam_binlog.result@stripped,
> 2007-10-09 15:19:49+03:00,
> aelkin@stripped +48 -4
> results changed
>
> mysql-test/r/multi_update.result@stripped, 2007-10-09
> 15:19:49+03:00, aelkin@stripped +22 -2
> results changed
>
> mysql-test/t/innodb.test@stripped, 2007-10-09 15:19:49+03:00,
> aelkin@stripped +32 -0
> trans table specific test added
>
> mysql-test/t/mix_innodb_myisam_binlog.test@stripped, 2007-10-09
> 15:19:50+03:00, aelkin@stripped +70 -6
> multi-update and multi-delete of mixure of ta and not-ta
> tables tests added (relates to bug_23333).
>
> mysql-test/t/multi_update.test@stripped, 2007-10-09
> 15:19:50+03:00, aelkin@stripped +34 -0
> testing another branch of mult-delete: send_eof()
> (binloggin there), send_error (early return)
>
> sql/sql_class.h@stripped, 2007-10-09 15:19:50+03:00,
> aelkin@stripped +10 -0
> a new flag to designate the fact the statement's error
> has been handled.
> The flag is checked by ::send_error() methods
> (multi_update and _delete classes)
>
> sql/sql_delete.cc@stripped, 2007-10-09 15:19:50+03:00,
> aelkin@stripped +26 -5
> expanding multi_delete::send_error to
> 1. early return if error_handled == t
> 2. binlogging locally if there was a non-trans table
> modified side effect
>
> sql/sql_parse.cc@stripped, 2007-10-09 15:19:50+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-10-09 15:19:50+03:00,
> aelkin@stripped +11 -11
> issues relating to
>
> 1. bug_27716 with zeroing of `updated' to serve as the
> flag of early return from send_error().
> The flag is changed to be a new member error_handled;
> also moved outside binlogging branch.
> The reason for this change is that bug_23333 fixes
> were pushed after the bug_27716's and they
> left this flaw (also no test coverage).
> 2. bug_30763 with assertion on trans_safe. I decide to
> make 2 liner fix for that bug here instead of to remove
> those two assertions. This new bug test case is the
> same as for multi-update on the mixure of tables.
> The rational for this fix:
> presumption for mutli_update::trans_safe to be set to zero at
> multi_update::multi_update or
> multi_update::initialize_tables() is incorrect.
>
> trans_safe := false should happen only when a
> non-transactional table gets modified.
> Therefore, at initialization the member must be be set to true.
>
> diff -Nrup a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result
> --- a/mysql-test/r/innodb.result 2007-07-18 15:22:00 +03:00
> +++ b/mysql-test/r/innodb.result 2007-10-09 15:19:49 +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
> @@ -1792,10 +1805,10 @@ Variable_name Value
> Innodb_page_size 16384
> show status like "Innodb_rows_deleted";
> Variable_name Value
> -Innodb_rows_deleted 72
> +Innodb_rows_deleted 73
> show status like "Innodb_rows_inserted";
> Variable_name Value
> -Innodb_rows_inserted 29732
> +Innodb_rows_inserted 29734
> show status like "Innodb_rows_updated";
> Variable_name Value
> Innodb_rows_updated 29532
> diff -Nrup a/mysql-test/r/mix_innodb_myisam_binlog.result
> b/mysql-test/r/mix_innodb_myisam_binlog.result
> --- a/mysql-test/r/mix_innodb_myisam_binlog.result
> 2007-08-22 10:40:35 +03:00
> +++ b/mysql-test/r/mix_innodb_myisam_binlog.result
> 2007-10-09 15:19:49 +03:00
> @@ -351,7 +351,7 @@ 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)
> +create function bug27417(n int)
> RETURNS int(11)
> begin
> insert into t1 values (null);
> @@ -393,7 +393,9 @@ count(*)
> drop table t1,t2;
> CREATE TABLE t1 (a int NOT NULL auto_increment primary key)
> ENGINE=MyISAM; CREATE TABLE t2 (a int, PRIMARY KEY (a))
> ENGINE=InnoDB; -CREATE TABLE t3 (a int, PRIMARY KEY (a), b
> int unique);
> +CREATE TABLE t3 (a int, PRIMARY KEY (a), b int unique)
> ENGINE=MyISAM;
> +CREATE TABLE t4 (a int, PRIMARY KEY (a), b int unique)
> ENGINE=Innodb;
> +CREATE TABLE t5 (a int, PRIMARY KEY (a)) ENGINE=InnoDB;
> insert into t2 values (1);
> reset master;
> insert into t2 values (bug27417(1));
> @@ -427,6 +429,31 @@ master-bin.000001 190
> select count(*) from t1 /* must be 2 */;
> count(*)
> 2
> +delete from t3;
> +delete from t4;
> +insert into t3 values (1,1);
> +insert into t4 values (1,1),(2,2);
> +reset master;
> +UPDATE t4,t3 SET t4.a=t3.a + bug27417(1) /* top level non-ta
> table */;
> +ERROR 23000: Duplicate entry '2' for key 1 show master status /* the
> +offset must denote there is the query */;
> +File Position Binlog_Do_DB Binlog_Ignore_DB
> +master-bin.000001 301
> +select count(*) from t1 /* must be 2 */;
> +count(*)
> +4
> +delete from t1;
> +delete from t3;
> +delete from t4;
> +insert into t3 values (1,1),(2,2);
> +insert into t4 values (1,1),(2,2);
> +reset master;
> +UPDATE t3,t4 SET t3.a=t4.a + bug27417(1); ERROR 23000:
> Duplicate entry
> +'2' for key 1 select count(*) from t1 /* must be 1 */;
> +count(*)
> +1
> +drop table t4;
> delete from t1;
> delete from t2;
> delete from t3;
> @@ -443,6 +470,23 @@ master-bin.000001 246
> select count(*) from t1 /* must be 1 */;
> count(*)
> 1
> +drop trigger trg_del;
> +delete from t1;
> +delete from t2;
> +delete from t5;
> +create trigger trg_del_t2 after delete on t2 for each row
> insert into
> +t1 values (1); insert into t2 values (2),(3); insert into t5 values
> +(1),(2); reset master; delete t2.* from t2,t5 where t2.a=t5.a + 1;
> +ERROR 23000: Duplicate entry '1' for key 1 show master status /* the
> +offset must denote there is the query */;
> +File Position Binlog_Do_DB Binlog_Ignore_DB
> +master-bin.000001 274
> +select count(*) from t1 /* must be 1 */;
> +count(*)
> +1
> delete from t1;
> create table t4 (a int default 0, b int primary key)
> engine=innodb; insert into t4 values (0, 17); @@ -458,7
> +502,7 @@ count(*) show master status /* the offset must
> denote there is the query */;
> File Position Binlog_Do_DB Binlog_Ignore_DB
> master-bin.000001 376
> -drop trigger trg_del;
> -drop table t1,t2,t3,t4;
> +drop trigger trg_del_t2;
> +drop table t1,t2,t3,t4,t5;
> drop function bug27417;
> end of tests
> diff -Nrup a/mysql-test/r/multi_update.result
> b/mysql-test/r/multi_update.result
> --- a/mysql-test/r/multi_update.result 2007-06-01
> 11:14:01 +03:00
> +++ b/mysql-test/r/multi_update.result 2007-10-09
> 15:19:49 +03:00
> @@ -545,7 +545,7 @@ a b
> 4 4
> show master status /* there must be the UPDATE query event */;
> File Position Binlog_Do_DB Binlog_Ignore_DB
> -master-bin.000001 189
> +master-bin.000001 260
> delete from t1;
> delete from t2;
> insert into t1 values (1,2),(3,4),(4,4); @@ -555,6 +555,26
> @@ UPDATE t2,t1 SET t2.a=t2.b where t2.a=t ERROR 23000:
> Duplicate entry '4' for key 1 show master status /* there
> must be the UPDATE query event */;
> File Position Binlog_Do_DB Binlog_Ignore_DB
> -master-bin.000001 204
> +master-bin.000001 275
> 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 before 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 select
> count(*)
> +from t1 /* must be 1 */;
> +count(*)
> +1
> +select count(*) from t3 /* must be 1 */;
> +count(*)
> +1
> +show binlog events from 98;
> +Log_name Pos Event_type Server_id
> End_log_pos Info
> +master-bin.000001 98 Query 1 # use
> `test`; delete t3.* from t2,t3 where t2.a=t3.a
> +drop table t1, t2, t3;
> end of tests
> diff -Nrup a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test
> --- a/mysql-test/t/innodb.test 2007-07-18 15:22:00 +03:00
> +++ b/mysql-test/t/innodb.test 2007-10-09 15:19:49 +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() 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; diff -Nrup
> a/mysql-test/t/mix_innodb_myisam_binlog.test
> b/mysql-test/t/mix_innodb_myisam_binlog.test
> --- a/mysql-test/t/mix_innodb_myisam_binlog.test
> 2007-08-22 10:40:35 +03:00
> +++ b/mysql-test/t/mix_innodb_myisam_binlog.test
> 2007-10-09 15:19:50 +03:00
> @@ -347,7 +347,7 @@ CREATE TABLE t1 (a int NOT NULL auto_inc
> CREATE TABLE t2 (a int NOT NULL auto_increment, PRIMARY KEY (a));
>
> delimiter |;
> -create function bug27417(n int)
> +create function bug27417(n int)
> RETURNS int(11)
> begin
> insert into t1 values (null);
> @@ -385,13 +385,17 @@ drop table t1,t2;
>
> #
> # Bug#23333 using the patch (and the test) for bug#27471
> +#
> # throughout the bug tests
> # t1 - non-trans side effects gatherer; # t2 -
> transactional table; #
> +
> CREATE TABLE t1 (a int NOT NULL auto_increment primary key)
> ENGINE=MyISAM; CREATE TABLE t2 (a int, PRIMARY KEY (a))
> ENGINE=InnoDB; -CREATE TABLE t3 (a int, PRIMARY KEY (a), b
> int unique);
> +CREATE TABLE t3 (a int, PRIMARY KEY (a), b int unique)
> ENGINE=MyISAM;
> +CREATE TABLE t4 (a int, PRIMARY KEY (a), b int unique)
> ENGINE=Innodb;
> +CREATE TABLE t5 (a int, PRIMARY KEY (a)) ENGINE=InnoDB;
>
>
> #
> @@ -434,7 +438,7 @@ CREATE TABLE t3 (a int, PRIMARY KEY (a),
> select count(*) from t1 /* must be 2 */;
>
> #
> -# UPDATE (multi-update see bug#27716)
> +# UPDATE inc multi-update
> #
>
> # prepare
> @@ -450,9 +454,48 @@ CREATE TABLE t3 (a int, PRIMARY KEY (a),
> show master status /* the offset must denote there is the query */;
> select count(*) from t1 /* must be 2 */;
>
> +## multi_update::send_eof() branch
> +
> +# prepare
> + delete from t3;
> + delete from t4;
> + insert into t3 values (1,1);
> + insert into t4 values (1,1),(2,2);
> +
> + reset master;
> +
> +# execute
> + --error ER_DUP_ENTRY
> + UPDATE t4,t3 SET t4.a=t3.a + bug27417(1) /* top level
> non-ta table */;
> +
> +# check
> + show master status /* the offset must denote there is the
> query */;
> +select count(*) from t1 /* must be 2 */;
> +
> +## send_error() branch of multi_update
> +
> +# prepare
> + delete from t1;
> + delete from t3;
> + delete from t4;
> + insert into t3 values (1,1),(2,2);
> + insert into t4 values (1,1),(2,2);
> +
> + reset master;
> +
> +# execute
> + --error ER_DUP_ENTRY
> + UPDATE t3,t4 SET t3.a=t4.a + bug27417(1);
> +
> +# check
> + select count(*) from t1 /* must be 1 */;
> +
> +# cleanup
> + drop table t4;
> +
>
> #
> -# DELETE (for multi-delete see Bug #29136)
> +# DELETE incl multi-delete
> #
>
> # prepare
> @@ -472,6 +515,27 @@ CREATE TABLE t3 (a int, PRIMARY KEY (a),
> show master status /* the offset must denote there is the query */;
> select count(*) from t1 /* must be 1 */;
>
> +# cleanup
> + drop trigger trg_del;
> +
> +# prepare
> + delete from t1;
> + delete from t2;
> + delete from t5;
> + create trigger trg_del_t2 after delete on t2 for each row
> + insert into t1 values (1);
> + insert into t2 values (2),(3);
> + insert into t5 values (1),(2);
> + reset master;
> +
> +# execute
> + --error ER_DUP_ENTRY
> + delete t2.* from t2,t5 where t2.a=t5.a + 1;
> +
> +# check
> + show master status /* the offset must denote there is the
> query */;
> +select count(*) from t1 /* must be 1 */;
> +
>
> #
> # LOAD DATA
> @@ -496,8 +560,8 @@ CREATE TABLE t3 (a int, PRIMARY KEY (a), #
>
>
> -drop trigger trg_del;
> -drop table t1,t2,t3,t4;
> +drop trigger trg_del_t2;
> +drop table t1,t2,t3,t4,t5;
> drop function bug27417;
>
>
> diff -Nrup a/mysql-test/t/multi_update.test
> b/mysql-test/t/multi_update.test
> --- a/mysql-test/t/multi_update.test 2007-06-01 11:14:01 +03:00
> +++ b/mysql-test/t/multi_update.test 2007-10-09 15:19:50 +03:00
> @@ -574,4 +574,38 @@ 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 before 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
> +select count(*) from t1 /* must be 1 */; select count(*) from t3 /*
> +must be 1 */; # the query must be in binlog (no surprise
> though) source
> +include/show_binlog_events.inc;
> +
> +# cleanup bug#29136
> +drop table t1, t2, t3;
> +
> +
> --echo end of tests
> diff -Nrup a/sql/sql_class.h b/sql/sql_class.h
> --- a/sql/sql_class.h 2007-10-03 12:57:12 +03:00
> +++ b/sql/sql_class.h 2007-10-09 15:19:50 +03:00
> @@ -2356,6 +2356,11 @@ class multi_delete :public select_result
> /* True if at least one table we delete from is not
> transactional */
> bool normal_tables;
> bool delete_while_scanning;
> + /*
> + error handling (rollback and binlogging) can happen in
> send_eof()
> + so that afterward send_error() needs to find out that.
> + */
> + bool error_handled;
>
> public:
> multi_delete(TABLE_LIST *dt, uint num_of_tables); @@
> -2391,6 +2396,11 @@ class multi_update :public select_result
> /* True if the update operation has made a change in a
> transactional table */
> bool transactional_tables;
> bool ignore;
> + /*
> + error handling (rollback and binlogging) can happen in
> send_eof()
> + so that afterward send_error() needs to find out that.
> + */
> + bool error_handled;
>
> public:
> multi_update(TABLE_LIST *ut, TABLE_LIST *leaves_list, diff
> -Nrup a/sql/sql_delete.cc b/sql/sql_delete.cc
> --- a/sql/sql_delete.cc 2007-08-21 15:16:52 +03:00
> +++ b/sql/sql_delete.cc 2007-10-09 15:19:50 +03:00
> @@ -504,7 +504,7 @@ bool mysql_multi_delete_prepare(THD *thd
> multi_delete::multi_delete(TABLE_LIST *dt, uint num_of_tables_arg)
> : delete_tables(dt), deleted(0), found(0),
> num_of_tables(num_of_tables_arg), error(0),
> - do_delete(0), transactional_tables(0), normal_tables(0)
> + do_delete(0), transactional_tables(0), normal_tables(0),
> + error_handled(0)
> {
> tempfiles= (Unique **) sql_calloc(sizeof(Unique *) *
> num_of_tables); } @@ -685,12 +685,14 @@ 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)
> + /* the error was handled or nothing deleted and no side effects
> + return */ if (error_handled ||
> + !thd->transaction.stmt.modified_non_trans_table && !deleted)
> 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 @@ -709,13 +711,30 @@ void multi_delete::send_error(uint errco
> error log
> */
> error= 1;
> - send_eof();
> + send_eof(); // will reset deleted to zero
> + DBUG_ASSERT(error_handled);
> + DBUG_VOID_RETURN;
> + }
> +
> + if (thd->transaction.stmt.modified_non_trans_table)
> + {
> + /*
> + there is only side effects; to 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);
> + }
> + thd->transaction.all.modified_non_trans_table= true;
> }
> DBUG_ASSERT(!normal_tables || !deleted ||
> thd->transaction.stmt.modified_non_trans_table);
> DBUG_VOID_RETURN;
> }
>
>
> +
> /*
> Do delete from other tables.
> Returns values:
> @@ -832,6 +851,8 @@ bool multi_delete::send_eof()
> if (thd->transaction.stmt.modified_non_trans_table)
> thd->transaction.all.modified_non_trans_table= TRUE;
> }
> + if (local_error != 0)
> + error_handled= TRUE; // to force early leave from ::send_error()
>
> /* Commit or rollback the current SQL statement */
> if (transactional_tables)
> diff -Nrup a/sql/sql_parse.cc b/sql/sql_parse.cc
> --- a/sql/sql_parse.cc 2007-10-03 13:43:51 +03:00
> +++ b/sql/sql_parse.cc 2007-10-09 15:19:50 +03:00
> @@ -3701,6 +3701,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, "Execution
> of the query failed");
> + del_result->abort();
> + }
> delete del_result;
> }
> else
> diff -Nrup a/sql/sql_update.cc b/sql/sql_update.cc
> --- a/sql/sql_update.cc 2007-08-21 15:16:52 +03:00
> +++ b/sql/sql_update.cc 2007-10-09 15:19:50 +03:00
> @@ -994,8 +994,8 @@ multi_update::multi_update(TABLE_LIST *t
> :all_tables(table_list), leaves(leaves_list), update_tables(0),
> tmp_tables(0), updated(0), found(0), fields(field_list),
> values(value_list), table_count(0), copy_field(0),
> - handle_duplicates(handle_duplicates_arg), do_update(1),
> trans_safe(0),
> - transactional_tables(1), ignore(ignore_arg)
> + handle_duplicates(handle_duplicates_arg), do_update(1),
> trans_safe(1),
> + transactional_tables(1), ignore(ignore_arg), error_handled(0)
> {}
>
>
> @@ -1202,7 +1202,6 @@ multi_update::initialize_tables(JOIN *jo
> if ((thd->options & OPTION_SAFE_UPDATES) &&
> error_if_full_join(join))
> DBUG_RETURN(1);
> main_table=join->join_tab->table;
> - trans_safe= transactional_tables=
> main_table->file->has_transactions();
> table_to_update= 0;
>
> /* Any update has at least one pair (field, value) */ @@
> -1484,12 +1483,14 @@ void multi_update::send_error(uint errco
> /* First send error what ever it is ... */
> my_error(errcode, MYF(0), err);
>
> - /* If nothing updated return */
> - if (updated == 0) /* the counter might be reset in send_eof */
> - return; /* and then the query has been binlogged */
> + /* the error was handled or nothing deleted and no side effects
> + return */ if (error_handled ||
> + !thd->transaction.stmt.modified_non_trans_table && !updated)
> + return;
>
> /* Something already updated so we have to invalidate cache */
> - query_cache_invalidate3(thd, update_tables, 1);
> + if (updated)
> + query_cache_invalidate3(thd, update_tables, 1);
> /*
> If all tables that has been updated are trans safe then
> just do rollback.
> If not attempt to do remaining updates.
> @@ -1525,8 +1526,7 @@ void multi_update::send_error(uint errco
> transactional_tables, FALSE);
> mysql_bin_log.write(&qinfo);
> }
> - if (!trans_safe)
> - thd->transaction.all.modified_non_trans_table= TRUE;
> + thd->transaction.all.modified_non_trans_table= TRUE;
> }
> DBUG_ASSERT(trans_safe || !updated ||
> thd->transaction.stmt.modified_non_trans_table);
>
> @@ -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 (thd->transaction.stmt.modified_non_trans_table)
> thd->transaction.all.modified_non_trans_table= TRUE;
> }
> + if (local_error != 0)
> + error_handled= TRUE; // to force early leave from ::send_error()
>
> if (transactional_tables)
> {
>
> --
> MySQL Code Commits Mailing List
> For list archives: http://lists.mysql.com/commits
> To unsubscribe:
> http://lists.mysql.com/commits?unsub=1
>