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

Commit 8e6fc9d

Browse files
author
Nikita Glukhov
committed
Add jsonpath array constructors
1 parent c27849a commit 8e6fc9d

File tree

8 files changed

+123
-4
lines changed

8 files changed

+123
-4
lines changed

src/backend/utils/adt/jsonpath.c

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -132,12 +132,15 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item,
132132
case jpiPlus:
133133
case jpiMinus:
134134
case jpiExists:
135+
case jpiArray:
135136
{
136-
int32 arg;
137+
int32 arg = item->value.arg ? buf->len : 0;
137138

138-
arg = buf->len;
139139
appendBinaryStringInfo(buf, (char*)&arg /* fake value */, sizeof(arg));
140140

141+
if (!item->value.arg)
142+
break;
143+
141144
chld = flattenJsonPathParseItem(buf, item->value.arg,
142145
item->type == jpiFilter ||
143146
allowCurrent,
@@ -602,6 +605,15 @@ printJsonPathItem(StringInfo buf, JsonPathItem *v, bool inKey, bool printBracket
602605
if (printBracketes || jspHasNext(v))
603606
appendStringInfoChar(buf, ')');
604607
break;
608+
case jpiArray:
609+
appendStringInfoChar(buf, '[');
610+
if (v->content.arg)
611+
{
612+
jspGetArg(v, &elem);
613+
printJsonPathItem(buf, &elem, false, false);
614+
}
615+
appendStringInfoChar(buf, ']');
616+
break;
605617
default:
606618
elog(ERROR, "Unknown jsonpath item type: %d", v->type);
607619
}
@@ -735,6 +747,7 @@ jspInitByBuffer(JsonPathItem *v, char *base, int32 pos)
735747
case jpiPlus:
736748
case jpiMinus:
737749
case jpiFilter:
750+
case jpiArray:
738751
read_int32(v->content.arg, base, pos);
739752
break;
740753
case jpiIndexArray:
@@ -765,7 +778,8 @@ jspGetArg(JsonPathItem *v, JsonPathItem *a)
765778
v->type == jpiIsUnknown ||
766779
v->type == jpiExists ||
767780
v->type == jpiPlus ||
768-
v->type == jpiMinus
781+
v->type == jpiMinus ||
782+
v->type == jpiArray
769783
);
770784

771785
jspInitByBuffer(a, v->base, v->content.arg);
@@ -818,7 +832,8 @@ jspGetNext(JsonPathItem *v, JsonPathItem *a)
818832
v->type == jpiDatetime ||
819833
v->type == jpiKeyValue ||
820834
v->type == jpiStartsWith ||
821-
v->type == jpiSequence
835+
v->type == jpiSequence ||
836+
v->type == jpiArray
822837
);
823838

824839
if (a)

src/backend/utils/adt/jsonpath_exec.c

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

23072307
break;
23082308
}
2309+
case jpiArray:
2310+
{
2311+
JsonValueList list = { 0 };
2312+
2313+
if (jsp->content.arg)
2314+
{
2315+
jspGetArg(jsp, &elem);
2316+
res = recursiveExecute(cxt, &elem, jb, &list);
2317+
2318+
if (jperIsError(res))
2319+
break;
2320+
}
2321+
2322+
res = recursiveExecuteNext(cxt, jsp, NULL,
2323+
wrapItemsInArray(&list),
2324+
found, false);
2325+
}
2326+
break;
23092327
default:
23102328
elog(ERROR, "unrecognized jsonpath item type: %d", jsp->type);
23112329
}

src/backend/utils/adt/jsonpath_gram.y

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,8 @@ path_primary:
403403
| '@' { $$ = makeItemType(jpiCurrent); }
404404
| LAST_P { $$ = makeItemType(jpiLast); }
405405
| '(' expr_seq ')' { $$ = $2; }
406+
| '[' ']' { $$ = makeItemUnary(jpiArray, NULL); }
407+
| '[' expr_or_seq ']' { $$ = makeItemUnary(jpiArray, $2); }
406408
;
407409

408410
accessor_expr:

src/include/utils/jsonpath.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ typedef enum JsonPathItemType {
8787
jpiStartsWith,
8888
jpiLikeRegex,
8989
jpiSequence,
90+
jpiArray,
9091
} JsonPathItemType;
9192

9293
/* XQuery regex mode flags for LIKE_REGEX predicate */

src/test/regress/expected/jsonb_jsonpath.out

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1684,6 +1684,12 @@ SELECT jsonb '[{"a": 1}, {"a": 2}]' @* '$[*] ? (@.a > 10)';
16841684
----------
16851685
(0 rows)
16861686

1687+
SELECT jsonb '[{"a": 1}, {"a": 2}]' @* '[$[*].a]';
1688+
?column?
1689+
----------
1690+
[1, 2]
1691+
(1 row)
1692+
16871693
SELECT jsonb '[{"a": 1}, {"a": 2}]' @# '$[*].a';
16881694
?column?
16891695
----------
@@ -1702,6 +1708,12 @@ SELECT jsonb '[{"a": 1}, {"a": 2}]' @# '$[*].a ? (@ > 10)';
17021708

17031709
(1 row)
17041710

1711+
SELECT jsonb '[{"a": 1}, {"a": 2}]' @# '[$[*].a]';
1712+
?column?
1713+
----------
1714+
[1, 2]
1715+
(1 row)
1716+
17051717
SELECT jsonb '[{"a": 1}, {"a": 2}]' @? '$[*].a ? (@ > 1)';
17061718
?column?
17071719
----------
@@ -1780,3 +1792,48 @@ select jsonb '[1,2,3,4,5]' @* '$[(0, $[*], 5) ? (@ == 3)]';
17801792

17811793
select jsonb '[1,2,3,4,5]' @* '$[(0, $[*], 3) ? (@ == 3)]';
17821794
ERROR: Invalid SQL/JSON subscript
1795+
-- extension: array constructors
1796+
select jsonb '[1, 2, 3]' @* '[]';
1797+
?column?
1798+
----------
1799+
[]
1800+
(1 row)
1801+
1802+
select jsonb '[1, 2, 3]' @* '[1, 2, $[*], 4, 5]';
1803+
?column?
1804+
-----------------------
1805+
[1, 2, 1, 2, 3, 4, 5]
1806+
(1 row)
1807+
1808+
select jsonb '[1, 2, 3]' @* '[1, 2, $[*], 4, 5][*]';
1809+
?column?
1810+
----------
1811+
1
1812+
2
1813+
1
1814+
2
1815+
3
1816+
4
1817+
5
1818+
(7 rows)
1819+
1820+
select jsonb '[1, 2, 3]' @* '[(1, (2, $[*])), (4, 5)]';
1821+
?column?
1822+
-----------------------
1823+
[1, 2, 1, 2, 3, 4, 5]
1824+
(1 row)
1825+
1826+
select jsonb '[1, 2, 3]' @* '[[1, 2], [$[*], 4], 5, [(1,2)?(@ > 5)]]';
1827+
?column?
1828+
-------------------------------
1829+
[[1, 2], [1, 2, 3, 4], 5, []]
1830+
(1 row)
1831+
1832+
select jsonb '[1, 2, 3]' @* 'strict [1, 2, $[*].a, 4, 5]';
1833+
ERROR: SQL/JSON member not found
1834+
select jsonb '[[1, 2], [3, 4, 5], [], [6, 7]]' @* '[$[*][*] ? (@ > 3)]';
1835+
?column?
1836+
--------------
1837+
[4, 5, 6, 7]
1838+
(1 row)
1839+

src/test/regress/expected/jsonpath.out

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

549+
select '[]'::jsonpath;
550+
jsonpath
551+
----------
552+
[]
553+
(1 row)
554+
555+
select '[[1, 2], ([(3, 4, 5), 6], []), $.a[*]]'::jsonpath;
556+
jsonpath
557+
------------------------------------------
558+
[[1, 2], ([(3, 4, 5), 6], []), $."a"[*]]
559+
(1 row)
560+
549561
select '$ ? (@.a < 1)'::jsonpath;
550562
jsonpath
551563
---------------

src/test/regress/sql/jsonb_jsonpath.sql

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,10 +377,12 @@ set time zone default;
377377

378378
SELECT jsonb '[{"a": 1}, {"a": 2}]' @* '$[*]';
379379
SELECT jsonb '[{"a": 1}, {"a": 2}]' @* '$[*] ? (@.a > 10)';
380+
SELECT jsonb '[{"a": 1}, {"a": 2}]' @* '[$[*].a]';
380381

381382
SELECT jsonb '[{"a": 1}, {"a": 2}]' @# '$[*].a';
382383
SELECT jsonb '[{"a": 1}, {"a": 2}]' @# '$[*].a ? (@ == 1)';
383384
SELECT jsonb '[{"a": 1}, {"a": 2}]' @# '$[*].a ? (@ > 10)';
385+
SELECT jsonb '[{"a": 1}, {"a": 2}]' @# '[$[*].a]';
384386

385387
SELECT jsonb '[{"a": 1}, {"a": 2}]' @? '$[*].a ? (@ > 1)';
386388
SELECT jsonb '[{"a": 1}, {"a": 2}]' @? '$[*] ? (@.a > 2)';
@@ -396,3 +398,12 @@ select jsonb '[1,2,3,4,5]' @* '-(10, 20, $[1 to 3], 30)';
396398
select jsonb '[1,2,3,4,5]' @* 'lax (10, 20.5, $[1 to 3], "30").double()';
397399
select jsonb '[1,2,3,4,5]' @* '$[(0, $[*], 5) ? (@ == 3)]';
398400
select jsonb '[1,2,3,4,5]' @* '$[(0, $[*], 3) ? (@ == 3)]';
401+
402+
-- extension: array constructors
403+
select jsonb '[1, 2, 3]' @* '[]';
404+
select jsonb '[1, 2, 3]' @* '[1, 2, $[*], 4, 5]';
405+
select jsonb '[1, 2, 3]' @* '[1, 2, $[*], 4, 5][*]';
406+
select jsonb '[1, 2, 3]' @* '[(1, (2, $[*])), (4, 5)]';
407+
select jsonb '[1, 2, 3]' @* '[[1, 2], [$[*], 4], 5, [(1,2)?(@ > 5)]]';
408+
select jsonb '[1, 2, 3]' @* 'strict [1, 2, $[*].a, 4, 5]';
409+
select jsonb '[[1, 2], [3, 4, 5], [], [6, 7]]' @* '[$[*][*] ? (@ > 3)]';

src/test/regress/sql/jsonpath.sql

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,9 @@ select '(1, 2, $.a) == 5'::jsonpath;
103103
select '$[(1, 2, $.a) to (3, 4)]'::jsonpath;
104104
select '$[(1, (2, $.a)), 3, (4, 5)]'::jsonpath;
105105
106+
select '[]'::jsonpath;
107+
select '[[1, 2], ([(3, 4, 5), 6], []), $.a[*]]'::jsonpath;
108+
106109
select '$ ? (@.a < 1)'::jsonpath;
107110
select '$ ? (@.a < -1)'::jsonpath;
108111
select '$ ? (@.a < +1)'::jsonpath;

0 commit comments

Comments
 (0)