Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit d57758a

Browse filesBrowse files
author
Nikita Glukhov
committed
fixup! add array/object length as @#
1 parent c624498 commit d57758a
Copy full SHA for d57758a

File tree

3 files changed

+115
-106
lines changed
Filter options

3 files changed

+115
-106
lines changed

‎expected/jsquery.out

Copy file name to clipboardExpand all lines: expected/jsquery.out
+24Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1391,6 +1391,30 @@ select '{"a":[1,2]}' @@ '@# = 1'::jsquery;
13911391
t
13921392
(1 row)
13931393

1394+
select '[]' @@ '@# is numeric'::jsquery;
1395+
?column?
1396+
----------
1397+
t
1398+
(1 row)
1399+
1400+
select '{}' @@ '@# is numeric'::jsquery;
1401+
?column?
1402+
----------
1403+
t
1404+
(1 row)
1405+
1406+
select '0' @@ '@# is numeric'::jsquery;
1407+
?column?
1408+
----------
1409+
f
1410+
(1 row)
1411+
1412+
select '0' @@ '@# = 1'::jsquery;
1413+
?column?
1414+
----------
1415+
f
1416+
(1 row)
1417+
13941418
--ALL
13951419
select 'a.*: = 4'::jsquery;
13961420
jsquery

‎jsquery_op.c

Copy file name to clipboardExpand all lines: jsquery_op.c
+87-106Lines changed: 87 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929

3030
#include "jsquery.h"
3131

32-
static bool recursiveExecute(JsQueryItem *jsq, JsonbValue *jb, JsQueryItem *jsqLeftArg);
32+
static bool recursiveExecute(JsQueryItem *jsq, JsonbValue *jb);
3333

3434
static int
3535
compareNumeric(Numeric a, Numeric b)
@@ -59,6 +59,43 @@ JsonbType(JsonbValue *jb)
5959
return type;
6060
}
6161

62+
static JsonbValue *
63+
JsonbSize(JsonbValue *jb, JsonbValue *size)
64+
{
65+
JsonbValue v;
66+
JsonbIterator *it;
67+
JsonbIteratorToken r;
68+
int32 length;
69+
int type = JsonbType(jb);
70+
71+
if (type != jbvArray && type != jbvObject)
72+
return NULL;
73+
74+
Assert(jb->type == jbvBinary);
75+
76+
it = JsonbIteratorInit(jb->val.binary.data);
77+
r = JsonbIteratorNext(&it, &v, true);
78+
Assert(r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT);
79+
80+
if (r == WJB_BEGIN_ARRAY)
81+
{
82+
length = v.val.array.nElems;
83+
if (length < 0)
84+
length = JsonGetArraySize(jb->val.binary.data);
85+
}
86+
else
87+
{
88+
length = v.val.object.nPairs;
89+
if (length < 0)
90+
length = JsonGetObjectSize(jb->val.binary.data);
91+
}
92+
93+
size->type = jbvNumeric;
94+
size->val.numeric = DatumGetNumeric(DirectFunctionCall1(
95+
int4_numeric, Int32GetDatum(length)));
96+
return size;
97+
}
98+
6299
static bool
63100
recursiveAny(JsQueryItem *jsq, JsonbValue *jb)
64101
{
@@ -81,7 +118,7 @@ recursiveAny(JsQueryItem *jsq, JsonbValue *jb)
81118

82119
if (r == WJB_VALUE || r == WJB_ELEM)
83120
{
84-
res = recursiveExecute(jsq, &v, NULL);
121+
res = recursiveExecute(jsq, &v);
85122

86123
if (res == false && v.type == jbvBinary)
87124
res = recursiveAny(jsq, &v);
@@ -113,7 +150,7 @@ recursiveAll(JsQueryItem *jsq, JsonbValue *jb)
113150

114151
if (r == WJB_VALUE || r == WJB_ELEM)
115152
{
116-
if ((res = recursiveExecute(jsq, &v, NULL)) == true)
153+
if ((res = recursiveExecute(jsq, &v)) == true)
117154
{
118155
if (v.type == jbvBinary)
119156
res = recursiveAll(jsq, &v);
@@ -312,7 +349,7 @@ makeCompare(JsQueryItem *jsq, int32 op, JsonbValue *jb)
312349
}
313350

314351
static bool
315-
executeExpr(JsQueryItem *jsq, int32 op, JsonbValue *jb, JsQueryItem *jsqLeftArg)
352+
executeExpr(JsQueryItem *jsq, int32 op, JsonbValue *jb)
316353
{
317354
bool res = false;
318355
/*
@@ -322,100 +359,37 @@ executeExpr(JsQueryItem *jsq, int32 op, JsonbValue *jb, JsQueryItem *jsqLeftArg)
322359
Assert(jsq->type == jqiAny || jsq->type == jqiString || jsq->type == jqiNumeric ||
323360
jsq->type == jqiNull || jsq->type == jqiBool || jsq->type == jqiArray);
324361

325-
if (jsqLeftArg && jsqLeftArg->type == jqiLength)
362+
switch(op)
326363
{
327-
if (JsonbType(jb) == jbvArray || JsonbType(jb) == jbvObject)
328-
{
329-
int32 length;
330-
JsonbIterator *it;
331-
JsonbValue v;
332-
int r;
333-
334-
it = JsonbIteratorInit(jb->val.binary.data);
335-
r = JsonbIteratorNext(&it, &v, true);
336-
Assert(r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT);
337-
338-
if (r == WJB_BEGIN_ARRAY)
339-
{
340-
length = v.val.array.nElems;
341-
342-
if (length < 0)
343-
length = JsonGetArraySize(jb->val.binary.data);
344-
}
364+
case jqiEqual:
365+
if (JsonbType(jb) == jbvArray && jsq->type == jqiArray)
366+
res = checkArrayEquality(jsq, jb);
345367
else
346-
{
347-
length = v.val.object.nPairs;
348-
349-
if (length < 0)
350-
{
351-
length = 0;
352-
353-
while ((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
354-
{
355-
if (r == WJB_KEY)
356-
length++;
357-
}
358-
}
359-
}
360-
361-
v.type = jbvNumeric;
362-
v.val.numeric = DatumGetNumeric(DirectFunctionCall1(int4_numeric, Int32GetDatum(length)));
363-
364-
switch(op)
365-
{
366-
case jqiEqual:
367-
case jqiLess:
368-
case jqiGreater:
369-
case jqiLessOrEqual:
370-
case jqiGreaterOrEqual:
371-
res = makeCompare(jsq, op, &v);
372-
break;
373-
case jqiIn:
374-
res = checkScalarIn(jsq, &v);
375-
break;
376-
case jqiOverlap:
377-
case jqiContains:
378-
case jqiContained:
379-
break;
380-
default:
381-
elog(ERROR, "Unknown operation");
382-
}
383-
}
384-
}
385-
else
386-
{
387-
switch(op)
388-
{
389-
case jqiEqual:
390-
if (JsonbType(jb) == jbvArray && jsq->type == jqiArray)
391-
res = checkArrayEquality(jsq, jb);
392-
else
393-
res = checkScalarEquality(jsq, jb);
394-
break;
395-
case jqiIn:
396-
res = checkScalarIn(jsq, jb);
397-
break;
398-
case jqiOverlap:
399-
case jqiContains:
400-
case jqiContained:
401-
res = executeArrayOp(jsq, op, jb);
402-
break;
403-
case jqiLess:
404-
case jqiGreater:
405-
case jqiLessOrEqual:
406-
case jqiGreaterOrEqual:
407-
res = makeCompare(jsq, op, jb);
408-
break;
409-
default:
410-
elog(ERROR, "Unknown operation");
411-
}
368+
res = checkScalarEquality(jsq, jb);
369+
break;
370+
case jqiIn:
371+
res = checkScalarIn(jsq, jb);
372+
break;
373+
case jqiOverlap:
374+
case jqiContains:
375+
case jqiContained:
376+
res = executeArrayOp(jsq, op, jb);
377+
break;
378+
case jqiLess:
379+
case jqiGreater:
380+
case jqiLessOrEqual:
381+
case jqiGreaterOrEqual:
382+
res = makeCompare(jsq, op, jb);
383+
break;
384+
default:
385+
elog(ERROR, "Unknown operation");
412386
}
413387

414388
return res;
415389
}
416390

417391
static bool
418-
recursiveExecute(JsQueryItem *jsq, JsonbValue *jb, JsQueryItem *jsqLeftArg)
392+
recursiveExecute(JsQueryItem *jsq, JsonbValue *jb)
419393
{
420394
JsQueryItem elem;
421395
bool res = false;
@@ -425,25 +399,25 @@ recursiveExecute(JsQueryItem *jsq, JsonbValue *jb, JsQueryItem *jsqLeftArg)
425399
switch(jsq->type) {
426400
case jqiAnd:
427401
jsqGetLeftArg(jsq, &elem);
428-
res = recursiveExecute(&elem, jb, jsqLeftArg);
402+
res = recursiveExecute(&elem, jb);
429403
if (res == true)
430404
{
431405
jsqGetRightArg(jsq, &elem);
432-
res = recursiveExecute(&elem, jb, jsqLeftArg);
406+
res = recursiveExecute(&elem, jb);
433407
}
434408
break;
435409
case jqiOr:
436410
jsqGetLeftArg(jsq, &elem);
437-
res = recursiveExecute(&elem, jb, jsqLeftArg);
411+
res = recursiveExecute(&elem, jb);
438412
if (res == false)
439413
{
440414
jsqGetRightArg(jsq, &elem);
441-
res = recursiveExecute(&elem, jb, jsqLeftArg);
415+
res = recursiveExecute(&elem, jb);
442416
}
443417
break;
444418
case jqiNot:
445419
jsqGetArg(jsq, &elem);
446-
res = !recursiveExecute(&elem, jb, jsqLeftArg);
420+
res = !recursiveExecute(&elem, jb);
447421
break;
448422
case jqiKey:
449423
if (JsonbType(jb) == jbvObject) {
@@ -457,7 +431,7 @@ recursiveExecute(JsQueryItem *jsq, JsonbValue *jb, JsQueryItem *jsqLeftArg)
457431
if (v != NULL)
458432
{
459433
jsqGetNext(jsq, &elem);
460-
res = recursiveExecute(&elem, v, NULL);
434+
res = recursiveExecute(&elem, v);
461435
pfree(v);
462436
}
463437
}
@@ -480,23 +454,23 @@ recursiveExecute(JsQueryItem *jsq, JsonbValue *jb, JsQueryItem *jsqLeftArg)
480454
r = JsonbIteratorNext(&it, &v, true);
481455
Assert(r == WJB_ELEM);
482456

483-
res = recursiveExecute(&elem, &v, jsqLeftArg);
457+
res = recursiveExecute(&elem, &v);
484458
}
485459
else
486460
{
487-
res = recursiveExecute(&elem, jb, jsqLeftArg);
461+
res = recursiveExecute(&elem, jb);
488462
}
489463
break;
490464
case jqiAny:
491465
jsqGetNext(jsq, &elem);
492-
if (recursiveExecute(&elem, jb, NULL))
466+
if (recursiveExecute(&elem, jb))
493467
res = true;
494468
else if (jb->type == jbvBinary)
495469
res = recursiveAny(&elem, jb);
496470
break;
497471
case jqiAll:
498472
jsqGetNext(jsq, &elem);
499-
if ((res = recursiveExecute(&elem, jb, NULL)) == true)
473+
if ((res = recursiveExecute(&elem, jb)) == true)
500474
{
501475
if (jb->type == jbvBinary)
502476
res = recursiveAll(&elem, jb);
@@ -520,7 +494,7 @@ recursiveExecute(JsQueryItem *jsq, JsonbValue *jb, JsQueryItem *jsqLeftArg)
520494
{
521495
if (r == WJB_ELEM)
522496
{
523-
res = recursiveExecute(&elem, &v, NULL);
497+
res = recursiveExecute(&elem, &v);
524498

525499
if (jsq->type == jqiAnyArray)
526500
{
@@ -554,7 +528,7 @@ recursiveExecute(JsQueryItem *jsq, JsonbValue *jb, JsQueryItem *jsqLeftArg)
554528
{
555529
if (r == WJB_VALUE)
556530
{
557-
res = recursiveExecute(&elem, &v, NULL);
531+
res = recursiveExecute(&elem, &v);
558532

559533
if (jsq->type == jqiAnyKey)
560534
{
@@ -580,12 +554,19 @@ recursiveExecute(JsQueryItem *jsq, JsonbValue *jb, JsQueryItem *jsqLeftArg)
580554
case jqiContained:
581555
case jqiOverlap:
582556
jsqGetArg(jsq, &elem);
583-
res = executeExpr(&elem, jsq->type, jb, jsqLeftArg);
557+
res = executeExpr(&elem, jsq->type, jb);
584558
break;
585559
case jqiLength:
560+
{
561+
JsonbValue size;
586562
jsqGetNext(jsq, &elem);
587-
res = recursiveExecute(&elem, jb, jsq);
563+
if (JsonbSize(jb, &size))
564+
{
565+
res = recursiveExecute(&elem, &size);
566+
pfree(size.val.numeric);
567+
}
588568
break;
569+
}
589570
case jqiIs:
590571
if (JsonbType(jb) == jbvScalar)
591572
{
@@ -631,7 +612,7 @@ jsquery_json_exec(PG_FUNCTION_ARGS)
631612

632613
jsqInit(&jsq, jq);
633614

634-
res = recursiveExecute(&jsq, &jbv, NULL);
615+
res = recursiveExecute(&jsq, &jbv);
635616

636617
PG_FREE_IF_COPY(jq, 0);
637618
PG_FREE_IF_COPY_JSONB(jb, 1);
@@ -653,7 +634,7 @@ json_jsquery_exec(PG_FUNCTION_ARGS)
653634

654635
jsqInit(&jsq, jq);
655636

656-
res = recursiveExecute(&jsq, &jbv, NULL);
637+
res = recursiveExecute(&jsq, &jbv);
657638

658639
PG_FREE_IF_COPY_JSONB(jb, 0);
659640
PG_FREE_IF_COPY(jq, 1);

‎sql/jsquery.sql

Copy file name to clipboardExpand all lines: sql/jsquery.sql
+4Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,10 @@ select '{"a":[1,2]}' @@ '%.@# in (2, 4)'::jsquery;
283283
select '{"a":[1,2]}' @@ '*.@# in (2, 4)'::jsquery;
284284
select '{"a":[1,2]}' @@ '*.@# ($ = 4 or $ = 2)'::jsquery;
285285
select '{"a":[1,2]}' @@ '@# = 1'::jsquery;
286+
select '[]' @@ '@# is numeric'::jsquery;
287+
select '{}' @@ '@# is numeric'::jsquery;
288+
select '0' @@ '@# is numeric'::jsquery;
289+
select '0' @@ '@# = 1'::jsquery;
286290

287291
--ALL
288292
select 'a.*: = 4'::jsquery;

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.