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)
213213 char * connstr = NULL ;
214214 char * connname = NULL ;
215215 char * msg ;
216- MemoryContext oldcontext ;
217216 PGconn * conn = NULL ;
218217 remoteConn * rconn = NULL ;
219218
@@ -227,17 +226,14 @@ dblink_connect(PG_FUNCTION_ARGS)
227226 else if (PG_NARGS () == 1 )
228227 connstr = text_to_cstring (PG_GETARG_TEXT_PP (0 ));
229228
230- oldcontext = MemoryContextSwitchTo (TopMemoryContext );
231-
232229 if (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 */
236234 dblink_connstr_check (connstr );
237235 conn = PQconnectdb (connstr );
238236
239- MemoryContextSwitchTo (oldcontext );
240-
241237 if (PQstatus (conn ) == CONNECTION_BAD )
242238 {
243239 msg = pstrdup (PQerrorMessage (conn ));
@@ -562,10 +558,10 @@ dblink_fetch(PG_FUNCTION_ARGS)
562558 funcctx = 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-
569565 res = PQexec (conn , buf .data );
570566 if (!res ||
571567 (PQresultStatus (res ) != PGRES_COMMAND_OK &&
@@ -607,24 +603,32 @@ dblink_fetch(PG_FUNCTION_ARGS)
607603 break ;
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 */
614607 if (PQnfields (res ) != tupdesc -> natts )
615608 ereport (ERROR ,
616609 (errcode (ERRCODE_DATATYPE_MISMATCH ),
617610 errmsg ("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+ */
621617 if (funcctx -> max_calls < 1 )
622618 {
623- if (res )
624- PQclear (res );
619+ PQclear (res );
625620 SRF_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 */
629633 attinmeta = TupleDescGetAttInMetadata (tupdesc );
630634 funcctx -> attinmeta = attinmeta ;
@@ -815,7 +819,10 @@ dblink_record_internal(FunctionCallInfo fcinfo, bool is_async, bool do_get)
815819 res = PQgetResult (conn );
816820 /* NULL means we're all done with the async results */
817821 if (!res )
822+ {
823+ MemoryContextSwitchTo (oldcontext );
818824 SRF_RETURN_DONE (funcctx );
825+ }
819826 }
820827
821828 if (!res ||
@@ -825,6 +832,7 @@ dblink_record_internal(FunctionCallInfo fcinfo, bool is_async, bool do_get)
825832 dblink_res_error (conname , res , "could not execute query" , fail );
826833 if (freeconn )
827834 PQfinish (conn );
835+ MemoryContextSwitchTo (oldcontext );
828836 SRF_RETURN_DONE (funcctx );
829837 }
830838
@@ -894,6 +902,7 @@ dblink_record_internal(FunctionCallInfo fcinfo, bool is_async, bool do_get)
894902 {
895903 if (res )
896904 PQclear (res );
905+ MemoryContextSwitchTo (oldcontext );
897906 SRF_RETURN_DONE (funcctx );
898907 }
899908
@@ -1261,8 +1270,11 @@ dblink_get_pkey(PG_FUNCTION_ARGS)
12611270 funcctx -> user_fctx = results ;
12621271 }
12631272 else
1273+ {
12641274 /* fast track when no results */
1275+ MemoryContextSwitchTo (oldcontext );
12651276 SRF_RETURN_DONE (funcctx );
1277+ }
12661278
12671279 MemoryContextSwitchTo (oldcontext );
12681280 }
0 commit comments