@@ -1180,12 +1180,11 @@ JsonbIteratorInit(JsonContainer *cont)
11801180 */
11811181
11821182bool
1183- JsonbDeepContains (JsonIterator * * val , JsonIterator * * mContained )
1183+ JsonbDeepContains (JsonContainer * cval , JsonContainer * ccont )
11841184{
1185- JsonbValue vval ,
1186- vcontained ;
1187- JsonbIteratorToken rval ,
1188- rcont ;
1185+ JsonIterator * icont ;
1186+ JsonbValue vcont ;
1187+ JsonbIteratorToken rcont ;
11891188
11901189 /*
11911190 * Guard against stack overflow due to overly complex Jsonb.
@@ -1195,94 +1194,76 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
11951194 */
11961195 check_stack_depth ();
11971196
1198- rval = JsonIteratorNext (val , & vval , false);
1199- rcont = JsonIteratorNext (mContained , & vcontained , false);
1200-
1201- if (rval != rcont )
1197+ if (JsonContainerIsObject (cval ) != JsonContainerIsObject (ccont ))
12021198 {
12031199 /*
12041200 * The differing return values can immediately be taken as indicating
12051201 * two differing container types at this nesting level, which is
12061202 * sufficient reason to give up entirely (but it should be the case
12071203 * that they're both some container type).
12081204 */
1209- Assert (rval == WJB_BEGIN_OBJECT || rval == WJB_BEGIN_ARRAY );
1210- Assert (rcont == WJB_BEGIN_OBJECT || rcont == WJB_BEGIN_ARRAY );
12111205 return false;
12121206 }
1213- else if (rcont == WJB_BEGIN_OBJECT )
1207+ else if (JsonContainerIsObject ( cval ) )
12141208 {
1215- Assert (vval .type == jbvObject );
1216- Assert (vcontained .type == jbvObject );
1217-
12181209 /*
12191210 * If the lhs has fewer pairs than the rhs, it can't possibly contain
12201211 * the rhs. (This conclusion is safe only because we de-duplicate
12211212 * keys in all Jsonb objects; thus there can be no corresponding
12221213 * optimization in the array case.) The case probably won't arise
12231214 * often, but since it's such a cheap check we may as well make it.
12241215 */
1225- if (vval .val .object .nPairs < vcontained .val .object .nPairs )
1216+ if (JsonContainerSize (cval ) >= 0 &&
1217+ JsonContainerSize (ccont ) >= 0 &&
1218+ JsonContainerSize (cval ) < JsonContainerSize (ccont ))
12261219 return false;
12271220
1228- /* Work through rhs "is it contained within?" object */
1229- for (;;)
1230- {
1231- JsonbValue * lhsVal ; /* lhsVal is from pair in lhs object */
1232- JsonbValue lhsValBuf ;
1233-
1234- rcont = JsonIteratorNext (mContained , & vcontained , false);
1221+ icont = JsonIteratorInit (ccont );
1222+ rcont = JsonIteratorNext (& icont , & vcont , false);
1223+ Assert (rcont == WJB_BEGIN_OBJECT );
12351224
1236- /*
1237- * When we get through caller's rhs "is it contained within?"
1238- * object without failing to find one of its values, it's
1239- * contained.
1240- */
1241- if (rcont == WJB_END_OBJECT )
1242- return true;
1243-
1244- Assert (rcont == WJB_KEY );
1245- Assert (vcontained .type == jbvString );
1225+ /*
1226+ * Work through rhs "is it contained within?" object.
1227+ *
1228+ * When we get through caller's rhs "is it contained within?"
1229+ * object without failing to find one of its values, it's
1230+ * contained.
1231+ */
1232+ while ((rcont = JsonIteratorNext (& icont , & vcont , false)) == WJB_KEY )
1233+ {
1234+ /* First, find value by key in lhs object ... */
1235+ JsonbValue * lhsVal = JsonFindKeyInObject (cval ,
1236+ vcont .val .string .val ,
1237+ vcont .val .string .len );
12461238
1247- /* First, find value by key... */
1248- lhsVal = JsonFindKeyInObject ((* val )-> container ,
1249- vcontained .val .string .val ,
1250- vcontained .val .string .len );
12511239 if (!lhsVal )
12521240 return false;
12531241
12541242 /*
12551243 * ...at this stage it is apparent that there is at least a key
12561244 * match for this rhs pair.
12571245 */
1258- rcont = JsonIteratorNext (mContained , & vcontained , true);
1259-
1246+ rcont = JsonIteratorNext (& icont , & vcont , true);
12601247 Assert (rcont == WJB_VALUE );
12611248
12621249 /*
12631250 * Compare rhs pair's value with lhs pair's value just found using
12641251 * key
12651252 */
1266- if (lhsVal -> type != vcontained .type )
1253+ if (lhsVal -> type != vcont .type )
12671254 {
12681255 return false;
12691256 }
12701257 else if (IsAJsonbScalar (lhsVal ))
12711258 {
1272- if (!equalsJsonbScalarValue (lhsVal , & vcontained ))
1259+ if (!equalsJsonbScalarValue (lhsVal , & vcont ))
12731260 return false;
12741261 }
12751262 else
12761263 {
12771264 /* Nested container value (object or array) */
1278- JsonIterator * nestval ,
1279- * nestContained ;
1280-
12811265 Assert (lhsVal -> type == jbvBinary );
1282- Assert (vcontained .type == jbvBinary );
1283-
1284- nestval = JsonIteratorInit (lhsVal -> val .binary .data );
1285- nestContained = JsonIteratorInit (vcontained .val .binary .data );
1266+ Assert (vcont .type == jbvBinary );
12861267
12871268 /*
12881269 * Match "value" side of rhs datum object's pair recursively.
@@ -1304,18 +1285,19 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
13041285 * of containment (plus of course the mapped nodes must be
13051286 * equal).
13061287 */
1307- if (!JsonbDeepContains (& nestval , & nestContained ))
1288+ if (!JsonbDeepContains (lhsVal -> val .binary .data ,
1289+ vcont .val .binary .data ))
13081290 return false;
13091291 }
13101292 }
1293+
1294+ Assert (rcont == WJB_END_OBJECT );
1295+ Assert (icont == NULL );
13111296 }
1312- else if ( rcont == WJB_BEGIN_ARRAY )
1297+ else
13131298 {
1314- JsonbValue * lhsConts = NULL ;
1315- uint32 nLhsElems = vval .val .array .nElems ;
1316-
1317- Assert (vval .type == jbvArray );
1318- Assert (vcontained .type == jbvArray );
1299+ JsonbValue * lhsConts = NULL ;
1300+ uint32 nLhsElems = JsonContainerSize (cval );
13191301
13201302 /*
13211303 * Handle distinction between "raw scalar" pseudo arrays, and real
@@ -1327,29 +1309,25 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
13271309 * only contain pairs, never raw scalars (a pair is represented by an
13281310 * rhs object argument with a single contained pair).
13291311 */
1330- if (vval . val . array . rawScalar && !vcontained . val . array . rawScalar )
1312+ if (JsonContainerIsScalar ( cval ) && !JsonContainerIsScalar ( ccont ) )
13311313 return false;
13321314
1333- /* Work through rhs "is it contained within?" array */
1334- for (;;)
1335- {
1336- rcont = JsonIteratorNext (mContained , & vcontained , true);
1315+ icont = JsonIteratorInit (ccont );
1316+ rcont = JsonIteratorNext (& icont , & vcont , false);
1317+ Assert (rcont == WJB_BEGIN_ARRAY );
13371318
1338- /*
1339- * When we get through caller's rhs "is it contained within?"
1340- * array without failing to find one of its values, it's
1341- * contained.
1342- */
1343- if (rcont == WJB_END_ARRAY )
1344- return true;
1345-
1346- Assert (rcont == WJB_ELEM );
1347-
1348- if (IsAJsonbScalar (& vcontained ))
1319+ /*
1320+ * Work through rhs "is it contained within?" array.
1321+ *
1322+ * When we get through caller's rhs "is it contained within?"
1323+ * array without failing to find one of its values, it's
1324+ * contained.
1325+ */
1326+ while ((rcont = JsonIteratorNext (& icont , & vcont , true)) == WJB_ELEM )
1327+ {
1328+ if (IsAJsonbScalar (& vcont ))
13491329 {
1350- if (!findJsonbValueFromContainer ((* val )-> container ,
1351- JB_FARRAY ,
1352- & vcontained ))
1330+ if (!findJsonbValueFromContainer (cval , JB_FARRAY , & vcont ))
13531331 return false;
13541332 }
13551333 else
@@ -1362,21 +1340,37 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
13621340 */
13631341 if (lhsConts == NULL )
13641342 {
1365- uint32 j = 0 ;
1343+ uint32 j = 0 ;
1344+ JsonIterator * ival ;
1345+ JsonbValue vval ;
1346+
1347+ if ((int32 ) nLhsElems < 0 )
1348+ nLhsElems = JsonGetArraySize (cval );
1349+
1350+ if (nLhsElems == 0 )
1351+ return false;
13661352
13671353 /* Make room for all possible values */
13681354 lhsConts = palloc (sizeof (JsonbValue ) * nLhsElems );
13691355
1356+ ival = JsonIteratorInit (cval );
1357+ rcont = JsonIteratorNext (& ival , & vval , true);
1358+ Assert (rcont == WJB_BEGIN_ARRAY );
1359+
13701360 for (i = 0 ; i < nLhsElems ; i ++ )
13711361 {
13721362 /* Store all lhs elements in temp array */
1373- rcont = JsonIteratorNext (val , & vval , true);
1363+ rcont = JsonIteratorNext (& ival , & vval , true);
13741364 Assert (rcont == WJB_ELEM );
13751365
13761366 if (vval .type == jbvBinary )
13771367 lhsConts [j ++ ] = vval ;
13781368 }
13791369
1370+ rcont = JsonIteratorNext (& ival , & vval , true);
1371+ Assert (rcont == WJB_END_ARRAY );
1372+ Assert (ival == NULL );
1373+
13801374 /* No container elements in temp array, so give up now */
13811375 if (j == 0 )
13821376 return false;
@@ -1389,20 +1383,8 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
13891383 for (i = 0 ; i < nLhsElems ; i ++ )
13901384 {
13911385 /* Nested container value (object or array) */
1392- JsonIterator * nestval ,
1393- * nestContained ;
1394- bool contains ;
1395-
1396- nestval = JsonIteratorInit (lhsConts [i ].val .binary .data );
1397- nestContained = JsonIteratorInit (vcontained .val .binary .data );
1398-
1399- contains = JsonbDeepContains (& nestval , & nestContained );
1400-
1401- if (nestval )
1402- pfree (nestval );
1403- if (nestContained )
1404- pfree (nestContained );
1405- if (contains )
1386+ if (JsonbDeepContains (lhsConts [i ].val .binary .data ,
1387+ vcont .val .binary .data ))
14061388 break ;
14071389 }
14081390
@@ -1414,14 +1396,15 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
14141396 return false;
14151397 }
14161398 }
1417- }
1418- else
1419- {
1420- elog (ERROR , "invalid jsonb container type" );
1399+
1400+ Assert (rcont == WJB_END_ARRAY );
1401+ Assert (icont == NULL );
1402+
1403+ if (lhsConts != NULL )
1404+ pfree (lhsConts );
14211405 }
14221406
1423- elog (ERROR , "unexpectedly fell off end of jsonb container" );
1424- return false;
1407+ return true;
14251408}
14261409
14271410/*
0 commit comments