diff --git a/contrib/dblink/dblink.c b/contrib/dblink/dblink.c index 463eb0f510a..a7f2aead50e 100644 --- a/contrib/dblink/dblink.c +++ b/contrib/dblink/dblink.c @@ -70,7 +70,6 @@ static Oid get_relid_from_relname(text *relname_text); static dblink_results *get_res_ptr(int32 res_id_index); static void append_res_ptr(dblink_results * results); static void remove_res_ptr(dblink_results * results); -static TupleDesc pgresultGetTupleDesc(PGresult *res); static char *generate_relation_name(Oid relid); /* Global */ @@ -273,6 +272,7 @@ dblink_fetch(PG_FUNCTION_ARGS) StringInfo str = makeStringInfo(); char *curname = GET_STR(PG_GETARG_TEXT_P(0)); int howmany = PG_GETARG_INT32(1); + ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo; /* create a function context for cross-call persistence */ funcctx = SRF_FIRSTCALL_INIT(); @@ -326,7 +326,14 @@ dblink_fetch(PG_FUNCTION_ARGS) if (functyptype == 'c') tupdesc = TypeGetTupleDesc(functypeid, NIL); else if (functyptype == 'p' && functypeid == RECORDOID) - tupdesc = pgresultGetTupleDesc(res); + { + if (!rsinfo || !IsA(rsinfo, ReturnSetInfo)) + elog(ERROR, "function returning record called in context " + "that cannot accept type record"); + + /* get the requested return tuple description */ + tupdesc = CreateTupleDescCopy(rsinfo->expectedDesc); + } else if (functyptype == 'b') elog(ERROR, "dblink_fetch: invalid kind of return type specified for function"); else @@ -417,6 +424,7 @@ dblink_record(PG_FUNCTION_ARGS) PGconn *conn = NULL; char *connstr = NULL; char *sql = NULL; + ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo; /* create a function context for cross-call persistence */ funcctx = SRF_FIRSTCALL_INIT(); @@ -505,7 +513,14 @@ dblink_record(PG_FUNCTION_ARGS) if (functyptype == 'c') tupdesc = TypeGetTupleDesc(functypeid, NIL); else if (functyptype == 'p' && functypeid == RECORDOID) - tupdesc = pgresultGetTupleDesc(res); + { + if (!rsinfo || !IsA(rsinfo, ReturnSetInfo)) + elog(ERROR, "function returning record called in context " + "that cannot accept type record"); + + /* get the requested return tuple description */ + tupdesc = CreateTupleDescCopy(rsinfo->expectedDesc); + } else if (functyptype == 'b') elog(ERROR, "Invalid kind of return type specified for function"); else @@ -1964,59 +1979,6 @@ remove_res_ptr(dblink_results * results) res_id_index = 0; } -static TupleDesc -pgresultGetTupleDesc(PGresult *res) -{ - int natts; - AttrNumber attnum; - TupleDesc desc; - char *attname; - int32 atttypmod; - int attdim; - bool attisset; - Oid atttypid; - int i; - - /* - * allocate a new tuple descriptor - */ - natts = PQnfields(res); - if (natts < 1) - elog(ERROR, "cannot create a description for empty results"); - - desc = CreateTemplateTupleDesc(natts, false); - - attnum = 0; - - for (i = 0; i < natts; i++) - { - /* - * for each field, get the name and type information from the - * query result and have TupleDescInitEntry fill in the attribute - * information we need. - */ - attnum++; - - attname = PQfname(res, i); - atttypid = PQftype(res, i); - atttypmod = PQfmod(res, i); - - if (PQfsize(res, i) != get_typlen(atttypid)) - elog(ERROR, "Size of remote field \"%s\" does not match size " - "of local type \"%s\"", - attname, - format_type_with_typemod(atttypid, atttypmod)); - - attdim = 0; - attisset = false; - - TupleDescInitEntry(desc, attnum, attname, atttypid, - atttypmod, attdim, attisset); - } - - return desc; -} - /* * generate_relation_name - copied from ruleutils.c * Compute the name to display for a relation specified by OID