diff --git a/doc/src/sgml/ref/create_type.sgml b/doc/src/sgml/ref/create_type.sgml
index 69899d84f53d7b94ab45db3fa04077837d256433..4f002b65194974bbb4ee7e776ea937b0b5cf3e69 100644
--- a/doc/src/sgml/ref/create_type.sgml
+++ b/doc/src/sgml/ref/create_type.sgml
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/create_type.sgml,v 1.55 2005/05/01 18:56:17 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/create_type.sgml,v 1.56 2005/07/10 21:13:57 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -125,12 +125,13 @@ CREATE TYPE <replaceable class="parameter">name</replaceable> (
    function should perform adequate checking to ensure that the value is
    valid.
    The receive function may be declared as taking one argument of type
-   <type>internal</type>, or two arguments of types <type>internal</type>
-   and <type>oid</type>.  It must return a value of the data type itself.
-   (The first argument is a pointer to a <type>StringInfo</type> buffer
-   holding the received byte string; the optional second argument is the
-   element type OID in case this is an array type, or the type's own OID for a
-   composite type.)  Similarly, the optional
+   <type>internal</type>, or as taking three arguments of types
+   <type>internal</type>, <type>oid</type>, <type>integer</type>.
+   The first argument is a pointer to a <type>StringInfo</type> buffer
+   holding the received byte string; the optional arguments are the
+   same as for the text input function.
+   The receive function must return a value of the data type itself.
+   Similarly, the optional
    <replaceable class="parameter">send_function</replaceable> converts
    from the internal representation to the external binary representation.
    If this function is not supplied, the type cannot participate in binary
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 10e68684b8e6e62f3e141b6a05da72f4eb8e1637..d25189d0ac34174ef23f75a2cfa60e6eb7cd11cc 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.246 2005/06/28 05:08:53 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.247 2005/07/10 21:13:58 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -144,7 +144,7 @@ static char *CopyReadAttributeCSV(const char *delim, const char *null_print,
 					 char *quote, char *escape,
 					 CopyReadResult *result, bool *isnull);
 static Datum CopyReadBinaryAttribute(int column_no, FmgrInfo *flinfo,
-						Oid typioparam, bool *isnull);
+						Oid typioparam, int32 typmod, bool *isnull);
 static void CopyAttributeOut(char *string, char *delim);
 static void CopyAttributeOutCSV(char *string, char *delim, char *quote,
 					char *escape, bool force_quote);
