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

Commit f66f26c

Browse files
author
Nikita Glukhov
committed
Allow jsonpath $ everywhere
1 parent 6ee595c commit f66f26c

File tree

6 files changed

+40
-26
lines changed

6 files changed

+40
-26
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;
@@ -92,11 +92,11 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item,
9292
appendBinaryStringInfo(buf, (char*)&right /* fake value */, sizeof(right));
9393

9494
chld = flattenJsonPathParseItem(buf, item->value.args.left,
95-
forbiddenRoot,
95+
allowCurrent,
9696
insideArraySubscript);
9797
*(int32*)(buf->data + left) = chld;
9898
chld = flattenJsonPathParseItem(buf, item->value.args.right,
99-
forbiddenRoot,
99+
allowCurrent,
100100
insideArraySubscript);
101101
*(int32*)(buf->data + right) = chld;
102102
}
@@ -119,7 +119,7 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item,
119119
appendStringInfoChar(buf, '\0');
120120

121121
chld = flattenJsonPathParseItem(buf, item->value.like_regex.expr,
122-
forbiddenRoot,
122+
allowCurrent,
123123
insideArraySubscript);
124124
*(int32 *)(buf->data + offs) = chld;
125125
}
@@ -147,24 +147,20 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item,
147147

148148
chld = flattenJsonPathParseItem(buf, item->value.arg,
149149
item->type == jpiFilter ||
150-
forbiddenRoot,
150+
allowCurrent,
151151
insideArraySubscript);
152152
*(int32*)(buf->data + arg) = chld;
153153
}
154154
break;
155155
case jpiNull:
156156
break;
157157
case jpiRoot:
158-
if (forbiddenRoot)
159-
ereport(ERROR,
160-
(errcode(ERRCODE_SYNTAX_ERROR),
161-
errmsg("root is not allowed in expression")));
162158
break;
163159
case jpiAnyArray:
164160
case jpiAnyKey:
165161
break;
166162
case jpiCurrent:
167-
if (!forbiddenRoot)
163+
if (!allowCurrent)
168164
ereport(ERROR,
169165
(errcode(ERRCODE_SYNTAX_ERROR),
170166
errmsg("@ is not allowed in root expressions")));
@@ -232,7 +228,7 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item,
232228

233229
if (item->next)
234230
{
235-
chld = flattenJsonPathParseItem(buf, item->next, forbiddenRoot,
231+
chld = flattenJsonPathParseItem(buf, item->next, allowCurrent,
236232
insideArraySubscript);
237233
*(int32 *)(buf->data + next) = chld;
238234
}

src/backend/utils/adt/jsonpath_exec.c

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

@@ -1231,6 +1232,9 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
12311232
res = jperMakeError(ERRCODE_JSON_MEMBER_NOT_FOUND);
12321233
}
12331234
break;
1235+
case jpiRoot:
1236+
jb = cxt->root;
1237+
/* fall through */
12341238
case jpiCurrent:
12351239
if (!jspGetNext(jsp, &elem))
12361240
{
@@ -1493,19 +1497,6 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
14931497
case jpiPlus:
14941498
case jpiMinus:
14951499
res = executeUnaryArithmExpr(cxt, jsp, jb, found);
1496-
break;
1497-
case jpiRoot:
1498-
if (jspGetNext(jsp, &elem))
1499-
{
1500-
res = recursiveExecute(cxt, &elem, jb, found);
1501-
}
1502-
else
1503-
{
1504-
res = jperOk;
1505-
if (found)
1506-
*found = lappend(*found, copyJsonbValue(jb));
1507-
}
1508-
15091500
break;
15101501
case jpiFilter:
15111502
jspGetArg(jsp, &elem);
@@ -2050,12 +2041,11 @@ executeJsonPath(JsonPath *path, List *vars, Jsonb *json, List **foundJson)
20502041
JsonPathItem jsp;
20512042
JsonbValue jbv;
20522043

2053-
JsonbInitBinary(&jbv, json);
2054-
20552044
jspInit(&jsp, path);
20562045

20572046
cxt.vars = vars;
20582047
cxt.lax = (path->header & JSONPATH_LAX) != 0;
2048+
cxt.root = JsonbInitBinary(&jbv, json);
20592049
cxt.innermostArraySize = -1;
20602050

20612051
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
@@ -657,6 +657,12 @@ select _jsonpath_exists(jsonb '{"c": {"a": 1, "b":1}}', '$.c ? (.a == .b)');
657657
t
658658
(1 row)
659659

660+
select _jsonpath_exists(jsonb '{"c": {"a": 1, "b":1}}', '$.c ? ($.c.a == .b)');
661+
_jsonpath_exists
662+
------------------
663+
t
664+
(1 row)
665+
660666
select _jsonpath_exists(jsonb '{"c": {"a": 1, "b":1}}', '$.* ? (.a == .b)');
661667
_jsonpath_exists
662668
------------------
@@ -765,6 +771,12 @@ select _jsonpath_exists(jsonb '[1,2,3]', '$ ? (-@[*] < -3)');
765771
f
766772
(1 row)
767773

774+
select _jsonpath_exists(jsonb '1', '$ ? ($ > 0)');
775+
_jsonpath_exists
776+
------------------
777+
t
778+
(1 row)
779+
768780
-- unwrapping of operator arguments in lax mode
769781
select _jsonpath_query(jsonb '{"a": [2]}', 'lax $.a * 3');
770782
_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
@@ -134,6 +134,7 @@ from
134134
select _jsonpath_exists(jsonb '{"a": 1, "b":1}', '$ ? (.a == .b)');
135135
select _jsonpath_exists(jsonb '{"c": {"a": 1, "b":1}}', '$ ? (.a == .b)');
136136
select _jsonpath_exists(jsonb '{"c": {"a": 1, "b":1}}', '$.c ? (.a == .b)');
137+
select _jsonpath_exists(jsonb '{"c": {"a": 1, "b":1}}', '$.c ? ($.c.a == .b)');
137138
select _jsonpath_exists(jsonb '{"c": {"a": 1, "b":1}}', '$.* ? (.a == .b)');
138139
select _jsonpath_exists(jsonb '{"a": 1, "b":1}', '$.** ? (.a == .b)');
139140
select _jsonpath_exists(jsonb '{"c": {"a": 1, "b":1}}', '$.** ? (.a == .b)');
@@ -153,6 +154,7 @@ select _jsonpath_exists(jsonb '[1,2,3]', '$ ? (+@[*] > +2)');
153154
select _jsonpath_exists(jsonb '[1,2,3]', '$ ? (+@[*] > +3)');
154155
select _jsonpath_exists(jsonb '[1,2,3]', '$ ? (-@[*] < -2)');
155156
select _jsonpath_exists(jsonb '[1,2,3]', '$ ? (-@[*] < -3)');
157+
select _jsonpath_exists(jsonb '1', '$ ? ($ > 0)');
156158

157159
-- unwrapping of operator arguments in lax mode
158160
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)