diff --git a/doc/src/sgml/ref/create_type.sgml b/doc/src/sgml/ref/create_type.sgml
index 038cf8c256f90c5de3cf30b197418d50a7d4329d..be13351d0a262804995ba4cfb78824674a2c11dc 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.71 2007/05/12 00:54:59 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/create_type.sgml,v 1.72 2007/06/15 20:56:49 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -195,11 +195,11 @@ CREATE TYPE <replaceable class="parameter">name</replaceable>
    are needed if the type supports modifiers, that is optional constraints
    attached to a type declaration, such as <literal>char(5)</> or
    <literal>numeric(30,2)</>.  <productname>PostgreSQL</productname> allows
-   user-defined types to take one or more integer constants as modifiers;
-   however, this information must be capable of being packed into a single
-   non-negative integer value for storage in the system catalogs.  The
+   user-defined types to take one or more simple constants or identifiers as
+   modifiers; however, this information must be capable of being packed into a
+   single non-negative integer value for storage in the system catalogs.  The
    <replaceable class="parameter">type_modifier_input_function</replaceable>
-   is passed the declared modifier(s) in the form of an <type>integer</>
+   is passed the declared modifier(s) in the form of a <type>cstring</>
    array.  It must check the values for validity (throwing an error if they
    are wrong), and if they are correct, return a single non-negative
    <type>integer</> value that will be stored as the column <quote>typmod</>.
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index 5402cde74cdbd65d6ff6d0a05379d31d6d8462fe..d9748cf0ea8952f11009e43bada4e838a57dfdf0 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.104 2007/05/12 00:54:59 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.105 2007/06/15 20:56:49 tgl Exp $
  *
  * DESCRIPTION
  *	  The "DefineFoo" routines take the parse tree and pick out the
@@ -1270,9 +1270,9 @@ findTypeTypmodinFunction(List *procname)
 	Oid			procOid;
 
 	/*
-	 * typmodin functions always take one int4[] argument and return int4.
+	 * typmodin functions always take one cstring[] argument and return int4.
 	 */
-	argList[0] = INT4ARRAYOID;
+	argList[0] = CSTRINGARRAYOID;
 
 	procOid = LookupFuncName(procname, 1, argList, true);
 	if (!OidIsValid(procOid))
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index da3afda8fb33d0b23e85c631007fab9db21b6125..8ec562c5e316c65b5f5072f3118f33929c1df5a1 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.593 2007/06/11 22:22:41 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.594 2007/06/15 20:56:49 tgl Exp $
  *
  * HISTORY
  *	  AUTHOR			DATE			MAJOR EVENT
@@ -6695,7 +6695,7 @@ ConstTypename:
  * by the standard, including qualified names.  We also allow type modifiers.
  * To avoid parsing conflicts against function invocations, the modifiers
  * have to be shown as expr_list here, but parse analysis will only accept
- * integer constants for them.
+ * constants for them.
  */
 GenericType:
 			type_function_name opt_type_modifiers
diff --git a/src/backend/parser/parse_type.c b/src/backend/parser/parse_type.c
index d3198f0496a7226d4d96b672d6cce822c3eea1e6..f86dd43d54889c4c2a29b388f4f65357ceae9c4a 100644
--- a/src/backend/parser/parse_type.c
+++ b/src/backend/parser/parse_type.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/parser/parse_type.c,v 1.90 2007/05/11 17:57:12 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/parser/parse_type.c,v 1.91 2007/06/15 20:56:50 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -289,28 +289,55 @@ typenameTypeMod(ParseState *pstate, const TypeName *typename,
 				 parser_errposition(pstate, typename->location)));
 
 	/*
-	 * Convert the list of (raw grammar output) expressions to an integer
-	 * array.  Currently, we only allow simple integer constants, though
-	 * possibly this could be extended.
+	 * Convert the list of raw-grammar-output expressions to a cstring array.
+	 * Currently, we allow simple numeric constants, string literals, and
+	 * identifiers; possibly this list could be extended.
 	 */
 	datums = (Datum *) palloc(list_length(typename->typmods) * sizeof(Datum));
 	n = 0;
 	foreach(l, typename->typmods)
 	{
-		A_Const	*ac = (A_Const *) lfirst(l);
+		Node	*tm = (Node *) lfirst(l);
+		char	*cstr = NULL;
 
-		if (!IsA(ac, A_Const) ||
-			!IsA(&ac->val, Integer))
+		if (IsA(tm, A_Const))
+		{
+			A_Const	   *ac = (A_Const *) tm;
+
+			/*
+			 * The grammar hands back some integers with ::int4 attached,
+			 * so allow a cast decoration if it's an Integer value, but
+			 * not otherwise.
+			 */
+			if (IsA(&ac->val, Integer))
+			{
+				cstr = (char *) palloc(32);
+				snprintf(cstr, 32, "%ld", (long) ac->val.val.ival);
+			}
+			else if (ac->typename == NULL)	/* no casts allowed */
+			{
+				/* otherwise we can just use the str field directly. */
+				cstr = ac->val.val.str;
+			}
+		}
+		else if (IsA(tm, ColumnRef))
+		{
+			ColumnRef   *cr = (ColumnRef *) tm;
+
+			if (list_length(cr->fields) == 1)
+				cstr = strVal(linitial(cr->fields));
+		}
+		if (!cstr)
 			ereport(ERROR,
 					(errcode(ERRCODE_SYNTAX_ERROR),
-					 errmsg("type modifiers must be integer constants"),
+					 errmsg("type modifiers must be simple constants or identifiers"),
 					 parser_errposition(pstate, typename->location)));
-		datums[n++] = Int32GetDatum(ac->val.val.ival);
+		datums[n++] = CStringGetDatum(cstr);
 	}
 
-	/* hardwired knowledge about int4's representation details here */
-	arrtypmod = construct_array(datums, n, INT4OID,
-								sizeof(int4), true, 'i');
+	/* hardwired knowledge about cstring's representation details here */
+	arrtypmod = construct_array(datums, n, CSTRINGOID,
+								-2, false, 'c');
 
 	result = DatumGetInt32(OidFunctionCall1(typmodin,
 											PointerGetDatum(arrtypmod)));
diff --git a/src/backend/utils/adt/arrayutils.c b/src/backend/utils/adt/arrayutils.c
index 695f45163299a4ec3815652669c73ac6633156eb..cd59ffb62d62aa8c8d0d832ce29f1bb43ce3eb28 100644
--- a/src/backend/utils/adt/arrayutils.c
+++ b/src/backend/utils/adt/arrayutils.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/arrayutils.c,v 1.23 2007/01/05 22:19:40 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/arrayutils.c,v 1.24 2007/06/15 20:56:50 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -17,6 +17,7 @@
 
 #include "catalog/pg_type.h"
 #include "utils/array.h"
+#include "utils/builtins.h"
 #include "utils/memutils.h"
 
 
@@ -191,16 +192,21 @@ mda_next_tuple(int n, int *curr, const int *span)
 }
 
 /*
- * ArrayGetTypmods: verify that argument is a 1-D integer array,
- * return its length and a pointer to the first contained integer.
+ * ArrayGetIntegerTypmods: verify that argument is a 1-D cstring array,
+ * and get the contents converted to integers.  Returns a palloc'd array
+ * and places the length at *n.
  */
 int32 *
-ArrayGetTypmods(ArrayType *arr, int *n)
+ArrayGetIntegerTypmods(ArrayType *arr, int *n)
 {
-	if (ARR_ELEMTYPE(arr) != INT4OID)
+	int32	   *result;
+	Datum	   *elem_values;
+	int			i;
+
+	if (ARR_ELEMTYPE(arr) != CSTRINGOID)
 		ereport(ERROR,
 				(errcode(ERRCODE_ARRAY_ELEMENT_ERROR),
-				 errmsg("typmod array must be type integer[]")));
+				 errmsg("typmod array must be type cstring[]")));
 
 	if (ARR_NDIM(arr) != 1)
 		ereport(ERROR,
@@ -212,7 +218,18 @@ ArrayGetTypmods(ArrayType *arr, int *n)
 				(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
 				 errmsg("typmod array must not contain nulls")));
 
-	*n = ArrayGetNItems(ARR_NDIM(arr), ARR_DIMS(arr));
+	/* hardwired knowledge about cstring's representation details here */
+	deconstruct_array(arr, CSTRINGOID,
+					  -2, false, 'c',
+					  &elem_values, NULL, n);
+
+	result = (int32 *) palloc(*n * sizeof(int32));
+
+	for (i = 0; i < *n; i++)
+		result[i] = pg_atoi(DatumGetCString(elem_values[i]),
+							sizeof(int32), '\0');
+
+	pfree(elem_values);
 
-	return (int32 *) ARR_DATA_PTR(arr);
+	return result;
 }
diff --git a/src/backend/utils/adt/date.c b/src/backend/utils/adt/date.c
index 4914736116fa6d0b509ff5402a4eb3b836232d2c..a66680f4772c50019847c5a09464e7afbda1e8e9 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.132 2007/06/05 21:31:06 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/date.c,v 1.133 2007/06/15 20:56:50 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,7 +53,7 @@ anytime_typmodin(bool istz, ArrayType *ta)
 	int32	*tl;
 	int		n;
 
-	tl = ArrayGetTypmods(ta, &n);
+	tl = ArrayGetIntegerTypmods(ta, &n);
 
 	/*
 	 * we're not too tense about good error message here because grammar
diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c
index 95309cbff477151696ff196bb4038c4c43f7ffa7..02523b8a5fc41e10477a1aa19d35d71c1bbfcaf2 100644
--- a/src/backend/utils/adt/numeric.c
+++ b/src/backend/utils/adt/numeric.c
@@ -14,7 +14,7 @@
  * Copyright (c) 1998-2007, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/numeric.c,v 1.104 2007/06/09 15:52:30 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/numeric.c,v 1.105 2007/06/15 20:56:50 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -547,7 +547,7 @@ numerictypmodin(PG_FUNCTION_ARGS)
 	int			n;
 	int32		typmod;
 
-	tl = ArrayGetTypmods(ta, &n);
+	tl = ArrayGetIntegerTypmods(ta, &n);
 
 	if (n == 2)
 	{
diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c
index f7c385ad46aec60c3b3cea4ab4d429884b18e195..d20193511687b68461985fe12e07e574808b454c 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.177 2007/06/05 21:31:06 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.178 2007/06/15 20:56:50 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -64,7 +64,7 @@ anytimestamp_typmodin(bool istz, ArrayType *ta)
 	int32    *tl;
 	int		n;
 
-	tl = ArrayGetTypmods(ta, &n);
+	tl = ArrayGetIntegerTypmods(ta, &n);
 
 	/*
 	 * we're not too tense about good error message here because grammar
@@ -719,7 +719,7 @@ intervaltypmodin(PG_FUNCTION_ARGS)
     int    		n;
 	int32		typmod;
 
-	tl = ArrayGetTypmods(ta, &n);
+	tl = ArrayGetIntegerTypmods(ta, &n);
 
 	/*
 	 * tl[0] - opt_interval
diff --git a/src/backend/utils/adt/varbit.c b/src/backend/utils/adt/varbit.c
index a9eef1e0e7d078c61a8f44f46ad60fef85a86739..3126bd689cb071943db0f9b0d5173635ee9c74e6 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.53 2007/02/27 23:48:09 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/varbit.c,v 1.54 2007/06/15 20:56:51 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -32,7 +32,7 @@ anybit_typmodin(ArrayType *ta, const char *typename)
 	int32	*tl;
 	int		n;
 
-	tl = ArrayGetTypmods(ta, &n);
+	tl = ArrayGetIntegerTypmods(ta, &n);
 
 	/*
 	 * we're not too tense about good error message here because grammar
diff --git a/src/backend/utils/adt/varchar.c b/src/backend/utils/adt/varchar.c
index 77a6ab9c4fc51bb7b452b3655de54827b087326d..43315dd9ebce913c899e6da670d1a324987f54c3 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.123 2007/04/06 04:21:43 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/varchar.c,v 1.124 2007/06/15 20:56:51 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -31,7 +31,7 @@ anychar_typmodin(ArrayType *ta, const char *typename)
 	int32	*tl;
 	int		n;
 
-	tl = ArrayGetTypmods(ta, &n);
+	tl = ArrayGetIntegerTypmods(ta, &n);
 
 	/*
 	 * we're not too tense about good error message here because grammar
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index 8dfca8ecc7255a7d5e5450344e9e10c9aa4ffe5b..415af0e6cb21dce71aff3609f25918a3ea197afb 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -37,7 +37,7 @@
  * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.411 2007/06/06 23:00:40 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.412 2007/06/15 20:56:51 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*							yyyymmddN */
-#define CATALOG_VERSION_NO	200706061
+#define CATALOG_VERSION_NO	200706151
 
 #endif
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index 49c1429e377033b46585d6b7d0c43982f54f7ccc..11e13b36aae12d8e53e6bda601f980f3ad3905a2 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.459 2007/06/06 23:00:41 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.460 2007/06/15 20:56:51 tgl Exp $
  *
  * NOTES
  *	  The script catalog/genbki.sh reads this file and generates .bki
@@ -1308,7 +1308,7 @@ DATA(insert OID = 1044 (  bpcharin		   PGNSP PGUID 12 1 0 f f t f i 3 1042 "2275
 DESCR("I/O");
 DATA(insert OID = 1045 (  bpcharout		   PGNSP PGUID 12 1 0 f f t f i 1 2275 "1042" _null_ _null_ _null_	bpcharout - _null_ ));
 DESCR("I/O");
-DATA(insert OID = 2913 (  bpchartypmodin   PGNSP PGUID 12 1 0 f f t f i 1 23 "1007" _null_ _null_ _null_	bpchartypmodin - _null_ ));
+DATA(insert OID = 2913 (  bpchartypmodin   PGNSP PGUID 12 1 0 f f t f i 1 23 "1263" _null_ _null_ _null_	bpchartypmodin - _null_ ));
 DESCR("I/O typmod");
 DATA(insert OID = 2914 (  bpchartypmodout  PGNSP PGUID 12 1 0 f f t f i 1 2275 "23" _null_ _null_ _null_	bpchartypmodout - _null_ ));
 DESCR("I/O typmod");
@@ -1316,7 +1316,7 @@ DATA(insert OID = 1046 (  varcharin		   PGNSP PGUID 12 1 0 f f t f i 3 1043 "227
 DESCR("I/O");
 DATA(insert OID = 1047 (  varcharout	   PGNSP PGUID 12 1 0 f f t f i 1 2275 "1043" _null_ _null_ _null_	varcharout - _null_ ));
 DESCR("I/O");
-DATA(insert OID = 2915 (  varchartypmodin  PGNSP PGUID 12 1 0 f f t f i 1 23 "1007" _null_ _null_ _null_	varchartypmodin - _null_ ));
+DATA(insert OID = 2915 (  varchartypmodin  PGNSP PGUID 12 1 0 f f t f i 1 23 "1263" _null_ _null_ _null_	varchartypmodin - _null_ ));
 DESCR("I/O typmod");
 DATA(insert OID = 2916 (  varchartypmodout PGNSP PGUID 12 1 0 f f t f i 1 2275 "23" _null_ _null_ _null_	varchartypmodout - _null_ ));
 DESCR("I/O typmod");
@@ -1389,7 +1389,7 @@ DATA(insert OID = 1143 (  time_in		   PGNSP PGUID 12 1 0 f f t f s 3 1083 "2275
 DESCR("I/O");
 DATA(insert OID = 1144 (  time_out		   PGNSP PGUID 12 1 0 f f t f i 1 2275 "1083" _null_ _null_ _null_	time_out - _null_ ));
 DESCR("I/O");
-DATA(insert OID = 2909 (  timetypmodin   	PGNSP PGUID 12 1 0 f f t f i 1 23 "1007" _null_ _null_ _null_	timetypmodin - _null_ ));
+DATA(insert OID = 2909 (  timetypmodin   	PGNSP PGUID 12 1 0 f f t f i 1 23 "1263" _null_ _null_ _null_	timetypmodin - _null_ ));
 DESCR("I/O typmod");
 DATA(insert OID = 2910 (  timetypmodout  	PGNSP PGUID 12 1 0 f f t f i 1 2275 "23" _null_ _null_ _null_	timetypmodout - _null_ ));
 DESCR("I/O typmod");
@@ -1409,7 +1409,7 @@ DATA(insert OID = 1150 (  timestamptz_in   PGNSP PGUID 12 1 0 f f t f s 3 1184 "
 DESCR("I/O");
 DATA(insert OID = 1151 (  timestamptz_out  PGNSP PGUID 12 1 0 f f t f s 1 2275 "1184" _null_ _null_ _null_	timestamptz_out - _null_ ));
 DESCR("I/O");
-DATA(insert OID = 2907 (  timestamptztypmodin   	PGNSP PGUID 12 1 0 f f t f i 1 23 "1007" _null_ _null_ _null_	timestamptztypmodin - _null_ ));
+DATA(insert OID = 2907 (  timestamptztypmodin   	PGNSP PGUID 12 1 0 f f t f i 1 23 "1263" _null_ _null_ _null_	timestamptztypmodin - _null_ ));
 DESCR("I/O typmod");
 DATA(insert OID = 2908 (  timestamptztypmodout  	PGNSP PGUID 12 1 0 f f t f i 1 2275 "23" _null_ _null_ _null_	timestamptztypmodout - _null_ ));
 DESCR("I/O typmod");
@@ -1434,7 +1434,7 @@ DATA(insert OID = 1160 (  interval_in	   PGNSP PGUID 12 1 0 f f t f s 3 1186 "22
 DESCR("I/O");
 DATA(insert OID = 1161 (  interval_out	   PGNSP PGUID 12 1 0 f f t f i 1 2275 "1186" _null_ _null_ _null_	interval_out - _null_ ));
 DESCR("I/O");
-DATA(insert OID = 2903 (  intervaltypmodin   	PGNSP PGUID 12 1 0 f f t f i 1 23 "1007" _null_ _null_ _null_	intervaltypmodin - _null_ ));
+DATA(insert OID = 2903 (  intervaltypmodin   	PGNSP PGUID 12 1 0 f f t f i 1 23 "1263" _null_ _null_ _null_	intervaltypmodin - _null_ ));
 DESCR("I/O typmod");
 DATA(insert OID = 2904 (  intervaltypmodout  	PGNSP PGUID 12 1 0 f f t f i 1 2275 "23" _null_ _null_ _null_	intervaltypmodout - _null_ ));
 DESCR("I/O typmod");
@@ -1644,7 +1644,7 @@ DATA(insert OID = 1312 (  timestamp_in		 PGNSP PGUID 12 1 0 f f t f s 3 1114 "22
 DESCR("I/O");
 DATA(insert OID = 1313 (  timestamp_out		 PGNSP PGUID 12 1 0 f f t f s 1 2275 "1114" _null_ _null_ _null_ timestamp_out - _null_ ));
 DESCR("I/O");
-DATA(insert OID = 2905 (  timestamptypmodin   	PGNSP PGUID 12 1 0 f f t f i 1 23 "1007" _null_ _null_ _null_	timestamptypmodin - _null_ ));
+DATA(insert OID = 2905 (  timestamptypmodin   	PGNSP PGUID 12 1 0 f f t f i 1 23 "1263" _null_ _null_ _null_	timestamptypmodin - _null_ ));
 DESCR("I/O typmod");
 DATA(insert OID = 2906 (  timestamptypmodout  	PGNSP PGUID 12 1 0 f f t f i 1 2275 "23" _null_ _null_ _null_	timestamptypmodout - _null_ ));
 DESCR("I/O typmod");
@@ -1701,7 +1701,7 @@ DATA(insert OID = 1350 (  timetz_in		   PGNSP PGUID 12 1 0 f f t f s 3 1266 "227
 DESCR("I/O");
 DATA(insert OID = 1351 (  timetz_out	   PGNSP PGUID 12 1 0 f f t f i 1 2275 "1266" _null_ _null_ _null_	timetz_out - _null_ ));
 DESCR("I/O");
-DATA(insert OID = 2911 (  timetztypmodin   	PGNSP PGUID 12 1 0 f f t f i 1 23 "1007" _null_ _null_ _null_	timetztypmodin - _null_ ));
+DATA(insert OID = 2911 (  timetztypmodin   	PGNSP PGUID 12 1 0 f f t f i 1 23 "1263" _null_ _null_ _null_	timetztypmodin - _null_ ));
 DESCR("I/O typmod");
 DATA(insert OID = 2912 (  timetztypmodout  	PGNSP PGUID 12 1 0 f f t f i 1 2275 "23" _null_ _null_ _null_	timetztypmodout - _null_ ));
 DESCR("I/O typmod");
@@ -2033,7 +2033,7 @@ DATA(insert OID = 1564 (  bit_in			PGNSP PGUID 12 1 0 f f t f i 3 1560 "2275 26
 DESCR("I/O");
 DATA(insert OID = 1565 (  bit_out			PGNSP PGUID 12 1 0 f f t f i 1 2275 "1560" _null_ _null_ _null_ bit_out - _null_ ));
 DESCR("I/O");
-DATA(insert OID = 2919 (  bittypmodin   	PGNSP PGUID 12 1 0 f f t f i 1 23 "1007" _null_ _null_ _null_	bittypmodin - _null_ ));
+DATA(insert OID = 2919 (  bittypmodin   	PGNSP PGUID 12 1 0 f f t f i 1 23 "1263" _null_ _null_ _null_	bittypmodin - _null_ ));
 DESCR("I/O typmod");
 DATA(insert OID = 2920 (  bittypmodout  	PGNSP PGUID 12 1 0 f f t f i 1 2275 "23" _null_ _null_ _null_	bittypmodout - _null_ ));
 DESCR("I/O typmod");
@@ -2062,7 +2062,7 @@ DATA(insert OID = 1579 (  varbit_in			PGNSP PGUID 12 1 0 f f t f i 3 1562 "2275
 DESCR("I/O");
 DATA(insert OID = 1580 (  varbit_out		PGNSP PGUID 12 1 0 f f t f i 1 2275 "1562" _null_ _null_ _null_ varbit_out - _null_ ));
 DESCR("I/O");
-DATA(insert OID = 2902 (  varbittypmodin   	PGNSP PGUID 12 1 0 f f t f i 1 23 "1007" _null_ _null_ _null_	varbittypmodin - _null_ ));
+DATA(insert OID = 2902 (  varbittypmodin   	PGNSP PGUID 12 1 0 f f t f i 1 23 "1263" _null_ _null_ _null_	varbittypmodin - _null_ ));
 DESCR("I/O typmod");
 DATA(insert OID = 2921 (  varbittypmodout  	PGNSP PGUID 12 1 0 f f t f i 1 2275 "23" _null_ _null_ _null_	varbittypmodout - _null_ ));
 DESCR("I/O typmod");
@@ -2485,7 +2485,7 @@ DATA(insert OID = 1701 ( numeric_in				PGNSP PGUID 12 1 0 f f t f i 3 1700 "2275
 DESCR("I/O");
 DATA(insert OID = 1702 ( numeric_out			PGNSP PGUID 12 1 0 f f t f i 1 2275 "1700" _null_ _null_ _null_ numeric_out - _null_ ));
 DESCR("I/O");
-DATA(insert OID = 2917 (  numerictypmodin   	PGNSP PGUID 12 1 0 f f t f i 1 23 "1007" _null_ _null_ _null_	numerictypmodin - _null_ ));
+DATA(insert OID = 2917 (  numerictypmodin   	PGNSP PGUID 12 1 0 f f t f i 1 23 "1263" _null_ _null_ _null_	numerictypmodin - _null_ ));
 DESCR("I/O typmod");
 DATA(insert OID = 2918 (  numerictypmodout  	PGNSP PGUID 12 1 0 f f t f i 1 2275 "23" _null_ _null_ _null_	numerictypmodout - _null_ ));
 DESCR("I/O typmod");
diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h
index 753487348b4efe18a63bb3599cc366291092d6f3..01db6c616fc61df27373475e28382cea1a4464e5 100644
--- a/src/include/catalog/pg_type.h
+++ b/src/include/catalog/pg_type.h
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_type.h,v 1.185 2007/06/06 23:00:43 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_type.h,v 1.186 2007/06/15 20:56:52 tgl Exp $
  *
  * NOTES
  *	  the genbki.sh script reads this file and generates .bki
@@ -451,8 +451,11 @@ DESCR("access control list");
 #define ACLITEMOID		1033
 DATA(insert OID = 1034 (  _aclitem	 PGNSP PGUID -1 f b t \054 0 1033 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ ));
 DATA(insert OID = 1040 (  _macaddr	 PGNSP PGUID -1 f b t \054 0  829 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ ));
-DATA(insert OID = 1041 (  _inet    PGNSP PGUID -1 f b t \054 0	869 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ ));
-DATA(insert OID = 651  (  _cidr    PGNSP PGUID -1 f b t \054 0	650 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 1041 (  _inet		 PGNSP PGUID -1 f b t \054 0  869 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 651  (  _cidr		 PGNSP PGUID -1 f b t \054 0  650 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 1263 (  _cstring	 PGNSP PGUID -1 f b t \054 0 2275 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ ));
+#define CSTRINGARRAYOID		1263
+
 DATA(insert OID = 1042 ( bpchar		 PGNSP PGUID -1 f b t \054 0	0 1014 bpcharin bpcharout bpcharrecv bpcharsend bpchartypmodin bpchartypmodout - i x f 0 -1 0 _null_ _null_ ));
 DESCR("char(length), blank-padded string, fixed storage length");
 #define BPCHAROID		1042
@@ -554,10 +557,14 @@ DATA(insert OID = 2951 ( _uuid			PGNSP PGUID -1 f b t \054 0 2950 0 array_in arr
  * These cannot be used to define table columns, but are valid as function
  * argument and result types (if supported by the function's implementation
  * language).
+ *
+ * Note: cstring is a borderline case; it is still considered a pseudo-type,
+ * but there is now support for it in records and arrays.  Perhaps we should
+ * just treat it as a regular base type?
  */
 DATA(insert OID = 2249 ( record			PGNSP PGUID -1 f p t \054 0 0 0 record_in record_out record_recv record_send - - - d x f 0 -1 0 _null_ _null_ ));
 #define RECORDOID		2249
-DATA(insert OID = 2275 ( cstring		PGNSP PGUID -2 f p t \054 0 0 0 cstring_in cstring_out cstring_recv cstring_send - - - c p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 2275 ( cstring		PGNSP PGUID -2 f p t \054 0 0 1263 cstring_in cstring_out cstring_recv cstring_send - - - c p f 0 -1 0 _null_ _null_ ));
 #define CSTRINGOID		2275
 DATA(insert OID = 2276 ( any			PGNSP PGUID  4 t p t \054 0 0 0 any_in any_out - - - - - i p f 0 -1 0 _null_ _null_ ));
 #define ANYOID			2276
diff --git a/src/include/utils/array.h b/src/include/utils/array.h
index 534adef53f6d36464f73008a3cfa4f8c70c43732..69a2178cf53c7e58c010cd48381fdc6eccdcb478 100644
--- a/src/include/utils/array.h
+++ b/src/include/utils/array.h
@@ -49,7 +49,7 @@
  * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/array.h,v 1.64 2007/03/27 23:21:12 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/utils/array.h,v 1.65 2007/06/15 20:56:52 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -256,7 +256,7 @@ extern void mda_get_range(int n, int *span, const int *st, const int *endp);
 extern void mda_get_prod(int n, const int *range, int *prod);
 extern void mda_get_offset_values(int n, int *dist, const int *prod, const int *span);
 extern int	mda_next_tuple(int n, int *curr, const int *span);
-extern int32 *ArrayGetTypmods(ArrayType *arr, int *n);
+extern int32 *ArrayGetIntegerTypmods(ArrayType *arr, int *n);
 
 /*
  * prototypes for functions defined in array_userfuncs.c
diff --git a/src/test/regress/expected/type_sanity.out b/src/test/regress/expected/type_sanity.out
index 702cf7eecf1003a9b73c049196ccf963a675f4c0..2a551a7d0b89b332631d47f11a4d1f209f6abf06 100644
--- a/src/test/regress/expected/type_sanity.out
+++ b/src/test/regress/expected/type_sanity.out
@@ -227,7 +227,7 @@ SELECT p1.oid, p1.typname, p2.oid, p2.proname
 FROM pg_type AS p1, pg_proc AS p2
 WHERE p1.typmodin = p2.oid AND p1.typtype in ('b', 'p') AND NOT
     (p2.pronargs = 1 AND
-     p2.proargtypes[0] = 'int4[]'::regtype AND
+     p2.proargtypes[0] = 'cstring[]'::regtype AND
      p2.prorettype = 'int4'::regtype AND NOT p2.proretset);
  oid | typname | oid | proname 
 -----+---------+-----+---------
diff --git a/src/test/regress/sql/type_sanity.sql b/src/test/regress/sql/type_sanity.sql
index e549fd74892b7ddd9d4868cb5d61dc33fae1af3d..d0967e69c92cc09d606bb35e53a19b392c6fa183 100644
--- a/src/test/regress/sql/type_sanity.sql
+++ b/src/test/regress/sql/type_sanity.sql
@@ -176,7 +176,7 @@ SELECT p1.oid, p1.typname, p2.oid, p2.proname
 FROM pg_type AS p1, pg_proc AS p2
 WHERE p1.typmodin = p2.oid AND p1.typtype in ('b', 'p') AND NOT
     (p2.pronargs = 1 AND
-     p2.proargtypes[0] = 'int4[]'::regtype AND
+     p2.proargtypes[0] = 'cstring[]'::regtype AND
      p2.prorettype = 'int4'::regtype AND NOT p2.proretset);
 
 -- Check for bogus typmodout routines