88 * Darko Prenosil <Darko.Prenosil@finteh.hr>
99 * Shridhar Daithankar <shridhar_daithankar@persistent.co.in>
1010 *
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 $
1212 * Copyright (c) 2001-2008, PostgreSQL Global Development Group
1313 * ALL RIGHTS RESERVED;
1414 *
@@ -213,7 +213,6 @@ dblink_connect(PG_FUNCTION_ARGS)
213213char * connstr = NULL ;
214214char * connname = NULL ;
215215char * msg ;
216- MemoryContext oldcontext ;
217216PGconn * conn = NULL ;
218217remoteConn * rconn = NULL ;
219218
@@ -227,17 +226,14 @@ dblink_connect(PG_FUNCTION_ARGS)
227226else if (PG_NARGS ()== 1 )
228227connstr = text_to_cstring (PG_GETARG_TEXT_PP (0 ));
229228
230- oldcontext = MemoryContextSwitchTo (TopMemoryContext );
231-
232229if (connname )
233- rconn = (remoteConn * )palloc (sizeof (remoteConn ));
230+ rconn = (remoteConn * )MemoryContextAlloc (TopMemoryContext ,
231+ sizeof (remoteConn ));
234232
235233/* check password in connection string if not superuser */
236234dblink_connstr_check (connstr );
237235conn = PQconnectdb (connstr );
238236
239- MemoryContextSwitchTo (oldcontext );
240-
241237if (PQstatus (conn )== CONNECTION_BAD )
242238{
243239msg = pstrdup (PQerrorMessage (conn ));
@@ -562,10 +558,10 @@ dblink_fetch(PG_FUNCTION_ARGS)
562558funcctx = SRF_FIRSTCALL_INIT ();
563559
564560/*
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.
566564 */
567- oldcontext = MemoryContextSwitchTo (funcctx -> multi_call_memory_ctx );
568-
569565res = PQexec (conn ,buf .data );
570566if (!res ||
571567(PQresultStatus (res )!= PGRES_COMMAND_OK &&
@@ -607,24 +603,32 @@ dblink_fetch(PG_FUNCTION_ARGS)
607603break ;
608604}
609605
610- /* make sure we have a persistent copy of the tupdesc */
611- tupdesc = CreateTupleDescCopy (tupdesc );
612-
613606/* check result and tuple descriptor have the same number of columns */
614607if (PQnfields (res )!= tupdesc -> natts )
615608ereport (ERROR ,
616609(errcode (ERRCODE_DATATYPE_MISMATCH ),
617610errmsg ("remote query result rowtype does not match "
618611"the specified FROM clause rowtype" )));
619612
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+ */
621617if (funcctx -> max_calls < 1 )
622618{
623- if (res )
624- PQclear (res );
619+ PQclear (res );
625620SRF_RETURN_DONE (funcctx );
626621}
627622
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+
628632/* store needed metadata for subsequent calls */
629633attinmeta = TupleDescGetAttInMetadata (tupdesc );
630634funcctx -> attinmeta = attinmeta ;
@@ -815,7 +819,10 @@ dblink_record_internal(FunctionCallInfo fcinfo, bool is_async, bool do_get)
815819res = PQgetResult (conn );
816820/* NULL means we're all done with the async results */
817821if (!res )
822+ {
823+ MemoryContextSwitchTo (oldcontext );
818824SRF_RETURN_DONE (funcctx );
825+ }
819826}
820827
821828if (!res ||
@@ -825,6 +832,7 @@ dblink_record_internal(FunctionCallInfo fcinfo, bool is_async, bool do_get)
825832dblink_res_error (conname ,res ,"could not execute query" ,fail );
826833if (freeconn )
827834PQfinish (conn );
835+ MemoryContextSwitchTo (oldcontext );
828836SRF_RETURN_DONE (funcctx );
829837}
830838
@@ -894,6 +902,7 @@ dblink_record_internal(FunctionCallInfo fcinfo, bool is_async, bool do_get)
894902{
895903if (res )
896904PQclear (res );
905+ MemoryContextSwitchTo (oldcontext );
897906SRF_RETURN_DONE (funcctx );
898907}
899908
@@ -1261,8 +1270,11 @@ dblink_get_pkey(PG_FUNCTION_ARGS)
12611270funcctx -> user_fctx = results ;
12621271}
12631272else
1273+ {
12641274/* fast track when no results */
1275+ MemoryContextSwitchTo (oldcontext );
12651276SRF_RETURN_DONE (funcctx );
1277+ }
12661278
12671279MemoryContextSwitchTo (oldcontext );
12681280}