@@ -1152,12 +1152,11 @@ JsonbIteratorInit(JsonContainer *cont)
1152
1152
*/
1153
1153
1154
1154
bool
1155
- JsonbDeepContains (JsonIterator * * val , JsonIterator * * mContained )
1155
+ JsonbDeepContains (JsonContainer * cval , JsonContainer * ccont )
1156
1156
{
1157
- JsonbValue vval ,
1158
- vcontained ;
1159
- JsonbIteratorToken rval ,
1160
- rcont ;
1157
+ JsonIterator * icont ;
1158
+ JsonbValue vcont ;
1159
+ JsonbIteratorToken rcont ;
1161
1160
1162
1161
/*
1163
1162
* Guard against stack overflow due to overly complex Jsonb.
@@ -1167,57 +1166,46 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
1167
1166
*/
1168
1167
check_stack_depth ();
1169
1168
1170
- rval = JsonIteratorNext (val ,& vval , false);
1171
- rcont = JsonIteratorNext (mContained ,& vcontained , false);
1172
-
1173
- if (rval != rcont )
1169
+ if (JsonContainerIsObject (cval )!= JsonContainerIsObject (ccont ))
1174
1170
{
1175
1171
/*
1176
1172
* The differing return values can immediately be taken as indicating
1177
1173
* two differing container types at this nesting level, which is
1178
1174
* sufficient reason to give up entirely (but it should be the case
1179
1175
* that they're both some container type).
1180
1176
*/
1181
- Assert (rval == WJB_BEGIN_OBJECT || rval == WJB_BEGIN_ARRAY );
1182
- Assert (rcont == WJB_BEGIN_OBJECT || rcont == WJB_BEGIN_ARRAY );
1183
1177
return false;
1184
1178
}
1185
- else if (rcont == WJB_BEGIN_OBJECT )
1179
+ else if (JsonContainerIsObject ( cval ) )
1186
1180
{
1187
- Assert (vval .type == jbvObject );
1188
- Assert (vcontained .type == jbvObject );
1189
-
1190
1181
/*
1191
1182
* If the lhs has fewer pairs than the rhs, it can't possibly contain
1192
1183
* the rhs. (This conclusion is safe only because we de-duplicate
1193
1184
* keys in all Jsonb objects; thus there can be no corresponding
1194
1185
* optimization in the array case.) The case probably won't arise
1195
1186
* often, but since it's such a cheap check we may as well make it.
1196
1187
*/
1197
- if (vval .val .object .nPairs < vcontained .val .object .nPairs )
1188
+ if (JsonContainerSize (cval ) >=0 &&
1189
+ JsonContainerSize (ccont ) >=0 &&
1190
+ JsonContainerSize (cval )< JsonContainerSize (ccont ))
1198
1191
return false;
1199
1192
1200
- /* Work through rhs "is it contained within?" object */
1201
- for (;;)
1202
- {
1203
- JsonbValue * lhsVal ;/* lhsVal is from pair in lhs object */
1204
-
1205
- rcont = JsonIteratorNext (mContained ,& vcontained , false);
1193
+ icont = JsonIteratorInit (ccont );
1194
+ rcont = JsonIteratorNext (& icont ,& vcont , false);
1195
+ Assert (rcont == WJB_BEGIN_OBJECT );
1206
1196
1207
- /*
1208
- * When we get through caller's rhs "is it contained within?"
1209
- * object without failing to find one of its values, it's
1210
- * contained.
1211
- */
1212
- if (rcont == WJB_END_OBJECT )
1213
- return true;
1214
-
1215
- Assert (rcont == WJB_KEY );
1216
-
1217
- /* First, find value by key... */
1218
- lhsVal = findJsonbValueFromContainer ((* val )-> container ,
1219
- JB_FOBJECT ,
1220
- & vcontained );
1197
+ /*
1198
+ * Work through rhs "is it contained within?" object.
1199
+ *
1200
+ * When we get through caller's rhs "is it contained within?"
1201
+ * object without failing to find one of its values, it's
1202
+ * contained.
1203
+ */
1204
+ while ((rcont = JsonIteratorNext (& icont ,& vcont , false))== WJB_KEY )
1205
+ {
1206
+ /* First, find value by key in lhs object ... */
1207
+ JsonbValue * lhsVal = findJsonbValueFromContainer (cval ,JB_FOBJECT ,
1208
+ & vcont );
1221
1209
1222
1210
if (!lhsVal )
1223
1211
return false;
@@ -1226,34 +1214,27 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
1226
1214
* ...at this stage it is apparent that there is at least a key
1227
1215
* match for this rhs pair.
1228
1216
*/
1229
- rcont = JsonIteratorNext (mContained ,& vcontained , true);
1230
-
1217
+ rcont = JsonIteratorNext (& icont ,& vcont , true);
1231
1218
Assert (rcont == WJB_VALUE );
1232
1219
1233
1220
/*
1234
1221
* Compare rhs pair's value with lhs pair's value just found using
1235
1222
* key
1236
1223
*/
1237
- if (lhsVal -> type != vcontained .type )
1224
+ if (lhsVal -> type != vcont .type )
1238
1225
{
1239
1226
return false;
1240
1227
}
1241
1228
else if (IsAJsonbScalar (lhsVal ))
1242
1229
{
1243
- if (!equalsJsonbScalarValue (lhsVal ,& vcontained ))
1230
+ if (!equalsJsonbScalarValue (lhsVal ,& vcont ))
1244
1231
return false;
1245
1232
}
1246
1233
else
1247
1234
{
1248
1235
/* Nested container value (object or array) */
1249
- JsonIterator * nestval ,
1250
- * nestContained ;
1251
-
1252
1236
Assert (lhsVal -> type == jbvBinary );
1253
- Assert (vcontained .type == jbvBinary );
1254
-
1255
- nestval = JsonIteratorInit (lhsVal -> val .binary .data );
1256
- nestContained = JsonIteratorInit (vcontained .val .binary .data );
1237
+ Assert (vcont .type == jbvBinary );
1257
1238
1258
1239
/*
1259
1240
* Match "value" side of rhs datum object's pair recursively.
@@ -1275,18 +1256,19 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
1275
1256
* of containment (plus of course the mapped nodes must be
1276
1257
* equal).
1277
1258
*/
1278
- if (!JsonbDeepContains (& nestval ,& nestContained ))
1259
+ if (!JsonbDeepContains (lhsVal -> val .binary .data ,
1260
+ vcont .val .binary .data ))
1279
1261
return false;
1280
1262
}
1281
1263
}
1264
+
1265
+ Assert (rcont == WJB_END_OBJECT );
1266
+ Assert (icont == NULL );
1282
1267
}
1283
- else if ( rcont == WJB_BEGIN_ARRAY )
1268
+ else
1284
1269
{
1285
- JsonbValue * lhsConts = NULL ;
1286
- uint32 nLhsElems = vval .val .array .nElems ;
1287
-
1288
- Assert (vval .type == jbvArray );
1289
- Assert (vcontained .type == jbvArray );
1270
+ JsonbValue * lhsConts = NULL ;
1271
+ uint32 nLhsElems = JsonContainerSize (cval );
1290
1272
1291
1273
/*
1292
1274
* Handle distinction between "raw scalar" pseudo arrays, and real
@@ -1298,29 +1280,25 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
1298
1280
* only contain pairs, never raw scalars (a pair is represented by an
1299
1281
* rhs object argument with a single contained pair).
1300
1282
*/
1301
- if (vval . val . array . rawScalar && !vcontained . val . array . rawScalar )
1283
+ if (JsonContainerIsScalar ( cval ) && !JsonContainerIsScalar ( ccont ) )
1302
1284
return false;
1303
1285
1304
- /* Work through rhs "is it contained within?" array */
1305
- for (;;)
1306
- {
1307
- rcont = JsonIteratorNext (mContained ,& vcontained , true);
1286
+ icont = JsonIteratorInit (ccont );
1287
+ rcont = JsonIteratorNext (& icont ,& vcont , false);
1288
+ Assert (rcont == WJB_BEGIN_ARRAY );
1308
1289
1309
- /*
1310
- * When we get through caller's rhs "is it contained within?"
1311
- * array without failing to find one of its values, it's
1312
- * contained.
1313
- */
1314
- if (rcont == WJB_END_ARRAY )
1315
- return true;
1316
-
1317
- Assert (rcont == WJB_ELEM );
1318
-
1319
- if (IsAJsonbScalar (& vcontained ))
1290
+ /*
1291
+ * Work through rhs "is it contained within?" array.
1292
+ *
1293
+ * When we get through caller's rhs "is it contained within?"
1294
+ * array without failing to find one of its values, it's
1295
+ * contained.
1296
+ */
1297
+ while ((rcont = JsonIteratorNext (& icont ,& vcont , true))== WJB_ELEM )
1298
+ {
1299
+ if (IsAJsonbScalar (& vcont ))
1320
1300
{
1321
- if (!findJsonbValueFromContainer ((* val )-> container ,
1322
- JB_FARRAY ,
1323
- & vcontained ))
1301
+ if (!findJsonbValueFromContainer (cval ,JB_FARRAY ,& vcont ))
1324
1302
return false;
1325
1303
}
1326
1304
else
@@ -1333,21 +1311,37 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
1333
1311
*/
1334
1312
if (lhsConts == NULL )
1335
1313
{
1336
- uint32 j = 0 ;
1314
+ uint32 j = 0 ;
1315
+ JsonIterator * ival ;
1316
+ JsonbValue vval ;
1317
+
1318
+ if ((int32 )nLhsElems < 0 )
1319
+ nLhsElems = JsonGetArraySize (cval );
1320
+
1321
+ if (nLhsElems == 0 )
1322
+ return false;
1337
1323
1338
1324
/* Make room for all possible values */
1339
1325
lhsConts = palloc (sizeof (JsonbValue )* nLhsElems );
1340
1326
1327
+ ival = JsonIteratorInit (cval );
1328
+ rcont = JsonIteratorNext (& ival ,& vval , true);
1329
+ Assert (rcont == WJB_BEGIN_ARRAY );
1330
+
1341
1331
for (i = 0 ;i < nLhsElems ;i ++ )
1342
1332
{
1343
1333
/* Store all lhs elements in temp array */
1344
- rcont = JsonIteratorNext (val ,& vval , true);
1334
+ rcont = JsonIteratorNext (& ival ,& vval , true);
1345
1335
Assert (rcont == WJB_ELEM );
1346
1336
1347
1337
if (vval .type == jbvBinary )
1348
1338
lhsConts [j ++ ]= vval ;
1349
1339
}
1350
1340
1341
+ rcont = JsonIteratorNext (& ival ,& vval , true);
1342
+ Assert (rcont == WJB_END_ARRAY );
1343
+ Assert (ival == NULL );
1344
+
1351
1345
/* No container elements in temp array, so give up now */
1352
1346
if (j == 0 )
1353
1347
return false;
@@ -1360,20 +1354,8 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
1360
1354
for (i = 0 ;i < nLhsElems ;i ++ )
1361
1355
{
1362
1356
/* Nested container value (object or array) */
1363
- JsonIterator * nestval ,
1364
- * nestContained ;
1365
- bool contains ;
1366
-
1367
- nestval = JsonIteratorInit (lhsConts [i ].val .binary .data );
1368
- nestContained = JsonIteratorInit (vcontained .val .binary .data );
1369
-
1370
- contains = JsonbDeepContains (& nestval ,& nestContained );
1371
-
1372
- if (nestval )
1373
- pfree (nestval );
1374
- if (nestContained )
1375
- pfree (nestContained );
1376
- if (contains )
1357
+ if (JsonbDeepContains (lhsConts [i ].val .binary .data ,
1358
+ vcont .val .binary .data ))
1377
1359
break ;
1378
1360
}
1379
1361
@@ -1385,14 +1367,15 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
1385
1367
return false;
1386
1368
}
1387
1369
}
1388
- }
1389
- else
1390
- {
1391
- elog (ERROR ,"invalid jsonb container type" );
1370
+
1371
+ Assert (rcont == WJB_END_ARRAY );
1372
+ Assert (icont == NULL );
1373
+
1374
+ if (lhsConts != NULL )
1375
+ pfree (lhsConts );
1392
1376
}
1393
1377
1394
- elog (ERROR ,"unexpectedly fell off end of jsonb container" );
1395
- return false;
1378
+ return true;
1396
1379
}
1397
1380
1398
1381
/*