aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoe Conway <mail@joeconway.com>2004-02-24 06:07:52 +0000
committerJoe Conway <mail@joeconway.com>2004-02-24 06:07:52 +0000
commita7e5e2fe740fc1b8a111df9494ba8adfe4eec7ca (patch)
treebd59a43fae8e7997dfdc8b54b607f62640e6a847
parent7ce7e3f03699e87517826275a4ed2c2f2c5a177a (diff)
downloadpostgresql-a7e5e2fe740fc1b8a111df9494ba8adfe4eec7ca.tar.gz
postgresql-a7e5e2fe740fc1b8a111df9494ba8adfe4eec7ca.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.c74
1 files changed, 18 insertions, 56 deletions
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