diff --git a/contrib/dblink/dblink.c b/contrib/dblink/dblink.c
index 61585644f92de1a96e0b6328618622d7411cf745..d3875529fd01185939696f2534af83e6bea66e77 100644
--- a/contrib/dblink/dblink.c
+++ b/contrib/dblink/dblink.c
@@ -8,7 +8,7 @@
  * Darko Prenosil <Darko.Prenosil@finteh.hr>
  * Shridhar Daithankar <shridhar_daithankar@persistent.co.in>
  *
- * $PostgreSQL: pgsql/contrib/dblink/dblink.c,v 1.84 2009/09/12 23:20:52 joe Exp $
+ * $PostgreSQL: pgsql/contrib/dblink/dblink.c,v 1.85 2009/12/29 17:40:59 heikki Exp $
  * Copyright (c) 2001-2009, PostgreSQL Global Development Group
  * ALL RIGHTS RESERVED;
  *
@@ -1703,10 +1703,7 @@ dblink_get_notify(PG_FUNCTION_ARGS)
 		else
 			nulls[2] = true;
 
-		/* switch to appropriate context while storing the tuple */
-		MemoryContextSwitchTo(per_query_ctx);
 		tuplestore_putvalues(tupstore, tupdesc, values, nulls);
-		MemoryContextSwitchTo(oldcontext);
 
 		PQfreemem(notify);
 		PQconsumeInput(conn);
diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c
index e2b3afa4b6f36419013a892b58607d0d329a0bf6..691254302307cd6dc452994435937026680b5858 100644
--- a/contrib/pg_stat_statements/pg_stat_statements.c
+++ b/contrib/pg_stat_statements/pg_stat_statements.c
@@ -14,7 +14,7 @@
  * Copyright (c) 2008-2009, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/contrib/pg_stat_statements/pg_stat_statements.c,v 1.9 2009/12/15 20:04:49 tgl Exp $
+ *	  $PostgreSQL: pgsql/contrib/pg_stat_statements/pg_stat_statements.c,v 1.10 2009/12/29 17:40:59 heikki Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -783,6 +783,8 @@ pg_stat_statements(PG_FUNCTION_ARGS)
 	rsinfo->setResult = tupstore;
 	rsinfo->setDesc = tupdesc;
 
+	MemoryContextSwitchTo(oldcontext);
+
 	LWLockAcquire(pgss->lock, LW_SHARED);
 
 	hash_seq_init(&hash_seq, pgss_hash);
@@ -793,9 +795,6 @@ pg_stat_statements(PG_FUNCTION_ARGS)
 		int			i = 0;
 		Counters	tmp;
 
-		/* generate junk in short-term context */
-		MemoryContextSwitchTo(oldcontext);
-
 		memset(values, 0, sizeof(values));
 		memset(nulls, 0, sizeof(nulls));
 
@@ -833,8 +832,6 @@ pg_stat_statements(PG_FUNCTION_ARGS)
 
 		Assert(i == PG_STAT_STATEMENTS_COLS);
 
-		/* switch to appropriate context while storing the tuple */
-		MemoryContextSwitchTo(per_query_ctx);
 		tuplestore_putvalues(tupstore, tupdesc, values, nulls);
 	}
 
@@ -843,8 +840,6 @@ pg_stat_statements(PG_FUNCTION_ARGS)
 	/* clean up and return the tuplestore */
 	tuplestore_donestoring(tupstore);
 
-	MemoryContextSwitchTo(oldcontext);
-
 	return (Datum) 0;
 }
 
diff --git a/contrib/tablefunc/tablefunc.c b/contrib/tablefunc/tablefunc.c
index 48512bd9349d8688b945e36ffe1cf4ffb6baf223..272b1b437774ca1df90fb6f23af7d6e10b8f8985 100644
--- a/contrib/tablefunc/tablefunc.c
+++ b/contrib/tablefunc/tablefunc.c
@@ -1,5 +1,5 @@
 /*
- * $PostgreSQL: pgsql/contrib/tablefunc/tablefunc.c,v 1.60 2009/06/11 14:48:52 momjian Exp $
+ * $PostgreSQL: pgsql/contrib/tablefunc/tablefunc.c,v 1.61 2009/12/29 17:40:59 heikki Exp $
  *
  *
  * tablefunc
@@ -567,14 +567,9 @@ crosstab(PG_FUNCTION_ARGS)
 		{
 			HeapTuple	tuple;
 
-			/* build the tuple */
+			/* build the tuple and store it */
 			tuple = BuildTupleFromCStrings(attinmeta, values);
-
-			/* switch to appropriate context while storing the tuple */
-			oldcontext = MemoryContextSwitchTo(per_query_ctx);
 			tuplestore_puttuple(tupstore, tuple);
-			MemoryContextSwitchTo(oldcontext);
-
 			heap_freetuple(tuple);
 		}
 
@@ -807,7 +802,6 @@ get_crosstab_tuplestore(char *sql,
 	HeapTuple	tuple;
 	int			ret;
 	int			proc;
-	MemoryContext SPIcontext;
 
 	/* initialize our tuplestore (while still in query context!) */
 	tupstore = tuplestore_begin_heap(randomAccess, false, work_mem);
@@ -907,10 +901,7 @@ get_crosstab_tuplestore(char *sql,
 					/* rowid changed, flush the previous output row */
 					tuple = BuildTupleFromCStrings(attinmeta, values);
 
-					/* switch to appropriate context while storing the tuple */
-					SPIcontext = MemoryContextSwitchTo(per_query_ctx);
 					tuplestore_puttuple(tupstore, tuple);
-					MemoryContextSwitchTo(SPIcontext);
 
 					for (j = 0; j < result_ncols; j++)
 						xpfree(values[j]);
@@ -943,10 +934,7 @@ get_crosstab_tuplestore(char *sql,
 		/* flush the last output row */
 		tuple = BuildTupleFromCStrings(attinmeta, values);
 
-		/* switch to appropriate context while storing the tuple */
-		SPIcontext = MemoryContextSwitchTo(per_query_ctx);
 		tuplestore_puttuple(tupstore, tuple);
-		MemoryContextSwitchTo(SPIcontext);
 	}
 
 	if (SPI_finish() != SPI_OK_FINISH)
@@ -1232,7 +1220,6 @@ build_tuplestore_recursively(char *key_fld,
 							 Tuplestorestate *tupstore)
 {
 	TupleDesc	tupdesc = attinmeta->tupdesc;
-	MemoryContext oldcontext;
 	int			ret;
 	int			proc;
 	int			serial_column;
@@ -1310,15 +1297,9 @@ build_tuplestore_recursively(char *key_fld,
 		/* construct the tuple */
 		tuple = BuildTupleFromCStrings(attinmeta, values);
 
-		/* switch to long lived context while storing the tuple */
-		oldcontext = MemoryContextSwitchTo(per_query_ctx);
-
 		/* now store it */
 		tuplestore_puttuple(tupstore, tuple);
 
-		/* now reset the context */
-		MemoryContextSwitchTo(oldcontext);
-
 		/* increment level */
 		level++;
 	}
@@ -1404,15 +1385,9 @@ build_tuplestore_recursively(char *key_fld,
 			xpfree(current_key);
 			xpfree(current_key_parent);
 
-			/* switch to long lived context while storing the tuple */
-			oldcontext = MemoryContextSwitchTo(per_query_ctx);
-
 			/* store the tuple for later use */
 			tuplestore_puttuple(tupstore, tuple);
 
-			/* now reset the context */
-			MemoryContextSwitchTo(oldcontext);
-
 			heap_freetuple(tuple);
 
 			/* recurse using current_key_parent as the new start_with */
diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 203e53905be560cd34803dbd6bdcc928d4a183d2..a003dd00c82132dabfb74108341deff19591fffb 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -1,5 +1,5 @@
 /*
- * $PostgreSQL: pgsql/contrib/xml2/xpath.c,v 1.23 2009/06/11 14:48:53 momjian Exp $
+ * $PostgreSQL: pgsql/contrib/xml2/xpath.c,v 1.24 2009/12/29 17:40:59 heikki Exp $
  *
  * Parser interface for DOM-based parser (libxml) rather than
  * stream-based SAX-type parser
@@ -821,9 +821,7 @@ xpath_table(PG_FUNCTION_ARGS)
 		{
 			/* not well-formed, so output all-NULL tuple */
 			ret_tuple = BuildTupleFromCStrings(attinmeta, values);
-			oldcontext = MemoryContextSwitchTo(per_query_ctx);
 			tuplestore_puttuple(tupstore, ret_tuple);
-			MemoryContextSwitchTo(oldcontext);
 			heap_freetuple(ret_tuple);
 		}
 		else
@@ -897,9 +895,7 @@ xpath_table(PG_FUNCTION_ARGS)
 				if (had_values)
 				{
 					ret_tuple = BuildTupleFromCStrings(attinmeta, values);
-					oldcontext = MemoryContextSwitchTo(per_query_ctx);
 					tuplestore_puttuple(tupstore, ret_tuple);
-					MemoryContextSwitchTo(oldcontext);
 					heap_freetuple(ret_tuple);
 				}
 
diff --git a/src/backend/commands/prepare.c b/src/backend/commands/prepare.c
index 021c2daf26d998174d6f5e7f94003e253ce1411a..8df3b4be41c0b5a9fb649d9a32ad6da4b6beebf9 100644
--- a/src/backend/commands/prepare.c
+++ b/src/backend/commands/prepare.c
@@ -10,7 +10,7 @@
  * Copyright (c) 2002-2009, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/prepare.c,v 1.100 2009/11/04 22:26:05 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/prepare.c,v 1.101 2009/12/29 17:40:59 heikki Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -779,6 +779,9 @@ pg_prepared_statement(PG_FUNCTION_ARGS)
 		tuplestore_begin_heap(rsinfo->allowedModes & SFRM_Materialize_Random,
 							  false, work_mem);
 
+	/* generate junk in short-term context */
+	MemoryContextSwitchTo(oldcontext);
+
 	/* hash table might be uninitialized */
 	if (prepared_queries)
 	{
@@ -791,9 +794,6 @@ pg_prepared_statement(PG_FUNCTION_ARGS)
 			Datum		values[5];
 			bool		nulls[5];
 
-			/* generate junk in short-term context */
-			MemoryContextSwitchTo(oldcontext);
-
 			MemSet(nulls, 0, sizeof(nulls));
 
 			values[0] = CStringGetTextDatum(prep_stmt->stmt_name);
@@ -803,8 +803,6 @@ pg_prepared_statement(PG_FUNCTION_ARGS)
 										  prep_stmt->plansource->num_params);
 			values[4] = BoolGetDatum(prep_stmt->from_sql);
 
-			/* switch to appropriate context while storing the tuple */
-			MemoryContextSwitchTo(per_query_ctx);
 			tuplestore_putvalues(tupstore, tupdesc, values, nulls);
 		}
 	}
@@ -812,8 +810,6 @@ pg_prepared_statement(PG_FUNCTION_ARGS)
 	/* clean up and return the tuplestore */
 	tuplestore_donestoring(tupstore);
 
-	MemoryContextSwitchTo(oldcontext);
-
 	rsinfo->returnMode = SFRM_Materialize;
 	rsinfo->setResult = tupstore;
 	rsinfo->setDesc = tupdesc;
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c
index 93b668181ff234e1d4fc3ad8caf02e4d5ac8a952..a56045375154450b54959e94895a18cc4337aed2 100644
--- a/src/backend/executor/execQual.c
+++ b/src/backend/executor/execQual.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.256 2009/12/14 02:15:49 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.257 2009/12/29 17:40:59 heikki Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2038,15 +2038,10 @@ ExecMakeTableFunctionResult(ExprState *funcexpr,
 				tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
 				tmptup.t_data = td;
 
-				oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
 				tuplestore_puttuple(tupstore, &tmptup);
 			}
 			else
-			{
-				oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
 				tuplestore_putvalues(tupstore, tupdesc, &result, &fcinfo.isnull);
-			}
-			MemoryContextSwitchTo(oldcontext);
 
 			/*
 			 * Are we done?
diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c
index 8ac98236ec384cac2298d50b1367ac142fe96a31..3b269668d26450a2814198b182421cd9db6415ae 100644
--- a/src/backend/executor/functions.c
+++ b/src/backend/executor/functions.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.138 2009/12/15 04:57:47 rhaas Exp $
+ *	  $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.139 2009/12/29 17:40:59 heikki Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1405,15 +1405,12 @@ static void
 sqlfunction_receive(TupleTableSlot *slot, DestReceiver *self)
 {
 	DR_sqlfunction *myState = (DR_sqlfunction *) self;
-	MemoryContext oldcxt;
 
 	/* Filter tuple as needed */
 	slot = ExecFilterJunk(myState->filter, slot);
 
 	/* Store the filtered tuple into the tuplestore */
-	oldcxt = MemoryContextSwitchTo(myState->cxt);
 	tuplestore_puttupleslot(myState->tstore, slot);
-	MemoryContextSwitchTo(oldcxt);
 }
 
 /*
diff --git a/src/backend/executor/nodeWindowAgg.c b/src/backend/executor/nodeWindowAgg.c
index acc2f55ea94e75e45439482e78dff079399820fb..ea28e09eae210c2b4cc9ac07574d98e14532230e 100644
--- a/src/backend/executor/nodeWindowAgg.c
+++ b/src/backend/executor/nodeWindowAgg.c
@@ -27,7 +27,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/executor/nodeWindowAgg.c,v 1.7 2009/09/27 21:10:53 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/executor/nodeWindowAgg.c,v 1.8 2009/12/29 17:40:59 heikki Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -723,7 +723,7 @@ spool_tuples(WindowAggState *winstate, int64 pos)
 
 	outerPlan = outerPlanState(winstate);
 
-	/* Must be in query context to call outerplan or touch tuplestore */
+	/* Must be in query context to call outerplan */
 	oldcontext = MemoryContextSwitchTo(winstate->ss.ps.ps_ExprContext->ecxt_per_query_memory);
 
 	while (winstate->spooled_rows <= pos || pos == -1)
