diff --git a/contrib/dblink/dblink.c b/contrib/dblink/dblink.c
index 4e29ee94072f1154489db3c0e4afa519c33553b9..226e737e2d9b0762f43806be9422f2a0eaccf37b 100644
--- a/contrib/dblink/dblink.c
+++ b/contrib/dblink/dblink.c
@@ -8,7 +8,7 @@
  * Darko Prenosil <Darko.Prenosil@finteh.hr>
  * Shridhar Daithankar <shridhar_daithankar@persistent.co.in>
  *
- * $PostgreSQL: pgsql/contrib/dblink/dblink.c,v 1.73 2008/04/04 17:02:56 momjian Exp $
+ * $PostgreSQL: pgsql/contrib/dblink/dblink.c,v 1.74 2008/07/03 03:56:57 joe Exp $
  * Copyright (c) 2001-2008, PostgreSQL Global Development Group
  * ALL RIGHTS RESERVED;
  *
@@ -94,6 +94,7 @@ static HeapTuple get_tuple_of_interest(Oid relid, int2vector *pkattnums, int16 p
 static Oid	get_relid_from_relname(text *relname_text);
 static char *generate_relation_name(Oid relid);
 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);
 
 /* Global */
 static remoteConn *pconn = NULL;
@@ -125,34 +126,20 @@ typedef struct remoteConnHashEnt
 		} \
 	} while (0)
 
-#define DBLINK_RES_INTERNALERROR(p2) \
-	do { \
-			msg = pstrdup(PQerrorMessage(conn)); \
-			if (res) \
-				PQclear(res); \
-			elog(ERROR, "%s: %s", p2, msg); \
-	} while (0)
-
-#define DBLINK_RES_ERROR(p2) \
+#define xpstrdup(var_c, var_) \
 	do { \
-			msg = pstrdup(PQerrorMessage(conn)); \
-			if (res) \
-				PQclear(res); \
-			ereport(ERROR, \
-					(errcode(ERRCODE_SYNTAX_ERROR), \
-					 errmsg("%s", p2), \
-					 errdetail("%s", msg))); \
+		if (var_ != NULL) \
+			var_c = pstrdup(var_); \
+		else \
+			var_c = NULL; \
 	} while (0)
 
-#define DBLINK_RES_ERROR_AS_NOTICE(p2) \
+#define DBLINK_RES_INTERNALERROR(p2) \
 	do { \
 			msg = pstrdup(PQerrorMessage(conn)); \
 			if (res) \
 				PQclear(res); \
-			ereport(NOTICE, \
-					(errcode(ERRCODE_SYNTAX_ERROR), \
-					 errmsg("%s", p2), \
-					 errdetail("%s", msg))); \
+			elog(ERROR, "%s: %s", p2, msg); \
 	} while (0)
 
 #define DBLINK_CONN_NOT_AVAIL \
@@ -396,13 +383,8 @@ dblink_open(PG_FUNCTION_ARGS)
 	res = PQexec(conn, buf.data);
 	if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
 	{
-		if (fail)
-			DBLINK_RES_ERROR("sql error");
-		else
-		{
-			DBLINK_RES_ERROR_AS_NOTICE("sql error");
-			PG_RETURN_TEXT_P(cstring_to_text("ERROR"));
-		}
+		dblink_res_error(conname, res, "could not open cursor", fail);
+		PG_RETURN_TEXT_P(cstring_to_text("ERROR"));
 	}
 
 	PQclear(res);
@@ -470,13 +452,8 @@ dblink_close(PG_FUNCTION_ARGS)
 	res = PQexec(conn, buf.data);
 	if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
 	{
-		if (fail)
-			DBLINK_RES_ERROR("sql error");
-		else
-		{
-			DBLINK_RES_ERROR_AS_NOTICE("sql error");
-			PG_RETURN_TEXT_P(cstring_to_text("ERROR"));
-		}
+		dblink_res_error(conname, res, "could not close cursor", fail);
+		PG_RETURN_TEXT_P(cstring_to_text("ERROR"));
 	}
 
 	PQclear(res);
