@@ -1012,43 +1012,84 @@ executeUnaryArithmExpr(JsonPathExecContext *cxt, JsonPathItem *jsp,
1012
1012
return jper ;
1013
1013
}
1014
1014
1015
+ static JsonValueList
1016
+ prependKey (JsonbValue * key , const JsonValueList * items )
1017
+ {
1018
+ JsonValueList objs = { 0 };
1019
+ JsonValueListIterator it = { 0 };
1020
+ JsonbValue * val ;
1021
+
1022
+ while ((val = JsonValueListNext (items , & it )))
1023
+ {
1024
+ JsonbValue * obj ;
1025
+ JsonbValue bin ;
1026
+ JsonbParseState * ps = NULL ;
1027
+
1028
+ if (val -> type == jbvObject || val -> type == jbvArray )
1029
+ val = JsonbWrapInBinary (val , & bin );
1030
+
1031
+ pushJsonbValue (& ps , WJB_BEGIN_OBJECT , NULL );
1032
+ pushJsonbValue (& ps , WJB_KEY , key );
1033
+ pushJsonbValue (& ps , WJB_VALUE , val );
1034
+ obj = pushJsonbValue (& ps , WJB_END_OBJECT , NULL );
1035
+
1036
+ JsonValueListAppend (& objs , obj );
1037
+ }
1038
+
1039
+ return objs ;
1040
+ }
1041
+
1015
1042
/*
1016
1043
* implements jpiAny node (** operator)
1017
1044
*/
1018
1045
static JsonPathExecResult
1019
1046
recursiveAny (JsonPathExecContext * cxt , JsonPathItem * jsp , JsonbValue * jb ,
1020
- JsonValueList * found , uint32 level , uint32 first , uint32 last )
1047
+ JsonValueList * found , bool outPath ,
1048
+ uint32 level , uint32 first , uint32 last )
1021
1049
{
1022
1050
JsonPathExecResult res = jperNotFound ;
1023
1051
JsonbIterator * it ;
1024
1052
int32 r ;
1025
1053
JsonbValue v ;
1054
+ bool isObject ;
1055
+ JsonValueList items = { 0 };
1056
+ JsonValueList * pitems = found ;
1026
1057
1027
1058
check_stack_depth ();
1028
1059
1029
1060
if (level > last )
1030
1061
return res ;
1031
1062
1063
+ if (pitems && outPath )
1064
+ pitems = & items ;
1065
+
1066
+ isObject = JsonContainerIsObject (jb -> val .binary .data );
1067
+
1032
1068
it = JsonbIteratorInit (jb -> val .binary .data );
1033
1069
1034
1070
/*
1035
1071
* Recursivly iterate over jsonb objects/arrays
1036
1072
*/
1037
1073
while ((r = JsonbIteratorNext (& it , & v , true)) != WJB_DONE )
1038
1074
{
1075
+ JsonbValue key ;
1076
+
1039
1077
if (r == WJB_KEY )
1040
1078
{
1079
+ key = v ;
1041
1080
r = JsonbIteratorNext (& it , & v , true);
1042
1081
Assert (r == WJB_VALUE );
1082
+
1083
+ if (pitems == & items )
1084
+ JsonValueListClear (pitems );
1043
1085
}
1044
1086
1045
1087
if (r == WJB_VALUE || r == WJB_ELEM )
1046
1088
{
1047
-
1048
1089
if (level >= first )
1049
1090
{
1050
1091
/* check expression */
1051
- res = recursiveExecuteNext (cxt , NULL , jsp , & v , found , true);
1092
+ res = recursiveExecuteNext (cxt , NULL , jsp , & v , pitems , true);
1052
1093
1053
1094
if (jperIsError (res ))
1054
1095
break ;
@@ -1059,17 +1100,24 @@ recursiveAny(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb,
1059
1100
1060
1101
if (level < last && v .type == jbvBinary )
1061
1102
{
1062
- res = recursiveAny (cxt , jsp , & v , found , level + 1 , first , last );
1103
+ res = recursiveAny (cxt , jsp , & v , pitems , outPath ,
1104
+ level + 1 , first , last );
1063
1105
1064
1106
if (jperIsError (res ))
1065
1107
break ;
1066
1108
1067
1109
if (res == jperOk && found == NULL )
1068
1110
break ;
1069
1111
}
1112
+
1113
+ if (isObject && !JsonValueListIsEmpty (& items ) && !jperIsError (res ))
1114
+ JsonValueListConcat (found , prependKey (& key , & items ));
1070
1115
}
1071
1116
}
1072
1117
1118
+ if (!isObject && !JsonValueListIsEmpty (& items ) && !jperIsError (res ))
1119
+ JsonValueListAppend (found , wrapItemsInArray (& items ));
1120
+
1073
1121
return res ;
1074
1122
}
1075
1123
@@ -1325,7 +1373,8 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
1325
1373
case jpiKey :
1326
1374
if (JsonbType (jb ) == jbvObject )
1327
1375
{
1328
- JsonbValue * v , key ;
1376
+ JsonbValue * v ;
1377
+ JsonbValue key ;
1329
1378
JsonbValue obj ;
1330
1379
1331
1380
if (jb -> type == jbvObject )
@@ -1338,10 +1387,19 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
1338
1387
1339
1388
if (v != NULL )
1340
1389
{
1341
- res = recursiveExecuteNext (cxt , jsp , NULL , v , found , false);
1390
+ JsonValueList items = { 0 };
1391
+ JsonValueList * pitems = found ;
1392
+
1393
+ if (pitems && jspOutPath (jsp ))
1394
+ pitems = & items ;
1395
+
1396
+ res = recursiveExecuteNext (cxt , jsp , NULL , v , pitems , false);
1342
1397
1343
1398
if (jspHasNext (jsp ) || !found )
1344
1399
pfree (v ); /* free value if it was not added to found list */
1400
+
1401
+ if (!JsonValueListIsEmpty (& items ) && !jperIsError (res ))
1402
+ JsonValueListConcat (found , prependKey (& key , & items ));
1345
1403
}
1346
1404
else if (!cxt -> lax && found )
1347
1405
res = jperMakeError (ERRCODE_JSON_MEMBER_NOT_FOUND );
@@ -1397,6 +1455,13 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
1397
1455
case jpiAnyArray :
1398
1456
if (JsonbType (jb ) == jbvArray )
1399
1457
{
1458
+ JsonValueList items = { 0 };
1459
+ JsonValueList * pitems = found ;
1460
+ bool wrap = pitems && jspOutPath (jsp );
1461
+
1462
+ if (wrap )
1463
+ pitems = & items ;
1464
+
1400
1465
hasNext = jspGetNext (jsp , & elem );
1401
1466
1402
1467
if (jb -> type == jbvArray )
@@ -1406,7 +1471,7 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
1406
1471
1407
1472
for (; el < last_el ; el ++ )
1408
1473
{
1409
- res = recursiveExecuteNext (cxt , jsp , & elem , el , found , true);
1474
+ res = recursiveExecuteNext (cxt , jsp , & elem , el , pitems , true);
1410
1475
1411
1476
if (jperIsError (res ))
1412
1477
break ;
@@ -1427,7 +1492,7 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
1427
1492
{
1428
1493
if (r == WJB_ELEM )
1429
1494
{
1430
- res = recursiveExecuteNext (cxt , jsp , & elem , & v , found , true);
1495
+ res = recursiveExecuteNext (cxt , jsp , & elem , & v , pitems , true);
1431
1496
1432
1497
if (jperIsError (res ))
1433
1498
break ;
@@ -1437,6 +1502,9 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
1437
1502
}
1438
1503
}
1439
1504
}
1505
+
1506
+ if (wrap && !jperIsError (res ))
1507
+ JsonValueListAppend (found , wrapItemsInArray (& items ));
1440
1508
}
1441
1509
else
1442
1510
res = jperMakeError (ERRCODE_JSON_ARRAY_NOT_FOUND );
@@ -1449,6 +1517,12 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
1449
1517
int i ;
1450
1518
int size = JsonbArraySize (jb );
1451
1519
bool binary = jb -> type == jbvBinary ;
1520
+ JsonValueList items = { 0 };
1521
+ JsonValueList * pitems = found ;
1522
+ bool wrap = pitems && jspOutPath (jsp );
1523
+
1524
+ if (wrap )
1525
+ pitems = & items ;
1452
1526
1453
1527
cxt -> innermostArraySize = size ; /* for LAST evaluation */
1454
1528
@@ -1505,7 +1579,7 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
1505
1579
if (v == NULL )
1506
1580
continue ;
1507
1581
1508
- res = recursiveExecuteNext (cxt , jsp , & elem , v , found ,
1582
+ res = recursiveExecuteNext (cxt , jsp , & elem , v , pitems ,
1509
1583
!binary );
1510
1584
1511
1585
if (jperIsError (res ))
@@ -1523,13 +1597,22 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
1523
1597
}
1524
1598
1525
1599
cxt -> innermostArraySize = innermostArraySize ;
1600
+
1601
+ if (wrap && !jperIsError (res ))
1602
+ JsonValueListAppend (found , wrapItemsInArray (& items ));
1526
1603
}
1527
1604
else if (JsonbType (jb ) == jbvObject )
1528
1605
{
1529
1606
int innermostArraySize = cxt -> innermostArraySize ;
1530
1607
int i ;
1531
1608
JsonbValue bin ;
1532
1609
JsonbValue * wrapped = NULL ;
1610
+ JsonValueList items = { 0 };
1611
+ JsonValueList * pitems = found ;
1612
+ bool wrap = pitems && jspOutPath (jsp );
1613
+
1614
+ if (wrap )
1615
+ pitems = & items ;
1533
1616
1534
1617
if (jb -> type == jbvBinary )
1535
1618
jb = JsonbWrapInBinary (jb , & bin );
@@ -1569,7 +1652,7 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
1569
1652
if (index_from <= 0 && index_to >= 0 )
1570
1653
{
1571
1654
res = recursiveExecuteNext (cxt , jsp , NULL , jb ,
1572
- found , true);
1655
+ pitems , true);
1573
1656
if (jperIsError (res ))
1574
1657
return res ;
1575
1658
@@ -1607,7 +1690,7 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
1607
1690
if (!index )
1608
1691
{
1609
1692
res = recursiveExecuteNext (cxt , jsp , NULL , jb ,
1610
- found , true);
1693
+ pitems , true);
1611
1694
if (jperIsError (res ))
1612
1695
return res ;
1613
1696
}
@@ -1620,7 +1703,7 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
1620
1703
if (key )
1621
1704
{
1622
1705
res = recursiveExecuteNext (cxt , jsp , NULL , key ,
1623
- found , false);
1706
+ pitems , false);
1624
1707
if (jperIsError (res ))
1625
1708
return res ;
1626
1709
}
@@ -1635,6 +1718,9 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
1635
1718
}
1636
1719
1637
1720
cxt -> innermostArraySize = innermostArraySize ;
1721
+
1722
+ if (wrap && !jperIsError (res ))
1723
+ JsonValueListAppend (found , wrapItemsInArray (& items ));
1638
1724
}
1639
1725
else
1640
1726
{
@@ -1692,15 +1778,31 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
1692
1778
1693
1779
while ((r = JsonbIteratorNext (& it , & v , true)) != WJB_DONE )
1694
1780
{
1781
+ JsonbValue key ;
1782
+ JsonValueList items = { 0 };
1783
+ JsonValueList * pitems = found ;
1784
+
1785
+ if (r == WJB_KEY && jspOutPath (jsp ))
1786
+ {
1787
+ key = v ;
1788
+ r = JsonbIteratorNext (& it , & v , true);
1789
+
1790
+ if (pitems )
1791
+ pitems = & items ;
1792
+ }
1793
+
1695
1794
if (r == WJB_VALUE )
1696
1795
{
1697
- res = recursiveExecuteNext (cxt , jsp , & elem , & v , found , true);
1796
+ res = recursiveExecuteNext (cxt , jsp , & elem , & v , pitems , true);
1698
1797
1699
1798
if (jperIsError (res ))
1700
1799
break ;
1701
1800
1702
1801
if (res == jperOk && !found )
1703
1802
break ;
1803
+
1804
+ if (!JsonValueListIsEmpty (& items ) && !jperIsError (res ))
1805
+ JsonValueListConcat (found , prependKey (& key , & items ));
1704
1806
}
1705
1807
}
1706
1808
}
@@ -1747,15 +1849,15 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
1747
1849
res = recursiveExecuteNext (cxt , jsp , & elem , jb , found , true);
1748
1850
1749
1851
if (res == jperOk && !found )
1750
- break ;
1852
+ break ;
1751
1853
}
1752
1854
1753
1855
if (jb -> type == jbvArray || jb -> type == jbvObject )
1754
1856
jb = JsonbWrapInBinary (jb , & jbvbuf );
1755
1857
1756
1858
if (jb -> type == jbvBinary )
1757
1859
res = recursiveAny (cxt , hasNext ? & elem : NULL , jb , found ,
1758
- 1 ,
1860
+ jspOutPath ( jsp ), 1 ,
1759
1861
jsp -> content .anybounds .first ,
1760
1862
jsp -> content .anybounds .last );
1761
1863
break ;
0 commit comments