Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
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

+39-12
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)