Skip to content

Commit 0abe1a1

Browse files
author
Nikita Glukhov
committed
Add raw jbvArray and jbvObject support to jsonpath
1 parent 55e4b88 commit 0abe1a1

File tree

1 file changed

+85
-11
lines changed

1 file changed

+85
-11
lines changed

src/backend/utils/adt/jsonpath_exec.c

Lines changed: 85 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ static JsonbValue *JsonbInitBinary(JsonbValue *jbv, Jsonb *jb);
254254
static int JsonbType(JsonbValue *jb);
255255
static JsonbValue *getScalar(JsonbValue *scalar, enum jbvType type);
256256
static JsonbValue *wrapItemsInArray(const JsonValueList *items);
257+
static JsonbValue *wrapJsonObjectOrArray(JsonbValue *jbv, JsonbValue *buf);
257258
static int compareDatetime(Datum val1, Oid typid1, Datum val2, Oid typid2,
258259
bool useTz, bool *have_error);
259260

@@ -646,7 +647,14 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
646647
}
647648

648649
case jpiKey:
649-
if (JsonbType(jb) == jbvObject)
650+
if (jb->type == jbvObject)
651+
{
652+
JsonbValue obj;
653+
654+
jb = wrapJsonObjectOrArray(jb, &obj);
655+
return executeItemOptUnwrapTarget(cxt, jsp, jb, found, unwrap);
656+
}
657+
else if (jb->type == jbvBinary && JsonbType(jb) == jbvObject)
650658
{
651659
JsonbValue *v;
652660
JsonbValue key;
@@ -725,6 +733,7 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
725733
int innermostArraySize = cxt->innermostArraySize;
726734
int i;
727735
int size = JsonbArraySize(jb);
736+
bool binary = jb->type == jbvBinary;
728737
bool singleton = size < 0;
729738
bool hasNext = jspGetNext(jsp, &elem);
730739

@@ -784,7 +793,7 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
784793
v = jb;
785794
copy = true;
786795
}
787-
else
796+
else if (binary)
788797
{
789798
v = getIthJsonbValueFromContainer(jb->val.binary.data,
790799
(uint32) index);
@@ -794,6 +803,11 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
794803

795804
copy = false;
796805
}
806+
else
807+
{
808+
v = &jb->val.array.elems[index];
809+
copy = true;
810+
}
797811

