@@ -1090,43 +1090,84 @@ executeUnaryArithmExpr(JsonPathExecContext *cxt, JsonPathItem *jsp,
1090
1090
return jper ;
1091
1091
}
1092
1092
1093
+ static JsonValueList
1094
+ prependKey (JsonbValue * key , const JsonValueList * items )
1095
+ {
1096
+ JsonValueList objs = { 0 };
1097
+ JsonValueListIterator it = { 0 };
1098
+ JsonbValue * val ;
1099
+
1100
+ while ((val = JsonValueListNext (items , & it )))
1101
+ {
1102
+ JsonbValue * obj ;
1103
+ JsonbValue bin ;
1104
+ JsonbParseState * ps = NULL ;
1105
+
1106
+ if (val -> type == jbvObject || val -> type == jbvArray )
1107
+ val = JsonbWrapInBinary (val , & bin );
1108
+
1109
+ pushJsonbValue (& ps , WJB_BEGIN_OBJECT , NULL );
1110
+ pushJsonbValue (& ps , WJB_KEY , key );
1111
+ pushJsonbValue (& ps , WJB_VALUE , val );
1112
+ obj = pushJsonbValue (& ps , WJB_END_OBJECT , NULL );
1113
+
1114
+ JsonValueListAppend (& objs , obj );
1115
+ }
1116
+
1117
+ return objs ;
1118
+ }
1119
+
1093
1120
/*
1094
1121
* implements jpiAny node (** operator)
1095
1122
*/
1096
1123
static JsonPathExecResult
1097
1124
recursiveAny (JsonPathExecContext * cxt , JsonPathItem * jsp , JsonbValue * jb ,
1098
- JsonValueList * found , uint32 level , uint32 first , uint32 last )
1125
+ JsonValueList * found , bool outPath ,
1126
+ uint32 level , uint32 first , uint32 last )
1099
1127
{
1100
1128
JsonPathExecResult res = jperNotFound ;
1101
1129
JsonbIterator * it ;
1102
1130
int32 r ;
1103
1131
JsonbValue v ;
1132
+ bool isObject ;
1133
+ JsonValueList items = { 0 };
1134
+ JsonValueList * pitems = found ;
1104
1135
1105
1136
check_stack_depth ();
1106
1137
1107
1138
if (level > last )
1108
1139
return res ;
1109
1140
1141
+ if (pitems && outPath )
1142
+ pitems = & items ;
1143
+
1144
+ isObject = JsonContainerIsObject (jb -> val .binary .data );
1145
+
1110
1146
it = JsonbIteratorInit (jb -> val .binary .data );
1111
1147
1112
1148
/*
1113
1149
* Recursivly iterate over jsonb objects/arrays
1114
1150
*/
1115
1151
while ((r = JsonbIteratorNext (& it , & v , true)) != WJB_DONE )
1116
1152
{
1153
+ JsonbValue key ;
1154
+
1117
1155
if (r == WJB_KEY )
1118
1156
{
1157
+ key = v ;
1119
1158
r = JsonbIteratorNext (& it , & v , true);
1120
1159
Assert (r == WJB_VALUE );
1160
+
1161
+ if (pitems == & items )
1162
+ JsonValueListClear (pitems );
1121
1163
}
1122
1164
1123
1165
if (r == WJB_VALUE || r == WJB_ELEM )
1124
1166
{
1125
-
1126
1167
if (level >= first )
1127
1168
{
1128
1169
/* check expression */
1129
- res = recursiveExecuteNext (cxt , NULL , jsp , & v , found , true);
1170
+ res = recursiveExecuteNext (cxt , NULL , jsp , & v , pitems , true);
1130
1171
1131
1172
if (jperIsError (res ))
1132
1173
break ;
@@ -1137,17 +1178,24 @@ recursiveAny(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb,
1137
1178
1138
1179
if (level < last && v .type == jbvBinary )
1139
1180
{
1140
- res = recursiveAny (cxt , jsp , & v , found , level + 1 , first , last );
1181
+ res = recursiveAny (cxt , jsp , & v , pitems , outPath ,
1182
+ level + 1 , first , last );
1141
1183
1142
1184
if (jperIsError (res ))
1143
1185
break ;
1144
1186
1145
1187
if (res == jperOk && found == NULL )
1146
1188
break ;
1147
1189
}
1190
+
1191
+ if (isObject && !JsonValueListIsEmpty (& items ) && !jperIsError (res ))
1192
+ JsonValueListConcat (found , prependKey (& key , & items ));
1148
1193
}
1149
1194
}
1150
1195
1196
+ if (!isObject && !JsonValueListIsEmpty (& items ) && !jperIsError (res ))
1197
+ JsonValueListAppend (found , wrapItemsInArray (& items ));
1198
+
1151
1199
return res ;
1152
1200
}
1153
1201
@@ -1469,7 +1517,8 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
1469
1517
case jpiKey :
1470
1518
if (JsonbType (jb ) == jbvObject )
1471
1519
{
1472
- JsonbValue * v , key ;
1520
+ JsonbValue * v ;
1521
+ JsonbValue key ;
1473
1522
JsonbValue obj ;
1474
1523
1475
1524
if (jb -> type == jbvObject )
@@ -1482,10 +1531,19 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
1482
1531
1483
1532
if (v != NULL )
1484
1533
{
1485
- res = recursiveExecuteNext (cxt , jsp , NULL , v , found , false);
1534
+ JsonValueList items = { 0 };
1535
+ JsonValueList * pitems = found ;
1536
+
1537
+ if (pitems && jspOutPath (jsp ))
1538
+ pitems = & items ;
1539
+
1540
+ res = recursiveExecuteNext (cxt , jsp , NULL , v , pitems , false);
1486
1541
1487
1542
if (jspHasNext (jsp ) || !found )
1488
1543
pfree (v ); /* free value if it was not added to found list */
1544
+
1545
+ if (!JsonValueListIsEmpty (& items ) && !jperIsError (res ))
1546
+ JsonValueListConcat (found , prependKey (& key , & items ));
1489
1547
}
1490
1548
else if (!cxt -> lax )
1491
1549
{
@@ -1547,6 +1605,13 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
1547
1605
case jpiAnyArray :
1548
1606
if (JsonbType (jb ) == jbvArray )
1549
1607
{
1608
+ JsonValueList items = { 0 };
1609
+ JsonValueList * pitems = found ;
1610
+ bool wrap = pitems && jspOutPath (jsp );
1611
+
1612
+ if (wrap )
1613
+ pitems = & items ;
1614
+
1550
1615
hasNext = jspGetNext (jsp , & elem );
1551
1616
1552
1617
if (jb -> type == jbvArray )
@@ -1556,7 +1621,7 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
1556
1621
1557
1622
for (; el < last_el ; el ++ )
1558
1623
{
1559
- res = recursiveExecuteNext (cxt , jsp , & elem , el , found , true);
1624
+ res = recursiveExecuteNext (cxt , jsp , & elem , el , pitems , true);
1560
1625
1561
1626
if (jperIsError (res ))
1562
1627
break ;
@@ -1577,7 +1642,7 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
1577
1642
{
1578
1643
if (r == WJB_ELEM )
1579
1644
{
1580
- res = recursiveExecuteNext (cxt , jsp , & elem , & v , found , true);
1645
+ res = recursiveExecuteNext (cxt , jsp , & elem , & v , pitems , true);
1581
1646
1582
1647
if (jperIsError (res ))
1583
1648
break ;
@@ -1587,6 +1652,9 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
1587
1652
}
1588
1653
}
1589
1654
}
1655
+
1656
+ if (wrap && !jperIsError (res ))
1657
+ JsonValueListAppend (found , wrapItemsInArray (& items ));
1590
1658
}
1591
1659
else
1592
1660
res = jperMakeError (ERRCODE_JSON_ARRAY_NOT_FOUND );
@@ -1599,6 +1667,12 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
1599
1667
int i ;
1600
1668
int size = JsonbArraySize (jb );
1601
1669
bool binary = jb -> type == jbvBinary ;
1670
+ JsonValueList items = { 0 };
1671
+ JsonValueList * pitems = found ;
1672
+ bool wrap = pitems && jspOutPath (jsp );
1673
+
1674
+ if (wrap )
1675
+ pitems = & items ;
1602
1676
1603
1677
cxt -> innermostArraySize = size ; /* for LAST evaluation */
1604
1678
@@ -1655,7 +1729,7 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
1655
1729
if (v == NULL )
1656
1730
continue ;
1657
1731
1658
- res = recursiveExecuteNext (cxt , jsp , & elem , v , found ,
1732
+ res = recursiveExecuteNext (cxt , jsp , & elem , v , pitems ,
1659
1733
!binary );
1660
1734
1661
1735
if (jperIsError (res ))
@@ -1673,13 +1747,22 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
1673
1747
}
1674
1748
1675
1749
cxt -> innermostArraySize = innermostArraySize ;
1750
+
1751
+ if (wrap && !jperIsError (res ))
1752
+ JsonValueListAppend (found , wrapItemsInArray (& items ));
1676
1753
}
1677
1754
else if (JsonbType (jb ) == jbvObject )
1678
1755
{
1679
1756
int innermostArraySize = cxt -> innermostArraySize ;
1680
1757
int i ;
1681
1758
JsonbValue bin ;
1682
1759
JsonbValue * wrapped = NULL ;
1760
+ JsonValueList items = { 0 };
1761
+ JsonValueList * pitems = found ;
1762
+ bool wrap = pitems && jspOutPath (jsp );
1763
+
1764
+ if (wrap )
1765
+ pitems = & items ;
1683
1766
1684
1767
if (jb -> type != jbvBinary )
1685
1768
jb = JsonbWrapInBinary (jb , & bin );
@@ -1719,7 +1802,7 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
1719
1802
if (index_from <= 0 && index_to >= 0 )
1720
1803
{
1721
1804
res = recursiveExecuteNext (cxt , jsp , NULL , jb ,
1722
- found , true);
1805
+ pitems , true);
1723
1806
if (jperIsError (res ))
1724
1807
return res ;
1725
1808
@@ -1757,7 +1840,7 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
1757
1840
if (!index )
1758
1841
{
1759
1842
res = recursiveExecuteNext (cxt , jsp , NULL , jb ,
1760
- found , true);
1843
+ pitems , true);
1761
1844
if (jperIsError (res ))
1762
1845
return res ;
1763
1846
}
@@ -1770,7 +1853,7 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
1770
1853
if (key )
1771
1854
{
1772
1855
res = recursiveExecuteNext (cxt , jsp , NULL , key ,
1773
- found , false);
1856
+ pitems , false);
1774
1857
if (jperIsError (res ))
1775
1858
return res ;
1776
1859
}
@@ -1785,6 +1868,9 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
1785
1868
}
1786
1869
1787
1870
cxt -> innermostArraySize = innermostArraySize ;
1871
+
1872
+ if (wrap && !jperIsError (res ))
1873
+ JsonValueListAppend (found , wrapItemsInArray (& items ));
1788
1874
}
1789
1875
else
1790
1876
{
@@ -1842,15 +1928,31 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
1842
1928
1843
1929
while ((r = JsonbIteratorNext (& it , & v , true)) != WJB_DONE )
1844
1930
{
1931
+ JsonbValue key ;
1932
+ JsonValueList items = { 0 };
1933
+ JsonValueList * pitems = found ;
1934
+
1935
+ if (r == WJB_KEY && jspOutPath (jsp ))
1936
+ {
1937
+ key = v ;
1938
+ r = JsonbIteratorNext (& it , & v , true);
1939
+
1940
+ if (pitems )
1941
+ pitems = & items ;
1942
+ }
1943
+
1845
1944
if (r == WJB_VALUE )
1846
1945
{
1847
- res = recursiveExecuteNext (cxt , jsp , & elem , & v , found , true);
1946
+ res = recursiveExecuteNext (cxt , jsp , & elem , & v , pitems , true);
1848
1947
1849
1948
if (jperIsError (res ))
1850
1949
break ;
1851
1950
1852
1951
if (res == jperOk && !found )
1853
1952
break ;
1953
+
1954
+ if (!JsonValueListIsEmpty (& items ) && !jperIsError (res ))
1955
+ JsonValueListConcat (found , prependKey (& key , & items ));
1854
1956
}
1855
1957
}
1856
1958
}
@@ -1900,15 +2002,15 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
1900
2002
res = recursiveExecuteNext (cxt , jsp , & elem , jb , found , true);
1901
2003
1902
2004
if (res == jperOk && !found )
1903
- break ;
2005
+ break ;
1904
2006
}
1905
2007
1906
2008
if (jb -> type == jbvArray || jb -> type == jbvObject )
1907
2009
jb = JsonbWrapInBinary (jb , & jbvbuf );
1908
2010
1909
2011
if (jb -> type == jbvBinary )
1910
2012
res = recursiveAny (cxt , hasNext ? & elem : NULL , jb , found ,
1911
- 1 ,
2013
+ jspOutPath ( jsp ), 1 ,
1912
2014
jsp -> content .anybounds .first ,
1913
2015
jsp -> content .anybounds .last );
1914
2016
break ;
0 commit comments