@@ -513,7 +490,6 @@ dblink_fetch(PG_FUNCTION_ARGS)
 	int			call_cntr;
 	int			max_calls;
 	AttInMetadata *attinmeta;
-	char	   *msg;
 	PGresult   *res = NULL;
 	MemoryContext oldcontext;
 	char	   *conname = NULL;
@@ -590,13 +566,8 @@ dblink_fetch(PG_FUNCTION_ARGS)
 			(PQresultStatus(res) != PGRES_COMMAND_OK &&
 			 PQresultStatus(res) != PGRES_TUPLES_OK))
 		{
-			if (fail)
-				DBLINK_RES_ERROR("sql error");
-			else
-			{
-				DBLINK_RES_ERROR_AS_NOTICE("sql error");
-				SRF_RETURN_DONE(funcctx);
-			}
+			dblink_res_error(conname, res, "could not fetch from cursor", fail);
+			SRF_RETURN_DONE(funcctx);
 		}
 		else if (PQresultStatus(res) == PGRES_COMMAND_OK)
 		{
@@ -846,15 +817,10 @@ dblink_record_internal(FunctionCallInfo fcinfo, bool is_async, bool do_get)
 				(PQresultStatus(res) != PGRES_COMMAND_OK &&
 				 PQresultStatus(res) != PGRES_TUPLES_OK))
 			{
-				if (fail)
-					DBLINK_RES_ERROR("sql error");
-				else
-				{
-					DBLINK_RES_ERROR_AS_NOTICE("sql error");
-					if (freeconn)
-						PQfinish(conn);
-					SRF_RETURN_DONE(funcctx);
-				}
+				dblink_res_error(conname, res, "could not execute query", fail);
+				if (freeconn)
+					PQfinish(conn);
+				SRF_RETURN_DONE(funcctx);
 			}
 
 			if (PQresultStatus(res) == PGRES_COMMAND_OK)
@@ -1180,10 +1146,7 @@ dblink_exec(PG_FUNCTION_ARGS)
 		(PQresultStatus(res) != PGRES_COMMAND_OK &&
 		 PQresultStatus(res) != PGRES_TUPLES_OK))
 	{
-		if (fail)
-			DBLINK_RES_ERROR("sql error");
-		else
-			DBLINK_RES_ERROR_AS_NOTICE("sql error");
+		dblink_res_error(conname, res, "could not execute command", fail);
 
 		/* need a tuple descriptor representing one TEXT column */
 		tupdesc = CreateTemplateTupleDesc(1, false);
@@ -1195,7 +1158,6 @@ dblink_exec(PG_FUNCTION_ARGS)
 		 * result tuple
 		 */
 		sql_cmd_status = cstring_to_text("ERROR");
-
 	}
 	else if (PQresultStatus(res) == PGRES_COMMAND_OK)
 	{
@@ -2288,3 +2250,54 @@ dblink_security_check(PGconn *conn, remoteConn *rconn)
 		}
 	}
 }
