diff options
author | Joe Conway <mail@joeconway.com> | 2016-12-22 09:48:05 -0800 |
---|---|---|
committer | Joe Conway <mail@joeconway.com> | 2016-12-22 09:48:55 -0800 |
commit | 2f802d95b4904dbed3dfdca1b3a607cd085d2e20 (patch) | |
tree | 65e083bdc0a5e74b06549fe07a37a89df68f7bae | |
parent | 3ee80672847c4100d5f9efdb9ea19cb96506d089 (diff) | |
download | postgresql-2f802d95b4904dbed3dfdca1b3a607cd085d2e20.tar.gz postgresql-2f802d95b4904dbed3dfdca1b3a607cd085d2e20.zip |
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
-rw-r--r-- | contrib/dblink/dblink.c | 31 |
1 files changed, 22 insertions, 9 deletions
diff --git a/contrib/dblink/dblink.c b/contrib/dblink/dblink.c index 10dc9bd347d..5b041ddc7ce 100644 --- a/contrib/dblink/dblink.c +++ b/contrib/dblink/dblink.c @@ -113,7 +113,8 @@ static Relation get_rel_from_relname(text *relname_text, LOCKMODE lockmode, AclM static char *generate_relation_name(Relation rel); static void dblink_connstr_check(const char *connstr); static void dblink_security_check(PGconn *conn, remoteConn *rconn); -static void dblink_res_error(const char *conname, PGresult *res, const char *dblink_context_msg, bool fail); +static void dblink_res_error(PGconn *conn, const char *conname, PGresult *res, + const char *dblink_context_msg, bool fail); static char *get_connect_string(const char *servername); static char *escape_param_str(const char *from); static void validate_pkattnums(Relation rel, @@ -428,7 +429,7 @@ dblink_open(PG_FUNCTION_ARGS) res = PQexec(conn, buf.data); if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) { - dblink_res_error(conname, res, "could not open cursor", fail); + dblink_res_error(conn, conname, res, "could not open cursor", fail); PG_RETURN_TEXT_P(cstring_to_text("ERROR")); } @@ -497,7 +498,7 @@ dblink_close(PG_FUNCTION_ARGS) res = PQexec(conn, buf.data); if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) { - dblink_res_error(conname, res, "could not close cursor", fail); + dblink_res_error(conn, conname, res, "could not close cursor", fail); PG_RETURN_TEXT_P(cstring_to_text("ERROR")); } @@ -600,7 +601,8 @@ dblink_fetch(PG_FUNCTION_ARGS) (PQresultStatus(res) != PGRES_COMMAND_OK && PQresultStatus(res) != PGRES_TUPLES_OK)) { - dblink_res_error(conname, res, "could not fetch from cursor", fail); + dblink_res_error(conn, conname, res, + "could not fetch from cursor", fail); return (Datum) 0; } else if (PQresultStatus(res) == PGRES_COMMAND_OK) @@ -751,8 +753,8 @@ dblink_record_internal(FunctionCallInfo fcinfo, bool is_async) if (PQresultStatus(res) != PGRES_COMMAND_OK && PQresultStatus(res) != PGRES_TUPLES_OK) { - dblink_res_error(conname, res, "could not execute query", - fail); + dblink_res_error(conn, conname, res, + "could not execute query", fail); /* if fail isn't set, we'll return an empty query result */ } else @@ -997,7 +999,8 @@ materializeQueryResult(FunctionCallInfo fcinfo, PGresult *res1 = res; res = NULL; - dblink_res_error(conname, res1, "could not execute query", fail); + dblink_res_error(conn, conname, res1, + "could not execute query", fail); /* if fail isn't set, we'll return an empty query result */ } else if (PQresultStatus(res) == PGRES_COMMAND_OK) @@ -1432,7 +1435,8 @@ dblink_exec(PG_FUNCTION_ARGS) (PQresultStatus(res) != PGRES_COMMAND_OK && PQresultStatus(res) != PGRES_TUPLES_OK)) { - dblink_res_error(conname, res, "could not execute command", fail); + dblink_res_error(conn, conname, res, + "could not execute command", fail); /* * and save a copy of the command status string to return as our @@ -2663,7 +2667,8 @@ dblink_connstr_check(const char *connstr) } static void -dblink_res_error(const char *conname, PGresult *res, const char *dblink_context_msg, bool fail) +dblink_res_error(PGconn *conn, const char *conname, PGresult *res, + const char *dblink_context_msg, bool fail) { int level; 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_ xpstrdup(message_hint, pg_diag_message_hint); xpstrdup(message_context, pg_diag_context); + /* + * If we don't get a message from the PGresult, try the PGconn. This + * is needed because for connection-level failures, PQexec may just + * return NULL, not a PGresult at all. + */ + if (message_primary == NULL) + message_primary = PQerrorMessage(conn); + if (res) PQclear(res); |