@@ -1090,43 +1090,84 @@ executeUnaryArithmExpr(JsonPathExecContext *cxt, JsonPathItem *jsp,
10901090 return jper ;
10911091}
10921092
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+
10931120/*
10941121 * implements jpiAny node (** operator)
10951122 */
10961123static JsonPathExecResult
10971124recursiveAny (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 )
10991127{
11001128 JsonPathExecResult res = jperNotFound ;
11011129 JsonbIterator * it ;
11021130 int32 r ;
11031131 JsonbValue v ;
1132+ bool isObject ;
1133+ JsonValueList items = { 0 };
1134+ JsonValueList * pitems = found ;
11041135
11051136 check_stack_depth ();
11061137
11071138 if (level > last )
11081139 return res ;
11091140
1141+ if (pitems && outPath )
1142+ pitems = & items ;
1143+
1144+ isObject = JsonContainerIsObject (jb -> val .binary .data );
1145+
11101146 it = JsonbIteratorInit (jb -> val .binary .data );
11111147
11121148 /*
11131149 * Recursivly iterate over jsonb objects/arrays
11141150 */
11151151 while ((r = JsonbIteratorNext (& it , & v , true)) != WJB_DONE )
11161152 {
1153+ JsonbValue key ;
1154+
11171155 if (r == WJB_KEY )
11181156 {
1157+ key = v ;
11191158 r = JsonbIteratorNext (& it , & v , true);
11201159 Assert (r == WJB_VALUE );
1160+
1161+ if (pitems == & items )
1162+ JsonValueListClear (pitems );
11211163 }
11221164
11231165 if (r == WJB_VALUE || r == WJB_ELEM )
11241166 {
1125-
11261167 if (level >= first )
11271168 {
11281169 /* check expression */
1129- res = recursiveExecuteNext (cxt , NULL , jsp , & v , found , true);
1170+ res = recursiveExecuteNext (cxt , NULL , jsp , & v , pitems , true);
11301171
11311172 if (jperIsError (res ))
11321173 break ;
@@ -1137,17 +1178,24 @@ recursiveAny(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb,
11371178
11381179 if (level < last && v .type == jbvBinary )
11391180 {
1140- res = recursiveAny (cxt , jsp , & v , found , level + 1 , first , last );
1181+ res = recursiveAny (cxt , jsp , & v , pitems , outPath ,
1182+ level + 1 , first , last );
11411183
11421184 if (jperIsError (res ))
11431185 break ;
11441186
11451187 if (res == jperOk && found == NULL )
11461188 break ;
11471189 }
1190+
1191+ if (isObject && !JsonValueListIsEmpty (& items ) && !jperIsError (res ))
1192+ JsonValueListConcat (found , prependKey (& key , & items ));
11481193 }
11491194 }
11501195
1196+ if (!isObject && !JsonValueListIsEmpty (& items ) && !jperIsError (res ))
1197+ JsonValueListAppend (found , wrapItemsInArray (& items ));
1198+
11511199 return res ;
11521200}
11531201
@@ -1469,7 +1517,8 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
14691517 case jpiKey :
14701518 if (JsonbType (jb ) == jbvObject )
14711519 {
1472- JsonbValue * v , key ;
1520+ JsonbValue * v ;
1521+ JsonbValue key ;
14731522 JsonbValue obj ;
14741523
14751524 if (jb -> type == jbvObject )
@@ -1482,10 +1531,19 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
14821531
14831532 if (v != NULL )
14841533 {
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);
14861541
14871542 if (jspHasNext (jsp ) || !found )
14881543 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 ));
14891547 }
14901548 else if (!cxt -> lax )
14911549 {
@@ -1547,6 +1605,13 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
15471605 case jpiAnyArray :
15481606 if (JsonbType (jb ) == jbvArray )
15491607 {
1608+ JsonValueList items = { 0 };
1609+ JsonValueList * pitems = found ;
1610+ bool wrap = pitems && jspOutPath (jsp );
1611+
1612+ if (wrap )
1613+ pitems = & items ;
1614+
15501615 hasNext = jspGetNext (jsp , & elem );
15511616
15521617 if (jb -> type == jbvArray )
@@ -1556,7 +1621,7 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
15561621
15571622 for (; el < last_el ; el ++ )
15581623 {
1559- res = recursiveExecuteNext (cxt , jsp , & elem , el , found , true);
1624+ res = recursiveExecuteNext (cxt , jsp , & elem , el , pitems , true);
15601625
15611626 if (jperIsError (res ))
15621627 break ;
@@ -1577,7 +1642,7 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
15771642 {
15781643 if (r == WJB_ELEM )
15791644 {
1580- res = recursiveExecuteNext (cxt , jsp , & elem , & v , found , true);
1645+ res = recursiveExecuteNext (cxt , jsp , & elem , & v , pitems , true);
15811646
15821647 if (jperIsError (res ))
15831648 break ;
@@ -1587,6 +1652,9 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
15871652 }
15881653 }
15891654 }
1655+
1656+ if (wrap && !jperIsError (res ))
1657+ JsonValueListAppend (found , wrapItemsInArray (& items ));
15901658 }
15911659 else
15921660 res = jperMakeError (ERRCODE_JSON_ARRAY_NOT_FOUND );
@@ -1599,6 +1667,12 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
15991667 int i ;
16001668 int size = JsonbArraySize (jb );
16011669 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 ;
16021676
16031677 cxt -> innermostArraySize = size ; /* for LAST evaluation */
16041678
@@ -1655,7 +1729,7 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
16551729 if (v == NULL )
16561730 continue ;
16571731
1658- res = recursiveExecuteNext (cxt , jsp , & elem , v , found ,
1732+ res = recursiveExecuteNext (cxt , jsp , & elem , v , pitems ,
16591733 !binary );
16601734
16611735 if (jperIsError (res ))
@@ -1673,13 +1747,22 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
16731747 }
16741748
16751749 cxt -> innermostArraySize = innermostArraySize ;
1750+
1751+ if (wrap && !jperIsError (res ))
1752+ JsonValueListAppend (found , wrapItemsInArray (& items ));
16761753 }
16771754 else if (JsonbType (jb ) == jbvObject )
16781755 {
16791756 int innermostArraySize = cxt -> innermostArraySize ;
16801757 int i ;
16811758 JsonbValue bin ;
16821759 JsonbValue * wrapped = NULL ;
1760+ JsonValueList items = { 0 };
1761+ JsonValueList * pitems = found ;
1762+ bool wrap = pitems && jspOutPath (jsp );
1763+
1764+ if (wrap )
1765+ pitems = & items ;
16831766
16841767 if (jb -> type != jbvBinary )
16851768 jb = JsonbWrapInBinary (jb , & bin );
@@ -1719,7 +1802,7 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
17191802 if (index_from <= 0 && index_to >= 0 )
17201803 {
17211804 res = recursiveExecuteNext (cxt , jsp , NULL , jb ,
1722- found , true);
1805+ pitems , true);
17231806 if (jperIsError (res ))
17241807 return res ;
17251808
@@ -1757,7 +1840,7 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
17571840 if (!index )
17581841 {
17591842 res = recursiveExecuteNext (cxt , jsp , NULL , jb ,
1760- found , true);
1843+ pitems , true);
17611844 if (jperIsError (res ))
17621845 return res ;
17631846 }
@@ -1770,7 +1853,7 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
17701853 if (key )
17711854 {
17721855 res = recursiveExecuteNext (cxt , jsp , NULL , key ,
1773- found , false);
1856+ pitems , false);
17741857 if (jperIsError (res ))
17751858 return res ;
17761859 }
@@ -1785,6 +1868,9 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
17851868 }
17861869
17871870 cxt -> innermostArraySize = innermostArraySize ;
1871+
1872+ if (wrap && !jperIsError (res ))
1873+ JsonValueListAppend (found , wrapItemsInArray (& items ));
17881874 }
17891875 else
17901876 {
@@ -1842,15 +1928,31 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
18421928
18431929 while ((r = JsonbIteratorNext (& it , & v , true)) != WJB_DONE )
18441930 {
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+
18451944 if (r == WJB_VALUE )
18461945 {
1847- res = recursiveExecuteNext (cxt , jsp , & elem , & v , found , true);
1946+ res = recursiveExecuteNext (cxt , jsp , & elem , & v , pitems , true);
18481947
18491948 if (jperIsError (res ))
18501949 break ;
18511950
18521951 if (res == jperOk && !found )
18531952 break ;
1953+
1954+ if (!JsonValueListIsEmpty (& items ) && !jperIsError (res ))
1955+ JsonValueListConcat (found , prependKey (& key , & items ));
18541956 }
18551957 }
18561958 }
@@ -1900,15 +2002,15 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
19002002 res = recursiveExecuteNext (cxt , jsp , & elem , jb , found , true);
19012003
19022004 if (res == jperOk && !found )
1903- break ;
2005+ break ;
19042006 }
19052007
19062008 if (jb -> type == jbvArray || jb -> type == jbvObject )
19072009 jb = JsonbWrapInBinary (jb , & jbvbuf );
19082010
19092011 if (jb -> type == jbvBinary )
19102012 res = recursiveAny (cxt , hasNext ? & elem : NULL , jb , found ,
1911- 1 ,
2013+ jspOutPath ( jsp ), 1 ,
19122014 jsp -> content .anybounds .first ,
19132015 jsp -> content .anybounds .last );
19142016 break ;
0 commit comments