29
29
30
30
#include "jsquery.h"
31
31
32
- static bool recursiveExecute (JsQueryItem * jsq , JsonbValue * jb , JsQueryItem * jsqLeftArg );
32
+ static bool recursiveExecute (JsQueryItem * jsq , JsonbValue * jb );
33
33
34
34
static int
35
35
compareNumeric (Numeric a , Numeric b )
@@ -59,6 +59,43 @@ JsonbType(JsonbValue *jb)
59
59
return type ;
60
60
}
61
61
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
+
62
99
static bool
63
100
recursiveAny (JsQueryItem * jsq , JsonbValue * jb )
64
101
{
@@ -81,7 +118,7 @@ recursiveAny(JsQueryItem *jsq, JsonbValue *jb)
81
118
82
119
if (r == WJB_VALUE || r == WJB_ELEM )
83
120
{
84
- res = recursiveExecute (jsq , & v , NULL );
121
+ res = recursiveExecute (jsq , & v );
85
122
86
123
if (res == false && v .type == jbvBinary )
87
124
res = recursiveAny (jsq , & v );
@@ -113,7 +150,7 @@ recursiveAll(JsQueryItem *jsq, JsonbValue *jb)
113
150
114
151
if (r == WJB_VALUE || r == WJB_ELEM )
115
152
{
116
- if ((res = recursiveExecute (jsq , & v , NULL )) == true)
153
+ if ((res = recursiveExecute (jsq , & v )) == true)
117
154
{
118
155
if (v .type == jbvBinary )
119
156
res = recursiveAll (jsq , & v );
@@ -312,7 +349,7 @@ makeCompare(JsQueryItem *jsq, int32 op, JsonbValue *jb)
312
349
}
313
350
314
351
static bool
315
- executeExpr (JsQueryItem * jsq , int32 op , JsonbValue * jb , JsQueryItem * jsqLeftArg )
352
+ executeExpr (JsQueryItem * jsq , int32 op , JsonbValue * jb )
316
353
{
317
354
bool res = false;
318
355
/*
@@ -322,100 +359,37 @@ executeExpr(JsQueryItem *jsq, int32 op, JsonbValue *jb, JsQueryItem *jsqLeftArg)
322
359
Assert (jsq -> type == jqiAny || jsq -> type == jqiString || jsq -> type == jqiNumeric ||
323
360
jsq -> type == jqiNull || jsq -> type == jqiBool || jsq -> type == jqiArray );
324
361
325
- if ( jsqLeftArg && jsqLeftArg -> type == jqiLength )
362
+ switch ( op )
326
363
{
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 );
345
367
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" );
412
386
}
413
387
414
388
return res ;
415
389
}
416
390
417
391
static bool
418
- recursiveExecute (JsQueryItem * jsq , JsonbValue * jb , JsQueryItem * jsqLeftArg )
392
+ recursiveExecute (JsQueryItem * jsq , JsonbValue * jb )
419
393
{
420
394
JsQueryItem elem ;
421
395
bool res = false;
@@ -425,25 +399,25 @@ recursiveExecute(JsQueryItem *jsq, JsonbValue *jb, JsQueryItem *jsqLeftArg)
425
399
switch (jsq -> type ) {
426
400
case jqiAnd :
427
401
jsqGetLeftArg (jsq , & elem );
428
- res = recursiveExecute (& elem , jb , jsqLeftArg );
402
+ res = recursiveExecute (& elem , jb );
429
403
if (res == true)
430
404
{
431
405
jsqGetRightArg (jsq , & elem );
432
- res = recursiveExecute (& elem , jb , jsqLeftArg );
406
+ res = recursiveExecute (& elem , jb );
433
407
}
434
408
break ;
435
409
case jqiOr :
436
410
jsqGetLeftArg (jsq , & elem );
437
- res = recursiveExecute (& elem , jb , jsqLeftArg );
411
+ res = recursiveExecute (& elem , jb );
438
412
if (res == false)
439
413
{
440
414
jsqGetRightArg (jsq , & elem );
441
- res = recursiveExecute (& elem , jb , jsqLeftArg );
415
+ res = recursiveExecute (& elem , jb );
442
416
}
443
417
break ;
444
418
case jqiNot :
445
419
jsqGetArg (jsq , & elem );
446
- res = !recursiveExecute (& elem , jb , jsqLeftArg );
420
+ res = !recursiveExecute (& elem , jb );
447
421
break ;
448
422
case jqiKey :
449
423
if (JsonbType (jb ) == jbvObject ) {
@@ -457,7 +431,7 @@ recursiveExecute(JsQueryItem *jsq, JsonbValue *jb, JsQueryItem *jsqLeftArg)
457
431
if (v != NULL )
458
432
{
459
433
jsqGetNext (jsq , & elem );
460
- res = recursiveExecute (& elem , v , NULL );
434
+ res = recursiveExecute (& elem , v );
461
435
pfree (v );
462
436
}
463
437
}
@@ -480,23 +454,23 @@ recursiveExecute(JsQueryItem *jsq, JsonbValue *jb, JsQueryItem *jsqLeftArg)
480
454
r = JsonbIteratorNext (& it , & v , true);
481
455
Assert (r == WJB_ELEM );
482
456
483
- res = recursiveExecute (& elem , & v , jsqLeftArg );
457
+ res = recursiveExecute (& elem , & v );
484
458
}
485
459
else
486
460
{
487
- res = recursiveExecute (& elem , jb , jsqLeftArg );
461
+ res = recursiveExecute (& elem , jb );
488
462
}
489
463
break ;
490
464
case jqiAny :
491
465
jsqGetNext (jsq , & elem );
492
- if (recursiveExecute (& elem , jb , NULL ))
466
+ if (recursiveExecute (& elem , jb ))
493
467
res = true;
494
468
else if (jb -> type == jbvBinary )
495
469
res = recursiveAny (& elem , jb );
496
470
break ;
497
471
case jqiAll :
498
472
jsqGetNext (jsq , & elem );
499
- if ((res = recursiveExecute (& elem , jb , NULL )) == true)
473
+ if ((res = recursiveExecute (& elem , jb )) == true)
500
474
{
501
475
if (jb -> type == jbvBinary )
502
476
res = recursiveAll (& elem , jb );
@@ -520,7 +494,7 @@ recursiveExecute(JsQueryItem *jsq, JsonbValue *jb, JsQueryItem *jsqLeftArg)
520
494
{
521
495
if (r == WJB_ELEM )
522
496
{
523
- res = recursiveExecute (& elem , & v , NULL );
497
+ res = recursiveExecute (& elem , & v );
524
498
525
499
if (jsq -> type == jqiAnyArray )
526
500
{
@@ -554,7 +528,7 @@ recursiveExecute(JsQueryItem *jsq, JsonbValue *jb, JsQueryItem *jsqLeftArg)
554
528
{
555
529
if (r == WJB_VALUE )
556
530
{
557
- res = recursiveExecute (& elem , & v , NULL );
531
+ res = recursiveExecute (& elem , & v );
558
532
559
533
if (jsq -> type == jqiAnyKey )
560
534
{
@@ -580,12 +554,19 @@ recursiveExecute(JsQueryItem *jsq, JsonbValue *jb, JsQueryItem *jsqLeftArg)
580
554
case jqiContained :
581
555
case jqiOverlap :
582
556
jsqGetArg (jsq , & elem );
583
- res = executeExpr (& elem , jsq -> type , jb , jsqLeftArg );
557
+ res = executeExpr (& elem , jsq -> type , jb );
584
558
break ;
585
559
case jqiLength :
560
+ {
561
+ JsonbValue size ;
586
562
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
+ }
588
568
break ;
569
+ }
589
570
case jqiIs :
590
571
if (JsonbType (jb ) == jbvScalar )
591
572
{
@@ -631,7 +612,7 @@ jsquery_json_exec(PG_FUNCTION_ARGS)
631
612
632
613
jsqInit (& jsq , jq );
633
614
634
- res = recursiveExecute (& jsq , & jbv , NULL );
615
+ res = recursiveExecute (& jsq , & jbv );
635
616
636
617
PG_FREE_IF_COPY (jq , 0 );
637
618
PG_FREE_IF_COPY_JSONB (jb , 1 );
@@ -653,7 +634,7 @@ json_jsquery_exec(PG_FUNCTION_ARGS)
653
634
654
635
jsqInit (& jsq , jq );
655
636
656
- res = recursiveExecute (& jsq , & jbv , NULL );
637
+ res = recursiveExecute (& jsq , & jbv );
657
638
658
639
PG_FREE_IF_COPY_JSONB (jb , 0 );
659
640
PG_FREE_IF_COPY (jq , 1 );
0 commit comments