? GNUmakefile
? config.cache
? config.log
? config.status
? src/GNUmakefile
? src/Makefile.global
? src/backend/postgres.def
? src/backend/catalog/postgres.bki
? src/backend/catalog/postgres.description
? src/backend/port/Makefile
? src/bin/initdb/initdb
? src/bin/initlocation/initlocation
? src/bin/ipcclean/ipcclean
? src/bin/pg_config/pg_config
? src/bin/pg_ctl/pg_ctl
? src/bin/pg_dump/pg_dumpall
? src/bin/scripts/createlang
? src/include/pg_config.h
? src/include/stamp-h
? src/interfaces/ecpg/lib/ecpg.def
? src/interfaces/ecpg/lib/ecpg.dll
? src/interfaces/libpgeasy/pgeasy.def
? src/interfaces/libpgeasy/pgeasy.dll
? src/interfaces/libpq/pq.def
? src/interfaces/libpq/pq.dll
? src/pl/plpgsql/src/plpgsql.def
? src/pl/plpgsql/src/plpgsql.dll
Index: src/backend/commands/define.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/commands/define.c,v
retrieving revision 1.64
diff -u -r1.64 define.c
--- src/backend/commands/define.c	2001/10/28 06:25:42	1.64
+++ src/backend/commands/define.c	2002/02/16 22:42:24
@@ -526,6 +526,150 @@
 }
 
 /*
+ * DefineDomain
+ *		Registers a new domain.
+ */
+void
+DefineDomain(CreateDomainStmt *stmt)
+{
+	int16		internalLength = -1;	/* int2 */
+	int16		externalLength = -1;	/* int2 */
+	char	   *inputName = NULL;
+	char	   *outputName = NULL;
+	char	   *sendName = NULL;
+	char	   *receiveName = NULL;
+	char	   *defaultValue = NULL;
+	bool		byValue = false;
+	char		delimiter = DEFAULT_TYPDELIM;
+	char		alignment = 'i';	/* default alignment */
+	char		storage = 'p';	/* default TOAST storage method */
+	char		typtype;
+	Datum		datum;
+
+	bool		isnull;
+	Relation	pg_type_rel;
+	TupleDesc	pg_type_dsc;
+	HeapTuple	typeTup;
+
+	/*
+	 * Domainnames, unlike typenames don't need to account for the '_'
+	 * prefix.  So they can be one character longer.
+	 */
+	if (strlen(stmt->domainname) > (NAMEDATALEN - 1))
+		elog(ERROR, "CREATE DOMAIN: domain names must be %d characters or less",
+			 NAMEDATALEN - 1);
+
+
+	/* Test for existing Domain (or type) of that name */
+	typeTup = SearchSysCache( TYPENAME
+							, PointerGetDatum(stmt->domainname)
+							, 0, 0, 0
+							);
+	if (HeapTupleIsValid(typeTup))
+	{
+		elog(ERROR, "CREATE DOMAIN: domain or type  %s already exists",
+			 stmt->domainname);
+	}
+
+
+	/*
+	 * Get the information about old types
+	 */
+	pg_type_rel = heap_openr(TypeRelationName, RowExclusiveLock);
+	pg_type_dsc = RelationGetDescr(pg_type_rel);
+
+	typeTup = SearchSysCache( TYPENAME
+							, PointerGetDatum(stmt->typename)
+							, 0, 0, 0
+							);
+	if (!HeapTupleIsValid(typeTup))
+	{
+		elog(ERROR, "CREATE DOMAIN: type %s does not exist",
+			 stmt->typename);
+	}
+
+	/* Check that this is a basetype */
+	typtype = 			DatumGetChar(heap_getattr(typeTup, Anum_pg_type_typtype, pg_type_dsc, &isnull));
+	Assert(!isnull);
+
+	if (typtype != 'b') {
+		elog(ERROR, "%s is not a basetype", stmt->typename);
+	}
+
+	elog(DEBUG, "NOTE: Extracting information");
+	/* Extract useful data */
+	byValue = 			DatumGetBool(heap_getattr(typeTup, Anum_pg_type_typbyval, pg_type_dsc, &isnull));
+	Assert(!isnull);
+
+	alignment = 		DatumGetChar(heap_getattr(typeTup, Anum_pg_type_typalign, pg_type_dsc, &isnull));
+	Assert(!isnull);
+
+	internalLength = 	DatumGetInt16(heap_getattr(typeTup, Anum_pg_type_typlen, pg_type_dsc, &isnull));
+	Assert(!isnull);
+
+	externalLength = 	DatumGetInt16(heap_getattr(typeTup, Anum_pg_type_typprtlen, pg_type_dsc, &isnull));
+	Assert(!isnull);
+
+	delimiter = 		DatumGetChar(heap_getattr(typeTup, Anum_pg_type_typdelim, pg_type_dsc, &isnull));
+	Assert(!isnull);
+
+
+	datum = 			heap_getattr(typeTup, Anum_pg_type_typinput, pg_type_dsc, &isnull);
+	Assert(!isnull);
+
+	inputName = 		DatumGetCString(DirectFunctionCall1(regprocout, datum));
+
+
+	datum = 			heap_getattr(typeTup, Anum_pg_type_typoutput, pg_type_dsc, &isnull);
+	Assert(!isnull);
+
+	outputName = 		DatumGetCString(DirectFunctionCall1(regprocout, datum));
+
+
+/* Not used
+	receiveName = 		DatumGetPointer(heap_getattr(typeTup, Anum_pg_type_typreceive, pg_type_dsc, &isnull));
+	Assert(!isnull);
+
+	sendName = 			DatumGetPointer(heap_getattr(typeTup, Anum_pg_type_typsend, pg_type_dsc, &isnull));
+	Assert(!isnull);
+*/
+
+	storage = 			DatumGetChar(heap_getattr(typeTup, Anum_pg_type_typstorage, pg_type_dsc, &isnull));
+	Assert(!isnull);
+
+
+	datum = 			heap_getattr(typeTup, Anum_pg_type_typdefault, pg_type_dsc, &isnull);
+	if (!isnull) {
+		defaultValue = 		DatumGetCString(DirectFunctionCall1(textout, datum));
+	}
+
+	/*
+	 * now have TypeCreate do all the real work.
+	 */
+	TypeCreate(stmt->domainname,	/* type name */
+			   InvalidOid,			/* preassigned type oid (not done here) */
+			   InvalidOid,			/* relation oid (n/a here) */
+			   internalLength,		/* internal size */
+			   externalLength,		/* external size */
+			   'd',					/* type-type (domain type) */
+			   delimiter,			/* array element delimiter */
+			   inputName,			/* input procedure */
+			   outputName,			/* output procedure */
+			   receiveName,			/* receive procedure */
+			   sendName,			/* send procedure */
+			   stmt->typename,		/* element type name */
+			   defaultValue,		/* default type value */
+			   byValue,				/* passed by value */
+			   alignment,			/* required alignment */
+			   storage);			/* TOAST strategy */
+
+	/*
+	 * Now we can clean up.
+	 */
+	heap_close(pg_type_rel, NoLock);
+}
+
+/*
  * DefineType
  *		Registers a new type.
  */
