diff --git a/doc/src/sgml/datatype.sgml b/doc/src/sgml/datatype.sgml
index 17357d8408850c10bf8e9861ed5bce92c2c7a337..3802aa24dff97bb096e682b091aeea1626e50602 100644
--- a/doc/src/sgml/datatype.sgml
+++ b/doc/src/sgml/datatype.sgml
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/datatype.sgml,v 1.202 2007/05/29 04:58:43 neilc Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/datatype.sgml,v 1.203 2007/06/01 23:40:18 neilc Exp $ -->
 
  <chapter id="datatype">
   <title id="datatype-title">Data Types</title>
@@ -2403,9 +2403,9 @@ January 8 04:05:06 1999 PST
      <member><literal>'no'</literal></member>
      <member><literal>'0'</literal></member>
     </simplelist>
-    Using the key words <literal>TRUE</literal> and
-    <literal>FALSE</literal> is preferred (and
-    <acronym>SQL</acronym>-compliant).
+    Leading and trailing whitespace is ignored. Using the key words
+    <literal>TRUE</literal> and <literal>FALSE</literal> is preferred
+    (and <acronym>SQL</acronym>-compliant).
    </para>
 
    <example id="datatype-boolean-example">
diff --git a/src/backend/utils/adt/bool.c b/src/backend/utils/adt/bool.c
index c743f4f82a62d1ecbbc5b1fd3ac9e24d3bde2159..e238e131beddcac10b1f8193968888a0d5a06f26 100644
--- a/src/backend/utils/adt/bool.c
+++ b/src/backend/utils/adt/bool.c
@@ -8,13 +8,15 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/bool.c,v 1.38 2007/01/05 22:19:40 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/bool.c,v 1.39 2007/06/01 23:40:18 neilc Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 #include "postgres.h"
 
+#include <ctype.h>
+
 #include "libpq/pqformat.h"
 #include "utils/builtins.h"
 
@@ -33,41 +35,54 @@
 Datum
 boolin(PG_FUNCTION_ARGS)
 {
-	char	   *b = PG_GETARG_CSTRING(0);
-
-	switch (*b)
+	const char	*in_str = PG_GETARG_CSTRING(0);
+	const char 	*str;
+	size_t 		 len;
+
+	/*
+	 * Skip leading and trailing whitespace
+	 */
+	str = in_str;
+	while (isspace((unsigned char) *str))
+		str++;
+
+	len = strlen(str);
+	while (len > 0 && isspace((unsigned char) str[len - 1]))
+		len--;
+
+	switch (*str)
 	{
 		case 't':
 		case 'T':
-			if (pg_strncasecmp(b, "true", strlen(b)) == 0)
+			if (pg_strncasecmp(str, "true", len) == 0)
 				PG_RETURN_BOOL(true);
 			break;
 
 		case 'f':
 		case 'F':
-			if (pg_strncasecmp(b, "false", strlen(b)) == 0)
+			if (pg_strncasecmp(str, "false", len) == 0)
 				PG_RETURN_BOOL(false);
 			break;
 
 		case 'y':
 		case 'Y':
-			if (pg_strncasecmp(b, "yes", strlen(b)) == 0)
+			if (pg_strncasecmp(str, "yes", len) == 0)
 				PG_RETURN_BOOL(true);
 			break;
 
 		case '1':
-			if (pg_strncasecmp(b, "1", strlen(b)) == 0)
+			if (pg_strncasecmp(str, "1", len) == 0)
 				PG_RETURN_BOOL(true);
 			break;
 
 		case 'n':
 		case 'N':
-			if (pg_strncasecmp(b, "no", strlen(b)) == 0)
+			if (pg_strncasecmp(str, "no", len) == 0)
 				PG_RETURN_BOOL(false);
 			break;
 
 		case '0':
-			if (pg_strncasecmp(b, "0", strlen(b)) == 0)
+			if (pg_strncasecmp(str, "0", len) == 0)
 				PG_RETURN_BOOL(false);
 			break;
 
@@ -77,7 +92,7 @@ boolin(PG_FUNCTION_ARGS)
 
 	ereport(ERROR,
 			(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
-			 errmsg("invalid input syntax for type boolean: \"%s\"", b)));
+			 errmsg("invalid input syntax for type boolean: \"%s\"", in_str)));
 
 	/* not reached */
 	PG_RETURN_BOOL(false);
@@ -127,6 +142,37 @@ boolsend(PG_FUNCTION_ARGS)
 	PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
 }
 
+/*
+ *	    textbool			- cast function for text => bool
+ */
+Datum
+textbool(PG_FUNCTION_ARGS)
+{
+	Datum 		 in_text = PG_GETARG_DATUM(0);
+	char 		*str;
+
+	str = DatumGetCString(DirectFunctionCall1(textout, in_text));
+
+	PG_RETURN_DATUM(DirectFunctionCall1(boolin, CStringGetDatum(str)));
+}
+
+/*
+ *	    booltext			- cast function for bool => text
+ */
+Datum
+booltext(PG_FUNCTION_ARGS)
+{
+	bool 		 arg1 = PG_GETARG_BOOL(0);
+	char 		*str;
+
+	if (arg1)
+		str = "true";
+	else
+		str = "false";
+
+	PG_RETURN_DATUM(DirectFunctionCall1(textin, CStringGetDatum(str)));
+}
+
 
 /*****************************************************************************
  *	 PUBLIC ROUTINES														 *
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index b71f718776b2e1628dcd9a7f8aaf3f8f323062b8..8f79a7a92032d9a8d97eb4694ee1aa6a17d202ea 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.408 2007/06/01 15:33:19 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.409 2007/06/01 23:40:18 neilc Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*							yyyymmddN */
-#define CATALOG_VERSION_NO	200706011
+#define CATALOG_VERSION_NO	200706012
 
 #endif
diff --git a/src/include/catalog/pg_cast.h b/src/include/catalog/pg_cast.h
index bc558b82e9eb1354b87a68fabb8eeb8edae4e1ac..0b518265a36aab154072e90a367b8cbfec27584d 100644
--- a/src/include/catalog/pg_cast.h
+++ b/src/include/catalog/pg_cast.h
@@ -10,7 +10,7 @@
  *
  * Copyright (c) 2002-2007, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_cast.h,v 1.32 2007/04/02 03:49:40 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_cast.h,v 1.33 2007/06/01 23:40:18 neilc Exp $
  *
  * NOTES
  *	  the genbki.sh script reads this file and generates .bki
@@ -302,6 +302,8 @@ DATA(insert ( 1700	 25 1688 i ));
 DATA(insert (	25 1700 1686 e ));
 DATA(insert (  142   25 2922 e ));
 DATA(insert (   25  142	2896 e ));
+DATA(insert (   16   25 2971 e ));
+DATA(insert (   25   16 2970 e ));
 
 /*
  * Cross-category casts to and from VARCHAR
@@ -342,6 +344,8 @@ DATA(insert ( 1700 1043 1688 a ));
 DATA(insert ( 1043 1700 1686 e ));
 DATA(insert (  142 1043 2922 e ));
 DATA(insert ( 1043  142 2896 e ));
+DATA(insert (   16 1043 2971 e ));
+DATA(insert ( 1043   16 2970 e ));
 
 /*
  * Cross-category casts to and from BPCHAR
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index 7d297e8a83eacff66b69fc2890e27de03712f5a3..7145b021ac976f0777123761c144676a896082d5 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.456 2007/05/21 17:10:29 petere Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.457 2007/06/01 23:40:18 neilc Exp $
  *
  * NOTES
  *	  The script catalog/genbki.sh reads this file and generates .bki
@@ -3221,6 +3221,10 @@ DESCR("List all files in a directory");
 DATA(insert OID = 2626 ( pg_sleep			PGNSP PGUID 12 1 0 f f t f v 1 2278 "701" _null_ _null_ _null_ pg_sleep - _null_ ));
 DESCR("Sleep for the specified time in seconds");
 
+DATA(insert OID = 2970 (  boolean			PGNSP PGUID 12 1 0 f f t f i 1 16 "25" _null_ _null_ _null_	textbool - _null_ ));
+DESCR("text to boolean");
+DATA(insert OID = 2971 (  text				PGNSP PGUID 12 1 0 f f t f i 1 25 "16" _null_ _null_ _null_	booltext - _null_ ));
+DESCR("boolean to text");
 
 /* Aggregates (moved here from pg_aggregate for 7.3) */
 
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
index ec5b9720da811d7a3b67170bfb5401b798d765d3..d0a7329f10f7331317ab9eb545cc86cdd94c5d23 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.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/utils/builtins.h,v 1.293 2007/05/17 23:31:49 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.294 2007/06/01 23:40:19 neilc Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -70,6 +70,8 @@ extern Datum boolin(PG_FUNCTION_ARGS);
 extern Datum boolout(PG_FUNCTION_ARGS);
 extern Datum boolrecv(PG_FUNCTION_ARGS);
 extern Datum boolsend(PG_FUNCTION_ARGS);
+extern Datum booltext(PG_FUNCTION_ARGS);
+extern Datum textbool(PG_FUNCTION_ARGS);
 extern Datum booleq(PG_FUNCTION_ARGS);
 extern Datum boolne(PG_FUNCTION_ARGS);
 extern Datum boollt(PG_FUNCTION_ARGS);
diff --git a/src/test/regress/expected/boolean.out b/src/test/regress/expected/boolean.out
index 93e475b673ff6a8d04b9469e48b22530bbf5ca94..511987e8b9bae7d32e9a138a16e257a1116fca80 100644
--- a/src/test/regress/expected/boolean.out
+++ b/src/test/regress/expected/boolean.out
@@ -18,7 +18,7 @@ SELECT bool 't' AS true;
  t
 (1 row)
 
-SELECT bool 'f' AS false;
+SELECT bool '   f           ' AS false;
  false 
 -------
  f
@@ -54,6 +54,30 @@ SELECT bool 't' <> bool 'f' AS true;
  t
 (1 row)
 
+-- explicit casts to/from text
+SELECT 'TrUe'::text::boolean AS true, 'fAlse'::text::boolean AS false;
+ true | false 
+------+-------
+ t    | f
+(1 row)
+
+SELECT '    true   '::text::boolean AS true,
+       '     FALSE'::text::boolean AS false;
+ true | false 
+------+-------
+ t    | f
+(1 row)
+
+SELECT true::boolean::text AS true, false::boolean::text AS false;
+ true | false 
+------+-------
+ true | false
+(1 row)
+
+SELECT '  tru e '::text::boolean AS invalid;    -- error
+ERROR:  invalid input syntax for type boolean: "  tru e "
+SELECT ''::text::boolean AS invalid;            -- error
+ERROR:  invalid input syntax for type boolean: ""
 CREATE TABLE BOOLTBL1 (f1 bool);
 INSERT INTO BOOLTBL1 (f1) VALUES (bool 't');
 INSERT INTO BOOLTBL1 (f1) VALUES (bool 'True');
diff --git a/src/test/regress/sql/boolean.sql b/src/test/regress/sql/boolean.sql
index df97dfab3b38fba7af0644dee7128affe5765d9d..c68f02e7a5a8252927f4bb20f716a964eeb90fe7 100644
--- a/src/test/regress/sql/boolean.sql
+++ b/src/test/regress/sql/boolean.sql
@@ -14,7 +14,7 @@ SELECT 1 AS one;
 
 SELECT bool 't' AS true;
 
-SELECT bool 'f' AS false;
+SELECT bool '   f           ' AS false;
 
 SELECT bool 't' or bool 'f' AS true;
 
@@ -26,6 +26,14 @@ SELECT bool 't' = bool 'f' AS false;
 
 SELECT bool 't' <> bool 'f' AS true;
 
+-- explicit casts to/from text
+SELECT 'TrUe'::text::boolean AS true, 'fAlse'::text::boolean AS false;
+SELECT '    true   '::text::boolean AS true,
+       '     FALSE'::text::boolean AS false;
+SELECT true::boolean::text AS true, false::boolean::text AS false;
+
+SELECT '  tru e '::text::boolean AS invalid;    -- error
+SELECT ''::text::boolean AS invalid;            -- error
 
 CREATE TABLE BOOLTBL1 (f1 bool);