*
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.96 2005/04/06 16:34:04 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.97 2005/04/10 18:04:20 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 static void init_sql_fcache(FmgrInfo *finfo);
 static void postquel_start(execution_state *es, SQLFunctionCachePtr fcache);
 static TupleTableSlot *postquel_getnext(execution_state *es);
-static void postquel_end(execution_state *es, SQLFunctionCachePtr fcache);
+static void postquel_end(execution_state *es);
 static void postquel_sub_params(SQLFunctionCachePtr fcache,
                    FunctionCallInfo fcinfo);
 static Datum postquel_execute(execution_state *es,
                 FunctionCallInfo fcinfo,
-                SQLFunctionCachePtr fcache);
+                SQLFunctionCachePtr fcache,
+                MemoryContext resultcontext);
 static void sql_exec_error_callback(void *arg);
 static void ShutdownSQLFunction(Datum arg);
 
 }
 
 static void
-postquel_end(execution_state *es, SQLFunctionCachePtr fcache)
+postquel_end(execution_state *es)
 {
    Snapshot    saveActiveSnapshot;
 
 static Datum
 postquel_execute(execution_state *es,
                 FunctionCallInfo fcinfo,
-                SQLFunctionCachePtr fcache)
+                SQLFunctionCachePtr fcache,
+                MemoryContext resultcontext)
 {
    TupleTableSlot *slot;
    Datum       value;
+   MemoryContext oldcontext;
 
    if (es->status == F_EXEC_START)
        postquel_start(es, fcache);
         * We fall out here for all cases except where we have obtained
         * a row from a function's final SELECT.
         */
-       postquel_end(es, fcache);
+       postquel_end(es);
        fcinfo->isnull = true;
        return (Datum) NULL;
    }
    Assert(LAST_POSTQUEL_COMMAND(es));
 
    /*
-    * Set up to return the function value.
+    * Set up to return the function value.  For pass-by-reference
+    * datatypes, be sure to allocate the result in resultcontext,
+    * not the current memory context (which has query lifespan).
     */
+   oldcontext = MemoryContextSwitchTo(resultcontext);
+
    if (fcache->returnsTuple)
    {
        /*
         * reasons why we do this:
         *
         * 1. To copy the tuple out of the child execution context and
-        * into our own context.
+        * into the desired result context.
         *
         * 2. To remove any junk attributes present in the raw subselect
         * result.  (This is probably not absolutely necessary, but it
    {
        /*
         * Returning a scalar, which we have to extract from the first
-        * column of the SELECT result, and then copy into current
-        * execution context if needed.
+        * column of the SELECT result, and then copy into result
+        * context if needed.
         */
        value = slot_getattr(slot, 1, &(fcinfo->isnull));
 
            value = datumCopy(value, fcache->typbyval, fcache->typlen);
    }
 
+   MemoryContextSwitchTo(oldcontext);
+
    /*
     * If this is a single valued function we have to end the function
     * execution now.
     */
    if (!fcinfo->flinfo->fn_retset)
-       postquel_end(es, fcache);
+       postquel_end(es);
 
    return value;
 }
     */
    while (es)
    {
-       result = postquel_execute(es, fcinfo, fcache);
+       result = postquel_execute(es, fcinfo, fcache, oldcontext);
        if (es->status != F_EXEC_DONE)
            break;
        es = es->next;
    {
        /* Shut down anything still running */
        if (es->status == F_EXEC_RUN)
-           postquel_end(es, fcache);
+           postquel_end(es);
        /* Reset states to START in case we're called again */
        es->status = F_EXEC_START;
        es = es->next;