Allow leading and trailing whitespace in the input to the boolean
authorNeil Conway <neilc@samurai.com>
Fri, 1 Jun 2007 23:40:19 +0000 (23:40 +0000)
committerNeil Conway <neilc@samurai.com>
Fri, 1 Jun 2007 23:40:19 +0000 (23:40 +0000)
type. Also, add explicit casts between boolean and text/varchar. Both
of these changes are for conformance with SQL:2003.

Update the regression tests, bump the catversion.

doc/src/sgml/datatype.sgml
src/backend/utils/adt/bool.c
src/include/catalog/catversion.h
src/include/catalog/pg_cast.h
src/include/catalog/pg_proc.h
src/include/utils/builtins.h
src/test/regress/expected/boolean.out
src/test/regress/sql/boolean.sql

index ed6269217f30dcd2ed4894014bdda009d23c6503..130b15e43739f3bcac44ef27c9c1b5d8480bd155 100644 (file)
@@ -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">
index d46ca0c31488cab6e01ad097e7c7a921ab34afec..3c367fd7cdbacb83677485c2f742ac3e69ed6806 100644 (file)
@@ -15,6 +15,8 @@
 
 #include "postgres.h"
 
+#include <ctype.h>
+
 #include "libpq/pqformat.h"
 #include "utils/builtins.h"
 
 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                                                                                                                 *
index 0303bcf84e3f569e71a09b34b14556cf83efdc08..f7403019af5721c1c27ccf2aac9ae67c544e8a62 100644 (file)
@@ -53,6 +53,6 @@
  */
 
 /*                                                     yyyymmddN */
-#define CATALOG_VERSION_NO     200706011
+#define CATALOG_VERSION_NO     200706012
 
 #endif
index ae6d5c22eb06632ef3c3b6fdfebb7253ab9e0fc5..bde147df86a39be0499acf38e5b2d12b50d07131 100644 (file)
@@ -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
index 69b96a6046e62ea839ccb9831f7412087758d703..a75baf9c18a59bc8069cfb6c828071c1266fcc98 100644 (file)
@@ -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) */
 
index 6e9df275e352b56d8c88a1f6f919a29541236cbf..97f41c30c42d247d00b0eceb4289516f9768b02d 100644 (file)
@@ -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);
index 93e475b673ff6a8d04b9469e48b22530bbf5ca94..511987e8b9bae7d32e9a138a16e257a1116fca80 100644 (file)
@@ -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');
index df97dfab3b38fba7af0644dee7128affe5765d9d..c68f02e7a5a8252927f4bb20f716a964eeb90fe7 100644 (file)
@@ -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);