Skip to content

Commit 5885d19

Browse files
author
Commitfest Bot
committed
[CF 6237] v2 - IS JSON predicate support for domain base type as JSON/JSONB/BYTEA/TEXT
This branch was automatically generated by a robot using patches from an email thread registered at: https://commitfest.postgresql.org/patch/6237 The branch will be overwritten each time a new patch version is posted to the thread, and also periodically to check for bitrot caused by changes on the master branch. Patch(es): https://www.postgresql.org/message-id/CACJufxEDN24yBCkFw9sgv2Ocoq=TAtydcJ1ZLR3PEb_NJnTfqA@mail.gmail.com Author(s): Jian He
2 parents b4cbc10 + e0e64b9 commit 5885d19

File tree

8 files changed

+356
-9
lines changed

8 files changed

+356
-9
lines changed

src/backend/executor/execExprInterp.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4746,6 +4746,8 @@ ExecEvalJsonIsPredicate(ExprState *state, ExprEvalStep *op)
47464746
}
47474747

47484748
exprtype = exprType(pred->expr);
4749+
if (exprtype != pred->resultBaseType)
4750+
exprtype = pred->resultBaseType;
47494751

47504752
if (exprtype == TEXTOID || exprtype == JSONOID)
47514753
{

src/backend/nodes/makefuncs.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -984,14 +984,15 @@ makeJsonKeyValue(Node *key, Node *value)
984984
*/
985985
Node *
986986
makeJsonIsPredicate(Node *expr, JsonFormat *format, JsonValueType item_type,
987-
bool unique_keys, int location)
987+
bool unique_keys, Oid resultBaseType, int location)
988988
{
989989
JsonIsPredicate *n = makeNode(JsonIsPredicate);
990990

991991
n->expr = expr;
992992
n->format = format;
993993
n->item_type = item_type;
994994
n->unique_keys = unique_keys;
995+
n->resultBaseType = resultBaseType;
995996
n->location = location;
996997

997998
return (Node *) n;

src/backend/parser/gram.y

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15522,7 +15522,7 @@ a_expr: c_expr { $$ = $1; }
1552215522
{
1552315523
JsonFormat *format = makeJsonFormat(JS_FORMAT_DEFAULT, JS_ENC_DEFAULT, -1);
1552415524

15525-
$$ = makeJsonIsPredicate($1, format, $3, $4, @1);
15525+
$$ = makeJsonIsPredicate($1, format, $3, $4, InvalidOid, @1);
1552615526
}
1552715527
/*
1552815528
* Required by SQL/JSON, but there are conflicts
@@ -15531,7 +15531,7 @@ a_expr: c_expr { $$ = $1; }
1553115531
IS json_predicate_type_constraint
1553215532
json_key_uniqueness_constraint_opt %prec IS
1553315533
{
15534-
$$ = makeJsonIsPredicate($1, $2, $4, $5, @1);
15534+
$$ = makeJsonIsPredicate($1, $2, $4, $5, InvalidOid, @1);
1553515535
}
1553615536
*/
1553715537
| a_expr IS NOT
@@ -15540,7 +15540,7 @@ a_expr: c_expr { $$ = $1; }
1554015540
{
1554115541
JsonFormat *format = makeJsonFormat(JS_FORMAT_DEFAULT, JS_ENC_DEFAULT, -1);
1554215542

15543-
$$ = makeNotExpr(makeJsonIsPredicate($1, format, $4, $5, @1), @1);
15543+
$$ = makeNotExpr(makeJsonIsPredicate($1, format, $4, $5, InvalidOid, @1), @1);
1554415544
}
1554515545
/*
1554615546
* Required by SQL/JSON, but there are conflicts
@@ -15550,7 +15550,7 @@ a_expr: c_expr { $$ = $1; }
1555015550
json_predicate_type_constraint
1555115551
json_key_uniqueness_constraint_opt %prec IS
1555215552
{
15553-
$$ = makeNotExpr(makeJsonIsPredicate($1, $2, $5, $6, @1), @1);
15553+
$$ = makeNotExpr(makeJsonIsPredicate($1, $2, $5, $6, InvalidOid, @1), @1);
1555415554
}
1555515555
*/
1555615556
| DEFAULT

src/backend/parser/parse_expr.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4056,7 +4056,7 @@ transformJsonParseArg(ParseState *pstate, Node *jsexpr, JsonFormat *format,
40564056
Node *raw_expr = transformExprRecurse(pstate, jsexpr);
40574057
Node *expr = raw_expr;
40584058

4059-
*exprtype = exprType(expr);
4059+
*exprtype = getBaseType(exprType(expr));
40604060

40614061
/* prepare input document */
40624062
if (*exprtype == BYTEAOID)
@@ -4111,11 +4111,12 @@ transformJsonIsPredicate(ParseState *pstate, JsonIsPredicate *pred)
41114111
ereport(ERROR,
41124112
(errcode(ERRCODE_DATATYPE_MISMATCH),
41134113
errmsg("cannot use type %s in IS JSON predicate",
4114-
format_type_be(exprtype))));
4114+
format_type_be(exprtype))),
4115+
parser_errposition(pstate, exprLocation(expr)));
41154116

41164117
/* This intentionally(?) drops the format clause. */
41174118
return makeJsonIsPredicate(expr, NULL, pred->item_type,
4118-
pred->unique_keys, pred->location);
4119+
pred->unique_keys, exprtype, pred->location);
41194120
}
41204121

41214122
/*

src/include/nodes/makefuncs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ extern JsonValueExpr *makeJsonValueExpr(Expr *raw_expr, Expr *formatted_expr,
117117
extern Node *makeJsonKeyValue(Node *key, Node *value);
118118
extern Node *makeJsonIsPredicate(Node *expr, JsonFormat *format,
119119
JsonValueType item_type, bool unique_keys,
120-
int location);
120+
Oid resultBaseType, int location);
121121
extern JsonBehavior *makeJsonBehavior(JsonBehaviorType btype, Node *expr,
122122
int location);
123123
extern JsonTablePath *makeJsonTablePath(Const *pathvalue, char *pathname);

src/include/nodes/primnodes.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1761,6 +1761,7 @@ typedef struct JsonIsPredicate
17611761
JsonFormat *format; /* FORMAT clause, if specified */
17621762
JsonValueType item_type; /* JSON item type */
17631763
bool unique_keys; /* check key uniqueness? */
1764+
Oid resultBaseType; /* base type of expr */
17641765
ParseLoc location; /* token location, or -1 if unknown */
17651766
} JsonIsPredicate;
17661767

src/test/regress/expected/sqljson.out

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1110,6 +1110,11 @@ CREATE OR REPLACE VIEW public.json_array_subquery_view AS
11101110
FROM ( VALUES (1), (2), (NULL::integer), (4)) foo(i)) q(a)) AS "json_array"
11111111
DROP VIEW json_array_subquery_view;
11121112
-- IS JSON predicate
1113+
CREATE DOMAIN jd1 AS JSON CHECK ((VALUE ->'a')::text <> '3');
1114+
CREATE DOMAIN jd2 AS JSONB CHECK ((VALUE ->'a') = '1'::jsonb);
1115+
CREATE DOMAIN jd3 AS text CHECK (VALUE <> 'a');
1116+
CREATE DOMAIN jd4 AS bytea CHECK (VALUE <> '\x61');
1117+
CREATE DOMAIN jd5 AS date CHECK (VALUE <> NULL);
11131118
SELECT NULL IS JSON;
11141119
?column?
11151120
----------
@@ -1148,6 +1153,131 @@ SELECT NULL::bytea IS JSON;
11481153