Index: src/backend/commands/remove.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/commands/remove.c,v
retrieving revision 1.65
diff -u -r1.65 remove.c
--- src/backend/commands/remove.c	2001/11/05 17:46:24	1.65
+++ src/backend/commands/remove.c	2002/02/16 22:42:24
@@ -1,7 +1,7 @@
 /*-------------------------------------------------------------------------
  *
  * remove.c
- *	  POSTGRES remove (function | type | operator ) utilty code.
+ *	  POSTGRES remove (function | domain | type | operator ) utilty code.
  *
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
@@ -22,6 +22,7 @@
 #include "commands/comment.h"
 #include "commands/defrem.h"
 #include "miscadmin.h"
+#include "parser/parse.h"
 #include "parser/parse_agg.h"
 #include "parser/parse_expr.h"
 #include "parser/parse_func.h"
@@ -274,6 +275,62 @@
 
 	heap_close(relation, RowExclusiveLock);
 }
+
+
+/*
+ *	RemoveDomain
+ *		Removes the domain 'typeName' and all attributes and relations that
+ *		use it.
+ */
+void
+RemoveDomain(char *domainName, int behavior)		/* domain name to be removed */
+{
+	Relation	relation;
+	HeapTuple	tup;
+	TupleDesc	description;
+	char		typtype;
+	bool		isnull;
+
+
+	/* Domains are stored as types.  Check for permissions on the type */
+	if (!pg_ownercheck(GetUserId(), domainName, TYPENAME))
+		elog(ERROR, "RemoveDomain: type '%s': permission denied",
+			 domainName);
+
+
+	relation = heap_openr(TypeRelationName, RowExclusiveLock);
+	description = RelationGetDescr(relation);
+
+	tup = SearchSysCache(TYPENAME,
+						 PointerGetDatum(domainName),
+						 0, 0, 0);
+	if (!HeapTupleIsValid(tup))
+		elog(ERROR, "RemoveType: type '%s' does not exist", domainName);
+
+
+	/* Check that this is actually a domain */
+	typtype = DatumGetChar(heap_getattr(tup, Anum_pg_type_typtype, description, &isnull));
+	Assert(!isnull);
+
+	if (typtype != 'd') {
+		elog(ERROR, "%s is not a domain", domainName);
+	}
+
+	/* CASCADE unsupported */
+	if (behavior == CASCADE) {
+		elog(ERROR, "DROP DOMAIN does not support the CASCADE keyword");
+	}
+
+	/* Delete any comments associated with this type */
+	DeleteComments(tup->t_data->t_oid, RelationGetRelid(relation));
+
+	simple_heap_delete(relation, &tup->t_self);
+
+	ReleaseSysCache(tup);
+
+	heap_close(relation, RowExclusiveLock);
+}
+
 
 /*
  * RemoveFunction
Index: src/backend/nodes/copyfuncs.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v
retrieving revision 1.160
diff -u -r1.160 copyfuncs.c
--- src/backend/nodes/copyfuncs.c	2001/11/05 05:00:14	1.160
+++ src/backend/nodes/copyfuncs.c	2002/02/16 22:42:25
@@ -2210,6 +2210,19 @@
 	return newnode;
 }
 
+static CreateDomainStmt *
+_copyCreateDomainStmt(CreateDomainStmt *from)
+{
+	CreateDomainStmt *newnode = makeNode(CreateDomainStmt);
+
+	if (from->domainname)
+		newnode->domainname = pstrdup(from->domainname);
+	if (from->typename)
+		newnode->typename = pstrdup(from->typename);
+
+	return newnode;
+}
+
 static CreatedbStmt *
 _copyCreatedbStmt(CreatedbStmt *from)
 {
Index: src/backend/nodes/equalfuncs.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v
retrieving revision 1.108
diff -u -r1.108 equalfuncs.c
--- src/backend/nodes/equalfuncs.c	2001/11/05 05:00:14	1.108
+++ src/backend/nodes/equalfuncs.c	2002/02/16 22:42:27
@@ -1086,6 +1086,17 @@
 }
 
 static bool
+_equalCreateDomainStmt(CreateDomainStmt *a, CreateDomainStmt *b)
+{
+	if (!equalstr(a->domainname, b->domainname))
+		return false;
+	if (!equalstr(a->typename, b->typename))
+		return false;
+
+	return true;
+}
+
+static bool
 _equalCreatedbStmt(CreatedbStmt *a, CreatedbStmt *b)
 {
 	if (!equalstr(a->dbname, b->dbname))
@@ -1973,6 +1984,12 @@
 		case T_LoadStmt:
 			retval = _equalLoadStmt(a, b);
 			break;
+		case T_CreateDomainStmt:
+			retval = _equalCreateDomainStmt(a, b);
+			break;
+/*		case T_DropDomainStmt:
+			retval = _equalDropdbStmt(a, b);
+			break;*/
 		case T_CreatedbStmt:
 			retval = _equalCreatedbStmt(a, b);
 			break;
Index: src/backend/parser/gram.y
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/parser/gram.y,v
retrieving revision 2.276
diff -u -r2.276 gram.y
--- src/backend/parser/gram.y	2001/12/09 04:39:39	2.276
+++ src/backend/parser/gram.y	2002/02/16 22:42:52
@@ -135,7 +135,8 @@
 		ClosePortalStmt, ClusterStmt, CommentStmt, ConstraintsSetStmt,
 		CopyStmt, CreateAsStmt, CreateGroupStmt, CreatePLangStmt,
 		CreateSchemaStmt, CreateSeqStmt, CreateStmt, CreateTrigStmt,
-		CreateUserStmt, CreatedbStmt, CursorStmt, DefineStmt, DeleteStmt,
+		CreateUserStmt, CreateDomainStmt, CreatedbStmt, CursorStmt,
+		DefineStmt, DeleteStmt,
 		DropGroupStmt, DropPLangStmt, DropSchemaStmt, DropStmt, DropTrigStmt,
 		DropUserStmt, DropdbStmt, ExplainStmt, FetchStmt,
 		GrantStmt, IndexStmt, InsertStmt, ListenStmt, LoadStmt, LockStmt,
@@ -284,6 +285,8 @@
 %type <list>	constraints_set_namelist
 %type <boolean>	constraints_set_mode
 
+%type <boolean> opt_as
+
 /*
  * If you make any token changes, remember to:
  *		- use "yacc -d" and update parse.h
@@ -338,7 +341,7 @@
 		WITHOUT
 
 /* Keywords (in SQL92 non-reserved words) */
-%token	COMMITTED, SERIALIZABLE, TYPE_P
+%token	COMMITTED, SERIALIZABLE, TYPE_P, DOMAIN_P
 
 /* Keywords for Postgres support (not in SQL92 reserved words)
  *
@@ -439,6 +442,7 @@
 		| CopyStmt
 		| CreateStmt
 		| CreateAsStmt
+		| CreateDomainStmt
 		| CreateSchemaStmt
 		| CreateGroupStmt
 		| CreateSeqStmt
@@ -748,8 +752,11 @@
 					n->dbname = $3;
 					$$ = (Node *)n;
 				}
+		;
 
 
+ 
+
 /*****************************************************************************
  *
  * Set PG internal variable
@@ -2039,6 +2046,15 @@
 					DropStmt *n = makeNode(DropStmt);
 					n->removeType = $2;
 					n->names = $3;
+					n->behavior = NULL;
+					$$ = (Node *)n;
+				}
+		| DROP DOMAIN_P name_list drop_behavior
+				{	
+					DropStmt *n = makeNode(DropStmt);
+					n->removeType = DROP_DOMAIN_P;
+					n->names = $3;
+					n->behavior = $4;
 					$$ = (Node *)n;
 				}
 		;
@@ -2071,7 +2087,7 @@
  *  The COMMENT ON statement can take different forms based upon the type of
  *  the object associated with the comment. The form of the statement is:
  *
- *  COMMENT ON [ [ DATABASE | INDEX | RULE | SEQUENCE | TABLE | TYPE | VIEW ] 
+ *  COMMENT ON [ [ DATABASE | DOMAIN | INDEX | RULE | SEQUENCE | TABLE | TYPE | VIEW ] 
  *               <objname> | AGGREGATE <aggname> (<aggtype>) | FUNCTION 
  *		 <funcname> (arg1, arg2, ...) | OPERATOR <op> 
  *		 (leftoperand_typ rightoperand_typ) | TRIGGER <triggername> ON
@@ -2157,6 +2173,7 @@
 		| RULE { $$ = RULE; }
 		| SEQUENCE { $$ = SEQUENCE; }
 		| TABLE { $$ = TABLE; }
+		| DOMAIN_P { $$ = TYPE_P; }
 		| TYPE_P { $$ = TYPE_P; }
 		| VIEW { $$ = VIEW; }
 		;		
@@ -3129,6 +3146,25 @@
 				}
 		;
 
+/*****************************************************************************
+ *
+ * Manipulate a domain
+ *
+ *
+ *****************************************************************************/
+
+CreateDomainStmt:  CREATE DOMAIN_P opt_as name name
+				{
+					CreateDomainStmt *n = makeNode(CreateDomainStmt);
+					n->domainname = $4;
+					n->typename = $5;
+					$$ = (Node *)n;
+				}	
+		;
+
+opt_as:	AS	{$$ = TRUE; }
+	| /* EMPTY */	{$$ = FALSE; }
+	;
 
 /*****************************************************************************
  *
@@ -5772,6 +5808,7 @@
 		| DEFERRED						{ $$ = "deferred"; }
 		| DELETE						{ $$ = "delete"; }
 		| DELIMITERS					{ $$ = "delimiters"; }
+		| DOMAIN_P						{ $$ = "domain"; }
 		| DOUBLE						{ $$ = "double"; }
 		| DROP							{ $$ = "drop"; }
 		| EACH							{ $$ = "each"; }
Index: src/backend/parser/keywords.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/parser/keywords.c,v
retrieving revision 1.99
diff -u -r1.99 keywords.c
--- src/backend/parser/keywords.c	2001/10/10 00:02:42	1.99
+++ src/backend/parser/keywords.c	2002/02/16 22:42:52
@@ -97,6 +97,7 @@
 	{"desc", DESC},
 	{"distinct", DISTINCT},
 	{"do", DO},
+	{"domain", DOMAIN_P},
 	{"double", DOUBLE},
 	{"drop", DROP},
 	{"each", EACH},
Index: src/backend/tcop/utility.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/tcop/utility.c,v
retrieving revision 1.125
diff -u -r1.125 utility.c
--- src/backend/tcop/utility.c	2002/02/07 00:27:30	1.125
+++ src/backend/tcop/utility.c	2002/02/16 22:42:53
@@ -280,6 +280,11 @@
 							/* RemoveType does its own permissions checks */
 							RemoveType(relname);
 							break;
+
+						case DROP_DOMAIN_P:
+							/* RemoveDomain does its own permissions checks */
+							RemoveDomain(relname, stmt->behavior);
+							break;
 					}
 
 					/*
@@ -796,6 +801,16 @@
 			set_ps_display(commandTag = "DROP");
 
 			DropProceduralLanguage((DropPLangStmt *) parsetree);
+			break;
+
+			/*
+			 * ******************************** DOMAIN statements ****
+			 *
+			 */
+		case T_CreateDomainStmt:
+			set_ps_display(commandTag = "CREATE DOMAIN");
+
+			DefineDomain((CreateDomainStmt *) parsetree);
 			break;
 
 			/*
Index: src/include/commands/defrem.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/commands/defrem.h,v
retrieving revision 1.28
diff -u -r1.28 defrem.h
--- src/include/commands/defrem.h	2001/11/05 17:46:33	1.28
+++ src/include/commands/defrem.h	2002/02/16 22:42:54
@@ -39,10 +39,12 @@
 extern void DefineOperator(char *name, List *parameters);
 extern void DefineAggregate(char *name, List *parameters);
 extern void DefineType(char *name, List *parameters);
+extern void DefineDomain(CreateDomainStmt *stmt);
 
 /*
  * prototypes in remove.c
  */
+extern void RemoveDomain(char *domainName, int behavior);
 extern void RemoveFunction(char *functionName, List *argTypes);
 extern void RemoveOperator(char *operatorName,
 			   char *typeName1, char *typeName2);
Index: src/include/nodes/nodes.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/nodes/nodes.h,v
retrieving revision 1.96
diff -u -r1.96 nodes.h
--- src/include/nodes/nodes.h	2001/11/05 17:46:34	1.96
+++ src/include/nodes/nodes.h	2002/02/16 22:42:54
@@ -172,6 +172,7 @@
 	T_TransactionStmt,
 	T_ViewStmt,
 	T_LoadStmt,
+	T_CreateDomainStmt,
 	T_CreatedbStmt,
 	T_DropdbStmt,
 	T_VacuumStmt,
Index: src/include/nodes/parsenodes.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/nodes/parsenodes.h,v
retrieving revision 1.151
diff -u -r1.151 parsenodes.h
--- src/include/nodes/parsenodes.h	2001/11/05 17:46:34	1.151
+++ src/include/nodes/parsenodes.h	2002/02/16 22:43:11
@@ -439,12 +439,14 @@
 #define DROP_INDEX	  4
 #define DROP_RULE	  5
 #define DROP_TYPE_P   6
+#define DROP_DOMAIN_P 7
 
 typedef struct DropStmt
 {
 	NodeTag		type;
 	List	   *names;
 	int			removeType;
+	int	   		behavior;		/* CASCADE or RESTRICT drop behavior */
 } DropStmt;
 
 /* ----------------------
@@ -652,6 +654,17 @@
 	NodeTag		type;
 	char	   *filename;		/* file to load */
 } LoadStmt;
+
+/* ----------------------
+ *		CreateDomain Statement
+ * ----------------------
+ */
+typedef struct CreateDomainStmt
+{
+	NodeTag		type;
+	char	   *domainname;			/* name of domain to create */
+	char	   *typename;			/* name of the type to base it off */
+} CreateDomainStmt;
 
 /* ----------------------
  *		Createdb Statement
