summaryrefslogtreecommitdiff
path: root/sql/sp_head.cc
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2020-06-06 18:50:25 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2020-06-06 18:50:25 +0300
commitb3e395a13ee7e9df323cb654d18dc81ff2f3fd1e (patch)
tree6078ccc55d5298796c3f626fb4886a131b833e37 /sql/sp_head.cc
parente14ffd85d09a62d098d3db9597fd34bf3d4c4fe3 (diff)
parent187b9c924ebaff8f02fb4e2139a01fd1512e3dc9 (diff)
downloadmariadb-git-b3e395a13ee7e9df323cb654d18dc81ff2f3fd1e.tar.gz
Merge 10.2 into 10.3
Diffstat (limited to 'sql/sp_head.cc')
-rw-r--r--sql/sp_head.cc93
1 files changed, 93 insertions, 0 deletions
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index f36650bafe9..59a304deb99 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -44,6 +44,9 @@
#include "transaction.h" // trans_commit_stmt
#include "sql_audit.h"
#include "debug_sync.h"
+#ifdef WITH_WSREP
+#include "wsrep_thd.h"
+#endif /* WITH_WSREP */
/*
Sufficient max length of printed destinations and frame offsets (all uints).
@@ -1171,6 +1174,7 @@ sp_head::execute(THD *thd, bool merge_da_on_success)
backup_arena;
query_id_t old_query_id;
TABLE *old_derived_tables;
+ TABLE *old_rec_tables;
LEX *old_lex;
Item_change_list old_change_list;
String old_packet;
@@ -1249,6 +1253,8 @@ sp_head::execute(THD *thd, bool merge_da_on_success)
old_query_id= thd->query_id;
old_derived_tables= thd->derived_tables;
thd->derived_tables= 0;
+ old_rec_tables= thd->rec_tables;
+ thd->rec_tables= 0;
save_sql_mode= thd->variables.sql_mode;
thd->variables.sql_mode= m_sql_mode;
save_abort_on_warning= thd->abort_on_warning;
@@ -1369,7 +1375,93 @@ sp_head::execute(THD *thd, bool merge_da_on_success)
thd->m_digest= NULL;
err_status= i->execute(thd, &ip);
+#ifdef WITH_WSREP
+ if (m_handler->type() == TYPE_ENUM_PROCEDURE)
+ {
+ mysql_mutex_lock(&thd->LOCK_thd_data);
+ if (thd->wsrep_conflict_state == MUST_REPLAY)
+ {
+ wsrep_replay_sp_transaction(thd);
+ err_status= thd->get_stmt_da()->is_set();
+ thd->wsrep_conflict_state= NO_CONFLICT;
+ }
+ else if (thd->wsrep_conflict_state == ABORTED ||
+ thd->wsrep_conflict_state == CERT_FAILURE)
+ {
+ /*
+ If the statement execution was BF aborted or was aborted
+ due to certification failure, clean up transaction here
+ and reset conflict state to NO_CONFLICT and thd->killed
+ to THD::NOT_KILLED. Error handling is done based on err_status
+ below. Error must have been raised by wsrep hton code before
+ entering here.
+ */
+ DBUG_ASSERT(err_status);
+ DBUG_ASSERT(thd->get_stmt_da()->is_error());
+ thd->wsrep_conflict_state= NO_CONFLICT;
+ thd->killed= NOT_KILLED;
+ }
+ mysql_mutex_unlock(&thd->LOCK_thd_data);
+ }
+#endif /* WITH_WSREP */
+#ifdef WITH_WSREP_NO
+ if (WSREP(thd))
+ {
+ if (((thd->wsrep_trx().state() == wsrep::transaction::s_executing) &&
+ (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.
+ */
+ 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)
@@ -1437,6 +1529,7 @@ sp_head::execute(THD *thd, bool merge_da_on_success)
thd->set_query_id(old_query_id);
DBUG_ASSERT(!thd->derived_tables);
thd->derived_tables= old_derived_tables;
+ thd->rec_tables= old_rec_tables;
thd->variables.sql_mode= save_sql_mode;
thd->abort_on_warning= save_abort_on_warning;
thd->m_reprepare_observer= save_reprepare_observer;