diff --git a/contrib/dblink/dblink.c b/contrib/dblink/dblink.c index 61585644f9..d3875529fd 100644 --- a/contrib/dblink/dblink.c +++ b/contrib/dblink/dblink.c @@ -8,7 +8,7 @@ * Darko Prenosil * Shridhar Daithankar * - * $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 e2b3afa4b6..6912543023 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 48512bd934..272b1b4377 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 203e53905b..a003dd00c8 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 021c2daf26..8df3b4be41 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 93b668181f..a560453751 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 8ac98236ec..3b269668d2 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 acc2f55ea9..ea28e09eae 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 19f348f13f..9ce61ec5c8 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 b8b2923c7d..ceb24a7a72 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 5b900b7a5e..a5edc1fdf3 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 f999495c87..4fe30bba27 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 117da74eb0..823cdbea47 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 25d1c03699..b0813ba33e 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;