diff --git a/src/backend/rewrite/rewriteDefine.c b/src/backend/rewrite/rewriteDefine.c
index 50ecf7e884c1dbba7f4110d5fe16d2b2027c39a5..660d06934606aabf314aaf1a87413ff38871b64e 100644
--- a/src/backend/rewrite/rewriteDefine.c
+++ b/src/backend/rewrite/rewriteDefine.c
@@ -633,6 +633,7 @@ checkRuleResultList(List *targetList, TupleDesc resultDesc, bool isSelect,
 	foreach(tllist, targetList)
 	{
 		TargetEntry *tle = (TargetEntry *) lfirst(tllist);
+		Oid			tletypid;
 		int32		tletypmod;
 		Form_pg_attribute attr;
 		char	   *attname;
@@ -664,19 +665,32 @@ checkRuleResultList(List *targetList, TupleDesc resultDesc, bool isSelect,
 					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 					 errmsg("cannot convert relation containing dropped columns to view")));
 
+		/* Check name match if required; no need for two error texts here */
 		if (requireColumnNameMatch && strcmp(tle->resname, attname) != 0)
 			ereport(ERROR,
 					(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
-					 errmsg("SELECT rule's target entry %d has different column name from \"%s\"", i, attname)));
-
-		if (attr->atttypid != exprType((Node *) tle->expr))
+					 errmsg("SELECT rule's target entry %d has different column name from column \"%s\"",
+							i, attname),
+					 errdetail("SELECT target entry is named \"%s\".",
+							   tle->resname)));
+
+		/* Check type match. */
+		tletypid = exprType((Node *) tle->expr);
+		if (attr->atttypid != tletypid)
 			ereport(ERROR,
 					(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
 					 isSelect ?
 					 errmsg("SELECT rule's target entry %d has different type from column \"%s\"",
 							i, attname) :
 					 errmsg("RETURNING list's entry %d has different type from column \"%s\"",
-							i, attname)));
+							i, attname),
+					 isSelect ?
+					 errdetail("SELECT target entry has type %s, but column has type %s.",
+							   format_type_be(tletypid),
+							   format_type_be(attr->atttypid)) :
+					 errdetail("RETURNING list entry has type %s, but column has type %s.",
+							   format_type_be(tletypid),
+							   format_type_be(attr->atttypid))));
 
 		/*
 		 * Allow typmods to be different only if one of them is -1, ie,
@@ -693,7 +707,16 @@ checkRuleResultList(List *targetList, TupleDesc resultDesc, bool isSelect,
 					 errmsg("SELECT rule's target entry %d has different size from column \"%s\"",
 							i, attname) :
 					 errmsg("RETURNING list's entry %d has different size from column \"%s\"",
-							i, attname)));
+							i, attname),
+					 isSelect ?
+					 errdetail("SELECT target entry has type %s, but column has type %s.",
+							   format_type_with_typemod(tletypid, tletypmod),
+							   format_type_with_typemod(attr->atttypid,
+														attr->atttypmod)) :
+					 errdetail("RETURNING list entry has type %s, but column has type %s.",
+							   format_type_with_typemod(tletypid, tletypmod),
+							   format_type_with_typemod(attr->atttypid,
+														attr->atttypmod))));
 	}
 
 	if (i != resultDesc->natts)