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

Commit 777b82b

Browse files
author
Nikita Glukhov
committed
Add jsonpath array constructors
1 parent 0bf4603 commit 777b82b

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
@@ -122,28 +122,23 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item,
122122
*(int32 *)(buf->data + offs) = chld;
123123
}
124124
break;
125-
case jpiDatetime:
126-
if (!item->value.arg)
127-
{
128-
int32 arg = 0;
129-
130-
appendBinaryStringInfo(buf, (char *) &arg, sizeof(arg));
131-
break;
132-
}
133-
/* fall through */
134125
case jpiFilter:
135126
case jpiIsUnknown:
136127
case jpiNot:
137128
case jpiPlus:
138129
case jpiMinus:
139130
case jpiExists:
131+
case jpiDatetime:
140132
case jpiMap:
133+
case jpiArray:
141134
{
142-
int32 arg;
135+
int32 arg = item->value.arg ? buf->len : 0;
143136

144-
arg = buf->len;
145137
appendBinaryStringInfo(buf, (char*)&arg /* fake value */, sizeof(arg));
146138

139+
if (!item->value.arg)
140+
break;
141+
147142
chld = flattenJsonPathParseItem(buf, item->value.arg,
148143
item->type == jpiFilter ||
149144
item->type == jpiMap ||
@@ -603,6 +598,15 @@ printJsonPathItem(StringInfo buf, JsonPathItem *v, bool inKey, bool printBracket
603598
if (printBracketes || jspHasNext(v))
604599
appendStringInfoChar(buf, ')');
605600
break;
601+
case jpiArray:
602+
appendStringInfoChar(buf, '[');
603+
if (v->content.arg)
604+
{
605+
jspGetArg(v, &elem);
606+
printJsonPathItem(buf, &elem, false, false);
607+
}
608+
appendStringInfoChar(buf, ']');
609+
break;
606610
default:
607611
elog(ERROR, "Unknown jsonpath item type: %d", v->type);
608612
}
@@ -737,6 +741,7 @@ jspInitByBuffer(JsonPathItem *v, char *base, int32 pos)
737741
case jpiFilter:
738742
case jpiDatetime:
739743
case jpiMap:
744+
case jpiArray:
740745
read_int32(v->content.arg, base, pos);
741746
break;
742747
case jpiIndexArray:
@@ -769,7 +774,8 @@ jspGetArg(JsonPathItem *v, JsonPathItem *a)
769774
v->type == jpiPlus ||
770775
v->type == jpiMinus ||
771776
v->type == jpiDatetime ||
772-
v->type == jpiMap
777+
v->type == jpiMap ||
778+
v->type == jpiArray
773779
);
774780

775781
jspInitByBuffer(a, v->base, v->content.arg);
@@ -823,7 +829,8 @@ jspGetNext(JsonPathItem *v, JsonPathItem *a)
823829
v->type == jpiKeyValue ||
824830
v->type == jpiStartsWith ||
825831
v->type == jpiMap ||
826-
v->type == jpiSequence
832+
v->type == jpiSequence ||
833+
v->type == jpiArray
827834
);
828835

829836
if (a)

src/backend/utils/adt/jsonpath_exec.c

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

21822182
break;
21832183
}
2184+
case jpiArray:
2185+
{
2186+
JsonValueList list = { 0 };
2187+
2188+
if (jsp->content.arg)
2189+
{
2190+
jspGetArg(jsp, &elem);
2191+
res = recursiveExecute(cxt, &elem, jb, &list);
2192+
2193+
if (jperIsError(res))
2194+
break;
2195+
}
2196+
2197+
res = recursiveExecuteNext(cxt, jsp, NULL,
2198+
wrapItemsInArray(&list),
2199+
found, false);
2200+
}
2201+
break;
21842202
default:
21852203
elog(ERROR, "unrecognized jsonpath item type: %d", jsp->type);
21862204
}

src/backend/utils/adt/jsonpath_gram.y

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,8 @@ path_primary:
390390
| '@' { $$ = makeItemType(jpiCurrent); }
391391
| LAST_P { $$ = makeItemType(jpiLast); }
392392
| '(' expr_seq ')' { $$ = $2; }
393+
| '[' ']' { $$ = makeItemUnary(jpiArray, NULL); }
394+
| '[' expr_or_seq ']' { $$ = makeItemUnary(jpiArray, $2); }
393395
;
394396

395397
accessor_expr:

src/include/utils/jsonpath.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ typedef enum JsonPathItemType {
8686
jpiLikeRegex,
8787
jpiMap,
8888
jpiSequence,
89+
jpiArray,
8990
} JsonPathItemType;
9091

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

src/test/regress/expected/jsonb_jsonpath.out

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

1624+
SELECT jsonb '[{"a": 1}, {"a": 2}]' @* '[$[*].a]';
1625+
?column?
1626+
----------
1627+
[1, 2]
1628+
(1 row)
1629+
16241630
SELECT jsonb '[{"a": 1}, {"a": 2}]' @? '$[*].a ? (@ > 1)';
16251631
?column?
16261632
----------
@@ -1720,3 +1726,48 @@ select jsonb '[1,2,3,4,5]' @* '$[(0, $[*], 5) ? (@ == 3)]';
17201726

17211727
select jsonb '[1,2,3,4,5]' @* '$[(0, $[*], 3) ? (@ == 3)]';
17221728
ERROR: Invalid SQL/JSON subscript
1729+
-- extension: array constructors
1730+
select jsonb '[1, 2, 3]' @* '[]';
1731+
?column?
1732+
----------
1733+
[]
1734+
(1 row)
1735+
1736+
select jsonb '[1, 2, 3]' @* '[1, 2, $.map(@ + 100)[*], 4, 5]';
1737+
?column?
1738+
-----------------------------
1739+
[1, 2, 101, 102, 103, 4, 5]
1740+
(1 row)
1741+
1742+
select jsonb '[1, 2, 3]' @* '[1, 2, $.map(@ + 100)[*], 4, 5][*]';
1743+
?column?
1744+
----------
1745+
1
1746+
2
1747+
101
1748+
102
1749+
103
1750+
4
1751+
5
1752+
(7 rows)
1753+
1754+
select jsonb '[1, 2, 3]' @* '[(1, (2, $.map(@ + 100)[*])), (4, 5)]';
1755+
?column?
1756+
-----------------------------
1757+
[1, 2, 101, 102, 103, 4, 5]
1758+
(1 row)
1759+
1760+
select jsonb '[1, 2, 3]' @* '[[1, 2], [$.map(@ + 100)[*], 4], 5, [(1,2)?(@ > 5)]]';
1761+
?column?
1762+
-------------------------------------
1763+
[[1, 2], [101, 102, 103, 4], 5, []]
1764+
(1 row)
1765+
1766+
select jsonb '[1, 2, 3]' @* 'strict [1, 2, $.map(@.a)[*], 4, 5]';
1767+
ERROR: SQL/JSON member not found
1768+
select jsonb '[[1, 2], [3, 4, 5], [], [6, 7]]' @* '[$[*].map(@ + 10)[*] ? (@ > 13)]';
1769+
?column?
1770+
------------------
1771+
[14, 15, 16, 17]
1772+
(1 row)
1773+

src/test/regress/expected/jsonpath.out

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

533+
select '[]'::jsonpath;
534+
jsonpath
535+
----------
536+
[]
537+
(1 row)
538+
539+
select '[[1, 2], ([(3, 4, 5), 6], []), $.a[*]]'::jsonpath;
540+
jsonpath
541+
------------------------------------------
542+
[[1, 2], ([(3, 4, 5), 6], []), $."a"[*]]
543+
(1 row)
544+
533545
select '$ ? (@.a < 1)'::jsonpath;
534546
jsonpath
535547
---------------

src/test/regress/sql/jsonb_jsonpath.sql

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,7 @@ set time zone default;
362362

363363
SELECT jsonb '[{"a": 1}, {"a": 2}]' @* '$[*]';
364364
SELECT jsonb '[{"a": 1}, {"a": 2}]' @* '$[*] ? (@.a > 10)';
365+
SELECT jsonb '[{"a": 1}, {"a": 2}]' @* '[$[*].a]';
365366

366367
SELECT jsonb '[{"a": 1}, {"a": 2}]' @? '$[*].a ? (@ > 1)';
367368
SELECT jsonb '[{"a": 1}, {"a": 2}]' @? '$[*] ? (@.a > 2)';
@@ -383,3 +384,12 @@ select jsonb '[1,2,3,4,5]' @* '-(10, 20, $[1 to 3], 30)';
383384
select jsonb '[1,2,3,4,5]' @* 'lax (10, 20, $[1 to 3], 30).map(@ + 100)';
384385
select jsonb '[1,2,3,4,5]' @* '$[(0, $[*], 5) ? (@ == 3)]';
385386
select jsonb '[1,2,3,4,5]' @* '$[(0, $[*], 3) ? (@ == 3)]';
387+
388+
-- extension: array constructors
389+
select jsonb '[1, 2, 3]' @* '[]';
390+
select jsonb '[1, 2, 3]' @* '[1, 2, $.map(@ + 100)[*], 4, 5]';
391+
select jsonb '[1, 2, 3]' @* '[1, 2, $.map(@ + 100)[*], 4, 5][*]';
392+
select jsonb '[1, 2, 3]' @* '[(1, (2, $.map(@ + 100)[*])), (4, 5)]';
393+
select jsonb '[1, 2, 3]' @* '[[1, 2], [$.map(@ + 100)[*], 4], 5, [(1,2)?(@ > 5)]]';
394+
select jsonb '[1, 2, 3]' @* 'strict [1, 2, $.map(@.a)[*], 4, 5]';
395+
select 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
@@ -99,6 +99,9 @@ select '(1, 2, $.a) == 5'::jsonpath;
9999
select '$[(1, 2, $.a) to (3, 4)]'::jsonpath;
100100
select '$[(1, (2, $.a)), 3, (4, 5)]'::jsonpath;
101101

102+
select '[]'::jsonpath;
103+
select '[[1, 2], ([(3, 4, 5), 6], []), $.a[*]]'::jsonpath;
104+
102105
select '$ ? (@.a < 1)'::jsonpath;
103106
select '$ ? (@.a < -1)'::jsonpath;
104107
select '$ ? (@.a < +1)'::jsonpath;

0 commit comments

Comments
 (0)