@@ -1180,12 +1180,11 @@ JsonbIteratorInit(JsonContainer *cont)
1180
1180
*/
1181
1181
1182
1182
bool
1183
- JsonbDeepContains (JsonIterator * * val , JsonIterator * * mContained )
1183
+ JsonbDeepContains (JsonContainer * cval , JsonContainer * ccont )
1184
1184
{
1185
- JsonbValue vval ,
1186
- vcontained ;
1187
- JsonbIteratorToken rval ,
1188
- rcont ;
1185
+ JsonIterator * icont ;
1186
+ JsonbValue vcont ;
1187
+ JsonbIteratorToken rcont ;
1189
1188
1190
1189
/*
1191
1190
* Guard against stack overflow due to overly complex Jsonb.
@@ -1195,94 +1194,76 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
1195
1194
*/
1196
1195
check_stack_depth ();
1197
1196
1198
- rval = JsonIteratorNext (val ,& vval , false);
1199
- rcont = JsonIteratorNext (mContained ,& vcontained , false);
1200
-
1201
- if (rval != rcont )
1197
+ if (JsonContainerIsObject (cval )!= JsonContainerIsObject (ccont ))
1202
1198
{
1203
1199
/*
1204
1200
* The differing return values can immediately be taken as indicating
1205
1201
* two differing container types at this nesting level, which is
1206
1202
* sufficient reason to give up entirely (but it should be the case
1207
1203
* that they're both some container type).
1208
1204
*/
1209
- Assert (rval == WJB_BEGIN_OBJECT || rval == WJB_BEGIN_ARRAY );
1210
- Assert (rcont == WJB_BEGIN_OBJECT || rcont == WJB_BEGIN_ARRAY );
1211
1205
return false;
1212
1206
}
1213
- else if (rcont == WJB_BEGIN_OBJECT )
1207
+ else if (JsonContainerIsObject ( cval ) )
1214
1208
{
1215
- Assert (vval .type == jbvObject );
1216
- Assert (vcontained .type == jbvObject );
1217
-
1218
1209
/*
1219
1210
* If the lhs has fewer pairs than the rhs, it can't possibly contain
1220
1211
* the rhs. (This conclusion is safe only because we de-duplicate
1221
1212
* keys in all Jsonb objects; thus there can be no corresponding
1222
1213
* optimization in the array case.) The case probably won't arise
1223
1214
* often, but since it's such a cheap check we may as well make it.
1224
1215
*/
1225
- if (vval .val .object .nPairs < vcontained .val .object .nPairs )
1216
+ if (JsonContainerSize (cval ) >=0 &&
1217
+ JsonContainerSize (ccont ) >=0 &&
1218
+ JsonContainerSize (cval )< JsonContainerSize (ccont ))
1226
1219
return false;
1227
1220
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 );
1235
1224
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 );
1246
1238
1247
- /* First, find value by key... */
1248
- lhsVal = JsonFindKeyInObject ((* val )-> container ,
1249
- vcontained .val .string .val ,
1250
- vcontained .val .string .len );
1251
1239
if (!lhsVal )
1252
1240
return false;
1253
1241
1254
1242
/*
1255
1243
* ...at this stage it is apparent that there is at least a key
1256
1244
* match for this rhs pair.
1257
1245
*/
1258
- rcont = JsonIteratorNext (mContained ,& vcontained , true);
1259
-
1246
+ rcont = JsonIteratorNext (& icont ,& vcont , true);
1260
1247
Assert (rcont == WJB_VALUE );
1261
1248
1262
1249
/*
1263
1250
* Compare rhs pair's value with lhs pair's value just found using
1264
1251
* key
1265
1252
*/
1266
- if (lhsVal -> type != vcontained .type )
1253
+ if (lhsVal -> type != vcont .type )
1267
1254
{
1268
1255
return false;
1269
1256
}
1270
1257
else if (IsAJsonbScalar (lhsVal ))
1271
1258
{
1272
- if (!equalsJsonbScalarValue (lhsVal ,& vcontained ))
1259
+ if (!equalsJsonbScalarValue (lhsVal ,& vcont ))
1273
1260
return false;
1274
1261
}
1275
1262
else
1276
1263
{
1277
1264
/* Nested container value (object or array) */
1278
- JsonIterator * nestval ,
1279
- * nestContained ;
1280
-
1281
1265
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 );
1286
1267
1287
1268
/*
1288
1269
* Match "value" side of rhs datum object's pair recursively.
@@ -1304,18 +1285,19 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
1304
1285
* of containment (plus of course the mapped nodes must be
1305
1286
* equal).
1306
1287
*/
1307
- if (!JsonbDeepContains (& nestval ,& nestContained ))
1288
+ if (!JsonbDeepContains (lhsVal -> val .binary .data ,
1289
+ vcont .val .binary .data ))
1308
1290
return false;
1309
1291
}
1310
1292
}
1293
+
1294
+ Assert (rcont == WJB_END_OBJECT );
1295
+ Assert (icont == NULL );
1311
1296
}
1312
- else if ( rcont == WJB_BEGIN_ARRAY )
1297
+ else
1313
1298
{
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 );
1319
1301
1320
1302
/*
1321
1303
* Handle distinction between "raw scalar" pseudo arrays, and real
@@ -1327,29 +1309,25 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
1327
1309
* only contain pairs, never raw scalars (a pair is represented by an
1328
1310
* rhs object argument with a single contained pair).
1329
1311
*/
1330
- if (vval . val . array . rawScalar && !vcontained . val . array . rawScalar )
1312
+ if (JsonContainerIsScalar ( cval ) && !JsonContainerIsScalar ( ccont ) )
1331
1313
return false;
1332
1314
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 );
1337
1318
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 ))
1349
1329
{
1350
- if (!findJsonbValueFromContainer ((* val )-> container ,
1351
- JB_FARRAY ,
1352
- & vcontained ))
1330
+ if (!findJsonbValueFromContainer (cval ,JB_FARRAY ,& vcont ))
1353
1331
return false;
1354
1332
}
1355
1333
else
@@ -1362,21 +1340,37 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
1362
1340
*/
1363
1341
if (lhsConts == NULL )
1364
1342
{
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;
1366
1352
1367
1353
/* Make room for all possible values */
1368
1354
lhsConts = palloc (sizeof (JsonbValue )* nLhsElems );
1369
1355
1356
+ ival = JsonIteratorInit (cval );
1357
+ rcont = JsonIteratorNext (& ival ,& vval , true);
1358
+ Assert (rcont == WJB_BEGIN_ARRAY );
1359
+
1370
1360
for (i = 0 ;i < nLhsElems ;i ++ )
1371
1361
{
1372
1362
/* Store all lhs elements in temp array */
1373
- rcont = JsonIteratorNext (val ,& vval , true);
1363
+ rcont = JsonIteratorNext (& ival ,& vval , true);
1374
1364
Assert (rcont == WJB_ELEM );
1375
1365
1376
1366
if (vval .type == jbvBinary )
1377
1367
lhsConts [j ++ ]= vval ;
1378
1368
}
1379
1369
1370
+ rcont = JsonIteratorNext (& ival ,& vval , true);
1371
+ Assert (rcont == WJB_END_ARRAY );
1372
+ Assert (ival == NULL );
1373
+
1380
1374
/* No container elements in temp array, so give up now */
1381
1375
if (j == 0 )
1382
1376
return false;
@@ -1389,20 +1383,8 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
1389
1383
for (i = 0 ;i < nLhsElems ;i ++ )
1390
1384
{
1391
1385
/* 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 ))
1406
1388
break ;
1407
1389
}
1408
1390
@@ -1414,14 +1396,15 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
1414
1396
return false;
1415
1397
}
1416
1398
}
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 );
1421
1405
}
1422
1406
1423
- elog (ERROR ,"unexpectedly fell off end of jsonb container" );
1424
- return false;
1407
+ return true;
1425
1408
}
1426
1409
1427
1410
/*