diff options
author | unknown <aelkin/elkin@koti.dsl.inet.fi> | 2007-10-13 15:49:42 +0300 |
---|---|---|
committer | unknown <aelkin/elkin@koti.dsl.inet.fi> | 2007-10-13 15:49:42 +0300 |
commit | c8b6d1050933f0b9b18367c421702c9f16907de5 (patch) | |
tree | 23f909d86ea905c39947805347dd334c866d0114 /sql/sql_delete.cc | |
parent | 5aba177bf6fd532386dcaf15e25ed7e9b1a44702 (diff) | |
download | mariadb-git-c8b6d1050933f0b9b18367c421702c9f16907de5.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_delete.cc')
-rw-r--r-- | sql/sql_delete.cc | 29 |
1 files changed, 25 insertions, 4 deletions
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 7555219f5d8..add37c8c552 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -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 errcode,const char *err) /* 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 @@ -710,12 +712,29 @@ void multi_delete::send_error(uint errcode,const char *err) */ error= 1; send_eof(); + 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) |