8000 Make dblink try harder to form useful error messages · iakio/postgres@44de099 · GitHub < 10000 link rel="manifest" href="/manifest.json" crossOrigin="use-credentials">
[go: up one dir, main page]

Skip to content

Commit 44de099

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 501c910 commit 44de099

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
@@ -106,7 +106,8 @@ static Relation get_rel_from_relname(text *relname_text, LOCKMODE lockmode, AclM
106106
static char *generate_relation_name(Relation rel);
107107
static void dblink_connstr_check(const char *connstr);
108108
static void dblink_security_check(PGconn *conn, remoteConn *rconn);
109-
static void dblink_res_error(const char *conname, PGresult *res, const char *dblink_context_msg, bool fail);
109+
static void dblink_res_error(PGconn *conn, const char *conname, PGresult *res,
110+
const char *dblink_context_msg, bool fail);
110111
static char *get_connect_string(const char *servername);
111112
static char *escape_param_str(const char *from);
112113
static void validate_pkattnums(Relation rel,
@@ -419,7 +420,7 @@ dblink_open(PG_FUNCTION_ARGS)
419420
res = PQexec(conn, buf.data);
420421
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
421422
{
422-
dblink_res_error(conname, res, "could not open cursor", fail);
423+
dblink_res_error(conn, conname, res, "could not open cursor", fail);
423424
PG_RETURN_TEXT_P(cstring_to_text("ERROR"));
424425
}
425426

@@ -488,7 +489,7 @@ dblink_close(PG_FUNCTION_ARGS)
488489
res = PQexec(conn, buf.data);
489490
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
490491
{
491-
dblink_res_error(conname, res, "could not close cursor", fail);
492+
dblink_res_error(conn, conname, res, "could not close cursor", fail);
492493
PG_RETURN_TEXT_P(cstring_to_text("ERROR"));
493494
}
494495

@@ -591,7 +592,8 @@ dblink_fetch(PG_FUNCTION_ARGS)
591592
(PQresultStatus(res) != PGRES_COMMAND_OK &&
592593
PQresultStatus(res) != PGRES_TUPLES_OK))
593594
{
594-
dblink_res_error(conname, res, "could not fetch from cursor", fail);
595+
dblink_res_error(conn, conname, res,
596+
"could not fetch from cursor", fail);
595597
return (Datum) 0;
596598
}
597599
else if (PQresultStatus(res) == PGRES_COMMAND_OK)
@@ -742,8 +744,8 @@ dblink_record_internal(FunctionCallInfo fcinfo, bool is_async)
742744
if (PQresultStatus(res) != PGRES_COMMAND_OK &&
743745
PQresultStatus(res) != PGRES_TUPLES_OK)
744746
{
745-
dblink_res_error(conname, res, "could not execute query",
746-
fail);
747+
dblink_res_error(conn, conname, res,
748+
"could not execute query", fail);
747749
/* if fail isn't set, we'll return an empty query result */
748750
}
749751
else
@@ -990,7 +992,8 @@ materializeQueryResult(FunctionCallInfo fcinfo,
990992
PGresult *res1 = res;
991993

992994
res = NULL;
993-
dblink_res_error(conname, res1, "could not execute query", fail);
995+
dblink_res_error(conn, conname, res1,
996+
"could not execute query", fail);
994997
/* if fail isn't set, we'll return an empty query result */
995998
}
996999
else if (PQresultStatus(res) == PGRES_COMMAND_OK)
@@ -1425,7 +1428,8 @@ dblink_exec(PG_FUNCTION_ARGS)
14251428
(PQresultStatus(res) != PGRES_COMMAND_OK &&
14261429
PQresultStatus(res) != PGRES_TUPLES_OK))
14271430
{
1428-
dblink_res_error(conname, res, "could not execute command", fail);
1431+
dblink_res_error(conn, conname, res,
1432+
"could not execute command", fail);
14291433

14301434
/*
14311435
* and save a copy of the command status string to return as our
@@ -2590,7 +2594,8 @@ dblink_connstr_check(const char *connstr)
25902594
}
25912595

25922596
static void
2593-
dblink_res_error(const char *conname, PGresult *res, const char *dblink_context_msg, bool fail)
2597+
dblink_res_error(PGconn *conn, const char *conname, PGresult *res,
2598+
const char *dblink_context_msg, bool fail)
25942599
{
25952600
int level;
25962601
char *pg_diag_sqlstate = PQresultErrorField(res, PG_DIAG_SQLSTATE);
@@ -2624,6 +2629,14 @@ dblink_res_error(const char *conname, PGresult *res, const char *dblink_context_
26242629
xpstrdup(message_hint, pg_diag_message_hint);
26252630
xpstrdup(message_context, pg_diag_context);
26262631

2632+
/*
2633+
* If we don't get a message from the PGresult, try the PGconn. This
2634+
* is needed because for connection-level failures, PQexec may just
2635+
* return NULL, not a PGresult at all.
2636+
*/
2637+
if (message_primary == NULL)
2638+
message_primary = PQerrorMessage(conn);
2639+
26272640
if (res)
26282641
PQclear(res);
26292642

0 commit comments

Comments
 (0)
0