Re: stand-alone composite types patch (was [HACKERS] Proposal: - Mailing list pgsql-patches

From Bruce Momjian
Subject Re: stand-alone composite types patch (was [HACKERS] Proposal:
Date
Msg-id 200208110509.g7B59Ho18342@candle.pha.pa.us
Whole thread Raw
In response to Re: stand-alone composite types patch (was [HACKERS] Proposal:  (Joe Conway <mail@joeconway.com>)
Responses Re: stand-alone composite types patch (was [HACKERS] Proposal:
List pgsql-patches
Your patch has been added to the PostgreSQL unapplied patches list at:

    http://candle.pha.pa.us/cgi-bin/pgpatches

I will try to apply it within the next 48 hours.

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


Joe Conway wrote:
> Tom Lane wrote:
> > If you did it that way then you'd not need that ugly kluge in
> > RemoveType.  What you'd need instead is some smarts (a kluge!?) in
> > setting up the dependency.  Currently that dependency is made in
> > TypeCreate which doesn't know what sort of relation it's creating
> > a type for.  Probably the best answer is to pull that particular
> > dependency out of TypeCreate, and make it (in the proper direction)
> > in AddNewRelationType.
>
> Fixed.
>
> > Also, I'm not following the point of the separation between
> > DefineCompositeType and DefineCompositeTypeRelation; nor do I see a need
> > for a CommandCounterIncrement call in there.
>
> Fixed.
>
>
> > You have missed a number of places where this new relkind ought to
> > be special-cased the same way RELKIND_VIEW is --- for example
> > CheckAttributeNames and AddNewAttributeTuples, since a composite type
> > presumably shouldn't have system columns associated.  I'd counsel
> > looking at all references to RELKIND_VIEW to see which places also need
> > to check for RELKIND_COMPOSITE_TYPE.
>
> Yup, I had missed lots of things, not the least of which was pg_dump.
> New patch attached includes pg_dump, psql (\dT), docs, and regression
> support.
>
> There is also a small adjustment to the expected output file for
> select-having. I was getting a regression failure based on ordering of
> the results, so I added ORDER BY clauses.
>
> Passes all regression tests. If no more objections, please apply.
>
> Thanks,
>
> 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    8 Aug 2002 14:49:57 -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.219
> diff -c -r1.219 heap.c
> *** src/backend/catalog/heap.c    6 Aug 2002 02:36:33 -0000    1.219
> --- src/backend/catalog/heap.c    8 Aug 2002 14:49:57 -0000
> ***************
> *** 358,364 ****
>        *
>        * Skip this for a view, since it doesn't have system attributes.
>        */
> !     if (relkind != RELKIND_VIEW)
>       {
>           for (i = 0; i < natts; i++)
>           {
> --- 358,364 ----
>        *
>        * Skip this for a view, since it doesn't have system attributes.
>        */
> !     if (relkind != RELKIND_VIEW && relkind != RELKIND_COMPOSITE_TYPE)
>       {
>           for (i = 0; i < natts; i++)
>           {
> ***************
> *** 475,481 ****
>        * 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++)
> --- 475,481 ----
>        * 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 && relkind != RELKIND_COMPOSITE_TYPE)
>       {
>           dpp = SysAtt;
>           for (i = 0; i < -1 - FirstLowInvalidHeapAttributeNumber; i++)
> ***************
> *** 764,770 ****
>       /*
>        * We create the disk file for this relation here
>        */
> !     if (relkind != RELKIND_VIEW)
>           heap_storage_create(new_rel_desc);
>
>       /*
> --- 764,770 ----
>       /*
>        * We create the disk file for this relation here
>        */
> !     if (relkind != RELKIND_VIEW && relkind != RELKIND_COMPOSITE_TYPE)
>           heap_storage_create(new_rel_desc);
>
>       /*
> ***************
> *** 1135,1141 ****
>       /*
>        * unlink the relation's physical file and finish up.
>        */
> !     if (rel->rd_rel->relkind != RELKIND_VIEW)
>           smgrunlink(DEFAULT_SMGR, rel);
>
>       /*
> --- 1135,1142 ----
>       /*
>        * 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.29
> diff -c -r1.29 namespace.c
> *** src/backend/catalog/namespace.c    8 Aug 2002 01:44:30 -0000    1.29
> --- src/backend/catalog/namespace.c    8 Aug 2002 14:49:57 -0000
> ***************
> *** 1578,1583 ****
> --- 1578,1584 ----
>               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    8 Aug 2002 17:30:27 -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    8 Aug 2002 14:49:57 -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    8 Aug 2002 18:04:58 -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    8 Aug 2002 17:33:43 -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    8 Aug 2002 14:49:57 -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    8 Aug 2002 14:49:58 -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    8 Aug 2002 14:49:58 -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.357
> diff -c -r2.357 gram.y
> *** src/backend/parser/gram.y    6 Aug 2002 05:40:45 -0000    2.357
> --- src/backend/parser/gram.y    8 Aug 2002 14:49:58 -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,
> ***************
> *** 2247,2252 ****
> --- 2247,2285 ----
>                       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);
> ***************
> *** 2255,2260 ****
> --- 2288,2296 ----
>                       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.128
> diff -c -r1.128 bufmgr.c
> *** src/backend/storage/buffer/bufmgr.c    6 Aug 2002 02:36:34 -0000    1.128
> --- src/backend/storage/buffer/bufmgr.c    8 Aug 2002 14:49:58 -0000
> ***************
> *** 1056,1061 ****
> --- 1056,1063 ----
>        */
>       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;
> 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    8 Aug 2002 14:49:59 -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.280
> diff -c -r1.280 postgres.c
> *** src/backend/tcop/postgres.c    6 Aug 2002 05:24:04 -0000    1.280
> --- src/backend/tcop/postgres.c    8 Aug 2002 14:49:59 -0000
> ***************
> *** 2264,2269 ****
> --- 2264,2273 ----
>               }
>               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    8 Aug 2002 14:49:59 -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    8 Aug 2002 14:49:59 -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    8 Aug 2002 14:49:59 -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.280
> diff -c -r1.280 pg_dump.c
> *** src/bin/pg_dump/pg_dump.c    4 Aug 2002 05:03:29 -0000    1.280
> --- src/bin/pg_dump/pg_dump.c    8 Aug 2002 22:42:58 -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,
> ***************
> *** 1178,1183 ****
> --- 1179,1188 ----
>           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;
>
> ***************
> *** 1582,1587 ****
> --- 1587,1593 ----
>       int            i_usename;
>       int            i_typelem;
>       int            i_typrelid;
> +     int            i_typrelkind;
>       int            i_typtype;
>       int            i_typisdefined;
>
> ***************
> *** 1602,1608 ****
>           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
> --- 1608,1616 ----
>           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
> ***************
> *** 1610,1616 ****
>           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");
>       }
>
> --- 1618,1626 ----
>           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");
>       }
>
> ***************
> *** 1632,1637 ****
> --- 1642,1648 ----
>       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");
>
> ***************
> *** 1644,1649 ****
> --- 1655,1661 ----
>           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);
>
>           /*
> ***************
> *** 2109,2115 ****
>           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 "
> --- 2121,2126 ----
> ***************
> *** 2120,2125 ****
> --- 2131,2137 ----
>       }
>       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, "
> ***************
> *** 2363,2368 ****
> --- 2375,2384 ----
>           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;
> ***************
> *** 3180,3185 ****
> --- 3196,3300 ----
>   }
>
>   /*
> +  * 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
>    */
> ***************
> *** 3195,3202 ****
>           if (!tinfo[i].typnamespace->dump)
>               continue;
>
> !         /* skip relation types */
> !         if (atooid(tinfo[i].typrelid) != 0)
>               continue;
>
>           /* skip undefined placeholder types */
> --- 3310,3317 ----
>           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 */
> ***************
> *** 3214,3219 ****
> --- 3329,3336 ----
>                               finfo, numFuncs, tinfo, numTypes);
>           else if (tinfo[i].typtype == 'd')
>               dumpOneDomain(fout, &tinfo[i]);
> +         else if (tinfo[i].typtype == 'c')
> +             dumpOneCompositeType(fout, &tinfo[i]);
>       }
>   }
>
> ***************
> *** 4839,4844 ****
> --- 4956,4962 ----
>
>           if (tbinfo->relkind != RELKIND_SEQUENCE)
>               continue;
> +
>           if (tbinfo->dump)
>           {
>               dumpOneSequence(fout, tbinfo, schemaOnly, dataOnly);
> ***************
> *** 4854,4859 ****
> --- 4972,4979 ----
>               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    8 Aug 2002 18:26:11 -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.57
> diff -c -r1.57 describe.c
> *** src/bin/psql/describe.c    2 Aug 2002 18:15:08 -0000    1.57
> --- src/bin/psql/describe.c    8 Aug 2002 22:26:38 -0000
> ***************
> *** 168,176 ****
>
>       /*
>        * do not include array types (start with underscore), do not include
> !      * user relations (typrelid!=0)
>        */
> !     appendPQExpBuffer(&buf, "FROM pg_type t\nWHERE t.typrelid = 0 AND t.typname !~ '^_.*'\n");
>
>       if (name)
>           /* accept either internal or external type name */
> --- 168,179 ----
>
>       /*
>        * do not include array types (start with underscore), do not include
> !      * user relations (typrelid!=0) unless they are type relations
>        */
> !     appendPQExpBuffer(&buf, "FROM pg_type t\nWHERE (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");
>
>       if (name)
>           /* accept either internal or external type name */
> 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    8 Aug 2002 14:49:59 -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    8 Aug 2002 14:49:59 -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    8 Aug 2002 14:49:59 -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    8 Aug 2002 14:49:59 -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.44
> diff -c -r1.44 pl_comp.c
> *** src/pl/plpgsql/src/pl_comp.c    8 Aug 2002 01:36:04 -0000    1.44
> --- src/pl/plpgsql/src/pl_comp.c    8 Aug 2002 14:50:00 -0000
> ***************
> *** 1030,1041 ****
>       }
>
>       /*
> !      * 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]);
> --- 1030,1042 ----
>       }
>
>       /*
> !      * 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]);
> ***************
> *** 1130,1139 ****
>       if (!HeapTupleIsValid(classtup))
>           elog(ERROR, "%s: no such class", cp[0]);
>       classStruct = (Form_pg_class) GETSTRUCT(classtup);
> !     /* 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", cp[0]);
>
>       /*
> --- 1131,1141 ----
>       if (!HeapTupleIsValid(classtup))
>           elog(ERROR, "%s: no such class", cp[0]);
>       classStruct = (Form_pg_class) GETSTRUCT(classtup);
> !     /* 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", cp[0]);
>
>       /*
> 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    8 Aug 2002 14:50:00 -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/expected/select_having.out
> ===================================================================
> RCS file: /opt/src/cvs/pgsql-server/src/test/regress/expected/select_having.out,v
> retrieving revision 1.7
> diff -c -r1.7 select_having.out
> *** src/test/regress/expected/select_having.out    26 Jun 2002 21:58:56 -0000    1.7
> --- src/test/regress/expected/select_having.out    8 Aug 2002 17:48:10 -0000
> ***************
> *** 14,20 ****
>   INSERT INTO test_having VALUES (8, 4, 'CCCC', 'I');
>   INSERT INTO test_having VALUES (9, 4, 'CCCC', 'j');
>   SELECT b, c FROM test_having
> !     GROUP BY b, c HAVING count(*) = 1;
>    b |    c
>   ---+----------
>    1 | XXXX
> --- 14,20 ----
>   INSERT INTO test_having VALUES (8, 4, 'CCCC', 'I');
>   INSERT INTO test_having VALUES (9, 4, 'CCCC', 'j');
>   SELECT b, c FROM test_having
> !     GROUP BY b, c HAVING count(*) = 1 ORDER BY b, c;
>    b |    c
>   ---+----------
>    1 | XXXX
> ***************
> *** 23,37 ****
>
>   -- HAVING is equivalent to WHERE in this case
>   SELECT b, c FROM test_having
> !     GROUP BY b, c HAVING b = 3;
>    b |    c
>   ---+----------
> -  3 | BBBB
>    3 | bbbb
>   (2 rows)
>
>   SELECT lower(c), count(c) FROM test_having
> !     GROUP BY lower(c) HAVING count(*) > 2 OR min(a) = max(a);
>     lower   | count
>   ----------+-------
>    bbbb     |     3
> --- 23,37 ----
>
>   -- HAVING is equivalent to WHERE in this case
>   SELECT b, c FROM test_having
> !     GROUP BY b, c HAVING b = 3 ORDER BY b, c;
>    b |    c
>   ---+----------
>    3 | bbbb
> +  3 | BBBB
>   (2 rows)
>
>   SELECT lower(c), count(c) FROM test_having
> !     GROUP BY lower(c) HAVING count(*) > 2 OR min(a) = max(a) ORDER BY lower(c);
>     lower   | count
>   ----------+-------
>    bbbb     |     3
> ***************
> *** 40,50 ****
>   (3 rows)
>
>   SELECT c, max(a) FROM test_having
> !     GROUP BY c HAVING count(*) > 2 OR min(a) = max(a);
>       c     | max
>   ----------+-----
> -  XXXX     |   0
>    bbbb     |   5
>   (2 rows)
>
>   DROP TABLE test_having;
> --- 40,50 ----
>   (3 rows)
>
>   SELECT c, max(a) FROM test_having
> !     GROUP BY c HAVING count(*) > 2 OR min(a) = max(a) ORDER BY c;
>       c     | max
>   ----------+-----
>    bbbb     |   5
> +  XXXX     |   0
>   (2 rows)
>
>   DROP TABLE test_having;
> 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    8 Aug 2002 14:50:00 -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;
> Index: src/test/regress/sql/select_having.sql
> ===================================================================
> RCS file: /opt/src/cvs/pgsql-server/src/test/regress/sql/select_having.sql,v
> retrieving revision 1.7
> diff -c -r1.7 select_having.sql
> *** src/test/regress/sql/select_having.sql    26 Jun 2002 21:58:56 -0000    1.7
> --- src/test/regress/sql/select_having.sql    8 Aug 2002 17:43:02 -0000
> ***************
> *** 16,32 ****
>   INSERT INTO test_having VALUES (9, 4, 'CCCC', 'j');
>
>   SELECT b, c FROM test_having
> !     GROUP BY b, c HAVING count(*) = 1;
>
>   -- HAVING is equivalent to WHERE in this case
>   SELECT b, c FROM test_having
> !     GROUP BY b, c HAVING b = 3;
>
>   SELECT lower(c), count(c) FROM test_having
> !     GROUP BY lower(c) HAVING count(*) > 2 OR min(a) = max(a);
>
>   SELECT c, max(a) FROM test_having
> !     GROUP BY c HAVING count(*) > 2 OR min(a) = max(a);
>
>   DROP TABLE test_having;
>
> --- 16,32 ----
>   INSERT INTO test_having VALUES (9, 4, 'CCCC', 'j');
>
>   SELECT b, c FROM test_having
> !     GROUP BY b, c HAVING count(*) = 1 ORDER BY b, c;
>
>   -- HAVING is equivalent to WHERE in this case
>   SELECT b, c FROM test_having
> !     GROUP BY b, c HAVING b = 3 ORDER BY b, c;
>
>   SELECT lower(c), count(c) FROM test_having
> !     GROUP BY lower(c) HAVING count(*) > 2 OR min(a) = max(a) ORDER BY lower(c);
>
>   SELECT c, max(a) FROM test_having
> !     GROUP BY c HAVING count(*) > 2 OR min(a) = max(a) ORDER BY c;
>
>   DROP TABLE test_having;
>

>
> ---------------------------(end of broadcast)---------------------------
> TIP 1: subscribe and unsubscribe commands go to majordomo@postgresql.org

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

pgsql-patches by date:

Previous
From: Tom Lane
Date:
Subject: Re: pg_settings view
Next
From: Bruce Momjian
Date:
Subject: Re: little psql additions