Commit f086be3d authored by Neil Conway's avatar Neil Conway

Allow leading and trailing whitespace in the input to the boolean

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.
parent bd0a2609
<!-- $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"> <chapter id="datatype">
<title id="datatype-title">Data Types</title> <title id="datatype-title">Data Types</title>
...@@ -2403,9 +2403,9 @@ January 8 04:05:06 1999 PST ...@@ -2403,9 +2403,9 @@ January 8 04:05:06 1999 PST
<member><literal>'no'</literal></member> <member><literal>'no'</literal></member>
<member><literal>'0'</literal></member> <member><literal>'0'</literal></member>
</simplelist> </simplelist>
Using the key words <literal>TRUE</literal> and Leading and trailing whitespace is ignored. Using the key words
<literal>FALSE</literal> is preferred (and <literal>TRUE</literal> and <literal>FALSE</literal> is preferred
<acronym>SQL</acronym>-compliant). (and <acronym>SQL</acronym>-compliant).
</para> </para>
<example id="datatype-boolean-example"> <example id="datatype-boolean-example">
......
...@@ -8,13 +8,15 @@ ...@@ -8,13 +8,15 @@
* *
* *
* IDENTIFICATION * 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 "postgres.h"
#include <ctype.h>
#include "libpq/pqformat.h" #include "libpq/pqformat.h"
#include "utils/builtins.h" #include "utils/builtins.h"
...@@ -33,41 +35,54 @@ ...@@ -33,41 +35,54 @@
Datum Datum
boolin(PG_FUNCTION_ARGS) boolin(PG_FUNCTION_ARGS)
{ {
char *b = PG_GETARG_CSTRING(0); const char *in_str = PG_GETARG_CSTRING(0);
const char *str;
switch (*b) 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':
case 'T': case 'T':
if (pg_strncasecmp(b, "true", strlen(b)) == 0) if (pg_strncasecmp(str, "true", len) == 0)
PG_RETURN_BOOL(true); PG_RETURN_BOOL(true);
break; break;
case 'f': case 'f':
case 'F': case 'F':
if (pg_strncasecmp(b, "false", strlen(b)) == 0) if (pg_strncasecmp(str, "false", len) == 0)
PG_RETURN_BOOL(false); PG_RETURN_BOOL(false);
break; break;
case 'y': case 'y':
case 'Y': case 'Y':
if (pg_strncasecmp(b, "yes", strlen(b)) == 0) if (pg_strncasecmp(str, "yes", len) == 0)
PG_RETURN_BOOL(true); PG_RETURN_BOOL(true);
break; break;
case '1': case '1':
if (pg_strncasecmp(b, "1", strlen(b)) == 0) if (pg_strncasecmp(str, "1", len) == 0)
PG_RETURN_BOOL(true); PG_RETURN_BOOL(true);
break; break;
case 'n': case 'n':
case 'N': case 'N':
if (pg_strncasecmp(b, "no", strlen(b)) == 0) if (pg_strncasecmp(str, "no", len) == 0)
PG_RETURN_BOOL(false); PG_RETURN_BOOL(false);
break; break;
case '0': case '0':
if (pg_strncasecmp(b, "0", strlen(b)) == 0) if (pg_strncasecmp(str, "0", len) == 0)
PG_RETURN_BOOL(false); PG_RETURN_BOOL(false);
break; break;
...@@ -77,7 +92,7 @@ boolin(PG_FUNCTION_ARGS) ...@@ -77,7 +92,7 @@ boolin(PG_FUNCTION_ARGS)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), (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 */ /* not reached */
PG_RETURN_BOOL(false); PG_RETURN_BOOL(false);
...@@ -127,6 +142,37 @@ boolsend(PG_FUNCTION_ARGS) ...@@ -127,6 +142,37 @@ boolsend(PG_FUNCTION_ARGS)
PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); 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 * * PUBLIC ROUTINES *
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 @@ ...@@ -53,6 +53,6 @@
*/ */
/* yyyymmddN */ /* yyyymmddN */
#define CATALOG_VERSION_NO 200706011 #define CATALOG_VERSION_NO 200706012
#endif #endif
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* Copyright (c) 2002-2007, PostgreSQL Global Development Group * 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 * NOTES
* the genbki.sh script reads this file and generates .bki * the genbki.sh script reads this file and generates .bki
...@@ -302,6 +302,8 @@ DATA(insert ( 1700 25 1688 i )); ...@@ -302,6 +302,8 @@ DATA(insert ( 1700 25 1688 i ));
DATA(insert ( 25 1700 1686 e )); DATA(insert ( 25 1700 1686 e ));
DATA(insert ( 142 25 2922 e )); DATA(insert ( 142 25 2922 e ));
DATA(insert ( 25 142 2896 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 * Cross-category casts to and from VARCHAR
...@@ -342,6 +344,8 @@ DATA(insert ( 1700 1043 1688 a )); ...@@ -342,6 +344,8 @@ DATA(insert ( 1700 1043 1688 a ));
DATA(insert ( 1043 1700 1686 e )); DATA(insert ( 1043 1700 1686 e ));
DATA(insert ( 142 1043 2922 e )); DATA(insert ( 142 1043 2922 e ));
DATA(insert ( 1043 142 2896 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 * Cross-category casts to and from BPCHAR
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 * NOTES
* The script catalog/genbki.sh reads this file and generates .bki * The script catalog/genbki.sh reads this file and generates .bki
...@@ -3221,6 +3221,10 @@ DESCR("List all files in a directory"); ...@@ -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_ )); 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"); 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) */ /* Aggregates (moved here from pg_aggregate for 7.3) */
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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); ...@@ -70,6 +70,8 @@ extern Datum boolin(PG_FUNCTION_ARGS);
extern Datum boolout(PG_FUNCTION_ARGS); extern Datum boolout(PG_FUNCTION_ARGS);
extern Datum boolrecv(PG_FUNCTION_ARGS); extern Datum boolrecv(PG_FUNCTION_ARGS);
extern Datum boolsend(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 booleq(PG_FUNCTION_ARGS);
extern Datum boolne(PG_FUNCTION_ARGS); extern Datum boolne(PG_FUNCTION_ARGS);
extern Datum boollt(PG_FUNCTION_ARGS); extern Datum boollt(PG_FUNCTION_ARGS);
......
...@@ -18,7 +18,7 @@ SELECT bool 't' AS true; ...@@ -18,7 +18,7 @@ SELECT bool 't' AS true;
t t
(1 row) (1 row)
SELECT bool 'f' AS false; SELECT bool ' f ' AS false;
false false
------- -------
f f
...@@ -54,6 +54,30 @@ SELECT bool 't' <> bool 'f' AS true; ...@@ -54,6 +54,30 @@ SELECT bool 't' <> bool 'f' AS true;
t t
(1 row) (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); CREATE TABLE BOOLTBL1 (f1 bool);
INSERT INTO BOOLTBL1 (f1) VALUES (bool 't'); INSERT INTO BOOLTBL1 (f1) VALUES (bool 't');
INSERT INTO BOOLTBL1 (f1) VALUES (bool 'True'); INSERT INTO BOOLTBL1 (f1) VALUES (bool 'True');
......
...@@ -14,7 +14,7 @@ SELECT 1 AS one; ...@@ -14,7 +14,7 @@ SELECT 1 AS one;
SELECT bool 't' AS true; SELECT bool 't' AS true;
SELECT bool 'f' AS false; SELECT bool ' f ' AS false;
SELECT bool 't' or bool 'f' AS true; SELECT bool 't' or bool 'f' AS true;
...@@ -26,6 +26,14 @@ SELECT bool 't' = bool 'f' AS false; ...@@ -26,6 +26,14 @@ SELECT bool 't' = bool 'f' AS false;
SELECT bool 't' <> bool 'f' AS true; 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); CREATE TABLE BOOLTBL1 (f1 bool);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment