Skip to content

Commit 94fe153

Browse files
committed
add array/object length as @#
1 parent 7ac0ce5 commit 94fe153

7 files changed

+318
-54
lines changed

expected/jsquery.out

+159
Original file line numberDiff line numberDiff line change
@@ -1238,6 +1238,153 @@ select 'a = /* noindex */ 5'::jsquery;
12381238
"a" = 5
12391239
(1 row)
12401240

1241+
--LENGTH
1242+
select 'a.@# = 4'::jsquery;
1243+
jsquery
1244+
------------
1245+
"a".@# = 4
1246+
(1 row)
1247+
1248+
select 'a.@#.$ = 4'::jsquery as noerror;
1249+
noerror
1250+
--------------
1251+
"a".@#.$ = 4
1252+
(1 row)
1253+
1254+
select 'a.@#.a = 4'::jsquery as error;
1255+
ERROR: Array length should be last in path
1256+
LINE 1: select 'a.@#.a = 4'::jsquery as error;
1257+
^
1258+
select 'a.@#.* = 4'::jsquery as error;
1259+
ERROR: Array length should be last in path
1260+
LINE 1: select 'a.@#.* = 4'::jsquery as error;
1261+
^
1262+
select 'a.@#.% = 4'::jsquery as error;
1263+
ERROR: Array length should be last in path
1264+
LINE 1: select 'a.@#.% = 4'::jsquery as error;
1265+
^
1266+
select 'a.@#.# = 4'::jsquery as error;
1267+
ERROR: Array length should be last in path
1268+
LINE 1: select 'a.@#.# = 4'::jsquery as error;
1269+
^
1270+
select 'a.@#.*: = 4'::jsquery as error;
1271+
ERROR: Array length should be last in path
1272+
LINE 1: select 'a.@#.*: = 4'::jsquery as error;
1273+
^
1274+
select 'a.@#.%: = 4'::jsquery as error;
1275+
ERROR: Array length should be last in path
1276+
LINE 1: select 'a.@#.%: = 4'::jsquery as error;
1277+
^
1278+
select 'a.@#.#: = 4'::jsquery as error;
1279+
ERROR: Array length should be last in path
1280+
LINE 1: select 'a.@#.#: = 4'::jsquery as error;
1281+
^
1282+
select 'a.@# (a = 5 or b = 6)'::jsquery as error;
1283+
ERROR: Array length should be last in path
1284+
LINE 1: select 'a.@# (a = 5 or b = 6)'::jsquery as error;
1285+
^
1286+
select '[]' @@ '@# = 0'::jsquery;
1287+
?column?
1288+
----------
1289+
t
1290+
(1 row)
1291+
1292+
select '[]' @@ '@# < 2'::jsquery;
1293+
?column?
1294+
----------
1295+
t
1296+
(1 row)
1297+
1298+
select '[]' @@ '@# > 1'::jsquery;
1299+
?column?
1300+
----------
1301+
f
1302+
(1 row)
1303+
1304+
select '[1]' @@ '@# = 0'::jsquery;
1305+
?column?
1306+
----------
1307+
f
1308+
(1 row)
1309+
1310+
select '[1]' @@ '@# < 2'::jsquery;
1311+
?column?
1312+
----------
1313+
t
1314+
(1 row)
1315+
1316+
select '[1]' @@ '@# > 1'::jsquery;
1317+
?column?
1318+
----------
1319+
f
1320+
(1 row)
1321+
1322+
select '[1,2]' @@ '@# = 0'::jsquery;
1323+
?column?
1324+
----------
1325+
f
1326+
(1 row)
1327+
1328+
select '[1,2]' @@ '@# < 2'::jsquery;
1329+
?column?
1330+
----------
1331+
f
1332+
(1 row)
1333+
1334+
select '[1,2]' @@ '@# > 1'::jsquery;
1335+
?column?
1336+
----------
1337+
t
1338+
(1 row)
1339+
1340+
select '[1,2]' @@ '@# in (1, 2)'::jsquery;
1341+
?column?
1342+
----------
1343+
t
1344+
(1 row)
1345+
1346+
select '[1,2]' @@ '@# in (1, 3)'::jsquery;
1347+
?column?
1348+
----------
1349+
f
1350+
(1 row)
1351+
1352+
select '{"a":[1,2]}' @@ '@# in (2, 4)'::jsquery;
1353+
?column?
1354+
----------
1355+
f
1356+
(1 row)
1357+
1358+
select '{"a":[1,2]}' @@ 'a.@# in (2, 4)'::jsquery;
1359+
?column?
1360+
----------
1361+
t
1362+
(1 row)
1363+
1364+
select '{"a":[1,2]}' @@ '%.@# in (2, 4)'::jsquery;
1365+
?column?
1366+
----------
1367+
t
1368+
(1 row)
1369+
1370+
select '{"a":[1,2]}' @@ '*.@# in (2, 4)'::jsquery;
1371+
?column?
1372+
----------
1373+
t
1374+
(1 row)
1375+
1376+
select '{"a":[1,2]}' @@ '*.@# ($ = 4 or $ = 2)'::jsquery;
1377+
?column?
1378+
----------
1379+
t
1380+
(1 row)
1381+
1382+
select '{"a":[1,2]}' @@ '@# = 1'::jsquery;
1383+
?column?
1384+
----------
1385+
t
1386+
(1 row)
1387+
12411388
--ALL
12421389
select 'a.*: = 4'::jsquery;
12431390
jsquery
@@ -1449,6 +1596,18 @@ select '{"a":{"aa":1}, "b":{"aa":1, "bb":2}}' @@ '*: (not $ is object or $.aa is
14491596
t
14501597
(1 row)
14511598

1599+
select '[]' @@ '(@# > 0 and #: = 16)'::jsquery;
1600+
?column?
1601+
----------
1602+
f
1603+
(1 row)
1604+
1605+
select '[16]' @@ '(@# > 0 and #: = 16)'::jsquery;
1606+
?column?
1607+
----------
1608+
t
1609+
(1 row)
1610+
14521611
--extract entries for index scan
14531612
SELECT gin_debug_query_path_value('NOT NOT NOT x(y(NOT (a=1) and NOT (b=2)) OR NOT NOT (c=3)) and z = 5');
14541613
gin_debug_query_path_value

jsquery.h

+1
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ typedef enum JsQueryItemType {
5454
jqiAllKey,
5555
jqiKey,
5656
jqiCurrent,
57+
jqiLength,
5758
jqiIn,
5859
jqiIs
5960
} JsQueryItemType;

jsquery_gram.y

+1
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,7 @@ key:
310310
| '#' ':' { $$ = makeItemType(jqiAllArray); }
311311
| '%' ':' { $$ = makeItemType(jqiAllKey); }
312312
| '$' { $$ = makeItemType(jqiCurrent); }
313+
| '@' '#' { $$ = makeItemType(jqiLength); }
313314
| STRING_P { $$ = makeItemKey(&$1); }
314315
| IN_P { $$ = makeItemKey(&$1); }
315316
| IS_P { $$ = makeItemKey(&$1); }

jsquery_io.c

+24-11
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
PG_MODULE_MAGIC;
2424

2525
static int
26-
flattenJsQueryParseItem(StringInfo buf, JsQueryParseItem *item)
26+
flattenJsQueryParseItem(StringInfo buf, JsQueryParseItem *item, bool onlyCurrentInPath)
2727
{
2828
int32 pos = buf->len - VARHDRSZ; /* position from begining of jsquery data */
2929
int32 chld, next;
@@ -42,6 +42,8 @@ flattenJsQueryParseItem(StringInfo buf, JsQueryParseItem *item)
4242
switch(item->type)
4343
{
4444
case jqiKey:
45+
if (onlyCurrentInPath)
46+
elog(ERROR,"Array length should be last in path");
4547
case jqiString:
4648
appendBinaryStringInfo(buf, (char*)&item->string.len, sizeof(item->string.len));
4749
appendBinaryStringInfo(buf, item->string.val, item->string.len);
@@ -69,7 +71,7 @@ flattenJsQueryParseItem(StringInfo buf, JsQueryParseItem *item)
6971

7072
for(i=0; i<item->array.nelems; i++)
7173
{
72-
chld = flattenJsQueryParseItem(buf, item->array.elems[i]);
74+
chld = flattenJsQueryParseItem(buf, item->array.elems[i], onlyCurrentInPath);
7375
*(int32*)(buf->data + arrayStart + i * sizeof(i)) = chld;
7476
}
7577

@@ -85,9 +87,9 @@ flattenJsQueryParseItem(StringInfo buf, JsQueryParseItem *item)
8587
right = buf->len;
8688
appendBinaryStringInfo(buf, (char*)&right /* fake value */, sizeof(right));
8789

88-
chld = flattenJsQueryParseItem(buf, item->args.left);
90+
chld = flattenJsQueryParseItem(buf, item->args.left, onlyCurrentInPath);
8991
*(int32*)(buf->data + left) = chld;
90-
chld = flattenJsQueryParseItem(buf, item->args.right);
92+
chld = flattenJsQueryParseItem(buf, item->args.right, onlyCurrentInPath);
9193
*(int32*)(buf->data + right) = chld;
9294
}
9395
break;
@@ -107,25 +109,30 @@ flattenJsQueryParseItem(StringInfo buf, JsQueryParseItem *item)
107109
arg = buf->len;
108110
appendBinaryStringInfo(buf, (char*)&arg /* fake value */, sizeof(arg));
109111

110-
chld = flattenJsQueryParseItem(buf, item->arg);
112+
chld = flattenJsQueryParseItem(buf, item->arg, onlyCurrentInPath);
111113
*(int32*)(buf->data + arg) = chld;
112114
}
113115
break;
114-
case jqiNull:
115-
case jqiCurrent:
116116
case jqiAny:
117117
case jqiAnyArray:
118118
case jqiAnyKey:
119119
case jqiAll:
120120
case jqiAllArray:
121121
case jqiAllKey:
122+
if (onlyCurrentInPath)
123+
elog(ERROR,"Array length should be last in path");
124+
case jqiCurrent:
125+
case jqiNull:
126+
break;
127+
case jqiLength:
128+
onlyCurrentInPath = true;
122129
break;
123130
default:
124131
elog(ERROR, "Unknown type: %d", item->type);
125132
}
126133

127134
if (item->next)
128-
*(int32*)(buf->data + next) = flattenJsQueryParseItem(buf, item->next);
135+
*(int32*)(buf->data + next) = flattenJsQueryParseItem(buf, item->next, onlyCurrentInPath);
129136

130137
return pos;
131138
}
@@ -137,8 +144,8 @@ jsquery_in(PG_FUNCTION_ARGS)
137144
char *in = PG_GETARG_CSTRING(0);
138145
int32 len = strlen(in);
139146
JsQueryParseItem *jsquery = parsejsquery(in, len);
140-
JsQuery *res;
141-
StringInfoData buf;
147+
JsQuery *res;
148+
StringInfoData buf;
142149

143150
initStringInfo(&buf);
144151
enlargeStringInfo(&buf, 4 * len /* estimation */);
@@ -147,7 +154,7 @@ jsquery_in(PG_FUNCTION_ARGS)
147154

148155
if (jsquery != NULL)
149156
{
150-
flattenJsQueryParseItem(&buf, jsquery);
157+
flattenJsQueryParseItem(&buf, jsquery, false);
151158

152159
res = (JsQuery*)buf.data;
153160
SET_VARSIZE(res, buf.len);
@@ -318,6 +325,12 @@ printJsQueryItem(StringInfo buf, JsQueryItem *v, bool inKey, bool printBracketes
318325
appendStringInfoChar(buf, '.');
319326
appendStringInfoChar(buf, '$');
320327
break;
328+
case jqiLength:
329+
if (inKey)
330+
appendStringInfoChar(buf, '.');
331+
appendStringInfoChar(buf, '@');
332+
appendStringInfoChar(buf, '#');
333+
break;
321334
case jqiAny:
322335
if (inKey)
323336
appendStringInfoChar(buf, '.');

0 commit comments

Comments
 (0)