@@ -113,7 +113,7 @@ static char *generate_relation_name(Relation rel);
113113static void dblink_connstr_check (const char * connstr );
114114static void dblink_security_check (PGconn * conn , remoteConn * rconn );
115115static void dblink_res_error (PGconn * conn , const char * conname , PGresult * res ,
116- const char * dblink_context_msg , bool fail );
116+ bool fail , const char * fmt ,...) pg_attribute_printf ( 5 , 6 );
117117static char * get_connect_string (const char * servername );
118118static char * escape_param_str (const char * from );
119119static void validate_pkattnums (Relation rel ,
@@ -441,7 +441,8 @@ dblink_open(PG_FUNCTION_ARGS)
441441 res = PQexec (conn , buf .data );
442442 if (!res || PQresultStatus (res ) != PGRES_COMMAND_OK )
443443 {
444- dblink_res_error (conn , conname , res , "could not open cursor" , fail );
444+ dblink_res_error (conn , conname , res , fail ,
445+ "while opening cursor \"%s\"" , curname );
445446 PG_RETURN_TEXT_P (cstring_to_text ("ERROR" ));
446447 }
447448
@@ -509,7 +510,8 @@ dblink_close(PG_FUNCTION_ARGS)
509510 res = PQexec (conn , buf .data );
510511 if (!res || PQresultStatus (res ) != PGRES_COMMAND_OK )
511512 {
512- dblink_res_error (conn , conname , res , "could not close cursor" , fail );
513+ dblink_res_error (conn , conname , res , fail ,
514+ "while closing cursor \"%s\"" , curname );
513515 PG_RETURN_TEXT_P (cstring_to_text ("ERROR" ));
514516 }
515517
@@ -612,8 +614,8 @@ dblink_fetch(PG_FUNCTION_ARGS)
612614 (PQresultStatus (res ) != PGRES_COMMAND_OK &&
613615 PQresultStatus (res ) != PGRES_TUPLES_OK ))
614616 {
615- dblink_res_error (conn , conname , res ,
616- "could not fetch from cursor" , fail );
617+ dblink_res_error (conn , conname , res , fail ,
618+ "while fetching from cursor \"%s\"" , curname );
617619 return (Datum ) 0 ;
618620 }
619621 else if (PQresultStatus (res ) == PGRES_COMMAND_OK )
@@ -763,8 +765,8 @@ dblink_record_internal(FunctionCallInfo fcinfo, bool is_async)
763765 if (PQresultStatus (res ) != PGRES_COMMAND_OK &&
764766 PQresultStatus (res ) != PGRES_TUPLES_OK )
765767 {
766- dblink_res_error (conn , conname , res ,
767- "could not execute query" , fail );
768+ dblink_res_error (conn , conname , res , fail ,
769+ "while executing query" );
768770 /* if fail isn't set, we'll return an empty query result */
769771 }
770772 else
@@ -1009,8 +1011,8 @@ materializeQueryResult(FunctionCallInfo fcinfo,
10091011 PGresult * res1 = res ;
10101012
10111013 res = NULL ;
1012- dblink_res_error (conn , conname , res1 ,
1013- "could not execute query" , fail );
1014+ dblink_res_error (conn , conname , res1 , fail ,
1015+ "while executing query" );
10141016 /* if fail isn't set, we'll return an empty query result */
10151017 }
10161018 else if (PQresultStatus (res ) == PGRES_COMMAND_OK )
@@ -1438,8 +1440,8 @@ dblink_exec(PG_FUNCTION_ARGS)
14381440 (PQresultStatus (res ) != PGRES_COMMAND_OK &&
14391441 PQresultStatus (res ) != PGRES_TUPLES_OK ))
14401442 {
1441- dblink_res_error (conn , conname , res ,
1442- "could not execute command" , fail );
1443+ dblink_res_error (conn , conname , res , fail ,
1444+ "while executing command" );
14431445
14441446 /*
14451447 * and save a copy of the command status string to return as our
@@ -1980,7 +1982,7 @@ dblink_fdw_validator(PG_FUNCTION_ARGS)
19801982 ereport (ERROR ,
19811983 (errcode (ERRCODE_FDW_OUT_OF_MEMORY ),
19821984 errmsg ("out of memory" ),
1983- errdetail ("could not get libpq's default connection options" )));
1985+ errdetail ("Could not get libpq's default connection options. " )));
19841986 }
19851987
19861988 /* Validate each supplied option. */
@@ -2676,9 +2678,17 @@ dblink_connstr_check(const char *connstr)
26762678 }
26772679}
26782680
2681+ /*
2682+ * Report an error received from the remote server
2683+ *
2684+ * res: the received error result (will be freed)
2685+ * fail: true for ERROR ereport, false for NOTICE
2686+ * fmt and following args: sprintf-style format and values for errcontext;
2687+ * the resulting string should be worded like "while <some action>"
2688+ */
26792689static void
26802690dblink_res_error (PGconn * conn , const char * conname , PGresult * res ,
2681- const char * dblink_context_msg , bool fail )
2691+ bool fail , const char * fmt ,... )
26822692{
26832693 int level ;
26842694 char * pg_diag_sqlstate = PQresultErrorField (res , PG_DIAG_SQLSTATE );
@@ -2691,7 +2701,8 @@ dblink_res_error(PGconn *conn, const char *conname, PGresult *res,
26912701 char * message_detail ;
26922702 char * message_hint ;
26932703 char * message_context ;
2694- const char * dblink_context_conname = "unnamed" ;
2704+ va_list ap ;
2705+ char dblink_context_msg [512 ];
26952706
26962707 if (fail )
26972708 level = ERROR ;
@@ -2720,21 +2731,38 @@ dblink_res_error(PGconn *conn, const char *conname, PGresult *res,
27202731 if (message_primary == NULL )
27212732 message_primary = pchomp (PQerrorMessage (conn ));
27222733
2734+ /*
2735+ * Now that we've copied all the data we need out of the PGresult, it's
2736+ * safe to free it. We must do this to avoid PGresult leakage. We're
2737+ * leaking all the strings too, but those are in palloc'd memory that will
2738+ * get cleaned up eventually.
2739+ */
27232740 if (res )
27242741 PQclear (res );
27252742
2726- if (conname )
2727- dblink_context_conname = conname ;
2743+ /*
2744+ * Format the basic errcontext string. Below, we'll add on something
2745+ * about the connection name. That's a violation of the translatability
2746+ * guidelines about constructing error messages out of parts, but since
2747+ * there's no translation support for dblink, there's no need to worry
2748+ * about that (yet).
2749+ */
2750+ va_start (ap , fmt );
2751+ vsnprintf (dblink_context_msg , sizeof (dblink_context_msg ), fmt , ap );
2752+ va_end (ap );
27282753
27292754 ereport (level ,
27302755 (errcode (sqlstate ),
27312756 message_primary ? errmsg_internal ("%s" , message_primary ) :
27322757 errmsg ("could not obtain message string for remote error" ),
27332758 message_detail ? errdetail_internal ("%s" , message_detail ) : 0 ,
27342759 message_hint ? errhint ("%s" , message_hint ) : 0 ,
2735- message_context ? errcontext ("%s" , message_context ) : 0 ,
2736- errcontext ("Error occurred on dblink connection named \"%s\": %s." ,
2737- dblink_context_conname , dblink_context_msg )));
2760+ message_context ? (errcontext ("%s" , message_context )) : 0 ,
2761+ conname ?
2762+ (errcontext ("%s on dblink connection named \"%s\"" ,
2763+ dblink_context_msg , conname )) :
2764+ (errcontext ("%s on unnamed dblink connection" ,
2765+ dblink_context_msg ))));
27382766}
27392767
27402768/*
@@ -2769,7 +2797,7 @@ get_connect_string(const char *servername)
27692797 ereport (ERROR ,
27702798 (errcode (ERRCODE_FDW_OUT_OF_MEMORY ),
27712799 errmsg ("out of memory" ),
2772- errdetail ("could not get libpq's default connection options" )));
2800+ errdetail ("Could not get libpq's default connection options. " )));
27732801 }
27742802
27752803 /* first gather the server connstr options */
0 commit comments