Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 515e8e7

Browse files
author
Nikita Glukhov
committed
Allow jsonpath scalars to be a part of path
1 parent 546fbbd commit 515e8e7

File tree

6 files changed

+111
-22
lines changed

6 files changed

+111
-22
lines changed

src/backend/utils/adt/jsonpath.c

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -48,30 +48,17 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item,
4848
{
4949
case jpiString:
5050
case jpiVariable:
51-
/* scalars aren't checked during grammar parse */
52-
if (item->next != NULL)
53-
ereport(ERROR,
54-
(errcode(ERRCODE_SYNTAX_ERROR),
55-
errmsg("scalar could not be a part of path")));
5651
case jpiKey:
5752
appendBinaryStringInfo(buf, (char*)&item->value.string.len,
5853
sizeof(item->value.string.len));
5954
appendBinaryStringInfo(buf, item->value.string.val, item->value.string.len);
6055
appendStringInfoChar(buf, '\0');
6156
break;
6257
case jpiNumeric:
63-
if (item->next != NULL)
64-
ereport(ERROR,
65-
(errcode(ERRCODE_SYNTAX_ERROR),
66-
errmsg("scalar could not be a part of path")));
6758
appendBinaryStringInfo(buf, (char*)item->value.numeric,
6859
VARSIZE(item->value.numeric));
6960
break;
7061
case jpiBool:
71-
if (item->next != NULL)
72-
ereport(ERROR,
73-
(errcode(ERRCODE_SYNTAX_ERROR),
74-
errmsg("scalar could not be a part of path")));
7562
appendBinaryStringInfo(buf, (char*)&item->value.boolean,
7663
sizeof(item->value.boolean));
7764
break;
@@ -126,10 +113,6 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item,
126113
}
127114
break;
128115
case jpiNull:
129-
if (item->next != NULL)
130-
ereport(ERROR,
131-
(errcode(ERRCODE_SYNTAX_ERROR),
132-
errmsg("scalar could not be a part of path")));
133116
break;
134117
case jpiRoot:
135118
if (forbiddenRoot)
@@ -592,6 +575,10 @@ jspGetNext(JsonPathItem *v, JsonPathItem *a)
592575
if (v->nextPos > 0)
593576
{
594577
Assert(
578+
v->type == jpiString ||
579+
v->type == jpiNumeric ||
580+
v->type == jpiBool ||
581+
v->type == jpiNull ||
595582
v->type == jpiKey ||
596583
v->type == jpiAny ||
597584
v->type == jpiAnyArray ||
@@ -601,6 +588,7 @@ jspGetNext(JsonPathItem *v, JsonPathItem *a)
601588
v->type == jpiCurrent ||
602589
v->type == jpiExists ||
603590
v->type == jpiRoot ||
591+
v->type == jpiVariable ||
604592
v->type == jpiType ||
605593
v->type == jpiSize ||
606594
v->type == jpiAbs ||

src/backend/utils/adt/jsonpath_exec.c

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1074,12 +1074,21 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
10741074
case jpiNumeric:
10751075
case jpiString:
10761076
case jpiVariable:
1077-
res = jperOk;
1078-
if (found)
1077+
if (jspGetNext(jsp, &elem))
10791078
{
1080-
JsonbValue *jbv = palloc(sizeof(*jbv));
1081-
computeJsonPathItem(cxt, jsp, jbv);
1082-
*found = lappend(*found, jbv);
1079+
JsonbValue jbv;
1080+
computeJsonPathItem(cxt, jsp, &jbv);
1081+
res = recursiveExecute(cxt, &elem, &jbv, found);
1082+
}
1083+
else
1084+
{
1085+
res = jperOk;
1086+
if (found)
1087+
{
1088+
JsonbValue *jbv = palloc(sizeof(*jbv));
1089+
computeJsonPathItem(cxt, jsp, jbv);
1090+
*found = lappend(*found, jbv);
1091+
}
10831092
}
10841093
break;
10851094
case jpiType:

src/test/regress/expected/jsonb_jsonpath.out

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -727,6 +727,36 @@ select _jsonpath_query(jsonb '[null,1,true,"a",[],{}]', '$[*].type()');
727727
"object"
728728
(6 rows)
729729

730+
select _jsonpath_query(jsonb 'null', 'null.type()');
731+
_jsonpath_query
732+
-----------------
733+
"null"
734+
(1 row)
735+
736+
select _jsonpath_query(jsonb 'null', 'true.type()');
737+
_jsonpath_query
738+
-----------------
739+
"boolean"
740+
(1 row)
741+
742+
select _jsonpath_query(jsonb 'null', '123.type()');
743+
_jsonpath_query
744+
-----------------
745+
"number"
746+
(1 row)
747+
748+
select _jsonpath_query(jsonb 'null', '"123".type()');
749+
_jsonpath_query
750+
-----------------
751+
"string"
752+
(1 row)
753+
754+
select _jsonpath_query(jsonb 'null', 'aaa.type()');
755+
_jsonpath_query
756+
-----------------
757+
"string"
758+
(1 row)
759+
730760
select _jsonpath_query(jsonb '[1,null,true,"11",[],[1],[1,2,3],{},{"a":1,"b":2}]', 'strict $[*].size()');
731761
ERROR: SQL/JSON array not found
732762
select _jsonpath_query(jsonb '[1,null,true,"11",[],[1],[1,2,3],{},{"a":1,"b":2}]', 'lax $[*].size()');

src/test/regress/expected/jsonpath.out

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,24 @@ select '$.g ? ((x >= 123 || a == 4) && exists (.x ? (@ == 14)))'::jsonpath;
267267
$."g"?(("x" >= 123 || "a" == 4) && exists (@."x"?(@ == 14)))
268268
(1 row)
269269

270+
select '$a'::jsonpath;
271+
jsonpath
272+
----------
273+
$"a"
274+
(1 row)
275+
276+
select '$a.b'::jsonpath;
277+
jsonpath
278+
----------
279+
$"a"."b"
280+
(1 row)
281+
282+
select '$a[*]'::jsonpath;
283+
jsonpath
284+
----------
285+
$"a"[*]
286+
(1 row)
287+
270288
select '$.g ? (zip == $zip)'::jsonpath;
271289
jsonpath
272290
-------------------------
@@ -285,6 +303,36 @@ select '$.a[1,2, 3 to 16]'::jsonpath;
285303
$."a"[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
286304
(1 row)
287305

306+
select 'null.type()'::jsonpath;
307+
jsonpath
308+
-------------
309+
null.type()
310+
(1 row)
311+
312+
select '1.type()'::jsonpath;
313+
jsonpath
314+
----------
315+
1.type()
316+
(1 row)
317+
318+
select '"aaa".type()'::jsonpath;
319+
jsonpath
320+
--------------
321+
"aaa".type()
322+
(1 row)
323+
324+
select 'aaa.type()'::jsonpath;
325+
jsonpath
326+
--------------
327+
"aaa".type()
328+
(1 row)
329+
330+
select 'true.type()'::jsonpath;
331+
jsonpath
332+
-------------
333+
true.type()
334+
(1 row)
335+
288336
select '$ ? (a < 1)'::jsonpath;
289337
jsonpath
290338
-------------

src/test/regress/sql/jsonb_jsonpath.sql

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,11 @@ select _jsonpath_query(jsonb '{"a": [1, 2]}', 'lax $.a * 3');
149149
select _jsonpath_query(jsonb '[null,1,true,"a",[],{}]', '$.type()');
150150
select _jsonpath_query(jsonb '[null,1,true,"a",[],{}]', 'lax $.type()');
151151
select _jsonpath_query(jsonb '[null,1,true,"a",[],{}]', '$[*].type()');
152+
select _jsonpath_query(jsonb 'null', 'null.type()');
153+
select _jsonpath_query(jsonb 'null', 'true.type()');
154+
select _jsonpath_query(jsonb 'null', '123.type()');
155+
select _jsonpath_query(jsonb 'null', '"123".type()');
156+
select _jsonpath_query(jsonb 'null', 'aaa.type()');
152157

153158
select _jsonpath_query(jsonb '[1,null,true,"11",[],[1],[1,2,3],{},{"a":1,"b":2}]', 'strict $[*].size()');
154159
select _jsonpath_query(jsonb '[1,null,true,"11",[],[1],[1,2,3],{},{"a":1,"b":2}]', 'lax $[*].size()');

src/test/regress/sql/jsonpath.sql

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,19 @@ select '$.g ? (exists (@.x ? (@ == 14)))'::jsonpath;
4747
select '$.g ? (exists (.x ? (@ == 14)))'::jsonpath;
4848
select '$.g ? ((x >= 123 || a == 4) && exists (.x ? (@ == 14)))'::jsonpath;
4949

50+
select '$a'::jsonpath;
51+
select '$a.b'::jsonpath;
52+
select '$a[*]'::jsonpath;
5053
select '$.g ? (zip == $zip)'::jsonpath;
5154
select '$.a.[1,2, 3 to 16]'::jsonpath;
5255
select '$.a[1,2, 3 to 16]'::jsonpath;
5356

57+
select 'null.type()'::jsonpath;
58+
select '1.type()'::jsonpath;
59+
select '"aaa".type()'::jsonpath;
60+
select 'aaa.type()'::jsonpath;
61+
select 'true.type()'::jsonpath;
62+
5463
select '$ ? (a < 1)'::jsonpath;
5564
select '$ ? (a < -1)'::jsonpath;
5665
select '$ ? (a < +1)'::jsonpath;

0 commit comments

Comments
 (0)