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

Commit fdac827

Browse files
author
Nikita Glukhov
committed
Allow jsonpath scalars to be a part of path
1 parent 3b8ba29 commit fdac827

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
@@ -1046,12 +1046,21 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
10461046
case jpiNumeric:
10471047
case jpiString:
10481048
case jpiVariable:
1049-
res = jperOk;
1050-
if (found)
1049+
if (jspGetNext(jsp, &elem))
10511050
{
1052-
JsonbValue *jbv = palloc(sizeof(*jbv));
1053-
computeJsonPathItem(cxt, jsp, jbv);
1054-
*found = lappend(*found, jbv);
1051+
JsonbValue jbv;
1052+
computeJsonPathItem(cxt, jsp, &jbv);
1053+
res = recursiveExecute(cxt, &elem, &jbv, found);
1054+
}
1055+
else
1056+
{
1057+
res = jperOk;
1058+
if (found)
1059+
{
1060+
JsonbValue *jbv = palloc(sizeof(*jbv));
1061+
computeJsonPathItem(cxt, jsp, jbv);
1062+
*found = lappend(*found, jbv);
1063+
}
10551064
}
10561065
break;
10571066
case jpiType:

src/test/regress/expected/jsonb_jsonpath.out

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

714+
select _jsonpath_query(jsonb 'null', 'null.type()');
715+
_jsonpath_query
716+
-----------------
717+
"null"
718+
(1 row)
719+
720+
select _jsonpath_query(jsonb 'null', 'true.type()');
721+
_jsonpath_query
722+
-----------------
723+
"boolean"
724+
(1 row)
725+
726+
select _jsonpath_query(jsonb 'null', '123.type()');
727+
_jsonpath_query
728+
-----------------
729+
"number"
730+
(1 row)
731+
732+
select _jsonpath_query(jsonb 'null', '"123".type()');
733+
_jsonpath_query
734+
-----------------
735+
"string"
736+
(1 row)
737+
738+
select _jsonpath_query(jsonb 'null', 'aaa.type()');
739+
_jsonpath_query
740+
-----------------
741+
"string"
742+
(1 row)
743+
714744
select _jsonpath_query(jsonb '[1,null,true,"11",[],[1],[1,2,3],{},{"a":1,"b":2}]', 'strict $[*].size()');
715745
ERROR: SQL/JSON array not found
716746
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
@@ -263,6 +263,24 @@ select '$.g ? ((x >= 123 || a == 4) && exists (.x ? (@ == 14)))'::jsonpath;
263263
$."g"?(("x" >= 123 || "a" == 4) && exists (@."x"?(@ == 14)))
264264
(1 row)
265265

266+
select '$a'::jsonpath;
267+
jsonpath
268+
----------
269+
$"a"
270+
(1 row)
271+
272+
select '$a.b'::jsonpath;
273+
jsonpath
274+
----------
275+
$"a"."b"
276+
(1 row)
277+
278+
select '$a[*]'::jsonpath;
279+
jsonpath
280+
----------
281+
$"a"[*]
282+
(1 row)
283+
266284
select '$.g ? (zip == $zip)'::jsonpath;
267285
jsonpath
268286
-------------------------
@@ -281,6 +299,36 @@ select '$.a[1,2, 3 to 16]'::jsonpath;
281299
$."a"[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
282300
(1 row)
283301

302+
select 'null.type()'::jsonpath;
303+
jsonpath
304+
-------------
305+
null.type()
306+
(1 row)
307+
308+
select '1.type()'::jsonpath;
309+
jsonpath
310+
----------
311+
1.type()
312+
(1 row)
313+
314+
select '"aaa".type()'::jsonpath;
315+
jsonpath
316+
--------------
317+
"aaa".type()
318+
(1 row)
319+
320+
select 'aaa.type()'::jsonpath;
321+
jsonpath
322+
--------------
323+
"aaa".type()
324+
(1 row)
325+
326+
select 'true.type()'::jsonpath;
327+
jsonpath
328+
-------------
329+
true.type()
330+
(1 row)
331+
284332
select '$ ? (a < 1)'::jsonpath;
285333
jsonpath
286334
-------------

src/test/regress/sql/jsonb_jsonpath.sql

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

152157
select _jsonpath_query(jsonb '[1,null,true,"11",[],[1],[1,2,3],{},{"a":1,"b":2}]', 'strict $[*].size()');
153158
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
@@ -46,10 +46,19 @@ select '$.g ? (exists (@.x ? (@ == 14)))'::jsonpath;
4646
select '$.g ? (exists (.x ? (@ == 14)))'::jsonpath;
4747
select '$.g ? ((x >= 123 || a == 4) && exists (.x ? (@ == 14)))'::jsonpath;
4848

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

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

0 commit comments

Comments
 (0)