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

Commit 71e8a1d

Browse files
author
Nikita Glukhov
committed
Allow jsonpath $ everywhere
1 parent 2bf616b commit 71e8a1d

File tree

6 files changed

+40
-24
lines changed

6 files changed

+40
-24
lines changed

src/backend/utils/adt/jsonpath.c

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
*/
2626
static int
2727
flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item,
28-
bool forbiddenRoot, bool insideArraySubscript)
28+
bool allowCurrent, bool insideArraySubscript)
2929
{
3030
/* position from begining of jsonpath data */
3131
int32 pos = buf->len - JSONPATH_HDRSZ;
@@ -90,11 +90,11 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item,
9090
appendBinaryStringInfo(buf, (char*)&right /* fake value */, sizeof(right));
9191

9292
chld = flattenJsonPathParseItem(buf, item->value.args.left,
93-
forbiddenRoot,
93+
allowCurrent,
9494
insideArraySubscript);
9595
*(int32*)(buf->data + left) = chld;
9696
chld = flattenJsonPathParseItem(buf, item->value.args.right,
97-
forbiddenRoot,
97+
allowCurrent,
9898
insideArraySubscript);
9999
*(int32*)(buf->data + right) = chld;
100100
}
@@ -117,7 +117,7 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item,
117117
appendStringInfoChar(buf, '\0');
118118

119119
chld = flattenJsonPathParseItem(buf, item->value.like_regex.expr,
120-
forbiddenRoot,
120+
allowCurrent,
121121
insideArraySubscript);
122122
*(int32 *)(buf->data + offs) = chld;
123123
}
@@ -145,24 +145,20 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item,
145145

146146
chld = flattenJsonPathParseItem(buf, item->value.arg,
147147
item->type == jpiFilter ||
148-
forbiddenRoot,
148+
allowCurrent,
149149
insideArraySubscript);
150150
*(int32*)(buf->data + arg) = chld;
151151
}
152152
break;
153153
case jpiNull:
154154
break;
155155
case jpiRoot:
156-
if (forbiddenRoot)
157-
ereport(ERROR,
158-
(errcode(ERRCODE_SYNTAX_ERROR),
159-
errmsg("root is not allowed in expression")));
160156
break;
161157
case jpiAnyArray:
162158
case jpiAnyKey:
163159
break;
164160
case jpiCurrent:
165-
if (!forbiddenRoot)
161+
if (!allowCurrent)
166162
ereport(ERROR,
167163
(errcode(ERRCODE_SYNTAX_ERROR),
168164
errmsg("@ is not allowed in root expressions")));
@@ -230,7 +226,7 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item,
230226

231227
if (item->next)
232228
*(int32*)(buf->data + next) =
233-
flattenJsonPathParseItem(buf, item->next, forbiddenRoot,
229+
flattenJsonPathParseItem(buf, item->next, allowCurrent,
234230
insideArraySubscript);
235231

236232
return pos;

src/backend/utils/adt/jsonpath_exec.c

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ typedef struct JsonPathExecContext
2727
{
2828
List *vars;
2929
bool lax;
30+
JsonbValue *root; /* for $ evaluation */
3031
int innermostArraySize; /* for LAST array index evaluation */
3132
} JsonPathExecContext;
3233

@@ -1209,6 +1210,9 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
12091210
res = jperMakeError(ERRCODE_JSON_MEMBER_NOT_FOUND);
12101211
}
12111212
break;
1213+
case jpiRoot:
1214+
jb = cxt->root;
1215+
/* fall through */
12121216
case jpiCurrent:
12131217
if (!jspGetNext(jsp, &elem))
12141218
{
@@ -1471,19 +1475,6 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
14711475
case jpiPlus:
14721476
case jpiMinus:
14731477
res = executeUnaryArithmExpr(cxt, jsp, jb, found);
1474-
break;
1475-
case jpiRoot:
1476-
if (jspGetNext(jsp, &elem))
1477-
{
1478-
res = recursiveExecute(cxt, &elem, jb, found);
1479-
}
1480-
else
1481-
{
1482-
res = jperOk;
1483-
if (found)
1484-
*found = lappend(*found, copyJsonbValue(jb));
1485-
}
1486-
14871478
break;
14881479
case jpiFilter:
14891480
jspGetArg(jsp, &elem);
@@ -2023,6 +2014,7 @@ executeJsonPath(JsonPath *path, List *vars, Jsonb *json, List **foundJson)
20232014

20242015
cxt.vars = vars;
20252016
cxt.lax = (path->header & JSONPATH_LAX) != 0;
2017+
cxt.root = &jbv;
20262018
cxt.innermostArraySize = -1;
20272019

20282020
if (!cxt.lax && !foundJson)

src/test/regress/expected/jsonb_jsonpath.out

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -647,6 +647,12 @@ select _jsonpath_exists(jsonb '{"c": {"a": 1, "b":1}}', '$.c ? (.a == .b)');
647647
t
648648
(1 row)
649649

650+
select _jsonpath_exists(jsonb '{"c": {"a": 1, "b":1}}', '$.c ? ($.c.a == .b)');
651+
_jsonpath_exists
652+
------------------
653+
t
654+
(1 row)
655+
650656
select _jsonpath_exists(jsonb '{"c": {"a": 1, "b":1}}', '$.* ? (.a == .b)');
651657
_jsonpath_exists
652658
------------------
@@ -755,6 +761,12 @@ select _jsonpath_exists(jsonb '[1,2,3]', '$ ? (-@[*] < -3)');
755761
f
756762
(1 row)
757763

764+
select _jsonpath_exists(jsonb '1', '$ ? ($ > 0)');
765+
_jsonpath_exists
766+
------------------
767+
t
768+
(1 row)
769+
758770
-- unwrapping of operator arguments in lax mode
759771
select _jsonpath_query(jsonb '{"a": [2]}', 'lax $.a * 3');
760772
_jsonpath_query

src/test/regress/expected/jsonpath.out

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,12 @@ select '$.a/+-1'::jsonpath;
177177
($."a" / -1)
178178
(1 row)
179179

180+
select '$.g ? ($.a == 1)'::jsonpath;
181+
jsonpath
182+
--------------------
183+
$."g"?($."a" == 1)
184+
(1 row)
185+
180186
select '$.g ? (@ == 1)'::jsonpath;
181187
jsonpath
182188
----------------
@@ -315,6 +321,12 @@ select '$.a[$a + 1, ($b[*]) to -(@[0] * 2)]'::jsonpath;
315321
$."a"[$"a" + 1,$"b"[*] to -(@[0] * 2)]
316322
(1 row)
317323

324+
select '$.a[$.a.size() - 3]'::jsonpath;
325+
jsonpath
326+
-------------------------
327+
$."a"[$."a".size() - 3]
328+
(1 row)
329+
318330
select 'last'::jsonpath;
319331
ERROR: LAST is allowed only in array subscripts
320332
LINE 1: select 'last'::jsonpath;

src/test/regress/sql/jsonb_jsonpath.sql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ from
133133
select _jsonpath_exists(jsonb '{"a": 1, "b":1}', '$ ? (.a == .b)');
134134
select _jsonpath_exists(jsonb '{"c": {"a": 1, "b":1}}', '$ ? (.a == .b)');
135135
select _jsonpath_exists(jsonb '{"c": {"a": 1, "b":1}}', '$.c ? (.a == .b)');
136+
select _jsonpath_exists(jsonb '{"c": {"a": 1, "b":1}}', '$.c ? ($.c.a == .b)');
136137
select _jsonpath_exists(jsonb '{"c": {"a": 1, "b":1}}', '$.* ? (.a == .b)');
137138
select _jsonpath_exists(jsonb '{"a": 1, "b":1}', '$.** ? (.a == .b)');
138139
select _jsonpath_exists(jsonb '{"c": {"a": 1, "b":1}}', '$.** ? (.a == .b)');
@@ -152,6 +153,7 @@ select _jsonpath_exists(jsonb '[1,2,3]', '$ ? (+@[*] > +2)');
152153
select _jsonpath_exists(jsonb '[1,2,3]', '$ ? (+@[*] > +3)');
153154
select _jsonpath_exists(jsonb '[1,2,3]', '$ ? (-@[*] < -2)');
154155
select _jsonpath_exists(jsonb '[1,2,3]', '$ ? (-@[*] < -3)');
156+
select _jsonpath_exists(jsonb '1', '$ ? ($ > 0)');
155157

156158
-- unwrapping of operator arguments in lax mode
157159
select _jsonpath_query(jsonb '{"a": [2]}', 'lax $.a * 3');

src/test/regress/sql/jsonpath.sql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ select '$-1'::jsonpath;
3131
select '$--+1'::jsonpath;
3232
select '$.a/+-1'::jsonpath;
3333

34+
select '$.g ? ($.a == 1)'::jsonpath;
3435
select '$.g ? (@ == 1)'::jsonpath;
3536
select '$.g ? (a == 1)'::jsonpath;
3637
select '$.g ? (.a == 1)'::jsonpath;
@@ -55,6 +56,7 @@ select '$.g ? (zip == $zip)'::jsonpath;
5556
select '$.a.[1,2, 3 to 16]'::jsonpath;
5657
select '$.a[1,2, 3 to 16]'::jsonpath;
5758
select '$.a[$a + 1, ($b[*]) to -(@[0] * 2)]'::jsonpath;
59+
select '$.a[$.a.size() - 3]'::jsonpath;
5860
select 'last'::jsonpath;
5961
select '"last"'::jsonpath;
6062
select '$.last'::jsonpath;

0 commit comments

Comments
 (0)