@@ -1012,43 +1012,84 @@ executeUnaryArithmExpr(JsonPathExecContext *cxt, JsonPathItem *jsp,
10121012 return jper ;
10131013}
10141014
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+
10151042/*
10161043 * implements jpiAny node (** operator)
10171044 */
10181045static JsonPathExecResult
10191046recursiveAny (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 )
10211049{
10221050 JsonPathExecResult res = jperNotFound ;
10231051 JsonbIterator * it ;
10241052 int32 r ;
10251053 JsonbValue v ;
1054+ bool isObject ;
1055+ JsonValueList items = { 0 };
1056+ JsonValueList * pitems = found ;
10261057
10271058 check_stack_depth ();
10281059
10291060 if (level > last )
10301061 return res ;
10311062
1063+ if (pitems && outPath )
1064+ pitems = & items ;
1065+
1066+ isObject = JsonContainerIsObject (jb -> val .binary .data );
1067+
10321068 it = JsonbIteratorInit (jb -> val .binary .data );
10331069
10341070 /*
10351071 * Recursivly iterate over jsonb objects/arrays
10361072 */
10371073 while ((r = JsonbIteratorNext (& it , & v , true)) != WJB_DONE )
10381074 {
1075+ JsonbValue key ;
1076+
10391077 if (r == WJB_KEY )
10401078 {
1079+ key = v ;
10411080 r = JsonbIteratorNext (& it , & v , true);
10421081 Assert (r == WJB_VALUE );
1082+
1083+ if (pitems == & items )
1084+ JsonValueListClear (pitems );
10431085 }
10441086
10451087 if (r == WJB_VALUE || r == WJB_ELEM )
10461088 {
1047-
10481089 if (level >= first )
10491090 {
10501091 /* check expression */
1051- res = recursiveExecuteNext (cxt , NULL , jsp , & v , found , true);
1092+ res = recursiveExecuteNext (cxt , NULL , jsp , & v , pitems , true);
10521093
10531094 if (jperIsError (res ))
10541095 break ;
@@ -1059,17 +1100,24 @@ recursiveAny(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb,
10591100
10601101 if (level < last && v .type == jbvBinary )
10611102 {
1062- res = recursiveAny (cxt , jsp , & v , found , level + 1 , first , last );
1103+ res = recursiveAny (cxt , jsp , & v , pitems , outPath ,
1104+ level + 1 , first , last );
10631105
10641106 if (jperIsError (res ))
10651107 break ;
10661108
10671109 if (res == jperOk && found == NULL )
10681110 break ;
10691111 }
1112+
1113+ if (isObject && !JsonValueListIsEmpty (& items ) && !jperIsError (res ))
1114+ JsonValueListConcat (found , prependKey (& key , & items ));
10701115 }
10711116 }
10721117
1118+ if (!isObject && !JsonValueListIsEmpty (& items ) && !jperIsError (res ))
1119+ JsonValueListAppend (found , wrapItemsInArray (& items ));
1120+
10731121 return res ;
10741122}
10751123
@@ -1325,7 +1373,8 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
13251373 case jpiKey :
13261374 if (JsonbType (jb ) == jbvObject )
13271375 {
1328- JsonbValue * v , key ;
1376+ JsonbValue * v ;
1377+ JsonbValue key ;
13291378 JsonbValue obj ;
13301379
13311380 if (jb -> type == jbvObject )
@@ -1338,10 +1387,19 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
13381387
13391388 if (v != NULL )
13401389 {
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);
13421397
13431398 if (jspHasNext (jsp ) || !found )
13441399 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 ));
13451403 }
13461404 else if (!cxt -> lax && found )
13471405 res = jperMakeError (ERRCODE_JSON_MEMBER_NOT_FOUND );
@@ -1397,6 +1455,13 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
13971455 case jpiAnyArray :
13981456 if (JsonbType (jb ) == jbvArray )
13991457 {
1458+ JsonValueList items = { 0 };
1459+ JsonValueList * pitems = found ;
1460+ bool wrap = pitems && jspOutPath (jsp );
1461+
1462+ if (wrap )
1463+ pitems = & items ;
1464+
14001465 hasNext = jspGetNext (jsp , & elem );
14011466
14021467 if (jb -> type == jbvArray )
@@ -1406,7 +1471,7 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
14061471
14071472 for (; el < last_el ; el ++ )
14081473 {
1409- res = recursiveExecuteNext (cxt , jsp , & elem , el , found , true);
1474+ res = recursiveExecuteNext (cxt , jsp , & elem , el , pitems , true);
14101475
14111476 if (jperIsError (res ))
14121477 break ;
@@ -1427,7 +1492,7 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
14271492 {
14281493 if (r == WJB_ELEM )
14291494 {
1430- res = recursiveExecuteNext (cxt , jsp , & elem , & v , found , true);
1495+ res = recursiveExecuteNext (cxt , jsp , & elem , & v , pitems , true);
14311496
14321497 if (jperIsError (res ))
14331498 break ;
@@ -1437,6 +1502,9 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
14371502 }
14381503 }
14391504 }
1505+
1506+ if (wrap && !jperIsError (res ))
1507+ JsonValueListAppend (found , wrapItemsInArray (& items ));
14401508 }
14411509 else
14421510 res = jperMakeError (ERRCODE_JSON_ARRAY_NOT_FOUND );
@@ -1449,6 +1517,12 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
14491517 int i ;
14501518 int size = JsonbArraySize (jb );
14511519 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 ;
14521526
14531527 cxt -> innermostArraySize = size ; /* for LAST evaluation */
14541528
@@ -1505,7 +1579,7 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
15051579 if (v == NULL )
15061580 continue ;
15071581
1508- res = recursiveExecuteNext (cxt , jsp , & elem , v , found ,
1582+ res = recursiveExecuteNext (cxt , jsp , & elem , v , pitems ,
15091583 !binary );
15101584
15111585 if (jperIsError (res ))
@@ -1523,13 +1597,22 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
15231597 }
15241598
15251599 cxt -> innermostArraySize = innermostArraySize ;
1600+
1601+ if (wrap && !jperIsError (res ))
1602+ JsonValueListAppend (found , wrapItemsInArray (& items ));
15261603 }
15271604 else if (JsonbType (jb ) == jbvObject )
15281605 {
15291606 int innermostArraySize = cxt -> innermostArraySize ;
15301607 int i ;
15311608 JsonbValue bin ;
15321609 JsonbValue * wrapped = NULL ;
1610+ JsonValueList items = { 0 };
1611+ JsonValueList * pitems = found ;
1612+ bool wrap = pitems && jspOutPath (jsp );
1613+
1614+ if (wrap )
1615+ pitems = & items ;
15331616
15341617 if (jb -> type == jbvBinary )
15351618 jb = JsonbWrapInBinary (jb , & bin );
@@ -1569,7 +1652,7 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
15691652 if (index_from <= 0 && index_to >= 0 )
15701653 {
15711654 res = recursiveExecuteNext (cxt , jsp , NULL , jb ,
1572- found , true);
1655+ pitems , true);
15731656 if (jperIsError (res ))
15741657 return res ;
15751658
@@ -1607,7 +1690,7 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
16071690 if (!index )
16081691 {
16091692 res = recursiveExecuteNext (cxt , jsp , NULL , jb ,
1610- found , true);
1693+ pitems , true);
16111694 if (jperIsError (res ))
16121695 return res ;
16131696 }
@@ -1620,7 +1703,7 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
16201703 if (key )
16211704 {
16221705 res = recursiveExecuteNext (cxt , jsp , NULL , key ,
1623- found , false);
1706+ pitems , false);
16241707 if (jperIsError (res ))
16251708 return res ;
16261709 }
@@ -1635,6 +1718,9 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
16351718 }
16361719
16371720 cxt -> innermostArraySize = innermostArraySize ;
1721+
1722+ if (wrap && !jperIsError (res ))
1723+ JsonValueListAppend (found , wrapItemsInArray (& items ));
16381724 }
16391725 else
16401726 {
@@ -1692,15 +1778,31 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
16921778
16931779 while ((r = JsonbIteratorNext (& it , & v , true)) != WJB_DONE )
16941780 {
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+
16951794 if (r == WJB_VALUE )
16961795 {
1697- res = recursiveExecuteNext (cxt , jsp , & elem , & v , found , true);
1796+ res = recursiveExecuteNext (cxt , jsp , & elem , & v , pitems , true);
16981797
16991798 if (jperIsError (res ))
17001799 break ;
17011800
17021801 if (res == jperOk && !found )
17031802 break ;
1803+
1804+ if (!JsonValueListIsEmpty (& items ) && !jperIsError (res ))
1805+ JsonValueListConcat (found , prependKey (& key , & items ));
17041806 }
17051807 }
17061808 }
@@ -1747,15 +1849,15 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
17471849 res = recursiveExecuteNext (cxt , jsp , & elem , jb , found , true);
17481850
17491851 if (res == jperOk && !found )
1750- break ;
1852+ break ;
17511853 }
17521854
17531855 if (jb -> type == jbvArray || jb -> type == jbvObject )
17541856 jb = JsonbWrapInBinary (jb , & jbvbuf );
17551857
17561858 if (jb -> type == jbvBinary )
17571859 res = recursiveAny (cxt , hasNext ? & elem : NULL , jb , found ,
1758- 1 ,
1860+ jspOutPath ( jsp ), 1 ,
17591861 jsp -> content .anybounds .first ,
17601862 jsp -> content .anybounds .last );
17611863 break ;
0 commit comments