88 *
99 *
1010 * IDENTIFICATION
11- * $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.96 2005/04/06 16:34:04 tgl Exp $
11+ * $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.97 2005/04/10 18:04:20 tgl Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
@@ -86,12 +86,13 @@ static execution_state *init_execution_state(List *queryTree_list,
8686static void init_sql_fcache (FmgrInfo * finfo );
8787static void postquel_start (execution_state * es ,SQLFunctionCachePtr fcache );
8888static TupleTableSlot * postquel_getnext (execution_state * es );
89- static void postquel_end (execution_state * es , SQLFunctionCachePtr fcache );
89+ static void postquel_end (execution_state * es );
9090static void postquel_sub_params (SQLFunctionCachePtr fcache ,
9191FunctionCallInfo fcinfo );
9292static Datum postquel_execute (execution_state * es ,
9393FunctionCallInfo fcinfo ,
94- SQLFunctionCachePtr fcache );
94+ SQLFunctionCachePtr fcache ,
95+ MemoryContext resultcontext );
9596static void sql_exec_error_callback (void * arg );
9697static void ShutdownSQLFunction (Datum arg );
9798
@@ -384,7 +385,7 @@ postquel_getnext(execution_state *es)
384385}
385386
386387static void
387- postquel_end (execution_state * es , SQLFunctionCachePtr fcache )
388+ postquel_end (execution_state * es )
388389{
389390Snapshot saveActiveSnapshot ;
390391
@@ -454,10 +455,12 @@ postquel_sub_params(SQLFunctionCachePtr fcache,
454455static Datum
455456postquel_execute (execution_state * es ,
456457FunctionCallInfo fcinfo ,
457- SQLFunctionCachePtr fcache )
458+ SQLFunctionCachePtr fcache ,
459+ MemoryContext resultcontext )
458460{
459461TupleTableSlot * slot ;
460462Datum value ;
463+ MemoryContext oldcontext ;
461464
462465if (es -> status == F_EXEC_START )
463466postquel_start (es ,fcache );
@@ -470,7 +473,7 @@ postquel_execute(execution_state *es,
470473 * We fall out here for all cases except where we have obtained
471474 * a row from a function's final SELECT.
472475 */
473- postquel_end (es , fcache );
476+ postquel_end (es );
474477fcinfo -> isnull = true;
475478return (Datum )NULL ;
476479}
@@ -482,8 +485,12 @@ postquel_execute(execution_state *es,
482485Assert (LAST_POSTQUEL_COMMAND (es ));
483486
484487/*
485- * Set up to return the function value.
488+ * Set up to return the function value. For pass-by-reference
489+ * datatypes, be sure to allocate the result in resultcontext,
490+ * not the current memory context (which has query lifespan).
486491 */
492+ oldcontext = MemoryContextSwitchTo (resultcontext );
493+
487494if (fcache -> returnsTuple )
488495{
489496/*
@@ -492,7 +499,7 @@ postquel_execute(execution_state *es,
492499 * reasons why we do this:
493500 *
494501 * 1. To copy the tuple out of the child execution context and
495- * intoour own context.
502+ * intothe desired result context.
496503 *
497504 * 2. To remove any junk attributes present in the raw subselect
498505 * result. (This is probably not absolutely necessary, but it
@@ -553,21 +560,23 @@ postquel_execute(execution_state *es,
553560{
554561/*
555562 * Returning a scalar, which we have to extract from the first
556- * column of the SELECT result, and then copy intocurrent
557- *execution context if needed.
563+ * column of the SELECT result, and then copy intoresult
564+ * context if needed.
558565 */
559566value = slot_getattr (slot ,1 ,& (fcinfo -> isnull ));
560567
561568if (!fcinfo -> isnull )
562569value = datumCopy (value ,fcache -> typbyval ,fcache -> typlen );
563570}
564571
572+ MemoryContextSwitchTo (oldcontext );
573+
565574/*
566575 * If this is a single valued function we have to end the function
567576 * execution now.
568577 */
569578if (!fcinfo -> flinfo -> fn_retset )
570- postquel_end (es , fcache );
579+ postquel_end (es );
571580
572581return value ;
573582}
@@ -627,7 +636,7 @@ fmgr_sql(PG_FUNCTION_ARGS)
627636 */
628637while (es )
629638{
630- result = postquel_execute (es ,fcinfo ,fcache );
639+ result = postquel_execute (es ,fcinfo ,fcache , oldcontext );
631640if (es -> status != F_EXEC_DONE )
632641break ;
633642es = es -> next ;
@@ -824,7 +833,7 @@ ShutdownSQLFunction(Datum arg)
824833{
825834/* Shut down anything still running */
826835if (es -> status == F_EXEC_RUN )
827- postquel_end (es , fcache );
836+ postquel_end (es );
828837/* Reset states to START in case we're called again */
829838es -> status = F_EXEC_START ;
830839es = es -> next ;