aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoe Conway <mail@joeconway.com>2004-02-24 06:07:34 +0000
committerJoe Conway <mail@joeconway.com>2004-02-24 06:07:34 +0000
commit27ae96c2b63c6ba68a2b8776cdd478dc779b641d (patch)
treebbc03dbbfcc55c4c20ce10eb742eabae77774c80
parent78c97b156ecb697e4bda3bb3fb4a9684458d7019 (diff)
downloadpostgresql-27ae96c2b63c6ba68a2b8776cdd478dc779b641d.tar.gz
postgresql-27ae96c2b63c6ba68a2b8776cdd478dc779b641d.zip
When returning type "record", replace use of pgresultGetTupleDesc
with ReturnSetInfo->expectedDesc. This allows custom datatypes (e.g. from tsearch2) to be returned at runtime. Previous behavior depended on the type oid to match between the remote and local database, which obviously doesn't work well for custom types. Per report from Mark Gibson.
-rw-r--r--contrib/dblink/dblink.c82
1 files changed, 22 insertions, 60 deletions
diff --git a/contrib/dblink/dblink.c b/contrib/dblink/dblink.c
index ad5365595c7..3fea501b60c 100644
--- a/contrib/dblink/dblink.c
+++ b/contrib/dblink/dblink.c
@@ -82,7 +82,6 @@ static char *quote_ident_cstr(char *rawstr);
static int16 get_attnum_pk_pos(int16 *pkattnums, int16 pknumatts, int16 key);
static HeapTuple get_tuple_of_interest(Oid relid, int16 *pkattnums, int16 pknumatts, char **src_pkattvals);
static Oid get_relid_from_relname(text *relname_text);
-static TupleDesc pgresultGetTupleDesc(PGresult *res);
static char *generate_relation_name(Oid relid);
/* Global */
@@ -395,6 +394,7 @@ dblink_fetch(PG_FUNCTION_ARGS)
StringInfo str = makeStringInfo();
char *curname = NULL;
int howmany = 0;
+ ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
if (PG_NARGS() == 3)
{
@@ -457,7 +457,16 @@ 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))
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("function returning record called in context "
+ "that cannot accept type record")));
+
+ /* get the requested return tuple description */
+ tupdesc = CreateTupleDescCopy(rsinfo->expectedDesc);
+ }
else
/* shouldn't happen */
elog(ERROR, "return type must be a row type");
@@ -550,6 +559,7 @@ dblink_record(PG_FUNCTION_ARGS)
char *sql = NULL;
char *conname = NULL;
remoteConn *rcon = NULL;
+ ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
/* create a function context for cross-call persistence */
funcctx = SRF_FIRSTCALL_INIT();
@@ -620,7 +630,16 @@ 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))
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("function returning record called in context "
+ "that cannot accept type record")));
+
+ /* get the requested return tuple description */
+ tupdesc = CreateTupleDescCopy(rsinfo->expectedDesc);
+ }
else
/* shouldn't happen */
elog(ERROR, "return type must be a row type");
@@ -1801,63 +1820,6 @@ get_relid_from_relname(text *relname_text)
return relid;
}
-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)
- /* shouldn't happen */
- 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))
- ereport(ERROR,
- (errcode(ERRCODE_MOST_SPECIFIC_TYPE_MISMATCH),
- errmsg("field size mismatch"),
- errdetail("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