|
3 | 3 | * procedural language
|
4 | 4 | *
|
5 | 5 | * IDENTIFICATION
|
6 |
| - * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.158 2005/12/28 01:30:01 tgl Exp $ |
| 6 | + * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.159 2006/01/03 22:48:10 tgl Exp $ |
7 | 7 | *
|
8 | 8 | * This software is copyrighted by Jan Wieck - Hamburg.
|
9 | 9 | *
|
@@ -343,10 +343,48 @@ plpgsql_exec_function(PLpgSQL_function *func, FunctionCallInfo fcinfo)
|
343 | 343 | {
|
344 | 344 | if (estate.retistuple)
|
345 | 345 | {
|
346 |
| -/* Copy tuple to upper executor memory, as a tuple Datum */ |
| 346 | +/* |
| 347 | + * We have to check that the returned tuple actually matches |
| 348 | + * the expected result type. XXX would be better to cache the |
| 349 | + * tupdesc instead of repeating get_call_result_type() |
| 350 | + */ |
| 351 | +TupleDesctupdesc; |
| 352 | + |
| 353 | +switch (get_call_result_type(fcinfo,NULL,&tupdesc)) |
| 354 | +{ |
| 355 | +caseTYPEFUNC_COMPOSITE: |
| 356 | +/* got the expected result rowtype, now check it */ |
| 357 | +if (estate.rettupdesc==NULL|| |
| 358 | +!compatible_tupdesc(estate.rettupdesc,tupdesc)) |
| 359 | +ereport(ERROR, |
| 360 | +(errcode(ERRCODE_DATATYPE_MISMATCH), |
| 361 | +errmsg("returned record type does not match expected record type"))); |
| 362 | +break; |
| 363 | +caseTYPEFUNC_RECORD: |
| 364 | +/* |
| 365 | + * Failed to determine actual type of RECORD. We could |
| 366 | + * raise an error here, but what this means in practice |
| 367 | + * is that the caller is expecting any old generic |
| 368 | + * rowtype, so we don't really need to be restrictive. |
| 369 | + * Pass back the generated result type, instead. |
| 370 | + */ |
| 371 | +tupdesc=estate.rettupdesc; |
| 372 | +if (tupdesc==NULL)/* shouldn't happen */ |
| 373 | +elog(ERROR,"return type must be a row type"); |
| 374 | +break; |
| 375 | +default: |
| 376 | +/* shouldn't get here if retistuple is true ... */ |
| 377 | +elog(ERROR,"return type must be a row type"); |
| 378 | +break; |
| 379 | +} |
| 380 | + |
| 381 | +/* |
| 382 | + * Copy tuple to upper executor memory, as a tuple Datum. |
| 383 | + * Make sure it is labeled with the caller-supplied tuple type. |
| 384 | + */ |
347 | 385 | estate.retval=
|
348 | 386 | PointerGetDatum(SPI_returntuple((HeapTuple) (estate.retval),
|
349 |
| -estate.rettupdesc)); |
| 387 | +tupdesc)); |
350 | 388 | }
|
351 | 389 | else
|
352 | 390 | {
|
|