Skip to content

Commit ba790a5

Browse files
committed
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
1 parent bffc4b6 commit ba790a5

File tree

5 files changed

+242
-14
lines changed

5 files changed

+242
-14
lines changed

src/backend/access/common/tupdesc.c

+110-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.78 2002/03/29 19:05:59 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.79 2002/06/20 17:19:08 momjian Exp $
1212
*
1313
* NOTES
1414
* some of the executor utility code such as "ExecTypeFromTL" should be
@@ -19,6 +19,9 @@
1919

2020
#include "postgres.h"
2121

22+
#include "funcapi.h"
23+
#include "access/heapam.h"
24+
#include "catalog/namespace.h"
2225
#include "catalog/pg_type.h"
2326
#include "nodes/parsenodes.h"
2427
#include "parser/parse_type.h"
@@ -549,3 +552,109 @@ BuildDescForRelation(List *schema)
549552
}
550553
return desc;
551554
}
555+
556+
557+
/*
558+
* RelationNameGetTupleDesc
559+
*
560+
* Given a (possibly qualified) relation name, build a TupleDesc.
561+
*/
562+
TupleDesc
563+
RelationNameGetTupleDesc(char *relname)
564+
{
565+
RangeVar *relvar;
566+
Relation rel;
567+
TupleDesc tupdesc;
568+
List *relname_list;
569+
570+
/* Open relation and get the tuple description */
571+
relname_list = stringToQualifiedNameList(relname, "RelationNameGetTupleDesc");
572+
relvar = makeRangeVarFromNameList(relname_list);
573+
rel = heap_openrv(relvar, AccessShareLock);
574+
tupdesc = CreateTupleDescCopy(RelationGetDescr(rel));
575+
relation_close(rel, AccessShareLock);
576+
577+
return tupdesc;
578+
}
579+
580+
/*
581+
* TypeGetTupleDesc
582+
*
583+
* Given a type Oid, build a TupleDesc.
584+
*
585+
* If the type is composite, *and* a colaliases List is provided, *and*
586+
* the List is of natts length, use the aliases instead of the relation
587+
* attnames.
588+
*
589+
* If the type is a base type, a single item alias List is required.
590+
*/
591+
TupleDesc
592+
TypeGetTupleDesc(Oid typeoid, List *colaliases)
593+
{
594+
Oid relid = typeidTypeRelid(typeoid);
595+
TupleDesc tupdesc;
596+
597+
/*
598+
* Build a suitable tupledesc representing the output rows
599+
*/
600+
if (OidIsValid(relid))
601+
{
602+
/* Composite data type, i.e. a table's row type */
603+
Relation rel;
604+
int natts;
605+
606+
rel = relation_open(relid, AccessShareLock);
607+
tupdesc = CreateTupleDescCopy(RelationGetDescr(rel));
608+
natts = tupdesc->natts;
609+
relation_close(rel, AccessShareLock);
610+
611+
/* check to see if we've given column aliases */
612+
if(colaliases != NIL)
613+
{
614+
char *label;
615+
int varattno;
616+
617+
/* does the List length match the number of attributes */
618+
if (length(colaliases) != natts)
619+
elog(ERROR, "TypeGetTupleDesc: number of aliases does not match number of attributes");
620+
621+
/* OK, use the aliases instead */
622+
for (varattno = 0; varattno < natts; varattno++)
623+
{
624+
label = strVal(nth(varattno, colaliases));
625+
626+
if (label != NULL)
627+
namestrcpy(&(tupdesc->attrs[varattno]->attname), label);
628+
else
629+
MemSet(NameStr(tupdesc->attrs[varattno]->attname), 0, NAMEDATALEN);
630+
}
631+
}
632+
}
633+
else
634+
{
635+
/* Must be a base data type, i.e. scalar */
636+
char *attname;
637+
638+
/* the alias List is required for base types */
639+
if (colaliases == NIL)
640+
elog(ERROR, "TypeGetTupleDesc: no column alias was provided");
641+
642+
/* the alias List length must be 1 */
643+
if (length(colaliases) != 1)
644+
elog(ERROR, "TypeGetTupleDesc: number of aliases does not match number of attributes");
645+
646+
/* OK, get the column alias */
647+
attname = strVal(lfirst(colaliases));
648+
649+
tupdesc = CreateTemplateTupleDesc(1);
650+
TupleDescInitEntry(tupdesc,
651+
(AttrNumber) 1,
652+
attname,
653+
typeoid,
654+
-1,
655+
0,
656+
false);
657+
}
658+
659+
return tupdesc;
660+
}

src/backend/executor/execTuples.c

+122-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*
1616
*
1717
* IDENTIFICATION
18-
* $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.51 2002/03/21 06:21:04 tgl Exp $
18+
* $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.52 2002/06/20 17:19:08 momjian Exp $
1919
*
2020
*-------------------------------------------------------------------------
2121
*/
@@ -107,11 +107,11 @@
107107
*/
108108
#include "postgres.h"
109109

110+
#include "funcapi.h"
110111
#include "access/heapam.h"
111112
#include "catalog/pg_type.h"
112113
#include "executor/executor.h"
113114

114-
115115
/* ----------------------------------------------------------------
116116
* tuple table create/delete functions
117117
* ----------------------------------------------------------------
@@ -673,3 +673,123 @@ ExecTypeFromTL(List *targetList)
673673

674674
return typeInfo;
675675
}
676+
677+
/*
678+
* TupleDescGetSlot - Initialize a slot based on the supplied
679+
* tupledesc
680+
*/
681+
TupleTableSlot *
682+
TupleDescGetSlot(TupleDesc tupdesc)
683+
{
684+
TupleTableSlot *slot;
685+
686+
/* Make a standalone slot */
687+
slot = MakeTupleTableSlot();
688+
689+
/* Bind the tuple description to the slot */
690+
ExecSetSlotDescriptor(slot, tupdesc, true);
691+
692+
/* Return the slot */
693+
return slot;
694+
}
695+
696+
/*
697+
* TupleDescGetAttInMetadata - Get a pointer to AttInMetadata based on the
698+
* supplied TupleDesc. AttInMetadata can be used in conjunction with C strings
699+
* to produce a properly formed tuple.
700+
*/
701+
AttInMetadata *
702+
TupleDescGetAttInMetadata(TupleDesc tupdesc)
703+
{
704+
int natts;
705+
int i;
706+
Oid atttypeid;
707+
Oid attinfuncid;
708+
Oid attelem;
709+
FmgrInfo *attinfuncinfo;
710+
Oid *attelems;
711+
int4 *atttypmods;
712+
AttInMetadata *attinmeta;
713+
714+
attinmeta = (AttInMetadata *) palloc(sizeof(AttInMetadata));
715+
natts = tupdesc->natts;
716+
717+
/*
718+
* Gather info needed later to call the "in" function for each attribute
719+
*/
720+
attinfuncinfo = (FmgrInfo *) palloc(natts * sizeof(FmgrInfo));
721+
attelems = (Oid *) palloc(natts * sizeof(Oid));
722+
atttypmods = (int4 *) palloc(natts * sizeof(int4));
723+
724+
for (i = 0; i < natts; i++)
725+
{
726+
atttypeid = tupdesc->attrs[i]->atttypid;
727+
get_type_metadata(atttypeid, &attinfuncid, &attelem);
728+
729+
fmgr_info(attinfuncid, &attinfuncinfo[i]);
730+
attelems[i] = attelem;
731+
atttypmods[i] = tupdesc->attrs[i]->atttypmod;
732+
}
733+
attinmeta->tupdesc = tupdesc;
734+
attinmeta->attinfuncs = attinfuncinfo;
735+
attinmeta->attelems = attelems;
736+
attinmeta->atttypmods = atttypmods;
737+
738+
return attinmeta;
739+
}
740+
741+
/*
742+
* BuildTupleFromCStrings - build a HeapTuple given user data in C string form.
743+
* values is an array of C strings, one for each attribute of the return tuple.
744+
*/
745+
HeapTuple
746+
BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)
747+
{
748+
TupleDesc tupdesc;
749+
int natts;
750+
HeapTuple tuple;
751+
char *nulls;
752+
int i;
753+
Datum *dvalues;
754+
FmgrInfo attinfuncinfo;
755+
Oid attelem;
756+
int4 atttypmod;
757+
758+
tupdesc = attinmeta->tupdesc;
759+
natts = tupdesc->natts;
760+
761+
dvalues = (Datum *) palloc(natts * sizeof(Datum));
762+
763+
/* Call the "in" function for each attribute */
764+
for (i = 0; i < natts; i++)
765+
{
766+
if (values[i] != NULL)
767+
{
768+
attinfuncinfo = attinmeta->attinfuncs[i];
769+
attelem = attinmeta->attelems[i];
770+
atttypmod = attinmeta->atttypmods[i];
771+
772+
dvalues[i] = FunctionCall3(&attinfuncinfo, CStringGetDatum(values[i]),
773+
ObjectIdGetDatum(attelem),
774+
Int32GetDatum(atttypmod));
775+
}
776+
else
777+
dvalues[i] = PointerGetDatum(NULL);
778+
}
779+
780+
/*
781+
* Form a tuple
782+
*/
783+
nulls = (char *) palloc(natts * sizeof(char));
784+
for (i = 0; i < natts; i++)
785+
{
786+
if (DatumGetPointer(dvalues[i]) != NULL)
787+
nulls[i] = ' ';
788+
else
789+
nulls[i] = 'n';
790+
}
791+
tuple = heap_formtuple(tupdesc, dvalues, nulls);
792+
793+
return tuple;
794+
}
795+

src/backend/utils/adt/regproc.c

+6-8
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
*
1414
*
1515
* IDENTIFICATION
16-
* $Header: /cvsroot/pgsql/src/backend/utils/adt/regproc.c,v 1.68 2002/05/11 00:24:16 tgl Exp $
16+
* $Header: /cvsroot/pgsql/src/backend/utils/adt/regproc.c,v 1.69 2002/06/20 17:19:08 momjian Exp $
1717
*
1818
*-------------------------------------------------------------------------
1919
*/
@@ -37,8 +37,6 @@
3737
#include "utils/lsyscache.h"
3838
#include "utils/syscache.h"
3939

40-
41-
static List *stringToQualifiedNameList(const char *string, const char *caller);
4240
static void parseNameAndArgTypes(const char *string, const char *caller,
4341
const char *type0_spelling,
4442
List **names, int *nargs, Oid *argtypes);
@@ -960,14 +958,10 @@ regtypeout(PG_FUNCTION_ARGS)
960958
}
961959

962960

963-
/*****************************************************************************
964-
* SUPPORT ROUTINES *
965-
*****************************************************************************/
966-
967961
/*
968962
* Given a C string, parse it into a qualified-name list.
969963
*/
970-
static List *
964+
List *
971965
stringToQualifiedNameList(const char *string, const char *caller)
972966
{
973967
char *rawname;
@@ -997,6 +991,10 @@ stringToQualifiedNameList(const char *string, const char *caller)
997991
return result;
998992
}
999993

994+
/*****************************************************************************
995+
* SUPPORT ROUTINES *
996+
*****************************************************************************/
997+
1000998
/*
1001999
* Given a C string, parse it into a qualified function or operator name
10021000
* followed by a parenthesized list of type names. Reduce the

src/backend/utils/fmgr/Makefile

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@
44
# Makefile for utils/fmgr
55
#
66
# IDENTIFICATION
7-
# $Header: /cvsroot/pgsql/src/backend/utils/fmgr/Makefile,v 1.12 2001/09/16 16:11:11 petere Exp $
7+
# $Header: /cvsroot/pgsql/src/backend/utils/fmgr/Makefile,v 1.13 2002/06/20 17:19:08 momjian Exp $
88
#
99
#-------------------------------------------------------------------------
1010

1111
subdir = src/backend/utils/fmgr
1212
top_builddir = ../../../..
1313
include $(top_builddir)/src/Makefile.global
1414

15-
OBJS = dfmgr.o fmgr.o
15+
OBJS = dfmgr.o fmgr.o funcapi.o
1616

1717
override CPPFLAGS += -DPKGLIBDIR=\"$(pkglibdir)\" -DDLSUFFIX=\"$(DLSUFFIX)\"
1818

src/include/utils/builtins.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $Id: builtins.h,v 1.184 2002/06/13 03:40:49 tgl Exp $
10+
* $Id: builtins.h,v 1.185 2002/06/20 17:19:08 momjian Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -342,6 +342,7 @@ extern Datum regclassin(PG_FUNCTION_ARGS);
342342
extern Datum regclassout(PG_FUNCTION_ARGS);
343343
extern Datum regtypein(PG_FUNCTION_ARGS);
344344
extern Datum regtypeout(PG_FUNCTION_ARGS);
345+
extern List *stringToQualifiedNameList(const char *string, const char *caller);
345346

346347
/* ruleutils.c */
347348
extern Datum pg_get_ruledef(PG_FUNCTION_ARGS);

0 commit comments

Comments
 (0)