@@ -101,8 +101,8 @@ static void materializeQueryResult(FunctionCallInfo fcinfo,
101101 const char * conname ,
102102 const char * sql ,
103103 bool fail );
104- static PGresult * storeQueryResult (volatile storeInfo * sinfo , PGconn * conn , const char * sql );
105- static void storeRow (volatile storeInfo * sinfo , PGresult * res , bool first );
104+ static PGresult * storeQueryResult (storeInfo * sinfo , PGconn * conn , const char * sql );
105+ static void storeRow (storeInfo * sinfo , PGresult * res , bool first );
106106static remoteConn * getConnectionByName (const char * name );
107107static HTAB * createConnHash (void );
108108static remoteConn * createNewConnection (const char * name );
@@ -169,14 +169,6 @@ typedef struct remoteConnHashEnt
169169/* initial number of connection hashes */
170170#define NUMCONN 16
171171
172- static char *
173- xpstrdup (const char * in )
174- {
175- if (in == NULL )
176- return NULL ;
177- return pstrdup (in );
178- }
179-
180172pg_noreturn static void
181173dblink_res_internalerror (PGconn * conn , PGresult * res , const char * p2 )
182174{
@@ -870,17 +862,14 @@ static void
870862materializeResult (FunctionCallInfo fcinfo , PGconn * conn , PGresult * res )
871863{
872864 ReturnSetInfo * rsinfo = (ReturnSetInfo * ) fcinfo -> resultinfo ;
865+ TupleDesc tupdesc ;
866+ bool is_sql_cmd ;
867+ int ntuples ;
868+ int nfields ;
873869
874870 /* prepTuplestoreResult must have been called previously */
875871 Assert (rsinfo -> returnMode == SFRM_Materialize );
876872
877- PG_TRY ();
878- {
879- TupleDesc tupdesc ;
880- bool is_sql_cmd ;
881- int ntuples ;
882- int nfields ;
883-
884873 if (PQresultStatus (res ) == PGRES_COMMAND_OK )
885874 {
886875 is_sql_cmd = true;
@@ -988,13 +977,8 @@ materializeResult(FunctionCallInfo fcinfo, PGconn *conn, PGresult *res)
988977 /* clean up GUC settings, if we changed any */
989978 restoreLocalGucs (nestlevel );
990979 }
991- }
992- PG_FINALLY ();
993- {
994- /* be sure to release the libpq result */
980+
995981 PQclear (res );
996- }
997- PG_END_TRY ();
998982}
999983
1000984/*
@@ -1013,16 +997,17 @@ materializeQueryResult(FunctionCallInfo fcinfo,
1013997 bool fail )
1014998{
1015999 ReturnSetInfo * rsinfo = (ReturnSetInfo * ) fcinfo -> resultinfo ;
1016- PGresult * volatile res = NULL ;
1017- volatile storeInfo sinfo = {0 };
10181000
10191001 /* prepTuplestoreResult must have been called previously */
10201002 Assert (rsinfo -> returnMode == SFRM_Materialize );
10211003
1022- sinfo .fcinfo = fcinfo ;
1023-
1004+ /* Use a PG_TRY block to ensure we pump libpq dry of results */
10241005 PG_TRY ();
10251006 {
1007+ storeInfo sinfo = {0 };
1008+ PGresult * res ;
1009+
1010+ sinfo .fcinfo = fcinfo ;
10261011 /* Create short-lived memory context for data conversions */
10271012 sinfo .tmpcontext = AllocSetContextCreate (CurrentMemoryContext ,
10281013 "dblink temporary context" ,
@@ -1035,14 +1020,7 @@ materializeQueryResult(FunctionCallInfo fcinfo,
10351020 (PQresultStatus (res ) != PGRES_COMMAND_OK &&
10361021 PQresultStatus (res ) != PGRES_TUPLES_OK ))
10371022 {
1038- /*
1039- * dblink_res_error will clear the passed PGresult, so we need
1040- * this ugly dance to avoid doing so twice during error exit
1041- */
1042- PGresult * res1 = res ;
1043-
1044- res = NULL ;
1045- dblink_res_error (conn , conname , res1 , fail ,
1023+ dblink_res_error (conn , conname , res , fail ,
10461024 "while executing query" );
10471025 /* if fail isn't set, we'll return an empty query result */
10481026 }
@@ -1081,7 +1059,6 @@ materializeQueryResult(FunctionCallInfo fcinfo,
10811059 tuplestore_puttuple (tupstore , tuple );
10821060
10831061 PQclear (res );
1084- res = NULL ;
10851062 }
10861063 else
10871064 {
@@ -1090,26 +1067,20 @@ materializeQueryResult(FunctionCallInfo fcinfo,
10901067 Assert (rsinfo -> setResult != NULL );
10911068
10921069 PQclear (res );
1093- res = NULL ;
10941070 }
10951071
10961072 /* clean up data conversion short-lived memory context */
10971073 if (sinfo .tmpcontext != NULL )
10981074 MemoryContextDelete (sinfo .tmpcontext );
1099- sinfo .tmpcontext = NULL ;
11001075
11011076 PQclear (sinfo .last_res );
1102- sinfo .last_res = NULL ;
11031077 PQclear (sinfo .cur_res );
1104- sinfo .cur_res = NULL ;
11051078 }
11061079 PG_CATCH ();
11071080 {
1108- /* be sure to release any libpq result we collected */
1109- PQclear (res );
1110- PQclear (sinfo .last_res );
1111- PQclear (sinfo .cur_res );
1112- /* and clear out any pending data in libpq */
1081+ PGresult * res ;
1082+
1083+ /* be sure to clear out any pending data in libpq */
11131084 while ((res = libpqsrv_get_result (conn , dblink_we_get_result )) !=
11141085 NULL )
11151086 PQclear (res );
@@ -1122,7 +1093,7 @@ materializeQueryResult(FunctionCallInfo fcinfo,
11221093 * Execute query, and send any result rows to sinfo->tuplestore.
11231094 */
11241095static PGresult *
1125- storeQueryResult (volatile storeInfo * sinfo , PGconn * conn , const char * sql )
1096+ storeQueryResult (storeInfo * sinfo , PGconn * conn , const char * sql )
11261097{
11271098 bool first = true;
11281099 int nestlevel = -1 ;
@@ -1190,7 +1161,7 @@ storeQueryResult(volatile storeInfo *sinfo, PGconn *conn, const char *sql)
11901161 * (in this case the PGresult might contain either zero or one row).
11911162 */
11921163static void
1193- storeRow (volatile storeInfo * sinfo , PGresult * res , bool first )
1164+ storeRow (storeInfo * sinfo , PGresult * res , bool first )
11941165{
11951166 int nfields = PQnfields (res );
11961167 HeapTuple tuple ;
@@ -2795,26 +2766,25 @@ dblink_connstr_check(const char *connstr)
27952766/*
27962767 * Report an error received from the remote server
27972768 *
2798- * res: the received error result (will be freed)
2769+ * res: the received error result
27992770 * fail: true for ERROR ereport, false for NOTICE
28002771 * fmt and following args: sprintf-style format and values for errcontext;
28012772 * the resulting string should be worded like "while <some action>"
2773+ *
2774+ * If "res" is not NULL, it'll be PQclear'ed here (unless we throw error,
2775+ * in which case memory context cleanup will clear it eventually).
28022776 */
28032777static void
28042778dblink_res_error (PGconn * conn , const char * conname , PGresult * res ,
28052779 bool fail , const char * fmt ,...)
28062780{
28072781 int level ;
28082782 char * pg_diag_sqlstate = PQresultErrorField (res , PG_DIAG_SQLSTATE );
2809- char * pg_diag_message_primary = PQresultErrorField (res , PG_DIAG_MESSAGE_PRIMARY );
2810- char * pg_diag_message_detail = PQresultErrorField (res , PG_DIAG_MESSAGE_DETAIL );
2811- char * pg_diag_message_hint = PQresultErrorField (res , PG_DIAG_MESSAGE_HINT );
2812- char * pg_diag_context = PQresultErrorField (res , PG_DIAG_CONTEXT );
2783+ char * message_primary = PQresultErrorField (res , PG_DIAG_MESSAGE_PRIMARY );
2784+ char * message_detail = PQresultErrorField (res , PG_DIAG_MESSAGE_DETAIL );
2785+ char * message_hint = PQresultErrorField (res , PG_DIAG_MESSAGE_HINT );
2786+ char * message_context = PQresultErrorField (res , PG_DIAG_CONTEXT );
28132787 int sqlstate ;
2814- char * message_primary ;
2815- char * message_detail ;
2816- char * message_hint ;
2817- char * message_context ;
28182788 va_list ap ;
28192789 char dblink_context_msg [512 ];
28202790
@@ -2832,11 +2802,6 @@ dblink_res_error(PGconn *conn, const char *conname, PGresult *res,
28322802 else
28332803 sqlstate = ERRCODE_CONNECTION_FAILURE ;
28342804
2835- message_primary = xpstrdup (pg_diag_message_primary );
2836- message_detail = xpstrdup (pg_diag_message_detail );
2837- message_hint = xpstrdup (pg_diag_message_hint );
2838- message_context = xpstrdup (pg_diag_context );
2839-
28402805 /*
28412806 * If we don't get a message from the PGresult, try the PGconn. This is
28422807 * needed because for connection-level failures, PQgetResult may just
@@ -2845,14 +2810,6 @@ dblink_res_error(PGconn *conn, const char *conname, PGresult *res,
28452810 if (message_primary == NULL )
28462811 message_primary = pchomp (PQerrorMessage (conn ));
28472812
2848- /*
2849- * Now that we've copied all the data we need out of the PGresult, it's
2850- * safe to free it. We must do this to avoid PGresult leakage. We're
2851- * leaking all the strings too, but those are in palloc'd memory that will
2852- * get cleaned up eventually.
2853- */
2854- PQclear (res );
2855-
28562813 /*
28572814 * Format the basic errcontext string. Below, we'll add on something
28582815 * about the connection name. That's a violation of the translatability
@@ -2877,6 +2834,7 @@ dblink_res_error(PGconn *conn, const char *conname, PGresult *res,
28772834 dblink_context_msg , conname )) :
28782835 (errcontext ("%s on unnamed dblink connection" ,
28792836 dblink_context_msg ))));
2837+ PQclear (res );
28802838}
28812839
28822840/*
0 commit comments