Skip to content

Commit 51126cc

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 150841f commit 51126cc

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
@@ -997,7 +999,8 @@ materializeQueryResult(FunctionCallInfo fcinfo,
997999
PGresult *res1 = res;
9981000

9991001
res = NULL;
1000-
dblink_res_error(conname, res1, "could not execute query", fail);
1002+
dblink_res_error(conn, conname, res1,
1003+
"could not execute query", fail);
10011004
/* if fail isn't set, we'll return an empty query result */
10021005
}
10031006
else if (PQresultStatus(res) == PGRES_COMMAND_OK)
@@ -1432,7 +1435,8 @@ dblink_exec(PG_FUNCTION_ARGS)
14321435
(PQresultStatus(res) != PGRES_COMMAND_OK &&
14331436
PQresultStatus(res) != PGRES_TUPLES_OK))
14341437
{
1435-
dblink_res_error(conname, res, "could not execute command", fail);
1438+
dblink_res_error(conn, conname, res,
1439+
"could not execute command", fail);
14361440

14371441
/*
14381442
* and save a copy of the command status string to return as our
@@ -2663,7 +2667,8 @@ dblink_connstr_check(const char *connstr)
26632667
}
26642668

26652669
static void
2666-
dblink_res_error(const char *conname, PGresult *res, const char *dblink_context_msg, bool fail)
2670+
dblink_res_error(PGconn *conn, const char *conname, PGresult *res,
2671+
const char *dblink_context_msg, bool fail)
26672672
{
26682673
int level;
26692674
char *pg_diag_sqlstate = PQresultErrorField(res, PG_DIAG_SQLSTATE);
@@ -2697,6 +2702,14 @@ dblink_res_error(const char *conname, PGresult *res, const char *dblink_context_
26972702
xpstrdup(message_hint, pg_diag_message_hint);
26982703
xpstrdup(message_context, pg_diag_context);
26992704

2705+
/*
2706+
* If we don't get a message from the PGresult, try the PGconn. This
2707+
* is needed because for connection-level failures, PQexec may just
2708+
* return NULL, not a PGresult at all.
2709+
*/
2710+
if (message_primary == NULL)
2711+
message_primary = PQerrorMessage(conn);
2712+
27002713
if (res)
27012714
PQclear(res);
27022715

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