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

Commitfb4ab66

Browse files
author
Nikita Glukhov
committed
Refactor JsonbDeepContains()
1 parent4079d52 commitfb4ab66

File tree

3 files changed

+82
-111
lines changed

3 files changed

+82
-111
lines changed

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

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

119-
JsonbIterator*it1,
120-
*it2;
121-
122119
if (JB_ROOT_IS_OBJECT(val)!=JB_ROOT_IS_OBJECT(tmpl))
123120
PG_RETURN_BOOL(false);
124121

125-
it1=JsonbIteratorInit(&val->root);
126-
it2=JsonbIteratorInit(&tmpl->root);
127-
128-
PG_RETURN_BOOL(JsonbDeepContains(&it1,&it2));
122+
PG_RETURN_BOOL(JsonbDeepContains(JsonRoot(val),JsonRoot(tmpl)));
129123
}
130124

131125
Datum
@@ -135,16 +129,10 @@ jsonb_contained(PG_FUNCTION_ARGS)
135129
Jsonb*tmpl=PG_GETARG_JSONB_P(0);
136130
Jsonb*val=PG_GETARG_JSONB_P(1);
137131

138-
JsonbIterator*it1,
139-
*it2;
140-
141132
if (JB_ROOT_IS_OBJECT(val)!=JB_ROOT_IS_OBJECT(tmpl))
142133
PG_RETURN_BOOL(false);
143134

144-
it1=JsonbIteratorInit(&val->root);
145-
it2=JsonbIteratorInit(&tmpl->root);
146-
147-
PG_RETURN_BOOL(JsonbDeepContains(&it1,&it2));
135+
PG_RETURN_BOOL(JsonbDeepContains(JsonRoot(val),JsonRoot(tmpl)));
148136
}
149137

150138
Datum

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

Lines changed: 79 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -1227,12 +1227,11 @@ JsonbIteratorInit(JsonContainer *cont)
12271227
*/
12281228

12291229
bool
1230-
JsonbDeepContains(JsonIterator**val,JsonIterator**mContained)
1230+
JsonbDeepContains(JsonContainer*cval,JsonContainer*ccont)
12311231
{
1232-
JsonbValuevval,
1233-
vcontained;
1234-
JsonbIteratorTokenrval,
1235-
rcont;
1232+
JsonIterator*icont;
1233+
JsonbValuevcont;
1234+
JsonbIteratorTokenrcont;
12361235

12371236
/*
12381237
* Guard against stack overflow due to overly complex Jsonb.
@@ -1242,94 +1241,76 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
12421241
*/
12431242
check_stack_depth();
12441243

1245-
rval=JsonIteratorNext(val,&vval, false);
1246-
rcont=JsonIteratorNext(mContained,&vcontained, false);
1247-
1248-
if (rval!=rcont)
1244+
if (JsonContainerIsObject(cval)!=JsonContainerIsObject(ccont))
12491245
{
12501246
/*
12511247
* The differing return values can immediately be taken as indicating
12521248
* two differing container types at this nesting level, which is
12531249
* sufficient reason to give up entirely (but it should be the case
12541250
* that they're both some container type).
12551251
*/
1256-
Assert(rval==WJB_BEGIN_OBJECT||rval==WJB_BEGIN_ARRAY);
1257-
Assert(rcont==WJB_BEGIN_OBJECT||rcont==WJB_BEGIN_ARRAY);
12581252
return false;
12591253
}
1260-
elseif (rcont==WJB_BEGIN_OBJECT)
1254+
elseif (JsonContainerIsObject(cval))
12611255
{
1262-
Assert(vval.type==jbvObject);
1263-
Assert(vcontained.type==jbvObject);
1264-
12651256
/*
12661257
* If the lhs has fewer pairs than the rhs, it can't possibly contain
12671258
* the rhs. (This conclusion is safe only because we de-duplicate
12681259
* keys in all Jsonb objects; thus there can be no corresponding
12691260
* optimization in the array case.) The case probably won't arise
12701261
* often, but since it's such a cheap check we may as well make it.
12711262
*/
1272-
if (vval.val.object.nPairs<vcontained.val.object.nPairs)
1263+
if (JsonContainerSize(cval) >=0&&
1264+
JsonContainerSize(ccont) >=0&&
1265+
JsonContainerSize(cval)<JsonContainerSize(ccont))
12731266
return false;
12741267

1275-
/* Work through rhs "is it contained within?" object */
1276-
for (;;)
1277-
{
1278-
JsonbValue*lhsVal;/* lhsVal is from pair in lhs object */
1279-
JsonbValuelhsValBuf;
1280-
1281-
rcont=JsonIteratorNext(mContained,&vcontained, false);
1268+
icont=JsonIteratorInit(ccont);
1269+
rcont=JsonIteratorNext(&icont,&vcont, false);
1270+
Assert(rcont==WJB_BEGIN_OBJECT);
12821271

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

1294-
/* First, find value by key... */
1295-
lhsVal=JsonFindKeyInObject((*val)->container,
1296-
vcontained.val.string.val,
1297-
vcontained.val.string.len);
12981286
if (!lhsVal)
12991287
return false;
13001288

13011289
/*
13021290
* ...at this stage it is apparent that there is at least a key
13031291
* match for this rhs pair.
13041292
*/
1305-
rcont=JsonIteratorNext(mContained,&vcontained, true);
1306-
1293+
rcont=JsonIteratorNext(&icont,&vcont, true);
13071294
Assert(rcont==WJB_VALUE);
13081295

13091296
/*
13101297
* Compare rhs pair's value with lhs pair's value just found using
13111298
* key
13121299
*/
1313-
if (lhsVal->type!=vcontained.type)
1300+
if (lhsVal->type!=vcont.type)
13141301
{
13151302
return false;
13161303
}
13171304
elseif (IsAJsonbScalar(lhsVal))
13181305
{
1319-
if (!equalsJsonbScalarValue(lhsVal,&vcontained))
1306+
if (!equalsJsonbScalarValue(lhsVal,&vcont))
13201307
return false;
13211308
}
13221309
else
13231310
{
13241311
/* Nested container value (object or array) */
1325-
JsonIterator*nestval,
1326-
*nestContained;
1327-
13281312
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);
13331314

13341315
/*
13351316
* Match "value" side of rhs datum object's pair recursively.
@@ -1351,18 +1332,19 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
13511332
* of containment (plus of course the mapped nodes must be
13521333
* equal).
13531334
*/
1354-
if (!JsonbDeepContains(&nestval,&nestContained))
1335+
if (!JsonbDeepContains(lhsVal->val.binary.data,
1336+
vcont.val.binary.data))
13551337
return false;
13561338
}
13571339
}
1340+
1341+
Assert(rcont==WJB_END_OBJECT);
1342+
Assert(icont==NULL);
13581343
}
1359-
elseif (rcont==WJB_BEGIN_ARRAY)
1344+
else
13601345
{
1361-
JsonbValue*lhsConts=NULL;
1362-
uint32nLhsElems=vval.val.array.nElems;
1363-
1364-
Assert(vval.type==jbvArray);
1365-
Assert(vcontained.type==jbvArray);
1346+
JsonbValue*lhsConts=NULL;
1347+
uint32nLhsElems=JsonContainerSize(cval);
13661348

13671349
/*
13681350
* Handle distinction between "raw scalar" pseudo arrays, and real
@@ -1374,29 +1356,25 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
13741356
* only contain pairs, never raw scalars (a pair is represented by an
13751357
* rhs object argument with a single contained pair).
13761358
*/
1377-
if (vval.val.array.rawScalar&& !vcontained.val.array.rawScalar)
1359+
if (JsonContainerIsScalar(cval)&& !JsonContainerIsScalar(ccont))
13781360
return false;
13791361

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

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))
13961376
{
1397-
if (!findJsonbValueFromContainer((*val)->container,
1398-
JB_FARRAY,
1399-
&vcontained))
1377+
if (!findJsonbValueFromContainer(cval,JB_FARRAY,&vcont))
14001378
return false;
14011379
}
14021380
else
@@ -1409,21 +1387,37 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
14091387
*/
14101388
if (lhsConts==NULL)
14111389
{
1412-
uint32j=0;
1390+
uint32j=0;
1391+
JsonIterator*ival;
1392+
JsonbValuevval;
1393+
1394+
if ((int32)nLhsElems<0)
1395+
nLhsElems=JsonGetArraySize(cval);
1396+
1397+
if (nLhsElems==0)
1398+
return false;
14131399

14141400
/* Make room for all possible values */
14151401
lhsConts=palloc(sizeof(JsonbValue)*nLhsElems);
14161402

1403+
ival=JsonIteratorInit(cval);
1404+
rcont=JsonIteratorNext(&ival,&vval, true);
1405+
Assert(rcont==WJB_BEGIN_ARRAY);
1406+
14171407
for (i=0;i<nLhsElems;i++)
14181408
{
14191409
/* Store all lhs elements in temp array */
1420-
rcont=JsonIteratorNext(val,&vval, true);
1410+
rcont=JsonIteratorNext(&ival,&vval, true);
14211411
Assert(rcont==WJB_ELEM);
14221412

14231413
if (vval.type==jbvBinary)
14241414
lhsConts[j++]=vval;
14251415
}
14261416

1417+
rcont=JsonIteratorNext(&ival,&vval, true);
1418+
Assert(rcont==WJB_END_ARRAY);
1419+
Assert(ival==NULL);
1420+
14271421
/* No container elements in temp array, so give up now */
14281422
if (j==0)
14291423
return false;
@@ -1436,20 +1430,8 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
14361430
for (i=0;i<nLhsElems;i++)
14371431
{
14381432
/* Nested container value (object or array) */
1439-
JsonIterator*nestval,
1440-
*nestContained;
1441-
boolcontains;
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))
14531435
break;
14541436
}
14551437

@@ -1461,14 +1443,15 @@ JsonbDeepContains(JsonIterator **val, JsonIterator **mContained)
14611443
return false;
14621444
}
14631445
}
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);
14681452
}
14691453

1470-
elog(ERROR,"unexpectedly fell off end of jsonb container");
1471-
return false;
1454+
return true;
14721455
}
14731456

14741457
/*

‎src/include/utils/json_generic.h

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

294294
externintJsonCompareContainers(JsonContainer*a,JsonContainer*b);
295295

296-
externboolJsonbDeepContains(JsonIterator**val,JsonIterator**mContained);
296+
externboolJsonbDeepContains(JsonContainer*val,JsonContainer*mContained);
297297

298298
externJsonValue*JsonContainerExtractKeys(JsonContainer*jsc);
299299

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp