On 2021/12/03 23:04, Bharath Rupireddy wrote:
Let's not use the boolean just for the cancel request which isn't
scalable IMO. Maybe a macro/enum?

Otherwise, we could just do, although it doesn't look elegant:

if (pgfdw_get_cleanup_result(conn, endtime, &result, "(cancel request)"))

if (strcmp(query, "(cancel request)") == 0)
     WARNING without  "remote SQL command:
else
     WARNING with "remote SQL command:

Yeah, I agree that's not elegant..

So I'd like to propose new patch with different design from
what I proposed before. Patch attached.

This patch changes pgfdw_exec_cleanup_query() so that it tells
its callers the information about whether the timeout expired
or not. Then the callers (pgfdw_exec_cleanup_query and
pgfdw_cancel_query) report the warning messages based on
the results from pgfdw_exec_cleanup_query().

Regards,

--
Fujii Masao
Advanced Computing Technology Center
Research and Development Headquarters
NTT DATA CORPORATION
diff --git a/contrib/postgres_fdw/connection.c 
b/contrib/postgres_fdw/connection.c
index 5c0137220a..6bac4ad23e 100644
--- a/contrib/postgres_fdw/connection.c
+++ b/contrib/postgres_fdw/connection.c
@@ -104,7 +104,7 @@ static bool pgfdw_cancel_query(PGconn *conn);
 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);
+                                                                        
PGresult **result, bool *timed_out);
 static void pgfdw_abort_cleanup(ConnCacheEntry *entry, const char *sql,
                                                                bool toplevel);
 static bool UserMappingPasswordRequired(UserMapping *user);
@@ -1154,6 +1154,7 @@ pgfdw_cancel_query(PGconn *conn)
        char            errbuf[256];
        PGresult   *result = NULL;
        TimestampTz endtime;
+       bool            timed_out;
 
        /*
         * If it takes too long to cancel the query and discard the result, 
assume
@@ -1180,8 +1181,19 @@ pgfdw_cancel_query(PGconn *conn)
        }
 
        /* Get and discard the result of the query. */
-       if (pgfdw_get_cleanup_result(conn, endtime, &result))
+       if (pgfdw_get_cleanup_result(conn, endtime, &result, &timed_out))
+       {
+               if (timed_out)
+                       ereport(WARNING,
+                                       (errmsg("could not get result of cancel 
request due to timeout")));
+               else
+                       ereport(WARNING,
+                                       (errcode(ERRCODE_CONNECTION_FAILURE),
+                                        errmsg("could not get result of cancel 
request: %s",
+                                                       
pchomp(PQerrorMessage(conn)))));
+
                return false;
+       }
        PQclear(result);
 
        return true;
@@ -1204,6 +1216,7 @@ pgfdw_exec_cleanup_query(PGconn *conn, const char *query, 
bool ignore_errors)
 {
        PGresult   *result = NULL;
        TimestampTz endtime;
+       bool            timed_out;
 
        /*
         * 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)
        }
 
        /* Get the result of the query. */
-       if (pgfdw_get_cleanup_result(conn, endtime, &result))
+       if (pgfdw_get_cleanup_result(conn, endtime, &result, &timed_out))
+       {
+               if (timed_out)
+                       ereport(WARNING,
+                                       (errmsg("could not get query result due 
to timeout"),
+                                        query ? errcontext("remote SQL 
command: %s", query) : 0));
+               else
+                       pgfdw_report_error(WARNING, NULL, conn, false, query);
+
                return false;
+       }
 
        /* Issue a warning if not successful. */
        if (PQresultStatus(result) != PGRES_COMMAND_OK)
@@ -1245,15 +1267,19 @@ pgfdw_exec_cleanup_query(PGconn *conn, const char 
*query, bool ignore_errors)
  * side back to the appropriate state.
  *
  * endtime is the time at which we should give up and assume the remote
- * side is dead.  Returns true if the timeout expired, otherwise false.
- * Sets *result except in case of a timeout.
+ * side is dead.  Returns true if the timeout expired or connection trouble
+ * occurred, false otherwise.  Sets *result except in case of a timeout.
+ * Sets timed_out to true only when the timeout expired.
  */
 static bool
-pgfdw_get_cleanup_result(PGconn *conn, TimestampTz endtime, PGresult **result)
+pgfdw_get_cleanup_result(PGconn *conn, TimestampTz endtime, PGresult **result,
+                                                bool *timed_out)
 {
-       volatile bool timed_out = false;
+       volatile bool failed = false;
        PGresult   *volatile last_res = NULL;
 
+       *timed_out = false;
+
        /* In what follows, do not leak any PGresults on an error. */
        PG_TRY();
        {
@@ -1271,7 +1297,8 @@ pgfdw_get_cleanup_result(PGconn *conn, TimestampTz 
endtime, PGresult **result)
                                cur_timeout = 
TimestampDifferenceMilliseconds(now, endtime);
                                if (cur_timeout <= 0)
                                {
-                                       timed_out = true;
+                                       *timed_out = true;
+                                       failed = true;
                                        goto exit;
                                }
 
@@ -1290,8 +1317,8 @@ pgfdw_get_cleanup_result(PGconn *conn, TimestampTz 
endtime, PGresult **result)
                                {
                                        if (!PQconsumeInput(conn))
                                        {
-                                               /* connection trouble; treat 
the same as a timeout */
-                                               timed_out = true;
+                                               /* connection trouble */
+                                               failed = true;
                                                goto exit;
                                        }
                                }
@@ -1313,11 +1340,11 @@ exit:   ;
        }
        PG_END_TRY();
 
-       if (timed_out)
+       if (failed)
                PQclear(last_res);
        else
                *result = last_res;
-       return timed_out;
+       return failed;
 }
 
 /*

Reply via email to