diff --git a/src/backend/executor/tstoreReceiver.c b/src/backend/executor/tstoreReceiver.c
index 19f348f13f699996da1963d1842d68a235b166a3..9ce61ec5c8e19f589088c15329cc6c0b980b9327 100644
--- a/src/backend/executor/tstoreReceiver.c
+++ b/src/backend/executor/tstoreReceiver.c
@@ -13,7 +13,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/executor/tstoreReceiver.c,v 1.23 2009/06/11 14:48:57 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/executor/tstoreReceiver.c,v 1.24 2009/12/29 17:40:59 heikki Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -94,11 +94,8 @@ static void
 tstoreReceiveSlot_notoast(TupleTableSlot *slot, DestReceiver *self)
 {
 	TStoreState *myState = (TStoreState *) self;
-	MemoryContext oldcxt = MemoryContextSwitchTo(myState->cxt);
 
 	tuplestore_puttupleslot(myState->tstore, slot);
-
-	MemoryContextSwitchTo(oldcxt);
 }
 
 /*
diff --git a/src/backend/utils/mmgr/portalmem.c b/src/backend/utils/mmgr/portalmem.c
index b8b2923c7d4d8d78f82d88fa698bf674504a8570..ceb24a7a728e8edce01f621d97f22f5ba8a2d713 100644
--- a/src/backend/utils/mmgr/portalmem.c
+++ b/src/backend/utils/mmgr/portalmem.c
@@ -12,7 +12,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/mmgr/portalmem.c,v 1.113 2009/01/01 17:23:53 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/mmgr/portalmem.c,v 1.114 2009/12/29 17:40:59 heikki Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -923,6 +923,9 @@ pg_cursor(PG_FUNCTION_ARGS)
 		tuplestore_begin_heap(rsinfo->allowedModes & SFRM_Materialize_Random,
 							  false, work_mem);
 
+	/* generate junk in short-term context */
+	MemoryContextSwitchTo(oldcontext);
+
 	hash_seq_init(&hash_seq, PortalHashTable);
 	while ((hentry = hash_seq_search(&hash_seq)) != NULL)
 	{
@@ -934,9 +937,6 @@ pg_cursor(PG_FUNCTION_ARGS)
 		if (!portal->visible)
 			continue;
 
-		/* generate junk in short-term context */
-		MemoryContextSwitchTo(oldcontext);
-
 		MemSet(nulls, 0, sizeof(nulls));
 
 		values[0] = CStringGetTextDatum(portal->name);
@@ -946,16 +946,12 @@ pg_cursor(PG_FUNCTION_ARGS)
 		values[4] = BoolGetDatum(portal->cursorOptions & CURSOR_OPT_SCROLL);
 		values[5] = TimestampTzGetDatum(portal->creation_time);
 
-		/* switch to appropriate context while storing the tuple */
-		MemoryContextSwitchTo(per_query_ctx);
 		tuplestore_putvalues(tupstore, tupdesc, values, nulls);
 	}
 
 	/* clean up and return the tuplestore */
 	tuplestore_donestoring(tupstore);
 
-	MemoryContextSwitchTo(oldcontext);
-
 	rsinfo->returnMode = SFRM_Materialize;
 	rsinfo->setResult = tupstore;
 	rsinfo->setDesc = tupdesc;
diff --git a/src/backend/utils/sort/tuplestore.c b/src/backend/utils/sort/tuplestore.c
index 5b900b7a5ea6bae5aec397349496510255447b7e..a5edc1fdf3588ed02b4aaabaa9017d6f6e3197ce 100644
--- a/src/backend/utils/sort/tuplestore.c
+++ b/src/backend/utils/sort/tuplestore.c
@@ -47,7 +47,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/sort/tuplestore.c,v 1.48 2009/06/11 14:49:06 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/sort/tuplestore.c,v 1.49 2009/12/29 17:40:59 heikki Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -58,6 +58,7 @@
 #include "executor/executor.h"
 #include "storage/buffile.h"
 #include "utils/memutils.h"
+#include "utils/resowner.h"
 #include "utils/tuplestore.h"
 
 
@@ -105,6 +106,8 @@ struct Tuplestorestate
 	bool		truncated;		/* tuplestore_trim has removed tuples? */
 	long		availMem;		/* remaining memory available, in bytes */
 	BufFile    *myfile;			/* underlying file, or NULL if none */
+	MemoryContext context;		/* memory context for holding tuples */
+	ResourceOwner resowner;		/* resowner for holding temp files */
 
 	/*
 	 * These function pointers decouple the routines that must know what kind
@@ -246,6 +249,8 @@ tuplestore_begin_common(int eflags, bool interXact, int maxKBytes)
 	state->truncated = false;
 	state->availMem = maxKBytes * 1024L;
 	state->myfile = NULL;
+	state->context = CurrentMemoryContext;
+	state->resowner = CurrentResourceOwner;
 
 	state->memtupcount = 0;
 	state->memtupsize = 1024;	/* initial guess */
@@ -278,9 +283,9 @@ tuplestore_begin_common(int eflags, bool interXact, int maxKBytes)
  *
  * interXact: if true, the files used for on-disk storage persist beyond the
  * end of the current transaction.	NOTE: It's the caller's responsibility to
- * create such a tuplestore in a memory context that will also survive
- * transaction boundaries, and to ensure the tuplestore is closed when it's
- * no longer wanted.
+ * create such a tuplestore in a memory context and resource owner that will
+ * also survive transaction boundaries, and to ensure the tuplestore is closed
+ * when it's no longer wanted.
  *
  * maxKBytes: how much data to store in memory (any data beyond this
  * amount is paged to disk).  When in doubt, use work_mem.
@@ -533,6 +538,7 @@ tuplestore_puttupleslot(Tuplestorestate *state,
 						TupleTableSlot *slot)
 {
 	MinimalTuple tuple;
+	MemoryContext oldcxt = MemoryContextSwitchTo(state->context);
 
 	/*
 	 * Form a MinimalTuple in working memory
@@ -541,6 +547,8 @@ tuplestore_puttupleslot(Tuplestorestate *state,
 	USEMEM(state, GetMemoryChunkSpace(tuple));
 
 	tuplestore_puttuple_common(state, (void *) tuple);
+
+	MemoryContextSwitchTo(oldcxt);
 }
 
 /*
@@ -550,12 +558,16 @@ tuplestore_puttupleslot(Tuplestorestate *state,
 void
 tuplestore_puttuple(Tuplestorestate *state, HeapTuple tuple)
 {
+	MemoryContext oldcxt = MemoryContextSwitchTo(state->context);
+
 	/*
 	 * Copy the tuple.	(Must do this even in WRITEFILE case.)
 	 */
 	tuple = COPYTUP(state, tuple);
 
 	tuplestore_puttuple_common(state, (void *) tuple);
+
+	MemoryContextSwitchTo(oldcxt);
 }
 
 /*
@@ -568,10 +580,13 @@ tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc,
 					 Datum *values, bool *isnull)
 {
 	MinimalTuple tuple;
+	MemoryContext oldcxt = MemoryContextSwitchTo(state->context);
 
 	tuple = heap_form_minimal_tuple(tdesc, values, isnull);
 
 	tuplestore_puttuple_common(state, (void *) tuple);
+
+	MemoryContextSwitchTo(oldcxt);	
 }
 
 static void
@@ -579,6 +594,7 @@ tuplestore_puttuple_common(Tuplestorestate *state, void *tuple)
 {
 	TSReadPointer *readptr;
 	int			i;
+	ResourceOwner oldowner;
 
 	switch (state->status)
 	{
@@ -635,8 +651,15 @@ tuplestore_puttuple_common(Tuplestorestate *state, void *tuple)
 			 * the temp file(s) are created in suitable temp tablespaces.
 			 */
 			PrepareTempTablespaces();
