* procedural language
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.127.4.3 2005/06/20 22:51:49 tgl Exp $
+ * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.127.4.4 2006/01/03 22:48:28 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
{
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.
+ */
+ ReturnSetInfo *rsi = estate.rsi;
+ TupleDesc tupdesc;
+
+ if (rsi && IsA(rsi, ReturnSetInfo) &&
+ rsi->expectedDesc != NULL)
+ tupdesc = rsi->expectedDesc;
+ else if (estate.fn_rettype == RECORDOID)
+ {
+ /* assume caller can handle any record type */
+ tupdesc = estate.rettupdesc;
+ }
+ else
+ tupdesc = lookup_rowtype_tupdesc(estate.fn_rettype, -1);
+ /* 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")));
+
+ /*
+ * Copy tuple to upper executor memory, as a tuple Datum.
+ * Make sure it is labeled with the caller-supplied tuple type.
+ */
estate.retval =
PointerGetDatum(SPI_returntuple((HeapTuple) (estate.retval),
- estate.rettupdesc));
+ tupdesc));
}
else
{