@@ -101,8 +101,8 @@ static void materializeQueryResult(FunctionCallInfo fcinfo,
101
101
const char * conname ,
102
102
const char * sql ,
103
103
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 );
106
106
static remoteConn * getConnectionByName (const char * name );
107
107
static HTAB * createConnHash (void );
108
108
static remoteConn * createNewConnection (const char * name );
@@ -169,14 +169,6 @@ typedef struct remoteConnHashEnt
169
169
/* initial number of connection hashes */
170
170
#define NUMCONN 16
171
171
172
- static char *
173
- xpstrdup (const char * in )
174
- {
175
- if (in == NULL )
176
- return NULL ;
177
- return pstrdup (in );
178
- }
179
-
180
172
pg_noreturn static void
181
173
dblink_res_internalerror (PGconn * conn , PGresult * res , const char * p2 )
182
174
{
@@ -870,17 +862,14 @@ static void
870
862
materializeResult (FunctionCallInfo fcinfo , PGconn * conn , PGresult * res )
871
863
{
872
864
ReturnSetInfo * rsinfo = (ReturnSetInfo * ) fcinfo -> resultinfo ;
865
+ TupleDesc tupdesc ;
866
+ bool is_sql_cmd ;
867
+ int ntuples ;
868
+ int nfields ;
873
869
874
870
/* prepTuplestoreResult must have been called previously */
875
871
Assert (rsinfo -> returnMode == SFRM_Materialize );
876
872
877
- PG_TRY ();
878
- {
879
- TupleDesc tupdesc ;
880
- bool is_sql_cmd ;
881
- int ntuples ;
882
- int nfields ;
883
-
884
873
if (PQresultStatus (res ) == PGRES_COMMAND_OK )
885
874
{
886
875
is_sql_cmd = true;
@@ -988,13 +977,8 @@ materializeResult(FunctionCallInfo fcinfo, PGconn *conn, PGresult *res)
988
977
/* clean up GUC settings, if we changed any */
989
978
restoreLocalGucs (nestlevel );
990
979
}
991
- }
992
- PG_FINALLY ();
993
- {
994
- /* be sure to release the libpq result */
980
+
995
981
PQclear (res );
996
- }
997
- PG_END_TRY ();
998
982
}
999
983
1000
984
/*
@@ -1013,16 +997,17 @@ materializeQueryResult(FunctionCallInfo fcinfo,
1013
997
bool fail )
1014
998
{
1015
999
ReturnSetInfo * rsinfo = (ReturnSetInfo * ) fcinfo -> resultinfo ;
1016
- PGresult * volatile res = NULL ;
1017
- volatile storeInfo sinfo = {0 };
1018
1000
1019
1001
/* prepTuplestoreResult must have been called previously */
1020
1002
Assert (rsinfo -> returnMode == SFRM_Materialize );
1021
1003
1022
- sinfo .fcinfo = fcinfo ;
1023
-
1004
+ /* Use a PG_TRY block to ensure we pump libpq dry of results */
1024
1005
PG_TRY ();
1025
1006
{
1007
+ storeInfo sinfo = {0 };
1008
+ PGresult * res ;
1009
+
1010
+ sinfo .fcinfo = fcinfo ;
1026
1011
/* Create short-lived memory context for data conversions */
1027
1012
sinfo .tmpcontext = AllocSetContextCreate (CurrentMemoryContext ,
1028
1013
"dblink temporary context" ,
@@ -1035,14 +1020,7 @@ materializeQueryResult(FunctionCallInfo fcinfo,
1035
1020
(PQresultStatus (res ) != PGRES_COMMAND_OK &&
1036
1021
PQresultStatus (res ) != PGRES_TUPLES_OK ))
1037
1022
{
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 ,
1046
1024
"while executing query" );
1047
1025
/* if fail isn't set, we'll return an empty query result */
1048
1026
}
@@ -1081,7 +1059,6 @@ materializeQueryResult(FunctionCallInfo fcinfo,
1081
1059
tuplestore_puttuple (tupstore , tuple );
1082
1060
1083
1061
PQclear (res );
1084
- res = NULL ;
1085
1062
}
1086
1063
else
1087
1064
{
@@ -1090,26 +1067,20 @@ materializeQueryResult(FunctionCallInfo fcinfo,
1090
1067
Assert (rsinfo -> setResult != NULL );
1091
1068
1092
1069
PQclear (res );
1093
- res = NULL ;
1094
1070
}
1095
1071
1096
1072
/* clean up data conversion short-lived memory context */
1097
1073
if (sinfo .tmpcontext != NULL )
1098
1074
MemoryContextDelete (sinfo .tmpcontext );
1099
- sinfo .tmpcontext = NULL ;
1100
1075
1101
1076
PQclear (sinfo .last_res );
1102
- sinfo .last_res = NULL ;
1103
1077
PQclear (sinfo .cur_res );
1104
- sinfo .cur_res = NULL ;
1105
1078
}
1106
1079
PG_CATCH ();
1107
1080
{
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 */
1113
1084
while ((res = libpqsrv_get_result (conn , dblink_we_get_result )) !=
1114
1085
NULL )
1115
1086
PQclear (res );
@@ -1122,7 +1093,7 @@ materializeQueryResult(FunctionCallInfo fcinfo,
1122
1093
* Execute query, and send any result rows to sinfo->tuplestore.
1123
1094
*/
1124
1095
static PGresult *
1125
- storeQueryResult (volatile storeInfo * sinfo , PGconn * conn , const char * sql )
1096
+ storeQueryResult (storeInfo * sinfo , PGconn * conn , const char * sql )
1126
1097
{
1127
1098
bool first = true;
1128
1099
int nestlevel = -1 ;
@@ -1190,7 +1161,7 @@ storeQueryResult(volatile storeInfo *sinfo, PGconn *conn, const char *sql)
1190
1161
* (in this case the PGresult might contain either zero or one row).
1191
1162
*/
1192
1163
static void
1193
- storeRow (volatile storeInfo * sinfo , PGresult * res , bool first )
1164
+ storeRow (storeInfo * sinfo , PGresult * res , bool first )
1194
1165
{
1195
1166
int nfields = PQnfields (res );
1196
1167
HeapTuple tuple ;
@@ -2795,26 +2766,25 @@ dblink_connstr_check(const char *connstr)
2795
2766
/*
2796
2767
* Report an error received from the remote server
2797
2768
*
2798
- * res: the received error result (will be freed)
2769
+ * res: the received error result
2799
2770
* fail: true for ERROR ereport, false for NOTICE
2800
2771
* fmt and following args: sprintf-style format and values for errcontext;
2801
2772
* 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).
2802
2776
*/
2803
2777
static void
2804
2778
dblink_res_error (PGconn * conn , const char * conname , PGresult * res ,
2805
2779
bool fail , const char * fmt ,...)
2806
2780
{
2807
2781
int level ;
2808
2782
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 );
2813
2787
int sqlstate ;
2814
- char * message_primary ;
2815
- char * message_detail ;
2816
- char * message_hint ;
2817
- char * message_context ;
2818
2788
va_list ap ;
2819
2789
char dblink_context_msg [512 ];
2820
2790
@@ -2832,11 +2802,6 @@ dblink_res_error(PGconn *conn, const char *conname, PGresult *res,
2832
2802
else
2833
2803
sqlstate = ERRCODE_CONNECTION_FAILURE ;
2834
2804
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
-
2840
2805
/*
2841
2806
* If we don't get a message from the PGresult, try the PGconn. This is
2842
2807
* needed because for connection-level failures, PQgetResult may just
@@ -2845,14 +2810,6 @@ dblink_res_error(PGconn *conn, const char *conname, PGresult *res,
2845
2810
if (message_primary == NULL )
2846
2811
message_primary = pchomp (PQerrorMessage (conn ));
2847
2812
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
-
2856
2813
/*
2857
2814
* Format the basic errcontext string. Below, we'll add on something
2858
2815
* 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,
2877
2834
dblink_context_msg , conname )) :
2878
2835
(errcontext ("%s on unnamed dblink connection" ,
2879
2836
dblink_context_msg ))));
2837
+ PQclear (res );
2880
2838
}
2881
2839
2882
2840
/*
0 commit comments