@@ -409,6 +409,8 @@ static inline JsonbValue *JsonInitBinary(JsonbValue *jbv, Json *js);
409
409
static JsonItem * getScalar (JsonItem * scalar , enum jbvType type );
410
410
static JsonbValue * wrapItemsInArray (const JsonValueList * items , bool isJsonb );
411
411
static text * JsonItemUnquoteText (JsonItem * jsi , bool isJsonb );
412
+ static JsonItem * wrapJsonObjectOrArray (JsonItem * js , JsonItem * buf ,
413
+ bool isJsonb );
412
414
413
415
static JsonItem * getJsonObjectKey (JsonItem * jb , char * keystr , int keylen ,
414
416
bool isJsonb , JsonItem * val );
@@ -945,7 +947,15 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
945
947
}
946
948
947
949
case jpiKey :
948
- if (JsonbType (jb ) == jbvObject )
950
+ if (JsonItemIsObject (jb ))
951
+ {
952
+ JsonItem obj ;
953
+
954
+ jb = wrapJsonObjectOrArray (jb , & obj , cxt -> isJsonb );
955
+ return executeItemOptUnwrapTarget (cxt , jsp , jb , found , unwrap );
956
+ }
957
+ else if (JsonItemIsBinary (jb ) &&
958
+ JsonContainerIsObject (JsonItemBinary (jb ).data ))
949
959
{
950
960
JsonItem val ;
951
961
int keylen ;
@@ -1015,6 +1025,7 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
1015
1025
int innermostArraySize = cxt -> innermostArraySize ;
1016
1026
int i ;
1017
1027
int size = JsonxArraySize (jb , cxt -> isJsonb );
1028
+ bool binary = JsonItemIsBinary (jb );
1018
1029
bool singleton = size < 0 ;
1019
1030
bool hasNext = jspGetNext (jsp , & elem );
1020
1031
@@ -1073,14 +1084,19 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
1073
1084
{
1074
1085
jsi = jb ;
1075
1086
}
1076
- else
1087
+ else if ( binary )
1077
1088
{
1078
1089
jsi = getJsonArrayElement (jb , (uint32 ) index ,
1079
1090
cxt -> isJsonb , & jsibuf );
1080
1091
1081
1092
if (jsi == NULL )
1082
1093
continue ;
1083
1094
}
1095
+ else
1096
+ {
1097
+ jsi = JsonbValueToJsonItem (& JsonItemArray (jb ).elems [index ],
1098
+ & jsibuf );
1099
+ }
1084
1100
1085
1101
if (!hasNext && !found )
1086
1102
return jperOk ;
@@ -1143,11 +1159,10 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
1143
1159
case jpiAnyKey :
1144
1160
if (JsonbType (jb ) == jbvObject )
1145
1161
{
1162
+ JsonItem bin ;
1146
1163
bool hasNext = jspGetNext (jsp , & elem );
1147
1164
1148
- if (!JsonItemIsBinary (jb ))
1149
- elog (ERROR , "invalid jsonb object type: %d" ,
1150
- JsonItemGetType (jb ));
1165
+ jb = wrapJsonObjectOrArray (jb , & bin , cxt -> isJsonb );
1151
1166
1152
1167
return executeAnyItem
1153
1168
(cxt , hasNext ? & elem : NULL ,
@@ -1212,8 +1227,11 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
1212
1227
1213
1228
case jpiAny :
1214
1229
{
1230
+ JsonItem bin ;
1215
1231
bool hasNext = jspGetNext (jsp , & elem );
1216
1232
1233
+ jb = wrapJsonObjectOrArray (jb , & bin , cxt -> isJsonb );
1234
+
1217
1235
/* first try without any intermediate steps */
1218
1236
if (jsp -> content .anybounds .first == 0 )
1219
1237
{
@@ -1557,10 +1575,41 @@ executeItemUnwrapTargetArray(JsonPathExecContext *cxt, JsonPathItem *jsp,
1557
1575
JsonItem * jb , JsonValueList * found ,
1558
1576
bool unwrapElements )
1559
1577
{
1560
- if (! JsonItemIsBinary (jb ))
1578
+ if (JsonItemIsArray (jb ))
1561
1579
{
1562
- Assert (!JsonItemIsArray (jb ));
1563
- elog (ERROR , "invalid jsonb array value type: %d" , JsonItemGetType (jb ));
1580
+ JsonPathExecResult res = jperNotFound ;
1581
+ JsonbValue * elem = JsonItemArray (jb ).elems ;
1582
+ JsonbValue * last = elem + JsonItemArray (jb ).nElems ;
1583
+
1584
+ for (; elem < last ; elem ++ )
1585
+ {
1586
+ if (jsp )
1587
+ {
1588
+ JsonItem buf ;
1589
+
1590
+ res = executeItemOptUnwrapTarget (cxt , jsp ,
1591
+ JsonbValueToJsonItem (elem , & buf ),
1592
+ found , unwrapElements );
1593
+
1594
+ if (jperIsError (res ))
1595
+ break ;
1596
+ if (res == jperOk && !found )
1597
+ break ;
1598
+ }
1599
+ else
1600
+ {
1601
+ if (found )
1602
+ {
1603
+ JsonItem * jsi = palloc (sizeof (* jsi ));
1604
+
1605
+ JsonValueListAppend (found , JsonbValueToJsonItem (elem , jsi ));
1606
+ }
1607
+ else
1608
+ return jperOk ;
1609
+ }
1610
+ }
1611
+
1612
+ return res ;
1564
1613
}
1565
1614
1566
1615
return executeAnyItem
@@ -1639,8 +1688,6 @@ executeItemOptUnwrapResult(JsonPathExecContext *cxt, JsonPathItem *jsp,
1639
1688
JsonValueListInitIterator (& seq , & it );
1640
1689
while ((item = JsonValueListNext (& seq , & it )))
1641
1690
{
1642
- Assert (!JsonItemIsArray (item ));
1643
-
1644
1691
if (JsonbType (item ) == jbvArray )
1645
1692
executeItemUnwrapTargetArray (cxt , NULL , item , found , false);
1646
1693
else
@@ -2266,6 +2313,7 @@ executeKeyValueMethod(JsonPathExecContext *cxt, JsonPathItem *jsp,
2266
2313
JsonPathExecResult res = jperNotFound ;
2267
2314
JsonPathItem next ;
2268
2315
JsonbContainer * jbc ;
2316
+ JsonItem bin ;
2269
2317
JsonbValue key ;
2270
2318
JsonbValue val ;
2271
2319
JsonbValue idval ;
@@ -2278,12 +2326,13 @@ executeKeyValueMethod(JsonPathExecContext *cxt, JsonPathItem *jsp,
2278
2326
int64 id ;
2279
2327
bool hasNext ;
2280
2328
2281
- if (JsonbType (jb ) != jbvObject || ! JsonItemIsBinary ( jb ) )
2329
+ if (JsonbType (jb ) != jbvObject )
2282
2330
RETURN_ERROR (ereport (ERROR ,
2283
2331
(errcode (ERRCODE_JSON_OBJECT_NOT_FOUND ),
2284
2332
errmsg ("jsonpath item method .%s() can only be applied to an object" ,
2285
2333
jspOperationName (jsp -> type )))));
2286
2334
2335
+ jb = wrapJsonObjectOrArray (jb , & bin , cxt -> isJsonb );
2287
2336
jbc = JsonItemBinary (jb ).data ;
2288
2337
2289
2338
if (!JsonContainerSize (jbc ))
@@ -2529,7 +2578,8 @@ getJsonPathVariableFromJsonx(void *varsJsonx, bool isJsonb,
2529
2578
static int
2530
2579
JsonxArraySize (JsonItem * jb , bool isJsonb )
2531
2580
{
2532
- Assert (!JsonItemIsArray (jb ));
2581
+ if (JsonItemIsArray (jb ))
2582
+ return JsonItemArray (jb ).nElems ;
2533
2583
2534
2584
if (JsonItemIsBinary (jb ))
2535
2585
{
@@ -2897,6 +2947,41 @@ JsonInitBinary(JsonbValue *jbv, Json *js)
2897
2947
return jbv ;
2898
2948
}
2899
2949
2950
+ /*
2951
+ * Transform a JsonbValue into a binary JsonbValue by encoding it to a
2952
+ * binary jsonb container.
2953
+ */
2954
+ static JsonItem *
2955
+ JsonxWrapInBinary (JsonItem * jsi , JsonItem * out , bool isJsonb )
2956
+ {
2957
+ if (!out )
2958
+ out = palloc (sizeof (* out ));
2959
+
2960
+ if (isJsonb )
2961
+ {
2962
+ Jsonb * jb = JsonItemToJsonb (jsi );
2963
+
2964
+ JsonbInitBinary (JsonItemJbv (out ), jb );
2965
+ }
2966
+ else
2967
+ {
2968
+ Json * js = JsonItemToJson (jsi );
2969
+
2970
+ JsonInitBinary (JsonItemJbv (out ), js );
2971
+ }
2972
+
2973
+ return out ;
2974
+ }
2975
+
2976
+ static JsonItem *
2977
+ wrapJsonObjectOrArray (JsonItem * js , JsonItem * buf , bool isJsonb )
2978
+ {
2979
+ if (!JsonItemIsObject (js ) && !JsonItemIsArray (js ))
2980
+ return js ;
2981
+
2982
+ return JsonxWrapInBinary (js , buf , isJsonb );
2983
+ }
2984
+
2900
2985
/*
2901
2986
* Returns jbv* type of of JsonbValue. Note, it never returns jbvBinary as is.
2902
2987
*/
@@ -3096,15 +3181,20 @@ wrapItemsInArray(const JsonValueList *items, bool isJsonb)
3096
3181
JsonbParseState * ps = NULL ;
3097
3182
JsonValueListIterator it ;
3098
3183
JsonItem * jsi ;
3099
- JsonbValue jbv ;
3100
3184
JsonBuilderFunc push = isJsonb ? pushJsonbValue : pushJsonValue ;
3101
3185
3102
3186
push (& ps , WJB_BEGIN_ARRAY , NULL );
3103
3187
3104
3188
JsonValueListInitIterator (items , & it );
3105
3189
3106
3190
while ((jsi = JsonValueListNext (items , & it )))
3191
+ {
3192
+ JsonItem bin ;
3193
+ JsonbValue jbv ;
3194
+
3195
+ jsi = wrapJsonObjectOrArray (jsi , & bin , isJsonb );
3107
3196
push (& ps , WJB_ELEM , JsonItemToJsonbValue (jsi , & jbv ));
3197
+ }
3108
3198
3109
3199
return push (& ps , WJB_END_ARRAY , NULL );
3110
3200
}
0 commit comments