|
8 | 8 | *
|
9 | 9 | *
|
10 | 10 | * IDENTIFICATION
|
11 |
| - * $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.82 2004/06/11 01:08:42 tgl Exp $ |
| 11 | + * $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.83 2004/07/15 13:51:38 tgl Exp $ |
12 | 12 | *
|
13 | 13 | *-------------------------------------------------------------------------
|
14 | 14 | */
|
@@ -58,9 +58,10 @@ typedef struct local_es
|
58 | 58 | */
|
59 | 59 | typedef struct
|
60 | 60 | {
|
| 61 | + Oid rettype; /* actual return type */ |
61 | 62 | int typlen; /* length of the return type */
|
62 | 63 | bool typbyval; /* true if return type is pass by value */
|
63 |
| - bool returnsTuple; /* true if return type is a tuple */ |
| 64 | + bool returnsTuple; /* true if returning whole tuple result */ |
64 | 65 | bool shutdown_reg; /* true if registered shutdown callback */
|
65 | 66 |
|
66 | 67 | ParamListInfo paramLI; /* Param list representing current args */
|
@@ -167,6 +168,8 @@ init_sql_fcache(FmgrInfo *finfo)
|
167 | 168 | format_type_be(procedureStruct->prorettype))));
|
168 | 169 | }
|
169 | 170 |
|
| 171 | + fcache->rettype = rettype; |
| 172 | + |
170 | 173 | /* Now look up the actual result type */
|
171 | 174 | typeTuple = SearchSysCache(TYPEOID,
|
172 | 175 | ObjectIdGetDatum(rettype),
|
@@ -389,20 +392,36 @@ postquel_execute(execution_state *es,
|
389 | 392 | * Probably OK to leave them, as long as they are at the end.
|
390 | 393 | */
|
391 | 394 | HeapTupleHeader dtup;
|
| 395 | + Oid dtuptype; |
| 396 | + int32 dtuptypmod; |
392 | 397 |
|
393 | 398 | dtup = (HeapTupleHeader) palloc(tup->t_len);
|
394 | 399 | memcpy((char *) dtup, (char *) tup->t_data, tup->t_len);
|
395 | 400 |
|
396 | 401 | /*
|
397 |
| - * For RECORD results, make sure a typmod has been assigned. |
| 402 | + * Use the declared return type if it's not RECORD; else take |
| 403 | + * the type from the computed result, making sure a typmod has |
| 404 | + * been assigned. |
398 | 405 | */
|
399 |
| - if (tupDesc->tdtypeid == RECORDOID && |
400 |
| - tupDesc->tdtypmod < 0) |
401 |
| - assign_record_type_typmod(tupDesc); |
| 406 | + if (fcache->rettype != RECORDOID) |
| 407 | + { |
| 408 | + /* function has a named composite return type */ |
| 409 | + dtuptype = fcache->rettype; |
| 410 | + dtuptypmod = -1; |
| 411 | + } |
| 412 | + else |
| 413 | + { |
| 414 | + /* function is declared to return RECORD */ |
| 415 | + if (tupDesc->tdtypeid == RECORDOID && |
| 416 | + tupDesc->tdtypmod < 0) |
| 417 | + assign_record_type_typmod(tupDesc); |
| 418 | + dtuptype = tupDesc->tdtypeid; |
| 419 | + dtuptypmod = tupDesc->tdtypmod; |
| 420 | + } |
402 | 421 |
|
403 | 422 | HeapTupleHeaderSetDatumLength(dtup, tup->t_len);
|
404 |
| - HeapTupleHeaderSetTypeId(dtup, tupDesc->tdtypeid); |
405 |
| - HeapTupleHeaderSetTypMod(dtup, tupDesc->tdtypmod); |
| 423 | + HeapTupleHeaderSetTypeId(dtup, dtuptype); |
| 424 | + HeapTupleHeaderSetTypMod(dtup, dtuptypmod); |
406 | 425 |
|
407 | 426 | value = PointerGetDatum(dtup);
|
408 | 427 | fcinfo->isnull = false;
|
|
0 commit comments