diff --git a/contrib/postgres_fdw/connection.c b/contrib/postgres_fdw/connection.c index 3f4e71da9e..2deb4b2c4a 100644 --- a/contrib/postgres_fdw/connection.c +++ b/contrib/postgres_fdw/connection.c @@ -80,6 +80,18 @@ static unsigned int prep_stmt_number = 0; /* tracks whether any work is needed in callback functions */ static bool xact_got_connection = false; +/* macro for constructing abort command to be sent */ +#define CONSTRUCT_ABORT_COMMAND(sql, entry, toplevel) \ + do { \ + if (toplevel) \ + snprintf((sql), sizeof(sql), \ + "ABORT TRANSACTION"); \ + else \ + snprintf((sql), sizeof(sql), \ + "ROLLBACK TO SAVEPOINT s%d; RELEASE SAVEPOINT s%d", \ + (entry)->xact_depth, (entry)->xact_depth); \ + } while(0) + /* * SQL functions */ @@ -110,8 +122,7 @@ static bool pgfdw_exec_cleanup_query(PGconn *conn, const char *query, bool ignore_errors); static bool pgfdw_get_cleanup_result(PGconn *conn, TimestampTz endtime, PGresult **result, bool *timed_out); -static void pgfdw_abort_cleanup(ConnCacheEntry *entry, const char *sql, - bool toplevel); +static void pgfdw_abort_cleanup(ConnCacheEntry *entry, bool toplevel); static void pgfdw_finish_pre_commit_cleanup(List *pending_entries); static void pgfdw_finish_pre_subcommit_cleanup(List *pending_entries); static bool UserMappingPasswordRequired(UserMapping *user); @@ -1014,8 +1025,8 @@ pgfdw_xact_callback(XactEvent event, void *arg) break; case XACT_EVENT_PARALLEL_ABORT: case XACT_EVENT_ABORT: - - pgfdw_abort_cleanup(entry, "ABORT TRANSACTION", true); + /* Rollback all remote transactions during abort */ + pgfdw_abort_cleanup(entry, true); break; } } @@ -1108,10 +1119,7 @@ pgfdw_subxact_callback(SubXactEvent event, SubTransactionId mySubid, else { /* Rollback all remote subtransactions during abort */ - snprintf(sql, sizeof(sql), - "ROLLBACK TO SAVEPOINT s%d; RELEASE SAVEPOINT s%d", - curlevel, curlevel); - pgfdw_abort_cleanup(entry, sql, false); + pgfdw_abort_cleanup(entry, false); } /* OK, we're outta that level of subtransaction */ @@ -1464,10 +1472,7 @@ exit: ; } /* - * Abort remote transaction. - * - * The statement specified in "sql" is sent to the remote server, - * in order to rollback the remote transaction. + * Abort remote transaction or subtransaction. * * "toplevel" should be set to true if toplevel (main) transaction is * rollbacked, false otherwise. @@ -1475,8 +1480,10 @@ exit: ; * Set entry->changing_xact_state to false on success, true on failure. */ static void -pgfdw_abort_cleanup(ConnCacheEntry *entry, const char *sql, bool toplevel) +pgfdw_abort_cleanup(ConnCacheEntry *entry, bool toplevel) { + char sql[100]; + /* * Don't try to clean up the connection if we're already in error * recursion trouble. @@ -1508,8 +1515,9 @@ pgfdw_abort_cleanup(ConnCacheEntry *entry, const char *sql, bool toplevel) !pgfdw_cancel_query(entry->conn)) return; /* Unable to cancel running query */ + CONSTRUCT_ABORT_COMMAND(sql, entry, toplevel); if (!pgfdw_exec_cleanup_query(entry->conn, sql, false)) - return; /* Unable to abort remote transaction */ + return; /* Unable to abort remote (sub)transaction */ if (toplevel) {