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

Commit abc8c3a

Browse files
author
Nikita Glukhov
committed
Add jsonpath array constructors
1 parent 3704c75 commit abc8c3a

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,"2Wrong state: %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
@@ -1627,6 +1627,12 @@ SELECT jsonb '[{"a": 1}, {"a": 2}]' @* '$[*] ? (@.a > 10)';
16271627
----------
16281628
(0 rows)
16291629

1630+
SELECT jsonb '[{"a": 1}, {"a": 2}]' @* '[$[*].a]';
1631+
?column?
1632+
----------
1633+
[1, 2]
1634+
(1 row)
1635+
16301636
SELECT jsonb '[{"a": 1}, {"a": 2}]' @? '$[*].a ? (@ > 1)';
16311637
?column?
16321638
----------
@@ -1726,3 +1732,48 @@ select jsonb '[1,2,3,4,5]' @* '$[(0, $[*], 5) ? (@ == 3)]';
17261732

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

src/test/regress/expected/jsonpath.out

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

545+
select '[]'::jsonpath;
546+
jsonpath
547+
----------
548+
[]
549+
(1 row)
550+
551+
select '[[1, 2], ([(3, 4, 5), 6], []), $.a[*]]'::jsonpath;
552+
jsonpath
553+
------------------------------------------
554+
[[1, 2], ([(3, 4, 5), 6], []), $."a"[*]]
555+
(1 row)
556+
545557
select '$ ? (a < 1)'::jsonpath;
546558
jsonpath
547559
-------------

src/test/regress/sql/jsonb_jsonpath.sql

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

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

367368
SELECT jsonb '[{"a": 1}, {"a": 2}]' @? '$[*].a ? (@ > 1)';
368369
SELECT jsonb '[{"a": 1}, {"a": 2}]' @? '$[*] ? (@.a > 2)';
@@ -384,3 +385,12 @@ select jsonb '[1,2,3,4,5]' @* '-(10, 20, $[1 to 3], 30)';
384385
select jsonb '[1,2,3,4,5]' @* 'lax (10, 20, $[1 to 3], 30).map(@ + 100)';
385386
select jsonb '[1,2,3,4,5]' @* '$[(0, $[*], 5) ? (@ == 3)]';
386387
select jsonb '[1,2,3,4,5]' @* '$[(0, $[*], 3) ? (@ == 3)]';
388+
389+
-- extension: array constructors
390+
select jsonb '[1, 2, 3]' @* '[]';
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)]';
394+
select jsonb '[1, 2, 3]' @* '[[1, 2], [$.map(@ + 100)[*], 4], 5, [(1,2)?(@ > 5)]]';
395+
select jsonb '[1, 2, 3]' @* 'strict [1, 2, $.map(@.a)[*], 4, 5]';
396+
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
@@ -101,6 +101,9 @@ select '(1, 2, $.a) == 5'::jsonpath;
101101
select '$[(1, 2, $.a) to (3, 4)]'::jsonpath;
102102
select '$[(1, (2, $.a)), 3, (4, 5)]'::jsonpath;
103103

104+
select '[]'::jsonpath;
105+
select '[[1, 2], ([(3, 4, 5), 6], []), $.a[*]]'::jsonpath;
106+
104107
select '$ ? (a < 1)'::jsonpath;
105108
select '$ ? (a < -1)'::jsonpath;
106109
select '$ ? (a < +1)'::jsonpath;

0 commit comments

Comments
 (0)