Skip to content

Commit 12df9d0

Browse files
committed
Fix behavior of jsonpath .* on arrays
The behavior of the `.*` jpiAnyKey jsonpath selector seems incorrect: ``` select jsonb_path_query('[1,2,3]', '$.*'); jsonb_path_query ------------------ (0 rows) select jsonb_path_query('[1,2,3,{"b": [3,4,5]}]', '$.*'); jsonb_path_query ------------------ [3, 4, 5] ``` The first example might be expected, since `.*` is intended for object keys, but the handing of `jpiAnyKey` has a branch for unwrapping arrays. The second example, however, just seems weird: this is `.*`, not `.**`. Fix it by passing the next node to `executeAnyItem()` (via `executeItemUnwrapTargetArray()`) and then properly set `jperOk` when `executeAnyItem()` finds values when there is no current (next) node. While at it, document a couple functions.
1 parent cd2624f commit 12df9d0

File tree

3 files changed

+55
-4
lines changed

3 files changed

+55
-4
lines changed

src/backend/utils/adt/jsonpath_exec.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -864,8 +864,10 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
864864
jb->val.binary.data, found, 1, 1, 1,
865865
false, jspAutoUnwrap(cxt));
866866
}
867-
else if (unwrap && JsonbType(jb) == jbvArray)
868-
return executeItemUnwrapTargetArray(cxt, jsp, jb, found, false);
867+
else if (unwrap && JsonbType(jb) == jbvArray) {
868+
bool hasNext = jspGetNext(jsp, &elem);
869+
return executeItemUnwrapTargetArray(cxt, hasNext ? &elem : NULL, jb, found, false);
870+
}
869871
else if (!jspIgnoreStructuralErrors(cxt))
870872
{
871873
Assert(found);
@@ -2002,8 +2004,10 @@ executeAnyItem(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbContainer *jbc,
20022004
if (res == jperOk && !found)
20032005
break;
20042006
}
2005-
else if (found)
2007+
else if (found) {
20062008
JsonValueListAppend(found, copyJsonbValue(&v));
2009+
res = jperOk;
2010+
}
20072011
else
20082012
return jperOk;
20092013
}
@@ -2976,7 +2980,8 @@ getJsonPathItem(JsonPathExecContext *cxt, JsonPathItem *item,
29762980
}
29772981

29782982
/*
2979-
* Returns the computed value of a JSON path variable with given name.
2983+
* Definition of JsonPathGetVarCallback for when JsonPathExecContext.vars
2984+
* is specified as a List value.
29802985
*/
29812986
static JsonbValue *
29822987
GetJsonPathVar(void *cxt, char *varName, int varNameLen,
@@ -3022,6 +3027,10 @@ GetJsonPathVar(void *cxt, char *varName, int varNameLen,
30223027
return result;
30233028
}
30243029

3030+
/*
3031+
* Definition of JsonPathCountVarsCallback for when JsonPathExecContext.vars
3032+
* is specified as a List value.
3033+
*/
30253034
static int
30263035
CountJsonPathVars(void *cxt)
30273036
{

src/test/regress/expected/jsonb_jsonpath.out

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,42 @@ select jsonb_path_exists('[{"a": 1}, {"a": 2}, 3]', 'strict $[*].a', silent => t
245245

246246
(1 row)
247247

248+
select jsonb_path_query('{"a": [1,2,3], "b": [3,4,5]}', '$.*');
249+
jsonb_path_query
250+
------------------
251+
[1, 2, 3]
252+
[3, 4, 5]
253+
(2 rows)
254+
255+
select jsonb_path_query('[1,2,3]', '$.*');
256+
jsonb_path_query
257+
------------------
258+
1
259+
2
260+
3
261+
(3 rows)
262+
263+
select jsonb_path_query('[1,2,3,{"b": [3,4,5]}]', '$.*');
264+
jsonb_path_query
265+
------------------
266+
1
267+
2
268+
3
269+
{"b": [3, 4, 5]}
270+
(4 rows)
271+
272+
select jsonb '{"a": [1,2,3], "b": [3,4,5]}' @? '$.*';
273+
?column?
274+
----------
275+
t
276+
(1 row)
277+
278+
select jsonb '[1,2,3,{"b": [3,4,5]}]' @? '$.*';
279+
?column?
280+
----------
281+
t
282+
(1 row)
283+
248284
select jsonb_path_query('1', 'lax $.a');
249285
jsonb_path_query
250286
------------------

src/test/regress/sql/jsonb_jsonpath.sql

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,12 @@ select jsonb_path_exists('[{"a": 1}, {"a": 2}, 3]', 'lax $[*].a', silent => true
4444
select jsonb_path_exists('[{"a": 1}, {"a": 2}, 3]', 'strict $[*].a', silent => false);
4545
select jsonb_path_exists('[{"a": 1}, {"a": 2}, 3]', 'strict $[*].a', silent => true);
4646

47+
select jsonb_path_query('{"a": [1,2,3], "b": [3,4,5]}', '$.*');
48+
select jsonb_path_query('[1,2,3]', '$.*');
49+
select jsonb_path_query('[1,2,3,{"b": [3,4,5]}]', '$.*');
50+
select jsonb '{"a": [1,2,3], "b": [3,4,5]}' @? '$.*';
51+
select jsonb '[1,2,3,{"b": [3,4,5]}]' @? '$.*';
52+
4753
select jsonb_path_query('1', 'lax $.a');
4854
select jsonb_path_query('1', 'strict $.a');
4955
select jsonb_path_query('1', 'strict $.*');

0 commit comments

Comments
 (0)