From ba790a5608ead9db7e08f700eb869dbefd3358a4 Mon Sep 17 00:00:00 2001 From: Bruce Momjian Date: Thu, 20 Jun 2002 17:19:08 +0000 Subject: [PATCH] Here is a patch for Composite and Set returning function support. I made 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 | 111 ++++++++++++++++++++++++- src/backend/executor/execTuples.c | 124 +++++++++++++++++++++++++++- src/backend/utils/adt/regproc.c | 14 ++-- src/backend/utils/fmgr/Makefile | 4 +- src/include/utils/builtins.h | 3 +- 5 files changed, 242 insertions(+), 14 deletions(-) diff --git a/src/backend/access/common/tupdesc.c b/src/backend/access/common/tupdesc.c index 605ffb1bed..8bd1d7b529 100644 --- a/src/backend/access/common/tupdesc.c +++ b/src/backend/access/common/tupdesc.c @@ -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; +} diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c index 504876e738..85efe1d69f 100644 --- a/src/backend/executor/execTuples.c +++ b/src/backend/executor/execTuples.c @@ -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 $ * *------------------------------------------------------------------------- */ @@ -107,11 +107,11 @@ */ #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; +} + diff --git a/src/backend/utils/adt/regproc.c b/src/backend/utils/adt/regproc.c index f9de267796..0858d63f60 100644 --- a/src/backend/utils/adt/regproc.c +++ b/src/backend/utils/adt/regproc.c @@ -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 diff --git a/src/backend/utils/fmgr/Makefile b/src/backend/utils/fmgr/Makefile index ad96b1717d..13dd911029 100644 --- a/src/backend/utils/fmgr/Makefile +++ b/src/backend/utils/fmgr/Makefile @@ -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)\" diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h index 28ab44ce68..898f3b6047 100644 --- a/src/include/utils/builtins.h +++ b/src/include/utils/builtins.h @@ -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);