diff --git a/doc/src/sgml/datatype.sgml b/doc/src/sgml/datatype.sgml
index 93f733e50fd38dab93905927496a1b46a48773f3..bbbc85197bb725b4df47fc3b9e85460d0918f80c 100644
--- a/doc/src/sgml/datatype.sgml
+++ b/doc/src/sgml/datatype.sgml
@@ -1,5 +1,5 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.53 2001/05/12 22:51:34 petere Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.54 2001/05/21 16:54:45 petere Exp $
 -->
 
  <chapter id="datatype">
@@ -550,31 +550,13 @@ CREATE TABLE <replaceable class="parameter">tablename</replaceable> (<replaceabl
     <see>character strings</see>
    </indexterm>
 
-   <para>
-    <acronym>SQL</acronym> defines two primary character types:
-    <type>character</type> and <type>character varying</type>. 
-    <productname>Postgres</productname> supports these types, in
-    addition to the more general <type>text</type> type, 
-    which unlike <type>character varying</type>
-    does not require an explicit declared upper
-    limit on the size of the field.
-   </para>
-
-   <para>
-    Refer to <xref linkend="sql-syntax-strings"> for information about
-    the syntax of string literals, and to <xref linkend="functions">
-    for information about available operators and functions.
-   </para>
-
-   <para>
     <table tocentry="1">
      <title>Character Types</title>
-     <tgroup cols="4">
+     <tgroup cols="3">
       <thead>
        <row>
 	<entry>Type Name</entry>
 	<entry>Storage</entry>
-	<entry>Recommendation</entry>
 	<entry>Description</entry>
        </row>
       </thead>
@@ -582,33 +564,115 @@ CREATE TABLE <replaceable class="parameter">tablename</replaceable> (<replaceabl
        <row>
 	<entry>character(n), char(n)</entry>
 	<entry>(4+n) bytes</entry>
-	<entry><acronym>SQL</acronym>-compatible</entry>
 	<entry>Fixed-length blank padded</entry>
        </row>
        <row>
 	<entry>character varying(n), varchar(n)</entry>
 	<entry>(4+n) bytes</entry>
-	<entry><acronym>SQL</acronym>-compatible</entry>
 	<entry>Variable-length with limit</entry>
        </row>
        <row>
 	<entry>text</entry>
 	<entry>(4+n) bytes</entry>
-	<entry>Most flexible</entry>
 	<entry>Variable unlimited length</entry>
        </row>
       </tbody>
      </tgroup>
     </table>
 
-    <note>
-     <para>
-      Although the type <type>text</type> is not SQL-compliant, many
-      other RDBMS packages have it as well.
-     </para>
-    </note>
+   <para>
+    <acronym>SQL</acronym> defines two primary character types:
+    <type>character(<replaceable>n</>)</type> and <type>character
+    varying(<replaceable>n</>)</type>, where <replaceable>n</> is a
+    positive integer.  Both of these types can store strings up to
+    <replaceable>n</> characters in length.  An attempt to store a
+    longer string into a column of these types will result in an
+    error, unless the excess characters are all spaces, in which case
+    the string will be truncated to the maximum length.  (This
+    somewhat bizarre exception is required by the SQL standard.)  If
+    the string to be stored is shorter than the declared length,
+    values of type <type>character</type> will be space-padded; values
+    of type <type>character varying</type> will simply store the
+    shorter string.
+   </para>
+
+   <note>
+    <para>
+     Prior to PostgreSQL 7.2, strings that were too long were silently
+     truncated, no error was raised.
+    </para>
+   </note>
+
+   <para>
+    The notations <type>char(<replaceable>n</>)</type> and
+    <type>varchar(<replaceable>n</>)</type> are aliases for
+    <type>character(<replaceable>n</>)</type> and <type>character
+    varying(<replaceable>n</>)</type>,
+    respectively. <type>character</type> without length specifier is
+    equivalent to <type>character(1)</type>; if <type>character
+    varying</type> is used without length specifier, the type accepts
+    strings of any size.  The latter is a PostgreSQL extension.
    </para>
 
+   <para>
+    In addition, <productname>PostgreSQL</productname> supports the
+    more general <type>text</type> type, which stores strings of any
+    length.  Unlike <type>character varying</type>, <type>text</type>
+    does not require an explicit declared upper limit on the size of
+    the string.  Although the type <type>text</type> is not in the SQL
+    standard, many other RDBMS packages have it as well.
+   </para>
+
+   <para>
+    Refer to <xref linkend="sql-syntax-strings"> for information about
+    the syntax of string literals, and to <xref linkend="functions">
+    for information about available operators and functions.
+   </para>
+
+   <tip>
+    <para>
+     There are no performance differences between these three types,
+     apart from the increased storage size when using the blank-padded
+     type.
+    </para>
+   </tip>
+
+   <example>
+    <title>Using the character types</title>
+
+<programlisting>
+CREATE TABLE test1 (a character(4));
+INSERT INTO test1 VALUES ('ok');
+SELECT a, char_length(a) FROM test1; -- <co id="co.datatype-char">
+<computeroutput>
+  a   | char_length
+------+-------------
+ ok   |           4
+</computeroutput>
+
+CREATE TABLE test2 (b varchar(5));
+INSERT INTO test2 VALUES ('ok');
+INSERT INTO test2 VALUES ('good      ');
+INSERT INTO test2 VALUES ('too long');
+<computeroutput>ERROR:  value too long for type character varying(5)</computeroutput>
+SELECT b, char_length(b) FROM test2;
+<computeroutput>
+   b   | char_length
+-------+-------------
+ ok    |           2
+ good  |           5
+</computeroutput>
+</programlisting>
+    <calloutlist>
+     <callout arearefs="co.datatype-char">
+      <para>
+       The <function>char_length</function> function is discussed in
+       <xref linkend="functions-string">.
+      </para>
+     </callout>
+    </calloutlist>
+   </example>
+
    <para>
     There are two other fixed-length character types in
     <productname>Postgres</productname>.  The <type>name</type> type
@@ -625,7 +689,6 @@ CREATE TABLE <replaceable class="parameter">tablename</replaceable> (<replaceabl
     enumeration type.
    </para>
 
-   <para>
     <table tocentry="1">
      <title>Specialty Character Type</title>
      <tgroup cols="3">
@@ -650,7 +713,6 @@ CREATE TABLE <replaceable class="parameter">tablename</replaceable> (<replaceabl
       </tbody>
      </tgroup>
     </table>
-   </para>
 
   </sect1>
 
diff --git a/src/backend/utils/adt/varchar.c b/src/backend/utils/adt/varchar.c
index 588c735ca10faa6f703b719dbf80d1f062d9f17e..467a5cf7de3975223533af95ce35804d539949ac 100644
--- a/src/backend/utils/adt/varchar.c
+++ b/src/backend/utils/adt/varchar.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/varchar.c,v 1.77 2001/05/03 19:00:36 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/varchar.c,v 1.78 2001/05/21 16:54:46 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -55,9 +55,11 @@
  *****************************************************************************/
 
 /*
- * bpcharin -
- *	  converts a string of char() type to the internal representation.
- *	  len is the length specified in () plus VARHDRSZ bytes.
+ * Convert a C string to CHARACTER internal representation.  atttypmod
+ * is the declared length of the type plus VARHDRSZ.
+ *
+ * If the C 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)
@@ -71,30 +73,33 @@ bpcharin(PG_FUNCTION_ARGS)
 	int32		atttypmod = PG_GETARG_INT32(2);
 	BpChar	   *result;
 	char	   *r;
-	int			len;
+	size_t		len, maxlen;
 	int			i;
 
-	if (atttypmod < (int32) VARHDRSZ)
+	len = strlen(s);
+	maxlen = atttypmod - VARHDRSZ;
+
+	if (atttypmod >= (int32) VARHDRSZ && len > maxlen)
 	{
-		/* If typmod is -1 (or invalid), use the actual string length */
-		len = strlen(s);
-		atttypmod = len + VARHDRSZ;
-	}
-	else
 #ifdef MULTIBYTE
-	{
+		size_t mbmaxlen = pg_mbcliplen(s, len, maxlen);
 
-		/*
-		 * truncate multi-byte string preserving multi-byte boundary
-		 */
-		len = pg_mbcliplen(s, atttypmod - VARHDRSZ, atttypmod - VARHDRSZ);
-	}
+		if (strspn(s + mbmaxlen, " ") == len - mbmaxlen)
+			len = mbmaxlen;
 #else
-		len = atttypmod - VARHDRSZ;
+		if (strspn(s + maxlen, " ") == len - maxlen)
+			/* clip extra spaces */
+			len = maxlen;
 #endif
+		else
+			elog(ERROR, "value too long for type character(%d)", maxlen);
+	}
+	else
+		/* If typmod is -1 (or invalid), use the actual string length */
+		maxlen = len;
 
-	result = (BpChar *) palloc(atttypmod);
-	VARATT_SIZEP(result) = atttypmod;
+	result = palloc(maxlen + VARHDRSZ);
+	VARATT_SIZEP(result) = maxlen + VARHDRSZ;
 	r = VARDATA(result);
 	for (i = 0; i < len; i++, r++, s++)
 	{
@@ -108,16 +113,16 @@ bpcharin(PG_FUNCTION_ARGS)
 #endif
 
 	/* blank pad the string if necessary */
-#ifdef MULTIBYTE
-	for (; i < atttypmod - VARHDRSZ; i++)
-#else
-	for (; i < len; i++)
-#endif
+	for (; i < maxlen; i++)
 		*r++ = ' ';
 
 	PG_RETURN_BPCHAR_P(result);
 }
 
+
+/*
+ * Convert a CHARACTER value to a C string.
+ */
 Datum
 bpcharout(PG_FUNCTION_ARGS)
 {
@@ -138,75 +143,70 @@ bpcharout(PG_FUNCTION_ARGS)
 	PG_RETURN_CSTRING(result);
 }
 
-/* bpchar()
- * Converts a char() type to a specific internal length.
- * len is the length specified in () plus VARHDRSZ bytes.
+
+/*
+ * Converts a CHARACTER type to the specified size.  maxlen is the new
+ * declared length plus VARHDRSZ bytes.  Truncation
+ * rules see bpcharin() above.
  */
 Datum
 bpchar(PG_FUNCTION_ARGS)
 {
-	BpChar	   *str = PG_GETARG_BPCHAR_P(0);
-	int32		len = PG_GETARG_INT32(1);
+	BpChar	   *source = PG_GETARG_BPCHAR_P(0);
+	int32		maxlen = PG_GETARG_INT32(1);
 	BpChar	   *result;
-	char	   *r,
-			   *s;
-	int			rlen,
-				slen;
+	int32		len;
+	char	   *r;
+	char	   *s;
 	int			i;
 
+	len = VARSIZE(source);
 	/* No work if typmod is invalid or supplied data matches it already */
-	if (len < (int32) VARHDRSZ || len == VARSIZE(str))
-		PG_RETURN_BPCHAR_P(str);
+	if (len < (int32) VARHDRSZ || len == maxlen)
+		PG_RETURN_BPCHAR_P(source);
 
-	rlen = len - VARHDRSZ;
-
-#ifdef STRINGDEBUG
-	printf("bpchar- convert string length %d (%d) ->%d (%d)\n",
-		   VARSIZE(str) - VARHDRSZ, VARSIZE(str), rlen, len);
-#endif
+	if (len > maxlen)
+	{
+#ifdef MULTIBYTE
+		size_t		maxmblen;
 
-	result = (BpChar *) palloc(len);
-	VARATT_SIZEP(result) = len;
-	r = VARDATA(result);
+		maxmblen = pg_mbcliplen(VARDATA(source), len - VARHDRSZ,
+								maxlen - VARHDRSZ) + VARHDRSZ;
 
-#ifdef MULTIBYTE
+		for (i = maxmblen - VARHDRSZ; i < len - VARHDRSZ; i++)
+			if (*(VARDATA(source) + i) != ' ')
+				elog(ERROR, "value too long for type character(%d)",
+					 maxlen - VARHDRSZ);
 
-	/*
-	 * truncate multi-byte string in a way not to break multi-byte
-	 * boundary
-	 */
-	if (VARSIZE(str) > len)
-		slen = pg_mbcliplen(VARDATA(str), VARSIZE(str) - VARHDRSZ, rlen);
-	else
-		slen = VARSIZE(str) - VARHDRSZ;
+		len = maxmblen;
 #else
-	slen = VARSIZE(str) - VARHDRSZ;
-#endif
-	s = VARDATA(str);
+		for (i = maxlen - VARHDRSZ; i < len - VARHDRSZ; i++)
+			if (*(VARDATA(source) + i) != ' ')
+				elog(ERROR, "value too long for type character(%d)",
+					 maxlen - VARHDRSZ);
 
-#ifdef STRINGDEBUG
-	printf("bpchar- string is '");
+		/* clip extra spaces */
+		len = maxlen;
 #endif
-
-	for (i = 0; (i < rlen) && (i < slen); i++)
-	{
-#ifdef STRINGDEBUG
-		printf("%c", *s);
-#endif
-		*r++ = *s++;
 	}
 
-#ifdef STRINGDEBUG
-	printf("'\n");
-#endif
+	s = VARDATA(source);
+
+	result = palloc(maxlen);
+	VARATT_SIZEP(result) = maxlen;
+	r = VARDATA(result);
+
+	for (i = 0; (i < maxlen - VARHDRSZ) && (i < len - VARHDRSZ); i++)
+		*r++ = *s++;
 
 	/* blank pad the string if necessary */
-	for (; i < rlen; i++)
+	for (; i < maxlen - VARHDRSZ; i++)
 		*r++ = ' ';
 
 	PG_RETURN_BPCHAR_P(result);
 }
 
+
 /* _bpchar()
  * Converts an array of char() elements to a specific internal length.
  * len is the length specified in () plus VARHDRSZ bytes.
@@ -330,9 +330,11 @@ name_bpchar(PG_FUNCTION_ARGS)
  *****************************************************************************/
 
 /*
- * varcharin -
- *	  converts a string of varchar() type to the internal representation.
- *	  len is the length specified in () plus VARHDRSZ bytes.
+ * Convert a C string to VARCHAR internal representation.  atttypmod
+ * is the declared length of the type plus VARHDRSZ.
+ *
+ * If the C 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)
@@ -345,37 +347,52 @@ varcharin(PG_FUNCTION_ARGS)
 #endif
 	int32		atttypmod = PG_GETARG_INT32(2);
 	VarChar    *result;
-	int			len;
+	size_t		len, maxlen;
+
+	len = strlen(s);
+	maxlen = atttypmod - VARHDRSZ;
 
-	len = strlen(s) + VARHDRSZ;
-	if (atttypmod >= (int32) VARHDRSZ && len > atttypmod)
+	if (atttypmod >= (int32) VARHDRSZ && len > maxlen)
+	{
 #ifdef MULTIBYTE
-		len = pg_mbcliplen(s, len - VARHDRSZ, atttypmod - VARHDRSZ) + VARHDRSZ;
+		size_t mbmaxlen = pg_mbcliplen(s, len, maxlen);
+
+		if (strspn(s + mbmaxlen, " ") == len - mbmaxlen)
+			len = mbmaxlen;
 #else
-		len = atttypmod;		/* clip the string at max length */
+		if (strspn(s + maxlen, " ") == len - maxlen)
+			/* clip extra spaces */
+			len = maxlen;
 #endif
+		else
+			elog(ERROR, "value too long for type character varying(%d)", maxlen);
+	}
 
-	result = (VarChar *) palloc(len);
-	VARATT_SIZEP(result) = len;
-	memcpy(VARDATA(result), s, len - VARHDRSZ);
+	result = palloc(len + VARHDRSZ);
+	VARATT_SIZEP(result) = len + VARHDRSZ;
+	memcpy(VARDATA(result), s, len);
 
 #ifdef CYR_RECODE
-	convertstr(VARDATA(result), len - VARHDRSZ, 0);
+	convertstr(VARDATA(result), len, 0);
 #endif
 
 	PG_RETURN_VARCHAR_P(result);
 }
 
+
+/*
+ * Convert a VARCHAR value to a C string.
+ */
 Datum
 varcharout(PG_FUNCTION_ARGS)
 {
 	VarChar    *s = PG_GETARG_VARCHAR_P(0);
 	char	   *result;
-	int			len;
+	int32		len;
 
 	/* copy and add null term */
 	len = VARSIZE(s) - VARHDRSZ;
-	result = (char *) palloc(len + 1);
+	result = palloc(len + 1);
 	memcpy(result, VARDATA(s), len);
 	result[len] = '\0';
 
@@ -386,42 +403,60 @@ varcharout(PG_FUNCTION_ARGS)
 	PG_RETURN_CSTRING(result);
 }
 
-/* varchar()
- * Converts a varchar() type to the specified size.
- * slen is the length specified in () plus VARHDRSZ bytes.
+
+/*
+ * Converts a VARCHAR type to the specified size.  maxlen is the new
+ * declared length plus VARHDRSZ bytes.  Truncation
+ * rules see varcharin() above.
  */
 Datum
 varchar(PG_FUNCTION_ARGS)
 {
-	VarChar    *s = PG_GETARG_VARCHAR_P(0);
-	int32		slen = PG_GETARG_INT32(1);
+	VarChar    *source = PG_GETARG_VARCHAR_P(0);
+	int32		maxlen = PG_GETARG_INT32(1);
 	VarChar    *result;
-	int			len;
+	int32		len;
+	int			i;
 
-	len = VARSIZE(s);
-	if (slen < (int32) VARHDRSZ || len <= slen)
-		PG_RETURN_VARCHAR_P(s);
+	len = VARSIZE(source);
+	if (maxlen < (int32) VARHDRSZ || len <= maxlen)
+		PG_RETURN_VARCHAR_P(source);
 
-	/* only reach here if we need to truncate string... */
+	/* only reach here if string is too long... */
 
 #ifdef MULTIBYTE
+	{
+		size_t		maxmblen;
 
-	/*
-	 * truncate multi-byte string preserving multi-byte boundary
-	 */
-	len = pg_mbcliplen(VARDATA(s), slen - VARHDRSZ, slen - VARHDRSZ);
-	slen = len + VARHDRSZ;
+		/* truncate multi-byte string preserving multi-byte boundary */
+		maxmblen = pg_mbcliplen(VARDATA(source), len - VARHDRSZ,
+								maxlen - VARHDRSZ) + VARHDRSZ;
+
+		for (i = maxmblen - VARHDRSZ; i < len - VARHDRSZ; i++)
+			if (*(VARDATA(source) + i) != ' ')
+				elog(ERROR, "value too long for type character varying(%d)",
+					 maxlen - VARHDRSZ);
+
+		len = maxmblen;
+	}
 #else
-	len = slen - VARHDRSZ;
+	for (i = maxlen - VARHDRSZ; i < len - VARHDRSZ; i++)
+		if (*(VARDATA(source) + i) != ' ')
+			elog(ERROR, "value too long for type character varying(%d)",
+				 maxlen - VARHDRSZ);
+
+	/* clip extra spaces */
+	len = maxlen;
 #endif
 
-	result = (VarChar *) palloc(slen);
-	VARATT_SIZEP(result) = slen;
-	memcpy(VARDATA(result), VARDATA(s), len);
+	result = palloc(len);
+	VARATT_SIZEP(result) = len;
+	memcpy(VARDATA(result), VARDATA(source), len - VARHDRSZ);
 
 	PG_RETURN_VARCHAR_P(result);
 }
 
+
 /* _varchar()
  * Converts an array of varchar() elements to the specified size.
  * len is the length specified in () plus VARHDRSZ bytes.
@@ -452,6 +487,12 @@ _varchar(PG_FUNCTION_ARGS)
 	return array_map(&locfcinfo, VARCHAROID, VARCHAROID);
 }
 
+
+
+/*****************************************************************************
+ * Exported functions
+ *****************************************************************************/
+
 /* "True" length (not counting trailing blanks) of a BpChar */
 static int
 bcTruelen(BpChar *arg)
diff --git a/src/test/regress/expected/arrays.out b/src/test/regress/expected/arrays.out
index b68783806402aed6a04cc6de7b54b63056d77fe7..74c1008d907582c812530250cb9b8a46104cc467 100644
--- a/src/test/regress/expected/arrays.out
+++ b/src/test/regress/expected/arrays.out
@@ -1,6 +1,32 @@
 --
 -- ARRAYS
 --
+CREATE TABLE arrtest (
+	a 			int2[],
+	b 			int4[][][],
+	c 			name[],
+	d			text[][], 
+	e 			float8[],
+	f			char(5)[],
+	g			varchar(5)[]
+);
+--
+-- only this array as a 0-based 'e', the others are 1-based.
+-- 'e' is also a large object.
+--
+INSERT INTO arrtest (a[5], b[2][1][2], c, d, f, g)
+   VALUES ('{1,2,3,4,5}', '{{{},{1,2}}}', '{}', '{}', '{}', '{}');
+UPDATE arrtest SET e[0] = '1.1';
+UPDATE arrtest SET e[1] = '2.2';
+INSERT INTO arrtest (f)
+   VALUES ('{"too long"}');
+ERROR:  value too long for type character(5)
+INSERT INTO arrtest (a, b[2][2][1], c, d, e, f, g)
+   VALUES ('{11,12,23}', '{{3,4},{4,5}}', '{"foobar"}', 
+           '{{"elt1", "elt2"}}', '{"3.4", "6.7"}',
+           '{"abc","abcde"}', '{"abc","abcde"}');
+INSERT INTO arrtest (a, b[1][2][2], c, d[2][1])
+   VALUES ('{}', '{3,4}', '{foo,bar}', '{bar,foo}');
 SELECT * FROM arrtest;
       a      |        b        |       c       |         d         |       e       |         f         |        g        
 -------------+-----------------+---------------+-------------------+---------------+-------------------+-----------------
@@ -75,8 +101,8 @@ SELECT a,b,c FROM arrtest;
        a       |           b           |           c           
 ---------------+-----------------------+-----------------------
  {16,25,3,4,5} | {{{113,142},{1,147}}} | {}
- {16,25,23}    | {{3,4},{4,5}}         | {"foobar","new_word"}
  {}            | {3,4}                 | {"foo","new_word"}
+ {16,25,23}    | {{3,4},{4,5}}         | {"foobar","new_word"}
 (3 rows)
 
 SELECT a[1:3],
@@ -87,7 +113,7 @@ SELECT a[1:3],
      a      |           b           |           c           |     d      
 ------------+-----------------------+-----------------------+------------
  {16,25,3}  | {{{113,142},{1,147}}} |                       | 
- {16,25,23} |                       | {"foobar","new_word"} | {{"elt2"}}
             |                       | {"foo","new_word"}    | 
+ {16,25,23} |                       | {"foobar","new_word"} | {{"elt2"}}
 (3 rows)
 
diff --git a/src/test/regress/expected/char.out b/src/test/regress/expected/char.out
index 63606fba2d254545829fd0398fec1b6221954709..0c46e07976233fc0c6e7e3f947b5c1c490111189 100644
--- a/src/test/regress/expected/char.out
+++ b/src/test/regress/expected/char.out
@@ -1,6 +1,5 @@
 --
 -- CHAR
--- all inputs are SILENTLY truncated at 1 character
 --
 -- fixed-length by value
 -- internally passed by value if <= 4 bytes in storage
@@ -24,6 +23,8 @@ INSERT INTO CHAR_TBL (f1) VALUES ('3');
 INSERT INTO CHAR_TBL (f1) VALUES ('');
 -- try char's of greater than 1 length 
 INSERT INTO CHAR_TBL (f1) VALUES ('cd');
+ERROR:  value too long for type character(1)
+INSERT INTO CHAR_TBL (f1) VALUES ('c     ');
 SELECT '' AS seven, CHAR_TBL.*;
  seven | f1 
 -------+----
@@ -108,6 +109,8 @@ INSERT INTO CHAR_TBL (f1) VALUES ('a');
 INSERT INTO CHAR_TBL (f1) VALUES ('ab');
 INSERT INTO CHAR_TBL (f1) VALUES ('abcd');
 INSERT INTO CHAR_TBL (f1) VALUES ('abcde');
+ERROR:  value too long for type character(4)
+INSERT INTO CHAR_TBL (f1) VALUES ('abcd    ');
 SELECT '' AS four, CHAR_TBL.*;
  four |  f1  
 ------+------
diff --git a/src/test/regress/expected/create_misc.out b/src/test/regress/expected/create_misc.out
index add55bc767afd1b57fe409bd0a93f07222f0a20f..c7600fd13ff0d329bcc4130d7f6da13760d3de2e 100644
--- a/src/test/regress/expected/create_misc.out
+++ b/src/test/regress/expected/create_misc.out
@@ -121,23 +121,6 @@ INSERT INTO f_star (class, f)
    VALUES ('f', '(11111111,33333333),(22222222,44444444)'::polygon);
 INSERT INTO f_star (class) VALUES ('f');
 --
--- ARRAYS
---
---
--- only this array as a 0-based 'e', the others are 1-based.
--- 'e' is also a large object.
---
-INSERT INTO arrtest (a[5], b[2][1][2], c, d, f, g)
-   VALUES ('{1,2,3,4,5}', '{{{},{1,2}}}', '{}', '{}', '{}', '{}');
-UPDATE arrtest SET e[0] = '1.1';
-UPDATE arrtest SET e[1] = '2.2';
-INSERT INTO arrtest (a, b[2][2][1], c, d, e, f, g)
-   VALUES ('{11,12,23}', '{{3,4},{4,5}}', '{"foobar"}', 
-           '{{"elt1", "elt2"}}', '{"3.4", "6.7"}',
-           '{"abc","abcdefgh"}', '{"abc","abcdefgh"}');
-INSERT INTO arrtest (a, b[1][2][2], c, d[2][1])
-   VALUES ('{}', '{3,4}', '{foo,bar}', '{bar,foo}');
---
 -- for internal portal (cursor) tests
 --
 CREATE TABLE iportaltest (
diff --git a/src/test/regress/expected/create_table.out b/src/test/regress/expected/create_table.out
index a0ddd5ef609a3367d567673255ea75877381b1e7..3734960691d848c966748ed2d23c2cc32b0ec74e 100644
--- a/src/test/regress/expected/create_table.out
+++ b/src/test/regress/expected/create_table.out
@@ -147,15 +147,6 @@ CREATE TABLE aggtest (
 	a 			int2,
 	b			float4
 );
-CREATE TABLE arrtest (
-	a 			int2[],
-	b 			int4[][][],
-	c 			name[],
-	d			text[][], 
-	e 			float8[],
-	f			char(5)[],
-	g			varchar(5)[]
-);
 CREATE TABLE hash_i4_heap (
 	seqno 		int4,
 	random 		int4
diff --git a/src/test/regress/expected/strings.out b/src/test/regress/expected/strings.out
index e59ba8e1df5f8494f7884339319af1098b17635f..7562a25fdca5399ae0c4b745243c76a38b4e1afe 100644
--- a/src/test/regress/expected/strings.out
+++ b/src/test/regress/expected/strings.out
@@ -45,11 +45,13 @@ SELECT CAST(name 'namefield' AS text) AS "text(name)";
  namefield
 (1 row)
 
-SELECT CAST(f1 AS char(10)) AS "char(text)" FROM TEXT_TBL;
- char(text) 
-------------
- doh!      
- hi de ho n
+SELECT CAST(f1 AS char(10)) AS "char(text)" FROM TEXT_TBL; -- fail
+ERROR:  value too long for type character(10)
+SELECT CAST(f1 AS char(20)) AS "char(text)" FROM TEXT_TBL;
+      char(text)      
+----------------------
+ doh!                
+ hi de ho neighbor   
 (2 rows)
 
 SELECT CAST(f1 AS char(10)) AS "char(varchar)" FROM VARCHAR_TBL;
@@ -479,10 +481,10 @@ SELECT text 'text' || ' and unknown' AS "Concat text to unknown type";
  text and unknown
 (1 row)
 
-SELECT text 'text' || char(10) ' and characters' AS "Concat text to char";
+SELECT text 'text' || char(20) ' and characters' AS "Concat text to char";
  Concat text to char 
 ---------------------
- text and chara
+ text and characters
 (1 row)
 
 SELECT text 'text' || varchar ' and varchar' AS "Concat text to varchar";
diff --git a/src/test/regress/expected/varchar.out b/src/test/regress/expected/varchar.out
index 5f4c0f1f56f3b56cad70030f4bc46d8113652546..e33782eed74a818666bcc93591cd3d6fafeb9df5 100644
--- a/src/test/regress/expected/varchar.out
+++ b/src/test/regress/expected/varchar.out
@@ -12,6 +12,8 @@ INSERT INTO VARCHAR_TBL (f1) VALUES ('3');
 INSERT INTO VARCHAR_TBL (f1) VALUES ('');
 -- try varchar's of greater than 1 length 
 INSERT INTO VARCHAR_TBL (f1) VALUES ('cd');
+ERROR:  value too long for type character varying(1)
+INSERT INTO VARCHAR_TBL (f1) VALUES ('c     ');
 SELECT '' AS seven, VARCHAR_TBL.*;
  seven | f1 
 -------+----
@@ -96,6 +98,8 @@ INSERT INTO VARCHAR_TBL (f1) VALUES ('a');
 INSERT INTO VARCHAR_TBL (f1) VALUES ('ab');
 INSERT INTO VARCHAR_TBL (f1) VALUES ('abcd');
 INSERT INTO VARCHAR_TBL (f1) VALUES ('abcde');
+ERROR:  value too long for type character varying(4)
+INSERT INTO VARCHAR_TBL (f1) VALUES ('abcd    ');
 SELECT '' AS four, VARCHAR_TBL.*;
  four |  f1  
 ------+------
diff --git a/src/test/regress/sql/arrays.sql b/src/test/regress/sql/arrays.sql
index 3b02acf6427252a14e57a2aca414fbc28e9a8ad7..a3300eae129d2fea48c7961bf8b5fec5b9cc1ffb 100644
--- a/src/test/regress/sql/arrays.sql
+++ b/src/test/regress/sql/arrays.sql
@@ -2,6 +2,40 @@
 -- ARRAYS
 --
 
+CREATE TABLE arrtest (
+	a 			int2[],
+	b 			int4[][][],
+	c 			name[],
+	d			text[][], 
+	e 			float8[],
+	f			char(5)[],
+	g			varchar(5)[]
+);
+
+--
+-- only this array as a 0-based 'e', the others are 1-based.
+-- 'e' is also a large object.
+--
+
+INSERT INTO arrtest (a[5], b[2][1][2], c, d, f, g)
+   VALUES ('{1,2,3,4,5}', '{{{},{1,2}}}', '{}', '{}', '{}', '{}');
+
+UPDATE arrtest SET e[0] = '1.1';
+
+UPDATE arrtest SET e[1] = '2.2';
+
+INSERT INTO arrtest (f)
+   VALUES ('{"too long"}');
+
+INSERT INTO arrtest (a, b[2][2][1], c, d, e, f, g)
+   VALUES ('{11,12,23}', '{{3,4},{4,5}}', '{"foobar"}', 
+           '{{"elt1", "elt2"}}', '{"3.4", "6.7"}',
+           '{"abc","abcde"}', '{"abc","abcde"}');
+
+INSERT INTO arrtest (a, b[1][2][2], c, d[2][1])
+   VALUES ('{}', '{3,4}', '{foo,bar}', '{bar,foo}');
+
+
 SELECT * FROM arrtest;
 
 SELECT arrtest.a[1],
diff --git a/src/test/regress/sql/char.sql b/src/test/regress/sql/char.sql
index ba7167fc659b167c63154c3a06a267f7a079ef70..049f22fad39e5cbbdc7203db59932981d61c6203 100644
--- a/src/test/regress/sql/char.sql
+++ b/src/test/regress/sql/char.sql
@@ -1,6 +1,5 @@
 --
 -- CHAR
--- all inputs are SILENTLY truncated at 1 character
 --
 
 -- fixed-length by value
@@ -30,6 +29,7 @@ INSERT INTO CHAR_TBL (f1) VALUES ('');
 
 -- try char's of greater than 1 length 
 INSERT INTO CHAR_TBL (f1) VALUES ('cd');
+INSERT INTO CHAR_TBL (f1) VALUES ('c     ');
 
 
 SELECT '' AS seven, CHAR_TBL.*;
@@ -70,6 +70,6 @@ INSERT INTO CHAR_TBL (f1) VALUES ('a');
 INSERT INTO CHAR_TBL (f1) VALUES ('ab');
 INSERT INTO CHAR_TBL (f1) VALUES ('abcd');
 INSERT INTO CHAR_TBL (f1) VALUES ('abcde');
+INSERT INTO CHAR_TBL (f1) VALUES ('abcd    ');
 
 SELECT '' AS four, CHAR_TBL.*;
-
diff --git a/src/test/regress/sql/create_misc.sql b/src/test/regress/sql/create_misc.sql
index cd73f64060513bb34dc15c48ec4b09cc506bfced..078450a754416d6fa421bebc42080f260b66f05f 100644
--- a/src/test/regress/sql/create_misc.sql
+++ b/src/test/regress/sql/create_misc.sql
@@ -188,30 +188,6 @@ INSERT INTO f_star (class, f)
 
 INSERT INTO f_star (class) VALUES ('f');
 
---
--- ARRAYS
---
-
---
--- only this array as a 0-based 'e', the others are 1-based.
--- 'e' is also a large object.
---
-
-INSERT INTO arrtest (a[5], b[2][1][2], c, d, f, g)
-   VALUES ('{1,2,3,4,5}', '{{{},{1,2}}}', '{}', '{}', '{}', '{}');
-
-UPDATE arrtest SET e[0] = '1.1';
-
-UPDATE arrtest SET e[1] = '2.2';
-
-INSERT INTO arrtest (a, b[2][2][1], c, d, e, f, g)
-   VALUES ('{11,12,23}', '{{3,4},{4,5}}', '{"foobar"}', 
-           '{{"elt1", "elt2"}}', '{"3.4", "6.7"}',
-           '{"abc","abcdefgh"}', '{"abc","abcdefgh"}');
-
-INSERT INTO arrtest (a, b[1][2][2], c, d[2][1])
-   VALUES ('{}', '{3,4}', '{foo,bar}', '{bar,foo}');
-
 
 --
 -- for internal portal (cursor) tests
diff --git a/src/test/regress/sql/create_table.sql b/src/test/regress/sql/create_table.sql
index fe5470894483fa7cfadcb5293966f8342bfb5023..b6a0a8fe603d37d6b071657a9a4238c8799ddcca 100644
--- a/src/test/regress/sql/create_table.sql
+++ b/src/test/regress/sql/create_table.sql
@@ -172,16 +172,6 @@ CREATE TABLE aggtest (
 	b			float4
 );
 
-CREATE TABLE arrtest (
-	a 			int2[],
-	b 			int4[][][],
-	c 			name[],
-	d			text[][], 
-	e 			float8[],
-	f			char(5)[],
-	g			varchar(5)[]
-);
-
 CREATE TABLE hash_i4_heap (
 	seqno 		int4,
 	random 		int4
diff --git a/src/test/regress/sql/strings.sql b/src/test/regress/sql/strings.sql
index f1c7d5f298911bd586f0bbb835030cc5acdc9578..56510f83dddc9eee78dadaae42adfbc6340d8933 100644
--- a/src/test/regress/sql/strings.sql
+++ b/src/test/regress/sql/strings.sql
@@ -25,7 +25,9 @@ SELECT CAST(f1 AS text) AS "text(varchar)" FROM VARCHAR_TBL;
 
 SELECT CAST(name 'namefield' AS text) AS "text(name)";
 
-SELECT CAST(f1 AS char(10)) AS "char(text)" FROM TEXT_TBL;
+SELECT CAST(f1 AS char(10)) AS "char(text)" FROM TEXT_TBL; -- fail
+
+SELECT CAST(f1 AS char(20)) AS "char(text)" FROM TEXT_TBL;
 
 SELECT CAST(f1 AS char(10)) AS "char(varchar)" FROM VARCHAR_TBL;
 
@@ -158,7 +160,7 @@ SELECT 'unknown' || ' and unknown' AS "Concat unknown types";
 
 SELECT text 'text' || ' and unknown' AS "Concat text to unknown type";
 
-SELECT text 'text' || char(10) ' and characters' AS "Concat text to char";
+SELECT text 'text' || char(20) ' and characters' AS "Concat text to char";
 
 SELECT text 'text' || varchar ' and varchar' AS "Concat text to varchar";
 
diff --git a/src/test/regress/sql/varchar.sql b/src/test/regress/sql/varchar.sql
index e28c8f9b932bc8e52f1fbbb82b8f591b53e79f94..70fa8afb4b3754bc06240f419f67363a9ec56f4b 100644
--- a/src/test/regress/sql/varchar.sql
+++ b/src/test/regress/sql/varchar.sql
@@ -20,6 +20,7 @@ INSERT INTO VARCHAR_TBL (f1) VALUES ('');
 
 -- try varchar's of greater than 1 length 
 INSERT INTO VARCHAR_TBL (f1) VALUES ('cd');
+INSERT INTO VARCHAR_TBL (f1) VALUES ('c     ');
 
 
 SELECT '' AS seven, VARCHAR_TBL.*;
@@ -60,6 +61,6 @@ INSERT INTO VARCHAR_TBL (f1) VALUES ('a');
 INSERT INTO VARCHAR_TBL (f1) VALUES ('ab');
 INSERT INTO VARCHAR_TBL (f1) VALUES ('abcd');
 INSERT INTO VARCHAR_TBL (f1) VALUES ('abcde');
+INSERT INTO VARCHAR_TBL (f1) VALUES ('abcd    ');
 
 SELECT '' AS four, VARCHAR_TBL.*;
-