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

Commit 478ad69

Browse files
author
Nikita Glukhov
committed
Allow jsonpath scalars to be a part of path
1 parent 0c75652 commit 478ad69

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
@@ -50,30 +50,17 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item,
5050
{
5151
case jpiString:
5252
case jpiVariable:
53-
/* scalars aren't checked during grammar parse */
54-
if (item->next != NULL)
55-
ereport(ERROR,
56-
(errcode(ERRCODE_SYNTAX_ERROR),
57-
errmsg("scalar could not be a part of path")));
5853
case jpiKey:
5954
appendBinaryStringInfo(buf, (char*)&item->value.string.len,
6055
sizeof(item->value.string.len));
6156
appendBinaryStringInfo(buf, item->value.string.val, item->value.string.len);
6257
appendStringInfoChar(buf, '\0');
6358
break;
6459
case jpiNumeric:
65-
if (item->next != NULL)
66-
ereport(ERROR,
67-
(errcode(ERRCODE_SYNTAX_ERROR),
68-
errmsg("scalar could not be a part of path")));
6960
appendBinaryStringInfo(buf, (char*)item->value.numeric,
7061
VARSIZE(item->value.numeric));
7162
break;
7263
case jpiBool:
73-
if (item->next != NULL)
74-
ereport(ERROR,
75-
(errcode(ERRCODE_SYNTAX_ERROR),
76-
errmsg("scalar could not be a part of path")));
7764
appendBinaryStringInfo(buf, (char*)&item->value.boolean,
7865
sizeof(item->value.boolean));
7966
break;
@@ -128,10 +115,6 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item,
128115
}
129116
break;
130117
case jpiNull:
131-
if (item->next != NULL)
132-
ereport(ERROR,
133-
(errcode(ERRCODE_SYNTAX_ERROR),
134-
errmsg("scalar could not be a part of path")));
135118
break;
136119
case jpiRoot:
137120
if (forbiddenRoot)
@@ -596,6 +579,10 @@ jspGetNext(JsonPathItem *v, JsonPathItem *a)
596579
if (v->nextPos > 0)
597580
{
598581
Assert(
582+
v->type == jpiString ||
583+
v->type == jpiNumeric ||
584+
v->type == jpiBool ||
585+
v->type == jpiNull ||
599586
v->type == jpiKey ||
600587
v->type == jpiAny ||
601588
v->type == jpiAnyArray ||
@@ -605,6 +592,7 @@ jspGetNext(JsonPathItem *v, JsonPathItem *a)
605592
v->type == jpiCurrent ||
606593
v->type == jpiExists ||
607594
v->type == jpiRoot ||
595+
v->type == jpiVariable ||
608596
v->type == jpiType ||
609597
v->type == jpiSize ||
610598
v->type == jpiAbs ||

src/backend/utils/adt/jsonpath_exec.c

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1096,12 +1096,21 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
10961096
case jpiNumeric:
10971097
case jpiString:
10981098
case jpiVariable:
1099-
res = jperOk;
1100-
if (found)
1099+
if (jspGetNext(jsp, &elem))
11011100
{
1102-
JsonbValue *jbv = palloc(sizeof(*jbv));
1103-
computeJsonPathItem(cxt, jsp, jbv);
1104-
*found = lappend(*found, jbv);
1101+
JsonbValue jbv;
1102+
computeJsonPathItem(cxt, jsp, &jbv);
1103+
res = recursiveExecute(cxt, &elem, &jbv, found);
1104+
}
1105+
else
1106+
{
1107+
res = jperOk;
1108+
if (found)
1109+
{
1110+
JsonbValue *jbv = palloc(sizeof(*jbv));
1111+
computeJsonPathItem(cxt, jsp, jbv);
1112+
*found = lappend(*found, jbv);
1113+
}
11051114
}
11061115
break;
11071116
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)