798812
if (!hasNext && !found)
799813
return jperOk;
@@ -858,10 +872,10 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
858872
case jpiAnyKey:
859873
if (JsonbType(jb) == jbvObject)
860874
{
875+
JsonbValue bin;
861876
bool hasNext = jspGetNext(jsp, &elem);
862877

863-
if (jb->type != jbvBinary)
864-
elog(ERROR, "invalid jsonb object type: %d", jb->type);
878+
jb = wrapJsonObjectOrArray(jb, &bin);
865879

866880
return executeAnyItem
867881
(cxt, hasNext ? &elem : NULL,
@@ -926,8 +940,11 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
926940

927941
case jpiAny:
928942
{
943+
JsonbValue bin;
929944
bool hasNext = jspGetNext(jsp, &elem);
930945

946+
jb = wrapJsonObjectOrArray(jb, &bin);
947+
931948
/* first try without any intermediate steps */
932949
if (jsp->content.anybounds.first == 0)
933950
{
@@ -1127,10 +1144,34 @@ executeItemUnwrapTargetArray(JsonPathExecContext *cxt, JsonPathItem *jsp,
11271144
JsonbValue *jb, JsonValueList *found,
11281145
bool unwrapElements)
11291146
{
1130-
if (jb->type != jbvBinary)
1147+
if (jb->type == jbvArray)
11311148
{
1132-
Assert(jb->type != jbvArray);
1133-
elog(ERROR, "invalid jsonb array value type: %d", jb->type);
1149+
JsonPathExecResult res = jperNotFound;
1150+
JsonbValue *elem = jb->val.array.elems;
1151+
JsonbValue *last = elem + jb->val.array.nElems;
1152+
1153+
for (; elem < last; elem++)
1154+
{
1155+
if (jsp)
1156+
{
1157+
res = executeItemOptUnwrapTarget(cxt, jsp, elem, found,
1158+
unwrapElements);
1159+
1160+
if (jperIsError(res))
1161+
break;
1162+
if (res == jperOk && !found)
1163+
break;
1164+
}
1165+
else
1166+
{
1167+
if (found)
1168+
JsonValueListAppend(found, copyJsonbValue(elem));
1169+
else
1170+
return jperOk;
1171+
}
1172+
}
1173+
1174+
return res;
11341175
}
11351176

11361177
return executeAnyItem
@@ -1191,8 +1232,6 @@ executeItemOptUnwrapResult(JsonPathExecContext *cxt, JsonPathItem *jsp,
11911232
JsonValueListInitIterator(&seq, &it);
11921233
while ((item = JsonValueListNext(&seq, &it)))
11931234
{
1194-
Assert(item->type != jbvArray);
1195-
11961235
if (JsonbType(item) == jbvArray)
11971236
executeItemUnwrapTargetArray(cxt, NULL, item, found, false);
11981237
else
@@ -1940,6 +1979,7 @@ executeKeyValueMethod(JsonPathExecContext *cxt, JsonPathItem *jsp,
19401979
JsonPathExecResult res = jperNotFound;
19411980
JsonPathItem next;
19421981
JsonbContainer *jbc;
1982+
JsonbValue bin;
19431983
JsonbValue key;
19441984
JsonbValue val;
19451985
JsonbValue idval;
@@ -1951,12 +1991,13 @@ executeKeyValueMethod(JsonPathExecContext *cxt, JsonPathItem *jsp,
19511991
int64 id;
19521992
bool hasNext;
19531993

1954-
if (JsonbType(jb) != jbvObject || jb->type != jbvBinary)
1994+
if (JsonbType(jb) != jbvObject)
19551995
RETURN_ERROR(ereport(ERROR,
19561996
(errcode(ERRCODE_SQL_JSON_OBJECT_NOT_FOUND),
19571997
errmsg("jsonpath item method .%s() can only be applied to an object",
19581998
jspOperationName(jsp->type)))));
19591999

2000+
jb = wrapJsonObjectOrArray(jb, &bin);
19602001
jbc = jb->val.binary.data;
19612002

19622003
if (!JsonContainerSize(jbc))
@@ -2153,7 +2194,8 @@ getJsonPathVariable(JsonPathExecContext *cxt, JsonPathItem *variable,
21532194
static int
21542195
JsonbArraySize(JsonbValue *jb)
21552196
{
2156-
Assert(jb->type != jbvArray);
2197+
if (jb->type == jbvArray)
2198+
return jb->val.array.nElems;
21572199

21582200
if (jb->type == jbvBinary)
21592201
{
@@ -2529,6 +2571,33 @@ JsonbInitBinary(JsonbValue *jbv, Jsonb *jb)
25292571
return jbv;
25302572
}
25312573

2574+
/*
2575+
* Transform a JsonbValue into a binary JsonbValue by encoding it to a
2576+
* binary jsonb container.
2577+
*/
2578+
static JsonbValue *
2579+
JsonbWrapInBinary(JsonbValue *jbv, JsonbValue *out)
2580+
{
2581+
Jsonb *jb;
2582+
2583+
if (!out)
2584+
out = palloc(sizeof(*out));
2585+
2586+
jb = JsonbValueToJsonb(jbv);
2587+
JsonbInitBinary(out, jb);
2588+
2589+
return out;
2590+
}
2591+
2592+
static JsonbValue *
2593+
wrapJsonObjectOrArray(JsonbValue *jbv, JsonbValue *buf)
2594+
{
2595+
if (jbv->type != jbvObject && jbv->type != jbvArray)
2596+
return jbv;
2597+
2598+
return JsonbWrapInBinary(jbv, buf);
2599+
}
2600+
25322601
/*
25332602
* Returns jbv* type of JsonbValue. Note, it never returns jbvBinary as is.
25342603
*/
@@ -2578,7 +2647,12 @@ wrapItemsInArray(const JsonValueList *items)
25782647

25792648
JsonValueListInitIterator(items, &it);
25802649
while ((jbv = JsonValueListNext(items, &it)))
2650+
{
2651+
JsonbValue bin;
2652+
2653+
jbv = wrapJsonObjectOrArray(jbv, &bin);
25812654
pushJsonbValue(&ps, WJB_ELEM, jbv);
2655+
}
25822656

25832657
return pushJsonbValue(&ps, WJB_END_ARRAY, NULL);
25842658
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy