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

Commit 64b46ad

Browse files
author
Nikita Glukhov
committed
Add jsonpath support for JsonbValue objects and arrays
1 parent f16965f commit 64b46ad

File tree

1 file changed

+109
-40
lines changed

1 file changed

+109
-40
lines changed

src/backend/utils/adt/jsonpath_exec.c

Lines changed: 109 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -554,9 +554,6 @@ checkEquality(JsonbValue *jb1, JsonbValue *jb2, bool not)
554554
return jperError;
555555
}
556556

557-
if (jb1->type == jbvBinary)
558-
return jperError;
559-
560557
switch (jb1->type)
561558
{
562559
case jbvNull:
@@ -588,8 +585,14 @@ checkEquality(JsonbValue *jb1, JsonbValue *jb2, bool not)
588585

589586
break;
590587
}
588+
589+
case jbvBinary:
590+
case jbvObject:
591+
case jbvArray:
592+
return jperError;
593+
591594
default:
592-
elog(ERROR,"1Wrong state");
595+
elog(ERROR, "Unknown jsonb value type %d", jb1->type);
593596
}
594597

595598
return (not ^ eq) ? jperOk : jperNotFound;
@@ -1311,6 +1314,10 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
13111314
if (JsonbType(jb) == jbvObject)
13121315
{
13131316
JsonbValue *v, key;
1317+
JsonbValue obj;
1318+
1319+
if (jb->type == jbvObject)
1320+
jb = JsonbWrapInBinary(jb, &obj);
13141321

13151322
key.type = jbvString;
13161323
key.val.string.val = jspGetString(jsp, &key.val.string.len);
@@ -1366,18 +1373,16 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
13661373
case jpiAnyArray:
13671374
if (JsonbType(jb) == jbvArray)
13681375
{
1369-
JsonbIterator *it;
1370-
int32 r;
1371-
JsonbValue v;
1372-
13731376
hasNext = jspGetNext(jsp, &elem);
1374-
it = JsonbIteratorInit(jb->val.binary.data);
13751377

1376-
while((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
1378+
if (jb->type == jbvArray)
13771379
{
1378-
if (r == WJB_ELEM)
1380+
JsonbValue *el = jb->val.array.elems;
1381+
JsonbValue *last_el = el + jb->val.array.nElems;
1382+
1383+
for (; el < last_el; el++)
13791384
{
1380-
res = recursiveExecuteNext(cxt, jsp, &elem, &v, found, true);
1385+
res = recursiveExecuteNext(cxt, jsp, &elem, el, found, true);
13811386

13821387
if (jperIsError(res))
13831388
break;
@@ -1386,6 +1391,28 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
13861391
break;
13871392
}
13881393
}
1394+
else
1395+
{
1396+
JsonbValue v;
1397+
JsonbIterator *it;
1398+
JsonbIteratorToken r;
1399+
1400+
it = JsonbIteratorInit(jb->val.binary.data);
1401+
1402+
while((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
1403+
{
1404+
if (r == WJB_ELEM)
1405+
{
1406+
res = recursiveExecuteNext(cxt, jsp, &elem, &v, found, true);
1407+
1408+
if (jperIsError(res))
1409+
break;
1410+
1411+
if (res == jperOk && !found)
1412+
break;
1413+
}
1414+
}
1415+
}
13891416
}
13901417
else
13911418
res = jperMakeError(ERRCODE_JSON_ARRAY_NOT_FOUND);
@@ -1397,6 +1424,7 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
13971424
int innermostArraySize = cxt->innermostArraySize;
13981425
int i;
13991426
int size = JsonbArraySize(jb);
1427+
bool binary = jb->type == jbvBinary;
14001428

14011429
cxt->innermostArraySize = size; /* for LAST evaluation */
14021430

@@ -1445,14 +1473,16 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
14451473

14461474
for (index = index_from; index <= index_to; index++)
14471475
{
1448-
JsonbValue *v =
1476+
JsonbValue *v = binary ?
14491477
getIthJsonbValueFromContainer(jb->val.binary.data,
1450-
(uint32) index);
1478+
(uint32) index) :
1479+
&jb->val.array.elems[index];
14511480

14521481
if (v == NULL)
14531482
continue;
14541483

1455-
res = recursiveExecuteNext(cxt, jsp, &elem, v, found, false);
1484+
res = recursiveExecuteNext(cxt, jsp, &elem, v, found,
1485+
!binary);
14561486

14571487
if (jperIsError(res))
14581488
break;
@@ -1510,6 +1540,10 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
15101540
JsonbIterator *it;
15111541
int32 r;
15121542
JsonbValue v;
1543+
JsonbValue bin;
1544+
1545+
if (jb->type == jbvObject)
1546+
jb = JsonbWrapInBinary(jb, &bin);
15131547

15141548
hasNext = jspGetNext(jsp, &elem);
15151549
it = JsonbIteratorInit(jb->val.binary.data);
@@ -1562,25 +1596,30 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
15621596
res = recursiveExecuteNext(cxt, jsp, NULL, jb, found, true);
15631597
break;
15641598
case jpiAny:
1565-
{
1566-
bool hasNext = jspGetNext(jsp, &elem);
1567-
1568-
/* first try without any intermediate steps */
1569-
if (jsp->content.anybounds.first == 0)
15701599
{
1571-
res = recursiveExecuteNext(cxt, jsp, &elem, jb, found, true);
1600+
JsonbValue jbvbuf;
15721601

1573-
if (res == jperOk && !found)
1574-
break;
1575-
}
1602+
hasNext = jspGetNext(jsp, &elem);
15761603

1577-
if (jb->type == jbvBinary)
1578-
res = recursiveAny(cxt, hasNext ? &elem : NULL, jb, found,
1579-
1,
1580-
jsp->content.anybounds.first,
1581-
jsp->content.anybounds.last);
1582-
break;
1583-
}
1604+
/* first try without any intermediate steps */
1605+
if (jsp->content.anybounds.first == 0)
1606+
{
1607+
res = recursiveExecuteNext(cxt, jsp, &elem, jb, found, true);
1608+
1609+
if (res == jperOk && !found)
1610+
break;
1611+
}
1612+
1613+
if (jb->type == jbvArray || jb->type == jbvObject)
1614+
jb = JsonbWrapInBinary(jb, &jbvbuf);
1615+
1616+
if (jb->type == jbvBinary)
1617+
res = recursiveAny(cxt, hasNext ? &elem : NULL, jb, found,
1618+
1,
1619+
jsp->content.anybounds.first,
1620+
jsp->content.anybounds.last);
1621+
break;
1622+
}
15841623
case jpiExists:
15851624
jspGetArg(jsp, &elem);
15861625

@@ -1856,6 +1895,7 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
18561895
else
18571896
{
18581897
int32 r;
1898+
JsonbValue bin;
18591899
JsonbValue key;
18601900
JsonbValue val;
18611901
JsonbValue obj;
@@ -1866,7 +1906,9 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
18661906

18671907
hasNext = jspGetNext(jsp, &elem);
18681908

1869-
if (!JsonContainerSize(jb->val.binary.data))
1909+
if (jb->type == jbvBinary
1910+
? !JsonContainerSize(jb->val.binary.data)
1911+
: !jb->val.object.nPairs)
18701912
{
18711913
res = jperNotFound;
18721914
break;
@@ -1883,6 +1925,9 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
18831925
valstr.val.string.val = "value";
18841926
valstr.val.string.len = 5;
18851927

1928+
if (jb->type == jbvObject)
1929+
jb = JsonbWrapInBinary(jb, &bin);
1930+
18861931
it = JsonbIteratorInit(jb->val.binary.data);
18871932

18881933
while ((r = JsonbIteratorNext(&it, &key, true)) != WJB_DONE)
@@ -1945,24 +1990,43 @@ recursiveExecuteUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
19451990
{
19461991
if (cxt->lax && JsonbType(jb) == jbvArray)
19471992
{
1948-
JsonbValue v;
1949-
JsonbIterator *it;
1950-
JsonbIteratorToken tok;
19511993
JsonPathExecResult res = jperNotFound;
19521994

1953-
it = JsonbIteratorInit(jb->val.binary.data);
1954-
1955-
while ((tok = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
1995+
if (jb->type == jbvArray)
19561996
{
1957-
if (tok == WJB_ELEM)
1997+
JsonbValue *elem = jb->val.array.elems;
1998+
JsonbValue *last = elem + jb->val.array.nElems;
1999+
2000+
for (; elem < last; elem++)
19582001
{
1959-
res = recursiveExecuteNoUnwrap(cxt, jsp, &v, found);
2002+
res = recursiveExecuteNoUnwrap(cxt, jsp, elem, found);
2003+
19602004
if (jperIsError(res))
19612005
break;
19622006
if (res == jperOk && !found)
19632007
break;
19642008
}
19652009
}
2010+
else
2011+
{
2012+
JsonbValue v;
2013+
JsonbIterator *it;
2014+
JsonbIteratorToken tok;
2015+
2016+
it = JsonbIteratorInit(jb->val.binary.data);
2017+
2018+
while ((tok = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
2019+
{
2020+
if (tok == WJB_ELEM)
2021+
{
2022+
res = recursiveExecuteNoUnwrap(cxt, jsp, &v, found);
2023+
if (jperIsError(res))
2024+
break;
2025+
if (res == jperOk && !found)
2026+
break;
2027+
}
2028+
}
2029+
}
19662030

19672031
return res;
19682032
}
@@ -2345,10 +2409,15 @@ wrapItemsInArray(const JsonValueList *items)
23452409

23462410
while ((jbv = JsonValueListNext(items, &it)))
23472411
{
2412+
JsonbValue bin;
2413+
23482414
if (jbv->type == jbvBinary &&
23492415
JsonContainerIsScalar(jbv->val.binary.data))
23502416
JsonbExtractScalar(jbv->val.binary.data, jbv);
23512417

2418+
if (jbv->type == jbvObject || jbv->type == jbvArray)
2419+
jbv = JsonbWrapInBinary(jbv, &bin);
2420+
23522421
pushJsonbValue(&ps, WJB_ELEM, jbv);
23532422
}
23542423

0 commit comments

Comments
 (0)