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

Commit 1a1df16

Browse files
author
Nikita Glukhov
committed
Add jsonpath support for JsonbValue objects and arrays
1 parent cc71988 commit 1a1df16

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
@@ -441,9 +441,6 @@ checkEquality(JsonbValue *jb1, JsonbValue *jb2, bool not)
441441
return jperError;
442442
}
443443

444-
if (jb1->type == jbvBinary)
445-
return jperError;
446-
447444
switch (jb1->type)
448445
{
449446
case jbvNull:
@@ -494,8 +491,14 @@ checkEquality(JsonbValue *jb1, JsonbValue *jb2, bool not)
494491
jb2->val.datetime.value));
495492
break;
496493
}
494+
495+
case jbvBinary:
496+
case jbvObject:
497+
case jbvArray:
498+
return jperError;
499+
497500
default:
498-
elog(ERROR,"1Wrong state");
501+
elog(ERROR, "Unknown jsonb value type %d", jb1->type);
499502
}
500503

501504
return (not ^ eq) ? jperOk : jperNotFound;
@@ -1167,6 +1170,10 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
11671170
if (JsonbType(jb) == jbvObject)
11681171
{
11691172
JsonbValue *v, key;
1173+
JsonbValue obj;
1174+
1175+
if (jb->type == jbvObject)
1176+
jb = JsonbWrapInBinary(jb, &obj);
11701177

11711178
key.type = jbvString;
11721179
key.val.string.val = jspGetString(jsp, &key.val.string.len);
@@ -1216,18 +1223,16 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
12161223
case jpiAnyArray:
12171224
if (JsonbType(jb) == jbvArray)
12181225
{
1219-
JsonbIterator *it;
1220-
int32 r;
1221-
JsonbValue v;
1222-
12231226
hasNext = jspGetNext(jsp, &elem);
1224-
it = JsonbIteratorInit(jb->val.binary.data);
12251227

1226-
while((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
1228+
if (jb->type == jbvArray)
12271229
{
1228-
if (r == WJB_ELEM)
1230+
JsonbValue *el = jb->val.array.elems;
1231+
JsonbValue *last_el = el + jb->val.array.nElems;
1232+
1233+
for (; el < last_el; el++)
12291234
{
1230-
res = recursiveExecuteNext(cxt, jsp, &elem, &v, found, true);
1235+
res = recursiveExecuteNext(cxt, jsp, &elem, el, found, true);
12311236

12321237
if (jperIsError(res))
12331238
break;
@@ -1236,6 +1241,28 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
12361241
break;
12371242
}
12381243
}
1244+
else
1245+
{
1246+
JsonbValue v;
1247+
JsonbIterator *it;
1248+
JsonbIteratorToken r;
1249+
1250+
it = JsonbIteratorInit(jb->val.binary.data);
1251+
1252+
while((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
1253+
{
1254+
if (r == WJB_ELEM)
1255+
{
1256+
res = recursiveExecuteNext(cxt, jsp, &elem, &v, found, true);
1257+
1258+
if (jperIsError(res))
1259+
break;
1260+
1261+
if (res == jperOk && !found)
1262+
break;
1263+
}
1264+
}
1265+
}
12391266
}
12401267
else
12411268
res = jperMakeError(ERRCODE_JSON_ARRAY_NOT_FOUND);
@@ -1247,6 +1274,7 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
12471274
int innermostArraySize = cxt->innermostArraySize;
12481275
int i;
12491276
int size = JsonbArraySize(jb);
1277+
bool binary = jb->type == jbvBinary;
12501278

12511279
cxt->innermostArraySize = size; /* for LAST evaluation */
12521280

@@ -1295,14 +1323,16 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
12951323

12961324
for (index = index_from; index <= index_to; index++)
12971325
{
1298-
JsonbValue *v =
1326+
JsonbValue *v = binary ?
12991327
getIthJsonbValueFromContainer(jb->val.binary.data,
1300-
(uint32) index);
1328+
(uint32) index) :
1329+
&jb->val.array.elems[index];
13011330

13021331
if (v == NULL)
13031332
continue;
13041333

1305-
res = recursiveExecuteNext(cxt, jsp, &elem, v, found, false);
1334+
res = recursiveExecuteNext(cxt, jsp, &elem, v, found,
1335+
!binary);
13061336

13071337
if (jperIsError(res))
13081338
break;
@@ -1360,6 +1390,10 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
13601390
JsonbIterator *it;
13611391
int32 r;
13621392
JsonbValue v;
1393+
JsonbValue bin;
1394+
1395+
if (jb->type == jbvObject)
1396+
jb = JsonbWrapInBinary(jb, &bin);
13631397

13641398
hasNext = jspGetNext(jsp, &elem);
13651399
it = JsonbIteratorInit(jb->val.binary.data);
@@ -1409,25 +1443,30 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
14091443
res = recursiveExecuteNext(cxt, jsp, NULL, jb, found, true);
14101444
break;
14111445
case jpiAny:
1412-
{
1413-
bool hasNext = jspGetNext(jsp, &elem);
1414-
1415-
/* first try without any intermediate steps */
1416-
if (jsp->content.anybounds.first == 0)
14171446
{
1418-
res = recursiveExecuteNext(cxt, jsp, &elem, jb, found, true);
1447+
JsonbValue jbvbuf;
14191448

1420-
if (res == jperOk && !found)
1421-
break;
1422-
}
1449+
hasNext = jspGetNext(jsp, &elem);
14231450

1424-
if (jb->type == jbvBinary)
1425-
res = recursiveAny(cxt, hasNext ? &elem : NULL, jb, found,
1426-
1,
1427-
jsp->content.anybounds.first,
1428-
jsp->content.anybounds.last);
1429-
break;
1430-
}
1451+
/* first try without any intermediate steps */
1452+
if (jsp->content.anybounds.first == 0)
1453+
{
1454+
res = recursiveExecuteNext(cxt, jsp, &elem, jb, found, true);
1455+
1456+
if (res == jperOk && !found)
1457+
break;
1458+
}
1459+
1460+
if (jb->type == jbvArray || jb->type == jbvObject)
1461+
jb = JsonbWrapInBinary(jb, &jbvbuf);
1462+
1463+
if (jb->type == jbvBinary)
1464+
res = recursiveAny(cxt, hasNext ? &elem : NULL, jb, found,
1465+
1,
1466+
jsp->content.anybounds.first,
1467+
jsp->content.anybounds.last);
1468+
break;
1469+
}
14311470
case jpiExists:
14321471
jspGetArg(jsp, &elem);
14331472
res = recursiveExecute(cxt, &elem, jb, NULL);
@@ -1688,6 +1727,7 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
16881727
else
16891728
{
16901729
int32 r;
1730+
JsonbValue bin;
16911731
JsonbValue key;
16921732
JsonbValue val;
16931733
JsonbValue obj;
@@ -1698,7 +1738,9 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
16981738

16991739
hasNext = jspGetNext(jsp, &elem);
17001740

1701-
if (!JsonContainerSize(jb->val.binary.data))
1741+
if (jb->type == jbvBinary
1742+
? !JsonContainerSize(jb->val.binary.data)
1743+
: !jb->val.object.nPairs)
17021744
{
17031745
res = jperNotFound;
17041746
break;
@@ -1715,6 +1757,9 @@ recursiveExecuteNoUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
17151757
valstr.val.string.val = "value";
17161758
valstr.val.string.len = 5;
17171759

1760+
if (jb->type == jbvObject)
1761+
jb = JsonbWrapInBinary(jb, &bin);
1762+
17181763
it = JsonbIteratorInit(jb->val.binary.data);
17191764

17201765
while ((r = JsonbIteratorNext(&it, &key, true)) != WJB_DONE)
@@ -1774,24 +1819,43 @@ recursiveExecuteUnwrap(JsonPathExecContext *cxt, JsonPathItem *jsp,
17741819
{
17751820
if (cxt->lax && JsonbType(jb) == jbvArray)
17761821
{
1777-
JsonbValue v;
1778-
JsonbIterator *it;
1779-
JsonbIteratorToken tok;
17801822
JsonPathExecResult res = jperNotFound;
17811823

1782-
it = JsonbIteratorInit(jb->val.binary.data);
1783-
1784-
while ((tok = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
1824+
if (jb->type == jbvArray)
17851825
{
1786-
if (tok == WJB_ELEM)
1826+
JsonbValue *elem = jb->val.array.elems;
1827+
JsonbValue *last = elem + jb->val.array.nElems;
1828+
1829+
for (; elem < last; elem++)
17871830
{
1788-
res = recursiveExecuteNoUnwrap(cxt, jsp, &v, found);
1831+
res = recursiveExecuteNoUnwrap(cxt, jsp, elem, found);
1832+
17891833
if (jperIsError(res))
17901834
break;
17911835
if (res == jperOk && !found)
17921836
break;
17931837
}
17941838
}
1839+
else
1840+
{
1841+
JsonbValue v;
1842+
JsonbIterator *it;
1843+
JsonbIteratorToken tok;
1844+
1845+
it = JsonbIteratorInit(jb->val.binary.data);
1846+
1847+
while ((tok = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
1848+
{
1849+
if (tok == WJB_ELEM)
1850+
{
1851+
res = recursiveExecuteNoUnwrap(cxt, jsp, &v, found);
1852+
if (jperIsError(res))
1853+
break;
1854+
if (res == jperOk && !found)
1855+
break;
1856+
}
1857+
}
1858+
}
17951859

17961860
return res;
17971861
}
@@ -2139,10 +2203,15 @@ wrapItemsInArray(const JsonValueList *items)
21392203

21402204
while ((jbv = JsonValueListNext(items, &it)))
21412205
{
2206+
JsonbValue bin;
2207+
21422208
if (jbv->type == jbvBinary &&
21432209
JsonContainerIsScalar(jbv->val.binary.data))
21442210
JsonbExtractScalar(jbv->val.binary.data, jbv);
21452211

2212+
if (jbv->type == jbvObject || jbv->type == jbvArray)
2213+
jbv = JsonbWrapInBinary(jbv, &bin);
2214+
21462215
pushJsonbValue(&ps, WJB_ELEM, jbv);
21472216
}
21482217

0 commit comments

Comments
 (0)