mirror of
https://github.com/postgres/postgres.git
synced 2025-06-08 22:02:03 +03:00
Add checks to verify that a plpgsql function returning a rowtype is actually
returning the rowtype it's supposed to return. Per reports from David Niblett and Michael Fuhr.
This commit is contained in:
parent
a61ca095a9
commit
495be39266
@ -3,7 +3,7 @@
|
|||||||
* procedural language
|
* procedural language
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.154.2.1 2005/11/22 18:23:30 momjian Exp $
|
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.154.2.2 2006/01/03 22:48:21 tgl Exp $
|
||||||
*
|
*
|
||||||
* This software is copyrighted by Jan Wieck - Hamburg.
|
* This software is copyrighted by Jan Wieck - Hamburg.
|
||||||
*
|
*
|
||||||
@ -343,10 +343,48 @@ plpgsql_exec_function(PLpgSQL_function *func, FunctionCallInfo fcinfo)
|
|||||||
{
|
{
|
||||||
if (estate.retistuple)
|
if (estate.retistuple)
|
||||||
{
|
{
|
||||||
/* Copy tuple to upper executor memory, as a tuple Datum */
|
/*
|
||||||
|
* We have to check that the returned tuple actually matches
|
||||||
|
* the expected result type. XXX would be better to cache the
|
||||||
|
* tupdesc instead of repeating get_call_result_type()
|
||||||
|
*/
|
||||||
|
TupleDesc tupdesc;
|
||||||
|
|
||||||
|
switch (get_call_result_type(fcinfo, NULL, &tupdesc))
|
||||||
|
{
|
||||||
|
case TYPEFUNC_COMPOSITE:
|
||||||
|
/* got the expected result rowtype, now check it */
|
||||||
|
if (estate.rettupdesc == NULL ||
|
||||||
|
!compatible_tupdesc(estate.rettupdesc, tupdesc))
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
||||||
|
errmsg("returned record type does not match expected record type")));
|
||||||
|
break;
|
||||||
|
case TYPEFUNC_RECORD:
|
||||||
|
/*
|
||||||
|
* Failed to determine actual type of RECORD. We could
|
||||||
|
* raise an error here, but what this means in practice
|
||||||
|
* is that the caller is expecting any old generic
|
||||||
|
* rowtype, so we don't really need to be restrictive.
|
||||||
|
* Pass back the generated result type, instead.
|
||||||
|
*/
|
||||||
|
tupdesc = estate.rettupdesc;
|
||||||
|
if (tupdesc == NULL) /* shouldn't happen */
|
||||||
|
elog(ERROR, "return type must be a row type");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* shouldn't get here if retistuple is true ... */
|
||||||
|
elog(ERROR, "return type must be a row type");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copy tuple to upper executor memory, as a tuple Datum.
|
||||||
|
* Make sure it is labeled with the caller-supplied tuple type.
|
||||||
|
*/
|
||||||
estate.retval =
|
estate.retval =
|
||||||
PointerGetDatum(SPI_returntuple((HeapTuple) (estate.retval),
|
PointerGetDatum(SPI_returntuple((HeapTuple) (estate.retval),
|
||||||
estate.rettupdesc));
|
tupdesc));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user