diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2019-10-04 10:56:47 +0300 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2019-10-04 10:56:47 +0300 |
commit | 627027a6743672ce7b461971f772631d65f759f2 (patch) | |
tree | bf88020d3c2615bf8f0dbf4291ae6a6ad6a8d196 /sql/sp_head.cc | |
parent | 1950e3246476ae6bee01290f31a3fb98427da73b (diff) | |
parent | 5709a7777bd2c5c27b0f535099439f13c251de03 (diff) | |
download | mariadb-git-627027a6743672ce7b461971f772631d65f759f2.tar.gz |
Merge 10.4 into 10.5
Diffstat (limited to 'sql/sp_head.cc')
-rw-r--r-- | sql/sp_head.cc | 106 |
1 files changed, 63 insertions, 43 deletions
diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 90fb288cc3c..1968ba83101 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -1345,6 +1345,69 @@ sp_head::execute(THD *thd, bool merge_da_on_success) #endif /* WITH_WSREP */ err_status= i->execute(thd, &ip); +#ifdef WITH_WSREP + if (WSREP(thd)) + { + if (((thd->wsrep_trx().state() == wsrep::transaction::s_executing || thd->in_sub_stmt) && + (thd->is_fatal_error || thd->killed))) + { + WSREP_DEBUG("SP abort err status %d in sub %d trx state %d", + err_status, thd->in_sub_stmt, thd->wsrep_trx().state()); + err_status= 1; + thd->is_fatal_error= 1; + /* + SP was killed, and it is not due to a wsrep conflict. + We skip after_command hook at this point because + otherwise it clears the error, and cleans up the + whole transaction. For now we just return and finish + our handling once we are back to mysql_parse. + + Same applies to a SP execution, which was aborted due + to wsrep related conflict, but which is executing as sub statement. + SP in sub statement level should not commit not rollback, + we have to call for rollback is up-most SP level. + */ + WSREP_DEBUG("Skipping after_command hook for killed SP"); + } + else + { + const bool must_replay= wsrep_must_replay(thd); + if (must_replay) + { + WSREP_DEBUG("MUST_REPLAY set after SP, err_status %d trx state: %d", + err_status, thd->wsrep_trx().state()); + } + (void) wsrep_after_statement(thd); + + /* + Reset the return code to zero if the transaction was + replayed succesfully. + */ + if (must_replay && !wsrep_current_error(thd)) + { + err_status= 0; + thd->get_stmt_da()->reset_diagnostics_area(); + } + /* + Final wsrep error status for statement is known only after + wsrep_after_statement() call. If the error is set, override + error in thd diagnostics area and reset wsrep client_state error + so that the error does not get propagated via client-server protocol. + */ + if (wsrep_current_error(thd)) + { + wsrep_override_error(thd, wsrep_current_error(thd), + wsrep_current_error_status(thd)); + thd->wsrep_cs().reset_error(); + /* Reset also thd->killed if it has been set during BF abort. */ + if (thd->killed == KILL_QUERY) + thd->killed= NOT_KILLED; + /* if failed transaction was not replayed, must return with error from here */ + if (!must_replay) err_status = 1; + } + } + } +#endif /* WITH_WSREP */ thd->m_digest= parent_digest; if (i->free_list) @@ -3604,49 +3667,6 @@ sp_instr_stmt::exec_core(THD *thd, uint *nextp) (char *)thd->security_ctx->host_or_ip, 3); int res= mysql_execute_command(thd); -#ifdef WITH_WSREP - if (WSREP(thd)) - { - if ((thd->is_fatal_error || thd->killed_errno()) && - (thd->wsrep_trx().state() == wsrep::transaction::s_executing)) - { - /* - SP was killed, and it is not due to a wsrep conflict. - We skip after_statement hook at this point because - otherwise it clears the error, and cleans up the - whole transaction. For now we just return and finish - our handling once we are back to mysql_parse. - */ - WSREP_DEBUG("Skipping after_command hook for killed SP"); - } - else - { - const bool must_replay= wsrep_must_replay(thd); - (void) wsrep_after_statement(thd); - /* - Reset the return code to zero if the transaction was - replayed succesfully. - */ - if (res && must_replay && !wsrep_current_error(thd)) - res= 0; - /* - Final wsrep error status for statement is known only after - wsrep_after_statement() call. If the error is set, override - error in thd diagnostics area and reset wsrep client_state error - so that the error does not get propagated via client-server protocol. - */ - if (wsrep_current_error(thd)) - { - wsrep_override_error(thd, wsrep_current_error(thd), - wsrep_current_error_status(thd)); - thd->wsrep_cs().reset_error(); - /* Reset also thd->killed if it has been set during BF abort. */ - if (thd->killed == KILL_QUERY) - thd->reset_killed(); - } - } - } -#endif /* WITH_WSREP */ MYSQL_QUERY_EXEC_DONE(res); *nextp= m_ip+1; return res; |