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);