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

Commit ba458a7

Browse files
author
Nikita Glukhov
committed
Add jsonpath array constructors
1 parent aa76ea4 commit ba458a7

File tree

8 files changed

+117
-13
lines changed

8 files changed

+117
-13
lines changed

src/backend/utils/adt/jsonpath.c

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -99,28 +99,23 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item,
9999
*(int32*)(buf->data + right) = chld;
100100
}
101101
break;
102-
case jpiDatetime:
103-
if (!item->value.arg)
104-
{
105-
int32 arg = 0;
106-
107-
appendBinaryStringInfo(buf, (char *) &arg, sizeof(arg));
108-
break;
109-
}
110-
/* fall through */
111102
case jpiFilter:
112103
case jpiIsUnknown:
113104
case jpiNot:
114105
case jpiPlus:
115106
case jpiMinus:
116107
case jpiExists:
108+
case jpiDatetime:
117109
case jpiMap:
110+
case jpiArray:
118111
{
119-
int32 arg;
112+
int32 arg = item->value.arg ? buf->len : 0;
120113

121-
arg = buf->len;
122114
appendBinaryStringInfo(buf, (char*)&arg /* fake value */, sizeof(arg));
123115

116+
if (!item->value.arg)
117+
break;
118+
124119
chld = flattenJsonPathParseItem(buf, item->value.arg,
125120
item->type == jpiFilter ||
126121
item->type == jpiMap ||
@@ -548,6 +543,15 @@ printJsonPathItem(StringInfo buf, JsonPathItem *v, bool inKey, bool printBracket
548543
if (printBracketes || jspHasNext(v))
549544
appendStringInfoChar(buf, ')');
550545
break;
546+
case jpiArray:
547+
appendStringInfoChar(buf, '[');
548+
if (v->content.arg)
549+
{
550+
jspGetArg(v, &elem);
551+
printJsonPathItem(buf, &elem, false, false);
552+
}
553+
appendStringInfoChar(buf, ']');
554+
break;
551555
default:
552556
elog(ERROR, "Unknown jsonpath item type: %d", v->type);
553557
}
@@ -676,6 +680,7 @@ jspInitByBuffer(JsonPathItem *v, char *base, int32 pos)
676680
case jpiFilter:
677681
case jpiDatetime:
678682
case jpiMap:
683+
case jpiArray:
679684
read_int32(v->content.arg, base, pos);
680685
break;
681686
case jpiIndexArray:
@@ -708,7 +713,8 @@ jspGetArg(JsonPathItem *v, JsonPathItem *a)
708713
v->type == jpiPlus ||
709714
v->type == jpiMinus ||
710715
v->type == jpiDatetime ||
711-
v->type == jpiMap
716+
v->type == jpiMap ||
717+
v->type == jpiArray
712718
);
713719

714720
jspInitByBuffer(a, v->base, v->content.arg);
@@ -762,7 +768,8 @@ jspGetNext(JsonPathItem *v, JsonPathItem *a)
762768
v->type == jpiKeyValue ||
763769
v->type == jpiStartsWith ||
764770
v->type == jpiMap ||
765-
v->type == jpiSequence
771+
v->type == jpiSequence ||
772+
v->type == jpiArray
766773
);
767774

768775
if (a)

src/backend/utils/adt/jsonpath_exec.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2008,6 +2008,24 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
20082008

20092009
break;
20102010
}
2011+
case jpiArray:
2012+
{
2013+
JsonValueList list = { 0 };
2014+
2015+
if (jsp->content.arg)
2016+
{
2017+
jspGetArg(jsp, &elem);
2018+
res = recursiveExecute(cxt, &elem, jb, &list);
2019+
2020+
if (jperIsError(res))
2021+
break;
2022+
}
2023+
2024+
res = recursiveExecuteNext(cxt, jsp, NULL,
2025+
wrapItemsInArray(&list),
2026+
found, false);
2027+
}
2028+
break;
20112029
default:
20122030
elog(ERROR,"2Wrong state: %d", jsp->type);
20132031
}

src/backend/utils/adt/jsonpath_gram.y

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,8 @@ path_primary:
353353
| '@' { $$ = makeItemType(jpiCurrent); }
354354
| LAST_P { $$ = makeItemType(jpiLast); }
355355
| '(' expr_seq ')' { $$ = $2; }
356+
| '[' ']' { $$ = makeItemUnary(jpiArray, NULL); }
357+
| '[' expr_or_seq ']' { $$ = makeItemUnary(jpiArray, $2); }
356358
;
357359

358360
accessor_expr:

src/include/utils/jsonpath.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ typedef enum JsonPathItemType {
8585
jpiStartsWith,
8686
jpiMap,
8787
jpiSequence,
88+
jpiArray,
8889
} JsonPathItemType;
8990

9091

src/test/regress/expected/jsonb_jsonpath.out

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1584,6 +1584,12 @@ SELECT jsonb '[{"a": 1}, {"a": 2}]' @* '$[*] ? (@.a > 10)';
15841584
----------
15851585
(0 rows)
15861586

1587+
SELECT jsonb '[{"a": 1}, {"a": 2}]' @* '[$[*].a]';
1588+
?column?
1589+
----------
1590+
[1, 2]
1591+
(1 row)
1592+
15871593
SELECT jsonb '[{"a": 1}, {"a": 2}]' @? '$[*].a > 1';
15881594
?column?
15891595
----------
@@ -1671,3 +1677,48 @@ select _jsonpath_query(jsonb '[1,2,3,4,5]', '$[(0, $[*], 5) ? (@ == 3)]');
16711677

16721678
select _jsonpath_query(jsonb '[1,2,3,4,5]', '$[(0, $[*], 3) ? (@ == 3)]');
16731679
ERROR: Invalid SQL/JSON subscript
1680+
-- extension: array constructors
1681+
select _jsonpath_query(jsonb '[1, 2, 3]', '[]');
1682+
_jsonpath_query
1683+
-----------------
1684+
[]
1685+
(1 row)
1686+
1687+
select _jsonpath_query(jsonb '[1, 2, 3]', '[1, 2, $.map(@ + 100)[*], 4, 5]');
1688+
_jsonpath_query
1689+
-----------------------------
1690+
[1, 2, 101, 102, 103, 4, 5]
1691+
(1 row)
1692+
1693+
select _jsonpath_query(jsonb '[1, 2, 3]', '[1, 2, $.map(@ + 100)[*], 4, 5][*]');
1694+
_jsonpath_query
1695+
-----------------
1696+
1
1697+
2
1698+
101
1699+
102
1700+
103
1701+
4
1702+
5
1703+
(7 rows)
1704+
1705+
select _jsonpath_query(jsonb '[1, 2, 3]', '[(1, (2, $.map(@ + 100)[*])), (4, 5)]');
1706+
_jsonpath_query
1707+
-----------------------------
1708+
[1, 2, 101, 102, 103, 4, 5]
1709+
(1 row)
1710+
1711+
select _jsonpath_query(jsonb '[1, 2, 3]', '[[1, 2], [$.map(@ + 100)[*], 4], 5, [(1,2)?(@ > 5)]]');
1712+
_jsonpath_query
1713+
-------------------------------------
1714+
[[1, 2], [101, 102, 103, 4], 5, []]
1715+
(1 row)
1716+
1717+
select _jsonpath_query(jsonb '[1, 2, 3]', 'strict [1, 2, $.map(@.a)[*], 4, 5]');
1718+
ERROR: SQL/JSON member not found
1719+
select _jsonpath_query(jsonb '[[1, 2], [3, 4, 5], [], [6, 7]]', '[$[*].map(@ + 10)[*] ? (@ > 13)]');
1720+
_jsonpath_query
1721+
------------------
1722+
[14, 15, 16, 17]
1723+
(1 row)
1724+

src/test/regress/expected/jsonpath.out

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,18 @@ select '$[(1, (2, $.a)), 3, (4, 5)]'::jsonpath;
497497
$[(1, (2, $."a")),3,(4, 5)]
498498
(1 row)
499499

500+
select '[]'::jsonpath;
501+
jsonpath
502+
----------
503+
[]
504+
(1 row)
505+
506+
select '[[1, 2], ([(3, 4, 5), 6], []), $.a[*]]'::jsonpath;
507+
jsonpath
508+
------------------------------------------
509+
[[1, 2], ([(3, 4, 5), 6], []), $."a"[*]]
510+
(1 row)
511+
500512
select '$ ? (a < 1)'::jsonpath;
501513
jsonpath
502514
-------------

src/test/regress/sql/jsonb_jsonpath.sql

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,7 @@ select _jsonpath_query(jsonb
370370

371371
SELECT jsonb '[{"a": 1}, {"a": 2}]' @* '$[*]';
372372
SELECT jsonb '[{"a": 1}, {"a": 2}]' @* '$[*] ? (@.a > 10)';
373+
SELECT jsonb '[{"a": 1}, {"a": 2}]' @* '[$[*].a]';
373374

374375
SELECT jsonb '[{"a": 1}, {"a": 2}]' @? '$[*].a > 1';
375376
SELECT jsonb '[{"a": 1}, {"a": 2}]' @? '$[*].a > 2';
@@ -388,3 +389,12 @@ select _jsonpath_query(jsonb '[1,2,3,4,5]', '-(10, 20, $[1 to 3], 30)');
388389
select _jsonpath_query(jsonb '[1,2,3,4,5]', 'lax (10, 20, $[1 to 3], 30).map(@ + 100)');
389390
select _jsonpath_query(jsonb '[1,2,3,4,5]', '$[(0, $[*], 5) ? (@ == 3)]');
390391
select _jsonpath_query(jsonb '[1,2,3,4,5]', '$[(0, $[*], 3) ? (@ == 3)]');
392+
393+
-- extension: array constructors
394+
select _jsonpath_query(jsonb '[1, 2, 3]', '[]');
395+
select _jsonpath_query(jsonb '[1, 2, 3]', '[1, 2, $.map(@ + 100)[*], 4, 5]');
396+
select _jsonpath_query(jsonb '[1, 2, 3]', '[1, 2, $.map(@ + 100)[*], 4, 5][*]');
397+
select _jsonpath_query(jsonb '[1, 2, 3]', '[(1, (2, $.map(@ + 100)[*])), (4, 5)]');
398+
select _jsonpath_query(jsonb '[1, 2, 3]', '[[1, 2], [$.map(@ + 100)[*], 4], 5, [(1,2)?(@ > 5)]]');
399+
select _jsonpath_query(jsonb '[1, 2, 3]', 'strict [1, 2, $.map(@.a)[*], 4, 5]');
400+
select _jsonpath_query(jsonb '[[1, 2], [3, 4, 5], [], [6, 7]]', '[$[*].map(@ + 10)[*] ? (@ > 13)]');

src/test/regress/sql/jsonpath.sql

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,9 @@ select '(1, 2, $.a) == 5'::jsonpath;
9292
select '$[(1, 2, $.a) to (3, 4)]'::jsonpath;
9393
select '$[(1, (2, $.a)), 3, (4, 5)]'::jsonpath;
9494

95+
select '[]'::jsonpath;
96+
select '[[1, 2], ([(3, 4, 5), 6], []), $.a[*]]'::jsonpath;
97+
9598
select '$ ? (a < 1)'::jsonpath;
9699
select '$ ? (a < -1)'::jsonpath;
97100
select '$ ? (a < +1)'::jsonpath;

0 commit comments

Comments
 (0)