+
+			/* associate the file with the store's resource owner */
+			oldowner = CurrentResourceOwner;
+			CurrentResourceOwner = state->resowner;
+
 			state->myfile = BufFileCreateTemp(state->interXact);
 
+			CurrentResourceOwner = oldowner;
+
 			/*
 			 * Freeze the decision about whether trailing length words will be
 			 * used.  We can't change this choice once data is on tape, even
diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c
index f999495c877581362bc25101e67877511107a678..4fe30bba27a96d67d31d3fe21486252c2133014a 100644
--- a/src/pl/plperl/plperl.c
+++ b/src/pl/plperl/plperl.c
@@ -1,7 +1,7 @@
 /**********************************************************************
  * plperl.c - perl as a procedural language for PostgreSQL
  *
- *	  $PostgreSQL: pgsql/src/pl/plperl/plperl.c,v 1.155 2009/11/29 21:02:16 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/pl/plperl/plperl.c,v 1.156 2009/12/29 17:40:59 heikki Exp $
  *
  **********************************************************************/
 
@@ -2107,11 +2107,7 @@ plperl_return_next(SV *sv)
 
 		tuple = plperl_build_tuple_result((HV *) SvRV(sv),
 										  current_call_data->attinmeta);
-
-		/* Make sure to store the tuple in a long-lived memory context */
-		MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);
 		tuplestore_puttuple(current_call_data->tuple_store, tuple);
-		MemoryContextSwitchTo(old_cxt);
 	}
 	else
 	{
@@ -2141,14 +2137,12 @@ plperl_return_next(SV *sv)
 			isNull = true;
 		}
 
-		/* Make sure to store the tuple in a long-lived memory context */
-		MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);
 		tuplestore_putvalues(current_call_data->tuple_store,
 							 current_call_data->ret_tdesc,
 							 &ret, &isNull);
-		MemoryContextSwitchTo(old_cxt);
 	}
 
+	MemoryContextSwitchTo(old_cxt);
 	MemoryContextReset(current_call_data->tmp_cxt);
 }
 
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index 117da74eb0f109df2e899b49f6680bdb55ef754d..823cdbea47feb76cc88824a2917ff977b99c26dc 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.251 2009/11/09 00:26:55 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.252 2009/12/29 17:40:59 heikki Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2172,7 +2172,6 @@ exec_stmt_return_next(PLpgSQL_execstate *estate,
 {
 	TupleDesc	tupdesc;
 	int			natts;
-	MemoryContext oldcxt;
 	HeapTuple	tuple = NULL;
 	bool		free_tuple = false;
 
@@ -2212,10 +2211,8 @@ exec_stmt_return_next(PLpgSQL_execstate *estate,
 												tupdesc->attrs[0]->atttypmod,
 													isNull);
 
-					oldcxt = MemoryContextSwitchTo(estate->tuple_store_cxt);
 					tuplestore_putvalues(estate->tuple_store, tupdesc,
 										 &retval, &isNull);
-					MemoryContextSwitchTo(oldcxt);
 				}
 				break;
 
@@ -2285,10 +2282,8 @@ exec_stmt_return_next(PLpgSQL_execstate *estate,
 										tupdesc->attrs[0]->atttypmod,
 										isNull);
 
-		oldcxt = MemoryContextSwitchTo(estate->tuple_store_cxt);
 		tuplestore_putvalues(estate->tuple_store, tupdesc,
 							 &retval, &isNull);
-		MemoryContextSwitchTo(oldcxt);
 
 		exec_eval_cleanup(estate);
 	}
