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

Commit d3c7b27

Browse files
author
Nikita Glukhov
committed
WIP: Add jsonpath branch returning
1 parent 809c418 commit d3c7b27

File tree

6 files changed

+225
-19
lines changed

6 files changed

+225
-19
lines changed

src/backend/utils/adt/jsonpath.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,13 @@
2121
/*****************************INPUT/OUTPUT************************************/
2222

2323
static inline int32
24-
appendJsonPathItemHeader(StringInfo buf, JsonPathItemType type)
24+
appendJsonPathItemHeader(StringInfo buf, JsonPathItemType type, char flags)
2525
{
2626
int32 nextPos = 0; /* fake value */
2727
int32 nextOffs;
2828

2929
appendStringInfoChar(buf, (char) type);
30+
appendStringInfoChar(buf, (char) flags);
3031
alignStringInfoInt(buf);
3132

3233
nextOffs = buf->len;
@@ -52,7 +53,7 @@ copyJsonPathItem(StringInfo buf, JsonPathItem *item, int level,
5253

5354
check_stack_depth();
5455

55-
nextOffs = appendJsonPathItemHeader(buf, item->type);
56+
nextOffs = appendJsonPathItemHeader(buf, item->type, item->flags);
5657

5758
switch (item->type)
5859
{
@@ -342,7 +343,7 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item,
342343
pos = copyJsonPath(buf, item->value.binary, nestingLevel, &last, &next);
343344
else
344345
{
345-
next = appendJsonPathItemHeader(buf, item->type);
346+
next = appendJsonPathItemHeader(buf, item->type, item->flags);
346347
last = pos;
347348
}
348349

@@ -1039,6 +1040,7 @@ jspInitByBuffer(JsonPathItem *v, char *base, int32 pos)
10391040
v->base = base + pos;
10401041

10411042
read_byte(v->type, base, pos);
1043+
read_byte(v->flags, base, pos);
10421044
pos = INTALIGN((uintptr_t)(base + pos)) - (uintptr_t) base;
10431045
read_int32(v->nextPos, base, pos);
10441046

@@ -1344,6 +1346,7 @@ jspInitParseItem(JsonPathParseItem *item, JsonPathItemType type,
13441346
JsonPathParseItem *next)
13451347
{
13461348
item->type = type;
1349+
item->flags = 0;
13471350
item->next = next;
13481351
}
13491352

src/backend/utils/adt/jsonpath_exec.c

Lines changed: 117 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -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
*/
10181045
static JsonPathExecResult
10191046
recursiveAny(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

Comments
 (0)