8
8
* Darko Prenosil <[email protected] >
9
9
* Shridhar Daithankar <[email protected] >
10
10
*
11
- * $PostgreSQL: pgsql/contrib/dblink/dblink.c,v 1.75 2008/09/22 13:55:13 tgl Exp $
11
+ * $PostgreSQL: pgsql/contrib/dblink/dblink.c,v 1.76 2008/11/30 23:23:52 tgl Exp $
12
12
* Copyright (c) 2001-2008, PostgreSQL Global Development Group
13
13
* ALL RIGHTS RESERVED;
14
14
*
@@ -213,7 +213,6 @@ dblink_connect(PG_FUNCTION_ARGS)
213
213
char * connstr = NULL ;
214
214
char * connname = NULL ;
215
215
char * msg ;
216
- MemoryContext oldcontext ;
217
216
PGconn * conn = NULL ;
218
217
remoteConn * rconn = NULL ;
219
218
@@ -227,17 +226,14 @@ dblink_connect(PG_FUNCTION_ARGS)
227
226
else if (PG_NARGS () == 1 )
228
227
connstr = text_to_cstring (PG_GETARG_TEXT_PP (0 ));
229
228
230
- oldcontext = MemoryContextSwitchTo (TopMemoryContext );
231
-
232
229
if (connname )
233
- rconn = (remoteConn * ) palloc (sizeof (remoteConn ));
230
+ rconn = (remoteConn * ) MemoryContextAlloc (TopMemoryContext ,
231
+ sizeof (remoteConn ));
234
232
235
233
/* check password in connection string if not superuser */
236
234
dblink_connstr_check (connstr );
237
235
conn = PQconnectdb (connstr );
238
236
239
- MemoryContextSwitchTo (oldcontext );
240
-
241
237
if (PQstatus (conn ) == CONNECTION_BAD )
242
238
{
243
239
msg = pstrdup (PQerrorMessage (conn ));
@@ -562,10 +558,10 @@ dblink_fetch(PG_FUNCTION_ARGS)
562
558
funcctx = SRF_FIRSTCALL_INIT ();
563
559
564
560
/*
565
- * switch to memory context appropriate for multiple function calls
561
+ * Try to execute the query. Note that since libpq uses malloc,
562
+ * the PGresult will be long-lived even though we are still in
563
+ * a short-lived memory context.
566
564
*/
567
- oldcontext = MemoryContextSwitchTo (funcctx -> multi_call_memory_ctx );
568
-
569
565
res = PQexec (conn , buf .data );
570
566
if (!res ||
571
567
(PQresultStatus (res ) != PGRES_COMMAND_OK &&
@@ -607,24 +603,32 @@ dblink_fetch(PG_FUNCTION_ARGS)
607
603
break ;
608
604
}
609
605
610
- /* make sure we have a persistent copy of the tupdesc */
611
- tupdesc = CreateTupleDescCopy (tupdesc );
612
-
613
606
/* check result and tuple descriptor have the same number of columns */
614
607
if (PQnfields (res ) != tupdesc -> natts )
615
608
ereport (ERROR ,
616
609
(errcode (ERRCODE_DATATYPE_MISMATCH ),
617
610
errmsg ("remote query result rowtype does not match "
618
611
"the specified FROM clause rowtype" )));
619
612
620
- /* fast track when no results */
613
+ /*
614
+ * fast track when no results. We could exit earlier, but then
615
+ * we'd not report error if the result tuple type is wrong.
616
+ */
621
617
if (funcctx -> max_calls < 1 )
622
618
{
623
- if (res )
624
- PQclear (res );
619
+ PQclear (res );
625
620
SRF_RETURN_DONE (funcctx );
626
621
}
627
622
623
+ /*
624
+ * switch to memory context appropriate for multiple function calls,
625
+ * so we can make long-lived copy of tupdesc etc
626
+ */
627
+ oldcontext = MemoryContextSwitchTo (funcctx -> multi_call_memory_ctx );
628
+
629
+ /* make sure we have a persistent copy of the tupdesc */
630
+ tupdesc = CreateTupleDescCopy (tupdesc );
631
+
628
632
/* store needed metadata for subsequent calls */
629
633
attinmeta = TupleDescGetAttInMetadata (tupdesc );
630
634
funcctx -> attinmeta = attinmeta ;
@@ -815,7 +819,10 @@ dblink_record_internal(FunctionCallInfo fcinfo, bool is_async, bool do_get)
815
819
res = PQgetResult (conn );
816
820
/* NULL means we're all done with the async results */
817
821
if (!res )
822
+ {
823
+ MemoryContextSwitchTo (oldcontext );
818
824
SRF_RETURN_DONE (funcctx );
825
+ }
819
826
}
820
827
821
828
if (!res ||
@@ -825,6 +832,7 @@ dblink_record_internal(FunctionCallInfo fcinfo, bool is_async, bool do_get)
825
832
dblink_res_error (conname , res , "could not execute query" , fail );
826
833
if (freeconn )
827
834
PQfinish (conn );
835
+ MemoryContextSwitchTo (oldcontext );
828
836
SRF_RETURN_DONE (funcctx );
829
837
}
830
838
@@ -894,6 +902,7 @@ dblink_record_internal(FunctionCallInfo fcinfo, bool is_async, bool do_get)
894
902
{
895
903
if (res )
896
904
PQclear (res );
905
+ MemoryContextSwitchTo (oldcontext );
897
906
SRF_RETURN_DONE (funcctx );
898
907
}
899
908
@@ -1261,8 +1270,11 @@ dblink_get_pkey(PG_FUNCTION_ARGS)
1261
1270
funcctx -> user_fctx = results ;
1262
1271
}
1263
1272
else
1273
+ {
1264
1274
/* fast track when no results */
1275
+ MemoryContextSwitchTo (oldcontext );
1265
1276
SRF_RETURN_DONE (funcctx );
1277
+ }
1266
1278
1267
1279
MemoryContextSwitchTo (oldcontext );
1268
1280
}
0 commit comments