11491154
SELECT NULL::int IS JSON;
11501155
ERROR: cannot use type integer in IS JSON predicate
1156+
LINE 1: SELECT NULL::int IS JSON;
1157+
^
1158+
SELECT NULL::jd1 IS JSON;
1159+
?column?
1160+
----------
1161+
1162+
(1 row)
1163+
1164+
SELECT NULL::jd1 IS NOT JSON;
1165+
?column?
1166+
----------
1167+
1168+
(1 row)
1169+
1170+
SELECT NULL::jd2 IS JSON;
1171+
?column?
1172+
----------
1173+
1174+
(1 row)
1175+
1176+
SELECT NULL::jd3 IS JSON;
1177+
?column?
1178+
----------
1179+
1180+
(1 row)
1181+
1182+
SELECT NULL::jd4 IS JSON;
1183+
?column?
1184+
----------
1185+
1186+
(1 row)
1187+
1188+
SELECT NULL::jd4 IS NOT JSON;
1189+
?column?
1190+
----------
1191+
1192+
(1 row)
1193+
1194+
SELECT NULL::jd5 IS JSON; --error
1195+
ERROR: cannot use type date in IS JSON predicate
1196+
LINE 1: SELECT NULL::jd5 IS JSON;
1197+
^
1198+
SELECT NULL::jd5 IS JSON WITH UNIQUE KEYS; --error
1199+
ERROR: cannot use type date in IS JSON predicate
1200+
LINE 1: SELECT NULL::jd5 IS JSON WITH UNIQUE KEYS;
1201+
^
1202+
CREATE VIEW domain_isjson AS
1203+
WITH cte(a) as (VALUES('{"a": 1, "a": 2}'))
1204+
SELECT a::jd1 IS JSON WITH UNIQUE KEYS as col1,
1205+
a::jd3 IS JSON WITH UNIQUE KEYS as col2,
1206+
a::jd4 IS JSON WITH UNIQUE KEYS as col3
1207+
FROM cte;
1208+
\sv domain_isjson
1209+
CREATE OR REPLACE VIEW public.domain_isjson AS
1210+
WITH cte(a) AS (
1211+
VALUES ('{"a": 1, "a": 2}'::text)
1212+
)
1213+
SELECT a::jd1 IS JSON WITH UNIQUE KEYS AS col1,
1214+
a::jd3 IS JSON WITH UNIQUE KEYS AS col2,
1215+
a::jd4 IS JSON WITH UNIQUE KEYS AS col3
1216+
FROM cte
1217+
SELECT * FROM domain_isjson;
1218+
col1 | col2 | col3
1219+
------+------+------
1220+
f | f | f
1221+
(1 row)
1222+
1223+
CREATE TEMP TABLE ts_domain(js text);
1224+
INSERT INTO ts_domain VALUES ('{"a":3}'), ('{"a":"1"}'), ('a'), ('\x61');
1225+
SELECT js::jd1 IS JSON FROM ts_domain;
1226+
ERROR: value for domain jd1 violates check constraint "jd1_check"
1227+
SELECT js::jd2 IS JSON FROM ts_domain;
1228+
ERROR: value for domain jd2 violates check constraint "jd2_check"
1229+
SELECT js::jd3 IS JSON FROM ts_domain;
1230+
ERROR: value for domain jd3 violates check constraint "jd3_check"
1231+
SELECT js::jd4 IS JSON FROM ts_domain;
1232+
ERROR: value for domain jd4 violates check constraint "jd4_check"
1233+
SELECT js,
1234+
pg_typeof(js),
1235+
js IS JSON OBJECT "object?",
1236+
js IS JSON ARRAY "array?",
1237+
js IS JSON ARRAY WITH UNIQUE KEYS "array w. UK?",
1238+
js IS JSON ARRAY WITHOUT UNIQUE KEYS "array w/o UK?"
1239+
FROM (VALUES ('[{"a":"1"}, {"b":"2","b":"3"}]'::jd1)) foo(js);
1240+
js | pg_typeof | object? | array? | array w. UK? | array w/o UK?
1241+
--------------------------------+-----------+---------+--------+--------------+---------------
1242+
[{"a":"1"}, {"b":"2","b":"3"}] | jd1 | f | t | f | t
1243+
(1 row)
1244+
1245+
SELECT js,
1246+
pg_typeof(js),
1247+
js IS JSON OBJECT "object?",
1248+
js IS JSON ARRAY "array?",
1249+
js IS JSON ARRAY WITH UNIQUE KEYS "array w. UK?",
1250+
js IS JSON ARRAY WITHOUT UNIQUE KEYS "array w/o UK?"
1251+
FROM (VALUES ('[{"a":"1"}, {"b":"2","b":"3"}]'::jd2)) foo(js);
1252+
js | pg_typeof | object? | array? | array w. UK? | array w/o UK?
1253+
--------------------------+-----------+---------+--------+--------------+---------------
1254+
[{"a": "1"}, {"b": "3"}] | jd2 | f | t | t | t
1255+
(1 row)
1256+
1257+
SELECT js,
1258+
pg_typeof(js),
1259+
js IS JSON OBJECT "object?",
1260+
js IS JSON ARRAY "array?",
1261+
js IS JSON ARRAY WITH UNIQUE KEYS "array w. UK?",
1262+
js IS JSON ARRAY WITHOUT UNIQUE KEYS "array w/o UK?"
1263+
FROM (VALUES ('[{"a":"1"}, {"b":"2","b":"3"}]'::jd3)) foo(js);
1264+
js | pg_typeof | object? | array? | array w. UK? | array w/o UK?
1265+
--------------------------------+-----------+---------+--------+--------------+---------------
1266+
[{"a":"1"}, {"b":"2","b":"3"}] | jd3 | f | t | f | t
1267+
(1 row)
1268+
1269+
SELECT js,
1270+
pg_typeof(js),
1271+
js IS JSON OBJECT "object?",
1272+
js IS JSON ARRAY "array?",
1273+
js IS JSON ARRAY WITH UNIQUE KEYS "array w. UK?",
1274+
js IS JSON ARRAY WITHOUT UNIQUE KEYS "array w/o UK?"
1275+
FROM (VALUES ('[{"a":"1"}, {"b":"2","b":"3"}]'::jd4)) foo(js);
1276+
js | pg_typeof | object? | array? | array w. UK? | array w/o UK?
1277+
----------------------------------------------------------------+-----------+---------+--------+--------------+---------------
1278+
\x5b7b2261223a2231227d2c207b2262223a2232222c2262223a2233227d5d | jd4 | f | t | f | t
1279+
(1 row)
1280+
11511281
SELECT '' IS JSON;
11521282
?column?
11531283
----------
@@ -1206,6 +1336,33 @@ FROM
12061336
["a",] | f | t | f | f | f | f | f | f
12071337
(16 rows)
12081338

