Add json_typeof() and json_is_*() functions.
The attached patch adds four new SQL functions for the JSON type:
json_typeof(json) RETURNS text
json_is_object(json) RETURNS boolean
json_is_array(json) RETURNS boolean
json_is_scalar(json) RETURNS boolean
The motivating use-case for this patch is the ability to easily create a
domain type for what RFC 4627 calls "json text", where the top-level value
must be either an object or array. An example of this usage is:
CREATE DOMAIN json_document AS json CHECK (NOT json_is_scalar(VALUE));
An additional use-case arises when writing functions which can handle
arbitrary JSON values. This can be difficult when nested objects or arrays
are present or when the input may be either an array or an object. Many of
the built-in functions will raise an error when presented with an "invalid"
value, such as when giving an array to json_object_keys(). The
json_typeof() and json_is_*() functions should make it easier to call the
correct function in these cases, e.g.:
CASE json_typeof($1)
WHEN 'object' THEN json_object_keys($1)
WHEN 'array' THEN json_array_elements($1)
ELSE $1
END
These new functions operate by making a single call to json_lex() to get
the first token of the JSON value; this token uniquely determines the
value's type. (Thanks to Merlin Moncure for suggesting this approach.)
The patch also updates the "JSON Functions and Operators" section of the
docs to ensure that the words "value", "object", and "array" are used in a
consistent manner. "JSON object" and "JSON array" refer to parameters
which must be an object or an array or to results which are always an
object or an array. "JSON value" refers to parameters or results which may
be any kind of JSON.
Regards,
Andrew Tipton
Attachments:
json_typeof_v1.patchapplication/octet-stream; name=json_typeof_v1.patchDownload
diff -r 6dad7dad36a6 doc/src/sgml/func.sgml
--- a/doc/src/sgml/func.sgml Sat Jul 27 15:00:58 2013 -0400
+++ b/doc/src/sgml/func.sgml Mon Jul 29 15:06:37 2013 +0800
@@ -10040,7 +10040,7 @@
</entry>
<entry><type>json</type></entry>
<entry>
- Returns JSON object pointed to by <parameter>path_elems</parameter>.
+ Returns JSON value pointed to by <parameter>path_elems</parameter>.
</entry>
<entry><literal>json_extract_path('{"f2":{"f3":1},"f4":{"f5":99,"f6":"foo"}}','f4')</literal></entry>
<entry><literal>{"f5":99,"f6":"foo"}</literal></entry>
@@ -10054,7 +10054,7 @@
</entry>
<entry><type>text</type></entry>
<entry>
- Returns JSON object pointed to by <parameter>path_elems</parameter>.
+ Returns JSON value pointed to by <parameter>path_elems</parameter>.
</entry>
<entry><literal>json_extract_path_text('{"f2":{"f3":1},"f4":{"f5":99,"f6":"foo"}}','f4', 'f6')</literal></entry>
<entry><literal>foo</literal></entry>
@@ -10137,7 +10137,7 @@
</entry>
<entry><type>SETOF json</type></entry>
<entry>
- Expands a JSON array to a set of JSON elements.
+ Expands a JSON array to a set of JSON values.
</entry>
<entry><literal>json_array_elements('[1,true, [2,false]]')</literal></entry>
<entry>
@@ -10150,6 +10150,67 @@
</programlisting>
</entry>
</row>
+ <row>
+ <entry>
+ <indexterm>
+ <primary>json_typeof</primary>
+ </indexterm>
+ <literal>json_typeof(json)</literal>
+ </entry>
+ <entry><type>text</type></entry>
+ <entry>
+ Returns the type of the outermost JSON value as a text string. The types are
+ <literal>object</>, <literal>array</>, <literal>string</>, <literal>number</>,
+ <literal>boolean</>, and <literal>null</>. (See note below regarding the
+ distinction between a JSON <literal>null</> and a SQL NULL.)
+ </entry>
+ <entry><literal>json_typeof('-123.4')</literal></entry>
+ <entry><literal>number</literal></entry>
+ </row>
+ <row>
+ <entry>
+ <indexterm>
+ <primary>json_is_object</primary>
+ </indexterm>
+ <literal>json_is_object(json)</literal>
+ </entry>
+ <entry><type>boolean</type></entry>
+ <entry>
+ Check if the outermost JSON value is an object.
+ </entry>
+ <entry><literal>json_is_object('{"f1":true}')</literal></entry>
+ <entry><literal>'t'</literal></entry>
+ </row>
+ <row>
+ <entry>
+ <indexterm>
+ <primary>json_is_array</primary>
+ </indexterm>
+ <literal>json_is_array(json)</literal>
+ </entry>
+ <entry><type>boolean</type></entry>
+ <entry>
+ Check if the outermost JSON value is an array.
+ </entry>
+ <entry><literal>json_is_array('[1,2,3]')</literal></entry>
+ <entry><literal>'t'</literal></entry>
+ </row>
+ <row>
+ <entry>
+ <indexterm>
+ <primary>json_is_scalar</primary>
+ </indexterm>
+ <literal>json_is_scalar(json)</literal>
+ </entry>
+ <entry><type>boolean</type></entry>
+ <entry>
+ Check if the outermost JSON value is a scalar. (Strings, numbers, and the
+ <literal>true</>, <literal>false</>, and <literal>null</> literals are all
+ scalar values.)
+ </entry>
+ <entry><literal>json_is_scalar('"hello world"')</literal></entry>
+ <entry><literal>'t'</literal></entry>
+ </row>
</tbody>
</tgroup>
</table>
@@ -10182,6 +10243,14 @@
</para>
</note>
+ <note>
+ <para>
+ The <literal>json_typeof</> function's <literal>null</> return value should not be confused
+ with a SQL NULL. While calling <literal>json_typeof('null'::json)</> will return <literal>null</>,
+ calling <literal>json_typeof(NULL::json)</> will return a SQL NULL.
+ </para>
+ </note>
+
<para>
See also <xref linkend="functions-aggregate"> about the aggregate
function <function>json_agg</function> which aggregates record
diff -r 6dad7dad36a6 src/backend/utils/adt/json.c
--- a/src/backend/utils/adt/json.c Sat Jul 27 15:00:58 2013 -0400
+++ b/src/backend/utils/adt/json.c Mon Jul 29 15:06:37 2013 +0800
@@ -1826,3 +1826,166 @@
}
appendStringInfoCharMacro(buf, '\"');
}
+
+/*
+ * SQL function json_typeof(json) -> text
+ *
+ * Returns the type of the outermost JSON value as TEXT. Possible types are
+ * "object", "array", "string", "number", "boolean", and "null".
+ *
+ * Performs a single call to json_lex() to get the first token of the supplied
+ * value. This initial token uniquely determines the value's type. As our
+ * input must already have been validated by json_in() or json_recv(), the
+ * initial token should never be JSON_TOKEN_OBJECT_END, JSON_TOKEN_ARRAY_END,
+ * JSON_TOKEN_COLON, JSON_TOKEN_COMMA, or JSON_TOKEN_END.
+ */
+Datum
+json_typeof(PG_FUNCTION_ARGS)
+{
+ text *json = PG_GETARG_TEXT_P(0);
+
+ JsonLexContext *lex = makeJsonLexContext(json, false);
+ JsonTokenType tok;
+ char *type;
+
+ /* Lex exactly one token from the input and check its type. */
+ json_lex(lex);
+ tok = lex_peek(lex);
+ switch (tok)
+ {
+ case JSON_TOKEN_OBJECT_START:
+ type = "object";
+ break;
+ case JSON_TOKEN_ARRAY_START:
+ type = "array";
+ break;
+ case JSON_TOKEN_STRING:
+ type = "string";
+ break;
+ case JSON_TOKEN_NUMBER:
+ type = "number";
+ break;
+ case JSON_TOKEN_TRUE:
+ case JSON_TOKEN_FALSE:
+ type = "boolean";
+ break;
+ case JSON_TOKEN_NULL:
+ type = "null";
+ break;
+ default:
+ elog(ERROR, "unexpected json token: %d", tok);
+ }
+
+ PG_RETURN_TEXT_P(cstring_to_text(type));
+}
+
+/*
+ * SQL function json_is_object(json) -> boolean
+ *
+ * Operates in a similar manner to json_typeof().
+ */
+Datum
+json_is_object(PG_FUNCTION_ARGS)
+{
+ text *json = PG_GETARG_TEXT_P(0);
+
+ JsonLexContext *lex = makeJsonLexContext(json, false);
+ JsonTokenType tok;
+ int is_object;
+
+ /* Lex exactly one token from the input and check its type. */
+ json_lex(lex);
+ tok = lex_peek(lex);
+ switch (tok)
+ {
+ case JSON_TOKEN_OBJECT_START:
+ is_object = 1;
+ break;
+ case JSON_TOKEN_ARRAY_START:
+ case JSON_TOKEN_STRING:
+ case JSON_TOKEN_NUMBER:
+ case JSON_TOKEN_TRUE:
+ case JSON_TOKEN_FALSE:
+ case JSON_TOKEN_NULL:
+ is_object = 0;
+ break;
+ default:
+ elog(ERROR, "unexpected json token: %d", tok);
+ }
+
+ PG_RETURN_BOOL(is_object);
+}
+
+/*
+ * SQL function json_is_array(json) -> boolean
+ *
+ * Operates in a similar manner to json_typeof().
+ */
+Datum
+json_is_array(PG_FUNCTION_ARGS)
+{
+ text *json = PG_GETARG_TEXT_P(0);
+
+ JsonLexContext *lex = makeJsonLexContext(json, false);
+ JsonTokenType tok;
+ int is_array;
+
+ /* Lex exactly one token from the input and check its type. */
+ json_lex(lex);
+ tok = lex_peek(lex);
+ switch (tok)
+ {
+ case JSON_TOKEN_ARRAY_START:
+ is_array = 1;
+ break;
+ case JSON_TOKEN_OBJECT_START:
+ case JSON_TOKEN_STRING:
+ case JSON_TOKEN_NUMBER:
+ case JSON_TOKEN_TRUE:
+ case JSON_TOKEN_FALSE:
+ case JSON_TOKEN_NULL:
+ is_array = 0;
+ break;
+ default:
+ elog(ERROR, "unexpected json token: %d", tok);
+ }
+
+ PG_RETURN_BOOL(is_array);
+}
+
+/*
+ * SQL function json_is_scalar(json) -> boolean
+ *
+ * Operates in a similar manner to json_typeof().
+ */
+Datum
+json_is_scalar(PG_FUNCTION_ARGS)
+{
+ text *json = PG_GETARG_TEXT_P(0);
+
+ JsonLexContext *lex = makeJsonLexContext(json, false);
+ JsonTokenType tok;
+ int is_scalar;
+
+ /* Lex exactly one token from the input and check its type. */
+ json_lex(lex);
+ tok = lex_peek(lex);
+ switch (tok)
+ {
+ case JSON_TOKEN_OBJECT_START:
+ case JSON_TOKEN_ARRAY_START:
+ is_scalar = 0;
+ break;
+ case JSON_TOKEN_STRING:
+ case JSON_TOKEN_NUMBER:
+ case JSON_TOKEN_TRUE:
+ case JSON_TOKEN_FALSE:
+ case JSON_TOKEN_NULL:
+ is_scalar = 1;
+ break;
+ default:
+ elog(ERROR, "unexpected json token: %d", tok);
+ }
+
+ PG_RETURN_BOOL(is_scalar);
+}
diff -r 6dad7dad36a6 src/include/catalog/pg_proc.h
--- a/src/include/catalog/pg_proc.h Sat Jul 27 15:00:58 2013 -0400
+++ b/src/include/catalog/pg_proc.h Mon Jul 29 15:06:37 2013 +0800
@@ -4150,6 +4150,14 @@
DESCR("get record fields from a json object");
DATA(insert OID = 3961 ( json_populate_recordset PGNSP PGUID 12 1 100 0 0 f f f f f t s 3 0 2283 "2283 114 16" _null_ _null_ _null_ _null_ json_populate_recordset _null_ _null_ _null_ ));
DESCR("get set of records with fields from a json array of objects");
+DATA(insert OID = 3968 ( json_typeof PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 25 "114" _null_ _null_ _null_ _null_ json_typeof _null_ _null_ _null_ ));
+DESCR("get the type of a json value");
+DATA(insert OID = 3969 ( json_is_object PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 16 "114" _null_ _null_ _null_ _null_ json_is_object _null_ _null_ _null_ ));
+DESCR("is the json value an object");
+DATA(insert OID = 3970 ( json_is_array PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 16 "114" _null_ _null_ _null_ _null_ json_is_array _null_ _null_ _null_ ));
+DESCR("is the json value an array");
+DATA(insert OID = 3971 ( json_is_scalar PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 16 "114" _null_ _null_ _null_ _null_ json_is_scalar _null_ _null_ _null_ ));
+DESCR("is the json value neither an object nor an array");
/* uuid */
DATA(insert OID = 2952 ( uuid_in PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 2950 "2275" _null_ _null_ _null_ _null_ uuid_in _null_ _null_ _null_ ));
diff -r 6dad7dad36a6 src/include/utils/json.h
--- a/src/include/utils/json.h Sat Jul 27 15:00:58 2013 -0400
+++ b/src/include/utils/json.h Mon Jul 29 15:06:37 2013 +0800
@@ -33,6 +33,11 @@
extern void escape_json(StringInfo buf, const char *str);
+extern Datum json_typeof(PG_FUNCTION_ARGS);
+extern Datum json_is_object(PG_FUNCTION_ARGS);
+extern Datum json_is_array(PG_FUNCTION_ARGS);
+extern Datum json_is_scalar(PG_FUNCTION_ARGS);
+
/* functions in jsonfuncs.c */
extern Datum json_object_field(PG_FUNCTION_ARGS);
extern Datum json_object_field_text(PG_FUNCTION_ARGS);
diff -r 6dad7dad36a6 src/test/regress/expected/json.out
--- a/src/test/regress/expected/json.out Sat Jul 27 15:00:58 2013 -0400
+++ b/src/test/regress/expected/json.out Mon Jul 29 15:06:37 2013 +0800
@@ -962,3 +962,23 @@
null \u0000 escape
(1 row)
+--json_typeof() and the json_is_*() functions
+select value, json_typeof(value), json_is_object(value), json_is_array(value), json_is_scalar(value)
+ from (values (json '123.4'), (json '-1'), (json '"foo"'), (json 'true'), (json 'false'), (json 'null'),
+ (json '[1, 2, 3]'), (json '[]'), (json '{"x":"foo", "y":123}'), (json '{}'), (NULL::json))
+ as data(value);
+ value | json_typeof | json_is_object | json_is_array | json_is_scalar
+----------------------+-------------+----------------+---------------+----------------
+ 123.4 | number | f | f | t
+ -1 | number | f | f | t
+ "foo" | string | f | f | t
+ true | boolean | f | f | t
+ false | boolean | f | f | t
+ null | null | f | f | t
+ [1, 2, 3] | array | f | t | f
+ [] | array | f | t | f
+ {"x":"foo", "y":123} | object | t | f | f
+ {} | object | t | f | f
+ | | | |
+(11 rows)
+
diff -r 6dad7dad36a6 src/test/regress/expected/json_1.out
--- a/src/test/regress/expected/json_1.out Sat Jul 27 15:00:58 2013 -0400
+++ b/src/test/regress/expected/json_1.out Mon Jul 29 15:06:37 2013 +0800
@@ -958,3 +958,23 @@
null \u0000 escape
(1 row)
+--json_typeof() and the json_is_*() functions
+select value, json_typeof(value), json_is_object(value), json_is_array(value), json_is_scalar(value)
+ from (values (json '123.4'), (json '-1'), (json '"foo"'), (json 'true'), (json 'false'), (json 'null'),
+ (json '[1, 2, 3]'), (json '[]'), (json '{"x":"foo", "y":123}'), (json '{}'), (NULL::json))
+ as data(value);
+ value | json_typeof | json_is_object | json_is_array | json_is_scalar
+----------------------+-------------+----------------+---------------+----------------
+ 123.4 | number | f | f | t
+ -1 | number | f | f | t
+ "foo" | string | f | f | t
+ true | boolean | f | f | t
+ false | boolean | f | f | t
+ null | null | f | f | t
+ [1, 2, 3] | array | f | t | f
+ [] | array | f | t | f
+ {"x":"foo", "y":123} | object | t | f | f
+ {} | object | t | f | f
+ | | | |
+(11 rows)
+
diff -r 6dad7dad36a6 src/test/regress/sql/json.sql
--- a/src/test/regress/sql/json.sql Sat Jul 27 15:00:58 2013 -0400
+++ b/src/test/regress/sql/json.sql Mon Jul 29 15:06:37 2013 +0800
@@ -310,3 +310,9 @@
select json '{ "a": "the Copyright \u00a9 sign" }' ->> 'a' as correct_in_utf8;
select json '{ "a": "dollar \u0024 character" }' ->> 'a' as correct_everywhere;
select json '{ "a": "null \u0000 escape" }' ->> 'a' as not_unescaped;
+
+--json_typeof() and the json_is_*() functions
+select value, json_typeof(value), json_is_object(value), json_is_array(value), json_is_scalar(value)
+ from (values (json '123.4'), (json '-1'), (json '"foo"'), (json 'true'), (json 'false'), (json 'null'),
+ (json '[1, 2, 3]'), (json '[]'), (json '{"x":"foo", "y":123}'), (json '{}'), (NULL::json))
+ as data(value);
On 07/29/2013 03:16 AM, Andrew Tipton wrote:
The attached patch adds four new SQL functions for the JSON type:
json_typeof(json) RETURNS text
json_is_object(json) RETURNS boolean
json_is_array(json) RETURNS boolean
json_is_scalar(json) RETURNS boolean
Please add to the next CommitFest if you have not already done so.
cheers
andrew
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On Mon, Jul 29, 2013 at 2:16 AM, Andrew Tipton <andrew@kiwidrew.com> wrote:
The attached patch adds four new SQL functions for the JSON type:
json_typeof(json) RETURNS text
json_is_object(json) RETURNS boolean
json_is_array(json) RETURNS boolean
json_is_scalar(json) RETURNS booleanThe motivating use-case for this patch is the ability to easily create a
domain type for what RFC 4627 calls "json text", where the top-level value
must be either an object or array. An example of this usage is:CREATE DOMAIN json_document AS json CHECK (NOT json_is_scalar(VALUE));
An additional use-case arises when writing functions which can handle
arbitrary JSON values. This can be difficult when nested objects or arrays
are present or when the input may be either an array or an object. Many of
the built-in functions will raise an error when presented with an "invalid"
value, such as when giving an array to json_object_keys(). The
json_typeof() and json_is_*() functions should make it easier to call the
correct function in these cases, e.g.:CASE json_typeof($1)
WHEN 'object' THEN json_object_keys($1)
WHEN 'array' THEN json_array_elements($1)
ELSE $1
ENDThese new functions operate by making a single call to json_lex() to get the
first token of the JSON value; this token uniquely determines the value's
type. (Thanks to Merlin Moncure for suggesting this approach.)The patch also updates the "JSON Functions and Operators" section of the
docs to ensure that the words "value", "object", and "array" are used in a
consistent manner. "JSON object" and "JSON array" refer to parameters which
must be an object or an array or to results which are always an object or an
array. "JSON value" refers to parameters or results which may be any kind
of JSON.
you're welcome! :-).
small point:
Personally I would prune the supplied functions to json_typeof() and
json_is_scalar(). These functions are in the public namespace so
there is a certain minimum bang/buck ratio which IMNSHO
json_is_object() and json_is_array() don't meet -- just call
json_typeof() to get that info.
merlin
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On Mon, Jul 29, 2013 at 5:36 PM, Merlin Moncure <mmoncure@gmail.com> wrote:
On Mon, Jul 29, 2013 at 2:16 AM, Andrew Tipton <andrew@kiwidrew.com> wrote:
The attached patch adds four new SQL functions for the JSON type:
json_typeof(json) RETURNS text
json_is_object(json) RETURNS boolean
json_is_array(json) RETURNS boolean
json_is_scalar(json) RETURNS booleanThe motivating use-case for this patch is the ability to easily create a
domain type for what RFC 4627 calls "json text", where the top-level value
must be either an object or array. An example of this usage is:CREATE DOMAIN json_document AS json CHECK (NOT json_is_scalar(VALUE));
An additional use-case arises when writing functions which can handle
arbitrary JSON values. This can be difficult when nested objects or arrays
are present or when the input may be either an array or an object. Many of
the built-in functions will raise an error when presented with an "invalid"
value, such as when giving an array to json_object_keys(). The
json_typeof() and json_is_*() functions should make it easier to call the
correct function in these cases, e.g.:CASE json_typeof($1)
WHEN 'object' THEN json_object_keys($1)
WHEN 'array' THEN json_array_elements($1)
ELSE $1
ENDThese new functions operate by making a single call to json_lex() to get the
first token of the JSON value; this token uniquely determines the value's
type. (Thanks to Merlin Moncure for suggesting this approach.)The patch also updates the "JSON Functions and Operators" section of the
docs to ensure that the words "value", "object", and "array" are used in a
consistent manner. "JSON object" and "JSON array" refer to parameters which
must be an object or an array or to results which are always an object or an
array. "JSON value" refers to parameters or results which may be any kind
of JSON.you're welcome! :-).
small point:
Personally I would prune the supplied functions to json_typeof() and
json_is_scalar(). These functions are in the public namespace so
there is a certain minimum bang/buck ratio which IMNSHO
json_is_object() and json_is_array() don't meet -- just call
json_typeof() to get that info.
+1, but I'm wondering why we need anything more than just
json_typeof(). Doesn't that pretty much cover it?
--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On Fri, Aug 2, 2013 at 8:12 PM, Robert Haas <robertmhaas@gmail.com> wrote:
+1, but I'm wondering why we need anything more than just
json_typeof(). Doesn't that pretty much cover it?
I agree with Merlin that json_is_object() is superfluous, since it can just
be replaced with json_typeof() = 'object'. Likewise for json_is_array().
But without json_is_scalar(), the choice is one of these two forms:
json_typeof() NOT IN ('object', 'array')
json_typeof() IN ('string', 'number', 'boolean', 'null')
And it protects the user against forgetting about, say, the 'null' typeof()
when constructing their check expression.
Regards,
Andrew Tipton
On Fri, Aug 2, 2013 at 7:22 AM, Andrew Tipton <andrew@kiwidrew.com> wrote:
On Fri, Aug 2, 2013 at 8:12 PM, Robert Haas <robertmhaas@gmail.com> wrote:
+1, but I'm wondering why we need anything more than just
json_typeof(). Doesn't that pretty much cover it?I agree with Merlin that json_is_object() is superfluous, since it can just
be replaced with json_typeof() = 'object'. Likewise for json_is_array().
But without json_is_scalar(), the choice is one of these two forms:
json_typeof() NOT IN ('object', 'array')
json_typeof() IN ('string', 'number', 'boolean', 'null')And it protects the user against forgetting about, say, the 'null' typeof()
when constructing their check expression.
right: I was thinking also that if/when json were ever to get new
types, you'd appreciate that function.
merlin
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
Merlin Moncure escribi�:
On Fri, Aug 2, 2013 at 7:22 AM, Andrew Tipton <andrew@kiwidrew.com> wrote:
On Fri, Aug 2, 2013 at 8:12 PM, Robert Haas <robertmhaas@gmail.com> wrote:
+1, but I'm wondering why we need anything more than just
json_typeof(). Doesn't that pretty much cover it?I agree with Merlin that json_is_object() is superfluous, since it can just
be replaced with json_typeof() = 'object'. Likewise for json_is_array().
But without json_is_scalar(), the choice is one of these two forms:
json_typeof() NOT IN ('object', 'array')
json_typeof() IN ('string', 'number', 'boolean', 'null')And it protects the user against forgetting about, say, the 'null' typeof()
when constructing their check expression.right: I was thinking also that if/when json were ever to get new
types, you'd appreciate that function.
That was what I thought as well upon seen the code.
--
�lvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On Fri, Aug 2, 2013 at 8:22 AM, Andrew Tipton <andrew@kiwidrew.com> wrote:
But without json_is_scalar(), the choice is one of these two forms:
json_typeof() NOT IN ('object', 'array')
json_typeof() IN ('string', 'number', 'boolean', 'null')
The first of those is what seemed to make sense to me. The user can
always define their own convenience function if they so desire. I
don't think we need to bloat the default contents of pg_proc for that.
--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On 08/06/2013 08:42 AM, Robert Haas wrote:
On Fri, Aug 2, 2013 at 8:22 AM, Andrew Tipton <andrew@kiwidrew.com> wrote:
But without json_is_scalar(), the choice is one of these two forms:
json_typeof() NOT IN ('object', 'array')
json_typeof() IN ('string', 'number', 'boolean', 'null')The first of those is what seemed to make sense to me. The user can
always define their own convenience function if they so desire. I
don't think we need to bloat the default contents of pg_proc for that.
I agree. I have committed a version with just the one function.
cheers
andrew
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers