Skip to content

Commit 9b8507b

Browse files
committed
Make dblink try harder to form useful error messages
When libpq encounters a connection-level error, e.g. runs out of memory while forming a result, there will be no error associated with PGresult, but a message will be placed into PGconn's error buffer. postgres_fdw takes care to use the PGconn error message when PGresult does not have one, but dblink has been negligent in that regard. Modify dblink to mirror what postgres_fdw has been doing. Back-patch to all supported branches. Author: Joe Conway Reviewed-By: Tom Lane Discussion: https://postgr.es/m/02fa2d90-2efd-00bc-fefc-c23c00eb671e%40joeconway.com
1 parent bd46cce commit 9b8507b

File tree

1 file changed

+22
-9
lines changed

1 file changed

+22
-9
lines changed

contrib/dblink/dblink.c

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,8 @@ static Relation get_rel_from_relname(text *relname_text, LOCKMODE lockmode, AclM
113113
static char *generate_relation_name(Relation rel);
114114
static void dblink_connstr_check(const char *connstr);
115115
static void dblink_security_check(PGconn *conn, remoteConn *rconn);
116-
static void dblink_res_error(const char *conname, PGresult *res, const char *dblink_context_msg, bool fail);
116+
static void dblink_res_error(PGconn *conn, const char *conname, PGresult *res,
117+
const char *dblink_context_msg, bool fail);
117118
static char *get_connect_string(const char *servername);
118119
static char *escape_param_str(const char *from);
119120
static void validate_pkattnums(Relation rel,
@@ -428,7 +429,7 @@ dblink_open(PG_FUNCTION_ARGS)
428429
res = PQexec(conn, buf.data);
429430
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
430431
{
431-
dblink_res_error(conname, res, "could not open cursor", fail);
432+
dblink_res_error(conn, conname, res, "could not open cursor", fail);
432433
PG_RETURN_TEXT_P(cstring_to_text("ERROR"));
433434
}
434435

@@ -497,7 +498,7 @@ dblink_close(PG_FUNCTION_ARGS)
497498
res = PQexec(conn, buf.data);
498499
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
499500
{
500-
dblink_res_error(conname, res, "could not close cursor", fail);
501+
dblink_res_error(conn, conname, res, "could not close cursor", fail);
501502
PG_RETURN_TEXT_P(cstring_to_text("ERROR"));
502503
}
503504

@@ -600,7 +601,8 @@ dblink_fetch(PG_FUNCTION_ARGS)
600601
(PQresultStatus(res) != PGRES_COMMAND_OK &&
601602
PQresultStatus(res) != PGRES_TUPLES_OK))
602603
{
603-
dblink_res_error(conname, res, "could not fetch from cursor", fail);
604+
dblink_res_error(conn, conname, res,
605+
"could not fetch from cursor", fail);
604606
return (Datum) 0;
605607
}
606608
else if (PQresultStatus(res) == PGRES_COMMAND_OK)
@@ -751,8 +753,8 @@ dblink_record_internal(FunctionCallInfo fcinfo, bool is_async)
751753
if (PQresultStatus(res) != PGRES_COMMAND_OK &&
752754
PQresultStatus(res) != PGRES_TUPLES_OK)
753755
{
754-
dblink_res_error(conname, res, "could not execute query",
755-
fail);
756+
dblink_res_error(conn, conname, res,
757+
"could not execute query", fail);
756758
/* if fail isn't set, we'll return an empty query result */
757759
}
758760
else
@@ -999,7 +1001,8 @@ materializeQueryResult(FunctionCallInfo fcinfo,
9991001
PGresult *res1 = res;
10001002

10011003
res = NULL;
1002-
dblink_res_error(conname, res1, "could not execute query", fail);
1004+
dblink_res_error(conn, conname, res1,
1005+
"could not execute query", fail);
10031006
/* if fail isn't set, we'll return an empty query result */
10041007
}
10051008
else if (PQresultStatus(res) == PGRES_COMMAND_OK)
@@ -1434,7 +1437,8 @@ dblink_exec(PG_FUNCTION_ARGS)
14341437
(PQresultStatus(res) != PGRES_COMMAND_OK &&
14351438
PQresultStatus(res) != PGRES_TUPLES_OK))
14361439
{
1437-
dblink_res_error(conname, res, "could not execute command", fail);
1440+
dblink_res_error(conn, conname, res,
1441+
"could not execute command", fail);
14381442

14391443
/*
14401444
* and save a copy of the command status string to return as our
@@ -2668,7 +2672,8 @@ dblink_connstr_check(const char *connstr)
26682672
}
26692673

26702674
static void
2671-
dblink_res_error(const char *conname, PGresult *res, const char *dblink_context_msg, bool fail)
2675+
dblink_res_error(PGconn *conn, const char *conname, PGresult *res,
2676+
const char *dblink_context_msg, bool fail)
26722677
{
26732678
int level;
26742679
char *pg_diag_sqlstate = PQresultErrorField(res, PG_DIAG_SQLSTATE);
@@ -2702,6 +2707,14 @@ dblink_res_error(const char *conname, PGresult *res, const char *dblink_context_
27022707
xpstrdup(message_hint, pg_diag_message_hint);
27032708
xpstrdup(message_context, pg_diag_context);
27042709

2710+
/*
2711+
* If we don't get a message from the PGresult, try the PGconn. This
2712+
* is needed because for connection-level failures, PQexec may just
2713+
* return NULL, not a PGresult at all.
2714+
*/
2715+
if (message_primary == NULL)
2716+
message_primary = PQerrorMessage(conn);
2717+
27052718
if (res)
27062719
PQclear(res);
27072720

0 commit comments

Comments
 (0)