|
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