]> granicus.if.org Git - postgresql/commitdiff
When returning type "record", replace use of pgresultGetTupleDesc
authorJoe Conway <mail@joeconway.com>
Tue, 24 Feb 2004 06:07:52 +0000 (06:07 +0000)
committerJoe Conway <mail@joeconway.com>
Tue, 24 Feb 2004 06:07:52 +0000 (06:07 +0000)
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.

contrib/dblink/dblink.c

index 463eb0f510a76497c910047f591838977e4d328d..a7f2aead50ef8f97de3f78c4a2191b6356516b8d 100644 (file)
@@ -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