diff options
author | Robert Haas <rhaas@postgresql.org> | 2016-05-16 11:19:10 -0400 |
---|---|---|
committer | Robert Haas <rhaas@postgresql.org> | 2016-05-16 11:19:10 -0400 |
commit | 1b812afb0eafe125b820cc3b95e7ca03821aa675 (patch) | |
tree | e7c4f63d7ccf8531766414d7c3ce2a31d18e124a /contrib/postgres_fdw/connection.c | |
parent | b7a9347c11e19918a34b127a096061bfb002fcb5 (diff) | |
download | postgresql-1b812afb0eafe125b820cc3b95e7ca03821aa675.tar.gz postgresql-1b812afb0eafe125b820cc3b95e7ca03821aa675.zip |
Fix multiple problems in postgres_fdw query cancellation logic.
First, even if we cancel a query, we still have to roll back the
containing transaction; otherwise, the session will be left in a
failed transaction state.
Second, we need to support canceling queries whe aborting a
subtransaction as well as when aborting a toplevel transaction.
Etsuro Fujita, reviewed by Michael Paquier
Diffstat (limited to 'contrib/postgres_fdw/connection.c')
-rw-r--r-- | contrib/postgres_fdw/connection.c | 28 |
1 files changed, 25 insertions, 3 deletions
diff --git a/contrib/postgres_fdw/connection.c b/contrib/postgres_fdw/connection.c index 16ef38fff78..43c7fc9e080 100644 --- a/contrib/postgres_fdw/connection.c +++ b/contrib/postgres_fdw/connection.c @@ -677,8 +677,7 @@ pgfdw_xact_callback(XactEvent event, void *arg) * using an asynchronous execution function, the command * might not have yet completed. Check to see if a command * is still being processed by the remote server, and if so, - * request cancellation of the command; if not, abort - * gracefully. + * request cancellation of the command. */ if (PQtransactionStatus(entry->conn) == PQTRANS_ACTIVE) { @@ -694,7 +693,6 @@ pgfdw_xact_callback(XactEvent event, void *arg) errbuf))); PQfreeCancel(cancel); } - break; } /* If we're aborting, abort all remote transactions too */ @@ -798,6 +796,30 @@ pgfdw_subxact_callback(SubXactEvent event, SubTransactionId mySubid, { /* Assume we might have lost track of prepared statements */ entry->have_error = true; + + /* + * If a command has been submitted to the remote server by using an + * asynchronous execution function, the command might not have yet + * completed. Check to see if a command is still being processed by + * the remote server, and if so, request cancellation of the + * command. + */ + if (PQtransactionStatus(entry->conn) == PQTRANS_ACTIVE) + { + PGcancel *cancel; + char errbuf[256]; + + if ((cancel = PQgetCancel(entry->conn))) + { + if (!PQcancel(cancel, errbuf, sizeof(errbuf))) + ereport(WARNING, + (errcode(ERRCODE_CONNECTION_FAILURE), + errmsg("could not send cancel request: %s", + errbuf))); + PQfreeCancel(cancel); + } + } + /* Rollback all remote subtransactions during abort */ snprintf(sql, sizeof(sql), "ROLLBACK TO SAVEPOINT s%d; RELEASE SAVEPOINT s%d", |