Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 889305d

Browse files
author
Nikita Glukhov
committed
WIP: Add jsonpath branch returning
1 parent ff88671 commit 889305d

File tree

5 files changed

+245
-19
lines changed

5 files changed

+245
-19
lines changed

src/backend/utils/adt/jsonpath_exec.c

Lines changed: 144 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ static JsonPathBool executeNestedBoolItem(JsonPathExecContext *cxt,
336336
JsonPathItem *jsp, JsonItem *jb);
337337
static JsonPathExecResult executeAnyItem(JsonPathExecContext *cxt,
338338
JsonPathItem *jsp, JsonbContainer *jbc, JsonValueList *found,
339-
uint32 level, uint32 first, uint32 last,
339+
bool outPath, uint32 level, uint32 first, uint32 last,
340340
bool ignoreStructuralErrors, bool unwrapNext);
341341
static JsonPathBool executePredicate(JsonPathExecContext *cxt,
342342
JsonPathItem *pred, JsonPathItem *larg,
@@ -405,6 +405,7 @@ static JsonBaseObjectInfo setBaseObject(JsonPathExecContext *cxt,
405405
JsonItem *jsi, int32 id);
406406
static void JsonValueListClear(JsonValueList *jvl);
407407
static void JsonValueListAppend(JsonValueList *jvl, JsonItem *jbv);
408+
static void JsonValueListConcat(JsonValueList *jvl1, JsonValueList jvl2);
408409
static int JsonValueListLength(const JsonValueList *jvl);
409410
static bool JsonValueListIsEmpty(JsonValueList *jvl);
410411
static JsonItem *JsonValueListHead(JsonValueList *jvl);
@@ -424,6 +425,10 @@ static JsonItem *wrapItem(JsonItem *jbv, bool isJsonb);
424425
static text *JsonItemUnquoteText(JsonItem *jsi, bool isJsonb);
425426
static JsonItem *wrapJsonObjectOrArray(JsonItem *js, JsonItem *buf,
426427
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);
427432

428433
static JsonItem *getJsonObjectKey(JsonItem *jb, char *keystr, int keylen,
429434
bool isJsonb, JsonItem *res);
@@ -978,7 +983,18 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
978983

979984
if (jb != NULL)
980985
{
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));
982998
}
983999
else if (!jspIgnoreStructuralErrors(cxt))
9841000
{
@@ -1040,10 +1056,19 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
10401056
case jpiAnyArray:
10411057
if (JsonbType(jb) == jbvArray)
10421058
{
1059+
JsonValueList items = {0};
1060+
JsonValueList *pitems = found;
1061+
bool wrap = pitems && jspOutPath(jsp);
10431062
bool hasNext = jspGetNext(jsp, &elem);
10441063

1064+
if (wrap)
1065+
pitems = &items;
1066+
10451067
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);
10471072
}
10481073
else if (jspAutoWrap(cxt))
10491074
res = executeNextItem(cxt, jsp, NULL, jb, found, true);
@@ -1059,6 +1084,12 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
10591084
int innermostArraySize = cxt->innermostArraySize;
10601085
int i;
10611086
JsonItem bin;
1087+
JsonValueList items = {0};
1088+
JsonValueList *pitems = found;
1089+
bool wrap = pitems && jspOutPath(jsp);
1090+
1091+
if (wrap)
1092+
pitems = &items;
10621093

10631094
jb = wrapJsonObjectOrArray(jb, &bin, cxt->isJsonb);
10641095

@@ -1094,7 +1125,7 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
10941125

