diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index b92bf4bba166bfcae45ebfa6e5cac9c2914f3655..901090c70aca49f97db348352835b57039a2346d 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.18 2002/07/01 15:27:46 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.19 2002/07/06 20:16:35 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -48,7 +48,6 @@
 #include "utils/relcache.h"
 
 
-static List *MergeDomainAttributes(List *schema);
 static List *MergeAttributes(List *schema, List *supers, bool istemp,
 				List **supOids, List **supconstr, bool *supHasOids);
 static bool change_varattnos_of_a_node(Node *node, const AttrNumber *newattno);
@@ -122,13 +121,6 @@ DefineRelation(CreateStmt *stmt, char relkind)
 			aclcheck_error(aclresult, get_namespace_name(namespaceId));
 	}
 
-	/*
-	 * Merge domain attributes into the known columns before processing table
-	 * inheritance.  Otherwise we risk adding double constraints to a
-	 * domain-type column that's inherited.
-	 */
-	schema = MergeDomainAttributes(schema);
-
 	/*
 	 * Look up inheritance ancestors and generate relation schema,
 	 * including inherited attributes.
@@ -328,49 +320,6 @@ TruncateRelation(const RangeVar *relation)
 	heap_truncate(relid);
 }
 
-
-/*
- * MergeDomainAttributes
- *      Returns a new table schema with the constraints, types, and other
- *      attributes of domains resolved for fields using a domain as
- *      their type.
- */
-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 = typenameType(coldef->typename);
-		typeTup = (Form_pg_type) GETSTRUCT(tuple);
-
-		if (typeTup->typtype == 'd')
-		{
-			/* Force the column to have the correct typmod. */
-			coldef->typename->typmod = typeTup->typtypmod;
-			/* XXX more to do here? */
-		}
-
-		/* Enforce type NOT NULL || column definition NOT NULL -> NOT NULL */
-		/* Currently only used for domains, but could be valid for all */
-		coldef->is_not_null |= typeTup->typnotnull;
-
-		ReleaseSysCache(tuple);
-	}
-
-	return schema;
-}
-
 /*----------
  * MergeAttributes
  *		Returns new schema given initial schema and superclasses.
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c
index 789251b70e7872f673c065ab4c5029e24ca9a0b5..6bb2b5fa9428aca3cb3cd3f66bc184dc1ee34418 100644
--- a/src/backend/executor/execQual.c
+++ b/src/backend/executor/execQual.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.96 2002/07/04 16:44:08 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.97 2002/07/06 20:16:35 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -66,6 +66,8 @@ static Datum ExecEvalNullTest(NullTest *ntest, ExprContext *econtext,
 				 bool *isNull, ExprDoneCond *isDone);
 static Datum ExecEvalBooleanTest(BooleanTest *btest, ExprContext *econtext,
 					bool *isNull, ExprDoneCond *isDone);
+static Datum ExecEvalConstraint(Constraint *constraint, ExprContext *econtext,
+								bool *isNull, ExprDoneCond *isDone);
 
 
 /*----------
@@ -1226,6 +1228,43 @@ ExecEvalNullTest(NullTest *ntest,
 	}
 }
 
+/*
+ * ExecEvalConstraint
+ *
+ * Test the constraint against the data provided.  If the data fits
+ * within the constraint specifications, pass it through (return the
+ * datum) otherwise throw an error.
+ */
+static Datum
+ExecEvalConstraint(Constraint *constraint, ExprContext *econtext,
+				   bool *isNull, ExprDoneCond *isDone)
+{
+	Datum		result;
+
+	result = ExecEvalExpr(constraint->raw_expr, econtext, isNull, isDone);
+
+	/* Test for the constraint type */
+	switch(constraint->contype)
+	{
+		case CONSTR_NOTNULL:
+			if (*isNull)
+			{
+				elog(ERROR, "Domain %s does not allow NULL values", constraint->name);
+			}
+			break;
+		case CONSTR_CHECK:
+
+				elog(ERROR, "ExecEvalConstraint: Domain CHECK Constraints not yet implemented");
+			break;
+		default:
+			elog(ERROR, "ExecEvalConstraint: Constraint type unknown");
+			break;
+	}
+
+	/* If all has gone well (constraint did not fail) return the datum */
+	return result;
+}
+
 /* ----------------------------------------------------------------
  *		ExecEvalBooleanTest
  *
@@ -1473,6 +1512,12 @@ ExecEvalExpr(Node *expression,
 									isNull,
 									isDone);
 			break;
+		case T_Constraint:
+			retDatum = ExecEvalConstraint((Constraint *) expression,
+										 econtext,
+										 isNull,
+										 isDone);
+			break;
 		case T_CaseExpr:
 			retDatum = ExecEvalCase((CaseExpr *) expression,
 									econtext,
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index 5b0ae52f7c6436eafbd653a87e87ce553dab7ffb..889a10b9ee3b28d9d1d983c19b1a8d5934ab8758 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.102 2002/07/04 15:23:58 thomas Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.103 2002/07/06 20:16:35 momjian Exp $
  *
  * HISTORY
  *	  AUTHOR			DATE			MAJOR EVENT
@@ -1882,6 +1882,8 @@ expression_tree_walker(Node *node,
 					return true;
 			}
 			break;
+		case T_Constraint:
+			return walker(((Constraint *) node)->raw_expr, context);
 		case T_NullTest:
 			return walker(((NullTest *) node)->arg, context);
 		case T_BooleanTest:
@@ -2236,6 +2238,20 @@ expression_tree_mutator(Node *node,
 				return (Node *) newnode;
 			}
 			break;
+		case T_Constraint:
+			{
+				/*
+				 * Used for confirming domains.  Only needed fields
+				 * within the executor are the name, raw expression
+				 * and constraint type.
+				 */
+				Constraint *con = (Constraint *) node;
+				Constraint *newnode;
+
+				FLATCOPY(newnode, con, Constraint);
+				MUTATE(newnode->raw_expr, con->raw_expr, Node *);
+				return (Node *) newnode;
+			}
 		case T_NullTest:
 			{
 				NullTest   *ntest = (NullTest *) node;
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 410caf72e0a9d7e0f9beba97cd52c868bc1c7a08..e8e5aeabc77da8d4634eebe22a82d53c4dfeffb1 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.336 2002/07/04 15:23:59 thomas Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.337 2002/07/06 20:16:35 momjian Exp $
  *
  * HISTORY
  *	  AUTHOR			DATE			MAJOR EVENT
@@ -6968,24 +6968,16 @@ static Node *
 makeTypeCast(Node *arg, TypeName *typename)
 {
 	/*
-	 * If arg is an A_Const, just stick the typename into the
-	 * field reserved for it --- unless there's something there already!
-	 * (We don't want to collapse x::type1::type2 into just x::type2.)
-	 * Otherwise, generate a TypeCast node.
+	 * Simply generate a TypeCast node.
+	 *
+	 * Earlier we would determine whether an A_Const would
+	 * be acceptable, however Domains require coerce_type()
+	 * to process them -- applying constraints as required. 
 	 */
-	if (IsA(arg, A_Const) &&
-		((A_Const *) arg)->typename == NULL)
-	{
-		((A_Const *) arg)->typename = typename;
-		return arg;
-	}
-	else
-	{
-		TypeCast *n = makeNode(TypeCast);
-		n->arg = arg;
-		n->typename = typename;
-		return (Node *) n;
-	}
+	TypeCast *n = makeNode(TypeCast);
+	n->arg = arg;
+	n->typename = typename;
+	return (Node *) n;
 }
 
 static Node *
diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c
index 3c441509b1de7f60a3d31116a801682b10dc85f3..b258368626a971f109be38a4abd026339d572280 100644
--- a/src/backend/parser/parse_coerce.c
+++ b/src/backend/parser/parse_coerce.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.74 2002/06/20 20:29:32 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.75 2002/07/06 20:16:36 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -33,7 +33,7 @@ static Oid	PreferredType(CATEGORY category, Oid type);
 static Node *build_func_call(Oid funcid, Oid rettype, List *args);
 static Oid	find_coercion_function(Oid targetTypeId, Oid inputTypeId,
 								   Oid secondArgType, bool isExplicit);
-
+static Node	*TypeConstraints(Node *arg, Oid typeId);
 
 /* coerce_type()
  * Convert a function argument to a different type.
@@ -48,7 +48,7 @@ coerce_type(ParseState *pstate, Node *node, Oid inputTypeId,
 		targetTypeId == InvalidOid ||
 		node == NULL)
 	{
-		/* no conversion needed */
+		/* no conversion needed, but constraints may need to be applied */
 		result = node;
 	}
 	else if (inputTypeId == UNKNOWNOID && IsA(node, Const))
@@ -72,6 +72,7 @@ coerce_type(ParseState *pstate, Node *node, Oid inputTypeId,
 		Const	   *con = (Const *) node;
 		Const	   *newcon = makeNode(Const);
 		Type		targetType = typeidType(targetTypeId);
+		Oid			baseTypeId = getBaseType(targetTypeId);
 
 		newcon->consttype = targetTypeId;
 		newcon->constlen = typeLen(targetType);
@@ -83,14 +84,16 @@ coerce_type(ParseState *pstate, Node *node, Oid inputTypeId,
 		{
 			char	   *val = DatumGetCString(DirectFunctionCall1(unknownout,
 													   con->constvalue));
-
 			newcon->constvalue = stringTypeDatum(targetType, val, atttypmod);
 			pfree(val);
 		}
 
 		ReleaseSysCache(targetType);
 
+		/* Test for domain, and apply appropriate constraints */
 		result = (Node *) newcon;
+		if (targetTypeId != baseTypeId)
+			result = (Node *) TypeConstraints(result, targetTypeId);
 	}
 	else if (IsBinaryCompatible(inputTypeId, targetTypeId))
 	{
@@ -103,8 +106,17 @@ coerce_type(ParseState *pstate, Node *node, Oid inputTypeId,
 		 * default -1 typmod, to save a possible length-coercion later?
 		 * Would work if both types have same interpretation of typmod,
 		 * which is likely but not certain.
+		 *
+		 * Domains may have value restrictions beyond the base type that
+		 * must be accounted for.
 		 */
-		result = (Node *) makeRelabelType(node, targetTypeId, -1);
+		Oid			baseTypeId = getBaseType(targetTypeId);
+		result = node;
+		if (targetTypeId != baseTypeId)
+			result = (Node *) TypeConstraints(result, targetTypeId);
+
+		result = (Node *) makeRelabelType(result, targetTypeId, -1);
+
 	}
 	else if (typeInheritsFrom(inputTypeId, targetTypeId))
 	{
@@ -125,8 +137,8 @@ coerce_type(ParseState *pstate, Node *node, Oid inputTypeId,
 		 *
 		 * For domains, we use the coercion function for the base type.
 		 */
-		Oid			baseTypeId = getBaseType(targetTypeId);
 		Oid			funcId;
+		Oid			baseTypeId = getBaseType(targetTypeId);
 
 		funcId = find_coercion_function(baseTypeId,
 										getBaseType(inputTypeId),
@@ -138,9 +150,12 @@ coerce_type(ParseState *pstate, Node *node, Oid inputTypeId,
 
 		result = build_func_call(funcId, baseTypeId, makeList1(node));
 
-		/* if domain, relabel with domain type ID */
+		/*
+		 * If domain, relabel with domain type ID and test against domain
+		 * constraints
+		 */
 		if (targetTypeId != baseTypeId)
-			result = (Node *) makeRelabelType(result, targetTypeId, -1);
+			result = (Node *) TypeConstraints(result, targetTypeId);
 
 		/*
 		 * If the input is a constant, apply the type conversion function
@@ -275,6 +290,21 @@ coerce_type_typmod(ParseState *pstate, Node *node,
 {
 	Oid			baseTypeId;
 	Oid			funcId;
+	int32		domainTypMod = NULL;
+
+	/* If given type is a domain, use base type instead */
+	baseTypeId = getBaseTypeTypeMod(targetTypeId, &domainTypMod);
+
+
+	/*
+	 * Use the domain typmod rather than what was supplied if the
+	 * domain was empty.  atttypmod will always be -1 if domains are in use.
+	 */
+	if (baseTypeId != targetTypeId)
+	{
+		Assert(atttypmod < 0);
+		atttypmod = domainTypMod;
+	}
 
 	/*
 	 * A negative typmod is assumed to mean that no coercion is wanted.
@@ -282,12 +312,8 @@ coerce_type_typmod(ParseState *pstate, Node *node,
 	if (atttypmod < 0 || atttypmod == exprTypmod(node))
 		return node;
 
-	/* If given type is a domain, use base type instead */
-	baseTypeId = getBaseType(targetTypeId);
-
 	/* Note this is always implicit coercion */
 	funcId = find_coercion_function(baseTypeId, baseTypeId, INT4OID, false);
-
 	if (OidIsValid(funcId))
 	{
 		Const	   *cons;
@@ -301,10 +327,6 @@ coerce_type_typmod(ParseState *pstate, Node *node,
 						 false);
 
 		node = build_func_call(funcId, baseTypeId, makeList2(node, cons));
-
-		/* relabel if it's domain case */
-		if (targetTypeId != baseTypeId)
-			node = (Node *) makeRelabelType(node, targetTypeId, atttypmod);
 	}
 
 	return node;
@@ -805,3 +827,58 @@ build_func_call(Oid funcid, Oid rettype, List *args)
 
 	return (Node *) expr;
 }
+
+/*
+ * Create an expression tree to enforce the constraints (if any)
+ * which should be applied by the type.
+ */
+static Node *
+TypeConstraints(Node *arg, Oid typeId)
+{
+	char   *notNull = NULL;
+
+	for (;;)
+	{
+		HeapTuple	tup;
+		Form_pg_type typTup;
+
+		tup = SearchSysCache(TYPEOID,
+							 ObjectIdGetDatum(typeId),
+							 0, 0, 0);
+		if (!HeapTupleIsValid(tup))
+			elog(ERROR, "getBaseType: failed to lookup type %u", typeId);
+		typTup = (Form_pg_type) GETSTRUCT(tup);
+
+		/* Test for NOT NULL Constraint */
+		if (typTup->typnotnull && notNull == NULL)
+			notNull = NameStr(typTup->typname);
+
+		/* TODO: Add CHECK Constraints to domains */
+
+		if (typTup->typtype != 'd')
+		{
+			/* Not a domain, so done */
+			ReleaseSysCache(tup);
+			break;
+		}
+
+		typeId = typTup->typbasetype;
+		ReleaseSysCache(tup);
+	}
+
+	/*
+	 * Only need to add one NOT NULL check regardless of how many 
+	 * domains in the tree request it.
+	 */
+	if (notNull != NULL) {
+		Constraint *r = makeNode(Constraint);
+
+		r->raw_expr = arg;
+		r->contype = CONSTR_NOTNULL;
+		r->name	= notNull; 
+
+		arg = (Node *) r;
+	}	
+
+	return arg;
+}
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index ac4a5b6e5f39cc5fe1c53594be65aa63e57683ef..d93aeb55b5d3f126c1d4c2d5154b4c4205847715 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.120 2002/07/04 15:24:01 thomas Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.121 2002/07/06 20:16:36 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -864,7 +864,7 @@ exprType(Node *expr)
 					TargetEntry *tent;
 
 					if (!qtree || !IsA(qtree, Query))
-						elog(ERROR, "Cannot get type for untransformed sublink");
+						elog(ERROR, "exprType: Cannot get type for untransformed sublink");
 					tent = (TargetEntry *) lfirst(qtree->targetList);
 					type = tent->resdom->restype;
 				}
@@ -881,6 +881,9 @@ exprType(Node *expr)
 		case T_CaseWhen:
 			type = exprType(((CaseWhen *) expr)->result);
 			break;
+		case T_Constraint:
+			type = exprType(((Constraint *) expr)->raw_expr);
+			break;
 		case T_NullTest:
 			type = BOOLOID;
 			break;
@@ -888,7 +891,7 @@ exprType(Node *expr)
 			type = BOOLOID;
 			break;
 		default:
-			elog(ERROR, "Do not know how to get type for %d node",
+			elog(ERROR, "exprType: Do not know how to get type for %d node",
 				 nodeTag(expr));
 			break;
 	}
diff --git a/src/backend/parser/parse_type.c b/src/backend/parser/parse_type.c
index 04cefb299049a15beeb52c41fa69bc090daf16d3..14510a69b1b565a7dac09239450a16ca7ade83d5 100644
--- a/src/backend/parser/parse_type.c
+++ b/src/backend/parser/parse_type.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_type.c,v 1.43 2002/06/20 20:29:33 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_type.c,v 1.44 2002/07/06 20:16:36 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -450,7 +450,7 @@ parseTypeString(const char *str, Oid *type_id, int32 *typmod)
 	List	   *raw_parsetree_list;
 	SelectStmt *stmt;
 	ResTarget  *restarget;
-	A_Const    *aconst;
+	TypeCast   *typecast;   
 	TypeName   *typename;
 
 	initStringInfo(&buf);
@@ -463,7 +463,7 @@ parseTypeString(const char *str, Oid *type_id, int32 *typmod)
 	 * paranoia is justified since the string might contain anything.
 	 */
 	if (length(raw_parsetree_list) != 1)
-		elog(ERROR, "Invalid type name '%s'", str);
+		elog(ERROR, "parseTypeString: Invalid type name '%s'", str);
 	stmt = (SelectStmt *) lfirst(raw_parsetree_list);
 	if (stmt == NULL ||
 		!IsA(stmt, SelectStmt) ||
@@ -479,25 +479,23 @@ parseTypeString(const char *str, Oid *type_id, int32 *typmod)
 		stmt->limitCount != NULL ||
 		stmt->forUpdate != NIL ||
 		stmt->op != SETOP_NONE)
-		elog(ERROR, "Invalid type name '%s'", str);
+		elog(ERROR, "parseTypeString: Invalid type name '%s'", str);
 	if (length(stmt->targetList) != 1)
-		elog(ERROR, "Invalid type name '%s'", str);
+		elog(ERROR, "parseTypeString: Invalid type name '%s'", str);
 	restarget = (ResTarget *) lfirst(stmt->targetList);
 	if (restarget == NULL ||
 		!IsA(restarget, ResTarget) ||
 		restarget->name != NULL ||
 		restarget->indirection != NIL)
-		elog(ERROR, "Invalid type name '%s'", str);
-	aconst = (A_Const *) restarget->val;
-	if (aconst == NULL ||
-		!IsA(aconst, A_Const) ||
-		aconst->val.type != T_Null)
-		elog(ERROR, "Invalid type name '%s'", str);
-	typename = aconst->typename;
+		elog(ERROR, "parseTypeString: Invalid type name '%s'", str);
+	typecast = (TypeCast *) restarget->val;
+	if (typecast == NULL ||
+		!IsA(typecast->arg, A_Const))
+		elog(ERROR, "parseTypeString: Invalid type name '%s'", str);
+	typename = typecast->typename;
 	if (typename == NULL ||
 		!IsA(typename, TypeName))
-		elog(ERROR, "Invalid type name '%s'", str);
-
+		elog(ERROR, "parseTypeString: Invalid type name '%s'", str);
 	*type_id = typenameTypeId(typename);
 	*typmod = typename->typmod;
 
diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c
index 233910a85c33160bf34282490902a81c5dcfea4e..5063225afce29cd00eaad96f08248726d850d54c 100644
--- a/src/backend/utils/cache/lsyscache.c
+++ b/src/backend/utils/cache/lsyscache.c
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.74 2002/06/20 20:29:39 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.75 2002/07/06 20:16:36 momjian Exp $
  *
  * NOTES
  *	  Eventually, the index information should go through here, too.
@@ -1057,6 +1057,43 @@ getBaseType(Oid typid)
 	return typid;
 }
 
+/*
+ * getBaseTypeTypeMod
+ *		If the given type is a domain, return its base type;
+ *		otherwise return the type's own OID.
+ */
+Oid
+getBaseTypeTypeMod(Oid typid, int32 *typmod)
+{
+	/*
+	 * We loop to find the bottom base type in a stack of domains.
+	 */
+	for (;;)
+	{
+		HeapTuple	tup;
+		Form_pg_type typTup;
+
+		tup = SearchSysCache(TYPEOID,
+							 ObjectIdGetDatum(typid),
+							 0, 0, 0);
+		if (!HeapTupleIsValid(tup))
+			elog(ERROR, "getBaseType: failed to lookup type %u", typid);
+		typTup = (Form_pg_type) GETSTRUCT(tup);
+		if (typTup->typtype != 'd')
+		{
+			/* Not a domain, so done */
+			ReleaseSysCache(tup);
+			break;
+		}
+
+		typid = typTup->typbasetype;
+		*typmod = typTup->typtypmod;
+		ReleaseSysCache(tup);
+	}
+
+	return typid;
+}
+
 /*
  * get_typavgwidth
  *
diff --git a/src/include/utils/lsyscache.h b/src/include/utils/lsyscache.h
index 32d5dc1744e5730c48830e6822b64fea24ef8a0f..ca361ebc2cca1339d9e7a5d410e9b1848078fbfd 100644
--- a/src/include/utils/lsyscache.h
+++ b/src/include/utils/lsyscache.h
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: lsyscache.h,v 1.53 2002/06/20 20:29:53 momjian Exp $
+ * $Id: lsyscache.h,v 1.54 2002/07/06 20:16:36 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -52,6 +52,7 @@ extern void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval);
 extern char get_typstorage(Oid typid);
 extern Node *get_typdefault(Oid typid);
 extern Oid getBaseType(Oid typid);
+extern Oid getBaseTypeTypeMod(Oid typid, int32 *typmod);
 extern int32 get_typavgwidth(Oid typid, int32 typmod);
 extern int32 get_attavgwidth(Oid relid, AttrNumber attnum);
 extern bool get_attstatsslot(HeapTuple statstuple,
diff --git a/src/test/regress/expected/domain.out b/src/test/regress/expected/domain.out
index 7127215869a3c90bb2bb081ec15827035876c5a9..078d2386bf944fe07be7cb2aeb3b8b71af8a2204 100644
--- a/src/test/regress/expected/domain.out
+++ b/src/test/regress/expected/domain.out
@@ -11,6 +11,15 @@ create domain domainvarchar varchar(5);
 create domain domainnumeric numeric(8,2);
 create domain domainint4 int4;
 create domain domaintext text;
+-- Test coercions
+SELECT cast('123456' as domainvarchar); -- fail
+ERROR:  value too long for type character varying(5)
+SELECT cast('12345' as domainvarchar); -- pass
+ domainvarchar 
+---------------
+ 12345
+(1 row)
+
 -- Test tables using domains
 create table basictest
            ( testint4 domainint4
@@ -80,7 +89,7 @@ drop table domarrtest;
 drop domain domainint4arr restrict;
 drop domain domaintextarr restrict;
 create domain dnotnull varchar(15) NOT NULL;
-create domain dnull    varchar(15) NULL;
+create domain dnull    varchar(15);
 create table nulltest
            ( col1 dnotnull
            , col2 dnotnull NULL  -- NOT NULL in the domain cannot be overridden
@@ -88,12 +97,12 @@ create table nulltest
            , col4 dnull
            );
 INSERT INTO nulltest DEFAULT VALUES;
-ERROR:  ExecAppend: Fail to add null value in not null attribute col1
+ERROR:  ExecAppend: Fail to add null value in not null attribute col3
 INSERT INTO nulltest values ('a', 'b', 'c', 'd');  -- Good
 INSERT INTO nulltest values (NULL, 'b', 'c', 'd');
-ERROR:  ExecAppend: Fail to add null value in not null attribute col1
+ERROR:  Domain dnotnull does not allow NULL values
 INSERT INTO nulltest values ('a', NULL, 'c', 'd');
-ERROR:  ExecAppend: Fail to add null value in not null attribute col2
+ERROR:  Domain dnotnull does not allow NULL values
 INSERT INTO nulltest values ('a', 'b', NULL, 'd');
 ERROR:  ExecAppend: Fail to add null value in not null attribute col3
 INSERT INTO nulltest values ('a', 'b', 'c', NULL); -- Good
@@ -104,6 +113,20 @@ select * from nulltest;
  a    | b    | c    | 
 (2 rows)
 
+-- Test out coerced (casted) constraints
+SELECT cast('1' as dnotnull);
+ dnotnull 
+----------
+ 1
+(1 row)
+
+SELECT cast(NULL as dnotnull); -- fail
+ERROR:  Domain dnotnull does not allow NULL values
+SELECT cast(cast(NULL as dnull) as dnotnull); -- fail
+ERROR:  Domain dnotnull does not allow NULL values
+SELECT cast(col4 as dnotnull) from nulltest; -- fail
+ERROR:  Domain dnotnull does not allow NULL values
+-- cleanup
 drop table nulltest;
 drop domain dnotnull restrict;
 drop domain dnull restrict;
diff --git a/src/test/regress/sql/domain.sql b/src/test/regress/sql/domain.sql
index cecb876c3863cd78cfe9432bcce14b924e31797d..055c377decb872883f2ce60c19be3864b07d7afa 100644
--- a/src/test/regress/sql/domain.sql
+++ b/src/test/regress/sql/domain.sql
@@ -17,6 +17,9 @@ create domain domainnumeric numeric(8,2);
 create domain domainint4 int4;
 create domain domaintext text;
 
+-- Test coercions
+SELECT cast('123456' as domainvarchar); -- fail
+SELECT cast('12345' as domainvarchar); -- pass
 
 -- Test tables using domains
 create table basictest
@@ -65,7 +68,7 @@ drop domain domaintextarr restrict;
 
 
 create domain dnotnull varchar(15) NOT NULL;
-create domain dnull    varchar(15) NULL;
+create domain dnull    varchar(15);
 
 create table nulltest
            ( col1 dnotnull
@@ -81,6 +84,13 @@ INSERT INTO nulltest values ('a', 'b', NULL, 'd');
 INSERT INTO nulltest values ('a', 'b', 'c', NULL); -- Good
 select * from nulltest;
 
+-- Test out coerced (casted) constraints
+SELECT cast('1' as dnotnull);
+SELECT cast(NULL as dnotnull); -- fail
+SELECT cast(cast(NULL as dnull) as dnotnull); -- fail
+SELECT cast(col4 as dnotnull) from nulltest; -- fail
+
+-- cleanup
 drop table nulltest;
 drop domain dnotnull restrict;
 drop domain dnull restrict;