comp-type.2002.08.07.2.patch

text/plain

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

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 3 2
src/backend/commands/typecmds.c 93 3
src/backend/nodes/copyfuncs.c 14 0
src/backend/nodes/equalfuncs.c 14 0
src/backend/parser/gram.y 37 1
src/backend/tcop/postgres.c 4 0
src/backend/tcop/utility.c 8 0
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/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	8 Aug 2002 03:54:32 -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 02:49:47 -0000
***************
*** 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/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 02:49:47 -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"
***************
*** 49,55 ****
  
  
  static Oid findTypeIOFunction(List *procname, bool isOutput);
! 
  
  /*
   * DefineType
--- 50,57 ----
  
  
  static Oid findTypeIOFunction(List *procname, bool isOutput);
! static void DefineCompositeTypeRelation(const RangeVar *typevar,
! 											List *coldeflist);
  
  /*
   * DefineType
***************
*** 251,256 ****
--- 253,259 ----
  	Oid			typeoid;
  	HeapTuple	tup;
  	ObjectAddress object;
+ 	char		typtype;
  
  	/* Make a TypeName so we can use standard type lookup machinery */
  	typename = makeNode(TypeName);
***************
*** 277,289 ****
  								 GetUserId()))
  		aclcheck_error(ACLCHECK_NOT_OWNER, TypeNameToString(typename));
  
  	ReleaseSysCache(tup);
  
  	/*
  	 * Do the deletion
  	 */
! 	object.classId = RelOid_pg_type;
! 	object.objectId = typeoid;
  	object.objectSubId = 0;
  
  	performDeletion(&object, behavior);
--- 280,317 ----
  								 GetUserId()))
  		aclcheck_error(ACLCHECK_NOT_OWNER, TypeNameToString(typename));
  
+ 	typtype = ((Form_pg_type) GETSTRUCT(tup))->typtype;
+ 
  	ReleaseSysCache(tup);
  
  	/*
  	 * Do the deletion
  	 */
! 	if (typtype != 'c')
! 	{
! 		object.classId = RelOid_pg_type;
! 		object.objectId = typeoid;
! 	}
! 	else
! 	{
! 		Oid			relid = typeidTypeRelid(typeoid);
! 		Relation	rel = relation_open(relid, AccessShareLock);
! 		char		relkind = rel->rd_rel->relkind;
! 
! 		relation_close(rel, AccessShareLock);
! 
! 		if (relkind == RELKIND_COMPOSITE_TYPE)
! 		{
! 			object.classId = RelOid_pg_class;
! 			object.objectId = relid;
! 		}
! 		else
! 		{
! 			object.classId = RelOid_pg_type;
! 			object.objectId = typeoid;
! 		}
! 
! 	}
  	object.objectSubId = 0;
  
  	performDeletion(&object, behavior);
***************
*** 665,668 ****
--- 693,758 ----
  	}
  
  	return procOid;
+ }
+ 
+ /*---------------------------------------------------------------------
+  * DefineCompositeTypeRelation
+  *
+  * 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...
+  *---------------------------------------------------------------------
+  */
+ static void
+ DefineCompositeTypeRelation(const RangeVar *typevar, List *coldeflist)
+ {
+ 	Oid			relid;
+ 	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...
+ 	 */
+ 	relid = DefineRelation(createStmt, RELKIND_COMPOSITE_TYPE);
+ }
+ 
+ /*-------------------------------------------------------------------
+  * DefineCompositeType
+  *
+  *		- takes a "typevar", "coldeflist" pair and then
+  *		constructs the "virtual" relation
+  *-------------------------------------------------------------------
+  */
+ void
+ DefineCompositeType(const RangeVar *typevar, List *coldeflist)
+ {
+ 	/*
+ 	 * Create the composite type relation
+ 	 *
+ 	 * NOTE: if it already exists, the xact will be aborted.
+ 	 */
+ 	DefineCompositeTypeRelation(typevar, coldeflist);
+ 
+ 	/*
+ 	 * The relation we have just created is not visible to any other
+ 	 * commands running with the same transaction & command id. So,
+ 	 * increment the command id counter (but do NOT pfree any memory!!!!)
+ 	 */
+ 	CommandCounterIncrement();
  }
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 02:49:47 -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 02:49:47 -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 03:38:46 -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/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 02:49:47 -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 02:49:47 -0000
***************
*** 573,578 ****
--- 573,586 ----
  			}
  			break;
  
+ 		case T_CompositeTypeStmt:		/* CREATE TYPE (composite) */
+ 			{
+ 				CompositeTypeStmt   *stmt = (CompositeTypeStmt *) parsetree;
+ 
+ 				DefineCompositeType(stmt->typevar, stmt->coldeflist);
+ 			}
+ 			break;
+ 
  		case T_ViewStmt:		/* CREATE VIEW */
  			{
  				ViewStmt   *stmt = (ViewStmt *) parsetree;
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 02:49:47 -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 02:49:47 -0000
***************
*** 58,63 ****
--- 58,64 ----
  extern void RemoveTypeById(Oid typeOid);
  extern void DefineDomain(CreateDomainStmt *stmt);
  extern void RemoveDomain(List *names, DropBehavior behavior);
+ extern void 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 02:49:47 -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 02:49:47 -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/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 03:41:27 -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	8 Aug 2002 03:09:48 -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;