10951126
if (index_from <= 0 && index_to >= 0)
10961127
{
1097-
res = executeNextItem(cxt, jsp, NULL, jb, found,
1128+
res = executeNextItem(cxt, jsp, NULL, jb, pitems,
10981129
true);
10991130
if (jperIsError(res))
11001131
return res;
@@ -1137,7 +1168,7 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
11371168

11381169
if (!index)
11391170
{
1140-
res = executeNextItem(cxt, jsp, NULL, jb, found,
1171+
res = executeNextItem(cxt, jsp, NULL, jb, pitems,
11411172
true);
11421173
if (jperIsError(res))
11431174
return res;
@@ -1158,7 +1189,7 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
11581189

11591190
if (val)
11601191
{
1161-
res = executeNextItem(cxt, jsp, NULL, val, found,
1192+
res = executeNextItem(cxt, jsp, NULL, val, pitems,
11621193
true);
11631194
if (jperIsError(res))
11641195
return res;
@@ -1178,6 +1209,9 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
11781209
}
11791210

11801211
cxt->innermostArraySize = innermostArraySize;
1212+
1213+
if (wrap && !jperIsError(res))
1214+
appendWrappedItems(found, &items, cxt->isJsonb);
11811215
}
11821216
else if (JsonbType(jb) == jbvArray || jspAutoWrap(cxt))
11831217
{
@@ -1186,8 +1220,14 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
11861220
int size = JsonxArraySize(jb, cxt->isJsonb);
11871221
bool binary = JsonItemIsBinary(jb);
11881222
bool singleton = size < 0;
1223+
JsonValueList items = {0};
1224+
JsonValueList *pitems = found;
1225+
bool wrap = pitems && jspOutPath(jsp);
11891226
bool hasNext = jspGetNext(jsp, &elem);
11901227

1228+
if (wrap)
1229+
pitems = &items;
1230+
11911231
if (singleton)
11921232
size = 1;
11931233

@@ -1260,7 +1300,7 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
12601300
if (!hasNext && !found)
12611301
return jperOk;
12621302

1263-
res = executeNextItem(cxt, jsp, &elem, jsi, found,
1303+
res = executeNextItem(cxt, jsp, &elem, jsi, pitems,
12641304
true);
12651305

12661306
if (jperIsError(res))
@@ -1278,6 +1318,9 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
12781318
}
12791319

12801320
cxt->innermostArraySize = innermostArraySize;
1321+
1322+
if (wrap && !jperIsError(res))
1323+
appendWrappedItems(found, &items, cxt->isJsonb);
12811324
}
12821325
else if (!jspIgnoreStructuralErrors(cxt))
12831326
{
@@ -1325,7 +1368,7 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
13251368

13261369
return executeAnyItem
13271370
(cxt, hasNext ? &elem : NULL,
1328-
JsonItemBinary(jb).data, found, 1, 1, 1,
1371+
JsonItemBinary(jb).data, found, jspOutPath(jsp), 1, 1, 1,
13291372
false, jspAutoUnwrap(cxt));
13301373
}
13311374
else if (unwrap && JsonbType(jb) == jbvArray)
@@ -1403,8 +1446,7 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
14031446

14041447
savedIgnoreStructuralErrors = cxt->ignoreStructuralErrors;
14051448
cxt->ignoreStructuralErrors = true;
1406-
res = executeNextItem(cxt, jsp, &elem,
1407-
jb, found, true);
1449+
res = executeNextItem(cxt, jsp, &elem, jb, found, true);
14081450
cxt->ignoreStructuralErrors = savedIgnoreStructuralErrors;
14091451

14101452
if (res == jperOk && !found)
@@ -1414,7 +1456,7 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
14141456
if (JsonItemIsBinary(jb))
14151457
res = executeAnyItem
14161458
(cxt, hasNext ? &elem : NULL,
1417-
JsonItemBinary(jb).data, found,
1459+
JsonItemBinary(jb).data, found, jspOutPath(jsp),
14181460
1,
14191461
jsp->content.anybounds.first,
14201462
jsp->content.anybounds.last,
@@ -1950,7 +1992,7 @@ executeItemUnwrapTargetArray(JsonPathExecContext *cxt, JsonPathItem *jsp,
19501992
}
19511993

19521994
return executeAnyItem
1953-
(cxt, jsp, JsonItemBinary(jb).data, found, 1, 1, 1,
1995+
(cxt, jsp, JsonItemBinary(jb).data, found, false, 1, 1, 1,
19541996
false, unwrapElements);
19551997
}
19561998

@@ -2212,19 +2254,28 @@ executeNestedBoolItem(JsonPathExecContext *cxt, JsonPathItem *jsp,
22122254
*/
22132255
static JsonPathExecResult
22142256
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)
22172259
{
22182260
JsonPathExecResult res = jperNotFound;
22192261
JsonxIterator it;
22202262
int32 r;
22212263
JsonItem v;
2264+
char *keyStr = NULL;
2265+
int keyLen = 0;
2266+
JsonValueList items = {0};
2267+
JsonValueList *pitems = found;
2268+
bool isObject;
22222269

22232270
check_stack_depth();
22242271

22252272
if (level > last)
22262273
return res;
22272274

2275+
if (pitems && outPath)
2276+
pitems = &items;
2277+
2278+
isObject = JsonContainerIsObject(jbc);
22282279

22292280
JsonxIteratorInit(&it, jbc, cxt->isJsonb);
22302281

@@ -2235,8 +2286,13 @@ executeAnyItem(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbContainer *jbc,
22352286
{
22362287
if (r == WJB_KEY)
22372288
{
2289+
keyStr = JsonItemString(&v).val;
2290+
keyLen = JsonItemString(&v).len;
22382291
r = JsonxIteratorNext(&it, JsonItemJbv(&v), true);
22392292
Assert(r == WJB_VALUE);
2293+
2294+
if (pitems == &items)
2295+
JsonValueListClear(pitems);
22402296
}
22412297

22422298
if (r == WJB_VALUE || r == WJB_ELEM)
@@ -2255,11 +2311,11 @@ executeAnyItem(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbContainer *jbc,
22552311

22562312
savedIgnoreStructuralErrors = cxt->ignoreStructuralErrors;
22572313
cxt->ignoreStructuralErrors = true;
2258-
res = executeItemOptUnwrapTarget(cxt, jsp, &v, found, unwrapNext);
2314+
res = executeItemOptUnwrapTarget(cxt, jsp, &v, pitems, unwrapNext);
22592315
cxt->ignoreStructuralErrors = savedIgnoreStructuralErrors;
22602316
}
22612317
else
2262-
res = executeItemOptUnwrapTarget(cxt, jsp, &v, found, unwrapNext);
2318+
res = executeItemOptUnwrapTarget(cxt, jsp, &v, pitems, unwrapNext);
22632319

22642320
if (jperIsError(res))
22652321
break;
@@ -2268,15 +2324,15 @@ executeAnyItem(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbContainer *jbc,
22682324
break;
22692325
}
22702326
else if (found)
2271-
JsonValueListAppend(found, copyJsonItem(&v));
2327+
JsonValueListAppend(pitems, copyJsonItem(&v));
22722328
else
22732329
return jperOk;
22742330
}
22752331

22762332
if (level < last && JsonItemIsBinary(&v))
22772333
{
22782334
res = executeAnyItem
2279-
(cxt, jsp, JsonItemBinary(&v).data, found,
2335+
(cxt, jsp, JsonItemBinary(&v).data, pitems, outPath,
22802336
level + 1, first, last,
22812337
ignoreStructuralErrors, unwrapNext);
22822338

@@ -2287,8 +2343,15 @@ executeAnyItem(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbContainer *jbc,
22872343
break;
22882344
}
22892345
}
2346+
2347+
if (isObject && !JsonValueListIsEmpty(&items) && !jperIsError(res))
2348+
JsonValueListConcat(found, prependKey(keyStr, keyLen,
2349+
&items, cxt->isJsonb));
22902350
}
22912351

2352+
if (!isObject && !JsonValueListIsEmpty(&items) && !jperIsError(res))
2353+
appendWrappedItems(found, &items, cxt->isJsonb);
2354+
22922355
return res;
22932356
}
22942357

@@ -3347,6 +3410,24 @@ JsonValueListAppend(JsonValueList *jvl, JsonItem *jsi)
33473410
jvl->length++;
33483411
}
33493412

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+
33503431
static int
33513432
JsonValueListLength(const JsonValueList *jvl)
33523433
{
@@ -3733,6 +3814,51 @@ wrapItemsInArray(const JsonValueList *items, bool isJsonb)
37333814
return push(&ps, WJB_END_ARRAY, NULL);
37343815
}
37353816

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+
37363862
static void
37373863
pushJsonItem(JsonItemStack *stack, JsonItemStackEntry *entry, JsonItem *item,
37383864
JsonBaseObjectInfo *base)

0 commit comments

Comments
 (0)