@@ -1244,12 +1244,11 @@ jsonbIteratorInit(JsonContainer *cont)
12441244 */
12451245
12461246bool
1247- JsonbDeepContains (JsonIterator * * val , JsonIterator * * mContained )
1247+ JsonbDeepContains (JsonContainer * cval , JsonContainer * ccont )
12481248{
1249- JsonbValue vval ,
1250- vcontained ;
1251- JsonbIteratorToken rval ,
1252- rcont ;
1249+ JsonbIterator * icont ;
1250+ JsonbValue vcont ;
1251+ JsonbIteratorToken rcont ;
12531252
12541253 /*
12551254 * Guard against stack overflow due to overly complex Jsonb.
@@ -1259,95 +1258,78 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
12591258 */
12601259 check_stack_depth ();
12611260
1262- rval = JsonbIteratorNext (val , & vval , false);
1263- rcont = JsonbIteratorNext (mContained , & vcontained , false);
1264-
1265- if (rval != rcont )
1261+ if (JsonContainerIsObject (cval ) != JsonContainerIsObject (ccont ))
12661262 {
12671263 /*
12681264 * The differing return values can immediately be taken as indicating
12691265 * two differing container types at this nesting level, which is
12701266 * sufficient reason to give up entirely (but it should be the case
12711267 * that they're both some container type).
12721268 */
1273- Assert (rval == WJB_BEGIN_OBJECT || rval == WJB_BEGIN_ARRAY );
1274- Assert (rcont == WJB_BEGIN_OBJECT || rcont == WJB_BEGIN_ARRAY );
12751269 return false;
12761270 }
1277- else if (rcont == WJB_BEGIN_OBJECT )
1271+ else if (JsonContainerIsObject ( cval ) )
12781272 {
1279- Assert (vval .type == jbvObject );
1280- Assert (vcontained .type == jbvObject );
1281-
12821273 /*
12831274 * If the lhs has fewer pairs than the rhs, it can't possibly contain
12841275 * the rhs. (This conclusion is safe only because we de-duplicate
12851276 * keys in all Jsonb objects; thus there can be no corresponding
12861277 * optimization in the array case.) The case probably won't arise
12871278 * often, but since it's such a cheap check we may as well make it.
12881279 */
1289- if (vval .val .object .nPairs < vcontained .val .object .nPairs )
1280+ if (JsonContainerSize (cval ) >= 0 &&
1281+ JsonContainerSize (ccont ) >= 0 &&
1282+ JsonContainerSize (cval ) < JsonContainerSize (ccont ))
12901283 return false;
12911284
1292- /* Work through rhs "is it contained within?" object */
1293- for (;;)
1285+ icont = JsonbIteratorInit (ccont );
1286+ rcont = JsonbIteratorNext (& icont , & vcont , false);
1287+ Assert (rcont == WJB_BEGIN_OBJECT );
1288+
1289+ /*
1290+ * Work through rhs "is it contained within?" object.
1291+ *
1292+ * When we get through caller's rhs "is it contained within?"
1293+ * object without failing to find one of its values, it's
1294+ * contained.
1295+ */
1296+ while ((rcont = JsonbIteratorNext (& icont , & vcont , false)) == WJB_KEY )
12941297 {
1295- JsonbValue * lhsVal ; /* lhsVal is from pair in lhs object */
1298+ /* First, find value by key in lhs object ... */
12961299 JsonbValue lhsValBuf ;
1300+ JsonbValue * lhsVal = JsonFindKeyInObject (cval ,
1301+ vcont .val .string .val ,
1302+ vcont .val .string .len ,
1303+ & lhsValBuf );
12971304
1298- rcont = JsonbIteratorNext (mContained , & vcontained , false);
1299-
1300- /*
1301- * When we get through caller's rhs "is it contained within?"
1302- * object without failing to find one of its values, it's
1303- * contained.
1304- */
1305- if (rcont == WJB_END_OBJECT )
1306- return true;
1307-
1308- Assert (rcont == WJB_KEY );
1309- Assert (vcontained .type == jbvString );
1310-
1311- /* First, find value by key... */
1312- lhsVal = getKeyJsonValueFromContainer ((* val )-> container ,
1313- vcontained .val .string .val ,
1314- vcontained .val .string .len ,
1315- & lhsValBuf );
13161305 if (!lhsVal )
13171306 return false;
13181307
13191308 /*
13201309 * ...at this stage it is apparent that there is at least a key
13211310 * match for this rhs pair.
13221311 */
1323- rcont = JsonbIteratorNext (mContained , & vcontained , true);
1324-
1312+ rcont = JsonbIteratorNext (& icont , & vcont , true);
13251313 Assert (rcont == WJB_VALUE );
13261314
13271315 /*
13281316 * Compare rhs pair's value with lhs pair's value just found using
13291317 * key
13301318 */
1331- if (lhsVal -> type != vcontained .type )
1319+ if (lhsVal -> type != vcont .type )
13321320 {
13331321 return false;
13341322 }
13351323 else if (IsAJsonbScalar (lhsVal ))
13361324 {
1337- if (!equalsJsonbScalarValue (lhsVal , & vcontained ))
1325+ if (!equalsJsonbScalarValue (lhsVal , & vcont ))
13381326 return false;
13391327 }
13401328 else
13411329 {
13421330 /* Nested container value (object or array) */
1343- JsonIterator * nestval ,
1344- * nestContained ;
1345-
13461331 Assert (lhsVal -> type == jbvBinary );
1347- Assert (vcontained .type == jbvBinary );
1348-
1349- nestval = JsonbIteratorInit (lhsVal -> val .binary .data );
1350- nestContained = JsonbIteratorInit (vcontained .val .binary .data );
1332+ Assert (vcont .type == jbvBinary );
13511333
13521334 /*
13531335 * Match "value" side of rhs datum object's pair recursively.
@@ -1369,18 +1351,19 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
13691351 * of containment (plus of course the mapped nodes must be
13701352 * equal).
13711353 */
1372- if (!JsonbDeepContains (& nestval , & nestContained ))
1354+ if (!JsonbDeepContains (lhsVal -> val .binary .data ,
1355+ vcont .val .binary .data ))
13731356 return false;
13741357 }
13751358 }
1359+
1360+ Assert (rcont == WJB_END_OBJECT );
1361+ Assert (icont == NULL );
13761362 }
1377- else if ( rcont == WJB_BEGIN_ARRAY )
1363+ else
13781364 {
1379- JsonbValue * lhsConts = NULL ;
1380- uint32 nLhsElems = vval .val .array .nElems ;
1381-
1382- Assert (vval .type == jbvArray );
1383- Assert (vcontained .type == jbvArray );
1365+ JsonbValue * lhsConts = NULL ;
1366+ uint32 nLhsElems = JsonContainerSize (cval );
13841367
13851368 /*
13861369 * Handle distinction between "raw scalar" pseudo arrays, and real
@@ -1392,29 +1375,25 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
13921375 * only contain pairs, never raw scalars (a pair is represented by an
13931376 * rhs object argument with a single contained pair).
13941377 */
1395- if (vval . val . array . rawScalar && !vcontained . val . array . rawScalar )
1378+ if (JsonContainerIsScalar ( cval ) && !JsonContainerIsScalar ( ccont ) )
13961379 return false;
13971380
1398- /* Work through rhs "is it contained within?" array */
1399- for (;;)
1400- {
1401- rcont = JsonbIteratorNext (mContained , & vcontained , true);
1381+ icont = JsonbIteratorInit (ccont );
1382+ rcont = JsonbIteratorNext (& icont , & vcont , false);
1383+ Assert (rcont == WJB_BEGIN_ARRAY );
14021384
1403- /*
1404- * When we get through caller's rhs "is it contained within?"
1405- * array without failing to find one of its values, it's
1406- * contained.
1407- */
1408- if (rcont == WJB_END_ARRAY )
1409- return true;
1410-
1411- Assert (rcont == WJB_ELEM );
1412-
1413- if (IsAJsonbScalar (& vcontained ))
1385+ /*
1386+ * Work through rhs "is it contained within?" array.
1387+ *
1388+ * When we get through caller's rhs "is it contained within?"
1389+ * array without failing to find one of its values, it's
1390+ * contained.
1391+ */
1392+ while ((rcont = JsonbIteratorNext (& icont , & vcont , true)) == WJB_ELEM )
1393+ {
1394+ if (IsAJsonbScalar (& vcont ))
14141395 {
1415- if (!findJsonbValueFromContainer ((* val )-> container ,
1416- JB_FARRAY ,
1417- & vcontained ))
1396+ if (!findJsonbValueFromContainer (cval , JB_FARRAY , & vcont ))
14181397 return false;
14191398 }
14201399 else
@@ -1427,21 +1406,37 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
14271406 */
14281407 if (lhsConts == NULL )
14291408 {
1430- uint32 j = 0 ;
1409+ uint32 j = 0 ;
1410+ JsonbIterator * ival ;
1411+ JsonbValue vval ;
1412+
1413+ if ((int32 ) nLhsElems < 0 )
1414+ nLhsElems = JsonGetArraySize (cval );
1415+
1416+ if (nLhsElems == 0 )
1417+ return false;
14311418
14321419 /* Make room for all possible values */
14331420 lhsConts = palloc (sizeof (JsonbValue ) * nLhsElems );
14341421
1422+ ival = JsonbIteratorInit (cval );
1423+ rcont = JsonbIteratorNext (& ival , & vval , true);
1424+ Assert (rcont == WJB_BEGIN_ARRAY );
1425+
14351426 for (i = 0 ; i < nLhsElems ; i ++ )
14361427 {
14371428 /* Store all lhs elements in temp array */
1438- rcont = JsonbIteratorNext (val , & vval , true);
1429+ rcont = JsonbIteratorNext (& ival , & vval , true);
14391430 Assert (rcont == WJB_ELEM );
14401431
14411432 if (vval .type == jbvBinary )
14421433 lhsConts [j ++ ] = vval ;
14431434 }
14441435
1436+ rcont = JsonbIteratorNext (& ival , & vval , true);
1437+ Assert (rcont == WJB_END_ARRAY );
1438+ Assert (ival == NULL );
1439+
14451440 /* No container elements in temp array, so give up now */
14461441 if (j == 0 )
14471442 return false;
@@ -1454,20 +1449,8 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
14541449 for (i = 0 ; i < nLhsElems ; i ++ )
14551450 {
14561451 /* Nested container value (object or array) */
1457- JsonIterator * nestval ,
1458- * nestContained ;
1459- bool contains ;
1460-
1461- nestval = JsonbIteratorInit (lhsConts [i ].val .binary .data );
1462- nestContained = JsonbIteratorInit (vcontained .val .binary .data );
1463-
1464- contains = JsonbDeepContains (& nestval , & nestContained );
1465-
1466- if (nestval )
1467- pfree (nestval );
1468- if (nestContained )
1469- pfree (nestContained );
1470- if (contains )
1452+ if (JsonbDeepContains (lhsConts [i ].val .binary .data ,
1453+ vcont .val .binary .data ))
14711454 break ;
14721455 }
14731456
@@ -1479,14 +1462,15 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
14791462 return false;
14801463 }
14811464 }
1482- }
1483- else
1484- {
1485- elog (ERROR , "invalid jsonb container type" );
1465+
1466+ Assert (rcont == WJB_END_ARRAY );
1467+ Assert (icont == NULL );
1468+
1469+ if (lhsConts != NULL )
1470+ pfree (lhsConts );
14861471 }
14871472
1488- elog (ERROR , "unexpectedly fell off end of jsonb container" );
1489- return false;
1473+ return true;
14901474}
14911475
14921476/*
0 commit comments