From 49f4107082e2c609696ac1dd6c789e7981d6615a Mon Sep 17 00:00:00 2001 From: Siavash Tavakoli Date: Thu, 8 Apr 2021 17:08:54 +0100 Subject: [PATCH] driver-mysql: Rollback a failed multi-statement transaction If transaction failed, send "ROLLBACK" statement. --- src/lib-sql/driver-mysql.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/src/lib-sql/driver-mysql.c b/src/lib-sql/driver-mysql.c index d382cd3fbf..78510eabf4 100644 --- a/src/lib-sql/driver-mysql.c +++ b/src/lib-sql/driver-mysql.c @@ -66,6 +66,7 @@ struct mysql_transaction_context { bool failed:1; bool committed:1; + bool commit_started:1; }; extern const struct sql_db driver_mysql_db; @@ -653,7 +654,10 @@ static int driver_mysql_try_commit_s(struct mysql_transaction_context *ctx) return -1; /* we got disconnected, retry */ return 0; + } else if (multi) { + ctx->commit_started = TRUE; } + while (_ctx->head != NULL) { if (transaction_send_query(ctx, _ctx->head->query, _ctx->head->affected_rows) < 0) @@ -702,11 +706,26 @@ driver_mysql_transaction_rollback(struct sql_transaction_context *_ctx) struct mysql_transaction_context *ctx = (struct mysql_transaction_context *)_ctx; - if (ctx->failed) + if (ctx->failed) { + bool rolledback = FALSE; + const char *orig_error = t_strdup(ctx->error); + if (ctx->commit_started) { + /* reset failed flag so ROLLBACK is actually sent. + otherwise, transaction_send_query() will return + without trying to send the query. */ + ctx->failed = FALSE; + if (transaction_send_query(ctx, "ROLLBACK", NULL) < 0) + e_debug(event_create_passthrough(_ctx->event)-> + add_str("error", ctx->error)->event(), + "Rollback failed: %s", ctx->error); + else + rolledback = TRUE; + } e_debug(sql_transaction_finished_event(_ctx)-> - add_str("error", ctx->error)->event(), - "Transaction failed: %s", ctx->error); - else if (ctx->committed) + add_str("error", orig_error)->event(), + "Transaction failed: %s%s", orig_error, + rolledback ? " - Rolled back" : ""); + } else if (ctx->committed) e_debug(sql_transaction_finished_event(_ctx)->event(), "Transaction committed"); else -- 2.47.3