Here is a patch for Composite and Set returning function support. I made
authorBruce Momjian
Thu, 20 Jun 2002 17:19:08 +0000 (17:19 +0000)
committerBruce Momjian
Thu, 20 Jun 2002 17:19:08 +0000 (17:19 +0000)
two small changes to the API since last patch, which hopefully completes
the decoupling of composite function support from SRF specific support.

Joe Conway

src/backend/access/common/tupdesc.c
src/backend/executor/execTuples.c
src/backend/utils/adt/regproc.c
src/backend/utils/fmgr/Makefile
src/include/utils/builtins.h

index 605ffb1bed7960b33cba4377ae8936ba7dcd8710..8bd1d7b529995bd0be994709e584f35419c37696 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.78 2002/03/29 19:05:59 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.79 2002/06/20 17:19:08 momjian Exp $
  *
  * NOTES
  *   some of the executor utility code such as "ExecTypeFromTL" should be
@@ -19,6 +19,9 @@
 
 #include "postgres.h"
 
+#include "funcapi.h"
+#include "access/heapam.h"
+#include "catalog/namespace.h"
 #include "catalog/pg_type.h"
 #include "nodes/parsenodes.h"
 #include "parser/parse_type.h"
@@ -549,3 +552,109 @@ BuildDescForRelation(List *schema)
    }
    return desc;
 }
+
+
+/*
+ * RelationNameGetTupleDesc
+ *
+ * Given a (possibly qualified) relation name, build a TupleDesc.
+ */
+TupleDesc
+RelationNameGetTupleDesc(char *relname)
+{
+   RangeVar   *relvar;
+   Relation    rel;
+   TupleDesc   tupdesc;
+   List       *relname_list;
+
+   /* Open relation and get the tuple description */
+   relname_list = stringToQualifiedNameList(relname, "RelationNameGetTupleDesc");
+   relvar = makeRangeVarFromNameList(relname_list);
+   rel = heap_openrv(relvar, AccessShareLock);
+   tupdesc = CreateTupleDescCopy(RelationGetDescr(rel));
+   relation_close(rel, AccessShareLock);
+
+   return tupdesc;
+}
+
+/*
+ * TypeGetTupleDesc
+ *
+ * Given a type Oid, build a TupleDesc.
+ *
+ * If the type is composite, *and* a colaliases List is provided, *and*
+ * the List is of natts length, use the aliases instead of the relation
+ * attnames.
+ *
+ * If the type is a base type, a single item alias List is required.
+ */
+TupleDesc
+TypeGetTupleDesc(Oid typeoid, List *colaliases)
+{
+   Oid         relid = typeidTypeRelid(typeoid);
+   TupleDesc   tupdesc;
+
+   /*
+    * Build a suitable tupledesc representing the output rows
+    */
+   if (OidIsValid(relid))
+   {
+       /* Composite data type, i.e. a table's row type */
+       Relation    rel;
+       int         natts;
+
+       rel = relation_open(relid, AccessShareLock);
+       tupdesc = CreateTupleDescCopy(RelationGetDescr(rel));
+       natts = tupdesc->natts;
+       relation_close(rel, AccessShareLock);
+
+       /* check to see if we've given column aliases */
+       if(colaliases != NIL)
+       {
+           char       *label;
+           int         varattno;
+
+           /* does the List length match the number of attributes */
+           if (length(colaliases) != natts)
+               elog(ERROR, "TypeGetTupleDesc: number of aliases does not match number of attributes");
+
+           /* OK, use the aliases instead */
+           for (varattno = 0; varattno < natts; varattno++)
+           {
+               label = strVal(nth(varattno, colaliases));
+
+               if (label != NULL)
+                   namestrcpy(&(tupdesc->attrs[varattno]->attname), label);
+               else
+                   MemSet(NameStr(tupdesc->attrs[varattno]->attname), 0, NAMEDATALEN);
+           }
+       }
+   }
+   else
+   {
+       /* Must be a base data type, i.e. scalar */
+       char       *attname;
+
+       /* the alias List is required for base types */
+       if (colaliases == NIL)
+           elog(ERROR, "TypeGetTupleDesc: no column alias was provided");
+
+       /* the alias List length must be 1 */
+       if (length(colaliases) != 1)
+           elog(ERROR, "TypeGetTupleDesc: number of aliases does not match number of attributes");
+
+       /* OK, get the column alias */
+       attname = strVal(lfirst(colaliases));
+
+       tupdesc = CreateTemplateTupleDesc(1);
+       TupleDescInitEntry(tupdesc,
+                          (AttrNumber) 1,
+                          attname,
+                          typeoid,
+                          -1,
+                          0,
+                          false);
+   }
+
+   return tupdesc;
+}
index 504876e738fff656f39a6bb6ace61f6918b6eee4..85efe1d69fde9f92e5e4d1535b3e9269d6afdd35 100644 (file)
@@ -15,7 +15,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.51 2002/03/21 06:21:04 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.52 2002/06/20 17:19:08 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
  */
 #include "postgres.h"
 
