? doc/src/sgml/ref/create_domain.sgml
? doc/src/sgml/ref/drop_domain.sgml
Index: doc/src/sgml/catalogs.sgml
===================================================================
RCS file: /projects/cvsroot/pgsql/doc/src/sgml/catalogs.sgml,v
retrieving revision 2.30
diff -c -r2.30 catalogs.sgml
*** doc/src/sgml/catalogs.sgml	2002/02/18 23:10:59	2.30
--- doc/src/sgml/catalogs.sgml	2002/02/26 02:56:15
***************
*** 2497,2502 ****
--- 2497,2549 ----
       </row>
  
       <row>
+       <entry>typbasetype</entry>
+       <entry><type>oid</type></entry>
+       <entry></entry>
+       <entry><para>
+        <structfield>typbasetype</structfield> is the type that this one is based
+        off of.  Normally references the domains parent type, and is 0 otherwise.
+       </para></entry>
+      </row>
+ 
+ 	 <row>
+ 	  <entry>typnotnull</entry>
+ 	  <entry><type>boolean</type></entry>
+ 	  <entry></entry>
+ 	  <entry><para>
+ 	   <structfield>typnotnull</structfield> represents a NOT NULL
+ 	   constraint on a type.  Normally used only for domains.
+ 	  </para></entry>
+ 	 </row>
+ 
+      <row>
+       <entry>typmod</entry>
+       <entry><type>integer</type></entry>
+       <entry></entry>
+       <entry><para>
+        <structfield>typmod</structfield> records type-specific data
+        supplied at table creation time (for example, the maximum
+        length of a <type>varchar</type> column).  It is passed to
+        type-specific input and output functions as the third
+        argument. The value will generally be -1 for types that do not
+        need typmod.  This data is copied to
+        <structfield>pg_attribute.atttypmod</structfield> on creation
+        of a table using a domain as it's field type.
+        </para></entry>
+      </row>
+ 
+      <row>
+       <entry>typdefaultbin</entry>
+       <entry><type>text</type></entry>
+       <entry></entry>
+       <entry><para>
+        <structfield>typdefaultbin</structfield> is NULL for types without a
+        default value.  If it's not NULL, it contains the internal string
+        representation of the default expression node.
+       </para></entry>
+      </row>
+ 
+      <row>
        <entry>typdefault</entry>
        <entry><type>text</type></entry>
        <entry></entry>
Index: doc/src/sgml/reference.sgml
===================================================================
RCS file: /projects/cvsroot/pgsql/doc/src/sgml/reference.sgml,v
retrieving revision 1.20
diff -c -r1.20 reference.sgml
*** doc/src/sgml/reference.sgml	2002/01/15 05:05:49	1.20
--- doc/src/sgml/reference.sgml	2002/02/26 02:56:15
***************
*** 60,65 ****
--- 60,66 ----
     &createAggregate;
     &createConstraint;
     &createDatabase;
+    &createDomain;
     &createFunction;
     &createGroup;
     &createIndex;
***************
*** 77,82 ****
--- 78,84 ----
     &delete;
     &dropAggregate;
     &dropDatabase;
+    &dropDomain;
     &dropFunction;
     &dropGroup;
     &dropIndex;
***************
*** 114,120 ****
     &unlisten;
     &update;
     &vacuum;
!   
   </reference>
  
  <!--
--- 116,122 ----
     &unlisten;
     &update;
     &vacuum;
! 
   </reference>
  
  <!--
Index: doc/src/sgml/ref/allfiles.sgml
===================================================================
RCS file: /projects/cvsroot/pgsql/doc/src/sgml/ref/allfiles.sgml,v
retrieving revision 1.32
diff -c -r1.32 allfiles.sgml
*** doc/src/sgml/ref/allfiles.sgml	2002/01/15 05:05:49	1.32
--- doc/src/sgml/ref/allfiles.sgml	2002/02/26 02:56:15
***************
*** 51,56 ****
--- 51,57 ----
  <!entity createAggregate    system "create_aggregate.sgml">
  <!entity createConstraint   system "create_constraint.sgml">
  <!entity createDatabase     system "create_database.sgml">
+ <!entity createDomain       system "create_domain.sgml">
  <!entity createFunction     system "create_function.sgml">
  <!entity createGroup        system "create_group.sgml">
  <!entity createIndex        system "create_index.sgml">
***************
*** 68,73 ****
--- 69,75 ----
  <!entity delete             system "delete.sgml">
  <!entity dropAggregate      system "drop_aggregate.sgml">
  <!entity dropDatabase       system "drop_database.sgml">
+ <!entity dropDomain         system "drop_domain.sgml">
  <!entity dropFunction       system "drop_function.sgml">
  <!entity dropGroup          system "drop_group.sgml">
  <!entity dropIndex          system "drop_index.sgml">
Index: doc/src/sgml/ref/comment.sgml
===================================================================
RCS file: /projects/cvsroot/pgsql/doc/src/sgml/ref/comment.sgml,v
retrieving revision 1.12
diff -c -r1.12 comment.sgml
*** doc/src/sgml/ref/comment.sgml	2001/12/27 21:36:57	1.12
--- doc/src/sgml/ref/comment.sgml	2002/02/26 02:56:17
***************
*** 25,31 ****
    <synopsis>
  COMMENT ON
  [
!   [ DATABASE | INDEX | RULE | SEQUENCE | TABLE | TYPE | VIEW ] <replaceable class="PARAMETER">object_name</replaceable> |
    COLUMN <replaceable class="PARAMETER">table_name</replaceable>.<replaceable class="PARAMETER">column_name</replaceable> |
    AGGREGATE <replaceable class="PARAMETER">agg_name</replaceable> (<replaceable class="PARAMETER">agg_type</replaceable>) |
    FUNCTION <replaceable class="PARAMETER">func_name</replaceable> (<replaceable class="PARAMETER">arg1</replaceable>, <replaceable class="PARAMETER">arg2</replaceable>, ...) |
--- 25,31 ----
    <synopsis>
  COMMENT ON
  [
!   [ DATABASE | DOMAIN | INDEX | RULE | SEQUENCE | TABLE | TYPE | VIEW ] <replaceable class="PARAMETER">object_name</replaceable> |
    COLUMN <replaceable class="PARAMETER">table_name</replaceable>.<replaceable class="PARAMETER">column_name</replaceable> |
    AGGREGATE <replaceable class="PARAMETER">agg_name</replaceable> (<replaceable class="PARAMETER">agg_type</replaceable>) |
    FUNCTION <replaceable class="PARAMETER">func_name</replaceable> (<replaceable class="PARAMETER">arg1</replaceable>, <replaceable class="PARAMETER">arg2</replaceable>, ...) |
***************
*** 33,39 ****
    TRIGGER <replaceable class="PARAMETER">trigger_name</replaceable> ON <replaceable class="PARAMETER">table_name</replaceable>
  ] IS <replaceable class="PARAMETER">'text'</replaceable>
    </synopsis>
!   
    <refsect2 id="R2-SQL-COMMENT-1">
     <refsect2info>
      <date>1999-10-25</date>
--- 33,39 ----
    TRIGGER <replaceable class="PARAMETER">trigger_name</replaceable> ON <replaceable class="PARAMETER">table_name</replaceable>
  ] IS <replaceable class="PARAMETER">'text'</replaceable>
    </synopsis>
! 
    <refsect2 id="R2-SQL-COMMENT-1">
     <refsect2info>
      <date>1999-10-25</date>
***************
*** 64,70 ****
      </variablelist>
     </para>
    </refsect2>
!   
    <refsect2 id="R2-SQL-COMMENT-2">
     <refsect2info>
      <date>1998-09-08</date>
--- 64,70 ----
      </variablelist>
     </para>
    </refsect2>
! 
    <refsect2 id="R2-SQL-COMMENT-2">
     <refsect2info>
      <date>1998-09-08</date>
***************
*** 99,105 ****
    </title>
    <para>
     <command>COMMENT</command> stores a comment about a database object.
!     Comments can be 
      easily retrieved with <command>psql</command>'s
      <command>\dd</command>, <command>\d+</command>, or <command>\l+</command>
      commands.  Other user interfaces to retrieve comments can be built atop
--- 99,105 ----
    </title>
    <para>
     <command>COMMENT</command> stores a comment about a database object.
!     Comments can be
      easily retrieved with <command>psql</command>'s
      <command>\dd</command>, <command>\d+</command>, or <command>\l+</command>
      commands.  Other user interfaces to retrieve comments can be built atop
***************
*** 141,146 ****
--- 141,147 ----
  
     <programlisting>
  COMMENT ON DATABASE my_database IS 'Development Database';
+ COMMENT ON DOMAIN my_domain IS 'Domains are like abstracted fields';
  COMMENT ON INDEX my_index IS 'Enforces uniqueness on employee id';
  COMMENT ON RULE my_rule IS 'Logs UPDATES of employee records';
  COMMENT ON SEQUENCE my_sequence IS 'Used to generate primary keys';
***************
*** 155,166 ****
     </programlisting>
    </para>
   </refsect1>
!  
   <refsect1 id="R1-SQL-COMMENT-3">
    <title>
     Compatibility
    </title>
!   
    <refsect2 id="R2-SQL-COMMENT-4">
     <refsect2info>
      <date>1998-09-08</date>
--- 156,167 ----
     </programlisting>
    </para>
   </refsect1>
! 
   <refsect1 id="R1-SQL-COMMENT-3">
    <title>
     Compatibility
    </title>
! 
    <refsect2 id="R2-SQL-COMMENT-4">
     <refsect2info>
      <date>1998-09-08</date>
Index: src/backend/catalog/heap.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/catalog/heap.c,v
retrieving revision 1.182
diff -c -r1.182 heap.c
*** src/backend/catalog/heap.c	2002/02/19 20:11:11	1.182
--- src/backend/catalog/heap.c	2002/02/26 02:56:21
***************
*** 700,709 ****
  			   "oidin",			/* receive procedure */
  			   "oidout",		/* send procedure */
  			   NULL,			/* array element type - irrelevant */
  			   NULL,			/* default type value - none */
  			   true,			/* passed by value */
  			   'i',				/* default alignment - same as for OID */
! 			   'p');			/* Not TOASTable */
  }
  
  /* --------------------------------
--- 700,714 ----
  			   "oidin",			/* receive procedure */
  			   "oidout",		/* send procedure */
  			   NULL,			/* array element type - irrelevant */
+ 			   NULL,			/* baseType Name -- typically for domiains */
  			   NULL,			/* default type value - none */
+ 			   NULL,			/* default type binary representation */
  			   true,			/* passed by value */
  			   'i',				/* default alignment - same as for OID */
! 			   'p',				/* Not TOASTable */
! 			   -1,				/* Type mod length */
! 			   0,				/* array dimensions for typBaseType */
! 			   false);			/* Type NOT NULL */
  }
  
  /* --------------------------------
***************
*** 1585,1590 ****
--- 1590,1599 ----
  	HeapTuple	reltup;
  	Form_pg_class relStruct;
  
+ 	/* Probably shouldn't be null by default */
+ 	Node	   *expr = NULL;
+ 
+ 
  	/*
  	 * Get info about existing constraints.
  	 */
***************
*** 1615,1684 ****
  	foreach(listptr, rawColDefaults)
  	{
  		RawColumnDefault *colDef = (RawColumnDefault *) lfirst(listptr);
- 		Node	   *expr;
- 		Oid			type_id;
  
- 		Assert(colDef->raw_default != NULL);
  
! 		/*
! 		 * Transform raw parsetree to executable expression.
! 		 */
! 		expr = transformExpr(pstate, colDef->raw_default, EXPR_COLUMN_FIRST);
  
! 		/*
! 		 * Make sure default expr does not refer to any vars.
! 		 */
! 		if (contain_var_clause(expr))
! 			elog(ERROR, "cannot use column references in DEFAULT clause");
  
  		/*
- 		 * No subplans or aggregates, either...
- 		 */
- 		if (contain_subplans(expr))
- 			elog(ERROR, "cannot use subselects in DEFAULT clause");
- 		if (contain_agg_clause(expr))
- 			elog(ERROR, "cannot use aggregate functions in DEFAULT clause");
- 
- 		/*
- 		 * Check that it will be possible to coerce the expression to the
- 		 * column's type.  We store the expression without coercion,
- 		 * however, to avoid premature coercion in cases like
- 		 *
- 		 * CREATE TABLE tbl (fld datetime DEFAULT 'now'::text);
- 		 *
- 		 * NB: this should match the code in optimizer/prep/preptlist.c that
- 		 * will actually do the coercion, to ensure we don't accept an
- 		 * unusable default expression.
- 		 */
- 		type_id = exprType(expr);
- 		if (type_id != InvalidOid)
- 		{
- 			Form_pg_attribute atp = rel->rd_att->attrs[colDef->attnum - 1];
- 
- 			if (type_id != atp->atttypid)
- 			{
- 				if (CoerceTargetExpr(NULL, expr, type_id,
- 								  atp->atttypid, atp->atttypmod) == NULL)
- 					elog(ERROR, "Column \"%s\" is of type %s"
- 						 " but default expression is of type %s"
- 					"\n\tYou will need to rewrite or cast the expression",
- 						 NameStr(atp->attname),
- 						 format_type_be(atp->atttypid),
- 						 format_type_be(type_id));
- 			}
- 		}
- 
- 		/*
- 		 * Might as well try to reduce any constant expressions.
- 		 */
- 		expr = eval_const_expressions(expr);
- 
- 		/*
- 		 * Must fix opids, in case any operators remain...
- 		 */
- 		fix_opids(expr);
- 
- 		/*
  		 * OK, store it.
  		 */
  		StoreAttrDefault(rel, colDef->attnum, nodeToString(expr), true);
--- 1624,1638 ----
  	foreach(listptr, rawColDefaults)
  	{
  		RawColumnDefault *colDef = (RawColumnDefault *) lfirst(listptr);
  
  
! 		Form_pg_attribute atp = rel->rd_att->attrs[colDef->attnum - 1];
  
! 		expr = cookDefault(pstate, colDef->raw_default
! 						, atp->atttypid, atp->atttypmod
! 						, NameStr(atp->attname));
  
  		/*
  		 * OK, store it.
  		 */
  		StoreAttrDefault(rel, colDef->attnum, nodeToString(expr), true);
***************
*** 1864,1869 ****
--- 1818,1905 ----
  	heap_freetuple(reltup);
  	heap_close(relrel, RowExclusiveLock);
  }
+ 
+ /*
+  * Take a raw default and convert it to a cooked format ready for
+  * storage.
+  *
+  * Parse state, attypid, attypmod and attname are required for
+  * CoerceTargetExpr() and more importantly transformExpr().
+  */
+ Node *
+ cookDefault(ParseState *pstate
+ 			, Node *raw_default
+ 			, Oid atttypid
+ 			, int32 atttypmod
+ 			, char *attname) {
+ 
+ 	Oid			type_id;
+ 	Node		*expr;
+ 
+ 	Assert(raw_default != NULL);
+ 
+ 	/*
+ 	 * Transform raw parsetree to executable expression.
+ 	 */
+ 	expr = transformExpr(pstate, raw_default, EXPR_COLUMN_FIRST);
+ 
+ 	/*
+ 	 * Make sure default expr does not refer to any vars.
+ 	 */
+ 	if (contain_var_clause(expr))
+ 		elog(ERROR, "cannot use column references in DEFAULT clause");
+ 
+ 	/*
+ 	 * No subplans or aggregates, either...
+ 	 */
+ 	if (contain_subplans(expr))
+ 		elog(ERROR, "cannot use subselects in DEFAULT clause");
+ 	if (contain_agg_clause(expr))
+ 		elog(ERROR, "cannot use aggregate functions in DEFAULT clause");
+ 
+ 	/*
+ 	 * Check that it will be possible to coerce the expression to the
+ 	 * column's type.  We store the expression without coercion,
+ 	 * however, to avoid premature coercion in cases like
+ 	 *
+ 	 * CREATE TABLE tbl (fld datetime DEFAULT 'now'::text);
+ 	 *
+ 	 * NB: this should match the code in optimizer/prep/preptlist.c that
+ 	 * will actually do the coercion, to ensure we don't accept an
+ 	 * unusable default expression.
+ 	 */
+ 	type_id = exprType(expr);
+ 	if (type_id != InvalidOid && atttypid != InvalidOid) {
+ 		if (type_id != atttypid) {
+ 
+ 			/* Try coercing to the base type of the domain if available */
+ 			if (CoerceTargetExpr(pstate, expr, type_id,
+ 								 getBaseType(atttypid),
+ 								 atttypmod) == NULL) {
+ 
+ 				elog(ERROR, "Column \"%s\" is of type %s"
+ 					" but default expression is of type %s"
+ 					"\n\tYou will need to rewrite or cast the expression",
+ 					 attname,
+ 					 format_type_be(atttypid),
+ 					 format_type_be(type_id));
+ 			}
+ 		}
+ 	}
+ 
+ 	/*
+ 	 * Might as well try to reduce any constant expressions.
+ 	 */
+ 	expr = eval_const_expressions(expr);
+ 
+ 	/*
+ 	 * Must fix opids, in case any operators remain...
+ 	 */
+ 	fix_opids(expr);
+ 
+ 	return(expr);
+ }
+ 
  
  static void
  RemoveAttrDefault(Relation rel)
Index: src/backend/catalog/pg_type.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/catalog/pg_type.c,v
retrieving revision 1.65
diff -c -r1.65 pg_type.c
*** src/backend/catalog/pg_type.c	2001/10/25 05:49:23	1.65
--- src/backend/catalog/pg_type.c	2002/02/26 02:56:23
***************
*** 178,185 ****
  	values[i++] = ObjectIdGetDatum(InvalidOid); /* 14 */
  	values[i++] = CharGetDatum('i');	/* 15 */
  	values[i++] = CharGetDatum('p');	/* 16 */
  	values[i++] = DirectFunctionCall1(textin,
! 									  CStringGetDatum(typeName));		/* 17 */
  
  	/*
  	 * create a new type tuple with FormHeapTuple
--- 178,190 ----
  	values[i++] = ObjectIdGetDatum(InvalidOid); /* 14 */
  	values[i++] = CharGetDatum('i');	/* 15 */
  	values[i++] = CharGetDatum('p');	/* 16 */
+ 		values[i++] = BoolGetDatum(false);	/* 17 */
+ 			values[i++] = Int32GetDatum(-1);	/* 18 */
  	values[i++] = DirectFunctionCall1(textin,
! 									  CStringGetDatum(typeName));		/* 19 */
! 	values[i++] = DirectFunctionCall1(textin,
! 									  CStringGetDatum(typeName));		/* 20 */
! 
  
  	/*
  	 * create a new type tuple with FormHeapTuple
***************
*** 264,270 ****
  Oid
  TypeCreate(char *typeName,
  		   Oid assignedTypeOid,
! 		   Oid relationOid,		/* only for 'c'atalog typeTypes */
  		   int16 internalSize,
  		   int16 externalSize,
  		   char typeType,
--- 269,275 ----
  Oid
  TypeCreate(char *typeName,
  		   Oid assignedTypeOid,
! 		   Oid relationOid,			/* only for 'c'atalog typeTypes */
  		   int16 internalSize,
  		   int16 externalSize,
  		   char typeType,
***************
*** 274,283 ****
  		   char *receiveProcedure,
  		   char *sendProcedure,
  		   char *elementTypeName,
! 		   char *defaultTypeValue,		/* internal rep */
  		   bool passedByValue,
  		   char alignment,
! 		   char storage)
  {
  	int			i,
  				j;
--- 279,293 ----
  		   char *receiveProcedure,
  		   char *sendProcedure,
  		   char *elementTypeName,
! 		   char *baseTypeName,
! 		   char *defaultTypeValue,	/* human readable rep */
! 		   char *defaultTypeBin,	/* cooked rep */
  		   bool passedByValue,
  		   char alignment,
! 		   char storage,
! 		   int32 typeMod,
! 		   int32 typNDims,			/* Array dimensions for baseTypeName */
! 		   bool typeNotNull)		/* binary default representation (cooked) */
  {
  	int			i,
  				j;
***************
*** 285,290 ****
--- 295,301 ----
  	HeapScanDesc pg_type_scan;
  	Oid			typeObjectId;
  	Oid			elementObjectId = InvalidOid;
+ 	Oid			baseObjectId = InvalidOid;
  	HeapTuple	tup;
  	char		nulls[Natts_pg_type];
  	char		replaces[Natts_pg_type];
***************
*** 318,323 ****
--- 329,345 ----
  	}
  
  	/*
+ 	 * if this type has an associated baseType, then we check that it
+ 	 * is defined.
+ 	 */
+ 	if (baseTypeName)
+ 	{
+ 		baseObjectId = TypeGet(baseTypeName, &defined);
+ 		if (!defined)
+ 			elog(ERROR, "type %s does not exist", baseTypeName);
+ 	}
+ 
+ 	/*
  	 * validate size specifications: either positive (fixed-length) or -1
  	 * (variable-length).
  	 */
***************
*** 388,394 ****
  			 * signature is 0,OIDOID,INT4OID.  The output procedures may
  			 * take 2 args (data value, element OID).
  			 */
! 			if (OidIsValid(elementObjectId))
  			{
  				int			nargs;
  
--- 410,416 ----
  			 * signature is 0,OIDOID,INT4OID.  The output procedures may
  			 * take 2 args (data value, element OID).
  			 */
! 			if (OidIsValid(elementObjectId) || OidIsValid(baseObjectId))
  			{
  				int			nargs;
  
***************
*** 411,416 ****
--- 433,439 ----
  										 PointerGetDatum(argList),
  										 0);
  			}
+ 
  			if (!OidIsValid(procOid))
  				func_error("TypeCreate", procname, 1, argList, NULL);
  		}
***************
*** 429,434 ****
--- 452,485 ----
  	values[i++] = CharGetDatum(storage);		/* 16 */
  
  	/*
+ 	 * set the typenotnull value
+ 	 */
+ 	values[i++] = BoolGetDatum(typeNotNull);	/* 17 */
+ 
+ 	/*
+ 	 * set the typemod value
+ 	 */
+ 	values[i++] = Int32GetDatum(typeMod);			/* 18 */
+ 
+ 	values[i++] = ObjectIdGetDatum(baseObjectId);	/* 19 */
+ 
+ 	/*
+ 	 * Dimension number for an array base type
+ 	 */
+ 	values[i++] = Int32GetDatum(typNDims);			/* 20 */
+ 
+ 	/*
+ 	 * initialize the default binary value for this type.  Check for
+ 	 * nulls of course.
+ 	 */
+ 	if (defaultTypeBin)
+ 		values[i] = DirectFunctionCall1(textin,
+ 									  CStringGetDatum(defaultTypeBin));
+ 	else
+ 		nulls[i] = 'n';
+ 	i++;										/* 21 */
+ 
+ 	/*
  	 * initialize the default value for this type.
  	 */
  	if (defaultTypeValue)
***************
*** 436,442 ****
  									  CStringGetDatum(defaultTypeValue));
  	else
  		nulls[i] = 'n';
! 	i++;						/* 17 */
  
  	/*
  	 * open pg_type and begin a scan for the type name.
--- 487,493 ----
  									  CStringGetDatum(defaultTypeValue));
  	else
  		nulls[i] = 'n';
! 	i++;						/* 22 */
  
  	/*
  	 * open pg_type and begin a scan for the type name.
Index: src/backend/commands/creatinh.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/commands/creatinh.c,v
retrieving revision 1.81
diff -c -r1.81 creatinh.c
*** src/backend/commands/creatinh.c	2001/10/25 05:49:24	1.81
--- src/backend/commands/creatinh.c	2002/02/26 02:56:25
***************
*** 39,46 ****
  static void StoreCatalogInheritance(Oid relationId, List *supers);
  static int	findAttrByName(const char *attributeName, List *schema);
  static void setRelhassubclassInRelation(Oid relationId, bool relhassubclass);
  
- 
  /* ----------------------------------------------------------------
   *		DefineRelation
   *				Creates a new relation.
--- 39,46 ----
  static void StoreCatalogInheritance(Oid relationId, List *supers);
  static int	findAttrByName(const char *attributeName, List *schema);
  static void setRelhassubclassInRelation(Oid relationId, bool relhassubclass);
+ static List *MergeDomainAttributes(List *schema);
  
  /* ----------------------------------------------------------------
   *		DefineRelation
   *				Creates a new relation.
***************
*** 70,75 ****
--- 70,82 ----
  	StrNCpy(relname, stmt->relname, NAMEDATALEN);
  
  	/*
+ 	 * Merge domain attributes into the known columns before inheritance
+ 	 * applies it's changes otherwise we risk adding double constraints
+ 	 * to a domain thats inherited.
+ 	 */
+ 	schema = MergeDomainAttributes(schema);
+ 
+ 	/*
  	 * Look up inheritance ancestors and generate relation schema,
  	 * including inherited attributes.
  	 */
***************
*** 235,240 ****
--- 242,329 ----
  {
  	AssertArg(name);
  	heap_truncate(name);
+ }
+ 
+ 
+ /*
+  * MergeDomainAttributes
+  *      Returns a new schema with the constraints, types, and other
+  *      attributes of the domain resolved.
+  *
+  * Defaults are processed at execution time by taking the default of
+  * the type (domain) if it is null.  This does not need to be merged
+  * here.
+  */
+ static List *
+ MergeDomainAttributes(List *schema)
+ {
+ 	List	   *entry;
+ 
+ 	/*
+ 	 * Loop through the table elements supplied. These should
+ 	 * never include inherited domains else they'll be
+ 	 * double (or more) processed.
+ 	 */
+ 	foreach(entry, schema)
+ 	{
+ 		ColumnDef  *coldef = lfirst(entry);
+ 		HeapTuple  tuple;
+ 		Form_pg_type typeTup;
+ 
+ 
+ 		tuple = SearchSysCache(TYPENAME,
+ 							   CStringGetDatum(coldef->typename->name),
+ 							   0,0,0);
+ 
+ 		if (!HeapTupleIsValid(tuple))
+ 			elog(ERROR, "MergeDomainAttributes: Type %s does not exist",
+ 				 coldef->typename->name);
+ 
+ 		typeTup = (Form_pg_type) GETSTRUCT(tuple);
+ 		if (typeTup->typtype == 'd') {
+ 			/*
+ 			 * This is a domain, lets force the properties of the domain on to
+ 			 * the new column.
+ 			 */
+ 
+ 			/* Enforce the typmod value */
+ 			coldef->typename->typmod = typeTup->typmod;
+ 
+ 			/* Enforce type NOT NULL || column definition NOT NULL -> NOT NULL */
+ 			coldef->is_not_null |= typeTup->typnotnull;
+ 
+ 			/* Enforce the element type in the event the domain is an array
+ 			 *
+ 			 * BUG: How do we fill out arrayBounds and attrname from typelem and typNDimms?
+ 			 */
+ 
+ 		}
+ 		ReleaseSysCache(tuple);
+ 
+ //typedef struct TypeName
+ //{
+ 	//NodeTag		type;
+ 	//char	   *name;			/* name of the type */
+ 	//bool		timezone;		/* timezone specified? */
+ 	//bool		setof;			/* is a set? */
+ 	//int32		typmod;			/* type modifier */
+ 	//List	   *arrayBounds;	/* array bounds */
+ 	//char	   *attrname;		/* field name when using %TYPE */
+ //} TypeName;
+ 
+ // ColumnDef
+ //		NodeTag		type;
+ //		char	   *colname;		/* name of column */
+ //		TypeName   *typename;		/* type of column */
+ //		bool		is_not_null;	/* NOT NULL constraint specified? */
+ //		Node	   *raw_default;	/* default value (untransformed parse
+ //								 * tree) */
+ //		char	   *cooked_default; /* nodeToString representation */
+ //		List	   *constraints;	/* other constraints on column */
+ 
+ 	}
+ 
+ 	return schema;
  }
  
  /*----------
Index: src/backend/commands/define.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/commands/define.c,v
retrieving revision 1.65
diff -c -r1.65 define.c
*** src/backend/commands/define.c	2002/02/18 23:11:10	1.65
--- src/backend/commands/define.c	2002/02/26 02:56:27
***************
*** 40,45 ****
--- 40,46 ----
  
  #include "access/heapam.h"
  #include "catalog/catname.h"
+ #include "catalog/heap.h"
  #include "catalog/pg_aggregate.h"
  #include "catalog/pg_language.h"
  #include "catalog/pg_operator.h"
***************
*** 476,481 ****
--- 477,798 ----
  }
  
  /*
+  * 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;
+ 
+ 	/*
+ 	 * Domains store the external representation in defaultValue
+ 	 * and the interal Node representation in defaultValueBin
+ 	 */
+ 	char	   *defaultValue = NULL;
+ 	char	   *defaultValueBin = 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		typNotNull = false;
+ 	char		*elemName = NULL;
+ 	int32		typNDims = 0;	/* No array dimensions by default */
+ 
+ 	bool		isnull;
+ 	Relation	pg_type_rel;
+ 	TupleDesc	pg_type_dsc;
+ 	HeapTuple	typeTup;
+ 	char	   *typeName = stmt->typename->name;
+ 
+ 	List	   *listptr;
+ 	List	   *schema = stmt->constraints;
+ 
+ 	/*
+ 	 * 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);
+ 
+ 
+ 	/*
+ 	 * When the type is an array for some reason we don't actually receive
+ 	 * the name here.  We receive the base types name.  Lets set Dims while
+ 	 * were at it.
+ 	 */
+ 	if (stmt->typename->arrayBounds > 0) {
+ 		typeName = makeArrayTypeName(stmt->typename->name);
+ 
+ 		typNDims = length(stmt->typename->arrayBounds);
+ 	}
+ 
+ 
+ 	typeTup = SearchSysCache( TYPENAME
+ 							, PointerGetDatum(typeName)
+ 							, 0, 0, 0
+ 							);
+ 
+ 	if (!HeapTupleIsValid(typeTup))
+ 	{
+ 		elog(ERROR, "CREATE DOMAIN: type %s does not exist",
+ 			 stmt->typename->name);
+ 	}
+ 
+ 
+ 	/* Check that this is a basetype */
+ 	typtype = DatumGetChar(heap_getattr(typeTup, Anum_pg_type_typtype, pg_type_dsc, &isnull));
+ 	Assert(!isnull);
+ 
+ 	/*
+ 	 * What we really don't want is domains of domains.  This could cause all sorts
+ 	 * of neat issues if we allow that.
+ 	 *
+ 	 * With testing, we may determine complex types should be allowed
+ 	 */
+ 	if (typtype != 'b') {
+ 		elog(ERROR, "DefineDomain: %s is not a basetype", stmt->typename->name);
+ 	}
+ 
+ 	/* passed by value */
+ 	byValue = 			DatumGetBool(heap_getattr(typeTup, Anum_pg_type_typbyval, pg_type_dsc, &isnull));
+ 	Assert(!isnull);
+ 
+ 	/* Required Alignment */
+ 	alignment = 		DatumGetChar(heap_getattr(typeTup, Anum_pg_type_typalign, pg_type_dsc, &isnull));
+ 	Assert(!isnull);
+ 
+ 	/* Storage Length */
+ 	internalLength = 	DatumGetInt16(heap_getattr(typeTup, Anum_pg_type_typlen, pg_type_dsc, &isnull));
+ 	Assert(!isnull);
+ 
+ 	/* External Length (unused) */
+ 	externalLength = 	DatumGetInt16(heap_getattr(typeTup, Anum_pg_type_typprtlen, pg_type_dsc, &isnull));
+ 	Assert(!isnull);
+ 
+ 	/* Array element Delimiter */
+ 	delimiter = 		DatumGetChar(heap_getattr(typeTup, Anum_pg_type_typdelim, pg_type_dsc, &isnull));
+ 	Assert(!isnull);
+ 
+ 	/* Input Function Name */
+ 	datum = 			heap_getattr(typeTup, Anum_pg_type_typinput, pg_type_dsc, &isnull);
+ 	Assert(!isnull);
+ 
+ 	inputName = 		DatumGetCString(DirectFunctionCall1(regprocout, datum));
+ 
+ 	/* Output Function Name */
+ 	datum = 			heap_getattr(typeTup, Anum_pg_type_typoutput, pg_type_dsc, &isnull);
+ 	Assert(!isnull);
+ 
+ 	outputName = 		DatumGetCString(DirectFunctionCall1(regprocout, datum));
+ 
+ 	/* ReceiveName */
+ 	datum = 			heap_getattr(typeTup, Anum_pg_type_typreceive, pg_type_dsc, &isnull);
+ 	Assert(!isnull);
+ 
+ 	receiveName = 		DatumGetCString(DirectFunctionCall1(regprocout, datum));
+ 
+ 	/* SendName */
+ 	datum = 			heap_getattr(typeTup, Anum_pg_type_typsend, pg_type_dsc, &isnull);
+ 	Assert(!isnull);
+ 
+ 	sendName = 			DatumGetCString(DirectFunctionCall1(regprocout, datum));
+ 
+ 	/* TOAST Strategy */
+ 	storage = 			DatumGetChar(heap_getattr(typeTup, Anum_pg_type_typstorage, pg_type_dsc, &isnull));
+ 	Assert(!isnull);
+ 
+ 	/* Inherited default value */
+ 	datum = 			heap_getattr(typeTup, Anum_pg_type_typdefault, pg_type_dsc, &isnull);
+ 	if (!isnull) {
+ 		defaultValue = 	DatumGetCString(DirectFunctionCall1(textout, datum));
+ 	}
+ 
+ 	/*
+ 	 * Pull out the typelem name of the parent OID.
+ 	 *
+ 	 * This is what enables us to make a domain of an array
+ 	 */
+ 	datum = 			heap_getattr(typeTup, Anum_pg_type_typelem, pg_type_dsc, &isnull);
+ 	Assert(!isnull);
+ 
+ 	if (DatumGetObjectId(datum) != InvalidOid) {
+ 		HeapTuple tup;
+ 
+ 		tup = SearchSysCache( TYPEOID
+ 							, datum
+ 							, 0, 0, 0
+ 							);
+ 
+ 		elemName = NameStr(((Form_pg_type) GETSTRUCT(tup))->typname);
+ 
+ 		ReleaseSysCache(tup);
+ 	}
+ 
+ 
+ 	/*
+ 	 * Run through constraints manually avoids the additional
+ 	 * processing conducted by DefineRelation() and friends.
+ 	 *
+ 	 * Besides, we don't want any constraints to be cooked.  We'll
+ 	 * do that when the table is created via MergeDomainAttributes().
+ 	 */
+ 	foreach(listptr, schema)
+ 	{
+ 		bool nullDefined = false;
+ 		Node	   *expr;
+ 		Constraint *colDef = lfirst(listptr);
+ 
+ 		/* Used for the statement transformation */
+ 		ParseState *pstate;
+ 
+ 		/*
+ 		 * Create a dummy ParseState and insert the target relation as its
+ 		 * sole rangetable entry.  We need a ParseState for transformExpr.
+ 		 */
+ 		pstate = make_parsestate(NULL);
+ 
+ 		switch(colDef->contype) {
+ 			/*
+ 	 		 * The inherited default value may be overridden by the user
+ 			 * with the DEFAULT <expr> statement.
+ 			 *
+ 	 		 * We have to search the entire constraint tree returned as we
+ 			 * don't want to cook or fiddle too much.
+ 			 */
+ 			case CONSTR_DEFAULT:
+ 
+ 				/*
+ 				 * Cook the colDef->raw_expr into an expression to ensure
+ 				 * that it can be done.  We store the text version of the
+ 				 * raw value.
+ 				 *
+ 				 * Note: Name is strictly for error message
+ 				 */
+ 				expr = cookDefault(pstate, colDef->raw_expr
+ 								, typeTup->t_data->t_oid
+ 								, stmt->typename->typmod
+ 								, stmt->typename->name);
+ 
+ 				/* Binary default required */
+ 				defaultValue = deparse_expression(expr,
+ 								deparse_context_for(stmt->domainname,
+ 													InvalidOid),
+ 												   false);
+ 
+ 				defaultValueBin = nodeToString(expr);
+ 
+ 				break;
+ 
+ 			/*
+ 			 * Find the NULL constraint.
+ 			 */
+ 			case CONSTR_NOTNULL:
+ 				if (nullDefined) {
+ 					elog(ERROR, "CREATE DOMAIN has conflicting NULL / NOT NULL constraint");
+ 				} else {
+ 					typNotNull = true;
+ 					nullDefined = true;
+ 				}
+ 
+ 		  		break;
+ 
+ 			case CONSTR_NULL:
+ 				if (nullDefined) {
+ 					elog(ERROR, "CREATE DOMAIN has conflicting NULL / NOT NULL constraint");
+ 				} else {
+ 					typNotNull = false;
+ 					nullDefined = true;
+ 				}
+ 
+ 		  		break;
+ 
+ 		  	case CONSTR_UNIQUE:
+ 		  		elog(ERROR, "CREATE DOMAIN / UNIQUE indecies not supported");
+ 		  		break;
+ 
+ 		  	case CONSTR_PRIMARY:
+ 		  		elog(ERROR, "CREATE DOMAIN / PRIMARY KEY indecies not supported");
+ 		  		break;
+ 
+ 
+ 		  	case CONSTR_CHECK:
+ 
+ 		  		elog(ERROR, "defineDomain: CHECK Constraints not supported");
+ 		  		break;
+ 
+ 		  	case CONSTR_ATTR_DEFERRABLE:
+ 		  	case CONSTR_ATTR_NOT_DEFERRABLE:
+ 		  	case CONSTR_ATTR_DEFERRED:
+ 		  	case CONSTR_ATTR_IMMEDIATE:
+ 		  		elog(ERROR, "defineDomain: DEFERRABLE, NON DEFERRABLE, DEFERRED and IMMEDIATE not supported");
+ 		  		break;
+ 		}
+ 
+ 	}
+ 
+ 	/*
+ 	 * 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 */
+ 			   elemName,			/* element type name */
+ 			   typeName,			/* base type name */
+ 			   defaultValue,		/* default type value */
+ 			   defaultValueBin,		/* default type value */
+ 			   byValue,				/* passed by value */
+ 			   alignment,			/* required alignment */
+ 			   storage,				/* TOAST strategy */
+ 			   stmt->typename->typmod, /* typeMod value */
+ 			   typNDims,			/* Array dimensions for base type */
+ 			   typNotNull);	/* Type NOT NULL */
+ 
+ 	/*
+ 	 * Now we can clean up.
+ 	 */
+ 	ReleaseSysCache(typeTup);
+ 	heap_close(pg_type_rel, NoLock);
+ }
+ 
+ 
+ /*
   * DefineType
   *		Registers a new type.
   */
***************
*** 490,495 ****
--- 807,814 ----
  	char	   *sendName = NULL;
  	char	   *receiveName = NULL;
  	char	   *defaultValue = NULL;
+ 	char	   *defaultValueBin = NULL;
+ 	Node	   *defaultRaw = (Node *) NULL;
  	bool		byValue = false;
  	char		delimiter = DEFAULT_TYPDELIM;
  	char	   *shadow_type;
***************
*** 531,537 ****
  		else if (strcasecmp(defel->defname, "element") == 0)
  			elemName = defGetString(defel);
  		else if (strcasecmp(defel->defname, "default") == 0)
! 			defaultValue = defGetString(defel);
  		else if (strcasecmp(defel->defname, "passedbyvalue") == 0)
  			byValue = true;
  		else if (strcasecmp(defel->defname, "alignment") == 0)
--- 850,856 ----
  		else if (strcasecmp(defel->defname, "element") == 0)
  			elemName = defGetString(defel);
  		else if (strcasecmp(defel->defname, "default") == 0)
! 			defaultRaw = defel->arg;
  		else if (strcasecmp(defel->defname, "passedbyvalue") == 0)
  			byValue = true;
  		else if (strcasecmp(defel->defname, "alignment") == 0)
***************
*** 591,596 ****
--- 910,941 ----
  	if (outputName == NULL)
  		elog(ERROR, "Define: \"output\" unspecified");
  
+ 
+ 	if (defaultRaw) {
+ 		Node   *expr;
+ 		ParseState *pstate;
+ 
+ 		/*
+ 		 * Create a dummy ParseState and insert the target relation as its
+ 		 * sole rangetable entry.  We need a ParseState for transformExpr.
+ 		 */
+ 		pstate = make_parsestate(NULL);
+ 
+ 		expr = cookDefault(pstate, defaultRaw,
+ 						   InvalidOid,
+ 						   -1,
+ 						   typeName);
+ 
+ 		/* Binary default required */
+ 		defaultValue = deparse_expression(expr,
+ 						deparse_context_for(typeName,
+ 											InvalidOid),
+ 										   false);
+ 
+ 		defaultValueBin = nodeToString(expr);
+ 	}
+ 
+ 
  	/*
  	 * now have TypeCreate do all the real work.
  	 */
***************
*** 606,615 ****
  			   receiveName,		/* receive procedure */
  			   sendName,		/* send procedure */
  			   elemName,		/* element type name */
  			   defaultValue,	/* default type value */
  			   byValue,			/* passed by value */
  			   alignment,		/* required alignment */
! 			   storage);		/* TOAST strategy */
  
  	/*
  	 * When we create a base type (as opposed to a complex type) we need
--- 951,965 ----
  			   receiveName,		/* receive procedure */
  			   sendName,		/* send procedure */
  			   elemName,		/* element type name */
+ 			   NULL,			/* base type name (Non-zero for domains) */
  			   defaultValue,	/* default type value */
+ 			   defaultValueBin,	/* default type value (Binary form) */
  			   byValue,			/* passed by value */
  			   alignment,		/* required alignment */
! 			   storage,			/* TOAST strategy */
! 			   -1,				/* typMod (Domains only) */
! 			   0,				/* Array Dimensions of typbasetype */
! 			   'f');			/* Type NOT NULL */
  
  	/*
  	 * When we create a base type (as opposed to a complex type) we need
***************
*** 632,641 ****
  			   "array_in",		/* receive procedure */
  			   "array_out",		/* send procedure */
  			   typeName,		/* element type name */
  			   NULL,			/* never a default type value */
  			   false,			/* never passed by value */
  			   alignment,		/* see above */
! 			   'x');			/* ARRAY is always toastable */
  
  	pfree(shadow_type);
  }
--- 982,996 ----
  			   "array_in",		/* receive procedure */
  			   "array_out",		/* send procedure */
  			   typeName,		/* element type name */
+ 			   NULL,			/* base type name */
  			   NULL,			/* never a default type value */
+ 			   NULL,			/* binary default isn't sent either */
  			   false,			/* never passed by value */
  			   alignment,		/* see above */
! 			   'x',				/* ARRAY is always toastable */
! 			   -1,				/* typMod (Domains only) */
! 			   0,				/* Array dimensions of typbasetype */
! 			   'f');			/* Type NOT NULL */
  
  	pfree(shadow_type);
  }
