comp-type.2002.08.14.2.patch

text/plain

Filename: comp-type.2002.08.14.2.patch
Type: text/plain
Part: 0
Message: Re: stand-alone composite types patch (was [HACKERS] Proposal:

Patch

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