@@ -336,7 +336,7 @@ static JsonPathBool executeNestedBoolItem(JsonPathExecContext *cxt,
336
336
JsonPathItem * jsp , JsonItem * jb );
337
337
static JsonPathExecResult executeAnyItem (JsonPathExecContext * cxt ,
338
338
JsonPathItem * jsp , JsonbContainer * jbc , JsonValueList * found ,
339
- uint32 level , uint32 first , uint32 last ,
339
+ bool outPath , uint32 level , uint32 first , uint32 last ,
340
340
bool ignoreStructuralErrors , bool unwrapNext );
341
341
static JsonPathBool executePredicate (JsonPathExecContext * cxt ,
342
342
JsonPathItem * pred , JsonPathItem * larg ,
@@ -405,6 +405,7 @@ static JsonBaseObjectInfo setBaseObject(JsonPathExecContext *cxt,
405
405
JsonItem * jsi , int32 id );
406
406
static void JsonValueListClear (JsonValueList * jvl );
407
407
static void JsonValueListAppend (JsonValueList * jvl , JsonItem * jbv );
408
+ static void JsonValueListConcat (JsonValueList * jvl1 , JsonValueList jvl2 );
408
409
static int JsonValueListLength (const JsonValueList * jvl );
409
410
static bool JsonValueListIsEmpty (JsonValueList * jvl );
410
411
static JsonItem * JsonValueListHead (JsonValueList * jvl );
@@ -424,6 +425,10 @@ static JsonItem *wrapItem(JsonItem *jbv, bool isJsonb);
424
425
static text * JsonItemUnquoteText (JsonItem * jsi , bool isJsonb );
425
426
static JsonItem * wrapJsonObjectOrArray (JsonItem * js , JsonItem * buf ,
426
427
bool isJsonb );
428
+ static void appendWrappedItems (JsonValueList * found , JsonValueList * items ,
429
+ bool isJsonb );
430
+ static JsonValueList prependKey (char * keystr , int keylen ,
431
+ const JsonValueList * items , bool isJsonb );
427
432
428
433
static JsonItem * getJsonObjectKey (JsonItem * jb , char * keystr , int keylen ,
429
434
bool isJsonb , JsonItem * res );
@@ -978,7 +983,18 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
978
983
979
984
if (jb != NULL )
980
985
{
981
- res = executeNextItem (cxt , jsp , NULL , jb , found , true);
986
+ JsonValueList items = {0 };
987
+ JsonValueList * pitems = found ;
988
+
989
+ if (pitems && jspOutPath (jsp ))
990
+ pitems = & items ;
991
+
992
+ res = executeNextItem (cxt , jsp , NULL , jb , pitems , true);
993
+
994
+ if (!JsonValueListIsEmpty (& items ) && !jperIsError (res ))
995
+ JsonValueListConcat (found , prependKey (key , keylen ,
996
+ & items ,
997
+ cxt -> isJsonb ));
982
998
}
983
999
else if (!jspIgnoreStructuralErrors (cxt ))
984
1000
{
@@ -1040,10 +1056,19 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
1040
1056
case jpiAnyArray :
1041
1057
if (JsonbType (jb ) == jbvArray )
1042
1058
{
1059
+ JsonValueList items = {0 };
1060
+ JsonValueList * pitems = found ;
1061
+ bool wrap = pitems && jspOutPath (jsp );
1043
1062
bool hasNext = jspGetNext (jsp , & elem );
1044
1063
1064
+ if (wrap )
1065
+ pitems = & items ;
1066
+
1045
1067
res = executeItemUnwrapTargetArray (cxt , hasNext ? & elem : NULL ,
1046
- jb , found , jspAutoUnwrap (cxt ));
1068
+ jb , pitems , jspAutoUnwrap (cxt ));
1069
+
1070
+ if (wrap && !jperIsError (res ))
1071
+ appendWrappedItems (found , & items , cxt -> isJsonb );
1047
1072
}
1048
1073
else if (jspAutoWrap (cxt ))
1049
1074
res = executeNextItem (cxt , jsp , NULL , jb , found , true);
@@ -1059,6 +1084,12 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
1059
1084
int innermostArraySize = cxt -> innermostArraySize ;
1060
1085
int i ;
1061
1086
JsonItem bin ;
1087
+ JsonValueList items = {0 };
1088
+ JsonValueList * pitems = found ;
1089
+ bool wrap = pitems && jspOutPath (jsp );
1090
+
1091
+ if (wrap )
1092
+ pitems = & items ;
1062
1093
1063
1094
jb = wrapJsonObjectOrArray (jb , & bin , cxt -> isJsonb );
1064
1095
@@ -1094,7 +1125,7 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
1094
1125
1095
1126
if (index_from <= 0 && index_to >= 0 )
1096
1127
{
1097
- res = executeNextItem (cxt , jsp , NULL , jb , found ,
1128
+ res = executeNextItem (cxt , jsp , NULL , jb , pitems ,
1098
1129
true);
1099
1130
if (jperIsError (res ))
1100
1131
return res ;
@@ -1137,7 +1168,7 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
1137
1168
1138
1169
if (!index )
1139
1170
{
1140
- res = executeNextItem (cxt , jsp , NULL , jb , found ,
1171
+ res = executeNextItem (cxt , jsp , NULL , jb , pitems ,
1141
1172
true);
1142
1173
if (jperIsError (res ))
1143
1174
return res ;
@@ -1158,7 +1189,7 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
1158
1189
1159
1190
if (val )
1160
1191
{
1161
- res = executeNextItem (cxt , jsp , NULL , val , found ,
1192
+ res = executeNextItem (cxt , jsp , NULL , val , pitems ,
1162
1193
true);
1163
1194
if (jperIsError (res ))
1164
1195
return res ;
@@ -1178,6 +1209,9 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
1178
1209
}
1179
1210
1180
1211
cxt -> innermostArraySize = innermostArraySize ;
1212
+
1213
+ if (wrap && !jperIsError (res ))
1214
+ appendWrappedItems (found , & items , cxt -> isJsonb );
1181
1215
}
1182
1216
else if (JsonbType (jb ) == jbvArray || jspAutoWrap (cxt ))
1183
1217
{
@@ -1186,8 +1220,14 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
1186
1220
int size = JsonxArraySize (jb , cxt -> isJsonb );
1187
1221
bool binary = JsonItemIsBinary (jb );
1188
1222
bool singleton = size < 0 ;
1223
+ JsonValueList items = {0 };
1224
+ JsonValueList * pitems = found ;
1225
+ bool wrap = pitems && jspOutPath (jsp );
1189
1226
bool hasNext = jspGetNext (jsp , & elem );
1190
1227
1228
+ if (wrap )
1229
+ pitems = & items ;
1230
+
1191
1231
if (singleton )
1192
1232
size = 1 ;
1193
1233
@@ -1260,7 +1300,7 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
1260
1300
if (!hasNext && !found )
1261
1301
return jperOk ;
1262
1302
1263
- res = executeNextItem (cxt , jsp , & elem , jsi , found ,
1303
+ res = executeNextItem (cxt , jsp , & elem , jsi , pitems ,
1264
1304
true);
1265
1305
1266
1306
if (jperIsError (res ))
@@ -1278,6 +1318,9 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
1278
1318
}
1279
1319
1280
1320
cxt -> innermostArraySize = innermostArraySize ;
1321
+
1322
+ if (wrap && !jperIsError (res ))
1323
+ appendWrappedItems (found , & items , cxt -> isJsonb );
1281
1324
}
1282
1325
else if (!jspIgnoreStructuralErrors (cxt ))
1283
1326
{
@@ -1325,7 +1368,7 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
1325
1368
1326
1369
return executeAnyItem
1327
1370
(cxt , hasNext ? & elem : NULL ,
1328
- JsonItemBinary (jb ).data , found , 1 , 1 , 1 ,
1371
+ JsonItemBinary (jb ).data , found , jspOutPath ( jsp ), 1 , 1 , 1 ,
1329
1372
false, jspAutoUnwrap (cxt ));
1330
1373
}
1331
1374
else if (unwrap && JsonbType (jb ) == jbvArray )
@@ -1403,8 +1446,7 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
1403
1446
1404
1447
savedIgnoreStructuralErrors = cxt -> ignoreStructuralErrors ;
1405
1448
cxt -> ignoreStructuralErrors = true;
1406
- res = executeNextItem (cxt , jsp , & elem ,
1407
- jb , found , true);
1449
+ res = executeNextItem (cxt , jsp , & elem , jb , found , true);
1408
1450
cxt -> ignoreStructuralErrors = savedIgnoreStructuralErrors ;
1409
1451
1410
1452
if (res == jperOk && !found )
@@ -1414,7 +1456,7 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
1414
1456
if (JsonItemIsBinary (jb ))
1415
1457
res = executeAnyItem
1416
1458
(cxt , hasNext ? & elem : NULL ,
1417
- JsonItemBinary (jb ).data , found ,
1459
+ JsonItemBinary (jb ).data , found , jspOutPath ( jsp ),
1418
1460
1 ,
1419
1461
jsp -> content .anybounds .first ,
1420
1462
jsp -> content .anybounds .last ,
@@ -1950,7 +1992,7 @@ executeItemUnwrapTargetArray(JsonPathExecContext *cxt, JsonPathItem *jsp,
1950
1992
}
1951
1993
1952
1994
return executeAnyItem
1953
- (cxt , jsp , JsonItemBinary (jb ).data , found , 1 , 1 , 1 ,
1995
+ (cxt , jsp , JsonItemBinary (jb ).data , found , false, 1 , 1 , 1 ,
1954
1996
false, unwrapElements );
1955
1997
}
1956
1998
@@ -2212,19 +2254,28 @@ executeNestedBoolItem(JsonPathExecContext *cxt, JsonPathItem *jsp,
2212
2254
*/
2213
2255
static JsonPathExecResult
2214
2256
executeAnyItem (JsonPathExecContext * cxt , JsonPathItem * jsp , JsonbContainer * jbc ,
2215
- JsonValueList * found , uint32 level , uint32 first , uint32 last ,
2216
- bool ignoreStructuralErrors , bool unwrapNext )
2257
+ JsonValueList * found , bool outPath , uint32 level , uint32 first ,
2258
+ uint32 last , bool ignoreStructuralErrors , bool unwrapNext )
2217
2259
{
2218
2260
JsonPathExecResult res = jperNotFound ;
2219
2261
JsonxIterator it ;
2220
2262
int32 r ;
2221
2263
JsonItem v ;
2264
+ char * keyStr = NULL ;
2265
+ int keyLen = 0 ;
2266
+ JsonValueList items = {0 };
2267
+ JsonValueList * pitems = found ;
2268
+ bool isObject ;
2222
2269
2223
2270
check_stack_depth ();
2224
2271
2225
2272
if (level > last )
2226
2273
return res ;
2227
2274
2275
+ if (pitems && outPath )
2276
+ pitems = & items ;
2277
+
2278
+ isObject = JsonContainerIsObject (jbc );
2228
2279
2229
2280
JsonxIteratorInit (& it , jbc , cxt -> isJsonb );
2230
2281
@@ -2235,8 +2286,13 @@ executeAnyItem(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbContainer *jbc,
2235
2286
{
2236
2287
if (r == WJB_KEY )
2237
2288
{
2289
+ keyStr = JsonItemString (& v ).val ;
2290
+ keyLen = JsonItemString (& v ).len ;
2238
2291
r = JsonxIteratorNext (& it , JsonItemJbv (& v ), true);
2239
2292
Assert (r == WJB_VALUE );
2293
+
2294
+ if (pitems == & items )
2295
+ JsonValueListClear (pitems );
2240
2296
}
2241
2297
2242
2298
if (r == WJB_VALUE || r == WJB_ELEM )
@@ -2255,11 +2311,11 @@ executeAnyItem(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbContainer *jbc,
2255
2311
2256
2312
savedIgnoreStructuralErrors = cxt -> ignoreStructuralErrors ;
2257
2313
cxt -> ignoreStructuralErrors = true;
2258
- res = executeItemOptUnwrapTarget (cxt , jsp , & v , found , unwrapNext );
2314
+ res = executeItemOptUnwrapTarget (cxt , jsp , & v , pitems , unwrapNext );
2259
2315
cxt -> ignoreStructuralErrors = savedIgnoreStructuralErrors ;
2260
2316
}
2261
2317
else
2262
- res = executeItemOptUnwrapTarget (cxt , jsp , & v , found , unwrapNext );
2318
+ res = executeItemOptUnwrapTarget (cxt , jsp , & v , pitems , unwrapNext );
2263
2319
2264
2320
if (jperIsError (res ))
2265
2321
break ;
@@ -2268,15 +2324,15 @@ executeAnyItem(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbContainer *jbc,
2268
2324
break ;
2269
2325
}
2270
2326
else if (found )
2271
- JsonValueListAppend (found , copyJsonItem (& v ));
2327
+ JsonValueListAppend (pitems , copyJsonItem (& v ));
2272
2328
else
2273
2329
return jperOk ;
2274
2330
}
2275
2331
2276
2332
if (level < last && JsonItemIsBinary (& v ))
2277
2333
{
2278
2334
res = executeAnyItem
2279
- (cxt , jsp , JsonItemBinary (& v ).data , found ,
2335
+ (cxt , jsp , JsonItemBinary (& v ).data , pitems , outPath ,
2280
2336
level + 1 , first , last ,
2281
2337
ignoreStructuralErrors , unwrapNext );
2282
2338
@@ -2287,8 +2343,15 @@ executeAnyItem(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbContainer *jbc,
2287
2343
break ;
2288
2344
}
2289
2345
}
2346
+
2347
+ if (isObject && !JsonValueListIsEmpty (& items ) && !jperIsError (res ))
2348
+ JsonValueListConcat (found , prependKey (keyStr , keyLen ,
2349
+ & items , cxt -> isJsonb ));
2290
2350
}
2291
2351
2352
+ if (!isObject && !JsonValueListIsEmpty (& items ) && !jperIsError (res ))
2353
+ appendWrappedItems (found , & items , cxt -> isJsonb );
2354
+
2292
2355
return res ;
2293
2356
}
2294
2357
@@ -3347,6 +3410,24 @@ JsonValueListAppend(JsonValueList *jvl, JsonItem *jsi)
3347
3410
jvl -> length ++ ;
3348
3411
}
3349
3412
3413
+ static void
3414
+ JsonValueListConcat (JsonValueList * jvl1 , JsonValueList jvl2 )
3415
+ {
3416
+ if (!jvl1 -> tail )
3417
+ {
3418
+ Assert (!jvl1 -> head );
3419
+ Assert (!jvl1 -> length );
3420
+ * jvl1 = jvl2 ;
3421
+ }
3422
+ else if (jvl2 .head )
3423
+ {
3424
+ Assert (jvl1 -> head );
3425
+ jvl1 -> tail -> next = jvl2 .head ;
3426
+ jvl1 -> tail = jvl2 .tail ;
3427
+ jvl1 -> length += jvl2 .length ;
3428
+ }
3429
+ }
3430
+
3350
3431
static int
3351
3432
JsonValueListLength (const JsonValueList * jvl )
3352
3433
{
@@ -3733,6 +3814,51 @@ wrapItemsInArray(const JsonValueList *items, bool isJsonb)
3733
3814
return push (& ps , WJB_END_ARRAY , NULL );
3734
3815
}
3735
3816
3817
+ static void
3818
+ appendWrappedItems (JsonValueList * found , JsonValueList * items , bool isJsonb )
3819
+ {
3820
+ JsonbValue * wrapped = wrapItemsInArray (items , isJsonb );
3821
+ JsonItem * jsi = palloc (sizeof (* jsi ));
3822
+
3823
+ JsonValueListAppend (found , JsonbValueToJsonItem (wrapped , jsi ));
3824
+ }
3825
+
3826
+ static JsonValueList
3827
+ prependKey (char * keystr , int keylen , const JsonValueList * items , bool isJsonb )
3828
+ {
3829
+ JsonValueList objs = {0 };
3830
+ JsonValueListIterator it ;
3831
+ JsonItem * val ;
3832
+ JsonbValue key ;
3833
+
3834
+ key .type = jbvString ;
3835
+ key .val .string .val = keystr ;
3836
+ key .val .string .len = keylen ;
3837
+
3838
+ JsonValueListInitIterator (items , & it );
3839
+
3840
+ while ((val = JsonValueListNext (items , & it )))
3841
+ {
3842
+ JsonbValue * obj ;
3843
+ JsonbValue valbuf ;
3844
+ JsonItem bin ;
3845
+ JsonItem * jsi = palloc (sizeof (* jsi ));
3846
+ JsonbParseState * ps = NULL ;
3847
+
3848
+ if (JsonItemIsObject (val ) || JsonItemIsArray (val ))
3849
+ val = JsonxWrapInBinary (val , & bin , isJsonb );
3850
+
3851
+ pushJsonbValue (& ps , WJB_BEGIN_OBJECT , NULL );
3852
+ pushJsonbValue (& ps , WJB_KEY , & key );
3853
+ pushJsonbValue (& ps , WJB_VALUE , JsonItemToJsonbValue (val , & valbuf ));
3854
+ obj = pushJsonbValue (& ps , WJB_END_OBJECT , NULL );
3855
+
3856
+ JsonValueListAppend (& objs , JsonbValueToJsonItem (obj , jsi ));
3857
+ }
3858
+
3859
+ return objs ;
3860
+ }
3861
+
3736
3862
static void
3737
3863
pushJsonItem (JsonItemStack * stack , JsonItemStackEntry * entry , JsonItem * item ,
3738
3864
JsonBaseObjectInfo * base )
0 commit comments