+#include "funcapi.h"
 #include "access/heapam.h"
 #include "catalog/pg_type.h"
 #include "executor/executor.h"
 
-
 /* ----------------------------------------------------------------
  *               tuple table create/delete functions
  * ----------------------------------------------------------------
@@ -673,3 +673,123 @@ ExecTypeFromTL(List *targetList)
 
    return typeInfo;
 }
+
+/*
+ * TupleDescGetSlot - Initialize a slot based on the supplied
+ * tupledesc
+ */
+TupleTableSlot *
+TupleDescGetSlot(TupleDesc tupdesc)
+{
+   TupleTableSlot     *slot;
+
+   /* Make a standalone slot */
+   slot = MakeTupleTableSlot();
+
+   /* Bind the tuple description to the slot */
+   ExecSetSlotDescriptor(slot, tupdesc, true);
+
+   /* Return the slot */
+   return slot;
+}
+
+/*
+ * TupleDescGetAttInMetadata - Get a pointer to AttInMetadata based on the
+ * supplied TupleDesc. AttInMetadata can be used in conjunction with C strings
+ * to produce a properly formed tuple.
+ */
+AttInMetadata *
+TupleDescGetAttInMetadata(TupleDesc tupdesc)
+{
+   int             natts;
+   int             i;
+   Oid             atttypeid;
+   Oid             attinfuncid;
+   Oid             attelem;
+   FmgrInfo       *attinfuncinfo;
+   Oid            *attelems;
+   int4           *atttypmods;
+   AttInMetadata  *attinmeta;
+
+   attinmeta = (AttInMetadata *) palloc(sizeof(AttInMetadata));
+   natts = tupdesc->natts;
+
+   /*
+    * Gather info needed later to call the "in" function for each attribute
+    */
+   attinfuncinfo = (FmgrInfo *) palloc(natts * sizeof(FmgrInfo));
+   attelems = (Oid *) palloc(natts * sizeof(Oid));
+   atttypmods = (int4 *) palloc(natts * sizeof(int4));
+
+   for (i = 0; i < natts; i++)
+   {
+       atttypeid = tupdesc->attrs[i]->atttypid;
+       get_type_metadata(atttypeid, &attinfuncid, &attelem);
+
+       fmgr_info(attinfuncid, &attinfuncinfo[i]);
+       attelems[i] = attelem;
+       atttypmods[i] = tupdesc->attrs[i]->atttypmod;
+   }
+   attinmeta->tupdesc = tupdesc;
+   attinmeta->attinfuncs = attinfuncinfo;
+   attinmeta->attelems = attelems;
+   attinmeta->atttypmods = atttypmods;
+
+   return attinmeta;
+}
+
+/*
+ * BuildTupleFromCStrings - build a HeapTuple given user data in C string form.
+ * values is an array of C strings, one for each attribute of the return tuple.
+ */
+HeapTuple
+BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)
+{
+   TupleDesc           tupdesc;
+   int                 natts;
+   HeapTuple           tuple;
+   char               *nulls;
+   int                 i;
+   Datum              *dvalues;
+   FmgrInfo            attinfuncinfo;
+   Oid                 attelem;
+   int4                atttypmod;
+
+   tupdesc = attinmeta->tupdesc;
+   natts = tupdesc->natts;
+
+   dvalues = (Datum *) palloc(natts * sizeof(Datum));
+
+   /* Call the "in" function for each attribute */
+   for (i = 0; i < natts; i++)
+   {
+       if (values[i] != NULL)
+       {
+           attinfuncinfo = attinmeta->attinfuncs[i];
+           attelem = attinmeta->attelems[i];
+           atttypmod = attinmeta->atttypmods[i];
+
+           dvalues[i] = FunctionCall3(&attinfuncinfo, CStringGetDatum(values[i]),
+                                       ObjectIdGetDatum(attelem),
+                                       Int32GetDatum(atttypmod));
+       }
+       else
+           dvalues[i] = PointerGetDatum(NULL);
+   }
+
+   /*
+    * Form a tuple
+    */
+   nulls = (char *) palloc(natts * sizeof(char));
+   for (i = 0; i < natts; i++)
+   {
+       if (DatumGetPointer(dvalues[i]) != NULL)
+           nulls[i] = ' ';
+       else
+           nulls[i] = 'n';
+   }
+   tuple = heap_formtuple(tupdesc, dvalues, nulls);
+
+   return tuple;
+}
+
index f9de2677969d9a8a506f2f80a49642c52d4c5744..0858d63f60ba268f8ce0a50b39847f73553a96fa 100644 (file)
@@ -13,7 +13,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/utils/adt/regproc.c,v 1.68 2002/05/11 00:24:16 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/utils/adt/regproc.c,v 1.69 2002/06/20 17:19:08 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -37,8 +37,6 @@
 #include "utils/lsyscache.h"
 #include "utils/syscache.h"
 
