@@ -254,6 +254,7 @@ static JsonbValue *JsonbInitBinary(JsonbValue *jbv, Jsonb *jb);
254254static int JsonbType (JsonbValue * jb );
255255static JsonbValue * getScalar (JsonbValue * scalar , enum jbvType type );
256256static JsonbValue * wrapItemsInArray (const JsonValueList * items );
257+ static JsonbValue * wrapJsonObjectOrArray (JsonbValue * jbv , JsonbValue * buf );
257258static 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,
21532194static int
21542195JsonbArraySize (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