1339+
SELECT
1340+
js,
1341+
js IS JSON "IS JSON",
1342+
js IS NOT JSON "IS NOT JSON",
1343+
js IS JSON VALUE "IS VALUE",
1344+
js IS JSON OBJECT "IS OBJECT",
1345+
js IS JSON ARRAY "IS ARRAY",
1346+
js IS JSON SCALAR "IS SCALAR",
1347+
js IS JSON WITHOUT UNIQUE KEYS "WITHOUT UNIQUE",
1348+
js IS JSON WITH UNIQUE KEYS "WITH UNIQUE"
1349+
FROM
1350+
(SELECT js::jd3 FROM test_is_json WHERE js IS JSON) foo(js);
1351+
js | IS JSON | IS NOT JSON | IS VALUE | IS OBJECT | IS ARRAY | IS SCALAR | WITHOUT UNIQUE | WITH UNIQUE
1352+
-----------------------------------------------+---------+-------------+----------+-----------+----------+-----------+----------------+-------------
1353+
123 | t | f | t | f | f | t | t | t
1354+
"aaa " | t | f | t | f | f | t | t | t
1355+
true | t | f | t | f | f | t | t | t
1356+
null | t | f | t | f | f | t | t | t
1357+
[] | t | f | t | f | t | f | t | t
1358+
[1, "2", {}] | t | f | t | f | t | f | t | t
1359+
{} | t | f | t | t | f | f | t | t
1360+
{ "a": 1, "b": null } | t | f | t | t | f | f | t | t
1361+
{ "a": 1, "a": null } | t | f | t | t | f | f | t | f
1362+
{ "a": 1, "b": [{ "a": 1 }, { "a": 2 }] } | t | f | t | t | f | f | t | t
1363+
{ "a": 1, "b": [{ "a": 1, "b": 0, "a": 2 }] } | t | f | t | t | f | f | t | f
1364+
(11 rows)
1365+
12091366
SELECT
12101367
js,
12111368
js IS JSON "IS JSON",
@@ -1233,6 +1390,46 @@ FROM
12331390
{ "a": 1, "b": [{ "a": 1, "b": 0, "a": 2 }] } | t | f | t | t | f | f | t | f
12341391
(11 rows)
12351392