-
-static List *stringToQualifiedNameList(const char *string, const char *caller);
 static void parseNameAndArgTypes(const char *string, const char *caller,
                                 const char *type0_spelling,
                                 List **names, int *nargs, Oid *argtypes);
@@ -960,14 +958,10 @@ regtypeout(PG_FUNCTION_ARGS)
 }
 
 
-/*****************************************************************************
- *  SUPPORT ROUTINES                                                        *
- *****************************************************************************/
-
 /*
  * Given a C string, parse it into a qualified-name list.
  */
-static List *
+List *
 stringToQualifiedNameList(const char *string, const char *caller)
 {
    char       *rawname;
@@ -997,6 +991,10 @@ stringToQualifiedNameList(const char *string, const char *caller)
    return result;
 }
 
+/*****************************************************************************
+ *  SUPPORT ROUTINES                                                        *
+ *****************************************************************************/
+
 /*
  * Given a C string, parse it into a qualified function or operator name
  * followed by a parenthesized list of type names.  Reduce the
index ad96b1717db0b988e6e6fefa6369ba7ca473ac73..13dd9110292d22c18ae7d58ac8fb2885f214c7cf 100644 (file)
@@ -4,7 +4,7 @@
 #    Makefile for utils/fmgr
 #
 # IDENTIFICATION
-#    $Header: /cvsroot/pgsql/src/backend/utils/fmgr/Makefile,v 1.12 2001/09/16 16:11:11 petere Exp $
+#    $Header: /cvsroot/pgsql/src/backend/utils/fmgr/Makefile,v 1.13 2002/06/20 17:19:08 momjian Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -12,7 +12,7 @@ subdir = src/backend/utils/fmgr
 top_builddir = ../../../..
 include $(top_builddir)/src/Makefile.global
 
-OBJS = dfmgr.o fmgr.o
+OBJS = dfmgr.o fmgr.o funcapi.o
 
 override CPPFLAGS += -DPKGLIBDIR=\"$(pkglibdir)\" -DDLSUFFIX=\"$(DLSUFFIX)\"
 
index 28ab44ce68b3b3a5e549044e8aa3ecc0f3c78e68..898f3b6047dd58a9b8f5e3f23b8106dbae4d0410 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: builtins.h,v 1.184 2002/06/13 03:40:49 tgl Exp $
+ * $Id: builtins.h,v 1.185 2002/06/20 17:19:08 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -342,6 +342,7 @@ extern Datum regclassin(PG_FUNCTION_ARGS);
 extern Datum regclassout(PG_FUNCTION_ARGS);
 extern Datum regtypein(PG_FUNCTION_ARGS);
 extern Datum regtypeout(PG_FUNCTION_ARGS);
+extern List *stringToQualifiedNameList(const char *string, const char *caller);
 
 /* ruleutils.c */
 extern Datum pg_get_ruledef(PG_FUNCTION_ARGS);