Re: stand-alone composite types patch (was [HACKERS] Proposal:

From: Bruce Momjian <pgman(at)candle(dot)pha(dot)pa(dot)us>
To: Joe Conway <mail(at)joeconway(dot)com>
Cc: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>, Patches <pgsql-patches(at)postgresql(dot)org>
Subject: Re: stand-alone composite types patch (was [HACKERS] Proposal:
Date: 2002-08-15 16:35:26
Message-ID: 200208151635.g7FGZQN01768@candle.pha.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers pgsql-patches


Patch applied. Thanks.

---------------------------------------------------------------------------

Joe Conway wrote:
> Tom Lane wrote:
> > There's no longer a separate call to heap_storage_create in that routine
> > --- the right place to make the test is now in the storage_create
> > boolean parameter being passed to heap_create. A simple change, but
> > it passeth patch's understanding ...
>
> Thanks.
>
> Attached is a patch against cvs tip as of 8:30 PM PST or so. Turned out
> that even after fixing the failed hunks, there was a new spot in
> bufmgr.c which needed to be fixed (related to temp relations;
> RelationUpdateNumberOfBlocks). But thankfully the regression test code
> caught it :-)
>
> Joe
>

> Index: doc/src/sgml/ref/create_type.sgml
> ===================================================================
> RCS file: /opt/src/cvs/pgsql-server/doc/src/sgml/ref/create_type.sgml,v
> retrieving revision 1.30
> diff -c -r1.30 create_type.sgml
> *** doc/src/sgml/ref/create_type.sgml 24 Jul 2002 19:11:07 -0000 1.30
> --- doc/src/sgml/ref/create_type.sgml 15 Aug 2002 03:06:23 -0000
> ***************
> *** 30,35 ****
> --- 30,42 ----
> [ , ALIGNMENT = <replaceable class="parameter">alignment</replaceable> ]
> [ , STORAGE = <replaceable class="parameter">storage</replaceable> ]
> )
> +
> + CREATE TYPE <replaceable class="parameter">typename</replaceable> AS
> + ( <replaceable class="PARAMETER">column_definition_list</replaceable> )
> +
> + where <replaceable class="PARAMETER">column_definition_list</replaceable> can be:
> +
> + ( <replaceable class="PARAMETER">column_name</replaceable> <replaceable class="PARAMETER">data_type</replaceable> [, ... ] )
> </synopsis>
>
> <refsect2 id="R2-SQL-CREATETYPE-1">
> ***************
> *** 138,143 ****
> --- 145,169 ----
> </para>
> </listitem>
> </varlistentry>
> +
> + <varlistentry>
> + <term><replaceable class="PARAMETER">column_name</replaceable></term>
> + <listitem>
> + <para>
> + The name of a column of the composite type.
> + </para>
> + </listitem>
> + </varlistentry>
> +
> + <varlistentry>
> + <term><replaceable class="PARAMETER">data_type</replaceable></term>
> + <listitem>
> + <para>
> + The name of an existing data type.
> + </para>
> + </listitem>
> + </varlistentry>
> +
> </variablelist>
> </para>
> </refsect2>
> ***************
> *** 191,199 ****
> </para>
>
> <para>
> ! <command>CREATE TYPE</command> requires the registration of two functions
> ! (using CREATE FUNCTION) before defining the type. The
> ! representation of a new base type is determined by
> <replaceable class="parameter">input_function</replaceable>, which
> converts the type's external representation to an internal
> representation usable by the
> --- 217,225 ----
> </para>
>
> <para>
> ! The first form of <command>CREATE TYPE</command> requires the
> ! registration of two functions (using CREATE FUNCTION) before defining the
> ! type. The representation of a new base type is determined by
> <replaceable class="parameter">input_function</replaceable>, which
> converts the type's external representation to an internal
> representation usable by the
> ***************
> *** 288,293 ****
> --- 314,327 ----
> <literal>extended</literal> and <literal>external</literal> items.)
> </para>
>
> + <para>
> + The second form of <command>CREATE TYPE</command> requires a column
> + definition list in the form ( <replaceable class="PARAMETER">column_name</replaceable>
> + <replaceable class="PARAMETER">data_type</replaceable> [, ... ] ). This
> + creates a composite type, similar to that of a TABLE or VIEW relation.
> + A stand-alone composite type is useful as the return type of FUNCTION.
> + </para>
> +
> <refsect2>
> <title>Array Types</title>
>
> ***************
> *** 370,375 ****
> --- 404,418 ----
> CREATE TYPE bigobj (INPUT = lo_filein, OUTPUT = lo_fileout,
> INTERNALLENGTH = VARIABLE);
> CREATE TABLE big_objs (id int4, obj bigobj);
> + </programlisting>
> + </para>
> +
> + <para>
> + This example creates a composite type and uses it in
> + a table function definition:
> + <programlisting>
> + CREATE TYPE compfoo AS (f1 int, f2 int);
> + CREATE FUNCTION getfoo() RETURNS SETOF compfoo AS 'SELECT fooid, foorefid FROM foo' LANGUAGE SQL;
> </programlisting>
> </para>
> </refsect1>
> Index: src/backend/catalog/heap.c
> ===================================================================
> RCS file: /opt/src/cvs/pgsql-server/src/backend/catalog/heap.c,v
> retrieving revision 1.220
> diff -c -r1.220 heap.c
> *** src/backend/catalog/heap.c 11 Aug 2002 21:17:34 -0000 1.220
> --- src/backend/catalog/heap.c 15 Aug 2002 04:21:03 -0000
> ***************
> *** 357,365 ****
> /*
> * first check for collision with system attribute names
> *
> ! * Skip this for a view, since it doesn't have system attributes.
> */
> ! if (relkind != RELKIND_VIEW)
> {
> for (i = 0; i < natts; i++)
> {
> --- 357,366 ----
> /*
> * first check for collision with system attribute names
> *
> ! * Skip this for a view and type relation, since it doesn't have system
> ! * attributes.
> */
> ! if (relkind != RELKIND_VIEW && relkind != RELKIND_COMPOSITE_TYPE)
> {
> for (i = 0; i < natts; i++)
> {
> ***************
> *** 473,482 ****
>
> /*
> * Next we add the system attributes. Skip OID if rel has no OIDs.
> ! * Skip all for a view. We don't bother with making datatype
> ! * dependencies here, since presumably all these types are pinned.
> */
> ! if (relkind != RELKIND_VIEW)
> {
> dpp = SysAtt;
> for (i = 0; i < -1 - FirstLowInvalidHeapAttributeNumber; i++)
> --- 474,483 ----
>
> /*
> * Next we add the system attributes. Skip OID if rel has no OIDs.
> ! * Skip all for a view or type relation. We don't bother with making
> ! * datatype dependencies here, since presumably all these types are pinned.
> */
> ! if (relkind != RELKIND_VIEW && relkind != RELKIND_COMPOSITE_TYPE)
> {
> dpp = SysAtt;
> for (i = 0; i < -1 - FirstLowInvalidHeapAttributeNumber; i++)
> ***************
> *** 689,701 ****
> * physical disk file. (If we fail further down, it's the smgr's
> * responsibility to remove the disk file again.)
> *
> ! * NB: create a physical file only if it's not a view.
> */
> new_rel_desc = heap_create(relname,
> relnamespace,
> tupdesc,
> shared_relation,
> ! (relkind != RELKIND_VIEW),
> allow_system_table_mods);
>
> /* Fetch the relation OID assigned by heap_create */
> --- 690,703 ----
> * physical disk file. (If we fail further down, it's the smgr's
> * responsibility to remove the disk file again.)
> *
> ! * NB: create a physical file only if it's not a view or type relation.
> */
> new_rel_desc = heap_create(relname,
> relnamespace,
> tupdesc,
> shared_relation,
> ! (relkind != RELKIND_VIEW &&
> ! relkind != RELKIND_COMPOSITE_TYPE),
> allow_system_table_mods);
>
> /* Fetch the relation OID assigned by heap_create */
> ***************
> *** 1131,1137 ****
> /*
> * unlink the relation's physical file and finish up.
> */
> ! if (rel->rd_rel->relkind != RELKIND_VIEW)
> smgrunlink(DEFAULT_SMGR, rel);
>
> /*
> --- 1133,1140 ----
> /*
> * unlink the relation's physical file and finish up.
> */
> ! if (rel->rd_rel->relkind != RELKIND_VIEW &&
> ! rel->rd_rel->relkind != RELKIND_COMPOSITE_TYPE)
> smgrunlink(DEFAULT_SMGR, rel);
>
> /*
> Index: src/backend/catalog/namespace.c
> ===================================================================
> RCS file: /opt/src/cvs/pgsql-server/src/backend/catalog/namespace.c,v
> retrieving revision 1.30
> diff -c -r1.30 namespace.c
> *** src/backend/catalog/namespace.c 9 Aug 2002 16:45:14 -0000 1.30
> --- src/backend/catalog/namespace.c 15 Aug 2002 03:06:23 -0000
> ***************
> *** 1585,1590 ****
> --- 1585,1591 ----
> case RELKIND_RELATION:
> case RELKIND_SEQUENCE:
> case RELKIND_VIEW:
> + case RELKIND_COMPOSITE_TYPE:
> AssertTupleDescHasOid(pgclass->rd_att);
> object.classId = RelOid_pg_class;
> object.objectId = HeapTupleGetOid(tuple);
> Index: src/backend/catalog/pg_type.c
> ===================================================================
> RCS file: /opt/src/cvs/pgsql-server/src/backend/catalog/pg_type.c,v
> retrieving revision 1.77
> diff -c -r1.77 pg_type.c
> *** src/backend/catalog/pg_type.c 5 Aug 2002 03:29:16 -0000 1.77
> --- src/backend/catalog/pg_type.c 15 Aug 2002 03:06:23 -0000
> ***************
> *** 311,325 ****
>
> /*
> * If the type is a rowtype for a relation, mark it as internally
> ! * dependent on the relation. This allows it to be auto-dropped
> ! * when the relation is, and not otherwise.
> */
> if (OidIsValid(relationOid))
> {
> referenced.classId = RelOid_pg_class;
> referenced.objectId = relationOid;
> referenced.objectSubId = 0;
> ! recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL);
> }
>
> /*
> --- 311,338 ----
>
> /*
> * If the type is a rowtype for a relation, mark it as internally
> ! * dependent on the relation, *unless* it is a stand-alone composite
> ! * type relation. For the latter case, we have to reverse the
> ! * dependency.
> ! *
> ! * In the former case, this allows the type to be auto-dropped
> ! * when the relation is, and not otherwise. And in the latter,
> ! * of course we get the opposite effect.
> */
> if (OidIsValid(relationOid))
> {
> + Relation rel = relation_open(relationOid, AccessShareLock);
> + char relkind = rel->rd_rel->relkind;
> + relation_close(rel, AccessShareLock);
> +
> referenced.classId = RelOid_pg_class;
> referenced.objectId = relationOid;
> referenced.objectSubId = 0;
> !
> ! if (relkind != RELKIND_COMPOSITE_TYPE)
> ! recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL);
> ! else
> ! recordDependencyOn(&referenced, &myself, DEPENDENCY_INTERNAL);
> }
>
> /*
> Index: src/backend/commands/copy.c
> ===================================================================
> RCS file: /opt/src/cvs/pgsql-server/src/backend/commands/copy.c,v
> retrieving revision 1.162
> diff -c -r1.162 copy.c
> *** src/backend/commands/copy.c 2 Aug 2002 18:15:06 -0000 1.162
> --- src/backend/commands/copy.c 15 Aug 2002 03:06:23 -0000
> ***************
> *** 398,403 ****
> --- 398,406 ----
> if (rel->rd_rel->relkind == RELKIND_VIEW)
> elog(ERROR, "You cannot copy view %s",
> RelationGetRelationName(rel));
> + else if (rel->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
> + elog(ERROR, "You cannot copy type relation %s",
> + RelationGetRelationName(rel));
> else if (rel->rd_rel->relkind == RELKIND_SEQUENCE)
> elog(ERROR, "You cannot change sequence relation %s",
> RelationGetRelationName(rel));
> ***************
> *** 442,447 ****
> --- 445,453 ----
> {
> if (rel->rd_rel->relkind == RELKIND_VIEW)
> elog(ERROR, "You cannot copy view %s",
> + RelationGetRelationName(rel));
> + else if (rel->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
> + elog(ERROR, "You cannot copy type relation %s",
> RelationGetRelationName(rel));
> else if (rel->rd_rel->relkind == RELKIND_SEQUENCE)
> elog(ERROR, "You cannot copy sequence %s",
> Index: src/backend/commands/tablecmds.c
> ===================================================================
> RCS file: /opt/src/cvs/pgsql-server/src/backend/commands/tablecmds.c,v
> retrieving revision 1.28
> diff -c -r1.28 tablecmds.c
> *** src/backend/commands/tablecmds.c 7 Aug 2002 21:45:01 -0000 1.28
> --- src/backend/commands/tablecmds.c 15 Aug 2002 03:06:23 -0000
> ***************
> *** 345,350 ****
> --- 345,354 ----
> elog(ERROR, "TRUNCATE cannot be used on views. '%s' is a view",
> RelationGetRelationName(rel));
>
> + if (rel->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
> + elog(ERROR, "TRUNCATE cannot be used on type relations. '%s' is a type",
> + RelationGetRelationName(rel));
> +
> if (!allowSystemTableMods && IsSystemRelation(rel))
> elog(ERROR, "TRUNCATE cannot be used on system tables. '%s' is a system table",
> RelationGetRelationName(rel));
> ***************
> *** 3210,3221 ****
> case RELKIND_RELATION:
> case RELKIND_INDEX:
> case RELKIND_VIEW:
> case RELKIND_SEQUENCE:
> case RELKIND_TOASTVALUE:
> /* ok to change owner */
> break;
> default:
> ! elog(ERROR, "ALTER TABLE: relation \"%s\" is not a table, TOAST table, index, view, or sequence",
> NameStr(tuple_class->relname));
> }
> }
> --- 3214,3226 ----
> case RELKIND_RELATION:
> case RELKIND_INDEX:
> case RELKIND_VIEW:
> + case RELKIND_COMPOSITE_TYPE:
> case RELKIND_SEQUENCE:
> case RELKIND_TOASTVALUE:
> /* ok to change owner */
> break;
> default:
> ! elog(ERROR, "ALTER TABLE: relation \"%s\" is not a table, TOAST table, index, view, type, or sequence",
> NameStr(tuple_class->relname));
> }
> }
> Index: src/backend/commands/typecmds.c
> ===================================================================
> RCS file: /opt/src/cvs/pgsql-server/src/backend/commands/typecmds.c,v
> retrieving revision 1.8
> diff -c -r1.8 typecmds.c
> *** src/backend/commands/typecmds.c 24 Jul 2002 19:11:09 -0000 1.8
> --- src/backend/commands/typecmds.c 15 Aug 2002 03:06:23 -0000
> ***************
> *** 38,43 ****
> --- 38,44 ----
> #include "catalog/namespace.h"
> #include "catalog/pg_type.h"
> #include "commands/defrem.h"
> + #include "commands/tablecmds.h"
> #include "miscadmin.h"
> #include "parser/parse_func.h"
> #include "parser/parse_type.h"
> ***************
> *** 50,56 ****
>
> static Oid findTypeIOFunction(List *procname, bool isOutput);
>
> -
> /*
> * DefineType
> * Registers a new type.
> --- 51,56 ----
> ***************
> *** 665,668 ****
> --- 665,707 ----
> }
>
> return procOid;
> + }
> +
> + /*-------------------------------------------------------------------
> + * DefineCompositeType
> + *
> + * Create a Composite Type relation.
> + * `DefineRelation' does all the work, we just provide the correct
> + * arguments!
> + *
> + * If the relation already exists, then 'DefineRelation' will abort
> + * the xact...
> + *
> + * DefineCompositeType returns relid for use when creating
> + * an implicit composite type during function creation
> + *-------------------------------------------------------------------
> + */
> + Oid
> + DefineCompositeType(const RangeVar *typevar, List *coldeflist)
> + {
> + CreateStmt *createStmt = makeNode(CreateStmt);
> +
> + if (coldeflist == NIL)
> + elog(ERROR, "attempted to define composite type relation with"
> + " no attrs");
> +
> + /*
> + * now create the parameters for keys/inheritance etc. All of them are
> + * nil...
> + */
> + createStmt->relation = (RangeVar *) typevar;
> + createStmt->tableElts = coldeflist;
> + createStmt->inhRelations = NIL;
> + createStmt->constraints = NIL;
> + createStmt->hasoids = false;
> +
> + /*
> + * finally create the relation...
> + */
> + return DefineRelation(createStmt, RELKIND_COMPOSITE_TYPE);
> }
> Index: src/backend/executor/execMain.c
> ===================================================================
> RCS file: /opt/src/cvs/pgsql-server/src/backend/executor/execMain.c,v
> retrieving revision 1.173
> diff -c -r1.173 execMain.c
> *** src/backend/executor/execMain.c 7 Aug 2002 21:45:02 -0000 1.173
> --- src/backend/executor/execMain.c 15 Aug 2002 03:06:23 -0000
> ***************
> *** 786,791 ****
> --- 786,795 ----
> elog(ERROR, "You can't change view relation %s",
> RelationGetRelationName(resultRelationDesc));
> break;
> + case RELKIND_COMPOSITE_TYPE:
> + elog(ERROR, "You can't change type relation %s",
> + RelationGetRelationName(resultRelationDesc));
> + break;
> }
>
> MemSet(resultRelInfo, 0, sizeof(ResultRelInfo));
> Index: src/backend/nodes/copyfuncs.c
> ===================================================================
> RCS file: /opt/src/cvs/pgsql-server/src/backend/nodes/copyfuncs.c,v
> retrieving revision 1.200
> diff -c -r1.200 copyfuncs.c
> *** src/backend/nodes/copyfuncs.c 4 Aug 2002 19:48:09 -0000 1.200
> --- src/backend/nodes/copyfuncs.c 15 Aug 2002 03:06:23 -0000
> ***************
> *** 2233,2238 ****
> --- 2233,2249 ----
> return newnode;
> }
>
> + static CompositeTypeStmt *
> + _copyCompositeTypeStmt(CompositeTypeStmt *from)
> + {
> + CompositeTypeStmt *newnode = makeNode(CompositeTypeStmt);
> +
> + Node_Copy(from, newnode, typevar);
> + Node_Copy(from, newnode, coldeflist);
> +
> + return newnode;
> + }
> +
> static ViewStmt *
> _copyViewStmt(ViewStmt *from)
> {
> ***************
> *** 2938,2943 ****
> --- 2949,2957 ----
> break;
> case T_TransactionStmt:
> retval = _copyTransactionStmt(from);
> + break;
> + case T_CompositeTypeStmt:
> + retval = _copyCompositeTypeStmt(from);
> break;
> case T_ViewStmt:
> retval = _copyViewStmt(from);
> Index: src/backend/nodes/equalfuncs.c
> ===================================================================
> RCS file: /opt/src/cvs/pgsql-server/src/backend/nodes/equalfuncs.c,v
> retrieving revision 1.149
> diff -c -r1.149 equalfuncs.c
> *** src/backend/nodes/equalfuncs.c 4 Aug 2002 23:49:59 -0000 1.149
> --- src/backend/nodes/equalfuncs.c 15 Aug 2002 03:06:23 -0000
> ***************
> *** 1062,1067 ****
> --- 1062,1078 ----
> }
>
> static bool
> + _equalCompositeTypeStmt(CompositeTypeStmt *a, CompositeTypeStmt *b)
> + {
> + if (!equal(a->typevar, b->typevar))
> + return false;
> + if (!equal(a->coldeflist, b->coldeflist))
> + return false;
> +
> + return true;
> + }
> +
> + static bool
> _equalViewStmt(ViewStmt *a, ViewStmt *b)
> {
> if (!equal(a->view, b->view))
> ***************
> *** 2110,2115 ****
> --- 2121,2129 ----
> break;
> case T_TransactionStmt:
> retval = _equalTransactionStmt(a, b);
> + break;
> + case T_CompositeTypeStmt:
> + retval = _equalCompositeTypeStmt(a, b);
> break;
> case T_ViewStmt:
> retval = _equalViewStmt(a, b);
> Index: src/backend/parser/gram.y
> ===================================================================
> RCS file: /opt/src/cvs/pgsql-server/src/backend/parser/gram.y,v
> retrieving revision 2.358
> diff -c -r2.358 gram.y
> *** src/backend/parser/gram.y 10 Aug 2002 19:01:53 -0000 2.358
> --- src/backend/parser/gram.y 15 Aug 2002 03:06:23 -0000
> ***************
> *** 205,211 ****
>
> %type <list> stmtblock, stmtmulti,
> OptTableElementList, TableElementList, OptInherit, definition,
> ! opt_distinct, opt_definition, func_args,
> func_args_list, func_as, createfunc_opt_list
> oper_argtypes, RuleActionList, RuleActionMulti,
> opt_column_list, columnList, opt_name_list,
> --- 205,211 ----
>
> %type <list> stmtblock, stmtmulti,
> OptTableElementList, TableElementList, OptInherit, definition,
> ! opt_distinct, opt_definition, func_args, rowdefinition
> func_args_list, func_as, createfunc_opt_list
> oper_argtypes, RuleActionList, RuleActionMulti,
> opt_column_list, columnList, opt_name_list,
> ***************
> *** 2233,2238 ****
> --- 2233,2271 ----
> n->definition = $4;
> $$ = (Node *)n;
> }
> + | CREATE TYPE_P any_name AS rowdefinition
> + {
> + CompositeTypeStmt *n = makeNode(CompositeTypeStmt);
> + RangeVar *r = makeNode(RangeVar);
> +
> + switch (length($3))
> + {
> + case 1:
> + r->catalogname = NULL;
> + r->schemaname = NULL;
> + r->relname = strVal(lfirst($3));
> + break;
> + case 2:
> + r->catalogname = NULL;
> + r->schemaname = strVal(lfirst($3));
> + r->relname = strVal(lsecond($3));
> + break;
> + case 3:
> + r->catalogname = strVal(lfirst($3));
> + r->schemaname = strVal(lsecond($3));
> + r->relname = strVal(lfirst(lnext(lnext($3))));
> + break;
> + default:
> + elog(ERROR,
> + "Improper qualified name "
> + "(too many dotted names): %s",
> + NameListToString($3));
> + break;
> + }
> + n->typevar = r;
> + n->coldeflist = $5;
> + $$ = (Node *)n;
> + }
> | CREATE CHARACTER SET opt_as any_name GET definition opt_collate
> {
> DefineStmt *n = makeNode(DefineStmt);
> ***************
> *** 2241,2246 ****
> --- 2274,2282 ----
> n->definition = $7;
> $$ = (Node *)n;
> }
> + ;
> +
> + rowdefinition: '(' TableFuncElementList ')' { $$ = $2; }
> ;
>
> definition: '(' def_list ')' { $$ = $2; }
> Index: src/backend/storage/buffer/bufmgr.c
> ===================================================================
> RCS file: /opt/src/cvs/pgsql-server/src/backend/storage/buffer/bufmgr.c,v
> retrieving revision 1.129
> diff -c -r1.129 bufmgr.c
> *** src/backend/storage/buffer/bufmgr.c 11 Aug 2002 21:17:34 -0000 1.129
> --- src/backend/storage/buffer/bufmgr.c 15 Aug 2002 04:47:07 -0000
> ***************
> *** 1051,1056 ****
> --- 1051,1058 ----
> */
> if (relation->rd_rel->relkind == RELKIND_VIEW)
> relation->rd_nblocks = 0;
> + else if (relation->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
> + relation->rd_nblocks = 0;
> else if (!relation->rd_isnew && !relation->rd_istemp)
> relation->rd_nblocks = smgrnblocks(DEFAULT_SMGR, relation);
> return relation->rd_nblocks;
> ***************
> *** 1068,1073 ****
> --- 1070,1077 ----
> RelationUpdateNumberOfBlocks(Relation relation)
> {
> if (relation->rd_rel->relkind == RELKIND_VIEW)
> + relation->rd_nblocks = 0;
> + else if (relation->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
> relation->rd_nblocks = 0;
> else
> relation->rd_nblocks = smgrnblocks(DEFAULT_SMGR, relation);
> Index: src/backend/storage/smgr/smgr.c
> ===================================================================
> RCS file: /opt/src/cvs/pgsql-server/src/backend/storage/smgr/smgr.c,v
> retrieving revision 1.58
> diff -c -r1.58 smgr.c
> *** src/backend/storage/smgr/smgr.c 6 Aug 2002 02:36:34 -0000 1.58
> --- src/backend/storage/smgr/smgr.c 15 Aug 2002 03:06:23 -0000
> ***************
> *** 263,268 ****
> --- 263,270 ----
>
> if (reln->rd_rel->relkind == RELKIND_VIEW)
> return -1;
> + if (reln->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
> + return -1;
> if ((fd = (*(smgrsw[which].smgr_open)) (reln)) < 0)
> if (!failOK)
> elog(ERROR, "cannot open %s: %m", RelationGetRelationName(reln));
> Index: src/backend/tcop/postgres.c
> ===================================================================
> RCS file: /opt/src/cvs/pgsql-server/src/backend/tcop/postgres.c,v
> retrieving revision 1.281
> diff -c -r1.281 postgres.c
> *** src/backend/tcop/postgres.c 10 Aug 2002 20:29:18 -0000 1.281
> --- src/backend/tcop/postgres.c 15 Aug 2002 03:06:23 -0000
> ***************
> *** 2233,2238 ****
> --- 2233,2242 ----
> }
> break;
>
> + case T_CompositeTypeStmt:
> + tag = "CREATE TYPE";
> + break;
> +
> case T_ViewStmt:
> tag = "CREATE VIEW";
> break;
> Index: src/backend/tcop/utility.c
> ===================================================================
> RCS file: /opt/src/cvs/pgsql-server/src/backend/tcop/utility.c,v
> retrieving revision 1.169
> diff -c -r1.169 utility.c
> *** src/backend/tcop/utility.c 7 Aug 2002 21:45:02 -0000 1.169
> --- src/backend/tcop/utility.c 15 Aug 2002 03:06:23 -0000
> ***************
> *** 70,75 ****
> --- 70,76 ----
> {RELKIND_SEQUENCE, "a", "sequence", "SEQUENCE"},
> {RELKIND_VIEW, "a", "view", "VIEW"},
> {RELKIND_INDEX, "an", "index", "INDEX"},
> + {RELKIND_COMPOSITE_TYPE, "a", "type", "TYPE"},
> {'\0', "a", "???", "???"}
> };
>
> ***************
> *** 570,575 ****
> --- 571,589 ----
> DefineAggregate(stmt->defnames, stmt->definition);
> break;
> }
> + }
> + break;
> +
> + case T_CompositeTypeStmt: /* CREATE TYPE (composite) */
> + {
> + Oid relid;
> + CompositeTypeStmt *stmt = (CompositeTypeStmt *) parsetree;
> +
> + /*
> + * DefineCompositeType returns relid for use when creating
> + * an implicit composite type during function creation
> + */
> + relid = DefineCompositeType(stmt->typevar, stmt->coldeflist);
> }
> break;
>
> Index: src/backend/utils/adt/tid.c
> ===================================================================
> RCS file: /opt/src/cvs/pgsql-server/src/backend/utils/adt/tid.c,v
> retrieving revision 1.32
> diff -c -r1.32 tid.c
> *** src/backend/utils/adt/tid.c 16 Jul 2002 17:55:25 -0000 1.32
> --- src/backend/utils/adt/tid.c 15 Aug 2002 03:06:23 -0000
> ***************
> *** 226,231 ****
> --- 226,234 ----
> if (rel->rd_rel->relkind == RELKIND_VIEW)
> return currtid_for_view(rel, tid);
>
> + if (rel->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
> + elog(ERROR, "currtid can't handle type relations");
> +
> ItemPointerCopy(tid, result);
> heap_get_latest_tid(rel, SnapshotNow, result);
>
> ***************
> *** 248,253 ****
> --- 251,259 ----
> rel = heap_openrv(relrv, AccessShareLock);
> if (rel->rd_rel->relkind == RELKIND_VIEW)
> return currtid_for_view(rel, tid);
> +
> + if (rel->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
> + elog(ERROR, "currtid can't handle type relations");
>
> result = (ItemPointer) palloc(sizeof(ItemPointerData));
> ItemPointerCopy(tid, result);
> Index: src/bin/pg_dump/common.c
> ===================================================================
> RCS file: /opt/src/cvs/pgsql-server/src/bin/pg_dump/common.c,v
> retrieving revision 1.67
> diff -c -r1.67 common.c
> *** src/bin/pg_dump/common.c 30 Jul 2002 21:56:04 -0000 1.67
> --- src/bin/pg_dump/common.c 15 Aug 2002 03:06:23 -0000
> ***************
> *** 215,223 ****
>
> for (i = 0; i < numTables; i++)
> {
> ! /* Sequences and views never have parents */
> if (tblinfo[i].relkind == RELKIND_SEQUENCE ||
> ! tblinfo[i].relkind == RELKIND_VIEW)
> continue;
>
> /* Don't bother computing anything for non-target tables, either */
> --- 215,224 ----
>
> for (i = 0; i < numTables; i++)
> {
> ! /* Sequences, views, and types never have parents */
> if (tblinfo[i].relkind == RELKIND_SEQUENCE ||
> ! tblinfo[i].relkind == RELKIND_VIEW ||
> ! tblinfo[i].relkind == RELKIND_COMPOSITE_TYPE)
> continue;
>
> /* Don't bother computing anything for non-target tables, either */
> ***************
> *** 269,277 ****
>
> for (i = 0; i < numTables; i++)
> {
> ! /* Sequences and views never have parents */
> if (tblinfo[i].relkind == RELKIND_SEQUENCE ||
> ! tblinfo[i].relkind == RELKIND_VIEW)
> continue;
>
> /* Don't bother computing anything for non-target tables, either */
> --- 270,279 ----
>
> for (i = 0; i < numTables; i++)
> {
> ! /* Sequences, views, and types never have parents */
> if (tblinfo[i].relkind == RELKIND_SEQUENCE ||
> ! tblinfo[i].relkind == RELKIND_VIEW ||
> ! tblinfo[i].relkind == RELKIND_COMPOSITE_TYPE)
> continue;
>
> /* Don't bother computing anything for non-target tables, either */
> Index: src/bin/pg_dump/pg_dump.c
> ===================================================================
> RCS file: /opt/src/cvs/pgsql-server/src/bin/pg_dump/pg_dump.c,v
> retrieving revision 1.281
> diff -c -r1.281 pg_dump.c
> *** src/bin/pg_dump/pg_dump.c 10 Aug 2002 16:57:31 -0000 1.281
> --- src/bin/pg_dump/pg_dump.c 15 Aug 2002 03:06:23 -0000
> ***************
> *** 95,100 ****
> --- 95,101 ----
> FuncInfo *g_finfo, int numFuncs,
> TypeInfo *g_tinfo, int numTypes);
> static void dumpOneDomain(Archive *fout, TypeInfo *tinfo);
> + static void dumpOneCompositeType(Archive *fout, TypeInfo *tinfo);
> static void dumpOneTable(Archive *fout, TableInfo *tbinfo,
> TableInfo *g_tblinfo);
> static void dumpOneSequence(Archive *fout, TableInfo *tbinfo,
> ***************
> *** 1171,1176 ****
> --- 1172,1181 ----
> if (tblinfo[i].relkind == RELKIND_VIEW)
> continue;
>
> + /* Skip TYPE relations */
> + if (tblinfo[i].relkind == RELKIND_COMPOSITE_TYPE)
> + continue;
> +
> if (tblinfo[i].relkind == RELKIND_SEQUENCE) /* already dumped */
> continue;
>
> ***************
> *** 1575,1580 ****
> --- 1580,1586 ----
> int i_usename;
> int i_typelem;
> int i_typrelid;
> + int i_typrelkind;
> int i_typtype;
> int i_typisdefined;
>
> ***************
> *** 1595,1601 ****
> appendPQExpBuffer(query, "SELECT pg_type.oid, typname, "
> "typnamespace, "
> "(select usename from pg_user where typowner = usesysid) as usename, "
> ! "typelem, typrelid, typtype, typisdefined "
> "FROM pg_type");
> }
> else
> --- 1601,1609 ----
> appendPQExpBuffer(query, "SELECT pg_type.oid, typname, "
> "typnamespace, "
> "(select usename from pg_user where typowner = usesysid) as usename, "
> ! "typelem, typrelid, "
> ! "(select relkind from pg_class where oid = typrelid) as typrelkind, "
> ! "typtype, typisdefined "
> "FROM pg_type");
> }
> else
> ***************
> *** 1603,1609 ****
> appendPQExpBuffer(query, "SELECT pg_type.oid, typname, "
> "0::oid as typnamespace, "
> "(select usename from pg_user where typowner = usesysid) as usename, "
> ! "typelem, typrelid, typtype, typisdefined "
> "FROM pg_type");
> }
>
> --- 1611,1619 ----
> appendPQExpBuffer(query, "SELECT pg_type.oid, typname, "
> "0::oid as typnamespace, "
> "(select usename from pg_user where typowner = usesysid) as usename, "
> ! "typelem, typrelid, "
> ! "''::char as typrelkind, "
> ! "typtype, typisdefined "
> "FROM pg_type");
> }
>
> ***************
> *** 1625,1630 ****
> --- 1635,1641 ----
> i_usename = PQfnumber(res, "usename");
> i_typelem = PQfnumber(res, "typelem");
> i_typrelid = PQfnumber(res, "typrelid");
> + i_typrelkind = PQfnumber(res, "typrelkind");
> i_typtype = PQfnumber(res, "typtype");
> i_typisdefined = PQfnumber(res, "typisdefined");
>
> ***************
> *** 1637,1642 ****
> --- 1648,1654 ----
> tinfo[i].usename = strdup(PQgetvalue(res, i, i_usename));
> tinfo[i].typelem = strdup(PQgetvalue(res, i, i_typelem));
> tinfo[i].typrelid = strdup(PQgetvalue(res, i, i_typrelid));
> + tinfo[i].typrelkind = *PQgetvalue(res, i, i_typrelkind);
> tinfo[i].typtype = *PQgetvalue(res, i, i_typtype);
>
> /*
> ***************
> *** 2102,2108 ****
> appendPQExpBuffer(query,
> "SELECT pg_class.oid, relname, relacl, relkind, "
> "relnamespace, "
> -
> "(select usename from pg_user where relowner = usesysid) as usename, "
> "relchecks, reltriggers, "
> "relhasindex, relhasrules, relhasoids "
> --- 2114,2119 ----
> ***************
> *** 2113,2118 ****
> --- 2124,2130 ----
> }
> else if (g_fout->remoteVersion >= 70200)
> {
> + /* before 7.3 there were no type relations with relkind 'c' */
> appendPQExpBuffer(query,
> "SELECT pg_class.oid, relname, relacl, relkind, "
> "0::oid as relnamespace, "
> ***************
> *** 2356,2361 ****
> --- 2368,2377 ----
> if (tblinfo[i].relkind == RELKIND_SEQUENCE)
> continue;
>
> + /* Don't bother to collect info for type relations */
> + if (tblinfo[i].relkind == RELKIND_COMPOSITE_TYPE)
> + continue;
> +
> /* Don't bother with uninteresting tables, either */
> if (!tblinfo[i].interesting)
> continue;
> ***************
> *** 3173,3178 ****
> --- 3189,3293 ----
> }
>
> /*
> + * dumpOneCompositeType
> + * writes out to fout the queries to recreate a user-defined stand-alone
> + * composite type as requested by dumpTypes
> + */
> + static void
> + dumpOneCompositeType(Archive *fout, TypeInfo *tinfo)
> + {
> + PQExpBuffer q = createPQExpBuffer();
> + PQExpBuffer delq = createPQExpBuffer();
> + PQExpBuffer query = createPQExpBuffer();
> + PGresult *res;
> + int ntups;
> + char *attname;
> + char *atttypdefn;
> + char *attbasetype;
> + const char *((*deps)[]);
> + int depIdx = 0;
> + int i;
> +
> + deps = malloc(sizeof(char *) * 10);
> +
> + /* Set proper schema search path so type references list correctly */
> + selectSourceSchema(tinfo->typnamespace->nspname);
> +
> + /* Fetch type specific details */
> + /* We assume here that remoteVersion must be at least 70300 */
> +
> + appendPQExpBuffer(query, "SELECT a.attname, "
> + "pg_catalog.format_type(a.atttypid, a.atttypmod) as atttypdefn, "
> + "a.atttypid as attbasetype "
> + "FROM pg_catalog.pg_type t, pg_catalog.pg_attribute a "
> + "WHERE t.oid = '%s'::pg_catalog.oid "
> + "AND a.attrelid = t.typrelid",
> + tinfo->oid);
> +
> + res = PQexec(g_conn, query->data);
> + if (!res ||
> + PQresultStatus(res) != PGRES_TUPLES_OK)
> + {
> + write_msg(NULL, "query to obtain type information failed: %s", PQerrorMessage(g_conn));
> + exit_nicely();
> + }
> +
> + /* Expecting at least a single result */
> + ntups = PQntuples(res);
> + if (ntups < 1)
> + {
> + write_msg(NULL, "Got no rows from: %s", query->data);
> + exit_nicely();
> + }
> +
> + /* DROP must be fully qualified in case same name appears in pg_catalog */
> + appendPQExpBuffer(delq, "DROP TYPE %s.",
> + fmtId(tinfo->typnamespace->nspname, force_quotes));
> + appendPQExpBuffer(delq, "%s RESTRICT;\n",
> + fmtId(tinfo->typname, force_quotes));
> +
> + appendPQExpBuffer(q,
> + "CREATE TYPE %s AS (",
> + fmtId(tinfo->typname, force_quotes));
> +
> + for (i = 0; i < ntups; i++)
> + {
> + attname = PQgetvalue(res, i, PQfnumber(res, "attname"));
> + atttypdefn = PQgetvalue(res, i, PQfnumber(res, "atttypdefn"));
> + attbasetype = PQgetvalue(res, i, PQfnumber(res, "attbasetype"));
> +
> + if (i > 0)
> + appendPQExpBuffer(q, ",\n\t %s %s", attname, atttypdefn);
> + else
> + appendPQExpBuffer(q, "%s %s", attname, atttypdefn);
> +
> + /* Depends on the base type */
> + (*deps)[depIdx++] = strdup(attbasetype);
> + }
> + appendPQExpBuffer(q, ");\n");
> +
> + (*deps)[depIdx++] = NULL; /* End of List */
> +
> + ArchiveEntry(fout, tinfo->oid, tinfo->typname,
> + tinfo->typnamespace->nspname,
> + tinfo->usename, "TYPE", deps,
> + q->data, delq->data, NULL, NULL, NULL);
> +
> + /*** Dump Type Comments ***/
> + resetPQExpBuffer(q);
> +
> + appendPQExpBuffer(q, "TYPE %s", fmtId(tinfo->typname, force_quotes));
> + dumpComment(fout, q->data,
> + tinfo->typnamespace->nspname, tinfo->usename,
> + tinfo->oid, "pg_type", 0, NULL);
> +
> + PQclear(res);
> + destroyPQExpBuffer(q);
> + destroyPQExpBuffer(delq);
> + destroyPQExpBuffer(query);
> + }
> +
> + /*
> * dumpTypes
> * writes out to fout the queries to recreate all the user-defined types
> */
> ***************
> *** 3188,3195 ****
> if (!tinfo[i].typnamespace->dump)
> continue;
>
> ! /* skip relation types */
> ! if (atooid(tinfo[i].typrelid) != 0)
> continue;
>
> /* skip undefined placeholder types */
> --- 3303,3310 ----
> if (!tinfo[i].typnamespace->dump)
> continue;
>
> ! /* skip relation types for non-stand-alone type relations*/
> ! if (atooid(tinfo[i].typrelid) != 0 && tinfo[i].typrelkind != 'c')
> continue;
>
> /* skip undefined placeholder types */
> ***************
> *** 3207,3212 ****
> --- 3322,3329 ----
> finfo, numFuncs, tinfo, numTypes);
> else if (tinfo[i].typtype == 'd')
> dumpOneDomain(fout, &tinfo[i]);
> + else if (tinfo[i].typtype == 'c')
> + dumpOneCompositeType(fout, &tinfo[i]);
> }
> }
>
> ***************
> *** 4832,4837 ****
> --- 4949,4955 ----
>
> if (tbinfo->relkind != RELKIND_SEQUENCE)
> continue;
> +
> if (tbinfo->dump)
> {
> dumpOneSequence(fout, tbinfo, schemaOnly, dataOnly);
> ***************
> *** 4847,4852 ****
> --- 4965,4972 ----
> TableInfo *tbinfo = &tblinfo[i];
>
> if (tbinfo->relkind == RELKIND_SEQUENCE) /* already dumped */
> + continue;
> + if (tbinfo->relkind == RELKIND_COMPOSITE_TYPE) /* dumped as a type */
> continue;
>
> if (tbinfo->dump)
> Index: src/bin/pg_dump/pg_dump.h
> ===================================================================
> RCS file: /opt/src/cvs/pgsql-server/src/bin/pg_dump/pg_dump.h,v
> retrieving revision 1.94
> diff -c -r1.94 pg_dump.h
> *** src/bin/pg_dump/pg_dump.h 2 Aug 2002 18:15:08 -0000 1.94
> --- src/bin/pg_dump/pg_dump.h 15 Aug 2002 03:06:23 -0000
> ***************
> *** 47,52 ****
> --- 47,53 ----
> char *usename; /* name of owner, or empty string */
> char *typelem; /* OID */
> char *typrelid; /* OID */
> + char typrelkind; /* 'r', 'v', 'c', etc */
> char typtype; /* 'b', 'c', etc */
> bool isArray; /* true if user-defined array type */
> bool isDefined; /* true if typisdefined */
> Index: src/bin/psql/describe.c
> ===================================================================
> RCS file: /opt/src/cvs/pgsql-server/src/bin/psql/describe.c,v
> retrieving revision 1.60
> diff -c -r1.60 describe.c
> *** src/bin/psql/describe.c 10 Aug 2002 16:01:16 -0000 1.60
> --- src/bin/psql/describe.c 15 Aug 2002 04:14:09 -0000
> ***************
> *** 210,218 ****
>
> /*
> * do not include array types (start with underscore), do not include
> ! * user relations (typrelid!=0)
> */
> ! appendPQExpBuffer(&buf, "WHERE t.typrelid = 0 AND t.typname !~ '^_'\n");
>
> /* Match name pattern against either internal or external name */
> processNamePattern(&buf, pattern, true, false,
> --- 210,221 ----
>
> /*
> * do not include array types (start with underscore), do not include
> ! * user relations (typrelid!=0) unless they are type relations
> */
> ! appendPQExpBuffer(&buf, "WHERE (t.typrelid = 0 ");
> ! appendPQExpBuffer(&buf, "OR (SELECT c.relkind = 'c' FROM pg_class c "
> ! "where c.oid = t.typrelid)) ");
> ! appendPQExpBuffer(&buf, "AND t.typname !~ '^_'\n");
>
> /* Match name pattern against either internal or external name */
> processNamePattern(&buf, pattern, true, false,
> Index: src/include/catalog/pg_class.h
> ===================================================================
> RCS file: /opt/src/cvs/pgsql-server/src/include/catalog/pg_class.h,v
> retrieving revision 1.70
> diff -c -r1.70 pg_class.h
> *** src/include/catalog/pg_class.h 2 Aug 2002 18:15:09 -0000 1.70
> --- src/include/catalog/pg_class.h 15 Aug 2002 03:06:23 -0000
> ***************
> *** 169,173 ****
> --- 169,174 ----
> #define RELKIND_UNCATALOGED 'u' /* temporary heap */
> #define RELKIND_TOASTVALUE 't' /* moved off huge values */
> #define RELKIND_VIEW 'v' /* view */
> + #define RELKIND_COMPOSITE_TYPE 'c' /* composite type */
>
> #endif /* PG_CLASS_H */
> Index: src/include/commands/defrem.h
> ===================================================================
> RCS file: /opt/src/cvs/pgsql-server/src/include/commands/defrem.h,v
> retrieving revision 1.43
> diff -c -r1.43 defrem.h
> *** src/include/commands/defrem.h 29 Jul 2002 22:14:11 -0000 1.43
> --- src/include/commands/defrem.h 15 Aug 2002 03:06:23 -0000
> ***************
> *** 58,63 ****
> --- 58,64 ----
> extern void RemoveTypeById(Oid typeOid);
> extern void DefineDomain(CreateDomainStmt *stmt);
> extern void RemoveDomain(List *names, DropBehavior behavior);
> + extern Oid DefineCompositeType(const RangeVar *typevar, List *coldeflist);
>
> extern void DefineOpClass(CreateOpClassStmt *stmt);
> extern void RemoveOpClass(RemoveOpClassStmt *stmt);
> Index: src/include/nodes/nodes.h
> ===================================================================
> RCS file: /opt/src/cvs/pgsql-server/src/include/nodes/nodes.h,v
> retrieving revision 1.114
> diff -c -r1.114 nodes.h
> *** src/include/nodes/nodes.h 29 Jul 2002 22:14:11 -0000 1.114
> --- src/include/nodes/nodes.h 15 Aug 2002 03:06:23 -0000
> ***************
> *** 238,243 ****
> --- 238,244 ----
> T_PrivTarget,
> T_InsertDefault,
> T_CreateOpClassItem,
> + T_CompositeTypeStmt,
>
> /*
> * TAGS FOR FUNCTION-CALL CONTEXT AND RESULTINFO NODES (see fmgr.h)
> Index: src/include/nodes/parsenodes.h
> ===================================================================
> RCS file: /opt/src/cvs/pgsql-server/src/include/nodes/parsenodes.h,v
> retrieving revision 1.198
> diff -c -r1.198 parsenodes.h
> *** src/include/nodes/parsenodes.h 4 Aug 2002 19:48:10 -0000 1.198
> --- src/include/nodes/parsenodes.h 15 Aug 2002 03:06:23 -0000
> ***************
> *** 1402,1407 ****
> --- 1402,1419 ----
> } TransactionStmt;
>
> /* ----------------------
> + * Create Type Statement, composite types
> + * ----------------------
> + */
> + typedef struct CompositeTypeStmt
> + {
> + NodeTag type;
> + RangeVar *typevar; /* the composite type to be created */
> + List *coldeflist; /* list of ColumnDef nodes */
> + } CompositeTypeStmt;
> +
> +
> + /* ----------------------
> * Create View Statement
> * ----------------------
> */
> Index: src/pl/plpgsql/src/pl_comp.c
> ===================================================================
> RCS file: /opt/src/cvs/pgsql-server/src/pl/plpgsql/src/pl_comp.c,v
> retrieving revision 1.45
> diff -c -r1.45 pl_comp.c
> *** src/pl/plpgsql/src/pl_comp.c 12 Aug 2002 14:25:07 -0000 1.45
> --- src/pl/plpgsql/src/pl_comp.c 15 Aug 2002 04:02:53 -0000
> ***************
> *** 1028,1039 ****
> }
>
> /*
> ! * It must be a relation, sequence or view
> */
> classStruct = (Form_pg_class) GETSTRUCT(classtup);
> if (classStruct->relkind != RELKIND_RELATION &&
> classStruct->relkind != RELKIND_SEQUENCE &&
> ! classStruct->relkind != RELKIND_VIEW)
> {
> ReleaseSysCache(classtup);
> pfree(cp[0]);
> --- 1028,1040 ----
> }
>
> /*
> ! * It must be a relation, sequence, view, or type
> */
> classStruct = (Form_pg_class) GETSTRUCT(classtup);
> if (classStruct->relkind != RELKIND_RELATION &&
> classStruct->relkind != RELKIND_SEQUENCE &&
> ! classStruct->relkind != RELKIND_VIEW &&
> ! classStruct->relkind != RELKIND_COMPOSITE_TYPE)
> {
> ReleaseSysCache(classtup);
> pfree(cp[0]);
> ***************
> *** 1145,1154 ****
> classStruct = (Form_pg_class) GETSTRUCT(classtup);
> relname = NameStr(classStruct->relname);
>
> ! /* accept relation, sequence, or view pg_class entries */
> if (classStruct->relkind != RELKIND_RELATION &&
> classStruct->relkind != RELKIND_SEQUENCE &&
> ! classStruct->relkind != RELKIND_VIEW)
> elog(ERROR, "%s isn't a table", relname);
>
> /*
> --- 1146,1156 ----
> classStruct = (Form_pg_class) GETSTRUCT(classtup);
> relname = NameStr(classStruct->relname);
>
> ! /* accept relation, sequence, view, or type pg_class entries */
> if (classStruct->relkind != RELKIND_RELATION &&
> classStruct->relkind != RELKIND_SEQUENCE &&
> ! classStruct->relkind != RELKIND_VIEW &&
> ! classStruct->relkind != RELKIND_COMPOSITE_TYPE)
> elog(ERROR, "%s isn't a table", relname);
>
> /*
> Index: src/test/regress/expected/create_type.out
> ===================================================================
> RCS file: /opt/src/cvs/pgsql-server/src/test/regress/expected/create_type.out,v
> retrieving revision 1.4
> diff -c -r1.4 create_type.out
> *** src/test/regress/expected/create_type.out 6 Sep 2001 02:07:42 -0000 1.4
> --- src/test/regress/expected/create_type.out 15 Aug 2002 03:06:23 -0000
> ***************
> *** 37,40 ****
> --- 37,53 ----
> zippo | 42
> (1 row)
>
> + -- Test stand-alone composite type
> + CREATE TYPE default_test_row AS (f1 text_w_default, f2 int42);
> + CREATE FUNCTION get_default_test() RETURNS SETOF default_test_row AS '
> + SELECT * FROM default_test;
> + ' LANGUAGE SQL;
> + SELECT * FROM get_default_test();
> + f1 | f2
> + -------+----
> + zippo | 42
> + (1 row)
> +
> + DROP TYPE default_test_row CASCADE;
> + NOTICE: Drop cascades to function get_default_test()
> DROP TABLE default_test;
> Index: src/test/regress/sql/create_type.sql
> ===================================================================
> RCS file: /opt/src/cvs/pgsql-server/src/test/regress/sql/create_type.sql,v
> retrieving revision 1.4
> diff -c -r1.4 create_type.sql
> *** src/test/regress/sql/create_type.sql 6 Sep 2001 02:07:42 -0000 1.4
> --- src/test/regress/sql/create_type.sql 15 Aug 2002 03:06:23 -0000
> ***************
> *** 41,44 ****
> --- 41,56 ----
>
> SELECT * FROM default_test;
>
> + -- Test stand-alone composite type
> +
> + CREATE TYPE default_test_row AS (f1 text_w_default, f2 int42);
> +
> + CREATE FUNCTION get_default_test() RETURNS SETOF default_test_row AS '
> + SELECT * FROM default_test;
> + ' LANGUAGE SQL;
> +
> + SELECT * FROM get_default_test();
> +
> + DROP TYPE default_test_row CASCADE;
> +
> DROP TABLE default_test;

--
Bruce Momjian | http://candle.pha.pa.us
pgman(at)candle(dot)pha(dot)pa(dot)us | (610) 359-1001
+ If your life is a hard drive, | 13 Roberts Road
+ Christ can be your backup. | Newtown Square, Pennsylvania 19073

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Vince Vielhaber 2002-08-15 16:38:45 Re: Open 7.3 items
Previous Message Vince Vielhaber 2002-08-15 16:34:40 Re: Open 7.3 items

Browse pgsql-patches by date

  From Date Subject
Next Message Bruce Momjian 2002-08-15 16:38:53 Re: improve FOUND in PL/PgSQL
Previous Message Ulrich Neumann 2002-08-15 14:27:19 Re: Antw: Re: File for /src/backend/port/netware