Index: src/backend/commands/remove.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/commands/remove.c,v
retrieving revision 1.65
diff -c -r1.65 remove.c
*** src/backend/commands/remove.c	2001/11/05 17:46:24	1.65
--- src/backend/commands/remove.c	2002/02/26 02:56:28
***************
*** 1,7 ****
  /*-------------------------------------------------------------------------
   *
   * remove.c
!  *	  POSTGRES remove (function | type | operator ) utilty code.
   *
   * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
   * Portions Copyright (c) 1994, Regents of the University of California
--- 1,7 ----
  /*-------------------------------------------------------------------------
   *
   * remove.c
!  *	  POSTGRES remove (domain | function | type | operator ) utilty code.
   *
   * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
   * Portions Copyright (c) 1994, Regents of the University of California
***************
*** 22,27 ****
--- 22,28 ----
  #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"
***************
*** 267,272 ****
--- 268,327 ----
  						 0, 0, 0);
  	if (!HeapTupleIsValid(tup))
  		elog(ERROR, "RemoveType: type '%s' does not exist", shadow_type);
+ 
+ 	simple_heap_delete(relation, &tup->t_self);
+ 
+ 	ReleaseSysCache(tup);
+ 
+ 	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);
  
Index: src/backend/nodes/copyfuncs.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v
retrieving revision 1.161
diff -c -r1.161 copyfuncs.c
*** src/backend/nodes/copyfuncs.c	2002/02/18 23:11:14	1.161
--- src/backend/nodes/copyfuncs.c	2002/02/26 02:56:31
***************
*** 2224,2229 ****
--- 2224,2242 ----
  	return newnode;
  }
  
+ static CreateDomainStmt *
+ _copyCreateDomainStmt(CreateDomainStmt *from)
+ {
+ 	CreateDomainStmt *newnode = makeNode(CreateDomainStmt);
+ 
+ 	if (from->domainname)
+ 		newnode->domainname = pstrdup(from->domainname);
+ 	if (from->typename)
+ 		newnode->typename = 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.109
diff -c -r1.109 equalfuncs.c
*** src/backend/nodes/equalfuncs.c	2002/02/18 23:11:14	1.109
--- src/backend/nodes/equalfuncs.c	2002/02/26 02:56:34
***************
*** 1095,1100 ****
--- 1095,1111 ----
  }
  
  static bool
+ _equalCreateDomainStmt(CreateDomainStmt *a, CreateDomainStmt *b)
+ {
+ 	if (!equalstr(a->domainname, b->domainname))
+ 		return false;
+ 	if (!equal(a->typename, b->typename))
+ 		return false;
+ 
+ 	return true;
+ }
+ 
+ static bool
  _equalCreatedbStmt(CreatedbStmt *a, CreatedbStmt *b)
  {
  	if (!equalstr(a->dbname, b->dbname))
***************
*** 1981,1986 ****
--- 1992,2000 ----
  			break;
  		case T_LoadStmt:
  			retval = _equalLoadStmt(a, b);
+ 			break;
+ 		case T_CreateDomainStmt:
+ 			retval = _equalCreateDomainStmt(a, b);
  			break;
  		case T_CreatedbStmt:
  			retval = _equalCreatedbStmt(a, b);
Index: src/backend/optimizer/prep/preptlist.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v
retrieving revision 1.46
diff -c -r1.46 preptlist.c
*** src/backend/optimizer/prep/preptlist.c	2001/11/05 17:46:26	1.46
--- src/backend/optimizer/prep/preptlist.c	2002/02/26 02:56:35
***************
*** 355,361 ****
  	Form_pg_attribute att_tup = rd_att->attrs[attrno - 1];
  	Oid			atttype = att_tup->atttypid;
  	int32		atttypmod = att_tup->atttypmod;
- 	bool		hasdefault;
  	Datum		typedefault;
  	int16		typlen;
  	bool		typbyval;
--- 355,360 ----
***************
*** 392,398 ****
  				if (type_id != atttype)
  				{
  					expr = CoerceTargetExpr(NULL, expr, type_id,
! 											atttype, atttypmod);
  
  					/*
  					 * This really shouldn't fail; should have checked the
--- 391,397 ----
  				if (type_id != atttype)
  				{
  					expr = CoerceTargetExpr(NULL, expr, type_id,
! 											getBaseType(atttype), atttypmod);
  
  					/*
  					 * This really shouldn't fail; should have checked the
***************
*** 430,470 ****
  		 * element type is, and the element type's default is irrelevant
  		 * too.
  		 */
- 		hasdefault = false;
- 		typedefault = (Datum) 0;
  		typlen = sizeof(Oid);
  		typbyval = true;
  	}
  	else
  	{
  #ifdef	_DROP_COLUMN_HACK__
  		if (COLUMN_IS_DROPPED(att_tup))
  		{
! 			hasdefault = false;
! 			typedefault = (Datum) 0;
  		}
  		else
  #endif   /* _DROP_COLUMN_HACK__ */
! 			hasdefault = get_typdefault(atttype, &typedefault);
  
  		get_typlenbyval(atttype, &typlen, &typbyval);
  	}
  
- 	expr = (Node *) makeConst(atttype,
- 							  typlen,
- 							  typedefault,
- 							  !hasdefault,
- 							  typbyval,
- 							  false,	/* not a set */
- 							  false);
- 
  	/*
  	 * If the column is a fixed-length type, it may need a length coercion
! 	 * as well as a type coercion.	But NULLs don't need that.
  	 */
! 	if (hasdefault)
! 		expr = coerce_type_typmod(NULL, expr,
! 								  atttype, atttypmod);
  
  	return expr;
  }
--- 429,481 ----
  		 * element type is, and the element type's default is irrelevant
  		 * too.
  		 */
  		typlen = sizeof(Oid);
  		typbyval = true;
+ 
+ 		expr = (Node *) makeConst(atttype,
+ 								  typlen,
+ 								  (Datum) 0,
+ 								  true,
+ 								  typbyval,
+ 								  false,           /* not a set */
+ 								  false);
  	}
  	else
  	{
  #ifdef	_DROP_COLUMN_HACK__
  		if (COLUMN_IS_DROPPED(att_tup))
  		{
! 
! 			expr = (Node *) makeConst(atttype,
! 									  typlen,
! 									  (Datum) 0,
! 									  true,
! 									  typbyval,
! 									  false,           /* not a set */
! 									  false);
  		}
  		else
  #endif   /* _DROP_COLUMN_HACK__ */
! 			expr = get_typdefault(atttype, atttypmod);
  
+ 		if (expr == NULL) {
+ 				expr = (Node *) makeConst(atttype,
+ 										  typlen,
+ 										  (Datum) 0,
+ 										  true,
+ 										  typbyval,
+ 										  false,		/* not a set */
+ 										  false);
+ 		}
  		get_typlenbyval(atttype, &typlen, &typbyval);
  	}
  
  	/*
  	 * If the column is a fixed-length type, it may need a length coercion
! 	 * as well as a type coercion, as well as direction to the final type.
  	 */
! 	expr = coerce_type_typmod(NULL, expr,
! 							  atttype, atttypmod);
  
  	return expr;
  }
Index: src/backend/parser/gram.y
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/parser/gram.y,v
retrieving revision 2.278
diff -c -r2.278 gram.y
*** src/backend/parser/gram.y	2002/02/18 23:11:17	2.278
--- src/backend/parser/gram.y	2002/02/26 02:56:46
***************
*** 135,141 ****
  		ClosePortalStmt, ClusterStmt, CommentStmt, ConstraintsSetStmt,
  		CopyStmt, CreateAsStmt, CreateGroupStmt, CreatePLangStmt,
  		CreateSchemaStmt, CreateSeqStmt, CreateStmt, CreateTrigStmt,
! 		CreateUserStmt, CreatedbStmt, CursorStmt, DefineStmt, DeleteStmt,
  		DropGroupStmt, DropPLangStmt, DropSchemaStmt, DropStmt, DropTrigStmt,
  		DropUserStmt, DropdbStmt, ExplainStmt, FetchStmt,
  		GrantStmt, IndexStmt, InsertStmt, ListenStmt, LoadStmt, LockStmt,
--- 135,142 ----
  		ClosePortalStmt, ClusterStmt, CommentStmt, ConstraintsSetStmt,
  		CopyStmt, CreateAsStmt, CreateGroupStmt, CreatePLangStmt,
  		CreateSchemaStmt, CreateSeqStmt, CreateStmt, CreateTrigStmt,
! 		CreateUserStmt, CreateDomainStmt, CreatedbStmt, CursorStmt,
! 		DefineStmt, DeleteStmt,
  		DropGroupStmt, DropPLangStmt, DropSchemaStmt, DropStmt, DropTrigStmt,
  		DropUserStmt, DropdbStmt, ExplainStmt, FetchStmt,
  		GrantStmt, IndexStmt, InsertStmt, ListenStmt, LoadStmt, LockStmt,
***************
*** 288,293 ****
--- 289,296 ----
  %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
***************
*** 342,348 ****
  		WITHOUT
  
  /* Keywords (in SQL92 non-reserved words) */
! %token	COMMITTED, SERIALIZABLE, TYPE_P
  
  /* Keywords for Postgres support (not in SQL92 reserved words)
   *
--- 345,351 ----
  		WITHOUT
  
  /* Keywords (in SQL92 non-reserved words) */
! %token	COMMITTED, SERIALIZABLE, TYPE_P, DOMAIN_P
  
  /* Keywords for Postgres support (not in SQL92 reserved words)
   *
***************
*** 443,448 ****
--- 446,452 ----
  		| CopyStmt
  		| CreateStmt
  		| CreateAsStmt
+ 		| CreateDomainStmt
  		| CreateSchemaStmt
  		| CreateGroupStmt
  		| CreateSeqStmt
***************
*** 752,758 ****
--- 756,765 ----
  					n->dbname = $3;
  					$$ = (Node *)n;
  				}
+ 		;
+ 
  
+  
  
  /*****************************************************************************
   *
***************
*** 1426,1432 ****
  					n->name = NULL;
  					if (exprIsNullConstant($2))
  					{
! 						/* DEFAULT NULL should be reported as empty expr */
  						n->raw_expr = NULL;
  					}
  					else
--- 1433,1442 ----
  					n->name = NULL;
  					if (exprIsNullConstant($2))
  					{
! 						/*
! 						 * DEFAULT NULL should be reported as empty expr
! 						 * Required for NOT NULL Domain overrides
! 						 */
  						n->raw_expr = NULL;
  					}
  					else
***************
*** 2008,2014 ****
  		| def_list ',' def_elem				{ $$ = lappend($1, $3); }
  		;
  
! def_elem:  ColLabel '=' def_arg
  				{
  					$$ = makeNode(DefElem);
  					$$->defname = $1;
--- 2018,2033 ----
  		| def_list ',' def_elem				{ $$ = lappend($1, $3); }
  		;
  
! def_elem:  DEFAULT '=' b_expr
! 				{
! 					$$ = makeNode(DefElem);
! 					$$->defname = "default";
! 					if (exprIsNullConstant($3))
! 						$$->arg = (Node *)NULL;
! 					else
! 						$$->arg = $3;
! 				}
! 		| ColLabel '=' def_arg
  				{
  					$$ = makeNode(DefElem);
  					$$->defname = $1;
***************
*** 2043,2048 ****
--- 2062,2076 ----
  					DropStmt *n = makeNode(DropStmt);
  					n->removeType = $2;
  					n->names = $3;
+ 					n->behavior = RESTRICT;		/* Restricted by default */
+ 					$$ = (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;
  				}
  		;
***************
*** 2075,2081 ****
   *  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 ] 
   *               <objname> | AGGREGATE <aggname> (<aggtype>) | FUNCTION 
   *		 <funcname> (arg1, arg2, ...) | OPERATOR <op> 
   *		 (leftoperand_typ rightoperand_typ) | TRIGGER <triggername> ON
--- 2103,2109 ----
   *  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 | DOMAIN | INDEX | RULE | SEQUENCE | TABLE | TYPE | VIEW ] 
   *               <objname> | AGGREGATE <aggname> (<aggtype>) | FUNCTION 
   *		 <funcname> (arg1, arg2, ...) | OPERATOR <op> 
   *		 (leftoperand_typ rightoperand_typ) | TRIGGER <triggername> ON
***************
*** 2161,2166 ****
--- 2189,2195 ----
  		| RULE { $$ = RULE; }
  		| SEQUENCE { $$ = SEQUENCE; }
  		| TABLE { $$ = TABLE; }
+ 		| DOMAIN_P { $$ = TYPE_P; }
  		| TYPE_P { $$ = TYPE_P; }
  		| VIEW { $$ = VIEW; }
  		;		
***************
*** 3156,3161 ****
--- 3185,3214 ----
  				}
  		;
  
+ /*****************************************************************************
+  *
+  * Manipulate a domain
+  *
+  *
+  *****************************************************************************/
+ 
+ CreateDomainStmt:  CREATE DOMAIN_P name opt_as Typename ColQualList opt_collate
+ 				{
+ 					CreateDomainStmt *n = makeNode(CreateDomainStmt);
+ 					n->domainname = $3;
+ 					n->typename = $5;
+ 					n->constraints = $6;
+ 					
+ 					if ($7 != NULL)
+ 						elog(NOTICE,"CREATE DOMAIN / COLLATE %s not yet "
+ 							"implemented; clause ignored", $7);
+ 					$$ = (Node *)n;
+ 				}
+ 		;
+ 
+ opt_as:	AS	{$$ = TRUE; }
+ 	| /* EMPTY */	{$$ = FALSE; }
+ 	;
  
  /*****************************************************************************
   *
***************
*** 5797,5802 ****
--- 5850,5856 ----
  		| 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.100
diff -c -r1.100 keywords.c
*** src/backend/parser/keywords.c	2002/02/18 23:11:18	1.100
--- src/backend/parser/keywords.c	2002/02/26 02:56:49
***************
*** 97,102 ****
--- 97,103 ----
  	{"desc", DESC},
  	{"distinct", DISTINCT},
  	{"do", DO},
+ 	{"domain", DOMAIN_P},
  	{"double", DOUBLE},
  	{"drop", DROP},
  	{"each", EACH},
Index: src/backend/parser/parse_coerce.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/parser/parse_coerce.c,v
retrieving revision 2.64
diff -c -r2.64 parse_coerce.c
*** src/backend/parser/parse_coerce.c	2001/10/25 05:49:39	2.64
--- src/backend/parser/parse_coerce.c	2002/02/26 02:56:49
***************
*** 38,43 ****
--- 38,44 ----
  {
  	Node	   *result;
  
+ 
  	if (targetTypeId == inputTypeId ||
  		targetTypeId == InvalidOid ||
  		node == NULL)
***************
*** 605,607 ****
--- 606,637 ----
  	}
  	return result;
  }	/* PreferredType() */
+ 
+ 
+ /*
+  * If the targetTypeId is a domain, we really want to coerce
+  * the tuple to the domain type -- not the domain itself
+  */
+ Oid
+ getBaseType(Oid inType)
+ {
+ 	HeapTuple	tup;
+ 	Form_pg_type typTup;
+ 
+ 	tup = SearchSysCache(TYPEOID,
+ 						 ObjectIdGetDatum(inType),
+ 						 0, 0, 0);
+ 
+ 	typTup = ((Form_pg_type) GETSTRUCT(tup));
+ 
+ 	/*
+ 	 * Assume that typbasetype exists and is a base type, where inType
+ 	 * was a domain
+ 	 */
+ 	if (typTup->typtype == 'd')
+ 		inType = typTup->typbasetype;
+ 
+ 	ReleaseSysCache(tup);
+ 
+ 	return inType;
+ }
\ No newline at end of file
Index: src/backend/parser/parse_expr.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/parser/parse_expr.c,v
retrieving revision 1.105
diff -c -r1.105 parse_expr.c
*** src/backend/parser/parse_expr.c	2001/11/12 20:05:24	1.105
--- src/backend/parser/parse_expr.c	2002/02/26 02:56:52
***************
*** 1027,1033 ****
  	if (inputType != targetType)
  	{
  		expr = CoerceTargetExpr(pstate, expr, inputType,
! 								targetType, typename->typmod);
  		if (expr == NULL)
  			elog(ERROR, "Cannot cast type '%s' to '%s'",
  				 format_type_be(inputType),
--- 1027,1034 ----
  	if (inputType != targetType)
  	{
  		expr = CoerceTargetExpr(pstate, expr, inputType,
! 								getBaseType(targetType),
! 								typename->typmod);
  		if (expr == NULL)
  			elog(ERROR, "Cannot cast type '%s' to '%s'",
  				 format_type_be(inputType),
***************
*** 1039,1045 ****
  	 * as well as a type coercion.
  	 */
  	expr = coerce_type_typmod(pstate, expr,
! 							  targetType, typename->typmod);
  
  	return expr;
  }
--- 1040,1046 ----
  	 * as well as a type coercion.
  	 */
  	expr = coerce_type_typmod(pstate, expr,
! 							  getBaseType(targetType), typename->typmod);
  
  	return expr;
  }
Index: src/backend/tcop/utility.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/tcop/utility.c,v
retrieving revision 1.125
diff -c -r1.125 utility.c
*** src/backend/tcop/utility.c	2002/02/07 00:27:30	1.125
--- src/backend/tcop/utility.c	2002/02/26 02:56:53
***************
*** 280,285 ****
--- 280,290 ----
  							/* 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,801 ****
--- 801,816 ----
  			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/backend/utils/adt/format_type.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/utils/adt/format_type.c,v
retrieving revision 1.23
diff -c -r1.23 format_type.c
*** src/backend/utils/adt/format_type.c	2001/11/19 19:51:20	1.23
--- src/backend/utils/adt/format_type.c	2002/02/26 02:56:54
***************
*** 126,131 ****
--- 126,132 ----
  	bool		is_array;
  	char	   *name;
  	char	   *buf;
+ 	char		typtype;
  
  	if (type_oid == InvalidOid && allow_invalid)
  		return pstrdup("-");
***************
*** 144,149 ****
--- 145,175 ----
  
  	array_base_type = ((Form_pg_type) GETSTRUCT(tuple))->typelem;
  	typlen = ((Form_pg_type) GETSTRUCT(tuple))->typlen;
+ 	typtype = ((Form_pg_type) GETSTRUCT(tuple))->typtype;
+ 
+ 	/*
+ 	 * Domains look alot like arrays, so lets process them first, and return
+ 	 * back to avoid the array and 'standard' formatting procedures that are
+ 	 * use for base types.
+ 	 */
+ 	if (typtype == 'd') {
+ 		name = NameStr(((Form_pg_type) GETSTRUCT(tuple))->typname);
+ 
+ 		/*
+ 		 * Double-quote the name if it's not a standard identifier.
+ 		 * Note this is *necessary* for ruleutils.c's use.
+ 		 */
+ 		if (strspn(name, "abcdefghijklmnopqrstuvwxyz0123456789_") != strlen(name)
+ 			|| isdigit((unsigned char) name[0]))
+ 				buf = psnprintf(strlen(name) + 3, "\"%s\"", name);
+ 		else
+ 			buf = pstrdup(name);
+ 
+ 		ReleaseSysCache(tuple);
+ 
+ 		return buf;
+ 	}
+ 
  	if (array_base_type != InvalidOid && typlen < 0)
  	{
  		/* Switch our attention to the array element type */
Index: src/backend/utils/cache/lsyscache.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v
retrieving revision 1.59
diff -c -r1.59 lsyscache.c
*** src/backend/utils/cache/lsyscache.c	2001/10/25 05:49:46	1.59
--- src/backend/utils/cache/lsyscache.c	2002/02/26 02:56:55
***************
*** 23,28 ****
--- 23,29 ----
  #include "catalog/pg_shadow.h"
  #include "catalog/pg_statistic.h"
  #include "catalog/pg_type.h"
+ #include "parser/parse_coerce.h"
  #include "utils/array.h"
  #include "utils/builtins.h"
  #include "utils/lsyscache.h"
***************
*** 752,767 ****
   *	  Returns FALSE if there is no default (effectively, default is NULL).
   *	  The result points to palloc'd storage for pass-by-reference types.
   */
! bool
! get_typdefault(Oid typid, Datum *defaultValue)
  {
  	HeapTuple	typeTuple;
  	Form_pg_type type;
! 	Oid			typinput,
! 				typelem;
! 	Datum		textDefaultVal;
  	bool		isNull;
! 	char	   *strDefaultVal;
  
  	typeTuple = SearchSysCache(TYPEOID,
  							   ObjectIdGetDatum(typid),
--- 753,769 ----
   *	  Returns FALSE if there is no default (effectively, default is NULL).
   *	  The result points to palloc'd storage for pass-by-reference types.
   */
! Node *
! get_typdefault(Oid typid, int32 atttypmod)
  {
  	HeapTuple	typeTuple;
  	Form_pg_type type;
! 	Oid			typinput;
! 	Oid			typbasetype;
! 	char		typtype;
! 	Datum		datum;
  	bool		isNull;
! 	Node	   *expr;
  
  	typeTuple = SearchSysCache(TYPEOID,
  							   ObjectIdGetDatum(typid),
***************
*** 773,810 ****
  	type = (Form_pg_type) GETSTRUCT(typeTuple);
  
  	typinput = type->typinput;
! 	typelem = type->typelem;
  
  	/*
! 	 * typdefault is potentially null, so don't try to access it as a
  	 * struct field. Must do it the hard way with SysCacheGetAttr.
  	 */
! 	textDefaultVal = SysCacheGetAttr(TYPEOID,
! 									 typeTuple,
! 									 Anum_pg_type_typdefault,
! 									 &isNull);
  
  	if (isNull)
! 	{
! 		ReleaseSysCache(typeTuple);
! 		*defaultValue = (Datum) 0;
! 		return false;
! 	}
  
! 	/* Convert text datum to C string */
! 	strDefaultVal = DatumGetCString(DirectFunctionCall1(textout,
! 														textDefaultVal));
! 
! 	/* Convert C string to a value of the given type */
! 	*defaultValue = OidFunctionCall3(typinput,
! 									 CStringGetDatum(strDefaultVal),
! 									 ObjectIdGetDatum(typelem),
! 									 Int32GetDatum(-1));
  
! 	pfree(strDefaultVal);
! 	ReleaseSysCache(typeTuple);
  
! 	return true;
  }
  
  /*
--- 775,815 ----
  	type = (Form_pg_type) GETSTRUCT(typeTuple);
  
  	typinput = type->typinput;
! 	typbasetype = type->typbasetype;
! 	typtype = type->typtype;
  
  	/*
! 	 * typdefaultbin is potentially null, so don't try to access it as a
  	 * struct field. Must do it the hard way with SysCacheGetAttr.
  	 */
! 	datum = SysCacheGetAttr(TYPEOID,
! 							typeTuple,
! 							Anum_pg_type_typdefaultbin,
! 							&isNull);
  
+ 	ReleaseSysCache(typeTuple);
  	if (isNull)
! 		return (Node *) NULL;
  
! 	/* Convert Datum to a Node */
! 	expr = stringToNode(DatumGetCString(
! 						DirectFunctionCall1(textout, datum)));
  
! 
! 	/*
! 	 * Ensure we goto the basetype before the domain type.
! 	 *
! 	 * Prevents scenarios like the below from failing:
! 	 * CREATE DOMAIN dom text DEFAULT random();
! 	 *
! 	 */
! 	if (typbasetype != InvalidOid) {
! 		expr = coerce_type(NULL, expr, typid,
! 						  typbasetype, atttypmod);
! 	}
! 
  
! 	return expr;
  }
  
  /*
Index: src/backend/utils/cache/relcache.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/utils/cache/relcache.c,v
retrieving revision 1.152
diff -c -r1.152 relcache.c
*** src/backend/utils/cache/relcache.c	2002/02/19 20:11:17	1.152
--- src/backend/utils/cache/relcache.c	2002/02/26 02:57:08
***************
*** 512,519 ****
  			   (char *) attp,
  			   ATTRIBUTE_TUPLE_SIZE);
  
! 		/* Update constraint/default info */
! 		if (attp->attnotnull)
  			constr->has_not_null = true;
  
  		if (attp->atthasdef)
--- 512,523 ----
  			   (char *) attp,
  			   ATTRIBUTE_TUPLE_SIZE);
  
! 
! 
! 		/*
! 		 * Update constraint/default info
! 		 */
!        if (attp->attnotnull)
  			constr->has_not_null = true;
  
  		if (attp->atthasdef)
Index: src/include/catalog/heap.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/catalog/heap.h,v
retrieving revision 1.41
diff -c -r1.41 heap.h
*** src/include/catalog/heap.h	2001/11/05 17:46:31	1.41
--- src/include/catalog/heap.h	2002/02/26 02:57:09
***************
*** 15,20 ****
--- 15,22 ----
  #define HEAP_H
  
  #include "catalog/pg_attribute.h"
+ #include "nodes/parsenodes.h"
+ #include "parser/parse_node.h"
  #include "utils/rel.h"
  
  typedef struct RawColumnDefault
***************
*** 44,49 ****
--- 46,57 ----
  extern void AddRelationRawConstraints(Relation rel,
  						  List *rawColDefaults,
  						  List *rawConstraints);
+ 
+ extern Node *cookDefault(ParseState *pstate
+ 						, Node *raw_default
+ 						, Oid atttypid
+ 						, int32 atttypmod
+ 						, char *attname);
  
  extern int	RemoveCheckConstraint(Relation rel, const char *constrName, bool inh);
  
Index: src/include/catalog/pg_attribute.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/catalog/pg_attribute.h,v
retrieving revision 1.80
diff -c -r1.80 pg_attribute.h
*** src/include/catalog/pg_attribute.h	2002/02/18 23:11:33	1.80
--- src/include/catalog/pg_attribute.h	2002/02/26 02:57:12
***************
*** 240,247 ****
  { 1247, {"typsend"},	   24, 0,	4, 14, 0, -1, -1, true, 'p', false, 'i', false, false }, \
  { 1247, {"typalign"},	   18, 0,	1, 15, 0, -1, -1, true, 'p', false, 'c', false, false }, \
  { 1247, {"typstorage"},    18, 0,	1, 16, 0, -1, -1, true, 'p', false, 'c', false, false }, \
! { 1247, {"typdefault"},    25, 0,  -1, 17, 0, -1, -1, false , 'x', false, 'i', false, false }
  
  DATA(insert ( 1247 typname			19 DEFAULT_ATTSTATTARGET NAMEDATALEN   1 0 -1 -1 f p f i f f));
  DATA(insert ( 1247 typowner			23 0  4   2 0 -1 -1 t p f i f f));
  DATA(insert ( 1247 typlen			21 0  2   3 0 -1 -1 t p f s f f));
--- 240,253 ----
  { 1247, {"typsend"},	   24, 0,	4, 14, 0, -1, -1, true, 'p', false, 'i', false, false }, \
  { 1247, {"typalign"},	   18, 0,	1, 15, 0, -1, -1, true, 'p', false, 'c', false, false }, \
  { 1247, {"typstorage"},    18, 0,	1, 16, 0, -1, -1, true, 'p', false, 'c', false, false }, \
! { 1247, {"typnotnull"},    16, 0,   1, 17, 0, -1, -1, true, 'p', false, 'c', false, false }, \
! { 1247, {"typmod"},        23, 0,	4, 18, 0, -1, -1, true, 'p', false, 'i', false, false }, \
! { 1247, {"typbasetype"},   26, 0,	4, 19, 0, -1, -1, true, 'p', false, 'i', false, false }, \
! { 1247, {"typndims"},      23, 0,	4, 20, 0, -1, -1, true, 'p', false, 'i', false, false }, \
! { 1247, {"typdefaultbin"}, 25, 0,  -1, 21, 0, -1, -1, false, 'x', false, 'i', false, false }, \
! { 1247, {"typdefault"},    25, 0,  -1, 22, 0, -1, -1, false, 'x', false, 'i', false, false }
  
+ 
  DATA(insert ( 1247 typname			19 DEFAULT_ATTSTATTARGET NAMEDATALEN   1 0 -1 -1 f p f i f f));
  DATA(insert ( 1247 typowner			23 0  4   2 0 -1 -1 t p f i f f));
  DATA(insert ( 1247 typlen			21 0  2   3 0 -1 -1 t p f s f f));
***************
*** 258,264 ****
  DATA(insert ( 1247 typsend			24 0  4  14 0 -1 -1 t p f i f f));
  DATA(insert ( 1247 typalign			18 0  1  15 0 -1 -1 t p f c f f));
  DATA(insert ( 1247 typstorage		18 0  1  16 0 -1 -1 t p f c f f));
! DATA(insert ( 1247 typdefault		25 0 -1  17 0 -1 -1 f x f i f f));
  DATA(insert ( 1247 ctid				27 0  6  -1 0 -1 -1 f p f i f f));
  DATA(insert ( 1247 oid				26 0  4  -2 0 -1 -1 t p f i f f));
  DATA(insert ( 1247 xmin				28 0  4  -3 0 -1 -1 t p f i f f));
--- 264,275 ----
  DATA(insert ( 1247 typsend			24 0  4  14 0 -1 -1 t p f i f f));
  DATA(insert ( 1247 typalign			18 0  1  15 0 -1 -1 t p f c f f));
  DATA(insert ( 1247 typstorage		18 0  1  16 0 -1 -1 t p f c f f));
! DATA(insert ( 1247 typnotnull		16 0  1  17 0 -1 -1 t p f c f f));
! DATA(insert ( 1247 typmod			23 0  4  18 0 -1 -1 t p f i f f));
! DATA(insert ( 1247 typbasetype		26 0  4  19 0 -1 -1 t p f i f f));
! DATA(insert ( 1247 typndims			23 0  4  20 0 -1 -1 t p f i f f));
! DATA(insert ( 1247 typdefaultbin	25 0 -1  21 0 -1 -1 f x f i f f));
! DATA(insert ( 1247 typdefault		25 0 -1  22 0 -1 -1 f x f i f f));
  DATA(insert ( 1247 ctid				27 0  6  -1 0 -1 -1 f p f i f f));
  DATA(insert ( 1247 oid				26 0  4  -2 0 -1 -1 t p f i f f));
  DATA(insert ( 1247 xmin				28 0  4  -3 0 -1 -1 t p f i f f));
Index: src/include/catalog/pg_class.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/catalog/pg_class.h,v
retrieving revision 1.58
diff -c -r1.58 pg_class.h
*** src/include/catalog/pg_class.h	2002/02/18 23:11:34	1.58
--- src/include/catalog/pg_class.h	2002/02/26 02:57:12
***************
*** 132,138 ****
   * ----------------
   */
  
! DATA(insert OID = 1247 (  pg_type		71	PGUID 0 1247 0 0 0 0 f f r 17 0 0 0 0 0 t f f f _null_ ));
  DESCR("");
  DATA(insert OID = 1249 (  pg_attribute	75	PGUID 0 1249 0 0 0 0 f f r 15 0 0 0 0 0 f f f f _null_ ));
  DESCR("");
--- 132,138 ----
   * ----------------
   */
  
! DATA(insert OID = 1247 (  pg_type		71	PGUID 0 1247 0 0 0 0 f f r 22 0 0 0 0 0 t f f f _null_ ));
  DESCR("");
  DATA(insert OID = 1249 (  pg_attribute	75	PGUID 0 1249 0 0 0 0 f f r 15 0 0 0 0 0 f f f f _null_ ));
  DESCR("");
Index: src/include/catalog/pg_type.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/catalog/pg_type.h,v
retrieving revision 1.114
diff -c -r1.114 pg_type.h
*** src/include/catalog/pg_type.h	2001/11/05 17:46:33	1.114
--- src/include/catalog/pg_type.h	2002/02/26 02:57:14
***************
*** 141,152 ****
  	char		typstorage;
  
  	/*
  	 * typdefault is NULL if the type has no associated default value. If
  	 * it's not NULL, it contains the external representation of the
! 	 * type's default value --- this default is used whenever no
! 	 * per-column default is specified for a column of the datatype.
  	 */
  	text		typdefault;		/* VARIABLE LENGTH FIELD */
  } FormData_pg_type;
  
  /* ----------------
--- 141,189 ----
  	char		typstorage;
  
  	/*
+ 	 * This flag represents a "NOT NULL" constraint against this datatype.
+ 	 *
+ 	 * If true, the attnotnull column for a corresponding table column using
+ 	 * this datatype will always enforce the NOT NULL constraint.
+ 	 *
+ 	 * Used primarily for domain types.
+ 	 */
+ 	bool		typnotnull;
+ 
+ 	/*
+ 	 * typmod records type-specific data supplied at domain creation
+ 	 * time (for example, the max length of a varchar field).  It is
+ 	 * passed to type-specific input and output functions as the third
+ 	 * argument. The value will generally be -1 for types that do not need
+ 	 * typmod.  This value is copied to pg_attribute.atttypmod.
+ 	 */
+ 	int4		typmod;
+ 
+ 	/*
+ 	 * Domains use typbasetype to determine the base (or complex)type that
+ 	 * the domain is based off.  It must be non-zero if the type is a
+ 	 * domain.
+ 	 */
+ 	Oid			typbasetype;
+ 
+ 	/*
+ 	 * typndims is the declared number of dimensions, if an array typbasetype,
+ 	 * otherwise zero.
+ 	 */
+ 	int4		typndims;
+ 
+ 	/*
+ 	 * typdefaultbin is the binary representation of typdefault
+ 	 */
+ 	text		typdefaultbin;	/* VARIABLE LENGTH FIELD */
+ 
+ 	/*
  	 * typdefault is NULL if the type has no associated default value. If
  	 * it's not NULL, it contains the external representation of the
! 	 * type's default value
  	 */
  	text		typdefault;		/* VARIABLE LENGTH FIELD */
+ 
  } FormData_pg_type;
  
  /* ----------------
***************
*** 160,166 ****
   *		compiler constants for pg_type
   * ----------------
   */
! #define Natts_pg_type					17
  #define Anum_pg_type_typname			1
  #define Anum_pg_type_typowner			2
  #define Anum_pg_type_typlen				3
--- 197,203 ----
   *		compiler constants for pg_type
   * ----------------
   */
! #define Natts_pg_type					22
  #define Anum_pg_type_typname			1
  #define Anum_pg_type_typowner			2
  #define Anum_pg_type_typlen				3
***************
*** 177,183 ****
  #define Anum_pg_type_typsend			14
  #define Anum_pg_type_typalign			15
  #define Anum_pg_type_typstorage			16
! #define Anum_pg_type_typdefault			17
  
  /* ----------------
   *		initial contents of pg_type
--- 214,226 ----
  #define Anum_pg_type_typsend			14
  #define Anum_pg_type_typalign			15
  #define Anum_pg_type_typstorage			16
! #define Anum_pg_type_typnotnull			17
! #define Anum_pg_type_typmod				18
! #define Anum_pg_type_typbasetype		19
! #define Anum_pg_type_typndims			20
! #define Anum_pg_type_typdefaultbin		21
! #define Anum_pg_type_typdefault			22
! 
  
  /* ----------------
   *		initial contents of pg_type
***************
*** 192,273 ****
  */
  
  /* OIDS 1 - 99 */
! DATA(insert OID = 16 (	bool	   PGUID  1   1 t b t \054 0   0 boolin boolout boolin boolout c p _null_ ));
  DESCR("boolean, 'true'/'false'");
  #define BOOLOID			16
  
! DATA(insert OID = 17 (	bytea	   PGUID -1  -1 f b t \054 0  0 byteain byteaout byteain byteaout i x _null_ ));
  DESCR("variable-length string, binary values escaped");
  #define BYTEAOID		17
  
! DATA(insert OID = 18 (	char	   PGUID  1   1 t b t \054 0   0 charin charout charin charout c p _null_ ));
  DESCR("single character");
  #define CHAROID			18
  
! DATA(insert OID = 19 (	name	   PGUID NAMEDATALEN NAMEDATALEN  f b t \054 0	18 namein nameout namein nameout i p _null_ ));
  DESCR("31-character type for storing system identifiers");
  #define NAMEOID			19
  
! DATA(insert OID = 20 (	int8	   PGUID  8  20 f b t \054 0   0 int8in int8out int8in int8out d p _null_ ));
  DESCR("~18 digit integer, 8-byte storage");
  #define INT8OID			20
  
! DATA(insert OID = 21 (	int2	   PGUID  2   5 t b t \054 0   0 int2in int2out int2in int2out s p _null_ ));
  DESCR("-32 thousand to 32 thousand, 2-byte storage");
  #define INT2OID			21
  
! DATA(insert OID = 22 (	int2vector PGUID INDEX_MAX_KEYS*2 -1 f b t \054 0  21 int2vectorin int2vectorout int2vectorin int2vectorout i p _null_ ));
  DESCR("array of INDEX_MAX_KEYS int2 integers, used in system tables");
  #define INT2VECTOROID	22
  
! DATA(insert OID = 23 (	int4	   PGUID  4  10 t b t \054 0   0 int4in int4out int4in int4out i p _null_ ));
  DESCR("-2 billion to 2 billion integer, 4-byte storage");
  #define INT4OID			23
  
! DATA(insert OID = 24 (	regproc    PGUID  4  16 t b t \054 0   0 regprocin regprocout regprocin regprocout i p _null_ ));
  DESCR("registered procedure");
  #define REGPROCOID		24
  
! DATA(insert OID = 25 (	text	   PGUID -1  -1 f b t \054 0  0 textin textout textin textout i x _null_ ));
  DESCR("variable-length string, no limit specified");
  #define TEXTOID			25
  
! DATA(insert OID = 26 (	oid		   PGUID  4  10 t b t \054 0   0 oidin oidout oidin oidout i p _null_ ));
  DESCR("object identifier(oid), maximum 4 billion");
  #define OIDOID			26
  
! DATA(insert OID = 27 (	tid		   PGUID  6  19 f b t \054 0   0 tidin tidout tidin tidout i p _null_ ));
  DESCR("(Block, offset), physical location of tuple");
  #define TIDOID		27
  
! DATA(insert OID = 28 (	xid		   PGUID  4  12 t b t \054 0   0 xidin xidout xidin xidout i p _null_ ));
  DESCR("transaction id");
  #define XIDOID 28
  
! DATA(insert OID = 29 (	cid		   PGUID  4  10 t b t \054 0   0 cidin cidout cidin cidout i p _null_ ));
  DESCR("command identifier type, sequence in transaction id");
  #define CIDOID 29
  
! DATA(insert OID = 30 (	oidvector  PGUID INDEX_MAX_KEYS*4 -1 f b t \054 0  26 oidvectorin oidvectorout oidvectorin oidvectorout i p _null_ ));
  DESCR("array of INDEX_MAX_KEYS oids, used in system tables");
  #define OIDVECTOROID	30
  
! DATA(insert OID = 32 (	SET		   PGUID -1  -1 f b t \054 0   0 textin textout textin textout i p _null_ ));
  DESCR("set of tuples");
  
! DATA(insert OID = 71 (	pg_type		 PGUID 4 4 t c t \054 1247 0 int4in int4out int4in int4out i p _null_));
! DATA(insert OID = 75 (	pg_attribute PGUID 4 4 t c t \054 1249 0 int4in int4out int4in int4out i p _null_));
! DATA(insert OID = 81 (	pg_proc		 PGUID 4 4 t c t \054 1255 0 int4in int4out int4in int4out i p _null_));
! DATA(insert OID = 83 (	pg_class	 PGUID 4 4 t c t \054 1259 0 int4in int4out int4in int4out i p _null_));
! DATA(insert OID = 86 (	pg_shadow	 PGUID 4 4 t c t \054 1260 0 int4in int4out int4in int4out i p _null_));
! DATA(insert OID = 87 (	pg_group	 PGUID 4 4 t c t \054 1261 0 int4in int4out int4in int4out i p _null_));
! DATA(insert OID = 88 (	pg_database  PGUID 4 4 t c t \054 1262 0 int4in int4out int4in int4out i p _null_));
  
  /* OIDS 100 - 199 */
  
  /* OIDS 200 - 299 */
  
! DATA(insert OID = 210 (  smgr	   PGUID 2	12 t b t \054 0 0 smgrin smgrout smgrin smgrout s p _null_ ));
  DESCR("storage manager");
  
  /* OIDS 300 - 399 */
--- 235,316 ----
  */
  
  /* OIDS 1 - 99 */
! DATA(insert OID = 16 (	bool	   PGUID  1   1 t b t \054 0   0 boolin boolout boolin boolout c p f -1 0 0 _null_ _null_ ));
  DESCR("boolean, 'true'/'false'");
  #define BOOLOID			16
  
! DATA(insert OID = 17 (	bytea	   PGUID -1  -1 f b t \054 0  0 byteain byteaout byteain byteaout i x f -1 0 0 _null_ _null_ ));
  DESCR("variable-length string, binary values escaped");
  #define BYTEAOID		17
  
! DATA(insert OID = 18 (	char	   PGUID  1   1 t b t \054 0   0 charin charout charin charout c p f -1 0 0 _null_ _null_ ));
  DESCR("single character");
  #define CHAROID			18
  
! DATA(insert OID = 19 (	name	   PGUID NAMEDATALEN NAMEDATALEN  f b t \054 0	18 namein nameout namein nameout i p f -1 0 0 _null_ _null_ ));
  DESCR("31-character type for storing system identifiers");
  #define NAMEOID			19
  
! DATA(insert OID = 20 (	int8	   PGUID  8  20 f b t \054 0   0 int8in int8out int8in int8out d p f -1 0 0 _null_ _null_ ));
  DESCR("~18 digit integer, 8-byte storage");
  #define INT8OID			20
  
! DATA(insert OID = 21 (	int2	   PGUID  2   5 t b t \054 0   0 int2in int2out int2in int2out s p f -1 0 0 _null_ _null_ ));
  DESCR("-32 thousand to 32 thousand, 2-byte storage");
  #define INT2OID			21
  
! DATA(insert OID = 22 (	int2vector PGUID INDEX_MAX_KEYS*2 -1 f b t \054 0  21 int2vectorin int2vectorout int2vectorin int2vectorout i p f -1 0 0 _null_ _null_ ));
  DESCR("array of INDEX_MAX_KEYS int2 integers, used in system tables");
  #define INT2VECTOROID	22
  
! DATA(insert OID = 23 (	int4	   PGUID  4  10 t b t \054 0   0 int4in int4out int4in int4out i p f -1 0 0 _null_ _null_ ));
  DESCR("-2 billion to 2 billion integer, 4-byte storage");
  #define INT4OID			23
  
! DATA(insert OID = 24 (	regproc    PGUID  4  16 t b t \054 0   0 regprocin regprocout regprocin regprocout i p f -1 0 0 _null_ _null_ ));
  DESCR("registered procedure");
  #define REGPROCOID		24
  
! DATA(insert OID = 25 (	text	   PGUID -1  -1 f b t \054 0  0 textin textout textin textout i x f -1 0 0 _null_ _null_ ));
  DESCR("variable-length string, no limit specified");
  #define TEXTOID			25
  
! DATA(insert OID = 26 (	oid		   PGUID  4  10 t b t \054 0   0 oidin oidout oidin oidout i p f -1 0 0 _null_ _null_ ));
  DESCR("object identifier(oid), maximum 4 billion");
  #define OIDOID			26
  
! DATA(insert OID = 27 (	tid		   PGUID  6  19 f b t \054 0   0 tidin tidout tidin tidout i p f -1 0 0 _null_ _null_ ));
  DESCR("(Block, offset), physical location of tuple");
  #define TIDOID		27
  
! DATA(insert OID = 28 (	xid		   PGUID  4  12 t b t \054 0   0 xidin xidout xidin xidout i p f -1 0 0 _null_ _null_ ));
  DESCR("transaction id");
  #define XIDOID 28
  
! DATA(insert OID = 29 (	cid		   PGUID  4  10 t b t \054 0   0 cidin cidout cidin cidout i p f -1 0 0 _null_ _null_ ));
  DESCR("command identifier type, sequence in transaction id");
  #define CIDOID 29
  
! DATA(insert OID = 30 (	oidvector  PGUID INDEX_MAX_KEYS*4 -1 f b t \054 0  26 oidvectorin oidvectorout oidvectorin oidvectorout i p f -1 0 0 _null_ _null_ ));
  DESCR("array of INDEX_MAX_KEYS oids, used in system tables");
  #define OIDVECTOROID	30
  
! DATA(insert OID = 32 (	SET		   PGUID -1  -1 f b t \054 0   0 textin textout textin textout i p f -1 0 0 _null_ _null_ ));
  DESCR("set of tuples");
  
! DATA(insert OID = 71 (	pg_type		 PGUID 4 4 t c t \054 1247 0 int4in int4out int4in int4out i p f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 75 (	pg_attribute PGUID 4 4 t c t \054 1249 0 int4in int4out int4in int4out i p f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 81 (	pg_proc		 PGUID 4 4 t c t \054 1255 0 int4in int4out int4in int4out i p f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 83 (	pg_class	 PGUID 4 4 t c t \054 1259 0 int4in int4out int4in int4out i p f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 86 (	pg_shadow	 PGUID 4 4 t c t \054 1260 0 int4in int4out int4in int4out i p f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 87 (	pg_group	 PGUID 4 4 t c t \054 1261 0 int4in int4out int4in int4out i p f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 88 (	pg_database  PGUID 4 4 t c t \054 1262 0 int4in int4out int4in int4out i p f -1 0 0 _null_ _null_ ));
  
  /* OIDS 100 - 199 */
  
  /* OIDS 200 - 299 */
  
! DATA(insert OID = 210 (  smgr	   PGUID 2	12 t b t \054 0 0 smgrin smgrout smgrin smgrout s p f -1 0 0 _null_ _null_ ));
  DESCR("storage manager");
  
  /* OIDS 300 - 399 */
***************
*** 277,443 ****
  /* OIDS 500 - 599 */
  
  /* OIDS 600 - 699 */
! DATA(insert OID = 600 (  point	   PGUID 16  24 f b t \054 0 701 point_in point_out point_in point_out d p _null_ ));
  DESCR("geometric point '(x, y)'");
  #define POINTOID		600
! DATA(insert OID = 601 (  lseg	   PGUID 32  48 f b t \054 0 600 lseg_in lseg_out lseg_in lseg_out d p _null_ ));
  DESCR("geometric line segment '(pt1,pt2)'");
  #define LSEGOID			601
! DATA(insert OID = 602 (  path	   PGUID -1  -1 f b t \054 0 0 path_in path_out path_in path_out d x _null_ ));
  DESCR("geometric path '(pt1,...)'");
  #define PATHOID			602
! DATA(insert OID = 603 (  box	   PGUID 32 100 f b t \073 0 600 box_in box_out box_in box_out d p _null_ ));
  DESCR("geometric box '(lower left,upper right)'");
  #define BOXOID			603
! DATA(insert OID = 604 (  polygon   PGUID -1  -1 f b t \054 0   0 poly_in poly_out poly_in poly_out d x _null_ ));
  DESCR("geometric polygon '(pt1,...)'");
  #define POLYGONOID		604
  
! DATA(insert OID = 628 (  line	   PGUID 32  48 f b t \054 0 701 line_in line_out line_in line_out d p _null_ ));
  DESCR("geometric line '(pt1,pt2)'");
  #define LINEOID			628
! DATA(insert OID = 629 (  _line	   PGUID  -1 -1 f b t \054 0 628 array_in array_out array_in array_out d x _null_ ));
  DESCR("");
  
  /* OIDS 700 - 799 */
  
! DATA(insert OID = 700 (  float4    PGUID  4  12 f b t \054 0   0 float4in float4out float4in float4out i p _null_ ));
  DESCR("single-precision floating point number, 4-byte storage");
  #define FLOAT4OID 700
! DATA(insert OID = 701 (  float8    PGUID  8  24 f b t \054 0   0 float8in float8out float8in float8out d p _null_ ));
  DESCR("double-precision floating point number, 8-byte storage");
  #define FLOAT8OID 701
! DATA(insert OID = 702 (  abstime   PGUID  4  20 t b t \054 0   0 nabstimein nabstimeout nabstimein nabstimeout i p _null_ ));
  DESCR("absolute, limited-range date and time (Unix system time)");
  #define ABSTIMEOID		702
! DATA(insert OID = 703 (  reltime   PGUID  4  20 t b t \054 0   0 reltimein reltimeout reltimein reltimeout i p _null_ ));
  DESCR("relative, limited-range time interval (Unix delta time)");
  #define RELTIMEOID		703
! DATA(insert OID = 704 (  tinterval PGUID 12  47 f b t \054 0   0 tintervalin tintervalout tintervalin tintervalout i p _null_ ));
  DESCR("(abstime,abstime), time interval");
  #define TINTERVALOID	704
! DATA(insert OID = 705 (  unknown   PGUID -1  -1 f b t \054 0   0 textin textout textin textout i p _null_ ));
  DESCR("");
  #define UNKNOWNOID		705
  
! DATA(insert OID = 718 (  circle    PGUID  24 47 f b t \054 0	0 circle_in circle_out circle_in circle_out d p _null_ ));
  DESCR("geometric circle '(center,radius)'");
  #define CIRCLEOID		718
! DATA(insert OID = 719 (  _circle   PGUID  -1 -1 f b t \054 0  718 array_in array_out array_in array_out d x _null_ ));
! DATA(insert OID = 790 (  money	   PGUID   4 24 f b t \054 0	0 cash_in cash_out cash_in cash_out i p _null_ ));
  DESCR("$d,ddd.cc, money");
  #define CASHOID 790
! DATA(insert OID = 791 (  _money    PGUID  -1 -1 f b t \054 0  790 array_in array_out array_in array_out i x _null_ ));
  
  /* OIDS 800 - 899 */
! DATA(insert OID = 829 ( macaddr    PGUID  6 -1 f b t \054 0 0 macaddr_in macaddr_out macaddr_in macaddr_out i p _null_ ));
  DESCR("XX:XX:XX:XX:XX:XX, MAC address");
  #define MACADDROID 829
! DATA(insert OID = 869 ( inet	   PGUID  -1 -1 f b t \054 0 0 inet_in inet_out inet_in inet_out i p _null_ ));
  DESCR("IP address/netmask, host address, netmask optional");
  #define INETOID 869
! DATA(insert OID = 650 ( cidr	   PGUID  -1 -1 f b t \054 0 0 cidr_in cidr_out cidr_in cidr_out i p _null_ ));
  DESCR("network IP address/netmask, network address");
  #define CIDROID 650
  
  /* OIDS 900 - 999 */
  
  /* OIDS 1000 - 1099 */
! DATA(insert OID = 1000 (  _bool		 PGUID -1  -1 f b t \054 0	16 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1001 (  _bytea	 PGUID -1  -1 f b t \054 0	17 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1002 (  _char		 PGUID -1  -1 f b t \054 0	18 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1003 (  _name		 PGUID -1  -1 f b t \054 0	19 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1005 (  _int2		 PGUID -1  -1 f b t \054 0	21 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1006 (  _int2vector PGUID -1 -1 f b t \054 0	22 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1007 (  _int4		 PGUID -1  -1 f b t \054 0	23 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1008 (  _regproc	 PGUID -1  -1 f b t \054 0	24 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1009 (  _text		 PGUID -1  -1 f b t \054 0	25 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1028 (  _oid		 PGUID -1  -1 f b t \054 0	26 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1010 (  _tid		 PGUID -1  -1 f b t \054 0	27 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1011 (  _xid		 PGUID -1  -1 f b t \054 0	28 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1012 (  _cid		 PGUID -1  -1 f b t \054 0	29 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1013 (  _oidvector PGUID -1  -1 f b t \054 0	30 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1014 (  _bpchar	 PGUID -1  -1 f b t \054 0 1042 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1015 (  _varchar	 PGUID -1  -1 f b t \054 0 1043 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1016 (  _int8		 PGUID -1  -1 f b t \054 0	20 array_in array_out array_in array_out d x _null_ ));
! DATA(insert OID = 1017 (  _point	 PGUID -1  -1 f b t \054 0 600 array_in array_out array_in array_out d x _null_ ));
! DATA(insert OID = 1018 (  _lseg		 PGUID -1  -1 f b t \054 0 601 array_in array_out array_in array_out d x _null_ ));
! DATA(insert OID = 1019 (  _path		 PGUID -1  -1 f b t \054 0 602 array_in array_out array_in array_out d x _null_ ));
! DATA(insert OID = 1020 (  _box		 PGUID -1  -1 f b t \073 0 603 array_in array_out array_in array_out d x _null_ ));
! DATA(insert OID = 1021 (  _float4	 PGUID -1  -1 f b t \054 0 700 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1022 (  _float8	 PGUID -1  -1 f b t \054 0 701 array_in array_out array_in array_out d x _null_ ));
! DATA(insert OID = 1023 (  _abstime	 PGUID -1  -1 f b t \054 0 702 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1024 (  _reltime	 PGUID -1  -1 f b t \054 0 703 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1025 (  _tinterval PGUID -1  -1 f b t \054 0 704 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1027 (  _polygon	 PGUID -1  -1 f b t \054 0 604 array_in array_out array_in array_out d x _null_ ));
  /*
   *	Note: the size of aclitem needs to match sizeof(AclItem) in acl.h.
   *	Thanks to some padding, this will be 8 on all platforms.
   *	We also have an Assert to make sure.
   */
  #define ACLITEMSIZE 8
! DATA(insert OID = 1033 (  aclitem	 PGUID 8   -1 f b t \054 0 0 aclitemin aclitemout aclitemin aclitemout i p _null_ ));
  DESCR("access control list");
! DATA(insert OID = 1034 (  _aclitem	 PGUID -1 -1 f b t \054 0 1033 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1040 (  _macaddr	 PGUID -1 -1 f b t \054 0  829 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1041 (  _inet    PGUID -1 -1 f b t \054 0  869 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 651  (  _cidr    PGUID -1 -1 f b t \054 0  650 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1042 ( bpchar		 PGUID -1  -1 f b t \054 0	0 bpcharin bpcharout bpcharin bpcharout i x _null_ ));
  DESCR("char(length), blank-padded string, fixed storage length");
  #define BPCHAROID		1042
! DATA(insert OID = 1043 ( varchar	 PGUID -1  -1 f b t \054 0	0 varcharin varcharout varcharin varcharout i x _null_ ));
  DESCR("varchar(length), non-blank-padded string, variable storage length");
  #define VARCHAROID		1043
  
! DATA(insert OID = 1082 ( date		 PGUID	4  10 t b t \054 0	0 date_in date_out date_in date_out i p _null_ ));
  DESCR("ANSI SQL date");
  #define DATEOID			1082
! DATA(insert OID = 1083 ( time		 PGUID	8  16 f b t \054 0	0 time_in time_out time_in time_out d p _null_ ));
  DESCR("hh:mm:ss, ANSI SQL time");
  #define TIMEOID			1083
  
  /* OIDS 1100 - 1199 */
! DATA(insert OID = 1114 ( timestamp	 PGUID	8  47 f b t \054 0	0 timestamp_in timestamp_out timestamp_in timestamp_out d p _null_ ));
  DESCR("date and time");
  #define TIMESTAMPOID	1114
! DATA(insert OID = 1115 ( _timestamp  PGUID	-1 -1 f b t \054 0	1184 array_in array_out array_in array_out d x _null_ ));
! DATA(insert OID = 1182 ( _date		 PGUID	-1 -1 f b t \054 0	1082 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1183 ( _time		 PGUID	-1 -1 f b t \054 0	1083 array_in array_out array_in array_out d x _null_ ));
! DATA(insert OID = 1184 ( timestamptz PGUID	8  47 f b t \054 0	0 timestamptz_in timestamptz_out timestamptz_in timestamptz_out d p _null_ ));
  DESCR("date and time with time zone");
  #define TIMESTAMPTZOID	1184
! DATA(insert OID = 1185 ( _timestamptz PGUID -1 -1 f b t \054 0	1184 array_in array_out array_in array_out d x _null_ ));
! DATA(insert OID = 1186 ( interval	 PGUID 12  47 f b t \054 0	0 interval_in interval_out interval_in interval_out d p _null_ ));
  DESCR("@ <number> <units>, time interval");
  #define INTERVALOID		1186
! DATA(insert OID = 1187 ( _interval	 PGUID	-1 -1 f b t \054 0	1186 array_in array_out array_in array_out d x _null_ ));
  
  /* OIDS 1200 - 1299 */
! DATA(insert OID = 1231 (  _numeric	 PGUID -1  -1 f b t \054 0	1700 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1266 ( timetz		 PGUID 12  22 f b t \054 0	0 timetz_in timetz_out timetz_in timetz_out d p _null_ ));
  DESCR("hh:mm:ss, ANSI SQL time");
  #define TIMETZOID		1266
! DATA(insert OID = 1270 ( _timetz	 PGUID	-1 -1 f b t \054 0	1266 array_in array_out array_in array_out d x _null_ ));
  
  /* OIDS 1500 - 1599 */
! DATA(insert OID = 1560 ( bit		 PGUID -1  -1 f b t \054 0	0 bit_in bit_out bit_in bit_out i x _null_ ));
  DESCR("fixed-length bit string");
  #define BITOID	 1560
! DATA(insert OID = 1561 ( _bit		 PGUID	-1 -1 f b t \054 0	1560 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1562 ( varbit		 PGUID -1  -1 f b t \054 0	0 varbit_in varbit_out varbit_in varbit_out i x _null_ ));
  DESCR("variable-length bit string");
  #define VARBITOID	  1562
! DATA(insert OID = 1563 ( _varbit	 PGUID	-1 -1 f b t \054 0	1562 array_in array_out array_in array_out i x _null_ ));
  
  /* OIDS 1600 - 1699 */
  
  /* OIDS 1700 - 1799 */
! DATA(insert OID = 1700 ( numeric	   PGUID -1  -1 f b t \054 0  0 numeric_in numeric_out numeric_in numeric_out i m _null_ ));
  DESCR("numeric(precision, decimal), arbitrary precision number");
  #define NUMERICOID		1700
  
  /* OID 1790 */
! DATA(insert OID = 1790 ( refcursor	   PGUID -1  -1 f b t \054 0  0 textin textout textin textout i x _null_ ));
  DESCR("reference cursor (portal name)");
  #define REFCURSOROID	1790
  
--- 320,486 ----
  /* OIDS 500 - 599 */
  
  /* OIDS 600 - 699 */
! DATA(insert OID = 600 (  point	   PGUID 16  24 f b t \054 0 701 point_in point_out point_in point_out d p f -1 0 0 _null_ _null_ ));
  DESCR("geometric point '(x, y)'");
  #define POINTOID		600
! DATA(insert OID = 601 (  lseg	   PGUID 32  48 f b t \054 0 600 lseg_in lseg_out lseg_in lseg_out d p f -1 0 0 _null_ _null_ ));
  DESCR("geometric line segment '(pt1,pt2)'");
  #define LSEGOID			601
! DATA(insert OID = 602 (  path	   PGUID -1  -1 f b t \054 0 0 path_in path_out path_in path_out d x f -1 0 0 _null_ _null_ ));
  DESCR("geometric path '(pt1,...)'");
  #define PATHOID			602
! DATA(insert OID = 603 (  box	   PGUID 32 100 f b t \073 0 600 box_in box_out box_in box_out d p f -1 0 0 _null_ _null_ ));
  DESCR("geometric box '(lower left,upper right)'");
  #define BOXOID			603
! DATA(insert OID = 604 (  polygon   PGUID -1  -1 f b t \054 0   0 poly_in poly_out poly_in poly_out d x f -1 0 0 _null_ _null_ ));
  DESCR("geometric polygon '(pt1,...)'");
  #define POLYGONOID		604
  
! DATA(insert OID = 628 (  line	   PGUID 32  48 f b t \054 0 701 line_in line_out line_in line_out d p f -1 0 0 _null_ _null_ ));
  DESCR("geometric line '(pt1,pt2)'");
  #define LINEOID			628
! DATA(insert OID = 629 (  _line	   PGUID  -1 -1 f b t \054 0 628 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
  DESCR("");
  
  /* OIDS 700 - 799 */
  
! DATA(insert OID = 700 (  float4    PGUID  4  12 f b t \054 0   0 float4in float4out float4in float4out i p f -1 0 0 _null_ _null_ ));
  DESCR("single-precision floating point number, 4-byte storage");
  #define FLOAT4OID 700
! DATA(insert OID = 701 (  float8    PGUID  8  24 f b t \054 0   0 float8in float8out float8in float8out d p f -1 0 0 _null_ _null_ ));
  DESCR("double-precision floating point number, 8-byte storage");
  #define FLOAT8OID 701
! DATA(insert OID = 702 (  abstime   PGUID  4  20 t b t \054 0   0 nabstimein nabstimeout nabstimein nabstimeout i p f -1 0 0 _null_ _null_ ));
  DESCR("absolute, limited-range date and time (Unix system time)");
  #define ABSTIMEOID		702
! DATA(insert OID = 703 (  reltime   PGUID  4  20 t b t \054 0   0 reltimein reltimeout reltimein reltimeout i p f -1 0 0 _null_ _null_ ));
  DESCR("relative, limited-range time interval (Unix delta time)");
  #define RELTIMEOID		703
! DATA(insert OID = 704 (  tinterval PGUID 12  47 f b t \054 0   0 tintervalin tintervalout tintervalin tintervalout i p f -1 0 0 _null_ _null_ ));
  DESCR("(abstime,abstime), time interval");
  #define TINTERVALOID	704
! DATA(insert OID = 705 (  unknown   PGUID -1  -1 f b t \054 0   0 textin textout textin textout i p f -1 0 0 _null_ _null_ ));
  DESCR("");
  #define UNKNOWNOID		705
  
! DATA(insert OID = 718 (  circle    PGUID  24 47 f b t \054 0	0 circle_in circle_out circle_in circle_out d p f -1 0 0 _null_ _null_ ));
  DESCR("geometric circle '(center,radius)'");
  #define CIRCLEOID		718
! DATA(insert OID = 719 (  _circle   PGUID  -1 -1 f b t \054 0  718 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 790 (  money	   PGUID   4 24 f b t \054 0	0 cash_in cash_out cash_in cash_out i p f -1 0 0 _null_ _null_ ));
  DESCR("$d,ddd.cc, money");
  #define CASHOID 790
! DATA(insert OID = 791 (  _money    PGUID  -1 -1 f b t \054 0  790 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
  
  /* OIDS 800 - 899 */
! DATA(insert OID = 829 ( macaddr    PGUID  6 -1 f b t \054 0 0 macaddr_in macaddr_out macaddr_in macaddr_out i p f -1 0 0 _null_ _null_ ));
  DESCR("XX:XX:XX:XX:XX:XX, MAC address");
  #define MACADDROID 829
! DATA(insert OID = 869 ( inet	   PGUID  -1 -1 f b t \054 0 0 inet_in inet_out inet_in inet_out i p f -1 0 0 _null_ _null_ ));
  DESCR("IP address/netmask, host address, netmask optional");
  #define INETOID 869
! DATA(insert OID = 650 ( cidr	   PGUID  -1 -1 f b t \054 0 0 cidr_in cidr_out cidr_in cidr_out i p f -1 0 0 _null_ _null_ ));
  DESCR("network IP address/netmask, network address");
  #define CIDROID 650
  
  /* OIDS 900 - 999 */
  
  /* OIDS 1000 - 1099 */
! DATA(insert OID = 1000 (  _bool		 PGUID -1  -1 f b t \054 0	16 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1001 (  _bytea	 PGUID -1  -1 f b t \054 0	17 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1002 (  _char		 PGUID -1  -1 f b t \054 0	18 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1003 (  _name		 PGUID -1  -1 f b t \054 0	19 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1005 (  _int2		 PGUID -1  -1 f b t \054 0	21 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1006 (  _int2vector PGUID -1 -1 f b t \054 0	22 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1007 (  _int4		 PGUID -1  -1 f b t \054 0	23 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1008 (  _regproc	 PGUID -1  -1 f b t \054 0	24 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1009 (  _text		 PGUID -1  -1 f b t \054 0	25 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1028 (  _oid		 PGUID -1  -1 f b t \054 0	26 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1010 (  _tid		 PGUID -1  -1 f b t \054 0	27 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1011 (  _xid		 PGUID -1  -1 f b t \054 0	28 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1012 (  _cid		 PGUID -1  -1 f b t \054 0	29 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1013 (  _oidvector PGUID -1  -1 f b t \054 0	30 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1014 (  _bpchar	 PGUID -1  -1 f b t \054 0 1042 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1015 (  _varchar	 PGUID -1  -1 f b t \054 0 1043 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1016 (  _int8		 PGUID -1  -1 f b t \054 0	20 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1017 (  _point	 PGUID -1  -1 f b t \054 0 600 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1018 (  _lseg		 PGUID -1  -1 f b t \054 0 601 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1019 (  _path		 PGUID -1  -1 f b t \054 0 602 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1020 (  _box		 PGUID -1  -1 f b t \073 0 603 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1021 (  _float4	 PGUID -1  -1 f b t \054 0 700 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1022 (  _float8	 PGUID -1  -1 f b t \054 0 701 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1023 (  _abstime	 PGUID -1  -1 f b t \054 0 702 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1024 (  _reltime	 PGUID -1  -1 f b t \054 0 703 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1025 (  _tinterval PGUID -1  -1 f b t \054 0 704 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1027 (  _polygon	 PGUID -1  -1 f b t \054 0 604 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
  /*
   *	Note: the size of aclitem needs to match sizeof(AclItem) in acl.h.
   *	Thanks to some padding, this will be 8 on all platforms.
   *	We also have an Assert to make sure.
   */
  #define ACLITEMSIZE 8
! DATA(insert OID = 1033 (  aclitem	 PGUID 8   -1 f b t \054 0 0 aclitemin aclitemout aclitemin aclitemout i p f -1 0 0 _null_ _null_ ));
  DESCR("access control list");
! DATA(insert OID = 1034 (  _aclitem	 PGUID -1 -1 f b t \054 0 1033 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1040 (  _macaddr	 PGUID -1 -1 f b t \054 0  829 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1041 (  _inet    PGUID -1 -1 f b t \054 0  869 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 651  (  _cidr    PGUID -1 -1 f b t \054 0  650 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1042 ( bpchar		 PGUID -1  -1 f b t \054 0	0 bpcharin bpcharout bpcharin bpcharout i x f -1 0 0 _null_ _null_ ));
  DESCR("char(length), blank-padded string, fixed storage length");
  #define BPCHAROID		1042
! DATA(insert OID = 1043 ( varchar	 PGUID -1  -1 f b t \054 0	0 varcharin varcharout varcharin varcharout i x f -1 0 0 _null_ _null_ ));
  DESCR("varchar(length), non-blank-padded string, variable storage length");
  #define VARCHAROID		1043
  
! DATA(insert OID = 1082 ( date		 PGUID	4  10 t b t \054 0	0 date_in date_out date_in date_out i p f -1 0 0 _null_ _null_ ));
  DESCR("ANSI SQL date");
  #define DATEOID			1082
! DATA(insert OID = 1083 ( time		 PGUID	8  16 f b t \054 0	0 time_in time_out time_in time_out d p f -1 0 0 _null_ _null_ ));
  DESCR("hh:mm:ss, ANSI SQL time");
  #define TIMEOID			1083
  
  /* OIDS 1100 - 1199 */
! DATA(insert OID = 1114 ( timestamp	 PGUID	8  47 f b t \054 0	0 timestamp_in timestamp_out timestamp_in timestamp_out d p f -1 0 0 _null_ _null_ ));
  DESCR("date and time");
  #define TIMESTAMPOID	1114
! DATA(insert OID = 1115 ( _timestamp  PGUID	-1 -1 f b t \054 0	1184 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1182 ( _date		 PGUID	-1 -1 f b t \054 0	1082 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1183 ( _time		 PGUID	-1 -1 f b t \054 0	1083 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1184 ( timestamptz PGUID	8  47 f b t \054 0	0 timestamptz_in timestamptz_out timestamptz_in timestamptz_out d p f -1 0 0 _null_ _null_ ));
  DESCR("date and time with time zone");
  #define TIMESTAMPTZOID	1184
! DATA(insert OID = 1185 ( _timestamptz PGUID -1 -1 f b t \054 0	1184 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1186 ( interval	 PGUID 12  47 f b t \054 0	0 interval_in interval_out interval_in interval_out d p f -1 0 0 _null_ _null_ ));
  DESCR("@ <number> <units>, time interval");
  #define INTERVALOID		1186
! DATA(insert OID = 1187 ( _interval	 PGUID	-1 -1 f b t \054 0	1186 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
  
  /* OIDS 1200 - 1299 */
! DATA(insert OID = 1231 (  _numeric	 PGUID -1  -1 f b t \054 0	1700 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1266 ( timetz		 PGUID 12  22 f b t \054 0	0 timetz_in timetz_out timetz_in timetz_out d p f -1 0 0 _null_ _null_ ));
  DESCR("hh:mm:ss, ANSI SQL time");
  #define TIMETZOID		1266
! DATA(insert OID = 1270 ( _timetz	 PGUID	-1 -1 f b t \054 0	1266 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
  
  /* OIDS 1500 - 1599 */
! DATA(insert OID = 1560 ( bit		 PGUID -1  -1 f b t \054 0	0 bit_in bit_out bit_in bit_out i x f -1 0 0 _null_ _null_ ));
  DESCR("fixed-length bit string");
  #define BITOID	 1560
! DATA(insert OID = 1561 ( _bit		 PGUID	-1 -1 f b t \054 0	1560 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1562 ( varbit		 PGUID -1  -1 f b t \054 0	0 varbit_in varbit_out varbit_in varbit_out i x f -1 0 0 _null_ _null_ ));
  DESCR("variable-length bit string");
  #define VARBITOID	  1562
! DATA(insert OID = 1563 ( _varbit	 PGUID	-1 -1 f b t \054 0	1562 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
  
  /* OIDS 1600 - 1699 */
  
  /* OIDS 1700 - 1799 */
! DATA(insert OID = 1700 ( numeric	   PGUID -1  -1 f b t \054 0  0 numeric_in numeric_out numeric_in numeric_out i m f -1 0 0 _null_ _null_ ));
  DESCR("numeric(precision, decimal), arbitrary precision number");
  #define NUMERICOID		1700
  
  /* OID 1790 */
! DATA(insert OID = 1790 ( refcursor	   PGUID -1  -1 f b t \054 0  0 textin textout textin textout i x f -1 0 0 _null_ _null_ ));
  DESCR("reference cursor (portal name)");
  #define REFCURSOROID	1790
  
***************
*** 447,452 ****
--- 490,496 ----
   */
  extern Oid	TypeGet(char *typeName, bool *defined);
  extern Oid	TypeShellMake(char *typeName);
+ 
  extern Oid TypeCreate(char *typeName,
  		   Oid assignedTypeOid,
  		   Oid relationOid,
***************
*** 459,468 ****
  		   char *receiveProcedure,
  		   char *sendProcedure,
  		   char *elementTypeName,
  		   char *defaultTypeValue,
  		   bool passedByValue,
  		   char alignment,
! 		   char storage);
  extern void TypeRename(const char *oldTypeName, const char *newTypeName);
  extern char *makeArrayTypeName(char *typeName);
  
--- 503,519 ----
  		   char *receiveProcedure,
  		   char *sendProcedure,
  		   char *elementTypeName,
+ 		   char *baseTypeName,
  		   char *defaultTypeValue,
+ 		   char *defaultTypeBin,
  		   bool passedByValue,
  		   char alignment,
! 		   char storage,
! 		   int32 typeMod,
! 		   int32 typNDims,
! 		   bool typeNotNull);
! 
! 
  extern void TypeRename(const char *oldTypeName, const char *newTypeName);
  extern char *makeArrayTypeName(char *typeName);
  
Index: src/include/commands/defrem.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/commands/defrem.h,v
retrieving revision 1.28
diff -c -r1.28 defrem.h
*** src/include/commands/defrem.h	2001/11/05 17:46:33	1.28
--- src/include/commands/defrem.h	2002/02/26 02:57:14
***************
*** 39,48 ****
--- 39,50 ----
  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.97
diff -c -r1.97 nodes.h
*** src/include/nodes/nodes.h	2002/02/18 23:11:41	1.97
--- src/include/nodes/nodes.h	2002/02/26 02:57:23
***************
*** 172,177 ****
--- 172,178 ----
  	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.152
diff -c -r1.152 parsenodes.h
*** src/include/nodes/parsenodes.h	2002/02/18 23:11:41	1.152
--- src/include/nodes/parsenodes.h	2002/02/26 02:57:27
***************
*** 457,468 ****
--- 457,470 ----
  #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;
  
  /* ----------------------
***************
*** 671,676 ****
--- 673,679 ----
  	char	   *filename;		/* file to load */
  } LoadStmt;
  
+ 
  /* ----------------------
   *		Createdb Statement
   * ----------------------
***************
*** 1255,1260 ****
--- 1258,1279 ----
  	Node	   *arg;			/* a (Value *) or a (TypeName *) */
  } DefElem;
  
+ 
+ /****************************************************************************
+  *	Nodes for a Domain Creation tree
+  ****************************************************************************/
+ /* ----------------------
+  *		CreateDomain Statement
+  * ----------------------
+  * Down here as it required TypeName to be defined first.
+  */
+ typedef struct CreateDomainStmt
+ {
+ 	NodeTag		type;
+ 	char	   *domainname;			/* name of domain to create */
+ 	TypeName   *typename;			/* the typecast */
+ 	List	   *constraints;		/* constraints (list of Constraint nodes) */
+ } CreateDomainStmt;
  
  /****************************************************************************
   *	Nodes for a Query tree
Index: src/include/parser/parse_coerce.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/parser/parse_coerce.h,v
retrieving revision 1.37
diff -c -r1.37 parse_coerce.h
*** src/include/parser/parse_coerce.h	2001/11/05 17:46:34	1.37
--- src/include/parser/parse_coerce.h	2002/02/26 02:57:27
***************
*** 81,85 ****
--- 81,86 ----
  extern Node *coerce_to_common_type(ParseState *pstate, Node *node,
  					  Oid targetTypeId,
  					  const char *context);
+ extern Oid getBaseType(Oid inType);
  
  #endif   /* PARSE_COERCE_H */
Index: src/include/utils/lsyscache.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/utils/lsyscache.h,v
retrieving revision 1.39
diff -c -r1.39 lsyscache.h
*** src/include/utils/lsyscache.h	2001/11/05 17:46:36	1.39
--- src/include/utils/lsyscache.h	2002/02/26 02:57:27
***************
*** 42,48 ****
  extern bool get_typbyval(Oid typid);
  extern void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval);
  extern char get_typstorage(Oid typid);
! extern bool get_typdefault(Oid typid, Datum *defaultValue);
  extern int32 get_typavgwidth(Oid typid, int32 typmod);
  extern int32 get_attavgwidth(Oid relid, AttrNumber attnum);
  extern bool get_attstatsslot(HeapTuple statstuple,
--- 42,48 ----
  extern bool get_typbyval(Oid typid);
  extern void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval);
  extern char get_typstorage(Oid typid);
! extern Node *get_typdefault(Oid typid, int32 atttypmod);
  extern int32 get_typavgwidth(Oid typid, int32 typmod);
  extern int32 get_attavgwidth(Oid relid, AttrNumber attnum);
  extern bool get_attstatsslot(HeapTuple statstuple,
