@@ -60,11 +60,13 @@ void _PG_init(void);
6060#define JBE_ISCONTAINER_PTR (je_ )(((je_) & JENTRY_TYPEMASK) == JENTRY_ISCONTAINER_PTR)
6161
6262#define JBC_TOBJECT_TOASTED 0x10000000 /* object with toasted keys */
63+ #define JBC_TOBJECT_COMPRESSED 0x60000000 /* object with compressed keys */
6364
6465#define JB_HEADER (jb ) ((jb)->root.header)
6566#define JX_HEADER_IS_OBJECT (hdr ) (((hdr) & JBC_TMASK) == JBC_TOBJECT || \
6667 ((hdr) & JBC_TMASK) == JBC_TOBJECT_SORTED || \
67- ((hdr) & JBC_TMASK) == JBC_TOBJECT_TOASTED)
68+ ((hdr) & JBC_TMASK) == JBC_TOBJECT_TOASTED || \
69+ ((hdr) & JBC_TMASK) == JBC_TOBJECT_COMPRESSED)
6870#define JX_ROOT_IS_OBJECT (jbp_ ) JX_HEADER_IS_OBJECT(JB_HEADER(jbp_))
6971
7072typedef struct varatt_external JsonbToastPointer ;
@@ -195,10 +197,11 @@ static bool JsonContainerIsToasted(JsonContainer *jc,
195197 JsonbToastedContainerPointerData * jbcptr );
196198static bool JsonContainerIsCompressed (JsonContainer * jc ,
197199 JsonbCompressedContainerData * jbcptr );
198- static bool JsonValueContainsToasted (const JsonValue * jv );
199- static bool JsonValueIsToasted (JsonValue * jv , JsonbToastedContainerPointerData * jbcptr );
200- static bool JsonValueIsCompressed (JsonValue * jv , JsonbCompressedContainerData * jbcptr );
200+ static bool JsonValueIsToasted (const JsonValue * jv , JsonbToastedContainerPointerData * jbcptr );
201+ static bool JsonValueIsCompressed (const JsonValue * jv , JsonbCompressedContainerData * jbcptr );
201202static bool JsonContainerContainsToasted (JsonContainer * jc );
203+ static bool JsonContainerContainsToastedOrCompressed (JsonContainer * jc , bool * toasted , bool * compressed );
204+ static bool JsonValueContainsToastedOrCompressed (const JsonValue * jv , bool * toasted , bool * compressed );
202205
203206static bool jsonb_toast_fields = true; /* GUC */
204207static bool jsonb_toast_fields_recursively = true; /* GUC */
@@ -822,6 +825,7 @@ JsonxIteratorInit(JsonContainer *cont, const JsonbContainerHeader *container,
822825 case JBC_TOBJECT :
823826 case JBC_TOBJECT_SORTED :
824827 case JBC_TOBJECT_TOASTED :
828+ case JBC_TOBJECT_COMPRESSED :
825829 it -> dataProper =
826830 (char * ) it -> children + it -> nElems * sizeof (JEntry ) * 2 ;
827831 it -> dataProper = initKVMap (& it -> kvmap , it -> dataProper , it -> nElems ,
@@ -902,9 +906,14 @@ JsonxEncode(StringInfoData *buffer, const JsonbValue *val, void *cxt)
902906static void *
903907jsonxEncode (JsonValue * jv , JsonContainerOps * ops , Oid toasterid )
904908{
905- if (ops == & jsonbContainerOps &&
906- JsonValueContainsToasted (jv ))
907- return JsonEncode (jv , JsonxEncode , (void * )(intptr_t ) toasterid );
909+ if (ops == & jsonbContainerOps )
910+ {
911+ bool toasted ;
912+ bool compressed ;
913+
914+ if (JsonValueContainsToastedOrCompressed (jv , & toasted , & compressed ))
915+ return JsonEncode (jv , JsonxEncode , (void * )(intptr_t ) toasterid );
916+ }
908917
909918 return NULL ;
910919}
@@ -1204,24 +1213,83 @@ JsonContainerContainsToasted(JsonContainer *jc)
12041213}
12051214
12061215static bool
1207- JsonValueIsToasted (JsonValue * jv , JsonbToastedContainerPointerData * jbcptr )
1216+ JsonContainerContainsToastedOrCompressed (JsonContainer * jc ,
1217+ bool * toasted , bool * compressed )
1218+ {
1219+ if (jc -> ops == & jsonxContainerOps )
1220+ {
1221+ JsonbContainerHeader * jbc = JsonContainerDataPtr (jc );
1222+
1223+ * toasted = (jbc -> header & JBC_TMASK ) == JBC_TOBJECT_TOASTED ;
1224+ * compressed = (jbc -> header & JBC_TMASK ) == JBC_TOBJECT_COMPRESSED ;
1225+
1226+ return * toasted || * compressed ;
1227+ }
1228+ else if (jc -> ops == & jsonxzContainerOps )
1229+ {
1230+ CompressedJsonx * cjb = jsonxzGetCompressedJsonx (jc );
1231+
1232+ * toasted = (cjb -> header & JBC_TMASK ) == JBC_TOBJECT_TOASTED ;
1233+ * compressed = (cjb -> header & JBC_TMASK ) == JBC_TOBJECT_COMPRESSED ;
1234+
1235+ return * toasted || * compressed ;
1236+ }
1237+ #if 0 /* XXX jsonv */
1238+ else if (jc -> ops == & jsonvContainerOps )
1239+ return JsonValueContainsToastedOrCompressed (JsonContainerDataPtr (jc ), toasted , compressed );
1240+ #endif
1241+ else
1242+ {
1243+ * toasted = * compressed = false;
1244+ return false; /* XXX other container types */
1245+ }
1246+ }
1247+
1248+ static bool
1249+ JsonValueIsToasted (const JsonValue * jv , JsonbToastedContainerPointerData * jbcptr )
12081250{
12091251 return jv -> type == jbvBinary &&
12101252 JsonContainerIsToasted (jv -> val .binary .data , jbcptr );
12111253}
12121254
12131255static bool
1214- JsonValueIsCompressed (JsonValue * jv , JsonbCompressedContainerData * jbcptr )
1256+ JsonValueIsCompressed (const JsonValue * jv , JsonbCompressedContainerData * jbcptr )
12151257{
12161258 return jv -> type == jbvBinary &&
12171259 JsonContainerIsCompressed (jv -> val .binary .data , jbcptr );
12181260}
12191261
1262+ static inline bool
1263+ JsonValueContainsToastedOrCompressedAccum (const JsonValue * val ,
1264+ bool * toasted , bool * compressed )
1265+ {
1266+ bool has_toasted ;
1267+ bool has_compressed ;
1268+
1269+ * toasted |= JsonValueIsToasted (val , NULL );
1270+ * compressed |= JsonValueIsCompressed (val , NULL );
1271+
1272+ if (* toasted && * compressed )
1273+ return true;
1274+
1275+ if (JsonValueContainsToastedOrCompressed (val , & has_toasted , & has_compressed ))
1276+ {
1277+ * toasted |= has_toasted ;
1278+ * compressed |= has_compressed ;
1279+ }
1280+
1281+ return * toasted && * compressed ;
1282+ }
1283+
12201284static bool
1221- JsonValueContainsToasted (const JsonValue * jv )
1285+ JsonValueContainsToastedOrCompressed (const JsonValue * jv ,
1286+ bool * toasted , bool * compressed )
12221287{
12231288 if (jv -> type == jbvBinary )
1224- return JsonContainerContainsToasted (jv -> val .binary .data );
1289+ return JsonContainerContainsToastedOrCompressed (jv -> val .binary .data ,
1290+ toasted , compressed );
1291+
1292+ * toasted = * compressed = false;
12251293
12261294 if (jv -> type == jbvObject )
12271295 {
@@ -1231,8 +1299,7 @@ JsonValueContainsToasted(const JsonValue *jv)
12311299 {
12321300 JsonValue * val = & jv -> val .object .pairs [i ].value ;
12331301
1234- if (JsonValueIsToasted (val , NULL ) ||
1235- JsonValueContainsToasted (val ))
1302+ if (JsonValueContainsToastedOrCompressedAccum (val , toasted , compressed ))
12361303 return true;
12371304 }
12381305 }
@@ -1244,15 +1311,15 @@ JsonValueContainsToasted(const JsonValue *jv)
12441311 {
12451312 JsonValue * val = & jv -> val .array .elems [i ];
12461313
1247- if (JsonValueIsToasted (val , NULL ) ||
1248- JsonValueContainsToasted (val ))
1314+ if (JsonValueContainsToastedOrCompressedAccum (val , toasted , compressed ))
12491315 return true;
12501316 }
12511317 }
12521318
1253- return false ;
1319+ return * toasted || * compressed ;
12541320}
12551321
1322+
12561323static void
12571324convertJsonbObject (StringInfo buffer , JEntry * pheader , const JsonbValue * val , int level )
12581325{
@@ -1266,6 +1333,7 @@ convertJsonbObject(StringInfo buffer, JEntry *pheader, const JsonbValue *val, in
12661333 int kvmap_entry_size ;
12671334 bool sorted_values = jsonb_sort_field_values && nPairs > 1 ;
12681335 bool have_toasted_values = false;
1336+ bool have_compressed_values = false;
12691337 struct
12701338 {
12711339 int size ;
@@ -1274,11 +1342,8 @@ convertJsonbObject(StringInfo buffer, JEntry *pheader, const JsonbValue *val, in
12741342
12751343 Assert (nPairs >= 0 );
12761344
1277- if (JsonValueContainsToasted (val ))
1278- {
1279- have_toasted_values = true;
1345+ if (JsonValueContainsToastedOrCompressed (val , & have_toasted_values , & have_compressed_values ))
12801346 sorted_values = false; /* FIXME */
1281- }
12821347
12831348 values = sorted_values ? palloc (sizeof (* values ) * nPairs ) : NULL ;
12841349
@@ -1318,7 +1383,8 @@ convertJsonbObject(StringInfo buffer, JEntry *pheader, const JsonbValue *val, in
13181383 */
13191384 header = nPairs |
13201385 (sorted_values ? JBC_TOBJECT_SORTED :
1321- have_toasted_values ? JBC_TOBJECT_TOASTED : JBC_TOBJECT );
1386+ have_toasted_values ? JBC_TOBJECT_TOASTED :
1387+ have_compressed_values ? JBC_TOBJECT_COMPRESSED : JBC_TOBJECT );
13221388 appendToBuffer (buffer , (char * ) & header , sizeof (uint32 ));
13231389
13241390 /* Reserve space for the JEntries of the keys and values. */
@@ -1617,6 +1683,7 @@ jsonxInitContainerFromHeader(JsonContainerData *jc, JsonbContainerHdr header)
16171683 case JBC_TOBJECT :
16181684 case JBC_TOBJECT_SORTED :
16191685 case JBC_TOBJECT_TOASTED :
1686+ case JBC_TOBJECT_COMPRESSED :
16201687 jc -> type = jbvObject ;
16211688 break ;
16221689 case JBC_TARRAY :
0 commit comments