summaryrefslogtreecommitdiff
path: root/sql/sql_update.cc
diff options
context:
space:
mode:
authorunknown <aelkin/elkin@koti.dsl.inet.fi>2007-10-13 15:49:42 +0300
committerunknown <aelkin/elkin@koti.dsl.inet.fi>2007-10-13 15:49:42 +0300
commit166fab60611bfaab1bc613fbcf0d6904777c05a5 (patch)
tree23f909d86ea905c39947805347dd334c866d0114 /sql/sql_update.cc
parentb15b88077d56b2cee048b5a7635ba2ad01e85bea (diff)
downloadmariadb-git-166fab60611bfaab1bc613fbcf0d6904777c05a5.tar.gz
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: results changed mysql-test/r/mix_innodb_myisam_binlog.result: results changed mysql-test/r/multi_update.result: results changed mysql-test/t/innodb.test: trans table specific test added mysql-test/t/mix_innodb_myisam_binlog.test: 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: testing another branch of mult-delete: send_eof() (binloggin there), send_error (early return) sql/sql_class.h: 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: 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: adding multi_update::send_error which can perform binlogging and rollback job in needed sql/sql_update.cc: 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.
Diffstat (limited to 'sql/sql_update.cc')
-rw-r--r--sql/sql_update.cc22
1 files changed, 11 insertions, 11 deletions
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 3f38ad8b33c..f3695976508 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -994,8 +994,8 @@ multi_update::multi_update(TABLE_LIST *table_list,
: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 *join)
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 errcode,const char *err)
/* 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 errcode,const char *err)
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)
{