mirror of
https://github.com/postgres/postgres.git
synced 2025-09-03 15:22:11 +03:00
Previous fix for temporary file management broke returning a set from
PL/pgSQL function within an exception handler. Make sure we use the right resource owner when we create the tuplestore to hold returned tuples. Simplify tuplestore API so that the caller doesn't need to be in the right memory context when calling tuplestore_put* functions. tuplestore.c automatically switches to the memory context used when the tuplestore was created. Tuplesort was already modified like this earlier. This patch also removes the now useless MemoryContextSwitch calls from callers. Report by Aleksei on pgsql-bugs on Dec 22 2009. Backpatch to 8.1, like the previous patch that broke this.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
/**********************************************************************
|
||||
* plperl.c - perl as a procedural language for PostgreSQL
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/pl/plperl/plperl.c,v 1.150.2.3 2009/11/29 21:02:22 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/pl/plperl/plperl.c,v 1.150.2.4 2009/12/29 17:41:09 heikki Exp $
|
||||
*
|
||||
**********************************************************************/
|
||||
|
||||
@@ -1981,11 +1981,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
|
||||
{
|
||||
@@ -2015,14 +2011,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);
|
||||
}
|
||||
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.244.2.1 2009/07/18 19:15:50 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.244.2.2 2009/12/29 17:41:09 heikki Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -2140,7 +2140,6 @@ exec_stmt_return_next(PLpgSQL_execstate *estate,
|
||||
{
|
||||
TupleDesc tupdesc;
|
||||
int natts;
|
||||
MemoryContext oldcxt;
|
||||
HeapTuple tuple = NULL;
|
||||
bool free_tuple = false;
|
||||
|
||||
@@ -2180,10 +2179,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;
|
||||
|
||||
@@ -2245,10 +2242,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);
|
||||
}
|
||||
@@ -2261,9 +2256,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);
|
||||
@@ -2311,14 +2304,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];
|
||||
@@ -2326,7 +2317,6 @@ exec_stmt_return_query(PLpgSQL_execstate *estate,
|
||||
tuplestore_puttuple(estate->tuple_store, tuple);
|
||||
processed++;
|
||||
}
|
||||
MemoryContextSwitchTo(old_cxt);
|
||||
|
||||
SPI_freetuptable(SPI_tuptable);
|
||||
}
|
||||
@@ -2345,6 +2335,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
|
||||
@@ -2356,12 +2347,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;
|
||||
@@ -2581,7 +2582,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->trig_nargs = 0;
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.113 2009/06/11 14:49:14 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.113.2.1 2009/12/29 17:41:09 heikki Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -705,6 +705,7 @@ typedef struct
|
||||
|
||||
Tuplestorestate *tuple_store; /* SRFs accumulate results here */
|
||||
MemoryContext tuple_store_cxt;
|
||||
ResourceOwner tuple_store_owner;
|
||||
ReturnSetInfo *rsi;
|
||||
|
||||
int trig_nargs;
|
||||
|
Reference in New Issue
Block a user