@@ -1227,12 +1227,11 @@ JsonbIteratorInit(JsonContainer *cont)
1227
1227
*/
1228
1228
1229
1229
bool
1230
- JsonbDeepContains (JsonIterator * * val , JsonIterator * * mContained )
1230
+ JsonbDeepContains (JsonContainer * cval , JsonContainer * ccont )
1231
1231
{
1232
- JsonbValue vval ,
1233
- vcontained ;
1234
- JsonbIteratorToken rval ,
1235
- rcont ;
1232
+ JsonIterator * icont ;
1233
+ JsonbValue vcont ;
1234
+ JsonbIteratorToken rcont ;
1236
1235
1237
1236
/*
1238
1237
* Guard against stack overflow due to overly complex Jsonb.
@@ -1242,94 +1241,76 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
1242
1241
*/
1243
1242
check_stack_depth ();
1244
1243
1245
- rval = JsonIteratorNext (val ,& vval , false);
1246
- rcont = JsonIteratorNext (mContained ,& vcontained , false);
1247
-
1248
- if (rval != rcont )
1244
+ if (JsonContainerIsObject (cval )!= JsonContainerIsObject (ccont ))
1249
1245
{
1250
1246
/*
1251
1247
* The differing return values can immediately be taken as indicating
1252
1248
* two differing container types at this nesting level, which is
1253
1249
* sufficient reason to give up entirely (but it should be the case
1254
1250
* that they're both some container type).
1255
1251
*/
1256
- Assert (rval == WJB_BEGIN_OBJECT || rval == WJB_BEGIN_ARRAY );
1257
- Assert (rcont == WJB_BEGIN_OBJECT || rcont == WJB_BEGIN_ARRAY );
1258
1252
return false;
1259
1253
}
1260
- else if (rcont == WJB_BEGIN_OBJECT )
1254
+ else if (JsonContainerIsObject ( cval ) )
1261
1255
{
1262
- Assert (vval .type == jbvObject );
1263
- Assert (vcontained .type == jbvObject );
1264
-
1265
1256
/*
1266
1257
* If the lhs has fewer pairs than the rhs, it can't possibly contain
1267
1258
* the rhs. (This conclusion is safe only because we de-duplicate
1268
1259
* keys in all Jsonb objects; thus there can be no corresponding
1269
1260
* optimization in the array case.) The case probably won't arise
1270
1261
* often, but since it's such a cheap check we may as well make it.
1271
1262
*/
1272
- if (vval .val .object .nPairs < vcontained .val .object .nPairs )
1263
+ if (JsonContainerSize (cval ) >=0 &&
1264
+ JsonContainerSize (ccont ) >=0 &&
1265
+ JsonContainerSize (cval )< JsonContainerSize (ccont ))
1273
1266
return false;
1274
1267
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 );
1282
1271
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 );
1293
1285
1294
- /* First, find value by key... */
1295
- lhsVal = JsonFindKeyInObject ((* val )-> container ,
1296
- vcontained .val .string .val ,
1297
- vcontained .val .string .len );
1298
1286
if (!lhsVal )
1299
1287
return false;
1300
1288
1301
1289
/*
1302
1290
* ...at this stage it is apparent that there is at least a key
1303
1291
* match for this rhs pair.
1304
1292
*/
1305
- rcont = JsonIteratorNext (mContained ,& vcontained , true);
1306
-
1293
+ rcont = JsonIteratorNext (& icont ,& vcont , true);
1307
1294
Assert (rcont == WJB_VALUE );
1308
1295
1309
1296
/*
1310
1297
* Compare rhs pair's value with lhs pair's value just found using
1311
1298
* key
1312
1299
*/
1313
- if (lhsVal -> type != vcontained .type )
1300
+ if (lhsVal -> type != vcont .type )
1314
1301
{
1315
1302
return false;
1316
1303
}
1317
1304
else if (IsAJsonbScalar (lhsVal ))
1318
1305
{
1319
- if (!equalsJsonbScalarValue (lhsVal ,& vcontained ))
1306
+ if (!equalsJsonbScalarValue (lhsVal ,& vcont ))
1320
1307
return false;
1321
1308
}
1322
1309
else
1323
1310
{
1324
1311
/* Nested container value (object or array) */
1325
- JsonIterator * nestval ,
1326
- * nestContained ;
1327
-
1328
1312
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 );
1333
1314
1334
1315
/*
1335
1316
* Match "value" side of rhs datum object's pair recursively.
@@ -1351,18 +1332,19 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
1351
1332
* of containment (plus of course the mapped nodes must be
1352
1333
* equal).
1353
1334
*/
1354
- if (!JsonbDeepContains (& nestval ,& nestContained ))
1335
+ if (!JsonbDeepContains (lhsVal -> val .binary .data ,
1336
+ vcont .val .binary .data ))
1355
1337
return false;
1356
1338
}
1357
1339
}
1340
+
1341
+ Assert (rcont == WJB_END_OBJECT );
1342
+ Assert (icont == NULL );
1358
1343
}
1359
- else if ( rcont == WJB_BEGIN_ARRAY )
1344
+ else
1360
1345
{
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 );
1366
1348
1367
1349
/*
1368
1350
* Handle distinction between "raw scalar" pseudo arrays, and real
@@ -1374,29 +1356,25 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
1374
1356
* only contain pairs, never raw scalars (a pair is represented by an
1375
1357
* rhs object argument with a single contained pair).
1376
1358
*/
1377
- if (vval . val . array . rawScalar && !vcontained . val . array . rawScalar )
1359
+ if (JsonContainerIsScalar ( cval ) && !JsonContainerIsScalar ( ccont ) )
1378
1360
return false;
1379
1361
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 );
1384
1365
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 ))
1396
1376
{
1397
- if (!findJsonbValueFromContainer ((* val )-> container ,
1398
- JB_FARRAY ,
1399
- & vcontained ))
1377
+ if (!findJsonbValueFromContainer (cval ,JB_FARRAY ,& vcont ))
1400
1378
return false;
1401
1379
}
1402
1380
else
@@ -1409,21 +1387,37 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
1409
1387
*/
1410
1388
if (lhsConts == NULL )
1411
1389
{
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;
1413
1399
1414
1400
/* Make room for all possible values */
1415
1401
lhsConts = palloc (sizeof (JsonbValue )* nLhsElems );
1416
1402
1403
+ ival = JsonIteratorInit (cval );
1404
+ rcont = JsonIteratorNext (& ival ,& vval , true);
1405
+ Assert (rcont == WJB_BEGIN_ARRAY );
1406
+
1417
1407
for (i = 0 ;i < nLhsElems ;i ++ )
1418
1408
{
1419
1409
/* Store all lhs elements in temp array */
1420
- rcont = JsonIteratorNext (val ,& vval , true);
1410
+ rcont = JsonIteratorNext (& ival ,& vval , true);
1421
1411
Assert (rcont == WJB_ELEM );
1422
1412
1423
1413
if (vval .type == jbvBinary )
1424
1414
lhsConts [j ++ ]= vval ;
1425
1415
}
1426
1416
1417
+ rcont = JsonIteratorNext (& ival ,& vval , true);
1418
+ Assert (rcont == WJB_END_ARRAY );
1419
+ Assert (ival == NULL );
1420
+
1427
1421
/* No container elements in temp array, so give up now */
1428
1422
if (j == 0 )
1429
1423
return false;
@@ -1436,20 +1430,8 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
1436
1430
for (i = 0 ;i < nLhsElems ;i ++ )
1437
1431
{
1438
1432
/* 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 ))
1453
1435
break ;
1454
1436
}
1455
1437
@@ -1461,14 +1443,15 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
1461
1443
return false;
1462
1444
}
1463
1445
}
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 );
1468
1452
}
1469
1453
1470
- elog (ERROR ,"unexpectedly fell off end of jsonb container" );
1471
- return false;
1454
+ return true;
1472
1455
}
1473
1456
1474
1457
/*