@@ -305,19 +305,24 @@ makePathItem(PathItemType type, PathItem *parent)
305
305
typedef struct ExtractedJsonPath
306
306
{
307
307
PathItem * path ;
308
+ List * filters ;
308
309
bool indirect ;
309
310
bool type ;
310
311
} ExtractedJsonPath ;
311
312
312
313
static bool
313
314
recursiveExtractJsonPath (JsonPathItem * jpi ,
314
315
bool lax , bool not , bool indirect , bool unwrap ,
315
- PathItem * parent , List * * paths );
316
+ PathItem * parent , List * * paths , List * filters );
317
+
318
+ static ExtractedNode *
319
+ recursiveExtractJsonPathExpr (JsonPathItem * jpi , bool lax , bool not ,
320
+ PathItem * path );
316
321
317
322
static bool
318
323
recursiveExtractJsonPath2 (JsonPathItem * jpi ,
319
324
bool lax , bool not , bool indirect , bool unwrap ,
320
- PathItem * parent , List * * paths )
325
+ PathItem * parent , List * * paths , List * filters )
321
326
{
322
327
JsonPathItem next ;
323
328
PathItem * path ;
@@ -373,6 +378,24 @@ recursiveExtractJsonPath2(JsonPathItem *jpi,
373
378
indirect = true;
374
379
break ;
375
380
381
+ case jpiFilter :
382
+ {
383
+ JsonPathItem arg ;
384
+ ExtractedNode * expr ;
385
+
386
+ if (not )
387
+ return false;
388
+
389
+ jspGetArg (jpi , & arg );
390
+ expr = recursiveExtractJsonPathExpr (& arg , lax , not , parent );
391
+
392
+ if (expr )
393
+ filters = lappend (list_copy (filters ), expr );
394
+
395
+ path = parent ;
396
+ break ;
397
+ }
398
+
376
399
default :
377
400
/* elog(ERROR,"Wrong state: %d", jpi->type); */
378
401
return false;
@@ -384,6 +407,7 @@ recursiveExtractJsonPath2(JsonPathItem *jpi,
384
407
ExtractedJsonPath * ejp = palloc (sizeof (* ejp ));
385
408
386
409
ejp -> path = path ;
410
+ ejp -> filters = filters ;
387
411
ejp -> indirect = indirect ;
388
412
ejp -> type = jspHasNext (jpi ) && next .type == jpiType ;
389
413
@@ -394,6 +418,7 @@ recursiveExtractJsonPath2(JsonPathItem *jpi,
394
418
{
395
419
ejp = palloc (sizeof (* ejp ));
396
420
ejp -> path = makePathItem (iAnyArray , path );
421
+ ejp -> filters = filters ;
397
422
ejp -> indirect = indirect ;
398
423
ejp -> type = false;
399
424
@@ -404,13 +429,13 @@ recursiveExtractJsonPath2(JsonPathItem *jpi,
404
429
}
405
430
406
431
return recursiveExtractJsonPath (& next , lax , not , indirect , unwrap , path ,
407
- paths );
432
+ paths , filters );
408
433
}
409
434
410
435
static bool
411
436
recursiveExtractJsonPath (JsonPathItem * jpi ,
412
437
bool lax , bool not , bool indirect , bool unwrap ,
413
- PathItem * parent , List * * paths )
438
+ PathItem * parent , List * * paths , List * filters )
414
439
{
415
440
switch (jpi -> type )
416
441
{
@@ -430,13 +455,14 @@ recursiveExtractJsonPath(JsonPathItem *jpi,
430
455
ExtractedJsonPath * ejp = palloc (sizeof (* ejp ));
431
456
432
457
ejp -> path = parent ;
458
+ ejp -> filters = filters ;
433
459
ejp -> indirect = indirect ;
434
460
ejp -> type = false;
435
461
436
462
* paths = lappend (* paths , ejp );
437
463
}
438
464
else if (!recursiveExtractJsonPath2 (& next , lax , not , indirect , unwrap ,
439
- parent , paths ))
465
+ parent , paths , filters ))
440
466
return false;
441
467
}
442
468
@@ -448,7 +474,7 @@ recursiveExtractJsonPath(JsonPathItem *jpi,
448
474
if (lax &&
449
475
!recursiveExtractJsonPath2 (jpi , lax , not , true, unwrap ,
450
476
makePathItem (iAnyArray , parent ),
451
- paths ))
477
+ paths , filters ))
452
478
return false;
453
479
break ;
454
480
@@ -457,7 +483,7 @@ recursiveExtractJsonPath(JsonPathItem *jpi,
457
483
}
458
484
459
485
return recursiveExtractJsonPath2 (jpi , lax , not , indirect , unwrap , parent ,
460
- paths );
486
+ paths , filters );
461
487
}
462
488
463
489
static inline JsQueryItem *
@@ -496,7 +522,77 @@ jspConstToJsQueryItem(JsonPathItem *jpi)
496
522
}
497
523
498
524
static ExtractedNode *
499
- recursiveExtractJsonPathExpr (JsonPathItem * jpi , bool lax , bool not )
525
+ appendJsonPathExprNode (ExtractedNode * result , ExtractedNode * node , PathItem * path ,
526
+ List * filters )
527
+ {
528
+ ExtractedNode * orNode ;
529
+
530
+ if (filters )
531
+ {
532
+ ListCell * flc ;
533
+
534
+ foreach (flc , filters )
535
+ {
536
+ ExtractedNode * filter = lfirst (flc );
537
+ ExtractedNode * andNode = palloc (sizeof (ExtractedNode ));
538
+
539
+ andNode -> type = eAnd ;
540
+ andNode -> hint = jsqIndexDefault ;
541
+ andNode -> path = path ;
542
+ andNode -> indirect = false;
543
+ andNode -> args .items = palloc (2 * sizeof (ExtractedNode * ));
544
+ andNode -> args .items [0 ] = node ;
545
+ andNode -> args .items [1 ] = filter ;
546
+ andNode -> args .count = 2 ;
547
+
548
+ node = andNode ;
549
+ }
550
+ }
551
+
552
+ if (!result )
553
+ return node ;
554
+
555
+ orNode = palloc (sizeof (ExtractedNode ));
556
+
557
+ orNode -> type = eOr ;
558
+ orNode -> hint = jsqIndexDefault ;
559
+ orNode -> path = path ;
560
+ orNode -> indirect = false;
561
+ orNode -> args .items = palloc (2 * sizeof (ExtractedNode * ));
562
+ orNode -> args .items [0 ] = result ;
563
+ orNode -> args .items [1 ] = node ;
564
+ orNode -> args .count = 2 ;
565
+
566
+ return orNode ;
567
+ }
568
+
569
+ static ExtractedNode *
570
+ extractJsonPathExists (JsonPathItem * jpi , bool lax , PathItem * path )
571
+ {
572
+ List * paths = NIL ;
573
+ ListCell * lc ;
574
+ ExtractedNode * result ;
575
+
576
+ if (!recursiveExtractJsonPath (jpi , lax , false, false /* FIXME */ , false,
577
+ path , & paths , NIL ))
578
+ return NULL ;
579
+
580
+ result = NULL ;
581
+
582
+ foreach (lc , paths )
583
+ {
584
+ ExtractedJsonPath * ejp = lfirst (lc );
585
+ ExtractedNode * node = makeAnyNode (false, ejp -> indirect , ejp -> path );
586
+
587
+ result = appendJsonPathExprNode (result , node , path , ejp -> filters );
588
+ }
589
+
590
+ return result ;
591
+ }
592
+
593
+ static ExtractedNode *
594
+ recursiveExtractJsonPathExpr (JsonPathItem * jpi , bool lax , bool not ,
595
+ PathItem * path )
500
596
{
501
597
ExtractedNode * result ;
502
598
JsonPathItem elem ;
@@ -516,10 +612,10 @@ recursiveExtractJsonPathExpr(JsonPathItem *jpi, bool lax, bool not)
516
612
type = ((jpi -> type == jpiAnd ) == not ) ? eOr : eAnd ;
517
613
518
614
jspGetLeftArg (jpi , & elem );
519
- leftNode = recursiveExtractJsonPathExpr (& elem , lax , not );
615
+ leftNode = recursiveExtractJsonPathExpr (& elem , lax , not , path );
520
616
521
617
jspGetRightArg (jpi , & elem );
522
- rightNode = recursiveExtractJsonPathExpr (& elem , lax , not );
618
+ rightNode = recursiveExtractJsonPathExpr (& elem , lax , not , path );
523
619
524
620
if (!leftNode || !rightNode )
525
621
{
@@ -540,7 +636,7 @@ recursiveExtractJsonPathExpr(JsonPathItem *jpi, bool lax, bool not)
540
636
541
637
result = palloc (sizeof (ExtractedNode ));
542
638
result -> type = type ;
543
- result -> path = NULL ;
639
+ result -> path = path ;
544
640
result -> indirect = indirect ;
545
641
result -> args .items = palloc (2 * sizeof (ExtractedNode * ));
546
642
result -> args .items [0 ] = leftNode ;
@@ -552,7 +648,7 @@ recursiveExtractJsonPathExpr(JsonPathItem *jpi, bool lax, bool not)
552
648
553
649
case jpiNot :
554
650
jspGetArg (jpi , & elem );
555
- return recursiveExtractJsonPathExpr (& elem , lax , !not );
651
+ return recursiveExtractJsonPathExpr (& elem , lax , !not , path );
556
652
557
653
case jpiEqual :
558
654
case jpiLess :
@@ -585,8 +681,8 @@ recursiveExtractJsonPathExpr(JsonPathItem *jpi, bool lax, bool not)
585
681
{
586
682
bound = jspConstToJsQueryItem (& rarg );
587
683
588
- if (!recursiveExtractJsonPath (& larg , lax , not , false/* FIXME */ , true, NULL ,
589
- & paths ))
684
+ if (!recursiveExtractJsonPath (& larg , lax , not , false/* FIXME */ , true, path ,
685
+ & paths , NIL ))
590
686
return NULL ;
591
687
}
592
688
else if (larg .type == jpiNumeric ||
@@ -597,8 +693,8 @@ recursiveExtractJsonPathExpr(JsonPathItem *jpi, bool lax, bool not)
597
693
{
598
694
bound = jspConstToJsQueryItem (& larg );
599
695
600
- if (!recursiveExtractJsonPath (& rarg , lax , not , false/* FIXME */ , true, NULL ,
601
- & paths ))
696
+ if (!recursiveExtractJsonPath (& rarg , lax , not , false/* FIXME */ , true, path ,
697
+ & paths , NIL ))
602
698
return NULL ;
603
699
604
700
greater = !greater ;
@@ -674,27 +770,23 @@ recursiveExtractJsonPathExpr(JsonPathItem *jpi, bool lax, bool not)
674
770
}
675
771
}
676
772
677
- if (result )
678
- {
679
- ExtractedNode * orNode = palloc (sizeof (ExtractedNode ));
680
-
681
- orNode -> type = eOr ;
682
- orNode -> path = NULL ;
683
- orNode -> indirect = false;
684
- orNode -> args .items = palloc (2 * sizeof (ExtractedNode * ));
685
- orNode -> args .items [0 ] = result ;
686
- orNode -> args .items [1 ] = node ;
687
- orNode -> args .count = 2 ;
688
-
689
- result = orNode ;
690
- }
691
- else
692
- result = node ;
773
+ result = appendJsonPathExprNode (result , node , path ,
774
+ ejp -> filters );
693
775
}
694
776
695
777
return result ;
696
778
}
697
779
780
+ case jpiExists :
781
+ {
782
+ if (not )
783
+ return NULL ;
784
+
785
+ jspGetArg (jpi , & elem );
786
+
787
+ return extractJsonPathExists (& elem , lax , path );
788
+ }
789
+
698
790
default :
699
791
/* elog(ERROR,"Wrong state: %d", jpi->type); */
700
792
return NULL ;
@@ -1262,7 +1354,7 @@ extractJsonPath(JsonPath *jp, MakeEntryHandler makeHandler,
1262
1354
bool lax = (jp -> header & JSONPATH_LAX ) != 0 ;
1263
1355
1264
1356
jspInit (& jsp , jp );
1265
- root = recursiveExtractJsonPathExpr (& jsp , lax , false);
1357
+ root = recursiveExtractJsonPathExpr (& jsp , lax , false, NULL );
1266
1358
if (root )
1267
1359
{
1268
1360
flatternTree (root );
0 commit comments