1393+
SELECT
1394+
js,
1395+
js IS JSON "IS JSON",
1396+
js IS NOT JSON "IS NOT JSON",
1397+
js IS JSON VALUE "IS VALUE",
1398+
js IS JSON OBJECT "IS OBJECT",
1399+
js IS JSON ARRAY "IS ARRAY",
1400+
js IS JSON SCALAR "IS SCALAR",
1401+
js IS JSON WITHOUT UNIQUE KEYS "WITHOUT UNIQUE",
1402+
js IS JSON WITH UNIQUE KEYS "WITH UNIQUE"
1403+
FROM
1404+
(SELECT js::jd1 FROM test_is_json WHERE js IS JSON) foo(js);
1405+
js | IS JSON | IS NOT JSON | IS VALUE | IS OBJECT | IS ARRAY | IS SCALAR | WITHOUT UNIQUE | WITH UNIQUE
1406+
-----------------------------------------------+---------+-------------+----------+-----------+----------+-----------+----------------+-------------
1407+
123 | t | f | t | f | f | t | t | t
1408+
"aaa " | t | f | t | f | f | t | t | t
1409+
true | t | f | t | f | f | t | t | t
1410+
null | t | f | t | f | f | t | t | t
1411+
[] | t | f | t | f | t | f | t | t
1412+
[1, "2", {}] | t | f | t | f | t | f | t | t
1413+
{} | t | f | t | t | f | f | t | t
1414+
{ "a": 1, "b": null } | t | f | t | t | f | f | t | t
1415+
{ "a": 1, "a": null } | t | f | t | t | f | f | t | f
1416+
{ "a": 1, "b": [{ "a": 1 }, { "a": 2 }] } | t | f | t | t | f | f | t | t
1417+
{ "a": 1, "b": [{ "a": 1, "b": 0, "a": 2 }] } | t | f | t | t | f | f | t | f
1418+
(11 rows)
1419+
1420+
SELECT
1421+
js,
1422+
js IS JSON "IS JSON",
1423+
js IS NOT JSON "IS NOT JSON",
1424+
js IS JSON VALUE "IS VALUE",
1425+
js IS JSON OBJECT "IS OBJECT",
1426+
js IS JSON ARRAY "IS ARRAY",
1427+
js IS JSON SCALAR "IS SCALAR",
1428+
js IS JSON WITHOUT UNIQUE KEYS "WITHOUT UNIQUE",
1429+
js IS JSON WITH UNIQUE KEYS "WITH UNIQUE"
1430+
FROM
1431+
(SELECT js::jd2 FROM test_is_json WHERE js IS JSON) foo(js);
1432+
ERROR: value for domain jd2 violates check constraint "jd2_check"
12361433
SELECT
12371434
js0,
12381435
js IS JSON "IS JSON",
@@ -1260,6 +1457,33 @@ FROM
12601457
{ "a": 1, "b": [{ "a": 1, "b": 0, "a": 2 }] } | t | f | t | t | f | f | t | f
12611458
(11 rows)
12621459

1460+
SELECT
1461+
js0,
1462+
js IS JSON "IS JSON",
1463+
js IS NOT JSON "IS NOT JSON",
1464+
js IS JSON VALUE "IS VALUE",
1465+
js IS JSON OBJECT "IS OBJECT",
1466+
js IS JSON ARRAY "IS ARRAY",
1467+
js IS JSON SCALAR "IS SCALAR",
1468+
js IS JSON WITHOUT UNIQUE KEYS "WITHOUT UNIQUE",
1469+
js IS JSON WITH UNIQUE KEYS "WITH UNIQUE"
1470+
FROM
1471+
(SELECT js, js::jd4 FROM test_is_json WHERE js IS JSON) foo(js0, js);
1472+
js0 | IS JSON | IS NOT JSON | IS VALUE | IS OBJECT | IS ARRAY | IS SCALAR | WITHOUT UNIQUE | WITH UNIQUE
1473+
-----------------------------------------------+---------+-------------+----------+-----------+----------+-----------+----------------+-------------
1474+
123 | t | f | t | f | f | t | t | t
1475+
"aaa " | t | f | t | f | f | t | t | t
1476+
true | t | f | t | f | f | t | t | t
1477+
null | t | f | t | f | f | t | t | t
1478+
[] | t | f | t | f | t | f | t | t
1479+
[1, "2", {}] | t | f | t | f | t | f | t | t
1480+
{} | t | f | t | t | f | f | t | t
1481+
{ "a": 1, "b": null } | t | f | t | t | f | f | t | t
1482+
{ "a": 1, "a": null } | t | f | t | t | f | f | t | f
1483+
{ "a": 1, "b": [{ "a": 1 }, { "a": 2 }] } | t | f | t | t | f | f | t | t
1484+
{ "a": 1, "b": [{ "a": 1, "b": 0, "a": 2 }] } | t | f | t | t | f | f | t | f
1485+
(11 rows)
1486+
12631487
SELECT
12641488
js,
12651489
js IS JSON "IS JSON",

0 commit comments

Comments
 (0)