@@ -1843,8 +1843,9 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
 				copy_attname = "oid";
 				loaded_oid =
 					DatumGetObjectId(CopyReadBinaryAttribute(0,
-														&oid_in_function,
-														  oid_typioparam,
+															 &oid_in_function,
+															 oid_typioparam,
+															 -1,
 															 &isnull));
 				if (isnull || loaded_oid == InvalidOid)
 					ereport(ERROR,
@@ -1864,6 +1865,7 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
 				values[m] = CopyReadBinaryAttribute(i,
 													&in_functions[m],
 													typioparams[m],
+													attr[m]->atttypmod,
 													&isnull);
 				nulls[m] = isnull ? 'n' : ' ';
 				copy_attname = NULL;
@@ -2556,7 +2558,8 @@ CopyReadAttributeCSV(const char *delim, const char *null_print, char *quote,
  * Read a binary attribute
  */
 static Datum
-CopyReadBinaryAttribute(int column_no, FmgrInfo *flinfo, Oid typioparam,
+CopyReadBinaryAttribute(int column_no, FmgrInfo *flinfo,
+						Oid typioparam, int32 typmod,
 						bool *isnull)
 {
 	int32		fld_size;
@@ -2594,9 +2597,10 @@ CopyReadBinaryAttribute(int column_no, FmgrInfo *flinfo, Oid typioparam,
 	attribute_buf.data[fld_size] = '\0';
 
 	/* Call the column type's binary input converter */
-	result = FunctionCall2(flinfo,
+	result = FunctionCall3(flinfo,
 						   PointerGetDatum(&attribute_buf),
-						   ObjectIdGetDatum(typioparam));
+						   ObjectIdGetDatum(typioparam),
+						   Int32GetDatum(typmod));
 
 	/* Trouble if it didn't eat the whole buffer */
 	if (attribute_buf.cursor != attribute_buf.len)
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index e5f2a2f762bc7281827c5b51c58d023bd3752548..7406e15376abd7d76b4ff8e3e37df93d974a4d4e 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.74 2005/07/07 20:39:58 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.75 2005/07/10 21:13:58 tgl Exp $
  *
  * DESCRIPTION
  *	  The "DefineFoo" routines take the parse tree and pick out the
@@ -859,7 +859,7 @@ findTypeInputFunction(List *procname, Oid typeOid)
 
 	/*
 	 * Input functions can take a single argument of type CSTRING, or
-	 * three arguments (string, element OID, typmod).
+	 * three arguments (string, typioparam OID, typmod).
 	 *
 	 * For backwards compatibility we allow OPAQUE in place of CSTRING; if we
 	 * see this, we issue a warning and fix up the pg_proc entry.
@@ -973,12 +973,12 @@ findTypeOutputFunction(List *procname, Oid typeOid)
 static Oid
 findTypeReceiveFunction(List *procname, Oid typeOid)
 {
-	Oid			argList[2];
+	Oid			argList[3];
 	Oid			procOid;
 
 	/*
 	 * Receive functions can take a single argument of type INTERNAL, or
-	 * two arguments (internal, oid).
+	 * three arguments (internal, typioparam OID, typmod).
 	 */
 	argList[0] = INTERNALOID;
 
@@ -987,8 +987,9 @@ findTypeReceiveFunction(List *procname, Oid typeOid)
 		return procOid;
 
 	argList[1] = OIDOID;
+	argList[2] = INT4OID;
 
-	procOid = LookupFuncName(procname, 2, argList, true);
+	procOid = LookupFuncName(procname, 3, argList, true);
 	if (OidIsValid(procOid))
 		return procOid;
 
diff --git a/src/backend/tcop/fastpath.c b/src/backend/tcop/fastpath.c
index bd9b490378592d113fcc90991b31d61aecd8727c..a870f2c9c883c59a6efa940b11f8292259f8b277 100644
--- a/src/backend/tcop/fastpath.c
+++ b/src/backend/tcop/fastpath.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/tcop/fastpath.c,v 1.80 2005/05/01 18:56:18 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/tcop/fastpath.c,v 1.81 2005/07/10 21:13:58 tgl Exp $
  *
  * NOTES
  *	  This cruft is the server side of PQfn.
@@ -493,9 +493,10 @@ parse_fcall_arguments(StringInfo msgBuf, struct fp_info * fip,
 			/* Call the argument type's binary input converter */
 			getTypeBinaryInputInfo(fip->argtypes[i], &typreceive, &typioparam);
 
-			fcinfo->arg[i] = OidFunctionCall2(typreceive,
+			fcinfo->arg[i] = OidFunctionCall3(typreceive,
 											  PointerGetDatum(&abuf),
-										   ObjectIdGetDatum(typioparam));
+											  ObjectIdGetDatum(typioparam),
+											  Int32GetDatum(-1));
 
 			/* Trouble if it didn't eat the whole buffer */
 			if (abuf.cursor != abuf.len)
@@ -579,9 +580,10 @@ parse_fcall_arguments_20(StringInfo msgBuf, struct fp_info * fip,
 		/* Call the argument type's binary input converter */
 		getTypeBinaryInputInfo(fip->argtypes[i], &typreceive, &typioparam);
 
-		fcinfo->arg[i] = OidFunctionCall2(typreceive,
+		fcinfo->arg[i] = OidFunctionCall3(typreceive,
 										  PointerGetDatum(&abuf),
-										  ObjectIdGetDatum(typioparam));
+										  ObjectIdGetDatum(typioparam),
+										  Int32GetDatum(-1));
 
 		/* Trouble if it didn't eat the whole buffer */
 		if (abuf.cursor != abuf.len)
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6973e9d3b3cb48fd566ead7ecbb23425b04de60c..038a482239f0c4a4dad63da2b60b7ee2bcd6bbb7 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.452 2005/07/04 04:51:49 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.453 2005/07/10 21:13:58 tgl Exp $
  *
  * NOTES
  *	  this is the "main" module of the postgres backend and
@@ -1571,9 +1571,10 @@ exec_bind_message(StringInfo input_message)
 						getTypeBinaryInputInfo(ptype, &typreceive, &typioparam);
 
 						params[i].value =
-							OidFunctionCall2(typreceive,
+							OidFunctionCall3(typreceive,
 											 PointerGetDatum(&pbuf),
-										   ObjectIdGetDatum(typioparam));
+											 ObjectIdGetDatum(typioparam),
+											 Int32GetDatum(-1));
 
 						/* Trouble if it didn't eat the whole buffer */
 						if (pbuf.cursor != pbuf.len)
diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c
index 794b95e22975d2be4b786789348ffcf1a0f8f76a..07edd7014da341c0233046af9342164624fc573b 100644
--- a/src/backend/utils/adt/arrayfuncs.c
+++ b/src/backend/utils/adt/arrayfuncs.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.120 2005/05/01 18:56:18 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.121 2005/07/10 21:13:58 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -81,7 +81,7 @@ static Datum *ReadArrayStr(char *arrayStr, const char *origStr,
 			 int typlen, bool typbyval, char typalign,
 			 int *nbytes);
 static Datum *ReadArrayBinary(StringInfo buf, int nitems,
-				FmgrInfo *receiveproc, Oid typioparam,
+				FmgrInfo *receiveproc, Oid typioparam, int32 typmod,
 				int typlen, bool typbyval, char typalign,
 				int *nbytes);
 static void CopyArrayEls(char *p, Datum *values, int nitems,
@@ -1121,6 +1121,8 @@ array_recv(PG_FUNCTION_ARGS)
 	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);
 	Oid			spec_element_type = PG_GETARG_OID(1);	/* type of an array
 														 * element */
+	int32		typmod = PG_GETARG_INT32(2);	/* typmod for array
+												 * elements */
 	Oid			element_type;
 	int			typlen;
 	bool		typbyval;
@@ -1215,7 +1217,8 @@ array_recv(PG_FUNCTION_ARGS)
 	typalign = my_extra->typalign;
 	typioparam = my_extra->typioparam;
 
-	dataPtr = ReadArrayBinary(buf, nitems, &my_extra->proc, typioparam,
+	dataPtr = ReadArrayBinary(buf, nitems, &my_extra->proc,
+							  typioparam, typmod,
 							  typlen, typbyval, typalign,
 							  &nbytes);
 	nbytes += ARR_OVERHEAD(ndim);
@@ -1249,6 +1252,7 @@ ReadArrayBinary(StringInfo buf,
 				int nitems,
 				FmgrInfo *receiveproc,
 				Oid typioparam,
+				int32 typmod,
 				int typlen,
 				bool typbyval,
 				char typalign,
@@ -1289,9 +1293,10 @@ ReadArrayBinary(StringInfo buf,
 		buf->data[buf->cursor] = '\0';
 
 		/* Now call the element's receiveproc */
-		values[i] = FunctionCall2(receiveproc,
+		values[i] = FunctionCall3(receiveproc,
 								  PointerGetDatum(&elem_buf),
-								  ObjectIdGetDatum(typioparam));
+								  ObjectIdGetDatum(typioparam),
+								  Int32GetDatum(typmod));
 
 		/* Trouble if it didn't eat the whole buffer */
 		if (elem_buf.cursor != itemlen)
diff --git a/src/backend/utils/adt/date.c b/src/backend/utils/adt/date.c
index abc6155594f137f242268fb8deff5d36c26da894..4f8f96075d92448683ce5a1f6c2feab61213039c 100644
--- a/src/backend/utils/adt/date.c
+++ b/src/backend/utils/adt/date.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/date.c,v 1.110 2005/06/15 00:34:08 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/date.c,v 1.111 2005/07/10 21:13:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -982,12 +982,21 @@ Datum
 time_recv(PG_FUNCTION_ARGS)
 {
 	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);
+#ifdef NOT_USED
+	Oid			typelem = PG_GETARG_OID(1);
+#endif
+	int32		typmod = PG_GETARG_INT32(2);
+	TimeADT		result;
 
 #ifdef HAVE_INT64_TIMESTAMP
-	PG_RETURN_TIMEADT((TimeADT) pq_getmsgint64(buf));
+	result = pq_getmsgint64(buf);
 #else
-	PG_RETURN_TIMEADT((TimeADT) pq_getmsgfloat8(buf));
+	result = pq_getmsgfloat8(buf);
 #endif
+
+	AdjustTimeForTypmod(&result, typmod);
+
+	PG_RETURN_TIMEADT(result);
 }
 
 /*
@@ -1774,18 +1783,24 @@ Datum
 timetz_recv(PG_FUNCTION_ARGS)
 {
 	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);
-	TimeTzADT  *time;
+#ifdef NOT_USED
+	Oid			typelem = PG_GETARG_OID(1);
+#endif
+	int32		typmod = PG_GETARG_INT32(2);
+	TimeTzADT  *result;
 
-	time = (TimeTzADT *) palloc(sizeof(TimeTzADT));
+	result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
 
 #ifdef HAVE_INT64_TIMESTAMP
-	time->time = pq_getmsgint64(buf);
+	result->time = pq_getmsgint64(buf);
 #else
-	time->time = pq_getmsgfloat8(buf);
+	result->time = pq_getmsgfloat8(buf);
 #endif
-	time->zone = pq_getmsgint(buf, sizeof(time->zone));
+	result->zone = pq_getmsgint(buf, sizeof(result->zone));
+
+	AdjustTimeForTypmod(&(result->time), typmod);
 
-	PG_RETURN_TIMETZADT_P(time);
+	PG_RETURN_TIMETZADT_P(result);
 }
 
 /*
diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c
index 8b39bb4248cc97caf4ce421b8db9d8ee180e0041..4aa631ee5778df3b4726c804e3effd27e3ca12bf 100644
--- a/src/backend/utils/adt/numeric.c
+++ b/src/backend/utils/adt/numeric.c
@@ -14,7 +14,7 @@
  * Copyright (c) 1998-2005, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/numeric.c,v 1.84 2005/06/04 14:12:50 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/numeric.c,v 1.85 2005/07/10 21:13:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -383,6 +383,10 @@ Datum
 numeric_recv(PG_FUNCTION_ARGS)
 {
 	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);
+#ifdef NOT_USED
+	Oid			typelem = PG_GETARG_OID(1);
+#endif
+	int32		typmod = PG_GETARG_INT32(2);
 	NumericVar	value;
 	Numeric		res;
 	int			len,
@@ -419,6 +423,8 @@ numeric_recv(PG_FUNCTION_ARGS)
 		value.digits[i] = d;
 	}
 
+	apply_typmod(&value, typmod);
+
 	res = make_result(&value);
 	free_var(&value);
 
diff --git a/src/backend/utils/adt/rowtypes.c b/src/backend/utils/adt/rowtypes.c
index d3a151a8ab14778f3184c21bfa6549e88c1614dc..07a5cf54eeaab3e93446104c37f5f8bee3e540cb 100644
--- a/src/backend/utils/adt/rowtypes.c
+++ b/src/backend/utils/adt/rowtypes.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/rowtypes.c,v 1.11 2005/05/01 18:56:18 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/rowtypes.c,v 1.12 2005/07/10 21:13:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -54,6 +54,9 @@ record_in(PG_FUNCTION_ARGS)
 {
 	char	   *string = PG_GETARG_CSTRING(0);
 	Oid			tupType = PG_GETARG_OID(1);
+#ifdef NOT_USED
+	int32		typmod = PG_GETARG_INT32(2);
+#endif
 	HeapTupleHeader result;
 	int32		tupTypmod;
 	TupleDesc	tupdesc;
@@ -417,6 +420,9 @@ record_recv(PG_FUNCTION_ARGS)
 {
 	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);
 	Oid			tupType = PG_GETARG_OID(1);
+#ifdef NOT_USED
+	int32		typmod = PG_GETARG_INT32(2);
+#endif
 	HeapTupleHeader result;
 	int32		tupTypmod;
 	TupleDesc	tupdesc;
@@ -560,10 +566,10 @@ record_recv(PG_FUNCTION_ARGS)
 				column_info->column_type = column_type;
 			}
 
-			values[i] = FunctionCall2(&column_info->proc,
+			values[i] = FunctionCall3(&column_info->proc,
 									  PointerGetDatum(&item_buf),
-							  ObjectIdGetDatum(column_info->typioparam));
-
+									  ObjectIdGetDatum(column_info->typioparam),
+									  Int32GetDatum(tupdesc->attrs[i]->atttypmod));
 			nulls[i] = ' ';
 
 			/* Trouble if it didn't eat the whole buffer */
diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c
index 8b64711e63548e9493bc82b5ca59a916fab1513b..0f928ef57494d7494d4c043bca20682467bb084c 100644
--- a/src/backend/utils/adt/timestamp.c
+++ b/src/backend/utils/adt/timestamp.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.129 2005/07/04 14:38:31 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.130 2005/07/10 21:13:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -170,6 +170,10 @@ Datum
 timestamp_recv(PG_FUNCTION_ARGS)
 {
 	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);
+#ifdef NOT_USED
+	Oid			typelem = PG_GETARG_OID(1);
+#endif
+	int32		typmod = PG_GETARG_INT32(2);
 	Timestamp timestamp;
 	struct pg_tm tt,
 			   *tm = &tt;
@@ -177,7 +181,6 @@ timestamp_recv(PG_FUNCTION_ARGS)
 
 #ifdef HAVE_INT64_TIMESTAMP
 	timestamp = (Timestamp) pq_getmsgint64(buf);
-
 #else
 	timestamp = (Timestamp) pq_getmsgfloat8(buf);
 #endif
@@ -185,11 +188,13 @@ timestamp_recv(PG_FUNCTION_ARGS)
 	/* rangecheck: see if timestamp_out would like it */
 	if (TIMESTAMP_NOT_FINITE(timestamp))
 		 /* ok */ ;
-	else if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) !=0)
+	else if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0)
 		ereport(ERROR,
 				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
 				 errmsg("timestamp out of range")));
 
+	AdjustTimestampForTypmod(&timestamp, typmod);
+
 	PG_RETURN_TIMESTAMP(timestamp);
 }
 
@@ -409,6 +414,10 @@ Datum
 timestamptz_recv(PG_FUNCTION_ARGS)
 {
 	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);
+#ifdef NOT_USED
+	Oid			typelem = PG_GETARG_OID(1);
+#endif
+	int32		typmod = PG_GETARG_INT32(2);
 	TimestampTz timestamp;
 	int			tz;
 	struct pg_tm tt,
@@ -418,7 +427,6 @@ timestamptz_recv(PG_FUNCTION_ARGS)
 
 #ifdef HAVE_INT64_TIMESTAMP
 	timestamp = (TimestampTz) pq_getmsgint64(buf);
-
 #else
 	timestamp = (TimestampTz) pq_getmsgfloat8(buf);
 #endif
@@ -431,6 +439,8 @@ timestamptz_recv(PG_FUNCTION_ARGS)
 				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
 				 errmsg("timestamp out of range")));
 
+	AdjustTimestampForTypmod(&timestamp, typmod);
+
 	PG_RETURN_TIMESTAMPTZ(timestamp);
 }
 
@@ -526,7 +536,6 @@ interval_in(PG_FUNCTION_ARGS)
 				ereport(ERROR,
 						(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
 						 errmsg("interval out of range")));
-			AdjustIntervalForTypmod(result, typmod);
 			break;
 
 		case DTK_INVALID:
@@ -540,6 +549,8 @@ interval_in(PG_FUNCTION_ARGS)
 				 dtype, str);
 	}
 
+	AdjustIntervalForTypmod(result, typmod);
+
 	PG_RETURN_INTERVAL_P(result);
 }
 
@@ -573,18 +584,23 @@ Datum
 interval_recv(PG_FUNCTION_ARGS)
 {
 	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);
+#ifdef NOT_USED
+	Oid			typelem = PG_GETARG_OID(1);
+#endif
+	int32		typmod = PG_GETARG_INT32(2);
 	Interval   *interval;
 
 	interval = (Interval *) palloc(sizeof(Interval));
 
 #ifdef HAVE_INT64_TIMESTAMP
 	interval->time = pq_getmsgint64(buf);
-
 #else
 	interval->time = pq_getmsgfloat8(buf);
 #endif
 	interval->month = pq_getmsgint(buf, sizeof(interval->month));
 
+	AdjustIntervalForTypmod(interval, typmod);
+
 	PG_RETURN_INTERVAL_P(interval);
 }
 
diff --git a/src/backend/utils/adt/varbit.c b/src/backend/utils/adt/varbit.c
index bdbf43c8993b3cd919278c2a06f9803ffc59c0af..1996638d28ea9f23503e4aaecbfcfcd8eb9eb616 100644
--- a/src/backend/utils/adt/varbit.c
+++ b/src/backend/utils/adt/varbit.c
@@ -9,7 +9,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/varbit.c,v 1.44 2004/12/31 22:01:22 pgsql Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/varbit.c,v 1.45 2005/07/10 21:13:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -221,8 +221,49 @@ bit_out(PG_FUNCTION_ARGS)
 Datum
 bit_recv(PG_FUNCTION_ARGS)
 {
-	/* Exactly the same as varbit_recv, so share code */
-	return varbit_recv(fcinfo);
+	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);
+#ifdef NOT_USED
+	Oid			typelem = PG_GETARG_OID(1);
+#endif
+	int32		atttypmod = PG_GETARG_INT32(2);
+	VarBit	   *result;
+	int			len,
+				bitlen;
+	int			ipad;
+	bits8		mask;
+
+	bitlen = pq_getmsgint(buf, sizeof(int32));
+	if (bitlen < 0)
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
+				 errmsg("invalid length in external bit string")));
+
+	/*
+	 * Sometimes atttypmod is not supplied. If it is supplied we need to
+	 * make sure that the bitstring fits.
+	 */
+	if (atttypmod > 0 && bitlen != atttypmod)
+		ereport(ERROR,
+				(errcode(ERRCODE_STRING_DATA_LENGTH_MISMATCH),
+			   errmsg("bit string length %d does not match type bit(%d)",
+					  bitlen, atttypmod)));
+
+	len = VARBITTOTALLEN(bitlen);
+	result = (VarBit *) palloc(len);
+	VARATT_SIZEP(result) = len;
+	VARBITLEN(result) = bitlen;
+
+	pq_copymsgbytes(buf, (char *) VARBITS(result), VARBITBYTES(result));
+
+	/* Make sure last byte is zero-padded if needed */
+	ipad = VARBITPAD(result);
+	if (ipad > 0)
+	{
+		mask = BITMASK << ipad;
+		*(VARBITS(result) + VARBITBYTES(result) - 1) &= mask;
+	}
+
+	PG_RETURN_VARBIT_P(result);
 }
 
 /*
@@ -459,6 +500,10 @@ Datum
 varbit_recv(PG_FUNCTION_ARGS)
 {
 	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);
+#ifdef NOT_USED
+	Oid			typelem = PG_GETARG_OID(1);
+#endif
+	int32		atttypmod = PG_GETARG_INT32(2);
 	VarBit	   *result;
 	int			len,
 				bitlen;
@@ -471,6 +516,16 @@ varbit_recv(PG_FUNCTION_ARGS)
 				(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
 				 errmsg("invalid length in external bit string")));
 
+	/*
+	 * Sometimes atttypmod is not supplied. If it is supplied we need to
+	 * make sure that the bitstring fits.
+	 */
+	if (atttypmod > 0 && bitlen > atttypmod)
+		ereport(ERROR,
+				(errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
+				 errmsg("bit string too long for type bit varying(%d)",
+						atttypmod)));
+
 	len = VARBITTOTALLEN(bitlen);
 	result = (VarBit *) palloc(len);
 	VARATT_SIZEP(result) = len;
diff --git a/src/backend/utils/adt/varchar.c b/src/backend/utils/adt/varchar.c
index 6d89b3df2f70b9ed488d080804ba7984623eaeea..5c5c1075c71a0a9d4fab6b7a3e64674ddb6dbf13 100644
--- a/src/backend/utils/adt/varchar.c
+++ b/src/backend/utils/adt/varchar.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/varchar.c,v 1.110 2005/05/29 20:15:59 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/varchar.c,v 1.111 2005/07/10 21:13:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -16,6 +16,8 @@
 
 #include "access/hash.h"
 #include "catalog/pg_type.h"
+#include "lib/stringinfo.h"
+#include "libpq/pqformat.h"
 #include "miscadmin.h"
 #include "utils/array.h"
 #include "utils/builtins.h"
@@ -53,28 +55,25 @@
  *****************************************************************************/
 
 /*
- * Convert a C string to CHARACTER internal representation.  atttypmod
- * is the declared length of the type plus VARHDRSZ.
+ * bpchar_input -- common guts of bpcharin and bpcharrecv
+ *
+ * s is the input text of length len (may not be null-terminated)
+ * atttypmod is the typmod value to apply
  *
- * If the C string is too long, raise an error, unless the extra
+ * Note that atttypmod is measured in characters, which
+ * is not necessarily the same as the number of bytes.
+ *
+ * If the input string is too long, raise an error, unless the extra
  * characters are spaces, in which case they're truncated.  (per SQL)
  */
-Datum
-bpcharin(PG_FUNCTION_ARGS)
+static BpChar *
+bpchar_input(const char *s, size_t len, int32 atttypmod)
 {
-	char	   *s = PG_GETARG_CSTRING(0);
-
-#ifdef NOT_USED
-	Oid			typelem = PG_GETARG_OID(1);
-#endif
-	int32		atttypmod = PG_GETARG_INT32(2);
 	BpChar	   *result;
 	char	   *r;
-	size_t		len,
-				maxlen;
+	size_t		maxlen;
 
 	/* verify encoding */
-	len = strlen(s);
 	pg_verifymbstr(s, len, false);
 
 	/* If typmod is -1 (or invalid), use the actual string length */
@@ -85,30 +84,32 @@ bpcharin(PG_FUNCTION_ARGS)
 		size_t		charlen;		/* number of CHARACTERS in the input */
 
 		maxlen = atttypmod - VARHDRSZ;
-		charlen = pg_mbstrlen(s);
+		charlen = pg_mbstrlen_with_len(s, len);
 		if (charlen > maxlen)
 		{
 			/* Verify that extra characters are spaces, and clip them off */
 			size_t		mbmaxlen = pg_mbcharcliplen(s, len, maxlen);
+			size_t		j;
 
 			/*
 			 * at this point, len is the actual BYTE length of the input
 			 * string, maxlen is the max number of CHARACTERS allowed for this
-			 * bpchar type.
+			 * bpchar type, mbmaxlen is the length in BYTES of those chars.
 			 */
-			if (strspn(s + mbmaxlen, " ") == len - mbmaxlen)
-				len = mbmaxlen;
-			else
-				ereport(ERROR,
-						(errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
-						 errmsg("value too long for type character(%d)",
-								(int) maxlen)));
+			for (j = mbmaxlen; j < len; j++)
+			{
+				if (s[j] != ' ')
+					ereport(ERROR,
+							(errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
+							 errmsg("value too long for type character(%d)",
+									(int) maxlen)));
+			}
 
 			/*
 			 * Now we set maxlen to the necessary byte length, not
 			 * the number of CHARACTERS!
 			 */
-			maxlen = len;
+			maxlen = len = mbmaxlen;
 		}
 		else
 		{
@@ -120,7 +121,7 @@ bpcharin(PG_FUNCTION_ARGS)
 		}
 	}
 
-	result = palloc(maxlen + VARHDRSZ);
+	result = (BpChar *) palloc(maxlen + VARHDRSZ);
 	VARATT_SIZEP(result) = maxlen + VARHDRSZ;
 	r = VARDATA(result);
 	memcpy(r, s, len);
@@ -129,6 +130,24 @@ bpcharin(PG_FUNCTION_ARGS)
 	if (maxlen > len)
 		memset(r + len, ' ', maxlen - len);
 
+	return result;
+}
+
+/*
+ * Convert a C string to CHARACTER internal representation.  atttypmod
+ * is the declared length of the type plus VARHDRSZ.
+ */
+Datum
+bpcharin(PG_FUNCTION_ARGS)
+{
+	char	   *s = PG_GETARG_CSTRING(0);
+#ifdef NOT_USED
+	Oid			typelem = PG_GETARG_OID(1);
+#endif
+	int32		atttypmod = PG_GETARG_INT32(2);
+	BpChar	   *result;
+
+	result = bpchar_input(s, strlen(s), atttypmod);
 	PG_RETURN_BPCHAR_P(result);
 }
 
@@ -158,8 +177,19 @@ bpcharout(PG_FUNCTION_ARGS)
 Datum
 bpcharrecv(PG_FUNCTION_ARGS)
 {
-	/* Exactly the same as textrecv, so share code */
-	return textrecv(fcinfo);
+	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);
+#ifdef NOT_USED
+	Oid			typelem = PG_GETARG_OID(1);
+#endif
+	int32		atttypmod = PG_GETARG_INT32(2);
+	BpChar	   *result;
+	char	   *str;
+	int			nbytes;
+
+	str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
+	result = bpchar_input(str, nbytes, atttypmod);
+	pfree(str);
+	PG_RETURN_BPCHAR_P(result);
 }
 
 /*
@@ -344,30 +374,24 @@ name_bpchar(PG_FUNCTION_ARGS)
  *****************************************************************************/
 
 /*
- * Convert a C string to VARCHAR internal representation.  atttypmod
- * is the declared length of the type plus VARHDRSZ.
+ * varchar_input -- common guts of varcharin and varcharrecv
+ *
+ * s is the input text of length len (may not be null-terminated)
+ * atttypmod is the typmod value to apply
  *
- * Note that atttypmod is regarded as the number of characters, which
+ * Note that atttypmod is measured in characters, which
  * is not necessarily the same as the number of bytes.
  *
- * If the C string is too long, raise an error, unless the extra characters
- * are spaces, in which case they're truncated.  (per SQL)
+ * If the input string is too long, raise an error, unless the extra
+ * characters are spaces, in which case they're truncated.  (per SQL)
  */
-Datum
-varcharin(PG_FUNCTION_ARGS)
+static VarChar *
+varchar_input(const char *s, size_t len, int32 atttypmod)
 {
-	char	   *s = PG_GETARG_CSTRING(0);
-
-#ifdef NOT_USED
-	Oid			typelem = PG_GETARG_OID(1);
-#endif
-	int32		atttypmod = PG_GETARG_INT32(2);
 	VarChar    *result;
-	size_t		len,
-				maxlen;
+	size_t		maxlen;
 
 	/* verify encoding */
-	len = strlen(s);
 	pg_verifymbstr(s, len, false);
 
 	maxlen = atttypmod - VARHDRSZ;
@@ -376,20 +400,42 @@ varcharin(PG_FUNCTION_ARGS)
 	{
 		/* Verify that extra characters are spaces, and clip them off */
 		size_t		mbmaxlen = pg_mbcharcliplen(s, len, maxlen);
+		size_t		j;
 
-		if (strspn(s + mbmaxlen, " ") == len - mbmaxlen)
-			len = mbmaxlen;
-		else
-			ereport(ERROR,
-					(errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
-				  errmsg("value too long for type character varying(%d)",
-						 (int) maxlen)));
+		for (j = mbmaxlen; j < len; j++)
+		{
+			if (s[j] != ' ')
+				ereport(ERROR,
+						(errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
+						 errmsg("value too long for type character varying(%d)",
+								(int) maxlen)));
+		}
+
+		len = mbmaxlen;
 	}
 
-	result = palloc(len + VARHDRSZ);
+	result = (VarChar *) palloc(len + VARHDRSZ);
 	VARATT_SIZEP(result) = len + VARHDRSZ;
 	memcpy(VARDATA(result), s, len);
 
+	return result;
+}
+
+/*
+ * Convert a C string to VARCHAR internal representation.  atttypmod
+ * is the declared length of the type plus VARHDRSZ.
+ */
+Datum
+varcharin(PG_FUNCTION_ARGS)
+{
+	char	   *s = PG_GETARG_CSTRING(0);
+#ifdef NOT_USED
+	Oid			typelem = PG_GETARG_OID(1);
+#endif
+	int32		atttypmod = PG_GETARG_INT32(2);
+	VarChar    *result;
+
+	result = varchar_input(s, strlen(s), atttypmod);
 	PG_RETURN_VARCHAR_P(result);
 }
 
@@ -419,8 +465,19 @@ varcharout(PG_FUNCTION_ARGS)
 Datum
 varcharrecv(PG_FUNCTION_ARGS)
 {
-	/* Exactly the same as textrecv, so share code */
-	return textrecv(fcinfo);
+	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);
+#ifdef NOT_USED
+	Oid			typelem = PG_GETARG_OID(1);
+#endif
+	int32		atttypmod = PG_GETARG_INT32(2);
+	VarChar	   *result;
+	char	   *str;
+	int			nbytes;
+
+	str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
+	result = varchar_input(str, nbytes, atttypmod);
+	pfree(str);
+	PG_RETURN_VARCHAR_P(result);
 }
 
 /*
diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c
index ba40747df41c4a0c3bbcaa6bbd1f0e73c9f06432..9b57a497a1d713169dbbe09ab356fb6f8c9777c2 100644
--- a/src/backend/utils/adt/varlena.c
+++ b/src/backend/utils/adt/varlena.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/varlena.c,v 1.127 2005/07/10 04:54:30 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/varlena.c,v 1.128 2005/07/10 21:13:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -299,6 +299,10 @@ textrecv(PG_FUNCTION_ARGS)
 	int			nbytes;
 
 	str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
+
+	/* verify encoding */
+	pg_verifymbstr(str, nbytes, false);
+
 	result = (text *) palloc(nbytes + VARHDRSZ);
 	VARATT_SIZEP(result) = nbytes + VARHDRSZ;
 	memcpy(VARDATA(result), str, nbytes);
diff --git a/src/backend/utils/mb/mbutils.c b/src/backend/utils/mb/mbutils.c
index 541f9c2a5d302a6e1611bca9c9aade540d63cc26..a670bcce624c975825b8806c2bd31d8de4dd5dc3 100644
--- a/src/backend/utils/mb/mbutils.c
+++ b/src/backend/utils/mb/mbutils.c
@@ -4,7 +4,7 @@
  * (currently mule internal code (mic) is used)
  * Tatsuo Ishii
  *
- * $PostgreSQL: pgsql/src/backend/utils/mb/mbutils.c,v 1.49 2005/03/07 04:30:52 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/mb/mbutils.c,v 1.50 2005/07/10 21:13:59 tgl Exp $
  */
 #include "postgres.h"
 
@@ -489,16 +489,21 @@ pg_mbstrlen(const unsigned char *mbstr)
 }
 
 /* returns the length (counted as a wchar) of a multibyte string
-   (not necessarily  NULL terminated) */
+ * (not necessarily NULL terminated)
+ */
 int
 pg_mbstrlen_with_len(const unsigned char *mbstr, int limit)
 {
 	int			len = 0;
-	int			l;
+
+	/* optimization for single byte encoding */
+	if (pg_database_encoding_max_length() == 1)
+		return limit;
 
 	while (limit > 0 && *mbstr)
 	{
-		l = pg_mblen(mbstr);
+		int		l = pg_mblen(mbstr);
+
 		limit -= l;
 		mbstr += l;
 		len++;
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index 3452b246d17537adfb02e56891ccd7ea5178d805..5ce6b4724e12f905e57a4f761f7671a07a4a385d 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -37,7 +37,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.287 2005/07/10 04:54:31 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.288 2005/07/10 21:13:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*							yyyymmddN */
-#define CATALOG_VERSION_NO	200507101
+#define CATALOG_VERSION_NO	200507102
 
 #endif
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index 9ea413a6f541c3bf59e652c0015e594d1c241a8a..f0ecaa9d9baebeefbb1ff2d3a12f8fc2e092036c 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.375 2005/07/10 04:54:31 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.376 2005/07/10 21:13:59 tgl Exp $
  *
  * NOTES
  *	  The script catalog/genbki.sh reads this file and generates .bki
@@ -3236,7 +3236,7 @@ DESCR("current user privilege on tablespace by tablespace name");
 DATA(insert OID = 2395 (  has_tablespace_privilege		   PGNSP PGUID 12 f f t f s 2 16 "26 25" _null_ _null_ _null_ has_tablespace_privilege_id - _null_ ));
 DESCR("current user privilege on tablespace by tablespace oid");
 
-DATA(insert OID = 2290 (  record_in			PGNSP PGUID 12 f f t f v 2 2249 "2275 26" _null_ _null_ _null_	record_in - _null_ ));
+DATA(insert OID = 2290 (  record_in			PGNSP PGUID 12 f f t f v 3 2249 "2275 26 23" _null_ _null_ _null_	record_in - _null_ ));
 DESCR("I/O");
 DATA(insert OID = 2291 (  record_out		PGNSP PGUID 12 f f t f v 1 2275 "2249" _null_ _null_ _null_	record_out - _null_ ));
 DESCR("I/O");
@@ -3377,11 +3377,11 @@ DESCR("less-equal-greater");
 
 
 /* send/receive functions */
-DATA(insert OID = 2400 (  array_recv		   PGNSP PGUID 12 f f t f s 2 2277 "2281 26" _null_ _null_ _null_  array_recv - _null_ ));
+DATA(insert OID = 2400 (  array_recv		   PGNSP PGUID 12 f f t f s 3 2277 "2281 26 23" _null_ _null_ _null_  array_recv - _null_ ));
 DESCR("I/O");
 DATA(insert OID = 2401 (  array_send		   PGNSP PGUID 12 f f t f s 1 17 "2277" _null_ _null_ _null_	array_send - _null_ ));
 DESCR("I/O");
-DATA(insert OID = 2402 (  record_recv		   PGNSP PGUID 12 f f t f v 2 2249 "2281 26" _null_ _null_ _null_  record_recv - _null_ ));
+DATA(insert OID = 2402 (  record_recv		   PGNSP PGUID 12 f f t f v 3 2249 "2281 26 23" _null_ _null_ _null_  record_recv - _null_ ));
 DESCR("I/O");
 DATA(insert OID = 2403 (  record_send		   PGNSP PGUID 12 f f t f v 1 17 "2249" _null_ _null_ _null_  record_send - _null_ ));
 DESCR("I/O");
@@ -3437,11 +3437,11 @@ DATA(insert OID = 2428 (  point_recv		   PGNSP PGUID 12 f f t f i 1 600 "2281" _
 DESCR("I/O");
 DATA(insert OID = 2429 (  point_send		   PGNSP PGUID 12 f f t f i 1 17 "600" _null_ _null_ _null_	point_send - _null_ ));
 DESCR("I/O");
-DATA(insert OID = 2430 (  bpcharrecv		   PGNSP PGUID 12 f f t f s 1 1042 "2281" _null_ _null_ _null_  bpcharrecv - _null_ ));
+DATA(insert OID = 2430 (  bpcharrecv		   PGNSP PGUID 12 f f t f s 3 1042 "2281 26 23" _null_ _null_ _null_  bpcharrecv - _null_ ));
 DESCR("I/O");
 DATA(insert OID = 2431 (  bpcharsend		   PGNSP PGUID 12 f f t f s 1 17 "1042" _null_ _null_ _null_	bpcharsend - _null_ ));
 DESCR("I/O");
-DATA(insert OID = 2432 (  varcharrecv		   PGNSP PGUID 12 f f t f s 1 1043 "2281" _null_ _null_ _null_  varcharrecv - _null_ ));
+DATA(insert OID = 2432 (  varcharrecv		   PGNSP PGUID 12 f f t f s 3 1043 "2281 26 23" _null_ _null_ _null_  varcharrecv - _null_ ));
 DESCR("I/O");
 DATA(insert OID = 2433 (  varcharsend		   PGNSP PGUID 12 f f t f s 1 17 "1043" _null_ _null_ _null_	varcharsend - _null_ ));
 DESCR("I/O");
@@ -3489,15 +3489,15 @@ DATA(insert OID = 2454 (  regtyperecv		   PGNSP PGUID 12 f f t f i 1 2206 "2281"
 DESCR("I/O");
 DATA(insert OID = 2455 (  regtypesend		   PGNSP PGUID 12 f f t f i 1 17 "2206" _null_ _null_ _null_	regtypesend - _null_ ));
 DESCR("I/O");
-DATA(insert OID = 2456 (  bit_recv			   PGNSP PGUID 12 f f t f i 1 1560 "2281" _null_ _null_ _null_  bit_recv - _null_ ));
+DATA(insert OID = 2456 (  bit_recv			   PGNSP PGUID 12 f f t f i 3 1560 "2281 26 23" _null_ _null_ _null_  bit_recv - _null_ ));
 DESCR("I/O");
 DATA(insert OID = 2457 (  bit_send			   PGNSP PGUID 12 f f t f i 1 17 "1560" _null_ _null_ _null_	bit_send - _null_ ));
 DESCR("I/O");
-DATA(insert OID = 2458 (  varbit_recv		   PGNSP PGUID 12 f f t f i 1 1562 "2281" _null_ _null_ _null_  varbit_recv - _null_ ));
+DATA(insert OID = 2458 (  varbit_recv		   PGNSP PGUID 12 f f t f i 3 1562 "2281 26 23" _null_ _null_ _null_  varbit_recv - _null_ ));
 DESCR("I/O");
 DATA(insert OID = 2459 (  varbit_send		   PGNSP PGUID 12 f f t f i 1 17 "1562" _null_ _null_ _null_	varbit_send - _null_ ));
 DESCR("I/O");
-DATA(insert OID = 2460 (  numeric_recv		   PGNSP PGUID 12 f f t f i 1 1700 "2281" _null_ _null_ _null_  numeric_recv - _null_ ));
+DATA(insert OID = 2460 (  numeric_recv		   PGNSP PGUID 12 f f t f i 3 1700 "2281 26 23" _null_ _null_ _null_  numeric_recv - _null_ ));
 DESCR("I/O");
 DATA(insert OID = 2461 (  numeric_send		   PGNSP PGUID 12 f f t f i 1 17 "1700" _null_ _null_ _null_	numeric_send - _null_ ));
 DESCR("I/O");
@@ -3517,23 +3517,23 @@ DATA(insert OID = 2468 (  date_recv			   PGNSP PGUID 12 f f t f i 1 1082 "2281"
 DESCR("I/O");
 DATA(insert OID = 2469 (  date_send			   PGNSP PGUID 12 f f t f i 1 17 "1082" _null_ _null_ _null_	date_send - _null_ ));
 DESCR("I/O");
-DATA(insert OID = 2470 (  time_recv			   PGNSP PGUID 12 f f t f i 1 1083 "2281" _null_ _null_ _null_  time_recv - _null_ ));
+DATA(insert OID = 2470 (  time_recv			   PGNSP PGUID 12 f f t f i 3 1083 "2281 26 23" _null_ _null_ _null_  time_recv - _null_ ));
 DESCR("I/O");
 DATA(insert OID = 2471 (  time_send			   PGNSP PGUID 12 f f t f i 1 17 "1083" _null_ _null_ _null_	time_send - _null_ ));
 DESCR("I/O");
-DATA(insert OID = 2472 (  timetz_recv		   PGNSP PGUID 12 f f t f i 1 1266 "2281" _null_ _null_ _null_  timetz_recv - _null_ ));
+DATA(insert OID = 2472 (  timetz_recv		   PGNSP PGUID 12 f f t f i 3 1266 "2281 26 23" _null_ _null_ _null_  timetz_recv - _null_ ));
 DESCR("I/O");
 DATA(insert OID = 2473 (  timetz_send		   PGNSP PGUID 12 f f t f i 1 17 "1266" _null_ _null_ _null_	timetz_send - _null_ ));
 DESCR("I/O");
-DATA(insert OID = 2474 (  timestamp_recv	   PGNSP PGUID 12 f f t f i 1 1114 "2281" _null_ _null_ _null_  timestamp_recv - _null_ ));
+DATA(insert OID = 2474 (  timestamp_recv	   PGNSP PGUID 12 f f t f i 3 1114 "2281 26 23" _null_ _null_ _null_  timestamp_recv - _null_ ));
 DESCR("I/O");
 DATA(insert OID = 2475 (  timestamp_send	   PGNSP PGUID 12 f f t f i 1 17 "1114" _null_ _null_ _null_	timestamp_send - _null_ ));
 DESCR("I/O");
-DATA(insert OID = 2476 (  timestamptz_recv	   PGNSP PGUID 12 f f t f i 1 1184 "2281" _null_ _null_ _null_  timestamptz_recv - _null_ ));
+DATA(insert OID = 2476 (  timestamptz_recv	   PGNSP PGUID 12 f f t f i 3 1184 "2281 26 23" _null_ _null_ _null_  timestamptz_recv - _null_ ));
 DESCR("I/O");
 DATA(insert OID = 2477 (  timestamptz_send	   PGNSP PGUID 12 f f t f i 1 17 "1184" _null_ _null_ _null_	timestamptz_send - _null_ ));
 DESCR("I/O");
-DATA(insert OID = 2478 (  interval_recv		   PGNSP PGUID 12 f f t f i 1 1186 "2281" _null_ _null_ _null_  interval_recv - _null_ ));
+DATA(insert OID = 2478 (  interval_recv		   PGNSP PGUID 12 f f t f i 3 1186 "2281 26 23" _null_ _null_ _null_  interval_recv - _null_ ));
 DESCR("I/O");
 DATA(insert OID = 2479 (  interval_send		   PGNSP PGUID 12 f f t f i 1 17 "1186" _null_ _null_ _null_	interval_send - _null_ ));
 DESCR("I/O");
diff --git a/src/test/regress/expected/type_sanity.out b/src/test/regress/expected/type_sanity.out
index 0eb6bb8e9613c53af17562842b5f0609c86ba866..73d51925c2ffaab57d4327dba2819f1fbf9f2d16 100644
--- a/src/test/regress/expected/type_sanity.out
+++ b/src/test/regress/expected/type_sanity.out
@@ -69,11 +69,10 @@ WHERE p1.typtype in ('b') AND p1.typname NOT LIKE E'\\_%' AND NOT EXISTS
  705 | unknown
 (2 rows)
 
--- Conversion routines must be provided except in 'c' entries.
+-- Text conversion routines must be provided.
 SELECT p1.oid, p1.typname
 FROM pg_type as p1
-WHERE p1.typtype != 'c' AND
-    (p1.typinput = 0 OR p1.typoutput = 0);
+WHERE (p1.typinput = 0 OR p1.typoutput = 0);
  oid | typname 
 -----+---------
 (0 rows)
@@ -83,8 +82,6 @@ SELECT p1.oid, p1.typname, p2.oid, p2.proname
 FROM pg_type AS p1, pg_proc AS p2
 WHERE p1.typinput = p2.oid AND p1.typtype in ('b', 'p') AND NOT
     ((p2.pronargs = 1 AND p2.proargtypes[0] = 'cstring'::regtype) OR
-     (p2.pronargs = 2 AND p2.proargtypes[0] = 'cstring'::regtype AND
-      p2.proargtypes[1] = 'oid'::regtype) OR
      (p2.pronargs = 3 AND p2.proargtypes[0] = 'cstring'::regtype AND
       p2.proargtypes[1] = 'oid'::regtype AND
       p2.proargtypes[2] = 'int4'::regtype));
@@ -148,8 +145,9 @@ SELECT p1.oid, p1.typname, p2.oid, p2.proname
 FROM pg_type AS p1, pg_proc AS p2
 WHERE p1.typreceive = p2.oid AND p1.typtype in ('b', 'p') AND NOT
     ((p2.pronargs = 1 AND p2.proargtypes[0] = 'internal'::regtype) OR
-     (p2.pronargs = 2 AND p2.proargtypes[0] = 'internal'::regtype AND
-      p2.proargtypes[1] = 'oid'::regtype));
+     (p2.pronargs = 3 AND p2.proargtypes[0] = 'internal'::regtype AND
+      p2.proargtypes[1] = 'oid'::regtype AND
+      p2.proargtypes[2] = 'int4'::regtype));
  oid | typname | oid | proname 
 -----+---------+-----+---------
 (0 rows)
@@ -181,6 +179,15 @@ ORDER BY 1;
   30 | oidvector  | 2420 | oidvectorrecv
 (2 rows)
 
+-- Suspicious if typreceive doesn't take same number of args as typinput
+SELECT p1.oid, p1.typname, p2.oid, p2.proname, p3.oid, p3.proname
+FROM pg_type AS p1, pg_proc AS p2, pg_proc AS p3
+WHERE p1.typinput = p2.oid AND p1.typreceive = p3.oid AND
+    p2.pronargs != p3.pronargs;
+ oid | typname | oid | proname | oid | proname 
+-----+---------+-----+---------+-----+---------
+(0 rows)
+
 -- Check for bogus typsend routines
 -- As of 7.4, this check finds refcursor, which is borrowing
 -- other types' I/O routines
diff --git a/src/test/regress/sql/type_sanity.sql b/src/test/regress/sql/type_sanity.sql
index 20f6a75ffae9f5ad6af61a775cce828f0f0f104b..3969b4cce2ef4808dcfeac26d294cf6a30d13f5a 100644
--- a/src/test/regress/sql/type_sanity.sql
+++ b/src/test/regress/sql/type_sanity.sql
@@ -59,12 +59,11 @@ WHERE p1.typtype in ('b') AND p1.typname NOT LIKE E'\\_%' AND NOT EXISTS
      WHERE p2.typname = ('_' || p1.typname)::name AND
            p2.typelem = p1.oid);
 
--- Conversion routines must be provided except in 'c' entries.
+-- Text conversion routines must be provided.
 
 SELECT p1.oid, p1.typname
 FROM pg_type as p1
-WHERE p1.typtype != 'c' AND
-    (p1.typinput = 0 OR p1.typoutput = 0);
+WHERE (p1.typinput = 0 OR p1.typoutput = 0);
 
 -- Check for bogus typinput routines
 
@@ -72,8 +71,6 @@ SELECT p1.oid, p1.typname, p2.oid, p2.proname
 FROM pg_type AS p1, pg_proc AS p2
 WHERE p1.typinput = p2.oid AND p1.typtype in ('b', 'p') AND NOT
     ((p2.pronargs = 1 AND p2.proargtypes[0] = 'cstring'::regtype) OR
-     (p2.pronargs = 2 AND p2.proargtypes[0] = 'cstring'::regtype AND
-      p2.proargtypes[1] = 'oid'::regtype) OR
      (p2.pronargs = 3 AND p2.proargtypes[0] = 'cstring'::regtype AND
       p2.proargtypes[1] = 'oid'::regtype AND
       p2.proargtypes[2] = 'int4'::regtype));
@@ -120,8 +117,9 @@ SELECT p1.oid, p1.typname, p2.oid, p2.proname
 FROM pg_type AS p1, pg_proc AS p2
 WHERE p1.typreceive = p2.oid AND p1.typtype in ('b', 'p') AND NOT
     ((p2.pronargs = 1 AND p2.proargtypes[0] = 'internal'::regtype) OR
-     (p2.pronargs = 2 AND p2.proargtypes[0] = 'internal'::regtype AND
-      p2.proargtypes[1] = 'oid'::regtype));
+     (p2.pronargs = 3 AND p2.proargtypes[0] = 'internal'::regtype AND
+      p2.proargtypes[1] = 'oid'::regtype AND
+      p2.proargtypes[2] = 'int4'::regtype));
 
 -- As of 7.4, this check finds refcursor, which is borrowing
 -- other types' I/O routines
@@ -141,6 +139,12 @@ WHERE p1.typreceive = p2.oid AND p1.typtype in ('b', 'p') AND
     (p2.oid = 'array_recv'::regproc)
 ORDER BY 1;
 
+-- Suspicious if typreceive doesn't take same number of args as typinput
+SELECT p1.oid, p1.typname, p2.oid, p2.proname, p3.oid, p3.proname
+FROM pg_type AS p1, pg_proc AS p2, pg_proc AS p3
+WHERE p1.typinput = p2.oid AND p1.typreceive = p3.oid AND
+    p2.pronargs != p3.pronargs;
+
 -- Check for bogus typsend routines
 
 -- As of 7.4, this check finds refcursor, which is borrowing