+
+static void
+dblink_res_error(const char *conname, PGresult *res, const char *dblink_context_msg, bool fail)
+{
+	int			level;
+	char	   *pg_diag_sqlstate = PQresultErrorField(res, PG_DIAG_SQLSTATE);
+	char	   *pg_diag_message_primary = PQresultErrorField(res, PG_DIAG_MESSAGE_PRIMARY);
+	char	   *pg_diag_message_detail = PQresultErrorField(res, PG_DIAG_MESSAGE_DETAIL);
+	char	   *pg_diag_message_hint = PQresultErrorField(res, PG_DIAG_MESSAGE_HINT);
+	char	   *pg_diag_context = PQresultErrorField(res, PG_DIAG_CONTEXT);
+	int			sqlstate;
+	char	   *message_primary;
+	char	   *message_detail;
+	char	   *message_hint;
+	char	   *message_context;
+	const char *dblink_context_conname = "unnamed";
+
+	if (fail)
+		level = ERROR;
+	else
+		level = NOTICE;
+
+	if (pg_diag_sqlstate)
+		sqlstate = MAKE_SQLSTATE(pg_diag_sqlstate[0],
+								 pg_diag_sqlstate[1],
+								 pg_diag_sqlstate[2],
+								 pg_diag_sqlstate[3],
+								 pg_diag_sqlstate[4]);
+	else
+		sqlstate = ERRCODE_CONNECTION_FAILURE;
+
+	xpstrdup(message_primary, pg_diag_message_primary);
+	xpstrdup(message_detail, pg_diag_message_detail);
+	xpstrdup(message_hint, pg_diag_message_hint);
+	xpstrdup(message_context, pg_diag_context);
+
+	if (res)
+		PQclear(res);
+
+	if (conname)
+		dblink_context_conname = conname;
+
+	ereport(level,
+		(errcode(sqlstate),
+		 message_primary ? errmsg("%s", message_primary) : errmsg("unknown error"),
+		 message_detail ? errdetail("%s", message_detail) : 0,
+		 message_hint ? errhint("%s", message_hint) : 0,
+		 message_context ? errcontext("%s", message_context) : 0,
+		 errcontext("Error occurred on dblink connection named \"%s\": %s.",
+					dblink_context_conname, dblink_context_msg)));
+}
diff --git a/contrib/dblink/expected/dblink.out b/contrib/dblink/expected/dblink.out
index 170d69c286c155ff55a28a4f44369fd063b17eba..f2eb6aa5e2fc65b5fd8f5b17455b1e544b10df51 100644
--- a/contrib/dblink/expected/dblink.out
+++ b/contrib/dblink/expected/dblink.out
@@ -125,9 +125,8 @@ WHERE t.a > 7;
 
 -- open a cursor with bad SQL and fail_on_error set to false
 SELECT dblink_open('rmt_foo_cursor','SELECT * FROM foobar',false);
-NOTICE:  sql error
-DETAIL:  ERROR:  relation "foobar" does not exist
-
+NOTICE:  relation "foobar" does not exist
+CONTEXT:  Error occurred on dblink connection named "unnamed": could not open cursor.
  dblink_open 
 -------------
  ERROR
@@ -194,9 +193,8 @@ FROM dblink_fetch('rmt_foo_cursor',4) AS t(a int, b text, c text[]);
 -- intentionally botch a fetch
 SELECT *
 FROM dblink_fetch('rmt_foobar_cursor',4,false) AS t(a int, b text, c text[]);
-NOTICE:  sql error
-DETAIL:  ERROR:  cursor "rmt_foobar_cursor" does not exist
-
+NOTICE:  cursor "rmt_foobar_cursor" does not exist
+CONTEXT:  Error occurred on dblink connection named "unnamed": could not fetch from cursor.
  a | b | c 
 ---+---+---
 (0 rows)
@@ -210,9 +208,8 @@ SELECT dblink_exec('ABORT');
 
 -- close the wrong cursor
 SELECT dblink_close('rmt_foobar_cursor',false);
-NOTICE:  sql error
-DETAIL:  ERROR:  cursor "rmt_foobar_cursor" does not exist
-
+NOTICE:  cursor "rmt_foobar_cursor" does not exist
+CONTEXT:  Error occurred on dblink connection named "unnamed": could not close cursor.
  dblink_close 
 --------------
  ERROR
@@ -221,15 +218,13 @@ DETAIL:  ERROR:  cursor "rmt_foobar_cursor" does not exist
 -- should generate 'cursor "rmt_foo_cursor" not found' error
 SELECT *
 FROM dblink_fetch('rmt_foo_cursor',4) AS t(a int, b text, c text[]);
-ERROR:  sql error
-DETAIL:  ERROR:  cursor "rmt_foo_cursor" does not exist
-
+ERROR:  cursor "rmt_foo_cursor" does not exist
+CONTEXT:  Error occurred on dblink connection named "unnamed": could not fetch from cursor.
 -- this time, 'cursor "rmt_foo_cursor" not found' as a notice
 SELECT *
 FROM dblink_fetch('rmt_foo_cursor',4,false) AS t(a int, b text, c text[]);
-NOTICE:  sql error
-DETAIL:  ERROR:  cursor "rmt_foo_cursor" does not exist
-
+NOTICE:  cursor "rmt_foo_cursor" does not exist
+CONTEXT:  Error occurred on dblink connection named "unnamed": could not fetch from cursor.
  a | b | c 
 ---+---+---
 (0 rows)
