@@ -1227,12 +1227,11 @@ JsonbIteratorInit(JsonContainer *cont)
12271227 */
12281228
12291229bool
1230- JsonbDeepContains (JsonIterator * * val , JsonIterator * * mContained )
1230+ JsonbDeepContains (JsonContainer * cval , JsonContainer * ccont )
12311231{
1232- JsonbValue vval ,
1233- vcontained ;
1234- JsonbIteratorToken rval ,
1235- rcont ;
1232+ JsonIterator * icont ;
1233+ JsonbValue vcont ;
1234+ JsonbIteratorToken rcont ;
12361235
12371236 /*
12381237 * Guard against stack overflow due to overly complex Jsonb.
@@ -1242,94 +1241,76 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
12421241 */
12431242 check_stack_depth ();
12441243
1245- rval = JsonIteratorNext (val , & vval , false);
1246- rcont = JsonIteratorNext (mContained , & vcontained , false);
1247-
1248- if (rval != rcont )
1244+ if (JsonContainerIsObject (cval ) != JsonContainerIsObject (ccont ))
12491245 {
12501246 /*
12511247 * The differing return values can immediately be taken as indicating
12521248 * two differing container types at this nesting level, which is
12531249 * sufficient reason to give up entirely (but it should be the case
12541250 * that they're both some container type).
12551251 */
1256- Assert (rval == WJB_BEGIN_OBJECT || rval == WJB_BEGIN_ARRAY );
1257- Assert (rcont == WJB_BEGIN_OBJECT || rcont == WJB_BEGIN_ARRAY );
12581252 return false;
12591253 }
1260- else if (rcont == WJB_BEGIN_OBJECT )
1254+ else if (JsonContainerIsObject ( cval ) )
12611255 {
1262- Assert (vval .type == jbvObject );
1263- Assert (vcontained .type == jbvObject );
1264-
12651256 /*
12661257 * If the lhs has fewer pairs than the rhs, it can't possibly contain
12671258 * the rhs. (This conclusion is safe only because we de-duplicate
12681259 * keys in all Jsonb objects; thus there can be no corresponding
12691260 * optimization in the array case.) The case probably won't arise
12701261 * often, but since it's such a cheap check we may as well make it.
12711262 */
1272- if (vval .val .object .nPairs < vcontained .val .object .nPairs )
1263+ if (JsonContainerSize (cval ) >= 0 &&
1264+ JsonContainerSize (ccont ) >= 0 &&
1265+ JsonContainerSize (cval ) < JsonContainerSize (ccont ))
12731266 return false;
12741267
1275- /* Work through rhs "is it contained within?" object */
1276- for (;;)
1277- {
1278- JsonbValue * lhsVal ; /* lhsVal is from pair in lhs object */
1279- JsonbValue lhsValBuf ;
1280-
1281- rcont = JsonIteratorNext (mContained , & vcontained , false);
1268+ icont = JsonIteratorInit (ccont );
1269+ rcont = JsonIteratorNext (& icont , & vcont , false);
1270+ Assert (rcont == WJB_BEGIN_OBJECT );
12821271
1283- /*
1284- * When we get through caller's rhs "is it contained within?"
1285- * object without failing to find one of its values, it's
1286- * contained.
1287- */
1288- if (rcont == WJB_END_OBJECT )
1289- return true;
1290-
1291- Assert (rcont == WJB_KEY );
1292- Assert (vcontained .type == jbvString );
1272+ /*
1273+ * Work through rhs "is it contained within?" object.
1274+ *
1275+ * When we get through caller's rhs "is it contained within?"
1276+ * object without failing to find one of its values, it's
1277+ * contained.
1278+ */
1279+ while ((rcont = JsonIteratorNext (& icont , & vcont , false)) == WJB_KEY )
1280+ {
1281+ /* First, find value by key in lhs object ... */
1282+ JsonbValue * lhsVal = JsonFindKeyInObject (cval ,
1283+ vcont .val .string .val ,
1284+ vcont .val .string .len );
12931285
1294- /* First, find value by key... */
1295- lhsVal = JsonFindKeyInObject ((* val )-> container ,
1296- vcontained .val .string .val ,
1297- vcontained .val .string .len );
12981286 if (!lhsVal )
12991287 return false;
13001288
13011289 /*
13021290 * ...at this stage it is apparent that there is at least a key
13031291 * match for this rhs pair.
13041292 */
1305- rcont = JsonIteratorNext (mContained , & vcontained , true);
1306-
1293+ rcont = JsonIteratorNext (& icont , & vcont , true);
13071294 Assert (rcont == WJB_VALUE );
13081295
13091296 /*
13101297 * Compare rhs pair's value with lhs pair's value just found using
13111298 * key
13121299 */
1313- if (lhsVal -> type != vcontained .type )
1300+ if (lhsVal -> type != vcont .type )
13141301 {
13151302 return false;
13161303 }
13171304 else if (IsAJsonbScalar (lhsVal ))
13181305 {
1319- if (!equalsJsonbScalarValue (lhsVal , & vcontained ))
1306+ if (!equalsJsonbScalarValue (lhsVal , & vcont ))
13201307 return false;
13211308 }
13221309 else
13231310 {
13241311 /* Nested container value (object or array) */
1325- JsonIterator * nestval ,
1326- * nestContained ;
1327-
13281312 Assert (lhsVal -> type == jbvBinary );
1329- Assert (vcontained .type == jbvBinary );
1330-
1331- nestval = JsonIteratorInit (lhsVal -> val .binary .data );
1332- nestContained = JsonIteratorInit (vcontained .val .binary .data );
1313+ Assert (vcont .type == jbvBinary );
13331314
13341315 /*
13351316 * Match "value" side of rhs datum object's pair recursively.
@@ -1351,18 +1332,19 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
13511332 * of containment (plus of course the mapped nodes must be
13521333 * equal).
13531334 */
1354- if (!JsonbDeepContains (& nestval , & nestContained ))
1335+ if (!JsonbDeepContains (lhsVal -> val .binary .data ,
1336+ vcont .val .binary .data ))
13551337 return false;
13561338 }
13571339 }
1340+
1341+ Assert (rcont == WJB_END_OBJECT );
1342+ Assert (icont == NULL );
13581343 }
1359- else if ( rcont == WJB_BEGIN_ARRAY )
1344+ else
13601345 {
1361- JsonbValue * lhsConts = NULL ;
1362- uint32 nLhsElems = vval .val .array .nElems ;
1363-
1364- Assert (vval .type == jbvArray );
1365- Assert (vcontained .type == jbvArray );
1346+ JsonbValue * lhsConts = NULL ;
1347+ uint32 nLhsElems = JsonContainerSize (cval );
13661348
13671349 /*
13681350 * Handle distinction between "raw scalar" pseudo arrays, and real
@@ -1374,29 +1356,25 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
13741356 * only contain pairs, never raw scalars (a pair is represented by an
13751357 * rhs object argument with a single contained pair).
13761358 */
1377- if (vval . val . array . rawScalar && !vcontained . val . array . rawScalar )
1359+ if (JsonContainerIsScalar ( cval ) && !JsonContainerIsScalar ( ccont ) )
13781360 return false;
13791361
1380- /* Work through rhs "is it contained within?" array */
1381- for (;;)
1382- {
1383- rcont = JsonIteratorNext (mContained , & vcontained , true);
1362+ icont = JsonIteratorInit (ccont );
1363+ rcont = JsonIteratorNext (& icont , & vcont , false);
1364+ Assert (rcont == WJB_BEGIN_ARRAY );
13841365
1385- /*
1386- * When we get through caller's rhs "is it contained within?"
1387- * array without failing to find one of its values, it's
1388- * contained.
1389- */
1390- if (rcont == WJB_END_ARRAY )
1391- return true;
1392-
1393- Assert (rcont == WJB_ELEM );
1394-
1395- if (IsAJsonbScalar (& vcontained ))
1366+ /*
1367+ * Work through rhs "is it contained within?" array.
1368+ *
1369+ * When we get through caller's rhs "is it contained within?"
1370+ * array without failing to find one of its values, it's
1371+ * contained.
1372+ */
1373+ while ((rcont = JsonIteratorNext (& icont , & vcont , true)) == WJB_ELEM )
1374+ {
1375+ if (IsAJsonbScalar (& vcont ))
13961376 {
1397- if (!findJsonbValueFromContainer ((* val )-> container ,
1398- JB_FARRAY ,
1399- & vcontained ))
1377+ if (!findJsonbValueFromContainer (cval , JB_FARRAY , & vcont ))
14001378 return false;
14011379 }
14021380 else
@@ -1409,21 +1387,37 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
14091387 */
14101388 if (lhsConts == NULL )
14111389 {
1412- uint32 j = 0 ;
1390+ uint32 j = 0 ;
1391+ JsonIterator * ival ;
1392+ JsonbValue vval ;
1393+
1394+ if ((int32 ) nLhsElems < 0 )
1395+ nLhsElems = JsonGetArraySize (cval );
1396+
1397+ if (nLhsElems == 0 )
1398+ return false;
14131399
14141400 /* Make room for all possible values */
14151401 lhsConts = palloc (sizeof (JsonbValue ) * nLhsElems );
14161402
1403+ ival = JsonIteratorInit (cval );
1404+ rcont = JsonIteratorNext (& ival , & vval , true);
1405+ Assert (rcont == WJB_BEGIN_ARRAY );
1406+
14171407 for (i = 0 ; i < nLhsElems ; i ++ )
14181408 {
14191409 /* Store all lhs elements in temp array */
1420- rcont = JsonIteratorNext (val , & vval , true);
1410+ rcont = JsonIteratorNext (& ival , & vval , true);
14211411 Assert (rcont == WJB_ELEM );
14221412
14231413 if (vval .type == jbvBinary )
14241414 lhsConts [j ++ ] = vval ;
14251415 }
14261416
1417+ rcont = JsonIteratorNext (& ival , & vval , true);
1418+ Assert (rcont == WJB_END_ARRAY );
1419+ Assert (ival == NULL );
1420+
14271421 /* No container elements in temp array, so give up now */
14281422 if (j == 0 )
14291423 return false;
@@ -1436,20 +1430,8 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
14361430 for (i = 0 ; i < nLhsElems ; i ++ )
14371431 {
14381432 /* Nested container value (object or array) */
1439- JsonIterator * nestval ,
1440- * nestContained ;
1441- bool contains ;
1442-
1443- nestval = JsonIteratorInit (lhsConts [i ].val .binary .data );
1444- nestContained = JsonIteratorInit (vcontained .val .binary .data );
1445-
1446- contains = JsonbDeepContains (& nestval , & nestContained );
1447-
1448- if (nestval )
1449- pfree (nestval );
1450- if (nestContained )
1451- pfree (nestContained );
1452- if (contains )
1433+ if (JsonbDeepContains (lhsConts [i ].val .binary .data ,
1434+ vcont .val .binary .data ))
14531435 break ;
14541436 }
14551437
@@ -1461,14 +1443,15 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
14611443 return false;
14621444 }
14631445 }
1464- }
1465- else
1466- {
1467- elog (ERROR , "invalid jsonb container type" );
1446+
1447+ Assert (rcont == WJB_END_ARRAY );
1448+ Assert (icont == NULL );
1449+
1450+ if (lhsConts != NULL )
1451+ pfree (lhsConts );
14681452 }
14691453
1470- elog (ERROR , "unexpectedly fell off end of jsonb container" );
1471- return false;
1454+ return true;
14721455}
14731456
14741457/*
0 commit comments