@@ -1244,12 +1244,11 @@ jsonbIteratorInit(JsonContainer *cont)
1244
1244
*/
1245
1245
1246
1246
bool
1247
- JsonbDeepContains (JsonIterator * * val , JsonIterator * * mContained )
1247
+ JsonbDeepContains (JsonContainer * cval , JsonContainer * ccont )
1248
1248
{
1249
- JsonbValue vval ,
1250
- vcontained ;
1251
- JsonbIteratorToken rval ,
1252
- rcont ;
1249
+ JsonbIterator * icont ;
1250
+ JsonbValue vcont ;
1251
+ JsonbIteratorToken rcont ;
1253
1252
1254
1253
/*
1255
1254
* Guard against stack overflow due to overly complex Jsonb.
@@ -1259,95 +1258,78 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
1259
1258
*/
1260
1259
check_stack_depth ();
1261
1260
1262
- rval = JsonbIteratorNext (val , & vval , false);
1263
- rcont = JsonbIteratorNext (mContained , & vcontained , false);
1264
-
1265
- if (rval != rcont )
1261
+ if (JsonContainerIsObject (cval ) != JsonContainerIsObject (ccont ))
1266
1262
{
1267
1263
/*
1268
1264
* The differing return values can immediately be taken as indicating
1269
1265
* two differing container types at this nesting level, which is
1270
1266
* sufficient reason to give up entirely (but it should be the case
1271
1267
* that they're both some container type).
1272
1268
*/
1273
- Assert (rval == WJB_BEGIN_OBJECT || rval == WJB_BEGIN_ARRAY );
1274
- Assert (rcont == WJB_BEGIN_OBJECT || rcont == WJB_BEGIN_ARRAY );
1275
1269
return false;
1276
1270
}
1277
- else if (rcont == WJB_BEGIN_OBJECT )
1271
+ else if (JsonContainerIsObject ( cval ) )
1278
1272
{
1279
- Assert (vval .type == jbvObject );
1280
- Assert (vcontained .type == jbvObject );
1281
-
1282
1273
/*
1283
1274
* If the lhs has fewer pairs than the rhs, it can't possibly contain
1284
1275
* the rhs. (This conclusion is safe only because we de-duplicate
1285
1276
* keys in all Jsonb objects; thus there can be no corresponding
1286
1277
* optimization in the array case.) The case probably won't arise
1287
1278
* often, but since it's such a cheap check we may as well make it.
1288
1279
*/
1289
- if (vval .val .object .nPairs < vcontained .val .object .nPairs )
1280
+ if (JsonContainerSize (cval ) >= 0 &&
1281
+ JsonContainerSize (ccont ) >= 0 &&
1282
+ JsonContainerSize (cval ) < JsonContainerSize (ccont ))
1290
1283
return false;
1291
1284
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 )
1294
1297
{
1295
- JsonbValue * lhsVal ; /* lhsVal is from pair in lhs object */
1298
+ /* First, find value by key in lhs object ... */
1296
1299
JsonbValue lhsValBuf ;
1300
+ JsonbValue * lhsVal = JsonFindKeyInObject (cval ,
1301
+ vcont .val .string .val ,
1302
+ vcont .val .string .len ,
1303
+ & lhsValBuf );
1297
1304
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 );
1316
1305
if (!lhsVal )
1317
1306
return false;
1318
1307
1319
1308
/*
1320
1309
* ...at this stage it is apparent that there is at least a key
1321
1310
* match for this rhs pair.
1322
1311
*/
1323
- rcont = JsonbIteratorNext (mContained , & vcontained , true);
1324
-
1312
+ rcont = JsonbIteratorNext (& icont , & vcont , true);
1325
1313
Assert (rcont == WJB_VALUE );
1326
1314
1327
1315
/*
1328
1316
* Compare rhs pair's value with lhs pair's value just found using
1329
1317
* key
1330
1318
*/
1331
- if (lhsVal -> type != vcontained .type )
1319
+ if (lhsVal -> type != vcont .type )
1332
1320
{
1333
1321
return false;
1334
1322
}
1335
1323
else if (IsAJsonbScalar (lhsVal ))
1336
1324
{
1337
- if (!equalsJsonbScalarValue (lhsVal , & vcontained ))
1325
+ if (!equalsJsonbScalarValue (lhsVal , & vcont ))
1338
1326
return false;
1339
1327
}
1340
1328
else
1341
1329
{
1342
1330
/* Nested container value (object or array) */
1343
- JsonIterator * nestval ,
1344
- * nestContained ;
1345
-
1346
1331
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 );
1351
1333
1352
1334
/*
1353
1335
* Match "value" side of rhs datum object's pair recursively.
@@ -1369,18 +1351,19 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
1369
1351
* of containment (plus of course the mapped nodes must be
1370
1352
* equal).
1371
1353
*/
1372
- if (!JsonbDeepContains (& nestval , & nestContained ))
1354
+ if (!JsonbDeepContains (lhsVal -> val .binary .data ,
1355
+ vcont .val .binary .data ))
1373
1356
return false;
1374
1357
}
1375
1358
}
1359
+
1360
+ Assert (rcont == WJB_END_OBJECT );
1361
+ Assert (icont == NULL );
1376
1362
}
1377
- else if ( rcont == WJB_BEGIN_ARRAY )
1363
+ else
1378
1364
{
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 );
1384
1367
1385
1368
/*
1386
1369
* Handle distinction between "raw scalar" pseudo arrays, and real
@@ -1392,29 +1375,25 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
1392
1375
* only contain pairs, never raw scalars (a pair is represented by an
1393
1376
* rhs object argument with a single contained pair).
1394
1377
*/
1395
- if (vval . val . array . rawScalar && !vcontained . val . array . rawScalar )
1378
+ if (JsonContainerIsScalar ( cval ) && !JsonContainerIsScalar ( ccont ) )
1396
1379
return false;
1397
1380
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 );
1402
1384
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 ))
1414
1395
{
1415
- if (!findJsonbValueFromContainer ((* val )-> container ,
1416
- JB_FARRAY ,
1417
- & vcontained ))
1396
+ if (!findJsonbValueFromContainer (cval , JB_FARRAY , & vcont ))
1418
1397
return false;
1419
1398
}
1420
1399
else
@@ -1427,21 +1406,37 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
1427
1406
*/
1428
1407
if (lhsConts == NULL )
1429
1408
{
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;
1431
1418
1432
1419
/* Make room for all possible values */
1433
1420
lhsConts = palloc (sizeof (JsonbValue ) * nLhsElems );
1434
1421
1422
+ ival = JsonbIteratorInit (cval );
1423
+ rcont = JsonbIteratorNext (& ival , & vval , true);
1424
+ Assert (rcont == WJB_BEGIN_ARRAY );
1425
+
1435
1426
for (i = 0 ; i < nLhsElems ; i ++ )
1436
1427
{
1437
1428
/* Store all lhs elements in temp array */
1438
- rcont = JsonbIteratorNext (val , & vval , true);
1429
+ rcont = JsonbIteratorNext (& ival , & vval , true);
1439
1430
Assert (rcont == WJB_ELEM );
1440
1431
1441
1432
if (vval .type == jbvBinary )
1442
1433
lhsConts [j ++ ] = vval ;
1443
1434
}
1444
1435
1436
+ rcont = JsonbIteratorNext (& ival , & vval , true);
1437
+ Assert (rcont == WJB_END_ARRAY );
1438
+ Assert (ival == NULL );
1439
+
1445
1440
/* No container elements in temp array, so give up now */
1446
1441
if (j == 0 )
1447
1442
return false;
@@ -1454,20 +1449,8 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
1454
1449
for (i = 0 ; i < nLhsElems ; i ++ )
1455
1450
{
1456
1451
/* 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 ))
1471
1454
break ;
1472
1455
}
1473
1456
@@ -1479,14 +1462,15 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
1479
1462
return false;
1480
1463
}
1481
1464
}
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 );
1486
1471
}
1487
1472
1488
- elog (ERROR , "unexpectedly fell off end of jsonb container" );
1489
- return false;
1473
+ return true;
1490
1474
}
1491
1475
1492
1476
/*
0 commit comments