aboutsummaryrefslogtreecommitdiff
path: root/contrib/postgres_fdw/connection.c
diff options
context:
space:
mode:
authorRobert Haas <rhaas@postgresql.org>2016-05-16 11:19:10 -0400
committerRobert Haas <rhaas@postgresql.org>2016-05-16 11:19:10 -0400
commit1b812afb0eafe125b820cc3b95e7ca03821aa675 (patch)
treee7c4f63d7ccf8531766414d7c3ce2a31d18e124a /contrib/postgres_fdw/connection.c
parentb7a9347c11e19918a34b127a096061bfb002fcb5 (diff)
downloadpostgresql-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.c28
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",