@@ -2301,9 +2296,7 @@ exec_stmt_return_next(PLpgSQL_execstate *estate,
 
 	if (HeapTupleIsValid(tuple))
 	{
-		oldcxt = MemoryContextSwitchTo(estate->tuple_store_cxt);
 		tuplestore_puttuple(estate->tuple_store, tuple);
-		MemoryContextSwitchTo(oldcxt);
 
 		if (free_tuple)
 			heap_freetuple(tuple);
@@ -2353,14 +2346,12 @@ exec_stmt_return_query(PLpgSQL_execstate *estate,
 
 	while (true)
 	{
-		MemoryContext old_cxt;
 		int			i;
 
 		SPI_cursor_fetch(portal, true, 50);
 		if (SPI_processed == 0)
 			break;
 
-		old_cxt = MemoryContextSwitchTo(estate->tuple_store_cxt);
 		for (i = 0; i < SPI_processed; i++)
 		{
 			HeapTuple	tuple = SPI_tuptable->vals[i];
@@ -2372,7 +2363,6 @@ exec_stmt_return_query(PLpgSQL_execstate *estate,
 				heap_freetuple(tuple);
 			processed++;
 		}
-		MemoryContextSwitchTo(old_cxt);
 
 		SPI_freetuptable(SPI_tuptable);
 	}
@@ -2394,6 +2384,7 @@ exec_init_tuple_store(PLpgSQL_execstate *estate)
 {
 	ReturnSetInfo *rsi = estate->rsi;
 	MemoryContext oldcxt;
+	ResourceOwner oldowner;
 
 	/*
 	 * Check caller can handle a set result in the way we want
@@ -2405,12 +2396,22 @@ exec_init_tuple_store(PLpgSQL_execstate *estate)
 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 				 errmsg("set-valued function called in context that cannot accept a set")));
 
-	estate->tuple_store_cxt = rsi->econtext->ecxt_per_query_memory;
-
+	/*
+	 * Switch to the right memory context and resource owner for storing
+	 * the tuplestore for return set. If we're within a subtransaction opened
+	 * for an exception-block, for example, we must still create the
+	 * tuplestore in the resource owner that was active when this function was
+	 * entered, and not in the subtransaction resource owner.
+	 */
 	oldcxt = MemoryContextSwitchTo(estate->tuple_store_cxt);
+	oldowner = CurrentResourceOwner;
+	CurrentResourceOwner = estate->tuple_store_owner;
+
 	estate->tuple_store =
 		tuplestore_begin_heap(rsi->allowedModes & SFRM_Materialize_Random,
 							  false, work_mem);
+
+	CurrentResourceOwner = oldowner;
 	MemoryContextSwitchTo(oldcxt);
 
 	estate->rettupdesc = rsi->expectedDesc;
@@ -2635,7 +2636,16 @@ plpgsql_estate_setup(PLpgSQL_execstate *estate,
 	estate->exitlabel = NULL;
 
 	estate->tuple_store = NULL;
-	estate->tuple_store_cxt = NULL;
+	if (rsi)
+	{
+		estate->tuple_store_cxt = rsi->econtext->ecxt_per_query_memory;
+		estate->tuple_store_owner = CurrentResourceOwner;
+	}
+	else
+	{
+		estate->tuple_store_cxt = NULL;
+		estate->tuple_store_owner = NULL;
+	}
 	estate->rsi = rsi;
 
 	estate->found_varno = func->found_varno;
diff --git a/src/pl/plpgsql/src/plpgsql.h b/src/pl/plpgsql/src/plpgsql.h
index 25d1c0369990f54154ec70768159e88ed04de0ce..b0813ba33edfdecc902ac0179311e396b70734ab 100644
--- a/src/pl/plpgsql/src/plpgsql.h
+++ b/src/pl/plpgsql/src/plpgsql.h
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.125 2009/11/13 22:43:42 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.126 2009/12/29 17:40:59 heikki Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -701,6 +701,7 @@ typedef struct PLpgSQL_execstate
 
 	Tuplestorestate *tuple_store;		/* SRFs accumulate results here */
 	MemoryContext tuple_store_cxt;
+	ResourceOwner tuple_store_owner;
 	ReturnSetInfo *rsi;
 
 	int			found_varno;