@@ -291,9 +286,8 @@ FROM dblink('SELECT * FROM foo') AS t(a int, b text, c text[]);
 -- bad remote select
 SELECT *
 FROM dblink('SELECT * FROM foobar',false) AS t(a int, b text, c text[]);
-NOTICE:  sql error
-DETAIL:  ERROR:  relation "foobar" does not exist
-
+NOTICE:  relation "foobar" does not exist
+CONTEXT:  Error occurred on dblink connection named "unnamed": could not execute query.
  a | b | c 
 ---+---+---
 (0 rows)
@@ -316,9 +310,8 @@ WHERE a = 11;
 
 -- botch a change to some other data
 SELECT dblink_exec('UPDATE foobar SET f3[2] = ''b99'' WHERE f1 = 11',false);
-NOTICE:  sql error
-DETAIL:  ERROR:  relation "foobar" does not exist
-
+NOTICE:  relation "foobar" does not exist
+CONTEXT:  Error occurred on dblink connection named "unnamed": could not execute command.
  dblink_exec 
 -------------
  ERROR
@@ -378,9 +371,8 @@ WHERE t.a > 7;
 SELECT *
 FROM dblink('myconn','SELECT * FROM foobar',false) AS t(a int, b text, c text[])
 WHERE t.a > 7;
-NOTICE:  sql error
-DETAIL:  ERROR:  relation "foobar" does not exist
-
+NOTICE:  relation "foobar" does not exist
+CONTEXT:  Error occurred on dblink connection named "unnamed": could not execute query.
  a | b | c 
 ---+---+---
 (0 rows)
@@ -416,9 +408,8 @@ SELECT dblink_disconnect('myconn2');
 
 -- open a cursor incorrectly
 SELECT dblink_open('myconn','rmt_foo_cursor','SELECT * FROM foobar',false);
-NOTICE:  sql error
-DETAIL:  ERROR:  relation "foobar" does not exist
-
+NOTICE:  relation "foobar" does not exist
+CONTEXT:  Error occurred on dblink connection named "myconn": could not open cursor.
  dblink_open 
 -------------
  ERROR
@@ -503,9 +494,8 @@ SELECT dblink_close('myconn','rmt_foo_cursor');
 
 -- this should fail because there is no open transaction
 SELECT dblink_exec('myconn','DECLARE xact_test CURSOR FOR SELECT * FROM foo');
-ERROR:  sql error
-DETAIL:  ERROR:  DECLARE CURSOR can only be used in transaction blocks
-
+ERROR:  DECLARE CURSOR can only be used in transaction blocks
+CONTEXT:  Error occurred on dblink connection named "unnamed": could not execute command.
 -- reset remote transaction state
 SELECT dblink_exec('myconn','ABORT');
  dblink_exec 
@@ -554,9 +544,8 @@ FROM dblink_fetch('myconn','rmt_foo_cursor',4) AS t(a int, b text, c text[]);
 -- fetch some data incorrectly
 SELECT *
 FROM dblink_fetch('myconn','rmt_foobar_cursor',4,false) AS t(a int, b text, c text[]);
-NOTICE:  sql error
-DETAIL:  ERROR:  cursor "rmt_foobar_cursor" does not exist
-
+NOTICE:  cursor "rmt_foobar_cursor" does not exist
+CONTEXT:  Error occurred on dblink connection named "myconn": could not fetch from cursor.
  a | b | c 
 ---+---+---
 (0 rows)
@@ -571,9 +560,8 @@ SELECT dblink_exec('myconn','ABORT');
 -- should generate 'cursor "rmt_foo_cursor" not found' error
 SELECT *
 FROM dblink_fetch('myconn','rmt_foo_cursor',4) AS t(a int, b text, c text[]);
-ERROR:  sql error
-DETAIL:  ERROR:  cursor "rmt_foo_cursor" does not exist
-
+ERROR:  cursor "rmt_foo_cursor" does not exist
+CONTEXT:  Error occurred on dblink connection named "myconn": could not fetch from cursor.
 -- close the named persistent connection
 SELECT dblink_disconnect('myconn');
  dblink_disconnect