Skip to content

Commit 815d61f

Browse files
committed
postgres_fdw: Report warning when timeout expires while getting query result.
When aborting remote transaction or sending cancel request to a remote server, postgres_fdw calls pgfdw_get_cleanup_result() to wait for the result of transaction abort query or cancel request to arrive. It fails to get the result if the timeout expires or a connection trouble happens. Previously postgres_fdw reported no warning message even when the timeout expired or a connection trouble happened in pgfdw_get_cleanup_result(). This could make the troubleshooting harder when such an event occurred. This commit makes pgfdw_get_cleanup_result() tell its caller what trouble (timeout or connection error) occurred, on failure, and also makes its caller report the proper warning message based on that information. Author: Fujii Masao Reviewed-by: Bharath Rupireddy Discussion: https://postgr.es/m/15aa988c-722e-ad3e-c936-4420c5b2bfea@oss.nttdata.com
1 parent d6f96ed commit 815d61f

File tree

1 file changed

+39
-12
lines changed

1 file changed

+39
-12
lines changed

contrib/postgres_fdw/connection.c

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ static bool pgfdw_cancel_query(PGconn *conn);
104104
static bool pgfdw_exec_cleanup_query(PGconn *conn, const char *query,
105105
bool ignore_errors);
106106
static bool pgfdw_get_cleanup_result(PGconn *conn, TimestampTz endtime,
107-
PGresult **result);
107+
PGresult **result, bool *timed_out);
108108
static void pgfdw_abort_cleanup(ConnCacheEntry *entry, const char *sql,
109109
bool toplevel);
110110
static bool UserMappingPasswordRequired(UserMapping *user);
@@ -1154,6 +1154,7 @@ pgfdw_cancel_query(PGconn *conn)
11541154
char errbuf[256];
11551155
PGresult *result = NULL;
11561156
TimestampTz endtime;
1157+
bool timed_out;
11571158

11581159
/*
11591160
* If it takes too long to cancel the query and discard the result, assume
@@ -1180,8 +1181,19 @@ pgfdw_cancel_query(PGconn *conn)
11801181
}
11811182

11821183
/* Get and discard the result of the query. */
1183-
if (pgfdw_get_cleanup_result(conn, endtime, &result))
1184+
if (pgfdw_get_cleanup_result(conn, endtime, &result, &timed_out))
1185+
{
1186+
if (timed_out)
1187+
ereport(WARNING,
1188+
(errmsg("could not get result of cancel request due to timeout")));
1189+
else
1190+
ereport(WARNING,
1191+
(errcode(ERRCODE_CONNECTION_FAILURE),
1192+
errmsg("could not get result of cancel request: %s",
1193+
pchomp(PQerrorMessage(conn)))));
1194+
11841195
return false;
1196+
}
11851197
PQclear(result);
11861198

11871199
return true;
@@ -1204,6 +1216,7 @@ pgfdw_exec_cleanup_query(PGconn *conn, const char *query, bool ignore_errors)
12041216
{
12051217
PGresult *result = NULL;
12061218
TimestampTz endtime;
1219+
bool timed_out;
12071220

12081221
/*
12091222
* If it takes too long to execute a cleanup query, assume the connection
@@ -1224,8 +1237,17 @@ pgfdw_exec_cleanup_query(PGconn *conn, const char *query, bool ignore_errors)
12241237
}
12251238

12261239
/* Get the result of the query. */
1227-
if (pgfdw_get_cleanup_result(conn, endtime, &result))
1240+
if (pgfdw_get_cleanup_result(conn, endtime, &result, &timed_out))
1241+
{
1242+
if (timed_out)
1243+
ereport(WARNING,
1244+
(errmsg("could not get query result due to timeout"),
1245+
query ? errcontext("remote SQL command: %s", query) : 0));
1246+
else
1247+
pgfdw_report_error(WARNING, NULL, conn, false, query);
1248+
12281249
return false;
1250+
}
12291251

12301252
/* Issue a warning if not successful. */
12311253
if (PQresultStatus(result) != PGRES_COMMAND_OK)
@@ -1245,15 +1267,19 @@ pgfdw_exec_cleanup_query(PGconn *conn, const char *query, bool ignore_errors)
12451267
* side back to the appropriate state.
12461268
*
12471269
* endtime is the time at which we should give up and assume the remote
1248-
* side is dead. Returns true if the timeout expired, otherwise false.
1249-
* Sets *result except in case of a timeout.
1270+
* side is dead. Returns true if the timeout expired or connection trouble
1271+
* occurred, false otherwise. Sets *result except in case of a timeout.
1272+
* Sets timed_out to true only when the timeout expired.
12501273
*/
12511274
static bool
1252-
pgfdw_get_cleanup_result(PGconn *conn, TimestampTz endtime, PGresult **result)
1275+
pgfdw_get_cleanup_result(PGconn *conn, TimestampTz endtime, PGresult **result,
1276+
bool *timed_out)
12531277
{
1254-
volatile bool timed_out = false;
1278+
volatile bool failed = false;
12551279
PGresult *volatile last_res = NULL;
12561280

1281+
*timed_out = false;
1282+
12571283
/* In what follows, do not leak any PGresults on an error. */
12581284
PG_TRY();
12591285
{
@@ -1271,7 +1297,8 @@ pgfdw_get_cleanup_result(PGconn *conn, TimestampTz endtime, PGresult **result)
12711297
cur_timeout = TimestampDifferenceMilliseconds(now, endtime);
12721298
if (cur_timeout <= 0)
12731299
{
1274-
timed_out = true;
1300+
*timed_out = true;
1301+
failed = true;
12751302
goto exit;
12761303
}
12771304

@@ -1290,8 +1317,8 @@ pgfdw_get_cleanup_result(PGconn *conn, TimestampTz endtime, PGresult **result)
12901317
{
12911318
if (!PQconsumeInput(conn))
12921319
{
1293-
/* connection trouble; treat the same as a timeout */
1294-
timed_out = true;
1320+
/* connection trouble */
1321+
failed = true;
12951322
goto exit;
12961323
}
12971324
}
@@ -1313,11 +1340,11 @@ exit: ;
13131340
}
13141341
PG_END_TRY();
13151342

1316-
if (timed_out)
1343+
if (failed)
13171344
PQclear(last_res);
13181345
else
13191346
*result = last_res;
1320-
return timed_out;
1347+
return failed;
13211348
}
13221349

13231350
/*

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy