summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Eisentraut2009-03-09 14:34:35 +0000
committerPeter Eisentraut2009-03-09 14:34:35 +0000
commit94358346c1e4f9a71b5a938140cc7def0c14c1a6 (patch)
treecf50ca0f3187b0a949f34a1e8f90039da36344a0
parent6d54da500caaaaee949a5cfac392d295cfa7da7d (diff)
Accept 'on' and 'off' as input for boolean data type, unifying the syntax
that the data type and GUC accepts. ITAGAKI Takahiro
-rw-r--r--doc/src/sgml/datatype.sgml2
-rw-r--r--src/backend/utils/adt/bool.c139
-rw-r--r--src/backend/utils/misc/guc.c68
-rw-r--r--src/include/utils/builtins.h2
-rw-r--r--src/include/utils/guc.h1
-rw-r--r--src/test/regress/expected/boolean.out30
-rw-r--r--src/test/regress/sql/boolean.sql12
7 files changed, 144 insertions, 110 deletions
diff --git a/doc/src/sgml/datatype.sgml b/doc/src/sgml/datatype.sgml
index c9d55a0136..accb05b19e 100644
--- a/doc/src/sgml/datatype.sgml
+++ b/doc/src/sgml/datatype.sgml
@@ -2686,6 +2686,7 @@ P <optional> <replaceable>years</>-<replaceable>months</>-<replaceable>days</> <
<member><literal>'true'</literal></member>
<member><literal>'y'</literal></member>
<member><literal>'yes'</literal></member>
+ <member><literal>'on'</literal></member>
<member><literal>'1'</literal></member>
</simplelist>
For the <quote>false</quote> state, the following values can be
@@ -2696,6 +2697,7 @@ P <optional> <replaceable>years</>-<replaceable>months</>-<replaceable>days</> <
<member><literal>'false'</literal></member>
<member><literal>'n'</literal></member>
<member><literal>'no'</literal></member>
+ <member><literal>'off'</literal></member>
<member><literal>'0'</literal></member>
</simplelist>
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 a109a82be7..a6ded6d83b 100644
--- a/src/backend/utils/adt/bool.c
+++ b/src/backend/utils/adt/bool.c
@@ -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 8fa48ab162..e435f64cee 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -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 77b7acdac1..c1b93932ee 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -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 3d103c0bde..6fce90a59d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/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;