For a SQL function declared to return a named composite type, make
sure the tuple datums it returns actually show that type and not RECORD.
This commit is contained in:
parent
93a1fce5cc
commit
473165aff8
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.82 2004/06/11 01:08:42 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.83 2004/07/15 13:51:38 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -58,9 +58,10 @@ typedef struct local_es
|
|||||||
*/
|
*/
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
Oid rettype; /* actual return type */
|
||||||
int typlen; /* length of the return type */
|
int typlen; /* length of the return type */
|
||||||
bool typbyval; /* true if return type is pass by value */
|
bool typbyval; /* true if return type is pass by value */
|
||||||
bool returnsTuple; /* true if return type is a tuple */
|
bool returnsTuple; /* true if returning whole tuple result */
|
||||||
bool shutdown_reg; /* true if registered shutdown callback */
|
bool shutdown_reg; /* true if registered shutdown callback */
|
||||||
|
|
||||||
ParamListInfo paramLI; /* Param list representing current args */
|
ParamListInfo paramLI; /* Param list representing current args */
|
||||||
@ -167,6 +168,8 @@ init_sql_fcache(FmgrInfo *finfo)
|
|||||||
format_type_be(procedureStruct->prorettype))));
|
format_type_be(procedureStruct->prorettype))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fcache->rettype = rettype;
|
||||||
|
|
||||||
/* Now look up the actual result type */
|
/* Now look up the actual result type */
|
||||||
typeTuple = SearchSysCache(TYPEOID,
|
typeTuple = SearchSysCache(TYPEOID,
|
||||||
ObjectIdGetDatum(rettype),
|
ObjectIdGetDatum(rettype),
|
||||||
@ -389,20 +392,36 @@ postquel_execute(execution_state *es,
|
|||||||
* Probably OK to leave them, as long as they are at the end.
|
* Probably OK to leave them, as long as they are at the end.
|
||||||
*/
|
*/
|
||||||
HeapTupleHeader dtup;
|
HeapTupleHeader dtup;
|
||||||
|
Oid dtuptype;
|
||||||
|
int32 dtuptypmod;
|
||||||
|
|
||||||
dtup = (HeapTupleHeader) palloc(tup->t_len);
|
dtup = (HeapTupleHeader) palloc(tup->t_len);
|
||||||
memcpy((char *) dtup, (char *) tup->t_data, tup->t_len);
|
memcpy((char *) dtup, (char *) tup->t_data, tup->t_len);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For RECORD results, make sure a typmod has been assigned.
|
* Use the declared return type if it's not RECORD; else take
|
||||||
|
* the type from the computed result, making sure a typmod has
|
||||||
|
* been assigned.
|
||||||
*/
|
*/
|
||||||
if (tupDesc->tdtypeid == RECORDOID &&
|
if (fcache->rettype != RECORDOID)
|
||||||
tupDesc->tdtypmod < 0)
|
{
|
||||||
assign_record_type_typmod(tupDesc);
|
/* function has a named composite return type */
|
||||||
|
dtuptype = fcache->rettype;
|
||||||
|
dtuptypmod = -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* function is declared to return RECORD */
|
||||||
|
if (tupDesc->tdtypeid == RECORDOID &&
|
||||||
|
tupDesc->tdtypmod < 0)
|
||||||
|
assign_record_type_typmod(tupDesc);
|
||||||
|
dtuptype = tupDesc->tdtypeid;
|
||||||
|
dtuptypmod = tupDesc->tdtypmod;
|
||||||
|
}
|
||||||
|
|
||||||
HeapTupleHeaderSetDatumLength(dtup, tup->t_len);
|
HeapTupleHeaderSetDatumLength(dtup, tup->t_len);
|
||||||
HeapTupleHeaderSetTypeId(dtup, tupDesc->tdtypeid);
|
HeapTupleHeaderSetTypeId(dtup, dtuptype);
|
||||||
HeapTupleHeaderSetTypMod(dtup, tupDesc->tdtypmod);
|
HeapTupleHeaderSetTypMod(dtup, dtuptypmod);
|
||||||
|
|
||||||
value = PointerGetDatum(dtup);
|
value = PointerGetDatum(dtup);
|
||||||
fcinfo->isnull = false;
|
fcinfo->isnull = false;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user