From e0e64b90e825b4f7131fcfc537fe4d1e2cae166f Mon Sep 17 00:00:00 2001 From: jian he Date: Tue, 2 Dec 2025 23:00:22 +0800 Subject: [PATCH] IS JSON predicate work with domain type IS JSON predicate work with domain base type is TEXT, JSON, JSONB, BYTEA. https://commitfest.postgresql.org/patch/6237/ discussion: https://postgr.es/m/CACJufxEk34DnJFG72CRsPPT4tsJL9arobX0tNPsn7yH28J=zQg@mail.gmail.com --- src/backend/executor/execExprInterp.c | 2 + src/backend/nodes/makefuncs.c | 3 +- src/backend/parser/gram.y | 8 +- src/backend/parser/parse_expr.c | 7 +- src/include/nodes/makefuncs.h | 2 +- src/include/nodes/primnodes.h | 1 + src/test/regress/expected/sqljson.out | 224 ++++++++++++++++++++++++++ src/test/regress/sql/sqljson.sql | 118 ++++++++++++++ 8 files changed, 356 insertions(+), 9 deletions(-) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 5e7bd933afc3..9e61fa1a7f9d 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -4746,6 +4746,8 @@ ExecEvalJsonIsPredicate(ExprState *state, ExprEvalStep *op) } exprtype = exprType(pred->expr); + if (exprtype != pred->resultBaseType) + exprtype = pred->resultBaseType; if (exprtype == TEXTOID || exprtype == JSONOID) { diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c index e2d9e9be41a6..18cfa6df4a7f 100644 --- a/src/backend/nodes/makefuncs.c +++ b/src/backend/nodes/makefuncs.c @@ -984,7 +984,7 @@ makeJsonKeyValue(Node *key, Node *value) */ Node * makeJsonIsPredicate(Node *expr, JsonFormat *format, JsonValueType item_type, - bool unique_keys, int location) + bool unique_keys, Oid resultBaseType, int location) { JsonIsPredicate *n = makeNode(JsonIsPredicate); @@ -992,6 +992,7 @@ makeJsonIsPredicate(Node *expr, JsonFormat *format, JsonValueType item_type, n->format = format; n->item_type = item_type; n->unique_keys = unique_keys; + n->resultBaseType = resultBaseType; n->location = location; return (Node *) n; diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 7856ce9d78fc..7bd101456116 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -15522,7 +15522,7 @@ a_expr: c_expr { $$ = $1; } { JsonFormat *format = makeJsonFormat(JS_FORMAT_DEFAULT, JS_ENC_DEFAULT, -1); - $$ = makeJsonIsPredicate($1, format, $3, $4, @1); + $$ = makeJsonIsPredicate($1, format, $3, $4, InvalidOid, @1); } /* * Required by SQL/JSON, but there are conflicts @@ -15531,7 +15531,7 @@ a_expr: c_expr { $$ = $1; } IS json_predicate_type_constraint json_key_uniqueness_constraint_opt %prec IS { - $$ = makeJsonIsPredicate($1, $2, $4, $5, @1); + $$ = makeJsonIsPredicate($1, $2, $4, $5, InvalidOid, @1); } */ | a_expr IS NOT @@ -15540,7 +15540,7 @@ a_expr: c_expr { $$ = $1; } { JsonFormat *format = makeJsonFormat(JS_FORMAT_DEFAULT, JS_ENC_DEFAULT, -1); - $$ = makeNotExpr(makeJsonIsPredicate($1, format, $4, $5, @1), @1); + $$ = makeNotExpr(makeJsonIsPredicate($1, format, $4, $5, InvalidOid, @1), @1); } /* * Required by SQL/JSON, but there are conflicts @@ -15550,7 +15550,7 @@ a_expr: c_expr { $$ = $1; } json_predicate_type_constraint json_key_uniqueness_constraint_opt %prec IS { - $$ = makeNotExpr(makeJsonIsPredicate($1, $2, $5, $6, @1), @1); + $$ = makeNotExpr(makeJsonIsPredicate($1, $2, $5, $6, InvalidOid, @1), @1); } */ | DEFAULT diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index 6b8fa15fca33..24765997fb2a 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -4056,7 +4056,7 @@ transformJsonParseArg(ParseState *pstate, Node *jsexpr, JsonFormat *format, Node *raw_expr = transformExprRecurse(pstate, jsexpr); Node *expr = raw_expr; - *exprtype = exprType(expr); + *exprtype = getBaseType(exprType(expr)); /* prepare input document */ if (*exprtype == BYTEAOID) @@ -4111,11 +4111,12 @@ transformJsonIsPredicate(ParseState *pstate, JsonIsPredicate *pred) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("cannot use type %s in IS JSON predicate", - format_type_be(exprtype)))); + format_type_be(exprtype))), + parser_errposition(pstate, exprLocation(expr))); /* This intentionally(?) drops the format clause. */ return makeJsonIsPredicate(expr, NULL, pred->item_type, - pred->unique_keys, pred->location); + pred->unique_keys, exprtype, pred->location); } /* diff --git a/src/include/nodes/makefuncs.h b/src/include/nodes/makefuncs.h index 5473ce9a288a..09a64bf5d05f 100644 --- a/src/include/nodes/makefuncs.h +++ b/src/include/nodes/makefuncs.h @@ -117,7 +117,7 @@ extern JsonValueExpr *makeJsonValueExpr(Expr *raw_expr, Expr *formatted_expr, extern Node *makeJsonKeyValue(Node *key, Node *value); extern Node *makeJsonIsPredicate(Node *expr, JsonFormat *format, JsonValueType item_type, bool unique_keys, - int location); + Oid resultBaseType, int location); extern JsonBehavior *makeJsonBehavior(JsonBehaviorType btype, Node *expr, int location); extern JsonTablePath *makeJsonTablePath(Const *pathvalue, char *pathname); diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h index 1b4436f2ff6d..b8ee6cf68f72 100644 --- a/src/include/nodes/primnodes.h +++ b/src/include/nodes/primnodes.h @@ -1761,6 +1761,7 @@ typedef struct JsonIsPredicate JsonFormat *format; /* FORMAT clause, if specified */ JsonValueType item_type; /* JSON item type */ bool unique_keys; /* check key uniqueness? */ + Oid resultBaseType; /* base type of expr */ ParseLoc location; /* token location, or -1 if unknown */ } JsonIsPredicate; diff --git a/src/test/regress/expected/sqljson.out b/src/test/regress/expected/sqljson.out index c7b9e575445e..8ac12dc37a99 100644 --- a/src/test/regress/expected/sqljson.out +++ b/src/test/regress/expected/sqljson.out @@ -1110,6 +1110,11 @@ CREATE OR REPLACE VIEW public.json_array_subquery_view AS FROM ( VALUES (1), (2), (NULL::integer), (4)) foo(i)) q(a)) AS "json_array" DROP VIEW json_array_subquery_view; -- IS JSON predicate +CREATE DOMAIN jd1 AS JSON CHECK ((VALUE ->'a')::text <> '3'); +CREATE DOMAIN jd2 AS JSONB CHECK ((VALUE ->'a') = '1'::jsonb); +CREATE DOMAIN jd3 AS text CHECK (VALUE <> 'a'); +CREATE DOMAIN jd4 AS bytea CHECK (VALUE <> '\x61'); +CREATE DOMAIN jd5 AS date CHECK (VALUE <> NULL); SELECT NULL IS JSON; ?column? ---------- @@ -1148,6 +1153,131 @@ SELECT NULL::bytea IS JSON; SELECT NULL::int IS JSON; ERROR: cannot use type integer in IS JSON predicate +LINE 1: SELECT NULL::int IS JSON; + ^ +SELECT NULL::jd1 IS JSON; + ?column? +---------- + +(1 row) + +SELECT NULL::jd1 IS NOT JSON; + ?column? +---------- + +(1 row) + +SELECT NULL::jd2 IS JSON; + ?column? +---------- + +(1 row) + +SELECT NULL::jd3 IS JSON; + ?column? +---------- + +(1 row) + +SELECT NULL::jd4 IS JSON; + ?column? +---------- + +(1 row) + +SELECT NULL::jd4 IS NOT JSON; + ?column? +---------- + +(1 row) + +SELECT NULL::jd5 IS JSON; --error +ERROR: cannot use type date in IS JSON predicate +LINE 1: SELECT NULL::jd5 IS JSON; + ^ +SELECT NULL::jd5 IS JSON WITH UNIQUE KEYS; --error +ERROR: cannot use type date in IS JSON predicate +LINE 1: SELECT NULL::jd5 IS JSON WITH UNIQUE KEYS; + ^ +CREATE VIEW domain_isjson AS +WITH cte(a) as (VALUES('{"a": 1, "a": 2}')) +SELECT a::jd1 IS JSON WITH UNIQUE KEYS as col1, + a::jd3 IS JSON WITH UNIQUE KEYS as col2, + a::jd4 IS JSON WITH UNIQUE KEYS as col3 +FROM cte; +\sv domain_isjson +CREATE OR REPLACE VIEW public.domain_isjson AS + WITH cte(a) AS ( + VALUES ('{"a": 1, "a": 2}'::text) + ) + SELECT a::jd1 IS JSON WITH UNIQUE KEYS AS col1, + a::jd3 IS JSON WITH UNIQUE KEYS AS col2, + a::jd4 IS JSON WITH UNIQUE KEYS AS col3 + FROM cte +SELECT * FROM domain_isjson; + col1 | col2 | col3 +------+------+------ + f | f | f +(1 row) + +CREATE TEMP TABLE ts_domain(js text); +INSERT INTO ts_domain VALUES ('{"a":3}'), ('{"a":"1"}'), ('a'), ('\x61'); +SELECT js::jd1 IS JSON FROM ts_domain; +ERROR: value for domain jd1 violates check constraint "jd1_check" +SELECT js::jd2 IS JSON FROM ts_domain; +ERROR: value for domain jd2 violates check constraint "jd2_check" +SELECT js::jd3 IS JSON FROM ts_domain; +ERROR: value for domain jd3 violates check constraint "jd3_check" +SELECT js::jd4 IS JSON FROM ts_domain; +ERROR: value for domain jd4 violates check constraint "jd4_check" +SELECT js, + pg_typeof(js), + js IS JSON OBJECT "object?", + js IS JSON ARRAY "array?", + js IS JSON ARRAY WITH UNIQUE KEYS "array w. UK?", + js IS JSON ARRAY WITHOUT UNIQUE KEYS "array w/o UK?" +FROM (VALUES ('[{"a":"1"}, {"b":"2","b":"3"}]'::jd1)) foo(js); + js | pg_typeof | object? | array? | array w. UK? | array w/o UK? +--------------------------------+-----------+---------+--------+--------------+--------------- + [{"a":"1"}, {"b":"2","b":"3"}] | jd1 | f | t | f | t +(1 row) + +SELECT js, + pg_typeof(js), + js IS JSON OBJECT "object?", + js IS JSON ARRAY "array?", + js IS JSON ARRAY WITH UNIQUE KEYS "array w. UK?", + js IS JSON ARRAY WITHOUT UNIQUE KEYS "array w/o UK?" +FROM (VALUES ('[{"a":"1"}, {"b":"2","b":"3"}]'::jd2)) foo(js); + js | pg_typeof | object? | array? | array w. UK? | array w/o UK? +--------------------------+-----------+---------+--------+--------------+--------------- + [{"a": "1"}, {"b": "3"}] | jd2 | f | t | t | t +(1 row) + +SELECT js, + pg_typeof(js), + js IS JSON OBJECT "object?", + js IS JSON ARRAY "array?", + js IS JSON ARRAY WITH UNIQUE KEYS "array w. UK?", + js IS JSON ARRAY WITHOUT UNIQUE KEYS "array w/o UK?" +FROM (VALUES ('[{"a":"1"}, {"b":"2","b":"3"}]'::jd3)) foo(js); + js | pg_typeof | object? | array? | array w. UK? | array w/o UK? +--------------------------------+-----------+---------+--------+--------------+--------------- + [{"a":"1"}, {"b":"2","b":"3"}] | jd3 | f | t | f | t +(1 row) + +SELECT js, + pg_typeof(js), + js IS JSON OBJECT "object?", + js IS JSON ARRAY "array?", + js IS JSON ARRAY WITH UNIQUE KEYS "array w. UK?", + js IS JSON ARRAY WITHOUT UNIQUE KEYS "array w/o UK?" +FROM (VALUES ('[{"a":"1"}, {"b":"2","b":"3"}]'::jd4)) foo(js); + js | pg_typeof | object? | array? | array w. UK? | array w/o UK? +----------------------------------------------------------------+-----------+---------+--------+--------------+--------------- + \x5b7b2261223a2231227d2c207b2262223a2232222c2262223a2233227d5d | jd4 | f | t | f | t +(1 row) + SELECT '' IS JSON; ?column? ---------- @@ -1206,6 +1336,33 @@ FROM ["a",] | f | t | f | f | f | f | f | f (16 rows) +SELECT + js, + js IS JSON "IS JSON", + js IS NOT JSON "IS NOT JSON", + js IS JSON VALUE "IS VALUE", + js IS JSON OBJECT "IS OBJECT", + js IS JSON ARRAY "IS ARRAY", + js IS JSON SCALAR "IS SCALAR", + js IS JSON WITHOUT UNIQUE KEYS "WITHOUT UNIQUE", + js IS JSON WITH UNIQUE KEYS "WITH UNIQUE" +FROM + (SELECT js::jd3 FROM test_is_json WHERE js IS JSON) foo(js); + js | IS JSON | IS NOT JSON | IS VALUE | IS OBJECT | IS ARRAY | IS SCALAR | WITHOUT UNIQUE | WITH UNIQUE +-----------------------------------------------+---------+-------------+----------+-----------+----------+-----------+----------------+------------- + 123 | t | f | t | f | f | t | t | t + "aaa " | t | f | t | f | f | t | t | t + true | t | f | t | f | f | t | t | t + null | t | f | t | f | f | t | t | t + [] | t | f | t | f | t | f | t | t + [1, "2", {}] | t | f | t | f | t | f | t | t + {} | t | f | t | t | f | f | t | t + { "a": 1, "b": null } | t | f | t | t | f | f | t | t + { "a": 1, "a": null } | t | f | t | t | f | f | t | f + { "a": 1, "b": [{ "a": 1 }, { "a": 2 }] } | t | f | t | t | f | f | t | t + { "a": 1, "b": [{ "a": 1, "b": 0, "a": 2 }] } | t | f | t | t | f | f | t | f +(11 rows) + SELECT js, js IS JSON "IS JSON", @@ -1233,6 +1390,46 @@ FROM { "a": 1, "b": [{ "a": 1, "b": 0, "a": 2 }] } | t | f | t | t | f | f | t | f (11 rows) +SELECT + js, + js IS JSON "IS JSON", + js IS NOT JSON "IS NOT JSON", + js IS JSON VALUE "IS VALUE", + js IS JSON OBJECT "IS OBJECT", + js IS JSON ARRAY "IS ARRAY", + js IS JSON SCALAR "IS SCALAR", + js IS JSON WITHOUT UNIQUE KEYS "WITHOUT UNIQUE", + js IS JSON WITH UNIQUE KEYS "WITH UNIQUE" +FROM + (SELECT js::jd1 FROM test_is_json WHERE js IS JSON) foo(js); + js | IS JSON | IS NOT JSON | IS VALUE | IS OBJECT | IS ARRAY | IS SCALAR | WITHOUT UNIQUE | WITH UNIQUE +-----------------------------------------------+---------+-------------+----------+-----------+----------+-----------+----------------+------------- + 123 | t | f | t | f | f | t | t | t + "aaa " | t | f | t | f | f | t | t | t + true | t | f | t | f | f | t | t | t + null | t | f | t | f | f | t | t | t + [] | t | f | t | f | t | f | t | t + [1, "2", {}] | t | f | t | f | t | f | t | t + {} | t | f | t | t | f | f | t | t + { "a": 1, "b": null } | t | f | t | t | f | f | t | t + { "a": 1, "a": null } | t | f | t | t | f | f | t | f + { "a": 1, "b": [{ "a": 1 }, { "a": 2 }] } | t | f | t | t | f | f | t | t + { "a": 1, "b": [{ "a": 1, "b": 0, "a": 2 }] } | t | f | t | t | f | f | t | f +(11 rows) + +SELECT + js, + js IS JSON "IS JSON", + js IS NOT JSON "IS NOT JSON", + js IS JSON VALUE "IS VALUE", + js IS JSON OBJECT "IS OBJECT", + js IS JSON ARRAY "IS ARRAY", + js IS JSON SCALAR "IS SCALAR", + js IS JSON WITHOUT UNIQUE KEYS "WITHOUT UNIQUE", + js IS JSON WITH UNIQUE KEYS "WITH UNIQUE" +FROM + (SELECT js::jd2 FROM test_is_json WHERE js IS JSON) foo(js); +ERROR: value for domain jd2 violates check constraint "jd2_check" SELECT js0, js IS JSON "IS JSON", @@ -1260,6 +1457,33 @@ FROM { "a": 1, "b": [{ "a": 1, "b": 0, "a": 2 }] } | t | f | t | t | f | f | t | f (11 rows) +SELECT + js0, + js IS JSON "IS JSON", + js IS NOT JSON "IS NOT JSON", + js IS JSON VALUE "IS VALUE", + js IS JSON OBJECT "IS OBJECT", + js IS JSON ARRAY "IS ARRAY", + js IS JSON SCALAR "IS SCALAR", + js IS JSON WITHOUT UNIQUE KEYS "WITHOUT UNIQUE", + js IS JSON WITH UNIQUE KEYS "WITH UNIQUE" +FROM + (SELECT js, js::jd4 FROM test_is_json WHERE js IS JSON) foo(js0, js); + js0 | IS JSON | IS NOT JSON | IS VALUE | IS OBJECT | IS ARRAY | IS SCALAR | WITHOUT UNIQUE | WITH UNIQUE +-----------------------------------------------+---------+-------------+----------+-----------+----------+-----------+----------------+------------- + 123 | t | f | t | f | f | t | t | t + "aaa " | t | f | t | f | f | t | t | t + true | t | f | t | f | f | t | t | t + null | t | f | t | f | f | t | t | t + [] | t | f | t | f | t | f | t | t + [1, "2", {}] | t | f | t | f | t | f | t | t + {} | t | f | t | t | f | f | t | t + { "a": 1, "b": null } | t | f | t | t | f | f | t | t + { "a": 1, "a": null } | t | f | t | t | f | f | t | f + { "a": 1, "b": [{ "a": 1 }, { "a": 2 }] } | t | f | t | t | f | f | t | t + { "a": 1, "b": [{ "a": 1, "b": 0, "a": 2 }] } | t | f | t | t | f | f | t | f +(11 rows) + SELECT js, js IS JSON "IS JSON", diff --git a/src/test/regress/sql/sqljson.sql b/src/test/regress/sql/sqljson.sql index 343d344d2707..88d6bc37333d 100644 --- a/src/test/regress/sql/sqljson.sql +++ b/src/test/regress/sql/sqljson.sql @@ -387,6 +387,12 @@ SELECT JSON_ARRAY(SELECT i FROM (VALUES (1), (2), (NULL), (4)) foo(i) RETURNING DROP VIEW json_array_subquery_view; -- IS JSON predicate +CREATE DOMAIN jd1 AS JSON CHECK ((VALUE ->'a')::text <> '3'); +CREATE DOMAIN jd2 AS JSONB CHECK ((VALUE ->'a') = '1'::jsonb); +CREATE DOMAIN jd3 AS text CHECK (VALUE <> 'a'); +CREATE DOMAIN jd4 AS bytea CHECK (VALUE <> '\x61'); +CREATE DOMAIN jd5 AS date CHECK (VALUE <> NULL); + SELECT NULL IS JSON; SELECT NULL IS NOT JSON; SELECT NULL::json IS JSON; @@ -395,6 +401,66 @@ SELECT NULL::text IS JSON; SELECT NULL::bytea IS JSON; SELECT NULL::int IS JSON; +SELECT NULL::jd1 IS JSON; +SELECT NULL::jd1 IS NOT JSON; +SELECT NULL::jd2 IS JSON; +SELECT NULL::jd3 IS JSON; +SELECT NULL::jd4 IS JSON; +SELECT NULL::jd4 IS NOT JSON; + +SELECT NULL::jd5 IS JSON; --error +SELECT NULL::jd5 IS JSON WITH UNIQUE KEYS; --error + +CREATE VIEW domain_isjson AS +WITH cte(a) as (VALUES('{"a": 1, "a": 2}')) +SELECT a::jd1 IS JSON WITH UNIQUE KEYS as col1, + a::jd3 IS JSON WITH UNIQUE KEYS as col2, + a::jd4 IS JSON WITH UNIQUE KEYS as col3 +FROM cte; + +\sv domain_isjson +SELECT * FROM domain_isjson; + +CREATE TEMP TABLE ts_domain(js text); +INSERT INTO ts_domain VALUES ('{"a":3}'), ('{"a":"1"}'), ('a'), ('\x61'); + +SELECT js::jd1 IS JSON FROM ts_domain; +SELECT js::jd2 IS JSON FROM ts_domain; +SELECT js::jd3 IS JSON FROM ts_domain; +SELECT js::jd4 IS JSON FROM ts_domain; + +SELECT js, + pg_typeof(js), + js IS JSON OBJECT "object?", + js IS JSON ARRAY "array?", + js IS JSON ARRAY WITH UNIQUE KEYS "array w. UK?", + js IS JSON ARRAY WITHOUT UNIQUE KEYS "array w/o UK?" +FROM (VALUES ('[{"a":"1"}, {"b":"2","b":"3"}]'::jd1)) foo(js); + +SELECT js, + pg_typeof(js), + js IS JSON OBJECT "object?", + js IS JSON ARRAY "array?", + js IS JSON ARRAY WITH UNIQUE KEYS "array w. UK?", + js IS JSON ARRAY WITHOUT UNIQUE KEYS "array w/o UK?" +FROM (VALUES ('[{"a":"1"}, {"b":"2","b":"3"}]'::jd2)) foo(js); + +SELECT js, + pg_typeof(js), + js IS JSON OBJECT "object?", + js IS JSON ARRAY "array?", + js IS JSON ARRAY WITH UNIQUE KEYS "array w. UK?", + js IS JSON ARRAY WITHOUT UNIQUE KEYS "array w/o UK?" +FROM (VALUES ('[{"a":"1"}, {"b":"2","b":"3"}]'::jd3)) foo(js); + +SELECT js, + pg_typeof(js), + js IS JSON OBJECT "object?", + js IS JSON ARRAY "array?", + js IS JSON ARRAY WITH UNIQUE KEYS "array w. UK?", + js IS JSON ARRAY WITHOUT UNIQUE KEYS "array w/o UK?" +FROM (VALUES ('[{"a":"1"}, {"b":"2","b":"3"}]'::jd4)) foo(js); + SELECT '' IS JSON; SELECT bytea '\x00' IS JSON; @@ -432,6 +498,19 @@ SELECT FROM test_is_json; +SELECT + js, + js IS JSON "IS JSON", + js IS NOT JSON "IS NOT JSON", + js IS JSON VALUE "IS VALUE", + js IS JSON OBJECT "IS OBJECT", + js IS JSON ARRAY "IS ARRAY", + js IS JSON SCALAR "IS SCALAR", + js IS JSON WITHOUT UNIQUE KEYS "WITHOUT UNIQUE", + js IS JSON WITH UNIQUE KEYS "WITH UNIQUE" +FROM + (SELECT js::jd3 FROM test_is_json WHERE js IS JSON) foo(js); + SELECT js, js IS JSON "IS JSON", @@ -445,6 +524,32 @@ SELECT FROM (SELECT js::json FROM test_is_json WHERE js IS JSON) foo(js); +SELECT + js, + js IS JSON "IS JSON", + js IS NOT JSON "IS NOT JSON", + js IS JSON VALUE "IS VALUE", + js IS JSON OBJECT "IS OBJECT", + js IS JSON ARRAY "IS ARRAY", + js IS JSON SCALAR "IS SCALAR", + js IS JSON WITHOUT UNIQUE KEYS "WITHOUT UNIQUE", + js IS JSON WITH UNIQUE KEYS "WITH UNIQUE" +FROM + (SELECT js::jd1 FROM test_is_json WHERE js IS JSON) foo(js); + +SELECT + js, + js IS JSON "IS JSON", + js IS NOT JSON "IS NOT JSON", + js IS JSON VALUE "IS VALUE", + js IS JSON OBJECT "IS OBJECT", + js IS JSON ARRAY "IS ARRAY", + js IS JSON SCALAR "IS SCALAR", + js IS JSON WITHOUT UNIQUE KEYS "WITHOUT UNIQUE", + js IS JSON WITH UNIQUE KEYS "WITH UNIQUE" +FROM + (SELECT js::jd2 FROM test_is_json WHERE js IS JSON) foo(js); + SELECT js0, js IS JSON "IS JSON", @@ -458,6 +563,19 @@ SELECT FROM (SELECT js, js::bytea FROM test_is_json WHERE js IS JSON) foo(js0, js); +SELECT + js0, + js IS JSON "IS JSON", + js IS NOT JSON "IS NOT JSON", + js IS JSON VALUE "IS VALUE", + js IS JSON OBJECT "IS OBJECT", + js IS JSON ARRAY "IS ARRAY", + js IS JSON SCALAR "IS SCALAR", + js IS JSON WITHOUT UNIQUE KEYS "WITHOUT UNIQUE", + js IS JSON WITH UNIQUE KEYS "WITH UNIQUE" +FROM + (SELECT js, js::jd4 FROM test_is_json WHERE js IS JSON) foo(js0, js); + SELECT js, js IS JSON "IS JSON",