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: