Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit611cdfe

Browse files
author
Nikita Glukhov
committed
Refactor JsonbDeepContains()
1 parentf8d860b commit611cdfe

File tree

3 files changed

+83
-111
lines changed

3 files changed

+83
-111
lines changed

‎src/backend/utils/adt/jsonb_op.c‎

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -114,16 +114,10 @@ jsonb_contains(PG_FUNCTION_ARGS)
114114
Jsonb*val=PG_GETARG_JSONB_P(0);
115115
Jsonb*tmpl=PG_GETARG_JSONB_P(1);
116116

117-
JsonbIterator*it1,
118-
*it2;
119-
120117
if (JB_ROOT_IS_OBJECT(val)!=JB_ROOT_IS_OBJECT(tmpl))
121118
PG_RETURN_BOOL(false);
122119

123-
it1=JsonbIteratorInit(&val->root);
124-
it2=JsonbIteratorInit(&tmpl->root);
125-
126-
PG_RETURN_BOOL(JsonbDeepContains(&it1,&it2));
120+
PG_RETURN_BOOL(JsonbDeepContains(JsonRoot(val),JsonRoot(tmpl)));
127121
}
128122

129123
Datum
@@ -133,16 +127,10 @@ jsonb_contained(PG_FUNCTION_ARGS)
133127
Jsonb*tmpl=PG_GETARG_JSONB_P(0);
134128
Jsonb*val=PG_GETARG_JSONB_P(1);
135129

136-
JsonbIterator*it1,
137-
*it2;
138-
139130
if (JB_ROOT_IS_OBJECT(val)!=JB_ROOT_IS_OBJECT(tmpl))
140131
PG_RETURN_BOOL(false);
141132

142-
it1=JsonbIteratorInit(&val->root);
143-
it2=JsonbIteratorInit(&tmpl->root);
144-
145-
PG_RETURN_BOOL(JsonbDeepContains(&it1,&it2));
133+
PG_RETURN_BOOL(JsonbDeepContains(JsonRoot(val),JsonRoot(tmpl)));
146134
}
147135

148136
Datum

‎src/backend/utils/adt/jsonb_util.c‎

Lines changed: 80 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -1244,12 +1244,11 @@ jsonbIteratorInit(JsonContainer *cont)
12441244
*/
12451245

12461246
bool
1247-
JsonbDeepContains(JsonIterator**val,JsonIterator**mContained)
1247+
JsonbDeepContains(JsonContainer*cval,JsonContainer*ccont)
12481248
{
1249-
JsonbValuevval,
1250-
vcontained;
1251-
JsonbIteratorTokenrval,
1252-
rcont;
1249+
JsonbIterator*icont;
1250+
JsonbValuevcont;
1251+
JsonbIteratorTokenrcont;
12531252

12541253
/*
12551254
* Guard against stack overflow due to overly complex Jsonb.
@@ -1259,95 +1258,78 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
12591258
*/
12601259
check_stack_depth();
12611260

1262-
rval=JsonbIteratorNext(val,&vval, false);
1263-
rcont=JsonbIteratorNext(mContained,&vcontained, false);
1264-
1265-
if (rval!=rcont)
1261+
if (JsonContainerIsObject(cval)!=JsonContainerIsObject(ccont))
12661262
{
12671263
/*
12681264
* The differing return values can immediately be taken as indicating
12691265
* two differing container types at this nesting level, which is
12701266
* sufficient reason to give up entirely (but it should be the case
12711267
* that they're both some container type).
12721268
*/
1273-
Assert(rval==WJB_BEGIN_OBJECT||rval==WJB_BEGIN_ARRAY);
1274-
Assert(rcont==WJB_BEGIN_OBJECT||rcont==WJB_BEGIN_ARRAY);
12751269
return false;
12761270
}
1277-
elseif (rcont==WJB_BEGIN_OBJECT)
1271+
elseif (JsonContainerIsObject(cval))
12781272
{
1279-
Assert(vval.type==jbvObject);
1280-
Assert(vcontained.type==jbvObject);
1281-
12821273
/*
12831274
* If the lhs has fewer pairs than the rhs, it can't possibly contain
12841275
* the rhs. (This conclusion is safe only because we de-duplicate
12851276
* keys in all Jsonb objects; thus there can be no corresponding
12861277
* optimization in the array case.) The case probably won't arise
12871278
* often, but since it's such a cheap check we may as well make it.
12881279
*/
1289-
if (vval.val.object.nPairs<vcontained.val.object.nPairs)
1280+
if (JsonContainerSize(cval) >=0&&
1281+
JsonContainerSize(ccont) >=0&&
1282+
JsonContainerSize(cval)<JsonContainerSize(ccont))
12901283
return false;
12911284

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)
12941297
{
1295-
JsonbValue*lhsVal;/*lhsVal is from pairin lhs object */
1298+
/*First, find value by keyin lhs object ... */
12961299
JsonbValuelhsValBuf;
1300+
JsonbValue*lhsVal=JsonFindKeyInObject(cval,
1301+
vcont.val.string.val,
1302+
vcont.val.string.len,
1303+
&lhsValBuf);
12971304

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);
13161305
if (!lhsVal)
13171306
return false;
13181307

13191308
/*
13201309
* ...at this stage it is apparent that there is at least a key
13211310
* match for this rhs pair.
13221311
*/
1323-
rcont=JsonbIteratorNext(mContained,&vcontained, true);
1324-
1312+
rcont=JsonbIteratorNext(&icont,&vcont, true);
13251313
Assert(rcont==WJB_VALUE);
13261314

13271315
/*
13281316
* Compare rhs pair's value with lhs pair's value just found using
13291317
* key
13301318
*/
1331-
if (lhsVal->type!=vcontained.type)
1319+
if (lhsVal->type!=vcont.type)
13321320
{
13331321
return false;
13341322
}
13351323
elseif (IsAJsonbScalar(lhsVal))
13361324
{
1337-
if (!equalsJsonbScalarValue(lhsVal,&vcontained))
1325+
if (!equalsJsonbScalarValue(lhsVal,&vcont))
13381326
return false;
13391327
}
13401328
else
13411329
{
13421330
/* Nested container value (object or array) */
1343-
JsonIterator*nestval,
1344-
*nestContained;
1345-
13461331
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);
13511333

13521334
/*
13531335
* Match "value" side of rhs datum object's pair recursively.
@@ -1369,18 +1351,19 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
13691351
* of containment (plus of course the mapped nodes must be
13701352
* equal).
13711353
*/
1372-
if (!JsonbDeepContains(&nestval,&nestContained))
1354+
if (!JsonbDeepContains(lhsVal->val.binary.data,
1355+
vcont.val.binary.data))
13731356
return false;
13741357
}
13751358
}
1359+
1360+
Assert(rcont==WJB_END_OBJECT);
1361+
Assert(icont==NULL);
13761362
}
1377-
elseif (rcont==WJB_BEGIN_ARRAY)
1363+
else
13781364
{
1379-
JsonbValue*lhsConts=NULL;
1380-
uint32nLhsElems=vval.val.array.nElems;
1381-
1382-
Assert(vval.type==jbvArray);
1383-
Assert(vcontained.type==jbvArray);
1365+
JsonbValue*lhsConts=NULL;
1366+
uint32nLhsElems=JsonContainerSize(cval);
13841367

13851368
/*
13861369
* Handle distinction between "raw scalar" pseudo arrays, and real
@@ -1392,29 +1375,25 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
13921375
* only contain pairs, never raw scalars (a pair is represented by an
13931376
* rhs object argument with a single contained pair).
13941377
*/
1395-
if (vval.val.array.rawScalar&& !vcontained.val.array.rawScalar)
1378+
if (JsonContainerIsScalar(cval)&& !JsonContainerIsScalar(ccont))
13961379
return false;
13971380

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);
14021384

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))
14141395
{
1415-
if (!findJsonbValueFromContainer((*val)->container,
1416-
JB_FARRAY,
1417-
&vcontained))
1396+
if (!findJsonbValueFromContainer(cval,JB_FARRAY,&vcont))
14181397
return false;
14191398
}
14201399
else
@@ -1427,21 +1406,37 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
14271406
*/
14281407
if (lhsConts==NULL)
14291408
{
1430-
uint32j=0;
1409+
uint32j=0;
1410+
JsonbIterator*ival;
1411+
JsonbValuevval;
1412+
1413+
if ((int32)nLhsElems<0)
1414+
nLhsElems=JsonGetArraySize(cval);
1415+
1416+
if (nLhsElems==0)
1417+
return false;
14311418

14321419
/* Make room for all possible values */
14331420
lhsConts=palloc(sizeof(JsonbValue)*nLhsElems);
14341421

1422+
ival=JsonbIteratorInit(cval);
1423+
rcont=JsonbIteratorNext(&ival,&vval, true);
1424+
Assert(rcont==WJB_BEGIN_ARRAY);
1425+
14351426
for (i=0;i<nLhsElems;i++)
14361427
{
14371428
/* Store all lhs elements in temp array */
1438-
rcont=JsonbIteratorNext(val,&vval, true);
1429+
rcont=JsonbIteratorNext(&ival,&vval, true);
14391430
Assert(rcont==WJB_ELEM);
14401431

14411432
if (vval.type==jbvBinary)
14421433
lhsConts[j++]=vval;
14431434
}
14441435

1436+
rcont=JsonbIteratorNext(&ival,&vval, true);
1437+
Assert(rcont==WJB_END_ARRAY);
1438+
Assert(ival==NULL);
1439+
14451440
/* No container elements in temp array, so give up now */
14461441
if (j==0)
14471442
return false;
@@ -1454,20 +1449,8 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
14541449
for (i=0;i<nLhsElems;i++)
14551450
{
14561451
/* Nested container value (object or array) */
1457-
JsonIterator*nestval,
1458-
*nestContained;
1459-
boolcontains;
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))
14711454
break;
14721455
}
14731456

@@ -1479,14 +1462,15 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
14791462
return false;
14801463
}
14811464
}
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);
14861471
}
14871472

1488-
elog(ERROR,"unexpectedly fell off end of jsonb container");
1489-
return false;
1473+
return true;
14901474
}
14911475

14921476
/*

‎src/include/utils/json_generic.h‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ extern const char *JsonbTypeName(JsonbValue *jb);
281281

282282
externintJsonCompareContainers(JsonContainer*a,JsonContainer*b);
283283

284-
externboolJsonbDeepContains(JsonIterator**val,JsonIterator**mContained);
284+
externboolJsonbDeepContains(JsonContainer*val,JsonContainer*mContained);
285285

286286
externJsonValue*JsonContainerExtractKeys(JsonContainer*jsc);
287287

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp