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 = alignment ]
[ , STORAGE = storage ]
)
+
+ CREATE TYPE typename AS
+ ( column_definition_list )
+
+ where column_definition_list can be:
+
+ ( column_name data_type [, ... ] )
***************
*** 138,143 ****
--- 145,169 ----
+
+
+ column_name
+
+
+ The name of a column of the composite type.
+
+
+
+
+
+ data_type
+
+
+ The name of an existing data type.
+
+
+
+
***************
*** 191,199 ****
! CREATE TYPE requires the registration of two functions
! (using CREATE FUNCTION) before defining the type. The
! representation of a new base type is determined by
input_function, which
converts the type's external representation to an internal
representation usable by the
--- 217,225 ----
! The first form of CREATE TYPE requires the
! registration of two functions (using CREATE FUNCTION) before defining the
! type. The representation of a new base type is determined by
input_function, which
converts the type's external representation to an internal
representation usable by the
***************
*** 288,293 ****
--- 314,327 ----
extended and external items.)
+
+ The second form of CREATE TYPE requires a column
+ definition list in the form ( column_name
+ data_type [, ... ] ). 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.
+
+
Array Types
***************
*** 370,375 ****
--- 404,418 ----
CREATE TYPE bigobj (INPUT = lo_filein, OUTPUT = lo_fileout,
INTERNALLENGTH = VARIABLE);
CREATE TABLE big_objs (id int4, obj bigobj);
+
+
+
+
+ This example creates a composite type and uses it in
+ a table function definition:
+
+ CREATE TYPE compfoo AS (f1 int, f2 int);
+ CREATE FUNCTION getfoo() RETURNS SETOF compfoo AS 'SELECT fooid, foorefid FROM foo' LANGUAGE SQL;
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 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 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;