@@ -254,6 +254,7 @@ static JsonbValue *JsonbInitBinary(JsonbValue *jbv, Jsonb *jb);
254
254
static int JsonbType (JsonbValue * jb );
255
255
static JsonbValue * getScalar (JsonbValue * scalar ,enum jbvType type );
256
256
static JsonbValue * wrapItemsInArray (const JsonValueList * items );
257
+ static JsonbValue * wrapJsonObjectOrArray (JsonbValue * jbv ,JsonbValue * buf );
257
258
static int compareDatetime (Datum val1 ,Oid typid1 ,Datum val2 ,Oid typid2 ,
258
259
bool useTz ,bool * have_error );
259
260
@@ -646,7 +647,14 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
646
647
}
647
648
648
649
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 )
650
658
{
651
659
JsonbValue * v ;
652
660
JsonbValue key ;
@@ -725,6 +733,7 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
725
733
int innermostArraySize = cxt -> innermostArraySize ;
726
734
int i ;
727
735
int size = JsonbArraySize (jb );
736
+ bool binary = jb -> type == jbvBinary ;
728
737
bool singleton = size < 0 ;
729
738
bool hasNext = jspGetNext (jsp ,& elem );
730
739
@@ -784,7 +793,7 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
784
793
v = jb ;
785
794
copy = true;
786
795
}
787
- else
796
+ else if ( binary )
788
797
{
789
798
v = getIthJsonbValueFromContainer (jb -> val .binary .data ,
790
799
(uint32 )index );
@@ -794,6 +803,11 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
794
803
795
804
copy = false;
796
805
}
806
+ else
807
+ {
808
+ v = & jb -> val .array .elems [index ];
809
+ copy = true;
810
+ }
797
811
798
812
if (!hasNext && !found )
799
813
return jperOk ;
@@ -858,10 +872,10 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
858
872
case jpiAnyKey :
859
873
if (JsonbType (jb )== jbvObject )
860
874
{
875
+ JsonbValue bin ;
861
876
bool hasNext = jspGetNext (jsp ,& elem );
862
877
863
- if (jb -> type != jbvBinary )
864
- elog (ERROR ,"invalid jsonb object type: %d" ,jb -> type );
878
+ jb = wrapJsonObjectOrArray (jb ,& bin );
865
879
866
880
return executeAnyItem
867
881
(cxt ,hasNext ?& elem :NULL ,
@@ -926,8 +940,11 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
926
940
927
941
case jpiAny :
928
942
{
943
+ JsonbValue bin ;
929
944
bool hasNext = jspGetNext (jsp ,& elem );
930
945
946
+ jb = wrapJsonObjectOrArray (jb ,& bin );
947
+
931
948
/* first try without any intermediate steps */
932
949
if (jsp -> content .anybounds .first == 0 )
933
950
{
@@ -1127,10 +1144,34 @@ executeItemUnwrapTargetArray(JsonPathExecContext *cxt, JsonPathItem *jsp,
1127
1144
JsonbValue * jb ,JsonValueList * found ,
1128
1145
bool unwrapElements )
1129
1146
{
1130
- if (jb -> type != jbvBinary )
1147
+ if (jb -> type == jbvArray )
1131
1148
{
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 ;
1134
1175
}
1135
1176
1136
1177
return executeAnyItem
@@ -1191,8 +1232,6 @@ executeItemOptUnwrapResult(JsonPathExecContext *cxt, JsonPathItem *jsp,
1191
1232
JsonValueListInitIterator (& seq ,& it );
1192
1233
while ((item = JsonValueListNext (& seq ,& it )))
1193
1234
{
1194
- Assert (item -> type != jbvArray );
1195
-
1196
1235
if (JsonbType (item )== jbvArray )
1197
1236
executeItemUnwrapTargetArray (cxt ,NULL ,item ,found , false);
1198
1237
else
@@ -1940,6 +1979,7 @@ executeKeyValueMethod(JsonPathExecContext *cxt, JsonPathItem *jsp,
1940
1979
JsonPathExecResult res = jperNotFound ;
1941
1980
JsonPathItem next ;
1942
1981
JsonbContainer * jbc ;
1982
+ JsonbValue bin ;
1943
1983
JsonbValue key ;
1944
1984
JsonbValue val ;
1945
1985
JsonbValue idval ;
@@ -1951,12 +1991,13 @@ executeKeyValueMethod(JsonPathExecContext *cxt, JsonPathItem *jsp,
1951
1991
int64 id ;
1952
1992
bool hasNext ;
1953
1993
1954
- if (JsonbType (jb )!= jbvObject || jb -> type != jbvBinary )
1994
+ if (JsonbType (jb )!= jbvObject )
1955
1995
RETURN_ERROR (ereport (ERROR ,
1956
1996
(errcode (ERRCODE_SQL_JSON_OBJECT_NOT_FOUND ),
1957
1997
errmsg ("jsonpath item method .%s() can only be applied to an object" ,
1958
1998
jspOperationName (jsp -> type )))));
1959
1999
2000
+ jb = wrapJsonObjectOrArray (jb ,& bin );
1960
2001
jbc = jb -> val .binary .data ;
1961
2002
1962
2003
if (!JsonContainerSize (jbc ))
@@ -2153,7 +2194,8 @@ getJsonPathVariable(JsonPathExecContext *cxt, JsonPathItem *variable,
2153
2194
static int
2154
2195
JsonbArraySize (JsonbValue * jb )
2155
2196
{
2156
- Assert (jb -> type != jbvArray );
2197
+ if (jb -> type == jbvArray )
2198
+ return jb -> val .array .nElems ;
2157
2199
2158
2200
if (jb -> type == jbvBinary )
2159
2201
{
@@ -2529,6 +2571,33 @@ JsonbInitBinary(JsonbValue *jbv, Jsonb *jb)
2529
2571
return jbv ;
2530
2572
}
2531
2573
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
+
2532
2601
/*
2533
2602
* Returns jbv* type of JsonbValue. Note, it never returns jbvBinary as is.
2534
2603
*/
@@ -2578,7 +2647,12 @@ wrapItemsInArray(const JsonValueList *items)
2578
2647
2579
2648
JsonValueListInitIterator (items ,& it );
2580
2649
while ((jbv = JsonValueListNext (items ,& it )))
2650
+ {
2651
+ JsonbValue bin ;
2652
+
2653
+ jbv = wrapJsonObjectOrArray (jbv ,& bin );
2581
2654
pushJsonbValue (& ps ,WJB_ELEM ,jbv );
2655
+ }
2582
2656
2583
2657
return pushJsonbValue (& ps ,WJB_END_ARRAY ,NULL );
2584
2658
}