diff --git a/src/backend/utils/adt/varchar.c b/src/backend/utils/adt/varchar.c
index cbd113bba859110fde6d48cee5faae0e0bcf360e..7f30f2bab6915cdc16cdbca6fab4ac7c69e25a41 100644
--- a/src/backend/utils/adt/varchar.c
+++ b/src/backend/utils/adt/varchar.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/varchar.c,v 1.30 1998/04/27 17:08:26 scrappy Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/varchar.c,v 1.31 1998/05/09 22:42:07 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -130,12 +130,103 @@ bpcharout(char *s)
 	return (result);
 }
 
+/* bpchar()
+ * Converts a char() type to a specific internal length.
+ * len is the length specified in () plus VARHDRSZ bytes.
+ */
+char *
+bpchar(char *s, int32 len)
+{
+	char	   *result,
+			   *r;
+	int			rlen, slen;
+	int			i;
+
+	if (s == NULL)
+		return ((char *) NULL);
+
+	if ((len == -1) || (len == VARSIZE(s)))
+		return (s);
+
+	rlen = len - VARHDRSZ;
+
+	if (rlen > 4096)
+		elog(ERROR, "bpchar: length of char() must be less than 4096");
+
+#ifdef STRINGDEBUG
+printf("bpchar- convert string length %d (%d) ->%d (%d)\n",
+ VARSIZE(s)-VARHDRSZ, VARSIZE(s), rlen, len);
+#endif
+
+	result = (char *) palloc(len);
+	VARSIZE(result) = len;
+	r = VARDATA(result);
+	slen = VARSIZE(s) - VARHDRSZ;
+	s = VARDATA(s);
+
+#ifdef STRINGDEBUG
+printf("bpchar- string is '");
+#endif
+
+	for (i = 0; (i < rlen) && (i < slen); i++)
+	{
+		if (*s == '\0')
+			break;
+
+#ifdef STRINGDEBUG
+printf("%c", *s);
+#endif
+
+		*r++ = *s++;
+	}
+
+#ifdef STRINGDEBUG
+printf("'\n");
+#endif
+
+	/* blank pad the string if necessary */
+	for (; i < rlen; i++)
+	{
+		*r++ = ' ';
+	}
+
+	return (result);
+} /* bpchar() */
+
+
+/* bpchar_char()
+ * Convert bpchar(1) to char.
+ */
+int32
+bpchar_char(char *s)
+{
+	return ((int32) *VARDATA(s));
+} /* char_bpchar() */
+
+
+/* char_bpchar()
+ * Convert char to bpchar(1).
+ */
+char *
+char_bpchar(int32 c)
+{
+	char *result;
+
+	result = palloc(VARHDRSZ+1);
+
+	VARSIZE(result) = VARHDRSZ+1;
+	*(VARDATA(result)) = (char) c;
+
+	return result;
+} /* char_bpchar() */
+
+
 /*****************************************************************************
  *	 varchar - varchar()													 *
  *****************************************************************************/
 
 /*
- * vcharin -
+ * varcharin -
  *	  converts a string of varchar() type to the internal representation.
  *	  len is the length specified in () plus VARHDRSZ bytes. (XXX dummy is here
  *	  because we pass typelem as the second argument for array_in.)
@@ -193,6 +284,38 @@ varcharout(char *s)
 	return (result);
 }
 
+/* varchar()
+ * Converts a varchar() type to the specified size.
+ * slen is the length specified in () plus VARHDRSZ bytes.
+ */
+char *
+varchar(char *s, int32 slen)
+{
+	char	   *result;
+	int			len;
+
+	if (s == NULL)
+		return ((char *) NULL);
+
+	len = VARSIZE(s);
+	if ((slen == -1) || (len <= slen))
+		return ((char *) s);
+
+	/* only reach here if we need to truncate string... */
+
+	len = slen - VARHDRSZ;
+
+	if (len > 4096)
+		elog(ERROR, "varchar: length of varchar() must be less than 4096");
+
+	result = (char *) palloc(slen);
+	VARSIZE(result) = slen;
+	strncpy(VARDATA(result), VARDATA(s), len);
+
+	return (result);
+} /* varchar() */
+
+
 /*****************************************************************************
  *	Comparison Functions used for bpchar
  *****************************************************************************/
diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c
index d094924db1463ff848d15894d5accf622c54e0cf..1fad410b85aa8ea1e76352c18c51a50c1c47f826 100644
--- a/src/backend/utils/adt/varlena.c
+++ b/src/backend/utils/adt/varlena.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.33 1998/04/27 17:08:28 scrappy Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.34 1998/05/09 22:42:07 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -255,8 +255,6 @@ textoctetlen(text *t)
  * Updated by Thomas, Thomas.Lockhart@jpl.nasa.gov 1997-07-10.
  * Allocate space for output in all cases.
  * XXX - thomas 1997-07-10
- * As in previous code, allow concatenation when one string is NULL.
- * Is this OK?
  */
 text *
 textcat(text *t1, text *t2)
@@ -267,33 +265,34 @@ textcat(text *t1, text *t2)
 	char	   *ptr;
 	text	   *result;
 
-	if (!PointerIsValid(t1) && !PointerIsValid(t2))
+	if (!PointerIsValid(t1) || !PointerIsValid(t2))
 		return (NULL);
 
-	len1 = (PointerIsValid(t1) ? (VARSIZE(t1) - VARHDRSZ) : 0);
+	len1 = (VARSIZE(t1) - VARHDRSZ);
 	if (len1 < 0)
 		len1 = 0;
 	while (len1 > 0 && VARDATA(t1)[len1 - 1] == '\0')
 		len1--;
 
-	len2 = (PointerIsValid(t2) ? (VARSIZE(t2) - VARHDRSZ) : 0);
+	len2 = (VARSIZE(t2) - VARHDRSZ);
 	if (len2 < 0)
 		len2 = 0;
 	while (len2 > 0 && VARDATA(t2)[len2 - 1] == '\0')
 		len2--;
 
-	result = palloc(len = len1 + len2 + VARHDRSZ);
+	len = len1 + len2 + VARHDRSZ;
+	result = palloc(len);
+
+	/* Set size of result string... */
+	VARSIZE(result) = len;
 
 	/* Fill data field of result string... */
 	ptr = VARDATA(result);
-	if (PointerIsValid(t1))
+	if (len1 > 0)
 		memcpy(ptr, VARDATA(t1), len1);
-	if (PointerIsValid(t2))
+	if (len2 > 0)
 		memcpy(ptr + len1, VARDATA(t2), len2);
 
-	/* Set size of result string... */
-	VARSIZE(result) = len;
-
 	return (result);
 }	/* textcat() */
 
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
index 9e83ba12e60636b7cb3db94c4ade577774fc9a30..3d47cc7f462b0eede933d2f032e4f94ddd00de10 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: builtins.h,v 1.41 1998/04/27 17:09:28 scrappy Exp $
+ * $Id: builtins.h,v 1.42 1998/05/09 22:45:14 thomas Exp $
  *
  * NOTES
  *	  This should normally only be included by fmgr.h.
@@ -392,6 +392,9 @@ time_t		datetime_timestamp(DateTime *datetime);
 /* varchar.c */
 extern char *bpcharin(char *s, int dummy, int16 atttypmod);
 extern char *bpcharout(char *s);
+extern char *bpchar(char *s, int32 slen);
+extern char *char_bpchar(int32 c);
+extern int32 bpchar_char(char *s);
 extern bool bpchareq(char *arg1, char *arg2);
 extern bool bpcharne(char *arg1, char *arg2);
 extern bool bpcharlt(char *arg1, char *arg2);
@@ -405,6 +408,7 @@ extern uint32 hashbpchar(struct varlena * key);
 
 extern char *varcharin(char *s, int dummy, int16 atttypmod);
 extern char *varcharout(char *s);
+extern char *varchar(char *s, int32 slen);
 extern bool varchareq(char *arg1, char *arg2);
 extern bool varcharne(char *arg1, char *arg2);
 extern bool varcharlt(char *arg1, char *arg2);