From 05a7db05826c5eb68173b6d7ef1553c19322ef48 Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Mon, 9 Mar 2009 14:34:35 +0000 Subject: [PATCH] Accept 'on' and 'off' as input for boolean data type, unifying the syntax that the data type and GUC accepts. ITAGAKI Takahiro --- doc/src/sgml/datatype.sgml | 4 +- src/backend/utils/adt/bool.c | 141 ++++++++++++++++++-------- src/backend/utils/misc/guc.c | 70 +------------ src/include/utils/builtins.h | 4 +- src/include/utils/guc.h | 3 +- src/test/regress/expected/boolean.out | 30 ++++++ src/test/regress/sql/boolean.sql | 12 +++ 7 files changed, 149 insertions(+), 115 deletions(-) diff --git a/doc/src/sgml/datatype.sgml b/doc/src/sgml/datatype.sgml index 6a61c0c5bf..fe7f95f086 100644 --- a/doc/src/sgml/datatype.sgml +++ b/doc/src/sgml/datatype.sgml @@ -1,4 +1,4 @@ - + Data Types @@ -2686,6 +2686,7 @@ P years-months-days < 'true' 'y' 'yes' + 'on' '1' For the false state, the following values can be @@ -2696,6 +2697,7 @@ P years-months-days < 'false' 'n' 'no' + 'off' '0' Leading and trailing whitespace is ignored. Using the key words diff --git a/src/backend/utils/adt/bool.c b/src/backend/utils/adt/bool.c index 8584b3c290..7d3f9e55a1 100644 --- a/src/backend/utils/adt/bool.c +++ b/src/backend/utils/adt/bool.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/bool.c,v 1.45 2009/01/01 17:23:49 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/bool.c,v 1.46 2009/03/09 14:34:34 petere Exp $ * *------------------------------------------------------------------------- */ @@ -20,6 +20,99 @@ #include "libpq/pqformat.h" #include "utils/builtins.h" +/* + * Try to interpret value as boolean value. Valid values are: true, + * false, yes, no, on, off, 1, 0; as well as unique prefixes thereof. + * If the string parses okay, return true, else false. + * If okay and result is not NULL, return the value in *result. + */ +bool +parse_bool(const char *value, bool *result) +{ + return parse_bool_with_len(value, strlen(value), result); +} + +bool +parse_bool_with_len(const char *value, size_t len, bool *result) +{ + switch (*value) + { + case 't': + case 'T': + if (pg_strncasecmp(value, "true", len) == 0) + { + if (result) + *result = true; + return true; + } + break; + case 'f': + case 'F': + if (pg_strncasecmp(value, "false", len) == 0) + { + if (result) + *result = false; + return true; + } + break; + case 'y': + case 'Y': + if (pg_strncasecmp(value, "yes", len) == 0) + { + if (result) + *result = true; + return true; + } + break; + case 'n': + case 'N': + if (pg_strncasecmp(value, "no", len) == 0) + { + if (result) + *result = false; + return true; + } + break; + case 'o': + case 'O': + /* 'o' is not unique enough */ + if (pg_strncasecmp(value, "on", (len > 2 ? len : 2)) == 0) + { + if (result) + *result = true; + return true; + } + else if (pg_strncasecmp(value, "off", (len > 2 ? len : 2)) == 0) + { + if (result) + *result = false; + return true; + } + break; + case '1': + if (len == 1) + { + if (result) + *result = true; + return true; + } + break; + case '0': + if (len == 1) + { + if (result) + *result = false; + return true; + } + break; + default: + break; + } + + *result = false; /* suppress compiler warning */ + return false; +} + /***************************************************************************** * USER I/O ROUTINES * *****************************************************************************/ @@ -27,8 +120,8 @@ /* * boolin - converts "t" or "f" to 1 or 0 * - * Check explicitly for "true/false" and TRUE/FALSE, 1/0, YES/NO. - * Reject other values. - thomas 1997-10-05 + * Check explicitly for "true/false" and TRUE/FALSE, 1/0, YES/NO, ON/OFF. + * Reject other values. * * In the switch statement, check the most-used possibilities first. */ @@ -38,6 +131,7 @@ boolin(PG_FUNCTION_ARGS) const char *in_str = PG_GETARG_CSTRING(0); const char *str; size_t len; + bool result; /* * Skip leading and trailing whitespace @@ -50,45 +144,8 @@ boolin(PG_FUNCTION_ARGS) while (len > 0 && isspace((unsigned char) str[len - 1])) len--; - switch (*str) - { - case 't': - case 'T': - if (pg_strncasecmp(str, "true", len) == 0) - PG_RETURN_BOOL(true); - break; - - case 'f': - case 'F': - if (pg_strncasecmp(str, "false", len) == 0) - PG_RETURN_BOOL(false); - break; - - case 'y': - case 'Y': - if (pg_strncasecmp(str, "yes", len) == 0) - PG_RETURN_BOOL(true); - break; - - case '1': - if (pg_strncasecmp(str, "1", len) == 0) - PG_RETURN_BOOL(true); - break; - - case 'n': - case 'N': - if (pg_strncasecmp(str, "no", len) == 0) - PG_RETURN_BOOL(false); - break; - - case '0': - if (pg_strncasecmp(str, "0", len) == 0) - PG_RETURN_BOOL(false); - break; - - default: - break; - } + if (parse_bool_with_len(str, len, &result)) + PG_RETURN_BOOL(result); ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 5411840b2a..8bf2305736 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -10,7 +10,7 @@ * Written by Peter Eisentraut . * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.496 2009/02/28 00:10:51 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.497 2009/03/09 14:34:34 petere Exp $ * *-------------------------------------------------------------------- */ @@ -4086,74 +4086,6 @@ ReportGUCOption(struct config_generic * record) } } - -/* - * Try to interpret value as boolean value. Valid values are: true, - * false, yes, no, on, off, 1, 0; as well as unique prefixes thereof. - * If the string parses okay, return true, else false. - * If okay and result is not NULL, return the value in *result. - */ -bool -parse_bool(const char *value, bool *result) -{ - size_t len = strlen(value); - - if (pg_strncasecmp(value, "true", len) == 0) - { - if (result) - *result = true; - } - else if (pg_strncasecmp(value, "false", len) == 0) - { - if (result) - *result = false; - } - - else if (pg_strncasecmp(value, "yes", len) == 0) - { - if (result) - *result = true; - } - else if (pg_strncasecmp(value, "no", len) == 0) - { - if (result) - *result = false; - } - - /* 'o' is not unique enough */ - else if (pg_strncasecmp(value, "on", (len > 2 ? len : 2)) == 0) - { - if (result) - *result = true; - } - else if (pg_strncasecmp(value, "off", (len > 2 ? len : 2)) == 0) - { - if (result) - *result = false; - } - - else if (pg_strcasecmp(value, "1") == 0) - { - if (result) - *result = true; - } - else if (pg_strcasecmp(value, "0") == 0) - { - if (result) - *result = false; - } - - else - { - if (result) - *result = false; /* suppress compiler warning */ - return false; - } - return true; -} - - - /* * Try to parse value as an integer. The accepted formats are the * usual decimal, octal, or hexadecimal formats, optionally followed by diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h index 155abf456b..06d8e04d1d 100644 --- a/src/include/utils/builtins.h +++ b/src/include/utils/builtins.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.331 2009/02/06 21:15:12 tgl Exp $ + * $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.332 2009/03/09 14:34:34 petere Exp $ * *------------------------------------------------------------------------- */ @@ -109,6 +109,8 @@ extern Datum boolle(PG_FUNCTION_ARGS); extern Datum boolge(PG_FUNCTION_ARGS); extern Datum booland_statefunc(PG_FUNCTION_ARGS); extern Datum boolor_statefunc(PG_FUNCTION_ARGS); +extern bool parse_bool(const char *value, bool *result); +extern bool parse_bool_with_len(const char *value, size_t len, bool *result); /* char.c */ extern Datum charin(PG_FUNCTION_ARGS); diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h index dcd00b97c3..cded751f92 100644 --- a/src/include/utils/guc.h +++ b/src/include/utils/guc.h @@ -7,7 +7,7 @@ * Copyright (c) 2000-2009, PostgreSQL Global Development Group * Written by Peter Eisentraut . * - * $PostgreSQL: pgsql/src/include/utils/guc.h,v 1.100 2009/01/01 17:24:02 momjian Exp $ + * $PostgreSQL: pgsql/src/include/utils/guc.h,v 1.101 2009/03/09 14:34:35 petere Exp $ *-------------------------------------------------------------------- */ #ifndef GUC_H @@ -257,7 +257,6 @@ extern int NewGUCNestLevel(void); extern void AtEOXact_GUC(bool isCommit, int nestLevel); extern void BeginReportingGUCOptions(void); extern void ParseLongOption(const char *string, char **name, char **value); -extern bool parse_bool(const char *value, bool *result); extern bool parse_int(const char *value, int *result, int flags, const char **hintmsg); extern bool parse_real(const char *value, double *result); diff --git a/src/test/regress/expected/boolean.out b/src/test/regress/expected/boolean.out index a3629f2282..28d7cf9526 100644 --- a/src/test/regress/expected/boolean.out +++ b/src/test/regress/expected/boolean.out @@ -88,6 +88,36 @@ SELECT bool 'nay' AS error; ERROR: invalid input syntax for type boolean: "nay" LINE 1: SELECT bool 'nay' AS error; ^ +SELECT bool 'on' AS true; + true +------ + t +(1 row) + +SELECT bool 'off' AS false; + false +------- + f +(1 row) + +SELECT bool 'of' AS false; + false +------- + f +(1 row) + +SELECT bool 'o' AS error; +ERROR: invalid input syntax for type boolean: "o" +LINE 1: SELECT bool 'o' AS error; + ^ +SELECT bool 'on_' AS error; +ERROR: invalid input syntax for type boolean: "on_" +LINE 1: SELECT bool 'on_' AS error; + ^ +SELECT bool 'off_' AS error; +ERROR: invalid input syntax for type boolean: "off_" +LINE 1: SELECT bool 'off_' AS error; + ^ SELECT bool '1' AS true; true ------ diff --git a/src/test/regress/sql/boolean.sql b/src/test/regress/sql/boolean.sql index 63dd22f877..a605302e12 100644 --- a/src/test/regress/sql/boolean.sql +++ b/src/test/regress/sql/boolean.sql @@ -40,6 +40,18 @@ SELECT bool 'no' AS false; SELECT bool 'nay' AS error; +SELECT bool 'on' AS true; + +SELECT bool 'off' AS false; + +SELECT bool 'of' AS false; + +SELECT bool 'o' AS error; + +SELECT bool 'on_' AS error; + +SELECT bool 'off_' AS error; + SELECT bool '1' AS true; SELECT bool '11' AS error; -- 2.40.0