1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-27 12:41:57 +03:00

Fix coredump in plpgsql when trying to return a rowtype result.

Need to return a TupleTableSlot, not just a bare tuple.
This commit is contained in:
Tom Lane
2001-11-05 19:41:56 +00:00
parent ea08e6cd55
commit 0053cebea5
4 changed files with 206 additions and 35 deletions

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/spi.c,v 1.60 2001/10/25 05:49:29 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/executor/spi.c,v 1.61 2001/11/05 19:41:56 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -360,6 +360,40 @@ SPI_copytupledesc(TupleDesc tupdesc)
return ctupdesc;
}
TupleTableSlot *
SPI_copytupleintoslot(HeapTuple tuple, TupleDesc tupdesc)
{
MemoryContext oldcxt = NULL;
TupleTableSlot *cslot;
HeapTuple ctuple;
TupleDesc ctupdesc;
if (tuple == NULL || tupdesc == NULL)
{
SPI_result = SPI_ERROR_ARGUMENT;
return NULL;
}
if (_SPI_curid + 1 == _SPI_connected) /* connected */
{
if (_SPI_current != &(_SPI_stack[_SPI_curid + 1]))
elog(FATAL, "SPI: stack corrupted");
oldcxt = MemoryContextSwitchTo(_SPI_current->savedcxt);
}
ctuple = heap_copytuple(tuple);
ctupdesc = CreateTupleDescCopy(tupdesc);
cslot = MakeTupleTableSlot();
ExecSetSlotDescriptor(cslot, ctupdesc, true);
cslot = ExecStoreTuple(ctuple, cslot, InvalidBuffer, true);
if (oldcxt)
MemoryContextSwitchTo(oldcxt);
return cslot;
}
HeapTuple
SPI_modifytuple(Relation rel, HeapTuple tuple, int natts, int *attnum,
Datum *Values, char *Nulls)

View File

@ -2,7 +2,7 @@
*
* spi.h
*
* $Id: spi.h,v 1.31 2001/11/05 17:46:33 momjian Exp $
* $Id: spi.h,v 1.32 2001/11/05 19:41:56 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -89,6 +89,8 @@ extern int SPI_freeplan(void *plan);
extern HeapTuple SPI_copytuple(HeapTuple tuple);
extern TupleDesc SPI_copytupledesc(TupleDesc tupdesc);
extern TupleTableSlot *SPI_copytupleintoslot(HeapTuple tuple,
TupleDesc tupdesc);
extern HeapTuple SPI_modifytuple(Relation rel, HeapTuple tuple, int natts,
int *attnum, Datum *Values, char *Nulls);
extern int SPI_fnumber(TupleDesc tupdesc, char *fname);

View File

@ -3,7 +3,7 @@
* procedural language
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.48 2001/10/25 05:50:20 momjian Exp $
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.49 2001/11/05 19:41:56 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
@ -400,32 +400,43 @@ plpgsql_exec_function(PLpgSQL_function * func, FunctionCallInfo fcinfo)
fcinfo->isnull = estate.retisnull;
if (!estate.retistuple)
if (!estate.retisnull)
{
estate.retval = exec_cast_value(estate.retval, estate.rettype,
func->fn_rettype,
&(func->fn_retinput),
func->fn_rettypelem,
-1,
&fcinfo->isnull);
/*
* If the functions return type isn't by value, copy the value
* into upper executor memory context.
*/
if (!fcinfo->isnull && !func->fn_retbyval)
if (estate.retistuple)
{
int len;
Datum tmp;
/* Copy tuple to upper executor memory */
/* Here we need to return a TupleTableSlot not just a tuple */
estate.retval = (Datum)
SPI_copytupleintoslot((HeapTuple) (estate.retval),
estate.rettupdesc);
}
else
{
/* Cast value to proper type */
estate.retval = exec_cast_value(estate.retval, estate.rettype,
func->fn_rettype,
&(func->fn_retinput),
func->fn_rettypelem,
-1,
&fcinfo->isnull);
/*
* If the functions return type isn't by value, copy the value
* into upper executor memory context.
*/
if (!fcinfo->isnull && !func->fn_retbyval)
{
int len;
Datum tmp;
if (func->fn_rettyplen < 0)
len = VARSIZE(estate.retval);
else
len = func->fn_rettyplen;
if (func->fn_rettyplen < 0)
len = VARSIZE(estate.retval);
else
len = func->fn_rettyplen;
tmp = (Datum) SPI_palloc(len);
memcpy((void *) tmp, (void *) estate.retval, len);
estate.retval = tmp;
tmp = (Datum) SPI_palloc(len);
memcpy((void *) tmp, (void *) estate.retval, len);
estate.retval = tmp;
}
}
}
@ -1619,8 +1630,8 @@ exec_stmt_return(PLpgSQL_execstate * estate, PLpgSQL_stmt_return * stmt)
if (HeapTupleIsValid(rec->tup))
{
estate->retval = (Datum) SPI_copytuple(rec->tup);
estate->rettupdesc = SPI_copytupledesc(rec->tupdesc);
estate->retval = (Datum) rec->tup;
estate->rettupdesc = rec->tupdesc;
estate->retisnull = false;
}
return PLPGSQL_RC_RETURN;
@ -1631,16 +1642,10 @@ exec_stmt_return(PLpgSQL_execstate * estate, PLpgSQL_stmt_return * stmt)
exec_run_select(estate, stmt->expr, 1, NULL);
if (estate->eval_processed > 0)
{
estate->retval = (Datum) SPI_copytuple(estate->eval_tuptable->vals[0]);
estate->rettupdesc = SPI_copytupledesc(estate->eval_tuptable->tupdesc);
estate->retval = (Datum) estate->eval_tuptable->vals[0];
estate->rettupdesc = estate->eval_tuptable->tupdesc;
estate->retisnull = false;
}
/*
* Okay to clean up here, since we already copied result tuple
* to upper executor.
*/
exec_eval_cleanup(estate);
}
return PLPGSQL_RC_RETURN;
}