Skip to content

Commit 3342d8a

Browse files
committed
filter works
1 parent 72552ec commit 3342d8a

File tree

9 files changed

+454
-73
lines changed

9 files changed

+454
-73
lines changed

expected/jsquery.out

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1446,6 +1446,175 @@ select '{"a":[1,2]}' @@ '@# = 1'::jsquery;
14461446
t
14471447
(1 row)
14481448

1449+
--filter
1450+
select '?( not b>0). x'::jsquery;
1451+
jsquery
1452+
------------------------
1453+
?((NOT "b" > 0)) ."x"
1454+
(1 row)
1455+
1456+
select 'a.?(b>0 and x= 0 ) .c'::jsquery;
1457+
jsquery
1458+
-----------------------------------
1459+
"a" ?(("b" > 0 AND "x" = 0)) ."c"
1460+
(1 row)
1461+
1462+
select 'a.$. ?(b>0 and x= 0 ) . c.k'::jsquery;
1463+
jsquery
1464+
-----------------------------------------
1465+
"a".$ ?(("b" > 0 AND "x" = 0)) ."c"."k"
1466+
(1 row)
1467+
1468+
select 'a.$.? (b>0 and x.*= 0 ).c.k'::jsquery;
1469+
jsquery
1470+
-------------------------------------------
1471+
"a".$ ?(("b" > 0 AND "x".* = 0)) ."c"."k"
1472+
(1 row)
1473+
1474+
select '[{"a":1, "b":10}, {"a":2, "b":20}, {"a":3, "b":30}]'::jsonb @@ '#. ?(a < 0) (b=20)';
1475+
?column?
1476+
----------
1477+
f
1478+
(1 row)
1479+
1480+
select '[{"a":1, "b":10}, {"a":2, "b":20}, {"a":3, "b":30}]'::jsonb @@ '#. ?(a > 0) (b=20)';
1481+
?column?
1482+
----------
1483+
t
1484+
(1 row)
1485+
1486+
select '[{"a":1, "b":10}, {"a":2, "b":20}, {"a":3, "b":30}]'::jsonb @@ '#. ?(a > 1) (b=20)';
1487+
?column?
1488+
----------
1489+
t
1490+
(1 row)
1491+
1492+
select '[{"a":1, "b":10}, {"a":2, "b":20}, {"a":3, "b":30}]'::jsonb @@ '#. ?(a > 2) (b=20)';
1493+
?column?
1494+
----------
1495+
f
1496+
(1 row)
1497+
1498+
select '[{"a":1, "b":10}, {"a":2, "b":20}, {"a":3, "b":30}]'::jsonb @@ '#. ?(a > 3) (b=20)';
1499+
?column?
1500+
----------
1501+
f
1502+
(1 row)
1503+
1504+
select '[{"a":1, "b":10}, {"a":2, "b":20}]'::jsonb ~~ '#.a';
1505+
?column?
1506+
----------
1507+
[1, 2]
1508+
(1 row)
1509+
1510+
select '[{"a":1, "b":10}, {"a":2, "b":20}]'::jsonb ~~ '#. ?(a > 1). b';
1511+
?column?
1512+
----------
1513+
[20]
1514+
(1 row)
1515+
1516+
select '[{"a":1, "b":10}, {"a":2, "b":20}, {"a":3, "b":30}]'::jsonb ~~ '# . ?(a > 1)';
1517+
?column?
1518+
----------------------------------------
1519+
[{"a": 2, "b": 20}, {"a": 3, "b": 30}]
1520+
(1 row)
1521+
1522+
select '[{"a":1, "b":10}, {"a":2, "b":20}, {"a":3, "b":30}]'::jsonb ~~ '%';
1523+
?column?
1524+
----------
1525+
1526+
(1 row)
1527+
1528+
select '{"a":1, "b":2, "c":3}'::jsonb ~~ '%';
1529+
?column?
1530+
-----------
1531+
[1, 2, 3]
1532+
(1 row)
1533+
1534+
select '{"a":1, "b":2, "c":3}'::jsonb ~~ '% . ? ( $ > 2 )';
1535+
?column?
1536+
----------
1537+
[3]
1538+
(1 row)
1539+
1540+
select '{"a":1, "b":2, "c":3}'::jsonb ~~ '% . ? ( $ > 2 ).$';
1541+
?column?
1542+
----------
1543+
[3]
1544+
(1 row)
1545+
1546+
select '{"a":1, "b":2, "c":3}'::jsonb ~~ '? ( % > 2 )';
1547+
?column?
1548+
----------------------------
1549+
[{"a": 1, "b": 2, "c": 3}]
1550+
(1 row)
1551+
1552+
select '{"a":1, "b":2, "c":3}'::jsonb ~~ '? ( %: > 0 )';
1553+
?column?
1554+
----------------------------
1555+
[{"a": 1, "b": 2, "c": 3}]
1556+
(1 row)
1557+
1558+
select '{"a":1, "b":2, "c":3}'::jsonb ~~ '? ( %: > 2 )';
1559+
?column?
1560+
----------
1561+
1562+
(1 row)
1563+
1564+
select '[{"a":1, "b":10}, {"a":2, "b":20}, {"a":3, "b":30}]'::jsonb ~~ '#';
1565+
?column?
1566+
-----------------------------------------------------------
1567+
[{"a": 1, "b": 10}, {"a": 2, "b": 20}, {"a": 3, "b": 30}]
1568+
(1 row)
1569+
1570+
select '[1,2,3]'::jsonb ~~ '#';
1571+
?column?
1572+
-----------
1573+
[1, 2, 3]
1574+
(1 row)
1575+
1576+
select '[1,2,3]'::jsonb ~~ '#. ?($ > 2)';
1577+
?column?
1578+
----------
1579+
[3]
1580+
(1 row)
1581+
1582+
select '[1,2,3]'::jsonb ~~ '#. ?($ > 2).$';
1583+
?column?
1584+
----------
1585+
[3]
1586+
(1 row)
1587+
1588+
select '[1,2,3]'::jsonb ~~ ' ?(#.$ > 2).$';
1589+
?column?
1590+
-------------
1591+
[[1, 2, 3]]
1592+
(1 row)
1593+
1594+
select '[1,2,3]'::jsonb ~~ ' ?(#:.$ > 2).$';
1595+
?column?
1596+
----------
1597+
1598+
(1 row)
1599+
1600+
select '[1,2,3]'::jsonb ~~ ' ?(#:.$ > 0).$';
1601+
?column?
1602+
-------------
1603+
[[1, 2, 3]]
1604+
(1 row)
1605+
1606+
select '{"a": {"b": {"c": 1}}}'::jsonb ~~ '*.?(c >0)';
1607+
?column?
1608+
------------
1609+
[{"c": 1}]
1610+
(1 row)
1611+
1612+
select '{"a": {"b": {"c": 1}}}'::jsonb ~~ '?(*.c >0)';
1613+
?column?
1614+
--------------------------
1615+
[{"a": {"b": {"c": 1}}}]
1616+
(1 row)
1617+
14491618
--ALL
14501619
select 'a.*: = 4'::jsquery;
14511620
jsquery

jsquery--1.0.sql

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,17 @@ CREATE OPERATOR @@ (
4848
JOIN = contjoinsel
4949
);
5050

51+
CREATE FUNCTION json_jsquery_filter(jsonb, jsquery)
52+
RETURNS jsonb
53+
AS 'MODULE_PATHNAME'
54+
LANGUAGE C STRICT IMMUTABLE;
55+
56+
CREATE OPERATOR ~~ (
57+
LEFTARG = jsonb,
58+
RIGHTARG = jsquery,
59+
PROCEDURE = json_jsquery_filter
60+
);
61+
5162
CREATE FUNCTION jsquery_join_and(jsquery, jsquery)
5263
RETURNS jsquery
5364
AS 'MODULE_PATHNAME'

jsquery.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,13 @@ typedef enum JsQueryItemType {
5757
jqiLength,
5858
jqiIn,
5959
jqiIs,
60-
jqiIndexArray
60+
jqiIndexArray,
61+
jqiFilter
6162
} JsQueryItemType;
6263

6364
/*
6465
* JsQueryHint is stored in the same byte as JsQueryItemType so
65-
* JsQueryItemType should not use two high bits
66+
* JsQueryItemType should not use three high bits
6667
*/
6768
typedef enum JsQueryHint {
6869
jsqIndexDefault = 0x00,
@@ -84,7 +85,7 @@ typedef enum JsQueryHint {
8485
typedef struct JsQueryItem {
8586
JsQueryItemType type;
8687
JsQueryHint hint;
87-
int32 nextPos;
88+
uint32 nextPos;
8889
char *base;
8990

9091
union {
@@ -135,6 +136,7 @@ struct JsQueryParseItem {
135136
JsQueryItemType type;
136137
JsQueryHint hint;
137138
JsQueryParseItem *next; /* next in path */
139+
bool filter;
138140

139141
union {
140142
struct {

jsquery_gram.y

Lines changed: 33 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
/*-------------------------------------------------------------------------
22
*
33
* jsquery_gram.y
4-
* Grammar definitions for jsquery datatype
4+
* Grammar definitions for jsquery datatype
55
*
66
* Copyright (c) 2014, PostgreSQL Global Development Group
77
* Author: Teodor Sigaev <teodor@sigaev.ru>
88
*
99
* IDENTIFICATION
10-
* contrib/jsquery/jsquery_gram.y
10+
* contrib/jsquery/jsquery_gram.y
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -43,8 +43,8 @@ fprintf_to_ereport(const char *fmt, const char *msg)
4343

4444
/* struct string is shared between scan and gram */
4545
typedef struct string {
46-
char *val;
47-
int len;
46+
char *val;
47+
int len;
4848
int total;
4949
} string;
5050
#include <jsquery_gram.h>
@@ -188,6 +188,9 @@ makeItemList(List *list) {
188188

189189
head = end = (JsQueryParseItem*)linitial(list);
190190

191+
while(end->next)
192+
end = end->next;
193+
191194
foreach(cell, list)
192195
{
193196
JsQueryParseItem *c = (JsQueryParseItem*)lfirst(cell);
@@ -197,6 +200,9 @@ makeItemList(List *list) {
197200

198201
end->next = c;
199202
end = c;
203+
204+
while(end->next)
205+
end = end->next;
200206
}
201207

202208
return head;
@@ -212,7 +218,7 @@ makeItemList(List *list) {
212218
%parse-param {JsQueryParseItem **result}
213219

214220
%union {
215-
string str;
221+
string str;
216222
List *elems; /* list of JsQueryParseItem */
217223

218224
JsQueryParseItem *value;
@@ -225,25 +231,26 @@ makeItemList(List *list) {
225231

226232
%token <str> STRING_P NUMERIC_P INT_P
227233

228-
%type <value> result scalar_value
234+
%type <value> result scalar_value
229235

230236
%type <elems> path value_list
231237

232-
%type <value> key key_any right_expr expr array numeric
238+
%type <value> key key_any right_expr expr array numeric
233239

234240
%token <hint> HINT_P
235241

236-
%left OR_P
237-
%left AND_P
238-
%right NOT_P
239-
%nonassoc IN_P IS_P
242+
%left OR_P
243+
%left AND_P
244+
%right NOT_P
245+
%nonassoc IN_P IS_P
240246
%nonassoc '(' ')'
241247

242248
/* Grammar follows */
243249
%%
244250

245-
result:
246-
expr { *result = $1; }
251+
result:
252+
expr { *result = $1; }
253+
| path { *result = makeItemList($1); }
247254
| /* EMPTY */ { *result = NULL; }
248255
;
249256

@@ -271,8 +278,8 @@ scalar_value:
271278
;
272279

273280
value_list:
274-
scalar_value { $$ = lappend(NIL, $1); }
275-
| value_list ',' scalar_value { $$ = lappend($1, $3); }
281+
scalar_value { $$ = lappend(NIL, $1); }
282+
| value_list ',' scalar_value { $$ = lappend($1, $3); }
276283
;
277284

278285
numeric:
@@ -289,20 +296,20 @@ right_expr:
289296
| '>' numeric { $$ = makeItemUnary(jqiGreater, $2); }
290297
| '<' '=' numeric { $$ = makeItemUnary(jqiLessOrEqual, $3); }
291298
| '>' '=' numeric { $$ = makeItemUnary(jqiGreaterOrEqual, $3); }
292-
| '@' '>' array { $$ = makeItemUnary(jqiContains, $3); }
293-
| '<' '@' array { $$ = makeItemUnary(jqiContained, $3); }
299+
| '@' '>' array { $$ = makeItemUnary(jqiContains, $3); }
300+
| '<' '@' array { $$ = makeItemUnary(jqiContained, $3); }
294301
| '&' '&' array { $$ = makeItemUnary(jqiOverlap, $3); }
295-
| IS_P ARRAY_T { $$ = makeItemIs(jbvArray); }
296-
| IS_P NUMERIC_T { $$ = makeItemIs(jbvNumeric); }
297-
| IS_P OBJECT_T { $$ = makeItemIs(jbvObject); }
298-
| IS_P STRING_T { $$ = makeItemIs(jbvString); }
299-
| IS_P BOOLEAN_T { $$ = makeItemIs(jbvBool); }
302+
| IS_P ARRAY_T { $$ = makeItemIs(jbvArray); }
303+
| IS_P NUMERIC_T { $$ = makeItemIs(jbvNumeric); }
304+
| IS_P OBJECT_T { $$ = makeItemIs(jbvObject); }
305+
| IS_P STRING_T { $$ = makeItemIs(jbvString); }
306+
| IS_P BOOLEAN_T { $$ = makeItemIs(jbvBool); }
300307
;
301308

302309
expr:
303310
path right_expr { $$ = makeItemList(lappend($1, $2)); }
304311
| path HINT_P right_expr { $3->hint = $2; $$ = makeItemList(lappend($1, $3)); }
305-
| NOT_P expr { $$ = makeItemUnary(jqiNot, $2); }
312+
| NOT_P expr { $$ = makeItemUnary(jqiNot, $2); }
306313
/*
307314
* In next two lines NOT_P is a path actually, not a an
308315
* logical expression.
@@ -346,15 +353,17 @@ key:
346353
;
347354

348355
/*
349-
* NOT keyword needs separate processing
356+
* NOT keyword needs separate processing
350357
*/
351358
key_any:
352359
key { $$ = $$; }
360+
| '?' '(' expr ')' { $$ = makeItemUnary(jqiFilter, $3); }
353361
| NOT_P { $$ = makeItemKey(&$1); }
354362
;
355363

356364
path:
357365
key { $$ = lappend(NIL, $1); }
366+
| '?' '(' expr ')' { $$ = lappend(NIL, makeItemUnary(jqiFilter, $3)); }
358367
| path '.' key_any { $$ = lappend($1, $3); }
359368
| NOT_P '.' key_any { $$ = lappend(lappend(NIL, makeItemKey(&$1)), $3); }
360369
;

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy